1f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin/* 2f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Copyright (C) 2010 The Android Open Source Project 3f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 4f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Licensed under the Apache License, Version 2.0 (the "License"); 5f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * you may not use this file except in compliance with the License. 6f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * You may obtain a copy of the License at 7f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 8f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * http://www.apache.org/licenses/LICENSE-2.0 9f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 10f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Unless required by applicable law or agreed to in writing, software 11f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * distributed under the License is distributed on an "AS IS" BASIS, 12f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * See the License for the specific language governing permissions and 14f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * limitations under the License. 15f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */ 16f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 17a4eae1abb4f2547dfbda84301ee764ce35464881John Reckpackage com.android.gallery3d.glrenderer; 18a4eae1abb4f2547dfbda84301ee764ce35464881John Reck 19a4eae1abb4f2547dfbda84301ee764ce35464881John Reckimport android.util.Log; 20f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 21f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.common.Utils; 22f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 23f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.WeakHashMap; 24f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 25f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// BasicTexture is a Texture corresponds to a real GL texture. 26f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// The state of a BasicTexture indicates whether its data is loaded to GL memory. 27f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// If a BasicTexture is loaded into GL memory, it has a GL texture id. 28a4eae1abb4f2547dfbda84301ee764ce35464881John Reckpublic abstract class BasicTexture implements Texture { 29f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 30f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @SuppressWarnings("unused") 31f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final String TAG = "BasicTexture"; 32f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin protected static final int UNSPECIFIED = -1; 33f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 34f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin protected static final int STATE_UNLOADED = 0; 35f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin protected static final int STATE_LOADED = 1; 36f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin protected static final int STATE_ERROR = -1; 37f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 386b41f11759977c4d34755627858192b7e9cd33c7Bobby Georgescu // Log a warning if a texture is larger along a dimension 396b41f11759977c4d34755627858192b7e9cd33c7Bobby Georgescu private static final int MAX_TEXTURE_SIZE = 4096; 4049affdc4e274098a34e4eb2dbe4a89a750f1ba7fOwen Lin 417da54d7e41e04ea5122009b40de19be0724e1ca4George Mount protected int mId = -1; 42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin protected int mState; 43f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 44f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin protected int mWidth = UNSPECIFIED; 45f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin protected int mHeight = UNSPECIFIED; 46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 47a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin protected int mTextureWidth; 48a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin protected int mTextureHeight; 49f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 501a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang private boolean mHasBorder; 511a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang 523950038a697470bb8b7cd6798716aecd8285eb00Chih-Chung Chang protected GLCanvas mCanvasRef = null; 53f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static WeakHashMap<BasicTexture, Object> sAllTextures 54f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin = new WeakHashMap<BasicTexture, Object>(); 55f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static ThreadLocal sInFinalizer = new ThreadLocal(); 56f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 57f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin protected BasicTexture(GLCanvas canvas, int id, int state) { 58f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin setAssociatedCanvas(canvas); 59f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mId = id; 60f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mState = state; 61f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin synchronized (sAllTextures) { 62f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin sAllTextures.put(this, null); 63f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 64f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 65f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 66f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin protected BasicTexture() { 67f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin this(null, 0, STATE_UNLOADED); 68f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 69f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 70f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin protected void setAssociatedCanvas(GLCanvas canvas) { 713950038a697470bb8b7cd6798716aecd8285eb00Chih-Chung Chang mCanvasRef = canvas; 72f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 73f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 74f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin /** 75f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Sets the content size of this texture. In OpenGL, the actual texture 76f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * size must be of power of 2, the size of the content may be smaller. 77f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */ 78a4eae1abb4f2547dfbda84301ee764ce35464881John Reck public void setSize(int width, int height) { 79f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mWidth = width; 80f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mHeight = height; 8126353bc4c528057ae171d89ad3251586b832e69bJohn Reck mTextureWidth = width > 0 ? Utils.nextPowerOf2(width) : 0; 8226353bc4c528057ae171d89ad3251586b832e69bJohn Reck mTextureHeight = height > 0 ? Utils.nextPowerOf2(height) : 0; 8349affdc4e274098a34e4eb2dbe4a89a750f1ba7fOwen Lin if (mTextureWidth > MAX_TEXTURE_SIZE || mTextureHeight > MAX_TEXTURE_SIZE) { 8449affdc4e274098a34e4eb2dbe4a89a750f1ba7fOwen Lin Log.w(TAG, String.format("texture is too large: %d x %d", 8549affdc4e274098a34e4eb2dbe4a89a750f1ba7fOwen Lin mTextureWidth, mTextureHeight), new Exception()); 8649affdc4e274098a34e4eb2dbe4a89a750f1ba7fOwen Lin } 87f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 8944a1b22eb7098819ac0251764b9fa686d8339d66George Mount public boolean isFlippedVertically() { 9044a1b22eb7098819ac0251764b9fa686d8339d66George Mount return false; 9144a1b22eb7098819ac0251764b9fa686d8339d66George Mount } 9244a1b22eb7098819ac0251764b9fa686d8339d66George Mount 93f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int getId() { 94f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mId; 95f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 96f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 977817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @Override 98f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int getWidth() { 99f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mWidth; 100f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 101f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 1027817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @Override 103f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int getHeight() { 104f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mHeight; 105f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 106f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 107f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Returns the width rounded to the next power of 2. 108f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int getTextureWidth() { 109f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mTextureWidth; 110f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 111f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 112f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Returns the height rounded to the next power of 2. 113f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int getTextureHeight() { 114f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mTextureHeight; 1151a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang } 1161a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang 1171a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang // Returns true if the texture has one pixel transparent border around the 1181a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang // actual content. This is used to avoid jigged edges. 1191a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang // 1201a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang // The jigged edges appear because we use GL_CLAMP_TO_EDGE for texture wrap 1211a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang // mode (GL_CLAMP is not available in OpenGL ES), so a pixel partially 1221a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang // covered by the texture will use the color of the edge texel. If we add 1231a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang // the transparent border, the color of the edge texel will be mixed with 1241a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang // appropriate amount of transparent. 1251a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang // 1261a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang // Currently our background is black, so we can draw the thumbnails without 1271a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang // enabling blending. 1281a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang public boolean hasBorder() { 1291a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang return mHasBorder; 1301a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang } 1311a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang 1321a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang protected void setBorder(boolean hasBorder) { 1331a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang mHasBorder = hasBorder; 134f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 135f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 1367817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @Override 137f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void draw(GLCanvas canvas, int x, int y) { 138f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin canvas.drawTexture(this, x, y, getWidth(), getHeight()); 139f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 140f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 1417817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @Override 142f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void draw(GLCanvas canvas, int x, int y, int w, int h) { 143f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin canvas.drawTexture(this, x, y, w, h); 144f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 145f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 146f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // onBind is called before GLCanvas binds this texture. 147f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // It should make sure the data is uploaded to GL memory. 148f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin abstract protected boolean onBind(GLCanvas canvas); 149f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 150b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang // Returns the GL texture target for this texture (e.g. GL_TEXTURE_2D). 151b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang abstract protected int getTarget(); 152b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang 15337c605949219b8bf54c165c34d6405f5f2989f50Owen Lin public boolean isLoaded() { 1543950038a697470bb8b7cd6798716aecd8285eb00Chih-Chung Chang return mState == STATE_LOADED; 155f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 156f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 157f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // recycle() is called when the texture will never be used again, 158f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // so it can free all resources. 159f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void recycle() { 160f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin freeResource(); 161f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 162f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 163f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // yield() is called when the texture will not be used temporarily, 164f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // so it can free some resources. 165f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // The default implementation unloads the texture from GL memory, so 166f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // the subclass should make sure it can reload the texture to GL memory 167f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // later, or it will have to override this method. 168f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void yield() { 169f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin freeResource(); 170f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 171f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 172f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private void freeResource() { 1733950038a697470bb8b7cd6798716aecd8285eb00Chih-Chung Chang GLCanvas canvas = mCanvasRef; 1747da54d7e41e04ea5122009b40de19be0724e1ca4George Mount if (canvas != null && mId != -1) { 175f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin canvas.unloadTexture(this); 1767da54d7e41e04ea5122009b40de19be0724e1ca4George Mount mId = -1; // Don't free it again. 177f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 17837c605949219b8bf54c165c34d6405f5f2989f50Owen Lin mState = STATE_UNLOADED; 179f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin setAssociatedCanvas(null); 180f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 181f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 182f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 183f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin protected void finalize() { 184f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin sInFinalizer.set(BasicTexture.class); 185f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin recycle(); 186f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin sInFinalizer.set(null); 187f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 188f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 189f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // This is for deciding if we can call Bitmap's recycle(). 190f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // We cannot call Bitmap's recycle() in finalizer because at that point 191f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // the finalizer of Bitmap may already be called so recycle() will crash. 192f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static boolean inFinalizer() { 193f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return sInFinalizer.get() != null; 194f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 195f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 196f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static void yieldAllTextures() { 197f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin synchronized (sAllTextures) { 198f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (BasicTexture t : sAllTextures.keySet()) { 199f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin t.yield(); 200f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 201f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 202f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 2033950038a697470bb8b7cd6798716aecd8285eb00Chih-Chung Chang 2043950038a697470bb8b7cd6798716aecd8285eb00Chih-Chung Chang public static void invalidateAllTextures() { 2053950038a697470bb8b7cd6798716aecd8285eb00Chih-Chung Chang synchronized (sAllTextures) { 2063950038a697470bb8b7cd6798716aecd8285eb00Chih-Chung Chang for (BasicTexture t : sAllTextures.keySet()) { 2073950038a697470bb8b7cd6798716aecd8285eb00Chih-Chung Chang t.mState = STATE_UNLOADED; 2083950038a697470bb8b7cd6798716aecd8285eb00Chih-Chung Chang t.setAssociatedCanvas(null); 2093950038a697470bb8b7cd6798716aecd8285eb00Chih-Chung Chang } 2103950038a697470bb8b7cd6798716aecd8285eb00Chih-Chung Chang } 2113950038a697470bb8b7cd6798716aecd8285eb00Chih-Chung Chang } 212f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin} 213