• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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 package com.android.compatibility.common.deviceinfo;
17 
18 import android.app.Activity;
19 import android.app.ActivityManager;
20 import android.app.Instrumentation;
21 import android.content.Context;
22 import android.content.pm.ConfigurationInfo;
23 import android.content.res.Configuration;
24 import android.os.Bundle;
25 import android.view.Window;
26 import android.view.WindowManager;
27 import android.opengl.GLES20;
28 import android.opengl.GLES30;
29 import android.opengl.GLSurfaceView;
30 import android.util.Log;
31 
32 import java.lang.reflect.Field;
33 import java.nio.FloatBuffer;
34 import java.util.ArrayList;
35 import java.util.List;
36 import java.util.Locale;
37 import java.util.HashSet;
38 import java.util.HashMap;
39 import java.util.Scanner;
40 import java.util.Set;
41 import java.util.concurrent.CountDownLatch;
42 
43 import javax.microedition.khronos.egl.EGLConfig;
44 import javax.microedition.khronos.opengles.GL10;
45 
46 /** Stub activity to collect data from the GlesView */
47 public final class GlesStubActivity extends Activity {
48 
49     private static final String LOG_TAG = "GlesStubActivity";
50     private int mVersion = -1;
51     private GraphicsDeviceInfo mGraphicsDeviceInfo;
52     private CountDownLatch mDone = new CountDownLatch(1);
53     private HashSet<String> mOpenGlExtensions = new HashSet<String>();
54     private HashSet<String> mFormats = new HashSet<String>();
55     private HashMap<String, Object> mImplVariables = new HashMap<String, Object>();
56     private HashSet<String> mDynamicArrayVariables = new HashSet<String>();
57     private String mGraphicsVendor;
58     private String mGraphicsRenderer;
59 
60     @Override
onCreate(Bundle bundle)61     public void onCreate(Bundle bundle) {
62         // Dismiss keyguard and keep screen on while this test is on.
63         Window window = getWindow();
64         window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
65                 WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
66                 WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
67 
68         super.onCreate(bundle);
69 
70         window.setFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED,
71                 WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
72 
73         ActivityManager activityManager =
74                 (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
75         ConfigurationInfo info = activityManager.getDeviceConfigurationInfo();
76 
77         mVersion = (info.reqGlEsVersion & 0xffff0000) >> 16;
78 
79         new Thread() {
80             @Override
81             public void run() {
82                 runIterations(mVersion);
83             }
84         }.start();
85     }
86 
87      /**
88      * Wait for this activity to finish gathering information
89      */
waitForActivityToFinish()90     public void waitForActivityToFinish() {
91         try {
92             mDone.await();
93         } catch (InterruptedException e) {
94             // just move on
95         }
96     }
97 
runIterations(int glVersion)98     private void runIterations(int glVersion) {
99         for (int i = 1; i <= glVersion; i++) {
100             final CountDownLatch done = new CountDownLatch(1);
101             final int version = i;
102             GlesStubActivity.this.runOnUiThread(new Runnable() {
103                 @Override
104                 public void run() {
105                     setContentView(new GlesSurfaceView(GlesStubActivity.this, version, done));
106                 }
107             });
108             try {
109                 done.await();
110             } catch (InterruptedException e) {
111                 // just move on
112             }
113         }
114         mDone.countDown();
115     }
116 
getGlVersion()117     int getGlVersion() {
118         return mVersion;
119     }
120 
getOpenGlExtensions()121     List<String> getOpenGlExtensions() {
122         return new ArrayList<>(mOpenGlExtensions);
123     }
124 
addOpenGlExtension(String openGlExtension)125     void addOpenGlExtension(String openGlExtension) {
126         mOpenGlExtensions.add(openGlExtension);
127     }
128 
getCompressedTextureFormats()129     List<String> getCompressedTextureFormats() {
130         return new ArrayList<>(mFormats);
131     }
132 
addCompressedTextureFormat(String format)133     void addCompressedTextureFormat(String format) {
134         mFormats.add(format);
135     }
136 
getVendor()137     String getVendor() {
138         return mGraphicsVendor;
139     }
140 
setVendor(String vendor)141     void setVendor(String vendor) {
142         mGraphicsVendor = vendor;
143     }
144 
getRenderer()145     String getRenderer() {
146         return mGraphicsRenderer;
147     }
148 
setRenderer(String renderer)149     void setRenderer(String renderer) {
150         mGraphicsRenderer = renderer;
151     }
152 
getImplementationVariableNames()153     public Set<String> getImplementationVariableNames() {
154         return mImplVariables.keySet();
155     }
156 
getImplementationVariable(String name)157     public Object getImplementationVariable(String name) {
158         return mImplVariables.get(name);
159     }
160 
isDynamicArrayVariable(String name)161     public boolean isDynamicArrayVariable(String name) {
162         return mDynamicArrayVariables.contains(name);
163     }
164 
addImplementationVariable(String name, Object value, boolean isDynamicArray)165     void addImplementationVariable(String name, Object value, boolean isDynamicArray) {
166         mImplVariables.put(name, value);
167         if (isDynamicArray) {
168             mDynamicArrayVariables.add(name);
169         }
170     }
171 
172     static class GlesSurfaceView extends GLSurfaceView {
173 
GlesSurfaceView(GlesStubActivity parent, int glVersion, CountDownLatch done)174         public GlesSurfaceView(GlesStubActivity parent, int glVersion, CountDownLatch done) {
175             super(parent);
176 
177             if (glVersion > 1) {
178                 // Default is 1 so only set if bigger than 1
179                 setEGLContextClientVersion(glVersion);
180             }
181             setRenderer(new OpenGlesRenderer(parent, glVersion, done));
182         }
183     }
184 
185     static abstract class ImplementationVariable {
186         private Field mField;
ImplementationVariable(String fieldName)187         public ImplementationVariable(String fieldName) {
188             try {
189                 mField = GLES30.class.getField(fieldName);
190             } catch (NoSuchFieldException e) {
191                 Log.e(LOG_TAG, "Failed to get field reflection", e);
192             }
193         }
194 
getName()195         public String getName() {
196             return mField.getName();
197         }
198 
getFieldIdValue()199         public int getFieldIdValue() throws IllegalAccessException {
200             return mField.getInt(null);
201         }
202 
getValue()203         abstract public Object getValue();
204 
getIntValues(int fieldId, int count)205         static protected int[] getIntValues(int fieldId, int count) throws IllegalAccessException{
206             int[] resultInts = new int[count];
207             GLES20.glGetIntegerv(fieldId, resultInts, 0);
208             return resultInts;
209         }
210     }
211 
212     static class IntVectorValue extends ImplementationVariable {
213         private int mCount;
214 
IntVectorValue(String fieldName, int count)215         public IntVectorValue(String fieldName, int count) {
216             super(fieldName);
217             mCount = count;
218         }
219 
220         @Override
getValue()221         public Object getValue() {
222             Log.i(LOG_TAG, "Getting : " + this.getName() + " " + mCount);
223             try {
224                 return getIntValues(this.getFieldIdValue(), mCount);
225             } catch (IllegalAccessException e) {
226                 Log.e(LOG_TAG, "Failed to read the GL field", e);
227             }
228             return null;
229         }
230     }
231 
232     static class DynamicIntVectorValue extends ImplementationVariable {
233         private Field mCountField;
234 
DynamicIntVectorValue(String fieldName, String countFieldName)235         public DynamicIntVectorValue(String fieldName, String countFieldName) {
236             super(fieldName);
237             try {
238                 mCountField = GLES30.class.getField(countFieldName);
239             } catch (NoSuchFieldException e) {
240                 Log.e(LOG_TAG, "Failed to get field reflection", e);
241             }
242         }
243 
244         @Override
getValue()245         public Object getValue() {
246             Log.i(LOG_TAG, "Getting : " + this.getName() + " " + mCountField.getName());
247             try {
248                 int[] count = new int[] {0};
249                 GLES20.glGetIntegerv(mCountField.getInt(null), count, 0);
250                 Log.i(LOG_TAG, "Getting : " + mCountField.getName() + " " + count[0]);
251                 return getIntValues(this.getFieldIdValue(), count[0]);
252             } catch (IllegalAccessException e) {
253                 Log.e(LOG_TAG, "Failed to read the GL field", e);
254             }
255             return null;
256         }
257     }
258 
259     static class FloatVectorValue extends ImplementationVariable {
260         private int mCount;
261 
FloatVectorValue(String fieldName, int count)262         public FloatVectorValue(String fieldName, int count) {
263             super(fieldName);
264             mCount = count;
265         }
266 
267         @Override
getValue()268         public Object getValue() {
269             Log.i(LOG_TAG, "Getting : " + this.getName() + " " + mCount);
270             try {
271                 float[] result = new float[mCount];
272                 GLES20.glGetFloatv(getFieldIdValue(), result, 0);
273                 return result;
274             } catch (IllegalAccessException e) {
275                 Log.e(LOG_TAG, "Failed to read the GL field", e);
276             }
277             return null;
278         }
279     }
280 
281     static class LongVectorValue extends ImplementationVariable {
282         private int mCount;
283 
LongVectorValue(String fieldName, int count)284         public LongVectorValue(String fieldName, int count) {
285             super(fieldName);
286             mCount = count;
287         }
288 
289         @Override
getValue()290         public Object getValue() {
291             Log.i(LOG_TAG, "Getting : " + this.getName() + " " + mCount);
292             try {
293                 long result[] = new long[mCount];
294                 GLES30.glGetInteger64v(getFieldIdValue(), result, 0);
295                 return result;
296             } catch (IllegalAccessException e) {
297                 Log.e(LOG_TAG, "Failed to read the GL field", e);
298             }
299             return null;
300         }
301     }
302 
303     static class StringValue extends ImplementationVariable {
StringValue(String fieldName)304         public StringValue(String fieldName) {
305             super(fieldName);
306         }
307 
308         @Override
getValue()309         public Object getValue() {
310             Log.i(LOG_TAG, "Getting : " + this.getName());
311             String result = null;
312             try {
313                 result = GLES20.glGetString(this.getFieldIdValue());
314             } catch (IllegalAccessException e) {
315                 Log.e(LOG_TAG, "Failed to read the GL field", e);
316             }
317             return result;
318         }
319     }
320 
321 	// NOTE: Changes to the types of the variables will carry over to
322     // GraphicsDeviceInfo proto via GraphicsDeviceInfo. See
323     // go/edi-userguide for details.
324     static ImplementationVariable[] GLES2_IMPLEMENTATION_VARIABLES = {
325         new IntVectorValue("GL_SUBPIXEL_BITS", 1),
326         new IntVectorValue("GL_MAX_TEXTURE_SIZE", 1),
327         new IntVectorValue("GL_MAX_CUBE_MAP_TEXTURE_SIZE", 1),
328         new IntVectorValue("GL_MAX_VIEWPORT_DIMS", 2),
329         new FloatVectorValue("GL_ALIASED_POINT_SIZE_RANGE", 2),
330         new FloatVectorValue("GL_ALIASED_LINE_WIDTH_RANGE", 2),
331         new DynamicIntVectorValue("GL_COMPRESSED_TEXTURE_FORMATS", "GL_NUM_COMPRESSED_TEXTURE_FORMATS"),
332         new DynamicIntVectorValue("GL_SHADER_BINARY_FORMATS", "GL_NUM_SHADER_BINARY_FORMATS"),
333         new IntVectorValue("GL_SHADER_COMPILER", 1),
334         new StringValue("GL_SHADING_LANGUAGE_VERSION"),
335         new StringValue("GL_VERSION"),
336         new IntVectorValue("GL_MAX_VERTEX_ATTRIBS", 1),
337         new IntVectorValue("GL_MAX_VERTEX_UNIFORM_VECTORS", 1),
338         new IntVectorValue("GL_MAX_VARYING_VECTORS", 1),
339         new IntVectorValue("GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS", 1),
340         new IntVectorValue("GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS", 1),
341         new IntVectorValue("GL_MAX_TEXTURE_IMAGE_UNITS", 1),
342         new IntVectorValue("GL_MAX_FRAGMENT_UNIFORM_VECTORS", 1),
343         new IntVectorValue("GL_MAX_RENDERBUFFER_SIZE", 1)
344     };
345 
346     static ImplementationVariable[] GLES3_IMPLEMENTATION_VARIABLES = {
347         new LongVectorValue("GL_MAX_ELEMENT_INDEX", 1),
348         new IntVectorValue("GL_MAX_3D_TEXTURE_SIZE", 1),
349         new IntVectorValue("GL_MAX_ARRAY_TEXTURE_LAYERS", 1),
350         new FloatVectorValue("GL_MAX_TEXTURE_LOD_BIAS", 1),
351         new IntVectorValue("GL_MAX_DRAW_BUFFERS", 1),
352         new IntVectorValue("GL_MAX_COLOR_ATTACHMENTS", 1),
353         new IntVectorValue("GL_MAX_ELEMENTS_INDICES", 1),
354         new IntVectorValue("GL_MAX_ELEMENTS_VERTICES", 1),
355         new DynamicIntVectorValue("GL_PROGRAM_BINARY_FORMATS", "GL_NUM_PROGRAM_BINARY_FORMATS"),
356         new LongVectorValue("GL_MAX_SERVER_WAIT_TIMEOUT", 1),
357         new IntVectorValue("GL_MAJOR_VERSION", 1),
358         new IntVectorValue("GL_MINOR_VERSION", 1),
359         new IntVectorValue("GL_MAX_VERTEX_UNIFORM_COMPONENTS", 1),
360         new IntVectorValue("GL_MAX_VERTEX_UNIFORM_BLOCKS", 1),
361         new IntVectorValue("GL_MAX_VERTEX_OUTPUT_COMPONENTS", 1),
362         new IntVectorValue("GL_MAX_FRAGMENT_UNIFORM_COMPONENTS", 1),
363         new IntVectorValue("GL_MAX_FRAGMENT_UNIFORM_BLOCKS", 1),
364         new IntVectorValue("GL_MAX_FRAGMENT_INPUT_COMPONENTS", 1),
365         new IntVectorValue("GL_MIN_PROGRAM_TEXEL_OFFSET", 1),
366         new IntVectorValue("GL_MAX_PROGRAM_TEXEL_OFFSET", 1),
367         new IntVectorValue("GL_MAX_UNIFORM_BUFFER_BINDINGS", 1),
368         new LongVectorValue("GL_MAX_UNIFORM_BLOCK_SIZE", 1),
369         new IntVectorValue("GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT", 1),
370         new IntVectorValue("GL_MAX_COMBINED_UNIFORM_BLOCKS", 1),
371         new LongVectorValue("GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS", 1),
372         new LongVectorValue("GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS", 1),
373         new IntVectorValue("GL_MAX_VARYING_COMPONENTS", 1),
374         new IntVectorValue("GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS", 1),
375         new IntVectorValue("GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS", 1),
376         new IntVectorValue("GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS", 1)
377     };
378 
379     static class OpenGlesRenderer implements GLSurfaceView.Renderer {
380 
381         private final GlesStubActivity mParent;
382         private final int mGlVersion;
383         private final CountDownLatch mDone;
384 
OpenGlesRenderer(GlesStubActivity parent, int glVersion, CountDownLatch done)385         OpenGlesRenderer(GlesStubActivity parent, int glVersion, CountDownLatch done) {
386             mParent = parent;
387             mGlVersion = glVersion;
388             mDone = done;
389         }
390 
391         @Override
onSurfaceCreated(GL10 gl, EGLConfig config)392         public void onSurfaceCreated(GL10 gl, EGLConfig config) {
393             String extensions;
394             String vendor;
395             String renderer;
396             if (mGlVersion == 2) {
397                 extensions = GLES20.glGetString(GLES20.GL_EXTENSIONS);
398                 vendor = GLES20.glGetString(GLES20.GL_VENDOR);
399                 renderer = GLES20.glGetString(GLES20.GL_RENDERER);
400                 collectImplementationVariables(GLES2_IMPLEMENTATION_VARIABLES);
401             } else if (mGlVersion == 3) {
402                 extensions = GLES30.glGetString(GLES30.GL_EXTENSIONS);
403                 vendor = GLES30.glGetString(GLES30.GL_VENDOR);
404                 renderer = GLES30.glGetString(GLES30.GL_RENDERER);
405                 collectImplementationVariables(GLES3_IMPLEMENTATION_VARIABLES);
406             } else {
407                 extensions = gl.glGetString(GL10.GL_EXTENSIONS);
408                 vendor = gl.glGetString(GL10.GL_VENDOR);
409                 renderer = gl.glGetString(GL10.GL_RENDERER);
410             }
411             mParent.setVendor(vendor);
412             mParent.setRenderer(renderer);
413             Scanner scanner = new Scanner(extensions);
414             scanner.useDelimiter(" ");
415             while (scanner.hasNext()) {
416                 String ext = scanner.next();
417                 mParent.addOpenGlExtension(ext);
418                 if (ext.contains("texture")) {
419                     if (ext.contains("compression") || ext.contains("compressed")) {
420                         mParent.addCompressedTextureFormat(ext);
421                     }
422                 }
423             }
424             scanner.close();
425 
426             mDone.countDown();
427         }
428 
429         @Override
onSurfaceChanged(GL10 gl, int width, int height)430         public void onSurfaceChanged(GL10 gl, int width, int height) {}
431 
432         @Override
onDrawFrame(GL10 gl)433         public void onDrawFrame(GL10 gl) {}
434 
collectImplementationVariables(ImplementationVariable[] variables)435         private void collectImplementationVariables(ImplementationVariable[] variables) {
436             for (int i = 0; i < variables.length; i++) {
437                 String name = variables[i].getName();
438                 Object value = variables[i].getValue();
439                 boolean dynamicArray = variables[i] instanceof DynamicIntVectorValue;
440                 mParent.addImplementationVariable(name, value, dynamicArray);
441             }
442         }
443     }
444 }
445