diff options
author | 2016-08-11 03:56:12 -0700 | |
---|---|---|
committer | 2016-08-11 03:56:13 -0700 | |
commit | d230149ef889e920556949d2e50a1519b93aefea (patch) | |
tree | 6c8c787ed91f97fa875093e8abd518c43cf7b49e /src/core/SkLiteDL.cpp | |
parent | a9ca05ca5e604b9ee18e9cce19b059085ca0e22c (diff) |
Revert of SkLiteDL: turn vtable sideways (patchset #7 id:120001 of https://codereview.chromium.org/2231103002/ )
Reason for revert:
speculative revert to fix DEPS roll
Original issue's description:
> SkLiteDL: turn vtable sideways
>
> Instead of using virtuals for polymorphism, store each polymorphic operation
> in its own array of function pointers. This removes an indirection when calling
> the function, and lets us use nullptr as a signal to skip the call entirely.
>
> Unfortunately (as the old code is rather simpler) this makes an unambiguous speed improvement.
>
> Before:
> curr/maxrss loops min median mean max stddev samples config bench
> 21/26 MB 2 44.6µs 46.4µs 48.3µs 274µs 13% 51724 nonrendering desk_nytimes.skp
> 23/26 MB 11 11.4µs 11.9µs 12.4µs 75.1µs 15% 36716 nonrendering keymobi_nytimes_com_.skp
>
> After:
> 19/26 MB 4 40.4µs 41.6µs 42.5µs 197µs 10% 29379 nonrendering desk_nytimes.skp
> 20/26 MB 14 10.5µs 10.7µs 11.2µs 59.5µs 13% 31971 nonrendering keymobi_nytimes_com_.skp
>
> Broader comparison:
> keymobi_linkedin.skp 1.76us -> 1.77us 1x
> keymobi_bing_com_search_q_sloth.skp 5.09us -> 5.05us 0.99x
> keymobi_digg_com.skp 17.4us -> 17.3us 0.99x
> keymobi_theverge_com.skp 3.37us -> 3.34us 0.99x
> top25desk_mail_google_com_mail_.skp 30.8us -> 30.4us 0.99x
> tabl_gmail.skp 3.44us -> 3.38us 0.98x
> top25desk_wikipedia__1_tab_.skp 100us -> 97.7us 0.98x
> keymobi_cnn_com_2012_10_03_poli.skp 52.9us -> 51.7us 0.98x
> desk_chalkboard.skp 107us -> 104us 0.97x
> desk_css3gradients.skp 17.8us -> 17.3us 0.97x
> keymobi_androidpolice_com_2012_.skp 42.3us -> 41.1us 0.97x
> desk_googlehome.skp 1.94us -> 1.88us 0.97x
> keymobi_mlb_com_.skp 5.38us -> 5.18us 0.96x
> top25desk_pinterest.skp 92.1us -> 88.5us 0.96x
> keymobi_iphone_capitolvolkswage.skp 15.1us -> 14.5us 0.96x
> keymobi_techcrunch_com.skp 9.45us -> 9.05us 0.96x
> desk_espn.skp 31.3us -> 30us 0.96x
> keymobi_slashdot_org_.skp 8.72us -> 8.34us 0.96x
> desk_tiger8svg.skp 30.6us -> 29.2us 0.96x
> keymobi_blogger.skp 4.09us -> 3.91us 0.95x
> keymobi_baidu_com_s_wd_barack_o.skp 11.9us -> 11.3us 0.95x
> keymobi_cuteoverload_com.skp 54.2us -> 51.6us 0.95x
> keymobi_deviantart_com_.skp 17.2us -> 16.4us 0.95x
> desk_mapsvg.skp 163ns -> 155ns 0.95x
> keymobi_pinterest.skp 6.97us -> 6.62us 0.95x
> top25desk_games_yahoo_com.skp 94.1us -> 89.3us 0.95x
> top25desk_google_com_calendar_.skp 18us -> 17us 0.95x
> keymobi_google_co_uk_search_hl_.skp 11.4us -> 10.8us 0.95x
> tabl_pravda.skp 38.5us -> 36.4us 0.94x
> desk_gmailthread.skp 19us -> 17.9us 0.94x
> keymobi_reddit_com_r_programmin.skp 76.1us -> 71.7us 0.94x
> top25desk_linkedin.skp 20us -> 18.8us 0.94x
> tabl_gamedeksiam.skp 118us -> 112us 0.94x
> keymobi_boingboing_net.skp 20.4us -> 19.1us 0.93x
> top25desk_google_com__hl_en_q_b.skp 17.6us -> 16.4us 0.93x
> keymobi_amazon_com_gp_aw_s_ref_.skp 12.5us -> 11.6us 0.93x
> keymobi_sfgate_com_.skp 16.6us -> 15.5us 0.93x
> keymobi_booking_com_searchresul.skp 16.2us -> 15.1us 0.93x
> tabl_digg.skp 28.8us -> 26.8us 0.93x
> tabl_mozilla.skp 80.4us -> 74.6us 0.93x
> desk_wowwiki.skp 39.2us -> 36.4us 0.93x
> top25desk_youtube_com.skp 42us -> 38.9us 0.93x
> top25desk_facebook.skp 23.7us -> 22us 0.93x
> top25desk_blogger.skp 38.2us -> 35.4us 0.93x
> keymobi_online_wsj_com_home_pag.skp 12.8us -> 11.9us 0.93x
> top25desk_wordpress.skp 28.9us -> 26.8us 0.93x
> top25desk_answers_yahoo_com.skp 37.2us -> 34.4us 0.93x
> keymobi_plus_google_com_app_bas.skp 9.56us -> 8.85us 0.93x
> keymobi_wordpress.skp 16.1us -> 14.9us 0.92x
> keymobi_mobile_news_sandbox_goo.skp 27.1us -> 24.9us 0.92x
> top25desk_techcrunch_com.skp 31.1us -> 28.6us 0.92x
> keymobi_worldjournal_com_.skp 50.7us -> 46.5us 0.92x
> keymobi_theverge_com_2012_10_28.skp 26.2us -> 24us 0.92x
> desk_jsfiddlebigcar.skp 1.73us -> 1.59us 0.92x
> top25desk_weather_com.skp 31.3us -> 28.7us 0.92x
> top25desk_google_com_search_q_c.skp 48.2us -> 44.1us 0.92x
> top25desk_twitter.skp 27.8us -> 25.5us 0.92x
> tabl_worldjournal.skp 29.3us -> 26.8us 0.91x
> desk_nytimes.skp 46us -> 42us 0.91x
> top25desk_docs___1_open_documen.skp 6.04us -> 5.51us 0.91x
> keymobi_wikipedia__1_tab_.skp 59.7us -> 54.4us 0.91x
> desk_unicodetable.skp 1.12ms -> 1.02ms 0.91x
> top25desk_ebay_com.skp 17.8us -> 16.2us 0.91x
> keymobi_ftw_usatoday_com_2014_0.skp 26.8us -> 24.3us 0.91x
> top25desk_sports_yahoo_com_.skp 49.9us -> 45.3us 0.91x
> keymobi_cnn_com.skp 9.94us -> 9.03us 0.91x
> keymobi_m_youtube_com_watch_v_9.skp 13.4us -> 12.2us 0.91x
> top25desk_amazon_com.skp 26.6us -> 24.1us 0.91x
> keymobi_news_yahoo_com.skp 17.5us -> 15.8us 0.9x
> keymobi_wowwiki_com_world_of_wa.skp 11.2us -> 10.2us 0.9x
> top25desk_plus_google_com_11003.skp 93.5us -> 84.4us 0.9x
> desk_carsvg.skp 53.5us -> 48.2us 0.9x
> top25desk_news_yahoo_com.skp 44.7us -> 40.3us 0.9x
> keymobi_wikipedia__1_tab____del.skp 59.4us -> 53.4us 0.9x
> desk_googlespreadsheet.skp 66us -> 59.2us 0.9x
> keymobi_answers_yahoo_com_quest.skp 30.2us -> 27us 0.89x
> desk_ugamsolutions.skp 13us -> 11.6us 0.89x
> keymobi_shop_mobileweb_ebay_com.skp 6.96us -> 6.21us 0.89x
> keymobi_nytimes_com_.skp 12.1us -> 10.8us 0.89x
> keymobi_gsp_ro.skp 5.54us -> 4.92us 0.89x
> top25desk_booking_com.skp 54.9us -> 48.6us 0.89x
> top25desk_espn.skp 37us -> 32.6us 0.88x
> keymobi_facebook_com_barackobam.skp 23.3us -> 20.4us 0.88x
>
> BUG=skia:
> GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2231103002
>
> Committed: https://skia.googlesource.com/skia/+/ac243914af957a806d842318a43dddaf5f941dc3
TBR=mtklein@google.com,mtklein@chromium.org
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=skia:
Review-Url: https://codereview.chromium.org/2232183002
Diffstat (limited to 'src/core/SkLiteDL.cpp')
-rw-r--r-- | src/core/SkLiteDL.cpp | 247 |
1 files changed, 84 insertions, 163 deletions
diff --git a/src/core/SkLiteDL.cpp b/src/core/SkLiteDL.cpp index f847c42742..c6a3a8e8ea 100644 --- a/src/core/SkLiteDL.cpp +++ b/src/core/SkLiteDL.cpp @@ -59,42 +59,18 @@ static void make_threadsafe(SkPath* path, SkMatrix* matrix) { } namespace { -#define TYPES(M) \ - M(Save) M(Restore) M(SaveLayer) \ - M(Concat) M(SetMatrix) M(TranslateZ) \ - M(ClipPath) M(ClipRect) M(ClipRRect) M(ClipRegion) \ - M(DrawPaint) M(DrawPath) M(DrawRect) M(DrawOval) M(DrawRRect) M(DrawDRRect) \ - M(DrawAnnotation) M(DrawDrawable) M(DrawPicture) M(DrawShadowedPicture) \ - M(DrawImage) M(DrawImageNine) M(DrawImageRect) M(DrawImageLattice) \ - M(DrawText) M(DrawPosText) M(DrawPosTextH) \ - M(DrawTextOnPath) M(DrawTextRSXform) M(DrawTextBlob) \ - M(DrawPatch) M(DrawPoints) M(DrawVertices) M(DrawAtlas) - -#define M(T) T, - enum class Type : uint8_t { TYPES(M) }; -#undef M - struct Op { - // These are never called, only used to distinguish Ops that implement - // them from those that don't by return type: the real methods return void. - int optimizeFor(GrContext*) { sk_throw(); return 0;} - int makeThreadsafe() { sk_throw(); return 0;} + virtual ~Op() {} + virtual void draw(SkCanvas*) = 0; + virtual void optimizeFor(GrContext*) {} + virtual void makeThreadsafe() {} - uint32_t type : 8; - uint32_t skip : 24; + size_t skip; }; - static_assert(sizeof(Op) == 4, ""); - struct Save final : Op { - static const auto kType = Type::Save; - void draw(SkCanvas* c) { c->save(); } - }; - struct Restore final : Op { - static const auto kType = Type::Restore; - void draw(SkCanvas* c) { c->restore(); } - }; + struct Save final : Op { void draw(SkCanvas* c) override { c-> save(); } }; + struct Restore final : Op { void draw(SkCanvas* c) override { c->restore(); } }; struct SaveLayer final : Op { - static const auto kType = Type::SaveLayer; SaveLayer(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop, SkCanvas::SaveLayerFlags flags) { if (bounds) { this->bounds = *bounds; } @@ -106,31 +82,28 @@ namespace { SkPaint paint; sk_sp<const SkImageFilter> backdrop; SkCanvas::SaveLayerFlags flags; - void draw(SkCanvas* c) { + void draw(SkCanvas* c) override { c->saveLayer({ maybe_unset(bounds), &paint, backdrop.get(), flags }); } - void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); } }; struct Concat final : Op { - static const auto kType = Type::Concat; Concat(const SkMatrix& matrix) : matrix(matrix) {} SkMatrix matrix; - void draw(SkCanvas* c) { c->concat(matrix); } - void makeThreadsafe() { make_threadsafe(nullptr, &matrix); } + void draw(SkCanvas* c) override { c->concat(matrix); } + void makeThreadsafe() override { make_threadsafe(nullptr, &matrix); } }; struct SetMatrix final : Op { - static const auto kType = Type::SetMatrix; SetMatrix(const SkMatrix& matrix) : matrix(matrix) {} SkMatrix matrix; - void draw(SkCanvas* c) { c->setMatrix(matrix); } - void makeThreadsafe() { make_threadsafe(nullptr, &matrix); } + void draw(SkCanvas* c) override { c->setMatrix(matrix); } + void makeThreadsafe() override { make_threadsafe(nullptr, &matrix); } }; struct TranslateZ final : Op { - static const auto kType = Type::TranslateZ; TranslateZ(SkScalar dz) : dz(dz) {} SkScalar dz; - void draw(SkCanvas* c) { + void draw(SkCanvas* c) override { #ifdef SK_EXPERIMENTAL_SHADOWING c->translateZ(dz); #endif @@ -138,114 +111,101 @@ namespace { }; struct ClipPath final : Op { - static const auto kType = Type::ClipPath; ClipPath(const SkPath& path, SkRegion::Op op, bool aa) : path(path), op(op), aa(aa) {} SkPath path; SkRegion::Op op; bool aa; - void draw(SkCanvas* c) { c->clipPath(path, op, aa); } - void makeThreadsafe() { make_threadsafe(&path, nullptr); } + void draw(SkCanvas* c) override { c->clipPath(path, op, aa); } + void makeThreadsafe() override { make_threadsafe(&path, nullptr); } }; struct ClipRect final : Op { - static const auto kType = Type::ClipRect; ClipRect(const SkRect& rect, SkRegion::Op op, bool aa) : rect(rect), op(op), aa(aa) {} SkRect rect; SkRegion::Op op; bool aa; - void draw(SkCanvas* c) { c->clipRect(rect, op, aa); } + void draw(SkCanvas* c) override { c->clipRect(rect, op, aa); } }; struct ClipRRect final : Op { - static const auto kType = Type::ClipRRect; ClipRRect(const SkRRect& rrect, SkRegion::Op op, bool aa) : rrect(rrect), op(op), aa(aa) {} SkRRect rrect; SkRegion::Op op; bool aa; - void draw(SkCanvas* c) { c->clipRRect(rrect, op, aa); } + void draw(SkCanvas* c) override { c->clipRRect(rrect, op, aa); } }; struct ClipRegion final : Op { - static const auto kType = Type::ClipRegion; ClipRegion(const SkRegion& region, SkRegion::Op op) : region(region), op(op) {} SkRegion region; SkRegion::Op op; - void draw(SkCanvas* c) { c->clipRegion(region, op); } + void draw(SkCanvas* c) override { c->clipRegion(region, op); } }; struct DrawPaint final : Op { - static const auto kType = Type::DrawPaint; DrawPaint(const SkPaint& paint) : paint(paint) {} SkPaint paint; - void draw(SkCanvas* c) { c->drawPaint(paint); } - void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } + void draw(SkCanvas* c) override { c->drawPaint(paint); } + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); } }; struct DrawPath final : Op { - static const auto kType = Type::DrawPath; DrawPath(const SkPath& path, const SkPaint& paint) : path(path), paint(paint) {} SkPath path; SkPaint paint; - void draw(SkCanvas* c) { c->drawPath(path, paint); } - void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } - void makeThreadsafe() { make_threadsafe(&path, nullptr); } + void draw(SkCanvas* c) override { c->drawPath(path, paint); } + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); } + void makeThreadsafe() override { make_threadsafe(&path, nullptr); } }; struct DrawRect final : Op { - static const auto kType = Type::DrawRect; DrawRect(const SkRect& rect, const SkPaint& paint) : rect(rect), paint(paint) {} SkRect rect; SkPaint paint; - void draw(SkCanvas* c) { c->drawRect(rect, paint); } - void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } + void draw(SkCanvas* c) override { c->drawRect(rect, paint); } + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); } }; struct DrawOval final : Op { - static const auto kType = Type::DrawOval; DrawOval(const SkRect& oval, const SkPaint& paint) : oval(oval), paint(paint) {} SkRect oval; SkPaint paint; - void draw(SkCanvas* c) { c->drawOval(oval, paint); } - void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } + void draw(SkCanvas* c) override { c->drawOval(oval, paint); } + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); } }; struct DrawRRect final : Op { - static const auto kType = Type::DrawRRect; DrawRRect(const SkRRect& rrect, const SkPaint& paint) : rrect(rrect), paint(paint) {} SkRRect rrect; SkPaint paint; - void draw(SkCanvas* c) { c->drawRRect(rrect, paint); } - void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } + void draw(SkCanvas* c) override { c->drawRRect(rrect, paint); } + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); } }; struct DrawDRRect final : Op { - static const auto kType = Type::DrawDRRect; DrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) : outer(outer), inner(inner), paint(paint) {} SkRRect outer, inner; SkPaint paint; - void draw(SkCanvas* c) { c->drawDRRect(outer, inner, paint); } - void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } + void draw(SkCanvas* c) override { c->drawDRRect(outer, inner, paint); } + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); } }; struct DrawAnnotation final : Op { - static const auto kType = Type::DrawAnnotation; DrawAnnotation(const SkRect& rect, SkData* value) : rect(rect), value(sk_ref_sp(value)) {} SkRect rect; sk_sp<SkData> value; - void draw(SkCanvas* c) { c->drawAnnotation(rect, pod<char>(this), value.get()); } + void draw(SkCanvas* c) override { c->drawAnnotation(rect, pod<char>(this), value.get()); } }; struct DrawDrawable final : Op { - static const auto kType = Type::DrawDrawable; DrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) : drawable(sk_ref_sp(drawable)) { if (matrix) { this->matrix = *matrix; } } sk_sp<SkDrawable> drawable; sk_sp<const SkPicture> snapped; SkMatrix matrix = SkMatrix::I(); - void draw(SkCanvas* c) { + void draw(SkCanvas* c) override { snapped ? c->drawPicture(snapped.get(), &matrix, nullptr) : c->drawDrawable(drawable.get(), &matrix); } - void makeThreadsafe() { + void makeThreadsafe() override { snapped.reset(drawable->newPictureSnapshot()); make_threadsafe(nullptr, &matrix); } }; struct DrawPicture final : Op { - static const auto kType = Type::DrawPicture; DrawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) : picture(sk_ref_sp(picture)) { if (matrix) { this->matrix = *matrix; } @@ -255,14 +215,13 @@ namespace { SkMatrix matrix = SkMatrix::I(); SkPaint paint; bool has_paint = false; // TODO: why is a default paint not the same? - void draw(SkCanvas* c) { + void draw(SkCanvas* c) override { c->drawPicture(picture.get(), &matrix, has_paint ? &paint : nullptr); } - void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } - void makeThreadsafe() { make_threadsafe(nullptr, &matrix); } + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); } + void makeThreadsafe() override { make_threadsafe(nullptr, &matrix); } }; struct DrawShadowedPicture final : Op { - static const auto kType = Type::DrawShadowedPicture; DrawShadowedPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) : picture(sk_ref_sp(picture)) { if (matrix) { this->matrix = *matrix; } @@ -271,17 +230,16 @@ namespace { sk_sp<const SkPicture> picture; SkMatrix matrix = SkMatrix::I(); SkPaint paint; - void draw(SkCanvas* c) { + void draw(SkCanvas* c) override { #ifdef SK_EXPERIMENTAL_SHADOWING c->drawShadowedPicture(picture.get(), &matrix, &paint); #endif } - void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } - void makeThreadsafe() { make_threadsafe(nullptr, &matrix); } + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); } + void makeThreadsafe() override { make_threadsafe(nullptr, &matrix); } }; struct DrawImage final : Op { - static const auto kType = Type::DrawImage; DrawImage(sk_sp<const SkImage>&& image, SkScalar x, SkScalar y, const SkPaint* paint) : image(std::move(image)), x(x), y(y) { if (paint) { this->paint = *paint; } @@ -289,11 +247,10 @@ namespace { sk_sp<const SkImage> image; SkScalar x,y; SkPaint paint; - void draw(SkCanvas* c) { c->drawImage(image.get(), x,y, &paint); } - void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint, &image); } + void draw(SkCanvas* c) override { c->drawImage(image.get(), x,y, &paint); } + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint, &image); } }; struct DrawImageNine final : Op { - static const auto kType = Type::DrawImageNine; DrawImageNine(sk_sp<const SkImage>&& image, const SkIRect& center, const SkRect& dst, const SkPaint* paint) : image(std::move(image)), center(center), dst(dst) { @@ -303,11 +260,10 @@ namespace { SkIRect center; SkRect dst; SkPaint paint; - void draw(SkCanvas* c) { c->drawImageNine(image.get(), center, dst, &paint); } - void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint, &image); } + void draw(SkCanvas* c) override { c->drawImageNine(image.get(), center, dst, &paint); } + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint, &image); } }; struct DrawImageRect final : Op { - static const auto kType = Type::DrawImageRect; DrawImageRect(sk_sp<const SkImage>&& image, const SkRect* src, const SkRect& dst, const SkPaint* paint, SkCanvas::SrcRectConstraint constraint) : image(std::move(image)), dst(dst), constraint(constraint) { @@ -318,13 +274,12 @@ namespace { SkRect src, dst; SkPaint paint; SkCanvas::SrcRectConstraint constraint; - void draw(SkCanvas* c) { + void draw(SkCanvas* c) override { c->drawImageRect(image.get(), src, dst, &paint, constraint); } - void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint, &image); } + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint, &image); } }; struct DrawImageLattice final : Op { - static const auto kType = Type::DrawImageLattice; DrawImageLattice(sk_sp<const SkImage>&& image, int xs, int ys, const SkRect& dst, const SkPaint* paint) : image(std::move(image)), xs(xs), ys(ys), dst(dst) { @@ -334,55 +289,51 @@ namespace { int xs, ys; SkRect dst; SkPaint paint; - void draw(SkCanvas* c) { + void draw(SkCanvas* c) override { auto xdivs = pod<int>(this, 0), ydivs = pod<int>(this, xs*sizeof(int)); c->drawImageLattice(image.get(), {xdivs, xs, ydivs, ys}, dst, &paint); } - void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint, &image); } + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint, &image); } }; struct DrawText final : Op { - static const auto kType = Type::DrawText; DrawText(size_t bytes, SkScalar x, SkScalar y, const SkPaint& paint) : bytes(bytes), x(x), y(y), paint(paint) {} size_t bytes; SkScalar x,y; SkPaint paint; - void draw(SkCanvas* c) { c->drawText(pod<void>(this), bytes, x,y, paint); } - void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } + void draw(SkCanvas* c) override { c->drawText(pod<void>(this), bytes, x,y, paint); } + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); } }; struct DrawPosText final : Op { - static const auto kType = Type::DrawPosText; DrawPosText(size_t bytes, const SkPaint& paint, int n) : bytes(bytes), paint(paint), n(n) {} size_t bytes; SkPaint paint; int n; - void draw(SkCanvas* c) { + void draw(SkCanvas* c) override { auto points = pod<SkPoint>(this); auto text = pod<void>(this, n*sizeof(SkPoint)); c->drawPosText(text, bytes, points, paint); } - void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); } }; struct DrawPosTextH final : Op { - static const auto kType = Type::DrawPosTextH; DrawPosTextH(size_t bytes, SkScalar y, const SkPaint& paint, int n) : bytes(bytes), y(y), paint(paint), n(n) {} size_t bytes; SkScalar y; SkPaint paint; int n; - void draw(SkCanvas* c) { + void draw(SkCanvas* c) override { auto xs = pod<SkScalar>(this); auto text = pod<void>(this, n*sizeof(SkScalar)); c->drawPosTextH(text, bytes, xs, y, paint); } - void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); } }; struct DrawTextOnPath final : Op { - static const auto kType = Type::DrawTextOnPath; DrawTextOnPath(size_t bytes, const SkPath& path, const SkMatrix* matrix, const SkPaint& paint) : bytes(bytes), path(path), paint(paint) { @@ -392,14 +343,13 @@ namespace { SkPath path; SkMatrix matrix = SkMatrix::I(); SkPaint paint; - void draw(SkCanvas* c) { + void draw(SkCanvas* c) override { c->drawTextOnPath(pod<void>(this), bytes, path, &matrix, paint); } - void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } - void makeThreadsafe() { make_threadsafe(&path, &matrix); } + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); } + void makeThreadsafe() override { make_threadsafe(&path, &matrix); } }; struct DrawTextRSXform final : Op { - static const auto kType = Type::DrawTextRSXform; DrawTextRSXform(size_t bytes, const SkRect* cull, const SkPaint& paint) : bytes(bytes), paint(paint) { if (cull) { this->cull = *cull; } @@ -407,25 +357,23 @@ namespace { size_t bytes; SkRect cull = kUnset; SkPaint paint; - void draw(SkCanvas* c) { + void draw(SkCanvas* c) override { c->drawTextRSXform(pod<void>(this), bytes, pod<SkRSXform>(this, bytes), maybe_unset(cull), paint); } - void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); } }; struct DrawTextBlob final : Op { - static const auto kType = Type::DrawTextBlob; DrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint) : blob(sk_ref_sp(blob)), x(x), y(y), paint(paint) {} sk_sp<const SkTextBlob> blob; SkScalar x,y; SkPaint paint; - void draw(SkCanvas* c) { c->drawTextBlob(blob.get(), x,y, paint); } - void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } + void draw(SkCanvas* c) override { c->drawTextBlob(blob.get(), x,y, paint); } + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); } }; struct DrawPatch final : Op { - static const auto kType = Type::DrawPatch; DrawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texs[4], SkXfermode* xfermode, const SkPaint& paint) : xfermode(sk_ref_sp(xfermode)), paint(paint) { @@ -440,24 +388,22 @@ namespace { SkPaint paint; bool has_colors = false; bool has_texs = false; - void draw(SkCanvas* c) { + void draw(SkCanvas* c) override { c->drawPatch(cubics, has_colors ? colors : nullptr, has_texs ? texs : nullptr, xfermode.get(), paint); } - void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); } }; struct DrawPoints final : Op { - static const auto kType = Type::DrawPoints; DrawPoints(SkCanvas::PointMode mode, size_t count, const SkPaint& paint) : mode(mode), count(count), paint(paint) {} SkCanvas::PointMode mode; size_t count; SkPaint paint; - void draw(SkCanvas* c) { c->drawPoints(mode, count, pod<SkPoint>(this), paint); } - void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } + void draw(SkCanvas* c) override { c->drawPoints(mode, count, pod<SkPoint>(this), paint); } + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); } }; struct DrawVertices final : Op { - static const auto kType = Type::DrawVertices; DrawVertices(SkCanvas::VertexMode mode, int count, SkXfermode* xfermode, int nindices, const SkPaint& paint, bool has_texs, bool has_colors, bool has_indices) : mode(mode), count(count), xfermode(sk_ref_sp(xfermode)), nindices(nindices) @@ -470,7 +416,7 @@ namespace { bool has_texs; bool has_colors; bool has_indices; - void draw(SkCanvas* c) { + void draw(SkCanvas* c) override { SkPoint* vertices = pod<SkPoint>(this, 0); size_t offset = count*sizeof(SkPoint); @@ -493,10 +439,9 @@ namespace { c->drawVertices(mode, count, vertices, texs, colors, xfermode.get(), indices, nindices, paint); } - void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint); } + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); } }; struct DrawAtlas final : Op { - static const auto kType = Type::DrawAtlas; DrawAtlas(const SkImage* atlas, int count, SkXfermode::Mode xfermode, const SkRect* cull, const SkPaint* paint, bool has_colors) : atlas(sk_ref_sp(atlas)), count(count), xfermode(xfermode), has_colors(has_colors) { @@ -509,7 +454,7 @@ namespace { SkRect cull = kUnset; SkPaint paint; bool has_colors; - void draw(SkCanvas* c) { + void draw(SkCanvas* c) override { auto xforms = pod<SkRSXform>(this, 0); auto texs = pod<SkRect>(this, count*sizeof(SkRSXform)); auto colors = has_colors @@ -518,14 +463,13 @@ namespace { c->drawAtlas(atlas.get(), xforms, texs, colors, count, xfermode, maybe_unset(cull), &paint); } - void optimizeFor(GrContext* ctx) { optimize_for(ctx, &paint, &atlas); } + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint, &atlas); } }; } template <typename T, typename... Args> void* SkLiteDL::push(size_t pod, Args&&... args) { size_t skip = SkAlignPtr(sizeof(T) + pod); - SkASSERT(skip < (1<<24)); if (fUsed + skip > fReserved) { fReserved = (fUsed + skip + 4096) & ~4095; // Next greater multiple of 4096. fBytes.realloc(fReserved); @@ -534,22 +478,17 @@ void* SkLiteDL::push(size_t pod, Args&&... args) { auto op = (T*)(fBytes.get() + fUsed); fUsed += skip; new (op) T{ std::forward<Args>(args)... }; - op->type = (uint32_t)T::kType; op->skip = skip; return op+1; } -template <typename... Args> -inline void SkLiteDL::map(void (*const fns[])(void*, Args...), Args... args) { +template <typename Fn> +void SkLiteDL::map(Fn&& fn) { auto end = fBytes.get() + fUsed; for (uint8_t* ptr = fBytes.get(); ptr < end; ) { auto op = (Op*)ptr; - auto type = op->type; - auto skip = op->skip; - if (auto fn = fns[type]) { // We replace no-op functions with nullptrs - fn(op, args...); // to avoid the overhead of a pointless call. - } - ptr += skip; + fn(op); + ptr += op->skip; } } @@ -714,36 +653,18 @@ void SkLiteDL::drawAtlas(const SkImage* atlas, const SkRSXform xforms[], const S colors, colors ? count : 0); } -typedef void(* skcanvas_fn)(void*, SkCanvas*); -typedef void(*grcontext_fn)(void*, GrContext*); -typedef void(* void_fn)(void*); - -// All ops implement draw(). -#define M(T) [](void* op, SkCanvas* c) { ((T*)op)->draw(c); }, -static const skcanvas_fn draw_fns[] = { TYPES(M) }; -#undef M -// Ops that implement optimizeFor() or makeThreadsafe() return void from those functions; -// the (throwing) defaults return int. -#define M(T) std::is_void<decltype(((T*)nullptr)->optimizeFor(nullptr))>::value \ - ? [](void* op, GrContext* ctx) { ((T*)op)->optimizeFor(ctx); } : (grcontext_fn)nullptr, -static const grcontext_fn optimize_for_fns[] = { TYPES(M) }; -#undef M - -#define M(T) std::is_void<decltype(((T*)nullptr)->makeThreadsafe())>::value \ - ? [](void* op) { ((T*)op)->makeThreadsafe(); } : (void_fn)nullptr, -static const void_fn make_threadsafe_fns[] = { TYPES(M) }; -#undef M +void SkLiteDL::onDraw(SkCanvas* canvas) { + this->map([canvas](Op* op) { op->draw(canvas); }); +} -// Most state ops (matrix, clip, save, restore) have a trivial destructor. -#define M(T) !std::is_trivially_destructible<T>::value \ - ? [](void* op) { ((T*)op)->~T(); } : (void_fn)nullptr, -static const void_fn dtor_fns[] = { TYPES(M) }; -#undef M +void SkLiteDL::optimizeFor(GrContext* ctx) { + this->map([ctx](Op* op) { op->optimizeFor(ctx); }); +} -void SkLiteDL::onDraw (SkCanvas* canvas) { this->map(draw_fns, canvas); } -void SkLiteDL::optimizeFor (GrContext* ctx) { this->map(optimize_for_fns, ctx); } -void SkLiteDL::makeThreadsafe() { this->map(make_threadsafe_fns); } +void SkLiteDL::makeThreadsafe() { + this->map([](Op* op) { op->makeThreadsafe(); }); +} SkRect SkLiteDL::onGetBounds() { return fBounds; @@ -784,7 +705,7 @@ void SkLiteDL::internal_dispose() const { this->internal_dispose_restore_refcnt_to_1(); auto self = const_cast<SkLiteDL*>(this); - self->map(dtor_fns); + self->map([](Op* op) { op->~Op(); }); if (--self->fUsesRemaining > 0) { self->fUsed = 0; |