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

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

Merge "Reduce the amount of data cached by the gradients cache."

parents 349f5d55 6203f6c8
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);