• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 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 
17 package android.opengl.cts;
18 
19 import android.content.Context;
20 import android.opengl.GLES20;
21 import android.opengl.GLSurfaceView;
22 import android.util.Log;
23 
24 import java.nio.ByteBuffer;
25 import java.nio.ByteOrder;
26 import java.nio.FloatBuffer;
27 
28 import javax.microedition.khronos.egl.EGL10;
29 import javax.microedition.khronos.egl.EGLConfig;
30 import javax.microedition.khronos.egl.EGLDisplay;
31 import javax.microedition.khronos.opengles.GL10;
32 
33 /**
34  * {@link GLSurfaceView} that uses the EGL configuration specified. Draws a couple frames of a red
35  * triangle and then calls the callback.
36  */
37 public class EglConfigGLSurfaceView extends GLSurfaceView {
38 
39     private static final String TAG = EglConfigGLSurfaceView.class.getName();
40 
41     private final int mConfigId;
42 
43     private final Runnable mCallback;
44 
EglConfigGLSurfaceView(Context context, int configId, int contextClientVersion, Runnable callback)45     public EglConfigGLSurfaceView(Context context, int configId, int contextClientVersion,
46             Runnable callback) {
47         super(context);
48         mConfigId = configId;
49         mCallback = callback;
50         setEGLConfigChooser(new ConfigChooser());
51         setEGLContextClientVersion(contextClientVersion);
52         setRenderer(contextClientVersion == 1
53                 ? new Renderer()
54                 : new Renderer20());
55     }
56 
57     private class ConfigChooser implements GLSurfaceView.EGLConfigChooser {
58 
chooseConfig(EGL10 egl, EGLDisplay display)59         public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
60             int[] attributeList = new int[] {
61                     EGL10.EGL_CONFIG_ID, mConfigId,
62                     EGL10.EGL_NONE
63             };
64 
65             EGLConfig[] configs = new EGLConfig[1];
66             if (egl.eglChooseConfig(display, attributeList, configs, 1, new int[] {1})) {
67                 // Print out the configuration since we may crash...
68                 printConfig(egl, display, configs[0]);
69                 return configs[0];
70             } else {
71                 throw new IllegalStateException("Could not get EGL config...");
72             }
73         }
74     }
75 
76     private class Renderer implements GLSurfaceView.Renderer {
77 
78         private int mNumFrames;
79 
80         private FloatBuffer mFloatBuffer;
81 
onSurfaceCreated(GL10 gl, EGLConfig config)82         public void onSurfaceCreated(GL10 gl, EGLConfig config) {
83             float[] triangleVertices = {
84                     0.0f, 1.0f, -1.0f,
85                     -1.0f, -1.0f, -1.0f,
86                     1.0f, -1.0f, -1.0f
87             };
88 
89             ByteBuffer byteBuffer = ByteBuffer.allocateDirect(triangleVertices.length * 4);
90             byteBuffer.order(ByteOrder.nativeOrder());
91 
92             mFloatBuffer = ByteBuffer.allocateDirect(triangleVertices.length * 4)
93                     .order(ByteOrder.nativeOrder())
94                     .asFloatBuffer();
95             mFloatBuffer.put(triangleVertices).position(0);
96 
97             gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
98         }
99 
onDrawFrame(GL10 gl)100         public void onDrawFrame(GL10 gl) {
101             gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
102             gl.glColor4f(1.0f, 0, 0, 0);
103             gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mFloatBuffer);
104             gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 9);
105 
106             if (++mNumFrames == 10) {
107                 post(mCallback);
108             }
109         }
110 
onSurfaceChanged(GL10 gl, int width, int height)111         public void onSurfaceChanged(GL10 gl, int width, int height) {
112             gl.glViewport(0, 0, width, height);
113         }
114     }
115 
116     private class Renderer20 implements GLSurfaceView.Renderer {
117 
118         private FloatBuffer mFloatBuffer;
119 
120         private final String mVertexShader =
121             "attribute vec4 aPosition;\n" +
122             "void main() {\n" +
123             "  gl_Position = aPosition;\n" +
124             "}\n";
125 
126         private final String mFragmentShader =
127             "void main() {\n" +
128             "  gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);\n" +
129             "}\n";
130 
131         private int mProgram;
132 
133         private int maPositionHandle;
134 
135         private int mNumFrames;
136 
onSurfaceCreated(GL10 gl, EGLConfig config)137         public void onSurfaceCreated(GL10 gl, EGLConfig config) {
138             mProgram = createProgram(mVertexShader, mFragmentShader);
139             if (mProgram == 0) {
140                 throw new RuntimeException("Could not create program");
141             }
142 
143             maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
144             checkGlError("glGetAttribLocation aPosition");
145             if (maPositionHandle == -1) {
146                 throw new RuntimeException("Could not get attrib location for aPosition");
147             }
148 
149             float[] triangleVertices = {
150                     0.0f, 1.0f, 0.0f,
151                     -1.0f, -1.0f, 0.0f,
152                     1.0f, -1.0f, 0.0f
153             };
154 
155             mFloatBuffer = ByteBuffer.allocateDirect(triangleVertices.length * 4)
156                     .order(ByteOrder.nativeOrder())
157                     .asFloatBuffer();
158             mFloatBuffer.put(triangleVertices).position(0);
159         }
160 
createProgram(String vertexSource, String fragmentSource)161         private int createProgram(String vertexSource, String fragmentSource) {
162             int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
163             if (vertexShader == 0) {
164                 return 0;
165             }
166 
167             int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
168             if (pixelShader == 0) {
169                 return 0;
170             }
171 
172             int program = GLES20.glCreateProgram();
173             if (program != 0) {
174                 GLES20.glAttachShader(program, vertexShader);
175                 checkGlError("glAttachShader");
176                 GLES20.glAttachShader(program, pixelShader);
177                 checkGlError("glAttachShader");
178                 GLES20.glLinkProgram(program);
179                 int[] linkStatus = new int[1];
180                 GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
181                 if (linkStatus[0] != GLES20.GL_TRUE) {
182                     Log.e(TAG, "Could not link program: ");
183                     Log.e(TAG, GLES20.glGetProgramInfoLog(program));
184                     GLES20.glDeleteProgram(program);
185                     program = 0;
186                 }
187             }
188             return program;
189         }
190 
loadShader(int shaderType, String source)191         private int loadShader(int shaderType, String source) {
192             int shader = GLES20.glCreateShader(shaderType);
193             if (shader != 0) {
194                 GLES20.glShaderSource(shader, source);
195                 GLES20.glCompileShader(shader);
196                 int[] compiled = new int[1];
197                 GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
198                 if (compiled[0] == 0) {
199                     Log.e(TAG, "Could not compile shader " + shaderType + ":");
200                     Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
201                     GLES20.glDeleteShader(shader);
202                     shader = 0;
203                 }
204             }
205             return shader;
206         }
207 
checkGlError(String op)208         private void checkGlError(String op) {
209             int error;
210             while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
211                 Log.e(TAG, op + ": glError " + error);
212                 throw new RuntimeException(op + ": glError " + error);
213             }
214         }
215 
216         @Override
onDrawFrame(GL10 gl)217         public void onDrawFrame(GL10 gl) {
218             GLES20.glClearColor(0, 0, 0, 1);
219             GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
220             GLES20.glUseProgram(mProgram);
221 
222             GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false,
223                     0, mFloatBuffer);
224             checkGlError("glVertexAttribPointer maPosition");
225 
226             GLES20.glEnableVertexAttribArray(maPositionHandle);
227             checkGlError("glEnableVertexAttribArray maPositionHandle");
228 
229             GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
230             checkGlError("glDrawArrays");
231 
232             if (++mNumFrames == 10) {
233                 post(mCallback);
234             }
235         }
236 
onSurfaceChanged(GL10 gl, int width, int height)237         public void onSurfaceChanged(GL10 gl, int width, int height) {
238             GLES20.glViewport(0, 0, width, height);
239         }
240     }
241 
242     /** Ripped from the NDK sample GL2JNIView class. */
printConfig(EGL10 egl, EGLDisplay display, EGLConfig config)243     private static void printConfig(EGL10 egl, EGLDisplay display,
244             EGLConfig config) {
245         int[] attributes = {
246                 EGL10.EGL_BUFFER_SIZE,
247                 EGL10.EGL_ALPHA_SIZE,
248                 EGL10.EGL_BLUE_SIZE,
249                 EGL10.EGL_GREEN_SIZE,
250                 EGL10.EGL_RED_SIZE,
251                 EGL10.EGL_DEPTH_SIZE,
252                 EGL10.EGL_STENCIL_SIZE,
253                 EGL10.EGL_CONFIG_CAVEAT,
254                 EGL10.EGL_CONFIG_ID,
255                 EGL10.EGL_LEVEL,
256                 EGL10.EGL_MAX_PBUFFER_HEIGHT,
257                 EGL10.EGL_MAX_PBUFFER_PIXELS,
258                 EGL10.EGL_MAX_PBUFFER_WIDTH,
259                 EGL10.EGL_NATIVE_RENDERABLE,
260                 EGL10.EGL_NATIVE_VISUAL_ID,
261                 EGL10.EGL_NATIVE_VISUAL_TYPE,
262                 0x3030, // EGL10.EGL_PRESERVED_RESOURCES,
263                 EGL10.EGL_SAMPLES,
264                 EGL10.EGL_SAMPLE_BUFFERS,
265                 EGL10.EGL_SURFACE_TYPE,
266                 EGL10.EGL_TRANSPARENT_TYPE,
267                 EGL10.EGL_TRANSPARENT_RED_VALUE,
268                 EGL10.EGL_TRANSPARENT_GREEN_VALUE,
269                 EGL10.EGL_TRANSPARENT_BLUE_VALUE,
270                 0x3039, // EGL10.EGL_BIND_TO_TEXTURE_RGB,
271                 0x303A, // EGL10.EGL_BIND_TO_TEXTURE_RGBA,
272                 0x303B, // EGL10.EGL_MIN_SWAP_INTERVAL,
273                 0x303C, // EGL10.EGL_MAX_SWAP_INTERVAL,
274                 EGL10.EGL_LUMINANCE_SIZE,
275                 EGL10.EGL_ALPHA_MASK_SIZE,
276                 EGL10.EGL_COLOR_BUFFER_TYPE,
277                 EGL10.EGL_RENDERABLE_TYPE,
278                 0x3042 // EGL10.EGL_CONFORMANT
279         };
280         String[] names = {
281                 "EGL_BUFFER_SIZE",
282                 "EGL_ALPHA_SIZE",
283                 "EGL_BLUE_SIZE",
284                 "EGL_GREEN_SIZE",
285                 "EGL_RED_SIZE",
286                 "EGL_DEPTH_SIZE",
287                 "EGL_STENCIL_SIZE",
288                 "EGL_CONFIG_CAVEAT",
289                 "EGL_CONFIG_ID",
290                 "EGL_LEVEL",
291                 "EGL_MAX_PBUFFER_HEIGHT",
292                 "EGL_MAX_PBUFFER_PIXELS",
293                 "EGL_MAX_PBUFFER_WIDTH",
294                 "EGL_NATIVE_RENDERABLE",
295                 "EGL_NATIVE_VISUAL_ID",
296                 "EGL_NATIVE_VISUAL_TYPE",
297                 "EGL_PRESERVED_RESOURCES",
298                 "EGL_SAMPLES",
299                 "EGL_SAMPLE_BUFFERS",
300                 "EGL_SURFACE_TYPE",
301                 "EGL_TRANSPARENT_TYPE",
302                 "EGL_TRANSPARENT_RED_VALUE",
303                 "EGL_TRANSPARENT_GREEN_VALUE",
304                 "EGL_TRANSPARENT_BLUE_VALUE",
305                 "EGL_BIND_TO_TEXTURE_RGB",
306                 "EGL_BIND_TO_TEXTURE_RGBA",
307                 "EGL_MIN_SWAP_INTERVAL",
308                 "EGL_MAX_SWAP_INTERVAL",
309                 "EGL_LUMINANCE_SIZE",
310                 "EGL_ALPHA_MASK_SIZE",
311                 "EGL_COLOR_BUFFER_TYPE",
312                 "EGL_RENDERABLE_TYPE",
313                 "EGL_CONFORMANT"
314         };
315         int[] value = new int[1];
316         for (int i = 0; i < attributes.length; i++) {
317             int attribute = attributes[i];
318             String name = names[i];
319             if (egl.eglGetConfigAttrib(display, config, attribute, value)) {
320                 Log.w(TAG, String.format("  %s: %d\n", name, value[0]));
321             } else {
322                 // Log.w(TAG, String.format("  %s: failed\n", name));
323                 while (egl.eglGetError() != EGL10.EGL_SUCCESS);
324             }
325         }
326     }
327 }
328