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():
37fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy        mCache(GenerationCache<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):
616c81893c626499e58c8eeb20d6c35ec4e1ce808bRomain Guy        mCache(GenerationCache<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
22252439570800891345981c0968b513843edc2b27aRomain Guy    const bool canMipMap = Caches::getInstance().extensions.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