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