Home | History | Annotate | Download | only in gldual
      1 /*
      2  * Copyright (C) 2009 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.gldual;
     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 javax.microedition.khronos.egl.EGL10;
     36 import javax.microedition.khronos.egl.EGLConfig;
     37 import javax.microedition.khronos.egl.EGLContext;
     38 import javax.microedition.khronos.egl.EGLDisplay;
     39 import javax.microedition.khronos.opengles.GL10;
     40 
     41 import android.content.Context;
     42 import android.opengl.GLSurfaceView;
     43 import android.util.AttributeSet;
     44 import android.util.Log;
     45 
     46 /**
     47  * An implementation of SurfaceView that uses the dedicated surface for
     48  * displaying an OpenGL animation.  This allows the animation to run in a
     49  * separate thread, without requiring that it be driven by the update mechanism
     50  * of the view hierarchy.
     51  *
     52  * The application-specific rendering code is delegated to a GLView.Renderer
     53  * instance.
     54  */
     55 class GLDualGL2View extends GLSurfaceView {
     56     private static String TAG = "GLDualGL2View";
     57 
     58     public GLDualGL2View(Context context) {
     59         super(context);
     60         init(false, 0, 0);
     61     }
     62 
     63     public GLDualGL2View(Context context, AttributeSet set) {
     64         super(context, set);
     65         init(false, 0, 0);
     66     }
     67 
     68     public GLDualGL2View(Context context, boolean translucent, int depth, int stencil) {
     69         super(context);
     70         init(translucent, depth, stencil);
     71     }
     72 
     73     private void init(boolean translucent, int depth, int stencil) {
     74         setEGLContextFactory(new ContextFactory());
     75         setEGLConfigChooser( translucent ?
     76               new ConfigChooser(8,8,8,8, depth, stencil) :
     77               new ConfigChooser(5,6,5,0, depth, stencil));
     78         setRenderer(new Renderer());
     79     }
     80 
     81     private static class ContextFactory implements GLSurfaceView.EGLContextFactory {
     82         private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
     83         public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {
     84             Log.w(TAG, "creating OpenGL ES 2.0 context");
     85             checkEglError("Before eglCreateContext", egl);
     86             int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
     87             EGLContext context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
     88             checkEglError("After eglCreateContext", egl);
     89             return context;
     90         }
     91 
     92         public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) {
     93             egl.eglDestroyContext(display, context);
     94         }
     95     }
     96 
     97     private static void checkEglError(String prompt, EGL10 egl) {
     98         int error;
     99         while ((error = egl.eglGetError()) != EGL10.EGL_SUCCESS) {
    100             Log.e(TAG, String.format("%s: EGL error: 0x%x", prompt, error));
    101         }
    102     }
    103 
    104     private static class ConfigChooser implements GLSurfaceView.EGLConfigChooser {
    105         private static int EGL_OPENGL_ES2_BIT = 4;
    106         private static int[] s_configAttribs2 =
    107         {
    108             EGL10.EGL_RED_SIZE, 4,
    109             EGL10.EGL_GREEN_SIZE, 4,
    110             EGL10.EGL_BLUE_SIZE, 4,
    111             EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
    112             EGL10.EGL_NONE
    113         };
    114 
    115         public ConfigChooser(int r, int g, int b, int a, int depth, int stencil) {
    116             mRedSize = r;
    117             mGreenSize = g;
    118             mBlueSize = b;
    119             mAlphaSize = a;
    120             mDepthSize = depth;
    121             mStencilSize = stencil;
    122         }
    123 
    124         public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
    125 
    126             int[] num_config = new int[1];
    127             egl.eglChooseConfig(display, s_configAttribs2, null, 0, num_config);
    128 
    129             int numConfigs = num_config[0];
    130 
    131             if (numConfigs <= 0) {
    132                 throw new IllegalArgumentException("No configs match configSpec");
    133             }
    134             EGLConfig[] configs = new EGLConfig[numConfigs];
    135             egl.eglChooseConfig(display, s_configAttribs2, configs, numConfigs, num_config);
    136             // printConfigs(egl, display, configs);
    137             return chooseConfig(egl, display, configs);
    138         }
    139 
    140         public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
    141                 EGLConfig[] configs) {
    142             EGLConfig closestConfig = null;
    143             int closestDistance = 1000;
    144             for(EGLConfig config : configs) {
    145                 int d = findConfigAttrib(egl, display, config,
    146                         EGL10.EGL_DEPTH_SIZE, 0);
    147                 int s = findConfigAttrib(egl, display, config,
    148                         EGL10.EGL_STENCIL_SIZE, 0);
    149                 if (d >= mDepthSize && s>= mStencilSize) {
    150                     int r = findConfigAttrib(egl, display, config,
    151                             EGL10.EGL_RED_SIZE, 0);
    152                     int g = findConfigAttrib(egl, display, config,
    153                              EGL10.EGL_GREEN_SIZE, 0);
    154                     int b = findConfigAttrib(egl, display, config,
    155                               EGL10.EGL_BLUE_SIZE, 0);
    156                     int a = findConfigAttrib(egl, display, config,
    157                             EGL10.EGL_ALPHA_SIZE, 0);
    158                     int distance = Math.abs(r - mRedSize)
    159                                 + Math.abs(g - mGreenSize)
    160                                 + Math.abs(b - mBlueSize)
    161                                 + Math.abs(a - mAlphaSize);
    162                     if (distance < closestDistance) {
    163                         closestDistance = distance;
    164                         closestConfig = config;
    165                     }
    166                 }
    167             }
    168             return closestConfig;
    169         }
    170 
    171         private int findConfigAttrib(EGL10 egl, EGLDisplay display,
    172                 EGLConfig config, int attribute, int defaultValue) {
    173 
    174             if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
    175                 return mValue[0];
    176             }
    177             return defaultValue;
    178         }
    179 
    180         private void printConfigs(EGL10 egl, EGLDisplay display,
    181             EGLConfig[] configs) {
    182             int numConfigs = configs.length;
    183             Log.w(TAG, String.format("%d configurations", numConfigs));
    184             for (int i = 0; i < numConfigs; i++) {
    185                 Log.w(TAG, String.format("Configuration %d:\n", i));
    186                 printConfig(egl, display, configs[i]);
    187             }
    188         }
    189 
    190         private void printConfig(EGL10 egl, EGLDisplay display,
    191                 EGLConfig config) {
    192             int[] attributes = {
    193                     EGL10.EGL_BUFFER_SIZE,
    194                     EGL10.EGL_ALPHA_SIZE,
    195                     EGL10.EGL_BLUE_SIZE,
    196                     EGL10.EGL_GREEN_SIZE,
    197                     EGL10.EGL_RED_SIZE,
    198                     EGL10.EGL_DEPTH_SIZE,
    199                     EGL10.EGL_STENCIL_SIZE,
    200                     EGL10.EGL_CONFIG_CAVEAT,
    201                     EGL10.EGL_CONFIG_ID,
    202                     EGL10.EGL_LEVEL,
    203                     EGL10.EGL_MAX_PBUFFER_HEIGHT,
    204                     EGL10.EGL_MAX_PBUFFER_PIXELS,
    205                     EGL10.EGL_MAX_PBUFFER_WIDTH,
    206                     EGL10.EGL_NATIVE_RENDERABLE,
    207                     EGL10.EGL_NATIVE_VISUAL_ID,
    208                     EGL10.EGL_NATIVE_VISUAL_TYPE,
    209                     0x3030, // EGL10.EGL_PRESERVED_RESOURCES,
    210                     EGL10.EGL_SAMPLES,
    211                     EGL10.EGL_SAMPLE_BUFFERS,
    212                     EGL10.EGL_SURFACE_TYPE,
    213                     EGL10.EGL_TRANSPARENT_TYPE,
    214                     EGL10.EGL_TRANSPARENT_RED_VALUE,
    215                     EGL10.EGL_TRANSPARENT_GREEN_VALUE,
    216                     EGL10.EGL_TRANSPARENT_BLUE_VALUE,
    217                     0x3039, // EGL10.EGL_BIND_TO_TEXTURE_RGB,
    218                     0x303A, // EGL10.EGL_BIND_TO_TEXTURE_RGBA,
    219                     0x303B, // EGL10.EGL_MIN_SWAP_INTERVAL,
    220                     0x303C, // EGL10.EGL_MAX_SWAP_INTERVAL,
    221                     EGL10.EGL_LUMINANCE_SIZE,
    222                     EGL10.EGL_ALPHA_MASK_SIZE,
    223                     EGL10.EGL_COLOR_BUFFER_TYPE,
    224                     EGL10.EGL_RENDERABLE_TYPE,
    225                     0x3042 // EGL10.EGL_CONFORMANT
    226             };
    227             String[] names = {
    228                     "EGL_BUFFER_SIZE",
    229                     "EGL_ALPHA_SIZE",
    230                     "EGL_BLUE_SIZE",
    231                     "EGL_GREEN_SIZE",
    232                     "EGL_RED_SIZE",
    233                     "EGL_DEPTH_SIZE",
    234                     "EGL_STENCIL_SIZE",
    235                     "EGL_CONFIG_CAVEAT",
    236                     "EGL_CONFIG_ID",
    237                     "EGL_LEVEL",
    238                     "EGL_MAX_PBUFFER_HEIGHT",
    239                     "EGL_MAX_PBUFFER_PIXELS",
    240                     "EGL_MAX_PBUFFER_WIDTH",
    241                     "EGL_NATIVE_RENDERABLE",
    242                     "EGL_NATIVE_VISUAL_ID",
    243                     "EGL_NATIVE_VISUAL_TYPE",
    244                     "EGL_PRESERVED_RESOURCES",
    245                     "EGL_SAMPLES",
    246                     "EGL_SAMPLE_BUFFERS",
    247                     "EGL_SURFACE_TYPE",
    248                     "EGL_TRANSPARENT_TYPE",
    249                     "EGL_TRANSPARENT_RED_VALUE",
    250                     "EGL_TRANSPARENT_GREEN_VALUE",
    251                     "EGL_TRANSPARENT_BLUE_VALUE",
    252                     "EGL_BIND_TO_TEXTURE_RGB",
    253                     "EGL_BIND_TO_TEXTURE_RGBA",
    254                     "EGL_MIN_SWAP_INTERVAL",
    255                     "EGL_MAX_SWAP_INTERVAL",
    256                     "EGL_LUMINANCE_SIZE",
    257                     "EGL_ALPHA_MASK_SIZE",
    258                     "EGL_COLOR_BUFFER_TYPE",
    259                     "EGL_RENDERABLE_TYPE",
    260                     "EGL_CONFORMANT"
    261             };
    262             int[] value = new int[1];
    263             for (int i = 0; i < attributes.length; i++) {
    264                 int attribute = attributes[i];
    265                 String name = names[i];
    266                 if ( egl.eglGetConfigAttrib(display, config, attribute, value)) {
    267                     Log.w(TAG, String.format("  %s: %d\n", name, value[0]));
    268                 } else {
    269                     // Log.w(TAG, String.format("  %s: failed\n", name));
    270                     while (egl.eglGetError() != EGL10.EGL_SUCCESS);
    271                 }
    272             }
    273         }
    274 
    275         // Subclasses can adjust these values:
    276         protected int mRedSize;
    277         protected int mGreenSize;
    278         protected int mBlueSize;
    279         protected int mAlphaSize;
    280         protected int mDepthSize;
    281         protected int mStencilSize;
    282         private int[] mValue = new int[1];
    283     }
    284 
    285     private static class Renderer implements GLSurfaceView.Renderer {
    286         public void onDrawFrame(GL10 gl) {
    287             GLDualLib.step();
    288         }
    289 
    290         public void onSurfaceChanged(GL10 gl, int width, int height) {
    291             GLDualLib.init(width, height);
    292         }
    293 
    294         public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    295             // Do nothing.
    296         }
    297     }
    298 }
    299 
    300