Fix the issue that mixed textures cannot be drawn correctly when
alpha is set.
Change-Id: Ibd90e9c9309bd5ef2ea86725b3d3f3ab689727ec
diff --git a/new3d/src/com/android/gallery3d/ui/GLCanvasImp.java b/new3d/src/com/android/gallery3d/ui/GLCanvasImp.java
index 820c1e7..ed43e84 100644
--- a/new3d/src/com/android/gallery3d/ui/GLCanvasImp.java
+++ b/new3d/src/com/android/gallery3d/ui/GLCanvasImp.java
@@ -4,7 +4,6 @@
import android.graphics.RectF;
import android.opengl.GLU;
import android.opengl.Matrix;
-import android.util.Log;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@@ -16,6 +15,7 @@
import javax.microedition.khronos.opengles.GL11Ext;
public class GLCanvasImp implements GLCanvas {
+ @SuppressWarnings("unused")
private static final String TAG = "GLCanvasImp";
// We need 16 vertices for a normal nine-patch image (the 4x4 vertices)
@@ -28,7 +28,6 @@
private final GL11 mGL;
- private final int mTextureId[] = new int[1];
private final float mMatrixValues[] = new float[16];
private final float mUvBuffer[] = new float[VERTEX_BUFFER_SIZE];
@@ -55,9 +54,9 @@
new Stack<ConfigState>();
private ConfigState mRecycledRestoreAction;
- private RectF mDrawTextureSourceRect = new RectF();
- private RectF mDrawTextureTargetRect = new RectF();
- private float[] mTempMatrix = new float[32];
+ private final RectF mDrawTextureSourceRect = new RectF();
+ private final RectF mDrawTextureTargetRect = new RectF();
+ private final float[] mTempMatrix = new float[32];
private final IntArray mUnboundIds = new IntArray();
GLCanvasImp(GL11 gl) {
@@ -183,8 +182,7 @@
System.arraycopy(temp, 16, mMatrixValues, 0, 16);
}
- private void textureRect(float x, float y, float width, float height, float alpha) {
- mGLState.setTextureAlpha(alpha);
+ private void textureRect(float x, float y, float width, float height) {
GL11 gl = mGL;
gl.glLoadMatrixf(mMatrixValues, 0);
putRectangle(x, y, width, height, mXyBuffer, mXyPointer);
@@ -416,7 +414,7 @@
}
private void drawBoundTexture(
- BasicTexture texture, int x, int y, int width, int height, float alpha) {
+ BasicTexture texture, int x, int y, int width, int height) {
// Test whether it has been rotated or flipped, if so, glDrawTexiOES
// won't work
if (isMatrixRotatedOrFlipped(mMatrixValues)) {
@@ -424,7 +422,7 @@
(texture.mWidth - 0.5f) / texture.mTextureWidth,
(texture.mHeight - 0.5f) / texture.mTextureHeight,
mUvBuffer, mUvPointer);
- textureRect(x, y, width, height, alpha);
+ textureRect(x, y, width, height);
} else {
// draw the rect from bottom-left to top-right
float points[] = mapPoints(
@@ -433,12 +431,10 @@
y = (int) points[1];
width = (int) points[2] - x;
height = (int) points[3] - y;
- mGLState.setTextureAlpha(alpha);
if (width > 0 && height > 0) {
((GL11Ext) mGL).glDrawTexiOES(x, y, 0, width, height);
}
}
-
}
public void drawTexture(
@@ -452,7 +448,8 @@
mGLState.setBlendEnabled(!texture.isOpaque() || alpha < OPAQUE_ALPHA);
bindTexture(texture);
- drawBoundTexture(texture, x, y, width, height, alpha);
+ mGLState.setTextureAlpha(alpha);
+ drawBoundTexture(texture, x, y, width, height);
}
public void drawTexture(BasicTexture texture, RectF source, RectF target) {
@@ -468,8 +465,8 @@
bindTexture(texture);
convertCoordinate(source, target, texture);
setTextureCoords(source);
- textureRect(target.left, target.top, target.right - target.left,
- target.bottom - target.top, mAlpha);
+ mGLState.setTextureAlpha(mAlpha);
+ textureRect(target.left, target.top, target.width(), target.height());
}
// This function changes the source coordinate to the texture coordinates.
@@ -527,14 +524,30 @@
public void drawMixed(BasicTexture from, BasicTexture to,
float ratio, int x, int y, int width, int height, float alpha) {
- if (alpha < OPAQUE_ALPHA) {
- throw new RuntimeException("Cannot support alpha value");
- }
- mGLState.setBlendEnabled(!from.isOpaque() || !to.isOpaque());
+ mGLState.setBlendEnabled(!from.isOpaque()
+ || !to.isOpaque() || alpha < OPAQUE_ALPHA);
final GL11 gl = mGL;
bindTexture(from);
+ //
+ // The formula we want:
+ // alpha * ((1 - ratio) * from + ratio * to)
+ // The formula that GL supports is in the form of:
+ // (1 - combo) * (modulate * from) + combo * to
+ //
+ // So, we have combo = alpha * ratio
+ // and modulate = alpha * (1f - ratio) / (1 - combo)
+ //
+ float comboRatio = alpha * ratio;
+
+ // handle the case that (1 - comboRatio) == 0
+ if (alpha < OPAQUE_ALPHA) {
+ mGLState.setTextureAlpha(alpha * (1f - ratio) / (1f - comboRatio));
+ } else {
+ mGLState.setTextureAlpha(1f);
+ }
+
gl.glActiveTexture(GL11.GL_TEXTURE1);
bindTexture(to);
gl.glEnable(GL11.GL_TEXTURE_2D);
@@ -546,7 +559,8 @@
// Specify the interpolation factor via the alpha component of
// GL_TEXTURE_ENV_COLORs.
- setTextureColor(ratio, ratio, ratio, ratio);
+ // We don't use the RGB color, so just give them 0s.
+ setTextureColor(0, 0, 0, comboRatio);
gl.glTexEnvfv(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_COLOR, mTextureColor, 0);
// Wire up the interpolation factor for RGB.
@@ -558,7 +572,7 @@
gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_OPERAND2_ALPHA, GL11.GL_SRC_ALPHA);
// Draw the combined texture.
- drawBoundTexture(to, x, y, width, height, alpha);
+ drawBoundTexture(to, x, y, width, height);
// Disable TEXTURE1.
gl.glDisable(GL11.GL_TEXTURE_2D);
@@ -645,9 +659,7 @@
// Enable used features
gl.glEnable(GL11.GL_DITHER);
-
gl.glEnable(GL11.GL_SCISSOR_TEST);
- gl.glEnable(GL11.GL_STENCIL_TEST);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
diff --git a/new3d/src/com/android/gallery3d/ui/PopupWindow.java b/new3d/src/com/android/gallery3d/ui/PopupWindow.java
index c08c46d..784d046 100644
--- a/new3d/src/com/android/gallery3d/ui/PopupWindow.java
+++ b/new3d/src/com/android/gallery3d/ui/PopupWindow.java
@@ -123,6 +123,7 @@
int aYoffset = height - aHeight;
GL11 gl = canvas.getGLInstance();
if (mAnchor != null) {
+ gl.glEnable(GL11.GL_STENCIL_TEST);
gl.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_REPLACE);
gl.glStencilFunc(GL11.GL_ALWAYS, 1, 1);
mAnchor.draw(canvas, aXoffset, aYoffset);
@@ -134,6 +135,10 @@
mBackground.draw(canvas, 0, 0,
width, height - aHeight + mAnchorOffset);
}
+
+ if (mAnchor != null) {
+ gl.glDisable(GL11.GL_STENCIL_TEST);
+ }
}
private void renderBackgroundWithoutStencil(GLCanvas canvas) {
diff --git a/new3d/tests/src/com/android/gallery3d/ui/GLCanvasTest.java b/new3d/tests/src/com/android/gallery3d/ui/GLCanvasTest.java
index 020f5e9..46fae89 100644
--- a/new3d/tests/src/com/android/gallery3d/ui/GLCanvasTest.java
+++ b/new3d/tests/src/com/android/gallery3d/ui/GLCanvasTest.java
@@ -5,7 +5,6 @@
import junit.framework.TestCase;
-import java.nio.Buffer;
import java.util.Arrays;
import javax.microedition.khronos.opengles.GL10;
@@ -211,7 +210,7 @@
// are used directly.
private static class FillRectTest extends GLMock {
private int mDrawArrayCalled = 0;
- private int[] mResult = new int[8];
+ private final int[] mResult = new int[8];
@Override
public void glDrawArrays(int mode, int first, int count) {
@@ -279,8 +278,8 @@
// The matrix here are all listed in column major order.
//
private static class TransformTest extends GLMock {
- private float[] mModelViewMatrixUsed = new float[16];
- private float[] mProjectionMatrixUsed = new float[16];
+ private final float[] mModelViewMatrixUsed = new float[16];
+ private final float[] mProjectionMatrixUsed = new float[16];
@Override
public void glDrawArrays(int mode, int first, int count) {
@@ -498,6 +497,7 @@
mIsOpaque = isOpaque;
}
+ @Override
protected void onBind(GLCanvas canvas) {
mBindCalled++;
}
@@ -664,9 +664,7 @@
@Override
public void glTexEnvfv(int target, int pname, float[] params, int offset) {
if (target == GL_TEXTURE_ENV && pname == GL_TEXTURE_ENV_COLOR) {
- for (int i = 0; i < 4; i++) {
- assertEquals(0.5f, params[offset + i]);
- }
+ assertEquals(0.5f, params[offset + 3]);
}
}
@@ -701,9 +699,9 @@
assertFalse(mTexture2DEnabled1);
// The test is currently broken, waiting for the fix
- //canvas.setAlpha(0.3f);
- //canvas.drawMixed(from, to, 0.5f, 100, 200, 300, 400, 1.0f);
- //assertEquals(GL_COMBINE, getTexEnvi(GL_TEXTURE_ENV_MODE));
+ canvas.setAlpha(0.3f);
+ canvas.drawMixed(from, to, 0.5f, 100, 200, 300, 400, 1.0f);
+ assertEquals(GL_COMBINE, getTexEnvi(GL_TEXTURE_ENV_MODE));
}
}