Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0820262b authored by Owen Lin's avatar Owen Lin Committed by Android (Google) Code Review
Browse files

Merge "Add support to draw on texture." into jb-dev

parents eea90e65 8ac2e863
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -117,4 +117,8 @@ public interface GLCanvas {

    // Dump statistics information and clear the counters. For debug only.
    public void dumpStatisticsAndClear();

    public void beginRenderTarget(RawTexture texture);

    public void endRenderTarget();
}
+96 −11
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package com.android.gallery3d.ui;

import android.graphics.Rect;
import android.graphics.RectF;
import android.opengl.GLU;
import android.opengl.Matrix;
@@ -32,6 +31,7 @@ import java.util.ArrayList;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;
import javax.microedition.khronos.opengles.GL11Ext;
import javax.microedition.khronos.opengles.GL11ExtensionPack;

public class GLCanvasImpl implements GLCanvas {
    @SuppressWarnings("unused")
@@ -61,10 +61,10 @@ public class GLCanvasImpl implements GLCanvas {
    private int mBoxCoords;

    private final GLState mGLState;
    private final ArrayList<RawTexture> mTargetStack = new ArrayList<RawTexture>();

    private float mAlpha;
    private final ArrayList<ConfigState> mRestoreStack =
            new ArrayList<ConfigState>();
    private final ArrayList<ConfigState> mRestoreStack = new ArrayList<ConfigState>();
    private ConfigState mRecycledRestoreAction;

    private final RectF mDrawTextureSourceRect = new RectF();
@@ -72,8 +72,12 @@ public class GLCanvasImpl implements GLCanvas {
    private final float[] mTempMatrix = new float[32];
    private final IntArray mUnboundTextures = new IntArray();
    private final IntArray mDeleteBuffers = new IntArray();
    private int mHeight;
    private int mScreenWidth;
    private int mScreenHeight;
    private boolean mBlendEnabled = true;
    private int mFrameBuffer[] = new int[1];

    private RawTexture mTargetTexture;

    // Drawing statistics
    int mCountDrawLine;
@@ -90,7 +94,12 @@ public class GLCanvasImpl implements GLCanvas {

    public void setSize(int width, int height) {
        Utils.assertTrue(width >= 0 && height >= 0);
        mHeight = height;

        if (mTargetTexture == null) {
            mScreenWidth = width;
            mScreenHeight = height;
        }
        mAlpha = 1.0f;

        GL11 gl = mGL;
        gl.glViewport(0, 0, width, height);
@@ -100,12 +109,15 @@ public class GLCanvasImpl implements GLCanvas {

        gl.glMatrixMode(GL11.GL_MODELVIEW);
        gl.glLoadIdentity();
        float matrix[] = mMatrixValues;

        float matrix[] = mMatrixValues;
        Matrix.setIdentityM(matrix, 0);
        Matrix.translateM(matrix, 0, 0, mHeight, 0);
        // to match the graphic coordinate system in android, we flip it vertically.
        if (mTargetTexture == null) {
            Matrix.translateM(matrix, 0, 0, height, 0);
            Matrix.scaleM(matrix, 0, 1, -1, 1);
        }
    }

    public void setAlpha(float alpha) {
        Utils.assertTrue(alpha >= 0 && alpha <= 1);
@@ -151,8 +163,7 @@ public class GLCanvasImpl implements GLCanvas {
        gl.glClientActiveTexture(GL11.GL_TEXTURE0);
        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

        // mMatrixValues will be initialized in setSize()
        mAlpha = 1.0f;
        // mMatrixValues and mAlpha will be initialized in setSize()
    }

    public void drawRect(float x, float y, float width, float height, GLPaint paint) {
@@ -724,7 +735,6 @@ public class GLCanvasImpl implements GLCanvas {

    private static class ConfigState {
        float mAlpha;
        Rect mRect = new Rect();
        float mMatrix[] = new float[16];
        ConfigState mNextFree;

@@ -756,4 +766,79 @@ public class GLCanvasImpl implements GLCanvas {
    private void restoreTransform() {
        System.arraycopy(mTempMatrix, 0, mMatrixValues, 0, 16);
    }

    private void setRenderTarget(RawTexture texture) {
        GL11ExtensionPack gl11ep = (GL11ExtensionPack) mGL;

        if (mTargetTexture == null && texture != null) {
            GLId.glGenBuffers(1, mFrameBuffer, 0);
            gl11ep.glBindFramebufferOES(
                    GL11ExtensionPack.GL_FRAMEBUFFER_OES, mFrameBuffer[0]);
        }
        if (mTargetTexture != null && texture  == null) {
            gl11ep.glBindFramebufferOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, 0);
            gl11ep.glDeleteFramebuffersOES(1, mFrameBuffer, 0);
        }

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

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

            gl11ep.glFramebufferTexture2DOES(
                    GL11ExtensionPack.GL_FRAMEBUFFER_OES,
                    GL11ExtensionPack.GL_COLOR_ATTACHMENT0_OES,
                    GL11.GL_TEXTURE_2D, texture.getId(), 0);

            checkFramebufferStatus(gl11ep);
        }
    }

    @Override
    public void endRenderTarget() {
        RawTexture texture = mTargetStack.remove(mTargetStack.size() - 1);
        setRenderTarget(texture);
        restore(); // restore matrix and alpha
    }

    @Override
    public void beginRenderTarget(RawTexture texture) {
        save(); // save matrix and alpha
        mTargetStack.add(mTargetTexture);
        setRenderTarget(texture);
    }

    private static void checkFramebufferStatus(GL11ExtensionPack gl11ep) {
        int status = gl11ep.glCheckFramebufferStatusOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES);
        if (status != GL11ExtensionPack.GL_FRAMEBUFFER_COMPLETE_OES) {
            String msg = "";
            switch (status) {
                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES:
                    msg = "FRAMEBUFFER_FORMATS";
                    break;
                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES:
                    msg = "FRAMEBUFFER_ATTACHMENT";
                    break;
                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES:
                    msg = "FRAMEBUFFER_MISSING_ATTACHMENT";
                    break;
                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_OES:
                    msg = "FRAMEBUFFER_DRAW_BUFFER";
                    break;
                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_OES:
                    msg = "FRAMEBUFFER_READ_BUFFER";
                    break;
                case GL11ExtensionPack.GL_FRAMEBUFFER_UNSUPPORTED_OES:
                    msg = "FRAMEBUFFER_UNSUPPORTED";
                    break;
                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES:
                    msg = "FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
                    break;
            }
            throw new RuntimeException(msg + ":" + Integer.toHexString(status));
        }
    }
}
+0 −169
Original line number Diff line number Diff line
/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.gallery3d.ui;

import android.opengl.GLU;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL11;
import javax.microedition.khronos.opengles.GL11Ext;
import javax.microedition.khronos.opengles.GL11ExtensionPack;

/**
 * A wrapper class of GL 2D texture.
 */
public class Raw2DTexture extends BasicTexture {
    private static final int[] sTextureId = new int[1];
    // OpenGL related fields used when copy.
    private static final int[] sBufferName = new int[1];
    private int mFBO;  // Frame buffer object.

    // We need copy from another texture when in camera capture animation.
    // The copy is done through a framebuffer object with an attached
    // destination texture. The source texture is rendered to the framebuffer
    // and the data will be stored in the destination texture.
    public static void copy(GLCanvas canvas, BasicTexture src, Raw2DTexture dst) {
        int[] viewPort = new int[4];
        GL11 gl11 = canvas.getGLInstance();
        GL11ExtensionPack gl11ep = (GL11ExtensionPack) gl11;

        if (!dst.isLoaded(canvas)) {
            dst.prepare(canvas.getGLInstance());
        }

        gl11ep.glBindFramebufferOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, dst.mFBO);
        gl11ep.glFramebufferTexture2DOES(
                GL11ExtensionPack.GL_FRAMEBUFFER_OES,
                GL11ExtensionPack.GL_COLOR_ATTACHMENT0_OES,
                GL11.GL_TEXTURE_2D,
                dst.getId(), 0);
        checkFramebufferStatus(gl11ep);

        // Draw the source onto our destination.
        // The texture coords and vertex pointer are already set properly. We don't
        // need to set again.
        gl11.glBindTexture(src.getTarget(), src.getId());
        boolean targetEnabled = gl11.glIsEnabled(src.getTarget());
        gl11.glEnable(src.getTarget());

        // Set the texture matrix.
        gl11.glMatrixMode(GL11.GL_TEXTURE);
        gl11.glPushMatrix();
        gl11.glLoadIdentity();

        // Set the view port.
        gl11.glGetIntegerv(GL11.GL_VIEWPORT, viewPort, 0);
        gl11.glViewport(0, 0, dst.getTextureWidth(), dst.getTextureHeight());

        // Set the projection matrix.
        gl11.glMatrixMode(GL11.GL_PROJECTION);
        gl11.glPushMatrix();
        gl11.glLoadIdentity();
        GLU.gluOrtho2D(gl11, 0, 1, 0, 1);

        // Set the modelview matrix.
        gl11.glMatrixMode(GL11.GL_MODELVIEW);
        gl11.glPushMatrix();
        gl11.glLoadIdentity();

        // Draw the texture.
        gl11.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, 4);

        // Clear.
        if (!targetEnabled) gl11.glDisable(src.getTarget());
        gl11ep.glBindFramebufferOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, 0);
        gl11.glBindTexture(src.getTarget(), 0);
        gl11.glViewport(viewPort[0], viewPort[1], viewPort[2], viewPort[3]);
        gl11.glMatrixMode(GL11.GL_TEXTURE);
        gl11.glPopMatrix();
        gl11.glMatrixMode(GL11.GL_PROJECTION);
        gl11.glPopMatrix();
        gl11.glMatrixMode(GL11.GL_MODELVIEW);
        gl11.glPopMatrix();
        GLId.glDeleteFramebuffers(gl11ep, 1, dst.sBufferName, 0);
    }

    public Raw2DTexture(int w, int h) {
        setSize(w, h);
        GLId.glGenTextures(1, sTextureId, 0);
        mId = sTextureId[0];
        GLId.glGenBuffers(1, sBufferName, 0);
        mFBO = sBufferName[0];
    }

    private void prepare(GL11 gl11) {
        gl11.glBindTexture(GL11.GL_TEXTURE_2D, mId);
        gl11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP_TO_EDGE);
        gl11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP_TO_EDGE);
        gl11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
        gl11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
        gl11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA,
                getTextureWidth(), getTextureHeight(),
                0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, null);
        gl11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
        mState = UploadedTexture.STATE_LOADED;
    }

    @Override
    protected boolean onBind(GLCanvas canvas) {
        if (!isLoaded(canvas)) {
            return false;
        }

        return true;
    }

    @Override
    public int getTarget() {
        return GL11.GL_TEXTURE_2D;
    }

    public boolean isOpaque() {
        return true;
    }

    @Override
    public void yield() {
        // we cannot free the texture because we have no backup.
    }

    private static void checkFramebufferStatus(GL11ExtensionPack gl11ep) {
        int status = gl11ep.glCheckFramebufferStatusOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES);
        if (status != GL11ExtensionPack.GL_FRAMEBUFFER_COMPLETE_OES) {
            String msg = "";
            switch (status) {
                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES:
                    msg = "FRAMEBUFFER_FORMATS"; break;
                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES:
                    msg = "FRAMEBUFFER_ATTACHMENT"; break;
                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES:
                    msg = "FRAMEBUFFER_MISSING_ATTACHMENT"; break;
                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_OES:
                    msg = "FRAMEBUFFER_DRAW_BUFFER"; break;
                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_OES:
                    msg = "FRAMEBUFFER_READ_BUFFER"; break;
                case GL11ExtensionPack.GL_FRAMEBUFFER_UNSUPPORTED_OES:
                    msg = "FRAMEBUFFER_UNSUPPORTED"; break;
                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES:
                    msg = "FRAMEBUFFER_INCOMPLETE_DIMENSIONS"; break;
            }
            throw new RuntimeException(msg + ":" + Integer.toHexString(status));
        }
    }
}
+91 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.gallery3d.ui;

import javax.microedition.khronos.opengles.GL11;
import javax.microedition.khronos.opengles.GL11Ext;

public class RawTexture extends BasicTexture {
    private static final String TAG = "RawTexture";

    private final static int[] sTextureId = new int[1];
    private final static float[] sCropRect = new float[4];

    private final boolean mOpaque;

    public RawTexture(int width, int height, boolean opaque) {
        mOpaque = opaque;
        setSize(width, height);
    }

    @Override
    public boolean isOpaque() {
        return mOpaque;
    }

    protected void prepare(GLCanvas canvas) {
        GL11 gl = canvas.getGLInstance();

        // Define a vertically flipped crop rectangle for
        // OES_draw_texture.
        // The four values in sCropRect are: left, bottom, width, and
        // height. Negative value of width or height means flip.
        sCropRect[0] = 0;
        sCropRect[1] = mHeight;
        sCropRect[2] = mWidth;
        sCropRect[3] = -mHeight;

        // Upload the bitmap to a new texture.
        GLId.glGenTextures(1, sTextureId, 0);
        gl.glBindTexture(GL11.GL_TEXTURE_2D, sTextureId[0]);
        gl.glTexParameterfv(GL11.GL_TEXTURE_2D,
                GL11Ext.GL_TEXTURE_CROP_RECT_OES, sCropRect, 0);
        gl.glTexParameteri(GL11.GL_TEXTURE_2D,
                GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP_TO_EDGE);
        gl.glTexParameteri(GL11.GL_TEXTURE_2D,
                GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP_TO_EDGE);
        gl.glTexParameterf(GL11.GL_TEXTURE_2D,
                GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
        gl.glTexParameterf(GL11.GL_TEXTURE_2D,
                GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);

        gl.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA,
                getTextureWidth(), getTextureHeight(),
                0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, null);

        mId = sTextureId[0];
        mState = UploadedTexture.STATE_LOADED;
        setAssociatedCanvas(canvas);
    }

    @Override
    protected boolean onBind(GLCanvas canvas) {
        if (isLoaded(canvas)) return true;
        Log.w(TAG, "lost the content due to context change");
        return false;
    }

    @Override
     public void yield() {
         // we cannot free the texture because we have no backup.
     }

    @Override
    protected int getTarget() {
        return GL11.GL_TEXTURE_2D;
    }
}
+2 −0
Original line number Diff line number Diff line
@@ -80,4 +80,6 @@ public class GLCanvasStub implements GLCanvas {
    public void deleteRecycledResources() {}
    public void multiplyMatrix(float[] mMatrix, int offset) {}
    public void dumpStatisticsAndClear() {}
    public void beginRenderTarget(RawTexture texture) {}
    public void endRenderTarget() {}
}