OSDN Git Service

Add support to draw on texture.
authorOwen Lin <owenlin@google.com>
Tue, 24 Apr 2012 06:08:44 +0000 (14:08 +0800)
committerOwen Lin <owenlin@google.com>
Wed, 2 May 2012 08:28:37 +0000 (16:28 +0800)
Change-Id: I95dd5d29352692b702503969e1ebe07bc91a8a73

src/com/android/gallery3d/ui/GLCanvas.java
src/com/android/gallery3d/ui/GLCanvasImpl.java
src/com/android/gallery3d/ui/Raw2DTexture.java [deleted file]
src/com/android/gallery3d/ui/RawTexture.java [new file with mode: 0644]
tests/src/com/android/gallery3d/ui/GLCanvasStub.java

index 9b8053f..c12a9f7 100644 (file)
@@ -117,4 +117,8 @@ public interface GLCanvas {
 
     // Dump statistics information and clear the counters. For debug only.
     public void dumpStatisticsAndClear();
+
+    public void beginRenderTarget(RawTexture texture);
+
+    public void endRenderTarget();
 }
index 6123851..1efe5af 100644 (file)
@@ -16,7 +16,6 @@
 
 package com.android.gallery3d.ui;
 
-import android.graphics.Rect;
 import android.graphics.RectF;
 import android.opengl.GLU;
 import android.opengl.Matrix;
@@ -32,6 +31,7 @@ import java.util.ArrayList;
 import javax.microedition.khronos.opengles.GL10;
 import javax.microedition.khronos.opengles.GL11;
 import javax.microedition.khronos.opengles.GL11Ext;
+import javax.microedition.khronos.opengles.GL11ExtensionPack;
 
 public class GLCanvasImpl implements GLCanvas {
     @SuppressWarnings("unused")
@@ -61,10 +61,10 @@ public class GLCanvasImpl implements GLCanvas {
     private int mBoxCoords;
 
     private final GLState mGLState;
+    private final ArrayList<RawTexture> mTargetStack = new ArrayList<RawTexture>();
 
     private float mAlpha;
-    private final ArrayList<ConfigState> mRestoreStack =
-            new ArrayList<ConfigState>();
+    private final ArrayList<ConfigState> mRestoreStack = new ArrayList<ConfigState>();
     private ConfigState mRecycledRestoreAction;
 
     private final RectF mDrawTextureSourceRect = new RectF();
@@ -72,8 +72,12 @@ public class GLCanvasImpl implements GLCanvas {
     private final float[] mTempMatrix = new float[32];
     private final IntArray mUnboundTextures = new IntArray();
     private final IntArray mDeleteBuffers = new IntArray();
-    private int mHeight;
+    private int mScreenWidth;
+    private int mScreenHeight;
     private boolean mBlendEnabled = true;
+    private int mFrameBuffer[] = new int[1];
+
+    private RawTexture mTargetTexture;
 
     // Drawing statistics
     int mCountDrawLine;
@@ -90,7 +94,12 @@ public class GLCanvasImpl implements GLCanvas {
 
     public void setSize(int width, int height) {
         Utils.assertTrue(width >= 0 && height >= 0);
-        mHeight = height;
+
+        if (mTargetTexture == null) {
+            mScreenWidth = width;
+            mScreenHeight = height;
+        }
+        mAlpha = 1.0f;
 
         GL11 gl = mGL;
         gl.glViewport(0, 0, width, height);
@@ -100,11 +109,14 @@ public class GLCanvasImpl implements GLCanvas {
 
         gl.glMatrixMode(GL11.GL_MODELVIEW);
         gl.glLoadIdentity();
-        float matrix[] = mMatrixValues;
 
+        float matrix[] = mMatrixValues;
         Matrix.setIdentityM(matrix, 0);
-        Matrix.translateM(matrix, 0, 0, mHeight, 0);
-        Matrix.scaleM(matrix, 0, 1, -1, 1);
+        // to match the graphic coordinate system in android, we flip it vertically.
+        if (mTargetTexture == null) {
+            Matrix.translateM(matrix, 0, 0, height, 0);
+            Matrix.scaleM(matrix, 0, 1, -1, 1);
+        }
     }
 
     public void setAlpha(float alpha) {
@@ -151,8 +163,7 @@ public class GLCanvasImpl implements GLCanvas {
         gl.glClientActiveTexture(GL11.GL_TEXTURE0);
         gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
 
-        // mMatrixValues will be initialized in setSize()
-        mAlpha = 1.0f;
+        // mMatrixValues and mAlpha will be initialized in setSize()
     }
 
     public void drawRect(float x, float y, float width, float height, GLPaint paint) {
@@ -724,7 +735,6 @@ public class GLCanvasImpl implements GLCanvas {
 
     private static class ConfigState {
         float mAlpha;
-        Rect mRect = new Rect();
         float mMatrix[] = new float[16];
         ConfigState mNextFree;
 
@@ -756,4 +766,79 @@ public class GLCanvasImpl implements GLCanvas {
     private void restoreTransform() {
         System.arraycopy(mTempMatrix, 0, mMatrixValues, 0, 16);
     }
+
+    private void setRenderTarget(RawTexture texture) {
+        GL11ExtensionPack gl11ep = (GL11ExtensionPack) mGL;
+
+        if (mTargetTexture == null && texture != null) {
+            GLId.glGenBuffers(1, mFrameBuffer, 0);
+            gl11ep.glBindFramebufferOES(
+                    GL11ExtensionPack.GL_FRAMEBUFFER_OES, mFrameBuffer[0]);
+        }
+        if (mTargetTexture != null && texture  == null) {
+            gl11ep.glBindFramebufferOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, 0);
+            gl11ep.glDeleteFramebuffersOES(1, mFrameBuffer, 0);
+        }
+
+        mTargetTexture = texture;
+        if (texture == null) {
+            setSize(mScreenWidth, mScreenHeight);
+        } else {
+            setSize(texture.getWidth(), texture.getHeight());
+
+            if (!texture.isLoaded(this)) texture.prepare(this);
+
+            gl11ep.glFramebufferTexture2DOES(
+                    GL11ExtensionPack.GL_FRAMEBUFFER_OES,
+                    GL11ExtensionPack.GL_COLOR_ATTACHMENT0_OES,
+                    GL11.GL_TEXTURE_2D, texture.getId(), 0);
+
+            checkFramebufferStatus(gl11ep);
+        }
+    }
+
+    @Override
+    public void endRenderTarget() {
+        RawTexture texture = mTargetStack.remove(mTargetStack.size() - 1);
+        setRenderTarget(texture);
+        restore(); // restore matrix and alpha
+    }
+
+    @Override
+    public void beginRenderTarget(RawTexture texture) {
+        save(); // save matrix and alpha
+        mTargetStack.add(mTargetTexture);
+        setRenderTarget(texture);
+    }
+
+    private static void checkFramebufferStatus(GL11ExtensionPack gl11ep) {
+        int status = gl11ep.glCheckFramebufferStatusOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES);
+        if (status != GL11ExtensionPack.GL_FRAMEBUFFER_COMPLETE_OES) {
+            String msg = "";
+            switch (status) {
+                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES:
+                    msg = "FRAMEBUFFER_FORMATS";
+                    break;
+                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES:
+                    msg = "FRAMEBUFFER_ATTACHMENT";
+                    break;
+                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES:
+                    msg = "FRAMEBUFFER_MISSING_ATTACHMENT";
+                    break;
+                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_OES:
+                    msg = "FRAMEBUFFER_DRAW_BUFFER";
+                    break;
+                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_OES:
+                    msg = "FRAMEBUFFER_READ_BUFFER";
+                    break;
+                case GL11ExtensionPack.GL_FRAMEBUFFER_UNSUPPORTED_OES:
+                    msg = "FRAMEBUFFER_UNSUPPORTED";
+                    break;
+                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES:
+                    msg = "FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
+                    break;
+            }
+            throw new RuntimeException(msg + ":" + Integer.toHexString(status));
+        }
+    }
 }
diff --git a/src/com/android/gallery3d/ui/Raw2DTexture.java b/src/com/android/gallery3d/ui/Raw2DTexture.java
deleted file mode 100644 (file)
index b7e4e6d..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.gallery3d.ui;
-
-import android.opengl.GLU;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.FloatBuffer;
-import javax.microedition.khronos.opengles.GL11;
-import javax.microedition.khronos.opengles.GL11Ext;
-import javax.microedition.khronos.opengles.GL11ExtensionPack;
-
-/**
- * A wrapper class of GL 2D texture.
- */
-public class Raw2DTexture extends BasicTexture {
-    private static final int[] sTextureId = new int[1];
-    // OpenGL related fields used when copy.
-    private static final int[] sBufferName = new int[1];
-    private int mFBO;  // Frame buffer object.
-
-    // We need copy from another texture when in camera capture animation.
-    // The copy is done through a framebuffer object with an attached
-    // destination texture. The source texture is rendered to the framebuffer
-    // and the data will be stored in the destination texture.
-    public static void copy(GLCanvas canvas, BasicTexture src, Raw2DTexture dst) {
-        int[] viewPort = new int[4];
-        GL11 gl11 = canvas.getGLInstance();
-        GL11ExtensionPack gl11ep = (GL11ExtensionPack) gl11;
-
-        if (!dst.isLoaded(canvas)) {
-            dst.prepare(canvas.getGLInstance());
-        }
-
-        gl11ep.glBindFramebufferOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, dst.mFBO);
-        gl11ep.glFramebufferTexture2DOES(
-                GL11ExtensionPack.GL_FRAMEBUFFER_OES,
-                GL11ExtensionPack.GL_COLOR_ATTACHMENT0_OES,
-                GL11.GL_TEXTURE_2D,
-                dst.getId(), 0);
-        checkFramebufferStatus(gl11ep);
-
-        // Draw the source onto our destination.
-        // The texture coords and vertex pointer are already set properly. We don't
-        // need to set again.
-        gl11.glBindTexture(src.getTarget(), src.getId());
-        boolean targetEnabled = gl11.glIsEnabled(src.getTarget());
-        gl11.glEnable(src.getTarget());
-
-        // Set the texture matrix.
-        gl11.glMatrixMode(GL11.GL_TEXTURE);
-        gl11.glPushMatrix();
-        gl11.glLoadIdentity();
-
-        // Set the view port.
-        gl11.glGetIntegerv(GL11.GL_VIEWPORT, viewPort, 0);
-        gl11.glViewport(0, 0, dst.getTextureWidth(), dst.getTextureHeight());
-
-        // Set the projection matrix.
-        gl11.glMatrixMode(GL11.GL_PROJECTION);
-        gl11.glPushMatrix();
-        gl11.glLoadIdentity();
-        GLU.gluOrtho2D(gl11, 0, 1, 0, 1);
-
-        // Set the modelview matrix.
-        gl11.glMatrixMode(GL11.GL_MODELVIEW);
-        gl11.glPushMatrix();
-        gl11.glLoadIdentity();
-
-        // Draw the texture.
-        gl11.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, 4);
-
-        // Clear.
-        if (!targetEnabled) gl11.glDisable(src.getTarget());
-        gl11ep.glBindFramebufferOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, 0);
-        gl11.glBindTexture(src.getTarget(), 0);
-        gl11.glViewport(viewPort[0], viewPort[1], viewPort[2], viewPort[3]);
-        gl11.glMatrixMode(GL11.GL_TEXTURE);
-        gl11.glPopMatrix();
-        gl11.glMatrixMode(GL11.GL_PROJECTION);
-        gl11.glPopMatrix();
-        gl11.glMatrixMode(GL11.GL_MODELVIEW);
-        gl11.glPopMatrix();
-        GLId.glDeleteFramebuffers(gl11ep, 1, dst.sBufferName, 0);
-    }
-
-    public Raw2DTexture(int w, int h) {
-        setSize(w, h);
-        GLId.glGenTextures(1, sTextureId, 0);
-        mId = sTextureId[0];
-        GLId.glGenBuffers(1, sBufferName, 0);
-        mFBO = sBufferName[0];
-    }
-
-    private void prepare(GL11 gl11) {
-        gl11.glBindTexture(GL11.GL_TEXTURE_2D, mId);
-        gl11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP_TO_EDGE);
-        gl11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP_TO_EDGE);
-        gl11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
-        gl11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
-        gl11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA,
-                getTextureWidth(), getTextureHeight(),
-                0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, null);
-        gl11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
-        mState = UploadedTexture.STATE_LOADED;
-    }
-
-    @Override
-    protected boolean onBind(GLCanvas canvas) {
-        if (!isLoaded(canvas)) {
-            return false;
-        }
-
-        return true;
-    }
-
-    @Override
-    public int getTarget() {
-        return GL11.GL_TEXTURE_2D;
-    }
-
-    public boolean isOpaque() {
-        return true;
-    }
-
-    @Override
-    public void yield() {
-        // we cannot free the texture because we have no backup.
-    }
-
-    private static void checkFramebufferStatus(GL11ExtensionPack gl11ep) {
-        int status = gl11ep.glCheckFramebufferStatusOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES);
-        if (status != GL11ExtensionPack.GL_FRAMEBUFFER_COMPLETE_OES) {
-            String msg = "";
-            switch (status) {
-                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES:
-                    msg = "FRAMEBUFFER_FORMATS"; break;
-                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES:
-                    msg = "FRAMEBUFFER_ATTACHMENT"; break;
-                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES:
-                    msg = "FRAMEBUFFER_MISSING_ATTACHMENT"; break;
-                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_OES:
-                    msg = "FRAMEBUFFER_DRAW_BUFFER"; break;
-                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_OES:
-                    msg = "FRAMEBUFFER_READ_BUFFER"; break;
-                case GL11ExtensionPack.GL_FRAMEBUFFER_UNSUPPORTED_OES:
-                    msg = "FRAMEBUFFER_UNSUPPORTED"; break;
-                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES:
-                    msg = "FRAMEBUFFER_INCOMPLETE_DIMENSIONS"; break;
-            }
-            throw new RuntimeException(msg + ":" + Integer.toHexString(status));
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/ui/RawTexture.java b/src/com/android/gallery3d/ui/RawTexture.java
new file mode 100644 (file)
index 0000000..e1af7d2
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gallery3d.ui;
+
+import javax.microedition.khronos.opengles.GL11;
+import javax.microedition.khronos.opengles.GL11Ext;
+
+public class RawTexture extends BasicTexture {
+    private static final String TAG = "RawTexture";
+
+    private final static int[] sTextureId = new int[1];
+    private final static float[] sCropRect = new float[4];
+
+    private final boolean mOpaque;
+
+    public RawTexture(int width, int height, boolean opaque) {
+        mOpaque = opaque;
+        setSize(width, height);
+    }
+
+    @Override
+    public boolean isOpaque() {
+        return mOpaque;
+    }
+
+    protected void prepare(GLCanvas canvas) {
+        GL11 gl = canvas.getGLInstance();
+
+        // Define a vertically flipped crop rectangle for
+        // OES_draw_texture.
+        // The four values in sCropRect are: left, bottom, width, and
+        // height. Negative value of width or height means flip.
+        sCropRect[0] = 0;
+        sCropRect[1] = mHeight;
+        sCropRect[2] = mWidth;
+        sCropRect[3] = -mHeight;
+
+        // Upload the bitmap to a new texture.
+        GLId.glGenTextures(1, sTextureId, 0);
+        gl.glBindTexture(GL11.GL_TEXTURE_2D, sTextureId[0]);
+        gl.glTexParameterfv(GL11.GL_TEXTURE_2D,
+                GL11Ext.GL_TEXTURE_CROP_RECT_OES, sCropRect, 0);
+        gl.glTexParameteri(GL11.GL_TEXTURE_2D,
+                GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP_TO_EDGE);
+        gl.glTexParameteri(GL11.GL_TEXTURE_2D,
+                GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP_TO_EDGE);
+        gl.glTexParameterf(GL11.GL_TEXTURE_2D,
+                GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
+        gl.glTexParameterf(GL11.GL_TEXTURE_2D,
+                GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
+
+        gl.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA,
+                getTextureWidth(), getTextureHeight(),
+                0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, null);
+
+        mId = sTextureId[0];
+        mState = UploadedTexture.STATE_LOADED;
+        setAssociatedCanvas(canvas);
+    }
+
+    @Override
+    protected boolean onBind(GLCanvas canvas) {
+        if (isLoaded(canvas)) return true;
+        Log.w(TAG, "lost the content due to context change");
+        return false;
+    }
+
+    @Override
+     public void yield() {
+         // we cannot free the texture because we have no backup.
+     }
+
+    @Override
+    protected int getTarget() {
+        return GL11.GL_TEXTURE_2D;
+    }
+}
index ee43cb9..5f749d8 100644 (file)
@@ -80,4 +80,6 @@ public class GLCanvasStub implements GLCanvas {
     public void deleteRecycledResources() {}
     public void multiplyMatrix(float[] mMatrix, int offset) {}
     public void dumpStatisticsAndClear() {}
+    public void beginRenderTarget(RawTexture texture) {}
+    public void endRenderTarget() {}
 }