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