1 /* 2 * Copyright 2017 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 #ifndef SkThreadedBMPDevice_DEFINED 9 #define SkThreadedBMPDevice_DEFINED 10 11 #include "SkBitmapDevice.h" 12 #include "SkDraw.h" 13 #include "SkTaskGroup2D.h" 14 15 class SkThreadedBMPDevice : public SkBitmapDevice { 16 public: 17 // When threads = 0, we make fThreadCnt = tiles. Otherwise fThreadCnt = threads. 18 // When executor = nullptr, we manages the thread pool. Otherwise, the caller manages it. 19 SkThreadedBMPDevice(const SkBitmap& bitmap, int tiles, int threads = 0, 20 SkExecutor* executor = nullptr); 21 22 ~SkThreadedBMPDevice() override { fQueue.finish(); } 23 24 protected: 25 void drawPaint(const SkPaint& paint) override; 26 void drawPoints(SkCanvas::PointMode mode, size_t count, 27 const SkPoint[], const SkPaint& paint) override; 28 void drawRect(const SkRect& r, const SkPaint& paint) override; 29 void drawRRect(const SkRRect& rr, const SkPaint& paint) override; 30 31 void drawPath(const SkPath&, const SkPaint&, const SkMatrix* prePathMatrix, 32 bool pathIsMutable) override; 33 void drawBitmap(const SkBitmap&, SkScalar x, SkScalar y, const SkPaint&) override; 34 void drawSprite(const SkBitmap&, int x, int y, const SkPaint&) override; 35 36 void drawText(const void* text, size_t len, SkScalar x, SkScalar y, 37 const SkPaint&) override; 38 void drawPosText(const void* text, size_t len, const SkScalar pos[], 39 int scalarsPerPos, const SkPoint& offset, const SkPaint& paint) override; 40 void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&) override; 41 void drawDevice(SkBaseDevice*, int x, int y, const SkPaint&) override; 42 43 void flush() override; 44 45 private: 46 struct DrawState { 47 SkPixmap fDst; 48 SkMatrix fMatrix; 49 SkRasterClip fRC; 50 51 DrawState() {} 52 explicit DrawState(SkThreadedBMPDevice* dev); 53 54 SkDraw getDraw() const; 55 }; 56 57 class TileDraw : public SkDraw { 58 public: TileDraw(const DrawState& ds, const SkIRect& tileBounds); 59 private: SkRasterClip fTileRC; 60 }; 61 62 struct DrawElement { 63 using DrawFn = std::function<void(SkArenaAlloc* threadAlloc, const DrawState& ds, 64 const SkIRect& tileBounds)>; 65 66 DrawFn fDrawFn; 67 DrawState fDS; 68 SkIRect fDrawBounds; 69 }; 70 71 class DrawQueue { 72 public: 73 static constexpr int MAX_QUEUE_SIZE = 100000; 74 75 DrawQueue(SkThreadedBMPDevice* device) : fDevice(device) {} 76 void reset(); 77 78 // For ~SkThreadedBMPDevice() to shutdown tasks, we use this instead of reset because reset 79 // will start new tasks. 80 void finish() { fTasks->finish(); } 81 82 SK_ALWAYS_INLINE void push(const SkRect& rawDrawBounds, 83 DrawElement::DrawFn&& drawFn) { 84 if (fSize == MAX_QUEUE_SIZE) { 85 this->reset(); 86 } 87 SkASSERT(fSize < MAX_QUEUE_SIZE); 88 89 DrawElement* element = &fElements[fSize++]; 90 element->fDS = DrawState(fDevice); 91 element->fDrawFn = std::move(drawFn); 92 element->fDrawBounds = fDevice->transformDrawBounds(rawDrawBounds); 93 fTasks->addColumn(); 94 } 95 96 private: 97 SkThreadedBMPDevice* fDevice; 98 std::unique_ptr<SkTaskGroup2D> fTasks; 99 DrawElement fElements[MAX_QUEUE_SIZE]; 100 int fSize; 101 }; 102 103 SkIRect transformDrawBounds(const SkRect& drawBounds) const; 104 105 const int fTileCnt; 106 const int fThreadCnt; 107 SkTArray<SkIRect> fTileBounds; 108 109 /** 110 * This can either be 111 * 1. fInternalExecutor.get() which means that we're managing the thread pool's life cycle. 112 * 2. provided by our caller which means that our caller is managing the threads' life cycle. 113 * In the 2nd case, fInternalExecutor == nullptr. 114 */ 115 SkExecutor* fExecutor = nullptr; 116 std::unique_ptr<SkExecutor> fInternalExecutor; 117 118 DrawQueue fQueue; 119 120 typedef SkBitmapDevice INHERITED; 121 }; 122 123 #endif // SkThreadedBMPDevice_DEFINED 124