Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit baea5269 authored by Romain Guy's avatar Romain Guy Committed by Android (Google) Code Review
Browse files

Merge "Add TaskManager API" into jb-mr2-dev

parents c6da8d29 5dc7fa70
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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 \
+5 −0
Original line number Diff line number Diff line
@@ -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"
@@ -278,6 +281,8 @@ public:

    GammaFontRenderer* fontRenderer;

    TaskManager tasks;

    Dither dither;
    Stencil stencil;

+41 −68
Original line number Diff line number Diff line
@@ -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) {
@@ -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);
    }
}

+21 −18
Original line number Diff line number Diff line
@@ -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;
@@ -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
+14 −18
Original line number Diff line number Diff line
@@ -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 {
@@ -62,14 +61,8 @@ struct PathTexture: public Texture {
    PathTexture(): Texture() {
    }

    PathTexture(bool hasFuture): Texture() {
        if (hasFuture) {
            mFuture = new Future<SkBitmap*>();
        }
    }

    ~PathTexture() {
        clearFuture();
        clearTask();
    }

    /**
@@ -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

/**
@@ -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