TextureCache.cpp revision bd0e6aa0ff0bd8b376772c3e23513a6021bdda87
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 "TextureCache.h" 22 23namespace android { 24namespace uirenderer { 25 26/////////////////////////////////////////////////////////////////////////////// 27// Constructors/destructor 28/////////////////////////////////////////////////////////////////////////////// 29 30TextureCache::TextureCache(uint32_t maxByteSize): 31 mCache(GenerationCache<SkBitmap*, Texture*>::kUnlimitedCapacity), 32 mSize(0), mMaxSize(maxByteSize) { 33 mCache.setOnEntryRemovedListener(this); 34} 35 36TextureCache::~TextureCache() { 37 mCache.clear(); 38} 39 40/////////////////////////////////////////////////////////////////////////////// 41// Size management 42/////////////////////////////////////////////////////////////////////////////// 43 44uint32_t TextureCache::getSize() { 45 return mSize; 46} 47 48uint32_t TextureCache::getMaxSize() { 49 return mMaxSize; 50} 51 52void TextureCache::setMaxSize(uint32_t maxSize) { 53 mMaxSize = maxSize; 54 while (mSize > mMaxSize) { 55 mCache.removeOldest(); 56 } 57} 58 59/////////////////////////////////////////////////////////////////////////////// 60// Callbacks 61/////////////////////////////////////////////////////////////////////////////// 62 63void TextureCache::operator()(SkBitmap*& bitmap, Texture*& texture) { 64 if (bitmap) { 65 const uint32_t size = bitmap->rowBytes() * bitmap->height(); 66 mSize -= size; 67 } 68 69 if (texture) { 70 glDeleteTextures(1, &texture->id); 71 delete texture; 72 } 73} 74 75/////////////////////////////////////////////////////////////////////////////// 76// Caching 77/////////////////////////////////////////////////////////////////////////////// 78 79Texture* TextureCache::get(SkBitmap* bitmap) { 80 Texture* texture = mCache.get(bitmap); 81 if (!texture) { 82 const uint32_t size = bitmap->rowBytes() * bitmap->height(); 83 // Don't even try to cache a bitmap that's bigger than the cache 84 if (size < mMaxSize) { 85 while (mSize + size > mMaxSize) { 86 mCache.removeOldest(); 87 } 88 } 89 90 texture = new Texture; 91 generateTexture(bitmap, texture, false); 92 93 if (size < mMaxSize) { 94 mSize += size; 95 mCache.put(bitmap, texture); 96 } 97 } else if (bitmap->getGenerationID() != texture->generation) { 98 generateTexture(bitmap, texture, true); 99 } 100 // TODO: Do something to destroy the texture object if it's too big for the cache 101 return texture; 102} 103 104void TextureCache::remove(SkBitmap* bitmap) { 105 mCache.remove(bitmap); 106} 107 108void TextureCache::clear() { 109 mCache.clear(); 110} 111 112void TextureCache::generateTexture(SkBitmap* bitmap, Texture* texture, bool regenerate) { 113 SkAutoLockPixels alp(*bitmap); 114 if (!bitmap->readyToDraw()) { 115 LOGE("Cannot generate texture from bitmap"); 116 return; 117 } 118 119 if (!regenerate) { 120 texture->generation = bitmap->getGenerationID(); 121 texture->width = bitmap->width(); 122 texture->height = bitmap->height(); 123 124 glGenTextures(1, &texture->id); 125 } 126 127 glBindTexture(GL_TEXTURE_2D, texture->id); 128 glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel()); 129 130 switch (bitmap->getConfig()) { 131 case SkBitmap::kA8_Config: 132 texture->blend = true; 133 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, bitmap->rowBytesAsPixels(), texture->height, 0, 134 GL_ALPHA, GL_UNSIGNED_BYTE, bitmap->getPixels()); 135 break; 136 case SkBitmap::kRGB_565_Config: 137 texture->blend = false; 138 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, bitmap->rowBytesAsPixels(), texture->height, 0, 139 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, bitmap->getPixels()); 140 break; 141 case SkBitmap::kARGB_8888_Config: 142 texture->blend = !bitmap->isOpaque(); 143 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap->rowBytesAsPixels(), texture->height, 0, 144 GL_RGBA, GL_UNSIGNED_BYTE, bitmap->getPixels()); 145 break; 146 default: 147 break; 148 } 149 150 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 151 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 152 153 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 154 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 155} 156 157}; // namespace uirenderer 158}; // namespace android 159