aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Yuqian Li <liyuqian@google.com>2017-08-28 16:29:46 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-08-30 19:39:27 +0000
commit604a71a5e08ed33b9c983113852e63120f8616ef (patch)
treecd51e485129f05d7b87103481f84248db5d7e2c8
parent195c05b6d5afbd65f803816938e24eebd51292c8 (diff)
Allow providing SkExecutor to SkThreadedBMPDevice
So that callers could manage the thread pool themselves instead of relying on SkThreadBMPDevice. Bug: skia: Change-Id: Idbeafc9ac5d111370fd1b74f6eab9ac8df179940 Reviewed-on: https://skia-review.googlesource.com/39760 Reviewed-by: Mike Klein <mtklein@google.com> Commit-Queue: Yuqian Li <liyuqian@google.com>
-rw-r--r--src/core/SkThreadedBMPDevice.cpp35
-rw-r--r--src/core/SkThreadedBMPDevice.h23
2 files changed, 41 insertions, 17 deletions
diff --git a/src/core/SkThreadedBMPDevice.cpp b/src/core/SkThreadedBMPDevice.cpp
index ac004b1a76..9b6be1cfba 100644
--- a/src/core/SkThreadedBMPDevice.cpp
+++ b/src/core/SkThreadedBMPDevice.cpp
@@ -176,7 +176,6 @@ private:
};
void SkThreadedBMPDevice::startThreads() {
- SkASSERT(fThreadFutures.count() == 0);
SkASSERT(fQueueSize == 0);
TiledDrawScheduler::WorkFunc work = [this](int tileIndex, int drawIndex){
@@ -190,29 +189,40 @@ void SkThreadedBMPDevice::startThreads() {
// using Scheduler = TiledDrawSchedulerBySpinning;
using Scheduler = TiledDrawSchedulerFlexible;
fScheduler.reset(new Scheduler(fTileCnt, work));
- for(int i = 0; i < fThreadCnt; ++i) {
- fThreadFutures.push_back(std::async(std::launch::async, [this, i]() {
- int tileIndex = i;
- while (fScheduler->next(tileIndex)) {}
- }));
- }
+
+ // We intentionally call the int parameter tileIndex although it ranges from 0 to fThreadCnt-1.
+ // For some schedulers (e.g., TiledDrawSchedulerBySemaphores and TiledDrawSchedulerBySpinning),
+ // fThreadCnt should be equal to fTileCnt so it doesn't make a difference.
+ //
+ // For TiledDrawSchedulerFlexible, the input tileIndex provides only a hint about which tile
+ // the current thread should draw; the scheduler may later modify that tileIndex to draw on
+ // another tile.
+ fTaskGroup->batch(fThreadCnt, [this](int tileIndex){
+ while (fScheduler->next(tileIndex)) {}
+ });
}
void SkThreadedBMPDevice::finishThreads() {
fScheduler->finish();
- for(auto& future : fThreadFutures) {
- future.wait();
- }
- fThreadFutures.reset();
+ fTaskGroup->wait();
fQueueSize = 0;
fScheduler.reset(nullptr);
}
-SkThreadedBMPDevice::SkThreadedBMPDevice(const SkBitmap& bitmap, int tiles, int threads)
+SkThreadedBMPDevice::SkThreadedBMPDevice(const SkBitmap& bitmap,
+ int tiles,
+ int threads,
+ SkExecutor* executor)
: INHERITED(bitmap)
, fTileCnt(tiles)
, fThreadCnt(threads <= 0 ? tiles : threads)
{
+ if (executor == nullptr) {
+ fInternalExecutor = SkExecutor::MakeThreadPool(fThreadCnt);
+ executor = fInternalExecutor.get();
+ }
+ fExecutor = executor;
+
// Tiling using stripes for now; we'll explore better tiling in the future.
int h = (bitmap.height() + fTileCnt - 1) / SkTMax(fTileCnt, 1);
int w = bitmap.width();
@@ -221,6 +231,7 @@ SkThreadedBMPDevice::SkThreadedBMPDevice(const SkBitmap& bitmap, int tiles, int
fTileBounds.push_back(SkIRect::MakeLTRB(0, top, w, top + h));
}
fQueueSize = 0;
+ fTaskGroup.reset(new SkTaskGroup(*fExecutor));
startThreads();
}
diff --git a/src/core/SkThreadedBMPDevice.h b/src/core/SkThreadedBMPDevice.h
index d7f3d6b3b7..aa2276bd27 100644
--- a/src/core/SkThreadedBMPDevice.h
+++ b/src/core/SkThreadedBMPDevice.h
@@ -8,11 +8,10 @@
#ifndef SkThreadedBMPDevice_DEFINED
#define SkThreadedBMPDevice_DEFINED
+#include "SkTaskGroup.h"
#include "SkDraw.h"
#include "SkBitmapDevice.h"
-#include <future>
-
class TiledDrawScheduler {
public:
using WorkFunc = std::function<void(int, int)>;
@@ -39,8 +38,11 @@ public:
///////////////////////////////////////////////////////////////////////////////
class SkThreadedBMPDevice : public SkBitmapDevice {
public:
- // When threads = 0, we make fThreadCnt = fTileCnt
- SkThreadedBMPDevice(const SkBitmap& bitmap, int tiles, int threads = 0);
+ // When threads = 0, we make fThreadCnt = tiles. Otherwise fThreadCnt = threads.
+ // When executor = nullptr, we manages the thread pool. Otherwise, the caller manages it.
+ SkThreadedBMPDevice(const SkBitmap& bitmap, int tiles, int threads = 0,
+ SkExecutor* executor = nullptr);
+
~SkThreadedBMPDevice() override { finishThreads(); }
protected:
@@ -83,7 +85,18 @@ private:
const int fThreadCnt;
std::unique_ptr<TiledDrawScheduler> fScheduler;
SkTArray<SkIRect> fTileBounds;
- SkTArray<std::future<void>> fThreadFutures;
+
+ /**
+ * This can either be
+ * 1. fInternalExecutor.get() which means that we're managing the thread pool's life cycle.
+ * 2. provided by our caller which means that our caller is managing the threads' life cycle.
+ * In the 2nd case, fInternalExecutor == nullptr.
+ */
+ SkExecutor* fExecutor = nullptr;
+ std::unique_ptr<SkExecutor> fInternalExecutor;
+
+ std::unique_ptr<SkTaskGroup> fTaskGroup; // generated from fExecutor
+
DrawElement fQueue[MAX_QUEUE_SIZE];
int fQueueSize;