mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
encode DPR for shadows into DisplayList (flutter/engine#27289)
This commit is contained in:
parent
4b936db762
commit
ab8a90ddeb
@ -796,24 +796,28 @@ struct DrawTextBlobOp final : DLOp {
|
||||
};
|
||||
|
||||
// 4 byte header + 28 byte payload packs evenly into 32 bytes
|
||||
struct DrawShadowOp final : DLOp {
|
||||
static const auto kType = DisplayListOpType::kDrawShadow;
|
||||
|
||||
DrawShadowOp(const SkPath& path,
|
||||
SkColor color,
|
||||
SkScalar elevation,
|
||||
bool occludes)
|
||||
: color(color), elevation(elevation), occludes(occludes), path(path) {}
|
||||
|
||||
const SkColor color;
|
||||
const SkScalar elevation;
|
||||
const bool occludes;
|
||||
const SkPath path;
|
||||
|
||||
void dispatch(Dispatcher& dispatcher) const {
|
||||
dispatcher.drawShadow(path, color, elevation, occludes);
|
||||
}
|
||||
};
|
||||
#define DEFINE_DRAW_SHADOW_OP(name, occludes) \
|
||||
struct Draw##name##Op final : DLOp { \
|
||||
static const auto kType = DisplayListOpType::kDraw##name; \
|
||||
\
|
||||
Draw##name##Op(const SkPath& path, \
|
||||
SkColor color, \
|
||||
SkScalar elevation, \
|
||||
SkScalar dpr) \
|
||||
: color(color), elevation(elevation), dpr(dpr), path(path) {} \
|
||||
\
|
||||
const SkColor color; \
|
||||
const SkScalar elevation; \
|
||||
const SkScalar dpr; \
|
||||
const SkPath path; \
|
||||
\
|
||||
void dispatch(Dispatcher& dispatcher) const { \
|
||||
dispatcher.drawShadow(path, color, elevation, occludes, dpr); \
|
||||
} \
|
||||
};
|
||||
DEFINE_DRAW_SHADOW_OP(Shadow, false)
|
||||
DEFINE_DRAW_SHADOW_OP(ShadowOccludes, true)
|
||||
#undef DEFINE_DRAW_SHADOW_OP
|
||||
|
||||
#pragma pack(pop, DLOp_Alignment)
|
||||
|
||||
@ -1351,8 +1355,11 @@ void DisplayListBuilder::drawTextBlob(const sk_sp<SkTextBlob> blob,
|
||||
void DisplayListBuilder::drawShadow(const SkPath& path,
|
||||
const SkColor color,
|
||||
const SkScalar elevation,
|
||||
bool occludes) {
|
||||
Push<DrawShadowOp>(0, path, color, elevation, occludes);
|
||||
bool occludes,
|
||||
SkScalar dpr) {
|
||||
occludes //
|
||||
? Push<DrawShadowOccludesOp>(0, path, color, elevation, dpr)
|
||||
: Push<DrawShadowOp>(0, path, color, elevation, dpr);
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@ -144,7 +144,8 @@ namespace flutter {
|
||||
V(DrawDisplayList) \
|
||||
V(DrawTextBlob) \
|
||||
\
|
||||
V(DrawShadow)
|
||||
V(DrawShadow) \
|
||||
V(DrawShadowOccludes)
|
||||
|
||||
#define DL_OP_TO_ENUM_VALUE(name) k##name,
|
||||
enum class DisplayListOpType { FOR_EACH_DISPLAY_LIST_OP(DL_OP_TO_ENUM_VALUE) };
|
||||
@ -318,7 +319,8 @@ class Dispatcher {
|
||||
virtual void drawShadow(const SkPath& path,
|
||||
const SkColor color,
|
||||
const SkScalar elevation,
|
||||
bool occludes) = 0;
|
||||
bool occludes,
|
||||
SkScalar dpr) = 0;
|
||||
};
|
||||
|
||||
// The primary class used to build a display list. The list of methods
|
||||
@ -431,7 +433,8 @@ class DisplayListBuilder final : public virtual Dispatcher, public SkRefCnt {
|
||||
void drawShadow(const SkPath& path,
|
||||
const SkColor color,
|
||||
const SkScalar elevation,
|
||||
bool occludes) override;
|
||||
bool occludes,
|
||||
SkScalar dpr) override;
|
||||
|
||||
sk_sp<DisplayList> Build();
|
||||
|
||||
|
||||
@ -176,9 +176,10 @@ void DisplayListCanvasDispatcher::drawTextBlob(const sk_sp<SkTextBlob> blob,
|
||||
void DisplayListCanvasDispatcher::drawShadow(const SkPath& path,
|
||||
const SkColor color,
|
||||
const SkScalar elevation,
|
||||
bool occludes) {
|
||||
bool occludes,
|
||||
SkScalar dpr) {
|
||||
flutter::PhysicalShapeLayer::DrawShadow(canvas_, path, color, elevation,
|
||||
occludes, 1.0);
|
||||
occludes, dpr);
|
||||
}
|
||||
|
||||
DisplayListCanvasRecorder::DisplayListCanvasRecorder(const SkRect& bounds)
|
||||
|
||||
@ -110,7 +110,8 @@ class DisplayListCanvasDispatcher : public virtual Dispatcher,
|
||||
void drawShadow(const SkPath& path,
|
||||
const SkColor color,
|
||||
const SkScalar elevation,
|
||||
bool occludes) override;
|
||||
bool occludes,
|
||||
SkScalar dpr) override;
|
||||
|
||||
private:
|
||||
SkCanvas* canvas_;
|
||||
|
||||
@ -1350,7 +1350,7 @@ TEST(DisplayListCanvas, DrawShadow) {
|
||||
1.0);
|
||||
},
|
||||
[=](DisplayListBuilder& builder) { //
|
||||
builder.drawShadow(path, color, elevation, false);
|
||||
builder.drawShadow(path, color, elevation, false, 1.0);
|
||||
});
|
||||
CanvasCompareTester::UsingShadows = false;
|
||||
}
|
||||
@ -1373,7 +1373,30 @@ TEST(DisplayListCanvas, DrawOccludingShadow) {
|
||||
1.0);
|
||||
},
|
||||
[=](DisplayListBuilder& builder) { //
|
||||
builder.drawShadow(path, color, elevation, true);
|
||||
builder.drawShadow(path, color, elevation, true, 1.0);
|
||||
});
|
||||
CanvasCompareTester::UsingShadows = false;
|
||||
}
|
||||
|
||||
TEST(DisplayListCanvas, DrawShadowDpr) {
|
||||
CanvasCompareTester::UsingShadows = true;
|
||||
SkPath path;
|
||||
path.moveTo(RenderCenterX, RenderTop);
|
||||
path.lineTo(RenderRight, RenderBottom);
|
||||
path.lineTo(RenderLeft, RenderCenterY);
|
||||
path.lineTo(RenderRight, RenderCenterY);
|
||||
path.lineTo(RenderLeft, RenderBottom);
|
||||
path.close();
|
||||
const SkColor color = SK_ColorDKGRAY;
|
||||
const SkScalar elevation = 10;
|
||||
|
||||
CanvasCompareTester::RenderNoAttributes(
|
||||
[=](SkCanvas* canvas, SkPaint& paint) { //
|
||||
PhysicalShapeLayer::DrawShadow(canvas, path, color, elevation, false,
|
||||
2.5);
|
||||
},
|
||||
[=](DisplayListBuilder& builder) { //
|
||||
builder.drawShadow(path, color, elevation, false, 2.5);
|
||||
});
|
||||
CanvasCompareTester::UsingShadows = false;
|
||||
}
|
||||
|
||||
@ -663,11 +663,12 @@ std::vector<DisplayListInvocationGroup> allGroups = {
|
||||
// See: https://bugs.chromium.org/p/skia/issues/detail?id=12125
|
||||
{ "DrawShadow", {
|
||||
// cv shadows are turned into an opaque ShadowRec which is not exposed
|
||||
{1, 32, -1, 32, [](DisplayListBuilder& b) {b.drawShadow(TestPath1, SK_ColorGREEN, 1.0, false);}},
|
||||
{1, 32, -1, 32, [](DisplayListBuilder& b) {b.drawShadow(TestPath2, SK_ColorGREEN, 1.0, false);}},
|
||||
{1, 32, -1, 32, [](DisplayListBuilder& b) {b.drawShadow(TestPath1, SK_ColorBLUE, 1.0, false);}},
|
||||
{1, 32, -1, 32, [](DisplayListBuilder& b) {b.drawShadow(TestPath1, SK_ColorGREEN, 2.0, false);}},
|
||||
{1, 32, -1, 32, [](DisplayListBuilder& b) {b.drawShadow(TestPath1, SK_ColorGREEN, 1.0, true);}},
|
||||
{1, 32, -1, 32, [](DisplayListBuilder& b) {b.drawShadow(TestPath1, SK_ColorGREEN, 1.0, false, 1.0);}},
|
||||
{1, 32, -1, 32, [](DisplayListBuilder& b) {b.drawShadow(TestPath2, SK_ColorGREEN, 1.0, false, 1.0);}},
|
||||
{1, 32, -1, 32, [](DisplayListBuilder& b) {b.drawShadow(TestPath1, SK_ColorBLUE, 1.0, false, 1.0);}},
|
||||
{1, 32, -1, 32, [](DisplayListBuilder& b) {b.drawShadow(TestPath1, SK_ColorGREEN, 2.0, false, 1.0);}},
|
||||
{1, 32, -1, 32, [](DisplayListBuilder& b) {b.drawShadow(TestPath1, SK_ColorGREEN, 1.0, true, 1.0);}},
|
||||
{1, 32, -1, 32, [](DisplayListBuilder& b) {b.drawShadow(TestPath1, SK_ColorGREEN, 1.0, false, 2.5);}},
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@ -335,7 +335,8 @@ void DisplayListBoundsCalculator::drawTextBlob(const sk_sp<SkTextBlob> blob,
|
||||
void DisplayListBoundsCalculator::drawShadow(const SkPath& path,
|
||||
const SkColor color,
|
||||
const SkScalar elevation,
|
||||
bool occludes) {
|
||||
bool occludes,
|
||||
SkScalar dpr) {
|
||||
// Constants from physical_shape_layer.cc
|
||||
const SkScalar kLightHeight = 600;
|
||||
const SkScalar kLightRadius = 800;
|
||||
@ -348,9 +349,9 @@ void DisplayListBoundsCalculator::drawShadow(const SkPath& path,
|
||||
SkScalar shadow_y = bounds.top() - 600.0f;
|
||||
SkRect shadow_bounds;
|
||||
SkShadowUtils::GetLocalBounds(
|
||||
matrix(), path, SkPoint3::Make(0, 0, elevation),
|
||||
SkPoint3::Make(shadow_x, shadow_y, kLightHeight), kLightRadius, flags,
|
||||
&shadow_bounds);
|
||||
matrix(), path, SkPoint3::Make(0, 0, dpr * elevation),
|
||||
SkPoint3::Make(shadow_x, shadow_y, dpr * kLightHeight),
|
||||
dpr * kLightRadius, flags, &shadow_bounds);
|
||||
accumulateRect(shadow_bounds);
|
||||
}
|
||||
|
||||
|
||||
@ -308,7 +308,8 @@ class DisplayListBoundsCalculator final
|
||||
void drawShadow(const SkPath& path,
|
||||
const SkColor color,
|
||||
const SkScalar elevation,
|
||||
bool occludes) override;
|
||||
bool occludes,
|
||||
SkScalar dpr) override;
|
||||
|
||||
SkRect getBounds() { return accumulator_->getBounds(); }
|
||||
|
||||
|
||||
@ -499,6 +499,11 @@ void Canvas::drawShadow(const CanvasPath* path,
|
||||
ToDart("Canvas.drawShader called with non-genuine Path."));
|
||||
return;
|
||||
}
|
||||
SkScalar dpr = UIDartState::Current()
|
||||
->platform_configuration()
|
||||
->get_window(0)
|
||||
->viewport_metrics()
|
||||
.device_pixel_ratio;
|
||||
if (display_list_recorder_) {
|
||||
// The DrawShadow mechanism results in non-public operations to be
|
||||
// performed on the canvas involving an SkDrawShadowRec. Since we
|
||||
@ -507,13 +512,9 @@ void Canvas::drawShadow(const CanvasPath* path,
|
||||
// that situation we bypass the canvas interface and inject the
|
||||
// shadow parameters directly into the underlying DisplayList.
|
||||
// See: https://bugs.chromium.org/p/skia/issues/detail?id=12125
|
||||
builder()->drawShadow(path->path(), color, elevation, transparentOccluder);
|
||||
builder()->drawShadow(path->path(), color, elevation, transparentOccluder,
|
||||
dpr);
|
||||
} else {
|
||||
SkScalar dpr = UIDartState::Current()
|
||||
->platform_configuration()
|
||||
->get_window(0)
|
||||
->viewport_metrics()
|
||||
.device_pixel_ratio;
|
||||
flutter::PhysicalShapeLayer::DrawShadow(
|
||||
canvas_, path->path(), color, elevation, transparentOccluder, dpr);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user