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