GradientCache.cpp revision 9cccc2b9bdd4850a3f9679569aaec3ab98477a5d
1edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project/* 2edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Copyright (C) 2010 The Android Open Source Project 3edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * 4edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * you may not use this file except in compliance with the License. 6edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * You may obtain a copy of the License at 7edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * 8edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * 10edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * See the License for the specific language governing permissions and 14edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * limitations under the License. 15edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project */ 16edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 17208059f67ed2dd9fa025e07fcb6954d3cb61c79eMathias Agopian#define LOG_TAG "OpenGLRenderer" 18208059f67ed2dd9fa025e07fcb6954d3cb61c79eMathias Agopian 19edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <GLES2/gl2.h> 20208059f67ed2dd9fa025e07fcb6954d3cb61c79eMathias Agopian 21edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <SkCanvas.h> 22c5b2c0bf8007562536b822eb060fc54a01f8e08bMathias Agopian#include <SkGradientShader.h> 23c5b2c0bf8007562536b822eb060fc54a01f8e08bMathias Agopian 24c5b2c0bf8007562536b822eb060fc54a01f8e08bMathias Agopian#include "GradientCache.h" 25c5b2c0bf8007562536b822eb060fc54a01f8e08bMathias Agopian 26c5b2c0bf8007562536b822eb060fc54a01f8e08bMathias Agopiannamespace android { 27edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectnamespace uirenderer { 28edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 29edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 30002e1e58dfe19dd3e49a59c6827cbf51573941a2Mathias Agopian// Constructors/destructor 31002e1e58dfe19dd3e49a59c6827cbf51573941a2Mathias Agopian/////////////////////////////////////////////////////////////////////////////// 32002e1e58dfe19dd3e49a59c6827cbf51573941a2Mathias Agopian 33208059f67ed2dd9fa025e07fcb6954d3cb61c79eMathias AgopianGradientCache::GradientCache(uint32_t maxByteSize): 34208059f67ed2dd9fa025e07fcb6954d3cb61c79eMathias Agopian mCache(GenerationCache<SkShader*, Texture*>::kUnlimitedCapacity), 35208059f67ed2dd9fa025e07fcb6954d3cb61c79eMathias Agopian mSize(0), mMaxSize(maxByteSize) { 36edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project mCache.setOnEntryRemovedListener(this); 377e790af756d7891cb1cf1374bb283a8fbcbe6b49Dianne Hackborn} 387e790af756d7891cb1cf1374bb283a8fbcbe6b49Dianne Hackborn 397e790af756d7891cb1cf1374bb283a8fbcbe6b49Dianne HackbornGradientCache::~GradientCache() { 407e790af756d7891cb1cf1374bb283a8fbcbe6b49Dianne Hackborn mCache.clear(); 417e790af756d7891cb1cf1374bb283a8fbcbe6b49Dianne Hackborn} 427e790af756d7891cb1cf1374bb283a8fbcbe6b49Dianne Hackborn 43208059f67ed2dd9fa025e07fcb6954d3cb61c79eMathias Agopian/////////////////////////////////////////////////////////////////////////////// 44208059f67ed2dd9fa025e07fcb6954d3cb61c79eMathias Agopian// Size management 45208059f67ed2dd9fa025e07fcb6954d3cb61c79eMathias Agopian/////////////////////////////////////////////////////////////////////////////// 46edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 47208059f67ed2dd9fa025e07fcb6954d3cb61c79eMathias Agopianuint32_t GradientCache::getSize() { 48 return mSize; 49} 50 51uint32_t GradientCache::getMaxSize() { 52 return mMaxSize; 53} 54 55void GradientCache::setMaxSize(uint32_t maxSize) { 56 mMaxSize = maxSize; 57 while (mSize > mMaxSize) { 58 mCache.removeOldest(); 59 } 60} 61 62/////////////////////////////////////////////////////////////////////////////// 63// Callbacks 64/////////////////////////////////////////////////////////////////////////////// 65 66void GradientCache::operator()(SkShader*& shader, Texture*& texture) { 67 if (shader) { 68 const uint32_t size = texture->width * texture->height * 4; 69 mSize -= size; 70 } 71 72 if (texture) { 73 glDeleteTextures(1, &texture->id); 74 delete texture; 75 } 76} 77 78/////////////////////////////////////////////////////////////////////////////// 79// Caching 80/////////////////////////////////////////////////////////////////////////////// 81 82Texture* GradientCache::get(SkShader* shader) { 83 return mCache.get(shader); 84} 85 86void GradientCache::remove(SkShader* shader) { 87 mCache.remove(shader); 88} 89 90void GradientCache::clear() { 91 mCache.clear(); 92} 93 94Texture* GradientCache::addLinearGradient(SkShader* shader, float* bounds, uint32_t* colors, 95 float* positions, int count, SkShader::TileMode tileMode) { 96 SkBitmap bitmap; 97 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1024, 1); 98 bitmap.allocPixels(); 99 bitmap.eraseColor(0); 100 101 SkCanvas canvas(bitmap); 102 103 SkPoint points[2]; 104 points[0].set(0.0f, 0.0f); 105 points[1].set(bitmap.width(), 0.0f); 106 107 SkShader* localShader = SkGradientShader::CreateLinear(points, 108 reinterpret_cast<const SkColor*>(colors), positions, count, tileMode); 109 110 SkPaint p; 111 p.setStyle(SkPaint::kStrokeAndFill_Style); 112 p.setShader(localShader)->unref(); 113 114 canvas.drawRectCoords(0.0f, 0.0f, bitmap.width(), 1.0f, p); 115 116 // Asume the cache is always big enough 117 const uint32_t size = bitmap.rowBytes() * bitmap.height(); 118 while (mSize + size > mMaxSize) { 119 mCache.removeOldest(); 120 } 121 122 Texture* texture = new Texture; 123 generateTexture(&bitmap, texture); 124 125 mSize += size; 126 mCache.put(shader, texture); 127 128 return texture; 129} 130 131void GradientCache::generateTexture(SkBitmap* bitmap, Texture* texture) { 132 SkAutoLockPixels autoLock(*bitmap); 133 if (!bitmap->readyToDraw()) { 134 LOGE("Cannot generate texture from shader"); 135 return; 136 } 137 138 texture->generation = bitmap->getGenerationID(); 139 texture->width = bitmap->width(); 140 texture->height = bitmap->height(); 141 142 glGenTextures(1, &texture->id); 143 144 glBindTexture(GL_TEXTURE_2D, texture->id); 145 glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel()); 146 147 texture->blend = !bitmap->isOpaque(); 148 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap->rowBytesAsPixels(), texture->height, 0, 149 GL_RGBA, GL_UNSIGNED_BYTE, bitmap->getPixels()); 150 151 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 152 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 153 154 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 155 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 156} 157 158}; // namespace uirenderer 159}; // namespace android 160