2 * Copyright (C) 2010 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.gallery3d.glrenderer;
19 import android.util.Log;
21 import com.android.gallery3d.common.Utils;
23 import java.util.WeakHashMap;
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 {
30 private static final String TAG = "BasicTexture";
31 protected static final int UNSPECIFIED = -1;
33 protected static final int STATE_UNLOADED = 0;
34 protected static final int STATE_LOADED = 1;
35 protected static final int STATE_ERROR = -1;
37 // Log a warning if a texture is larger along a dimension
38 private static final int MAX_TEXTURE_SIZE = 4096;
40 protected int mId = -1;
43 protected int mWidth = UNSPECIFIED;
44 protected int mHeight = UNSPECIFIED;
46 protected int mTextureWidth;
47 protected int mTextureHeight;
49 private boolean mHasBorder;
51 protected GLCanvas mCanvasRef = null;
52 private static WeakHashMap<BasicTexture, Object> sAllTextures
53 = new WeakHashMap<BasicTexture, Object>();
54 private static ThreadLocal sInFinalizer = new ThreadLocal();
56 protected BasicTexture(GLCanvas canvas, int id, int state) {
57 setAssociatedCanvas(canvas);
60 synchronized (sAllTextures) {
61 sAllTextures.put(this, null);
65 protected BasicTexture() {
66 this(null, 0, STATE_UNLOADED);
69 protected void setAssociatedCanvas(GLCanvas canvas) {
74 * Sets the content size of this texture. In OpenGL, the actual texture
75 * size must be of power of 2, the size of the content may be smaller.
77 public void setSize(int width, int height) {
80 mTextureWidth = width > 0 ? Utils.nextPowerOf2(width) : 0;
81 mTextureHeight = height > 0 ? Utils.nextPowerOf2(height) : 0;
82 if (mTextureWidth > MAX_TEXTURE_SIZE || mTextureHeight > MAX_TEXTURE_SIZE) {
83 Log.w(TAG, String.format("texture is too large: %d x %d",
84 mTextureWidth, mTextureHeight), new Exception());
88 public boolean isFlippedVertically() {
97 public int getWidth() {
102 public int getHeight() {
106 // Returns the width rounded to the next power of 2.
107 public int getTextureWidth() {
108 return mTextureWidth;
111 // Returns the height rounded to the next power of 2.
112 public int getTextureHeight() {
113 return mTextureHeight;
116 // Returns true if the texture has one pixel transparent border around the
117 // actual content. This is used to avoid jigged edges.
119 // The jigged edges appear because we use GL_CLAMP_TO_EDGE for texture wrap
120 // mode (GL_CLAMP is not available in OpenGL ES), so a pixel partially
121 // covered by the texture will use the color of the edge texel. If we add
122 // the transparent border, the color of the edge texel will be mixed with
123 // appropriate amount of transparent.
125 // Currently our background is black, so we can draw the thumbnails without
126 // enabling blending.
127 public boolean hasBorder() {
131 protected void setBorder(boolean hasBorder) {
132 mHasBorder = hasBorder;
136 public void draw(GLCanvas canvas, int x, int y) {
137 canvas.drawTexture(this, x, y, getWidth(), getHeight());
141 public void draw(GLCanvas canvas, int x, int y, int w, int h) {
142 canvas.drawTexture(this, x, y, w, h);
145 // onBind is called before GLCanvas binds this texture.
146 // It should make sure the data is uploaded to GL memory.
147 abstract protected boolean onBind(GLCanvas canvas);
149 // Returns the GL texture target for this texture (e.g. GL_TEXTURE_2D).
150 abstract protected int getTarget();
152 public boolean isLoaded() {
153 return mState == STATE_LOADED;
156 // recycle() is called when the texture will never be used again,
157 // so it can free all resources.
158 public void recycle() {
162 // yield() is called when the texture will not be used temporarily,
163 // so it can free some resources.
164 // The default implementation unloads the texture from GL memory, so
165 // the subclass should make sure it can reload the texture to GL memory
166 // later, or it will have to override this method.
167 public void yield() {
171 private void freeResource() {
172 GLCanvas canvas = mCanvasRef;
173 if (canvas != null && mId != -1) {
174 canvas.unloadTexture(this);
175 mId = -1; // Don't free it again.
177 mState = STATE_UNLOADED;
178 setAssociatedCanvas(null);
182 protected void finalize() {
183 sInFinalizer.set(BasicTexture.class);
185 sInFinalizer.set(null);
188 // This is for deciding if we can call Bitmap's recycle().
189 // We cannot call Bitmap's recycle() in finalizer because at that point
190 // the finalizer of Bitmap may already be called so recycle() will crash.
191 public static boolean inFinalizer() {
192 return sInFinalizer.get() != null;
195 public static void yieldAllTextures() {
196 synchronized (sAllTextures) {
197 for (BasicTexture t : sAllTextures.keySet()) {
203 public static void invalidateAllTextures() {
204 synchronized (sAllTextures) {
205 for (BasicTexture t : sAllTextures.keySet()) {
206 t.mState = STATE_UNLOADED;
207 t.setAssociatedCanvas(null);