GradientCache.cpp revision 059e12ccd20f5c249724a8362d6bac325334ea76
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 19059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy#include <utils/JenkinsHash.h> 20a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy#include <utils/threads.h> 21a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy 22320d46bf844b84351cb80c5d4a4768d86447ac81Romain Guy#include "Caches.h" 23c9855a53edfac818dc68714557185977556f849dRomain Guy#include "Debug.h" 24c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy#include "GradientCache.h" 25fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy#include "Properties.h" 26c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 27c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guynamespace android { 28c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guynamespace uirenderer { 29c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 30c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy/////////////////////////////////////////////////////////////////////////////// 3142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy// Defines 3242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy/////////////////////////////////////////////////////////////////////////////// 3342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy 3442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy#define GRADIENT_TEXTURE_HEIGHT 2 3542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy#define GRADIENT_BYTES_PER_PIXEL 4 3642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy 3742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy/////////////////////////////////////////////////////////////////////////////// 3842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy// Functions 3942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy/////////////////////////////////////////////////////////////////////////////// 4042e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy 4142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guytemplate<typename T> 4242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guystatic inline T min(T a, T b) { 4342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy return a < b ? a : b; 4442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy} 4542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy 4642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy/////////////////////////////////////////////////////////////////////////////// 47059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy// Cache entry 48059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy/////////////////////////////////////////////////////////////////////////////// 49059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 50059e12ccd20f5c249724a8362d6bac325334ea76Romain Guyhash_t GradientCacheEntry::hash() const { 51059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy uint32_t hash = JenkinsHashMix(0, count); 52059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy hash = JenkinsHashMix(hash, tileMode); 53059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy for (uint32_t i = 0; i < count; i++) { 54059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy hash = JenkinsHashMix(hash, android::hash_type(colors[i])); 55059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy hash = JenkinsHashMix(hash, android::hash_type(positions[i])); 56059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy } 57059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy return JenkinsHashWhiten(hash); 58059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy} 59059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 60059e12ccd20f5c249724a8362d6bac325334ea76Romain Guyint GradientCacheEntry::compare(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs) { 61059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy int deltaInt = int(lhs.count) - int(rhs.count); 62059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy if (deltaInt != 0) return deltaInt; 63059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 64059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy deltaInt = lhs.tileMode - rhs.tileMode; 65059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy if (deltaInt != 0) return deltaInt; 66059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 67059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy deltaInt = memcmp(lhs.colors, rhs.colors, lhs.count * sizeof(uint32_t)); 68059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy if (deltaInt != 0) return deltaInt; 69059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 70059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy return memcmp(lhs.positions, rhs.positions, lhs.count * sizeof(float)); 71059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy} 72059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 73059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy/////////////////////////////////////////////////////////////////////////////// 74c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy// Constructors/destructor 75c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy/////////////////////////////////////////////////////////////////////////////// 76c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 77fb8b763f762ae21923c58d64caa729b012f40e05Romain GuyGradientCache::GradientCache(): 78059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy mCache(LruCache<GradientCacheEntry, Texture*>::kUnlimitedCapacity), 79fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy mSize(0), mMaxSize(MB(DEFAULT_GRADIENT_CACHE_SIZE)) { 80fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy char property[PROPERTY_VALUE_MAX]; 81fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy if (property_get(PROPERTY_GRADIENT_CACHE_SIZE, property, NULL) > 0) { 82c9855a53edfac818dc68714557185977556f849dRomain Guy INIT_LOGD(" Setting gradient cache size to %sMB", property); 83fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy setMaxSize(MB(atof(property))); 84fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy } else { 85c9855a53edfac818dc68714557185977556f849dRomain Guy INIT_LOGD(" Using default gradient cache size of %.2fMB", DEFAULT_GRADIENT_CACHE_SIZE); 86fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy } 87fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 88a8557d2169e14997637f57bc897640c8882d4a46Mathias Agopian glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize); 898dcfd5e836341b4a803b04d104a930bb312182d3Romain Guy 90fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy mCache.setOnEntryRemovedListener(this); 91fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy} 92fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 93c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain GuyGradientCache::GradientCache(uint32_t maxByteSize): 94059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy mCache(LruCache<GradientCacheEntry, Texture*>::kUnlimitedCapacity), 95c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy mSize(0), mMaxSize(maxByteSize) { 96c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy mCache.setOnEntryRemovedListener(this); 97c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy} 98c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 99c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain GuyGradientCache::~GradientCache() { 100c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy mCache.clear(); 101c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy} 102c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 103c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy/////////////////////////////////////////////////////////////////////////////// 104c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy// Size management 105c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy/////////////////////////////////////////////////////////////////////////////// 106c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 107c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guyuint32_t GradientCache::getSize() { 108c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy return mSize; 109c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy} 110c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 111c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guyuint32_t GradientCache::getMaxSize() { 112c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy return mMaxSize; 113c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy} 114c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 115c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guyvoid GradientCache::setMaxSize(uint32_t maxSize) { 116c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy mMaxSize = maxSize; 117c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy while (mSize > mMaxSize) { 118c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy mCache.removeOldest(); 119c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy } 120c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy} 121c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 122c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy/////////////////////////////////////////////////////////////////////////////// 123c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy// Callbacks 124c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy/////////////////////////////////////////////////////////////////////////////// 125c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 1266203f6c8147069976342be8f42add797a50f9557Romain Guyvoid GradientCache::operator()(GradientCacheEntry& shader, Texture*& texture) { 1276203f6c8147069976342be8f42add797a50f9557Romain Guy if (texture) { 12842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy const uint32_t size = texture->width * texture->height * GRADIENT_BYTES_PER_PIXEL; 129c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy mSize -= size; 130c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy } 131c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 132c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy if (texture) { 133c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy glDeleteTextures(1, &texture->id); 134c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy delete texture; 135c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy } 136c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy} 137c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 138c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy/////////////////////////////////////////////////////////////////////////////// 139c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy// Caching 140c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy/////////////////////////////////////////////////////////////////////////////// 141c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 14242e1e0d482d774cf18a55773e434f02edb9e4462Romain GuyTexture* GradientCache::get(uint32_t* colors, float* positions, int count) { 143c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 14442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy GradientCacheEntry gradient(colors, positions, count); 1456203f6c8147069976342be8f42add797a50f9557Romain Guy Texture* texture = mCache.get(gradient); 146c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 1476203f6c8147069976342be8f42add797a50f9557Romain Guy if (!texture) { 14842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy texture = addLinearGradient(gradient, colors, positions, count); 149fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy } 1506203f6c8147069976342be8f42add797a50f9557Romain Guy 1516203f6c8147069976342be8f42add797a50f9557Romain Guy return texture; 152fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy} 153fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy 154fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guyvoid GradientCache::clear() { 155c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy mCache.clear(); 156c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy} 157c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 15842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guyvoid GradientCache::getGradientInfo(const uint32_t* colors, const int count, 15942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy GradientInfo& info) { 160320d46bf844b84351cb80c5d4a4768d86447ac81Romain Guy uint32_t width = 256 * (count - 1); 161320d46bf844b84351cb80c5d4a4768d86447ac81Romain Guy 162320d46bf844b84351cb80c5d4a4768d86447ac81Romain Guy if (!Caches::getInstance().extensions.hasNPot()) { 163320d46bf844b84351cb80c5d4a4768d86447ac81Romain Guy width = 1 << (31 - __builtin_clz(width)); 164320d46bf844b84351cb80c5d4a4768d86447ac81Romain Guy } 165c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 166320d46bf844b84351cb80c5d4a4768d86447ac81Romain Guy bool hasAlpha = false; 16742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy for (int i = 0; i < count; i++) { 16842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy if (((colors[i] >> 24) & 0xff) < 255) { 16942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy hasAlpha = true; 17042e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy break; 17142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy } 17242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy } 173c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 17442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy info.width = min(width, uint32_t(mMaxTextureSize)); 17542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy info.hasAlpha = hasAlpha; 17642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy} 177c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 17842e1e0d482d774cf18a55773e434f02edb9e4462Romain GuyTexture* GradientCache::addLinearGradient(GradientCacheEntry& gradient, 17942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy uint32_t* colors, float* positions, int count) { 180c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 18142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy GradientInfo info; 18242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy getGradientInfo(colors, count, info); 183c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 18442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy Texture* texture = new Texture; 18542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy texture->width = info.width; 18642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy texture->height = GRADIENT_TEXTURE_HEIGHT; 18742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy texture->blend = info.hasAlpha; 18842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy texture->generation = 1; 189c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 190c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy // Asume the cache is always big enough 19142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy const uint32_t size = texture->width * texture->height * GRADIENT_BYTES_PER_PIXEL; 192c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy while (mSize + size > mMaxSize) { 193c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy mCache.removeOldest(); 194c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy } 195c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 19642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy generateTexture(colors, positions, count, texture); 197c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 198c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy mSize += size; 1996203f6c8147069976342be8f42add797a50f9557Romain Guy mCache.put(gradient, texture); 200c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 201c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy return texture; 202c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy} 203c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 20442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guyvoid GradientCache::generateTexture(uint32_t* colors, float* positions, 20542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy int count, Texture* texture) { 20642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy 20742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy const uint32_t width = texture->width; 20842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy const GLsizei rowBytes = width * GRADIENT_BYTES_PER_PIXEL; 20942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy uint32_t pixels[width * texture->height]; 21042e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy 21142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy int currentPos = 1; 21242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy 21342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy float startA = (colors[0] >> 24) & 0xff; 21442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy float startR = (colors[0] >> 16) & 0xff; 21542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy float startG = (colors[0] >> 8) & 0xff; 21642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy float startB = (colors[0] >> 0) & 0xff; 21742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy 21842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy float endA = (colors[1] >> 24) & 0xff; 21942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy float endR = (colors[1] >> 16) & 0xff; 22042e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy float endG = (colors[1] >> 8) & 0xff; 22142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy float endB = (colors[1] >> 0) & 0xff; 22242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy 22342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy float start = positions[0]; 22442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy float distance = positions[1] - start; 22542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy 22642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy uint8_t* p = (uint8_t*) pixels; 22742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy for (uint32_t x = 0; x < width; x++) { 22842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy float pos = x / float(width - 1); 22942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy if (pos > positions[currentPos]) { 23042e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy startA = endA; 23142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy startR = endR; 23242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy startG = endG; 23342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy startB = endB; 23442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy start = positions[currentPos]; 23542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy 23642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy currentPos++; 23742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy 23842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy endA = (colors[currentPos] >> 24) & 0xff; 23942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy endR = (colors[currentPos] >> 16) & 0xff; 24042e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy endG = (colors[currentPos] >> 8) & 0xff; 24142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy endB = (colors[currentPos] >> 0) & 0xff; 24242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy distance = positions[currentPos] - start; 24342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy } 24442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy 24542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy float amount = (pos - start) / distance; 24642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy float oppAmount = 1.0f - amount; 24742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy 248d679b57ef279239cf11bb6c9bd14fb99b07971c9Romain Guy const float alpha = startA * oppAmount + endA * amount; 249d679b57ef279239cf11bb6c9bd14fb99b07971c9Romain Guy const float a = alpha / 255.0f; 250d679b57ef279239cf11bb6c9bd14fb99b07971c9Romain Guy *p++ = uint8_t(a * (startR * oppAmount + endR * amount)); 251d679b57ef279239cf11bb6c9bd14fb99b07971c9Romain Guy *p++ = uint8_t(a * (startG * oppAmount + endG * amount)); 252d679b57ef279239cf11bb6c9bd14fb99b07971c9Romain Guy *p++ = uint8_t(a * (startB * oppAmount + endB * amount)); 253d679b57ef279239cf11bb6c9bd14fb99b07971c9Romain Guy *p++ = uint8_t(alpha); 254c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy } 255c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 25642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy for (int i = 1; i < GRADIENT_TEXTURE_HEIGHT; i++) { 25742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy memcpy(pixels + width * i, pixels, rowBytes); 25842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy } 259c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 260c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy glGenTextures(1, &texture->id); 261c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 262c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy glBindTexture(GL_TEXTURE_2D, texture->id); 26342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy glPixelStorei(GL_UNPACK_ALIGNMENT, GRADIENT_BYTES_PER_PIXEL); 264c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 26542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, texture->height, 0, 26642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy GL_RGBA, GL_UNSIGNED_BYTE, pixels); 267c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 26839d252a6632d057d5077f7eaf1b8ed7a142f3397Romain Guy texture->setFilter(GL_LINEAR); 26939d252a6632d057d5077f7eaf1b8ed7a142f3397Romain Guy texture->setWrap(GL_CLAMP_TO_EDGE); 270c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy} 271c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 272c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy}; // namespace uirenderer 273c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy}; // namespace android 274