SkLiteDL.cpp revision baeec6d25e02596f32d3307b5b4f88649dd2994f
1/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkCanvas.h"
9#include "SkData.h"
10#include "SkImageFilter.h"
11#include "SkLiteDL.h"
12#include "SkPicture.h"
13#include "SkMutex.h"
14#include "SkRSXform.h"
15#include "SkSpinlock.h"
16#include "SkTextBlob.h"
17
18// A stand-in for an optional SkRect which was not set, e.g. bounds for a saveLayer().
19static const SkRect kUnset = {SK_ScalarInfinity, 0,0,0};
20static const SkRect* maybe_unset(const SkRect& r) {
21    return r.left() == SK_ScalarInfinity ? nullptr : &r;
22}
23
24// copy_v(dst, src,n, src,n, ...) copies an arbitrary number of typed srcs into dst.
25static void copy_v(void* dst) {}
26
27template <typename S, typename... Rest>
28static void copy_v(void* dst, const S* src, int n, Rest&&... rest) {
29    SkASSERTF(((uintptr_t)dst & (alignof(S)-1)) == 0,
30              "Expected %p to be aligned for at least %zu bytes.", dst, alignof(S));
31    sk_careful_memcpy(dst, src, n*sizeof(S));
32    copy_v(SkTAddOffset<void>(dst, n*sizeof(S)), std::forward<Rest>(rest)...);
33}
34
35// Helper for getting back at arrays which have been copy_v'd together after an Op.
36template <typename D, typename T>
37static D* pod(T* op, size_t offset = 0) {
38    return SkTAddOffset<D>(op+1, offset);
39}
40
41// Convert images and image-based shaders to textures.
42static void optimize_for(GrContext* ctx, SkPaint* paint, sk_sp<const SkImage>* image = nullptr) {
43    SkMatrix matrix;
44    SkShader::TileMode xy[2];
45    if (auto shader = paint->getShader())
46    if (auto image  = shader->isAImage(&matrix, xy)) {  // TODO: compose shaders, etc.
47        paint->setShader(image->makeTextureImage(ctx)->makeShader(xy[0], xy[1], &matrix));
48    }
49
50    if (image) {
51        *image = (*image)->makeTextureImage(ctx);
52    }
53}
54
55// Pre-cache lazy non-threadsafe fields on SkPath and/or SkMatrix.
56static void make_threadsafe(SkPath* path, SkMatrix* matrix) {
57    if (path)   { path->updateBoundsCache(); }
58    if (matrix) { (void)matrix->getType(); }
59}
60
61namespace {
62    struct Op {
63        virtual ~Op() {}
64        virtual void draw(SkCanvas*) = 0;
65        virtual void optimizeFor(GrContext*) {}
66        virtual void makeThreadsafe() {}
67
68        size_t skip;
69    };
70
71    struct Save    final : Op { void draw(SkCanvas* c) override { c->   save(); } };
72    struct Restore final : Op { void draw(SkCanvas* c) override { c->restore(); } };
73    struct SaveLayer final : Op {
74        SaveLayer(const SkRect* bounds, const SkPaint* paint,
75                  const SkImageFilter* backdrop, SkCanvas::SaveLayerFlags flags) {
76            if (bounds) { this->bounds = *bounds; }
77            if (paint)  { this->paint  = *paint;  }
78            this->backdrop = sk_ref_sp(backdrop);
79            this->flags = flags;
80        }
81        SkRect                     bounds = kUnset;
82        SkPaint                    paint;
83        sk_sp<const SkImageFilter> backdrop;
84        SkCanvas::SaveLayerFlags   flags;
85        void draw(SkCanvas* c) override {
86            c->saveLayer({ maybe_unset(bounds), &paint, backdrop.get(), flags });
87        }
88        void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
89    };
90
91    struct Concat final : Op {
92        Concat(const SkMatrix& matrix) : matrix(matrix) {}
93        SkMatrix matrix;
94        void draw(SkCanvas* c) override { c->concat(matrix); }
95        void makeThreadsafe() override { make_threadsafe(nullptr, &matrix); }
96    };
97    struct SetMatrix final : Op {
98        SetMatrix(const SkMatrix& matrix) : matrix(matrix) {}
99        SkMatrix matrix;
100        void draw(SkCanvas* c) override { c->setMatrix(matrix); }
101        void makeThreadsafe() override { make_threadsafe(nullptr, &matrix); }
102    };
103    struct TranslateZ final : Op {
104        TranslateZ(SkScalar dz) : dz(dz) {}
105        SkScalar dz;
106        void draw(SkCanvas* c) override {
107        #ifdef SK_EXPERIMENTAL_SHADOWING
108            c->translateZ(dz);
109        #endif
110        }
111    };
112
113    struct ClipPath final : Op {
114        ClipPath(const SkPath& path, SkRegion::Op op, bool aa) : path(path), op(op), aa(aa) {}
115        SkPath       path;
116        SkRegion::Op op;
117        bool         aa;
118        void draw(SkCanvas* c) override { c->clipPath(path, op, aa); }
119        void makeThreadsafe() override { make_threadsafe(&path, nullptr); }
120    };
121    struct ClipRect final : Op {
122        ClipRect(const SkRect& rect, SkRegion::Op op, bool aa) : rect(rect), op(op), aa(aa) {}
123        SkRect       rect;
124        SkRegion::Op op;
125        bool         aa;
126        void draw(SkCanvas* c) override { c->clipRect(rect, op, aa); }
127    };
128    struct ClipRRect final : Op {
129        ClipRRect(const SkRRect& rrect, SkRegion::Op op, bool aa) : rrect(rrect), op(op), aa(aa) {}
130        SkRRect      rrect;
131        SkRegion::Op op;
132        bool         aa;
133        void draw(SkCanvas* c) override { c->clipRRect(rrect, op, aa); }
134    };
135    struct ClipRegion final : Op {
136        ClipRegion(const SkRegion& region, SkRegion::Op op) : region(region), op(op) {}
137        SkRegion     region;
138        SkRegion::Op op;
139        void draw(SkCanvas* c) override { c->clipRegion(region, op); }
140    };
141
142    struct DrawPaint final : Op {
143        DrawPaint(const SkPaint& paint) : paint(paint) {}
144        SkPaint paint;
145        void draw(SkCanvas* c) override { c->drawPaint(paint); }
146        void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
147    };
148    struct DrawPath final : Op {
149        DrawPath(const SkPath& path, const SkPaint& paint) : path(path), paint(paint) {}
150        SkPath  path;
151        SkPaint paint;
152        void draw(SkCanvas* c) override { c->drawPath(path, paint); }
153        void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
154        void makeThreadsafe() override { make_threadsafe(&path, nullptr); }
155    };
156    struct DrawRect final : Op {
157        DrawRect(const SkRect& rect, const SkPaint& paint) : rect(rect), paint(paint) {}
158        SkRect  rect;
159        SkPaint paint;
160        void draw(SkCanvas* c) override { c->drawRect(rect, paint); }
161        void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
162    };
163    struct DrawOval final : Op {
164        DrawOval(const SkRect& oval, const SkPaint& paint) : oval(oval), paint(paint) {}
165        SkRect  oval;
166        SkPaint paint;
167        void draw(SkCanvas* c) override { c->drawOval(oval, paint); }
168        void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
169    };
170    struct DrawRRect final : Op {
171        DrawRRect(const SkRRect& rrect, const SkPaint& paint) : rrect(rrect), paint(paint) {}
172        SkRRect rrect;
173        SkPaint paint;
174        void draw(SkCanvas* c) override { c->drawRRect(rrect, paint); }
175        void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
176    };
177    struct DrawDRRect final : Op {
178        DrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint)
179            : outer(outer), inner(inner), paint(paint) {}
180        SkRRect outer, inner;
181        SkPaint paint;
182        void draw(SkCanvas* c) override { c->drawDRRect(outer, inner, paint); }
183        void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
184    };
185
186    struct DrawAnnotation final : Op {
187        DrawAnnotation(const SkRect& rect, SkData* value) : rect(rect), value(sk_ref_sp(value)) {}
188        SkRect        rect;
189        sk_sp<SkData> value;
190        void draw(SkCanvas* c) override { c->drawAnnotation(rect, pod<char>(this), value.get()); }
191    };
192    struct DrawDrawable final : Op {
193        DrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) : drawable(sk_ref_sp(drawable)) {
194            if (matrix) { this->matrix = *matrix; }
195        }
196        sk_sp<SkDrawable>      drawable;
197        sk_sp<const SkPicture> snapped;
198        SkMatrix               matrix = SkMatrix::I();
199        void draw(SkCanvas* c) override {
200            snapped ? c->drawPicture(snapped.get(), &matrix, nullptr)
201                    : c->drawDrawable(drawable.get(), &matrix);
202        }
203        void makeThreadsafe() override {
204            snapped.reset(drawable->newPictureSnapshot());
205            make_threadsafe(nullptr, &matrix);
206        }
207    };
208    struct DrawPicture final : Op {
209        DrawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint)
210            : picture(sk_ref_sp(picture)) {
211            if (matrix) { this->matrix = *matrix; }
212            if (paint)  { this->paint  = *paint; has_paint = true; }
213        }
214        sk_sp<const SkPicture> picture;
215        SkMatrix               matrix = SkMatrix::I();
216        SkPaint                paint;
217        bool                   has_paint = false;  // TODO: why is a default paint not the same?
218        void draw(SkCanvas* c) override {
219            c->drawPicture(picture.get(), &matrix, has_paint ? &paint : nullptr);
220        }
221        void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
222        void makeThreadsafe() override { make_threadsafe(nullptr, &matrix); }
223    };
224    struct DrawShadowedPicture final : Op {
225        DrawShadowedPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint)
226            : picture(sk_ref_sp(picture)) {
227            if (matrix) { this->matrix = *matrix; }
228            if (paint)  { this->paint  = *paint;  }
229        }
230        sk_sp<const SkPicture> picture;
231        SkMatrix               matrix = SkMatrix::I();
232        SkPaint                paint;
233        void draw(SkCanvas* c) override {
234        #ifdef SK_EXPERIMENTAL_SHADOWING
235            c->drawShadowedPicture(picture.get(), &matrix, &paint);
236        #endif
237        }
238        void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
239        void makeThreadsafe() override { make_threadsafe(nullptr, &matrix); }
240    };
241
242    struct DrawImage final : Op {
243        DrawImage(sk_sp<const SkImage>&& image, SkScalar x, SkScalar y, const SkPaint* paint)
244            : image(std::move(image)), x(x), y(y) {
245            if (paint) { this->paint = *paint; }
246        }
247        sk_sp<const SkImage> image;
248        SkScalar x,y;
249        SkPaint paint;
250        void draw(SkCanvas* c) override { c->drawImage(image.get(), x,y, &paint); }
251        void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint, &image); }
252    };
253    struct DrawImageNine final : Op {
254        DrawImageNine(sk_sp<const SkImage>&& image,
255                      const SkIRect& center, const SkRect& dst, const SkPaint* paint)
256            : image(std::move(image)), center(center), dst(dst) {
257            if (paint) { this->paint = *paint; }
258        }
259        sk_sp<const SkImage> image;
260        SkIRect center;
261        SkRect  dst;
262        SkPaint paint;
263        void draw(SkCanvas* c) override { c->drawImageNine(image.get(), center, dst, &paint); }
264        void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint, &image); }
265    };
266    struct DrawImageRect final : Op {
267        DrawImageRect(sk_sp<const SkImage>&& image, const SkRect* src, const SkRect& dst,
268                      const SkPaint* paint, SkCanvas::SrcRectConstraint constraint)
269            : image(std::move(image)), dst(dst), constraint(constraint) {
270            this->src = src ? *src : SkRect::MakeIWH(image->width(), image->height());
271            if (paint) { this->paint = *paint; }
272        }
273        sk_sp<const SkImage> image;
274        SkRect src, dst;
275        SkPaint paint;
276        SkCanvas::SrcRectConstraint constraint;
277        void draw(SkCanvas* c) override {
278            c->drawImageRect(image.get(), src, dst, &paint, constraint);
279        }
280        void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint, &image); }
281    };
282    struct DrawImageLattice final : Op {
283        DrawImageLattice(sk_sp<const SkImage>&& image, int xs, int ys,
284                         const SkRect& dst, const SkPaint* paint)
285            : image(std::move(image)), xs(xs), ys(ys), dst(dst) {
286            if (paint) { this->paint = *paint; }
287        }
288        sk_sp<const SkImage> image;
289        int                  xs, ys;
290        SkRect               dst;
291        SkPaint              paint;
292        void draw(SkCanvas* c) override {
293            auto xdivs = pod<int>(this, 0),
294                 ydivs = pod<int>(this, xs*sizeof(int));
295            c->drawImageLattice(image.get(), {xdivs, xs, ydivs, ys}, dst, &paint);
296        }
297        void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint, &image); }
298    };
299
300    struct DrawText final : Op {
301        DrawText(size_t bytes, SkScalar x, SkScalar y, const SkPaint& paint)
302            : bytes(bytes), x(x), y(y), paint(paint) {}
303        size_t bytes;
304        SkScalar x,y;
305        SkPaint paint;
306        void draw(SkCanvas* c) override { c->drawText(pod<void>(this), bytes, x,y, paint); }
307        void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
308    };
309    struct DrawPosText final : Op {
310        DrawPosText(size_t bytes, const SkPaint& paint, int n)
311            : bytes(bytes), paint(paint), n(n) {}
312        size_t bytes;
313        SkPaint paint;
314        int n;
315        void draw(SkCanvas* c) override {
316            auto points = pod<SkPoint>(this);
317            auto text   = pod<void>(this, n*sizeof(SkPoint));
318            c->drawPosText(text, bytes, points, paint);
319        }
320        void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
321    };
322    struct DrawPosTextH final : Op {
323        DrawPosTextH(size_t bytes, SkScalar y, const SkPaint& paint, int n)
324            : bytes(bytes), y(y), paint(paint), n(n) {}
325        size_t   bytes;
326        SkScalar y;
327        SkPaint  paint;
328        int n;
329        void draw(SkCanvas* c) override {
330            auto xs   = pod<SkScalar>(this);
331            auto text = pod<void>(this, n*sizeof(SkScalar));
332            c->drawPosTextH(text, bytes, xs, y, paint);
333        }
334        void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
335    };
336    struct DrawTextOnPath final : Op {
337        DrawTextOnPath(size_t bytes, const SkPath& path,
338                       const SkMatrix* matrix, const SkPaint& paint)
339            : bytes(bytes), path(path), paint(paint) {
340            if (matrix) { this->matrix = *matrix; }
341        }
342        size_t   bytes;
343        SkPath   path;
344        SkMatrix matrix = SkMatrix::I();
345        SkPaint  paint;
346        void draw(SkCanvas* c) override {
347            c->drawTextOnPath(pod<void>(this), bytes, path, &matrix, paint);
348        }
349        void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
350        void makeThreadsafe() override { make_threadsafe(&path, &matrix); }
351    };
352    struct DrawTextRSXform final : Op {
353        DrawTextRSXform(size_t bytes, const SkRect* cull, const SkPaint& paint)
354            : bytes(bytes), paint(paint) {
355            if (cull) { this->cull = *cull; }
356        }
357        size_t  bytes;
358        SkRect  cull = kUnset;
359        SkPaint paint;
360        void draw(SkCanvas* c) override {
361            c->drawTextRSXform(pod<void>(this), bytes, pod<SkRSXform>(this, bytes),
362                               maybe_unset(cull), paint);
363        }
364        void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
365    };
366    struct DrawTextBlob final : Op {
367        DrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint)
368            : blob(sk_ref_sp(blob)), x(x), y(y), paint(paint) {}
369        sk_sp<const SkTextBlob> blob;
370        SkScalar x,y;
371        SkPaint paint;
372        void draw(SkCanvas* c) override { c->drawTextBlob(blob.get(), x,y, paint); }
373        void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
374    };
375
376    struct DrawPatch final : Op {
377        DrawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texs[4],
378                  SkXfermode* xfermode, const SkPaint& paint)
379            : xfermode(sk_ref_sp(xfermode)), paint(paint) {
380            copy_v(this->cubics, cubics, 12);
381            if (colors) { copy_v(this->colors, colors, 4); has_colors = true; }
382            if (texs  ) { copy_v(this->texs  , texs  , 4); has_texs   = true; }
383        }
384        SkPoint           cubics[12];
385        SkColor           colors[4];
386        SkPoint           texs[4];
387        sk_sp<SkXfermode> xfermode;
388        SkPaint           paint;
389        bool              has_colors = false;
390        bool              has_texs   = false;
391        void draw(SkCanvas* c) override {
392            c->drawPatch(cubics, has_colors ? colors : nullptr, has_texs ? texs : nullptr,
393                         xfermode.get(), paint);
394        }
395        void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
396    };
397    struct DrawPoints final : Op {
398        DrawPoints(SkCanvas::PointMode mode, size_t count, const SkPaint& paint)
399            : mode(mode), count(count), paint(paint) {}
400        SkCanvas::PointMode mode;
401        size_t              count;
402        SkPaint             paint;
403        void draw(SkCanvas* c) override { c->drawPoints(mode, count, pod<SkPoint>(this), paint); }
404        void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
405    };
406    struct DrawVertices final : Op {
407        DrawVertices(SkCanvas::VertexMode mode, int count, SkXfermode* xfermode, int nindices,
408                     const SkPaint& paint, bool has_texs, bool has_colors, bool has_indices)
409            : mode(mode), count(count), xfermode(sk_ref_sp(xfermode)), nindices(nindices)
410            , paint(paint), has_texs(has_texs), has_colors(has_colors), has_indices(has_indices) {}
411        SkCanvas::VertexMode mode;
412        int                  count;
413        sk_sp<SkXfermode>    xfermode;
414        int                  nindices;
415        SkPaint              paint;
416        bool                 has_texs;
417        bool                 has_colors;
418        bool                 has_indices;
419        void draw(SkCanvas* c) override {
420            SkPoint* vertices = pod<SkPoint>(this, 0);
421            size_t offset = count*sizeof(SkPoint);
422
423            SkPoint* texs = nullptr;
424            if (has_texs) {
425                texs = pod<SkPoint>(this, offset);
426                offset += count*sizeof(SkPoint);
427            }
428
429            SkColor* colors = nullptr;
430            if (has_colors) {
431                colors = pod<SkColor>(this, offset);
432                offset += count*sizeof(SkColor);
433            }
434
435            uint16_t* indices = nullptr;
436            if (has_indices) {
437                indices = pod<uint16_t>(this, offset);
438            }
439            c->drawVertices(mode, count, vertices, texs, colors, xfermode.get(),
440                            indices, nindices, paint);
441        }
442        void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
443    };
444    struct DrawAtlas final : Op {
445        DrawAtlas(const SkImage* atlas, int count, SkXfermode::Mode xfermode,
446                  const SkRect* cull, const SkPaint* paint, bool has_colors)
447            : atlas(sk_ref_sp(atlas)), count(count), xfermode(xfermode), has_colors(has_colors) {
448            if (cull)  { this->cull  = *cull; }
449            if (paint) { this->paint = *paint; }
450        }
451        sk_sp<const SkImage> atlas;
452        int                  count;
453        SkXfermode::Mode     xfermode;
454        SkRect               cull = kUnset;
455        SkPaint              paint;
456        bool                 has_colors;
457        void draw(SkCanvas* c) override {
458            auto xforms = pod<SkRSXform>(this, 0);
459            auto   texs = pod<SkRect>(this, count*sizeof(SkRSXform));
460            auto colors = has_colors
461                ? pod<SkColor>(this, count*(sizeof(SkRSXform) + sizeof(SkRect)))
462                : nullptr;
463            c->drawAtlas(atlas.get(), xforms, texs, colors, count, xfermode,
464                         maybe_unset(cull), &paint);
465        }
466        void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint, &atlas); }
467    };
468}
469
470template <typename T, typename... Args>
471static void* push(SkTDArray<uint8_t>* bytes, size_t pod, Args&&... args) {
472    size_t skip = SkAlignPtr(sizeof(T) + pod);
473    auto op = (T*)bytes->append(skip);
474    new (op) T{ std::forward<Args>(args)... };
475    op->skip = skip;
476    return op+1;
477}
478
479template <typename Fn>
480static void map(SkTDArray<uint8_t>* bytes, Fn&& fn) {
481    auto end = bytes->end();
482    for (uint8_t* ptr = bytes->begin(); ptr < end; ) {
483        auto op = (Op*)ptr;
484        fn(op);
485        ptr += op->skip;
486    }
487}
488
489void SkLiteDL::   save() { push   <Save>(&fBytes, 0); }
490void SkLiteDL::restore() { push<Restore>(&fBytes, 0); }
491void SkLiteDL::saveLayer(const SkRect* bounds, const SkPaint* paint,
492                         const SkImageFilter* backdrop, SkCanvas::SaveLayerFlags flags) {
493    push<SaveLayer>(&fBytes, 0, bounds, paint, backdrop, flags);
494}
495
496void SkLiteDL::   concat(const SkMatrix& matrix) { push   <Concat>(&fBytes, 0, matrix); }
497void SkLiteDL::setMatrix(const SkMatrix& matrix) { push<SetMatrix>(&fBytes, 0, matrix); }
498void SkLiteDL::translateZ(SkScalar dz) { push<TranslateZ>(&fBytes, 0, dz); }
499
500void SkLiteDL::clipPath(const SkPath& path, SkRegion::Op op, bool aa) {
501    push<ClipPath>(&fBytes, 0, path, op, aa);
502}
503void SkLiteDL::clipRect(const SkRect& rect, SkRegion::Op op, bool aa) {
504    push<ClipRect>(&fBytes, 0, rect, op, aa);
505}
506void SkLiteDL::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool aa) {
507    push<ClipRRect>(&fBytes, 0, rrect, op, aa);
508}
509void SkLiteDL::clipRegion(const SkRegion& region, SkRegion::Op op) {
510    push<ClipRegion>(&fBytes, 0, region, op);
511}
512
513void SkLiteDL::drawPaint(const SkPaint& paint) {
514    push<DrawPaint>(&fBytes, 0, paint);
515}
516void SkLiteDL::drawPath(const SkPath& path, const SkPaint& paint) {
517    push<DrawPath>(&fBytes, 0, path, paint);
518}
519void SkLiteDL::drawRect(const SkRect& rect, const SkPaint& paint) {
520    push<DrawRect>(&fBytes, 0, rect, paint);
521}
522void SkLiteDL::drawOval(const SkRect& oval, const SkPaint& paint) {
523    push<DrawOval>(&fBytes, 0, oval, paint);
524}
525void SkLiteDL::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
526    push<DrawRRect>(&fBytes, 0, rrect, paint);
527}
528void SkLiteDL::drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) {
529    push<DrawDRRect>(&fBytes, 0, outer, inner, paint);
530}
531
532void SkLiteDL::drawAnnotation(const SkRect& rect, const char* key, SkData* value) {
533    size_t bytes = strlen(key)+1;
534    void* pod = push<DrawAnnotation>(&fBytes, bytes, rect, value);
535    copy_v(pod, key,bytes);
536}
537void SkLiteDL::drawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
538    push<DrawDrawable>(&fBytes, 0, drawable, matrix);
539}
540void SkLiteDL::drawPicture(const SkPicture* picture,
541                           const SkMatrix* matrix, const SkPaint* paint) {
542    push<DrawPicture>(&fBytes, 0, picture, matrix, paint);
543}
544void SkLiteDL::drawShadowedPicture(const SkPicture* picture,
545                                   const SkMatrix* matrix, const SkPaint* paint) {
546    push<DrawShadowedPicture>(&fBytes, 0, picture, matrix, paint);
547}
548
549void SkLiteDL::drawBitmap(const SkBitmap& bm, SkScalar x, SkScalar y, const SkPaint* paint) {
550    push<DrawImage>(&fBytes, 0, SkImage::MakeFromBitmap(bm), x,y, paint);
551}
552void SkLiteDL::drawBitmapNine(const SkBitmap& bm, const SkIRect& center,
553                              const SkRect& dst, const SkPaint* paint) {
554    push<DrawImageNine>(&fBytes, 0, SkImage::MakeFromBitmap(bm), center, dst, paint);
555}
556void SkLiteDL::drawBitmapRect(const SkBitmap& bm, const SkRect* src, const SkRect& dst,
557                              const SkPaint* paint, SkCanvas::SrcRectConstraint constraint) {
558    push<DrawImageRect>(&fBytes, 0, SkImage::MakeFromBitmap(bm), src, dst, paint, constraint);
559}
560
561void SkLiteDL::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
562    push<DrawImage>(&fBytes, 0, sk_ref_sp(image), x,y, paint);
563}
564void SkLiteDL::drawImageNine(const SkImage* image, const SkIRect& center,
565                             const SkRect& dst, const SkPaint* paint) {
566    push<DrawImageNine>(&fBytes, 0, sk_ref_sp(image), center, dst, paint);
567}
568void SkLiteDL::drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
569                             const SkPaint* paint, SkCanvas::SrcRectConstraint constraint) {
570    push<DrawImageRect>(&fBytes, 0, sk_ref_sp(image), src, dst, paint, constraint);
571}
572void SkLiteDL::drawImageLattice(const SkImage* image, const SkCanvas::Lattice& lattice,
573                                const SkRect& dst, const SkPaint* paint) {
574    int xs = lattice.fXCount, ys = lattice.fYCount;
575    size_t bytes = (xs + ys) * sizeof(int);
576    void* pod = push<DrawImageLattice>(&fBytes, bytes, sk_ref_sp(image), xs, ys, dst, paint);
577    copy_v(pod, lattice.fXDivs, xs,
578                lattice.fYDivs, ys);
579}
580
581void SkLiteDL::drawText(const void* text, size_t bytes,
582                        SkScalar x, SkScalar y, const SkPaint& paint) {
583    void* pod = push<DrawText>(&fBytes, bytes, bytes, x, y, paint);
584    copy_v(pod, (const char*)text,bytes);
585}
586void SkLiteDL::drawPosText(const void* text, size_t bytes,
587                           const SkPoint pos[], const SkPaint& paint) {
588    int n = paint.countText(text, bytes);
589    void* pod = push<DrawPosText>(&fBytes, n*sizeof(SkPoint)+bytes, bytes, paint, n);
590    copy_v(pod, pos,n, (const char*)text,bytes);
591}
592void SkLiteDL::drawPosTextH(const void* text, size_t bytes,
593                           const SkScalar xs[], SkScalar y, const SkPaint& paint) {
594    int n = paint.countText(text, bytes);
595    void* pod = push<DrawPosTextH>(&fBytes, n*sizeof(SkScalar)+bytes, bytes, y, paint, n);
596    copy_v(pod, xs,n, (const char*)text,bytes);
597}
598void SkLiteDL::drawTextOnPath(const void* text, size_t bytes,
599                              const SkPath& path, const SkMatrix* matrix, const SkPaint& paint) {
600    void* pod = push<DrawTextOnPath>(&fBytes, bytes, bytes, path, matrix, paint);
601    copy_v(pod, (const char*)text,bytes);
602}
603void SkLiteDL::drawTextRSXform(const void* text, size_t bytes,
604                               const SkRSXform xforms[], const SkRect* cull, const SkPaint& paint) {
605    int n = paint.countText(text, bytes);
606    void* pod = push<DrawTextRSXform>(&fBytes, bytes+n*sizeof(SkRSXform), bytes, cull, paint);
607    copy_v(pod, (const char*)text,bytes, xforms,n);
608}
609void SkLiteDL::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint) {
610    push<DrawTextBlob>(&fBytes, 0, blob, x,y, paint);
611}
612
613void SkLiteDL::drawPatch(const SkPoint points[12], const SkColor colors[4], const SkPoint texs[4],
614                         SkXfermode* xfermode, const SkPaint& paint) {
615    push<DrawPatch>(&fBytes, 0, points, colors, texs, xfermode, paint);
616}
617void SkLiteDL::drawPoints(SkCanvas::PointMode mode, size_t count, const SkPoint points[],
618                          const SkPaint& paint) {
619    void* pod = push<DrawPoints>(&fBytes, count*sizeof(SkPoint), mode, count, paint);
620    copy_v(pod, points,count);
621}
622void SkLiteDL::drawVertices(SkCanvas::VertexMode mode, int count, const SkPoint vertices[],
623                            const SkPoint texs[], const SkColor colors[], SkXfermode* xfermode,
624                            const uint16_t indices[], int nindices, const SkPaint& paint) {
625    size_t bytes = count * sizeof(SkPoint);
626    if (texs  )  { bytes += count    * sizeof(SkPoint); }
627    if (colors)  { bytes += count    * sizeof(SkColor); }
628    if (indices) { bytes += nindices * sizeof(uint16_t); }
629    void* pod = push<DrawVertices>(&fBytes, bytes, mode, count, xfermode, nindices, paint,
630                                   texs != nullptr, colors != nullptr, indices != nullptr);
631    copy_v(pod, vertices, count,
632                    texs, texs    ? count    : 0,
633                  colors, colors  ? count    : 0,
634                 indices, indices ? nindices : 0);
635}
636void SkLiteDL::drawAtlas(const SkImage* atlas, const SkRSXform xforms[], const SkRect texs[],
637                         const SkColor colors[], int count, SkXfermode::Mode xfermode,
638                         const SkRect* cull, const SkPaint* paint) {
639    size_t bytes = count*(sizeof(SkRSXform) + sizeof(SkRect));
640    if (colors) {
641        bytes += count*sizeof(SkColor);
642    }
643    void* pod = push<DrawAtlas>(&fBytes, bytes,
644                                atlas, count, xfermode, cull, paint, colors != nullptr);
645    copy_v(pod, xforms, count,
646                  texs, count,
647                colors, colors ? count : 0);
648}
649
650
651void SkLiteDL::onDraw(SkCanvas* canvas) {
652    map(&fBytes, [canvas](Op* op) { op->draw(canvas); });
653}
654
655void SkLiteDL::optimizeFor(GrContext* ctx) {
656    map(&fBytes, [ctx](Op* op) { op->optimizeFor(ctx); });
657}
658
659void SkLiteDL::makeThreadsafe() {
660    map(&fBytes, [](Op* op) { op->makeThreadsafe(); });
661}
662
663SkRect SkLiteDL::onGetBounds() {
664    return fBounds;
665}
666
667#if !defined(SK_LITEDL_USES)
668    #define  SK_LITEDL_USES 16
669#endif
670
671SkLiteDL:: SkLiteDL() : fUsesRemaining(SK_LITEDL_USES) {}
672SkLiteDL::~SkLiteDL() {}
673
674// If you're tempted to make this lock free, please don't forget about ABA.
675static SkSpinlock gFreeStackLock;
676static SkLiteDL*  gFreeStack = nullptr;
677
678sk_sp<SkLiteDL> SkLiteDL::New(SkRect bounds) {
679    sk_sp<SkLiteDL> dl;
680    {
681        SkAutoMutexAcquire lock(gFreeStackLock);
682        if (gFreeStack) {
683            dl.reset(gFreeStack);  // Adopts the ref the stack's been holding.
684            gFreeStack = gFreeStack->fNext;
685        }
686    }
687
688    if (!dl) {
689        dl.reset(new SkLiteDL);
690    }
691
692    dl->fBounds = bounds;
693    return dl;
694}
695
696void SkLiteDL::internal_dispose() const {
697    // Whether we delete this or leave it on the free stack,
698    // we want its refcnt at 1.
699    this->internal_dispose_restore_refcnt_to_1();
700
701    auto self = const_cast<SkLiteDL*>(this);
702    map(&self->fBytes, [](Op* op) { op->~Op(); });
703
704    if (--self->fUsesRemaining > 0) {
705        self->fBytes.rewind();
706
707        SkAutoMutexAcquire lock(gFreeStackLock);
708        self->fNext = gFreeStack;
709        gFreeStack = self;
710        return;
711    }
712
713    delete this;
714}
715
716void SkLiteDL::PurgeFreelist() {
717    SkAutoMutexAcquire lock(gFreeStackLock);
718    while (gFreeStack) {
719        SkLiteDL* top = gFreeStack;
720        gFreeStack = gFreeStack->fNext;
721        delete top;   // Calling unref() here would just put it back on the list!
722    }
723}
724