Home | History | Annotate | Download | only in cts
      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 
     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 
     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 
     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 
    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, 3);
    105 
    106             if (++mNumFrames == 10) {
    107                 post(mCallback);
    108             }
    109         }
    110 
    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 
    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 
    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 
    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 
    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
    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 
    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. */
    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