From 0db6ec1a2d602a48437a48ae47fbca01299fdcea Mon Sep 17 00:00:00 2001 From: George Mount Date: Thu, 1 Nov 2012 10:32:41 -0700 Subject: Separate GL calls into GLCanvas in preparation for adding GLES2. Change-Id: I2756c14294a36af7905766ee650fa08fb95e9477 --- src/com/android/gallery3d/ui/BasicTexture.java | 5 +- src/com/android/gallery3d/ui/CropView.java | 41 ++--- src/com/android/gallery3d/ui/ExtTexture.java | 34 +--- src/com/android/gallery3d/ui/GLCanvas.java | 177 ++++++++++++++++----- src/com/android/gallery3d/ui/GLCanvasImpl.java | 141 ++++++++++++++-- src/com/android/gallery3d/ui/GLId.java | 29 +--- src/com/android/gallery3d/ui/GLIdImpl.java | 68 ++++++++ src/com/android/gallery3d/ui/NinePatchTexture.java | 25 +-- src/com/android/gallery3d/ui/RawTexture.java | 38 +---- src/com/android/gallery3d/ui/SlideshowView.java | 9 +- src/com/android/gallery3d/ui/UploadedTexture.java | 53 ++---- 11 files changed, 390 insertions(+), 230 deletions(-) create mode 100644 src/com/android/gallery3d/ui/GLIdImpl.java (limited to 'src/com/android/gallery3d/ui') diff --git a/src/com/android/gallery3d/ui/BasicTexture.java b/src/com/android/gallery3d/ui/BasicTexture.java index 99cf0571c..38686d59f 100644 --- a/src/com/android/gallery3d/ui/BasicTexture.java +++ b/src/com/android/gallery3d/ui/BasicTexture.java @@ -36,7 +36,7 @@ abstract class BasicTexture implements Texture { // Log a warning if a texture is larger along a dimension private static final int MAX_TEXTURE_SIZE = 4096; - protected int mId; + protected int mId = -1; protected int mState; protected int mWidth = UNSPECIFIED; @@ -165,8 +165,9 @@ abstract class BasicTexture implements Texture { private void freeResource() { GLCanvas canvas = mCanvasRef; - if (canvas != null && isLoaded()) { + if (canvas != null && mId != -1) { canvas.unloadTexture(this); + mId = -1; // Don't free it again. } mState = STATE_UNLOADED; setAssociatedCanvas(null); diff --git a/src/com/android/gallery3d/ui/CropView.java b/src/com/android/gallery3d/ui/CropView.java index 1890c7630..a575557bb 100644 --- a/src/com/android/gallery3d/ui/CropView.java +++ b/src/com/android/gallery3d/ui/CropView.java @@ -38,8 +38,6 @@ import com.android.gallery3d.common.Utils; import java.util.ArrayList; -import javax.microedition.khronos.opengles.GL11; - /** * The activity can crop specific region of interest from an image. */ @@ -207,12 +205,11 @@ public class CropView extends GLView { } private void renderFace(GLCanvas canvas, RectF face, boolean pressed) { - GL11 gl = canvas.getGLInstance(); if (pressed) { - gl.glEnable(GL11.GL_STENCIL_TEST); - gl.glClear(GL11.GL_STENCIL_BUFFER_BIT); - gl.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_REPLACE); - gl.glStencilFunc(GL11.GL_ALWAYS, 1, 1); + canvas.enableStencil(); + canvas.clearStencilBuffer(); + canvas.updateStencil(true); + canvas.drawOnlyOutsideStencil(false); } RectF r = mAnimation.mapRect(face, mRect); @@ -220,7 +217,8 @@ public class CropView extends GLView { canvas.drawRect(r.left, r.top, r.width(), r.height(), mFacePaint); if (pressed) { - gl.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP); + canvas.updateStencil(false); + canvas.disableStencil(); } } @@ -231,11 +229,11 @@ public class CropView extends GLView { renderFace(canvas, faces.get(i), i == mPressedFaceIndex); } - GL11 gl = canvas.getGLInstance(); if (mPressedFaceIndex != INDEX_NONE) { - gl.glStencilFunc(GL11.GL_NOTEQUAL, 1, 1); + canvas.enableStencil(); + canvas.drawOnlyOutsideStencil(true); canvas.fillRect(0, 0, getWidth(), getHeight(), 0x66000000); - gl.glDisable(GL11.GL_STENCIL_TEST); + canvas.disableStencil(); } } @@ -622,18 +620,16 @@ public class CropView extends GLView { } private void drawHighlightRectangle(GLCanvas canvas, RectF r) { - GL11 gl = canvas.getGLInstance(); - gl.glLineWidth(3.0f); - gl.glEnable(GL11.GL_LINE_SMOOTH); - gl.glEnable(GL11.GL_STENCIL_TEST); - gl.glClear(GL11.GL_STENCIL_BUFFER_BIT); - gl.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_REPLACE); - gl.glStencilFunc(GL11.GL_ALWAYS, 1, 1); + canvas.enableStencil(); + canvas.clearStencilBuffer(); + canvas.updateStencil(true); + canvas.drawOnlyOutsideStencil(false); if (mSpotlightRatioX == 0 || mSpotlightRatioY == 0) { canvas.fillRect(r.left, r.top, r.width(), r.height(), Color.TRANSPARENT); canvas.drawRect(r.left, r.top, r.width(), r.height(), mPaint); + canvas.drawOnlyOutsideStencil(true); } else { float sx = r.width() * mSpotlightRatioX; float sy = r.height() * mSpotlightRatioY; @@ -644,20 +640,17 @@ public class CropView extends GLView { canvas.drawRect(cx - sx / 2, cy - sy / 2, sx, sy, mPaint); canvas.drawRect(r.left, r.top, r.width(), r.height(), mPaint); - gl.glStencilFunc(GL11.GL_NOTEQUAL, 1, 1); - gl.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_REPLACE); + canvas.drawOnlyOutsideStencil(true); canvas.drawRect(cx - sy / 2, cy - sx / 2, sy, sx, mPaint); canvas.fillRect(cx - sy / 2, cy - sx / 2, sy, sx, Color.TRANSPARENT); canvas.fillRect(r.left, r.top, r.width(), r.height(), 0x80000000); } - gl.glStencilFunc(GL11.GL_NOTEQUAL, 1, 1); - gl.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP); - + canvas.updateStencil(false); canvas.fillRect(0, 0, getWidth(), getHeight(), 0xA0000000); - gl.glDisable(GL11.GL_STENCIL_TEST); + canvas.disableStencil(); } } diff --git a/src/com/android/gallery3d/ui/ExtTexture.java b/src/com/android/gallery3d/ui/ExtTexture.java index eac504fe5..180a89dce 100644 --- a/src/com/android/gallery3d/ui/ExtTexture.java +++ b/src/com/android/gallery3d/ui/ExtTexture.java @@ -16,49 +16,21 @@ package com.android.gallery3d.ui; -import javax.microedition.khronos.opengles.GL11; -import javax.microedition.khronos.opengles.GL11Ext; // ExtTexture is a texture whose content comes from a external texture. // Before drawing, setSize() should be called. public class ExtTexture extends BasicTexture { - private static int[] sTextureId = new int[1]; - private static float[] sCropRect = new float[4]; private int mTarget; public ExtTexture(int target) { - GLId.glGenTextures(1, sTextureId, 0); - mId = sTextureId[0]; + GLId glId = GLCanvas.getGLId(); + mId = glId.generateTexture(); mTarget = target; } private void uploadToCanvas(GLCanvas canvas) { - GL11 gl = canvas.getGLInstance(); - - int width = getWidth(); - int height = getHeight(); - // 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] = height; - sCropRect[2] = width; - sCropRect[3] = -height; - - // Set texture parameters. - gl.glBindTexture(mTarget, mId); - gl.glTexParameterfv(mTarget, - GL11Ext.GL_TEXTURE_CROP_RECT_OES, sCropRect, 0); - gl.glTexParameteri(mTarget, - GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP_TO_EDGE); - gl.glTexParameteri(mTarget, - GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP_TO_EDGE); - gl.glTexParameterf(mTarget, - GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); - gl.glTexParameterf(mTarget, - GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); - + canvas.setTextureParameters(this); setAssociatedCanvas(canvas); mState = STATE_LOADED; } diff --git a/src/com/android/gallery3d/ui/GLCanvas.java b/src/com/android/gallery3d/ui/GLCanvas.java index 6f8baef7e..d1f5ba2c3 100644 --- a/src/com/android/gallery3d/ui/GLCanvas.java +++ b/src/com/android/gallery3d/ui/GLCanvas.java @@ -16,117 +16,218 @@ package com.android.gallery3d.ui; +import android.graphics.Bitmap; import android.graphics.RectF; -import javax.microedition.khronos.opengles.GL11; - // // GLCanvas gives a convenient interface to draw using OpenGL. // // When a rectangle is specified in this interface, it means the region // [x, x+width) * [y, y+height) // -public interface GLCanvas { +public abstract class GLCanvas { + public enum Blending { + Additive, Mix, + } + + private static GLId sGLId = new GLIdImpl(); + + public static GLId getGLId() { + return sGLId; + } + // Tells GLCanvas the size of the underlying GL surface. This should be // called before first drawing and when the size of GL surface is changed. // This is called by GLRoot and should not be called by the clients // who only want to draw on the GLCanvas. Both width and height must be // nonnegative. - public void setSize(int width, int height); + public abstract void setSize(int width, int height); // Clear the drawing buffers. This should only be used by GLRoot. - public void clearBuffer(); - public void clearBuffer(float[] argb); + public abstract void clearBuffer(); + + public abstract void clearBuffer(float[] argb); // Sets and gets the current alpha, alpha must be in [0, 1]. - public void setAlpha(float alpha); - public float getAlpha(); + public abstract void setAlpha(float alpha); + + public abstract float getAlpha(); // (current alpha) = (current alpha) * alpha - public void multiplyAlpha(float alpha); + public abstract void multiplyAlpha(float alpha); // Change the current transform matrix. - public void translate(float x, float y, float z); - public void translate(float x, float y); - public void scale(float sx, float sy, float sz); - public void rotate(float angle, float x, float y, float z); - public void multiplyMatrix(float[] mMatrix, int offset); + public abstract void translate(float x, float y, float z); + + public abstract void translate(float x, float y); + + public abstract void scale(float sx, float sy, float sz); + + public abstract void rotate(float angle, float x, float y, float z); + + public abstract void multiplyMatrix(float[] mMatrix, int offset); // Pushes the configuration state (matrix, and alpha) onto // a private stack. - public void save(); + public abstract void save(); // Same as save(), but only save those specified in saveFlags. - public void save(int saveFlags); + public abstract void save(int saveFlags); public static final int SAVE_FLAG_ALL = 0xFFFFFFFF; public static final int SAVE_FLAG_ALPHA = 0x01; public static final int SAVE_FLAG_MATRIX = 0x02; + public static final int SAVE_FLAG_BLEND = 0x04; // Pops from the top of the stack as current configuration state (matrix, // alpha, and clip). This call balances a previous call to save(), and is // used to remove all modifications to the configuration state since the // last save call. - public void restore(); + public abstract void restore(); // Draws a line using the specified paint from (x1, y1) to (x2, y2). // (Both end points are included). - public void drawLine(float x1, float y1, float x2, float y2, GLPaint paint); + public abstract void drawLine(float x1, float y1, float x2, float y2, GLPaint paint); // Draws a rectangle using the specified paint from (x1, y1) to (x2, y2). // (Both end points are included). - public void drawRect(float x1, float y1, float x2, float y2, GLPaint paint); + public abstract void drawRect(float x1, float y1, float x2, float y2, GLPaint paint); // Fills the specified rectangle with the specified color. - public void fillRect(float x, float y, float width, float height, int color); + public abstract void fillRect(float x, float y, float width, float height, int color); // Draws a texture to the specified rectangle. - public void drawTexture( + public abstract void drawTexture( BasicTexture texture, int x, int y, int width, int height); - public void drawMesh(BasicTexture tex, int x, int y, int xyBuffer, + + public abstract void drawMesh(BasicTexture tex, int x, int y, int xyBuffer, int uvBuffer, int indexBuffer, int indexCount); // Draws the source rectangle part of the texture to the target rectangle. - public void drawTexture(BasicTexture texture, RectF source, RectF target); + public abstract void drawTexture(BasicTexture texture, RectF source, RectF target); // Draw a texture with a specified texture transform. - public void drawTexture(BasicTexture texture, float[] mTextureTransform, + public abstract void drawTexture(BasicTexture texture, float[] mTextureTransform, int x, int y, int w, int h); // Draw two textures to the specified rectangle. The actual texture used is // from * (1 - ratio) + to * ratio // The two textures must have the same size. - public void drawMixed(BasicTexture from, int toColor, + public abstract void drawMixed(BasicTexture from, int toColor, float ratio, int x, int y, int w, int h); // Draw a region of a texture and a specified color to the specified // rectangle. The actual color used is from * (1 - ratio) + to * ratio. // The region of the texture is defined by parameter "src". The target // rectangle is specified by parameter "target". - public void drawMixed(BasicTexture from, int toColor, + public abstract void drawMixed(BasicTexture from, int toColor, float ratio, RectF src, RectF target); - // Gets the underlying GL instance. This is used only when direct access to - // GL is needed. - public GL11 getGLInstance(); - // Unloads the specified texture from the canvas. The resource allocated // to draw the texture will be released. The specified texture will return // to the unloaded state. This function should be called only from // BasicTexture or its descendant - public boolean unloadTexture(BasicTexture texture); + public abstract boolean unloadTexture(BasicTexture texture); // Delete the specified buffer object, similar to unloadTexture. - public void deleteBuffer(int bufferId); + public abstract void deleteBuffer(int bufferId); // Delete the textures and buffers in GL side. This function should only be // called in the GL thread. - public void deleteRecycledResources(); + public abstract void deleteRecycledResources(); // Dump statistics information and clear the counters. For debug only. - public void dumpStatisticsAndClear(); - - public void beginRenderTarget(RawTexture texture); - - public void endRenderTarget(); + public abstract void dumpStatisticsAndClear(); + + public abstract void beginRenderTarget(RawTexture texture); + + public abstract void endRenderTarget(); + + /** + * Sets texture parameters to use GL_CLAMP_TO_EDGE for both + * GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T. Sets texture parameters to be + * GL_LINEAR for GL_TEXTURE_MIN_FILTER and GL_TEXTURE_MAG_FILTER. + * bindTexture() must be called prior to this. + * + * @param texture The texture to set parameters on. + */ + public abstract void setTextureParameters(BasicTexture texture); + + /** + * Initializes the texture to a size by calling texImage2D on it. + * + * @param texture The texture to initialize the size. + * @param format The texture format (e.g. GL_RGBA) + * @param type The texture type (e.g. GL_UNSIGNED_BYTE) + */ + public abstract void initializeTextureSize(BasicTexture texture, int format, int type); + + /** + * Initializes the texture to a size by calling texImage2D on it. + * + * @param texture The texture to initialize the size. + * @param bitmap The bitmap to initialize the bitmap with. + */ + public abstract void initializeTexture(BasicTexture texture, Bitmap bitmap); + + /** + * Calls glTexSubImage2D to upload a bitmap to the texture. + * + * @param texture The target texture to write to. + * @param xOffset Specifies a texel offset in the x direction within the + * texture array. + * @param yOffset Specifies a texel offset in the y direction within the + * texture array. + * @param format The texture format (e.g. GL_RGBA) + * @param type The texture type (e.g. GL_UNSIGNED_BYTE) + */ + public abstract void texSubImage2D(BasicTexture texture, int xOffset, int yOffset, + Bitmap bitmap, + int format, int type); + + /** + * Generates buffers and uploads the buffer data. + * + * @param buffers An array of buffers to upload + * @return The buffer IDs that were generated. + */ + public abstract int[] uploadBuffers(java.nio.Buffer[] buffers); + + /** + * Sets the blending algorithm if a texture is not opaque. + * + * @param blending Either mixing (overlay) or adding a texture. + */ + public abstract void setBlending(Blending blending); + + /** + * Enable stencil test + */ + public abstract void enableStencil(); + + /** + * Disable stencil. + */ + public abstract void disableStencil(); + + /** + * Clears the stencil so that a new stencil can be generated. + */ + public abstract void clearStencilBuffer(); + + /** + * Start/stop updating the stencil buffer. + * + * @param update True if the stencil should be updated, false otherwise. + */ + public abstract void updateStencil(boolean update); + + /** + * Changes how the stencil buffer is used. + * + * @param onlyOutside If true, only the area outside the stencil can be + * changed. If false, the area inside the stencil can be drawn to + * as well. + */ + public abstract void drawOnlyOutsideStencil(boolean onlyOutside); } diff --git a/src/com/android/gallery3d/ui/GLCanvasImpl.java b/src/com/android/gallery3d/ui/GLCanvasImpl.java index 45903b3cd..ad49ec16a 100644 --- a/src/com/android/gallery3d/ui/GLCanvasImpl.java +++ b/src/com/android/gallery3d/ui/GLCanvasImpl.java @@ -16,13 +16,16 @@ package com.android.gallery3d.ui; +import android.graphics.Bitmap; import android.graphics.RectF; import android.opengl.GLU; +import android.opengl.GLUtils; import android.opengl.Matrix; import com.android.gallery3d.common.Utils; import com.android.gallery3d.util.IntArray; +import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; @@ -33,7 +36,7 @@ import javax.microedition.khronos.opengles.GL11; import javax.microedition.khronos.opengles.GL11Ext; import javax.microedition.khronos.opengles.GL11ExtensionPack; -public class GLCanvasImpl implements GLCanvas { +public class GLCanvasImpl extends GLCanvas { @SuppressWarnings("unused") private static final String TAG = "GLCanvasImp"; @@ -76,8 +79,10 @@ public class GLCanvasImpl implements GLCanvas { private int mScreenHeight; private boolean mBlendEnabled = true; private int mFrameBuffer[] = new int[1]; + private static float[] sCropRect = new float[4]; private RawTexture mTargetTexture; + private Blending mBlending = Blending.Mix; // Drawing statistics int mCountDrawLine; @@ -150,7 +155,8 @@ public class GLCanvasImpl implements GLCanvas { xyBuffer.put(BOX_COORDINATES, 0, BOX_COORDINATES.length).position(0); int[] name = new int[1]; - GLId.glGenBuffers(1, name, 0); + GLId glId = getGLId(); + glId.glGenBuffers(1, name, 0); mBoxCoords = name[0]; gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, mBoxCoords); @@ -683,11 +689,6 @@ public class GLCanvasImpl implements GLCanvas { } } - @Override - public GL11 getGLInstance() { - return mGL; - } - @Override public void clearBuffer(float[] argb) { if(argb != null && argb.length == 4) { @@ -748,14 +749,15 @@ public class GLCanvasImpl implements GLCanvas { public void deleteRecycledResources() { synchronized (mUnboundTextures) { IntArray ids = mUnboundTextures; + GLId glId = getGLId(); if (ids.size() > 0) { - GLId.glDeleteTextures(mGL, ids.size(), ids.getInternalArray(), 0); + glId.glDeleteTextures(mGL, ids.size(), ids.getInternalArray(), 0); ids.clear(); } ids = mDeleteBuffers; if (ids.size() > 0) { - GLId.glDeleteBuffers(mGL, ids.size(), ids.getInternalArray(), 0); + glId.glDeleteBuffers(mGL, ids.size(), ids.getInternalArray(), 0); ids.clear(); } } @@ -776,6 +778,11 @@ public class GLCanvasImpl implements GLCanvas { config.mAlpha = -1; } + if ((saveFlags & SAVE_FLAG_BLEND) != 0) { + config.mBlending = mBlending; + } else { + config.mBlending = null; + } if ((saveFlags & SAVE_FLAG_MATRIX) != 0) { System.arraycopy(mMatrixValues, 0, config.mMatrix, 0, 16); @@ -811,6 +818,7 @@ public class GLCanvasImpl implements GLCanvas { private static class ConfigState { float mAlpha; float mMatrix[] = new float[16]; + Blending mBlending; ConfigState mNextFree; public void restore(GLCanvasImpl canvas) { @@ -818,6 +826,9 @@ public class GLCanvasImpl implements GLCanvas { if (mMatrix[0] != Float.NEGATIVE_INFINITY) { System.arraycopy(mMatrix, 0, canvas.mMatrixValues, 0, 16); } + if (mBlending != null) { + canvas.setBlending(mBlending); + } } } @@ -847,7 +858,8 @@ public class GLCanvasImpl implements GLCanvas { GL11ExtensionPack gl11ep = (GL11ExtensionPack) mGL; if (mTargetTexture == null && texture != null) { - GLId.glGenBuffers(1, mFrameBuffer, 0); + GLId glId = getGLId(); + glId.glGenBuffers(1, mFrameBuffer, 0); gl11ep.glBindFramebufferOES( GL11ExtensionPack.GL_FRAMEBUFFER_OES, mFrameBuffer[0]); } @@ -917,4 +929,113 @@ public class GLCanvasImpl implements GLCanvas { throw new RuntimeException(msg + ":" + Integer.toHexString(status)); } } + + @Override + public void setTextureParameters(BasicTexture texture) { + int width = texture.getWidth(); + int height = texture.getHeight(); + // 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] = height; + sCropRect[2] = width; + sCropRect[3] = -height; + + // Set texture parameters. + int target = texture.getTarget(); + mGL.glBindTexture(target, texture.getId()); + mGL.glTexParameterfv(target, GL11Ext.GL_TEXTURE_CROP_RECT_OES, sCropRect, 0); + mGL.glTexParameteri(target, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP_TO_EDGE); + mGL.glTexParameteri(target, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP_TO_EDGE); + mGL.glTexParameterf(target, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); + mGL.glTexParameterf(target, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); + } + + @Override + public void initializeTextureSize(BasicTexture texture, int format, int type) { + int target = texture.getTarget(); + mGL.glBindTexture(target, texture.getId()); + int width = texture.getTextureWidth(); + int height = texture.getTextureHeight(); + mGL.glTexImage2D(target, 0, format, width, height, 0, format, type, null); + } + + @Override + public void initializeTexture(BasicTexture texture, Bitmap bitmap) { + int target = texture.getTarget(); + mGL.glBindTexture(target, texture.getId()); + GLUtils.texImage2D(target, 0, bitmap, 0); + } + + @Override + public void texSubImage2D(BasicTexture texture, int xOffset, int yOffset, Bitmap bitmap, + int format, int type) { + int target = texture.getTarget(); + mGL.glBindTexture(target, texture.getId()); + GLUtils.texSubImage2D(target, 0, xOffset, yOffset, bitmap, format, type); + } + + @Override + public int[] uploadBuffers(Buffer[] buffers) { + int[] bufferIds = new int[buffers.length]; + GLId glId = getGLId(); + glId.glGenBuffers(bufferIds.length, bufferIds, 0); + + for (int i = 0; i < bufferIds.length; i++) { + Buffer buf = buffers[i]; + int elementSize = 0; + if (buf instanceof FloatBuffer) { + elementSize = Float.SIZE / Byte.SIZE; + } else if (buf instanceof ByteBuffer) { + elementSize = 1; + } else { + Utils.fail("Unknown element size for %s", buf.getClass().getSimpleName()); + } + mGL.glBindBuffer(GL11.GL_ARRAY_BUFFER, bufferIds[i]); + mGL.glBufferData(GL11.GL_ARRAY_BUFFER, buf.capacity() * elementSize, buf, + GL11.GL_STATIC_DRAW); + } + + return bufferIds; + } + + @Override + public void setBlending(Blending blending) { + if (mBlending == blending) { + return; + } + Utils.assertTrue(blending == Blending.Additive || blending == Blending.Mix); + mBlending = blending; + int srcFunc = GL11.GL_ONE; + int dstFunc = (blending == Blending.Additive) ? GL11.GL_ONE : GL11.GL_ONE_MINUS_SRC_ALPHA; + mGL.glBlendFunc(srcFunc, dstFunc); + } + + @Override + public void enableStencil() { + mGL.glEnable(GL11.GL_STENCIL_TEST); + } + + @Override + public void disableStencil() { + mGL.glDisable(GL11.GL_STENCIL_TEST); + } + + @Override + public void clearStencilBuffer() { + mGL.glClear(GL11.GL_STENCIL_BUFFER_BIT); + } + + @Override + public void updateStencil(boolean update) { + int passOp = update ? GL11.GL_REPLACE : GL11.GL_KEEP; + mGL.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, passOp); + } + + @Override + public void drawOnlyOutsideStencil(boolean onlyOutside) { + int func = onlyOutside ? GL11.GL_NOTEQUAL : GL11.GL_ALWAYS; + mGL.glStencilFunc(func, 1, 1); + } } diff --git a/src/com/android/gallery3d/ui/GLId.java b/src/com/android/gallery3d/ui/GLId.java index 689cf192e..04977c337 100644 --- a/src/com/android/gallery3d/ui/GLId.java +++ b/src/com/android/gallery3d/ui/GLId.java @@ -20,31 +20,14 @@ import javax.microedition.khronos.opengles.GL11; import javax.microedition.khronos.opengles.GL11ExtensionPack; // This mimics corresponding GL functions. -public class GLId { - static int sNextId = 1; +public interface GLId { + public int generateTexture(); - public synchronized static void glGenTextures(int n, int[] textures, int offset) { - while (n-- > 0) { - textures[offset + n] = sNextId++; - } - } + public void glGenBuffers(int n, int[] buffers, int offset); - public synchronized static void glGenBuffers(int n, int[] buffers, int offset) { - while (n-- > 0) { - buffers[offset + n] = sNextId++; - } - } + public void glDeleteTextures(GL11 gl, int n, int[] textures, int offset); - public synchronized static void glDeleteTextures(GL11 gl, int n, int[] textures, int offset) { - gl.glDeleteTextures(n, textures, offset); - } + public void glDeleteBuffers(GL11 gl, int n, int[] buffers, int offset); - public synchronized static void glDeleteBuffers(GL11 gl, int n, int[] buffers, int offset) { - gl.glDeleteBuffers(n, buffers, offset); - } - - public synchronized static void glDeleteFramebuffers( - GL11ExtensionPack gl11ep, int n, int[] buffers, int offset) { - gl11ep.glDeleteFramebuffersOES(n, buffers, offset); - } + public void glDeleteFramebuffers(GL11ExtensionPack gl11ep, int n, int[] buffers, int offset); } diff --git a/src/com/android/gallery3d/ui/GLIdImpl.java b/src/com/android/gallery3d/ui/GLIdImpl.java new file mode 100644 index 000000000..7a0232bf0 --- /dev/null +++ b/src/com/android/gallery3d/ui/GLIdImpl.java @@ -0,0 +1,68 @@ +/* + * 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 javax.microedition.khronos.opengles.GL11; +import javax.microedition.khronos.opengles.GL11ExtensionPack; + +/** + * Open GL ES 1.1 implementation for generating and destroying texture IDs and + * buffer IDs + */ +public class GLIdImpl implements GLId { + private static int sNextId = 1; + // Mutex for sNextId + private static Object sLock = new Object(); + + @Override + public int generateTexture() { + synchronized (sLock) { + return sNextId++; + } + } + + @Override + public void glGenBuffers(int n, int[] buffers, int offset) { + synchronized (sLock) { + while (n-- > 0) { + buffers[offset + n] = sNextId++; + } + } + } + + @Override + public void glDeleteTextures(GL11 gl, int n, int[] textures, int offset) { + synchronized (sLock) { + gl.glDeleteTextures(n, textures, offset); + } + } + + @Override + public void glDeleteBuffers(GL11 gl, int n, int[] buffers, int offset) { + synchronized (sLock) { + gl.glDeleteBuffers(n, buffers, offset); + } + } + + @Override + public void glDeleteFramebuffers(GL11ExtensionPack gl11ep, int n, int[] buffers, int offset) { + synchronized (sLock) { + gl11ep.glDeleteFramebuffersOES(n, buffers, offset); + } + } + + +} diff --git a/src/com/android/gallery3d/ui/NinePatchTexture.java b/src/com/android/gallery3d/ui/NinePatchTexture.java index fa0e9cdc3..b60504c76 100644 --- a/src/com/android/gallery3d/ui/NinePatchTexture.java +++ b/src/com/android/gallery3d/ui/NinePatchTexture.java @@ -23,12 +23,11 @@ import android.graphics.Rect; import com.android.gallery3d.common.Utils; +import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; -import javax.microedition.khronos.opengles.GL11; - // NinePatchTexture is a texture backed by a NinePatch resource. // // getPaddings() returns paddings specified in the NinePatch. @@ -396,24 +395,10 @@ class NinePatchInstance { } private void prepareBuffers(GLCanvas canvas) { - mBufferNames = new int[3]; - GL11 gl = canvas.getGLInstance(); - GLId.glGenBuffers(3, mBufferNames, 0); - - gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, mBufferNames[0]); - gl.glBufferData(GL11.GL_ARRAY_BUFFER, - mXyBuffer.capacity() * (Float.SIZE / Byte.SIZE), - mXyBuffer, GL11.GL_STATIC_DRAW); - - gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, mBufferNames[1]); - gl.glBufferData(GL11.GL_ARRAY_BUFFER, - mUvBuffer.capacity() * (Float.SIZE / Byte.SIZE), - mUvBuffer, GL11.GL_STATIC_DRAW); - - gl.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, mBufferNames[2]); - gl.glBufferData(GL11.GL_ELEMENT_ARRAY_BUFFER, - mIndexBuffer.capacity(), - mIndexBuffer, GL11.GL_STATIC_DRAW); + Buffer[] buffers = { + mXyBuffer, mUvBuffer, mIndexBuffer + }; + mBufferNames = canvas.uploadBuffers(buffers); // These buffers are never used again. mXyBuffer = null; diff --git a/src/com/android/gallery3d/ui/RawTexture.java b/src/com/android/gallery3d/ui/RawTexture.java index 4c0d9d365..e67848f41 100644 --- a/src/com/android/gallery3d/ui/RawTexture.java +++ b/src/com/android/gallery3d/ui/RawTexture.java @@ -17,19 +17,17 @@ 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); + GLId glId = GLCanvas.getGLId(); + mId = glId.generateTexture(); } @Override @@ -38,36 +36,8 @@ public class RawTexture extends BasicTexture { } 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]; + canvas.setTextureParameters(this); + canvas.initializeTextureSize(this, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE); mState = STATE_LOADED; setAssociatedCanvas(canvas); } diff --git a/src/com/android/gallery3d/ui/SlideshowView.java b/src/com/android/gallery3d/ui/SlideshowView.java index bb36c47e9..7734eb236 100644 --- a/src/com/android/gallery3d/ui/SlideshowView.java +++ b/src/com/android/gallery3d/ui/SlideshowView.java @@ -21,11 +21,10 @@ import android.graphics.PointF; import com.android.gallery3d.anim.CanvasAnimation; import com.android.gallery3d.anim.FloatAnimation; +import com.android.gallery3d.ui.GLCanvas.Blending; import java.util.Random; -import javax.microedition.khronos.opengles.GL11; - public class SlideshowView extends GLView { @SuppressWarnings("unused") private static final String TAG = "SlideshowView"; @@ -93,8 +92,8 @@ public class SlideshowView extends GLView { protected void render(GLCanvas canvas) { long animTime = AnimationTime.get(); boolean requestRender = mTransitionAnimation.calculate(animTime); - GL11 gl = canvas.getGLInstance(); - gl.glBlendFunc(GL11.GL_ONE, GL11.GL_ONE); + canvas.save(GLCanvas.SAVE_FLAG_BLEND); + canvas.setBlending(Blending.Additive); float alpha = mPrevTexture == null ? 1f : mTransitionAnimation.get(); if (mPrevTexture != null && alpha != 1f) { @@ -118,7 +117,7 @@ public class SlideshowView extends GLView { canvas.restore(); } if (requestRender) invalidate(); - gl.glBlendFunc(GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + canvas.restore(); } private class SlideshowAnimation extends CanvasAnimation { diff --git a/src/com/android/gallery3d/ui/UploadedTexture.java b/src/com/android/gallery3d/ui/UploadedTexture.java index bb86d05ef..470ee6a98 100644 --- a/src/com/android/gallery3d/ui/UploadedTexture.java +++ b/src/com/android/gallery3d/ui/UploadedTexture.java @@ -25,7 +25,6 @@ import com.android.gallery3d.common.Utils; import java.util.HashMap; import javax.microedition.khronos.opengles.GL11; -import javax.microedition.khronos.opengles.GL11Ext; // UploadedTextures use a Bitmap for the content of the texture. // @@ -194,9 +193,7 @@ abstract class UploadedTexture extends BasicTexture { Bitmap bitmap = getBitmap(); int format = GLUtils.getInternalFormat(bitmap); int type = GLUtils.getType(bitmap); - canvas.getGLInstance().glBindTexture(GL11.GL_TEXTURE_2D, mId); - GLUtils.texSubImage2D(GL11.GL_TEXTURE_2D, 0, mBorder, mBorder, - bitmap, format, type); + canvas.texSubImage2D(this, mBorder, mBorder, bitmap, format, type); freeBitmap(); mContentValid = true; } @@ -210,11 +207,7 @@ abstract class UploadedTexture extends BasicTexture { return sUploadedCount > UPLOAD_LIMIT; } - static int[] sTextureId = new int[1]; - static float[] sCropRect = new float[4]; - private void uploadToCanvas(GLCanvas canvas) { - GL11 gl = canvas.getGLInstance(); Bitmap bitmap = getBitmap(); if (bitmap != null) { @@ -228,65 +221,40 @@ abstract class UploadedTexture extends BasicTexture { Utils.assertTrue(bWidth <= texWidth && bHeight <= texHeight); - // 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] = mBorder; - sCropRect[1] = mBorder + bHeight; - sCropRect[2] = bWidth; - sCropRect[3] = -bHeight; - // 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); + mId = GLCanvas.getGLId().generateTexture(); + canvas.setTextureParameters(this); if (bWidth == texWidth && bHeight == texHeight) { - GLUtils.texImage2D(GL11.GL_TEXTURE_2D, 0, bitmap, 0); + canvas.initializeTexture(this, bitmap); } else { int format = GLUtils.getInternalFormat(bitmap); int type = GLUtils.getType(bitmap); Config config = bitmap.getConfig(); - gl.glTexImage2D(GL11.GL_TEXTURE_2D, 0, format, - texWidth, texHeight, 0, format, type, null); - GLUtils.texSubImage2D(GL11.GL_TEXTURE_2D, 0, - mBorder, mBorder, bitmap, format, type); + canvas.initializeTextureSize(this, format, type); + canvas.texSubImage2D(this, mBorder, mBorder, bitmap, format, type); if (mBorder > 0) { // Left border Bitmap line = getBorderLine(true, config, texHeight); - GLUtils.texSubImage2D(GL11.GL_TEXTURE_2D, 0, - 0, 0, line, format, type); + canvas.texSubImage2D(this, 0, 0, line, format, type); // Top border line = getBorderLine(false, config, texWidth); - GLUtils.texSubImage2D(GL11.GL_TEXTURE_2D, 0, - 0, 0, line, format, type); + canvas.texSubImage2D(this, 0, 0, line, format, type); } // Right border if (mBorder + bWidth < texWidth) { Bitmap line = getBorderLine(true, config, texHeight); - GLUtils.texSubImage2D(GL11.GL_TEXTURE_2D, 0, - mBorder + bWidth, 0, line, format, type); + canvas.texSubImage2D(this, mBorder + bWidth, 0, line, format, type); } // Bottom border if (mBorder + bHeight < texHeight) { Bitmap line = getBorderLine(false, config, texWidth); - GLUtils.texSubImage2D(GL11.GL_TEXTURE_2D, 0, - 0, mBorder + bHeight, line, format, type); + canvas.texSubImage2D(this, 0, mBorder + bHeight, line, format, type); } } } finally { @@ -294,7 +262,6 @@ abstract class UploadedTexture extends BasicTexture { } // Update texture state. setAssociatedCanvas(canvas); - mId = sTextureId[0]; mState = STATE_LOADED; mContentValid = true; } else { -- cgit v1.2.3