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