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" 18ec4cefc152749f9805d3a971a4a395687b5a3831John Reck#define ATRACE_TAG ATRACE_TAG_VIEW 19121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 20ce0537b80087a6225273040a987414b1dd081aa0Romain Guy#include <GLES2/gl2.h> 21ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 227adaf3d1aa18c7e521f7154e545fe52d329763c3Romain Guy#include <SkCanvas.h> 2371d08a07189c2b433080203895d9d5e936b16b9eJohn Reck#include <SkPixelRef.h> 247adaf3d1aa18c7e521f7154e545fe52d329763c3Romain Guy 25ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy#include <utils/Mutex.h> 269aaa8269a3e7291aab84d01c3fc9c744d8f2d2f4Romain Guy 27ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck#include "AssetAtlas.h" 28713e1bb9df6bdfc21bd5c40d1a6ecf6c822a4be5Romain Guy#include "Caches.h" 29ce0537b80087a6225273040a987414b1dd081aa0Romain Guy#include "TextureCache.h" 30fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy#include "Properties.h" 3170850ea258cbf91477efa57a1f1a23cc0044cc93Chris Craik#include "utils/TraceUtils.h" 32ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 33ce0537b80087a6225273040a987414b1dd081aa0Romain Guynamespace android { 34ce0537b80087a6225273040a987414b1dd081aa0Romain Guynamespace uirenderer { 35ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 36121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy/////////////////////////////////////////////////////////////////////////////// 37121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy// Constructors/destructor 38121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy/////////////////////////////////////////////////////////////////////////////// 39121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 40fb8b763f762ae21923c58d64caa729b012f40e05Romain GuyTextureCache::TextureCache(): 4171d08a07189c2b433080203895d9d5e936b16b9eJohn Reck mCache(LruCache<uint32_t, Texture*>::kUnlimitedCapacity), 42eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy mSize(0), mMaxSize(MB(DEFAULT_TEXTURE_CACHE_SIZE)), 43ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck mFlushRate(DEFAULT_TEXTURE_CACHE_FLUSH_RATE), mAssetAtlas(0) { 44fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy char property[PROPERTY_VALUE_MAX]; 45fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy if (property_get(PROPERTY_TEXTURE_CACHE_SIZE, property, NULL) > 0) { 46c9855a53edfac818dc68714557185977556f849dRomain Guy INIT_LOGD(" Setting texture cache size to %sMB", property); 47fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy setMaxSize(MB(atof(property))); 48fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy } else { 49c9855a53edfac818dc68714557185977556f849dRomain Guy INIT_LOGD(" Using default texture cache size of %.2fMB", DEFAULT_TEXTURE_CACHE_SIZE); 50fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy } 51fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 52eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy if (property_get(PROPERTY_TEXTURE_CACHE_FLUSH_RATE, property, NULL) > 0) { 53eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy float flushRate = atof(property); 54eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy INIT_LOGD(" Setting texture cache flush rate to %.2f%%", flushRate * 100.0f); 55eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy setFlushRate(flushRate); 56eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy } else { 57eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy INIT_LOGD(" Using default texture cache flush rate of %.2f%%", 58eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy DEFAULT_TEXTURE_CACHE_FLUSH_RATE * 100.0f); 59eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy } 60eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy 61fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy init(); 62fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy} 63fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 647d139ba2c331f11e9b485753cc727a0ff202f2a4Romain GuyTextureCache::TextureCache(uint32_t maxByteSize): 6571d08a07189c2b433080203895d9d5e936b16b9eJohn Reck mCache(LruCache<uint32_t, Texture*>::kUnlimitedCapacity), 66ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck mSize(0), mMaxSize(maxByteSize), mAssetAtlas(0) { 67fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy init(); 68ce0537b80087a6225273040a987414b1dd081aa0Romain Guy} 69ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 70ce0537b80087a6225273040a987414b1dd081aa0Romain GuyTextureCache::~TextureCache() { 71ce0537b80087a6225273040a987414b1dd081aa0Romain Guy mCache.clear(); 72ce0537b80087a6225273040a987414b1dd081aa0Romain Guy} 73ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 74fb8b763f762ae21923c58d64caa729b012f40e05Romain Guyvoid TextureCache::init() { 75fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy mCache.setOnEntryRemovedListener(this); 76fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 77fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize); 78f6834478b379856d3e5de92ddce7de0e6ba9fa4aRomain Guy INIT_LOGD(" Maximum texture dimension is %d pixels", mMaxTextureSize); 79e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guy 80e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guy mDebugEnabled = readDebugLevel() & kDebugCaches; 81fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy} 82fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 83121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy/////////////////////////////////////////////////////////////////////////////// 84121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy// Size management 85121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy/////////////////////////////////////////////////////////////////////////////// 86121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 877d139ba2c331f11e9b485753cc727a0ff202f2a4Romain Guyuint32_t TextureCache::getSize() { 88121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy return mSize; 89121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy} 90121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 917d139ba2c331f11e9b485753cc727a0ff202f2a4Romain Guyuint32_t TextureCache::getMaxSize() { 92121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy return mMaxSize; 93121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy} 94121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 957d139ba2c331f11e9b485753cc727a0ff202f2a4Romain Guyvoid TextureCache::setMaxSize(uint32_t maxSize) { 96121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy mMaxSize = maxSize; 97121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy while (mSize > mMaxSize) { 98121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy mCache.removeOldest(); 99121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy } 100121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy} 101121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 102eca0ca2424afc1e98912405906edfc32f7733e16Romain Guyvoid TextureCache::setFlushRate(float flushRate) { 103eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy mFlushRate = fmaxf(0.0f, fminf(1.0f, flushRate)); 104eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy} 105eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy 106121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy/////////////////////////////////////////////////////////////////////////////// 107121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy// Callbacks 108121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy/////////////////////////////////////////////////////////////////////////////// 109121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 11071d08a07189c2b433080203895d9d5e936b16b9eJohn Reckvoid TextureCache::operator()(uint32_t&, Texture*& texture) { 1119aaa8269a3e7291aab84d01c3fc9c744d8f2d2f4Romain Guy // This will be called already locked 112121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy if (texture) { 1139aaa8269a3e7291aab84d01c3fc9c744d8f2d2f4Romain Guy mSize -= texture->bitmapSize; 1149e10841c27d973b930e1b49a099c69d866659505Romain Guy TEXTURE_LOGD("TextureCache::callback: name, removed size, mSize = %d, %d, %d", 1159e10841c27d973b930e1b49a099c69d866659505Romain Guy texture->id, texture->bitmapSize, mSize); 116e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guy if (mDebugEnabled) { 1175baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("Texture deleted, size = %d", texture->bitmapSize); 118e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guy } 119be1b127c7bec252e0c6ab0e06ed6babed07d496fRomain Guy texture->deleteTexture(); 120121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy delete texture; 121ce0537b80087a6225273040a987414b1dd081aa0Romain Guy } 122ce0537b80087a6225273040a987414b1dd081aa0Romain Guy} 123ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 124121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy/////////////////////////////////////////////////////////////////////////////// 125121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy// Caching 126121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy/////////////////////////////////////////////////////////////////////////////// 127121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 128ebd52610cfeff6e557fde284a7e1efc5e6438285John Reckvoid TextureCache::setAssetAtlas(AssetAtlas* assetAtlas) { 129ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck mAssetAtlas = assetAtlas; 130ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck} 131ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck 132860d155f866cc15a725e7ce03763280987f24901John Reckvoid TextureCache::resetMarkInUse() { 13371d08a07189c2b433080203895d9d5e936b16b9eJohn Reck LruCache<uint32_t, Texture*>::Iterator iter(mCache); 134860d155f866cc15a725e7ce03763280987f24901John Reck while (iter.next()) { 135860d155f866cc15a725e7ce03763280987f24901John Reck iter.value()->isInUse = false; 136860d155f866cc15a725e7ce03763280987f24901John Reck } 137860d155f866cc15a725e7ce03763280987f24901John Reck} 138860d155f866cc15a725e7ce03763280987f24901John Reck 139860d155f866cc15a725e7ce03763280987f24901John Reckbool TextureCache::canMakeTextureFromBitmap(const SkBitmap* bitmap) { 140860d155f866cc15a725e7ce03763280987f24901John Reck if (bitmap->width() > mMaxTextureSize || bitmap->height() > mMaxTextureSize) { 141860d155f866cc15a725e7ce03763280987f24901John Reck ALOGW("Bitmap too large to be uploaded into a texture (%dx%d, max=%dx%d)", 142860d155f866cc15a725e7ce03763280987f24901John Reck bitmap->width(), bitmap->height(), mMaxTextureSize, mMaxTextureSize); 143860d155f866cc15a725e7ce03763280987f24901John Reck return false; 144860d155f866cc15a725e7ce03763280987f24901John Reck } 145860d155f866cc15a725e7ce03763280987f24901John Reck return true; 146860d155f866cc15a725e7ce03763280987f24901John Reck} 147860d155f866cc15a725e7ce03763280987f24901John Reck 148860d155f866cc15a725e7ce03763280987f24901John Reck// Returns a prepared Texture* that either is already in the cache or can fit 149860d155f866cc15a725e7ce03763280987f24901John Reck// in the cache (and is thus added to the cache) 150860d155f866cc15a725e7ce03763280987f24901John ReckTexture* TextureCache::getCachedTexture(const SkBitmap* bitmap) { 151ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck if (CC_LIKELY(mAssetAtlas)) { 152ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck AssetAtlas::Entry* entry = mAssetAtlas->getEntry(bitmap); 153ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck if (CC_UNLIKELY(entry)) { 154ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck return entry->texture; 155ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck } 156ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck } 157ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck 15871d08a07189c2b433080203895d9d5e936b16b9eJohn Reck Texture* texture = mCache.get(bitmap->pixelRef()->getStableID()); 159a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy 160ce0537b80087a6225273040a987414b1dd081aa0Romain Guy if (!texture) { 161860d155f866cc15a725e7ce03763280987f24901John Reck if (!canMakeTextureFromBitmap(bitmap)) { 1629cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy return NULL; 1639cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy } 1649cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy 1657d139ba2c331f11e9b485753cc727a0ff202f2a4Romain Guy const uint32_t size = bitmap->rowBytes() * bitmap->height(); 166860d155f866cc15a725e7ce03763280987f24901John Reck bool canCache = size < mMaxSize; 167121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy // Don't even try to cache a bitmap that's bigger than the cache 168860d155f866cc15a725e7ce03763280987f24901John Reck while (canCache && mSize + size > mMaxSize) { 169860d155f866cc15a725e7ce03763280987f24901John Reck Texture* oldest = mCache.peekOldestValue(); 170860d155f866cc15a725e7ce03763280987f24901John Reck if (oldest && !oldest->isInUse) { 171121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy mCache.removeOldest(); 172860d155f866cc15a725e7ce03763280987f24901John Reck } else { 173860d155f866cc15a725e7ce03763280987f24901John Reck canCache = false; 174121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy } 175121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy } 176121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 177860d155f866cc15a725e7ce03763280987f24901John Reck if (canCache) { 178860d155f866cc15a725e7ce03763280987f24901John Reck texture = new Texture(); 179860d155f866cc15a725e7ce03763280987f24901John Reck texture->bitmapSize = size; 180860d155f866cc15a725e7ce03763280987f24901John Reck generateTexture(bitmap, texture, false); 181121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 182121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy mSize += size; 1839e10841c27d973b930e1b49a099c69d866659505Romain Guy TEXTURE_LOGD("TextureCache::get: create texture(%p): name, size, mSize = %d, %d, %d", 1849e10841c27d973b930e1b49a099c69d866659505Romain Guy bitmap, texture->id, size, mSize); 185e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guy if (mDebugEnabled) { 1865baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("Texture created, size = %d", size); 187e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guy } 18871d08a07189c2b433080203895d9d5e936b16b9eJohn Reck mCache.put(bitmap->pixelRef()->getStableID(), texture); 189121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy } 190860d155f866cc15a725e7ce03763280987f24901John Reck } else if (!texture->isInUse && bitmap->getGenerationID() != texture->generation) { 191860d155f866cc15a725e7ce03763280987f24901John Reck // Texture was in the cache but is dirty, re-upload 192860d155f866cc15a725e7ce03763280987f24901John Reck // TODO: Re-adjust the cache size if the bitmap's dimensions have changed 193fe8809471a40cac8acc984adfa51c39e13e83947Romain Guy generateTexture(bitmap, texture, true); 194ce0537b80087a6225273040a987414b1dd081aa0Romain Guy } 19522158e139a3d6c6a9787ca0de224e9368f643284Romain Guy 196ce0537b80087a6225273040a987414b1dd081aa0Romain Guy return texture; 197ce0537b80087a6225273040a987414b1dd081aa0Romain Guy} 198ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 199860d155f866cc15a725e7ce03763280987f24901John Reckbool TextureCache::prefetchAndMarkInUse(const SkBitmap* bitmap) { 200860d155f866cc15a725e7ce03763280987f24901John Reck Texture* texture = getCachedTexture(bitmap); 201860d155f866cc15a725e7ce03763280987f24901John Reck if (texture) { 202860d155f866cc15a725e7ce03763280987f24901John Reck texture->isInUse = true; 203860d155f866cc15a725e7ce03763280987f24901John Reck } 204860d155f866cc15a725e7ce03763280987f24901John Reck return texture; 205860d155f866cc15a725e7ce03763280987f24901John Reck} 206860d155f866cc15a725e7ce03763280987f24901John Reck 207860d155f866cc15a725e7ce03763280987f24901John ReckTexture* TextureCache::get(const SkBitmap* bitmap) { 208860d155f866cc15a725e7ce03763280987f24901John Reck Texture* texture = getCachedTexture(bitmap); 209860d155f866cc15a725e7ce03763280987f24901John Reck 210860d155f866cc15a725e7ce03763280987f24901John Reck if (!texture) { 211860d155f866cc15a725e7ce03763280987f24901John Reck if (!canMakeTextureFromBitmap(bitmap)) { 212860d155f866cc15a725e7ce03763280987f24901John Reck return NULL; 213860d155f866cc15a725e7ce03763280987f24901John Reck } 214860d155f866cc15a725e7ce03763280987f24901John Reck 215860d155f866cc15a725e7ce03763280987f24901John Reck const uint32_t size = bitmap->rowBytes() * bitmap->height(); 216860d155f866cc15a725e7ce03763280987f24901John Reck texture = new Texture(); 217860d155f866cc15a725e7ce03763280987f24901John Reck texture->bitmapSize = size; 218860d155f866cc15a725e7ce03763280987f24901John Reck generateTexture(bitmap, texture, false); 219860d155f866cc15a725e7ce03763280987f24901John Reck texture->cleanup = true; 220860d155f866cc15a725e7ce03763280987f24901John Reck } 221860d155f866cc15a725e7ce03763280987f24901John Reck 222860d155f866cc15a725e7ce03763280987f24901John Reck return texture; 223860d155f866cc15a725e7ce03763280987f24901John Reck} 224860d155f866cc15a725e7ce03763280987f24901John Reck 225d218a92c0afb8c0d98135b20b52ac87236e1c935Chris CraikTexture* TextureCache::getTransient(const SkBitmap* bitmap) { 2268aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy Texture* texture = new Texture(); 227e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy texture->bitmapSize = bitmap->rowBytes() * bitmap->height(); 228e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy texture->cleanup = true; 229e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy 230e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy generateTexture(bitmap, texture, false); 231e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy 232e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy return texture; 233e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy} 234e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy 23571d08a07189c2b433080203895d9d5e936b16b9eJohn Reckvoid TextureCache::releaseTexture(const SkBitmap* bitmap) { 23671d08a07189c2b433080203895d9d5e936b16b9eJohn Reck if (!bitmap || !bitmap->pixelRef()) return; 237ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 2389aaa8269a3e7291aab84d01c3fc9c744d8f2d2f4Romain Guy Mutex::Autolock _l(mLock); 23971d08a07189c2b433080203895d9d5e936b16b9eJohn Reck mGarbage.push(bitmap->pixelRef()->getStableID()); 240fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy} 241fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy 242fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guyvoid TextureCache::clearGarbage() { 243fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy Mutex::Autolock _l(mLock); 244fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy size_t count = mGarbage.size(); 245fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy for (size_t i = 0; i < count; i++) { 24671d08a07189c2b433080203895d9d5e936b16b9eJohn Reck uint32_t pixelRefId = mGarbage.itemAt(i); 24771d08a07189c2b433080203895d9d5e936b16b9eJohn Reck mCache.remove(pixelRefId); 248fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy } 249fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy mGarbage.clear(); 250fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy} 251fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy 252fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guyvoid TextureCache::clear() { 253ce0537b80087a6225273040a987414b1dd081aa0Romain Guy mCache.clear(); 254912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy TEXTURE_LOGD("TextureCache:clear(), mSize = %d", mSize); 255ce0537b80087a6225273040a987414b1dd081aa0Romain Guy} 256ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 257eca0ca2424afc1e98912405906edfc32f7733e16Romain Guyvoid TextureCache::flush() { 258eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy if (mFlushRate >= 1.0f || mCache.size() == 0) return; 259eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy if (mFlushRate <= 0.0f) { 260eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy clear(); 261eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy return; 262eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy } 263eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy 264eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy uint32_t targetSize = uint32_t(mSize * mFlushRate); 265eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy TEXTURE_LOGD("TextureCache::flush: target size: %d", targetSize); 266eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy 267eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy while (mSize > targetSize) { 268eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy mCache.removeOldest(); 269eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy } 270eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy} 271eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy 272d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craikvoid TextureCache::generateTexture(const SkBitmap* bitmap, Texture* texture, bool regenerate) { 273c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy SkAutoLockPixels alp(*bitmap); 2749aaa8269a3e7291aab84d01c3fc9c744d8f2d2f4Romain Guy 275c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy if (!bitmap->readyToDraw()) { 2763762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Cannot generate texture from bitmap"); 277c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy return; 278c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy } 279c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy 28070850ea258cbf91477efa57a1f1a23cc0044cc93Chris Craik ATRACE_FORMAT("Upload %ux%u Texture", bitmap->width(), bitmap->height()); 281ec4cefc152749f9805d3a971a4a395687b5a3831John Reck 28252439570800891345981c0968b513843edc2b27aRomain Guy // We could also enable mipmapping if both bitmap dimensions are powers 28352439570800891345981c0968b513843edc2b27aRomain Guy // of 2 but we'd have to deal with size changes. Let's keep this simple 2843bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy const bool canMipMap = Extensions::getInstance().hasNPot(); 28552439570800891345981c0968b513843edc2b27aRomain Guy 286713e1bb9df6bdfc21bd5c40d1a6ecf6c822a4be5Romain Guy // If the texture had mipmap enabled but not anymore, 287713e1bb9df6bdfc21bd5c40d1a6ecf6c822a4be5Romain Guy // force a glTexImage2D to discard the mipmap levels 28829d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy const bool resize = !regenerate || bitmap->width() != int(texture->width) || 289713e1bb9df6bdfc21bd5c40d1a6ecf6c822a4be5Romain Guy bitmap->height() != int(texture->height) || 29052439570800891345981c0968b513843edc2b27aRomain Guy (regenerate && canMipMap && texture->mipMap && !bitmap->hasHardwareMipMap()); 291fe8809471a40cac8acc984adfa51c39e13e83947Romain Guy 2928c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy if (!regenerate) { 293fe8809471a40cac8acc984adfa51c39e13e83947Romain Guy glGenTextures(1, &texture->id); 294fe8809471a40cac8acc984adfa51c39e13e83947Romain Guy } 295ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 2968c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy texture->generation = bitmap->getGenerationID(); 2978c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy texture->width = bitmap->width(); 2988c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy texture->height = bitmap->height(); 2998c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy 3008aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy Caches::getInstance().bindTexture(texture->id); 301ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 3021103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed switch (bitmap->colorType()) { 3031103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed case kAlpha_8_SkColorType: 304d43b22da291fd08017fac627561091a633c85807Romain Guy glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 305c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua uploadToTexture(resize, GL_ALPHA, bitmap->rowBytesAsPixels(), bitmap->bytesPerPixel(), 306318ae7bb92869d99a05388c598ad105e7aa4cdbdRomain Guy texture->width, texture->height, GL_UNSIGNED_BYTE, bitmap->getPixels()); 3078c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy texture->blend = true; 308bd0e6aa0ff0bd8b376772c3e23513a6021bdda87Romain Guy break; 3091103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed case kRGB_565_SkColorType: 310d43b22da291fd08017fac627561091a633c85807Romain Guy glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel()); 311c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua uploadToTexture(resize, GL_RGB, bitmap->rowBytesAsPixels(), bitmap->bytesPerPixel(), 312318ae7bb92869d99a05388c598ad105e7aa4cdbdRomain Guy texture->width, texture->height, GL_UNSIGNED_SHORT_5_6_5, bitmap->getPixels()); 313c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy texture->blend = false; 314ce0537b80087a6225273040a987414b1dd081aa0Romain Guy break; 3151103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed case kN32_SkColorType: 316d43b22da291fd08017fac627561091a633c85807Romain Guy glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel()); 317c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua uploadToTexture(resize, GL_RGBA, bitmap->rowBytesAsPixels(), bitmap->bytesPerPixel(), 318318ae7bb92869d99a05388c598ad105e7aa4cdbdRomain Guy texture->width, texture->height, GL_UNSIGNED_BYTE, bitmap->getPixels()); 319e9e7fd0813f1485d20c6cd0014d59aff53c35d84Romain Guy // Do this after calling getPixels() to make sure Skia's deferred 320e9e7fd0813f1485d20c6cd0014d59aff53c35d84Romain Guy // decoding happened 321e9e7fd0813f1485d20c6cd0014d59aff53c35d84Romain Guy texture->blend = !bitmap->isOpaque(); 322ce0537b80087a6225273040a987414b1dd081aa0Romain Guy break; 3231103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed case kARGB_4444_SkColorType: 3241103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed case kIndex_8_SkColorType: 325d43b22da291fd08017fac627561091a633c85807Romain Guy glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel()); 3265b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy uploadLoFiTexture(resize, bitmap, texture->width, texture->height); 327b37cbec6d06578a72bdd9c2caa3fd964ade71c53Romain Guy texture->blend = !bitmap->isOpaque(); 3285b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy break; 329364703c6fa4aa1a7d2ef5b0c048ea2a0d57a4c40Romain Guy default: 3301103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed ALOGW("Unsupported bitmap colorType: %d", bitmap->colorType()); 331364703c6fa4aa1a7d2ef5b0c048ea2a0d57a4c40Romain Guy break; 332ce0537b80087a6225273040a987414b1dd081aa0Romain Guy } 333ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 33452439570800891345981c0968b513843edc2b27aRomain Guy if (canMipMap) { 335713e1bb9df6bdfc21bd5c40d1a6ecf6c822a4be5Romain Guy texture->mipMap = bitmap->hasHardwareMipMap(); 336713e1bb9df6bdfc21bd5c40d1a6ecf6c822a4be5Romain Guy if (texture->mipMap) { 337713e1bb9df6bdfc21bd5c40d1a6ecf6c822a4be5Romain Guy glGenerateMipmap(GL_TEXTURE_2D); 338713e1bb9df6bdfc21bd5c40d1a6ecf6c822a4be5Romain Guy } 339713e1bb9df6bdfc21bd5c40d1a6ecf6c822a4be5Romain Guy } 340713e1bb9df6bdfc21bd5c40d1a6ecf6c822a4be5Romain Guy 341d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy if (!regenerate) { 342d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy texture->setFilter(GL_NEAREST); 343d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy texture->setWrap(GL_CLAMP_TO_EDGE); 344d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy } 345ce0537b80087a6225273040a987414b1dd081aa0Romain Guy} 346ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 347d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craikvoid TextureCache::uploadLoFiTexture(bool resize, const SkBitmap* bitmap, 3487adaf3d1aa18c7e521f7154e545fe52d329763c3Romain Guy uint32_t width, uint32_t height) { 3497adaf3d1aa18c7e521f7154e545fe52d329763c3Romain Guy SkBitmap rgbaBitmap; 350b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed rgbaBitmap.allocPixels(SkImageInfo::MakeN32(width, height, bitmap->alphaType())); 3517adaf3d1aa18c7e521f7154e545fe52d329763c3Romain Guy rgbaBitmap.eraseColor(0); 3527adaf3d1aa18c7e521f7154e545fe52d329763c3Romain Guy 3537adaf3d1aa18c7e521f7154e545fe52d329763c3Romain Guy SkCanvas canvas(rgbaBitmap); 3547adaf3d1aa18c7e521f7154e545fe52d329763c3Romain Guy canvas.drawBitmap(*bitmap, 0.0f, 0.0f, NULL); 3557adaf3d1aa18c7e521f7154e545fe52d329763c3Romain Guy 356c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua uploadToTexture(resize, GL_RGBA, rgbaBitmap.rowBytesAsPixels(), rgbaBitmap.bytesPerPixel(), 357c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua width, height, GL_UNSIGNED_BYTE, rgbaBitmap.getPixels()); 3587adaf3d1aa18c7e521f7154e545fe52d329763c3Romain Guy} 3597adaf3d1aa18c7e521f7154e545fe52d329763c3Romain Guy 360c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghuavoid TextureCache::uploadToTexture(bool resize, GLenum format, GLsizei stride, GLsizei bpp, 361318ae7bb92869d99a05388c598ad105e7aa4cdbdRomain Guy GLsizei width, GLsizei height, GLenum type, const GLvoid * data) { 362318ae7bb92869d99a05388c598ad105e7aa4cdbdRomain Guy const bool useStride = stride != width && Extensions::getInstance().hasUnpackRowLength(); 363c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua if ((stride == width) || useStride) { 364c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua if (useStride) { 365c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua glPixelStorei(GL_UNPACK_ROW_LENGTH, stride); 366c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua } 367318ae7bb92869d99a05388c598ad105e7aa4cdbdRomain Guy 368c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua if (resize) { 369c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, type, data); 370c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua } else { 371c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, data); 372c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua } 373318ae7bb92869d99a05388c598ad105e7aa4cdbdRomain Guy 374c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua if (useStride) { 375c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); 376c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua } 3778c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy } else { 378c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua // With OpenGL ES 2.0 we need to copy the bitmap in a temporary buffer 379c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua // if the stride doesn't match the width 380c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua 381c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua GLvoid * temp = (GLvoid *) malloc(width * height * bpp); 382c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua if (!temp) return; 383c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua 384c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua uint8_t * pDst = (uint8_t *)temp; 385c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua uint8_t * pSrc = (uint8_t *)data; 386c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua for (GLsizei i = 0; i < height; i++) { 387c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua memcpy(pDst, pSrc, width * bpp); 388c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua pDst += width * bpp; 389c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua pSrc += stride * bpp; 390c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua } 391c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua 392c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua if (resize) { 393c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, type, temp); 394c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua } else { 395c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, temp); 396c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua } 397318ae7bb92869d99a05388c598ad105e7aa4cdbdRomain Guy 398c5e0a295418a1fd8c17608041962d70296af6794Lu, Shenghua free(temp); 399318ae7bb92869d99a05388c598ad105e7aa4cdbdRomain Guy } 4008c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy} 4018c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy 402ce0537b80087a6225273040a987414b1dd081aa0Romain Guy}; // namespace uirenderer 403ce0537b80087a6225273040a987414b1dd081aa0Romain Guy}; // namespace android 404