TextureCache.cpp revision 3bbacf27c0be1bae4e4483577fc89ae3113abe5d
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 217adaf3d1aa18c7e521f7154e545fe52d329763c3Romain Guy#include <SkCanvas.h> 227adaf3d1aa18c7e521f7154e545fe52d329763c3Romain Guy 239aaa8269a3e7291aab84d01c3fc9c744d8f2d2f4Romain Guy#include <utils/threads.h> 249aaa8269a3e7291aab84d01c3fc9c744d8f2d2f4Romain Guy 25713e1bb9df6bdfc21bd5c40d1a6ecf6c822a4be5Romain Guy#include "Caches.h" 26ce0537b80087a6225273040a987414b1dd081aa0Romain Guy#include "TextureCache.h" 27fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy#include "Properties.h" 28ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 29ce0537b80087a6225273040a987414b1dd081aa0Romain Guynamespace android { 30ce0537b80087a6225273040a987414b1dd081aa0Romain Guynamespace uirenderer { 31ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 32121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy/////////////////////////////////////////////////////////////////////////////// 33121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy// Constructors/destructor 34121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy/////////////////////////////////////////////////////////////////////////////// 35121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 36fb8b763f762ae21923c58d64caa729b012f40e05Romain GuyTextureCache::TextureCache(): 37059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy mCache(LruCache<SkBitmap*, Texture*>::kUnlimitedCapacity), 38eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy mSize(0), mMaxSize(MB(DEFAULT_TEXTURE_CACHE_SIZE)), 39eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy mFlushRate(DEFAULT_TEXTURE_CACHE_FLUSH_RATE) { 40fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy char property[PROPERTY_VALUE_MAX]; 41fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy if (property_get(PROPERTY_TEXTURE_CACHE_SIZE, property, NULL) > 0) { 42c9855a53edfac818dc68714557185977556f849dRomain Guy INIT_LOGD(" Setting texture cache size to %sMB", property); 43fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy setMaxSize(MB(atof(property))); 44fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy } else { 45c9855a53edfac818dc68714557185977556f849dRomain Guy INIT_LOGD(" Using default texture cache size of %.2fMB", DEFAULT_TEXTURE_CACHE_SIZE); 46fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy } 47fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 48eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy if (property_get(PROPERTY_TEXTURE_CACHE_FLUSH_RATE, property, NULL) > 0) { 49eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy float flushRate = atof(property); 50eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy INIT_LOGD(" Setting texture cache flush rate to %.2f%%", flushRate * 100.0f); 51eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy setFlushRate(flushRate); 52eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy } else { 53eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy INIT_LOGD(" Using default texture cache flush rate of %.2f%%", 54eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy DEFAULT_TEXTURE_CACHE_FLUSH_RATE * 100.0f); 55eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy } 56eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy 57fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy init(); 58fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy} 59fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 607d139ba2c331f11e9b485753cc727a0ff202f2a4Romain GuyTextureCache::TextureCache(uint32_t maxByteSize): 61059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy mCache(LruCache<SkBitmap*, Texture*>::kUnlimitedCapacity), 62121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy mSize(0), mMaxSize(maxByteSize) { 63fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy init(); 64ce0537b80087a6225273040a987414b1dd081aa0Romain Guy} 65ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 66ce0537b80087a6225273040a987414b1dd081aa0Romain GuyTextureCache::~TextureCache() { 67ce0537b80087a6225273040a987414b1dd081aa0Romain Guy mCache.clear(); 68ce0537b80087a6225273040a987414b1dd081aa0Romain Guy} 69ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 70fb8b763f762ae21923c58d64caa729b012f40e05Romain Guyvoid TextureCache::init() { 71fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy mCache.setOnEntryRemovedListener(this); 72fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 73fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize); 74f6834478b379856d3e5de92ddce7de0e6ba9fa4aRomain Guy INIT_LOGD(" Maximum texture dimension is %d pixels", mMaxTextureSize); 75e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guy 76e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guy mDebugEnabled = readDebugLevel() & kDebugCaches; 77fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy} 78fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 79121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy/////////////////////////////////////////////////////////////////////////////// 80121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy// Size management 81121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy/////////////////////////////////////////////////////////////////////////////// 82121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 837d139ba2c331f11e9b485753cc727a0ff202f2a4Romain Guyuint32_t TextureCache::getSize() { 84121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy return mSize; 85121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy} 86121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 877d139ba2c331f11e9b485753cc727a0ff202f2a4Romain Guyuint32_t TextureCache::getMaxSize() { 88121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy return mMaxSize; 89121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy} 90121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 917d139ba2c331f11e9b485753cc727a0ff202f2a4Romain Guyvoid TextureCache::setMaxSize(uint32_t maxSize) { 92121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy mMaxSize = maxSize; 93121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy while (mSize > mMaxSize) { 94121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy mCache.removeOldest(); 95121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy } 96121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy} 97121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 98eca0ca2424afc1e98912405906edfc32f7733e16Romain Guyvoid TextureCache::setFlushRate(float flushRate) { 99eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy mFlushRate = fmaxf(0.0f, fminf(1.0f, flushRate)); 100eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy} 101eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy 102121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy/////////////////////////////////////////////////////////////////////////////// 103121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy// Callbacks 104121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy/////////////////////////////////////////////////////////////////////////////// 105121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 106dda570201ac851dd85af3861f7e575721d3345daRomain Guyvoid TextureCache::operator()(SkBitmap*& bitmap, Texture*& texture) { 1079aaa8269a3e7291aab84d01c3fc9c744d8f2d2f4Romain Guy // This will be called already locked 108121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy if (texture) { 1099aaa8269a3e7291aab84d01c3fc9c744d8f2d2f4Romain Guy mSize -= texture->bitmapSize; 1109e10841c27d973b930e1b49a099c69d866659505Romain Guy TEXTURE_LOGD("TextureCache::callback: name, removed size, mSize = %d, %d, %d", 1119e10841c27d973b930e1b49a099c69d866659505Romain Guy texture->id, texture->bitmapSize, mSize); 112e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guy if (mDebugEnabled) { 1135baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("Texture deleted, size = %d", texture->bitmapSize); 114e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guy } 115121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy glDeleteTextures(1, &texture->id); 116121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy delete texture; 117ce0537b80087a6225273040a987414b1dd081aa0Romain Guy } 118ce0537b80087a6225273040a987414b1dd081aa0Romain Guy} 119ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 120121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy/////////////////////////////////////////////////////////////////////////////// 121121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy// Caching 122121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy/////////////////////////////////////////////////////////////////////////////// 123121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 124ce0537b80087a6225273040a987414b1dd081aa0Romain GuyTexture* TextureCache::get(SkBitmap* bitmap) { 125ce0537b80087a6225273040a987414b1dd081aa0Romain Guy Texture* texture = mCache.get(bitmap); 126a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy 127ce0537b80087a6225273040a987414b1dd081aa0Romain Guy if (!texture) { 1289cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy if (bitmap->width() > mMaxTextureSize || bitmap->height() > mMaxTextureSize) { 1298564c8da817a845353d213acd8636b76f567b234Steve Block ALOGW("Bitmap too large to be uploaded into a texture (%dx%d, max=%dx%d)", 1308f9a9f61ab793d9387a5942b307e74324704893bRomain Guy bitmap->width(), bitmap->height(), mMaxTextureSize, mMaxTextureSize); 1319cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy return NULL; 1329cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy } 1339cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy 1347d139ba2c331f11e9b485753cc727a0ff202f2a4Romain Guy const uint32_t size = bitmap->rowBytes() * bitmap->height(); 135121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy // Don't even try to cache a bitmap that's bigger than the cache 136121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy if (size < mMaxSize) { 137121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy while (mSize + size > mMaxSize) { 138121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy mCache.removeOldest(); 139121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy } 140121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy } 141121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 142364703c6fa4aa1a7d2ef5b0c048ea2a0d57a4c40Romain Guy texture = new Texture; 1439aaa8269a3e7291aab84d01c3fc9c744d8f2d2f4Romain Guy texture->bitmapSize = size; 144c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy generateTexture(bitmap, texture, false); 145121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 146121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy if (size < mMaxSize) { 147121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy mSize += size; 1489e10841c27d973b930e1b49a099c69d866659505Romain Guy TEXTURE_LOGD("TextureCache::get: create texture(%p): name, size, mSize = %d, %d, %d", 1499e10841c27d973b930e1b49a099c69d866659505Romain Guy bitmap, texture->id, size, mSize); 150e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guy if (mDebugEnabled) { 1515baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("Texture created, size = %d", size); 152e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guy } 153121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy mCache.put(bitmap, texture); 15422158e139a3d6c6a9787ca0de224e9368f643284Romain Guy } else { 15522158e139a3d6c6a9787ca0de224e9368f643284Romain Guy texture->cleanup = true; 156121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy } 157fe8809471a40cac8acc984adfa51c39e13e83947Romain Guy } else if (bitmap->getGenerationID() != texture->generation) { 158fe8809471a40cac8acc984adfa51c39e13e83947Romain Guy generateTexture(bitmap, texture, true); 159ce0537b80087a6225273040a987414b1dd081aa0Romain Guy } 16022158e139a3d6c6a9787ca0de224e9368f643284Romain Guy 161ce0537b80087a6225273040a987414b1dd081aa0Romain Guy return texture; 162ce0537b80087a6225273040a987414b1dd081aa0Romain Guy} 163ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 164e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain GuyTexture* TextureCache::getTransient(SkBitmap* bitmap) { 165e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy Texture* texture = new Texture; 166e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy texture->bitmapSize = bitmap->rowBytes() * bitmap->height(); 167e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy texture->cleanup = true; 168e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy 169e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy generateTexture(bitmap, texture, false); 170e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy 171e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy return texture; 172e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy} 173e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy 174121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guyvoid TextureCache::remove(SkBitmap* bitmap) { 175121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy mCache.remove(bitmap); 176ce0537b80087a6225273040a987414b1dd081aa0Romain Guy} 177ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 178fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guyvoid TextureCache::removeDeferred(SkBitmap* bitmap) { 1799aaa8269a3e7291aab84d01c3fc9c744d8f2d2f4Romain Guy Mutex::Autolock _l(mLock); 180fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy mGarbage.push(bitmap); 181fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy} 182fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy 183fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guyvoid TextureCache::clearGarbage() { 184fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy Mutex::Autolock _l(mLock); 185fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy size_t count = mGarbage.size(); 186fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy for (size_t i = 0; i < count; i++) { 187fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy mCache.remove(mGarbage.itemAt(i)); 188fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy } 189fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy mGarbage.clear(); 190fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy} 191fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy 192fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guyvoid TextureCache::clear() { 193ce0537b80087a6225273040a987414b1dd081aa0Romain Guy mCache.clear(); 194912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy TEXTURE_LOGD("TextureCache:clear(), mSize = %d", mSize); 195ce0537b80087a6225273040a987414b1dd081aa0Romain Guy} 196ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 197eca0ca2424afc1e98912405906edfc32f7733e16Romain Guyvoid TextureCache::flush() { 198eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy if (mFlushRate >= 1.0f || mCache.size() == 0) return; 199eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy if (mFlushRate <= 0.0f) { 200eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy clear(); 201eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy return; 202eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy } 203eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy 204eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy uint32_t targetSize = uint32_t(mSize * mFlushRate); 205eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy TEXTURE_LOGD("TextureCache::flush: target size: %d", targetSize); 206eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy 207eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy while (mSize > targetSize) { 208eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy mCache.removeOldest(); 209eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy } 210eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy} 211eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy 212fe8809471a40cac8acc984adfa51c39e13e83947Romain Guyvoid TextureCache::generateTexture(SkBitmap* bitmap, Texture* texture, bool regenerate) { 213c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy SkAutoLockPixels alp(*bitmap); 2149aaa8269a3e7291aab84d01c3fc9c744d8f2d2f4Romain Guy 215c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy if (!bitmap->readyToDraw()) { 2163762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Cannot generate texture from bitmap"); 217c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy return; 218c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy } 219c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy 22052439570800891345981c0968b513843edc2b27aRomain Guy // We could also enable mipmapping if both bitmap dimensions are powers 22152439570800891345981c0968b513843edc2b27aRomain Guy // of 2 but we'd have to deal with size changes. Let's keep this simple 2223bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy const bool canMipMap = Extensions::getInstance().hasNPot(); 22352439570800891345981c0968b513843edc2b27aRomain Guy 224713e1bb9df6bdfc21bd5c40d1a6ecf6c822a4be5Romain Guy // If the texture had mipmap enabled but not anymore, 225713e1bb9df6bdfc21bd5c40d1a6ecf6c822a4be5Romain Guy // force a glTexImage2D to discard the mipmap levels 22629d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy const bool resize = !regenerate || bitmap->width() != int(texture->width) || 227713e1bb9df6bdfc21bd5c40d1a6ecf6c822a4be5Romain Guy bitmap->height() != int(texture->height) || 22852439570800891345981c0968b513843edc2b27aRomain Guy (regenerate && canMipMap && texture->mipMap && !bitmap->hasHardwareMipMap()); 229fe8809471a40cac8acc984adfa51c39e13e83947Romain Guy 2308c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy if (!regenerate) { 231fe8809471a40cac8acc984adfa51c39e13e83947Romain Guy glGenTextures(1, &texture->id); 232fe8809471a40cac8acc984adfa51c39e13e83947Romain Guy } 233ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 2348c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy texture->generation = bitmap->getGenerationID(); 2358c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy texture->width = bitmap->width(); 2368c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy texture->height = bitmap->height(); 2378c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy 238ce0537b80087a6225273040a987414b1dd081aa0Romain Guy glBindTexture(GL_TEXTURE_2D, texture->id); 239ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 240ce0537b80087a6225273040a987414b1dd081aa0Romain Guy switch (bitmap->getConfig()) { 241bd0e6aa0ff0bd8b376772c3e23513a6021bdda87Romain Guy case SkBitmap::kA8_Config: 242d43b22da291fd08017fac627561091a633c85807Romain Guy glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 2438c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy uploadToTexture(resize, GL_ALPHA, bitmap->rowBytesAsPixels(), texture->height, 2448c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy GL_UNSIGNED_BYTE, bitmap->getPixels()); 2458c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy texture->blend = true; 246bd0e6aa0ff0bd8b376772c3e23513a6021bdda87Romain Guy break; 247ce0537b80087a6225273040a987414b1dd081aa0Romain Guy case SkBitmap::kRGB_565_Config: 248d43b22da291fd08017fac627561091a633c85807Romain Guy glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel()); 2498c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy uploadToTexture(resize, GL_RGB, bitmap->rowBytesAsPixels(), texture->height, 2508c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy GL_UNSIGNED_SHORT_5_6_5, bitmap->getPixels()); 251c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy texture->blend = false; 252ce0537b80087a6225273040a987414b1dd081aa0Romain Guy break; 253ce0537b80087a6225273040a987414b1dd081aa0Romain Guy case SkBitmap::kARGB_8888_Config: 254d43b22da291fd08017fac627561091a633c85807Romain Guy glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel()); 2558c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy uploadToTexture(resize, GL_RGBA, bitmap->rowBytesAsPixels(), texture->height, 2568c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy GL_UNSIGNED_BYTE, bitmap->getPixels()); 257e9e7fd0813f1485d20c6cd0014d59aff53c35d84Romain Guy // Do this after calling getPixels() to make sure Skia's deferred 258e9e7fd0813f1485d20c6cd0014d59aff53c35d84Romain Guy // decoding happened 259e9e7fd0813f1485d20c6cd0014d59aff53c35d84Romain Guy texture->blend = !bitmap->isOpaque(); 260ce0537b80087a6225273040a987414b1dd081aa0Romain Guy break; 2615b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy case SkBitmap::kARGB_4444_Config: 262b37cbec6d06578a72bdd9c2caa3fd964ade71c53Romain Guy case SkBitmap::kIndex8_Config: 263d43b22da291fd08017fac627561091a633c85807Romain Guy glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel()); 2645b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy uploadLoFiTexture(resize, bitmap, texture->width, texture->height); 265b37cbec6d06578a72bdd9c2caa3fd964ade71c53Romain Guy texture->blend = !bitmap->isOpaque(); 2665b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy break; 267364703c6fa4aa1a7d2ef5b0c048ea2a0d57a4c40Romain Guy default: 2688564c8da817a845353d213acd8636b76f567b234Steve Block ALOGW("Unsupported bitmap config: %d", bitmap->getConfig()); 269364703c6fa4aa1a7d2ef5b0c048ea2a0d57a4c40Romain Guy break; 270ce0537b80087a6225273040a987414b1dd081aa0Romain Guy } 271ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 27252439570800891345981c0968b513843edc2b27aRomain Guy if (canMipMap) { 273713e1bb9df6bdfc21bd5c40d1a6ecf6c822a4be5Romain Guy texture->mipMap = bitmap->hasHardwareMipMap(); 274713e1bb9df6bdfc21bd5c40d1a6ecf6c822a4be5Romain Guy if (texture->mipMap) { 275713e1bb9df6bdfc21bd5c40d1a6ecf6c822a4be5Romain Guy glGenerateMipmap(GL_TEXTURE_2D); 276713e1bb9df6bdfc21bd5c40d1a6ecf6c822a4be5Romain Guy } 277713e1bb9df6bdfc21bd5c40d1a6ecf6c822a4be5Romain Guy } 278713e1bb9df6bdfc21bd5c40d1a6ecf6c822a4be5Romain Guy 279d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy if (!regenerate) { 280d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy texture->setFilter(GL_NEAREST); 281d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy texture->setWrap(GL_CLAMP_TO_EDGE); 282d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy } 283ce0537b80087a6225273040a987414b1dd081aa0Romain Guy} 284ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 2855b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guyvoid TextureCache::uploadLoFiTexture(bool resize, SkBitmap* bitmap, 2867adaf3d1aa18c7e521f7154e545fe52d329763c3Romain Guy uint32_t width, uint32_t height) { 2877adaf3d1aa18c7e521f7154e545fe52d329763c3Romain Guy SkBitmap rgbaBitmap; 2887adaf3d1aa18c7e521f7154e545fe52d329763c3Romain Guy rgbaBitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height); 2897adaf3d1aa18c7e521f7154e545fe52d329763c3Romain Guy rgbaBitmap.allocPixels(); 2907adaf3d1aa18c7e521f7154e545fe52d329763c3Romain Guy rgbaBitmap.eraseColor(0); 291b37cbec6d06578a72bdd9c2caa3fd964ade71c53Romain Guy rgbaBitmap.setIsOpaque(bitmap->isOpaque()); 2927adaf3d1aa18c7e521f7154e545fe52d329763c3Romain Guy 2937adaf3d1aa18c7e521f7154e545fe52d329763c3Romain Guy SkCanvas canvas(rgbaBitmap); 2947adaf3d1aa18c7e521f7154e545fe52d329763c3Romain Guy canvas.drawBitmap(*bitmap, 0.0f, 0.0f, NULL); 2957adaf3d1aa18c7e521f7154e545fe52d329763c3Romain Guy 2967adaf3d1aa18c7e521f7154e545fe52d329763c3Romain Guy uploadToTexture(resize, GL_RGBA, rgbaBitmap.rowBytesAsPixels(), height, 2977adaf3d1aa18c7e521f7154e545fe52d329763c3Romain Guy GL_UNSIGNED_BYTE, rgbaBitmap.getPixels()); 2987adaf3d1aa18c7e521f7154e545fe52d329763c3Romain Guy} 2997adaf3d1aa18c7e521f7154e545fe52d329763c3Romain Guy 3008c749f87d29e1a363ddf9027c3a51753c612d510Romain Guyvoid TextureCache::uploadToTexture(bool resize, GLenum format, GLsizei width, GLsizei height, 3018c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy GLenum type, const GLvoid * data) { 3028c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy if (resize) { 3038c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, type, data); 3048c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy } else { 3058c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, data); 3068c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy } 3078c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy} 3088c749f87d29e1a363ddf9027c3a51753c612d510Romain Guy 309ce0537b80087a6225273040a987414b1dd081aa0Romain Guy}; // namespace uirenderer 310ce0537b80087a6225273040a987414b1dd081aa0Romain Guy}; // namespace android 311