Implement getPlatformDisplay with ANGLE support
Apps that care can request a specific ANGLE backend.
That would allow them to choose the native GL backend if
that was preferred (if available.)
Test: TODO
Bug: 80239516
Change-Id: I7bfdf7094749f15f8436c266d12c1191994e27ac
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 3a7979c..619297f 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -52,6 +52,21 @@
return cnx->platform.eglGetDisplay(display);
}
+EGLDisplay eglGetPlatformDisplay(EGLenum platform, EGLNativeDisplayType display,
+ const EGLAttrib* attrib_list) {
+ ATRACE_CALL();
+ clearError();
+
+ if (egl_init_drivers() == EGL_FALSE) {
+ return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
+ }
+
+ // Call down the chain, which usually points directly to the impl
+ // but may also be routed through layers
+ egl_connection_t* const cnx = &gEGLImpl;
+ return cnx->platform.eglGetPlatformDisplay(platform, display, attrib_list);
+}
+
EGLBoolean eglInitialize(EGLDisplay dpy, EGLint* major, EGLint* minor) {
clearError();
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 893cf0b..476b304 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -120,14 +120,15 @@
return false;
}
-EGLDisplay egl_display_t::getFromNativeDisplay(EGLNativeDisplayType disp) {
+EGLDisplay egl_display_t::getFromNativeDisplay(EGLNativeDisplayType disp,
+ const EGLAttrib* attrib_list) {
if (uintptr_t(disp) >= NUM_DISPLAYS)
return nullptr;
- return sDisplay[uintptr_t(disp)].getDisplay(disp);
+ return sDisplay[uintptr_t(disp)].getPlatformDisplay(disp, attrib_list);
}
-static void addAnglePlatformAttributes(egl_connection_t* const cnx, const EGLAttrib* attrib_list,
+static bool addAnglePlatformAttributes(egl_connection_t* const cnx, const EGLAttrib* attrib_list,
std::vector<EGLAttrib>& attrs) {
intptr_t vendorEGL = (intptr_t)cnx->vendorEGL;
@@ -154,24 +155,29 @@
}
}
- cnx->angleBackend = angleBackendDefault;
-
// Allow debug property to override application's
char prop[PROPERTY_VALUE_MAX];
property_get("debug.angle.backend", prop, "0");
switch (atoi(prop)) {
case 1:
ALOGV("addAnglePlatformAttributes: Requesting OpenGLES back-end");
- cnx->angleBackend = EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE;
+ angleBackendDefault = EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE;
break;
case 2:
ALOGV("addAnglePlatformAttributes: Requesting Vulkan back-end");
- cnx->angleBackend = EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
+ angleBackendDefault = EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
break;
default:
break;
}
+ if (cnx->angleBackend == 0) {
+ // Haven't been initialized yet, so set it.
+ cnx->angleBackend = angleBackendDefault;
+ } else if (cnx->angleBackend != angleBackendDefault) {
+ return false;
+ }
+
attrs.reserve(4 * 2);
attrs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
@@ -199,6 +205,8 @@
}
attrs.push_back(EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE);
attrs.push_back(EGL_FALSE);
+
+ return true;
}
// Initialize function ptrs for ANGLE PlatformMethods struct, used for systrace
@@ -238,24 +246,30 @@
return true;
}
-static EGLDisplay getDisplayAngle(EGLNativeDisplayType display, egl_connection_t* const cnx) {
+static EGLDisplay getPlatformDisplayAngle(EGLNativeDisplayType display, egl_connection_t* const cnx,
+ const EGLAttrib* attrib_list, EGLint* error) {
EGLDisplay dpy = EGL_NO_DISPLAY;
+ *error = EGL_NONE;
- // Locally define this until EGL 1.5 is supported
- typedef EGLDisplay (*PFNEGLGETPLATFORMDISPLAYPROC)(EGLenum platform, void* native_display,
- const EGLAttrib* attrib_list);
-
- PFNEGLGETPLATFORMDISPLAYPROC eglGetPlatformDisplay =
- reinterpret_cast<PFNEGLGETPLATFORMDISPLAYPROC>(
- cnx->egl.eglGetProcAddress("eglGetPlatformDisplay"));
-
- if (eglGetPlatformDisplay) {
+ if (cnx->egl.eglGetPlatformDisplay) {
std::vector<EGLAttrib> attrs;
- addAnglePlatformAttributes(cnx, nullptr, attrs);
+ if (attrib_list) {
+ for (const EGLAttrib* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
+ attrs.push_back(attr[0]);
+ attrs.push_back(attr[1]);
+ }
+ }
+
+ if (!addAnglePlatformAttributes(cnx, attrib_list, attrs)) {
+ ALOGE("eglGetDisplay(%p) failed: Mismatch display request", display);
+ *error = EGL_BAD_PARAMETER;
+ return EGL_NO_DISPLAY;
+ }
attrs.push_back(EGL_NONE);
- dpy = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE,
- reinterpret_cast<void*>(EGL_DEFAULT_DISPLAY), attrs.data());
+ dpy = cnx->egl.eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE,
+ reinterpret_cast<void*>(EGL_DEFAULT_DISPLAY),
+ attrs.data());
if (dpy == EGL_NO_DISPLAY) {
ALOGE("eglGetPlatformDisplay failed!");
} else {
@@ -271,8 +285,8 @@
return dpy;
}
-EGLDisplay egl_display_t::getDisplay(EGLNativeDisplayType display) {
-
+EGLDisplay egl_display_t::getPlatformDisplay(EGLNativeDisplayType display,
+ const EGLAttrib* attrib_list) {
std::lock_guard<std::mutex> _l(lock);
ATRACE_CALL();
@@ -284,10 +298,24 @@
EGLDisplay dpy = EGL_NO_DISPLAY;
if (cnx->useAngle) {
- dpy = getDisplayAngle(display, cnx);
+ EGLint error;
+ dpy = getPlatformDisplayAngle(display, cnx, attrib_list, &error);
+ if (error != EGL_NONE) {
+ return setError(error, dpy);
+ }
}
if (dpy == EGL_NO_DISPLAY) {
- dpy = cnx->egl.eglGetDisplay(display);
+ // NOTE: eglGetPlatformDisplay with a empty attribute list
+ // behaves the same as eglGetDisplay
+ if (cnx->egl.eglGetPlatformDisplay) {
+ dpy = cnx->egl.eglGetPlatformDisplay(EGL_PLATFORM_ANDROID_KHR, display,
+ attrib_list);
+ } else {
+ if (attrib_list) {
+ ALOGW("getPlatformDisplay: unexpected attribute list, attributes ignored");
+ }
+ dpy = cnx->egl.eglGetDisplay(display);
+ }
}
disp.dpy = dpy;
@@ -306,13 +334,20 @@
std::unique_lock<std::mutex> _l(refLock);
refs++;
if (refs > 1) {
- if (major != nullptr)
- *major = VERSION_MAJOR;
- if (minor != nullptr)
- *minor = VERSION_MINOR;
+ // We don't know what to report until we know what the
+ // driver supports. Make sure we are initialized before
+ // returning the version info.
while(!eglIsInitialized) {
refCond.wait(_l);
}
+ egl_connection_t* const cnx = &gEGLImpl;
+
+ // TODO: If device doesn't provide 1.4 or 1.5 then we'll be
+ // changing the behavior from the past where we always advertise
+ // version 1.4. May need to check that revision is valid
+ // before using cnx->major & cnx->minor
+ if (major != nullptr) *major = cnx->major;
+ if (minor != nullptr) *minor = cnx->minor;
return EGL_TRUE;
}
while(eglIsInitialized) {
@@ -465,10 +500,12 @@
traceGpuCompletion = true;
}
- if (major != nullptr)
- *major = VERSION_MAJOR;
- if (minor != nullptr)
- *minor = VERSION_MINOR;
+ // TODO: If device doesn't provide 1.4 or 1.5 then we'll be
+ // changing the behavior from the past where we always advertise
+ // version 1.4. May need to check that revision is valid
+ // before using cnx->major & cnx->minor
+ if (major != nullptr) *major = cnx->major;
+ if (minor != nullptr) *minor = cnx->minor;
}
{ // scope for refLock
diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h
index f764028..36856b7 100644
--- a/opengl/libs/EGL/egl_display.h
+++ b/opengl/libs/EGL/egl_display.h
@@ -49,6 +49,7 @@
class EGLAPI egl_display_t { // marked as EGLAPI for testing purposes
static egl_display_t sDisplay[NUM_DISPLAYS];
EGLDisplay getDisplay(EGLNativeDisplayType display);
+ EGLDisplay getPlatformDisplay(EGLNativeDisplayType display, const EGLAttrib* attrib_list);
void loseCurrentImpl(egl_context_t * cur_c);
public:
@@ -72,7 +73,7 @@
bool getObject(egl_object_t* object) const;
static egl_display_t* get(EGLDisplay dpy);
- static EGLDisplay getFromNativeDisplay(EGLNativeDisplayType disp);
+ static EGLDisplay getFromNativeDisplay(EGLNativeDisplayType disp, const EGLAttrib* attrib_list);
EGLBoolean makeCurrent(egl_context_t* c, egl_context_t* cur_c,
EGLSurface draw, EGLSurface read, EGLContext ctx,
diff --git a/opengl/libs/EGL/egl_entries.in b/opengl/libs/EGL/egl_entries.in
index 35c2ecb..177c154 100644
--- a/opengl/libs/EGL/egl_entries.in
+++ b/opengl/libs/EGL/egl_entries.in
@@ -47,6 +47,7 @@
/* EGL 1.5 */
EGL_ENTRY(EGLImage, eglCreateImage, EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLAttrib *)
EGL_ENTRY(EGLBoolean, eglDestroyImage, EGLDisplay, EGLImage)
+EGL_ENTRY(EGLDisplay, eglGetPlatformDisplay, EGLenum, void *, const EGLAttrib *)
/* EGL_EGLEXT_VERSION 3 */
diff --git a/opengl/libs/EGL/egl_platform_entries.cpp b/opengl/libs/EGL/egl_platform_entries.cpp
index 6ef0082..e6aa24d 100644
--- a/opengl/libs/EGL/egl_platform_entries.cpp
+++ b/opengl/libs/EGL/egl_platform_entries.cpp
@@ -135,6 +135,11 @@
"EGL_IMG_context_priority "
"EGL_KHR_no_config_context "
;
+
+char const * const gClientExtensionString =
+ "EGL_EXT_client_extensions "
+ "EGL_KHR_platform_android "
+ "EGL_ANGLE_platform_angle";
// clang-format on
// extensions not exposed to applications but used by the ANDROID system
@@ -279,17 +284,31 @@
// ----------------------------------------------------------------------------
-EGLDisplay eglGetDisplayImpl(EGLNativeDisplayType display)
-{
+static EGLDisplay eglGetPlatformDisplayTmpl(EGLenum platform, EGLNativeDisplayType display,
+ const EGLAttrib* attrib_list) {
+ if (platform != EGL_PLATFORM_ANDROID_KHR) {
+ return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
+ }
+
uintptr_t index = reinterpret_cast<uintptr_t>(display);
if (index >= NUM_DISPLAYS) {
return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
}
- EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
+ EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display, attrib_list);
return dpy;
}
+EGLDisplay eglGetDisplayImpl(EGLNativeDisplayType display) {
+ return eglGetPlatformDisplayTmpl(EGL_PLATFORM_ANDROID_KHR, display, nullptr);
+}
+
+EGLDisplay eglGetPlatformDisplayImpl(EGLenum platform, void* native_display,
+ const EGLAttrib* attrib_list) {
+ return eglGetPlatformDisplayTmpl(platform, static_cast<EGLNativeDisplayType>(native_display),
+ attrib_list);
+}
+
// ----------------------------------------------------------------------------
// Initialization
// ----------------------------------------------------------------------------
@@ -1402,15 +1421,10 @@
const char* eglQueryStringImpl(EGLDisplay dpy, EGLint name)
{
- // Generate an error quietly when client extensions (as defined by
- // EGL_EXT_client_extensions) are queried. We do not want to rely on
- // validate_display to generate the error as validate_display would log
- // the error, which can be misleading.
- //
- // If we want to support EGL_EXT_client_extensions later, we can return
- // the client extension string here instead.
- if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS)
- return setErrorQuiet(EGL_BAD_DISPLAY, (const char*)nullptr);
+ if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) {
+ // Return list of client extensions
+ return gClientExtensionString;
+ }
const egl_display_ptr dp = validate_display(dpy);
if (!dp) return (const char *) nullptr;
@@ -2434,6 +2448,7 @@
static const implementation_map_t sPlatformImplMap[] = {
// clang-format off
{ "eglGetDisplay", (EGLFuncPointer)&eglGetDisplayImpl },
+ { "eglGetPlatformDisplay", (EGLFuncPointer)&eglGetPlatformDisplayImpl },
{ "eglInitialize", (EGLFuncPointer)&eglInitializeImpl },
{ "eglTerminate", (EGLFuncPointer)&eglTerminateImpl },
{ "eglGetConfigs", (EGLFuncPointer)&eglGetConfigsImpl },
diff --git a/opengl/libs/platform_entries.in b/opengl/libs/platform_entries.in
index 6f087fd..95fa32d 100644
--- a/opengl/libs/platform_entries.in
+++ b/opengl/libs/platform_entries.in
@@ -1,4 +1,5 @@
EGL_ENTRY(EGLDisplay, eglGetDisplay, EGLNativeDisplayType)
+EGL_ENTRY(EGLDisplay, eglGetPlatformDisplay, EGLenum, EGLNativeDisplayType, const EGLAttrib*)
EGL_ENTRY(EGLBoolean, eglInitialize, EGLDisplay, EGLint*, EGLint*)
EGL_ENTRY(EGLBoolean, eglTerminate, EGLDisplay)
EGL_ENTRY(EGLBoolean, eglGetConfigs, EGLDisplay, EGLConfig*, EGLint, EGLint*)