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