1 /* 2 * Copyright (C) 2009 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.cooliris.media; 18 19 import javax.microedition.khronos.opengles.GL11; 20 import javax.microedition.khronos.opengles.GL11Ext; 21 22 import android.graphics.Bitmap; 23 import android.graphics.Canvas; 24 import android.opengl.GLUtils; 25 26 public abstract class CanvasTexture { 27 private int mWidth; 28 private int mHeight; 29 private int mTextureId; 30 private int mTextureWidth; 31 private int mTextureHeight; 32 private float mNormalizedWidth; 33 private float mNormalizedHeight; 34 35 private final Canvas mCanvas = new Canvas(); 36 private final Bitmap.Config mBitmapConfig; 37 private Bitmap mBitmap = null; 38 private boolean mNeedsDraw = false; 39 private boolean mNeedsResize = false; 40 private GL11 mCachedGL = null; 41 CanvasTexture(Bitmap.Config bitmapConfig)42 public CanvasTexture(Bitmap.Config bitmapConfig) { 43 mBitmapConfig = bitmapConfig; 44 } 45 setNeedsDraw()46 public final void setNeedsDraw() { 47 mNeedsDraw = true; 48 } 49 getWidth()50 public final int getWidth() { 51 return mWidth; 52 } 53 getHeight()54 public final int getHeight() { 55 return mHeight; 56 } 57 getNormalizedWidth()58 public final float getNormalizedWidth() { 59 return mNormalizedWidth; 60 } 61 getNormalizedHeight()62 public final float getNormalizedHeight() { 63 return mNormalizedHeight; 64 } 65 setSize(int width, int height)66 public final void setSize(int width, int height) { 67 mWidth = width; 68 mHeight = height; 69 mNeedsResize = true; 70 mTextureWidth = -1; 71 mTextureHeight = -1; 72 onSizeChanged(); 73 } 74 resetTexture()75 public void resetTexture() { 76 // Happens when restoring the scene. Need to manage this more 77 // automatically. 78 mTextureId = 0; 79 mNeedsResize = true; 80 } 81 82 // This code seems largely a dup of CanvasLayer. bind(GL11 gl)83 public boolean bind(GL11 gl) { 84 if (mCachedGL != gl) { 85 mCachedGL = gl; 86 resetTexture(); 87 } 88 int width = (int) mWidth; 89 int height = (int) mHeight; 90 int textureId = mTextureId; 91 int textureWidth = mTextureWidth; 92 int textureHeight = mTextureHeight; 93 Canvas canvas = mCanvas; 94 Bitmap bitmap = mBitmap; 95 96 if (mNeedsResize || mTextureId == 0) { 97 // Clear the resize flag and mark as needing draw. 98 mNeedsDraw = true; 99 100 // Compute the power-of-2 padded size for the texture. 101 int newTextureWidth = Shared.nextPowerOf2(width); 102 int newTextureHeight = Shared.nextPowerOf2(height); 103 104 // Reallocate the bitmap only if the padded size has changed. 105 // TODO: reuse same texture if it is already large enough, just 106 // change clip rect. 107 if (textureWidth != newTextureWidth || textureHeight != newTextureHeight || mTextureId == 0) { 108 // Allocate a texture if needed. 109 if (textureId == 0) { 110 int[] textureIdOut = new int[1]; 111 gl.glGenTextures(1, textureIdOut, 0); 112 textureId = textureIdOut[0]; 113 mNeedsResize = false; 114 mTextureId = textureId; 115 116 // Set texture parameters. 117 gl.glBindTexture(GL11.GL_TEXTURE_2D, textureId); 118 gl.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP_TO_EDGE); 119 gl.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP_TO_EDGE); 120 gl.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); 121 gl.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); 122 } 123 124 // Set the new texture width and height. 125 textureWidth = newTextureWidth; 126 textureHeight = newTextureHeight; 127 mTextureWidth = newTextureWidth; 128 mTextureHeight = newTextureHeight; 129 mNormalizedWidth = (float) width / textureWidth; 130 mNormalizedHeight = (float) height / textureHeight; 131 132 // Recycle the existing bitmap and create a new one. 133 if (bitmap != null) 134 bitmap.recycle(); 135 if (textureWidth > 0 && textureHeight > 0) { 136 bitmap = Bitmap.createBitmap(textureWidth, textureHeight, mBitmapConfig); 137 canvas.setBitmap(bitmap); 138 mBitmap = bitmap; 139 } 140 } 141 } 142 143 // Bind the texture to the context. 144 if (textureId == 0) { 145 return false; 146 } 147 gl.glBindTexture(GL11.GL_TEXTURE_2D, textureId); 148 149 // Redraw the contents of the texture if needed. 150 if (mNeedsDraw) { 151 mNeedsDraw = false; 152 renderCanvas(canvas, bitmap, width, height); 153 int[] cropRect = { 0, height, width, -height }; 154 gl.glTexParameteriv(GL11.GL_TEXTURE_2D, GL11Ext.GL_TEXTURE_CROP_RECT_OES, cropRect, 0); 155 GLUtils.texImage2D(GL11.GL_TEXTURE_2D, 0, bitmap, 0); 156 157 } 158 159 return true; 160 } 161 draw(RenderView view, GL11 gl, int x, int y)162 public void draw(RenderView view, GL11 gl, int x, int y) { 163 if (bind(gl)) { 164 view.draw2D(x, y, 0, mWidth, mHeight); 165 } 166 } 167 drawWithEffect(RenderView view, GL11 gl, float x, float y, float anchorX, float anchorY, float alpha, float scale)168 public void drawWithEffect(RenderView view, GL11 gl, float x, float y, float anchorX, float anchorY, float alpha, float scale) { 169 if (bind(gl)) { 170 float width = mWidth; 171 float height = mHeight; 172 173 // Apply scale transform if not identity. 174 if (scale != 1) { // CR: 1.0f 175 float originX = x + anchorX * width; 176 float originY = y + anchorY * height; 177 width *= scale; 178 height *= scale; 179 x = originX - anchorX * width; 180 y = originY - anchorY * height; 181 } 182 183 // Set alpha if needed. 184 if (alpha != 1f) { // CR: 1.0f 185 view.setAlpha(alpha); 186 } 187 view.draw2D(x, y, 0, width, height); 188 if (alpha != 1f) { 189 view.resetColor(); 190 } 191 } 192 } 193 onSizeChanged()194 protected abstract void onSizeChanged(); 195 renderCanvas(Canvas canvas, Bitmap backing, int width, int height)196 protected abstract void renderCanvas(Canvas canvas, Bitmap backing, int width, int height); 197 198 } // CR: superfluous newline above. 199