GradientCache.cpp revision 9cccc2b9bdd4850a3f9679569aaec3ab98477a5d
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "OpenGLRenderer" 18 19#include <GLES2/gl2.h> 20 21#include <SkCanvas.h> 22#include <SkGradientShader.h> 23 24#include "GradientCache.h" 25 26namespace android { 27namespace uirenderer { 28 29/////////////////////////////////////////////////////////////////////////////// 30// Constructors/destructor 31/////////////////////////////////////////////////////////////////////////////// 32 33GradientCache::GradientCache(uint32_t maxByteSize): 34 mCache(GenerationCache<SkShader*, Texture*>::kUnlimitedCapacity), 35 mSize(0), mMaxSize(maxByteSize) { 36 mCache.setOnEntryRemovedListener(this); 37} 38 39GradientCache::~GradientCache() { 40 mCache.clear(); 41} 42 43/////////////////////////////////////////////////////////////////////////////// 44// Size management 45/////////////////////////////////////////////////////////////////////////////// 46 47uint32_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