1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/gl/gl_surface_egl.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <map>
11 #include <memory>
12 #include <vector>
13
14 #include "base/command_line.h"
15 #include "base/lazy_instance.h"
16 #include "base/logging.h"
17 #include "base/macros.h"
18 #include "base/metrics/histogram_macros.h"
19 #include "base/stl_util.h"
20 #include "base/strings/string_number_conversions.h"
21 #include "base/strings/string_split.h"
22 #include "base/system/sys_info.h"
23 #include "base/trace_event/trace_event.h"
24 #include "build/build_config.h"
25 #include "ui/events/platform/platform_event_dispatcher.h"
26 #include "ui/gfx/geometry/rect.h"
27 #include "ui/gfx/gpu_fence.h"
28 #include "ui/gl/angle_platform_impl.h"
29 #include "ui/gl/egl_util.h"
30 #include "ui/gl/gl_context.h"
31 #include "ui/gl/gl_context_egl.h"
32 #include "ui/gl/gl_display_egl_util.h"
33 #include "ui/gl/gl_image.h"
34 #include "ui/gl/gl_implementation.h"
35 #include "ui/gl/gl_surface_presentation_helper.h"
36 #include "ui/gl/gl_surface_stub.h"
37 #include "ui/gl/gl_utils.h"
38 #include "ui/gl/gpu_switching_manager.h"
39 #include "ui/gl/scoped_make_current.h"
40 #include "ui/gl/sync_control_vsync_provider.h"
41
42 #if defined(OS_ANDROID)
43 #include <android/native_window_jni.h>
44 #include "base/android/build_info.h"
45 #endif
46
47 #if !defined(EGL_FIXED_SIZE_ANGLE)
48 #define EGL_FIXED_SIZE_ANGLE 0x3201
49 #endif
50
51 #if !defined(EGL_OPENGL_ES3_BIT)
52 #define EGL_OPENGL_ES3_BIT 0x00000040
53 #endif
54
55 #if defined(USE_X11)
56 #include "ui/base/x/x11_util.h"
57 #endif
58
59 // Not present egl/eglext.h yet.
60
61 #ifndef EGL_EXT_gl_colorspace_display_p3
62 #define EGL_EXT_gl_colorspace_display_p3 1
63 #define EGL_GL_COLORSPACE_DISPLAY_P3_EXT 0x3363
64 #endif /* EGL_EXT_gl_colorspace_display_p3 */
65
66 #ifndef EGL_EXT_gl_colorspace_display_p3_passthrough
67 #define EGL_EXT_gl_colorspace_display_p3_passthrough 1
68 #define EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT 0x3490
69 #endif /* EGL_EXT_gl_colorspace_display_p3_passthrough */
70
71 // From ANGLE's egl/eglext.h.
72
73 #ifndef EGL_ANGLE_platform_angle
74 #define EGL_ANGLE_platform_angle 1
75 #define EGL_PLATFORM_ANGLE_ANGLE 0x3202
76 #define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203
77 #define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3204
78 #define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3205
79 #define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3206
80 #define EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE 0x3451
81 #define EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE 0x3209
82 #define EGL_PLATFORM_ANGLE_DEVICE_TYPE_EGL_ANGLE 0x348E
83 #define EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE 0x320A
84 #define EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE 0x345E
85 #define EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE 0x3487
86 #endif /* EGL_ANGLE_platform_angle */
87
88 #ifndef EGL_ANGLE_platform_angle_d3d
89 #define EGL_ANGLE_platform_angle_d3d 1
90 #define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3207
91 #define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3208
92 #define EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE 0x320B
93 #define EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_REFERENCE_ANGLE 0x320C
94 #endif /* EGL_ANGLE_platform_angle_d3d */
95
96 #ifndef EGL_ANGLE_platform_angle_d3d_luid
97 #define EGL_ANGLE_platform_angle_d3d_luid 1
98 #define EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE 0x34A0
99 #define EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE 0x34A1
100 #endif /* EGL_ANGLE_platform_angle_d3d_luid */
101
102 #ifndef EGL_ANGLE_platform_angle_d3d11on12
103 #define EGL_ANGLE_platform_angle_d3d11on12 1
104 #define EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE 0x3488
105 #endif /* EGL_ANGLE_platform_angle_d3d11on12 */
106
107 #ifndef EGL_ANGLE_platform_angle_opengl
108 #define EGL_ANGLE_platform_angle_opengl 1
109 #define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x320D
110 #define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320E
111 #endif /* EGL_ANGLE_platform_angle_opengl */
112
113 #ifndef EGL_ANGLE_platform_angle_null
114 #define EGL_ANGLE_platform_angle_null 1
115 #define EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE 0x33AE
116 #endif /* EGL_ANGLE_platform_angle_null */
117
118 #ifndef EGL_ANGLE_platform_angle_vulkan
119 #define EGL_ANGLE_platform_angle_vulkan 1
120 #define EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE 0x3450
121 #endif /* EGL_ANGLE_platform_angle_vulkan */
122
123 #ifndef EGL_ANGLE_platform_angle_metal
124 #define EGL_ANGLE_platform_angle_metal 1
125 #define EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE 0x3489
126 #endif /* EGL_ANGLE_platform_angle_metal */
127
128 #ifndef EGL_ANGLE_x11_visual
129 #define EGL_ANGLE_x11_visual 1
130 #define EGL_X11_VISUAL_ID_ANGLE 0x33A3
131 #endif /* EGL_ANGLE_x11_visual */
132
133 #ifndef EGL_ANGLE_surface_orientation
134 #define EGL_ANGLE_surface_orientation
135 #define EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE 0x33A7
136 #define EGL_SURFACE_ORIENTATION_ANGLE 0x33A8
137 #define EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE 0x0001
138 #define EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE 0x0002
139 #endif /* EGL_ANGLE_surface_orientation */
140
141 #ifndef EGL_ANGLE_direct_composition
142 #define EGL_ANGLE_direct_composition 1
143 #define EGL_DIRECT_COMPOSITION_ANGLE 0x33A5
144 #endif /* EGL_ANGLE_direct_composition */
145
146 #ifndef EGL_ANGLE_flexible_surface_compatibility
147 #define EGL_ANGLE_flexible_surface_compatibility 1
148 #define EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE 0x33A6
149 #endif /* EGL_ANGLE_flexible_surface_compatibility */
150
151 #ifndef EGL_ANGLE_display_robust_resource_initialization
152 #define EGL_ANGLE_display_robust_resource_initialization 1
153 #define EGL_DISPLAY_ROBUST_RESOURCE_INITIALIZATION_ANGLE 0x3453
154 #endif /* EGL_ANGLE_display_robust_resource_initialization */
155
156 // From ANGLE's egl/eglext.h.
157 #ifndef EGL_ANGLE_feature_control
158 #define EGL_ANGLE_feature_control 1
159 #define EGL_FEATURE_NAME_ANGLE 0x3460
160 #define EGL_FEATURE_CATEGORY_ANGLE 0x3461
161 #define EGL_FEATURE_DESCRIPTION_ANGLE 0x3462
162 #define EGL_FEATURE_BUG_ANGLE 0x3463
163 #define EGL_FEATURE_STATUS_ANGLE 0x3464
164 #define EGL_FEATURE_COUNT_ANGLE 0x3465
165 #define EGL_FEATURE_OVERRIDES_ENABLED_ANGLE 0x3466
166 #define EGL_FEATURE_OVERRIDES_DISABLED_ANGLE 0x3467
167 #define EGL_FEATURE_ALL_DISABLED_ANGLE 0x3469
168 #endif /* EGL_ANGLE_feature_control */
169
170 using ui::GetLastEGLErrorString;
171 using ui::PlatformEvent;
172
173 namespace gl {
174
175 bool GLSurfaceEGL::initialized_ = false;
176
177 namespace {
178
179 class EGLGpuSwitchingObserver;
180
181 EGLDisplay g_egl_display = EGL_NO_DISPLAY;
182 EGLDisplayPlatform g_native_display(EGL_DEFAULT_DISPLAY);
183
184 const char* g_egl_extensions = nullptr;
185 bool g_egl_create_context_robustness_supported = false;
186 bool g_egl_robustness_video_memory_purge_supported = false;
187 bool g_egl_create_context_bind_generates_resource_supported = false;
188 bool g_egl_create_context_webgl_compatability_supported = false;
189 bool g_egl_sync_control_supported = false;
190 bool g_egl_sync_control_rate_supported = false;
191 bool g_egl_window_fixed_size_supported = false;
192 bool g_egl_surfaceless_context_supported = false;
193 bool g_egl_surface_orientation_supported = false;
194 bool g_egl_context_priority_supported = false;
195 bool g_egl_khr_colorspace = false;
196 bool g_egl_ext_colorspace_display_p3 = false;
197 bool g_egl_ext_colorspace_display_p3_passthrough = false;
198 bool g_egl_flexible_surface_compatibility_supported = false;
199 bool g_egl_robust_resource_init_supported = false;
200 bool g_egl_display_texture_share_group_supported = false;
201 bool g_egl_display_semaphore_share_group_supported = false;
202 bool g_egl_create_context_client_arrays_supported = false;
203 bool g_egl_android_native_fence_sync_supported = false;
204 bool g_egl_ext_pixel_format_float_supported = false;
205 bool g_egl_angle_feature_control_supported = false;
206 bool g_egl_angle_power_preference_supported = false;
207 EGLGpuSwitchingObserver* g_egl_gpu_switching_observer = nullptr;
208
209 constexpr const char kSwapEventTraceCategories[] = "gpu";
210
211 constexpr size_t kMaxTimestampsSupportable = 9;
212
213 struct TraceSwapEventsInitializer {
TraceSwapEventsInitializergl::__anon6d76d55a0111::TraceSwapEventsInitializer214 TraceSwapEventsInitializer()
215 : value(*TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
216 kSwapEventTraceCategories)) {}
217 const unsigned char& value;
218 };
219
220 static base::LazyInstance<TraceSwapEventsInitializer>::Leaky
221 g_trace_swap_enabled = LAZY_INSTANCE_INITIALIZER;
222
223 class EGLSyncControlVSyncProvider : public SyncControlVSyncProvider {
224 public:
EGLSyncControlVSyncProvider(EGLSurface surface)225 explicit EGLSyncControlVSyncProvider(EGLSurface surface)
226 : SyncControlVSyncProvider(),
227 surface_(surface) {
228 }
229
~EGLSyncControlVSyncProvider()230 ~EGLSyncControlVSyncProvider() override {}
231
IsSupported()232 static bool IsSupported() {
233 return SyncControlVSyncProvider::IsSupported() &&
234 g_egl_sync_control_supported;
235 }
236
237 protected:
GetSyncValues(int64_t * system_time,int64_t * media_stream_counter,int64_t * swap_buffer_counter)238 bool GetSyncValues(int64_t* system_time,
239 int64_t* media_stream_counter,
240 int64_t* swap_buffer_counter) override {
241 uint64_t u_system_time, u_media_stream_counter, u_swap_buffer_counter;
242 bool result =
243 eglGetSyncValuesCHROMIUM(g_egl_display, surface_, &u_system_time,
244 &u_media_stream_counter,
245 &u_swap_buffer_counter) == EGL_TRUE;
246 if (result) {
247 *system_time = static_cast<int64_t>(u_system_time);
248 *media_stream_counter = static_cast<int64_t>(u_media_stream_counter);
249 *swap_buffer_counter = static_cast<int64_t>(u_swap_buffer_counter);
250 }
251 return result;
252 }
253
GetMscRate(int32_t * numerator,int32_t * denominator)254 bool GetMscRate(int32_t* numerator, int32_t* denominator) override {
255 if (!g_egl_sync_control_rate_supported) {
256 return false;
257 }
258
259 bool result = eglGetMscRateANGLE(g_egl_display, surface_, numerator,
260 denominator) == EGL_TRUE;
261 return result;
262 }
263
IsHWClock() const264 bool IsHWClock() const override { return true; }
265
266 private:
267 EGLSurface surface_;
268
269 DISALLOW_COPY_AND_ASSIGN(EGLSyncControlVSyncProvider);
270 };
271
272 class EGLGpuSwitchingObserver final : public ui::GpuSwitchingObserver {
273 public:
OnGpuSwitched(gl::GpuPreference active_gpu_heuristic)274 void OnGpuSwitched(gl::GpuPreference active_gpu_heuristic) override {
275 DCHECK(GLSurfaceEGL::IsANGLEPowerPreferenceSupported());
276 eglHandleGPUSwitchANGLE(g_egl_display);
277 }
278 };
279
GetAttribArrayFromStringVector(const std::vector<std::string> & strings)280 std::vector<const char*> GetAttribArrayFromStringVector(
281 const std::vector<std::string>& strings) {
282 std::vector<const char*> attribs;
283 for (const std::string& item : strings) {
284 attribs.push_back(item.c_str());
285 }
286 attribs.push_back(0);
287 return attribs;
288 }
289
GetStringVectorFromCommandLine(const base::CommandLine * command_line,const char switch_name[])290 std::vector<std::string> GetStringVectorFromCommandLine(
291 const base::CommandLine* command_line,
292 const char switch_name[]) {
293 std::string command_string = command_line->GetSwitchValueASCII(switch_name);
294 return base::SplitString(command_string, ", ;", base::TRIM_WHITESPACE,
295 base::SPLIT_WANT_NONEMPTY);
296 }
297
GetPlatformANGLEDisplay(EGLDisplayPlatform native_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)298 EGLDisplay GetPlatformANGLEDisplay(
299 EGLDisplayPlatform native_display,
300 EGLenum platform_type,
301 const std::vector<std::string>& enabled_features,
302 const std::vector<std::string>& disabled_features,
303 const std::vector<EGLAttrib>& extra_display_attribs) {
304 std::vector<EGLAttrib> display_attribs(extra_display_attribs);
305
306 display_attribs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
307 display_attribs.push_back(static_cast<EGLAttrib>(platform_type));
308
309 if (platform_type == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE) {
310 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
311 if (command_line->HasSwitch(switches::kUseAdapterLuid)) {
312 // If the LUID is specified, the format is <high part>,<low part>. Split
313 // and add them to the EGL_ANGLE_platform_angle_d3d_luid ext attributes.
314 std::string luid =
315 command_line->GetSwitchValueASCII(switches::kUseAdapterLuid);
316 size_t comma = luid.find(',');
317 if (comma != std::string::npos) {
318 int32_t high;
319 uint32_t low;
320 if (!base::StringToInt(luid.substr(0, comma), &high) ||
321 !base::StringToUint(luid.substr(comma + 1), &low))
322 return EGL_NO_DISPLAY;
323
324 display_attribs.push_back(EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE);
325 display_attribs.push_back(high);
326
327 display_attribs.push_back(EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE);
328 display_attribs.push_back(low);
329 }
330 }
331 }
332
333 GLDisplayEglUtil::GetInstance()->GetPlatformExtraDisplayAttribs(
334 platform_type, &display_attribs);
335
336 std::vector<const char*> enabled_features_attribs =
337 GetAttribArrayFromStringVector(enabled_features);
338 std::vector<const char*> disabled_features_attribs =
339 GetAttribArrayFromStringVector(disabled_features);
340 if (g_egl_angle_feature_control_supported) {
341 if (!enabled_features_attribs.empty()) {
342 display_attribs.push_back(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE);
343 display_attribs.push_back(
344 reinterpret_cast<EGLAttrib>(enabled_features_attribs.data()));
345 }
346 if (!disabled_features_attribs.empty()) {
347 display_attribs.push_back(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE);
348 display_attribs.push_back(
349 reinterpret_cast<EGLAttrib>(disabled_features_attribs.data()));
350 }
351 }
352 // TODO(dbehr) Add an attrib to Angle to pass EGL platform.
353
354 display_attribs.push_back(EGL_NONE);
355
356 // This is an EGL 1.5 function that we know ANGLE supports. It's used to pass
357 // EGLAttribs (pointers) instead of EGLints into the display
358 return eglGetPlatformDisplay(
359 EGL_PLATFORM_ANGLE_ANGLE,
360 reinterpret_cast<void*>(native_display.GetDisplay()),
361 &display_attribs[0]);
362 }
363
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)364 EGLDisplay GetDisplayFromType(
365 DisplayType display_type,
366 EGLDisplayPlatform native_display,
367 const std::vector<std::string>& enabled_angle_features,
368 const std::vector<std::string>& disabled_angle_features,
369 bool disable_all_angle_features) {
370 std::vector<EGLAttrib> extra_display_attribs;
371 if (disable_all_angle_features) {
372 extra_display_attribs.push_back(EGL_FEATURE_ALL_DISABLED_ANGLE);
373 extra_display_attribs.push_back(EGL_TRUE);
374 }
375 switch (display_type) {
376 case DEFAULT:
377 case SWIFT_SHADER:
378 if (native_display.GetPlatform() != 0) {
379 return eglGetPlatformDisplay(
380 native_display.GetPlatform(),
381 reinterpret_cast<void*>(native_display.GetDisplay()), nullptr);
382 } else {
383 return eglGetDisplay(native_display.GetDisplay());
384 }
385 case ANGLE_D3D9:
386 return GetPlatformANGLEDisplay(
387 native_display, EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE,
388 enabled_angle_features, disabled_angle_features,
389 extra_display_attribs);
390 case ANGLE_D3D11:
391 return GetPlatformANGLEDisplay(
392 native_display, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
393 enabled_angle_features, disabled_angle_features,
394 extra_display_attribs);
395 case ANGLE_D3D11_NULL:
396 extra_display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
397 extra_display_attribs.push_back(
398 EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE);
399 return GetPlatformANGLEDisplay(
400 native_display, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
401 enabled_angle_features, disabled_angle_features,
402 extra_display_attribs);
403 case ANGLE_OPENGL:
404 return GetPlatformANGLEDisplay(
405 native_display, EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE,
406 enabled_angle_features, disabled_angle_features,
407 extra_display_attribs);
408 case ANGLE_OPENGL_EGL:
409 extra_display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
410 extra_display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_EGL_ANGLE);
411 return GetPlatformANGLEDisplay(
412 native_display, EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE,
413 enabled_angle_features, disabled_angle_features,
414 extra_display_attribs);
415 case ANGLE_OPENGL_NULL:
416 extra_display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
417 extra_display_attribs.push_back(
418 EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE);
419 return GetPlatformANGLEDisplay(
420 native_display, EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE,
421 enabled_angle_features, disabled_angle_features,
422 extra_display_attribs);
423 case ANGLE_OPENGLES:
424 return GetPlatformANGLEDisplay(
425 native_display, EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE,
426 enabled_angle_features, disabled_angle_features,
427 extra_display_attribs);
428 case ANGLE_OPENGLES_EGL:
429 extra_display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
430 extra_display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_EGL_ANGLE);
431 return GetPlatformANGLEDisplay(
432 native_display, EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE,
433 enabled_angle_features, disabled_angle_features,
434 extra_display_attribs);
435 case ANGLE_OPENGLES_NULL:
436 extra_display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
437 extra_display_attribs.push_back(
438 EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE);
439 return GetPlatformANGLEDisplay(
440 native_display, EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE,
441 enabled_angle_features, disabled_angle_features,
442 extra_display_attribs);
443 case ANGLE_NULL:
444 return GetPlatformANGLEDisplay(
445 native_display, EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE,
446 enabled_angle_features, disabled_angle_features,
447 extra_display_attribs);
448 case ANGLE_VULKAN:
449 return GetPlatformANGLEDisplay(
450 native_display, EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE,
451 enabled_angle_features, disabled_angle_features,
452 extra_display_attribs);
453 case ANGLE_VULKAN_NULL:
454 extra_display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
455 extra_display_attribs.push_back(
456 EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE);
457 return GetPlatformANGLEDisplay(
458 native_display, EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE,
459 enabled_angle_features, disabled_angle_features,
460 extra_display_attribs);
461 case ANGLE_D3D11on12:
462 extra_display_attribs.push_back(EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE);
463 extra_display_attribs.push_back(EGL_TRUE);
464 return GetPlatformANGLEDisplay(
465 native_display, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
466 enabled_angle_features, disabled_angle_features,
467 extra_display_attribs);
468 case ANGLE_SWIFTSHADER:
469 extra_display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
470 extra_display_attribs.push_back(
471 EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE);
472 return GetPlatformANGLEDisplay(
473 native_display, EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE,
474 enabled_angle_features, disabled_angle_features,
475 extra_display_attribs);
476 case ANGLE_METAL:
477 return GetPlatformANGLEDisplay(
478 native_display, EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE,
479 enabled_angle_features, disabled_angle_features,
480 extra_display_attribs);
481 case ANGLE_METAL_NULL:
482 extra_display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
483 extra_display_attribs.push_back(
484 EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE);
485 return GetPlatformANGLEDisplay(
486 native_display, EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE,
487 enabled_angle_features, disabled_angle_features,
488 extra_display_attribs);
489 default:
490 NOTREACHED();
491 return EGL_NO_DISPLAY;
492 }
493 }
494
GetANGLEImplementationFromDisplayType(DisplayType display_type)495 ANGLEImplementation GetANGLEImplementationFromDisplayType(
496 DisplayType display_type) {
497 switch (display_type) {
498 case ANGLE_D3D9:
499 return ANGLEImplementation::kD3D9;
500 case ANGLE_D3D11:
501 case ANGLE_D3D11_NULL:
502 case ANGLE_D3D11on12:
503 return ANGLEImplementation::kD3D11;
504 case ANGLE_OPENGL:
505 case ANGLE_OPENGL_NULL:
506 return ANGLEImplementation::kOpenGL;
507 case ANGLE_OPENGLES:
508 case ANGLE_OPENGLES_NULL:
509 return ANGLEImplementation::kOpenGLES;
510 case ANGLE_NULL:
511 return ANGLEImplementation::kNull;
512 case ANGLE_VULKAN:
513 case ANGLE_VULKAN_NULL:
514 return ANGLEImplementation::kVulkan;
515 case ANGLE_SWIFTSHADER:
516 return ANGLEImplementation::kSwiftShader;
517 case ANGLE_METAL:
518 case ANGLE_METAL_NULL:
519 return ANGLEImplementation::kMetal;
520 default:
521 return ANGLEImplementation::kNone;
522 }
523 }
524
DisplayTypeString(DisplayType display_type)525 const char* DisplayTypeString(DisplayType display_type) {
526 switch (display_type) {
527 case DEFAULT:
528 return "Default";
529 case SWIFT_SHADER:
530 return "SwiftShader";
531 case ANGLE_D3D9:
532 return "D3D9";
533 case ANGLE_D3D11:
534 return "D3D11";
535 case ANGLE_D3D11_NULL:
536 return "D3D11Null";
537 case ANGLE_OPENGL:
538 return "OpenGL";
539 case ANGLE_OPENGL_NULL:
540 return "OpenGLNull";
541 case ANGLE_OPENGLES:
542 return "OpenGLES";
543 case ANGLE_OPENGLES_NULL:
544 return "OpenGLESNull";
545 case ANGLE_NULL:
546 return "Null";
547 case ANGLE_VULKAN:
548 return "Vulkan";
549 case ANGLE_VULKAN_NULL:
550 return "VulkanNull";
551 case ANGLE_D3D11on12:
552 return "D3D11on12";
553 case ANGLE_SWIFTSHADER:
554 return "SwiftShader";
555 case ANGLE_OPENGL_EGL:
556 return "OpenGLEGL";
557 case ANGLE_OPENGLES_EGL:
558 return "OpenGLESEGL";
559 case ANGLE_METAL:
560 return "Metal";
561 case ANGLE_METAL_NULL:
562 return "MetalNull";
563 default:
564 NOTREACHED();
565 return "Err";
566 }
567 }
568
ValidateEglConfig(EGLDisplay display,const EGLint * config_attribs,EGLint * num_configs)569 bool ValidateEglConfig(EGLDisplay display,
570 const EGLint* config_attribs,
571 EGLint* num_configs) {
572 if (!eglChooseConfig(display,
573 config_attribs,
574 NULL,
575 0,
576 num_configs)) {
577 LOG(ERROR) << "eglChooseConfig failed with error "
578 << GetLastEGLErrorString();
579 return false;
580 }
581 if (*num_configs == 0) {
582 return false;
583 }
584 return true;
585 }
586
ChooseConfig(GLSurfaceFormat format,bool surfaceless)587 EGLConfig ChooseConfig(GLSurfaceFormat format, bool surfaceless) {
588 // Choose an EGL configuration.
589 // On X this is only used for PBuffer surfaces.
590
591 std::vector<EGLint> renderable_types;
592 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
593 switches::kDisableES3GLContext)) {
594 renderable_types.push_back(EGL_OPENGL_ES3_BIT);
595 }
596 renderable_types.push_back(EGL_OPENGL_ES2_BIT);
597
598 EGLint buffer_size = format.GetBufferSize();
599 EGLint alpha_size = 8;
600 bool want_rgb565 = buffer_size == 16;
601 EGLint depth_size = format.GetDepthBits();
602 EGLint stencil_size = format.GetStencilBits();
603 EGLint samples = format.GetSamples();
604
605 // Some platforms (eg. X11) may want to set custom values for alpha and buffer
606 // sizes.
607 GLDisplayEglUtil::GetInstance()->ChoosePlatformCustomAlphaAndBufferSize(
608 &alpha_size, &buffer_size);
609
610 EGLint surface_type =
611 (surfaceless ? EGL_DONT_CARE : EGL_WINDOW_BIT | EGL_PBUFFER_BIT);
612
613 for (auto renderable_type : renderable_types) {
614 EGLint config_attribs_8888[] = {EGL_BUFFER_SIZE,
615 buffer_size,
616 EGL_ALPHA_SIZE,
617 alpha_size,
618 EGL_BLUE_SIZE,
619 8,
620 EGL_GREEN_SIZE,
621 8,
622 EGL_RED_SIZE,
623 8,
624 EGL_SAMPLES,
625 samples,
626 EGL_DEPTH_SIZE,
627 depth_size,
628 EGL_STENCIL_SIZE,
629 stencil_size,
630 EGL_RENDERABLE_TYPE,
631 renderable_type,
632 EGL_SURFACE_TYPE,
633 surface_type,
634 EGL_NONE};
635
636 EGLint config_attribs_565[] = {EGL_BUFFER_SIZE,
637 16,
638 EGL_BLUE_SIZE,
639 5,
640 EGL_GREEN_SIZE,
641 6,
642 EGL_RED_SIZE,
643 5,
644 EGL_SAMPLES,
645 samples,
646 EGL_DEPTH_SIZE,
647 depth_size,
648 EGL_STENCIL_SIZE,
649 stencil_size,
650 EGL_RENDERABLE_TYPE,
651 renderable_type,
652 EGL_SURFACE_TYPE,
653 surface_type,
654 EGL_NONE};
655
656 EGLint* choose_attributes = config_attribs_8888;
657 if (want_rgb565) {
658 choose_attributes = config_attribs_565;
659 }
660
661 EGLint num_configs;
662 EGLint config_size = 1;
663 EGLConfig config = nullptr;
664 EGLConfig* config_data = &config;
665 // Validate if there are any configs for given attribs.
666 if (!ValidateEglConfig(g_egl_display, choose_attributes, &num_configs)) {
667 // Try the next renderable_type
668 continue;
669 }
670
671 std::unique_ptr<EGLConfig[]> matching_configs(new EGLConfig[num_configs]);
672 if (want_rgb565) {
673 config_size = num_configs;
674 config_data = matching_configs.get();
675 }
676
677 if (!eglChooseConfig(g_egl_display, choose_attributes, config_data,
678 config_size, &num_configs)) {
679 LOG(ERROR) << "eglChooseConfig failed with error "
680 << GetLastEGLErrorString();
681 return config;
682 }
683
684 if (want_rgb565) {
685 // Because of the EGL config sort order, we have to iterate
686 // through all of them (it'll put higher sum(R,G,B) bits
687 // first with the above attribs).
688 bool match_found = false;
689 for (int i = 0; i < num_configs; i++) {
690 EGLint red, green, blue, alpha;
691 // Read the relevant attributes of the EGLConfig.
692 if (eglGetConfigAttrib(g_egl_display, matching_configs[i], EGL_RED_SIZE,
693 &red) &&
694 eglGetConfigAttrib(g_egl_display, matching_configs[i],
695 EGL_BLUE_SIZE, &blue) &&
696 eglGetConfigAttrib(g_egl_display, matching_configs[i],
697 EGL_GREEN_SIZE, &green) &&
698 eglGetConfigAttrib(g_egl_display, matching_configs[i],
699 EGL_ALPHA_SIZE, &alpha) &&
700 alpha == 0 && red == 5 && green == 6 && blue == 5) {
701 config = matching_configs[i];
702 match_found = true;
703 break;
704 }
705 }
706 if (!match_found) {
707 // To fall back to default 32 bit format, choose with
708 // the right attributes again.
709 if (!ValidateEglConfig(g_egl_display, config_attribs_8888,
710 &num_configs)) {
711 // Try the next renderable_type
712 continue;
713 }
714 if (!eglChooseConfig(g_egl_display, config_attribs_8888, &config, 1,
715 &num_configs)) {
716 LOG(ERROR) << "eglChooseConfig failed with error "
717 << GetLastEGLErrorString();
718 return config;
719 }
720 }
721 }
722 return config;
723 }
724
725 LOG(ERROR) << "No suitable EGL configs found.";
726 return nullptr;
727 }
728
AddInitDisplay(std::vector<DisplayType> * init_displays,DisplayType display_type)729 void AddInitDisplay(std::vector<DisplayType>* init_displays,
730 DisplayType display_type) {
731 // Make sure to not add the same display type twice.
732 if (!base::Contains(*init_displays, display_type))
733 init_displays->push_back(display_type);
734 }
735
GetDebugMessageTypeString(EGLint source)736 const char* GetDebugMessageTypeString(EGLint source) {
737 switch (source) {
738 case EGL_DEBUG_MSG_CRITICAL_KHR:
739 return "Critical";
740 case EGL_DEBUG_MSG_ERROR_KHR:
741 return "Error";
742 case EGL_DEBUG_MSG_WARN_KHR:
743 return "Warning";
744 case EGL_DEBUG_MSG_INFO_KHR:
745 return "Info";
746 default:
747 return "UNKNOWN";
748 }
749 }
750
LogEGLDebugMessage(EGLenum error,const char * command,EGLint message_type,EGLLabelKHR thread_label,EGLLabelKHR object_label,const char * message)751 static void EGLAPIENTRY LogEGLDebugMessage(EGLenum error,
752 const char* command,
753 EGLint message_type,
754 EGLLabelKHR thread_label,
755 EGLLabelKHR object_label,
756 const char* message) {
757 std::string formatted_message = std::string("EGL Driver message (") +
758 GetDebugMessageTypeString(message_type) +
759 ") " + command + ": " + message;
760
761 // Assume that all labels that have been set are strings
762 if (thread_label) {
763 formatted_message += " thread: ";
764 formatted_message += static_cast<const char*>(thread_label);
765 }
766 if (object_label) {
767 formatted_message += " object: ";
768 formatted_message += static_cast<const char*>(object_label);
769 }
770
771 if (message_type == EGL_DEBUG_MSG_CRITICAL_KHR ||
772 message_type == EGL_DEBUG_MSG_ERROR_KHR) {
773 LOG(ERROR) << formatted_message;
774 } else {
775 DVLOG(1) << formatted_message;
776 }
777 }
778
779 } // namespace
780
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)781 void GetEGLInitDisplays(bool supports_angle_d3d,
782 bool supports_angle_opengl,
783 bool supports_angle_null,
784 bool supports_angle_vulkan,
785 bool supports_angle_swiftshader,
786 bool supports_angle_egl,
787 bool supports_angle_metal,
788 const base::CommandLine* command_line,
789 std::vector<DisplayType>* init_displays) {
790 // SwiftShader does not use the platform extensions
791 if (command_line->GetSwitchValueASCII(switches::kUseGL) ==
792 kGLImplementationSwiftShaderForWebGLName) {
793 AddInitDisplay(init_displays, SWIFT_SHADER);
794 return;
795 }
796
797 std::string requested_renderer =
798 command_line->GetSwitchValueASCII(switches::kUseANGLE);
799
800 bool use_angle_default =
801 !command_line->HasSwitch(switches::kUseANGLE) ||
802 requested_renderer == kANGLEImplementationDefaultName;
803
804 if (supports_angle_null &&
805 requested_renderer == kANGLEImplementationNullName) {
806 AddInitDisplay(init_displays, ANGLE_NULL);
807 return;
808 }
809
810 // If no display has been explicitly requested and the DefaultANGLEOpenGL
811 // experiment is enabled, try creating OpenGL displays first.
812 // TODO(oetuaho@nvidia.com): Only enable this path on specific GPUs with a
813 // blocklist entry. http://crbug.com/693090
814 if (supports_angle_opengl && use_angle_default &&
815 base::FeatureList::IsEnabled(features::kDefaultANGLEOpenGL)) {
816 AddInitDisplay(init_displays, ANGLE_OPENGL);
817 AddInitDisplay(init_displays, ANGLE_OPENGLES);
818 }
819
820 if (supports_angle_metal && use_angle_default &&
821 base::FeatureList::IsEnabled(features::kDefaultANGLEMetal)) {
822 AddInitDisplay(init_displays, ANGLE_METAL);
823 }
824
825 if (supports_angle_d3d) {
826 if (use_angle_default) {
827 // Default mode for ANGLE - try D3D11, else try D3D9
828 if (!command_line->HasSwitch(switches::kDisableD3D11)) {
829 AddInitDisplay(init_displays, ANGLE_D3D11);
830 }
831 AddInitDisplay(init_displays, ANGLE_D3D9);
832 } else {
833 if (requested_renderer == kANGLEImplementationD3D11Name) {
834 AddInitDisplay(init_displays, ANGLE_D3D11);
835 } else if (requested_renderer == kANGLEImplementationD3D9Name) {
836 AddInitDisplay(init_displays, ANGLE_D3D9);
837 } else if (requested_renderer == kANGLEImplementationD3D11NULLName) {
838 AddInitDisplay(init_displays, ANGLE_D3D11_NULL);
839 } else if (requested_renderer == kANGLEImplementationD3D11on12Name) {
840 AddInitDisplay(init_displays, ANGLE_D3D11on12);
841 }
842 }
843 }
844
845 if (supports_angle_opengl) {
846 if (use_angle_default && !supports_angle_d3d) {
847 #if defined(OS_ANDROID)
848 // Don't request desktopGL on android
849 AddInitDisplay(init_displays, ANGLE_OPENGLES);
850 #else
851 AddInitDisplay(init_displays, ANGLE_OPENGL);
852 AddInitDisplay(init_displays, ANGLE_OPENGLES);
853 #endif
854 } else {
855 if (requested_renderer == kANGLEImplementationOpenGLName) {
856 AddInitDisplay(init_displays, ANGLE_OPENGL);
857 } else if (requested_renderer == kANGLEImplementationOpenGLESName) {
858 AddInitDisplay(init_displays, ANGLE_OPENGLES);
859 } else if (requested_renderer == kANGLEImplementationOpenGLNULLName) {
860 AddInitDisplay(init_displays, ANGLE_OPENGL_NULL);
861 } else if (requested_renderer == kANGLEImplementationOpenGLESNULLName) {
862 AddInitDisplay(init_displays, ANGLE_OPENGLES_NULL);
863 } else if (requested_renderer == kANGLEImplementationOpenGLEGLName &&
864 supports_angle_egl) {
865 AddInitDisplay(init_displays, ANGLE_OPENGL_EGL);
866 } else if (requested_renderer == kANGLEImplementationOpenGLESEGLName &&
867 supports_angle_egl) {
868 AddInitDisplay(init_displays, ANGLE_OPENGLES_EGL);
869 }
870 }
871 }
872
873 if (supports_angle_vulkan) {
874 if (use_angle_default) {
875 if (!supports_angle_d3d && !supports_angle_opengl) {
876 AddInitDisplay(init_displays, ANGLE_VULKAN);
877 }
878 } else if (requested_renderer == kANGLEImplementationVulkanName) {
879 AddInitDisplay(init_displays, ANGLE_VULKAN);
880 } else if (requested_renderer == kANGLEImplementationVulkanNULLName) {
881 AddInitDisplay(init_displays, ANGLE_VULKAN_NULL);
882 }
883 }
884
885 if (supports_angle_swiftshader) {
886 if (requested_renderer == kANGLEImplementationSwiftShaderName) {
887 AddInitDisplay(init_displays, ANGLE_SWIFTSHADER);
888 }
889 }
890
891 if (supports_angle_metal) {
892 if (use_angle_default) {
893 if (!supports_angle_opengl) {
894 AddInitDisplay(init_displays, ANGLE_METAL);
895 }
896 } else if (requested_renderer == kANGLEImplementationMetalName) {
897 AddInitDisplay(init_displays, ANGLE_METAL);
898 } else if (requested_renderer == kANGLEImplementationMetalNULLName) {
899 AddInitDisplay(init_displays, ANGLE_METAL_NULL);
900 }
901 }
902
903 // If no displays are available due to missing angle extensions or invalid
904 // flags, request the default display.
905 if (init_displays->empty()) {
906 init_displays->push_back(DEFAULT);
907 }
908 }
909
GLSurfaceEGL()910 GLSurfaceEGL::GLSurfaceEGL() {}
911
GetFormat()912 GLSurfaceFormat GLSurfaceEGL::GetFormat() {
913 return format_;
914 }
915
GetDisplay()916 EGLDisplay GLSurfaceEGL::GetDisplay() {
917 return g_egl_display;
918 }
919
GetConfig()920 EGLConfig GLSurfaceEGL::GetConfig() {
921 if (!config_) {
922 config_ = ChooseConfig(format_, IsSurfaceless());
923 }
924 return config_;
925 }
926
927 // static
InitializeOneOff(EGLDisplayPlatform native_display)928 bool GLSurfaceEGL::InitializeOneOff(EGLDisplayPlatform native_display) {
929 if (initialized_)
930 return true;
931
932 // Must be called before InitializeDisplay().
933 g_driver_egl.InitializeClientExtensionBindings();
934
935 InitializeDisplay(native_display);
936 if (g_egl_display == EGL_NO_DISPLAY)
937 return false;
938
939 // Must be called after InitializeDisplay().
940 g_driver_egl.InitializeExtensionBindings();
941
942 return InitializeOneOffCommon();
943 }
944
945 // static
InitializeOneOffForTesting()946 bool GLSurfaceEGL::InitializeOneOffForTesting() {
947 g_driver_egl.InitializeClientExtensionBindings();
948 g_egl_display = eglGetCurrentDisplay();
949 g_driver_egl.InitializeExtensionBindings();
950 return InitializeOneOffCommon();
951 }
952
953 // static
InitializeOneOffCommon()954 bool GLSurfaceEGL::InitializeOneOffCommon() {
955 g_egl_extensions = eglQueryString(g_egl_display, EGL_EXTENSIONS);
956
957 g_egl_create_context_robustness_supported =
958 HasEGLExtension("EGL_EXT_create_context_robustness");
959 g_egl_robustness_video_memory_purge_supported =
960 HasEGLExtension("EGL_NV_robustness_video_memory_purge");
961 g_egl_create_context_bind_generates_resource_supported =
962 HasEGLExtension("EGL_CHROMIUM_create_context_bind_generates_resource");
963 g_egl_create_context_webgl_compatability_supported =
964 HasEGLExtension("EGL_ANGLE_create_context_webgl_compatibility");
965 g_egl_sync_control_supported = HasEGLExtension("EGL_CHROMIUM_sync_control");
966 g_egl_sync_control_rate_supported =
967 HasEGLExtension("EGL_ANGLE_sync_control_rate");
968 g_egl_window_fixed_size_supported =
969 HasEGLExtension("EGL_ANGLE_window_fixed_size");
970 g_egl_surface_orientation_supported =
971 HasEGLExtension("EGL_ANGLE_surface_orientation");
972 g_egl_khr_colorspace = HasEGLExtension("EGL_KHR_gl_colorspace");
973 g_egl_ext_colorspace_display_p3 =
974 HasEGLExtension("EGL_EXT_gl_colorspace_display_p3");
975 g_egl_ext_colorspace_display_p3_passthrough =
976 HasEGLExtension("EGL_EXT_gl_colorspace_display_p3_passthrough");
977 // According to https://source.android.com/compatibility/android-cdd.html the
978 // EGL_IMG_context_priority extension is mandatory for Virtual Reality High
979 // Performance support, but due to a bug in Android Nougat the extension
980 // isn't being reported even when it's present. As a fallback, check if other
981 // related extensions that were added for VR support are present, and assume
982 // that this implies context priority is also supported. See also:
983 // https://github.com/googlevr/gvr-android-sdk/issues/330
984 g_egl_context_priority_supported =
985 HasEGLExtension("EGL_IMG_context_priority") ||
986 (HasEGLExtension("EGL_ANDROID_front_buffer_auto_refresh") &&
987 HasEGLExtension("EGL_ANDROID_create_native_client_buffer"));
988
989 #if defined(OS_WIN)
990 // Need EGL_ANGLE_flexible_surface_compatibility to allow surfaces with and
991 // without alpha to be bound to the same context.
992 g_egl_flexible_surface_compatibility_supported =
993 HasEGLExtension("EGL_ANGLE_flexible_surface_compatibility");
994 #endif
995
996 g_egl_display_texture_share_group_supported =
997 HasEGLExtension("EGL_ANGLE_display_texture_share_group");
998 g_egl_display_semaphore_share_group_supported =
999 HasEGLExtension("EGL_ANGLE_display_semaphore_share_group");
1000 g_egl_create_context_client_arrays_supported =
1001 HasEGLExtension("EGL_ANGLE_create_context_client_arrays");
1002 g_egl_robust_resource_init_supported =
1003 HasEGLExtension("EGL_ANGLE_robust_resource_initialization");
1004
1005 // TODO(oetuaho@nvidia.com): Surfaceless is disabled on Android as a temporary
1006 // workaround, since code written for Android WebView takes different paths
1007 // based on whether GL surface objects have underlying EGL surface handles,
1008 // conflicting with the use of surfaceless. See https://crbug.com/382349
1009 #if defined(OS_ANDROID)
1010 DCHECK(!g_egl_surfaceless_context_supported);
1011 #else
1012 // Check if SurfacelessEGL is supported.
1013 g_egl_surfaceless_context_supported =
1014 HasEGLExtension("EGL_KHR_surfaceless_context");
1015 if (g_egl_surfaceless_context_supported) {
1016 // EGL_KHR_surfaceless_context is supported but ensure
1017 // GL_OES_surfaceless_context is also supported. We need a current context
1018 // to query for supported GL extensions.
1019 scoped_refptr<GLSurface> surface = new SurfacelessEGL(gfx::Size(1, 1));
1020 scoped_refptr<GLContext> context = InitializeGLContext(
1021 new GLContextEGL(nullptr), surface.get(), GLContextAttribs());
1022 if (!context || !context->MakeCurrent(surface.get()))
1023 g_egl_surfaceless_context_supported = false;
1024
1025 // Ensure context supports GL_OES_surfaceless_context.
1026 if (g_egl_surfaceless_context_supported) {
1027 g_egl_surfaceless_context_supported =
1028 context->HasExtension("GL_OES_surfaceless_context");
1029 context->ReleaseCurrent(surface.get());
1030 }
1031 }
1032 #endif
1033
1034 // The native fence sync extension is a bit complicated. It's reported as
1035 // present for ChromeOS, but Android currently doesn't report this extension
1036 // even when it's present, and older devices and Android emulator may export
1037 // a useless wrapper function. See crbug.com/775707 for details. In short, if
1038 // the symbol is present and we're on Android N or newer and we are not on
1039 // Android emulator, assume that it's usable even if the extension wasn't
1040 // reported. TODO(https://crbug.com/1086781): Once this is fixed at the
1041 // Android level, update the heuristic to trust the reported extension from
1042 // that version onward.
1043 g_egl_android_native_fence_sync_supported =
1044 HasEGLExtension("EGL_ANDROID_native_fence_sync");
1045 #if defined(OS_ANDROID)
1046 if (!g_egl_android_native_fence_sync_supported &&
1047 base::android::BuildInfo::GetInstance()->sdk_int() >=
1048 base::android::SDK_VERSION_NOUGAT &&
1049 g_driver_egl.fn.eglDupNativeFenceFDANDROIDFn &&
1050 base::SysInfo::GetAndroidHardwareEGL() != "swiftshader" &&
1051 base::SysInfo::GetAndroidHardwareEGL() != "emulation") {
1052 g_egl_android_native_fence_sync_supported = true;
1053 }
1054 #endif
1055
1056 g_egl_ext_pixel_format_float_supported =
1057 HasEGLExtension("EGL_EXT_pixel_format_float");
1058
1059 g_egl_angle_power_preference_supported =
1060 HasEGLExtension("EGL_ANGLE_power_preference");
1061
1062 if (g_egl_angle_power_preference_supported) {
1063 g_egl_gpu_switching_observer = new EGLGpuSwitchingObserver();
1064 ui::GpuSwitchingManager::GetInstance()->AddObserver(
1065 g_egl_gpu_switching_observer);
1066 }
1067
1068 initialized_ = true;
1069 return true;
1070 }
1071
1072 // static
InitializeExtensionSettingsOneOff()1073 bool GLSurfaceEGL::InitializeExtensionSettingsOneOff() {
1074 if (!initialized_)
1075 return false;
1076 g_driver_egl.UpdateConditionalExtensionBindings();
1077 g_egl_extensions = eglQueryString(g_egl_display, EGL_EXTENSIONS);
1078
1079 return true;
1080 }
1081
1082 // static
ShutdownOneOff()1083 void GLSurfaceEGL::ShutdownOneOff() {
1084 if (g_egl_gpu_switching_observer) {
1085 ui::GpuSwitchingManager::GetInstance()->RemoveObserver(
1086 g_egl_gpu_switching_observer);
1087 delete g_egl_gpu_switching_observer;
1088 g_egl_gpu_switching_observer = nullptr;
1089 }
1090
1091 angle::ResetPlatform(g_egl_display);
1092
1093 if (g_egl_display != EGL_NO_DISPLAY) {
1094 DCHECK(g_driver_egl.fn.eglTerminateFn);
1095 eglTerminate(g_egl_display);
1096 }
1097 g_egl_display = EGL_NO_DISPLAY;
1098
1099 g_egl_extensions = nullptr;
1100 g_egl_create_context_robustness_supported = false;
1101 g_egl_robustness_video_memory_purge_supported = false;
1102 g_egl_create_context_bind_generates_resource_supported = false;
1103 g_egl_create_context_webgl_compatability_supported = false;
1104 g_egl_sync_control_supported = false;
1105 g_egl_sync_control_rate_supported = false;
1106 g_egl_window_fixed_size_supported = false;
1107 g_egl_surface_orientation_supported = false;
1108 g_egl_surfaceless_context_supported = false;
1109 g_egl_robust_resource_init_supported = false;
1110 g_egl_display_texture_share_group_supported = false;
1111 g_egl_create_context_client_arrays_supported = false;
1112 g_egl_angle_feature_control_supported = false;
1113
1114 initialized_ = false;
1115 }
1116
1117 // static
GetHardwareDisplay()1118 EGLDisplay GLSurfaceEGL::GetHardwareDisplay() {
1119 return g_egl_display;
1120 }
1121
1122 // static
GetNativeDisplay()1123 EGLNativeDisplayType GLSurfaceEGL::GetNativeDisplay() {
1124 return g_native_display.GetDisplay();
1125 }
1126
1127 // static
GetEGLExtensions()1128 const char* GLSurfaceEGL::GetEGLExtensions() {
1129 return g_egl_extensions;
1130 }
1131
1132 // static
HasEGLExtension(const char * name)1133 bool GLSurfaceEGL::HasEGLExtension(const char* name) {
1134 return ExtensionsContain(GetEGLExtensions(), name);
1135 }
1136
1137 // static
IsCreateContextRobustnessSupported()1138 bool GLSurfaceEGL::IsCreateContextRobustnessSupported() {
1139 return g_egl_create_context_robustness_supported;
1140 }
1141
1142 // static
IsRobustnessVideoMemoryPurgeSupported()1143 bool GLSurfaceEGL::IsRobustnessVideoMemoryPurgeSupported() {
1144 return g_egl_robustness_video_memory_purge_supported;
1145 }
1146
IsCreateContextBindGeneratesResourceSupported()1147 bool GLSurfaceEGL::IsCreateContextBindGeneratesResourceSupported() {
1148 return g_egl_create_context_bind_generates_resource_supported;
1149 }
1150
IsCreateContextWebGLCompatabilitySupported()1151 bool GLSurfaceEGL::IsCreateContextWebGLCompatabilitySupported() {
1152 return g_egl_create_context_webgl_compatability_supported;
1153 }
1154
1155 // static
IsEGLSurfacelessContextSupported()1156 bool GLSurfaceEGL::IsEGLSurfacelessContextSupported() {
1157 return g_egl_surfaceless_context_supported;
1158 }
1159
1160 // static
IsEGLContextPrioritySupported()1161 bool GLSurfaceEGL::IsEGLContextPrioritySupported() {
1162 return g_egl_context_priority_supported;
1163 }
1164
1165 // static
IsEGLFlexibleSurfaceCompatibilitySupported()1166 bool GLSurfaceEGL::IsEGLFlexibleSurfaceCompatibilitySupported() {
1167 return g_egl_flexible_surface_compatibility_supported;
1168 }
1169
IsRobustResourceInitSupported()1170 bool GLSurfaceEGL::IsRobustResourceInitSupported() {
1171 return g_egl_robust_resource_init_supported;
1172 }
1173
IsDisplayTextureShareGroupSupported()1174 bool GLSurfaceEGL::IsDisplayTextureShareGroupSupported() {
1175 return g_egl_display_texture_share_group_supported;
1176 }
1177
IsDisplaySemaphoreShareGroupSupported()1178 bool GLSurfaceEGL::IsDisplaySemaphoreShareGroupSupported() {
1179 return g_egl_display_semaphore_share_group_supported;
1180 }
1181
IsCreateContextClientArraysSupported()1182 bool GLSurfaceEGL::IsCreateContextClientArraysSupported() {
1183 return g_egl_create_context_client_arrays_supported;
1184 }
1185
IsAndroidNativeFenceSyncSupported()1186 bool GLSurfaceEGL::IsAndroidNativeFenceSyncSupported() {
1187 return g_egl_android_native_fence_sync_supported;
1188 }
1189
IsPixelFormatFloatSupported()1190 bool GLSurfaceEGL::IsPixelFormatFloatSupported() {
1191 return g_egl_ext_pixel_format_float_supported;
1192 }
1193
IsANGLEFeatureControlSupported()1194 bool GLSurfaceEGL::IsANGLEFeatureControlSupported() {
1195 return g_egl_angle_feature_control_supported;
1196 }
1197
IsANGLEPowerPreferenceSupported()1198 bool GLSurfaceEGL::IsANGLEPowerPreferenceSupported() {
1199 return g_egl_angle_power_preference_supported;
1200 }
1201
~GLSurfaceEGL()1202 GLSurfaceEGL::~GLSurfaceEGL() {}
1203
1204 // InitializeDisplay is necessary because the static binding code
1205 // needs a full Display init before it can query the Display extensions.
1206 // static
InitializeDisplay(EGLDisplayPlatform native_display)1207 EGLDisplay GLSurfaceEGL::InitializeDisplay(EGLDisplayPlatform native_display) {
1208 if (g_egl_display != EGL_NO_DISPLAY) {
1209 return g_egl_display;
1210 }
1211
1212 g_native_display = native_display;
1213
1214 // If EGL_EXT_client_extensions not supported this call to eglQueryString
1215 // will return NULL.
1216 const char* client_extensions =
1217 eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
1218
1219 bool supports_egl_debug =
1220 client_extensions &&
1221 ExtensionsContain(client_extensions, "EGL_KHR_debug");
1222 if (supports_egl_debug) {
1223 EGLAttrib controls[] = {
1224 EGL_DEBUG_MSG_CRITICAL_KHR,
1225 EGL_TRUE,
1226 EGL_DEBUG_MSG_ERROR_KHR,
1227 EGL_TRUE,
1228 EGL_DEBUG_MSG_WARN_KHR,
1229 EGL_TRUE,
1230 EGL_DEBUG_MSG_INFO_KHR,
1231 EGL_TRUE,
1232 EGL_NONE,
1233 EGL_NONE,
1234 };
1235
1236 eglDebugMessageControlKHR(&LogEGLDebugMessage, controls);
1237 }
1238
1239 bool supports_angle_d3d = false;
1240 bool supports_angle_opengl = false;
1241 bool supports_angle_null = false;
1242 bool supports_angle_vulkan = false;
1243 bool supports_angle_swiftshader = false;
1244 bool supports_angle_egl = false;
1245 bool supports_angle_metal = false;
1246 // Check for availability of ANGLE extensions.
1247 if (client_extensions &&
1248 ExtensionsContain(client_extensions, "EGL_ANGLE_platform_angle")) {
1249 supports_angle_d3d =
1250 ExtensionsContain(client_extensions, "EGL_ANGLE_platform_angle_d3d");
1251 supports_angle_opengl =
1252 ExtensionsContain(client_extensions, "EGL_ANGLE_platform_angle_opengl");
1253 supports_angle_null =
1254 ExtensionsContain(client_extensions, "EGL_ANGLE_platform_angle_null");
1255 supports_angle_vulkan =
1256 ExtensionsContain(client_extensions, "EGL_ANGLE_platform_angle_vulkan");
1257 supports_angle_swiftshader = ExtensionsContain(
1258 client_extensions, "EGL_ANGLE_platform_angle_device_type_swiftshader");
1259 supports_angle_egl = ExtensionsContain(
1260 client_extensions, "EGL_ANGLE_platform_angle_device_type_egl_angle");
1261 supports_angle_metal =
1262 ExtensionsContain(client_extensions, "EGL_ANGLE_platform_angle_metal");
1263 }
1264
1265 bool supports_angle = supports_angle_d3d || supports_angle_opengl ||
1266 supports_angle_null || supports_angle_vulkan ||
1267 supports_angle_swiftshader || supports_angle_metal;
1268
1269 if (client_extensions) {
1270 g_egl_angle_feature_control_supported =
1271 ExtensionsContain(client_extensions, "EGL_ANGLE_feature_control");
1272 }
1273
1274 std::vector<DisplayType> init_displays;
1275 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
1276 GetEGLInitDisplays(supports_angle_d3d, supports_angle_opengl,
1277 supports_angle_null, supports_angle_vulkan,
1278 supports_angle_swiftshader, supports_angle_egl,
1279 supports_angle_metal, command_line, &init_displays);
1280
1281 std::vector<std::string> enabled_angle_features =
1282 GetStringVectorFromCommandLine(command_line,
1283 switches::kEnableANGLEFeatures);
1284 std::vector<std::string> disabled_angle_features =
1285 GetStringVectorFromCommandLine(command_line,
1286 switches::kDisableANGLEFeatures);
1287
1288 bool disable_all_angle_features =
1289 command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds);
1290
1291 for (size_t disp_index = 0; disp_index < init_displays.size(); ++disp_index) {
1292 DisplayType display_type = init_displays[disp_index];
1293 EGLDisplay display = GetDisplayFromType(
1294 display_type, g_native_display, enabled_angle_features,
1295 disabled_angle_features, disable_all_angle_features);
1296 if (display == EGL_NO_DISPLAY) {
1297 LOG(ERROR) << "EGL display query failed with error "
1298 << GetLastEGLErrorString();
1299 }
1300
1301 // Init ANGLE platform now that we have the global display.
1302 if (supports_angle) {
1303 if (!angle::InitializePlatform(display)) {
1304 LOG(ERROR) << "ANGLE Platform initialization failed.";
1305 }
1306
1307 SetANGLEImplementation(
1308 GetANGLEImplementationFromDisplayType(display_type));
1309 }
1310
1311 #if defined(USE_X11)
1312 // Unset DISPLAY env, so the vulkan can be initialized successfully, if the
1313 // X server doesn't support Vulkan surface.
1314 base::Optional<ui::ScopedUnsetDisplay> unset_display;
1315 if (display_type == ANGLE_VULKAN && !ui::IsVulkanSurfaceSupported())
1316 unset_display.emplace();
1317 #endif // defined(USE_X11)
1318
1319 if (!eglInitialize(display, nullptr, nullptr)) {
1320 bool is_last = disp_index == init_displays.size() - 1;
1321
1322 LOG(ERROR) << "eglInitialize " << DisplayTypeString(display_type)
1323 << " failed with error " << GetLastEGLErrorString()
1324 << (is_last ? "" : ", trying next display type");
1325 } else {
1326 UMA_HISTOGRAM_ENUMERATION("GPU.EGLDisplayType", display_type,
1327 DISPLAY_TYPE_MAX);
1328 g_egl_display = display;
1329 break;
1330 }
1331 }
1332
1333 return g_egl_display;
1334 }
1335
NativeViewGLSurfaceEGL(EGLNativeWindowType window,std::unique_ptr<gfx::VSyncProvider> vsync_provider)1336 NativeViewGLSurfaceEGL::NativeViewGLSurfaceEGL(
1337 EGLNativeWindowType window,
1338 std::unique_ptr<gfx::VSyncProvider> vsync_provider)
1339 : window_(window), vsync_provider_external_(std::move(vsync_provider)) {
1340 #if defined(OS_ANDROID)
1341 if (window)
1342 ANativeWindow_acquire(window);
1343 #endif
1344
1345 #if defined(OS_WIN)
1346 RECT windowRect;
1347 if (GetClientRect(window_, &windowRect))
1348 size_ = gfx::Rect(windowRect).size();
1349 #endif
1350 }
1351
Initialize(GLSurfaceFormat format)1352 bool NativeViewGLSurfaceEGL::Initialize(GLSurfaceFormat format) {
1353 DCHECK(!surface_);
1354 format_ = format;
1355
1356 if (!GetDisplay()) {
1357 LOG(ERROR) << "Trying to create surface with invalid display.";
1358 return false;
1359 }
1360
1361 // We need to make sure that window_ is correctly initialized with all
1362 // the platform-dependant quirks, if any, before creating the surface.
1363 if (!InitializeNativeWindow()) {
1364 LOG(ERROR) << "Error trying to initialize the native window.";
1365 return false;
1366 }
1367
1368 std::vector<EGLint> egl_window_attributes;
1369
1370 if (g_egl_window_fixed_size_supported && enable_fixed_size_angle_) {
1371 egl_window_attributes.push_back(EGL_FIXED_SIZE_ANGLE);
1372 egl_window_attributes.push_back(EGL_TRUE);
1373 egl_window_attributes.push_back(EGL_WIDTH);
1374 egl_window_attributes.push_back(size_.width());
1375 egl_window_attributes.push_back(EGL_HEIGHT);
1376 egl_window_attributes.push_back(size_.height());
1377 }
1378
1379 if (g_driver_egl.ext.b_EGL_NV_post_sub_buffer) {
1380 egl_window_attributes.push_back(EGL_POST_SUB_BUFFER_SUPPORTED_NV);
1381 egl_window_attributes.push_back(EGL_TRUE);
1382 }
1383
1384 if (g_egl_surface_orientation_supported) {
1385 EGLint attrib;
1386 eglGetConfigAttrib(GetDisplay(), GetConfig(),
1387 EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE, &attrib);
1388 surface_origin_ = (attrib == EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE)
1389 ? gfx::SurfaceOrigin::kTopLeft
1390 : gfx::SurfaceOrigin::kBottomLeft;
1391 }
1392
1393 if (surface_origin_ == gfx::SurfaceOrigin::kTopLeft) {
1394 egl_window_attributes.push_back(EGL_SURFACE_ORIENTATION_ANGLE);
1395 egl_window_attributes.push_back(EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE);
1396 }
1397
1398 switch (format_.GetColorSpace()) {
1399 case GLSurfaceFormat::COLOR_SPACE_UNSPECIFIED:
1400 break;
1401 case GLSurfaceFormat::COLOR_SPACE_SRGB:
1402 // Note that COLORSPACE_LINEAR refers to the sRGB color space, but
1403 // without opting into sRGB blending. It is equivalent to
1404 // COLORSPACE_SRGB with Disable(FRAMEBUFFER_SRGB).
1405 if (g_egl_khr_colorspace) {
1406 egl_window_attributes.push_back(EGL_GL_COLORSPACE_KHR);
1407 egl_window_attributes.push_back(EGL_GL_COLORSPACE_LINEAR_KHR);
1408 }
1409 break;
1410 case GLSurfaceFormat::COLOR_SPACE_DISPLAY_P3:
1411 // Note that it is not the case that
1412 // COLORSPACE_SRGB is to COLORSPACE_LINEAR_KHR
1413 // as
1414 // COLORSPACE_DISPLAY_P3 is to COLORSPACE_DISPLAY_P3_LINEAR
1415 // COLORSPACE_DISPLAY_P3 is equivalent to COLORSPACE_LINEAR, except with
1416 // with the P3 gamut instead of the the sRGB gamut.
1417 // COLORSPACE_DISPLAY_P3_LINEAR has a linear transfer function, and is
1418 // intended for use with 16-bit formats.
1419 bool p3_supported = g_egl_ext_colorspace_display_p3 ||
1420 g_egl_ext_colorspace_display_p3_passthrough;
1421 if (g_egl_khr_colorspace && p3_supported) {
1422 egl_window_attributes.push_back(EGL_GL_COLORSPACE_KHR);
1423 // Chrome relied on incorrect Android behavior when dealing with P3 /
1424 // framebuffer_srgb interactions. This behavior was fixed in Q, which
1425 // causes invalid Chrome rendering. To achieve Android-P behavior in Q+,
1426 // use EGL_GL_COLORSPACE_P3_PASSTHROUGH_EXT where possible.
1427 if (g_egl_ext_colorspace_display_p3_passthrough) {
1428 egl_window_attributes.push_back(
1429 EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT);
1430 } else {
1431 egl_window_attributes.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_EXT);
1432 }
1433 }
1434 break;
1435 }
1436
1437 egl_window_attributes.push_back(EGL_NONE);
1438 // Create a surface for the native window.
1439 surface_ = eglCreateWindowSurface(
1440 GetDisplay(), GetConfig(), window_, &egl_window_attributes[0]);
1441
1442 if (!surface_) {
1443 LOG(ERROR) << "eglCreateWindowSurface failed with error "
1444 << GetLastEGLErrorString();
1445 Destroy();
1446 return false;
1447 }
1448
1449 if (g_driver_egl.ext.b_EGL_NV_post_sub_buffer) {
1450 EGLint surfaceVal;
1451 EGLBoolean retVal = eglQuerySurface(
1452 GetDisplay(), surface_, EGL_POST_SUB_BUFFER_SUPPORTED_NV, &surfaceVal);
1453 supports_post_sub_buffer_ = (surfaceVal && retVal) == EGL_TRUE;
1454 }
1455
1456 supports_swap_buffer_with_damage_ =
1457 g_driver_egl.ext.b_EGL_KHR_swap_buffers_with_damage;
1458
1459 if (!vsync_provider_external_ && EGLSyncControlVSyncProvider::IsSupported()) {
1460 vsync_provider_internal_ =
1461 std::make_unique<EGLSyncControlVSyncProvider>(surface_);
1462 }
1463
1464 if (!vsync_provider_external_ && !vsync_provider_internal_)
1465 vsync_provider_internal_ = CreateVsyncProviderInternal();
1466
1467 presentation_helper_ =
1468 std::make_unique<GLSurfacePresentationHelper>(GetVSyncProvider());
1469 return true;
1470 }
1471
SupportsSwapTimestamps() const1472 bool NativeViewGLSurfaceEGL::SupportsSwapTimestamps() const {
1473 return g_driver_egl.ext.b_EGL_ANDROID_get_frame_timestamps;
1474 }
1475
SetEnableSwapTimestamps()1476 void NativeViewGLSurfaceEGL::SetEnableSwapTimestamps() {
1477 DCHECK(g_driver_egl.ext.b_EGL_ANDROID_get_frame_timestamps);
1478
1479 // If frame timestamps are supported, set the proper attribute to enable the
1480 // feature and then cache the timestamps supported by the underlying
1481 // implementation. EGL_DISPLAY_PRESENT_TIME_ANDROID support, in particular,
1482 // is spotty.
1483 // Clear the supported timestamps here to protect against Initialize() being
1484 // called twice.
1485 supported_egl_timestamps_.clear();
1486 supported_event_names_.clear();
1487 presentation_feedback_index_ = -1;
1488 composition_start_index_ = -1;
1489
1490 eglSurfaceAttrib(GetDisplay(), surface_, EGL_TIMESTAMPS_ANDROID, EGL_TRUE);
1491
1492 // Check if egl composite interval is supported or not. If not then return.
1493 // Else check which other timestamps are supported.
1494 EGLint interval_name = EGL_COMPOSITE_INTERVAL_ANDROID;
1495 if (!eglGetCompositorTimingSupportedANDROID(GetDisplay(), surface_,
1496 interval_name))
1497 return;
1498
1499 static const struct {
1500 EGLint egl_name;
1501 const char* name;
1502 } all_timestamps[kMaxTimestampsSupportable] = {
1503 {EGL_REQUESTED_PRESENT_TIME_ANDROID, "Queue"},
1504 {EGL_RENDERING_COMPLETE_TIME_ANDROID, "WritesDone"},
1505 {EGL_COMPOSITION_LATCH_TIME_ANDROID, "LatchedForDisplay"},
1506 {EGL_FIRST_COMPOSITION_START_TIME_ANDROID, "1stCompositeCpu"},
1507 {EGL_LAST_COMPOSITION_START_TIME_ANDROID, "NthCompositeCpu"},
1508 {EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID, "GpuCompositeDone"},
1509 {EGL_DISPLAY_PRESENT_TIME_ANDROID, "ScanOutStart"},
1510 {EGL_DEQUEUE_READY_TIME_ANDROID, "DequeueReady"},
1511 {EGL_READS_DONE_TIME_ANDROID, "ReadsDone"},
1512 };
1513
1514 supported_egl_timestamps_.reserve(kMaxTimestampsSupportable);
1515 supported_event_names_.reserve(kMaxTimestampsSupportable);
1516 for (const auto& ts : all_timestamps) {
1517 if (!eglGetFrameTimestampSupportedANDROID(GetDisplay(), surface_,
1518 ts.egl_name))
1519 continue;
1520
1521 // For presentation feedback, prefer the actual scan out time, but fallback
1522 // to SurfaceFlinger's composite time since some devices don't support
1523 // the former.
1524 switch (ts.egl_name) {
1525 case EGL_FIRST_COMPOSITION_START_TIME_ANDROID:
1526 // Value of presentation_feedback_index_ relies on the order of
1527 // all_timestamps.
1528 presentation_feedback_index_ =
1529 static_cast<int>(supported_egl_timestamps_.size());
1530 composition_start_index_ =
1531 static_cast<int>(supported_egl_timestamps_.size());
1532 presentation_flags_ = 0;
1533 break;
1534 case EGL_DISPLAY_PRESENT_TIME_ANDROID:
1535 presentation_feedback_index_ =
1536 static_cast<int>(supported_egl_timestamps_.size());
1537 presentation_flags_ = gfx::PresentationFeedback::kVSync |
1538 gfx::PresentationFeedback::kHWCompletion;
1539 break;
1540 }
1541
1542 // Stored in separate vectors so we can pass the egl timestamps
1543 // directly to the EGL functions.
1544 supported_egl_timestamps_.push_back(ts.egl_name);
1545 supported_event_names_.push_back(ts.name);
1546 }
1547 DCHECK_GE(presentation_feedback_index_, 0);
1548 DCHECK_GE(composition_start_index_, 0);
1549
1550 use_egl_timestamps_ = !supported_egl_timestamps_.empty();
1551 }
1552
InitializeNativeWindow()1553 bool NativeViewGLSurfaceEGL::InitializeNativeWindow() {
1554 return true;
1555 }
1556
Destroy()1557 void NativeViewGLSurfaceEGL::Destroy() {
1558 presentation_helper_ = nullptr;
1559 vsync_provider_internal_ = nullptr;
1560
1561 if (surface_) {
1562 if (!eglDestroySurface(GetDisplay(), surface_)) {
1563 LOG(ERROR) << "eglDestroySurface failed with error "
1564 << GetLastEGLErrorString();
1565 }
1566 surface_ = NULL;
1567 }
1568 }
1569
IsOffscreen()1570 bool NativeViewGLSurfaceEGL::IsOffscreen() {
1571 return false;
1572 }
1573
SwapBuffers(PresentationCallback callback)1574 gfx::SwapResult NativeViewGLSurfaceEGL::SwapBuffers(
1575 PresentationCallback callback) {
1576 TRACE_EVENT2("gpu", "NativeViewGLSurfaceEGL:RealSwapBuffers",
1577 "width", GetSize().width(),
1578 "height", GetSize().height());
1579
1580 if (!CommitAndClearPendingOverlays()) {
1581 DVLOG(1) << "Failed to commit pending overlay planes.";
1582 return gfx::SwapResult::SWAP_FAILED;
1583 }
1584
1585 EGLuint64KHR new_frame_id = 0;
1586 bool new_frame_id_is_valid = true;
1587 if (use_egl_timestamps_) {
1588 new_frame_id_is_valid =
1589 !!eglGetNextFrameIdANDROID(GetDisplay(), surface_, &new_frame_id);
1590 }
1591 if (!new_frame_id_is_valid)
1592 new_frame_id = -1;
1593
1594 GLSurfacePresentationHelper::ScopedSwapBuffers scoped_swap_buffers(
1595 presentation_helper_.get(), std::move(callback), new_frame_id);
1596
1597 if (!eglSwapBuffers(GetDisplay(), surface_)) {
1598 DVLOG(1) << "eglSwapBuffers failed with error "
1599 << GetLastEGLErrorString();
1600 scoped_swap_buffers.set_result(gfx::SwapResult::SWAP_FAILED);
1601 } else if (use_egl_timestamps_) {
1602 UpdateSwapEvents(new_frame_id, new_frame_id_is_valid);
1603 }
1604
1605 return scoped_swap_buffers.result();
1606 }
1607
UpdateSwapEvents(EGLuint64KHR newFrameId,bool newFrameIdIsValid)1608 void NativeViewGLSurfaceEGL::UpdateSwapEvents(EGLuint64KHR newFrameId,
1609 bool newFrameIdIsValid) {
1610 // Queue info for the frame just swapped.
1611 swap_info_queue_.push({newFrameIdIsValid, newFrameId});
1612
1613 // Make sure we have a frame old enough that all it's timstamps should
1614 // be available by now.
1615 constexpr int kFramesAgoToGetServerTimestamps = 4;
1616 if (swap_info_queue_.size() <= kFramesAgoToGetServerTimestamps)
1617 return;
1618
1619 // TraceEvents if needed.
1620 // If we weren't able to get a valid frame id before the swap, we can't get
1621 // its timestamps now.
1622 const SwapInfo& old_swap_info = swap_info_queue_.front();
1623 if (old_swap_info.frame_id_is_valid && g_trace_swap_enabled.Get().value)
1624 TraceSwapEvents(old_swap_info.frame_id);
1625
1626 swap_info_queue_.pop();
1627 }
1628
TraceSwapEvents(EGLuint64KHR oldFrameId)1629 void NativeViewGLSurfaceEGL::TraceSwapEvents(EGLuint64KHR oldFrameId) {
1630 // We shouldn't be calling eglGetFrameTimestampsANDROID with more timestamps
1631 // than it supports.
1632 DCHECK_LE(supported_egl_timestamps_.size(), kMaxTimestampsSupportable);
1633
1634 // Get the timestamps.
1635 std::vector<EGLnsecsANDROID> egl_timestamps(supported_egl_timestamps_.size(),
1636 EGL_TIMESTAMP_INVALID_ANDROID);
1637 if (!eglGetFrameTimestampsANDROID(
1638 GetDisplay(), surface_, oldFrameId,
1639 static_cast<EGLint>(supported_egl_timestamps_.size()),
1640 supported_egl_timestamps_.data(), egl_timestamps.data())) {
1641 TRACE_EVENT_INSTANT0("gpu", "eglGetFrameTimestamps:Failed",
1642 TRACE_EVENT_SCOPE_THREAD);
1643 return;
1644 }
1645
1646 // Track supported and valid time/name pairs.
1647 struct TimeNamePair {
1648 base::TimeTicks time;
1649 const char* name;
1650 };
1651
1652 std::vector<TimeNamePair> tracePairs;
1653 tracePairs.reserve(supported_egl_timestamps_.size());
1654 for (size_t i = 0; i < egl_timestamps.size(); i++) {
1655 // Although a timestamp of 0 is technically valid, we shouldn't expect to
1656 // see it in practice. 0's are more likely due to a known linux kernel bug
1657 // that inadvertently discards timestamp information when merging two
1658 // retired fences.
1659 if (egl_timestamps[i] == 0 ||
1660 egl_timestamps[i] == EGL_TIMESTAMP_INVALID_ANDROID ||
1661 egl_timestamps[i] == EGL_TIMESTAMP_PENDING_ANDROID) {
1662 continue;
1663 }
1664 // TODO(brianderson): Replace FromInternalValue usage.
1665 tracePairs.push_back(
1666 {base::TimeTicks::FromInternalValue(
1667 egl_timestamps[i] / base::TimeTicks::kNanosecondsPerMicrosecond),
1668 supported_event_names_[i]});
1669 }
1670 if (tracePairs.empty()) {
1671 TRACE_EVENT_INSTANT0("gpu", "TraceSwapEvents:NoValidTimestamps",
1672 TRACE_EVENT_SCOPE_THREAD);
1673 return;
1674 }
1675
1676 // Sort the pairs so we can trace them in order.
1677 std::sort(tracePairs.begin(), tracePairs.end(),
1678 [](auto& a, auto& b) { return a.time < b.time; });
1679
1680 // Trace the overall range under which the sub events will be nested.
1681 // Add an epsilon since the trace viewer interprets timestamp ranges
1682 // as closed on the left and open on the right. i.e.: [begin, end).
1683 // The last sub event isn't nested properly without the epsilon.
1684 auto epsilon = base::TimeDelta::FromMicroseconds(1);
1685 static const char* SwapEvents = "SwapEvents";
1686 const int64_t trace_id = oldFrameId;
1687 TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
1688 kSwapEventTraceCategories, SwapEvents, trace_id, tracePairs.front().time);
1689 TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP1(
1690 kSwapEventTraceCategories, SwapEvents, trace_id,
1691 tracePairs.back().time + epsilon, "id", trace_id);
1692
1693 // Trace the first event, which does not have a range before it.
1694 TRACE_EVENT_NESTABLE_ASYNC_INSTANT_WITH_TIMESTAMP0(
1695 kSwapEventTraceCategories, tracePairs.front().name, trace_id,
1696 tracePairs.front().time);
1697
1698 // Trace remaining events and their ranges.
1699 // Use the first characters to represent events still pending.
1700 // This helps color code the remaining events in the viewer, which makes
1701 // it obvious:
1702 // 1) when the order of events are different between frames and
1703 // 2) if multiple events occurred very close together.
1704 std::string valid_symbols(tracePairs.size(), '\0');
1705 for (size_t i = 0; i < valid_symbols.size(); i++)
1706 valid_symbols[i] = tracePairs[i].name[0];
1707
1708 const char* pending_symbols = valid_symbols.c_str();
1709 for (size_t i = 1; i < tracePairs.size(); i++) {
1710 pending_symbols++;
1711 TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
1712 kSwapEventTraceCategories, pending_symbols, trace_id,
1713 tracePairs[i - 1].time);
1714 TRACE_EVENT_COPY_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
1715 kSwapEventTraceCategories, pending_symbols, trace_id,
1716 tracePairs[i].time);
1717 TRACE_EVENT_NESTABLE_ASYNC_INSTANT_WITH_TIMESTAMP0(
1718 kSwapEventTraceCategories, tracePairs[i].name, trace_id,
1719 tracePairs[i].time);
1720 }
1721 }
1722
1723 std::unique_ptr<gfx::VSyncProvider>
CreateVsyncProviderInternal()1724 NativeViewGLSurfaceEGL::CreateVsyncProviderInternal() {
1725 return nullptr;
1726 }
1727
GetSize()1728 gfx::Size NativeViewGLSurfaceEGL::GetSize() {
1729 EGLint width;
1730 EGLint height;
1731 if (!eglQuerySurface(GetDisplay(), surface_, EGL_WIDTH, &width) ||
1732 !eglQuerySurface(GetDisplay(), surface_, EGL_HEIGHT, &height)) {
1733 NOTREACHED() << "eglQuerySurface failed with error "
1734 << GetLastEGLErrorString();
1735 return gfx::Size();
1736 }
1737
1738 return gfx::Size(width, height);
1739 }
1740
Resize(const gfx::Size & size,float scale_factor,const gfx::ColorSpace & color_space,bool has_alpha)1741 bool NativeViewGLSurfaceEGL::Resize(const gfx::Size& size,
1742 float scale_factor,
1743 const gfx::ColorSpace& color_space,
1744 bool has_alpha) {
1745 if (size == GetSize())
1746 return true;
1747 size_ = size;
1748 GLContext* context = GLContext::GetCurrent();
1749 DCHECK(context);
1750 GLSurface* surface = GLSurface::GetCurrent();
1751 DCHECK(surface);
1752 // Current surface may not be |this| if it is wrapped, but it should point to
1753 // the same handle.
1754 DCHECK_EQ(surface->GetHandle(), GetHandle());
1755 context->ReleaseCurrent(surface);
1756 Destroy();
1757 if (!Initialize(format_)) {
1758 LOG(ERROR) << "Failed to resize window.";
1759 return false;
1760 }
1761 if (!context->MakeCurrent(surface)) {
1762 LOG(ERROR) << "Failed to make current in NativeViewGLSurfaceEGL::Resize";
1763 return false;
1764 }
1765 SetVSyncEnabled(vsync_enabled_);
1766 return true;
1767 }
1768
Recreate()1769 bool NativeViewGLSurfaceEGL::Recreate() {
1770 GLContext* context = GLContext::GetCurrent();
1771 DCHECK(context);
1772 GLSurface* surface = GLSurface::GetCurrent();
1773 DCHECK(surface);
1774 // Current surface may not be |this| if it is wrapped, but it should point to
1775 // the same handle.
1776 DCHECK_EQ(surface->GetHandle(), GetHandle());
1777 context->ReleaseCurrent(surface);
1778 Destroy();
1779 if (!Initialize(format_)) {
1780 LOG(ERROR) << "Failed to create surface.";
1781 return false;
1782 }
1783 if (!context->MakeCurrent(surface)) {
1784 LOG(ERROR) << "Failed to make current in NativeViewGLSurfaceEGL::Recreate";
1785 return false;
1786 }
1787 SetVSyncEnabled(vsync_enabled_);
1788 return true;
1789 }
1790
GetHandle()1791 EGLSurface NativeViewGLSurfaceEGL::GetHandle() {
1792 return surface_;
1793 }
1794
SupportsPostSubBuffer()1795 bool NativeViewGLSurfaceEGL::SupportsPostSubBuffer() {
1796 return supports_post_sub_buffer_;
1797 }
1798
GetOrigin() const1799 gfx::SurfaceOrigin NativeViewGLSurfaceEGL::GetOrigin() const {
1800 return surface_origin_;
1801 }
1802
GetEGLTimestampClient()1803 EGLTimestampClient* NativeViewGLSurfaceEGL::GetEGLTimestampClient() {
1804 // This api call is used by GLSurfacePresentationHelper class which is member
1805 // of this class NativeViewGLSurfaceEGL. Hence its guaranteed "this" pointer
1806 // will live longer than the GLSurfacePresentationHelper class.
1807 return this;
1808 }
1809
IsEGLTimestampSupported() const1810 bool NativeViewGLSurfaceEGL::IsEGLTimestampSupported() const {
1811 return use_egl_timestamps_;
1812 }
1813
GetFrameTimestampInfoIfAvailable(base::TimeTicks * presentation_time,base::TimeDelta * composite_interval,uint32_t * presentation_flags,int frame_id)1814 bool NativeViewGLSurfaceEGL::GetFrameTimestampInfoIfAvailable(
1815 base::TimeTicks* presentation_time,
1816 base::TimeDelta* composite_interval,
1817 uint32_t* presentation_flags,
1818 int frame_id) {
1819 DCHECK(presentation_time);
1820 DCHECK(composite_interval);
1821 DCHECK(presentation_flags);
1822
1823 TRACE_EVENT1("gpu", "NativeViewGLSurfaceEGL:GetFrameTimestampInfoIfAvailable",
1824 "frame_id", frame_id);
1825
1826 // Get the composite interval.
1827 EGLint interval_name = EGL_COMPOSITE_INTERVAL_ANDROID;
1828 EGLnsecsANDROID composite_interval_ns = 0;
1829 *presentation_flags = 0;
1830
1831 // If an error is generated, we will treat it as a frame done for timestamp
1832 // reporting purpose.
1833 if (!eglGetCompositorTimingANDROID(GetDisplay(), surface_, 1, &interval_name,
1834 &composite_interval_ns)) {
1835 *composite_interval = base::TimeDelta::FromNanoseconds(
1836 base::TimeTicks::kNanosecondsPerSecond / 60);
1837 // If we couldn't get the correct presentation time due to some errors,
1838 // return the current time.
1839 *presentation_time = base::TimeTicks::Now();
1840 return true;
1841 }
1842
1843 // If the composite interval is pending, the frame is not yet done.
1844 if (composite_interval_ns == EGL_TIMESTAMP_PENDING_ANDROID) {
1845 return false;
1846 }
1847 DCHECK_GT(composite_interval_ns, 0);
1848 *composite_interval = base::TimeDelta::FromNanoseconds(composite_interval_ns);
1849
1850 // Get the all available timestamps for the frame. If a frame is invalid or
1851 // an error is generated, we will treat it as a frame done for timestamp
1852 // reporting purpose.
1853 std::vector<EGLnsecsANDROID> egl_timestamps(supported_egl_timestamps_.size(),
1854 EGL_TIMESTAMP_INVALID_ANDROID);
1855
1856 // TODO(vikassoni): File a driver bug for eglGetFrameTimestampsANDROID().
1857 // See https://bugs.chromium.org/p/chromium/issues/detail?id=966638.
1858 // As per the spec, the driver is expected to return a valid timestamp from
1859 // the call eglGetFrameTimestampsANDROID() when its not
1860 // EGL_TIMESTAMP_PENDING_ANDROID or EGL_TIMESTAMP_INVALID_ANDROID. But
1861 // currently some buggy drivers an invalid timestamp 0.
1862 // This is currentlt handled in chrome for by setting the presentation time to
1863 // TimeTicks::Now() (snapped to the next vsync) instead of 0.
1864 if ((frame_id < 0) ||
1865 !eglGetFrameTimestampsANDROID(
1866 GetDisplay(), surface_, frame_id,
1867 static_cast<EGLint>(supported_egl_timestamps_.size()),
1868 supported_egl_timestamps_.data(), egl_timestamps.data())) {
1869 // If we couldn't get the correct presentation time due to some errors,
1870 // return the current time.
1871 *presentation_time = base::TimeTicks::Now();
1872 return true;
1873 }
1874 DCHECK_GE(presentation_feedback_index_, 0);
1875 DCHECK_GE(composition_start_index_, 0);
1876
1877 // Get the presentation time.
1878 EGLnsecsANDROID presentation_time_ns =
1879 egl_timestamps[presentation_feedback_index_];
1880
1881 // If the presentation time is pending, the frame is not yet done.
1882 if (presentation_time_ns == EGL_TIMESTAMP_PENDING_ANDROID) {
1883 return false;
1884 }
1885 if (presentation_time_ns == EGL_TIMESTAMP_INVALID_ANDROID) {
1886 presentation_time_ns = egl_timestamps[composition_start_index_];
1887 if (presentation_time_ns == EGL_TIMESTAMP_INVALID_ANDROID ||
1888 presentation_time_ns == EGL_TIMESTAMP_PENDING_ANDROID) {
1889 *presentation_time = base::TimeTicks::Now();
1890 } else {
1891 *presentation_time = base::TimeTicks() + base::TimeDelta::FromNanoseconds(
1892 presentation_time_ns);
1893 }
1894 } else {
1895 *presentation_time = base::TimeTicks() +
1896 base::TimeDelta::FromNanoseconds(presentation_time_ns);
1897 *presentation_flags = presentation_flags_;
1898 }
1899 return true;
1900 }
1901
SwapBuffersWithDamage(const std::vector<int> & rects,PresentationCallback callback)1902 gfx::SwapResult NativeViewGLSurfaceEGL::SwapBuffersWithDamage(
1903 const std::vector<int>& rects,
1904 PresentationCallback callback) {
1905 DCHECK(supports_swap_buffer_with_damage_);
1906 if (!CommitAndClearPendingOverlays()) {
1907 DVLOG(1) << "Failed to commit pending overlay planes.";
1908 return gfx::SwapResult::SWAP_FAILED;
1909 }
1910
1911 GLSurfacePresentationHelper::ScopedSwapBuffers scoped_swap_buffers(
1912 presentation_helper_.get(), std::move(callback));
1913 if (!eglSwapBuffersWithDamageKHR(GetDisplay(), surface_,
1914 const_cast<EGLint*>(rects.data()),
1915 static_cast<EGLint>(rects.size() / 4))) {
1916 DVLOG(1) << "eglSwapBuffersWithDamageKHR failed with error "
1917 << GetLastEGLErrorString();
1918 scoped_swap_buffers.set_result(gfx::SwapResult::SWAP_FAILED);
1919 }
1920 return scoped_swap_buffers.result();
1921 }
1922
PostSubBuffer(int x,int y,int width,int height,PresentationCallback callback)1923 gfx::SwapResult NativeViewGLSurfaceEGL::PostSubBuffer(
1924 int x,
1925 int y,
1926 int width,
1927 int height,
1928 PresentationCallback callback) {
1929 TRACE_EVENT2("gpu", "NativeViewGLSurfaceEGL:PostSubBuffer", "width", width,
1930 "height", height);
1931 DCHECK(supports_post_sub_buffer_);
1932 if (!CommitAndClearPendingOverlays()) {
1933 DVLOG(1) << "Failed to commit pending overlay planes.";
1934 return gfx::SwapResult::SWAP_FAILED;
1935 }
1936 if (surface_origin_ == gfx::SurfaceOrigin::kTopLeft) {
1937 // With EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE the contents are rendered
1938 // inverted, but the PostSubBuffer rectangle is still measured from the
1939 // bottom left.
1940 y = GetSize().height() - y - height;
1941 }
1942
1943 GLSurfacePresentationHelper::ScopedSwapBuffers scoped_swap_buffers(
1944 presentation_helper_.get(), std::move(callback));
1945 if (!eglPostSubBufferNV(GetDisplay(), surface_, x, y, width, height)) {
1946 DVLOG(1) << "eglPostSubBufferNV failed with error "
1947 << GetLastEGLErrorString();
1948 scoped_swap_buffers.set_result(gfx::SwapResult::SWAP_FAILED);
1949 }
1950 return scoped_swap_buffers.result();
1951 }
1952
SupportsCommitOverlayPlanes()1953 bool NativeViewGLSurfaceEGL::SupportsCommitOverlayPlanes() {
1954 #if defined(OS_ANDROID)
1955 return true;
1956 #else
1957 return false;
1958 #endif
1959 }
1960
CommitOverlayPlanes(PresentationCallback callback)1961 gfx::SwapResult NativeViewGLSurfaceEGL::CommitOverlayPlanes(
1962 PresentationCallback callback) {
1963 DCHECK(SupportsCommitOverlayPlanes());
1964 // Here we assume that the overlays scheduled on this surface will display
1965 // themselves to the screen right away in |CommitAndClearPendingOverlays|,
1966 // rather than being queued and waiting for a "swap" signal.
1967 GLSurfacePresentationHelper::ScopedSwapBuffers scoped_swap_buffers(
1968 presentation_helper_.get(), std::move(callback));
1969 if (!CommitAndClearPendingOverlays())
1970 scoped_swap_buffers.set_result(gfx::SwapResult::SWAP_FAILED);
1971 return scoped_swap_buffers.result();
1972 }
1973
OnMakeCurrent(GLContext * context)1974 bool NativeViewGLSurfaceEGL::OnMakeCurrent(GLContext* context) {
1975 if (presentation_helper_)
1976 presentation_helper_->OnMakeCurrent(context, this);
1977 return GLSurfaceEGL::OnMakeCurrent(context);
1978 }
1979
GetVSyncProvider()1980 gfx::VSyncProvider* NativeViewGLSurfaceEGL::GetVSyncProvider() {
1981 return vsync_provider_external_ ? vsync_provider_external_.get()
1982 : vsync_provider_internal_.get();
1983 }
1984
SetVSyncEnabled(bool enabled)1985 void NativeViewGLSurfaceEGL::SetVSyncEnabled(bool enabled) {
1986 DCHECK(GLContext::GetCurrent() && GLContext::GetCurrent()->IsCurrent(this));
1987 vsync_enabled_ = enabled;
1988 if (!eglSwapInterval(GetDisplay(), enabled ? 1 : 0)) {
1989 LOG(ERROR) << "eglSwapInterval failed with error "
1990 << GetLastEGLErrorString();
1991 }
1992 }
1993
ScheduleOverlayPlane(int z_order,gfx::OverlayTransform transform,GLImage * image,const gfx::Rect & bounds_rect,const gfx::RectF & crop_rect,bool enable_blend,std::unique_ptr<gfx::GpuFence> gpu_fence)1994 bool NativeViewGLSurfaceEGL::ScheduleOverlayPlane(
1995 int z_order,
1996 gfx::OverlayTransform transform,
1997 GLImage* image,
1998 const gfx::Rect& bounds_rect,
1999 const gfx::RectF& crop_rect,
2000 bool enable_blend,
2001 std::unique_ptr<gfx::GpuFence> gpu_fence) {
2002 #if !defined(OS_ANDROID)
2003 NOTIMPLEMENTED();
2004 return false;
2005 #else
2006 pending_overlays_.push_back(GLSurfaceOverlay(z_order, transform, image,
2007 bounds_rect, crop_rect, true,
2008 std::move(gpu_fence)));
2009 return true;
2010 #endif
2011 }
2012
~NativeViewGLSurfaceEGL()2013 NativeViewGLSurfaceEGL::~NativeViewGLSurfaceEGL() {
2014 Destroy();
2015 #if defined(OS_ANDROID)
2016 if (window_)
2017 ANativeWindow_release(window_);
2018 #endif
2019 }
2020
CommitAndClearPendingOverlays()2021 bool NativeViewGLSurfaceEGL::CommitAndClearPendingOverlays() {
2022 if (pending_overlays_.empty())
2023 return true;
2024
2025 bool success = true;
2026 #if defined(OS_ANDROID)
2027 for (auto& overlay : pending_overlays_)
2028 success &= overlay.ScheduleOverlayPlane(window_);
2029 pending_overlays_.clear();
2030 #else
2031 NOTIMPLEMENTED();
2032 #endif
2033 return success;
2034 }
2035
PbufferGLSurfaceEGL(const gfx::Size & size)2036 PbufferGLSurfaceEGL::PbufferGLSurfaceEGL(const gfx::Size& size)
2037 : size_(size),
2038 surface_(NULL) {
2039 // Some implementations of Pbuffer do not support having a 0 size. For such
2040 // cases use a (1, 1) surface.
2041 if (size_.GetArea() == 0)
2042 size_.SetSize(1, 1);
2043 }
2044
Initialize(GLSurfaceFormat format)2045 bool PbufferGLSurfaceEGL::Initialize(GLSurfaceFormat format) {
2046 EGLSurface old_surface = surface_;
2047
2048 #if defined(OS_ANDROID)
2049 // This is to allow context virtualization which requires on- and offscreen
2050 // to use a compatible config. We expect the client to request RGB565
2051 // onscreen surface also for this to work (with the exception of
2052 // fullscreen video).
2053 if (base::SysInfo::AmountOfPhysicalMemoryMB() <= 512)
2054 format.SetRGB565();
2055 #endif
2056
2057 format_ = format;
2058
2059 EGLDisplay display = GetDisplay();
2060 if (!display) {
2061 LOG(ERROR) << "Trying to create surface with invalid display.";
2062 return false;
2063 }
2064
2065 // Allocate the new pbuffer surface before freeing the old one to ensure
2066 // they have different addresses. If they have the same address then a
2067 // future call to MakeCurrent might early out because it appears the current
2068 // context and surface have not changed.
2069 EGLint pbuffer_attribs[] = {
2070 EGL_WIDTH, size_.width(), EGL_HEIGHT, size_.height(), EGL_NONE,
2071 };
2072
2073 EGLSurface new_surface =
2074 eglCreatePbufferSurface(display, GetConfig(), pbuffer_attribs);
2075 if (!new_surface) {
2076 LOG(ERROR) << "eglCreatePbufferSurface failed with error "
2077 << GetLastEGLErrorString();
2078 return false;
2079 }
2080
2081 if (old_surface)
2082 eglDestroySurface(display, old_surface);
2083
2084 surface_ = new_surface;
2085 return true;
2086 }
2087
Destroy()2088 void PbufferGLSurfaceEGL::Destroy() {
2089 if (surface_) {
2090 if (!eglDestroySurface(GetDisplay(), surface_)) {
2091 LOG(ERROR) << "eglDestroySurface failed with error "
2092 << GetLastEGLErrorString();
2093 }
2094 surface_ = NULL;
2095 }
2096 }
2097
IsOffscreen()2098 bool PbufferGLSurfaceEGL::IsOffscreen() {
2099 return true;
2100 }
2101
SwapBuffers(PresentationCallback callback)2102 gfx::SwapResult PbufferGLSurfaceEGL::SwapBuffers(
2103 PresentationCallback callback) {
2104 NOTREACHED() << "Attempted to call SwapBuffers on a PbufferGLSurfaceEGL.";
2105 return gfx::SwapResult::SWAP_FAILED;
2106 }
2107
GetSize()2108 gfx::Size PbufferGLSurfaceEGL::GetSize() {
2109 return size_;
2110 }
2111
Resize(const gfx::Size & size,float scale_factor,const gfx::ColorSpace & color_space,bool has_alpha)2112 bool PbufferGLSurfaceEGL::Resize(const gfx::Size& size,
2113 float scale_factor,
2114 const gfx::ColorSpace& color_space,
2115 bool has_alpha) {
2116 if (size == size_)
2117 return true;
2118
2119 size_ = size;
2120
2121 GLContext* context = GLContext::GetCurrent();
2122 DCHECK(context);
2123 GLSurface* surface = GLSurface::GetCurrent();
2124 DCHECK(surface);
2125 // Current surface may not be |this| if it is wrapped, but it should point to
2126 // the same handle.
2127 DCHECK_EQ(surface->GetHandle(), GetHandle());
2128 context->ReleaseCurrent(surface);
2129
2130 if (!Initialize(format_)) {
2131 LOG(ERROR) << "Failed to resize pbuffer.";
2132 return false;
2133 }
2134
2135 if (!context->MakeCurrent(surface)) {
2136 LOG(ERROR) << "Failed to make current in PbufferGLSurfaceEGL::Resize";
2137 return false;
2138 }
2139
2140 return true;
2141 }
2142
GetHandle()2143 EGLSurface PbufferGLSurfaceEGL::GetHandle() {
2144 return surface_;
2145 }
2146
GetShareHandle()2147 void* PbufferGLSurfaceEGL::GetShareHandle() {
2148 #if defined(OS_ANDROID)
2149 NOTREACHED();
2150 return NULL;
2151 #else
2152 if (!g_driver_egl.ext.b_EGL_ANGLE_query_surface_pointer)
2153 return NULL;
2154
2155 if (!g_driver_egl.ext.b_EGL_ANGLE_surface_d3d_texture_2d_share_handle)
2156 return NULL;
2157
2158 void* handle;
2159 if (!eglQuerySurfacePointerANGLE(g_egl_display, GetHandle(),
2160 EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE,
2161 &handle)) {
2162 return NULL;
2163 }
2164
2165 return handle;
2166 #endif
2167 }
2168
~PbufferGLSurfaceEGL()2169 PbufferGLSurfaceEGL::~PbufferGLSurfaceEGL() {
2170 Destroy();
2171 }
2172
SurfacelessEGL(const gfx::Size & size)2173 SurfacelessEGL::SurfacelessEGL(const gfx::Size& size) : size_(size) {}
2174
Initialize(GLSurfaceFormat format)2175 bool SurfacelessEGL::Initialize(GLSurfaceFormat format) {
2176 format_ = format;
2177 return true;
2178 }
2179
Destroy()2180 void SurfacelessEGL::Destroy() {
2181 }
2182
IsOffscreen()2183 bool SurfacelessEGL::IsOffscreen() {
2184 return true;
2185 }
2186
IsSurfaceless() const2187 bool SurfacelessEGL::IsSurfaceless() const {
2188 return true;
2189 }
2190
SwapBuffers(PresentationCallback callback)2191 gfx::SwapResult SurfacelessEGL::SwapBuffers(PresentationCallback callback) {
2192 LOG(ERROR) << "Attempted to call SwapBuffers with SurfacelessEGL.";
2193 return gfx::SwapResult::SWAP_FAILED;
2194 }
2195
GetSize()2196 gfx::Size SurfacelessEGL::GetSize() {
2197 return size_;
2198 }
2199
Resize(const gfx::Size & size,float scale_factor,const gfx::ColorSpace & color_space,bool has_alpha)2200 bool SurfacelessEGL::Resize(const gfx::Size& size,
2201 float scale_factor,
2202 const gfx::ColorSpace& color_space,
2203 bool has_alpha) {
2204 size_ = size;
2205 return true;
2206 }
2207
GetHandle()2208 EGLSurface SurfacelessEGL::GetHandle() {
2209 return EGL_NO_SURFACE;
2210 }
2211
GetShareHandle()2212 void* SurfacelessEGL::GetShareHandle() {
2213 return NULL;
2214 }
2215
~SurfacelessEGL()2216 SurfacelessEGL::~SurfacelessEGL() {
2217 }
2218
2219 } // namespace gl
2220