blob: d7f3d6b3b7d78614c4ba64a23d18720f96ef4834 [file] [log] [blame]
/*
* 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 <future>
class TiledDrawScheduler {
public:
using WorkFunc = std::function<void(int, int)>;
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<void(const SkIRect& threadBounds)> 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<TiledDrawScheduler> fScheduler;
SkTArray<SkIRect> fTileBounds;
SkTArray<std::future<void>> fThreadFutures;
DrawElement fQueue[MAX_QUEUE_SIZE];
int fQueueSize;
typedef SkBitmapDevice INHERITED;
};
#endif // SkThreadedBMPDevice_DEFINED