Home | History | Annotate | Download | only in media
      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