1e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka/* 2e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Copyright (C) 2010 The Android Open Source Project 3e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * 4e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Licensed under the Apache License, Version 2.0 (the "License"); 5e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * you may not use this file except in compliance with the License. 6e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * You may obtain a copy of the License at 7e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * 8e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * http://www.apache.org/licenses/LICENSE-2.0 9e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * 10e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Unless required by applicable law or agreed to in writing, software 11e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * distributed under the License is distributed on an "AS IS" BASIS, 12e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * See the License for the specific language governing permissions and 14e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * limitations under the License. 15e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka */ 16e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 17e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkapackage com.android.gallery3d.glrenderer; 18e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 19e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.graphics.Bitmap; 20e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.graphics.Bitmap.Config; 21e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.opengl.GLUtils; 22e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 230589d8287ef05b701754dcb916cc3079c907f847Paul Duffinimport com.android.gallery3d.common.Utils; 240589d8287ef05b701754dcb916cc3079c907f847Paul Duffin 25e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport java.util.HashMap; 26e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 27e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport javax.microedition.khronos.opengles.GL11; 28e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 29e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka// UploadedTextures use a Bitmap for the content of the texture. 30e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka// 31e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka// Subclasses should implement onGetBitmap() to provide the Bitmap and 32e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka// implement onFreeBitmap(mBitmap) which will be called when the Bitmap 33e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka// is not needed anymore. 34e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka// 35e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka// isContentValid() is meaningful only when the isLoaded() returns true. 36e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka// It means whether the content needs to be updated. 37e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka// 38e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka// The user of this class should call recycle() when the texture is not 39e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka// needed anymore. 40e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka// 41e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka// By default an UploadedTexture is opaque (so it can be drawn faster without 42e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka// blending). The user or subclass can override it using setOpaque(). 43e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkapublic abstract class UploadedTexture extends BasicTexture { 44e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 45e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // To prevent keeping allocation the borders, we store those used borders here. 46e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Since the length will be power of two, it won't use too much memory. 47e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static HashMap<BorderKey, Bitmap> sBorderLines = 48e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka new HashMap<BorderKey, Bitmap>(); 49e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static BorderKey sBorderKey = new BorderKey(); 50e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 51e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @SuppressWarnings("unused") 52e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final String TAG = "Texture"; 53e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private boolean mContentValid = true; 54e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 55e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // indicate this textures is being uploaded in background 56e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private boolean mIsUploading = false; 57e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private boolean mOpaque = true; 58e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private boolean mThrottled = false; 59e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static int sUploadedCount; 60e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final int UPLOAD_LIMIT = 100; 61e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 62e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected Bitmap mBitmap; 63e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private int mBorder; 64e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 65e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected UploadedTexture() { 66e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka this(false); 67e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 68e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 69e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected UploadedTexture(boolean hasBorder) { 70e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka super(null, 0, STATE_UNLOADED); 71e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (hasBorder) { 72e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka setBorder(true); 73e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mBorder = 1; 74e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 75e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 76e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 77e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected void setIsUploading(boolean uploading) { 78e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mIsUploading = uploading; 79e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 80e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 81e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public boolean isUploading() { 82e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return mIsUploading; 83e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 84e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 85e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static class BorderKey implements Cloneable { 86e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public boolean vertical; 87e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public Config config; 88e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public int length; 89e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 90e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 91e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public int hashCode() { 92e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int x = config.hashCode() ^ length; 93e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return vertical ? x : -x; 94e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 95e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 96e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 97e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public boolean equals(Object object) { 98e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (!(object instanceof BorderKey)) return false; 99e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka BorderKey o = (BorderKey) object; 100e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return vertical == o.vertical 101e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka && config == o.config && length == o.length; 102e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 103e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 104e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 105e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public BorderKey clone() { 106e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka try { 107e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return (BorderKey) super.clone(); 108e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } catch (CloneNotSupportedException e) { 109e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka throw new AssertionError(e); 110e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 111e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 112e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 113e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 114e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected void setThrottled(boolean throttled) { 115e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mThrottled = throttled; 116e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 117e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 118e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static Bitmap getBorderLine( 119e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka boolean vertical, Config config, int length) { 120e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka BorderKey key = sBorderKey; 121e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka key.vertical = vertical; 122e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka key.config = config; 123e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka key.length = length; 124e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Bitmap bitmap = sBorderLines.get(key); 125e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (bitmap == null) { 126e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka bitmap = vertical 127e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka ? Bitmap.createBitmap(1, length, config) 128e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka : Bitmap.createBitmap(length, 1, config); 129e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka sBorderLines.put(key.clone(), bitmap); 130e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 131e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return bitmap; 132e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 133e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 134e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private Bitmap getBitmap() { 135e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (mBitmap == null) { 136e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mBitmap = onGetBitmap(); 137e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int w = mBitmap.getWidth() + mBorder * 2; 138e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int h = mBitmap.getHeight() + mBorder * 2; 139e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (mWidth == UNSPECIFIED) { 140e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka setSize(w, h); 141e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 142e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 143e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return mBitmap; 144e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 145e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 146e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private void freeBitmap() { 1470589d8287ef05b701754dcb916cc3079c907f847Paul Duffin Utils.assertTrue(mBitmap != null); 148e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka onFreeBitmap(mBitmap); 149e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mBitmap = null; 150e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 151e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 152e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 153e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public int getWidth() { 154e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (mWidth == UNSPECIFIED) getBitmap(); 155e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return mWidth; 156e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 157e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 158e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 159e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public int getHeight() { 160e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (mWidth == UNSPECIFIED) getBitmap(); 161e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return mHeight; 162e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 163e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 164e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected abstract Bitmap onGetBitmap(); 165e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 166e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected abstract void onFreeBitmap(Bitmap bitmap); 167e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 168e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected void invalidateContent() { 169e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (mBitmap != null) freeBitmap(); 170e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mContentValid = false; 171e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mWidth = UNSPECIFIED; 172e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mHeight = UNSPECIFIED; 173e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 174e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 175e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka /** 176e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Whether the content on GPU is valid. 177e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka */ 178e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public boolean isContentValid() { 179e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return isLoaded() && mContentValid; 180e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 181e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 182e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka /** 183e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Updates the content on GPU's memory. 184e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * @param canvas 185e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka */ 186e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void updateContent(GLCanvas canvas) { 187e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (!isLoaded()) { 188e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (mThrottled && ++sUploadedCount > UPLOAD_LIMIT) { 189e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return; 190e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 191e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka uploadToCanvas(canvas); 192e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } else if (!mContentValid) { 193e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Bitmap bitmap = getBitmap(); 194e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int format = GLUtils.getInternalFormat(bitmap); 195e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int type = GLUtils.getType(bitmap); 196e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka canvas.texSubImage2D(this, mBorder, mBorder, bitmap, format, type); 197e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka freeBitmap(); 198e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mContentValid = true; 199e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 200e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 201e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 202e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public static void resetUploadLimit() { 203e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka sUploadedCount = 0; 204e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 205e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 206e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public static boolean uploadLimitReached() { 207e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return sUploadedCount > UPLOAD_LIMIT; 208e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 209e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 210e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private void uploadToCanvas(GLCanvas canvas) { 211e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 212e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Bitmap bitmap = getBitmap(); 213e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (bitmap != null) { 214e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka try { 215e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int bWidth = bitmap.getWidth(); 216e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int bHeight = bitmap.getHeight(); 217e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int width = bWidth + mBorder * 2; 218e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int height = bHeight + mBorder * 2; 219e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int texWidth = getTextureWidth(); 220e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int texHeight = getTextureHeight(); 221e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 2220589d8287ef05b701754dcb916cc3079c907f847Paul Duffin Utils.assertTrue(bWidth <= texWidth && bHeight <= texHeight); 223e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 224e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Upload the bitmap to a new texture. 225e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mId = canvas.getGLId().generateTexture(); 226e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka canvas.setTextureParameters(this); 227e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 228e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (bWidth == texWidth && bHeight == texHeight) { 229e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka canvas.initializeTexture(this, bitmap); 230e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } else { 231e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int format = GLUtils.getInternalFormat(bitmap); 232e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int type = GLUtils.getType(bitmap); 233e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Config config = bitmap.getConfig(); 234e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 235e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka canvas.initializeTextureSize(this, format, type); 236e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka canvas.texSubImage2D(this, mBorder, mBorder, bitmap, format, type); 237e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 238e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (mBorder > 0) { 239e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Left border 240e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Bitmap line = getBorderLine(true, config, texHeight); 241e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka canvas.texSubImage2D(this, 0, 0, line, format, type); 242e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 243e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Top border 244e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka line = getBorderLine(false, config, texWidth); 245e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka canvas.texSubImage2D(this, 0, 0, line, format, type); 246e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 247e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 248e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Right border 249e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (mBorder + bWidth < texWidth) { 250e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Bitmap line = getBorderLine(true, config, texHeight); 251e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka canvas.texSubImage2D(this, mBorder + bWidth, 0, line, format, type); 252e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 253e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 254e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Bottom border 255e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (mBorder + bHeight < texHeight) { 256e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Bitmap line = getBorderLine(false, config, texWidth); 257e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka canvas.texSubImage2D(this, 0, mBorder + bHeight, line, format, type); 258e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 259e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 260e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } finally { 261e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka freeBitmap(); 262e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 263e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Update texture state. 264e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka setAssociatedCanvas(canvas); 265e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mState = STATE_LOADED; 266e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mContentValid = true; 267e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } else { 268e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mState = STATE_ERROR; 269e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka throw new RuntimeException("Texture load fail, no bitmap"); 270e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 271e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 272e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 273e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 274e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected boolean onBind(GLCanvas canvas) { 275e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka updateContent(canvas); 276e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return isContentValid(); 277e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 278e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 279e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 280e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected int getTarget() { 281e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return GL11.GL_TEXTURE_2D; 282e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 283e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 284e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void setOpaque(boolean isOpaque) { 285e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mOpaque = isOpaque; 286e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 287e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 288e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 289e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public boolean isOpaque() { 290e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return mOpaque; 291e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 292e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 293e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 294e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void recycle() { 295e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka super.recycle(); 296e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (mBitmap != null) freeBitmap(); 297e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 298e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka} 299