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 17f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpackage com.android.gallery3d.ui; 18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 19f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.graphics.Bitmap; 20f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.graphics.Bitmap.Config; 21f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.opengl.GLUtils; 22f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 232b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport com.android.gallery3d.common.Utils; 242b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Lin 25f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.HashMap; 262b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Lin 27f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport javax.microedition.khronos.opengles.GL11; 28f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport javax.microedition.khronos.opengles.GL11Ext; 29f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 30f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// UploadedTextures use a Bitmap for the content of the texture. 31f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// 32f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// Subclasses should implement onGetBitmap() to provide the Bitmap and 33f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// implement onFreeBitmap(mBitmap) which will be called when the Bitmap 34f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// is not needed anymore. 35f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// 36f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// isContentValid() is meaningful only when the isLoaded() returns true. 37f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// It means whether the content needs to be updated. 38f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// 39f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// The user of this class should call recycle() when the texture is not 40f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// needed anymore. 41f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// 42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// By default an UploadedTexture is opaque (so it can be drawn faster without 43f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// blending). The user or subclass can override it using setOpaque(). 44f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linabstract class UploadedTexture extends BasicTexture { 45f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // To prevent keeping allocation the borders, we store those used borders here. 47f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Since the length will be power of two, it won't use too much memory. 48f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static HashMap<BorderKey, Bitmap> sBorderLines = 49f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin new HashMap<BorderKey, Bitmap>(); 50f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static BorderKey sBorderKey = new BorderKey(); 51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 52f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @SuppressWarnings("unused") 53f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final String TAG = "Texture"; 54f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private boolean mContentValid = true; 5537c605949219b8bf54c165c34d6405f5f2989f50Owen Lin 5637c605949219b8bf54c165c34d6405f5f2989f50Owen Lin // indicate this textures is being uploaded in background 5737c605949219b8bf54c165c34d6405f5f2989f50Owen Lin private boolean mIsUploading = false; 58f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private boolean mOpaque = true; 59f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private boolean mThrottled = false; 60f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static int sUploadedCount; 61f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final int UPLOAD_LIMIT = 100; 62f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 63f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin protected Bitmap mBitmap; 641a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang private int mBorder; 65f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 66f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin protected UploadedTexture() { 671a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang this(false); 681a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang } 691a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang 701a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang protected UploadedTexture(boolean hasBorder) { 71f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin super(null, 0, STATE_UNLOADED); 721a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang if (hasBorder) { 731a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang setBorder(true); 741a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang mBorder = 1; 751a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang } 76f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 77f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 7837c605949219b8bf54c165c34d6405f5f2989f50Owen Lin protected void setIsUploading(boolean uploading) { 7937c605949219b8bf54c165c34d6405f5f2989f50Owen Lin mIsUploading = uploading; 8037c605949219b8bf54c165c34d6405f5f2989f50Owen Lin } 8137c605949219b8bf54c165c34d6405f5f2989f50Owen Lin 8237c605949219b8bf54c165c34d6405f5f2989f50Owen Lin public boolean isUploading() { 8337c605949219b8bf54c165c34d6405f5f2989f50Owen Lin return mIsUploading; 8437c605949219b8bf54c165c34d6405f5f2989f50Owen Lin } 8537c605949219b8bf54c165c34d6405f5f2989f50Owen Lin 86f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static class BorderKey implements Cloneable { 87f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public boolean vertical; 88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public Config config; 89f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int length; 90f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 91f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 92f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int hashCode() { 93f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int x = config.hashCode() ^ length; 94f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return vertical ? x : -x; 95f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 96f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 97f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 98f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public boolean equals(Object object) { 99f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (!(object instanceof BorderKey)) return false; 100f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin BorderKey o = (BorderKey) object; 101f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return vertical == o.vertical 102f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin && config == o.config && length == o.length; 103f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 104f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 105f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 106f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public BorderKey clone() { 107f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 108f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return (BorderKey) super.clone(); 109f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (CloneNotSupportedException e) { 110f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin throw new AssertionError(e); 111f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 112f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 113f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 114f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 115f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin protected void setThrottled(boolean throttled) { 116f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mThrottled = throttled; 117f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 118f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 119f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static Bitmap getBorderLine( 120f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin boolean vertical, Config config, int length) { 121f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin BorderKey key = sBorderKey; 122f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin key.vertical = vertical; 123f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin key.config = config; 124f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin key.length = length; 125f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Bitmap bitmap = sBorderLines.get(key); 126f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (bitmap == null) { 127f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin bitmap = vertical 128f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin ? Bitmap.createBitmap(1, length, config) 129f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin : Bitmap.createBitmap(length, 1, config); 130f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin sBorderLines.put(key.clone(), bitmap); 131f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 132f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return bitmap; 133f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 134f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 135f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private Bitmap getBitmap() { 136f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mBitmap == null) { 137f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mBitmap = onGetBitmap(); 1381a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang int w = mBitmap.getWidth() + mBorder * 2; 1391a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang int h = mBitmap.getHeight() + mBorder * 2; 140f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mWidth == UNSPECIFIED) { 1411a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang setSize(w, h); 142f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 143f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 144f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mBitmap; 145f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 146f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 147f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private void freeBitmap() { 148f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Utils.assertTrue(mBitmap != null); 149f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin onFreeBitmap(mBitmap); 150f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mBitmap = null; 151f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 152f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 153f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 154f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int getWidth() { 155f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mWidth == UNSPECIFIED) getBitmap(); 156f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mWidth; 157f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 158f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 159f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 160f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int getHeight() { 161f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mWidth == UNSPECIFIED) getBitmap(); 162f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mHeight; 163f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 164f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 165f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin protected abstract Bitmap onGetBitmap(); 166f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 167f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin protected abstract void onFreeBitmap(Bitmap bitmap); 168f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 169f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin protected void invalidateContent() { 170f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mBitmap != null) freeBitmap(); 171f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mContentValid = false; 172cb4fb7c19f20405fb5e08513e6297dffce824118Chih-Chung Chang mWidth = UNSPECIFIED; 173cb4fb7c19f20405fb5e08513e6297dffce824118Chih-Chung Chang mHeight = UNSPECIFIED; 174f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 175f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 176f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin /** 177f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Whether the content on GPU is valid. 178f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */ 17937c605949219b8bf54c165c34d6405f5f2989f50Owen Lin public boolean isContentValid() { 18037c605949219b8bf54c165c34d6405f5f2989f50Owen Lin return isLoaded() && mContentValid; 181f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 182f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 183f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin /** 184f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Updates the content on GPU's memory. 185f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * @param canvas 186f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */ 187f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void updateContent(GLCanvas canvas) { 18837c605949219b8bf54c165c34d6405f5f2989f50Owen Lin if (!isLoaded()) { 189f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mThrottled && ++sUploadedCount > UPLOAD_LIMIT) { 190f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return; 191f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 192f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin uploadToCanvas(canvas); 193f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else if (!mContentValid) { 194f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Bitmap bitmap = getBitmap(); 195f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int format = GLUtils.getInternalFormat(bitmap); 196f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int type = GLUtils.getType(bitmap); 197f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin canvas.getGLInstance().glBindTexture(GL11.GL_TEXTURE_2D, mId); 1981a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang GLUtils.texSubImage2D(GL11.GL_TEXTURE_2D, 0, mBorder, mBorder, 1991a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang bitmap, format, type); 200f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin freeBitmap(); 201f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mContentValid = true; 202f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 203f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 204f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 205f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static void resetUploadLimit() { 206f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin sUploadedCount = 0; 207f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 208f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 209f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static boolean uploadLimitReached() { 210f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return sUploadedCount > UPLOAD_LIMIT; 211f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 212f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 213f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin static int[] sTextureId = new int[1]; 214f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin static float[] sCropRect = new float[4]; 215f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 216f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private void uploadToCanvas(GLCanvas canvas) { 217f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin GL11 gl = canvas.getGLInstance(); 218f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 219f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Bitmap bitmap = getBitmap(); 220f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (bitmap != null) { 221f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 2221a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang int bWidth = bitmap.getWidth(); 2231a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang int bHeight = bitmap.getHeight(); 2241a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang int width = bWidth + mBorder * 2; 2251a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang int height = bHeight + mBorder * 2; 2261a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang int texWidth = getTextureWidth(); 2271a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang int texHeight = getTextureHeight(); 228c2c0b01fbbf243eee1a11c33ba6dd1ce918a9ce5Owen Lin 229c2c0b01fbbf243eee1a11c33ba6dd1ce918a9ce5Owen Lin Utils.assertTrue(bWidth <= texWidth && bHeight <= texHeight); 230c2c0b01fbbf243eee1a11c33ba6dd1ce918a9ce5Owen Lin 231f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Define a vertically flipped crop rectangle for 232f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // OES_draw_texture. 2331a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang // The four values in sCropRect are: left, bottom, width, and 2341a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang // height. Negative value of width or height means flip. 2351a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang sCropRect[0] = mBorder; 2361a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang sCropRect[1] = mBorder + bHeight; 2371a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang sCropRect[2] = bWidth; 2381a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang sCropRect[3] = -bHeight; 239f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 240f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Upload the bitmap to a new texture. 241b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang GLId.glGenTextures(1, sTextureId, 0); 242f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin gl.glBindTexture(GL11.GL_TEXTURE_2D, sTextureId[0]); 243f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin gl.glTexParameterfv(GL11.GL_TEXTURE_2D, 244f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin GL11Ext.GL_TEXTURE_CROP_RECT_OES, sCropRect, 0); 245f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin gl.glTexParameteri(GL11.GL_TEXTURE_2D, 246f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP_TO_EDGE); 247f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin gl.glTexParameteri(GL11.GL_TEXTURE_2D, 248f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP_TO_EDGE); 249f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin gl.glTexParameterf(GL11.GL_TEXTURE_2D, 250f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); 251f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin gl.glTexParameterf(GL11.GL_TEXTURE_2D, 252f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); 253f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 2541a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang if (bWidth == texWidth && bHeight == texHeight) { 255f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin GLUtils.texImage2D(GL11.GL_TEXTURE_2D, 0, bitmap, 0); 256f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 257f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int format = GLUtils.getInternalFormat(bitmap); 258f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int type = GLUtils.getType(bitmap); 259f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Config config = bitmap.getConfig(); 260f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 261f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin gl.glTexImage2D(GL11.GL_TEXTURE_2D, 0, format, 2621a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang texWidth, texHeight, 0, format, type, null); 2631a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang GLUtils.texSubImage2D(GL11.GL_TEXTURE_2D, 0, 2641a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang mBorder, mBorder, bitmap, format, type); 2651a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang 2661a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang if (mBorder > 0) { 2671a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang // Left border 2681a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang Bitmap line = getBorderLine(true, config, texHeight); 2691a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang GLUtils.texSubImage2D(GL11.GL_TEXTURE_2D, 0, 2701a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang 0, 0, line, format, type); 2711a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang 2721a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang // Top border 2731a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang line = getBorderLine(false, config, texWidth); 2741a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang GLUtils.texSubImage2D(GL11.GL_TEXTURE_2D, 0, 2751a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang 0, 0, line, format, type); 276f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 277f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 2781a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang // Right border 2791a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang if (mBorder + bWidth < texWidth) { 2801a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang Bitmap line = getBorderLine(true, config, texHeight); 2811a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang GLUtils.texSubImage2D(GL11.GL_TEXTURE_2D, 0, 2821a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang mBorder + bWidth, 0, line, format, type); 283f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 284f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 2851a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang // Bottom border 2861a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang if (mBorder + bHeight < texHeight) { 2871a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang Bitmap line = getBorderLine(false, config, texWidth); 2881a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang GLUtils.texSubImage2D(GL11.GL_TEXTURE_2D, 0, 2891a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang 0, mBorder + bHeight, line, format, type); 2901a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang } 291f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 292f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } finally { 293f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin freeBitmap(); 294f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 295f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Update texture state. 296f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin setAssociatedCanvas(canvas); 297f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mId = sTextureId[0]; 29837c605949219b8bf54c165c34d6405f5f2989f50Owen Lin mState = STATE_LOADED; 299f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mContentValid = true; 300f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 301f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mState = STATE_ERROR; 302f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin throw new RuntimeException("Texture load fail, no bitmap"); 303f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 304f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 305f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 306f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 307f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin protected boolean onBind(GLCanvas canvas) { 308f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin updateContent(canvas); 30937c605949219b8bf54c165c34d6405f5f2989f50Owen Lin return isContentValid(); 310f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 311f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 312b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang @Override 313b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang protected int getTarget() { 314b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang return GL11.GL_TEXTURE_2D; 315b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang } 316b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang 317f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void setOpaque(boolean isOpaque) { 318f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mOpaque = isOpaque; 319f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 320f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 321f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public boolean isOpaque() { 322f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mOpaque; 323f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 324f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 325f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 326f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void recycle() { 327f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin super.recycle(); 328f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mBitmap != null) freeBitmap(); 329f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 330f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin} 331