1f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka/* 2f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * Copyright (C) 2010 The Android Open Source Project 3f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * 4f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * Licensed under the Apache License, Version 2.0 (the "License"); 5f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * you may not use this file except in compliance with the License. 6f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * You may obtain a copy of the License at 7f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * 8f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * http://www.apache.org/licenses/LICENSE-2.0 9f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * 10f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * Unless required by applicable law or agreed to in writing, software 11f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * distributed under the License is distributed on an "AS IS" BASIS, 12f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * See the License for the specific language governing permissions and 14f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * limitations under the License. 15f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka */ 16f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 17f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkapackage com.android.gallery3d.glrenderer; 18f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 19f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.util.Log; 20f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 21f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport com.android.gallery3d.common.Utils; 22f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 23f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport java.util.WeakHashMap; 24f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 25f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka// BasicTexture is a Texture corresponds to a real GL texture. 26f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka// The state of a BasicTexture indicates whether its data is loaded to GL memory. 27f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka// If a BasicTexture is loaded into GL memory, it has a GL texture id. 28f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkapublic abstract class BasicTexture implements Texture { 29f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 30f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka private static final String TAG = "BasicTexture"; 31f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka protected static final int UNSPECIFIED = -1; 32f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 33f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka protected static final int STATE_UNLOADED = 0; 34f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka protected static final int STATE_LOADED = 1; 35f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka protected static final int STATE_ERROR = -1; 36f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 37f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka // Log a warning if a texture is larger along a dimension 38f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka private static final int MAX_TEXTURE_SIZE = 4096; 39f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 40f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka protected int mId = -1; 41f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka protected int mState; 42f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 43f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka protected int mWidth = UNSPECIFIED; 44f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka protected int mHeight = UNSPECIFIED; 45f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 46f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka protected int mTextureWidth; 47f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka protected int mTextureHeight; 48f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 49f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka protected GLCanvas mCanvasRef = null; 50f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka private static WeakHashMap<BasicTexture, Object> sAllTextures 51f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka = new WeakHashMap<BasicTexture, Object>(); 52f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka private static ThreadLocal sInFinalizer = new ThreadLocal(); 53f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 54f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka protected BasicTexture(GLCanvas canvas, int id, int state) { 55f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka setAssociatedCanvas(canvas); 56f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka mId = id; 57f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka mState = state; 58f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka synchronized (sAllTextures) { 59f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka sAllTextures.put(this, null); 60f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka } 61f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka } 62f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 63f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka protected BasicTexture() { 64f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka this(null, 0, STATE_UNLOADED); 65f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka } 66f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 67f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka protected void setAssociatedCanvas(GLCanvas canvas) { 68f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka mCanvasRef = canvas; 69f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka } 70f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 71f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka /** 72f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * Sets the content size of this texture. In OpenGL, the actual texture 73f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * size must be of power of 2, the size of the content may be smaller. 74f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka */ 75f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka public void setSize(int width, int height) { 76f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka mWidth = width; 77f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka mHeight = height; 78f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka mTextureWidth = width > 0 ? Utils.nextPowerOf2(width) : 0; 79f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka mTextureHeight = height > 0 ? Utils.nextPowerOf2(height) : 0; 80f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka if (mTextureWidth > MAX_TEXTURE_SIZE || mTextureHeight > MAX_TEXTURE_SIZE) { 81f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka Log.w(TAG, String.format("texture is too large: %d x %d", 82f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka mTextureWidth, mTextureHeight), new Exception()); 83f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka } 84f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka } 85f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 86f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka public int getId() { 87f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka return mId; 88f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka } 89f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 90f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka @Override 91f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka public int getWidth() { 92f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka return mWidth; 93f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka } 94f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 95f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka @Override 96f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka public int getHeight() { 97f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka return mHeight; 98f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka } 99f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 100f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka // Returns the width rounded to the next power of 2. 101f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka public int getTextureWidth() { 102f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka return mTextureWidth; 103f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka } 104f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 105f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka // Returns the height rounded to the next power of 2. 106f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka public int getTextureHeight() { 107f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka return mTextureHeight; 108f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka } 109f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 110f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka @Override 111f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka public void draw(GLCanvas canvas, int x, int y) { 112f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka canvas.drawTexture(this, x, y, getWidth(), getHeight()); 113f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka } 114f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 115f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka @Override 116f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka public void draw(GLCanvas canvas, int x, int y, int w, int h) { 117f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka canvas.drawTexture(this, x, y, w, h); 118f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka } 119f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 120f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka // onBind is called before GLCanvas binds this texture. 121f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka // It should make sure the data is uploaded to GL memory. 122f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka abstract protected boolean onBind(GLCanvas canvas); 123f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 124f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka public boolean isLoaded() { 125f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka return mState == STATE_LOADED; 126f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka } 127f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 128f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka // recycle() is called when the texture will never be used again, 129f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka // so it can free all resources. 130f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka public void recycle() { 131f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka freeResource(); 132f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka } 133f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 134f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka // yield() is called when the texture will not be used temporarily, 135f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka // so it can free some resources. 136f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka // The default implementation unloads the texture from GL memory, so 137f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka // the subclass should make sure it can reload the texture to GL memory 138f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka // later, or it will have to override this method. 139f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka public void yield() { 140f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka freeResource(); 141f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka } 142f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 143f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka private void freeResource() { 144f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka GLCanvas canvas = mCanvasRef; 145f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka if (canvas != null && mId != -1) { 146f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka canvas.unloadTexture(this); 147f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka mId = -1; // Don't free it again. 148f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka } 149f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka mState = STATE_UNLOADED; 150f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka setAssociatedCanvas(null); 151f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka } 152f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 153f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka @Override 154f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka protected void finalize() { 155f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka sInFinalizer.set(BasicTexture.class); 156f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka recycle(); 157f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka sInFinalizer.set(null); 158f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka } 159f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 160f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka public static void yieldAllTextures() { 161f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka synchronized (sAllTextures) { 162f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka for (BasicTexture t : sAllTextures.keySet()) { 163f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka t.yield(); 164f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka } 165f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka } 166f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka } 167f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka 168f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka public static void invalidateAllTextures() { 169f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka synchronized (sAllTextures) { 170f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka for (BasicTexture t : sAllTextures.keySet()) { 171f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka t.mState = STATE_UNLOADED; 172f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka t.setAssociatedCanvas(null); 173f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka } 174f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka } 175f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka } 176f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka} 177