1430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd// Copyright 2011 Google Inc. All Rights Reserved.
2430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
3430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Doddpackage com.example.android.videochatcameratest;
4430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
5430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Doddimport android.content.Context;
6430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Doddimport android.graphics.SurfaceTexture;
7430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Doddimport android.graphics.SurfaceTexture.OnFrameAvailableListener;
8430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Doddimport android.opengl.GLES20;
9430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Doddimport android.opengl.GLSurfaceView;
10430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Doddimport android.util.AttributeSet;
11430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Doddimport android.util.Log;
12430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
13430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Doddimport java.nio.ByteBuffer;
14430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Doddimport java.nio.ByteOrder;
15430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Doddimport java.nio.FloatBuffer;
16430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Doddimport java.util.concurrent.atomic.AtomicBoolean;
17430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Doddimport java.util.concurrent.atomic.AtomicInteger;
18430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
19430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Doddimport javax.microedition.khronos.egl.EGLConfig;
20430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Doddimport javax.microedition.khronos.opengles.GL10;
21430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
22430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Doddclass SurfaceTextureView extends GLSurfaceView {
23430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    static final private String TAG = "VideoChatTest";
24430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
25430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    private int mTextureName;
26430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    private SurfaceTexture mSurfaceTexture;
27430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    public int getTextureName() {
28430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        return mTextureName;
29430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    }
30430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    public SurfaceTexture getSurfaceTexture() {
31430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        return mSurfaceTexture;
32430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    }
33430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
34430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    public static int loadShader(int shaderType, String source) {
35430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        int shader = GLES20.glCreateShader(shaderType);
36430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        if (shader != 0) {
37430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            GLES20.glShaderSource(shader, source);
38430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            GLES20.glCompileShader(shader);
39430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            int[] compiled = new int[1];
40430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
41430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            if (compiled[0] == 0) {
42430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                Log.e(TAG, "Could not compile shader " + shaderType + ":");
43430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
44430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                GLES20.glDeleteShader(shader);
45430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                shader = 0;
46430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            }
47430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        }
48430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        return shader;
49430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    }
50430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
51430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    public static void checkGlError(String op) {
52430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        int error;
53430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
54430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            Log.e(TAG, op + ": glError " + error);
55430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            throw new RuntimeException(op + ": glError " + error);
56430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        }
57430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    }
58430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
59430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    public static int createProgram(String vertexSource, String fragmentSource) {
60430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
61430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        if (vertexShader == 0) {
62430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            return 0;
63430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        }
64430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
65430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        if (pixelShader == 0) {
66430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            return 0;
67430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        }
68430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
69430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        int program = GLES20.glCreateProgram();
70430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        if (program != 0) {
71430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            GLES20.glAttachShader(program, vertexShader);
72430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            checkGlError("glAttachShader");
73430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            GLES20.glAttachShader(program, pixelShader);
74430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            checkGlError("glAttachShader");
75430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            GLES20.glLinkProgram(program);
76430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            int[] linkStatus = new int[1];
77430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
78430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            if (linkStatus[0] != GLES20.GL_TRUE) {
79430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                Log.e(TAG, "Could not link program: ");
80430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                Log.e(TAG, GLES20.glGetProgramInfoLog(program));
81430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                GLES20.glDeleteProgram(program);
82430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                program = 0;
83430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            }
84430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        }
85430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        return program;
86430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    }
87430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
88430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    AtomicInteger mReportedFrameCount = new AtomicInteger();
89430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    AtomicBoolean mCameraEnabled = new AtomicBoolean();
90430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    AtomicInteger mCameraFrameCount = new AtomicInteger();
91430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
92430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    /**
93430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd     * @param context
94430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd     */
95430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    public SurfaceTextureView(Context context) {
96430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        super(context);
97430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        init();
98430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    }
99430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
100430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    public SurfaceTextureView(Context context, AttributeSet attrs) {
101430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        super(context, attrs);
102430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        init();
103430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    }
104430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
105430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    private void init() {
106430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        setEGLContextClientVersion(2);
107430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        setRenderer(new Renderer());
108430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    }
109430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
110430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    public void setCameraEnabled(boolean enabled) {
111430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        mCameraEnabled.set(enabled);
112430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    }
113430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
114430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    public void resetFrameCounter() {
115430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        mReportedFrameCount.set(0);
116430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    }
117430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
118430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    public int getFrameCounter() {
119430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        return mReportedFrameCount.get();
120430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    }
121430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
122430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    class Renderer implements GLSurfaceView.Renderer {
123430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        private final static String VERTEX_SHADER =
124430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            "attribute vec4 vPosition;\n" +
125430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            "attribute vec2 a_texCoord;\n" +
126430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            "varying vec2 v_texCoord;\n" +
127430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            "uniform mat4 u_xform;\n" +
128430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            "void main() {\n" +
129430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            "  gl_Position = vPosition;\n" +
130430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            "  v_texCoord = vec2(u_xform * vec4(a_texCoord, 1.0, 1.0));\n" +
131430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            "}\n";
132430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
133430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        private final static String FRAGMENT_SHADER =
134430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            "#extension GL_OES_EGL_image_external : require\n" +
135430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            "precision mediump float;\n" +
136430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            "uniform samplerExternalOES s_texture;\n" +
137430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            "varying vec2 v_texCoord;\n" +
138430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            "void main() {\n" +
139430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            "  gl_FragColor = texture2D(s_texture, v_texCoord);\n" +
140430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            "}\n";
141430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
142430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        private final float[] TEXTURE_VERTICES =
143430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            { 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f };
144430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
145430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        private final float[] QUAD_VERTICES =
146430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            { 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f };
147430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
148430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        private final static int FLOAT_SIZE_BYTES = 4;
149430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
150430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        private final FloatBuffer mTextureVertices;
151430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        private final FloatBuffer mQuadVertices;
152430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
153430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
154430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        private int mGLProgram;
155430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        private int mTexHandle;
156430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        private int mTexCoordHandle;
157430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        private int mTriangleVerticesHandle;
158430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        private int mTransformHandle;
159430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        private int mViewWidth;
160430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        private int mViewHeight;
161430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        private float[] mTransformMatrix;
162430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        private int mLastCameraFrameCount;
163430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        public Renderer() {
164430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            mTextureVertices = ByteBuffer.allocateDirect(TEXTURE_VERTICES.length *
165430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                    FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
166430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            mTextureVertices.put(TEXTURE_VERTICES).position(0);
167430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            mQuadVertices = ByteBuffer.allocateDirect(QUAD_VERTICES.length *
168430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                    FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
169430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            mQuadVertices.put(QUAD_VERTICES).position(0);
170430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            mTransformMatrix = new float[16];
171430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            mLastCameraFrameCount = mCameraFrameCount.get();
172430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        }
173430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
174430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        @Override
175430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
176430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            mGLProgram = createProgram(VERTEX_SHADER, FRAGMENT_SHADER);
177430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
178430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            mTexHandle = GLES20.glGetUniformLocation(mGLProgram, "s_texture");
179430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            mTexCoordHandle = GLES20.glGetAttribLocation(mGLProgram, "a_texCoord");
180430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            mTriangleVerticesHandle = GLES20.glGetAttribLocation(mGLProgram, "vPosition");
181430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            mTransformHandle = GLES20.glGetUniformLocation(mGLProgram, "u_xform");
182430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            int[] textures = new int[1];
183430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            GLES20.glGenTextures(1, textures, 0);
184430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            mTextureName = textures[0];
185430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            GLES20.glUseProgram(mGLProgram);
186430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            GLES20.glVertexAttribPointer(mTexCoordHandle, 2, GLES20.GL_FLOAT,
187430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                    false, 0, mTextureVertices);
188430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            GLES20.glVertexAttribPointer(mTriangleVerticesHandle, 2, GLES20.GL_FLOAT,
189430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                    false, 0, mQuadVertices);
190430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            checkGlError("initialization");
191430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            mSurfaceTexture = new SurfaceTexture(mTextureName);
192430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            mSurfaceTexture.setOnFrameAvailableListener(new OnFrameAvailableListener() {
193430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                @Override
194430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                public void onFrameAvailable(SurfaceTexture surfaceTexture) {
195430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                    mCameraFrameCount.incrementAndGet();
196430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                }
197430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            });
198430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        }
199430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
200430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        /* (non-Javadoc)
201430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd         * @see android.opengl.GLSurfaceView.Renderer#onSurfaceChanged(javax.microedition.khronos.opengles.GL10, int, int)
202430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd         */
203430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        @Override
204430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        public void onSurfaceChanged(GL10 gl, int width, int height) {
205430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            mViewWidth = width;
206430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            mViewHeight = height;
207430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        }
208430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
209430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        private static final int GL_TEXTURE_EXTERNAL_OES = 0x8D65;
210430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        @Override
211430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        public void onDrawFrame(GL10 gl) {
212430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            GLES20.glUseProgram(mGLProgram);
213430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            GLES20.glViewport(0, 0, mViewWidth, mViewHeight);
214430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            checkGlError("glViewport");
215430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
216430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            if (mCameraEnabled.get()) {
217430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                int cameraFrameCount = mCameraFrameCount.get();
218430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                if (mLastCameraFrameCount != cameraFrameCount) {
219430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                    mReportedFrameCount.incrementAndGet();
220430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                    mSurfaceTexture.updateTexImage();
221430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                    mSurfaceTexture.getTransformMatrix(mTransformMatrix);
222430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                    GLES20.glUniformMatrix4fv(mTransformHandle, 1, false, mTransformMatrix, 0);
223430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                    checkGlError("glUniformMatrix4fv");
224430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                    mLastCameraFrameCount = cameraFrameCount;
225430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                }
226430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                GLES20.glDisable(GLES20.GL_BLEND);
227430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                checkGlError("setup");
228430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
229430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                checkGlError("setup");
230430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureName);
231430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                checkGlError("setup");
232430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                GLES20.glUniform1i(mTexHandle, 0);
233430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                checkGlError("setup");
234430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                GLES20.glEnableVertexAttribArray(mTexCoordHandle);
235430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                checkGlError("setup");
236430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                GLES20.glEnableVertexAttribArray(mTriangleVerticesHandle);
237430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                checkGlError("setup");
238430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 4);
239430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                checkGlError("glDrawArrays");
240430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            } else {
241430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd                GLES20.glClearColor(0,0,0,0);
242430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd            }
243430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd        }
244430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd
245430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd    }
246430aa048a20aa42f089d213d8b4b6c67ab1b43feMike Dodd}
247