summaryrefslogtreecommitdiff
path: root/chromium/ui/gl/gl_display.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/ui/gl/gl_display.cc')
-rw-r--r--chromium/ui/gl/gl_display.cc1020
1 files changed, 953 insertions, 67 deletions
diff --git a/chromium/ui/gl/gl_display.cc b/chromium/ui/gl/gl_display.cc
index 5c1ca88af38..d1761467570 100644
--- a/chromium/ui/gl/gl_display.cc
+++ b/chromium/ui/gl/gl_display.cc
@@ -3,153 +3,1039 @@
// found in the LICENSE file.
#include "ui/gl/gl_display.h"
+
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/containers/contains.h"
+#include "base/debug/crash_logging.h"
+#include "base/export_template.h"
+#include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "base/system/sys_info.h"
+#include "build/build_config.h"
+#include "ui/gl/angle_platform_impl.h"
+#include "ui/gl/egl_util.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context_egl.h"
+#include "ui/gl/gl_display_egl_util.h"
+#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_surface.h"
#if defined(USE_GLX)
#include "ui/gl/glx_util.h"
#endif // defined(USE_GLX)
+#if defined(USE_OZONE)
+#include "ui/ozone/buildflags.h"
+#endif // defined(USE_OZONE)
+
+#if BUILDFLAG(IS_ANDROID)
+#include <android/native_window_jni.h>
+#include "base/android/build_info.h"
+#endif
+
+// From ANGLE's egl/eglext.h.
+
+#ifndef EGL_ANGLE_platform_angle
+#define EGL_ANGLE_platform_angle 1
+#define EGL_PLATFORM_ANGLE_ANGLE 0x3202
+#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203
+#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3204
+#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3205
+#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3206
+#define EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE 0x3451
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE 0x3209
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_EGL_ANGLE 0x348E
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE 0x320A
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE 0x345E
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE 0x3487
+#define EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE 0x348F
+#endif /* EGL_ANGLE_platform_angle */
+
+#ifndef EGL_ANGLE_platform_angle_d3d
+#define EGL_ANGLE_platform_angle_d3d 1
+#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3207
+#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3208
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE 0x320B
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_REFERENCE_ANGLE 0x320C
+#endif /* EGL_ANGLE_platform_angle_d3d */
+
+#ifndef EGL_ANGLE_platform_angle_d3d_luid
+#define EGL_ANGLE_platform_angle_d3d_luid 1
+#define EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE 0x34A0
+#define EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE 0x34A1
+#endif /* EGL_ANGLE_platform_angle_d3d_luid */
+
+#ifndef EGL_ANGLE_platform_angle_d3d11on12
+#define EGL_ANGLE_platform_angle_d3d11on12 1
+#define EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE 0x3488
+#endif /* EGL_ANGLE_platform_angle_d3d11on12 */
+
+#ifndef EGL_ANGLE_platform_angle_opengl
+#define EGL_ANGLE_platform_angle_opengl 1
+#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x320D
+#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320E
+#endif /* EGL_ANGLE_platform_angle_opengl */
+
+#ifndef EGL_ANGLE_platform_angle_null
+#define EGL_ANGLE_platform_angle_null 1
+#define EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE 0x33AE
+#endif /* EGL_ANGLE_platform_angle_null */
+
+#ifndef EGL_ANGLE_platform_angle_vulkan
+#define EGL_ANGLE_platform_angle_vulkan 1
+#define EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE 0x3450
+#define EGL_PLATFORM_VULKAN_DISPLAY_MODE_HEADLESS_ANGLE 0x34A5
+#endif /* EGL_ANGLE_platform_angle_vulkan */
+
+#ifndef EGL_ANGLE_platform_angle_metal
+#define EGL_ANGLE_platform_angle_metal 1
+#define EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE 0x3489
+#endif /* EGL_ANGLE_platform_angle_metal */
+
+#ifndef EGL_ANGLE_x11_visual
+#define EGL_ANGLE_x11_visual 1
+#define EGL_X11_VISUAL_ID_ANGLE 0x33A3
+#endif /* EGL_ANGLE_x11_visual */
+
+#ifndef EGL_ANGLE_direct_composition
+#define EGL_ANGLE_direct_composition 1
+#define EGL_DIRECT_COMPOSITION_ANGLE 0x33A5
+#endif /* EGL_ANGLE_direct_composition */
+
+#ifndef EGL_ANGLE_display_robust_resource_initialization
+#define EGL_ANGLE_display_robust_resource_initialization 1
+#define EGL_DISPLAY_ROBUST_RESOURCE_INITIALIZATION_ANGLE 0x3453
+#endif /* EGL_ANGLE_display_robust_resource_initialization */
+
+#ifndef EGL_ANGLE_display_power_preference
+#define EGL_ANGLE_display_power_preference 1
+#define EGL_POWER_PREFERENCE_ANGLE 0x3482
+#define EGL_LOW_POWER_ANGLE 0x0001
+#define EGL_HIGH_POWER_ANGLE 0x0002
+#endif /* EGL_ANGLE_power_preference */
+
+#ifndef EGL_ANGLE_platform_angle_device_id
+#define EGL_ANGLE_platform_angle_device_id
+#define EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE 0x34D6
+#define EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE 0x34D7
+#endif /* EGL_ANGLE_platform_angle_device_id */
+
+// From ANGLE's egl/eglext.h.
+#ifndef EGL_ANGLE_feature_control
+#define EGL_ANGLE_feature_control 1
+#define EGL_FEATURE_NAME_ANGLE 0x3460
+#define EGL_FEATURE_CATEGORY_ANGLE 0x3461
+#define EGL_FEATURE_DESCRIPTION_ANGLE 0x3462
+#define EGL_FEATURE_BUG_ANGLE 0x3463
+#define EGL_FEATURE_STATUS_ANGLE 0x3464
+#define EGL_FEATURE_COUNT_ANGLE 0x3465
+#define EGL_FEATURE_OVERRIDES_ENABLED_ANGLE 0x3466
+#define EGL_FEATURE_OVERRIDES_DISABLED_ANGLE 0x3467
+#define EGL_FEATURE_ALL_DISABLED_ANGLE 0x3469
+#endif /* EGL_ANGLE_feature_control */
+
+using ui::GetLastEGLErrorString;
+
namespace gl {
-GLDisplay::GLDisplay(uint64_t system_device_id)
- : system_device_id_(system_device_id) {}
+namespace {
-GLDisplay::~GLDisplay() = default;
+std::vector<const char*> GetAttribArrayFromStringVector(
+ const std::vector<std::string>& strings) {
+ std::vector<const char*> attribs;
+ for (const std::string& item : strings) {
+ attribs.push_back(item.c_str());
+ }
+ attribs.push_back(nullptr);
+ return attribs;
+}
-#if defined(USE_EGL)
-GLDisplayEGL::GLDisplayEGL(uint64_t system_device_id)
- : GLDisplay(system_device_id) {
- display_ = EGL_NO_DISPLAY;
+std::vector<std::string> GetStringVectorFromCommandLine(
+ const base::CommandLine* command_line,
+ const char switch_name[]) {
+ std::string command_string = command_line->GetSwitchValueASCII(switch_name);
+ return base::SplitString(command_string, ", ;", base::TRIM_WHITESPACE,
+ base::SPLIT_WANT_NONEMPTY);
}
-GLDisplayEGL::~GLDisplayEGL() = default;
+EGLDisplay GetPlatformANGLEDisplay(
+ EGLNativeDisplayType display,
+ EGLenum platform_type,
+ const std::vector<std::string>& enabled_features,
+ const std::vector<std::string>& disabled_features,
+ const std::vector<EGLAttrib>& extra_display_attribs) {
+ std::vector<EGLAttrib> display_attribs(extra_display_attribs);
-EGLDisplay GLDisplayEGL::GetDisplay() {
- return display_;
-}
+ display_attribs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
+ display_attribs.push_back(static_cast<EGLAttrib>(platform_type));
-void GLDisplayEGL::SetDisplay(EGLDisplay display) {
- display_ = display;
+ if (platform_type == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE) {
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kUseAdapterLuid)) {
+ // If the LUID is specified, the format is <high part>,<low part>. Split
+ // and add them to the EGL_ANGLE_platform_angle_d3d_luid ext attributes.
+ std::string luid =
+ command_line->GetSwitchValueASCII(switches::kUseAdapterLuid);
+ size_t comma = luid.find(',');
+ if (comma != std::string::npos) {
+ int32_t high;
+ uint32_t low;
+ if (!base::StringToInt(luid.substr(0, comma), &high) ||
+ !base::StringToUint(luid.substr(comma + 1), &low))
+ return EGL_NO_DISPLAY;
+
+ display_attribs.push_back(EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE);
+ display_attribs.push_back(high);
+
+ display_attribs.push_back(EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE);
+ display_attribs.push_back(low);
+ }
+ }
+ }
+
+ GLDisplayEglUtil::GetInstance()->GetPlatformExtraDisplayAttribs(
+ platform_type, &display_attribs);
+
+ std::vector<const char*> enabled_features_attribs =
+ GetAttribArrayFromStringVector(enabled_features);
+ std::vector<const char*> disabled_features_attribs =
+ GetAttribArrayFromStringVector(disabled_features);
+ if (g_driver_egl.client_ext.b_EGL_ANGLE_feature_control) {
+ if (!enabled_features_attribs.empty()) {
+ display_attribs.push_back(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE);
+ display_attribs.push_back(
+ reinterpret_cast<EGLAttrib>(enabled_features_attribs.data()));
+ }
+ if (!disabled_features_attribs.empty()) {
+ display_attribs.push_back(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE);
+ display_attribs.push_back(
+ reinterpret_cast<EGLAttrib>(disabled_features_attribs.data()));
+ }
+ }
+ // TODO(dbehr) Add an attrib to Angle to pass EGL platform.
+
+ if (g_driver_egl.client_ext.b_EGL_ANGLE_display_power_preference) {
+ GpuPreference pref =
+ GLSurface::AdjustGpuPreference(GpuPreference::kDefault);
+ switch (pref) {
+ case GpuPreference::kDefault:
+ // Don't request any GPU, let ANGLE and the native driver decide.
+ break;
+ case GpuPreference::kLowPower:
+ display_attribs.push_back(EGL_POWER_PREFERENCE_ANGLE);
+ display_attribs.push_back(EGL_LOW_POWER_ANGLE);
+ break;
+ case GpuPreference::kHighPerformance:
+ display_attribs.push_back(EGL_POWER_PREFERENCE_ANGLE);
+ display_attribs.push_back(EGL_HIGH_POWER_ANGLE);
+ break;
+ default:
+ NOTREACHED();
+ }
+ }
+
+ display_attribs.push_back(EGL_NONE);
+
+ // This is an EGL 1.5 function that we know ANGLE supports. It's used to pass
+ // EGLAttribs (pointers) instead of EGLints into the display
+ return eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE,
+ reinterpret_cast<void*>(display),
+ &display_attribs[0]);
}
-EGLDisplay GLDisplayEGL::GetHardwareDisplay() {
- return GetDisplay();
+EGLDisplay GetDisplayFromType(
+ DisplayType display_type,
+ EGLDisplayPlatform native_display,
+ const std::vector<std::string>& enabled_angle_features,
+ const std::vector<std::string>& disabled_angle_features,
+ bool disable_all_angle_features,
+ uint64_t system_device_id) {
+ std::vector<EGLAttrib> extra_display_attribs;
+ if (disable_all_angle_features) {
+ extra_display_attribs.push_back(EGL_FEATURE_ALL_DISABLED_ANGLE);
+ extra_display_attribs.push_back(EGL_TRUE);
+ }
+ if (system_device_id != 0 &&
+ g_driver_egl.client_ext.b_EGL_ANGLE_platform_angle_device_id) {
+ uint32_t low_part = system_device_id & 0xffffffff;
+ extra_display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE);
+ extra_display_attribs.push_back(low_part);
+
+ uint32_t high_part = (system_device_id >> 32) & 0xffffffff;
+ extra_display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE);
+ extra_display_attribs.push_back(high_part);
+ }
+ EGLNativeDisplayType display = native_display.GetDisplay();
+ switch (display_type) {
+ case DEFAULT:
+ case SWIFT_SHADER: {
+ if (native_display.GetPlatform() != 0) {
+ return eglGetPlatformDisplay(native_display.GetPlatform(),
+ reinterpret_cast<void*>(display), nullptr);
+ }
+ return eglGetDisplay(display);
+ }
+ case ANGLE_D3D9:
+ return GetPlatformANGLEDisplay(
+ display, EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE, enabled_angle_features,
+ disabled_angle_features, extra_display_attribs);
+ case ANGLE_D3D11:
+ return GetPlatformANGLEDisplay(
+ display, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, enabled_angle_features,
+ disabled_angle_features, extra_display_attribs);
+ case ANGLE_D3D11_NULL:
+ extra_display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
+ extra_display_attribs.push_back(
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE);
+ return GetPlatformANGLEDisplay(
+ display, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, enabled_angle_features,
+ disabled_angle_features, extra_display_attribs);
+ case ANGLE_OPENGL:
+ return GetPlatformANGLEDisplay(
+ display, EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, enabled_angle_features,
+ disabled_angle_features, extra_display_attribs);
+ case ANGLE_OPENGL_EGL:
+ extra_display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
+ extra_display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_EGL_ANGLE);
+ return GetPlatformANGLEDisplay(
+ display, EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, enabled_angle_features,
+ disabled_angle_features, extra_display_attribs);
+ case ANGLE_OPENGL_NULL:
+ extra_display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
+ extra_display_attribs.push_back(
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE);
+ return GetPlatformANGLEDisplay(
+ display, EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, enabled_angle_features,
+ disabled_angle_features, extra_display_attribs);
+ case ANGLE_OPENGLES:
+ return GetPlatformANGLEDisplay(
+ display, EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE,
+ enabled_angle_features, disabled_angle_features,
+ extra_display_attribs);
+ case ANGLE_OPENGLES_EGL:
+ extra_display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
+ extra_display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_EGL_ANGLE);
+ return GetPlatformANGLEDisplay(
+ display, EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE,
+ enabled_angle_features, disabled_angle_features,
+ extra_display_attribs);
+ case ANGLE_OPENGLES_NULL:
+ extra_display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
+ extra_display_attribs.push_back(
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE);
+ return GetPlatformANGLEDisplay(
+ display, EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE,
+ enabled_angle_features, disabled_angle_features,
+ extra_display_attribs);
+ case ANGLE_NULL:
+ return GetPlatformANGLEDisplay(
+ display, EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE, enabled_angle_features,
+ disabled_angle_features, extra_display_attribs);
+ case ANGLE_VULKAN:
+ return GetPlatformANGLEDisplay(
+ display, EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE, enabled_angle_features,
+ disabled_angle_features, extra_display_attribs);
+ case ANGLE_VULKAN_NULL:
+ extra_display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
+ extra_display_attribs.push_back(
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE);
+ return GetPlatformANGLEDisplay(
+ display, EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE, enabled_angle_features,
+ disabled_angle_features, extra_display_attribs);
+ case ANGLE_D3D11on12:
+ extra_display_attribs.push_back(EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE);
+ extra_display_attribs.push_back(EGL_TRUE);
+ return GetPlatformANGLEDisplay(
+ display, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, enabled_angle_features,
+ disabled_angle_features, extra_display_attribs);
+ case ANGLE_SWIFTSHADER:
+ extra_display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
+ extra_display_attribs.push_back(
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE);
+#if defined(USE_OZONE)
+#if BUILDFLAG(IS_CHROMEOS) && BUILDFLAG(OZONE_PLATFORM_X11)
+ extra_display_attribs.push_back(
+ EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE);
+ extra_display_attribs.push_back(
+ EGL_PLATFORM_VULKAN_DISPLAY_MODE_HEADLESS_ANGLE);
+#endif // BUILDFLAG(OZONE_PLATFORM_X11)
+#endif // defined(USE_OZONE)
+ return GetPlatformANGLEDisplay(
+ display, EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE, enabled_angle_features,
+ disabled_angle_features, extra_display_attribs);
+ case ANGLE_METAL:
+ return GetPlatformANGLEDisplay(
+ display, EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE, enabled_angle_features,
+ disabled_angle_features, extra_display_attribs);
+ case ANGLE_METAL_NULL:
+ extra_display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
+ extra_display_attribs.push_back(
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE);
+ return GetPlatformANGLEDisplay(
+ display, EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE, enabled_angle_features,
+ disabled_angle_features, extra_display_attribs);
+ default:
+ NOTREACHED();
+ return EGL_NO_DISPLAY;
+ }
}
-EGLNativeDisplayType GLDisplayEGL::GetNativeDisplay() {
- return native_display.GetDisplay();
+ANGLEImplementation GetANGLEImplementationFromDisplayType(
+ DisplayType display_type) {
+ switch (display_type) {
+ case ANGLE_D3D9:
+ return ANGLEImplementation::kD3D9;
+ case ANGLE_D3D11:
+ case ANGLE_D3D11_NULL:
+ case ANGLE_D3D11on12:
+ return ANGLEImplementation::kD3D11;
+ case ANGLE_OPENGL:
+ case ANGLE_OPENGL_NULL:
+ return ANGLEImplementation::kOpenGL;
+ case ANGLE_OPENGLES:
+ case ANGLE_OPENGLES_NULL:
+ return ANGLEImplementation::kOpenGLES;
+ case ANGLE_NULL:
+ return ANGLEImplementation::kNull;
+ case ANGLE_VULKAN:
+ case ANGLE_VULKAN_NULL:
+ return ANGLEImplementation::kVulkan;
+ case ANGLE_SWIFTSHADER:
+ return ANGLEImplementation::kSwiftShader;
+ case ANGLE_METAL:
+ case ANGLE_METAL_NULL:
+ return ANGLEImplementation::kMetal;
+ default:
+ return ANGLEImplementation::kNone;
+ }
}
-DisplayType GLDisplayEGL::GetDisplayType() {
- return display_type;
+const char* DisplayTypeString(DisplayType display_type) {
+ switch (display_type) {
+ case DEFAULT:
+ return "Default";
+ case SWIFT_SHADER:
+ return "SwiftShader";
+ case ANGLE_D3D9:
+ return "D3D9";
+ case ANGLE_D3D11:
+ return "D3D11";
+ case ANGLE_D3D11_NULL:
+ return "D3D11Null";
+ case ANGLE_OPENGL:
+ return "OpenGL";
+ case ANGLE_OPENGL_NULL:
+ return "OpenGLNull";
+ case ANGLE_OPENGLES:
+ return "OpenGLES";
+ case ANGLE_OPENGLES_NULL:
+ return "OpenGLESNull";
+ case ANGLE_NULL:
+ return "Null";
+ case ANGLE_VULKAN:
+ return "Vulkan";
+ case ANGLE_VULKAN_NULL:
+ return "VulkanNull";
+ case ANGLE_D3D11on12:
+ return "D3D11on12";
+ case ANGLE_SWIFTSHADER:
+ return "SwANGLE";
+ case ANGLE_OPENGL_EGL:
+ return "OpenGLEGL";
+ case ANGLE_OPENGLES_EGL:
+ return "OpenGLESEGL";
+ case ANGLE_METAL:
+ return "Metal";
+ case ANGLE_METAL_NULL:
+ return "MetalNull";
+ default:
+ NOTREACHED();
+ return "Err";
+ }
}
-bool GLDisplayEGL::HasEGLClientExtension(const char* name) {
- if (!egl_client_extensions)
- return false;
- return GLSurface::ExtensionsContain(egl_client_extensions, name);
+void AddInitDisplay(std::vector<DisplayType>* init_displays,
+ DisplayType display_type) {
+ // Make sure to not add the same display type twice.
+ if (!base::Contains(*init_displays, display_type))
+ init_displays->push_back(display_type);
}
-bool GLDisplayEGL::HasEGLExtension(const char* name) {
- return GLSurface::ExtensionsContain(egl_extensions, name);
+const char* GetDebugMessageTypeString(EGLint source) {
+ switch (source) {
+ case EGL_DEBUG_MSG_CRITICAL_KHR:
+ return "Critical";
+ case EGL_DEBUG_MSG_ERROR_KHR:
+ return "Error";
+ case EGL_DEBUG_MSG_WARN_KHR:
+ return "Warning";
+ case EGL_DEBUG_MSG_INFO_KHR:
+ return "Info";
+ default:
+ return "UNKNOWN";
+ }
}
-bool GLDisplayEGL::IsCreateContextRobustnessSupported() {
- return egl_create_context_robustness_supported;
+void EGLAPIENTRY LogEGLDebugMessage(EGLenum error,
+ const char* command,
+ EGLint message_type,
+ EGLLabelKHR thread_label,
+ EGLLabelKHR object_label,
+ const char* message) {
+ std::string formatted_message = std::string("EGL Driver message (") +
+ GetDebugMessageTypeString(message_type) +
+ ") " + command + ": " + message;
+
+ // Assume that all labels that have been set are strings
+ if (thread_label) {
+ formatted_message += " thread: ";
+ formatted_message += static_cast<const char*>(thread_label);
+ }
+ if (object_label) {
+ formatted_message += " object: ";
+ formatted_message += static_cast<const char*>(object_label);
+ }
+
+ if (message_type == EGL_DEBUG_MSG_CRITICAL_KHR ||
+ message_type == EGL_DEBUG_MSG_ERROR_KHR) {
+ LOG(ERROR) << formatted_message;
+ } else {
+ DVLOG(1) << formatted_message;
+ }
}
-bool GLDisplayEGL::IsRobustnessVideoMemoryPurgeSupported() {
- return egl_robustness_video_memory_purge_supported;
+void GetEGLInitDisplays(bool supports_angle_d3d,
+ bool supports_angle_opengl,
+ bool supports_angle_null,
+ bool supports_angle_vulkan,
+ bool supports_angle_swiftshader,
+ bool supports_angle_egl,
+ bool supports_angle_metal,
+ const base::CommandLine* command_line,
+ std::vector<DisplayType>* init_displays) {
+ // If we're already requesting software GL, make sure we don't fallback to the
+ // GPU
+ bool forceSoftwareGL = IsSoftwareGLImplementation(GetGLImplementationParts());
+
+ std::string requested_renderer =
+ forceSoftwareGL ? kANGLEImplementationSwiftShaderName
+ : command_line->GetSwitchValueASCII(switches::kUseANGLE);
+
+ bool use_angle_default =
+ !forceSoftwareGL &&
+ (!command_line->HasSwitch(switches::kUseANGLE) ||
+ requested_renderer == kANGLEImplementationDefaultName);
+
+ if (supports_angle_null &&
+ requested_renderer == kANGLEImplementationNullName) {
+ AddInitDisplay(init_displays, ANGLE_NULL);
+ return;
+ }
+
+ // If no display has been explicitly requested and the DefaultANGLEOpenGL
+ // experiment is enabled, try creating OpenGL displays first.
+ // TODO(oetuaho@nvidia.com): Only enable this path on specific GPUs with a
+ // blocklist entry. http://crbug.com/693090
+ if (supports_angle_opengl && use_angle_default &&
+ base::FeatureList::IsEnabled(features::kDefaultANGLEOpenGL)) {
+ AddInitDisplay(init_displays, ANGLE_OPENGL);
+ AddInitDisplay(init_displays, ANGLE_OPENGLES);
+ }
+
+ if (supports_angle_metal && use_angle_default &&
+ base::FeatureList::IsEnabled(features::kDefaultANGLEMetal)) {
+ AddInitDisplay(init_displays, ANGLE_METAL);
+ }
+
+ if (supports_angle_vulkan && use_angle_default &&
+ features::IsDefaultANGLEVulkan()) {
+ AddInitDisplay(init_displays, ANGLE_VULKAN);
+ }
+
+ if (supports_angle_d3d) {
+ if (use_angle_default) {
+ // Default mode for ANGLE - try D3D11, else try D3D9
+ if (!command_line->HasSwitch(switches::kDisableD3D11)) {
+ AddInitDisplay(init_displays, ANGLE_D3D11);
+ }
+ AddInitDisplay(init_displays, ANGLE_D3D9);
+ } else {
+ if (requested_renderer == kANGLEImplementationD3D11Name) {
+ AddInitDisplay(init_displays, ANGLE_D3D11);
+ } else if (requested_renderer == kANGLEImplementationD3D9Name) {
+ AddInitDisplay(init_displays, ANGLE_D3D9);
+ } else if (requested_renderer == kANGLEImplementationD3D11NULLName) {
+ AddInitDisplay(init_displays, ANGLE_D3D11_NULL);
+ } else if (requested_renderer == kANGLEImplementationD3D11on12Name) {
+ AddInitDisplay(init_displays, ANGLE_D3D11on12);
+ }
+ }
+ }
+
+ if (supports_angle_opengl) {
+ if (use_angle_default && !supports_angle_d3d) {
+#if BUILDFLAG(IS_ANDROID)
+ // Don't request desktopGL on android
+ AddInitDisplay(init_displays, ANGLE_OPENGLES);
+#else
+ AddInitDisplay(init_displays, ANGLE_OPENGL);
+ AddInitDisplay(init_displays, ANGLE_OPENGLES);
+#endif // BUILDFLAG(IS_ANDROID)
+ } else {
+ if (requested_renderer == kANGLEImplementationOpenGLName) {
+ AddInitDisplay(init_displays, ANGLE_OPENGL);
+ } else if (requested_renderer == kANGLEImplementationOpenGLESName) {
+ AddInitDisplay(init_displays, ANGLE_OPENGLES);
+ } else if (requested_renderer == kANGLEImplementationOpenGLNULLName) {
+ AddInitDisplay(init_displays, ANGLE_OPENGL_NULL);
+ } else if (requested_renderer == kANGLEImplementationOpenGLESNULLName) {
+ AddInitDisplay(init_displays, ANGLE_OPENGLES_NULL);
+ } else if (requested_renderer == kANGLEImplementationOpenGLEGLName &&
+ supports_angle_egl) {
+ AddInitDisplay(init_displays, ANGLE_OPENGL_EGL);
+ } else if (requested_renderer == kANGLEImplementationOpenGLESEGLName &&
+ supports_angle_egl) {
+ AddInitDisplay(init_displays, ANGLE_OPENGLES_EGL);
+ }
+ }
+ }
+
+ if (supports_angle_vulkan) {
+ if (use_angle_default) {
+ if (!supports_angle_d3d && !supports_angle_opengl) {
+ AddInitDisplay(init_displays, ANGLE_VULKAN);
+ }
+ } else if (requested_renderer == kANGLEImplementationVulkanName) {
+ AddInitDisplay(init_displays, ANGLE_VULKAN);
+ } else if (requested_renderer == kANGLEImplementationVulkanNULLName) {
+ AddInitDisplay(init_displays, ANGLE_VULKAN_NULL);
+ }
+ }
+
+ if (supports_angle_swiftshader) {
+ if (requested_renderer == kANGLEImplementationSwiftShaderName ||
+ requested_renderer == kANGLEImplementationSwiftShaderForWebGLName) {
+ AddInitDisplay(init_displays, ANGLE_SWIFTSHADER);
+ }
+ }
+
+ if (supports_angle_metal) {
+ if (use_angle_default) {
+ if (!supports_angle_opengl) {
+ AddInitDisplay(init_displays, ANGLE_METAL);
+ }
+ } else if (requested_renderer == kANGLEImplementationMetalName) {
+ AddInitDisplay(init_displays, ANGLE_METAL);
+ } else if (requested_renderer == kANGLEImplementationMetalNULLName) {
+ AddInitDisplay(init_displays, ANGLE_METAL_NULL);
+ }
+ }
+
+ // If no displays are available due to missing angle extensions or invalid
+ // flags, request the default display.
+ if (init_displays->empty()) {
+ init_displays->push_back(DEFAULT);
+ }
}
-bool GLDisplayEGL::IsCreateContextBindGeneratesResourceSupported() {
- return egl_create_context_bind_generates_resource_supported;
+} // namespace
+
+void GetEGLInitDisplaysForTesting(bool supports_angle_d3d,
+ bool supports_angle_opengl,
+ bool supports_angle_null,
+ bool supports_angle_vulkan,
+ bool supports_angle_swiftshader,
+ bool supports_angle_egl,
+ bool supports_angle_metal,
+ const base::CommandLine* command_line,
+ std::vector<DisplayType>* init_displays) {
+ GetEGLInitDisplays(supports_angle_d3d, supports_angle_opengl,
+ supports_angle_null, supports_angle_vulkan,
+ supports_angle_swiftshader, supports_angle_egl,
+ supports_angle_metal, command_line, init_displays);
}
-bool GLDisplayEGL::IsCreateContextWebGLCompatabilitySupported() {
- return egl_create_context_webgl_compatability_supported;
+GLDisplay::GLDisplay(uint64_t system_device_id, DisplayPlatform type)
+ : system_device_id_(system_device_id), type_(type) {}
+
+GLDisplay::~GLDisplay() = default;
+
+template <typename GLDisplayPlatform>
+GLDisplayPlatform* GLDisplay::GetAs() {
+ bool type_checked = false;
+ switch (type_) {
+ case NONE:
+ NOTREACHED();
+ break;
+
+ case EGL:
+#if defined(USE_EGL)
+ type_checked = std::is_same<GLDisplayPlatform, GLDisplayEGL>::value;
+#endif // defined(USE_EGL)
+ break;
+
+ case X11:
+#if defined(USE_GLX)
+ type_checked = std::is_same<GLDisplayPlatform, GLDisplayX11>::value;
+#endif // defined(USE_GLX)
+ break;
+ }
+ if (type_checked)
+ return static_cast<GLDisplayPlatform*>(this);
+
+ return nullptr;
}
-bool GLDisplayEGL::IsEGLSurfacelessContextSupported() {
- return egl_surfaceless_context_supported;
+#if defined(USE_EGL)
+template EXPORT_TEMPLATE_DEFINE(GL_EXPORT)
+ GLDisplayEGL* GLDisplay::GetAs<GLDisplayEGL>();
+#endif // defined(USE_EGL)
+
+#if defined(USE_GLX)
+template EXPORT_TEMPLATE_DEFINE(GL_EXPORT)
+ GLDisplayX11* GLDisplay::GetAs<GLDisplayX11>();
+#endif // defined(USE_GLX)
+
+#if defined(USE_EGL)
+GLDisplayEGL::EGLGpuSwitchingObserver::EGLGpuSwitchingObserver(
+ EGLDisplay display)
+ : display_(display) {
+ DCHECK(display != EGL_NO_DISPLAY);
}
-bool GLDisplayEGL::IsEGLContextPrioritySupported() {
- return egl_context_priority_supported;
+void GLDisplayEGL::EGLGpuSwitchingObserver::OnGpuSwitched(
+ GpuPreference active_gpu_heuristic) {
+ eglHandleGPUSwitchANGLE(display_);
}
-bool GLDisplayEGL::IsEGLNoConfigContextSupported() {
- return egl_no_config_context_supported;
+GLDisplayEGL::GLDisplayEGL(uint64_t system_device_id)
+ : GLDisplay(system_device_id, EGL), display_(EGL_NO_DISPLAY) {
+ ext = std::make_unique<DisplayExtensionsEGL>();
}
-bool GLDisplayEGL::IsRobustResourceInitSupported() {
- return egl_robust_resource_init_supported;
+GLDisplayEGL::~GLDisplayEGL() = default;
+
+EGLDisplay GLDisplayEGL::GetDisplay() {
+ return display_;
}
-bool GLDisplayEGL::IsDisplayTextureShareGroupSupported() {
- return egl_display_texture_share_group_supported;
+void GLDisplayEGL::Shutdown() {
+ if (display_ == EGL_NO_DISPLAY)
+ return;
+
+ if (gpu_switching_observer_.get()) {
+ ui::GpuSwitchingManager::GetInstance()->RemoveObserver(
+ gpu_switching_observer_.get());
+ gpu_switching_observer_.reset();
+ }
+
+ angle::ResetPlatform(display_);
+ DCHECK(g_driver_egl.fn.eglTerminateFn);
+ eglTerminate(display_);
+
+ display_ = EGL_NO_DISPLAY;
+ egl_surfaceless_context_supported_ = false;
+ egl_context_priority_supported_ = false;
+ egl_android_native_fence_sync_supported_ = false;
}
-bool GLDisplayEGL::IsDisplaySemaphoreShareGroupSupported() {
- return egl_display_semaphore_share_group_supported;
+bool GLDisplayEGL::IsInitialized() {
+ return display_ != EGL_NO_DISPLAY;
}
-bool GLDisplayEGL::IsCreateContextClientArraysSupported() {
- return egl_create_context_client_arrays_supported;
+void GLDisplayEGL::SetDisplay(EGLDisplay display) {
+ display_ = display;
}
-bool GLDisplayEGL::IsAndroidNativeFenceSyncSupported() {
- return egl_android_native_fence_sync_supported;
+EGLDisplayPlatform GLDisplayEGL::GetNativeDisplay() const {
+ return native_display_;
}
-bool GLDisplayEGL::IsPixelFormatFloatSupported() {
- return egl_ext_pixel_format_float_supported;
+DisplayType GLDisplayEGL::GetDisplayType() const {
+ return display_type_;
}
-bool GLDisplayEGL::IsANGLEFeatureControlSupported() {
- return egl_angle_feature_control_supported;
+// static
+GLDisplayEGL* GLDisplayEGL::GetDisplayForCurrentContext() {
+ GLContext* context = GLContext::GetCurrent();
+ return context ? context->GetGLDisplayEGL() : nullptr;
}
-bool GLDisplayEGL::IsANGLEPowerPreferenceSupported() {
- return egl_angle_power_preference_supported;
+bool GLDisplayEGL::IsEGLSurfacelessContextSupported() {
+ return egl_surfaceless_context_supported_;
}
-bool GLDisplayEGL::IsANGLEDisplayPowerPreferenceSupported() {
- return egl_angle_display_power_preference_supported;
+bool GLDisplayEGL::IsEGLContextPrioritySupported() {
+ return egl_context_priority_supported_;
}
-bool GLDisplayEGL::IsANGLEPlatformANGLEDeviceIdSupported() {
- return egl_angle_platform_angle_device_id_supported;
+bool GLDisplayEGL::IsAndroidNativeFenceSyncSupported() {
+ return egl_android_native_fence_sync_supported_;
}
bool GLDisplayEGL::IsANGLEExternalContextAndSurfaceSupported() {
- return egl_angle_external_context_and_surface_supported;
+ return this->ext->b_EGL_ANGLE_external_context_and_surface;
}
-bool GLDisplayEGL::IsANGLEContextVirtualizationSupported() {
- return egl_angle_context_virtualization_supported;
+bool GLDisplayEGL::Initialize(EGLDisplayPlatform native_display) {
+ if (display_ != EGL_NO_DISPLAY)
+ return true;
+
+ if (!InitializeDisplay(native_display))
+ return false;
+ InitializeCommon();
+
+ if (ext->b_EGL_ANGLE_power_preference) {
+ gpu_switching_observer_ =
+ std::make_unique<EGLGpuSwitchingObserver>(display_);
+ ui::GpuSwitchingManager::GetInstance()->AddObserver(
+ gpu_switching_observer_.get());
+ }
+ return true;
}
-bool GLDisplayEGL::IsANGLEVulkanImageSupported() {
- return egl_angle_vulkan_image_supported;
+void GLDisplayEGL::InitializeForTesting() {
+ display_ = eglGetCurrentDisplay();
+ ext->InitializeExtensionSettings(display_);
+ InitializeCommon();
}
-bool GLDisplayEGL::IsEGLQueryDeviceSupported() {
- return egl_ext_query_device_supported;
+bool GLDisplayEGL::InitializeExtensionSettings() {
+ if (display_ == EGL_NO_DISPLAY)
+ return false;
+ ext->UpdateConditionalExtensionSettings(display_);
+ return true;
}
+// InitializeDisplay is necessary because the static binding code
+// needs a full Display init before it can query the Display extensions.
+bool GLDisplayEGL::InitializeDisplay(EGLDisplayPlatform native_display) {
+ if (display_ != EGL_NO_DISPLAY)
+ return true;
+
+ native_display_ = native_display;
+
+ bool supports_egl_debug = g_driver_egl.client_ext.b_EGL_KHR_debug;
+ if (supports_egl_debug) {
+ EGLAttrib controls[] = {
+ EGL_DEBUG_MSG_CRITICAL_KHR,
+ EGL_TRUE,
+ EGL_DEBUG_MSG_ERROR_KHR,
+ EGL_TRUE,
+ EGL_DEBUG_MSG_WARN_KHR,
+ EGL_TRUE,
+ EGL_DEBUG_MSG_INFO_KHR,
+ EGL_TRUE,
+ EGL_NONE,
+ EGL_NONE,
+ };
+
+ eglDebugMessageControlKHR(&LogEGLDebugMessage, controls);
+ }
+
+ bool supports_angle_d3d = false;
+ bool supports_angle_opengl = false;
+ bool supports_angle_null = false;
+ bool supports_angle_vulkan = false;
+ bool supports_angle_swiftshader = false;
+ bool supports_angle_egl = false;
+ bool supports_angle_metal = false;
+ // Check for availability of ANGLE extensions.
+ if (g_driver_egl.client_ext.b_EGL_ANGLE_platform_angle) {
+ supports_angle_d3d = g_driver_egl.client_ext.b_EGL_ANGLE_platform_angle_d3d;
+ supports_angle_opengl =
+ g_driver_egl.client_ext.b_EGL_ANGLE_platform_angle_opengl;
+ supports_angle_null =
+ g_driver_egl.client_ext.b_EGL_ANGLE_platform_angle_null;
+ supports_angle_vulkan =
+ g_driver_egl.client_ext.b_EGL_ANGLE_platform_angle_vulkan;
+ supports_angle_swiftshader =
+ g_driver_egl.client_ext
+ .b_EGL_ANGLE_platform_angle_device_type_swiftshader;
+ supports_angle_egl = g_driver_egl.client_ext
+ .b_EGL_ANGLE_platform_angle_device_type_egl_angle;
+ supports_angle_metal =
+ g_driver_egl.client_ext.b_EGL_ANGLE_platform_angle_metal;
+ }
+
+ bool supports_angle = supports_angle_d3d || supports_angle_opengl ||
+ supports_angle_null || supports_angle_vulkan ||
+ supports_angle_swiftshader || supports_angle_metal;
+
+ std::vector<DisplayType> init_displays;
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ GetEGLInitDisplays(supports_angle_d3d, supports_angle_opengl,
+ supports_angle_null, supports_angle_vulkan,
+ supports_angle_swiftshader, supports_angle_egl,
+ supports_angle_metal, command_line, &init_displays);
+
+ std::vector<std::string> enabled_angle_features =
+ GetStringVectorFromCommandLine(command_line,
+ switches::kEnableANGLEFeatures);
+ std::vector<std::string> disabled_angle_features =
+ GetStringVectorFromCommandLine(command_line,
+ switches::kDisableANGLEFeatures);
+
+ bool disable_all_angle_features =
+ command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds);
+
+ for (size_t disp_index = 0; disp_index < init_displays.size(); ++disp_index) {
+ DisplayType display_type = init_displays[disp_index];
+ EGLDisplay display = GetDisplayFromType(
+ display_type, native_display, enabled_angle_features,
+ disabled_angle_features, disable_all_angle_features, system_device_id_);
+ if (display == EGL_NO_DISPLAY) {
+ LOG(ERROR) << "EGL display query failed with error "
+ << GetLastEGLErrorString();
+ }
+
+ // Init ANGLE platform now that we have the global display.
+ if (supports_angle) {
+ if (!angle::InitializePlatform(display)) {
+ LOG(ERROR) << "ANGLE Platform initialization failed.";
+ }
+
+ SetANGLEImplementation(
+ GetANGLEImplementationFromDisplayType(display_type));
+ }
+
+ // The platform may need to unset its platform specific display env in case
+ // of vulkan if the platform doesn't support Vulkan surface.
+ absl::optional<base::ScopedEnvironmentVariableOverride> unset_display;
+ if (display_type == ANGLE_VULKAN) {
+ unset_display = GLDisplayEglUtil::GetInstance()
+ ->MaybeGetScopedDisplayUnsetForVulkan();
+ }
+
+ if (!eglInitialize(display, nullptr, nullptr)) {
+ bool is_last = disp_index == init_displays.size() - 1;
+
+ LOG(ERROR) << "eglInitialize " << DisplayTypeString(display_type)
+ << " failed with error " << GetLastEGLErrorString()
+ << (is_last ? "" : ", trying next display type");
+ continue;
+ }
+
+ std::ostringstream display_type_string;
+ auto gl_implementation = GetGLImplementationParts();
+ display_type_string << GetGLImplementationGLName(gl_implementation);
+ if (gl_implementation.gl == kGLImplementationEGLANGLE) {
+ display_type_string << ":" << DisplayTypeString(display_type);
+ }
+
+ static auto* egl_display_type_key = base::debug::AllocateCrashKeyString(
+ "egl-display-type", base::debug::CrashKeySize::Size32);
+ base::debug::SetCrashKeyString(egl_display_type_key,
+ display_type_string.str());
+
+ UMA_HISTOGRAM_ENUMERATION("GPU.EGLDisplayType", display_type,
+ DISPLAY_TYPE_MAX);
+ display_ = display;
+ display_type_ = display_type;
+ ext->InitializeExtensionSettings(display);
+ return true;
+ }
+
+ return false;
+}
+
+void GLDisplayEGL::InitializeCommon() {
+ // According to https://source.android.com/compatibility/android-cdd.html the
+ // EGL_IMG_context_priority extension is mandatory for Virtual Reality High
+ // Performance support, but due to a bug in Android Nougat the extension
+ // isn't being reported even when it's present. As a fallback, check if other
+ // related extensions that were added for VR support are present, and assume
+ // that this implies context priority is also supported. See also:
+ // https://github.com/googlevr/gvr-android-sdk/issues/330
+ egl_context_priority_supported_ =
+ ext->b_EGL_IMG_context_priority ||
+ (ext->b_EGL_ANDROID_front_buffer_auto_refresh &&
+ ext->b_EGL_ANDROID_create_native_client_buffer);
+
+ // Check if SurfacelessEGL is supported.
+ egl_surfaceless_context_supported_ = ext->b_EGL_KHR_surfaceless_context;
+
+ // TODO(oetuaho@nvidia.com): Surfaceless is disabled on Android as a temporary
+ // workaround, since code written for Android WebView takes different paths
+ // based on whether GL surface objects have underlying EGL surface handles,
+ // conflicting with the use of surfaceless. ANGLE can still expose surfacelss
+ // because it is emulated with pbuffers if native support is not present. See
+ // https://crbug.com/382349.
+
+#if BUILDFLAG(IS_ANDROID)
+ // Use the WebGL compatibility extension for detecting ANGLE. ANGLE always
+ // exposes it.
+ bool is_angle = ext->b_EGL_ANGLE_create_context_webgl_compatibility;
+ if (!is_angle) {
+ egl_surfaceless_context_supported_ = false;
+ }
+#endif // BUILDFLAG(IS_ANDROID)
+
+ if (egl_surfaceless_context_supported_) {
+ // EGL_KHR_surfaceless_context is supported but ensure
+ // GL_OES_surfaceless_context is also supported. We need a current context
+ // to query for supported GL extensions.
+ scoped_refptr<GLSurface> surface =
+ new SurfacelessEGL(this, gfx::Size(1, 1));
+ scoped_refptr<GLContext> context = InitializeGLContext(
+ new GLContextEGL(nullptr), surface.get(), GLContextAttribs());
+ if (!context || !context->MakeCurrent(surface.get()))
+ egl_surfaceless_context_supported_ = false;
+
+ // Ensure context supports GL_OES_surfaceless_context.
+ if (egl_surfaceless_context_supported_) {
+ egl_surfaceless_context_supported_ =
+ context->HasExtension("GL_OES_surfaceless_context");
+ context->ReleaseCurrent(surface.get());
+ }
+ }
+
+ // The native fence sync extension is a bit complicated. It's reported as
+ // present for ChromeOS, but Android currently doesn't report this extension
+ // even when it's present, and older devices and Android emulator may export
+ // a useless wrapper function. See crbug.com/775707 for details. In short, if
+ // the symbol is present and we're on Android N or newer and we are not on
+ // Android emulator, assume that it's usable even if the extension wasn't
+ // reported. TODO(https://crbug.com/1086781): Once this is fixed at the
+ // Android level, update the heuristic to trust the reported extension from
+ // that version onward.
+ egl_android_native_fence_sync_supported_ =
+ ext->b_EGL_ANDROID_native_fence_sync;
+#if BUILDFLAG(IS_ANDROID)
+ if (!egl_android_native_fence_sync_supported_ &&
+ base::android::BuildInfo::GetInstance()->sdk_int() >=
+ base::android::SDK_VERSION_NOUGAT &&
+ g_driver_egl.fn.eglDupNativeFenceFDANDROIDFn &&
+ base::SysInfo::GetAndroidHardwareEGL() != "swiftshader" &&
+ base::SysInfo::GetAndroidHardwareEGL() != "emulation") {
+ egl_android_native_fence_sync_supported_ = true;
+ }
+#endif // BUILDFLAG(IS_ANDROID)
+}
#endif // defined(USE_EGL)
#if defined(USE_GLX)
GLDisplayX11::GLDisplayX11(uint64_t system_device_id)
- : GLDisplay(system_device_id) {}
+ : GLDisplay(system_device_id, X11) {}
GLDisplayX11::~GLDisplayX11() = default;
void* GLDisplayX11::GetDisplay() {
return x11::Connection::Get()->GetXlibDisplay();
}
+
+void GLDisplayX11::Shutdown() {}
+
+bool GLDisplayX11::IsInitialized() {
+ return true;
+}
#endif // defined(USE_GLX)
} // namespace gl