blob: 5a768166f0f3f9abc9a9dcfb59b5d0e136e318d5 [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.opengl.cts;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ConfigurationInfo;
import android.content.pm.FeatureInfo;
import android.content.pm.PackageManager;
import android.test.ActivityInstrumentationTestCase2;
import android.util.Log;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
/**
* Test for checking whether the ro.opengles.version property is set to the correct value.
*/
public class OpenGlEsVersionTest
extends ActivityInstrumentationTestCase2<OpenGlEsVersionCtsActivity> {
private static final String TAG = OpenGlEsVersionTest.class.getSimpleName();
// TODO: switch to android.opengl.EGL14/EGLExt and use the constants from there
private static final int EGL_OPENGL_ES_BIT = 0x0001;
private static final int EGL_OPENGL_ES2_BIT = 0x0004;
private static final int EGL_OPENGL_ES3_BIT_KHR = 0x0040;
private OpenGlEsVersionCtsActivity mActivity;
public OpenGlEsVersionTest() {
super("android.graphics.cts", OpenGlEsVersionCtsActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
mActivity = getActivity();
}
public void testOpenGlEsVersion() throws InterruptedException {
int detectedMajorVersion = getDetectedMajorVersion();
int reportedVersion = getVersionFromActivityManager(mActivity);
assertEquals("Reported OpenGL ES version from ActivityManager differs from PackageManager",
reportedVersion, getVersionFromPackageManager(mActivity));
assertGlVersionString(1, 1);
if (detectedMajorVersion == 2) {
restartActivityWithClientVersion(2);
assertGlVersionString(2, getMinorVersion(reportedVersion));
} else if (detectedMajorVersion == 3) {
restartActivityWithClientVersion(3);
assertGlVersionString(3, getMinorVersion(reportedVersion));
}
}
public void testRequiredExtensions() throws InterruptedException {
int reportedVersion = getVersionFromActivityManager(mActivity);
// We only have required extensions on ES3.1+
if (getMajorVersion(reportedVersion) != 3 || getMinorVersion(reportedVersion) < 1)
return;
restartActivityWithClientVersion(3);
String extensions = mActivity.getExtensionsString();
final String requiredList[] = {
"EXT_texture_sRGB_decode",
"KHR_blend_equation_advanced",
"KHR_debug",
"OES_shader_image_atomic",
"OES_texture_stencil8",
"OES_texture_storage_multisample_2d_array"
};
for (int i = 0; i < requiredList.length; ++i) {
assertTrue("OpenGL ES version 3.1+ is missing extension " + requiredList[i],
hasExtension(extensions, requiredList[i]));
}
}
public void testExtensionPack() throws InterruptedException {
// Requirements:
// 1. If the device claims support for the system feature, the extension must be available.
// 2. If the extension is available, the device must claim support for it.
// 3. If the extension is available, it must be correct:
// - ES 3.1+ must be supported
// - All included extensions must be available
int reportedVersion = getVersionFromActivityManager(mActivity);
boolean hasAepFeature = mActivity.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_OPENGLES_EXTENSION_PACK);
if (getMajorVersion(reportedVersion) != 3 || getMinorVersion(reportedVersion) < 1) {
assertFalse("FEATURE_OPENGLES_EXTENSION_PACK is available without OpenGL ES 3.1+",
hasAepFeature);
return;
}
restartActivityWithClientVersion(3);
String extensions = mActivity.getExtensionsString();
boolean hasAepExtension = hasExtension(extensions, "GL_ANDROID_extension_pack_es31a");
assertEquals("System feature FEATURE_OPENGLES_EXTENSION_PACK is "
+ (hasAepFeature ? "" : "not ") + "available, but extension GL_ANDROID_extension_pack_es31a is "
+ (hasAepExtension ? "" : "not ") + "in the OpenGL ES extension list.",
hasAepFeature, hasAepExtension);
}
public void testOpenGlEsVersionForVrHighPerformance() throws InterruptedException {
if (!supportsVrHighPerformance())
return;
restartActivityWithClientVersion(3);
int reportedVersion = getVersionFromActivityManager(mActivity);
int major = getMajorVersion(reportedVersion);
int minor = getMinorVersion(reportedVersion);
assertTrue("OpenGL ES version 3.2 or higher is required for VR high-performance devices " +
" but this device supports only version " + major + "." + minor,
(major == 3 && minor >= 2) || major > 3);
}
public void testRequiredExtensionsForVrHighPerformance() throws InterruptedException {
if (!supportsVrHighPerformance())
return;
restartActivityWithClientVersion(3);
String extensions = mActivity.getExtensionsString();
final String requiredList[] = {
"EXT_protected_textures",
"EXT_multisampled_render_to_texture",
"OVR_multiview",
"OVR_multiview_multisampled_render_to_texture",
"OVR_multiview2",
};
for (int i = 0; i < requiredList.length; ++i) {
assertTrue("Required extension for VR high-performance is missing: " + requiredList[i],
hasExtension(extensions, requiredList[i]));
}
EGL10 egl = (EGL10) EGLContext.getEGL();
EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
extensions = egl.eglQueryString(display, EGL10.EGL_EXTENSIONS);
final String requiredEglList[] = {
"EGL_ANDROID_create_native_client_buffer",
"EGL_ANDROID_front_buffer_auto_refresh",
"EGL_EXT_protected_content",
"EGL_KHR_mutable_render_buffer",
"EGL_KHR_wait_sync",
};
for (int i = 0; i < requiredList.length; ++i) {
assertTrue("Required EGL extension for VR high-performance is missing: " +
requiredEglList[i], hasExtension(extensions, requiredEglList[i]));
}
}
private static boolean hasExtension(String extensions, String name) {
return OpenGlEsVersionCtsActivity.hasExtension(extensions, name);
}
/** @return OpenGL ES major version 1, 2, or 3 or some non-positive number for error */
private static int getDetectedMajorVersion() {
/*
* Get all the device configurations and check the EGL_RENDERABLE_TYPE attribute
* to determine the highest ES version supported by any config. The
* EGL_KHR_create_context extension is required to check for ES3 support; if the
* extension is not present this test will fail to detect ES3 support. This
* effectively makes the extension mandatory for ES3-capable devices.
*/
EGL10 egl = (EGL10) EGLContext.getEGL();
EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
int[] numConfigs = new int[1];
if (egl.eglInitialize(display, null)) {
try {
boolean checkES3 = hasExtension(egl.eglQueryString(display, EGL10.EGL_EXTENSIONS),
"EGL_KHR_create_context");
if (egl.eglGetConfigs(display, null, 0, numConfigs)) {
EGLConfig[] configs = new EGLConfig[numConfigs[0]];
if (egl.eglGetConfigs(display, configs, numConfigs[0], numConfigs)) {
int highestEsVersion = 0;
int[] value = new int[1];
for (int i = 0; i < numConfigs[0]; i++) {
if (egl.eglGetConfigAttrib(display, configs[i],
EGL10.EGL_RENDERABLE_TYPE, value)) {
if (checkES3 && ((value[0] & EGL_OPENGL_ES3_BIT_KHR) ==
EGL_OPENGL_ES3_BIT_KHR)) {
if (highestEsVersion < 3) highestEsVersion = 3;
} else if ((value[0] & EGL_OPENGL_ES2_BIT) == EGL_OPENGL_ES2_BIT) {
if (highestEsVersion < 2) highestEsVersion = 2;
} else if ((value[0] & EGL_OPENGL_ES_BIT) == EGL_OPENGL_ES_BIT) {
if (highestEsVersion < 1) highestEsVersion = 1;
}
} else {
Log.w(TAG, "Getting config attribute with "
+ "EGL10#eglGetConfigAttrib failed "
+ "(" + i + "/" + numConfigs[0] + "): "
+ egl.eglGetError());
}
}
return highestEsVersion;
} else {
Log.e(TAG, "Getting configs with EGL10#eglGetConfigs failed: "
+ egl.eglGetError());
return -1;
}
} else {
Log.e(TAG, "Getting number of configs with EGL10#eglGetConfigs failed: "
+ egl.eglGetError());
return -2;
}
} finally {
egl.eglTerminate(display);
}
} else {
Log.e(TAG, "Couldn't initialize EGL.");
return -3;
}
}
private static int getVersionFromActivityManager(Context context) {
ActivityManager activityManager =
(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
ConfigurationInfo configInfo = activityManager.getDeviceConfigurationInfo();
if (configInfo.reqGlEsVersion != ConfigurationInfo.GL_ES_VERSION_UNDEFINED) {
return configInfo.reqGlEsVersion;
} else {
return 1 << 16; // Lack of property means OpenGL ES version 1
}
}
private static int getVersionFromPackageManager(Context context) {
PackageManager packageManager = context.getPackageManager();
FeatureInfo[] featureInfos = packageManager.getSystemAvailableFeatures();
if (featureInfos != null && featureInfos.length > 0) {
for (FeatureInfo featureInfo : featureInfos) {
// Null feature name means this feature is the open gl es version feature.
if (featureInfo.name == null) {
if (featureInfo.reqGlEsVersion != FeatureInfo.GL_ES_VERSION_UNDEFINED) {
return featureInfo.reqGlEsVersion;
} else {
return 1 << 16; // Lack of property means OpenGL ES version 1
}
}
}
}
return 1;
}
/** @see FeatureInfo#getGlEsVersion() */
private static int getMajorVersion(int glEsVersion) {
return ((glEsVersion & 0xffff0000) >> 16);
}
/** @see FeatureInfo#getGlEsVersion() */
private static int getMinorVersion(int glEsVersion) {
return glEsVersion & 0xffff;
}
/**
* Check that the version string has the form "OpenGL ES(-CM)? (\d+)\.(\d+)", where the two
* numbers match the major and minor parameters.
*/
private void assertGlVersionString(int major, int minor) throws InterruptedException {
Matcher matcher = Pattern.compile("OpenGL ES(?:-CM)? (\\d+)\\.(\\d+).*")
.matcher(mActivity.getVersionString());
assertTrue("OpenGL ES version string is not of the required form "
+ "'OpenGL ES(-CM)? (\\d+)\\.(\\d+).*'",
matcher.matches());
int stringMajor = Integer.parseInt(matcher.group(1));
int stringMinor = Integer.parseInt(matcher.group(2));
assertEquals("GL_VERSION string doesn't match ActivityManager major version (check ro.opengles.version property)",
major, stringMajor);
assertEquals("GL_VERSION string doesn't match ActivityManager minor version (check ro.opengles.version property)",
minor, stringMinor);
}
/** Restart {@link GLSurfaceViewCtsActivity} with a specific client version. */
private void restartActivityWithClientVersion(int version) {
mActivity.finish();
setActivity(null);
try {
Intent intent = OpenGlEsVersionCtsActivity.createIntent(version);
setActivityIntent(intent);
mActivity = getActivity();
} finally {
setActivityIntent(null);
}
}
/**
* Return whether the system supports FEATURE_VR_MODE and
* FEATURE_VR_MODE_HIGH_PERFORMANCE. This is used to skip some tests.
*/
private boolean supportsVrHighPerformance() {
PackageManager pm = mActivity.getPackageManager();
return pm.hasSystemFeature(PackageManager.FEATURE_VR_MODE_HIGH_PERFORMANCE);
}
}