OSDN Git Service

resolved conflicts for merge of 13ef17a3 to mnc-dr-dev
[android-x86/packages-apps-Launcher3.git] / WallpaperPicker / src / com / android / gallery3d / glrenderer / BasicTexture.java
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     private boolean mHasBorder;
50
51     protected GLCanvas mCanvasRef = null;
52     private static WeakHashMap<BasicTexture, Object> sAllTextures
53             = new WeakHashMap<BasicTexture, Object>();
54     private static ThreadLocal sInFinalizer = new ThreadLocal();
55
56     protected BasicTexture(GLCanvas canvas, int id, int state) {
57         setAssociatedCanvas(canvas);
58         mId = id;
59         mState = state;
60         synchronized (sAllTextures) {
61             sAllTextures.put(this, null);
62         }
63     }
64
65     protected BasicTexture() {
66         this(null, 0, STATE_UNLOADED);
67     }
68
69     protected void setAssociatedCanvas(GLCanvas canvas) {
70         mCanvasRef = canvas;
71     }
72
73     /**
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.
76      */
77     public void setSize(int width, int height) {
78         mWidth = width;
79         mHeight = 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());
85         }
86     }
87
88     public boolean isFlippedVertically() {
89       return false;
90     }
91
92     public int getId() {
93         return mId;
94     }
95
96     @Override
97     public int getWidth() {
98         return mWidth;
99     }
100
101     @Override
102     public int getHeight() {
103         return mHeight;
104     }
105
106     // Returns the width rounded to the next power of 2.
107     public int getTextureWidth() {
108         return mTextureWidth;
109     }
110
111     // Returns the height rounded to the next power of 2.
112     public int getTextureHeight() {
113         return mTextureHeight;
114     }
115
116     // Returns true if the texture has one pixel transparent border around the
117     // actual content. This is used to avoid jigged edges.
118     //
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.
124     //
125     // Currently our background is black, so we can draw the thumbnails without
126     // enabling blending.
127     public boolean hasBorder() {
128         return mHasBorder;
129     }
130
131     protected void setBorder(boolean hasBorder) {
132         mHasBorder = hasBorder;
133     }
134
135     @Override
136     public void draw(GLCanvas canvas, int x, int y) {
137         canvas.drawTexture(this, x, y, getWidth(), getHeight());
138     }
139
140     @Override
141     public void draw(GLCanvas canvas, int x, int y, int w, int h) {
142         canvas.drawTexture(this, x, y, w, h);
143     }
144
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);
148
149     // Returns the GL texture target for this texture (e.g. GL_TEXTURE_2D).
150     abstract protected int getTarget();
151
152     public boolean isLoaded() {
153         return mState == STATE_LOADED;
154     }
155
156     // recycle() is called when the texture will never be used again,
157     // so it can free all resources.
158     public void recycle() {
159         freeResource();
160     }
161
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() {
168         freeResource();
169     }
170
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.
176         }
177         mState = STATE_UNLOADED;
178         setAssociatedCanvas(null);
179     }
180
181     @Override
182     protected void finalize() {
183         sInFinalizer.set(BasicTexture.class);
184         recycle();
185         sInFinalizer.set(null);
186     }
187
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;
193     }
194
195     public static void yieldAllTextures() {
196         synchronized (sAllTextures) {
197             for (BasicTexture t : sAllTextures.keySet()) {
198                 t.yield();
199             }
200         }
201     }
202
203     public static void invalidateAllTextures() {
204         synchronized (sAllTextures) {
205             for (BasicTexture t : sAllTextures.keySet()) {
206                 t.mState = STATE_UNLOADED;
207                 t.setAssociatedCanvas(null);
208             }
209         }
210     }
211 }