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