FileDocCategorySizeDatePackage
GLES20Canvas.javaAPI DocAndroid 5.1 API37910Thu Mar 12 22:22:42 GMT 2015com.android.gallery3d.glrenderer

GLES20Canvas

public class GLES20Canvas extends Object implements GLCanvas

Fields Summary
private static final String
TAG
private static final int
FLOAT_SIZE
private static final float
OPAQUE_ALPHA
private static final int
COORDS_PER_VERTEX
private static final int
VERTEX_STRIDE
private static final int
COUNT_FILL_VERTEX
private static final int
COUNT_LINE_VERTEX
private static final int
COUNT_RECT_VERTEX
private static final int
OFFSET_FILL_RECT
private static final int
OFFSET_DRAW_LINE
private static final int
OFFSET_DRAW_RECT
private static final float[]
BOX_COORDINATES
private static final float[]
BOUNDS_COORDINATES
private static final String
POSITION_ATTRIBUTE
private static final String
COLOR_UNIFORM
private static final String
MATRIX_UNIFORM
private static final String
TEXTURE_MATRIX_UNIFORM
private static final String
TEXTURE_SAMPLER_UNIFORM
private static final String
ALPHA_UNIFORM
private static final String
TEXTURE_COORD_ATTRIBUTE
private static final String
DRAW_VERTEX_SHADER
private static final String
DRAW_FRAGMENT_SHADER
private static final String
TEXTURE_VERTEX_SHADER
private static final String
MESH_VERTEX_SHADER
private static final String
TEXTURE_FRAGMENT_SHADER
private static final String
OES_TEXTURE_FRAGMENT_SHADER
private static final int
INITIAL_RESTORE_STATE_SIZE
private static final int
MATRIX_SIZE
private float[]
mMatrices
private float[]
mAlphas
private com.android.gallery3d.util.IntArray
mSaveFlags
private int
mCurrentAlphaIndex
private int
mCurrentMatrixIndex
private int
mWidth
private int
mHeight
private float[]
mProjectionMatrix
private int
mScreenWidth
private int
mScreenHeight
private int
mDrawProgram
private int
mTextureProgram
private int
mOesTextureProgram
private int
mMeshProgram
private int
mBoxCoordinates
private static final int
INDEX_POSITION
private static final int
INDEX_MATRIX
private static final int
INDEX_COLOR
private static final int
INDEX_TEXTURE_MATRIX
private static final int
INDEX_TEXTURE_SAMPLER
private static final int
INDEX_ALPHA
private static final int
INDEX_TEXTURE_COORD
ShaderParameter[]
mDrawParameters
ShaderParameter[]
mTextureParameters
ShaderParameter[]
mOesTextureParameters
ShaderParameter[]
mMeshParameters
private final com.android.gallery3d.util.IntArray
mUnboundTextures
private final com.android.gallery3d.util.IntArray
mDeleteBuffers
private int
mCountDrawMesh
private int
mCountTextureRect
private int
mCountFillRect
private int
mCountDrawLine
private int[]
mFrameBuffer
private ArrayList
mTargetTextures
private final float[]
mTempMatrix
private final float[]
mTempColor
private final android.graphics.RectF
mTempSourceRect
private final android.graphics.RectF
mTempTargetRect
private final float[]
mTempTextureMatrix
private final int[]
mTempIntArray
private static final GLId
mGLId
Constructors Summary
public GLES20Canvas()


      
        Matrix.setIdentityM(mTempTextureMatrix, 0);
        Matrix.setIdentityM(mMatrices, mCurrentMatrixIndex);
        mAlphas[mCurrentAlphaIndex] = 1f;
        mTargetTextures.add(null);

        FloatBuffer boxBuffer = createBuffer(BOX_COORDINATES);
        mBoxCoordinates = uploadBuffer(boxBuffer);

        int drawVertexShader = loadShader(GLES20.GL_VERTEX_SHADER, DRAW_VERTEX_SHADER);
        int textureVertexShader = loadShader(GLES20.GL_VERTEX_SHADER, TEXTURE_VERTEX_SHADER);
        int meshVertexShader = loadShader(GLES20.GL_VERTEX_SHADER, MESH_VERTEX_SHADER);
        int drawFragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, DRAW_FRAGMENT_SHADER);
        int textureFragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, TEXTURE_FRAGMENT_SHADER);
        int oesTextureFragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,
                OES_TEXTURE_FRAGMENT_SHADER);

        mDrawProgram = assembleProgram(drawVertexShader, drawFragmentShader, mDrawParameters);
        mTextureProgram = assembleProgram(textureVertexShader, textureFragmentShader,
                mTextureParameters);
        mOesTextureProgram = assembleProgram(textureVertexShader, oesTextureFragmentShader,
                mOesTextureParameters);
        mMeshProgram = assembleProgram(meshVertexShader, textureFragmentShader, mMeshParameters);
        GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA);
        checkError();
    
Methods Summary
private intassembleProgram(int vertexShader, int fragmentShader, com.android.gallery3d.glrenderer.GLES20Canvas$ShaderParameter[] params)

        int program = GLES20.glCreateProgram();
        checkError();
        if (program == 0) {
            throw new RuntimeException("Cannot create GL program: " + GLES20.glGetError());
        }
        GLES20.glAttachShader(program, vertexShader);
        checkError();
        GLES20.glAttachShader(program, fragmentShader);
        checkError();
        GLES20.glLinkProgram(program);
        checkError();
        int[] mLinkStatus = mTempIntArray;
        GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, mLinkStatus, 0);
        if (mLinkStatus[0] != GLES20.GL_TRUE) {
            Log.e(TAG, "Could not link program: ");
            Log.e(TAG, GLES20.glGetProgramInfoLog(program));
            GLES20.glDeleteProgram(program);
            program = 0;
        }
        for (int i = 0; i < params.length; i++) {
            params[i].loadHandle(program);
        }
        return program;
    
public voidbeginRenderTarget(RawTexture texture)

        save(); // save matrix and alpha and blending
        RawTexture oldTexture = getTargetTexture();
        mTargetTextures.add(texture);
        setRenderTarget(oldTexture, texture);
    
public static voidcheckError()

        int error = GLES20.glGetError();
        if (error != 0) {
            Throwable t = new Throwable();
            Log.e(TAG, "GL error: " + error, t);
        }
    
private static voidcheckFramebufferStatus()

        int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
        if (status != GLES20.GL_FRAMEBUFFER_COMPLETE) {
            String msg = "";
            switch (status) {
                case GLES20.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
                    msg = "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
                    break;
                case GLES20.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
                    msg = "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
                    break;
                case GLES20.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
                    msg = "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
                    break;
                case GLES20.GL_FRAMEBUFFER_UNSUPPORTED:
                    msg = "GL_FRAMEBUFFER_UNSUPPORTED";
                    break;
            }
            throw new RuntimeException(msg + ":" + Integer.toHexString(status));
        }
    
public voidclearBuffer()

        GLES20.glClearColor(0f, 0f, 0f, 1f);
        checkError();
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
        checkError();
    
public voidclearBuffer(float[] argb)

        GLES20.glClearColor(argb[1], argb[2], argb[3], argb[0]);
        checkError();
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
        checkError();
    
private static voidconvertCoordinate(android.graphics.RectF source, android.graphics.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;
        }
    
private static voidcopyTextureCoordinates(BasicTexture texture, android.graphics.RectF outRect)

        int left = 0;
        int top = 0;
        int right = texture.getWidth();
        int bottom = texture.getHeight();
        if (texture.hasBorder()) {
            left = 1;
            top = 1;
            right -= 1;
            bottom -= 1;
        }
        outRect.set(left, top, right, bottom);
    
private static java.nio.FloatBuffercreateBuffer(float[] values)

        // First create an nio buffer, then create a VBO from it.
        int size = values.length * FLOAT_SIZE;
        FloatBuffer buffer = ByteBuffer.allocateDirect(size).order(ByteOrder.nativeOrder())
                .asFloatBuffer();
        buffer.put(values, 0, values.length).position(0);
        return buffer;
    
public voiddeleteBuffer(int bufferId)

        synchronized (mUnboundTextures) {
            mDeleteBuffers.add(bufferId);
        }
    
public voiddeleteRecycledResources()

        synchronized (mUnboundTextures) {
            IntArray ids = mUnboundTextures;
            if (mUnboundTextures.size() > 0) {
                mGLId.glDeleteTextures(null, ids.size(), ids.getInternalArray(), 0);
                ids.clear();
            }

            ids = mDeleteBuffers;
            if (ids.size() > 0) {
                mGLId.glDeleteBuffers(null, ids.size(), ids.getInternalArray(), 0);
                ids.clear();
            }
        }
    
private voiddraw(int type, int offset, int count, float x, float y, float width, float height, GLPaint paint)

        draw(type, offset, count, x, y, width, height, paint.getColor(), paint.getLineWidth());
    
private voiddraw(int type, int offset, int count, float x, float y, float width, float height, int color, float lineWidth)

        prepareDraw(offset, color, lineWidth);
        draw(mDrawParameters, type, count, x, y, width, height);
    
private voiddraw(com.android.gallery3d.glrenderer.GLES20Canvas$ShaderParameter[] params, int type, int count, float x, float y, float width, float height)

        setMatrix(params, x, y, width, height);
        int positionHandle = params[INDEX_POSITION].handle;
        GLES20.glEnableVertexAttribArray(positionHandle);
        checkError();
        GLES20.glDrawArrays(type, 0, count);
        checkError();
        GLES20.glDisableVertexAttribArray(positionHandle);
        checkError();
    
public voiddrawLine(float x1, float y1, float x2, float y2, GLPaint paint)

        draw(GLES20.GL_LINE_STRIP, OFFSET_DRAW_LINE, COUNT_LINE_VERTEX, x1, y1, x2 - x1, y2 - y1,
                paint);
        mCountDrawLine++;
    
public voiddrawMesh(BasicTexture texture, int x, int y, int xyBuffer, int uvBuffer, int indexBuffer, int indexCount)

        prepareTexture(texture, mMeshProgram, mMeshParameters);

        GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
        checkError();

        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, xyBuffer);
        checkError();
        int positionHandle = mMeshParameters[INDEX_POSITION].handle;
        GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false,
                VERTEX_STRIDE, 0);
        checkError();

        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, uvBuffer);
        checkError();
        int texCoordHandle = mMeshParameters[INDEX_TEXTURE_COORD].handle;
        GLES20.glVertexAttribPointer(texCoordHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT,
                false, VERTEX_STRIDE, 0);
        checkError();
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
        checkError();

        GLES20.glEnableVertexAttribArray(positionHandle);
        checkError();
        GLES20.glEnableVertexAttribArray(texCoordHandle);
        checkError();

        setMatrix(mMeshParameters, x, y, 1, 1);
        GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, indexCount, GLES20.GL_UNSIGNED_BYTE, 0);
        checkError();

        GLES20.glDisableVertexAttribArray(positionHandle);
        checkError();
        GLES20.glDisableVertexAttribArray(texCoordHandle);
        checkError();
        GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
        checkError();
        mCountDrawMesh++;
    
public voiddrawMixed(BasicTexture texture, int toColor, float ratio, int x, int y, int w, int h)

        copyTextureCoordinates(texture, mTempSourceRect);
        mTempTargetRect.set(x, y, x + w, y + h);
        drawMixed(texture, toColor, ratio, mTempSourceRect, mTempTargetRect);
    
public voiddrawMixed(BasicTexture texture, int toColor, float ratio, android.graphics.RectF source, android.graphics.RectF target)

        if (target.width() <= 0 || target.height() <= 0) {
            return;
        }
        save(SAVE_FLAG_ALPHA);

        float currentAlpha = getAlpha();
        float cappedRatio = Math.min(1f, Math.max(0f, ratio));

        float textureAlpha = (1f - cappedRatio) * currentAlpha;
        setAlpha(textureAlpha);
        drawTexture(texture, source, target);

        float colorAlpha = cappedRatio * currentAlpha;
        setAlpha(colorAlpha);
        fillRect(target.left, target.top, target.width(), target.height(), toColor);

        restore();
    
public voiddrawRect(float x, float y, float width, float height, GLPaint paint)

        draw(GLES20.GL_LINE_LOOP, OFFSET_DRAW_RECT, COUNT_RECT_VERTEX, x, y, width, height, paint);
        mCountDrawLine++;
    
public voiddrawTexture(BasicTexture texture, int x, int y, int width, int height)

        if (width <= 0 || height <= 0) {
            return;
        }
        copyTextureCoordinates(texture, mTempSourceRect);
        mTempTargetRect.set(x, y, x + width, y + height);
        convertCoordinate(mTempSourceRect, mTempTargetRect, texture);
        drawTextureRect(texture, mTempSourceRect, mTempTargetRect);
    
public voiddrawTexture(BasicTexture texture, android.graphics.RectF source, android.graphics.RectF target)

        if (target.width() <= 0 || target.height() <= 0) {
            return;
        }
        mTempSourceRect.set(source);
        mTempTargetRect.set(target);

        convertCoordinate(mTempSourceRect, mTempTargetRect, texture);
        drawTextureRect(texture, mTempSourceRect, mTempTargetRect);
    
public voiddrawTexture(BasicTexture texture, float[] textureTransform, int x, int y, int w, int h)

        if (w <= 0 || h <= 0) {
            return;
        }
        mTempTargetRect.set(x, y, x + w, y + h);
        drawTextureRect(texture, textureTransform, mTempTargetRect);
    
private voiddrawTextureRect(BasicTexture texture, android.graphics.RectF source, android.graphics.RectF target)

        setTextureMatrix(source);
        drawTextureRect(texture, mTempTextureMatrix, target);
    
private voiddrawTextureRect(BasicTexture texture, float[] textureMatrix, android.graphics.RectF target)

        ShaderParameter[] params = prepareTexture(texture);
        setPosition(params, OFFSET_FILL_RECT);
        GLES20.glUniformMatrix4fv(params[INDEX_TEXTURE_MATRIX].handle, 1, false, textureMatrix, 0);
        checkError();
        if (texture.isFlippedVertically()) {
            save(SAVE_FLAG_MATRIX);
            translate(0, target.centerY());
            scale(1, -1, 1);
            translate(0, -target.centerY());
        }
        draw(params, GLES20.GL_TRIANGLE_STRIP, COUNT_FILL_VERTEX, target.left, target.top,
                target.width(), target.height());
        if (texture.isFlippedVertically()) {
            restore();
        }
        mCountTextureRect++;
    
public voiddumpStatisticsAndClear()

        String line = String.format("MESH:%d, TEX_RECT:%d, FILL_RECT:%d, LINE:%d", mCountDrawMesh,
                mCountTextureRect, mCountFillRect, mCountDrawLine);
        mCountDrawMesh = 0;
        mCountTextureRect = 0;
        mCountFillRect = 0;
        mCountDrawLine = 0;
        Log.d(TAG, line);
    
private voidenableBlending(boolean enableBlending)

        if (enableBlending) {
            GLES20.glEnable(GLES20.GL_BLEND);
            checkError();
        } else {
            GLES20.glDisable(GLES20.GL_BLEND);
            checkError();
        }
    
public voidendRenderTarget()

        RawTexture oldTexture = mTargetTextures.remove(mTargetTextures.size() - 1);
        RawTexture texture = getTargetTexture();
        setRenderTarget(oldTexture, texture);
        restore(); // restore matrix and alpha
    
public voidfillRect(float x, float y, float width, float height, int color)

        draw(GLES20.GL_TRIANGLE_STRIP, OFFSET_FILL_RECT, COUNT_FILL_VERTEX, x, y, width, height,
                color, 0f);
        mCountFillRect++;
    
public floatgetAlpha()

        return mAlphas[mCurrentAlphaIndex];
    
public voidgetBounds(android.graphics.Rect bounds, int x, int y, int width, int height)

        Matrix.translateM(mTempMatrix, 0, mMatrices, mCurrentMatrixIndex, x, y, 0f);
        Matrix.scaleM(mTempMatrix, 0, width, height, 1f);
        Matrix.multiplyMV(mTempMatrix, MATRIX_SIZE, mTempMatrix, 0, BOUNDS_COORDINATES, 0);
        Matrix.multiplyMV(mTempMatrix, MATRIX_SIZE + 4, mTempMatrix, 0, BOUNDS_COORDINATES, 4);
        bounds.left = Math.round(mTempMatrix[MATRIX_SIZE]);
        bounds.right = Math.round(mTempMatrix[MATRIX_SIZE + 4]);
        bounds.top = Math.round(mTempMatrix[MATRIX_SIZE + 1]);
        bounds.bottom = Math.round(mTempMatrix[MATRIX_SIZE + 5]);
        bounds.sort();
    
private float[]getColor(int color)

        float alpha = ((color >>> 24) & 0xFF) / 255f * getAlpha();
        float red = ((color >>> 16) & 0xFF) / 255f * alpha;
        float green = ((color >>> 8) & 0xFF) / 255f * alpha;
        float blue = (color & 0xFF) / 255f * alpha;
        mTempColor[0] = red;
        mTempColor[1] = green;
        mTempColor[2] = blue;
        mTempColor[3] = alpha;
        return mTempColor;
    
public GLIdgetGLId()

        return mGLId;
    
private RawTexturegetTargetTexture()

        return mTargetTextures.get(mTargetTextures.size() - 1);
    
public voidinitializeTexture(BasicTexture texture, android.graphics.Bitmap bitmap)

        int target = texture.getTarget();
        GLES20.glBindTexture(target, texture.getId());
        checkError();
        GLUtils.texImage2D(target, 0, bitmap, 0);
    
public voidinitializeTextureSize(BasicTexture texture, int format, int type)

        int target = texture.getTarget();
        GLES20.glBindTexture(target, texture.getId());
        checkError();
        int width = texture.getTextureWidth();
        int height = texture.getTextureHeight();
        GLES20.glTexImage2D(target, 0, format, width, height, 0, format, type, null);
    
private static intloadShader(int type, java.lang.String shaderCode)

        // create a vertex shader type (GLES20.GL_VERTEX_SHADER)
        // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
        int shader = GLES20.glCreateShader(type);

        // add the source code to the shader and compile it
        GLES20.glShaderSource(shader, shaderCode);
        checkError();
        GLES20.glCompileShader(shader);
        checkError();

        return shader;
    
public voidmultiplyAlpha(float alpha)

        setAlpha(getAlpha() * alpha);
    
public voidmultiplyMatrix(float[] matrix, int offset)

        float[] temp = mTempMatrix;
        float[] currentMatrix = mMatrices;
        int index = mCurrentMatrixIndex;
        Matrix.multiplyMM(temp, 0, currentMatrix, index, matrix, offset);
        System.arraycopy(temp, 0, currentMatrix, index, 16);
    
private voidprepareDraw(int offset, int color, float lineWidth)

        GLES20.glUseProgram(mDrawProgram);
        checkError();
        if (lineWidth > 0) {
            GLES20.glLineWidth(lineWidth);
            checkError();
        }
        float[] colorArray = getColor(color);
        boolean blendingEnabled = (colorArray[3] < 1f);
        enableBlending(blendingEnabled);
        if (blendingEnabled) {
            GLES20.glBlendColor(colorArray[0], colorArray[1], colorArray[2], colorArray[3]);
            checkError();
        }

        GLES20.glUniform4fv(mDrawParameters[INDEX_COLOR].handle, 1, colorArray, 0);
        setPosition(mDrawParameters, offset);
        checkError();
    
private com.android.gallery3d.glrenderer.GLES20Canvas$ShaderParameter[]prepareTexture(BasicTexture texture)

        ShaderParameter[] params;
        int program;
        if (texture.getTarget() == GLES20.GL_TEXTURE_2D) {
            params = mTextureParameters;
            program = mTextureProgram;
        } else {
            params = mOesTextureParameters;
            program = mOesTextureProgram;
        }
        prepareTexture(texture, program, params);
        return params;
    
private voidprepareTexture(BasicTexture texture, int program, com.android.gallery3d.glrenderer.GLES20Canvas$ShaderParameter[] params)

        GLES20.glUseProgram(program);
        checkError();
        enableBlending(!texture.isOpaque() || getAlpha() < OPAQUE_ALPHA);
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        checkError();
        texture.onBind(this);
        GLES20.glBindTexture(texture.getTarget(), texture.getId());
        checkError();
        GLES20.glUniform1i(params[INDEX_TEXTURE_SAMPLER].handle, 0);
        checkError();
        GLES20.glUniform1f(params[INDEX_ALPHA].handle, getAlpha());
        checkError();
    
private static voidprintMatrix(java.lang.String message, float[] m, int offset)

        StringBuilder b = new StringBuilder(message);
        for (int i = 0; i < MATRIX_SIZE; i++) {
            b.append(' ");
            if (i % 4 == 0) {
                b.append('\n");
            }
            b.append(m[offset + i]);
        }
        Log.v(TAG, b.toString());
    
public voidrecoverFromLightCycle()

        GLES20.glViewport(0, 0, mWidth, mHeight);
        GLES20.glDisable(GLES20.GL_DEPTH_TEST);
        GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA);
        checkError();
    
public voidrestore()

        int restoreFlags = mSaveFlags.removeLast();
        boolean restoreAlpha = (restoreFlags & SAVE_FLAG_ALPHA) == SAVE_FLAG_ALPHA;
        if (restoreAlpha) {
            mCurrentAlphaIndex--;
        }
        boolean restoreMatrix = (restoreFlags & SAVE_FLAG_MATRIX) == SAVE_FLAG_MATRIX;
        if (restoreMatrix) {
            mCurrentMatrixIndex -= MATRIX_SIZE;
        }
    
public voidrotate(float angle, float x, float y, float z)

        if (angle == 0f) {
            return;
        }
        float[] temp = mTempMatrix;
        Matrix.setRotateM(temp, 0, angle, x, y, z);
        float[] matrix = mMatrices;
        int index = mCurrentMatrixIndex;
        Matrix.multiplyMM(temp, MATRIX_SIZE, matrix, index, temp, 0);
        System.arraycopy(temp, MATRIX_SIZE, matrix, index, MATRIX_SIZE);
    
public voidsave()

        save(SAVE_FLAG_ALL);
    
public voidsave(int saveFlags)

        boolean saveAlpha = (saveFlags & SAVE_FLAG_ALPHA) == SAVE_FLAG_ALPHA;
        if (saveAlpha) {
            float currentAlpha = getAlpha();
            mCurrentAlphaIndex++;
            if (mAlphas.length <= mCurrentAlphaIndex) {
                mAlphas = Arrays.copyOf(mAlphas, mAlphas.length * 2);
            }
            mAlphas[mCurrentAlphaIndex] = currentAlpha;
        }
        boolean saveMatrix = (saveFlags & SAVE_FLAG_MATRIX) == SAVE_FLAG_MATRIX;
        if (saveMatrix) {
            int currentIndex = mCurrentMatrixIndex;
            mCurrentMatrixIndex += MATRIX_SIZE;
            if (mMatrices.length <= mCurrentMatrixIndex) {
                mMatrices = Arrays.copyOf(mMatrices, mMatrices.length * 2);
            }
            System.arraycopy(mMatrices, currentIndex, mMatrices, mCurrentMatrixIndex, MATRIX_SIZE);
        }
        mSaveFlags.add(saveFlags);
    
public voidscale(float sx, float sy, float sz)

        Matrix.scaleM(mMatrices, mCurrentMatrixIndex, sx, sy, sz);
    
public voidsetAlpha(float alpha)

        mAlphas[mCurrentAlphaIndex] = alpha;
    
private voidsetMatrix(com.android.gallery3d.glrenderer.GLES20Canvas$ShaderParameter[] params, float x, float y, float width, float height)

        Matrix.translateM(mTempMatrix, 0, mMatrices, mCurrentMatrixIndex, x, y, 0f);
        Matrix.scaleM(mTempMatrix, 0, width, height, 1f);
        Matrix.multiplyMM(mTempMatrix, MATRIX_SIZE, mProjectionMatrix, 0, mTempMatrix, 0);
        GLES20.glUniformMatrix4fv(params[INDEX_MATRIX].handle, 1, false, mTempMatrix, MATRIX_SIZE);
        checkError();
    
private voidsetPosition(com.android.gallery3d.glrenderer.GLES20Canvas$ShaderParameter[] params, int offset)

        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mBoxCoordinates);
        checkError();
        GLES20.glVertexAttribPointer(params[INDEX_POSITION].handle, COORDS_PER_VERTEX,
                GLES20.GL_FLOAT, false, VERTEX_STRIDE, offset * VERTEX_STRIDE);
        checkError();
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
        checkError();
    
private voidsetRenderTarget(BasicTexture oldTexture, RawTexture texture)

        if (oldTexture == null && texture != null) {
            GLES20.glGenFramebuffers(1, mFrameBuffer, 0);
            checkError();
            GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBuffer[0]);
            checkError();
        } else if (oldTexture != null && texture == null) {
            GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
            checkError();
            GLES20.glDeleteFramebuffers(1, mFrameBuffer, 0);
            checkError();
        }

        if (texture == null) {
            setSize(mScreenWidth, mScreenHeight);
        } else {
            setSize(texture.getWidth(), texture.getHeight());

            if (!texture.isLoaded()) {
                texture.prepare(this);
            }

            GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
                    texture.getTarget(), texture.getId(), 0);
            checkError();

            checkFramebufferStatus();
        }
    
public voidsetSize(int width, int height)

        mWidth = width;
        mHeight = height;
        GLES20.glViewport(0, 0, mWidth, mHeight);
        checkError();
        Matrix.setIdentityM(mMatrices, mCurrentMatrixIndex);
        Matrix.orthoM(mProjectionMatrix, 0, 0, width, 0, height, -1, 1);
        if (getTargetTexture() == null) {
            mScreenWidth = width;
            mScreenHeight = height;
            Matrix.translateM(mMatrices, mCurrentMatrixIndex, 0, height, 0);
            Matrix.scaleM(mMatrices, mCurrentMatrixIndex, 1, -1, 1);
        }
    
private voidsetTextureMatrix(android.graphics.RectF source)

        mTempTextureMatrix[0] = source.width();
        mTempTextureMatrix[5] = source.height();
        mTempTextureMatrix[12] = source.left;
        mTempTextureMatrix[13] = source.top;
    
public voidsetTextureParameters(BasicTexture texture)

        int target = texture.getTarget();
        GLES20.glBindTexture(target, texture.getId());
        checkError();
        GLES20.glTexParameteri(target, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameteri(target, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameterf(target, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameterf(target, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
    
public voidtexSubImage2D(BasicTexture texture, int xOffset, int yOffset, android.graphics.Bitmap bitmap, int format, int type)

        int target = texture.getTarget();
        GLES20.glBindTexture(target, texture.getId());
        checkError();
        GLUtils.texSubImage2D(target, 0, xOffset, yOffset, bitmap, format, type);
    
public voidtranslate(float x, float y, float z)

        Matrix.translateM(mMatrices, mCurrentMatrixIndex, x, y, z);
    
public voidtranslate(float x, float y)

        int index = mCurrentMatrixIndex;
        float[] m = mMatrices;
        m[index + 12] += m[index + 0] * x + m[index + 4] * y;
        m[index + 13] += m[index + 1] * x + m[index + 5] * y;
        m[index + 14] += m[index + 2] * x + m[index + 6] * y;
        m[index + 15] += m[index + 3] * x + m[index + 7] * y;
    
public booleanunloadTexture(BasicTexture texture)

        boolean unload = texture.isLoaded();
        if (unload) {
            synchronized (mUnboundTextures) {
                mUnboundTextures.add(texture.getId());
            }
        }
        return unload;
    
public intuploadBuffer(java.nio.FloatBuffer buf)

        return uploadBuffer(buf, FLOAT_SIZE);
    
public intuploadBuffer(java.nio.ByteBuffer buf)

        return uploadBuffer(buf, 1);
    
private intuploadBuffer(java.nio.Buffer buffer, int elementSize)

        mGLId.glGenBuffers(1, mTempIntArray, 0);
        checkError();
        int bufferId = mTempIntArray[0];
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, bufferId);
        checkError();
        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, buffer.capacity() * elementSize, buffer,
                GLES20.GL_STATIC_DRAW);
        checkError();
        return bufferId;