From 8ac2e8630f33f4d5f65731dc56efa9bfb3570cd7 Mon Sep 17 00:00:00 2001 From: Owen Lin Date: Tue, 24 Apr 2012 14:08:44 +0800 Subject: [PATCH] Add support to draw on texture. Change-Id: I95dd5d29352692b702503969e1ebe07bc91a8a73 --- src/com/android/gallery3d/ui/GLCanvas.java | 4 + src/com/android/gallery3d/ui/GLCanvasImpl.java | 107 +++++++++++-- src/com/android/gallery3d/ui/Raw2DTexture.java | 169 --------------------- src/com/android/gallery3d/ui/RawTexture.java | 91 +++++++++++ .../src/com/android/gallery3d/ui/GLCanvasStub.java | 2 + 5 files changed, 193 insertions(+), 180 deletions(-) delete mode 100644 src/com/android/gallery3d/ui/Raw2DTexture.java create mode 100644 src/com/android/gallery3d/ui/RawTexture.java diff --git a/src/com/android/gallery3d/ui/GLCanvas.java b/src/com/android/gallery3d/ui/GLCanvas.java index 9b8053ffc..c12a9f78c 100644 --- a/src/com/android/gallery3d/ui/GLCanvas.java +++ b/src/com/android/gallery3d/ui/GLCanvas.java @@ -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(); } diff --git a/src/com/android/gallery3d/ui/GLCanvasImpl.java b/src/com/android/gallery3d/ui/GLCanvasImpl.java index 61238519b..1efe5af4e 100644 --- a/src/com/android/gallery3d/ui/GLCanvasImpl.java +++ b/src/com/android/gallery3d/ui/GLCanvasImpl.java @@ -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 mTargetStack = new ArrayList(); private float mAlpha; - private final ArrayList mRestoreStack = - new ArrayList(); + private final ArrayList mRestoreStack = new ArrayList(); 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 index b7e4e6d59..000000000 --- a/src/com/android/gallery3d/ui/Raw2DTexture.java +++ /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 index 000000000..e1af7d209 --- /dev/null +++ b/src/com/android/gallery3d/ui/RawTexture.java @@ -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; + } +} diff --git a/tests/src/com/android/gallery3d/ui/GLCanvasStub.java b/tests/src/com/android/gallery3d/ui/GLCanvasStub.java index ee43cb943..5f749d8fc 100644 --- a/tests/src/com/android/gallery3d/ui/GLCanvasStub.java +++ b/tests/src/com/android/gallery3d/ui/GLCanvasStub.java @@ -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() {} } -- 2.11.0