Home | History | Annotate | Download | only in src
      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 
     17 package com.android.gputest;
     18 /*
     19  * Copyright (C) 2008 The Android Open Source Project
     20  *
     21  * Licensed under the Apache License, Version 2.0 (the "License");
     22  * you may not use this file except in compliance with the License.
     23  * You may obtain a copy of the License at
     24  *
     25  *      http://www.apache.org/licenses/LICENSE-2.0
     26  *
     27  * Unless required by applicable law or agreed to in writing, software
     28  * distributed under the License is distributed on an "AS IS" BASIS,
     29  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     30  * See the License for the specific language governing permissions and
     31  * limitations under the License.
     32  */
     33 
     34 
     35 import android.content.Context;
     36 import android.graphics.PixelFormat;
     37 import android.opengl.GLSurfaceView;
     38 import android.util.AttributeSet;
     39 import android.util.Log;
     40 import android.view.KeyEvent;
     41 import android.view.MotionEvent;
     42 
     43 import javax.microedition.khronos.egl.EGL10;
     44 import javax.microedition.khronos.egl.EGLConfig;
     45 import javax.microedition.khronos.egl.EGLContext;
     46 import javax.microedition.khronos.egl.EGLDisplay;
     47 import javax.microedition.khronos.opengles.GL10;
     48 
     49 /**
     50  * A simple GLSurfaceView sub-class that demonstrate how to perform
     51  * OpenGL ES 2.0 rendering into a GL Surface. Note the following important
     52  * details:
     53  *
     54  * - The class must use a custom context factory to enable 2.0 rendering.
     55  *   See ContextFactory class definition below.
     56  *
     57  * - The class must use a custom EGLConfigChooser to be able to select
     58  *   an EGLConfig that supports 2.0. This is done by providing a config
     59  *   specification to eglChooseConfig() that has the attribute
     60  *   EGL10.ELG_RENDERABLE_TYPE containing the EGL_OPENGL_ES2_BIT flag
     61  *   set. See ConfigChooser class definition below.
     62  *
     63  * - The class must select the surface's format, then choose an EGLConfig
     64  *   that matches it exactly (with regards to red/green/blue/alpha channels
     65  *   bit depths). Failure to do so would result in an EGL_BAD_MATCH error.
     66  */
     67 class GLtestView extends GLSurfaceView {
     68     private static String TAG = "GLtestView";
     69     private static final boolean DEBUG = false;
     70 
     71     public GLtestView(Context context) {
     72         super(context);
     73         init(false, 0, 0);
     74     }
     75 
     76     public GLtestView(Context context, boolean translucent, int depth, int stencil) {
     77         super(context);
     78         init(translucent, depth, stencil);
     79     }
     80 
     81     private void init(boolean translucent, int depth, int stencil) {
     82 
     83         /* By default, GLSurfaceView() creates a RGB_565 opaque surface.
     84          * If we want a translucent one, we should change the surface's
     85          * format here, using PixelFormat.TRANSLUCENT for GL Surfaces
     86          * is interpreted as any 32-bit surface with alpha by SurfaceFlinger.
     87          */
     88         if (translucent) {
     89             this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
     90         }
     91 
     92         /* Setup the context factory for 2.0 rendering.
     93          * See ContextFactory class definition below
     94          */
     95         setEGLContextFactory(new ContextFactory());
     96 
     97         /* We need to choose an EGLConfig that matches the format of
     98          * our surface exactly. This is going to be done in our
     99          * custom config chooser. See ConfigChooser class definition
    100          * below.
    101          */
    102         setEGLConfigChooser( translucent ?
    103                              new ConfigChooser(8, 8, 8, 8, depth, stencil) :
    104                              new ConfigChooser(5, 6, 5, 0, depth, stencil) );
    105 
    106         /* Set the renderer responsible for frame rendering */
    107         setRenderer(new Renderer());
    108     }
    109 
    110     private static class ContextFactory implements GLSurfaceView.EGLContextFactory {
    111         private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
    112         public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {
    113             Log.w(TAG, "creating OpenGL ES 3.0 context");
    114             checkEglError("Before eglCreateContext", egl);
    115             int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL10.EGL_NONE };
    116             EGLContext context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
    117             checkEglError("After eglCreateContext", egl);
    118             return context;
    119         }
    120 
    121         public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) {
    122             egl.eglDestroyContext(display, context);
    123         }
    124     }
    125 
    126     private static void checkEglError(String prompt, EGL10 egl) {
    127         int error;
    128         while ((error = egl.eglGetError()) != EGL10.EGL_SUCCESS) {
    129             Log.e(TAG, String.format("%s: EGL error: 0x%x", prompt, error));
    130         }
    131     }
    132 
    133     private static class ConfigChooser implements GLSurfaceView.EGLConfigChooser {
    134 
    135         public ConfigChooser(int r, int g, int b, int a, int depth, int stencil) {
    136             mRedSize = r;
    137             mGreenSize = g;
    138             mBlueSize = b;
    139             mAlphaSize = a;
    140             mDepthSize = depth;
    141             mStencilSize = stencil;
    142         }
    143 
    144         /* This EGL config specification is used to specify 2.0 rendering.
    145          * We use a minimum size of 4 bits for red/green/blue, but will
    146          * perform actual matching in chooseConfig() below.
    147          */
    148         private static int EGL_OPENGL_ES2_BIT = 4;
    149         private static int[] s_configAttribs2 =
    150         {
    151             EGL10.EGL_RED_SIZE, 4,
    152             EGL10.EGL_GREEN_SIZE, 4,
    153             EGL10.EGL_BLUE_SIZE, 4,
    154             EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
    155             EGL10.EGL_NONE
    156         };
    157 
    158         public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
    159 
    160             /* Get the number of minimally matching EGL configurations
    161              */
    162             int[] num_config = new int[1];
    163             egl.eglChooseConfig(display, s_configAttribs2, null, 0, num_config);
    164 
    165             int numConfigs = num_config[0];
    166 
    167             if (numConfigs <= 0) {
    168                 throw new IllegalArgumentException("No configs match configSpec");
    169             }
    170 
    171             /* Allocate then read the array of minimally matching EGL configs
    172              */
    173             EGLConfig[] configs = new EGLConfig[numConfigs];
    174             egl.eglChooseConfig(display, s_configAttribs2, configs, numConfigs, num_config);
    175 
    176             if (DEBUG) {
    177                  printConfigs(egl, display, configs);
    178             }
    179             /* Now return the "best" one
    180              */
    181             return chooseConfig(egl, display, configs);
    182         }
    183 
    184         public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
    185                 EGLConfig[] configs) {
    186             for(EGLConfig config : configs) {
    187                 int d = findConfigAttrib(egl, display, config,
    188                         EGL10.EGL_DEPTH_SIZE, 0);
    189                 int s = findConfigAttrib(egl, display, config,
    190                         EGL10.EGL_STENCIL_SIZE, 0);
    191 
    192                 // We need at least mDepthSize and mStencilSize bits
    193                 if (d < mDepthSize || s < mStencilSize)
    194                     continue;
    195 
    196                 // We want an *exact* match for red/green/blue/alpha
    197                 int r = findConfigAttrib(egl, display, config,
    198                         EGL10.EGL_RED_SIZE, 0);
    199                 int g = findConfigAttrib(egl, display, config,
    200                             EGL10.EGL_GREEN_SIZE, 0);
    201                 int b = findConfigAttrib(egl, display, config,
    202                             EGL10.EGL_BLUE_SIZE, 0);
    203                 int a = findConfigAttrib(egl, display, config,
    204                         EGL10.EGL_ALPHA_SIZE, 0);
    205 
    206                 if (r == mRedSize && g == mGreenSize && b == mBlueSize && a == mAlphaSize)
    207                     return config;
    208             }
    209             return null;
    210         }
    211 
    212         private int findConfigAttrib(EGL10 egl, EGLDisplay display,
    213                 EGLConfig config, int attribute, int defaultValue) {
    214 
    215             if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
    216                 return mValue[0];
    217             }
    218             return defaultValue;
    219         }
    220 
    221         private void printConfigs(EGL10 egl, EGLDisplay display,
    222             EGLConfig[] configs) {
    223             int numConfigs = configs.length;
    224             Log.w(TAG, String.format("%d configurations", numConfigs));
    225             for (int i = 0; i < numConfigs; i++) {
    226                 Log.w(TAG, String.format("Configuration %d:\n", i));
    227                 printConfig(egl, display, configs[i]);
    228             }
    229         }
    230 
    231         private void printConfig(EGL10 egl, EGLDisplay display,
    232                 EGLConfig config) {
    233             int[] attributes = {
    234                     EGL10.EGL_BUFFER_SIZE,
    235                     EGL10.EGL_ALPHA_SIZE,
    236                     EGL10.EGL_BLUE_SIZE,
    237                     EGL10.EGL_GREEN_SIZE,
    238                     EGL10.EGL_RED_SIZE,
    239                     EGL10.EGL_DEPTH_SIZE,
    240                     EGL10.EGL_STENCIL_SIZE,
    241                     EGL10.EGL_CONFIG_CAVEAT,
    242                     EGL10.EGL_CONFIG_ID,
    243                     EGL10.EGL_LEVEL,
    244                     EGL10.EGL_MAX_PBUFFER_HEIGHT,
    245                     EGL10.EGL_MAX_PBUFFER_PIXELS,
    246                     EGL10.EGL_MAX_PBUFFER_WIDTH,
    247                     EGL10.EGL_NATIVE_RENDERABLE,
    248                     EGL10.EGL_NATIVE_VISUAL_ID,
    249                     EGL10.EGL_NATIVE_VISUAL_TYPE,
    250                     0x3030, // EGL10.EGL_PRESERVED_RESOURCES,
    251                     EGL10.EGL_SAMPLES,
    252                     EGL10.EGL_SAMPLE_BUFFERS,
    253                     EGL10.EGL_SURFACE_TYPE,
    254                     EGL10.EGL_TRANSPARENT_TYPE,
    255                     EGL10.EGL_TRANSPARENT_RED_VALUE,
    256                     EGL10.EGL_TRANSPARENT_GREEN_VALUE,
    257                     EGL10.EGL_TRANSPARENT_BLUE_VALUE,
    258                     0x3039, // EGL10.EGL_BIND_TO_TEXTURE_RGB,
    259                     0x303A, // EGL10.EGL_BIND_TO_TEXTURE_RGBA,
    260                     0x303B, // EGL10.EGL_MIN_SWAP_INTERVAL,
    261                     0x303C, // EGL10.EGL_MAX_SWAP_INTERVAL,
    262                     EGL10.EGL_LUMINANCE_SIZE,
    263                     EGL10.EGL_ALPHA_MASK_SIZE,
    264                     EGL10.EGL_COLOR_BUFFER_TYPE,
    265                     EGL10.EGL_RENDERABLE_TYPE,
    266                     0x3042 // EGL10.EGL_CONFORMANT
    267             };
    268             String[] names = {
    269                     "EGL_BUFFER_SIZE",
    270                     "EGL_ALPHA_SIZE",
    271                     "EGL_BLUE_SIZE",
    272                     "EGL_GREEN_SIZE",
    273                     "EGL_RED_SIZE",
    274                     "EGL_DEPTH_SIZE",
    275                     "EGL_STENCIL_SIZE",
    276                     "EGL_CONFIG_CAVEAT",
    277                     "EGL_CONFIG_ID",
    278                     "EGL_LEVEL",
    279                     "EGL_MAX_PBUFFER_HEIGHT",
    280                     "EGL_MAX_PBUFFER_PIXELS",
    281                     "EGL_MAX_PBUFFER_WIDTH",
    282                     "EGL_NATIVE_RENDERABLE",
    283                     "EGL_NATIVE_VISUAL_ID",
    284                     "EGL_NATIVE_VISUAL_TYPE",
    285                     "EGL_PRESERVED_RESOURCES",
    286                     "EGL_SAMPLES",
    287                     "EGL_SAMPLE_BUFFERS",
    288                     "EGL_SURFACE_TYPE",
    289                     "EGL_TRANSPARENT_TYPE",
    290                     "EGL_TRANSPARENT_RED_VALUE",
    291                     "EGL_TRANSPARENT_GREEN_VALUE",
    292                     "EGL_TRANSPARENT_BLUE_VALUE",
    293                     "EGL_BIND_TO_TEXTURE_RGB",
    294                     "EGL_BIND_TO_TEXTURE_RGBA",
    295                     "EGL_MIN_SWAP_INTERVAL",
    296                     "EGL_MAX_SWAP_INTERVAL",
    297                     "EGL_LUMINANCE_SIZE",
    298                     "EGL_ALPHA_MASK_SIZE",
    299                     "EGL_COLOR_BUFFER_TYPE",
    300                     "EGL_RENDERABLE_TYPE",
    301                     "EGL_CONFORMANT"
    302             };
    303             int[] value = new int[1];
    304             for (int i = 0; i < attributes.length; i++) {
    305                 int attribute = attributes[i];
    306                 String name = names[i];
    307                 if ( egl.eglGetConfigAttrib(display, config, attribute, value)) {
    308                     Log.w(TAG, String.format("  %s: %d\n", name, value[0]));
    309                 } else {
    310                     // Log.w(TAG, String.format("  %s: failed\n", name));
    311                     while (egl.eglGetError() != EGL10.EGL_SUCCESS);
    312                 }
    313             }
    314         }
    315 
    316         // Subclasses can adjust these values:
    317         protected int mRedSize;
    318         protected int mGreenSize;
    319         protected int mBlueSize;
    320         protected int mAlphaSize;
    321         protected int mDepthSize;
    322         protected int mStencilSize;
    323         private int[] mValue = new int[1];
    324     }
    325 
    326     private static class Renderer implements GLSurfaceView.Renderer {
    327         public void onDrawFrame(GL10 gl) {
    328             GLtestLib.step();
    329         }
    330 
    331         public void onSurfaceChanged(GL10 gl, int width, int height) {
    332             GLtestLib.init(width, height);
    333         }
    334 
    335         public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    336             // Do nothing.
    337         }
    338     }
    339 }
    340