/* * Copyright 2017 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SkThreadedBMPDevice_DEFINED #define SkThreadedBMPDevice_DEFINED #include "SkDraw.h" #include "SkBitmapDevice.h" #include class TiledDrawScheduler { public: using WorkFunc = std::function; virtual ~TiledDrawScheduler() {} virtual void signal() = 0; // signal that one more draw is available for all tiles // Tell scheduler that no more draw calls will be added (no signal will be called). virtual void finish() = 0; // Handle the next draw available. This method will block until // (1) the next draw is finished, or // (2) the finish is called // The method will return true for case (1) and false for case (2). // When there's no draw available and we haven't called finish, we will just wait. // In many cases, the parameter tileIndex specifies the tile that the next draw should happen. // However, for some schedulers, that tileIndex may only be a hint and the scheduler is free // to find another tile to draw. In that case, tileIndex will be changed to the actual tileIndex // where the draw happens. virtual bool next(int& tileIndex) = 0; }; /////////////////////////////////////////////////////////////////////////////// class SkThreadedBMPDevice : public SkBitmapDevice { public: // When threads = 0, we make fThreadCnt = fTileCnt SkThreadedBMPDevice(const SkBitmap& bitmap, int tiles, int threads = 0); ~SkThreadedBMPDevice() override { finishThreads(); } protected: void drawPaint(const SkPaint& paint) override; void drawPoints(SkCanvas::PointMode mode, size_t count, const SkPoint[], const SkPaint& paint) override; void drawRect(const SkRect& r, const SkPaint& paint) override; void drawRRect(const SkRRect& rr, const SkPaint& paint) override; void drawPath(const SkPath&, const SkPaint&, const SkMatrix* prePathMatrix, bool pathIsMutable) override; void drawBitmap(const SkBitmap&, SkScalar x, SkScalar y, const SkPaint&) override; void drawSprite(const SkBitmap&, int x, int y, const SkPaint&) override; void drawText(const void* text, size_t len, SkScalar x, SkScalar y, const SkPaint&) override; void drawPosText(const void* text, size_t len, const SkScalar pos[], int scalarsPerPos, const SkPoint& offset, const SkPaint& paint) override; void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&) override; void drawDevice(SkBaseDevice*, int x, int y, const SkPaint&) override; void flush() override; private: struct DrawElement { SkIRect fDrawBounds; std::function fDrawFn; }; struct DrawState; SkIRect transformDrawBounds(const SkRect& drawBounds) const; void startThreads(); void finishThreads(); static constexpr int MAX_QUEUE_SIZE = 100000; const int fTileCnt; const int fThreadCnt; std::unique_ptr fScheduler; SkTArray fTileBounds; SkTArray> fThreadFutures; DrawElement fQueue[MAX_QUEUE_SIZE]; int fQueueSize; typedef SkBitmapDevice INHERITED; }; #endif // SkThreadedBMPDevice_DEFINED