summaryrefslogtreecommitdiff
path: root/libs/hwui/PathCache.cpp
diff options
context:
space:
mode:
author Romain Guy <romainguy@google.com> 2013-03-11 20:48:31 -0700
committer Romain Guy <romainguy@google.com> 2013-03-12 15:06:42 -0700
commit5dc7fa709646799a5207a5d217f70aa02bf4a3aa (patch)
tree3ebf45fa51bd0373f77aa451868df2d6ae1a8a87 /libs/hwui/PathCache.cpp
parent8818d84a3540de6e53e5d82e2112292102574118 (diff)
Add TaskManager API
This API can be used to run arbitrary tasks on a pool of worker threads. The number of threads is calculated based on the number of CPU cores available. The API is made of 3 classes: TaskManager Creates and manages the worker threads. Task Describes the work to be done and the type of the output. A task contains a future used to wait for the worker thread to be done computing the result of the task. TaskProcessor The processor dispatches tasks to the TaskManager and is responsible for performing the computation required by each task. A processor will only be asked to process tasks sent to the manager through the processor. A typical use case: class MyTask: Task<MyType> class MyProcessor: TaskProcessor<MyType> TaskManager m = new TaskManager(); MyProcessor p = new MyProcessor(m); MyTask t = new MyTask(); p.add(t); // Waits until the result is available MyType result = t->getResult(); Change-Id: I1fe845ba4c49bb0e1b0627ab147f9a861c8e0749
Diffstat (limited to 'libs/hwui/PathCache.cpp')
-rw-r--r--libs/hwui/PathCache.cpp109
1 files changed, 41 insertions, 68 deletions
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index 9e6ec8488ebf..afdc2c9cd4ed 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -31,69 +31,32 @@ namespace uirenderer {
// Path precaching
///////////////////////////////////////////////////////////////////////////////
-bool PathCache::PrecacheThread::threadLoop() {
- mSignal.wait();
- Vector<Task> tasks;
- {
- Mutex::Autolock l(mLock);
- tasks = mTasks;
- mTasks.clear();
- }
-
- Caches& caches = Caches::getInstance();
- uint32_t maxSize = caches.maxTextureSize;
-
- ATRACE_BEGIN("pathPrecache");
- for (size_t i = 0; i < tasks.size(); i++) {
- const Task& task = tasks.itemAt(i);
-
- float left, top, offset;
- uint32_t width, height;
- PathCache::computePathBounds(task.path, task.paint, left, top, offset, width, height);
-
- if (width <= maxSize && height <= maxSize) {
- SkBitmap* bitmap = new SkBitmap();
-
- PathTexture* texture = task.texture;
- texture->left = left;
- texture->top = top;
- texture->offset = offset;
- texture->width = width;
- texture->height = height;
-
- PathCache::drawPath(task.path, task.paint, *bitmap, left, top, offset, width, height);
-
- texture->future()->produce(bitmap);
- } else {
- task.texture->future()->produce(NULL);
- }
- }
- ATRACE_END();
- return true;
+PathCache::PathProcessor::PathProcessor(Caches& caches):
+ TaskProcessor<SkBitmap*>(&caches.tasks), mMaxTextureSize(caches.maxTextureSize) {
}
-void PathCache::PrecacheThread::addTask(PathTexture* texture, SkPath* path, SkPaint* paint) {
- if (!isRunning()) {
- run("libhwui:pathPrecache", PRIORITY_DEFAULT);
- }
-
- Task task;
- task.texture = texture;
- task.path = path;
- task.paint = paint;
-
- Mutex::Autolock l(mLock);
- mTasks.add(task);
- mSignal.signal();
-}
-
-void PathCache::PrecacheThread::exit() {
- {
- Mutex::Autolock l(mLock);
- mTasks.clear();
+void PathCache::PathProcessor::onProcess(const sp<Task<SkBitmap*> >& task) {
+ sp<PathTask> t = static_cast<PathTask* >(task.get());
+ ATRACE_NAME("pathPrecache");
+
+ float left, top, offset;
+ uint32_t width, height;
+ PathCache::computePathBounds(t->path, t->paint, left, top, offset, width, height);
+
+ PathTexture* texture = t->texture;
+ texture->left = left;
+ texture->top = top;
+ texture->offset = offset;
+ texture->width = width;
+ texture->height = height;
+
+ if (width <= mMaxTextureSize && height <= mMaxTextureSize) {
+ SkBitmap* bitmap = new SkBitmap();
+ PathCache::drawPath(t->path, t->paint, *bitmap, left, top, offset, width, height);
+ t->setResult(bitmap);
+ } else {
+ t->setResult(NULL);
}
- requestExit();
- mSignal.signal();
}
///////////////////////////////////////////////////////////////////////////////
@@ -101,11 +64,10 @@ void PathCache::PrecacheThread::exit() {
///////////////////////////////////////////////////////////////////////////////
PathCache::PathCache(): ShapeCache<PathCacheEntry>("path",
- PROPERTY_PATH_CACHE_SIZE, DEFAULT_PATH_CACHE_SIZE), mThread(new PrecacheThread()) {
+ PROPERTY_PATH_CACHE_SIZE, DEFAULT_PATH_CACHE_SIZE) {
}
PathCache::~PathCache() {
- mThread->exit();
}
void PathCache::remove(SkPath* path) {
@@ -165,17 +127,18 @@ PathTexture* PathCache::get(SkPath* path, SkPaint* paint) {
} else {
// A bitmap is attached to the texture, this means we need to
// upload it as a GL texture
- if (texture->future() != NULL) {
+ const sp<Task<SkBitmap*> >& task = texture->task();
+ if (task != NULL) {
// But we must first wait for the worker thread to be done
// producing the bitmap, so let's wait
- SkBitmap* bitmap = texture->future()->get();
+ SkBitmap* bitmap = task->getResult();
if (bitmap) {
addTexture(entry, bitmap, texture);
- texture->clearFuture();
+ texture->clearTask();
} else {
ALOGW("Path too large to be rendered into a texture (%dx%d)",
texture->width, texture->height);
- texture->clearFuture();
+ texture->clearTask();
texture = NULL;
mCache.remove(entry);
}
@@ -189,6 +152,10 @@ PathTexture* PathCache::get(SkPath* path, SkPaint* paint) {
}
void PathCache::precache(SkPath* path, SkPaint* paint) {
+ if (!Caches::getInstance().tasks.canRunTasks()) {
+ return;
+ }
+
path = getSourcePath(path);
PathCacheEntry entry(path, paint);
@@ -205,7 +172,9 @@ void PathCache::precache(SkPath* path, SkPaint* paint) {
if (generate) {
// It is important to specify the generation ID so we do not
// attempt to precache the same path several times
- texture = createTexture(0.0f, 0.0f, 0.0f, 0, 0, path->getGenerationID(), true);
+ texture = createTexture(0.0f, 0.0f, 0.0f, 0, 0, path->getGenerationID());
+ sp<PathTask> task = new PathTask(path, paint, texture);
+ texture->setTask(task);
// During the precaching phase we insert path texture objects into
// the cache that do not point to any GL texture. They are instead
@@ -215,7 +184,11 @@ void PathCache::precache(SkPath* path, SkPaint* paint) {
// asks for a path texture. This is also when the cache limit will
// be enforced.
mCache.put(entry, texture);
- mThread->addTask(texture, path, paint);
+
+ if (mProcessor == NULL) {
+ mProcessor = new PathProcessor(Caches::getInstance());
+ }
+ mProcessor->add(task);
}
}