GradientCache.h revision b48800428906ae455c2b63acacd44e390e1fee49
1c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy/*
2c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Copyright (C) 2010 The Android Open Source Project
3c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy *
4c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Licensed under the Apache License, Version 2.0 (the "License");
5c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * you may not use this file except in compliance with the License.
6c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * You may obtain a copy of the License at
7c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy *
8c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy *      http://www.apache.org/licenses/LICENSE-2.0
9c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy *
10c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Unless required by applicable law or agreed to in writing, software
11c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * distributed under the License is distributed on an "AS IS" BASIS,
12c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * See the License for the specific language governing permissions and
14c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * limitations under the License.
15c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */
16c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
175b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy#ifndef ANDROID_HWUI_GRADIENT_CACHE_H
185b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy#define ANDROID_HWUI_GRADIENT_CACHE_H
19c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
20b48800428906ae455c2b63acacd44e390e1fee49Romain Guy#include <GLES3/gl3.h>
218dcfd5e836341b4a803b04d104a930bb312182d3Romain Guy
22c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy#include <SkShader.h>
23c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
24059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy#include <utils/LruCache.h>
25029f64303b8fe506ef34c12777da86b830d3bf7aDerek Sollenberger#include <utils/Mutex.h>
26fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy#include <utils/Vector.h>
27fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy
28c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy#include "Texture.h"
29c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
30c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guynamespace android {
31c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guynamespace uirenderer {
32c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
336203f6c8147069976342be8f42add797a50f9557Romain Guystruct GradientCacheEntry {
346203f6c8147069976342be8f42add797a50f9557Romain Guy    GradientCacheEntry() {
356203f6c8147069976342be8f42add797a50f9557Romain Guy        count = 0;
366203f6c8147069976342be8f42add797a50f9557Romain Guy        colors = NULL;
376203f6c8147069976342be8f42add797a50f9557Romain Guy        positions = NULL;
386203f6c8147069976342be8f42add797a50f9557Romain Guy    }
396203f6c8147069976342be8f42add797a50f9557Romain Guy
40059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    GradientCacheEntry(uint32_t* colors, float* positions, uint32_t count) {
4142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        copy(colors, positions, count);
426203f6c8147069976342be8f42add797a50f9557Romain Guy    }
436203f6c8147069976342be8f42add797a50f9557Romain Guy
446203f6c8147069976342be8f42add797a50f9557Romain Guy    GradientCacheEntry(const GradientCacheEntry& entry) {
4542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        copy(entry.colors, entry.positions, entry.count);
466203f6c8147069976342be8f42add797a50f9557Romain Guy    }
476203f6c8147069976342be8f42add797a50f9557Romain Guy
486203f6c8147069976342be8f42add797a50f9557Romain Guy    ~GradientCacheEntry() {
49e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy        delete[] colors;
50e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy        delete[] positions;
51e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy    }
52e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy
53e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy    GradientCacheEntry& operator=(const GradientCacheEntry& entry) {
54e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy        if (this != &entry) {
55e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy            delete[] colors;
56e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy            delete[] positions;
57e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy
5842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy            copy(entry.colors, entry.positions, entry.count);
59e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy        }
60e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy
61e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy        return *this;
626203f6c8147069976342be8f42add797a50f9557Romain Guy    }
636203f6c8147069976342be8f42add797a50f9557Romain Guy
64059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    hash_t hash() const;
65059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy
66059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    static int compare(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs);
67059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy
68059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    bool operator==(const GradientCacheEntry& other) const {
69059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy        return compare(*this, other) == 0;
70059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    }
71059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy
72059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    bool operator!=(const GradientCacheEntry& other) const {
73059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy        return compare(*this, other) != 0;
746203f6c8147069976342be8f42add797a50f9557Romain Guy    }
756203f6c8147069976342be8f42add797a50f9557Romain Guy
766203f6c8147069976342be8f42add797a50f9557Romain Guy    uint32_t* colors;
776203f6c8147069976342be8f42add797a50f9557Romain Guy    float* positions;
78059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    uint32_t count;
796203f6c8147069976342be8f42add797a50f9557Romain Guy
80e5df231434357424cea8d2b8d0cdf31253a98110Romain Guyprivate:
81059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    void copy(uint32_t* colors, float* positions, uint32_t count) {
82e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy        this->count = count;
83e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy        this->colors = new uint32_t[count];
84e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy        this->positions = new float[count];
85e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy
86e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy        memcpy(this->colors, colors, count * sizeof(uint32_t));
87e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy        memcpy(this->positions, positions, count * sizeof(float));
88e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy    }
89e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy
906203f6c8147069976342be8f42add797a50f9557Romain Guy}; // GradientCacheEntry
916203f6c8147069976342be8f42add797a50f9557Romain Guy
92059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy// Caching support
93059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy
94059e12ccd20f5c249724a8362d6bac325334ea76Romain Guyinline int strictly_order_type(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs) {
95059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    return GradientCacheEntry::compare(lhs, rhs) < 0;
96059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy}
97059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy
98059e12ccd20f5c249724a8362d6bac325334ea76Romain Guyinline int compare_type(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs) {
99059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    return GradientCacheEntry::compare(lhs, rhs);
100059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy}
101059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy
102059e12ccd20f5c249724a8362d6bac325334ea76Romain Guyinline hash_t hash_type(const GradientCacheEntry& entry) {
103059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    return entry.hash();
104059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy}
105059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy
106c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy/**
107c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * A simple LRU gradient cache. The cache has a maximum size expressed in bytes.
108c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Any texture added to the cache causing the cache to grow beyond the maximum
109c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * allowed size will also cause the oldest texture to be kicked out.
110c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */
1116203f6c8147069976342be8f42add797a50f9557Romain Guyclass GradientCache: public OnEntryRemoved<GradientCacheEntry, Texture*> {
112c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guypublic:
113fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy    GradientCache();
114c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    GradientCache(uint32_t maxByteSize);
115c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    ~GradientCache();
116c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
117c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    /**
118c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy     * Used as a callback when an entry is removed from the cache.
119c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy     * Do not invoke directly.
120c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy     */
1216203f6c8147069976342be8f42add797a50f9557Romain Guy    void operator()(GradientCacheEntry& shader, Texture*& texture);
122c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
123c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    /**
124c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy     * Returns the texture associated with the specified shader.
125c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy     */
12642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    Texture* get(uint32_t* colors, float* positions, int count);
12742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
128fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy    /**
129c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy     * Clears the cache. This causes all textures to be deleted.
130c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy     */
131c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    void clear();
132c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
133c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    /**
134c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy     * Sets the maximum size of the cache in bytes.
135c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy     */
136c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    void setMaxSize(uint32_t maxSize);
137c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    /**
138c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy     * Returns the maximum size of the cache in bytes.
139c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy     */
140c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    uint32_t getMaxSize();
141c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    /**
142c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy     * Returns the current size of the cache in bytes.
143c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy     */
144c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    uint32_t getSize();
145c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
146c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guyprivate:
1476203f6c8147069976342be8f42add797a50f9557Romain Guy    /**
1486203f6c8147069976342be8f42add797a50f9557Romain Guy     * Adds a new linear gradient to the cache. The generated texture is
1496203f6c8147069976342be8f42add797a50f9557Romain Guy     * returned.
1506203f6c8147069976342be8f42add797a50f9557Romain Guy     */
1516203f6c8147069976342be8f42add797a50f9557Romain Guy    Texture* addLinearGradient(GradientCacheEntry& gradient,
15242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy            uint32_t* colors, float* positions, int count);
15342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
15442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    void generateTexture(uint32_t* colors, float* positions, int count, Texture* texture);
15542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
15642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    struct GradientInfo {
15742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        uint32_t width;
15842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        bool hasAlpha;
15942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    };
1606203f6c8147069976342be8f42add797a50f9557Romain Guy
16142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    void getGradientInfo(const uint32_t* colors, const int count, GradientInfo& info);
162c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
163b48800428906ae455c2b63acacd44e390e1fee49Romain Guy    size_t bytesPerPixel() const;
164b48800428906ae455c2b63acacd44e390e1fee49Romain Guy
165b48800428906ae455c2b63acacd44e390e1fee49Romain Guy    struct GradientColor {
166b48800428906ae455c2b63acacd44e390e1fee49Romain Guy        float r;
167b48800428906ae455c2b63acacd44e390e1fee49Romain Guy        float g;
168b48800428906ae455c2b63acacd44e390e1fee49Romain Guy        float b;
169b48800428906ae455c2b63acacd44e390e1fee49Romain Guy        float a;
170b48800428906ae455c2b63acacd44e390e1fee49Romain Guy    };
171b48800428906ae455c2b63acacd44e390e1fee49Romain Guy
172b48800428906ae455c2b63acacd44e390e1fee49Romain Guy    typedef void (GradientCache::*ChannelSplitter)(uint32_t inColor,
173b48800428906ae455c2b63acacd44e390e1fee49Romain Guy            GradientColor& outColor) const;
174b48800428906ae455c2b63acacd44e390e1fee49Romain Guy
175b48800428906ae455c2b63acacd44e390e1fee49Romain Guy    void splitToBytes(uint32_t inColor, GradientColor& outColor) const;
176b48800428906ae455c2b63acacd44e390e1fee49Romain Guy    void splitToFloats(uint32_t inColor, GradientColor& outColor) const;
177b48800428906ae455c2b63acacd44e390e1fee49Romain Guy
178b48800428906ae455c2b63acacd44e390e1fee49Romain Guy    typedef void (GradientCache::*ChannelMixer)(GradientColor& start, GradientColor& end,
179b48800428906ae455c2b63acacd44e390e1fee49Romain Guy            float amount, uint8_t*& dst) const;
180b48800428906ae455c2b63acacd44e390e1fee49Romain Guy
181b48800428906ae455c2b63acacd44e390e1fee49Romain Guy    void mixBytes(GradientColor& start, GradientColor& end, float amount, uint8_t*& dst) const;
182b48800428906ae455c2b63acacd44e390e1fee49Romain Guy    void mixFloats(GradientColor& start, GradientColor& end, float amount, uint8_t*& dst) const;
183b48800428906ae455c2b63acacd44e390e1fee49Romain Guy
184059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    LruCache<GradientCacheEntry, Texture*> mCache;
185c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
186c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    uint32_t mSize;
187c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    uint32_t mMaxSize;
188a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy
1898dcfd5e836341b4a803b04d104a930bb312182d3Romain Guy    GLint mMaxTextureSize;
190b48800428906ae455c2b63acacd44e390e1fee49Romain Guy    bool mUseFloatTexture;
191b48800428906ae455c2b63acacd44e390e1fee49Romain Guy    bool mHasNpot;
1928dcfd5e836341b4a803b04d104a930bb312182d3Romain Guy
193fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy    Vector<SkShader*> mGarbage;
194a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy    mutable Mutex mLock;
195c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy}; // class GradientCache
196c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
197c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy}; // namespace uirenderer
198c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy}; // namespace android
199c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
2005b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy#endif // ANDROID_HWUI_GRADIENT_CACHE_H
201