GradientCache.cpp revision 42e1e0d482d774cf18a55773e434f02edb9e4462
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
17c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy#define LOG_TAG "OpenGLRenderer"
18c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
19a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy#include <utils/threads.h>
20a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy
21c9855a53edfac818dc68714557185977556f849dRomain Guy#include "Debug.h"
22c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy#include "GradientCache.h"
23fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy#include "Properties.h"
24c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
25c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guynamespace android {
26c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guynamespace uirenderer {
27c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
28c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy///////////////////////////////////////////////////////////////////////////////
2942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy// Defines
3042e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy///////////////////////////////////////////////////////////////////////////////
3142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
3242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy#define GRADIENT_TEXTURE_HEIGHT 2
3342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy#define GRADIENT_BYTES_PER_PIXEL 4
3442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
3542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy///////////////////////////////////////////////////////////////////////////////
3642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy// Functions
3742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy///////////////////////////////////////////////////////////////////////////////
3842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
3942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guytemplate<typename T>
4042e1e0d482d774cf18a55773e434f02edb9e4462Romain Guystatic inline T min(T a, T b) {
4142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    return a < b ? a : b;
4242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy}
4342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
4442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy///////////////////////////////////////////////////////////////////////////////
45c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy// Constructors/destructor
46c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy///////////////////////////////////////////////////////////////////////////////
47c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
48fb8b763f762ae21923c58d64caa729b012f40e05Romain GuyGradientCache::GradientCache():
496203f6c8147069976342be8f42add797a50f9557Romain Guy        mCache(GenerationCache<GradientCacheEntry, Texture*>::kUnlimitedCapacity),
50fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy        mSize(0), mMaxSize(MB(DEFAULT_GRADIENT_CACHE_SIZE)) {
51fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy    char property[PROPERTY_VALUE_MAX];
52fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy    if (property_get(PROPERTY_GRADIENT_CACHE_SIZE, property, NULL) > 0) {
53c9855a53edfac818dc68714557185977556f849dRomain Guy        INIT_LOGD("  Setting gradient cache size to %sMB", property);
54fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy        setMaxSize(MB(atof(property)));
55fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy    } else {
56c9855a53edfac818dc68714557185977556f849dRomain Guy        INIT_LOGD("  Using default gradient cache size of %.2fMB", DEFAULT_GRADIENT_CACHE_SIZE);
57fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy    }
58fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy
598dcfd5e836341b4a803b04d104a930bb312182d3Romain Guy    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
608dcfd5e836341b4a803b04d104a930bb312182d3Romain Guy
61fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy    mCache.setOnEntryRemovedListener(this);
62fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy}
63fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy
64c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain GuyGradientCache::GradientCache(uint32_t maxByteSize):
656203f6c8147069976342be8f42add797a50f9557Romain Guy        mCache(GenerationCache<GradientCacheEntry, Texture*>::kUnlimitedCapacity),
66c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy        mSize(0), mMaxSize(maxByteSize) {
67c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    mCache.setOnEntryRemovedListener(this);
68c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy}
69c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
70c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain GuyGradientCache::~GradientCache() {
71c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    mCache.clear();
72c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy}
73c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
74c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy///////////////////////////////////////////////////////////////////////////////
75c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy// Size management
76c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy///////////////////////////////////////////////////////////////////////////////
77c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
78c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guyuint32_t GradientCache::getSize() {
79c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    return mSize;
80c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy}
81c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
82c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guyuint32_t GradientCache::getMaxSize() {
83c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    return mMaxSize;
84c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy}
85c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
86c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guyvoid GradientCache::setMaxSize(uint32_t maxSize) {
87c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    mMaxSize = maxSize;
88c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    while (mSize > mMaxSize) {
89c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy        mCache.removeOldest();
90c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    }
91c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy}
92c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
93c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy///////////////////////////////////////////////////////////////////////////////
94c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy// Callbacks
95c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy///////////////////////////////////////////////////////////////////////////////
96c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
976203f6c8147069976342be8f42add797a50f9557Romain Guyvoid GradientCache::operator()(GradientCacheEntry& shader, Texture*& texture) {
986203f6c8147069976342be8f42add797a50f9557Romain Guy    if (texture) {
9942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        const uint32_t size = texture->width * texture->height * GRADIENT_BYTES_PER_PIXEL;
100c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy        mSize -= size;
101c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    }
102c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
103c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    if (texture) {
104c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy        glDeleteTextures(1, &texture->id);
105c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy        delete texture;
106c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    }
107c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy}
108c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
109c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy///////////////////////////////////////////////////////////////////////////////
110c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy// Caching
111c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy///////////////////////////////////////////////////////////////////////////////
112c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
11342e1e0d482d774cf18a55773e434f02edb9e4462Romain GuyTexture* GradientCache::get(uint32_t* colors, float* positions, int count) {
114c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
11542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    GradientCacheEntry gradient(colors, positions, count);
1166203f6c8147069976342be8f42add797a50f9557Romain Guy    Texture* texture = mCache.get(gradient);
117c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
1186203f6c8147069976342be8f42add797a50f9557Romain Guy    if (!texture) {
11942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        texture = addLinearGradient(gradient, colors, positions, count);
120fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy    }
1216203f6c8147069976342be8f42add797a50f9557Romain Guy
1226203f6c8147069976342be8f42add797a50f9557Romain Guy    return texture;
123fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy}
124fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy
125fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guyvoid GradientCache::clear() {
126c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    mCache.clear();
127c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy}
128c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
12942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guyvoid GradientCache::getGradientInfo(const uint32_t* colors, const int count,
13042e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        GradientInfo& info) {
13142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    uint32_t width = 1 << (31 - __builtin_clz(256 * (count - 1)));
13242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    bool hasAlpha = false;
133c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
13442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    for (int i = 0; i < count; i++) {
13542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        if (((colors[i] >> 24) & 0xff) < 255) {
13642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy            hasAlpha = true;
13742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy            break;
13842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        }
13942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    }
140c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
14142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    info.width = min(width, uint32_t(mMaxTextureSize));
14242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    info.hasAlpha = hasAlpha;
14342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy}
144c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
14542e1e0d482d774cf18a55773e434f02edb9e4462Romain GuyTexture* GradientCache::addLinearGradient(GradientCacheEntry& gradient,
14642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        uint32_t* colors, float* positions, int count) {
147c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
14842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    GradientInfo info;
14942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    getGradientInfo(colors, count, info);
150c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
15142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    Texture* texture = new Texture;
15242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    texture->width = info.width;
15342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    texture->height = GRADIENT_TEXTURE_HEIGHT;
15442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    texture->blend = info.hasAlpha;
15542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    texture->generation = 1;
156c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
157c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    // Asume the cache is always big enough
15842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    const uint32_t size = texture->width * texture->height * GRADIENT_BYTES_PER_PIXEL;
159c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    while (mSize + size > mMaxSize) {
160c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy        mCache.removeOldest();
161c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    }
162c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
16342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    generateTexture(colors, positions, count, texture);
164c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
165c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    mSize += size;
1666203f6c8147069976342be8f42add797a50f9557Romain Guy    mCache.put(gradient, texture);
167c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
168c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    return texture;
169c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy}
170c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
17142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guyvoid GradientCache::generateTexture(uint32_t* colors, float* positions,
17242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        int count, Texture* texture) {
17342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
17442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    const uint32_t width = texture->width;
17542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    const GLsizei rowBytes = width * GRADIENT_BYTES_PER_PIXEL;
17642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    uint32_t pixels[width * texture->height];
17742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
17842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    int currentPos = 1;
17942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
18042e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    float startA = (colors[0] >> 24) & 0xff;
18142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    float startR = (colors[0] >> 16) & 0xff;
18242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    float startG = (colors[0] >>  8) & 0xff;
18342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    float startB = (colors[0] >>  0) & 0xff;
18442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
18542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    float endA = (colors[1] >> 24) & 0xff;
18642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    float endR = (colors[1] >> 16) & 0xff;
18742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    float endG = (colors[1] >>  8) & 0xff;
18842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    float endB = (colors[1] >>  0) & 0xff;
18942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
19042e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    float start = positions[0];
19142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    float distance = positions[1] - start;
19242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
19342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    uint8_t* p = (uint8_t*) pixels;
19442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    for (uint32_t x = 0; x < width; x++) {
19542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        float pos = x / float(width - 1);
19642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        if (pos > positions[currentPos]) {
19742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy            startA = endA;
19842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy            startR = endR;
19942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy            startG = endG;
20042e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy            startB = endB;
20142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy            start = positions[currentPos];
20242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
20342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy            currentPos++;
20442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
20542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy            endA = (colors[currentPos] >> 24) & 0xff;
20642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy            endR = (colors[currentPos] >> 16) & 0xff;
20742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy            endG = (colors[currentPos] >>  8) & 0xff;
20842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy            endB = (colors[currentPos] >>  0) & 0xff;
20942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy            distance = positions[currentPos] - start;
21042e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        }
21142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
21242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        float amount = (pos - start) / distance;
21342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        float oppAmount = 1.0f - amount;
21442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
21542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        *p++ = uint8_t(startR * oppAmount + endR * amount);
21642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        *p++ = uint8_t(startG * oppAmount + endG * amount);
21742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        *p++ = uint8_t(startB * oppAmount + endB * amount);
21842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        *p++ = uint8_t(startA * oppAmount + endA * amount);
219c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    }
220c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
22142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    for (int i = 1; i < GRADIENT_TEXTURE_HEIGHT; i++) {
22242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        memcpy(pixels + width * i, pixels, rowBytes);
22342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    }
224c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
225c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    glGenTextures(1, &texture->id);
226c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
227c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    glBindTexture(GL_TEXTURE_2D, texture->id);
22842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    glPixelStorei(GL_UNPACK_ALIGNMENT, GRADIENT_BYTES_PER_PIXEL);
229c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
23042e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, texture->height, 0,
23142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy            GL_RGBA, GL_UNSIGNED_BYTE, pixels);
232c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
23339d252a6632d057d5077f7eaf1b8ed7a142f3397Romain Guy    texture->setFilter(GL_LINEAR);
23439d252a6632d057d5077f7eaf1b8ed7a142f3397Romain Guy    texture->setWrap(GL_CLAMP_TO_EDGE);
235c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy}
236c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
237c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy}; // namespace uirenderer
238c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy}; // namespace android
239