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.glperf;
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 GLPerfView extends GLSurfaceView {
58    private static String TAG = "GLPerfView";
59
60    public GLPerfView(Context context) {
61        super(context);
62        init(false, 0, 0);
63    }
64
65    public GLPerfView(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            GLPerfLib.step();
285        }
286
287        public void onSurfaceChanged(GL10 gl, int width, int height) {
288            GLPerfLib.init(width, height);
289        }
290
291        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
292            // Do nothing.
293        }
294    }
295}
296
297