TextureCache.cpp revision e9e7fd0813f1485d20c6cd0014d59aff53c35d84
1ce0537b80087a6225273040a987414b1dd081aa0Romain Guy/* 2ce0537b80087a6225273040a987414b1dd081aa0Romain Guy * Copyright (C) 2010 The Android Open Source Project 3ce0537b80087a6225273040a987414b1dd081aa0Romain Guy * 4ce0537b80087a6225273040a987414b1dd081aa0Romain Guy * Licensed under the Apache License, Version 2.0 (the "License"); 5ce0537b80087a6225273040a987414b1dd081aa0Romain Guy * you may not use this file except in compliance with the License. 6ce0537b80087a6225273040a987414b1dd081aa0Romain Guy * You may obtain a copy of the License at 7ce0537b80087a6225273040a987414b1dd081aa0Romain Guy * 8ce0537b80087a6225273040a987414b1dd081aa0Romain Guy * http://www.apache.org/licenses/LICENSE-2.0 9ce0537b80087a6225273040a987414b1dd081aa0Romain Guy * 10ce0537b80087a6225273040a987414b1dd081aa0Romain Guy * Unless required by applicable law or agreed to in writing, software 11ce0537b80087a6225273040a987414b1dd081aa0Romain Guy * distributed under the License is distributed on an "AS IS" BASIS, 12ce0537b80087a6225273040a987414b1dd081aa0Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ce0537b80087a6225273040a987414b1dd081aa0Romain Guy * See the License for the specific language governing permissions and 14ce0537b80087a6225273040a987414b1dd081aa0Romain Guy * limitations under the License. 15ce0537b80087a6225273040a987414b1dd081aa0Romain Guy */ 16ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 17121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy#define LOG_TAG "OpenGLRenderer" 18121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 19ce0537b80087a6225273040a987414b1dd081aa0Romain Guy#include <GLES2/gl2.h> 20ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 21ce0537b80087a6225273040a987414b1dd081aa0Romain Guy#include "TextureCache.h" 22ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 23ce0537b80087a6225273040a987414b1dd081aa0Romain Guynamespace android { 24ce0537b80087a6225273040a987414b1dd081aa0Romain Guynamespace uirenderer { 25ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 26121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy/////////////////////////////////////////////////////////////////////////////// 27121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy// Constructors/destructor 28121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy/////////////////////////////////////////////////////////////////////////////// 29121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 307d139ba2c331f11e9b485753cc727a0ff202f2a4Romain GuyTextureCache::TextureCache(uint32_t maxByteSize): 316c81893c626499e58c8eeb20d6c35ec4e1ce808bRomain Guy mCache(GenerationCache<SkBitmap*, Texture*>::kUnlimitedCapacity), 32121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy mSize(0), mMaxSize(maxByteSize) { 33ce0537b80087a6225273040a987414b1dd081aa0Romain Guy mCache.setOnEntryRemovedListener(this); 349cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy 35163935113919a184122b8b3bd672ef08c8df65dcRomain Guy glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize); 36163935113919a184122b8b3bd672ef08c8df65dcRomain Guy LOGD("Maximum texture dimension is %d pixels", mMaxTextureSize); 37ce0537b80087a6225273040a987414b1dd081aa0Romain Guy} 38ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 39ce0537b80087a6225273040a987414b1dd081aa0Romain GuyTextureCache::~TextureCache() { 40ce0537b80087a6225273040a987414b1dd081aa0Romain Guy mCache.clear(); 41ce0537b80087a6225273040a987414b1dd081aa0Romain Guy} 42ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 43121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy/////////////////////////////////////////////////////////////////////////////// 44121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy// Size management 45121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy/////////////////////////////////////////////////////////////////////////////// 46121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 477d139ba2c331f11e9b485753cc727a0ff202f2a4Romain Guyuint32_t TextureCache::getSize() { 48121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy return mSize; 49121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy} 50121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 517d139ba2c331f11e9b485753cc727a0ff202f2a4Romain Guyuint32_t TextureCache::getMaxSize() { 52121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy return mMaxSize; 53121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy} 54121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 557d139ba2c331f11e9b485753cc727a0ff202f2a4Romain Guyvoid TextureCache::setMaxSize(uint32_t maxSize) { 56121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy mMaxSize = maxSize; 57121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy while (mSize > mMaxSize) { 58121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy mCache.removeOldest(); 59121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy } 60121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy} 61121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 62121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy/////////////////////////////////////////////////////////////////////////////// 63121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy// Callbacks 64121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy/////////////////////////////////////////////////////////////////////////////// 65121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 66dda570201ac851dd85af3861f7e575721d3345daRomain Guyvoid TextureCache::operator()(SkBitmap*& bitmap, Texture*& texture) { 67121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy if (bitmap) { 687d139ba2c331f11e9b485753cc727a0ff202f2a4Romain Guy const uint32_t size = bitmap->rowBytes() * bitmap->height(); 69121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy mSize -= size; 70121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy } 71121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 72121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy if (texture) { 73121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy glDeleteTextures(1, &texture->id); 74121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy delete texture; 75ce0537b80087a6225273040a987414b1dd081aa0Romain Guy } 76ce0537b80087a6225273040a987414b1dd081aa0Romain Guy} 77ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 78121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy/////////////////////////////////////////////////////////////////////////////// 79121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy// Caching 80121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy/////////////////////////////////////////////////////////////////////////////// 81121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 82ce0537b80087a6225273040a987414b1dd081aa0Romain GuyTexture* TextureCache::get(SkBitmap* bitmap) { 83ce0537b80087a6225273040a987414b1dd081aa0Romain Guy Texture* texture = mCache.get(bitmap); 84ce0537b80087a6225273040a987414b1dd081aa0Romain Guy if (!texture) { 859cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy if (bitmap->width() > mMaxTextureSize || bitmap->height() > mMaxTextureSize) { 869cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy LOGW("Bitmap too large to be uploaded into a texture"); 879cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy return NULL; 889cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy } 899cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy 907d139ba2c331f11e9b485753cc727a0ff202f2a4Romain Guy const uint32_t size = bitmap->rowBytes() * bitmap->height(); 91121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy // Don't even try to cache a bitmap that's bigger than the cache 92121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy if (size < mMaxSize) { 93121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy while (mSize + size > mMaxSize) { 94121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy mCache.removeOldest(); 95121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy } 96121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy } 97121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 98364703c6fa4aa1a7d2ef5b0c048ea2a0d57a4c40Romain Guy texture = new Texture; 99c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy generateTexture(bitmap, texture, false); 100121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 101121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy if (size < mMaxSize) { 102121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy mSize += size; 103121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy mCache.put(bitmap, texture); 10422158e139a3d6c6a9787ca0de224e9368f643284Romain Guy } else { 10522158e139a3d6c6a9787ca0de224e9368f643284Romain Guy texture->cleanup = true; 106121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy } 107fe8809471a40cac8acc984adfa51c39e13e83947Romain Guy } else if (bitmap->getGenerationID() != texture->generation) { 108fe8809471a40cac8acc984adfa51c39e13e83947Romain Guy generateTexture(bitmap, texture, true); 109ce0537b80087a6225273040a987414b1dd081aa0Romain Guy } 11022158e139a3d6c6a9787ca0de224e9368f643284Romain Guy 111ce0537b80087a6225273040a987414b1dd081aa0Romain Guy return texture; 112ce0537b80087a6225273040a987414b1dd081aa0Romain Guy} 113ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 114121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guyvoid TextureCache::remove(SkBitmap* bitmap) { 115121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy mCache.remove(bitmap); 116ce0537b80087a6225273040a987414b1dd081aa0Romain Guy} 117ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 118ce0537b80087a6225273040a987414b1dd081aa0Romain Guyvoid TextureCache::clear() { 119ce0537b80087a6225273040a987414b1dd081aa0Romain Guy mCache.clear(); 120ce0537b80087a6225273040a987414b1dd081aa0Romain Guy} 121ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 122fe8809471a40cac8acc984adfa51c39e13e83947Romain Guyvoid TextureCache::generateTexture(SkBitmap* bitmap, Texture* texture, bool regenerate) { 123c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy SkAutoLockPixels alp(*bitmap); 124c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy if (!bitmap->readyToDraw()) { 125c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy LOGE("Cannot generate texture from bitmap"); 126c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy return; 127c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy } 128c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy 129fe8809471a40cac8acc984adfa51c39e13e83947Romain Guy if (!regenerate) { 130c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy texture->generation = bitmap->getGenerationID(); 131fe8809471a40cac8acc984adfa51c39e13e83947Romain Guy texture->width = bitmap->width(); 132fe8809471a40cac8acc984adfa51c39e13e83947Romain Guy texture->height = bitmap->height(); 133fe8809471a40cac8acc984adfa51c39e13e83947Romain Guy 134fe8809471a40cac8acc984adfa51c39e13e83947Romain Guy glGenTextures(1, &texture->id); 135fe8809471a40cac8acc984adfa51c39e13e83947Romain Guy } 136ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 137ce0537b80087a6225273040a987414b1dd081aa0Romain Guy glBindTexture(GL_TEXTURE_2D, texture->id); 138c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel()); 139ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 140ce0537b80087a6225273040a987414b1dd081aa0Romain Guy switch (bitmap->getConfig()) { 141bd0e6aa0ff0bd8b376772c3e23513a6021bdda87Romain Guy case SkBitmap::kA8_Config: 142bd0e6aa0ff0bd8b376772c3e23513a6021bdda87Romain Guy texture->blend = true; 143bd0e6aa0ff0bd8b376772c3e23513a6021bdda87Romain Guy glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, bitmap->rowBytesAsPixels(), texture->height, 0, 144bd0e6aa0ff0bd8b376772c3e23513a6021bdda87Romain Guy GL_ALPHA, GL_UNSIGNED_BYTE, bitmap->getPixels()); 145bd0e6aa0ff0bd8b376772c3e23513a6021bdda87Romain Guy break; 146ce0537b80087a6225273040a987414b1dd081aa0Romain Guy case SkBitmap::kRGB_565_Config: 147c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy texture->blend = false; 148c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, bitmap->rowBytesAsPixels(), texture->height, 0, 149c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy GL_RGB, GL_UNSIGNED_SHORT_5_6_5, bitmap->getPixels()); 150ce0537b80087a6225273040a987414b1dd081aa0Romain Guy break; 151ce0537b80087a6225273040a987414b1dd081aa0Romain Guy case SkBitmap::kARGB_8888_Config: 152c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap->rowBytesAsPixels(), texture->height, 0, 153c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy GL_RGBA, GL_UNSIGNED_BYTE, bitmap->getPixels()); 154e9e7fd0813f1485d20c6cd0014d59aff53c35d84Romain Guy // Do this after calling getPixels() to make sure Skia's deferred 155e9e7fd0813f1485d20c6cd0014d59aff53c35d84Romain Guy // decoding happened 156e9e7fd0813f1485d20c6cd0014d59aff53c35d84Romain Guy texture->blend = !bitmap->isOpaque(); 157ce0537b80087a6225273040a987414b1dd081aa0Romain Guy break; 158364703c6fa4aa1a7d2ef5b0c048ea2a0d57a4c40Romain Guy default: 159364703c6fa4aa1a7d2ef5b0c048ea2a0d57a4c40Romain Guy break; 160ce0537b80087a6225273040a987414b1dd081aa0Romain Guy } 161ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 162c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 163c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1648ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy 165c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 166c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 167ce0537b80087a6225273040a987414b1dd081aa0Romain Guy} 168ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 169ce0537b80087a6225273040a987414b1dd081aa0Romain Guy}; // namespace uirenderer 170ce0537b80087a6225273040a987414b1dd081aa0Romain Guy}; // namespace android 171