• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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 
17 package android.opengl.cts;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertFalse;
21 import static org.junit.Assert.assertTrue;
22 
23 import android.app.ActivityManager;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.pm.ConfigurationInfo;
27 import android.content.pm.FeatureInfo;
28 import android.content.pm.PackageManager;
29 import android.content.res.Configuration;
30 import android.util.Log;
31 
32 import androidx.test.filters.LargeTest;
33 import androidx.test.rule.ActivityTestRule;
34 import androidx.test.runner.AndroidJUnit4;
35 
36 import com.android.compatibility.common.util.CddTest;
37 
38 import org.junit.Assume;
39 import org.junit.Before;
40 import org.junit.Rule;
41 import org.junit.Test;
42 import org.junit.runner.RunWith;
43 
44 import java.util.regex.Matcher;
45 import java.util.regex.Pattern;
46 
47 import javax.microedition.khronos.egl.EGL10;
48 import javax.microedition.khronos.egl.EGLConfig;
49 import javax.microedition.khronos.egl.EGLContext;
50 import javax.microedition.khronos.egl.EGLDisplay;
51 
52 /**
53  * Test for checking whether the ro.opengles.version property is set to the correct value.
54  */
55 @LargeTest
56 @RunWith(AndroidJUnit4.class)
57 public class OpenGlEsVersionTest {
58 
59     private static final String TAG = OpenGlEsVersionTest.class.getSimpleName();
60 
61     // TODO: switch to android.opengl.EGL14/EGLExt and use the constants from there
62     private static final int EGL_OPENGL_ES_BIT = 0x0001;
63     private static final int EGL_OPENGL_ES2_BIT = 0x0004;
64     private static final int EGL_OPENGL_ES3_BIT_KHR = 0x0040;
65 
66     private OpenGlEsVersionCtsActivity mActivity;
67 
68     @Rule
69     public ActivityTestRule<OpenGlEsVersionCtsActivity> mActivityRule =
70             new ActivityTestRule<>(OpenGlEsVersionCtsActivity.class);
71 
72     @Rule
73     public ActivityTestRule<OpenGlEsVersionCtsActivity> mActivityRelaunchRule =
74             new ActivityTestRule<>(OpenGlEsVersionCtsActivity.class, false, false);
75 
76     @Before
setup()77     public void setup() {
78         mActivity = mActivityRule.getActivity();
79     }
80 
81     @CddTest(requirement="7.1.4.1/C-0-1")
82     @Test
testOpenGlEsVersion()83     public void testOpenGlEsVersion() throws InterruptedException {
84         int detectedMajorVersion = getDetectedMajorVersion();
85         int reportedVersion = getVersionFromActivityManager(mActivity);
86 
87         assertEquals("Reported OpenGL ES version from ActivityManager differs from PackageManager",
88                 reportedVersion, getVersionFromPackageManager(mActivity));
89 
90         verifyGlVersionString(1, 1);
91         if (detectedMajorVersion == 2) {
92             restartActivityWithClientVersion(2);
93             verifyGlVersionString(2, getMinorVersion(reportedVersion));
94         } else if (detectedMajorVersion == 3) {
95             restartActivityWithClientVersion(3);
96             verifyGlVersionString(3, getMinorVersion(reportedVersion));
97         }
98     }
99 
100     @CddTest(requirement="7.1.4.1/C-2-2")
101     @Test
testRequiredExtensions()102     public void testRequiredExtensions() throws InterruptedException {
103         int reportedVersion = getVersionFromActivityManager(mActivity);
104 
105         if (getMajorVersion(reportedVersion) < 3)
106             return;
107 
108         restartActivityWithClientVersion(3);
109 
110         String extensions = mActivity.getExtensionsString();
111 
112         if (getMajorVersion(reportedVersion) != 3 || getMinorVersion(reportedVersion) < 1)
113             return;
114 
115         final String es31RequiredList[] = {
116             "EXT_texture_sRGB_decode",
117             "KHR_blend_equation_advanced",
118             "KHR_debug",
119             "OES_shader_image_atomic",
120             "OES_texture_stencil8",
121             "OES_texture_storage_multisample_2d_array"
122         };
123 
124         for (int i = 0; i < es31RequiredList.length; ++i) {
125             assertTrue("OpenGL ES version 3.1+ is missing extension " + es31RequiredList[i],
126                     hasExtension(extensions, es31RequiredList[i]));
127         }
128     }
129 
130     @CddTest(requirement="7.1.4.1/C-2-1,C-5-1,C-4-1")
131     @Test
testExtensionPack()132     public void testExtensionPack() throws InterruptedException {
133         // Requirements:
134         // 1. If the device claims support for the system feature, the extension must be available.
135         // 2. If the extension is available, the device must claim support for it.
136         // 3. If the extension is available, it must be correct:
137         //    - ES 3.1+ must be supported
138         //    - All included extensions must be available
139 
140         int reportedVersion = getVersionFromActivityManager(mActivity);
141         boolean hasAepFeature = mActivity.getPackageManager().hasSystemFeature(
142                 PackageManager.FEATURE_OPENGLES_EXTENSION_PACK);
143 
144         if (getMajorVersion(reportedVersion) != 3 || getMinorVersion(reportedVersion) < 1) {
145             assertFalse("FEATURE_OPENGLES_EXTENSION_PACK is available without OpenGL ES 3.1+",
146                     hasAepFeature);
147             return;
148         }
149 
150         restartActivityWithClientVersion(3);
151 
152         String extensions = mActivity.getExtensionsString();
153         boolean hasAepExtension = hasExtension(extensions, "GL_ANDROID_extension_pack_es31a");
154         assertEquals("System feature FEATURE_OPENGLES_EXTENSION_PACK is "
155             + (hasAepFeature ? "" : "not ") + "available, but extension GL_ANDROID_extension_pack_es31a is "
156             + (hasAepExtension ? "" : "not ") + "in the OpenGL ES extension list.",
157             hasAepFeature, hasAepExtension);
158     }
159     @CddTest(requirement="7.9.2/C-1-4")
160     @Test
testOpenGlEsVersionForVrHighPerformance()161     public void testOpenGlEsVersionForVrHighPerformance() throws InterruptedException {
162         if (!supportsVrHighPerformance())
163             return;
164         restartActivityWithClientVersion(3);
165 
166         int reportedVersion = getVersionFromActivityManager(mActivity);
167         int major = getMajorVersion(reportedVersion);
168         int minor = getMinorVersion(reportedVersion);
169 
170         assertTrue("OpenGL ES version 3.2 or higher is required for VR high-performance devices " +
171             " but this device supports only version " + major + "." + minor,
172             (major == 3 && minor >= 2) || major > 3);
173     }
174 
175     @CddTest(requirement="7.9.2/C-1-6,C-1-8")
176     @Test
testRequiredExtensionsForVrHighPerformance()177     public void testRequiredExtensionsForVrHighPerformance() throws InterruptedException {
178         if (!supportsVrHighPerformance())
179             return;
180         restartActivityWithClientVersion(3);
181         final boolean isVrHeadset = (mActivity.getResources().getConfiguration().uiMode
182             & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_VR_HEADSET;
183 
184         String extensions = mActivity.getExtensionsString();
185         final String requiredList[] = {
186             "GL_EXT_multisampled_render_to_texture",
187             "GL_EXT_protected_textures",
188             "GL_OVR_multiview",
189             "GL_OVR_multiview2",
190             "GL_OVR_multiview_multisampled_render_to_texture",
191         };
192         final String vrHeadsetRequiredList[] = {
193             "GL_EXT_EGL_image_array",
194             "GL_EXT_external_buffer",
195             "GL_EXT_multisampled_render_to_texture2",
196         };
197 
198         for (String requiredExtension : requiredList) {
199             assertTrue("Required extension for VR high-performance is missing: " + requiredExtension,
200                     hasExtension(extensions, requiredExtension));
201         }
202         if (isVrHeadset) {
203             for (String requiredExtension : vrHeadsetRequiredList) {
204                 assertTrue("Required extension for VR high-performance is missing: " + requiredExtension,
205                         hasExtension(extensions, requiredExtension));
206             }
207         }
208 
209         EGL10 egl = (EGL10) EGLContext.getEGL();
210         EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
211         extensions = egl.eglQueryString(display, EGL10.EGL_EXTENSIONS);
212         final String requiredEglList[] = {
213             "EGL_ANDROID_front_buffer_auto_refresh",
214             "EGL_ANDROID_get_native_client_buffer",
215             "EGL_EXT_protected_content",
216             "EGL_IMG_context_priority",
217             "EGL_KHR_fence_sync",
218             "EGL_KHR_mutable_render_buffer",
219             "EGL_KHR_wait_sync",
220         };
221         final String vrHeadsetRequiredEglList[] = {
222             "EGL_EXT_image_gl_colorspace",
223         };
224 
225         for (String requiredExtension : requiredEglList) {
226             assertTrue("Required EGL extension for VR high-performance is missing: " + requiredExtension,
227                     hasExtension(extensions, requiredExtension));
228         }
229         if (isVrHeadset) {
230             for (String requiredExtension : vrHeadsetRequiredEglList) {
231                 assertTrue("Required EGL extension for VR high-performance is missing: " + requiredExtension,
232                         hasExtension(extensions, requiredExtension));
233             }
234         }
235     }
236     @CddTest(requirement="7.1.4.1/C-6-1")
237     @Test
testRequiredEglExtensions()238     public void testRequiredEglExtensions() {
239         // See CDD section 7.1.4
240         final String requiredEglList[] = {
241             "EGL_KHR_image",
242             "EGL_KHR_image_base",
243             "EGL_ANDROID_image_native_buffer",
244             "EGL_ANDROID_get_native_client_buffer",
245             "EGL_KHR_wait_sync",
246             "EGL_KHR_get_all_proc_addresses",
247             "EGL_ANDROID_presentation_time",
248             "EGL_KHR_swap_buffers_with_damage"
249         };
250 
251         EGL10 egl = (EGL10) EGLContext.getEGL();
252         EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
253 
254         if (egl.eglInitialize(display, null)) {
255             try {
256                 String eglExtensions = egl.eglQueryString(display, EGL10.EGL_EXTENSIONS);
257                 for (int i = 0; i < requiredEglList.length; ++i) {
258                     assertTrue("EGL Extension required by CDD section 7.1.4 missing: " +
259                                requiredEglList[i], hasExtension(eglExtensions, requiredEglList[i]));
260                 }
261                 if (hasExtension(eglExtensions, "EGL_KHR_mutable_render_buffer")) {
262                     assertTrue("Devices exposes EGL_KHR_mutable_render_buffer but not EGL_ANDROID_front_buffer_auto_refresh", hasExtension(eglExtensions, "EGL_ANDROID_front_buffer_auto_refresh"));
263                 }
264             } finally {
265                 egl.eglTerminate(display);
266             }
267         } else {
268             Log.e(TAG, "Couldn't initialize EGL.");
269         }
270     }
271 
272     @CddTest(requirement="7.1.4.5/H-1-1")
273     @Test
testRequiredEglExtensionsForHdrCapableDisplay()274     public void testRequiredEglExtensionsForHdrCapableDisplay() {
275         // See CDD section 7.1.4
276         // This test covers the EGL portion of the CDD requirement. The VK portion of the
277         // requirement is covered elsewhere.
278         final String requiredEglList[] = {
279             "EGL_EXT_gl_colorspace_bt2020_pq",
280             "EGL_EXT_surface_SMPTE2086_metadata",
281             "EGL_EXT_surface_CTA861_3_metadata",
282         };
283 
284         // This requirement only applies if device is handheld and claims to be HDR capable.
285         boolean isHdrCapable = mActivity.getResources().getConfiguration().isScreenHdr();
286         if (!isHdrCapable || !isHandheld())
287             return;
288 
289         EGL10 egl = (EGL10) EGLContext.getEGL();
290         EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
291 
292         if (egl.eglInitialize(display, null)) {
293             try {
294                 String eglExtensions = egl.eglQueryString(display, EGL10.EGL_EXTENSIONS);
295                 for (int i = 0; i < requiredEglList.length; ++i) {
296                     assertTrue("EGL extension required by CDD section 7.1.4.5 missing: " +
297                         requiredEglList[i], hasExtension(eglExtensions, requiredEglList[i]));
298                 }
299             } finally {
300                 egl.eglTerminate(display);
301             }
302         } else {
303             Log.e(TAG, "Couldn't initialize EGL.");
304         }
305     }
306 
307     @CddTest(requirement="7.1.4.5/C-1-4")
308     @Test
testRequiredGLESVersion()309     public void testRequiredGLESVersion() {
310         // This requirement only applies if device claims to be wide color capable.
311         boolean isWideColorCapable =
312             mActivity.getResources().getConfiguration().isScreenWideColorGamut();
313         if (!isWideColorCapable)
314             return;
315 
316         int reportedVersion = getVersionFromActivityManager(mActivity);
317         assertEquals("Reported OpenGL ES major version doesn't meet the requirement of" +
318             " CDD 7.1.4.5/C-1-4", 3, getMajorVersion(reportedVersion));
319         assertTrue("Reported OpenGL ES minor version doesn't meet the requirement of" +
320             " CDD 7.1.4.5/C-1-4", 1 == getMinorVersion(reportedVersion) ||
321                                   2 == getMinorVersion(reportedVersion));
322     }
323 
324     @CddTest(requirement="7.1.4.5/C-1-5")
325     @Test
testRequiredEglExtensionsForWideColorDisplay()326     public void testRequiredEglExtensionsForWideColorDisplay() {
327         // See CDD section 7.1.4.5
328         // This test covers the EGL portion of the CDD requirement. The VK portion of the
329         // requirement is covered elsewhere.
330         final String requiredEglList[] = {
331             "EGL_KHR_no_config_context",
332             "EGL_EXT_pixel_format_float",
333             "EGL_KHR_gl_colorspace",
334             "EGL_EXT_gl_colorspace_scrgb",
335             "EGL_EXT_gl_colorspace_scrgb_linear",
336             "EGL_EXT_gl_colorspace_display_p3",
337             "EGL_EXT_gl_colorspace_display_p3_linear",
338             "EGL_EXT_gl_colorspace_display_p3_passthrough",
339         };
340 
341         // This requirement only applies if device claims to be wide color capable.
342         boolean isWideColorCapable = mActivity.getResources().getConfiguration().isScreenWideColorGamut();
343         if (!isWideColorCapable)
344             return;
345 
346         EGL10 egl = (EGL10) EGLContext.getEGL();
347         EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
348 
349         if (egl.eglInitialize(display, null)) {
350             try {
351                 String eglExtensions = egl.eglQueryString(display, EGL10.EGL_EXTENSIONS);
352                 for (int i = 0; i < requiredEglList.length; ++i) {
353                     assertTrue("EGL extension required by CDD section 7.1.4.5 missing: " +
354                         requiredEglList[i], hasExtension(eglExtensions, requiredEglList[i]));
355                 }
356             } finally {
357                 egl.eglTerminate(display);
358             }
359         } else {
360             Log.e(TAG, "Couldn't initialize EGL.");
361         }
362     }
363 
isHandheld()364     private boolean isHandheld() {
365         // handheld nature is not exposed to package manager, for now
366         // we check for touchscreen and NOT watch and NOT tv
367         PackageManager pm = mActivity.getPackageManager();
368         return pm.hasSystemFeature(pm.FEATURE_TOUCHSCREEN)
369                 && !pm.hasSystemFeature(pm.FEATURE_WATCH)
370                 && !pm.hasSystemFeature(pm.FEATURE_TELEVISION);
371     }
372 
hasExtension(String extensions, String name)373     private static boolean hasExtension(String extensions, String name) {
374         return OpenGlEsVersionCtsActivity.hasExtension(extensions, name);
375     }
376 
377     /** @return OpenGL ES major version 1, 2, or 3 or some non-positive number for error */
getDetectedMajorVersion()378     private static int getDetectedMajorVersion() {
379         /*
380          * Get all the device configurations and check the EGL_RENDERABLE_TYPE attribute
381          * to determine the highest ES version supported by any config. The
382          * EGL_KHR_create_context extension is required to check for ES3 support; if the
383          * extension is not present this test will fail to detect ES3 support. This
384          * effectively makes the extension mandatory for ES3-capable devices.
385          */
386 
387         EGL10 egl = (EGL10) EGLContext.getEGL();
388         EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
389         int[] numConfigs = new int[1];
390 
391         if (egl.eglInitialize(display, null)) {
392             try {
393                 boolean checkES3 = hasExtension(egl.eglQueryString(display, EGL10.EGL_EXTENSIONS),
394                         "EGL_KHR_create_context");
395                 if (egl.eglGetConfigs(display, null, 0, numConfigs)) {
396                     EGLConfig[] configs = new EGLConfig[numConfigs[0]];
397                     if (egl.eglGetConfigs(display, configs, numConfigs[0], numConfigs)) {
398                         int highestEsVersion = 0;
399                         int[] value = new int[1];
400                         for (int i = 0; i < numConfigs[0]; i++) {
401                             if (egl.eglGetConfigAttrib(display, configs[i],
402                                     EGL10.EGL_RENDERABLE_TYPE, value)) {
403                                 if (checkES3 && ((value[0] & EGL_OPENGL_ES3_BIT_KHR) ==
404                                         EGL_OPENGL_ES3_BIT_KHR)) {
405                                     if (highestEsVersion < 3) highestEsVersion = 3;
406                                 } else if ((value[0] & EGL_OPENGL_ES2_BIT) == EGL_OPENGL_ES2_BIT) {
407                                     if (highestEsVersion < 2) highestEsVersion = 2;
408                                 } else if ((value[0] & EGL_OPENGL_ES_BIT) == EGL_OPENGL_ES_BIT) {
409                                     if (highestEsVersion < 1) highestEsVersion = 1;
410                                 }
411                             } else {
412                                 Log.w(TAG, "Getting config attribute with "
413                                         + "EGL10#eglGetConfigAttrib failed "
414                                         + "(" + i + "/" + numConfigs[0] + "): "
415                                         + egl.eglGetError());
416                             }
417                         }
418                         return highestEsVersion;
419                     } else {
420                         Log.e(TAG, "Getting configs with EGL10#eglGetConfigs failed: "
421                                 + egl.eglGetError());
422                         return -1;
423                     }
424                 } else {
425                     Log.e(TAG, "Getting number of configs with EGL10#eglGetConfigs failed: "
426                             + egl.eglGetError());
427                     return -2;
428                 }
429               } finally {
430                   egl.eglTerminate(display);
431               }
432         } else {
433             Log.e(TAG, "Couldn't initialize EGL.");
434             return -3;
435         }
436     }
437 
getVersionFromActivityManager(Context context)438     private static int getVersionFromActivityManager(Context context) {
439         ActivityManager activityManager =
440             (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
441         ConfigurationInfo configInfo = activityManager.getDeviceConfigurationInfo();
442         if (configInfo.reqGlEsVersion != ConfigurationInfo.GL_ES_VERSION_UNDEFINED) {
443             return configInfo.reqGlEsVersion;
444         } else {
445             return 1 << 16; // Lack of property means OpenGL ES version 1
446         }
447     }
448 
getVersionFromPackageManager(Context context)449     private static int getVersionFromPackageManager(Context context) {
450         PackageManager packageManager = context.getPackageManager();
451         FeatureInfo[] featureInfos = packageManager.getSystemAvailableFeatures();
452         if (featureInfos != null && featureInfos.length > 0) {
453             for (FeatureInfo featureInfo : featureInfos) {
454                 // Null feature name means this feature is the open gl es version feature.
455                 if (featureInfo.name == null) {
456                     if (featureInfo.reqGlEsVersion != FeatureInfo.GL_ES_VERSION_UNDEFINED) {
457                         return featureInfo.reqGlEsVersion;
458                     } else {
459                         return 1 << 16; // Lack of property means OpenGL ES version 1
460                     }
461                 }
462             }
463         }
464         return 1;
465     }
466 
467     /** @see FeatureInfo#getGlEsVersion() */
getMajorVersion(int glEsVersion)468     private static int getMajorVersion(int glEsVersion) {
469         return ((glEsVersion & 0xffff0000) >> 16);
470     }
471 
472     /** @see FeatureInfo#getGlEsVersion() */
getMinorVersion(int glEsVersion)473     private static int getMinorVersion(int glEsVersion) {
474         return glEsVersion & 0xffff;
475     }
476 
477     /**
478      * Check that the version string has the form "OpenGL ES(-CM)? (\d+)\.(\d+)", where the two
479      * numbers match the major and minor parameters.
480      */
481     @CddTest(requirement="7.1.4.1/C-0-1")
verifyGlVersionString(int major, int minor)482     private void verifyGlVersionString(int major, int minor) throws InterruptedException {
483         Matcher matcher = Pattern.compile("OpenGL ES(?:-CM)? (\\d+)\\.(\\d+).*")
484                                  .matcher(mActivity.getVersionString());
485         assertTrue("OpenGL ES version string is not of the required form "
486             + "'OpenGL ES(-CM)? (\\d+)\\.(\\d+).*'",
487             matcher.matches());
488         int stringMajor = Integer.parseInt(matcher.group(1));
489         int stringMinor = Integer.parseInt(matcher.group(2));
490         assertEquals("GL_VERSION string doesn't match ActivityManager major version (check ro.opengles.version property)",
491             major, stringMajor);
492         assertEquals("GL_VERSION string doesn't match ActivityManager minor version (check ro.opengles.version property)",
493             minor, stringMinor);
494     }
495 
496     /** Restart {@link GLSurfaceViewCtsActivity} with a specific client version. */
restartActivityWithClientVersion(int version)497     private void restartActivityWithClientVersion(int version) {
498         mActivity.finish();
499 
500         Intent intent = OpenGlEsVersionCtsActivity.createIntent(version);
501         mActivity = mActivityRelaunchRule.launchActivity(intent);
502     }
503 
504     /**
505      * Return whether the system supports FEATURE_VR_MODE_HIGH_PERFORMANCE.
506      * This is used to skip some tests.
507      */
supportsVrHighPerformance()508     private boolean supportsVrHighPerformance() {
509         PackageManager pm = mActivity.getPackageManager();
510         return pm.hasSystemFeature(PackageManager.FEATURE_VR_MODE_HIGH_PERFORMANCE);
511     }
512 }
513