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 42 public CanvasTexture(Bitmap.Config bitmapConfig) { 43 mBitmapConfig = bitmapConfig; 44 } 45 46 public final void setNeedsDraw() { 47 mNeedsDraw = true; 48 } 49 50 public final int getWidth() { 51 return mWidth; 52 } 53 54 public final int getHeight() { 55 return mHeight; 56 } 57 58 public final float getNormalizedWidth() { 59 return mNormalizedWidth; 60 } 61 62 public final float getNormalizedHeight() { 63 return mNormalizedHeight; 64 } 65 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 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. 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 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 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 194 protected abstract void onSizeChanged(); 195 196 protected abstract void renderCanvas(Canvas canvas, Bitmap backing, int width, int height); 197 198 } // CR: superfluous newline above. 199