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

Commit 6203f6c8 authored by Romain Guy's avatar Romain Guy
Browse files

Reduce the amount of data cached by the gradients cache.

Change-Id: I8546f5a5ecf38031c9a40bdcc434d4c7f22da63d
parent 0965a324
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -142,7 +142,6 @@ void Caches::dumpMemoryUsage(String8 &log) {

void Caches::clearGarbage() {
    textureCache.clearGarbage();
    gradientCache.clearGarbage();
    pathCache.clearGarbage();

    Mutex::Autolock _l(mGarbageLock);
+15 −25
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@ namespace uirenderer {
///////////////////////////////////////////////////////////////////////////////

GradientCache::GradientCache():
        mCache(GenerationCache<SkShader*, Texture*>::kUnlimitedCapacity),
        mCache(GenerationCache<GradientCacheEntry, Texture*>::kUnlimitedCapacity),
        mSize(0), mMaxSize(MB(DEFAULT_GRADIENT_CACHE_SIZE)) {
    char property[PROPERTY_VALUE_MAX];
    if (property_get(PROPERTY_GRADIENT_CACHE_SIZE, property, NULL) > 0) {
@@ -49,7 +49,7 @@ GradientCache::GradientCache():
}

GradientCache::GradientCache(uint32_t maxByteSize):
        mCache(GenerationCache<SkShader*, Texture*>::kUnlimitedCapacity),
        mCache(GenerationCache<GradientCacheEntry, Texture*>::kUnlimitedCapacity),
        mSize(0), mMaxSize(maxByteSize) {
    mCache.setOnEntryRemovedListener(this);
}
@@ -81,9 +81,8 @@ void GradientCache::setMaxSize(uint32_t maxSize) {
// Callbacks
///////////////////////////////////////////////////////////////////////////////

void GradientCache::operator()(SkShader*& shader, Texture*& texture) {
    // Already locked here
    if (shader) {
void GradientCache::operator()(GradientCacheEntry& shader, Texture*& texture) {
    if (texture) {
        const uint32_t size = texture->width * texture->height * 4;
        mSize -= size;
    }
@@ -98,34 +97,25 @@ void GradientCache::operator()(SkShader*& shader, Texture*& texture) {
// Caching
///////////////////////////////////////////////////////////////////////////////

Texture* GradientCache::get(SkShader* shader) {
    return mCache.get(shader);
}
Texture* GradientCache::get(uint32_t* colors, float* positions,
        int count, SkShader::TileMode tileMode) {

void GradientCache::remove(SkShader* shader) {
    mCache.remove(shader);
}
    GradientCacheEntry gradient(colors, positions, count, tileMode);
    Texture* texture = mCache.get(gradient);

void GradientCache::removeDeferred(SkShader* shader) {
    Mutex::Autolock _l(mLock);
    mGarbage.push(shader);
    if (!texture) {
        texture = addLinearGradient(gradient, colors, positions, count, tileMode);
    }

void GradientCache::clearGarbage() {
    Mutex::Autolock _l(mLock);
    size_t count = mGarbage.size();
    for (size_t i = 0; i < count; i++) {
        mCache.remove(mGarbage.itemAt(i));
    }
    mGarbage.clear();
    return texture;
}

void GradientCache::clear() {
    mCache.clear();
}

Texture* GradientCache::addLinearGradient(SkShader* shader, uint32_t* colors,
        float* positions, int count, SkShader::TileMode tileMode) {
Texture* GradientCache::addLinearGradient(GradientCacheEntry& gradient,
        uint32_t* colors, float* positions, int count, SkShader::TileMode tileMode) {
    SkBitmap bitmap;
    bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1024, 1);
    bitmap.allocPixels();
@@ -156,7 +146,7 @@ Texture* GradientCache::addLinearGradient(SkShader* shader, uint32_t* colors,
    generateTexture(&bitmap, texture);

    mSize += size;
    mCache.put(shader, texture);
    mCache.put(gradient, texture);

    return texture;
}
+70 −24
Original line number Diff line number Diff line
@@ -22,17 +22,74 @@
#include <utils/Vector.h>

#include "Texture.h"
#include "utils/Compare.h"
#include "utils/GenerationCache.h"

namespace android {
namespace uirenderer {

struct GradientCacheEntry {
    GradientCacheEntry() {
        count = 0;
        colors = NULL;
        positions = NULL;
        tileMode = SkShader::kClamp_TileMode;
    }

    GradientCacheEntry(uint32_t* colors, float* positions, int count,
            SkShader::TileMode tileMode) {
        this->count = count;
        this->colors = new uint32_t[count];
        this->positions = new float[count];
        this->tileMode = tileMode;

        memcpy(this->colors, colors, count * sizeof(uint32_t));
        memcpy(this->positions, positions, count * sizeof(float));
    }

    GradientCacheEntry(const GradientCacheEntry& entry) {
        this->count = entry.count;
        this->colors = new uint32_t[count];
        this->positions = new float[count];
        this->tileMode = entry.tileMode;

        memcpy(this->colors, entry.colors, count * sizeof(uint32_t));
        memcpy(this->positions, entry.positions, count * sizeof(float));
    }

    ~GradientCacheEntry() {
        delete[] colors;
        delete[] positions;
    }

    bool operator<(const GradientCacheEntry& r) const {
        const GradientCacheEntry& rhs = (const GradientCacheEntry&) r;
        LTE_INT(count) {
            LTE_INT(tileMode) {
                int result = memcmp(colors, rhs.colors, count * sizeof(uint32_t));
                if (result< 0) return true;
                else if (result == 0) {
                    result = memcmp(positions, rhs.positions, count * sizeof(float));
                    if (result < 0) return true;
                }
            }
        }
        return false;
    }

    uint32_t* colors;
    float* positions;
    int count;
    SkShader::TileMode tileMode;

}; // GradientCacheEntry

/**
 * A simple LRU gradient cache. The cache has a maximum size expressed in bytes.
 * Any texture added to the cache causing the cache to grow beyond the maximum
 * allowed size will also cause the oldest texture to be kicked out.
 */
class GradientCache: public OnEntryRemoved<SkShader*, Texture*> {
class GradientCache: public OnEntryRemoved<GradientCacheEntry, Texture*> {
public:
    GradientCache();
    GradientCache(uint32_t maxByteSize);
@@ -42,32 +99,13 @@ public:
     * Used as a callback when an entry is removed from the cache.
     * Do not invoke directly.
     */
    void operator()(SkShader*& shader, Texture*& texture);
    void operator()(GradientCacheEntry& shader, Texture*& texture);

    /**
     * Adds a new linear gradient to the cache. The generated texture is
     * returned.
     */
    Texture* addLinearGradient(SkShader* shader, uint32_t* colors, float* positions,
            int count, SkShader::TileMode tileMode = SkShader::kClamp_TileMode);
    /**
     * Returns the texture associated with the specified shader.
     */
    Texture* get(SkShader* shader);
    /**
     * Removes the texture associated with the specified shader.
     * Upon remove the texture is freed.
     */
    void remove(SkShader* shader);
    /**
     * Removes the texture associated with the specified shader. This is meant
     * to be called from threads that are not the EGL context thread.
     */
    void removeDeferred(SkShader* shader);
    /**
     * Process deferred removals.
     */
    void clearGarbage();
    Texture* get(uint32_t* colors, float* positions,
            int count, SkShader::TileMode tileMode = SkShader::kClamp_TileMode);
    /**
     * Clears the cache. This causes all textures to be deleted.
     */
@@ -87,9 +125,17 @@ public:
    uint32_t getSize();

private:
    /**
     * Adds a new linear gradient to the cache. The generated texture is
     * returned.
     */
    Texture* addLinearGradient(GradientCacheEntry& gradient,
            uint32_t* colors, float* positions, int count,
            SkShader::TileMode tileMode = SkShader::kClamp_TileMode);

    void generateTexture(SkBitmap* bitmap, Texture* texture);

    GenerationCache<SkShader*, Texture*> mCache;
    GenerationCache<GradientCacheEntry, Texture*> mCache;

    uint32_t mSize;
    uint32_t mMaxSize;
+0 −6
Original line number Diff line number Diff line
@@ -166,9 +166,6 @@ void ResourceCache::destructor(SkiaShader* resource) {
    ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
    if (ref == NULL) {
        // If we're not tracking this resource, just delete it
        if (Caches::hasInstance()) {
            Caches::getInstance().gradientCache.removeDeferred(resource->getSkShader());
        }
        delete resource;
        return;
    }
@@ -220,9 +217,6 @@ void ResourceCache::deleteResourceReference(void* resource, ResourceReference* r
            break;
            case kShader: {
                SkiaShader* shader = (SkiaShader*) resource;
                if (Caches::hasInstance()) {
                    Caches::getInstance().gradientCache.removeDeferred(shader->getSkShader());
                }
                delete shader;
            }
            break;
+2 −8
Original line number Diff line number Diff line
@@ -225,10 +225,7 @@ void SkiaLinearGradientShader::setupProgram(Program* program, const mat4& modelV
    GLuint textureSlot = (*textureUnit)++;
    glActiveTexture(gTextureUnitsMap[textureSlot]);

    Texture* texture = mGradientCache->get(mKey);
    if (!texture) {
        texture = mGradientCache->addLinearGradient(mKey, mColors, mPositions, mCount, mTileX);
    }
    Texture* texture = mGradientCache->get(mColors, mPositions, mCount, mTileX);

    mat4 screenSpace;
    computeScreenSpaceMatrix(screenSpace, modelView);
@@ -340,10 +337,7 @@ void SkiaSweepGradientShader::setupProgram(Program* program, const mat4& modelVi
    GLuint textureSlot = (*textureUnit)++;
    glActiveTexture(gTextureUnitsMap[textureSlot]);

    Texture* texture = mGradientCache->get(mKey);
    if (!texture) {
        texture = mGradientCache->addLinearGradient(mKey, mColors, mPositions, mCount);
    }
    Texture* texture = mGradientCache->get(mColors, mPositions, mCount);

    mat4 screenSpace;
    computeScreenSpaceMatrix(screenSpace, modelView);