Home | History | Annotate | Download | only in core
      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