OLD | NEW |
(Empty) | |
| 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 "SkLiteDL.h" |
| 10 #include "SkMutex.h" |
| 11 #include "SkSpinlock.h" |
| 12 |
| 13 namespace { |
| 14 struct Op { |
| 15 virtual ~Op() {} |
| 16 virtual void draw(SkCanvas*) = 0; |
| 17 |
| 18 size_t skip; |
| 19 }; |
| 20 |
| 21 struct Save final : Op { void draw(SkCanvas* c) override { c-> save();
} }; |
| 22 struct Restore final : Op { void draw(SkCanvas* c) override { c->restore();
} }; |
| 23 |
| 24 struct Concat final : Op { |
| 25 Concat(const SkMatrix& matrix) : matrix(matrix) {} |
| 26 SkMatrix matrix; |
| 27 void draw(SkCanvas* c) override { c->concat(matrix); } |
| 28 }; |
| 29 struct SetMatrix final : Op { |
| 30 SetMatrix(const SkMatrix& matrix) : matrix(matrix) {} |
| 31 SkMatrix matrix; |
| 32 void draw(SkCanvas* c) override { c->setMatrix(matrix); } |
| 33 }; |
| 34 |
| 35 struct ClipRect final : Op { |
| 36 ClipRect(const SkRect& rect, SkRegion::Op op, bool aa) : rect(rect), op(
op), aa(aa) {} |
| 37 SkRect rect; |
| 38 SkRegion::Op op; |
| 39 bool aa; |
| 40 void draw(SkCanvas* c) override { c->clipRect(rect, op, aa); } |
| 41 }; |
| 42 |
| 43 struct DrawRect final : Op { |
| 44 DrawRect(const SkRect& rect, const SkPaint& paint) : rect(rect), paint(p
aint) {} |
| 45 SkRect rect; |
| 46 SkPaint paint; |
| 47 void draw(SkCanvas* c) override { c->drawRect(rect, paint); } |
| 48 }; |
| 49 |
| 50 struct DrawPath final : Op { |
| 51 DrawPath(const SkPath& path, const SkPaint& paint) : path(path), paint(p
aint) {} |
| 52 SkPath path; |
| 53 SkPaint paint; |
| 54 void draw(SkCanvas* c) override { c->drawPath(path, paint); } |
| 55 }; |
| 56 |
| 57 template <typename T, typename... Args> |
| 58 static void* push(SkTDArray<uint8_t>* bytes, size_t pod, Args&&... args) { |
| 59 size_t skip = SkAlignPtr(sizeof(T) + pod); |
| 60 auto op = (T*)bytes->append(skip); |
| 61 new (op) T{ std::forward<Args>(args)... }; |
| 62 op->skip = skip; |
| 63 return op+1; |
| 64 } |
| 65 |
| 66 template <typename Fn> |
| 67 static void map(SkTDArray<uint8_t>* bytes, Fn&& fn) { |
| 68 for (uint8_t* ptr = bytes->begin(); ptr < bytes->end(); ) { |
| 69 auto op = (Op*)ptr; |
| 70 fn(op); |
| 71 ptr += op->skip; |
| 72 } |
| 73 } |
| 74 } |
| 75 |
| 76 void SkLiteDL:: save() { push <Save>(&fBytes, 0); } |
| 77 void SkLiteDL::restore() { push<Restore>(&fBytes, 0); } |
| 78 |
| 79 void SkLiteDL:: concat(const SkMatrix& matrix) { push <Concat>(&fBytes, 0, m
atrix); } |
| 80 void SkLiteDL::setMatrix(const SkMatrix& matrix) { push<SetMatrix>(&fBytes, 0, m
atrix); } |
| 81 |
| 82 void SkLiteDL::clipRect(const SkRect& rect, SkRegion::Op op, bool aa) { |
| 83 push<ClipRect>(&fBytes, 0, rect, op, aa); |
| 84 } |
| 85 |
| 86 void SkLiteDL::drawRect(const SkRect& rect, const SkPaint& paint) { |
| 87 push<DrawRect>(&fBytes, 0, rect, paint); |
| 88 } |
| 89 void SkLiteDL::drawPath(const SkPath& path, const SkPaint& paint) { |
| 90 push<DrawPath>(&fBytes, 0, path, paint); |
| 91 } |
| 92 |
| 93 void SkLiteDL::onDraw(SkCanvas* canvas) { |
| 94 map(&fBytes, [canvas](Op* op) { op->draw(canvas); }); |
| 95 } |
| 96 |
| 97 SkRect SkLiteDL::onGetBounds() { |
| 98 return fBounds; |
| 99 } |
| 100 |
| 101 SkLiteDL:: SkLiteDL() {} |
| 102 SkLiteDL::~SkLiteDL() {} |
| 103 |
| 104 static const int kFreeStackByteLimit = 128*1024; |
| 105 static const int kFreeStackCountLimit = 8; |
| 106 |
| 107 static SkSpinlock gFreeStackLock; |
| 108 static SkLiteDL* gFreeStack = nullptr; |
| 109 static int gFreeStackCount = 0; |
| 110 |
| 111 sk_sp<SkLiteDL> SkLiteDL::New(SkRect bounds) { |
| 112 sk_sp<SkLiteDL> dl; |
| 113 { |
| 114 SkAutoMutexAcquire lock(gFreeStackLock); |
| 115 if (gFreeStack) { |
| 116 dl.reset(gFreeStack); // Adopts the ref the stack's been holding. |
| 117 gFreeStack = gFreeStack->fNext; |
| 118 gFreeStackCount--; |
| 119 } |
| 120 } |
| 121 |
| 122 if (!dl) { |
| 123 dl.reset(new SkLiteDL); |
| 124 } |
| 125 |
| 126 dl->fBounds = bounds; |
| 127 return dl; |
| 128 } |
| 129 |
| 130 void SkLiteDL::internal_dispose() const { |
| 131 // Whether we delete this or leave it on the free stack, |
| 132 // we want its refcnt at 1. |
| 133 this->internal_dispose_restore_refcnt_to_1(); |
| 134 |
| 135 auto self = const_cast<SkLiteDL*>(this); |
| 136 map(&self->fBytes, [](Op* op) { op->~Op(); }); |
| 137 |
| 138 if (self->fBytes.reserved() < kFreeStackByteLimit) { |
| 139 self->fBytes.rewind(); |
| 140 SkAutoMutexAcquire lock(gFreeStackLock); |
| 141 if (gFreeStackCount < kFreeStackCountLimit) { |
| 142 self->fNext = gFreeStack; |
| 143 gFreeStack = self; |
| 144 gFreeStackCount++; |
| 145 return; |
| 146 } |
| 147 } |
| 148 |
| 149 delete this; |
| 150 } |
OLD | NEW |