Loading libs/hwui/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ ifeq ($(USE_OPENGL_RENDERER),true) LOCAL_SRC_FILES:= \ utils/Blur.cpp \ utils/SortedListImpl.cpp \ thread/TaskManager.cpp \ font/CacheTexture.cpp \ font/Font.cpp \ FontRenderer.cpp \ Loading libs/hwui/Caches.h +5 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,9 @@ #include <cutils/compiler.h> #include "thread/TaskProcessor.h" #include "thread/TaskManager.h" #include "FontRenderer.h" #include "GammaFontRenderer.h" #include "TextureCache.h" Loading Loading @@ -278,6 +281,8 @@ public: GammaFontRenderer* fontRenderer; TaskManager tasks; Dither dither; Stencil stencil; Loading libs/hwui/PathCache.cpp +41 −68 Original line number Diff line number Diff line Loading @@ -31,81 +31,43 @@ namespace uirenderer { // Path precaching /////////////////////////////////////////////////////////////////////////////// bool PathCache::PrecacheThread::threadLoop() { mSignal.wait(); Vector<Task> tasks; { Mutex::Autolock l(mLock); tasks = mTasks; mTasks.clear(); PathCache::PathProcessor::PathProcessor(Caches& caches): TaskProcessor<SkBitmap*>(&caches.tasks), mMaxTextureSize(caches.maxTextureSize) { } 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); 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(task.path, task.paint, left, top, offset, width, height); if (width <= maxSize && height <= maxSize) { SkBitmap* bitmap = new SkBitmap(); PathCache::computePathBounds(t->path, t->paint, left, top, offset, width, height); PathTexture* texture = task.texture; PathTexture* texture = t->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); 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 { task.texture->future()->produce(NULL); t->setResult(NULL); } } ATRACE_END(); return true; } 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(); } requestExit(); mSignal.signal(); } /////////////////////////////////////////////////////////////////////////////// // Path cache /////////////////////////////////////////////////////////////////////////////// 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) { Loading Loading @@ -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); } Loading @@ -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); Loading @@ -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 Loading @@ -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); } } Loading libs/hwui/PathCache.h +21 −18 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ #include "Debug.h" #include "ShapeCache.h" #include "thread/Signal.h" #include "thread/Task.h" #include "thread/TaskProcessor.h" class SkPaint; class SkPath; Loading Loading @@ -100,32 +102,33 @@ public: void precache(SkPath* path, SkPaint* paint); private: class PrecacheThread: public Thread { class PathTask: public Task<SkBitmap*> { public: PrecacheThread(): mSignal(Condition::WAKE_UP_ONE) { } PathTask(SkPath* path, SkPaint* paint, PathTexture* texture): path(path), paint(paint), texture(texture) { } void addTask(PathTexture* texture, SkPath* path, SkPaint* paint); void exit(); ~PathTask() { delete future()->get(); } private: struct Task { PathTexture* texture; SkPath* path; SkPaint* paint; PathTexture* texture; }; virtual bool threadLoop(); class PathProcessor: public TaskProcessor<SkBitmap*> { public: PathProcessor(Caches& caches); ~PathProcessor() { } // Lock for the list of tasks Mutex mLock; Vector<Task> mTasks; virtual void onProcess(const sp<Task<SkBitmap*> >& task); // Signal used to wake up the thread when a new // task is available in the list mutable Signal mSignal; private: uint32_t mMaxTextureSize; }; sp<PrecacheThread> mThread; sp<PathProcessor> mProcessor; Vector<SkPath*> mGarbage; mutable Mutex mLock; }; // class PathCache Loading libs/hwui/ShapeCache.h +14 −18 Original line number Diff line number Diff line Loading @@ -30,12 +30,11 @@ #include <utils/JenkinsHash.h> #include <utils/LruCache.h> #include <utils/Trace.h> #include <utils/CallStack.h> #include "Debug.h" #include "Properties.h" #include "Texture.h" #include "thread/Future.h" #include "thread/Task.h" namespace android { namespace uirenderer { Loading @@ -62,14 +61,8 @@ struct PathTexture: public Texture { PathTexture(): Texture() { } PathTexture(bool hasFuture): Texture() { if (hasFuture) { mFuture = new Future<SkBitmap*>(); } } ~PathTexture() { clearFuture(); clearTask(); } /** Loading @@ -85,19 +78,22 @@ struct PathTexture: public Texture { */ float offset; sp<Future<SkBitmap*> > future() const { return mFuture; sp<Task<SkBitmap*> > task() const { return mTask; } void setTask(const sp<Task<SkBitmap*> >& task) { mTask = task; } void clearFuture() { if (mFuture != NULL) { delete mFuture->get(); mFuture.clear(); void clearTask() { if (mTask != NULL) { mTask.clear(); } } private: sp<Future<SkBitmap*> > mFuture; sp<Task<SkBitmap*> > mTask; }; // struct PathTexture /** Loading Loading @@ -551,8 +547,8 @@ protected: } static PathTexture* createTexture(float left, float top, float offset, uint32_t width, uint32_t height, uint32_t id, bool hasFuture = false) { PathTexture* texture = new PathTexture(hasFuture); uint32_t width, uint32_t height, uint32_t id) { PathTexture* texture = new PathTexture(); texture->left = left; texture->top = top; texture->offset = offset; Loading Loading
libs/hwui/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ ifeq ($(USE_OPENGL_RENDERER),true) LOCAL_SRC_FILES:= \ utils/Blur.cpp \ utils/SortedListImpl.cpp \ thread/TaskManager.cpp \ font/CacheTexture.cpp \ font/Font.cpp \ FontRenderer.cpp \ Loading
libs/hwui/Caches.h +5 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,9 @@ #include <cutils/compiler.h> #include "thread/TaskProcessor.h" #include "thread/TaskManager.h" #include "FontRenderer.h" #include "GammaFontRenderer.h" #include "TextureCache.h" Loading Loading @@ -278,6 +281,8 @@ public: GammaFontRenderer* fontRenderer; TaskManager tasks; Dither dither; Stencil stencil; Loading
libs/hwui/PathCache.cpp +41 −68 Original line number Diff line number Diff line Loading @@ -31,81 +31,43 @@ namespace uirenderer { // Path precaching /////////////////////////////////////////////////////////////////////////////// bool PathCache::PrecacheThread::threadLoop() { mSignal.wait(); Vector<Task> tasks; { Mutex::Autolock l(mLock); tasks = mTasks; mTasks.clear(); PathCache::PathProcessor::PathProcessor(Caches& caches): TaskProcessor<SkBitmap*>(&caches.tasks), mMaxTextureSize(caches.maxTextureSize) { } 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); 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(task.path, task.paint, left, top, offset, width, height); if (width <= maxSize && height <= maxSize) { SkBitmap* bitmap = new SkBitmap(); PathCache::computePathBounds(t->path, t->paint, left, top, offset, width, height); PathTexture* texture = task.texture; PathTexture* texture = t->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); 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 { task.texture->future()->produce(NULL); t->setResult(NULL); } } ATRACE_END(); return true; } 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(); } requestExit(); mSignal.signal(); } /////////////////////////////////////////////////////////////////////////////// // Path cache /////////////////////////////////////////////////////////////////////////////// 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) { Loading Loading @@ -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); } Loading @@ -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); Loading @@ -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 Loading @@ -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); } } Loading
libs/hwui/PathCache.h +21 −18 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ #include "Debug.h" #include "ShapeCache.h" #include "thread/Signal.h" #include "thread/Task.h" #include "thread/TaskProcessor.h" class SkPaint; class SkPath; Loading Loading @@ -100,32 +102,33 @@ public: void precache(SkPath* path, SkPaint* paint); private: class PrecacheThread: public Thread { class PathTask: public Task<SkBitmap*> { public: PrecacheThread(): mSignal(Condition::WAKE_UP_ONE) { } PathTask(SkPath* path, SkPaint* paint, PathTexture* texture): path(path), paint(paint), texture(texture) { } void addTask(PathTexture* texture, SkPath* path, SkPaint* paint); void exit(); ~PathTask() { delete future()->get(); } private: struct Task { PathTexture* texture; SkPath* path; SkPaint* paint; PathTexture* texture; }; virtual bool threadLoop(); class PathProcessor: public TaskProcessor<SkBitmap*> { public: PathProcessor(Caches& caches); ~PathProcessor() { } // Lock for the list of tasks Mutex mLock; Vector<Task> mTasks; virtual void onProcess(const sp<Task<SkBitmap*> >& task); // Signal used to wake up the thread when a new // task is available in the list mutable Signal mSignal; private: uint32_t mMaxTextureSize; }; sp<PrecacheThread> mThread; sp<PathProcessor> mProcessor; Vector<SkPath*> mGarbage; mutable Mutex mLock; }; // class PathCache Loading
libs/hwui/ShapeCache.h +14 −18 Original line number Diff line number Diff line Loading @@ -30,12 +30,11 @@ #include <utils/JenkinsHash.h> #include <utils/LruCache.h> #include <utils/Trace.h> #include <utils/CallStack.h> #include "Debug.h" #include "Properties.h" #include "Texture.h" #include "thread/Future.h" #include "thread/Task.h" namespace android { namespace uirenderer { Loading @@ -62,14 +61,8 @@ struct PathTexture: public Texture { PathTexture(): Texture() { } PathTexture(bool hasFuture): Texture() { if (hasFuture) { mFuture = new Future<SkBitmap*>(); } } ~PathTexture() { clearFuture(); clearTask(); } /** Loading @@ -85,19 +78,22 @@ struct PathTexture: public Texture { */ float offset; sp<Future<SkBitmap*> > future() const { return mFuture; sp<Task<SkBitmap*> > task() const { return mTask; } void setTask(const sp<Task<SkBitmap*> >& task) { mTask = task; } void clearFuture() { if (mFuture != NULL) { delete mFuture->get(); mFuture.clear(); void clearTask() { if (mTask != NULL) { mTask.clear(); } } private: sp<Future<SkBitmap*> > mFuture; sp<Task<SkBitmap*> > mTask; }; // struct PathTexture /** Loading Loading @@ -551,8 +547,8 @@ protected: } static PathTexture* createTexture(float left, float top, float offset, uint32_t width, uint32_t height, uint32_t id, bool hasFuture = false) { PathTexture* texture = new PathTexture(hasFuture); uint32_t width, uint32_t height, uint32_t id) { PathTexture* texture = new PathTexture(); texture->left = left; texture->top = top; texture->offset = offset; Loading