diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 8fb85d22c..e09a9e938 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -19,6 +19,8 @@
+
+
mTargetStack = new ArrayList();
-
- private float mAlpha;
- private final ArrayList mRestoreStack = new ArrayList();
- private ConfigState mRecycledRestoreAction;
-
- private final RectF mDrawTextureSourceRect = new RectF();
- private final RectF mDrawTextureTargetRect = new RectF();
- private final float[] mTempMatrix = new float[32];
- private final IntArray mUnboundTextures = new IntArray();
- private final IntArray mDeleteBuffers = new IntArray();
- private int mScreenWidth;
- private int mScreenHeight;
- private boolean mBlendEnabled = true;
- private int mFrameBuffer[] = new int[1];
- private static float[] sCropRect = new float[4];
-
- private RawTexture mTargetTexture;
-
- // Drawing statistics
- int mCountDrawLine;
- int mCountFillRect;
- int mCountDrawMesh;
- int mCountTextureRect;
- int mCountTextureOES;
-
- private static GLId mGLId = new GLES11IdImpl();
-
- public GLES11Canvas(GL11 gl) {
- mGL = gl;
- mGLState = new GLState(gl);
- // First create an nio buffer, then create a VBO from it.
- int size = BOX_COORDINATES.length * Float.SIZE / Byte.SIZE;
- FloatBuffer xyBuffer = allocateDirectNativeOrderBuffer(size).asFloatBuffer();
- xyBuffer.put(BOX_COORDINATES, 0, BOX_COORDINATES.length).position(0);
-
- int[] name = new int[1];
- mGLId.glGenBuffers(1, name, 0);
- mBoxCoords = name[0];
-
- gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, mBoxCoords);
- gl.glBufferData(GL11.GL_ARRAY_BUFFER, xyBuffer.capacity() * (Float.SIZE / Byte.SIZE),
- xyBuffer, GL11.GL_STATIC_DRAW);
-
- gl.glVertexPointer(2, GL11.GL_FLOAT, 0, 0);
- gl.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 0);
-
- // Enable the texture coordinate array for Texture 1
- gl.glClientActiveTexture(GL11.GL_TEXTURE1);
- gl.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 0);
- gl.glClientActiveTexture(GL11.GL_TEXTURE0);
- gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
-
- // mMatrixValues and mAlpha will be initialized in setSize()
- }
-
- @Override
- public void setSize(int width, int height) {
- Assert.assertTrue(width >= 0 && height >= 0);
-
- if (mTargetTexture == null) {
- mScreenWidth = width;
- mScreenHeight = height;
- }
- mAlpha = 1.0f;
-
- GL11 gl = mGL;
- gl.glViewport(0, 0, width, height);
- gl.glMatrixMode(GL11.GL_PROJECTION);
- gl.glLoadIdentity();
- GLU.gluOrtho2D(gl, 0, width, 0, height);
-
- gl.glMatrixMode(GL11.GL_MODELVIEW);
- gl.glLoadIdentity();
-
- float matrix[] = mMatrixValues;
- Matrix.setIdentityM(matrix, 0);
- // 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);
- }
- }
-
- @Override
- public void setAlpha(float alpha) {
- Assert.assertTrue(alpha >= 0 && alpha <= 1);
- mAlpha = alpha;
- }
-
- @Override
- public float getAlpha() {
- return mAlpha;
- }
-
- @Override
- public void multiplyAlpha(float alpha) {
- Assert.assertTrue(alpha >= 0 && alpha <= 1);
- mAlpha *= alpha;
- }
-
- private static ByteBuffer allocateDirectNativeOrderBuffer(int size) {
- return ByteBuffer.allocateDirect(size).order(ByteOrder.nativeOrder());
- }
-
- @Override
- public void drawRect(float x, float y, float width, float height, GLPaint paint) {
- GL11 gl = mGL;
-
- mGLState.setColorMode(paint.getColor(), mAlpha);
- mGLState.setLineWidth(paint.getLineWidth());
-
- saveTransform();
- translate(x, y);
- scale(width, height, 1);
-
- gl.glLoadMatrixf(mMatrixValues, 0);
- gl.glDrawArrays(GL11.GL_LINE_LOOP, OFFSET_DRAW_RECT, 4);
-
- restoreTransform();
- mCountDrawLine++;
- }
-
- @Override
- public void drawOval(float cx, float cy, float radiusX, float radiusY, GLPaint paint) {
- // TODO
- }
-
- @Override
- public void drawArc(float cx, float cy, float radiusX, float radiusY, float sweepAngle, GLPaint paint) {
- // TODO
- }
-
- @Override
- public void drawLine(float x1, float y1, float x2, float y2, GLPaint paint) {
- GL11 gl = mGL;
-
- mGLState.setColorMode(paint.getColor(), mAlpha);
- mGLState.setLineWidth(paint.getLineWidth());
-
- saveTransform();
- translate(x1, y1);
- scale(x2 - x1, y2 - y1, 1);
-
- gl.glLoadMatrixf(mMatrixValues, 0);
- gl.glDrawArrays(GL11.GL_LINE_STRIP, OFFSET_DRAW_LINE, 2);
-
- restoreTransform();
- mCountDrawLine++;
- }
-
- @Override
- public void fillRect(float x, float y, float width, float height, int color) {
- mGLState.setColorMode(color, mAlpha);
- GL11 gl = mGL;
-
- saveTransform();
- translate(x, y);
- scale(width, height, 1);
-
- gl.glLoadMatrixf(mMatrixValues, 0);
- gl.glDrawArrays(GL11.GL_TRIANGLE_STRIP, OFFSET_FILL_RECT, 4);
-
- restoreTransform();
- mCountFillRect++;
- }
-
- @Override
- public void fillOval(float x, float y, float width, float height, int color) {
- // TODO
- }
-
- @Override
- public void fillSector(float cx, float cy, float radiusX, float radiusY, float sweepAngle, int color) {
- // TODO
- }
-
- @Override
- public void translate(float x, float y, float z) {
- Matrix.translateM(mMatrixValues, 0, x, y, z);
- }
-
- // This is a faster version of translate(x, y, z) because
- // (1) we knows z = 0, (2) we inline the Matrix.translateM call,
- // (3) we unroll the loop
- @Override
- public void translate(float x, float y) {
- float[] m = mMatrixValues;
- m[12] += m[0] * x + m[4] * y;
- m[13] += m[1] * x + m[5] * y;
- m[14] += m[2] * x + m[6] * y;
- m[15] += m[3] * x + m[7] * y;
- }
-
- @Override
- public void scale(float sx, float sy, float sz) {
- Matrix.scaleM(mMatrixValues, 0, sx, sy, sz);
- }
-
- @Override
- public void rotate(float angle, float x, float y, float z) {
- if (angle == 0) return;
- float[] temp = mTempMatrix;
- Matrix.setRotateM(temp, 0, angle, x, y, z);
- Matrix.multiplyMM(temp, 16, mMatrixValues, 0, temp, 0);
- System.arraycopy(temp, 16, mMatrixValues, 0, 16);
- }
-
- @Override
- public void multiplyMatrix(float matrix[], int offset) {
- float[] temp = mTempMatrix;
- Matrix.multiplyMM(temp, 0, mMatrixValues, 0, matrix, offset);
- System.arraycopy(temp, 0, mMatrixValues, 0, 16);
- }
-
- private void textureRect(float x, float y, float width, float height) {
- GL11 gl = mGL;
-
- saveTransform();
- translate(x, y);
- scale(width, height, 1);
-
- gl.glLoadMatrixf(mMatrixValues, 0);
- gl.glDrawArrays(GL11.GL_TRIANGLE_STRIP, OFFSET_FILL_RECT, 4);
-
- restoreTransform();
- mCountTextureRect++;
- }
-
- @Override
- public void drawMesh(BasicTexture tex, int x, int y, int xyBuffer,
- int uvBuffer, int indexBuffer, int indexCount) {
- float alpha = mAlpha;
- if (!bindTexture(tex)) return;
-
- mGLState.setBlendEnabled(mBlendEnabled
- && (!tex.isOpaque() || alpha < OPAQUE_ALPHA));
- mGLState.setTextureAlpha(alpha);
-
- // Reset the texture matrix. We will set our own texture coordinates
- // below.
- setTextureCoords(0, 0, 1, 1);
-
- saveTransform();
- translate(x, y);
-
- mGL.glLoadMatrixf(mMatrixValues, 0);
-
- mGL.glBindBuffer(GL11.GL_ARRAY_BUFFER, xyBuffer);
- mGL.glVertexPointer(2, GL11.GL_FLOAT, 0, 0);
-
- mGL.glBindBuffer(GL11.GL_ARRAY_BUFFER, uvBuffer);
- mGL.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 0);
-
- mGL.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
- mGL.glDrawElements(GL11.GL_TRIANGLE_STRIP,
- indexCount, GL11.GL_UNSIGNED_BYTE, 0);
-
- mGL.glBindBuffer(GL11.GL_ARRAY_BUFFER, mBoxCoords);
- mGL.glVertexPointer(2, GL11.GL_FLOAT, 0, 0);
- mGL.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 0);
-
- restoreTransform();
- mCountDrawMesh++;
- }
-
- // Transforms two points by the given matrix m. The result
- // {x1', y1', x2', y2'} are stored in mMapPointsBuffer and also returned.
- private float[] mapPoints(float m[], int x1, int y1, int x2, int y2) {
- float[] r = mMapPointsBuffer;
-
- // Multiply m and (x1 y1 0 1) to produce (x3 y3 z3 w3). z3 is unused.
- float x3 = m[0] * x1 + m[4] * y1 + m[12];
- float y3 = m[1] * x1 + m[5] * y1 + m[13];
- float w3 = m[3] * x1 + m[7] * y1 + m[15];
- r[0] = x3 / w3;
- r[1] = y3 / w3;
-
- // Same for x2 y2.
- float x4 = m[0] * x2 + m[4] * y2 + m[12];
- float y4 = m[1] * x2 + m[5] * y2 + m[13];
- float w4 = m[3] * x2 + m[7] * y2 + m[15];
- r[2] = x4 / w4;
- r[3] = y4 / w4;
-
- return r;
- }
-
- private void drawBoundTexture(
- 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)) {
- if (texture.hasBorder()) {
- setTextureCoords(
- 1.0f / texture.getTextureWidth(),
- 1.0f / texture.getTextureHeight(),
- (texture.getWidth() - 1.0f) / texture.getTextureWidth(),
- (texture.getHeight() - 1.0f) / texture.getTextureHeight());
- } else {
- setTextureCoords(0, 0,
- (float) texture.getWidth() / texture.getTextureWidth(),
- (float) texture.getHeight() / texture.getTextureHeight());
- }
- textureRect(x, y, width, height);
- } else {
- // draw the rect from bottom-left to top-right
- float points[] = mapPoints(
- mMatrixValues, x, y + height, x + width, y);
- x = (int) (points[0] + 0.5f);
- y = (int) (points[1] + 0.5f);
- width = (int) (points[2] + 0.5f) - x;
- height = (int) (points[3] + 0.5f) - y;
- if (width > 0 && height > 0) {
- ((GL11Ext) mGL).glDrawTexiOES(x, y, 0, width, height);
- mCountTextureOES++;
- }
- }
- }
-
- @Override
- public void drawTexture(
- BasicTexture texture, int x, int y, int width, int height) {
- drawTexture(texture, x, y, width, height, mAlpha);
- }
-
- private void drawTexture(BasicTexture texture,
- int x, int y, int width, int height, float alpha) {
- if (width <= 0 || height <= 0) return;
-
- mGLState.setBlendEnabled(mBlendEnabled
- && (!texture.isOpaque() || alpha < OPAQUE_ALPHA));
- if (!bindTexture(texture)) return;
- mGLState.setTextureAlpha(alpha);
- drawBoundTexture(texture, x, y, width, height);
- }
-
- @Override
- public void drawTexture(BasicTexture texture, RectF source, RectF target) {
- if (target.width() <= 0 || target.height() <= 0) return;
-
- // Copy the input to avoid changing it.
- mDrawTextureSourceRect.set(source);
- mDrawTextureTargetRect.set(target);
- source = mDrawTextureSourceRect;
- target = mDrawTextureTargetRect;
-
- mGLState.setBlendEnabled(mBlendEnabled
- && (!texture.isOpaque() || mAlpha < OPAQUE_ALPHA));
- if (!bindTexture(texture)) return;
- convertCoordinate(source, target, texture);
- setTextureCoords(source);
- mGLState.setTextureAlpha(mAlpha);
- textureRect(target.left, target.top, target.width(), target.height());
- }
-
- @Override
- public void drawTexture(BasicTexture texture, float[] mTextureTransform,
- int x, int y, int w, int h) {
- mGLState.setBlendEnabled(mBlendEnabled
- && (!texture.isOpaque() || mAlpha < OPAQUE_ALPHA));
- if (!bindTexture(texture)) return;
- setTextureCoords(mTextureTransform);
- mGLState.setTextureAlpha(mAlpha);
- textureRect(x, y, w, h);
- }
-
- // This function changes the source coordinate to the texture coordinates.
- // It also clips the source and target coordinates if it is beyond the
- // bound of the texture.
- private static void convertCoordinate(RectF source, RectF target,
- BasicTexture texture) {
-
- int width = texture.getWidth();
- int height = texture.getHeight();
- int texWidth = texture.getTextureWidth();
- int texHeight = texture.getTextureHeight();
- // Convert to texture coordinates
- source.left /= texWidth;
- source.right /= texWidth;
- source.top /= texHeight;
- source.bottom /= texHeight;
-
- // Clip if the rendering range is beyond the bound of the texture.
- float xBound = (float) width / texWidth;
- if (source.right > xBound) {
- target.right = target.left + target.width() *
- (xBound - source.left) / source.width();
- source.right = xBound;
- }
- float yBound = (float) height / texHeight;
- if (source.bottom > yBound) {
- target.bottom = target.top + target.height() *
- (yBound - source.top) / source.height();
- source.bottom = yBound;
- }
- }
-
- @Override
- public void drawMixed(BasicTexture from,
- int toColor, float ratio, int x, int y, int w, int h) {
- drawMixed(from, toColor, ratio, x, y, w, h, mAlpha);
- }
-
- private boolean bindTexture(BasicTexture texture) {
- if (!texture.onBind(this)) return false;
- int target = texture.getTarget();
- mGLState.setTextureTarget(target);
- mGL.glBindTexture(target, texture.getId());
- return true;
- }
-
- private void setTextureColor(float r, float g, float b, float alpha) {
- float[] color = mTextureColor;
- color[0] = r;
- color[1] = g;
- color[2] = b;
- color[3] = alpha;
- }
-
- private void setMixedColor(int toColor, float ratio, float alpha) {
- //
- // The formula we want:
- // alpha * ((1 - ratio) * from + ratio * to)
- //
- // The formula that GL supports is in the form of:
- // combo * from + (1 - combo) * to * scale
- //
- // So, we have combo = alpha * (1 - ratio)
- // and scale = alpha * ratio / (1 - combo)
- //
- float combo = alpha * (1 - ratio);
- float scale = alpha * ratio / (1 - combo);
-
- // Specify the interpolation factor via the alpha component of
- // GL_TEXTURE_ENV_COLORs.
- // RGB component are get from toColor and will used as SRC1
- float colorScale = scale * (toColor >>> 24) / (0xff * 0xff);
- setTextureColor(((toColor >>> 16) & 0xff) * colorScale,
- ((toColor >>> 8) & 0xff) * colorScale,
- (toColor & 0xff) * colorScale, combo);
- GL11 gl = mGL;
- gl.glTexEnvfv(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_COLOR, mTextureColor, 0);
-
- gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_COMBINE_RGB, GL11.GL_INTERPOLATE);
- gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_COMBINE_ALPHA, GL11.GL_INTERPOLATE);
- gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_SRC1_RGB, GL11.GL_CONSTANT);
- gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_OPERAND1_RGB, GL11.GL_SRC_COLOR);
- gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_SRC1_ALPHA, GL11.GL_CONSTANT);
- gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_OPERAND1_ALPHA, GL11.GL_SRC_ALPHA);
-
- // Wire up the interpolation factor for RGB.
- gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_SRC2_RGB, GL11.GL_CONSTANT);
- gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_OPERAND2_RGB, GL11.GL_SRC_ALPHA);
-
- // Wire up the interpolation factor for alpha.
- gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_SRC2_ALPHA, GL11.GL_CONSTANT);
- gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_OPERAND2_ALPHA, GL11.GL_SRC_ALPHA);
-
- }
-
- @Override
- public void drawMixed(BasicTexture from, int toColor, float ratio,
- RectF source, RectF target) {
- if (target.width() <= 0 || target.height() <= 0) return;
-
- if (ratio <= 0.01f) {
- drawTexture(from, source, target);
- return;
- } else if (ratio >= 1) {
- fillRect(target.left, target.top, target.width(), target.height(), toColor);
- return;
- }
-
- float alpha = mAlpha;
-
- // Copy the input to avoid changing it.
- mDrawTextureSourceRect.set(source);
- mDrawTextureTargetRect.set(target);
- source = mDrawTextureSourceRect;
- target = mDrawTextureTargetRect;
-
- mGLState.setBlendEnabled(mBlendEnabled && (!from.isOpaque()
- || !ColorUtils.isOpaque(toColor) || alpha < OPAQUE_ALPHA));
-
- if (!bindTexture(from)) return;
-
- // Interpolate the RGB and alpha values between both textures.
- mGLState.setTexEnvMode(GL11.GL_COMBINE);
- setMixedColor(toColor, ratio, alpha);
- convertCoordinate(source, target, from);
- setTextureCoords(source);
- textureRect(target.left, target.top, target.width(), target.height());
- mGLState.setTexEnvMode(GL11.GL_REPLACE);
- }
-
- private void drawMixed(BasicTexture from, int toColor,
- float ratio, int x, int y, int width, int height, float alpha) {
- // change from 0 to 0.01f to prevent getting divided by zero below
- if (ratio <= 0.01f) {
- drawTexture(from, x, y, width, height, alpha);
- return;
- } else if (ratio >= 1) {
- fillRect(x, y, width, height, toColor);
- return;
- }
-
- mGLState.setBlendEnabled(mBlendEnabled && (!from.isOpaque()
- || !ColorUtils.isOpaque(toColor) || alpha < OPAQUE_ALPHA));
-
- final GL11 gl = mGL;
- if (!bindTexture(from)) return;
-
- // Interpolate the RGB and alpha values between both textures.
- mGLState.setTexEnvMode(GL11.GL_COMBINE);
- setMixedColor(toColor, ratio, alpha);
-
- drawBoundTexture(from, x, y, width, height);
- mGLState.setTexEnvMode(GL11.GL_REPLACE);
- }
-
- // TODO: the code only work for 2D should get fixed for 3D or removed
- private static final int MSKEW_X = 4;
- private static final int MSKEW_Y = 1;
- private static final int MSCALE_X = 0;
- private static final int MSCALE_Y = 5;
-
- private static boolean isMatrixRotatedOrFlipped(float matrix[]) {
- final float eps = 1e-5f;
- return Math.abs(matrix[MSKEW_X]) > eps
- || Math.abs(matrix[MSKEW_Y]) > eps
- || matrix[MSCALE_X] < -eps
- || matrix[MSCALE_Y] > eps;
- }
-
- private static class GLState {
-
- private final GL11 mGL;
-
- private int mTexEnvMode = GL11.GL_REPLACE;
- private float mTextureAlpha = 1.0f;
- private int mTextureTarget = GL11.GL_TEXTURE_2D;
- private boolean mBlendEnabled = true;
- private float mLineWidth = 1.0f;
- private boolean mLineSmooth = false;
-
- public GLState(GL11 gl) {
- mGL = gl;
-
- // Disable unused state
- gl.glDisable(GL11.GL_LIGHTING);
-
- // Enable used features
- gl.glEnable(GL11.GL_DITHER);
-
- gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
- gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
- gl.glEnable(GL11.GL_TEXTURE_2D);
-
- gl.glTexEnvf(GL11.GL_TEXTURE_ENV,
- GL11.GL_TEXTURE_ENV_MODE, GL11.GL_REPLACE);
-
- // Set the background color
- gl.glClearColor(0f, 0f, 0f, 0f);
-
- gl.glEnable(GL11.GL_BLEND);
- gl.glBlendFunc(GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
-
- // We use 565 or 8888 format, so set the alignment to 2 bytes/pixel.
- gl.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 2);
- }
-
- public void setTexEnvMode(int mode) {
- if (mTexEnvMode == mode) return;
- mTexEnvMode = mode;
- mGL.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, mode);
- }
-
- public void setLineWidth(float width) {
- if (mLineWidth == width) return;
- mLineWidth = width;
- mGL.glLineWidth(width);
- }
-
- public void setTextureAlpha(float alpha) {
- if (mTextureAlpha == alpha) return;
- mTextureAlpha = alpha;
- if (alpha >= OPAQUE_ALPHA) {
- // The alpha is need for those texture without alpha channel
- mGL.glColor4f(1, 1, 1, 1);
- setTexEnvMode(GL11.GL_REPLACE);
- } else {
- mGL.glColor4f(alpha, alpha, alpha, alpha);
- setTexEnvMode(GL11.GL_MODULATE);
- }
- }
-
- public void setColorMode(int color, float alpha) {
- setBlendEnabled(!ColorUtils.isOpaque(color) || alpha < OPAQUE_ALPHA);
-
- // Set mTextureAlpha to an invalid value, so that it will reset
- // again in setTextureAlpha(float) later.
- mTextureAlpha = -1.0f;
-
- setTextureTarget(0);
-
- float prealpha = (color >>> 24) * alpha * 65535f / 255f / 255f;
- mGL.glColor4x(
- Math.round(((color >> 16) & 0xFF) * prealpha),
- Math.round(((color >> 8) & 0xFF) * prealpha),
- Math.round((color & 0xFF) * prealpha),
- Math.round(255 * prealpha));
- }
-
- // target is a value like GL_TEXTURE_2D. If target = 0, texturing is disabled.
- public void setTextureTarget(int target) {
- if (mTextureTarget == target) return;
- if (mTextureTarget != 0) {
- mGL.glDisable(mTextureTarget);
- }
- mTextureTarget = target;
- if (mTextureTarget != 0) {
- mGL.glEnable(mTextureTarget);
- }
- }
-
- public void setBlendEnabled(boolean enabled) {
- if (mBlendEnabled == enabled) return;
- mBlendEnabled = enabled;
- if (enabled) {
- mGL.glEnable(GL11.GL_BLEND);
- } else {
- mGL.glDisable(GL11.GL_BLEND);
- }
- }
- }
-
- @Override
- public void clearBuffer(float[] argb) {
- if(argb != null && argb.length == 4) {
- mGL.glClearColor(argb[1], argb[2], argb[3], argb[0]);
- } else {
- mGL.glClearColor(0, 0, 0, 1);
- }
- mGL.glClear(GL10.GL_COLOR_BUFFER_BIT);
- }
-
- @Override
- public void clearBuffer() {
- clearBuffer(null);
- }
-
- private void setTextureCoords(RectF source) {
- setTextureCoords(source.left, source.top, source.right, source.bottom);
- }
-
- private void setTextureCoords(float left, float top,
- float right, float bottom) {
- mGL.glMatrixMode(GL11.GL_TEXTURE);
- mTextureMatrixValues[0] = right - left;
- mTextureMatrixValues[5] = bottom - top;
- mTextureMatrixValues[10] = 1;
- mTextureMatrixValues[12] = left;
- mTextureMatrixValues[13] = top;
- mTextureMatrixValues[15] = 1;
- mGL.glLoadMatrixf(mTextureMatrixValues, 0);
- mGL.glMatrixMode(GL11.GL_MODELVIEW);
- }
-
- private void setTextureCoords(float[] mTextureTransform) {
- mGL.glMatrixMode(GL11.GL_TEXTURE);
- mGL.glLoadMatrixf(mTextureTransform, 0);
- mGL.glMatrixMode(GL11.GL_MODELVIEW);
- }
-
- // unloadTexture and deleteBuffer can be called from the finalizer thread,
- // so we synchronized on the mUnboundTextures object.
- @Override
- public boolean unloadTexture(BasicTexture t) {
- synchronized (mUnboundTextures) {
- if (!t.isLoaded()) return false;
- mUnboundTextures.add(t.mId);
- return true;
- }
- }
-
- @Override
- public void deleteBuffer(int bufferId) {
- synchronized (mUnboundTextures) {
- mDeleteBuffers.add(bufferId);
- }
- }
-
- @Override
- public void deleteRecycledResources() {
- synchronized (mUnboundTextures) {
- IntArray ids = mUnboundTextures;
- if (ids.size() > 0) {
- mGLId.glDeleteTextures(mGL, ids.size(), ids.getInternalArray(), 0);
- ids.clear();
- }
-
- ids = mDeleteBuffers;
- if (ids.size() > 0) {
- mGLId.glDeleteBuffers(mGL, ids.size(), ids.getInternalArray(), 0);
- ids.clear();
- }
- }
- }
-
- @Override
- public void save() {
- save(SAVE_FLAG_ALL);
- }
-
- @Override
- public void save(int saveFlags) {
- ConfigState config = obtainRestoreConfig();
-
- if ((saveFlags & SAVE_FLAG_ALPHA) != 0) {
- config.mAlpha = mAlpha;
- } else {
- config.mAlpha = -1;
- }
-
- if ((saveFlags & SAVE_FLAG_MATRIX) != 0) {
- System.arraycopy(mMatrixValues, 0, config.mMatrix, 0, 16);
- } else {
- config.mMatrix[0] = Float.NEGATIVE_INFINITY;
- }
-
- mRestoreStack.add(config);
- }
-
- @Override
- public void restore() {
- if (mRestoreStack.isEmpty()) throw new IllegalStateException();
- ConfigState config = mRestoreStack.remove(mRestoreStack.size() - 1);
- config.restore(this);
- freeRestoreConfig(config);
- }
-
- private void freeRestoreConfig(ConfigState action) {
- action.mNextFree = mRecycledRestoreAction;
- mRecycledRestoreAction = action;
- }
-
- private ConfigState obtainRestoreConfig() {
- if (mRecycledRestoreAction != null) {
- ConfigState result = mRecycledRestoreAction;
- mRecycledRestoreAction = result.mNextFree;
- return result;
- }
- return new ConfigState();
- }
-
- private static class ConfigState {
- float mAlpha;
- float mMatrix[] = new float[16];
- ConfigState mNextFree;
-
- public void restore(GLES11Canvas canvas) {
- if (mAlpha >= 0) canvas.setAlpha(mAlpha);
- if (mMatrix[0] != Float.NEGATIVE_INFINITY) {
- System.arraycopy(mMatrix, 0, canvas.mMatrixValues, 0, 16);
- }
- }
- }
-
- @Override
- public void dumpStatisticsAndClear() {
- String line = String.format(
- "MESH:%d, TEX_OES:%d, TEX_RECT:%d, FILL_RECT:%d, LINE:%d",
- mCountDrawMesh, mCountTextureRect, mCountTextureOES,
- mCountFillRect, mCountDrawLine);
- mCountDrawMesh = 0;
- mCountTextureRect = 0;
- mCountTextureOES = 0;
- mCountFillRect = 0;
- mCountDrawLine = 0;
- Log.d(TAG, line);
- }
-
- private void saveTransform() {
- System.arraycopy(mMatrixValues, 0, mTempMatrix, 0, 16);
- }
-
- private void restoreTransform() {
- System.arraycopy(mTempMatrix, 0, mMatrixValues, 0, 16);
- }
-
- private void setRenderTarget(RawTexture texture) {
- GL11ExtensionPack gl11ep = (GL11ExtensionPack) mGL;
-
- if (mTargetTexture == null && texture != null) {
- mGLId.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()) 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));
- }
- }
-
- @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 uploadBuffer(FloatBuffer buf) {
- return uploadBuffer(buf, Float.SIZE / Byte.SIZE);
- }
-
- @Override
- public int uploadBuffer(ByteBuffer buf) {
- return uploadBuffer(buf, 1);
- }
-
- private int uploadBuffer(Buffer buf, int elementSize) {
- int[] bufferIds = new int[1];
- mGLId.glGenBuffers(bufferIds.length, bufferIds, 0);
- int bufferId = bufferIds[0];
- mGL.glBindBuffer(GL11.GL_ARRAY_BUFFER, bufferId);
- mGL.glBufferData(GL11.GL_ARRAY_BUFFER, buf.capacity() * elementSize, buf,
- GL11.GL_STATIC_DRAW);
- return bufferId;
- }
-
- @Override
- public void recoverFromLightCycle() {
- // This is only required for GLES20
- }
-
- @Override
- public void getBounds(Rect bounds, int x, int y, int width, int height) {
- // This is only required for GLES20
- }
-
- @Override
- public GLId getGLId() {
- return mGLId;
- }
-}
diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/GLES11IdImpl.java b/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/GLES11IdImpl.java
deleted file mode 100644
index 2517dd589..000000000
--- a/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/GLES11IdImpl.java
+++ /dev/null
@@ -1,68 +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.hippo.ehviewer.gallery.glrenderer;
-
-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 GLES11IdImpl implements GLId {
- private static int sNextId = 1;
- // Mutex for sNextId
- private static final 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/app/src/main/java/com/hippo/ehviewer/gallery/ui/GLRootView.java b/app/src/main/java/com/hippo/ehviewer/gallery/ui/GLRootView.java
index 061844067..9e34a46a4 100644
--- a/app/src/main/java/com/hippo/ehviewer/gallery/ui/GLRootView.java
+++ b/app/src/main/java/com/hippo/ehviewer/gallery/ui/GLRootView.java
@@ -17,9 +17,7 @@
package com.hippo.ehviewer.gallery.ui;
import android.annotation.TargetApi;
-import android.app.ActivityManager;
import android.content.Context;
-import android.content.pm.ConfigurationInfo;
import android.graphics.Matrix;
import android.opengl.GLSurfaceView;
import android.os.Build;
@@ -33,7 +31,6 @@ import android.view.SurfaceHolder;
import com.hippo.ehviewer.gallery.anim.CanvasAnimation;
import com.hippo.ehviewer.gallery.glrenderer.BasicTexture;
import com.hippo.ehviewer.gallery.glrenderer.GLCanvas;
-import com.hippo.ehviewer.gallery.glrenderer.GLES11Canvas;
import com.hippo.ehviewer.gallery.glrenderer.GLES20Canvas;
import com.hippo.ehviewer.gallery.glrenderer.UploadedTexture;
import com.hippo.ehviewer.gallery.util.ApiHelper;
@@ -46,7 +43,9 @@ import java.util.ArrayList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
+import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;
@@ -106,13 +105,6 @@ public class GLRootView extends GLSurfaceView
private long mLastDrawFinishTime;
private boolean mInDownState = false;
//private boolean mFirstDraw = true;
- private boolean mGLES20Supported;
-
- public static boolean checkGLES20Support(Context context) {
- ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
- ConfigurationInfo info = am.getDeviceConfigurationInfo();
- return info.reqGlEsVersion >= 0x20000;
- }
public GLRootView(Context context) {
this(context, null);
@@ -121,17 +113,11 @@ public class GLRootView extends GLSurfaceView
public GLRootView(Context context, AttributeSet attrs) {
super(context, attrs);
mFlags |= FLAG_INITIALIZED;
- mGLES20Supported = checkGLES20Support(context);
setBackgroundDrawable(null);
- setEGLContextClientVersion(mGLES20Supported ? 2 : 1);
+ setEGLContextClientVersion(2);
- // We can't detect 888_PIXEL_FORMAT by Build.VERSION.SDK_INT,
- // for example CyanogenMod use ro.opengles.surface.rgb565,
- // so just use default EGLConfigChooser.
- // And we do not need depth buffer
- // TODO setEGLConfigChooser(8, 8, 8, 8, 0, 0) or setEGLConfigChooser(false)
- setEGLConfigChooser(8, 8, 8, 8, 0, 0);
- //setEGLConfigChooser(false);
+ // do not need depth buffer
+ setEGLConfigChooser(new ComponentSizeChooser(8, 8, 8, 8, 0, 0));
setRenderer(this);
// setFormat is done by SurfaceView in SDK 2.3 and newer.
//if (ApiHelper.USE_888_PIXEL_FORMAT) {
@@ -302,7 +288,7 @@ public class GLRootView extends GLSurfaceView
mRenderLock.lock();
try {
mGL = gl;
- mCanvas = mGLES20Supported ? new GLES20Canvas() : new GLES11Canvas(gl);
+ mCanvas = new GLES20Canvas();
BasicTexture.invalidateAllTextures();
} finally {
mRenderLock.unlock();
@@ -622,4 +608,146 @@ public class GLRootView extends GLSurfaceView
super.finalize();
}
}
+
+ private static abstract class BaseConfigChooser implements EGLConfigChooser {
+
+ public BaseConfigChooser(int[] configSpec) {
+ mConfigSpec = filterConfigSpec(configSpec);
+ }
+
+ @Override
+ public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
+ int[] num_config = new int[1];
+ if (!egl.eglChooseConfig(display, mConfigSpec, null, 0,
+ num_config)) {
+ throw new IllegalArgumentException("eglChooseConfig failed");
+ }
+
+ int numConfigs = num_config[0];
+
+ if (numConfigs <= 0) {
+ throw new IllegalArgumentException(
+ "No configs match configSpec");
+ }
+
+ EGLConfig[] configs = new EGLConfig[numConfigs];
+ if (!egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs,
+ num_config)) {
+ throw new IllegalArgumentException("eglChooseConfig#2 failed");
+ }
+ EGLConfig config = chooseConfig(egl, display, configs);
+ if (config == null) {
+ throw new IllegalArgumentException("No config chosen");
+ }
+ return config;
+ }
+
+ abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
+ EGLConfig[] configs);
+
+ protected int[] mConfigSpec;
+
+ private int[] filterConfigSpec(int[] configSpec) {
+ /* We know none of the subclasses define EGL_RENDERABLE_TYPE.
+ * And we know the configSpec is well formed.
+ */
+ int len = configSpec.length;
+ int[] newConfigSpec = new int[len + 2];
+ System.arraycopy(configSpec, 0, newConfigSpec, 0, len-1);
+ newConfigSpec[len-1] = EGL10.EGL_RENDERABLE_TYPE;
+ newConfigSpec[len] = 4; // EGL14.EGL_OPENGL_ES2_BIT; /* EGL_OPENGL_ES2_BIT */
+ newConfigSpec[len+1] = EGL10.EGL_NONE;
+ return newConfigSpec;
+ }
+ }
+
+ /**
+ * No guarantee to choose a configuration with exactly the specified r,g,b,a,depth,stencil sizes.
+ * But we try our best.
+ */
+ private static class ComponentSizeChooser extends BaseConfigChooser {
+ public ComponentSizeChooser(int redSize, int greenSize, int blueSize,
+ int alphaSize, int depthSize, int stencilSize) {
+ super(new int[] {
+ EGL10.EGL_RED_SIZE, redSize,
+ EGL10.EGL_GREEN_SIZE, greenSize,
+ EGL10.EGL_BLUE_SIZE, blueSize,
+ EGL10.EGL_ALPHA_SIZE, alphaSize,
+ EGL10.EGL_DEPTH_SIZE, depthSize,
+ EGL10.EGL_STENCIL_SIZE, stencilSize,
+ EGL10.EGL_NONE});
+ mValue = new int[1];
+ mRedSize = redSize;
+ mGreenSize = greenSize;
+ mBlueSize = blueSize;
+ mAlphaSize = alphaSize;
+ mDepthSize = depthSize;
+ mStencilSize = stencilSize;
+ }
+
+ @Override
+ public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
+ EGLConfig[] configs) {
+ // Use score to avoid "No config chosen"
+ int configIndex = 0;
+ int minScore = Integer.MAX_VALUE;
+
+ for (int i = 0, n = configs.length; i < n; i++) {
+ EGLConfig config = configs[i];
+ int d = findConfigAttrib(egl, display, config,
+ EGL10.EGL_DEPTH_SIZE, 0);
+ int s = findConfigAttrib(egl, display, config,
+ EGL10.EGL_STENCIL_SIZE, 0);
+ int r = findConfigAttrib(egl, display, config,
+ EGL10.EGL_RED_SIZE, 0);
+ int g = findConfigAttrib(egl, display, config,
+ EGL10.EGL_GREEN_SIZE, 0);
+ int b = findConfigAttrib(egl, display, config,
+ EGL10.EGL_BLUE_SIZE, 0);
+ int a = findConfigAttrib(egl, display, config,
+ EGL10.EGL_ALPHA_SIZE, 0);
+
+ int score = 0;
+ if (d < mDepthSize) {
+ score += 100;
+ } else if (d > mDepthSize) {
+ score += (d - mDepthSize);
+ }
+ if (s < mStencilSize) {
+ score += 100;
+ } else if (s > mStencilSize) {
+ score += (s - mStencilSize);
+ }
+ score += Math.abs(r - mRedSize);
+ score += Math.abs(g - mGreenSize);
+ score += Math.abs(b - mBlueSize);
+ score += Math.abs(a - mAlphaSize);
+
+ if (score < minScore) {
+ minScore = score;
+ configIndex = i;
+ }
+ }
+
+ return configs[configIndex];
+ }
+
+ private int findConfigAttrib(EGL10 egl, EGLDisplay display,
+ EGLConfig config, int attribute, int defaultValue) {
+
+ if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
+ return mValue[0];
+ }
+ return defaultValue;
+ }
+
+ private int[] mValue;
+ // Subclasses can adjust these values:
+ protected int mRedSize;
+ protected int mGreenSize;
+ protected int mBlueSize;
+ protected int mAlphaSize;
+ protected int mDepthSize;
+ protected int mStencilSize;
+ }
}
diff --git a/app/src/main/res/layout-v21/gallery_detail_header.xml b/app/src/main/res/layout-v21/gallery_detail_header.xml
deleted file mode 100644
index 9370ca2ba..000000000
--- a/app/src/main/res/layout-v21/gallery_detail_header.xml
+++ /dev/null
@@ -1,69 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-