[DisplayList] Migrate from SkRSXform to Impeller RSTransform (#161652)
Fixes SkRSXform task in https://github.com/flutter/flutter/issues/161456 Removes (nearly) all uses of Skia SkRSXform object from DisplayList and replaces it with a new Impeller RSTransform geometry object. There are remaining uses in: - Skia adapter code which needs to convert them back to SkRSXform when using the Skia backend - dl_rendering_tests which is waiting for a major conversion effort - ?Fuchsia? code has an SkCanvas spy adapter used in its embedder code (not DisplayList related) - web_ui/skwasm
This commit is contained in:
parent
1580a3d3fb
commit
a10e25e727
@ -174,6 +174,7 @@
|
||||
../../../flutter/impeller/geometry/path_unittests.cc
|
||||
../../../flutter/impeller/geometry/rect_unittests.cc
|
||||
../../../flutter/impeller/geometry/round_rect_unittests.cc
|
||||
../../../flutter/impeller/geometry/rstransform_unittests.cc
|
||||
../../../flutter/impeller/geometry/saturated_math_unittests.cc
|
||||
../../../flutter/impeller/geometry/size_unittests.cc
|
||||
../../../flutter/impeller/geometry/trig_unittests.cc
|
||||
|
@ -42513,6 +42513,8 @@ ORIGIN: ../../../flutter/impeller/geometry/round_rect.cc + ../../../flutter/LICE
|
||||
ORIGIN: ../../../flutter/impeller/geometry/round_rect.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/impeller/geometry/rounding_radii.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/impeller/geometry/rounding_radii.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/impeller/geometry/rstransform.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/impeller/geometry/rstransform.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/impeller/geometry/saturated_math.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/impeller/geometry/scalar.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/impeller/geometry/separated_vector.cc + ../../../flutter/LICENSE
|
||||
@ -45456,6 +45458,8 @@ FILE: ../../../flutter/impeller/geometry/round_rect.cc
|
||||
FILE: ../../../flutter/impeller/geometry/round_rect.h
|
||||
FILE: ../../../flutter/impeller/geometry/rounding_radii.cc
|
||||
FILE: ../../../flutter/impeller/geometry/rounding_radii.h
|
||||
FILE: ../../../flutter/impeller/geometry/rstransform.cc
|
||||
FILE: ../../../flutter/impeller/geometry/rstransform.h
|
||||
FILE: ../../../flutter/impeller/geometry/saturated_math.h
|
||||
FILE: ../../../flutter/impeller/geometry/scalar.h
|
||||
FILE: ../../../flutter/impeller/geometry/separated_vector.cc
|
||||
|
@ -158,7 +158,7 @@ class ComplexityCalculatorHelper
|
||||
}
|
||||
|
||||
void drawAtlas(const sk_sp<DlImage> atlas,
|
||||
const SkRSXform xform[],
|
||||
const DlRSTransform xform[],
|
||||
const DlRect tex[],
|
||||
const DlColor colors[],
|
||||
int count,
|
||||
|
@ -421,11 +421,11 @@ TEST(DisplayListComplexity, DrawAtlas) {
|
||||
bitmap.allocPixels(info, 0);
|
||||
auto image = SkImages::RasterFromBitmap(bitmap);
|
||||
|
||||
std::vector<SkRect> rects;
|
||||
std::vector<SkRSXform> xforms;
|
||||
std::vector<DlRect> rects;
|
||||
std::vector<DlRSTransform> xforms;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
rects.push_back(SkRect::MakeXYWH(0, 0, 10, 10));
|
||||
xforms.push_back(SkRSXform::Make(1, 0, 0, 0));
|
||||
rects.push_back(DlRect::MakeXYWH(0, 0, 10, 10));
|
||||
xforms.push_back(DlRSTransform(1, 0, 0, 0));
|
||||
}
|
||||
|
||||
DisplayListBuilder builder;
|
||||
|
@ -1201,7 +1201,10 @@ TEST_F(DisplayListTest, SingleOpsMightSupportGroupOpacityBlendMode) {
|
||||
kTestImage2, DlIRect::MakeLTRB(20, 20, 30, 30),
|
||||
DlRect::MakeLTRB(0, 0, 20, 20), DlFilterMode::kLinear, nullptr);
|
||||
, true);
|
||||
static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
|
||||
static DlRSTransform xforms[] = {
|
||||
DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(0)),
|
||||
DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(90)),
|
||||
};
|
||||
static DlRect texs[] = {
|
||||
DlRect::MakeLTRB(10, 10, 20, 20),
|
||||
DlRect::MakeLTRB(20, 20, 30, 30),
|
||||
@ -3502,7 +3505,10 @@ TEST_F(DisplayListTest, NopOperationsOmittedFromRecords) {
|
||||
builder.DrawImageNine(kTestImage1, DlIRect::MakeLTRB(10, 10, 20, 20),
|
||||
DlRect::MakeLTRB(10, 10, 100, 100),
|
||||
DlFilterMode::kLinear, &paint);
|
||||
SkRSXform xforms[] = {{1, 0, 10, 10}, {0, 1, 10, 10}};
|
||||
DlRSTransform xforms[] = {
|
||||
DlRSTransform::Make({10.0f, 10.0f}, 1.0f, DlDegrees(0)),
|
||||
DlRSTransform::Make({10.0f, 10.0f}, 1.0f, DlDegrees(90)),
|
||||
};
|
||||
DlRect rects[] = {
|
||||
DlRect::MakeLTRB(10, 10, 20, 20),
|
||||
DlRect::MakeLTRB(10, 20, 30, 20),
|
||||
|
@ -1467,7 +1467,7 @@ void DisplayListBuilder::DrawImageNine(const sk_sp<DlImage>& image,
|
||||
}
|
||||
}
|
||||
void DisplayListBuilder::drawAtlas(const sk_sp<DlImage> atlas,
|
||||
const SkRSXform xform[],
|
||||
const DlRSTransform xform[],
|
||||
const DlRect tex[],
|
||||
const DlColor colors[],
|
||||
int count,
|
||||
@ -1482,19 +1482,20 @@ void DisplayListBuilder::drawAtlas(const sk_sp<DlImage> atlas,
|
||||
if (result == OpResult::kNoEffect) {
|
||||
return;
|
||||
}
|
||||
SkPoint quad[4];
|
||||
DlQuad quad;
|
||||
AccumulationRect accumulator;
|
||||
for (int i = 0; i < count; i++) {
|
||||
const DlRect& src = tex[i];
|
||||
xform[i].toQuad(src.GetWidth(), src.GetHeight(), quad);
|
||||
xform[i].GetQuad(src.GetWidth(), src.GetHeight(), quad);
|
||||
for (int j = 0; j < 4; j++) {
|
||||
accumulator.accumulate(ToDlPoint(quad[j]));
|
||||
accumulator.accumulate(quad[j]);
|
||||
}
|
||||
}
|
||||
if (accumulator.is_empty() ||
|
||||
!AccumulateOpBounds(accumulator.GetBounds(), flags)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Accumulating the bounds might not trip the overlap condition if the
|
||||
// whole atlas operation is separated from other rendering calls, but
|
||||
// since each atlas op is treated as an independent operation, we have
|
||||
@ -1509,7 +1510,7 @@ void DisplayListBuilder::drawAtlas(const sk_sp<DlImage> atlas,
|
||||
current_layer().layer_local_accumulator.record_overlapping_bounds();
|
||||
}
|
||||
|
||||
int bytes = count * (sizeof(SkRSXform) + sizeof(SkRect));
|
||||
int bytes = count * (sizeof(DlRSTransform) + sizeof(DlRect));
|
||||
void* data_ptr;
|
||||
if (colors != nullptr) {
|
||||
bytes += count * sizeof(DlColor);
|
||||
@ -1541,7 +1542,7 @@ void DisplayListBuilder::drawAtlas(const sk_sp<DlImage> atlas,
|
||||
is_ui_thread_safe_ = is_ui_thread_safe_ && atlas->isUIThreadSafe();
|
||||
}
|
||||
void DisplayListBuilder::DrawAtlas(const sk_sp<DlImage>& atlas,
|
||||
const SkRSXform xform[],
|
||||
const DlRSTransform xform[],
|
||||
const DlRect tex[],
|
||||
const DlColor colors[],
|
||||
int count,
|
||||
|
@ -209,7 +209,7 @@ class DisplayListBuilder final : public virtual DlCanvas,
|
||||
const DlPaint* paint = nullptr) override;
|
||||
// |DlCanvas|
|
||||
void DrawAtlas(const sk_sp<DlImage>& atlas,
|
||||
const SkRSXform xform[],
|
||||
const DlRSTransform xform[],
|
||||
const DlRect tex[],
|
||||
const DlColor colors[],
|
||||
int count,
|
||||
@ -471,7 +471,7 @@ class DisplayListBuilder final : public virtual DlCanvas,
|
||||
bool render_with_attributes) override;
|
||||
// |DlOpReceiver|
|
||||
void drawAtlas(const sk_sp<DlImage> atlas,
|
||||
const SkRSXform xform[],
|
||||
const DlRSTransform xform[],
|
||||
const DlRect tex[],
|
||||
const DlColor colors[],
|
||||
int count,
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include "third_party/skia/include/core/SkMatrix.h"
|
||||
#include "third_party/skia/include/core/SkPath.h"
|
||||
#include "third_party/skia/include/core/SkRRect.h"
|
||||
#include "third_party/skia/include/core/SkRSXform.h"
|
||||
#include "third_party/skia/include/core/SkRect.h"
|
||||
#include "third_party/skia/include/core/SkTextBlob.h"
|
||||
|
||||
@ -189,7 +188,7 @@ class DlCanvas {
|
||||
DlFilterMode filter,
|
||||
const DlPaint* paint = nullptr) = 0;
|
||||
virtual void DrawAtlas(const sk_sp<DlImage>& atlas,
|
||||
const SkRSXform xform[],
|
||||
const DlRSTransform xform[],
|
||||
const DlRect tex[],
|
||||
const DlColor colors[],
|
||||
int count,
|
||||
@ -373,18 +372,6 @@ class DlCanvas {
|
||||
const DlPaint* paint = nullptr) {
|
||||
DrawImageNine(image, ToDlIRect(center), ToDlRect(dst), filter, paint);
|
||||
}
|
||||
void DrawAtlas(const sk_sp<DlImage>& atlas,
|
||||
const SkRSXform xform[],
|
||||
const SkRect tex[],
|
||||
const DlColor colors[],
|
||||
int count,
|
||||
DlBlendMode mode,
|
||||
DlImageSampling sampling,
|
||||
const SkRect* cullRect,
|
||||
const DlPaint* paint = nullptr) {
|
||||
DrawAtlas(atlas, xform, ToDlRects(tex), colors, count, mode, sampling,
|
||||
ToDlRect(cullRect), paint);
|
||||
}
|
||||
void DrawShadow(const SkPath& path,
|
||||
const DlColor color,
|
||||
const DlScalar elevation,
|
||||
|
@ -345,7 +345,7 @@ class DlOpReceiver {
|
||||
DlFilterMode filter,
|
||||
bool render_with_attributes) = 0;
|
||||
virtual void drawAtlas(const sk_sp<DlImage> atlas,
|
||||
const SkRSXform xform[],
|
||||
const DlRSTransform xform[],
|
||||
const DlRect tex[],
|
||||
const DlColor colors[],
|
||||
int count,
|
||||
|
@ -15,7 +15,6 @@
|
||||
|
||||
#include "flutter/impeller/geometry/path.h"
|
||||
#include "flutter/impeller/typographer/text_frame.h"
|
||||
#include "third_party/skia/include/core/SkRSXform.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
@ -841,7 +840,7 @@ DEFINE_DRAW_IMAGE_NINE_OP(DrawImageNineWithAttr, true)
|
||||
// 4 byte header + 40 byte payload uses 44 bytes but is rounded up to 48 bytes
|
||||
// (4 bytes unused)
|
||||
// Each of these is then followed by a number of lists.
|
||||
// SkRSXform list is a multiple of 16 bytes so it is always packed well
|
||||
// DlRSTransform list is a multiple of 16 bytes so it is always packed well
|
||||
// DlRect list is also a multiple of 16 bytes so it also packs well
|
||||
// DlColor list only packs well if the count is even, otherwise there
|
||||
// can be 4 unusued bytes at the end.
|
||||
@ -876,7 +875,7 @@ struct DrawAtlasBaseOp : DrawOpBase {
|
||||
render_with_attributes == other->render_with_attributes &&
|
||||
sampling == other->sampling && atlas->Equals(other->atlas));
|
||||
if (ret) {
|
||||
size_t bytes = count * (sizeof(SkRSXform) + sizeof(DlRect));
|
||||
size_t bytes = count * (sizeof(DlRSTransform) + sizeof(DlRect));
|
||||
if (has_colors) {
|
||||
bytes += count * sizeof(DlColor);
|
||||
}
|
||||
@ -906,7 +905,8 @@ struct DrawAtlasOp final : DrawAtlasBaseOp {
|
||||
render_with_attributes) {}
|
||||
|
||||
void dispatch(DlOpReceiver& receiver) const {
|
||||
const SkRSXform* xform = reinterpret_cast<const SkRSXform*>(this + 1);
|
||||
const DlRSTransform* xform =
|
||||
reinterpret_cast<const DlRSTransform*>(this + 1);
|
||||
const DlRect* tex = reinterpret_cast<const DlRect*>(xform + count);
|
||||
const DlColor* colors =
|
||||
has_colors ? reinterpret_cast<const DlColor*>(tex + count) : nullptr;
|
||||
@ -950,7 +950,8 @@ struct DrawAtlasCulledOp final : DrawAtlasBaseOp {
|
||||
const DlRect cull_rect;
|
||||
|
||||
void dispatch(DlOpReceiver& receiver) const {
|
||||
const SkRSXform* xform = reinterpret_cast<const SkRSXform*>(this + 1);
|
||||
const DlRSTransform* xform =
|
||||
reinterpret_cast<const DlRSTransform*>(this + 1);
|
||||
const DlRect* tex = reinterpret_cast<const DlRect*>(xform + count);
|
||||
const DlColor* colors =
|
||||
has_colors ? reinterpret_cast<const DlColor*>(tex + count) : nullptr;
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "flutter/impeller/geometry/path.h"
|
||||
#include "flutter/impeller/geometry/rect.h"
|
||||
#include "flutter/impeller/geometry/round_rect.h"
|
||||
#include "flutter/impeller/geometry/rstransform.h"
|
||||
#include "flutter/impeller/geometry/scalar.h"
|
||||
|
||||
#include "flutter/third_party/skia/include/core/SkM44.h"
|
||||
@ -34,6 +35,7 @@ using DlRoundRect = impeller::RoundRect;
|
||||
using DlRoundingRadii = impeller::RoundingRadii;
|
||||
using DlMatrix = impeller::Matrix;
|
||||
using DlQuad = impeller::Quad;
|
||||
using DlRSTransform = impeller::RSTransform;
|
||||
|
||||
static_assert(sizeof(SkPoint) == sizeof(DlPoint));
|
||||
static_assert(sizeof(SkIPoint) == sizeof(DlIPoint));
|
||||
|
@ -296,7 +296,7 @@ void DlSkCanvasAdapter::DrawImageNine(const sk_sp<DlImage>& image,
|
||||
}
|
||||
|
||||
void DlSkCanvasAdapter::DrawAtlas(const sk_sp<DlImage>& atlas,
|
||||
const SkRSXform xform[],
|
||||
const DlRSTransform xform[],
|
||||
const DlRect tex[],
|
||||
const DlColor colors[],
|
||||
int count,
|
||||
@ -311,9 +311,9 @@ void DlSkCanvasAdapter::DrawAtlas(const sk_sp<DlImage>& atlas,
|
||||
for (int i = 0; i < count; ++i) {
|
||||
sk_colors.push_back(colors[i].argb());
|
||||
}
|
||||
delegate_->drawAtlas(sk_image.get(), xform, ToSkRects(tex), sk_colors.data(),
|
||||
count, ToSk(mode), ToSk(sampling), ToSkRect(cullRect),
|
||||
sk_paint());
|
||||
delegate_->drawAtlas(sk_image.get(), ToSk(xform), ToSkRects(tex),
|
||||
sk_colors.data(), count, ToSk(mode), ToSk(sampling),
|
||||
ToSkRect(cullRect), sk_paint());
|
||||
}
|
||||
|
||||
void DlSkCanvasAdapter::DrawDisplayList(const sk_sp<DisplayList> display_list,
|
||||
|
@ -134,7 +134,7 @@ class DlSkCanvasAdapter final : public virtual DlCanvas {
|
||||
DlFilterMode filter,
|
||||
const DlPaint* paint = nullptr) override;
|
||||
void DrawAtlas(const sk_sp<DlImage>& atlas,
|
||||
const SkRSXform xform[],
|
||||
const DlRSTransform xform[],
|
||||
const DlRect tex[],
|
||||
const DlColor colors[],
|
||||
int count,
|
||||
|
@ -120,6 +120,10 @@ inline SkMatrix* ToSk(const DlMatrix* matrix, SkMatrix& scratch) {
|
||||
|
||||
extern sk_sp<SkVertices> ToSk(const std::shared_ptr<DlVertices>& vertices);
|
||||
|
||||
inline const SkRSXform* ToSk(const DlRSTransform* transforms) {
|
||||
return reinterpret_cast<const SkRSXform*>(transforms);
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_DISPLAY_LIST_SKIA_DL_SK_CONVERSIONS_H_
|
||||
|
@ -321,5 +321,56 @@ TEST(DisplayListSkConversions, ToSkDitheringEnabledForGradients) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DisplayListSkConversions, ToSkRSTransform) {
|
||||
constexpr size_t kTransformCount = 4;
|
||||
DlRSTransform transforms[kTransformCount] = {
|
||||
DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(0)),
|
||||
DlRSTransform::Make({12.25f, 14.75f}, 10.0f, DlDegrees(30)),
|
||||
DlRSTransform::Make({-10.4f, 8.25f}, 11.0f, DlDegrees(400)),
|
||||
DlRSTransform::Make({1.0f, 3.0f}, 0.5f, DlDegrees(45)),
|
||||
};
|
||||
SkRSXform expected_transforms[kTransformCount] = {
|
||||
SkRSXform::MakeFromRadians(1.0f, SkDegreesToRadians(0), //
|
||||
0.0f, 0.0f, 0.0f, 0.0f),
|
||||
SkRSXform::MakeFromRadians(10.0f, SkDegreesToRadians(30), //
|
||||
12.25f, 14.75f, 0.0f, 0.0f),
|
||||
SkRSXform::MakeFromRadians(11.0f, SkDegreesToRadians(400), //
|
||||
-10.4f, 8.25f, 0.0f, 0.0f),
|
||||
SkRSXform::MakeFromRadians(0.5f, SkDegreesToRadians(45), //
|
||||
1.0f, 3.0f, 0.0f, 0.0f),
|
||||
};
|
||||
auto sk_transforms = ToSk(transforms);
|
||||
for (size_t i = 0; i < kTransformCount; i++) {
|
||||
// Comparing dl values to transformed copy values
|
||||
// should match exactly because arrays were simply aliased
|
||||
EXPECT_EQ(sk_transforms[i].fSCos, transforms[i].scaled_cos) << i;
|
||||
EXPECT_EQ(sk_transforms[i].fSSin, transforms[i].scaled_sin) << i;
|
||||
EXPECT_EQ(sk_transforms[i].fTx, transforms[i].translate_x) << i;
|
||||
EXPECT_EQ(sk_transforms[i].fTy, transforms[i].translate_y) << i;
|
||||
|
||||
// Comparing dl values to computed Skia values
|
||||
// should match closely, but not exactly due to differences in trig
|
||||
EXPECT_FLOAT_EQ(sk_transforms[i].fSCos, expected_transforms[i].fSCos) << i;
|
||||
EXPECT_FLOAT_EQ(sk_transforms[i].fSSin, expected_transforms[i].fSSin) << i;
|
||||
EXPECT_EQ(sk_transforms[i].fTx, expected_transforms[i].fTx) << i;
|
||||
EXPECT_EQ(sk_transforms[i].fTy, expected_transforms[i].fTy) << i;
|
||||
|
||||
// Comparing the results of transforming a sprite with Skia vs Impeller
|
||||
SkPoint sk_quad[4];
|
||||
expected_transforms[i].toQuad(20, 30, sk_quad);
|
||||
DlQuad dl_quad;
|
||||
transforms[i].GetQuad(20, 30, dl_quad);
|
||||
// Skia order is UL,UR,LR,LL, Impeller order is UL,UR,LL,LR
|
||||
EXPECT_FLOAT_EQ(sk_quad[0].fX, dl_quad[0].x) << i;
|
||||
EXPECT_FLOAT_EQ(sk_quad[0].fY, dl_quad[0].y) << i;
|
||||
EXPECT_FLOAT_EQ(sk_quad[1].fX, dl_quad[1].x) << i;
|
||||
EXPECT_FLOAT_EQ(sk_quad[1].fY, dl_quad[1].y) << i;
|
||||
EXPECT_FLOAT_EQ(sk_quad[2].fX, dl_quad[3].x) << i;
|
||||
EXPECT_FLOAT_EQ(sk_quad[2].fY, dl_quad[3].y) << i;
|
||||
EXPECT_FLOAT_EQ(sk_quad[3].fX, dl_quad[2].x) << i;
|
||||
EXPECT_FLOAT_EQ(sk_quad[3].fY, dl_quad[2].y) << i;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace flutter
|
||||
|
@ -245,7 +245,7 @@ void DlSkCanvasDispatcher::drawImageNine(const sk_sp<DlImage> image,
|
||||
ToSk(filter), safe_paint(render_with_attributes));
|
||||
}
|
||||
void DlSkCanvasDispatcher::drawAtlas(const sk_sp<DlImage> atlas,
|
||||
const SkRSXform xform[],
|
||||
const DlRSTransform xform[],
|
||||
const DlRect tex[],
|
||||
const DlColor colors[],
|
||||
int count,
|
||||
@ -267,7 +267,7 @@ void DlSkCanvasDispatcher::drawAtlas(const sk_sp<DlImage> atlas,
|
||||
sk_colors.push_back(colors[i].argb());
|
||||
}
|
||||
}
|
||||
canvas_->drawAtlas(skia_atlas.get(), xform, ToSkRects(tex),
|
||||
canvas_->drawAtlas(skia_atlas.get(), ToSk(xform), ToSkRects(tex),
|
||||
sk_colors.empty() ? nullptr : sk_colors.data(), count,
|
||||
ToSk(mode), ToSk(sampling), ToSkRect(cullRect),
|
||||
safe_paint(render_with_attributes));
|
||||
|
@ -95,7 +95,7 @@ class DlSkCanvasDispatcher : public virtual DlOpReceiver,
|
||||
DlFilterMode filter,
|
||||
bool render_with_attributes) override;
|
||||
void drawAtlas(const sk_sp<DlImage> atlas,
|
||||
const SkRSXform xform[],
|
||||
const DlRSTransform xform[],
|
||||
const DlRect tex[],
|
||||
const DlColor colors[],
|
||||
int count,
|
||||
|
@ -3584,7 +3584,15 @@ TEST_F(DisplayListRendering, DrawImageNineLinear) {
|
||||
}
|
||||
|
||||
TEST_F(DisplayListRendering, DrawAtlasNearest) {
|
||||
const SkRSXform xform[] = {
|
||||
const SkRSXform sk_xform[] = {
|
||||
// clang-format off
|
||||
{ 1.2f, 0.0f, kRenderLeft, kRenderTop},
|
||||
{ 0.0f, 1.2f, kRenderRight, kRenderTop},
|
||||
{-1.2f, 0.0f, kRenderRight, kRenderBottom},
|
||||
{ 0.0f, -1.2f, kRenderLeft, kRenderBottom},
|
||||
// clang-format on
|
||||
};
|
||||
const DlRSTransform dl_xform[] = {
|
||||
// clang-format off
|
||||
{ 1.2f, 0.0f, kRenderLeft, kRenderTop},
|
||||
{ 0.0f, 1.2f, kRenderRight, kRenderTop},
|
||||
@ -3617,20 +3625,28 @@ TEST_F(DisplayListRendering, DrawAtlasNearest) {
|
||||
CanvasCompareTester::RenderAll( //
|
||||
TestParameters(
|
||||
[=](const SkRenderContext& ctx) {
|
||||
ctx.canvas->drawAtlas(ctx.image.get(), xform, tex, sk_colors, 4,
|
||||
ctx.canvas->drawAtlas(ctx.image.get(), sk_xform, tex, sk_colors, 4,
|
||||
SkBlendMode::kSrcOver, sk_sampling, nullptr,
|
||||
&ctx.paint);
|
||||
},
|
||||
[=](const DlRenderContext& ctx) {
|
||||
ctx.canvas->DrawAtlas(ctx.image, xform, tex, dl_colors, 4,
|
||||
DlBlendMode::kSrcOver, dl_sampling, nullptr,
|
||||
&ctx.paint);
|
||||
ctx.canvas->DrawAtlas(ctx.image, dl_xform, ToDlRects(tex),
|
||||
dl_colors, 4, DlBlendMode::kSrcOver,
|
||||
dl_sampling, nullptr, &ctx.paint);
|
||||
},
|
||||
kDrawAtlasWithPaintFlags));
|
||||
}
|
||||
|
||||
TEST_F(DisplayListRendering, DrawAtlasNearestNoPaint) {
|
||||
const SkRSXform xform[] = {
|
||||
const SkRSXform sk_xform[] = {
|
||||
// clang-format off
|
||||
{ 1.2f, 0.0f, kRenderLeft, kRenderTop},
|
||||
{ 0.0f, 1.2f, kRenderRight, kRenderTop},
|
||||
{-1.2f, 0.0f, kRenderRight, kRenderBottom},
|
||||
{ 0.0f, -1.2f, kRenderLeft, kRenderBottom},
|
||||
// clang-format on
|
||||
};
|
||||
const DlRSTransform dl_xform[] = {
|
||||
// clang-format off
|
||||
{ 1.2f, 0.0f, kRenderLeft, kRenderTop},
|
||||
{ 0.0f, 1.2f, kRenderRight, kRenderTop},
|
||||
@ -3663,20 +3679,28 @@ TEST_F(DisplayListRendering, DrawAtlasNearestNoPaint) {
|
||||
CanvasCompareTester::RenderAll( //
|
||||
TestParameters(
|
||||
[=](const SkRenderContext& ctx) {
|
||||
ctx.canvas->drawAtlas(ctx.image.get(), xform, tex, sk_colors, 4,
|
||||
ctx.canvas->drawAtlas(ctx.image.get(), sk_xform, tex, sk_colors, 4,
|
||||
SkBlendMode::kSrcOver, sk_sampling, //
|
||||
nullptr, nullptr);
|
||||
},
|
||||
[=](const DlRenderContext& ctx) {
|
||||
ctx.canvas->DrawAtlas(ctx.image, xform, tex, dl_colors, 4,
|
||||
DlBlendMode::kSrcOver, dl_sampling, //
|
||||
nullptr, nullptr);
|
||||
ctx.canvas->DrawAtlas(ctx.image, dl_xform, ToDlRects(tex),
|
||||
dl_colors, 4, DlBlendMode::kSrcOver,
|
||||
dl_sampling, nullptr, nullptr);
|
||||
},
|
||||
kDrawAtlasFlags));
|
||||
}
|
||||
|
||||
TEST_F(DisplayListRendering, DrawAtlasLinear) {
|
||||
const SkRSXform xform[] = {
|
||||
const SkRSXform sk_xform[] = {
|
||||
// clang-format off
|
||||
{ 1.2f, 0.0f, kRenderLeft, kRenderTop},
|
||||
{ 0.0f, 1.2f, kRenderRight, kRenderTop},
|
||||
{-1.2f, 0.0f, kRenderRight, kRenderBottom},
|
||||
{ 0.0f, -1.2f, kRenderLeft, kRenderBottom},
|
||||
// clang-format on
|
||||
};
|
||||
const DlRSTransform dl_xform[] = {
|
||||
// clang-format off
|
||||
{ 1.2f, 0.0f, kRenderLeft, kRenderTop},
|
||||
{ 0.0f, 1.2f, kRenderRight, kRenderTop},
|
||||
@ -3709,14 +3733,14 @@ TEST_F(DisplayListRendering, DrawAtlasLinear) {
|
||||
CanvasCompareTester::RenderAll( //
|
||||
TestParameters(
|
||||
[=](const SkRenderContext& ctx) {
|
||||
ctx.canvas->drawAtlas(ctx.image.get(), xform, tex, sk_colors, 2,
|
||||
ctx.canvas->drawAtlas(ctx.image.get(), sk_xform, tex, sk_colors, 2,
|
||||
SkBlendMode::kSrcOver, sk_sampling, //
|
||||
nullptr, &ctx.paint);
|
||||
},
|
||||
[=](const DlRenderContext& ctx) {
|
||||
ctx.canvas->DrawAtlas(ctx.image, xform, tex, dl_colors, 2,
|
||||
DlBlendMode::kSrcOver, dl_sampling, //
|
||||
nullptr, &ctx.paint);
|
||||
ctx.canvas->DrawAtlas(ctx.image, dl_xform, ToDlRects(tex),
|
||||
dl_colors, 2, DlBlendMode::kSrcOver,
|
||||
dl_sampling, nullptr, &ctx.paint);
|
||||
},
|
||||
kDrawAtlasWithPaintFlags));
|
||||
}
|
||||
|
@ -943,7 +943,10 @@ std::vector<DisplayListInvocationGroup> CreateAllRenderingOps() {
|
||||
{
|
||||
{1, 48 + 32 + 8, 1,
|
||||
[](DlOpReceiver& r) {
|
||||
static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
|
||||
static DlRSTransform xforms[] = {
|
||||
DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(0)),
|
||||
DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(90)),
|
||||
};
|
||||
static DlRect texs[] = {DlRect::MakeLTRB(10, 10, 20, 20),
|
||||
DlRect::MakeLTRB(20, 20, 30, 30)};
|
||||
r.drawAtlas(kTestImage1, xforms, texs, nullptr, 2,
|
||||
@ -952,7 +955,10 @@ std::vector<DisplayListInvocationGroup> CreateAllRenderingOps() {
|
||||
}},
|
||||
{1, 48 + 32 + 8, 1,
|
||||
[](DlOpReceiver& r) {
|
||||
static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
|
||||
static DlRSTransform xforms[] = {
|
||||
DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(0)),
|
||||
DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(90)),
|
||||
};
|
||||
static DlRect texs[] = {DlRect::MakeLTRB(10, 10, 20, 20),
|
||||
DlRect::MakeLTRB(20, 20, 30, 30)};
|
||||
r.drawAtlas(kTestImage1, xforms, texs, nullptr, 2,
|
||||
@ -960,7 +966,10 @@ std::vector<DisplayListInvocationGroup> CreateAllRenderingOps() {
|
||||
}},
|
||||
{1, 48 + 32 + 8, 1,
|
||||
[](DlOpReceiver& r) {
|
||||
static SkRSXform xforms[] = {{0, 1, 0, 0}, {0, 1, 0, 0}};
|
||||
static DlRSTransform xforms[] = {
|
||||
DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(0)),
|
||||
DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(45)),
|
||||
};
|
||||
static DlRect texs[] = {DlRect::MakeLTRB(10, 10, 20, 20),
|
||||
DlRect::MakeLTRB(20, 20, 30, 30)};
|
||||
r.drawAtlas(kTestImage1, xforms, texs, nullptr, 2,
|
||||
@ -969,7 +978,10 @@ std::vector<DisplayListInvocationGroup> CreateAllRenderingOps() {
|
||||
}},
|
||||
{1, 48 + 32 + 8, 1,
|
||||
[](DlOpReceiver& r) {
|
||||
static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
|
||||
static DlRSTransform xforms[] = {
|
||||
DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(0)),
|
||||
DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(90)),
|
||||
};
|
||||
static DlRect texs[] = {DlRect::MakeLTRB(10, 10, 20, 20),
|
||||
DlRect::MakeLTRB(20, 25, 30, 30)};
|
||||
r.drawAtlas(kTestImage1, xforms, texs, nullptr, 2,
|
||||
@ -978,7 +990,10 @@ std::vector<DisplayListInvocationGroup> CreateAllRenderingOps() {
|
||||
}},
|
||||
{1, 48 + 32 + 8, 1,
|
||||
[](DlOpReceiver& r) {
|
||||
static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
|
||||
static DlRSTransform xforms[] = {
|
||||
DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(0)),
|
||||
DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(90)),
|
||||
};
|
||||
static DlRect texs[] = {DlRect::MakeLTRB(10, 10, 20, 20),
|
||||
DlRect::MakeLTRB(20, 20, 30, 30)};
|
||||
r.drawAtlas(kTestImage1, xforms, texs, nullptr, 2,
|
||||
@ -986,7 +1001,10 @@ std::vector<DisplayListInvocationGroup> CreateAllRenderingOps() {
|
||||
}},
|
||||
{1, 48 + 32 + 8, 1,
|
||||
[](DlOpReceiver& r) {
|
||||
static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
|
||||
static DlRSTransform xforms[] = {
|
||||
DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(0)),
|
||||
DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(90)),
|
||||
};
|
||||
static DlRect texs[] = {DlRect::MakeLTRB(10, 10, 20, 20),
|
||||
DlRect::MakeLTRB(20, 20, 30, 30)};
|
||||
r.drawAtlas(kTestImage1, xforms, texs, nullptr, 2,
|
||||
@ -995,7 +1013,10 @@ std::vector<DisplayListInvocationGroup> CreateAllRenderingOps() {
|
||||
}},
|
||||
{1, 64 + 32 + 8, 1,
|
||||
[](DlOpReceiver& r) {
|
||||
static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
|
||||
static DlRSTransform xforms[] = {
|
||||
DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(0)),
|
||||
DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(90)),
|
||||
};
|
||||
static DlRect texs[] = {DlRect::MakeLTRB(10, 10, 20, 20),
|
||||
DlRect::MakeLTRB(20, 20, 30, 30)};
|
||||
static DlRect cull_rect = DlRect::MakeLTRB(0, 0, 200, 200);
|
||||
@ -1005,7 +1026,10 @@ std::vector<DisplayListInvocationGroup> CreateAllRenderingOps() {
|
||||
}},
|
||||
{1, 128, 1,
|
||||
[](DlOpReceiver& r) {
|
||||
static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
|
||||
static DlRSTransform xforms[] = {
|
||||
DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(0)),
|
||||
DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(90)),
|
||||
};
|
||||
static DlRect texs[] = {DlRect::MakeLTRB(10, 10, 20, 20),
|
||||
DlRect::MakeLTRB(20, 20, 30, 30)};
|
||||
static DlColor colors[] = {DlColor::kBlue(), DlColor::kGreen()};
|
||||
@ -1015,7 +1039,10 @@ std::vector<DisplayListInvocationGroup> CreateAllRenderingOps() {
|
||||
}},
|
||||
{1, 144, 1,
|
||||
[](DlOpReceiver& r) {
|
||||
static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
|
||||
static DlRSTransform xforms[] = {
|
||||
DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(0)),
|
||||
DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(90)),
|
||||
};
|
||||
static DlRect texs[] = {DlRect::MakeLTRB(10, 10, 20, 20),
|
||||
DlRect::MakeLTRB(20, 20, 30, 30)};
|
||||
static DlColor colors[] = {DlColor::kBlue(), DlColor::kGreen()};
|
||||
@ -1027,7 +1054,10 @@ std::vector<DisplayListInvocationGroup> CreateAllRenderingOps() {
|
||||
{1, 48 + 32 + 8, 1,
|
||||
[](DlOpReceiver& r) {
|
||||
auto dl_image = DlImage::Make(kTestSkImage);
|
||||
static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
|
||||
static DlRSTransform xforms[] = {
|
||||
DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(0)),
|
||||
DlRSTransform::Make({0.0f, 0.0f}, 1.0f, DlDegrees(90)),
|
||||
};
|
||||
static DlRect texs[] = {DlRect::MakeLTRB(10, 10, 20, 20),
|
||||
DlRect::MakeLTRB(20, 20, 30, 30)};
|
||||
r.drawAtlas(dl_image, xforms, texs, nullptr, 2,
|
||||
|
@ -124,7 +124,7 @@ class IgnoreDrawDispatchHelper : public virtual DlOpReceiver {
|
||||
DlFilterMode filter,
|
||||
bool render_with_attributes) override {}
|
||||
void drawAtlas(const sk_sp<DlImage> atlas,
|
||||
const SkRSXform xform[],
|
||||
const DlRSTransform xform[],
|
||||
const DlRect tex[],
|
||||
const DlColor colors[],
|
||||
int count,
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include "impeller/entity/contents/content_context.h"
|
||||
#include "impeller/geometry/color.h"
|
||||
#include "impeller/geometry/scalar.h"
|
||||
#include "include/core/SkRSXform.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
|
||||
namespace impeller {
|
||||
@ -25,34 +24,14 @@ namespace testing {
|
||||
using namespace flutter;
|
||||
|
||||
namespace {
|
||||
SkRSXform MakeTranslation(Scalar tx, Scalar ty) {
|
||||
return SkRSXform::Make(1, 0, tx, ty);
|
||||
RSTransform MakeTranslation(Scalar tx, Scalar ty) {
|
||||
return RSTransform::Make({tx, ty}, 1, DlDegrees(0));
|
||||
}
|
||||
|
||||
std::tuple<std::vector<SkRect>, std::vector<SkRSXform>, sk_sp<DlImageImpeller>>
|
||||
std::tuple<std::vector<DlRect>, //
|
||||
std::vector<RSTransform>, //
|
||||
sk_sp<DlImageImpeller>>
|
||||
CreateTestData(const AiksTest* test) {
|
||||
// Draws the image as four squares stiched together.
|
||||
auto atlas =
|
||||
DlImageImpeller::Make(test->CreateTextureForFixture("bay_bridge.jpg"));
|
||||
auto size = atlas->impeller_texture()->GetSize();
|
||||
// Divide image into four quadrants.
|
||||
Scalar half_width = size.width / 2;
|
||||
Scalar half_height = size.height / 2;
|
||||
std::vector<SkRect> texture_coordinates = {
|
||||
SkRect::MakeLTRB(0, 0, half_width, half_height),
|
||||
SkRect::MakeLTRB(half_width, 0, size.width, half_height),
|
||||
SkRect::MakeLTRB(0, half_height, half_width, size.height),
|
||||
SkRect::MakeLTRB(half_width, half_height, size.width, size.height)};
|
||||
// Position quadrants adjacent to eachother.
|
||||
std::vector<SkRSXform> transforms = {
|
||||
MakeTranslation(0, 0), MakeTranslation(half_width, 0),
|
||||
MakeTranslation(0, half_height),
|
||||
MakeTranslation(half_width, half_height)};
|
||||
return std::make_tuple(texture_coordinates, transforms, atlas);
|
||||
}
|
||||
|
||||
std::tuple<std::vector<DlRect>, std::vector<SkRSXform>, sk_sp<DlImageImpeller>>
|
||||
CreateDlTestData(const AiksTest* test) {
|
||||
// Draws the image as four squares stiched together.
|
||||
auto atlas =
|
||||
DlImageImpeller::Make(test->CreateTextureForFixture("bay_bridge.jpg"));
|
||||
@ -66,7 +45,7 @@ CreateDlTestData(const AiksTest* test) {
|
||||
DlRect::MakeLTRB(0, half_height, half_width, size.height),
|
||||
DlRect::MakeLTRB(half_width, half_height, size.width, size.height)};
|
||||
// Position quadrants adjacent to eachother.
|
||||
std::vector<SkRSXform> transforms = {
|
||||
std::vector<RSTransform> transforms = {
|
||||
MakeTranslation(0, 0), MakeTranslation(half_width, 0),
|
||||
MakeTranslation(0, half_height),
|
||||
MakeTranslation(half_width, half_height)};
|
||||
@ -138,9 +117,9 @@ TEST_P(AiksTest, DrawAtlasWithOpacity) {
|
||||
TEST_P(AiksTest, DrawAtlasNoColorFullSize) {
|
||||
auto atlas = DlImageImpeller::Make(CreateTextureForFixture("bay_bridge.jpg"));
|
||||
auto size = atlas->impeller_texture()->GetSize();
|
||||
std::vector<SkRect> texture_coordinates = {
|
||||
SkRect::MakeLTRB(0, 0, size.width, size.height)};
|
||||
std::vector<SkRSXform> transforms = {MakeTranslation(0, 0)};
|
||||
std::vector<DlRect> texture_coordinates = {
|
||||
DlRect::MakeLTRB(0, 0, size.width, size.height)};
|
||||
std::vector<RSTransform> transforms = {MakeTranslation(0, 0)};
|
||||
|
||||
DisplayListBuilder builder;
|
||||
builder.Scale(GetContentScale().x, GetContentScale().y);
|
||||
@ -199,7 +178,7 @@ TEST_P(AiksTest, DrawAtlasPlusWideGamut) {
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, DlAtlasGeometryNoBlend) {
|
||||
auto [texture_coordinates, transforms, atlas] = CreateDlTestData(this);
|
||||
auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
|
||||
|
||||
DlAtlasGeometry geom(atlas->impeller_texture(), transforms.data(),
|
||||
texture_coordinates.data(), nullptr, transforms.size(),
|
||||
@ -217,7 +196,7 @@ TEST_P(AiksTest, DlAtlasGeometryNoBlend) {
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, DlAtlasGeometryBlend) {
|
||||
auto [texture_coordinates, transforms, atlas] = CreateDlTestData(this);
|
||||
auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
|
||||
|
||||
std::vector<DlColor> colors;
|
||||
colors.reserve(texture_coordinates.size());
|
||||
@ -241,7 +220,7 @@ TEST_P(AiksTest, DlAtlasGeometryBlend) {
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, DlAtlasGeometryColorButNoBlend) {
|
||||
auto [texture_coordinates, transforms, atlas] = CreateDlTestData(this);
|
||||
auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
|
||||
|
||||
std::vector<DlColor> colors;
|
||||
colors.reserve(texture_coordinates.size());
|
||||
@ -258,7 +237,7 @@ TEST_P(AiksTest, DlAtlasGeometryColorButNoBlend) {
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, DlAtlasGeometrySkip) {
|
||||
auto [texture_coordinates, transforms, atlas] = CreateDlTestData(this);
|
||||
auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
|
||||
|
||||
std::vector<DlColor> colors;
|
||||
colors.reserve(texture_coordinates.size());
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include "include/core/SkCanvas.h"
|
||||
#include "include/core/SkMatrix.h"
|
||||
#include "include/core/SkPath.h"
|
||||
#include "include/core/SkRSXform.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
|
||||
namespace impeller {
|
||||
|
@ -16,7 +16,7 @@
|
||||
namespace impeller {
|
||||
|
||||
DlAtlasGeometry::DlAtlasGeometry(const std::shared_ptr<Texture>& atlas,
|
||||
const SkRSXform* xform,
|
||||
const RSTransform* xform,
|
||||
const flutter::DlRect* tex,
|
||||
const flutter::DlColor* colors,
|
||||
size_t count,
|
||||
@ -46,12 +46,10 @@ Rect DlAtlasGeometry::ComputeBoundingBox() const {
|
||||
if (cull_rect_.has_value()) {
|
||||
return cull_rect_.value();
|
||||
}
|
||||
Rect bounding_box = {};
|
||||
Rect bounding_box;
|
||||
for (size_t i = 0; i < count_; i++) {
|
||||
auto matrix = skia_conversions::ToRSXForm(xform_[i]);
|
||||
auto sample_rect = tex_[i];
|
||||
auto bounds = Rect::MakeSize(sample_rect.GetSize()).TransformBounds(matrix);
|
||||
bounding_box = bounds.Union(bounding_box);
|
||||
auto bounds = xform_[i].GetBounds(tex_[i].GetSize());
|
||||
bounding_box = Rect::Union(bounding_box, bounds);
|
||||
}
|
||||
cull_rect_ = bounding_box;
|
||||
return bounding_box;
|
||||
@ -84,10 +82,8 @@ VertexBuffer DlAtlasGeometry::CreateSimpleVertexBuffer(
|
||||
auto texture_size = atlas_->GetSize();
|
||||
for (auto i = 0u; i < count_; i++) {
|
||||
flutter::DlRect sample_rect = tex_[i];
|
||||
Matrix matrix = skia_conversions::ToRSXForm(xform_[i]);
|
||||
auto points = sample_rect.GetPoints();
|
||||
auto transformed_points = Rect::MakeSize(sample_rect.GetSize())
|
||||
.GetTransformedPoints(matrix);
|
||||
auto transformed_points = xform_[i].GetQuad(sample_rect.GetSize());
|
||||
for (size_t j = 0; j < 6; j++) {
|
||||
data[offset].position = transformed_points[indices[j]];
|
||||
data[offset].texture_coords = points[indices[j]] / texture_size;
|
||||
@ -119,10 +115,8 @@ VertexBuffer DlAtlasGeometry::CreateBlendVertexBuffer(
|
||||
auto texture_size = atlas_->GetSize();
|
||||
for (auto i = 0u; i < count_; i++) {
|
||||
flutter::DlRect sample_rect = tex_[i];
|
||||
Matrix matrix = skia_conversions::ToRSXForm(xform_[i]);
|
||||
auto points = sample_rect.GetPoints();
|
||||
auto transformed_points = Rect::MakeSize(sample_rect.GetSize())
|
||||
.GetTransformedPoints(matrix);
|
||||
auto transformed_points = xform_[i].GetQuad(sample_rect.GetSize());
|
||||
for (size_t j = 0; j < 6; j++) {
|
||||
data[offset].vertices = transformed_points[indices[j]];
|
||||
data[offset].texture_coords = points[indices[j]] / texture_size;
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "impeller/core/sampler_descriptor.h"
|
||||
#include "impeller/entity/contents/atlas_contents.h"
|
||||
#include "impeller/geometry/color.h"
|
||||
#include "include/core/SkRSXform.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
@ -18,7 +17,7 @@ namespace impeller {
|
||||
class DlAtlasGeometry : public AtlasGeometry {
|
||||
public:
|
||||
DlAtlasGeometry(const std::shared_ptr<Texture>& atlas,
|
||||
const SkRSXform* xform,
|
||||
const RSTransform* xform,
|
||||
const flutter::DlRect* tex,
|
||||
const flutter::DlColor* colors,
|
||||
size_t count,
|
||||
@ -47,7 +46,7 @@ class DlAtlasGeometry : public AtlasGeometry {
|
||||
|
||||
private:
|
||||
const std::shared_ptr<Texture> atlas_;
|
||||
const SkRSXform* xform_;
|
||||
const RSTransform* xform_;
|
||||
const flutter::DlRect* tex_;
|
||||
const flutter::DlColor* colors_;
|
||||
size_t count_;
|
||||
|
@ -774,7 +774,7 @@ void DlDispatcherBase::drawImageNine(const sk_sp<flutter::DlImage> image,
|
||||
|
||||
// |flutter::DlOpReceiver|
|
||||
void DlDispatcherBase::drawAtlas(const sk_sp<flutter::DlImage> atlas,
|
||||
const SkRSXform xform[],
|
||||
const RSTransform xform[],
|
||||
const DlRect tex[],
|
||||
const flutter::DlColor colors[],
|
||||
int count,
|
||||
|
@ -209,7 +209,7 @@ class DlDispatcherBase : public flutter::DlOpReceiver {
|
||||
|
||||
// |flutter::DlOpReceiver|
|
||||
void drawAtlas(const sk_sp<flutter::DlImage> atlas,
|
||||
const SkRSXform xform[],
|
||||
const RSTransform xform[],
|
||||
const DlRect tex[],
|
||||
const flutter::DlColor colors[],
|
||||
int count,
|
||||
|
@ -97,17 +97,6 @@ Color ToColor(const flutter::DlColor& color) {
|
||||
};
|
||||
}
|
||||
|
||||
Matrix ToRSXForm(const SkRSXform& form) {
|
||||
// clang-format off
|
||||
return Matrix{
|
||||
form.fSCos, form.fSSin, 0, 0,
|
||||
-form.fSSin, form.fSCos, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
form.fTx, form.fTy, 0, 1
|
||||
};
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
std::optional<impeller::PixelFormat> ToPixelFormat(SkColorType type) {
|
||||
switch (type) {
|
||||
case kRGBA_8888_SkColorType:
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "third_party/skia/include/core/SkPath.h"
|
||||
#include "third_party/skia/include/core/SkPoint.h"
|
||||
#include "third_party/skia/include/core/SkRRect.h"
|
||||
#include "third_party/skia/include/core/SkRSXform.h"
|
||||
#include "third_party/skia/include/core/SkTextBlob.h"
|
||||
|
||||
namespace impeller {
|
||||
@ -49,8 +48,6 @@ Size ToSize(const SkPoint& point);
|
||||
|
||||
Color ToColor(const flutter::DlColor& color);
|
||||
|
||||
Matrix ToRSXForm(const SkRSXform& form);
|
||||
|
||||
std::optional<impeller::PixelFormat> ToPixelFormat(SkColorType type);
|
||||
|
||||
impeller::SamplerDescriptor ToSamplerDescriptor(
|
||||
|
@ -33,6 +33,8 @@ impeller_component("geometry") {
|
||||
"round_rect.h",
|
||||
"rounding_radii.cc",
|
||||
"rounding_radii.h",
|
||||
"rstransform.cc",
|
||||
"rstransform.h",
|
||||
"saturated_math.h",
|
||||
"scalar.h",
|
||||
"separated_vector.cc",
|
||||
@ -76,6 +78,7 @@ impeller_component("geometry_unittests") {
|
||||
"path_unittests.cc",
|
||||
"rect_unittests.cc",
|
||||
"round_rect_unittests.cc",
|
||||
"rstransform_unittests.cc",
|
||||
"saturated_math_unittests.cc",
|
||||
"size_unittests.cc",
|
||||
"trig_unittests.cc",
|
||||
|
@ -602,7 +602,6 @@ struct Matrix {
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr Vector2 CosSin(Radians radians) {
|
||||
// The precision of a float around 1.0 is much lower than it is
|
||||
// around 0.0, so we end up with cases on quadrant rotations where
|
||||
|
@ -703,15 +703,13 @@ struct TRect {
|
||||
saturated::Cast<U, Type>(round(r.GetBottom())));
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr static std::optional<TRect> Union(
|
||||
const TRect& a,
|
||||
const std::optional<TRect> b) {
|
||||
[[nodiscard]] constexpr static TRect Union(const TRect& a,
|
||||
const std::optional<TRect> b) {
|
||||
return b.has_value() ? a.Union(b.value()) : a;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr static std::optional<TRect> Union(
|
||||
const std::optional<TRect> a,
|
||||
const TRect& b) {
|
||||
[[nodiscard]] constexpr static TRect Union(const std::optional<TRect> a,
|
||||
const TRect& b) {
|
||||
return a.has_value() ? a->Union(b) : b;
|
||||
}
|
||||
|
||||
|
@ -1457,16 +1457,14 @@ TEST(RectTest, OptRectUnion) {
|
||||
|
||||
auto test1 = [](const Rect& r) {
|
||||
// Rect, NullOpt
|
||||
EXPECT_TRUE(Rect::Union(r, std::nullopt).has_value());
|
||||
EXPECT_EQ(Rect::Union(r, std::nullopt).value(), r);
|
||||
EXPECT_EQ(Rect::Union(r, std::nullopt), r);
|
||||
|
||||
// OptRect, NullOpt
|
||||
EXPECT_TRUE(Rect::Union(std::optional(r), std::nullopt).has_value());
|
||||
EXPECT_EQ(Rect::Union(std::optional(r), std::nullopt).value(), r);
|
||||
|
||||
// NullOpt, Rect
|
||||
EXPECT_TRUE(Rect::Union(std::nullopt, r).has_value());
|
||||
EXPECT_EQ(Rect::Union(std::nullopt, r).value(), r);
|
||||
EXPECT_EQ(Rect::Union(std::nullopt, r), r);
|
||||
|
||||
// NullOpt, OptRect
|
||||
EXPECT_TRUE(Rect::Union(std::nullopt, std::optional(r)).has_value());
|
||||
@ -1481,12 +1479,10 @@ TEST(RectTest, OptRectUnion) {
|
||||
ASSERT_EQ(a.Union(b), u);
|
||||
|
||||
// Rect, OptRect
|
||||
EXPECT_TRUE(Rect::Union(a, std::optional(b)).has_value());
|
||||
EXPECT_EQ(Rect::Union(a, std::optional(b)).value(), u);
|
||||
EXPECT_EQ(Rect::Union(a, std::optional(b)), u);
|
||||
|
||||
// OptRect, Rect
|
||||
EXPECT_TRUE(Rect::Union(std::optional(a), b).has_value());
|
||||
EXPECT_EQ(Rect::Union(std::optional(a), b).value(), u);
|
||||
EXPECT_EQ(Rect::Union(std::optional(a), b), u);
|
||||
|
||||
// OptRect, OptRect
|
||||
EXPECT_TRUE(Rect::Union(std::optional(a), std::optional(b)).has_value());
|
||||
@ -1581,16 +1577,14 @@ TEST(RectTest, OptIRectUnion) {
|
||||
|
||||
auto test1 = [](const IRect& r) {
|
||||
// Rect, NullOpt
|
||||
EXPECT_TRUE(IRect::Union(r, std::nullopt).has_value());
|
||||
EXPECT_EQ(IRect::Union(r, std::nullopt).value(), r);
|
||||
EXPECT_EQ(IRect::Union(r, std::nullopt), r);
|
||||
|
||||
// OptRect, NullOpt
|
||||
EXPECT_TRUE(IRect::Union(std::optional(r), std::nullopt).has_value());
|
||||
EXPECT_EQ(IRect::Union(std::optional(r), std::nullopt).value(), r);
|
||||
|
||||
// NullOpt, Rect
|
||||
EXPECT_TRUE(IRect::Union(std::nullopt, r).has_value());
|
||||
EXPECT_EQ(IRect::Union(std::nullopt, r).value(), r);
|
||||
EXPECT_EQ(IRect::Union(std::nullopt, r), r);
|
||||
|
||||
// NullOpt, OptRect
|
||||
EXPECT_TRUE(IRect::Union(std::nullopt, std::optional(r)).has_value());
|
||||
@ -1605,12 +1599,10 @@ TEST(RectTest, OptIRectUnion) {
|
||||
ASSERT_EQ(a.Union(b), u);
|
||||
|
||||
// Rect, OptRect
|
||||
EXPECT_TRUE(IRect::Union(a, std::optional(b)).has_value());
|
||||
EXPECT_EQ(IRect::Union(a, std::optional(b)).value(), u);
|
||||
EXPECT_EQ(IRect::Union(a, std::optional(b)), u);
|
||||
|
||||
// OptRect, Rect
|
||||
EXPECT_TRUE(IRect::Union(std::optional(a), b).has_value());
|
||||
EXPECT_EQ(IRect::Union(std::optional(a), b).value(), u);
|
||||
EXPECT_EQ(IRect::Union(std::optional(a), b), u);
|
||||
|
||||
// OptRect, OptRect
|
||||
EXPECT_TRUE(IRect::Union(std::optional(a), std::optional(b)).has_value());
|
||||
|
57
engine/src/flutter/impeller/geometry/rstransform.cc
Normal file
57
engine/src/flutter/impeller/geometry/rstransform.cc
Normal file
@ -0,0 +1,57 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/impeller/geometry/rstransform.h"
|
||||
|
||||
#include "flutter/impeller/geometry/matrix.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
bool RSTransform::IsAxisAligned() const {
|
||||
return scaled_cos == 0.0f || scaled_sin == 0.0f;
|
||||
}
|
||||
|
||||
Matrix RSTransform::GetMatrix() const {
|
||||
// clang-format off
|
||||
return Matrix::MakeRow(scaled_cos, -scaled_sin, 0.0f, translate_x,
|
||||
scaled_sin, scaled_cos, 0.0f, translate_y,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f);
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
void RSTransform::GetQuad(Scalar width, Scalar height, Quad& quad) const {
|
||||
Point origin = {translate_x, translate_y};
|
||||
Point dx = width * Point{scaled_cos, scaled_sin};
|
||||
Point dy = height * Point{-scaled_sin, scaled_cos};
|
||||
quad = {
|
||||
// Ordered in the same Z pattern as Rect::GetPoints()
|
||||
origin,
|
||||
origin + dx,
|
||||
origin + dy,
|
||||
origin + dx + dy,
|
||||
};
|
||||
}
|
||||
|
||||
Quad RSTransform::GetQuad(Scalar width, Scalar height) const {
|
||||
Quad quad;
|
||||
GetQuad(width, height, quad);
|
||||
return quad;
|
||||
}
|
||||
|
||||
Quad RSTransform::GetQuad(Size size) const {
|
||||
Quad quad;
|
||||
GetQuad(size.width, size.height, quad);
|
||||
return quad;
|
||||
}
|
||||
|
||||
std::optional<Rect> RSTransform::GetBounds(Scalar width, Scalar height) const {
|
||||
return Rect::MakePointBounds(GetQuad(width, height));
|
||||
}
|
||||
|
||||
std::optional<Rect> RSTransform::GetBounds(Size size) const {
|
||||
return Rect::MakePointBounds(GetQuad(size));
|
||||
}
|
||||
|
||||
} // namespace impeller
|
89
engine/src/flutter/impeller/geometry/rstransform.h
Normal file
89
engine/src/flutter/impeller/geometry/rstransform.h
Normal file
@ -0,0 +1,89 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_IMPELLER_GEOMETRY_RSTRANSFORM_H_
|
||||
#define FLUTTER_IMPELLER_GEOMETRY_RSTRANSFORM_H_
|
||||
|
||||
#include "flutter/impeller/geometry/point.h"
|
||||
#include "flutter/impeller/geometry/rect.h"
|
||||
#include "flutter/impeller/geometry/scalar.h"
|
||||
#include "flutter/impeller/geometry/size.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
/// A utility struct that stores a simple transform composed of a translation,
|
||||
/// a rotation, and a uniform scale.
|
||||
///
|
||||
/// This transform is used by drawAtlas to transform the sprites.
|
||||
/// This structure mirrors the Flutter RSTransform class.
|
||||
struct RSTransform {
|
||||
constexpr RSTransform()
|
||||
: scaled_cos(1.0f),
|
||||
scaled_sin(0.0f),
|
||||
translate_x(0.0f),
|
||||
translate_y(0.0f) {}
|
||||
|
||||
constexpr RSTransform(Scalar scaled_cos,
|
||||
Scalar scaled_sin,
|
||||
Scalar translate_x,
|
||||
Scalar translate_y)
|
||||
: scaled_cos(scaled_cos),
|
||||
scaled_sin(scaled_sin),
|
||||
translate_x(translate_x),
|
||||
translate_y(translate_y) {}
|
||||
|
||||
/// Constructs an RSTransform from the indicated origin, uniform scale,
|
||||
/// and radians rotation.
|
||||
static constexpr RSTransform Make(Point origin,
|
||||
Scalar scale,
|
||||
Radians radians) {
|
||||
auto scaled_cos_sin = Matrix::CosSin(radians) * scale;
|
||||
return {scaled_cos_sin.x, scaled_cos_sin.y, origin.x, origin.y};
|
||||
}
|
||||
|
||||
Scalar scaled_cos;
|
||||
Scalar scaled_sin;
|
||||
Scalar translate_x;
|
||||
Scalar translate_y;
|
||||
|
||||
/// Returns true iff the resulting transformed quad will be aligned with
|
||||
/// the axes, even if rotated by a quadrant rotation.
|
||||
bool IsAxisAligned() const;
|
||||
|
||||
Matrix GetMatrix() const;
|
||||
|
||||
/// Returns the 4 corner points of the transformed quad for a sub-image
|
||||
/// of the indicated size in the same order as Rect::GetPoints.
|
||||
///
|
||||
/// The order is UpperLeft, UpperRight, LowerLeft, LowerRight
|
||||
void GetQuad(Scalar width, Scalar height, Quad& quad) const;
|
||||
Quad GetQuad(Scalar width, Scalar height) const;
|
||||
Quad GetQuad(Size size) const;
|
||||
|
||||
/// Returns the bounds of the 4 corner points of the transformed quad
|
||||
/// for a sub-image of the indicated size.
|
||||
std::optional<Rect> GetBounds(Scalar width, Scalar height) const;
|
||||
std::optional<Rect> GetBounds(Size size) const;
|
||||
};
|
||||
|
||||
} // namespace impeller
|
||||
|
||||
namespace std {
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out,
|
||||
const impeller::RSTransform& rst) {
|
||||
// clang-format off
|
||||
out << "("
|
||||
<< "scos: " << rst.scaled_cos << ", "
|
||||
<< "ssin: " << rst.scaled_sin << ", "
|
||||
<< "origin: (" << rst.translate_x << ", "
|
||||
<< rst.translate_y << ")"
|
||||
<< ")";
|
||||
// clang-format on
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif // FLUTTER_IMPELLER_GEOMETRY_RSTRANSFORM_H_
|
@ -0,0 +1,61 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "flutter/impeller/geometry/rstransform.h"
|
||||
|
||||
#include "flutter/impeller/geometry/geometry_asserts.h"
|
||||
|
||||
namespace impeller {
|
||||
namespace testing {
|
||||
|
||||
TEST(RSTransformTest, Construction) {
|
||||
RSTransform transform = RSTransform::Make({10.0f, 12.0f}, 2.0f, Degrees(90));
|
||||
|
||||
EXPECT_EQ(transform.scaled_cos, 0.0f);
|
||||
EXPECT_EQ(transform.scaled_sin, 2.0f);
|
||||
EXPECT_EQ(transform.translate_x, 10.0f);
|
||||
EXPECT_EQ(transform.translate_y, 12.0f);
|
||||
|
||||
EXPECT_EQ(transform.GetBounds(20.0f, 30.0f),
|
||||
// relative corners are at
|
||||
// 0, 0
|
||||
// 0, 40
|
||||
// -60, 0
|
||||
// -60, 40
|
||||
// then add 10, 12 to all values
|
||||
Rect::MakeLTRB(10 + -2 * 30, 12 + 0, 10 + 0, 12 + 40));
|
||||
}
|
||||
|
||||
TEST(RSTransformTest, CompareToMatrix) {
|
||||
for (int tx = 0; tx <= 100; tx += 10) {
|
||||
for (int ty = 0; ty <= 100; ty += 10) {
|
||||
Point origin(tx, ty);
|
||||
for (int scale = 1; scale <= 20; scale += 5) {
|
||||
// Overshoot a full circle by 30 degrees
|
||||
for (int degrees = 0; degrees <= 390; degrees += 45) {
|
||||
auto matrix = Matrix::MakeTranslation(origin) *
|
||||
Matrix::MakeRotationZ(Degrees(degrees)) *
|
||||
Matrix::MakeScale(Vector2(scale, scale));
|
||||
auto rst = RSTransform::Make(origin, scale, Degrees(degrees));
|
||||
EXPECT_MATRIX_NEAR(rst.GetMatrix(), matrix);
|
||||
for (int w = 10; w <= 100; w += 10) {
|
||||
for (int h = 10; h <= 100; h += 10) {
|
||||
Quad q = rst.GetQuad(w, h);
|
||||
auto points = Rect::MakeWH(w, h).GetTransformedPoints(matrix);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
EXPECT_NEAR(q[i].x, points[i].x, kEhCloseEnough);
|
||||
EXPECT_NEAR(q[i].y, points[i].y, kEhCloseEnough);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace impeller
|
@ -1747,7 +1747,7 @@ class RRect {
|
||||
///
|
||||
/// Used by [Canvas.drawAtlas]. This is a more efficient way to represent these
|
||||
/// simple transformations than a full matrix.
|
||||
// Modeled after Skia's SkRSXform.
|
||||
// Modeled after Impeller's RSTransform.
|
||||
class RSTransform {
|
||||
/// Creates an RSTransform.
|
||||
///
|
||||
|
@ -581,8 +581,8 @@ Dart_Handle Canvas::drawAtlas(Dart_Handle paint_objects,
|
||||
return ToDart(error.value());
|
||||
}
|
||||
|
||||
static_assert(sizeof(SkRSXform) == sizeof(float) * 4,
|
||||
"SkRSXform doesn't use floats.");
|
||||
static_assert(sizeof(DlRSTransform) == sizeof(float) * 4,
|
||||
"DlRSTransform doesn't use floats.");
|
||||
static_assert(sizeof(DlRect) == sizeof(float) * 4,
|
||||
"DlRect doesn't use floats.");
|
||||
|
||||
@ -605,7 +605,7 @@ Dart_Handle Canvas::drawAtlas(Dart_Handle paint_objects,
|
||||
const DlPaint* opt_paint =
|
||||
paint.paint(dl_paint, kDrawAtlasWithPaintFlags, DlTileMode::kClamp);
|
||||
builder()->DrawAtlas(
|
||||
dl_image, reinterpret_cast<const SkRSXform*>(transforms.data()),
|
||||
dl_image, reinterpret_cast<const DlRSTransform*>(transforms.data()),
|
||||
reinterpret_cast<const DlRect*>(rects.data()), dl_color.data(),
|
||||
rects.num_elements() / 4, // DlRect have four floats.
|
||||
blend_mode, sampling, reinterpret_cast<const DlRect*>(cull_rect.data()),
|
||||
|
@ -110,7 +110,7 @@ void DlOpSpy::drawImageNine(const sk_sp<DlImage> image,
|
||||
did_draw_ = true;
|
||||
}
|
||||
void DlOpSpy::drawAtlas(const sk_sp<DlImage> atlas,
|
||||
const SkRSXform xform[],
|
||||
const DlRSTransform xform[],
|
||||
const DlRect tex[],
|
||||
const DlColor colors[],
|
||||
int count,
|
||||
|
@ -84,7 +84,7 @@ class DlOpSpy final : public virtual DlOpReceiver,
|
||||
DlFilterMode filter,
|
||||
bool render_with_attributes) override;
|
||||
void drawAtlas(const sk_sp<DlImage> atlas,
|
||||
const SkRSXform xform[],
|
||||
const DlRSTransform xform[],
|
||||
const DlRect tex[],
|
||||
const DlColor colors[],
|
||||
int count,
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include "flutter/display_list/testing/dl_test_snippets.h"
|
||||
#include "flutter/shell/common/dl_op_spy.h"
|
||||
#include "flutter/testing/testing.h"
|
||||
#include "third_party/skia/include/core/SkRSXform.h"
|
||||
|
||||
namespace flutter {
|
||||
namespace testing {
|
||||
@ -456,7 +455,9 @@ TEST(DlOpSpy, Images) {
|
||||
{ // DrawAtlas
|
||||
DisplayListBuilder builder;
|
||||
DlPaint paint(DlColor::kBlack());
|
||||
const SkRSXform xform[] = {SkRSXform::Make(1, 0, 0, 0)};
|
||||
const DlRSTransform xform[] = {
|
||||
DlRSTransform::Make({0, 0}, 1.0f, DlDegrees(0)),
|
||||
};
|
||||
const DlRect tex[] = {DlRect::MakeXYWH(10, 10, 10, 10)};
|
||||
DlRect cull_rect = DlRect::MakeWH(5, 5);
|
||||
builder.DrawAtlas(kTestImage1, xform, tex, nullptr, 1, DlBlendMode::kSrc,
|
||||
|
@ -205,14 +205,6 @@ extern std::ostream& operator<<(std::ostream& os, const DlPath& path) {
|
||||
<< ")";
|
||||
}
|
||||
|
||||
static std::ostream& operator<<(std::ostream& os, const SkRSXform& xform) {
|
||||
return os << "SkRSXform("
|
||||
<< "scos: " << xform.fSCos << ", "
|
||||
<< "ssin: " << xform.fSSin << ", "
|
||||
<< "tx: " << xform.fTx << ", "
|
||||
<< "ty: " << xform.fTy << ")";
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const DlCanvas::ClipOp& op) {
|
||||
switch (op) {
|
||||
case DlCanvas::ClipOp::kDifference: return os << "ClipOp::kDifference";
|
||||
@ -912,7 +904,7 @@ void DisplayListStreamDispatcher::drawImageNine(const sk_sp<DlImage> image,
|
||||
<< ");" << std::endl;
|
||||
}
|
||||
void DisplayListStreamDispatcher::drawAtlas(const sk_sp<DlImage> atlas,
|
||||
const SkRSXform xform[],
|
||||
const DlRSTransform xform[],
|
||||
const DlRect tex[],
|
||||
const DlColor colors[],
|
||||
int count,
|
||||
|
@ -177,7 +177,7 @@ class DisplayListStreamDispatcher final : public DlOpReceiver {
|
||||
DlFilterMode filter,
|
||||
bool render_with_attributes) override;
|
||||
void drawAtlas(const sk_sp<DlImage> atlas,
|
||||
const SkRSXform xform[],
|
||||
const DlRSTransform xform[],
|
||||
const DlRect tex[],
|
||||
const DlColor colors[],
|
||||
int count,
|
||||
@ -500,7 +500,7 @@ class DisplayListGeneralReceiver : public DlOpReceiver {
|
||||
}
|
||||
}
|
||||
void drawAtlas(const sk_sp<DlImage> atlas,
|
||||
const SkRSXform xform[],
|
||||
const DlRSTransform xform[],
|
||||
const DlRect tex[],
|
||||
const DlColor colors[],
|
||||
int count,
|
||||
|
Loading…
x
Reference in New Issue
Block a user