1b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten/* 2b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * Copyright (C) 2011 The Android Open Source Project 3b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * 4b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 5b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * you may not use this file except in compliance with the License. 6b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * You may obtain a copy of the License at 7b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * 8b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 9b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * 10b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * Unless required by applicable law or agreed to in writing, software 11b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 12b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * See the License for the specific language governing permissions and 14b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * limitations under the License. 15b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten */ 16b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 17b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenpackage com.example.nativemedia; 18b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 19b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport android.graphics.SurfaceTexture; 20b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport android.util.Log; 21b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 22b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport java.nio.ByteBuffer; 23b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport java.nio.ByteOrder; 24b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport java.nio.FloatBuffer; 25b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 26b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport javax.microedition.khronos.egl.EGLConfig; 27b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport javax.microedition.khronos.opengles.GL10; 28b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 29b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport android.view.MotionEvent; 30b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport android.content.Context; 31b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 32b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport android.opengl.GLES20; 33b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport android.opengl.GLSurfaceView; 34b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport android.opengl.Matrix; 35b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 36b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport android.hardware.SensorManager; 37b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport android.hardware.SensorEvent; 38b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport android.hardware.SensorEventListener; 39b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport android.hardware.Sensor; 40b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 41b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten// Remove once surfacetexture timestamps are in 42b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport java.lang.System; 43b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 44b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport android.util.AttributeSet; 45b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 46c9034c3a484855366b663ce4b9b8c023be65ff95Ming Jiapublic class MyGLSurfaceView extends GLSurfaceView { 47b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 48c9034c3a484855366b663ce4b9b8c023be65ff95Ming Jia MyRenderer mRenderer; 49b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 50b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten public MyGLSurfaceView(Context context) { 51c9034c3a484855366b663ce4b9b8c023be65ff95Ming Jia super(context, null); 52c9034c3a484855366b663ce4b9b8c023be65ff95Ming Jia } 53c9034c3a484855366b663ce4b9b8c023be65ff95Ming Jia 54c9034c3a484855366b663ce4b9b8c023be65ff95Ming Jia public MyGLSurfaceView(Context context, AttributeSet attributeSet) { 55c9034c3a484855366b663ce4b9b8c023be65ff95Ming Jia super(context, attributeSet); 56b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten init(context); 57b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 58b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 59b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private void init(Context context) { 60b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten setEGLContextClientVersion(2); 61b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mRenderer = new MyRenderer(context); 62b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten setRenderer(mRenderer); 63b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 64b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 65b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten @Override 66b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten public void onPause() { 67b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten super.onPause(); 68b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 69b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 70b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten @Override 71b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten public void onResume() { 72b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten super.onResume(); 73b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 74b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 75c9034c3a484855366b663ce4b9b8c023be65ff95Ming Jia public SurfaceTexture getSurfaceTexture() { 76b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten return mRenderer.getSurfaceTexture(); 77b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 78b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten} 79b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 80b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenclass MyRenderer implements GLSurfaceView.Renderer, SurfaceTexture.OnFrameAvailableListener { 81c9034c3a484855366b663ce4b9b8c023be65ff95Ming Jia private Context mContext; 82b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 83b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten public MyRenderer(Context context) { 84b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mContext = context; 85b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 86c9034c3a484855366b663ce4b9b8c023be65ff95Ming Jia mVertices = ByteBuffer.allocateDirect(mVerticesData.length 87b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer(); 88c9034c3a484855366b663ce4b9b8c023be65ff95Ming Jia mVertices.put(mVerticesData).position(0); 89b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 90b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten Matrix.setIdentityM(mSTMatrix, 0); 91b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten Matrix.setIdentityM(mMMatrix, 0); 92c9034c3a484855366b663ce4b9b8c023be65ff95Ming Jia Matrix.rotateM(mMMatrix, 0, 20, 0, 1, 0); 93b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 94b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 95b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten public void onDrawFrame(GL10 glUnused) { 96b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten synchronized(this) { 97b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (updateSurface) { 98b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mSurface.updateTexImage(); 99b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 100b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mSurface.getTransformMatrix(mSTMatrix); 101b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten updateSurface = false; 102b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 103b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 104b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 105b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten // Ignore the passed-in GL10 interface, and use the GLES20 106b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten // class's static methods instead. 107b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT); 108b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glUseProgram(mProgram); 109b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glUseProgram"); 110b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 111b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 112b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureID); 113b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 114c9034c3a484855366b663ce4b9b8c023be65ff95Ming Jia mVertices.position(VERTICES_DATA_POS_OFFSET); 115b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, 116c9034c3a484855366b663ce4b9b8c023be65ff95Ming Jia VERTICES_DATA_STRIDE_BYTES, mVertices); 117b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glVertexAttribPointer maPosition"); 118b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glEnableVertexAttribArray(maPositionHandle); 119b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glEnableVertexAttribArray maPositionHandle"); 120b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 121c9034c3a484855366b663ce4b9b8c023be65ff95Ming Jia mVertices.position(VERTICES_DATA_UV_OFFSET); 122b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glVertexAttribPointer(maTextureHandle, 3, GLES20.GL_FLOAT, false, 123c9034c3a484855366b663ce4b9b8c023be65ff95Ming Jia VERTICES_DATA_STRIDE_BYTES, mVertices); 124b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glVertexAttribPointer maTextureHandle"); 125b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glEnableVertexAttribArray(maTextureHandle); 126b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glEnableVertexAttribArray maTextureHandle"); 127b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 128b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0); 129b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0); 130b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 131b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0); 132b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glUniformMatrix4fv(muSTMatrixHandle, 1, false, mSTMatrix, 0); 133b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 134b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); 135b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glDrawArrays"); 136b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 137b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 138b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten public void onSurfaceChanged(GL10 glUnused, int width, int height) { 139b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten // Ignore the passed-in GL10 interface, and use the GLES20 140b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten // class's static methods instead. 141b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glViewport(0, 0, width, height); 142b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mRatio = (float) width / height; 143b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten Matrix.frustumM(mProjMatrix, 0, -mRatio, mRatio, -1, 1, 3, 7); 144b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 145b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 146b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten public void onSurfaceCreated(GL10 glUnused, EGLConfig config) { 147b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten // Ignore the passed-in GL10 interface, and use the GLES20 148b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten // class's static methods instead. 149b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 150b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten /* Set up alpha blending and an Android background color */ 151b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glEnable(GLES20.GL_BLEND); 152b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA); 153b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glClearColor(0.643f, 0.776f, 0.223f, 1.0f); 154b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 155b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten /* Set up shaders and handles to their variables */ 156b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mProgram = createProgram(mVertexShader, mFragmentShader); 157b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (mProgram == 0) { 158b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten return; 159b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 160b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition"); 161b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glGetAttribLocation aPosition"); 162b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (maPositionHandle == -1) { 163b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten throw new RuntimeException("Could not get attrib location for aPosition"); 164b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 165b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten maTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord"); 166b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glGetAttribLocation aTextureCoord"); 167b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (maTextureHandle == -1) { 168b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten throw new RuntimeException("Could not get attrib location for aTextureCoord"); 169b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 170b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 171b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); 172b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glGetUniformLocation uMVPMatrix"); 173b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (muMVPMatrixHandle == -1) { 174b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten throw new RuntimeException("Could not get attrib location for uMVPMatrix"); 175b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 176b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 177b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten muSTMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uSTMatrix"); 178b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glGetUniformLocation uSTMatrix"); 179b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (muMVPMatrixHandle == -1) { 180b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten throw new RuntimeException("Could not get attrib location for uSTMatrix"); 181b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 182b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 183b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glGetUniformLocation uCRatio"); 184b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (muMVPMatrixHandle == -1) { 185b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten throw new RuntimeException("Could not get attrib location for uCRatio"); 186b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 187b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 188b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten /* 189b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * Create our texture. This has to be done each time the 190b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * surface is created. 191b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten */ 192b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 193b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten int[] textures = new int[1]; 194b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glGenTextures(1, textures, 0); 195b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 196b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mTextureID = textures[0]; 197b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureID); 198b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glBindTexture mTextureID"); 199b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 200b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten // Can't do mipmapping with camera source 201b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, 202b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.GL_NEAREST); 203b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, 204b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.GL_LINEAR); 205b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten // Clamp to edge is the only option 206b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, 207b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.GL_CLAMP_TO_EDGE); 208b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, 209b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.GL_CLAMP_TO_EDGE); 210b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glTexParameteri mTextureID"); 211b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 212b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten /* 213b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * Create the SurfaceTexture that will feed this textureID, and pass it to the camera 214b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten */ 215b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 216b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mSurface = new SurfaceTexture(mTextureID); 217b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mSurface.setOnFrameAvailableListener(this); 218b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 219c9034c3a484855366b663ce4b9b8c023be65ff95Ming Jia Matrix.setLookAtM(mVMatrix, 0, 0, 0, 4f, 0f, 0f, 0f, 0f, 1.0f, 0.0f); 220b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 221b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten synchronized(this) { 222b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten updateSurface = false; 223b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 224b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 225b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 226b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten synchronized public void onFrameAvailable(SurfaceTexture surface) { 227b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten /* For simplicity, SurfaceTexture calls here when it has new 228b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * data available. Call may come in from some random thread, 229b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * so let's be safe and use synchronize. No OpenGL calls can be done here. 230b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten */ 231b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten updateSurface = true; 2323bbd3bb7fcb082eba313614f072c11c41b38ebfeGlenn Kasten //Log.v(TAG, "onFrameAvailable " + surface.getTimestamp()); 233b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 234b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 235b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private int loadShader(int shaderType, String source) { 236b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten int shader = GLES20.glCreateShader(shaderType); 237b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (shader != 0) { 238b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glShaderSource(shader, source); 239b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glCompileShader(shader); 240b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten int[] compiled = new int[1]; 241b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0); 242b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (compiled[0] == 0) { 243b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten Log.e(TAG, "Could not compile shader " + shaderType + ":"); 244b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten Log.e(TAG, GLES20.glGetShaderInfoLog(shader)); 245b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glDeleteShader(shader); 246b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten shader = 0; 247b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 248b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 249b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten return shader; 250b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 251b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 252b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private int createProgram(String vertexSource, String fragmentSource) { 253b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource); 254b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (vertexShader == 0) { 255b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten return 0; 256b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 257b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource); 258b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (pixelShader == 0) { 259b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten return 0; 260b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 261b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 262b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten int program = GLES20.glCreateProgram(); 263b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (program != 0) { 264b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glAttachShader(program, vertexShader); 265b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glAttachShader"); 266b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glAttachShader(program, pixelShader); 267b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glAttachShader"); 268b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glLinkProgram(program); 269b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten int[] linkStatus = new int[1]; 270b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0); 271b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (linkStatus[0] != GLES20.GL_TRUE) { 272b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten Log.e(TAG, "Could not link program: "); 273b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten Log.e(TAG, GLES20.glGetProgramInfoLog(program)); 274b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glDeleteProgram(program); 275b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten program = 0; 276b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 277b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 278b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten return program; 279b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 280b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 281b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private void checkGlError(String op) { 282b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten int error; 283b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) { 284b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten Log.e(TAG, op + ": glError " + error); 285b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten throw new RuntimeException(op + ": glError " + error); 286b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 287b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 288b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 289b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private static final int FLOAT_SIZE_BYTES = 4; 290c9034c3a484855366b663ce4b9b8c023be65ff95Ming Jia private static final int VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES; 291c9034c3a484855366b663ce4b9b8c023be65ff95Ming Jia private static final int VERTICES_DATA_POS_OFFSET = 0; 292c9034c3a484855366b663ce4b9b8c023be65ff95Ming Jia private static final int VERTICES_DATA_UV_OFFSET = 3; 293c9034c3a484855366b663ce4b9b8c023be65ff95Ming Jia private final float[] mVerticesData = { 294b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten // X, Y, Z, U, V 295b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten -1.0f, -1.0f, 0, 0.f, 0.f, 296b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 1.0f, -1.0f, 0, 1.f, 0.f, 297b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten -1.0f, 1.0f, 0, 0.f, 1.f, 298b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 1.0f, 1.0f, 0, 1.f, 1.f, 299b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten }; 300b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 301c9034c3a484855366b663ce4b9b8c023be65ff95Ming Jia private FloatBuffer mVertices; 302b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 303b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private final String mVertexShader = 304b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "uniform mat4 uMVPMatrix;\n" + 305b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "uniform mat4 uSTMatrix;\n" + 306b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "attribute vec4 aPosition;\n" + 307b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "attribute vec4 aTextureCoord;\n" + 308b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "varying vec2 vTextureCoord;\n" + 309b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "void main() {\n" + 310c9034c3a484855366b663ce4b9b8c023be65ff95Ming Jia " gl_Position = uMVPMatrix * aPosition;\n" + 311b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten " vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n" + 312b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "}\n"; 313b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 314b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private final String mFragmentShader = 315b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "#extension GL_OES_EGL_image_external : require\n" + 316b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "precision mediump float;\n" + 317b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "varying vec2 vTextureCoord;\n" + 318b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "uniform samplerExternalOES sTexture;\n" + 319b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "void main() {\n" + 320b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten " gl_FragColor = texture2D(sTexture, vTextureCoord);\n" + 321b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "}\n"; 322b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 323b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private float[] mMVPMatrix = new float[16]; 324b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private float[] mProjMatrix = new float[16]; 325b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private float[] mMMatrix = new float[16]; 326b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private float[] mVMatrix = new float[16]; 327b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private float[] mSTMatrix = new float[16]; 328b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 329b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private int mProgram; 330b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private int mTextureID; 331b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private int muMVPMatrixHandle; 332b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private int muSTMatrixHandle; 333b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private int maPositionHandle; 334b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private int maTextureHandle; 335b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 336b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private float mRatio = 1.0f; 337b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private SurfaceTexture mSurface; 338b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private boolean updateSurface = false; 339b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 340b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private static final String TAG = "MyRenderer"; 341b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 342b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten // Magic key 343b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private static final int GL_TEXTURE_EXTERNAL_OES = 0x8D65; 344b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 345c9034c3a484855366b663ce4b9b8c023be65ff95Ming Jia public SurfaceTexture getSurfaceTexture() { 346b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten return mSurface; 347b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 348b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten} 349