SkLiteDL: thread the original canvas matrix through for SetMatrix::Draw().

The SkLiteDL is recorded in some identity space (imagine, SkMatrix::I()),
but played back in a different one (here named SkMatrix original).  Any
calls to setMatrix() need to be made relative to this new space.

All other ops already operate in relative coordinates.

This should let us not fiddle with setMatrix().

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2247353003

Review-Url: https://codereview.chromium.org/2247353003
This commit is contained in:
mtklein 2016-08-16 17:18:27 -07:00 committed by Commit bot
parent 287e7cb936
commit 6480619f9f
2 changed files with 59 additions and 44 deletions

View File

@ -92,11 +92,11 @@ namespace {
struct Save final : Op { struct Save final : Op {
static const auto kType = Type::Save; static const auto kType = Type::Save;
void draw(SkCanvas* c) { c->save(); } void draw(SkCanvas* c, const SkMatrix&) { c->save(); }
}; };
struct Restore final : Op { struct Restore final : Op {
static const auto kType = Type::Restore; static const auto kType = Type::Restore;
void draw(SkCanvas* c) { c->restore(); } void draw(SkCanvas* c, const SkMatrix&) { c->restore(); }
}; };
struct SaveLayer final : Op { struct SaveLayer final : Op {
static const auto kType = Type::SaveLayer; static const auto kType = Type::SaveLayer;
@ -111,7 +111,7 @@ namespace {
SkPaint paint; SkPaint paint;
sk_sp<const SkImageFilter> backdrop; sk_sp<const SkImageFilter> backdrop;
SkCanvas::SaveLayerFlags flags; SkCanvas::SaveLayerFlags flags;
void draw(SkCanvas* c) { void draw(SkCanvas* c, const SkMatrix&) {
c->saveLayer({ maybe_unset(bounds), &paint, backdrop.get(), flags }); c->saveLayer({ maybe_unset(bounds), &paint, backdrop.get(), flags });
} }
void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); }
@ -121,21 +121,23 @@ namespace {
static const auto kType = Type::Concat; static const auto kType = Type::Concat;
Concat(const SkMatrix& matrix) : matrix(matrix) {} Concat(const SkMatrix& matrix) : matrix(matrix) {}
SkMatrix matrix; SkMatrix matrix;
void draw(SkCanvas* c) { c->concat(matrix); } void draw(SkCanvas* c, const SkMatrix&) { c->concat(matrix); }
void makeThreadsafe() { make_threadsafe(nullptr, &matrix); } void makeThreadsafe() { make_threadsafe(nullptr, &matrix); }
}; };
struct SetMatrix final : Op { struct SetMatrix final : Op {
static const auto kType = Type::SetMatrix; static const auto kType = Type::SetMatrix;
SetMatrix(const SkMatrix& matrix) : matrix(matrix) {} SetMatrix(const SkMatrix& matrix) : matrix(matrix) {}
SkMatrix matrix; SkMatrix matrix;
void draw(SkCanvas* c) { c->setMatrix(matrix); } void draw(SkCanvas* c, const SkMatrix& original) {
c->setMatrix(SkMatrix::Concat(original, matrix));
}
void makeThreadsafe() { make_threadsafe(nullptr, &matrix); } void makeThreadsafe() { make_threadsafe(nullptr, &matrix); }
}; };
struct TranslateZ final : Op { struct TranslateZ final : Op {
static const auto kType = Type::TranslateZ; static const auto kType = Type::TranslateZ;
TranslateZ(SkScalar dz) : dz(dz) {} TranslateZ(SkScalar dz) : dz(dz) {}
SkScalar dz; SkScalar dz;
void draw(SkCanvas* c) { void draw(SkCanvas* c, const SkMatrix&) {
#ifdef SK_EXPERIMENTAL_SHADOWING #ifdef SK_EXPERIMENTAL_SHADOWING
c->translateZ(dz); c->translateZ(dz);
#endif #endif
@ -148,7 +150,7 @@ namespace {
SkPath path; SkPath path;
SkRegion::Op op; SkRegion::Op op;
bool aa; bool aa;
void draw(SkCanvas* c) { c->clipPath(path, op, aa); } void draw(SkCanvas* c, const SkMatrix&) { c->clipPath(path, op, aa); }
void makeThreadsafe() { make_threadsafe(&path, nullptr); } void makeThreadsafe() { make_threadsafe(&path, nullptr); }
}; };
struct ClipRect final : Op { struct ClipRect final : Op {
@ -157,7 +159,7 @@ namespace {
SkRect rect; SkRect rect;
SkRegion::Op op; SkRegion::Op op;
bool aa; bool aa;
void draw(SkCanvas* c) { c->clipRect(rect, op, aa); } void draw(SkCanvas* c, const SkMatrix&) { c->clipRect(rect, op, aa); }
}; };
struct ClipRRect final : Op { struct ClipRRect final : Op {
static const auto kType = Type::ClipRRect; static const auto kType = Type::ClipRRect;
@ -165,21 +167,21 @@ namespace {
SkRRect rrect; SkRRect rrect;
SkRegion::Op op; SkRegion::Op op;
bool aa; bool aa;
void draw(SkCanvas* c) { c->clipRRect(rrect, op, aa); } void draw(SkCanvas* c, const SkMatrix&) { c->clipRRect(rrect, op, aa); }
}; };
struct ClipRegion final : Op { struct ClipRegion final : Op {
static const auto kType = Type::ClipRegion; static const auto kType = Type::ClipRegion;
ClipRegion(const SkRegion& region, SkRegion::Op op) : region(region), op(op) {} ClipRegion(const SkRegion& region, SkRegion::Op op) : region(region), op(op) {}
SkRegion region; SkRegion region;
SkRegion::Op op; SkRegion::Op op;
void draw(SkCanvas* c) { c->clipRegion(region, op); } void draw(SkCanvas* c, const SkMatrix&) { c->clipRegion(region, op); }
}; };
struct DrawPaint final : Op { struct DrawPaint final : Op {
static const auto kType = Type::DrawPaint; static const auto kType = Type::DrawPaint;
DrawPaint(const SkPaint& paint) : paint(paint) {} DrawPaint(const SkPaint& paint) : paint(paint) {}
SkPaint paint; SkPaint paint;
void draw(SkCanvas* c) { c->drawPaint(paint); } void draw(SkCanvas* c, const SkMatrix&) { c->drawPaint(paint); }
void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); }
}; };
struct DrawPath final : Op { struct DrawPath final : Op {
@ -187,7 +189,7 @@ namespace {
DrawPath(const SkPath& path, const SkPaint& paint) : path(path), paint(paint) {} DrawPath(const SkPath& path, const SkPaint& paint) : path(path), paint(paint) {}
SkPath path; SkPath path;
SkPaint paint; SkPaint paint;
void draw(SkCanvas* c) { c->drawPath(path, paint); } void draw(SkCanvas* c, const SkMatrix&) { c->drawPath(path, paint); }
void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); }
void makeThreadsafe() { make_threadsafe(&path, nullptr); } void makeThreadsafe() { make_threadsafe(&path, nullptr); }
}; };
@ -196,7 +198,7 @@ namespace {
DrawRect(const SkRect& rect, const SkPaint& paint) : rect(rect), paint(paint) {} DrawRect(const SkRect& rect, const SkPaint& paint) : rect(rect), paint(paint) {}
SkRect rect; SkRect rect;
SkPaint paint; SkPaint paint;
void draw(SkCanvas* c) { c->drawRect(rect, paint); } void draw(SkCanvas* c, const SkMatrix&) { c->drawRect(rect, paint); }
void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); }
}; };
struct DrawOval final : Op { struct DrawOval final : Op {
@ -204,7 +206,7 @@ namespace {
DrawOval(const SkRect& oval, const SkPaint& paint) : oval(oval), paint(paint) {} DrawOval(const SkRect& oval, const SkPaint& paint) : oval(oval), paint(paint) {}
SkRect oval; SkRect oval;
SkPaint paint; SkPaint paint;
void draw(SkCanvas* c) { c->drawOval(oval, paint); } void draw(SkCanvas* c, const SkMatrix&) { c->drawOval(oval, paint); }
void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); }
}; };
struct DrawRRect final : Op { struct DrawRRect final : Op {
@ -212,7 +214,7 @@ namespace {
DrawRRect(const SkRRect& rrect, const SkPaint& paint) : rrect(rrect), paint(paint) {} DrawRRect(const SkRRect& rrect, const SkPaint& paint) : rrect(rrect), paint(paint) {}
SkRRect rrect; SkRRect rrect;
SkPaint paint; SkPaint paint;
void draw(SkCanvas* c) { c->drawRRect(rrect, paint); } void draw(SkCanvas* c, const SkMatrix&) { c->drawRRect(rrect, paint); }
void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); }
}; };
struct DrawDRRect final : Op { struct DrawDRRect final : Op {
@ -221,7 +223,7 @@ namespace {
: outer(outer), inner(inner), paint(paint) {} : outer(outer), inner(inner), paint(paint) {}
SkRRect outer, inner; SkRRect outer, inner;
SkPaint paint; SkPaint paint;
void draw(SkCanvas* c) { c->drawDRRect(outer, inner, paint); } void draw(SkCanvas* c, const SkMatrix&) { c->drawDRRect(outer, inner, paint); }
void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); }
}; };
@ -230,7 +232,9 @@ namespace {
DrawAnnotation(const SkRect& rect, SkData* value) : rect(rect), value(sk_ref_sp(value)) {} DrawAnnotation(const SkRect& rect, SkData* value) : rect(rect), value(sk_ref_sp(value)) {}
SkRect rect; SkRect rect;
sk_sp<SkData> value; sk_sp<SkData> value;
void draw(SkCanvas* c) { c->drawAnnotation(rect, pod<char>(this), value.get()); } void draw(SkCanvas* c, const SkMatrix&) {
c->drawAnnotation(rect, pod<char>(this), value.get());
}
}; };
struct DrawDrawable final : Op { struct DrawDrawable final : Op {
static const auto kType = Type::DrawDrawable; static const auto kType = Type::DrawDrawable;
@ -240,7 +244,7 @@ namespace {
sk_sp<SkDrawable> drawable; sk_sp<SkDrawable> drawable;
sk_sp<const SkPicture> snapped; sk_sp<const SkPicture> snapped;
SkMatrix matrix = SkMatrix::I(); SkMatrix matrix = SkMatrix::I();
void draw(SkCanvas* c) { void draw(SkCanvas* c, const SkMatrix&) {
snapped ? c->drawPicture(snapped.get(), &matrix, nullptr) snapped ? c->drawPicture(snapped.get(), &matrix, nullptr)
: c->drawDrawable(drawable.get(), &matrix); : c->drawDrawable(drawable.get(), &matrix);
} }
@ -260,7 +264,7 @@ namespace {
SkMatrix matrix = SkMatrix::I(); SkMatrix matrix = SkMatrix::I();
SkPaint paint; SkPaint paint;
bool has_paint = false; // TODO: why is a default paint not the same? bool has_paint = false; // TODO: why is a default paint not the same?
void draw(SkCanvas* c) { void draw(SkCanvas* c, const SkMatrix&) {
c->drawPicture(picture.get(), &matrix, has_paint ? &paint : nullptr); c->drawPicture(picture.get(), &matrix, has_paint ? &paint : nullptr);
} }
void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); }
@ -276,7 +280,7 @@ namespace {
sk_sp<const SkPicture> picture; sk_sp<const SkPicture> picture;
SkMatrix matrix = SkMatrix::I(); SkMatrix matrix = SkMatrix::I();
SkPaint paint; SkPaint paint;
void draw(SkCanvas* c) { void draw(SkCanvas* c, const SkMatrix&) {
#ifdef SK_EXPERIMENTAL_SHADOWING #ifdef SK_EXPERIMENTAL_SHADOWING
c->drawShadowedPicture(picture.get(), &matrix, &paint); c->drawShadowedPicture(picture.get(), &matrix, &paint);
#endif #endif
@ -294,7 +298,7 @@ namespace {
sk_sp<const SkImage> image; sk_sp<const SkImage> image;
SkScalar x,y; SkScalar x,y;
SkPaint paint; SkPaint paint;
void draw(SkCanvas* c) { c->drawImage(image.get(), x,y, &paint); } void draw(SkCanvas* c, const SkMatrix&) { c->drawImage(image.get(), x,y, &paint); }
void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint, &image); } void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint, &image); }
}; };
struct DrawImageNine final : Op { struct DrawImageNine final : Op {
@ -308,7 +312,9 @@ namespace {
SkIRect center; SkIRect center;
SkRect dst; SkRect dst;
SkPaint paint; SkPaint paint;
void draw(SkCanvas* c) { c->drawImageNine(image.get(), center, dst, &paint); } void draw(SkCanvas* c, const SkMatrix&) {
c->drawImageNine(image.get(), center, dst, &paint);
}
void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint, &image); } void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint, &image); }
}; };
struct DrawImageRect final : Op { struct DrawImageRect final : Op {
@ -323,7 +329,7 @@ namespace {
SkRect src, dst; SkRect src, dst;
SkPaint paint; SkPaint paint;
SkCanvas::SrcRectConstraint constraint; SkCanvas::SrcRectConstraint constraint;
void draw(SkCanvas* c) { void draw(SkCanvas* c, const SkMatrix&) {
c->drawImageRect(image.get(), src, dst, &paint, constraint); c->drawImageRect(image.get(), src, dst, &paint, constraint);
} }
void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint, &image); } void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint, &image); }
@ -339,7 +345,7 @@ namespace {
int xs, ys; int xs, ys;
SkRect dst; SkRect dst;
SkPaint paint; SkPaint paint;
void draw(SkCanvas* c) { void draw(SkCanvas* c, const SkMatrix&) {
auto xdivs = pod<int>(this, 0), auto xdivs = pod<int>(this, 0),
ydivs = pod<int>(this, xs*sizeof(int)); ydivs = pod<int>(this, xs*sizeof(int));
c->drawImageLattice(image.get(), {xdivs, xs, ydivs, ys}, dst, &paint); c->drawImageLattice(image.get(), {xdivs, xs, ydivs, ys}, dst, &paint);
@ -354,7 +360,9 @@ namespace {
size_t bytes; size_t bytes;
SkScalar x,y; SkScalar x,y;
SkPaint paint; SkPaint paint;
void draw(SkCanvas* c) { c->drawText(pod<void>(this), bytes, x,y, paint); } void draw(SkCanvas* c, const SkMatrix&) {
c->drawText(pod<void>(this), bytes, x,y, paint);
}
void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); }
}; };
struct DrawPosText final : Op { struct DrawPosText final : Op {
@ -364,7 +372,7 @@ namespace {
size_t bytes; size_t bytes;
SkPaint paint; SkPaint paint;
int n; int n;
void draw(SkCanvas* c) { void draw(SkCanvas* c, const SkMatrix&) {
auto points = pod<SkPoint>(this); auto points = pod<SkPoint>(this);
auto text = pod<void>(this, n*sizeof(SkPoint)); auto text = pod<void>(this, n*sizeof(SkPoint));
c->drawPosText(text, bytes, points, paint); c->drawPosText(text, bytes, points, paint);
@ -379,7 +387,7 @@ namespace {
SkScalar y; SkScalar y;
SkPaint paint; SkPaint paint;
int n; int n;
void draw(SkCanvas* c) { void draw(SkCanvas* c, const SkMatrix&) {
auto xs = pod<SkScalar>(this); auto xs = pod<SkScalar>(this);
auto text = pod<void>(this, n*sizeof(SkScalar)); auto text = pod<void>(this, n*sizeof(SkScalar));
c->drawPosTextH(text, bytes, xs, y, paint); c->drawPosTextH(text, bytes, xs, y, paint);
@ -397,7 +405,7 @@ namespace {
SkPath path; SkPath path;
SkMatrix matrix = SkMatrix::I(); SkMatrix matrix = SkMatrix::I();
SkPaint paint; SkPaint paint;
void draw(SkCanvas* c) { void draw(SkCanvas* c, const SkMatrix&) {
c->drawTextOnPath(pod<void>(this), bytes, path, &matrix, paint); c->drawTextOnPath(pod<void>(this), bytes, path, &matrix, paint);
} }
void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); }
@ -412,7 +420,7 @@ namespace {
size_t bytes; size_t bytes;
SkRect cull = kUnset; SkRect cull = kUnset;
SkPaint paint; SkPaint paint;
void draw(SkCanvas* c) { void draw(SkCanvas* c, const SkMatrix&) {
c->drawTextRSXform(pod<void>(this), bytes, pod<SkRSXform>(this, bytes), c->drawTextRSXform(pod<void>(this), bytes, pod<SkRSXform>(this, bytes),
maybe_unset(cull), paint); maybe_unset(cull), paint);
} }
@ -425,7 +433,9 @@ namespace {
sk_sp<const SkTextBlob> blob; sk_sp<const SkTextBlob> blob;
SkScalar x,y; SkScalar x,y;
SkPaint paint; SkPaint paint;
void draw(SkCanvas* c) { c->drawTextBlob(blob.get(), x,y, paint); } void draw(SkCanvas* c, const SkMatrix&) {
c->drawTextBlob(blob.get(), x,y, paint);
}
void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); }
}; };
@ -445,7 +455,7 @@ namespace {
SkPaint paint; SkPaint paint;
bool has_colors = false; bool has_colors = false;
bool has_texs = false; bool has_texs = false;
void draw(SkCanvas* c) { void draw(SkCanvas* c, const SkMatrix&) {
c->drawPatch(cubics, has_colors ? colors : nullptr, has_texs ? texs : nullptr, c->drawPatch(cubics, has_colors ? colors : nullptr, has_texs ? texs : nullptr,
xfermode.get(), paint); xfermode.get(), paint);
} }
@ -458,7 +468,9 @@ namespace {
SkCanvas::PointMode mode; SkCanvas::PointMode mode;
size_t count; size_t count;
SkPaint paint; SkPaint paint;
void draw(SkCanvas* c) { c->drawPoints(mode, count, pod<SkPoint>(this), paint); } void draw(SkCanvas* c, const SkMatrix&) {
c->drawPoints(mode, count, pod<SkPoint>(this), paint);
}
void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); }
}; };
struct DrawVertices final : Op { struct DrawVertices final : Op {
@ -475,7 +487,7 @@ namespace {
bool has_texs; bool has_texs;
bool has_colors; bool has_colors;
bool has_indices; bool has_indices;
void draw(SkCanvas* c) { void draw(SkCanvas* c, const SkMatrix&) {
SkPoint* vertices = pod<SkPoint>(this, 0); SkPoint* vertices = pod<SkPoint>(this, 0);
size_t offset = count*sizeof(SkPoint); size_t offset = count*sizeof(SkPoint);
@ -514,7 +526,7 @@ namespace {
SkRect cull = kUnset; SkRect cull = kUnset;
SkPaint paint; SkPaint paint;
bool has_colors; bool has_colors;
void draw(SkCanvas* c) { void draw(SkCanvas* c, const SkMatrix&) {
auto xforms = pod<SkRSXform>(this, 0); auto xforms = pod<SkRSXform>(this, 0);
auto texs = pod<SkRect>(this, count*sizeof(SkRSXform)); auto texs = pod<SkRect>(this, count*sizeof(SkRSXform));
auto colors = has_colors auto colors = has_colors
@ -546,8 +558,8 @@ void* SkLiteDL::push(size_t pod, Args&&... args) {
return op+1; return op+1;
} }
template <typename... Args> template <typename Fn, typename... Args>
inline void SkLiteDL::map(void (*const fns[])(void*, Args...), Args... args) { inline void SkLiteDL::map(const Fn fns[], Args... args) {
auto end = fBytes.get() + fUsed; auto end = fBytes.get() + fUsed;
for (uint8_t* ptr = fBytes.get(); ptr < end; ) { for (uint8_t* ptr = fBytes.get(); ptr < end; ) {
auto op = (Op*)ptr; auto op = (Op*)ptr;
@ -730,13 +742,13 @@ void SkLiteDL::drawAtlas(const SkImage* atlas, const SkRSXform xforms[], const S
colors, colors ? count : 0); colors, colors ? count : 0);
} }
typedef void(* skcanvas_fn)(void*, SkCanvas*); typedef void(* draw_fn)(void*, SkCanvas*, const SkMatrix&);
typedef void(*grcontext_fn)(void*, GrContext*); typedef void(*grcontext_fn)(void*, GrContext*);
typedef void(* void_fn)(void*); typedef void(* void_fn)(void*);
// All ops implement draw(). // All ops implement draw().
#define M(T) [](void* op, SkCanvas* c) { ((T*)op)->draw(c); }, #define M(T) [](void* op, SkCanvas* c, const SkMatrix& original) { ((T*)op)->draw(c, original); },
static const skcanvas_fn draw_fns[] = { TYPES(M) }; static const draw_fn draw_fns[] = { TYPES(M) };
#undef M #undef M
// Ops that implement optimizeFor() or makeThreadsafe() return void from those functions; // Ops that implement optimizeFor() or makeThreadsafe() return void from those functions;
@ -763,9 +775,12 @@ static const void_fn make_threadsafe_fns[] = { TYPES(M) };
static const void_fn dtor_fns[] = { TYPES(M) }; static const void_fn dtor_fns[] = { TYPES(M) };
#undef M #undef M
void SkLiteDL::onDraw (SkCanvas* canvas) { this->map(draw_fns, canvas); } void SkLiteDL::onDraw(SkCanvas* canvas) {
void SkLiteDL::optimizeFor (GrContext* ctx) { this->map(optimize_for_fns, ctx); } SkMatrix original = canvas->getTotalMatrix();
void SkLiteDL::makeThreadsafe() { this->map(make_threadsafe_fns); } this->map(draw_fns, canvas, original);
}
void SkLiteDL::optimizeFor (GrContext* ctx) { this->map(optimize_for_fns, ctx); }
void SkLiteDL::makeThreadsafe() { this->map(make_threadsafe_fns); }
SkRect SkLiteDL::onGetBounds() { SkRect SkLiteDL::onGetBounds() {
return fBounds; return fBounds;

View File

@ -89,8 +89,8 @@ private:
template <typename T, typename... Args> template <typename T, typename... Args>
void* push(size_t, Args&&...); void* push(size_t, Args&&...);
template <typename... Args> template <typename Fn, typename... Args>
void map(void (*const [])(void*, Args...), Args...); void map(const Fn[], Args...);
SkAutoTMalloc<uint8_t> fBytes; SkAutoTMalloc<uint8_t> fBytes;
size_t fUsed; size_t fUsed;