1 /*
2  * Copyright 2012 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 package com.skia;
9 
10 import javax.microedition.khronos.egl.EGL10;
11 import javax.microedition.khronos.egl.EGLConfig;
12 import javax.microedition.khronos.egl.EGLDisplay;
13 import javax.microedition.khronos.opengles.GL10;
14 
15 import android.content.Context;
16 import android.opengl.EGL14;
17 import android.opengl.GLSurfaceView;
18 import android.os.Build;
19 import android.util.Log;
20 import android.view.MotionEvent;
21 
22 public class SkiaSampleView extends GLSurfaceView {
23 
24     private final SkiaSampleRenderer mSampleRenderer;
25     private boolean mRequestedOpenGLAPI; // true == use (desktop) OpenGL. false == use OpenGL ES.
26     private int mRequestedMSAASampleCount;
27 
SkiaSampleView(Context ctx, String cmdLineFlags, boolean useOpenGL, int msaaSampleCount)28     public SkiaSampleView(Context ctx, String cmdLineFlags, boolean useOpenGL, int msaaSampleCount) {
29         super(ctx);
30 
31         mSampleRenderer = new SkiaSampleRenderer(this, cmdLineFlags);
32         mRequestedMSAASampleCount = msaaSampleCount;
33 
34         setEGLContextClientVersion(2);
35         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
36             setEGLConfigChooser(8, 8, 8, 8, 0, 8);
37         } else {
38             mRequestedOpenGLAPI = useOpenGL;
39             setEGLConfigChooser(new SampleViewEGLConfigChooser());
40         }
41         setRenderer(mSampleRenderer);
42         setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
43     }
44 
45     @Override
onTouchEvent(MotionEvent event)46     public boolean onTouchEvent(MotionEvent event) {
47         int count = event.getPointerCount();
48         for (int i = 0; i < count; i++) {
49             final float x = event.getX(i);
50             final float y = event.getY(i);
51             final int owner = event.getPointerId(i);
52             int action = event.getAction() & MotionEvent.ACTION_MASK;
53             switch (action) {
54             case MotionEvent.ACTION_POINTER_UP:
55                 action = MotionEvent.ACTION_UP;
56                 break;
57             case MotionEvent.ACTION_POINTER_DOWN:
58                 action = MotionEvent.ACTION_DOWN;
59                 break;
60             default:
61                 break;
62             }
63             final int finalAction = action;
64             queueEvent(new Runnable() {
65                 @Override
66                 public void run() {
67                     mSampleRenderer.handleClick(owner, x, y, finalAction);
68                 }
69             });
70         }
71         return true;
72     }
73 
inval()74     public void inval() {
75         queueEvent(new Runnable() {
76             @Override
77             public void run() {
78                 mSampleRenderer.postInval();
79             }
80         });
81     }
82 
terminate()83     public void terminate() {
84         queueEvent(new Runnable() {
85             @Override
86             public void run() {
87                 mSampleRenderer.term();
88             }
89         });
90     }
91 
showOverview()92     public void showOverview() {
93         queueEvent(new Runnable() {
94             @Override
95             public void run() {
96                 mSampleRenderer.showOverview();
97             }
98         });
99     }
100 
nextSample()101     public void nextSample() {
102         queueEvent(new Runnable() {
103             @Override
104             public void run() {
105                 mSampleRenderer.nextSample();
106             }
107         });
108     }
109 
previousSample()110     public void previousSample() {
111         queueEvent(new Runnable() {
112             @Override
113             public void run() {
114                 mSampleRenderer.previousSample();
115             }
116         });
117     }
118 
goToSample(final int position)119     public void goToSample(final int position) {
120         queueEvent(new Runnable() {
121             @Override
122             public void run() {
123                 mSampleRenderer.goToSample(position);
124             }
125         });
126     }
127 
toggleRenderingMode()128     public void toggleRenderingMode() {
129         queueEvent(new Runnable() {
130             @Override
131             public void run() {
132                 mSampleRenderer.toggleRenderingMode();
133             }
134         });
135     }
136 
toggleSlideshow()137     public void toggleSlideshow() {
138         queueEvent(new Runnable() {
139             @Override
140             public void run() {
141                 mSampleRenderer.toggleSlideshow();
142             }
143         });
144     }
145 
toggleFPS()146     public void toggleFPS() {
147         queueEvent(new Runnable() {
148             @Override
149             public void run() {
150                 mSampleRenderer.toggleFPS();
151             }
152         });
153     }
154 
toggleTiling()155     public void toggleTiling() {
156         queueEvent(new Runnable() {
157             @Override
158             public void run() {
159                 mSampleRenderer.toggleTiling();
160             }
161         });
162     }
163 
toggleBBox()164     public void toggleBBox() {
165         queueEvent(new Runnable() {
166             @Override
167             public void run() {
168                 mSampleRenderer.toggleBBox();
169             }
170         });
171     }
172 
saveToPDF()173     public void saveToPDF() {
174         queueEvent(new Runnable() {
175             @Override
176             public void run() {
177                 mSampleRenderer.saveToPDF();
178             }
179         });
180     }
181 
getUsesOpenGLAPI()182     public boolean getUsesOpenGLAPI() {
183         return mRequestedOpenGLAPI;
184     }
185 
getMSAASampleCount()186     public int getMSAASampleCount() {
187         return mSampleRenderer.getMSAASampleCount();
188     }
189 
190     private class SampleViewEGLConfigChooser implements GLSurfaceView.EGLConfigChooser {
191 
192         @Override
chooseConfig(EGL10 egl, EGLDisplay display)193         public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
194             int numConfigs = 0;
195             int[] configSpec = null;
196             int[] value = new int[1];
197 
198             int[] validAPIs = new int[] {
199                 EGL14.EGL_OPENGL_API,
200                 EGL14.EGL_OPENGL_ES_API
201             };
202             int initialAPI = mRequestedOpenGLAPI ? 0 : 1;
203 
204             for (int i = initialAPI; i < validAPIs.length && numConfigs == 0; i++) {
205                 int currentAPI = validAPIs[i];
206                 EGL14.eglBindAPI(currentAPI);
207 
208                 // setup the renderableType which will only be included in the
209                 // spec if we are attempting to get access to the OpenGL APIs.
210                 int renderableType = EGL14.EGL_OPENGL_BIT;
211                 if (currentAPI == EGL14.EGL_OPENGL_API) {
212                     renderableType = EGL14.EGL_OPENGL_ES2_BIT;
213                 }
214 
215                 if (mRequestedMSAASampleCount > 0) {
216                     configSpec = new int[] {
217                         EGL10.EGL_RED_SIZE, 8,
218                         EGL10.EGL_GREEN_SIZE, 8,
219                         EGL10.EGL_BLUE_SIZE, 8,
220                         EGL10.EGL_ALPHA_SIZE, 8,
221                         EGL10.EGL_DEPTH_SIZE, 0,
222                         EGL10.EGL_STENCIL_SIZE, 8,
223                         EGL10.EGL_SAMPLE_BUFFERS, 1,
224                         EGL10.EGL_SAMPLES, mRequestedMSAASampleCount,
225                         EGL10.EGL_RENDERABLE_TYPE, renderableType,
226                         EGL10.EGL_NONE
227                     };
228 
229                     // EGL_RENDERABLE_TYPE is only needed when attempting to use
230                     // the OpenGL API (not ES) and causes many EGL drivers to fail
231                     // with a BAD_ATTRIBUTE error.
232                     if (!mRequestedOpenGLAPI) {
233                       configSpec[16] = EGL10.EGL_NONE;
234                       Log.i("Skia", "spec: " + configSpec);
235                     }
236 
237                     if (!egl.eglChooseConfig(display, configSpec, null, 0, value)) {
238                         Log.i("Skia", "Could not get MSAA context count: " + mRequestedMSAASampleCount);
239                     }
240 
241                     numConfigs = value[0];
242                 }
243 
244                 if (numConfigs <= 0) {
245                     // Try without multisampling.
246                     configSpec = new int[] {
247                         EGL10.EGL_RED_SIZE, 8,
248                         EGL10.EGL_GREEN_SIZE, 8,
249                         EGL10.EGL_BLUE_SIZE, 8,
250                         EGL10.EGL_ALPHA_SIZE, 8,
251                         EGL10.EGL_DEPTH_SIZE, 0,
252                         EGL10.EGL_STENCIL_SIZE, 8,
253                         EGL10.EGL_RENDERABLE_TYPE, renderableType,
254                         EGL10.EGL_NONE
255                     };
256 
257                     // EGL_RENDERABLE_TYPE is only needed when attempting to use
258                     // the OpenGL API (not ES) and causes many EGL drivers to fail
259                     // with a BAD_ATTRIBUTE error.
260                     if (!mRequestedOpenGLAPI) {
261                       configSpec[12] = EGL10.EGL_NONE;
262                       Log.i("Skia", "spec: " + configSpec);
263                     }
264 
265                     if (!egl.eglChooseConfig(display, configSpec, null, 0, value)) {
266                       Log.i("Skia", "Could not get non-MSAA context count");
267                     }
268                     numConfigs = value[0];
269                 }
270             }
271 
272             if (numConfigs <= 0) {
273                 throw new IllegalArgumentException("No configs match configSpec");
274             }
275 
276             // Get all matching configurations.
277             EGLConfig[] configs = new EGLConfig[numConfigs];
278             if (!egl.eglChooseConfig(display, configSpec, configs, numConfigs, value)) {
279                 throw new IllegalArgumentException("Could not get config data");
280             }
281 
282             for (int i = 0; i < configs.length; ++i) {
283                 EGLConfig config = configs[i];
284                 if (findConfigAttrib(egl, display, config , EGL10.EGL_RED_SIZE, 0) == 8 &&
285                         findConfigAttrib(egl, display, config, EGL10.EGL_BLUE_SIZE, 0) == 8 &&
286                         findConfigAttrib(egl, display, config, EGL10.EGL_GREEN_SIZE, 0) == 8 &&
287                         findConfigAttrib(egl, display, config, EGL10.EGL_ALPHA_SIZE, 0) == 8 &&
288                         findConfigAttrib(egl, display, config, EGL10.EGL_STENCIL_SIZE, 0) == 8) {
289                     return config;
290                 }
291             }
292 
293             throw new IllegalArgumentException("Could not find suitable EGL config");
294         }
295 
findConfigAttrib(EGL10 egl, EGLDisplay display, EGLConfig config, int attribute, int defaultValue)296         private int findConfigAttrib(EGL10 egl, EGLDisplay display,
297                 EGLConfig config, int attribute, int defaultValue) {
298             int[] value = new int[1];
299             if (egl.eglGetConfigAttrib(display, config, attribute, value)) {
300                 return value[0];
301             }
302             return defaultValue;
303         }
304 
305     }
306 }
307