• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.cts.verifier.sensors.sixdof.Renderer.Renderable;
17 
18 import static com.android.cts.verifier.sensors.sixdof.Utils.MathsUtils.X;
19 import static com.android.cts.verifier.sensors.sixdof.Utils.MathsUtils.Y;
20 import static com.android.cts.verifier.sensors.sixdof.Utils.MathsUtils.Z;
21 
22 import android.content.Context;
23 import android.graphics.SurfaceTexture;
24 import android.opengl.GLES11Ext;
25 import android.opengl.GLES20;
26 import android.opengl.Matrix;
27 import android.util.Log;
28 
29 import com.android.cts.verifier.sensors.sixdof.Renderer.RenderUtils.CameraStreamManager;
30 import com.android.cts.verifier.sensors.sixdof.Renderer.RenderUtils.DrawParameters;
31 import com.android.cts.verifier.sensors.sixdof.Renderer.RenderUtils.ShaderHelper;
32 
33 import java.nio.ByteBuffer;
34 import java.nio.ByteOrder;
35 import java.nio.FloatBuffer;
36 
37 /**
38  * Shows the camera preview as an opengl texture.
39  */
40 public class CameraPreviewRenderable extends Renderable {
41     private static final String TAG = "CameraPreviewRenderable";
42     private final int TEXTURE_COORDINATE_DATA_SIZE = 2;
43     private static final float[] CAMERA_TEXTURE_DATA = {
44             0.0f, 0.0f,
45             0.0f, 1.0f,
46             1.0f, 0.0f,
47             0.0f, 1.0f,
48             1.0f, 1.0f,
49             1.0f, 0.0f
50     };
51     private static final float[] CAMERA_PREVIEW_POSITION = {0.0f, 0.0f, -3.0f};
52 
53     private FloatBuffer mPositionBuffer;
54     private FloatBuffer mTextureBuffer;
55 
56     private int mTextureUniformHandle;
57     private int mTextureCoordinateHandle;
58 
59     protected int mCameraTextureId = -1;
60 
61     private SurfaceTexture mCameraSurfaceTexture;
62     private Context mContext;
63     private CameraStreamManager mCameraStreamManager;
64     private boolean mInvertAxis;
65 
CameraPreviewRenderable()66     public CameraPreviewRenderable() {
67         // Reset the model matrix to the identity and move it so the OpenGL camera is looking at it.
68         Matrix.setIdentityM(getModelMatrix(), 0);
69         Matrix.translateM(getModelMatrix(), 0,
70                 CAMERA_PREVIEW_POSITION[X], CAMERA_PREVIEW_POSITION[Y], CAMERA_PREVIEW_POSITION[Z]);
71     }
72 
initialiseCameraPreview(float[] cameraPreviewPositionData, boolean invertAxis, Context context)73     public void initialiseCameraPreview(float[] cameraPreviewPositionData, boolean invertAxis, Context context) {
74         // float count / floats per vertex.
75         mVertexCount = cameraPreviewPositionData.length / POSITION_DATA_SIZE;
76 
77         // Initialize the buffers.
78         mPositionBuffer = ByteBuffer.allocateDirect(cameraPreviewPositionData.length * BYTES_PER_FLOAT)
79                 .order(ByteOrder.nativeOrder()).asFloatBuffer();
80 
81         mTextureBuffer = ByteBuffer.allocateDirect(CAMERA_TEXTURE_DATA.length * BYTES_PER_FLOAT)
82                 .order(ByteOrder.nativeOrder()).asFloatBuffer();
83 
84         mPositionBuffer.put(cameraPreviewPositionData).position(0);
85         mTextureBuffer.put(CAMERA_TEXTURE_DATA).position(0);
86 
87         final String vertexShader = ShaderHelper.getCameraPreviewVertexShader();
88         final String fragmentShader = ShaderHelper.getCameraPreviewFragmentShader();
89 
90         final int vertexShaderHandle =
91                 ShaderHelper.compileShader(GLES20.GL_VERTEX_SHADER, vertexShader);
92         final int fragmentShaderHandle =
93                 ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentShader);
94 
95         mProgramHandle = ShaderHelper.createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle,
96                 new String[]{"a_Position", "a_TexCoordinate"});
97 
98         mContext = context;
99         mInvertAxis = invertAxis;
100         connectCamera();
101     }
102 
103     @Override
draw(DrawParameters drawParameters)104     public void draw(DrawParameters drawParameters) {
105         GLES20.glUseProgram(mProgramHandle);
106 
107         // Set program handles for camera preview drawing.
108         mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_MVPMatrix");
109         mMVMatrixHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_MVMatrix");
110         mTextureUniformHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_Texture");
111         mPositionHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Position");
112         mTextureCoordinateHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_TexCoordinate");
113 
114         // Set the active texture unit to texture unit 0.
115         GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
116 
117         // Bind the texture to this unit.
118         if (mCameraTextureId != -1) {
119             GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mCameraTextureId);
120         }
121 
122         // Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0.
123         GLES20.glUniform1i(mTextureUniformHandle, 0);
124 
125         // Compose the model, view, and projection matrices into a single m-v-p matrix
126         updateMvpMatrix(drawParameters.getViewMatrix(), drawParameters.getProjectionMatrix());
127 
128         drawCameraPreview();
129     }
130 
131     /**
132      * Draws a camera preview.
133      */
drawCameraPreview()134     private void drawCameraPreview() {
135         // Pass in the position information
136         mPositionBuffer.position(0);
137         GLES20.glVertexAttribPointer(mPositionHandle, POSITION_DATA_SIZE, GLES20.GL_FLOAT, false,
138                 0, mPositionBuffer);
139 
140         GLES20.glEnableVertexAttribArray(mPositionHandle);
141 
142         // Pass in the texture coordinate information
143         mTextureBuffer.position(0);
144         GLES20.glVertexAttribPointer(mTextureCoordinateHandle, TEXTURE_COORDINATE_DATA_SIZE, GLES20.GL_FLOAT, false,
145                 0, mTextureBuffer);
146 
147         GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);
148 
149         // Pass in the modelview matrix.
150         GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, getMvMatrix(), 0);
151 
152         // Pass in the combined matrix.
153         GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, getMvpMatrix(), 0);
154 
155         // Draw the camera preview.
156         GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, mVertexCount);
157     }
158 
159     /**
160      * Updates the texture with the latest camera data.
161      *
162      * @return the timestamp of the RGB image rendered into the texture.
163      */
updateTexture()164     public synchronized double updateTexture() {
165         double latestCameraFrameTimestamp = -1.0;
166         if (mCameraTextureId != -1) {
167             // Copy the camera frame from the camera to the OpenGL texture
168             mCameraSurfaceTexture.updateTexImage();
169             latestCameraFrameTimestamp = mCameraSurfaceTexture.getTimestamp();
170         }
171         return latestCameraFrameTimestamp;
172     }
173 
174     /**
175      * Connects the camera to the OpenGl context
176      */
connectCamera()177     public void connectCamera() {
178         this.mCameraTextureId = connectCameraTexture();
179     }
180 
disconnectCamera()181     public void disconnectCamera() {
182         mCameraStreamManager.onStopCameraStream();
183     }
184 
185     /**
186      * Connects a texture to an Android camera
187      *
188      * @return textureId of texture with camera attached/
189      */
connectCameraTexture()190     private int connectCameraTexture() {
191         if (mCameraTextureId == -1) {
192             mCameraTextureId = createEmptyTexture();
193             mCameraSurfaceTexture = new SurfaceTexture(mCameraTextureId);
194             int width = mInvertAxis ? 1080 : 1920;
195             int height = mInvertAxis ? 1920 : 1080;
196             mCameraStreamManager = new CameraStreamManager(mContext, mCameraSurfaceTexture, width, height);
197             mCameraStreamManager.onStartCameraStream();
198         }
199         return mCameraTextureId;
200     }
201 
202     /**
203      * Creates an empty texture.
204      *
205      * @return textureId of empty texture.
206      */
createEmptyTexture()207     public static int createEmptyTexture() {
208         final int[] textureHandle = new int[1];
209 
210         GLES20.glGenTextures(1, textureHandle, 0);
211 
212         if (textureHandle[0] != 0) {
213             return textureHandle[0];
214         }
215 
216         return -1;
217     }
218 
219     @Override
destroy()220     public void destroy() {
221         if (mCameraStreamManager != null) {
222             mCameraStreamManager.onStopCameraStream();
223             mCameraStreamManager = null;
224         }
225 
226         mPositionBuffer = null;
227         mTextureBuffer = null;
228     }
229 }
230