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