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.
5 #include "ui/gl/gl_surface_egl.h"
7 #if defined(OS_ANDROID)
8 #include <android/native_window_jni.h>
11 #include "base/command_line.h"
12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/trace_event/trace_event.h"
16 #include "build/build_config.h"
17 #include "ui/gfx/geometry/rect.h"
18 #include "ui/gl/egl_util.h"
19 #include "ui/gl/gl_context.h"
20 #include "ui/gl/gl_implementation.h"
21 #include "ui/gl/gl_surface_stub.h"
22 #include "ui/gl/gl_switches.h"
23 #include "ui/gl/scoped_make_current.h"
24 #include "ui/gl/sync_control_vsync_provider.h"
32 #if defined (USE_OZONE)
33 #include "ui/ozone/public/ozone_platform.h"
34 #include "ui/ozone/public/surface_factory_ozone.h"
37 #if !defined(EGL_FIXED_SIZE_ANGLE)
38 #define EGL_FIXED_SIZE_ANGLE 0x3201
41 #if !defined(EGL_OPENGL_ES3_BIT)
42 #define EGL_OPENGL_ES3_BIT 0x00000040
45 // From ANGLE's egl/eglext.h.
47 #ifndef EGL_ANGLE_platform_angle
48 #define EGL_ANGLE_platform_angle 1
49 #define EGL_PLATFORM_ANGLE_ANGLE 0x3202
50 #define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203
51 #define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3204
52 #define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3205
53 #define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3206
54 #endif /* EGL_ANGLE_platform_angle */
56 #ifndef EGL_ANGLE_platform_angle_d3d
57 #define EGL_ANGLE_platform_angle_d3d 1
58 #define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3207
59 #define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3208
60 #define EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE 0x3209
61 #define EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE 0x320A
62 #define EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE 0x320B
63 #define EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE 0x320C
64 #endif /* EGL_ANGLE_platform_angle_d3d */
66 #ifndef EGL_ANGLE_platform_angle_opengl
67 #define EGL_ANGLE_platform_angle_opengl 1
68 #define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x320D
69 #define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320E
70 #endif /* EGL_ANGLE_platform_angle_opengl */
72 using ui::GetLastEGLErrorString
;
77 unsigned int NativeViewGLSurfaceEGL::current_swap_generation_
= 0;
78 unsigned int NativeViewGLSurfaceEGL::swaps_this_generation_
= 0;
79 unsigned int NativeViewGLSurfaceEGL::last_multiswap_generation_
= 0;
81 const unsigned int MULTISWAP_FRAME_VSYNC_THRESHOLD
= 60;
88 EGLNativeDisplayType g_native_display_type
;
90 // In the Cast environment, we need to destroy the EGLNativeDisplayType and
91 // EGLDisplay returned by the GPU platform when we switch to an external app
92 // which will temporarily own all screen and GPU resources.
93 // Even though Chromium is still in the background.
94 // As such, it must be reinitialized each time we come back to the foreground.
95 bool g_initialized
= false;
96 int g_num_surfaces
= 0;
97 bool g_terminate_pending
= false;
99 const char* g_egl_extensions
= NULL
;
100 bool g_egl_create_context_robustness_supported
= false;
101 bool g_egl_sync_control_supported
= false;
102 bool g_egl_window_fixed_size_supported
= false;
103 bool g_egl_surfaceless_context_supported
= false;
105 class EGLSyncControlVSyncProvider
106 : public gfx::SyncControlVSyncProvider
{
108 explicit EGLSyncControlVSyncProvider(EGLSurface surface
)
109 : SyncControlVSyncProvider(),
113 ~EGLSyncControlVSyncProvider() override
{}
116 bool GetSyncValues(int64
* system_time
,
117 int64
* media_stream_counter
,
118 int64
* swap_buffer_counter
) override
{
119 uint64 u_system_time
, u_media_stream_counter
, u_swap_buffer_counter
;
120 bool result
= eglGetSyncValuesCHROMIUM(
121 g_display
, surface_
, &u_system_time
,
122 &u_media_stream_counter
, &u_swap_buffer_counter
) == EGL_TRUE
;
124 *system_time
= static_cast<int64
>(u_system_time
);
125 *media_stream_counter
= static_cast<int64
>(u_media_stream_counter
);
126 *swap_buffer_counter
= static_cast<int64
>(u_swap_buffer_counter
);
131 bool GetMscRate(int32
* numerator
, int32
* denominator
) override
{
138 DISALLOW_COPY_AND_ASSIGN(EGLSyncControlVSyncProvider
);
141 void DeinitializeEgl() {
143 g_initialized
= false;
144 eglTerminate(g_display
);
148 EGLDisplay
GetPlatformANGLEDisplay(EGLNativeDisplayType native_display
,
149 EGLenum platform_type
,
151 std::vector
<EGLint
> display_attribs
;
153 display_attribs
.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE
);
154 display_attribs
.push_back(platform_type
);
157 display_attribs
.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE
);
158 display_attribs
.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE
);
161 display_attribs
.push_back(EGL_NONE
);
163 return eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE
,
164 reinterpret_cast<void*>(native_display
),
165 &display_attribs
[0]);
168 EGLDisplay
GetDisplayFromType(DisplayType display_type
,
169 EGLNativeDisplayType native_display
) {
170 switch (display_type
) {
173 return eglGetDisplay(native_display
);
175 return GetPlatformANGLEDisplay(native_display
,
176 EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE
, true);
178 return GetPlatformANGLEDisplay(native_display
,
179 EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE
, false);
181 return GetPlatformANGLEDisplay(
182 native_display
, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE
, false);
184 return GetPlatformANGLEDisplay(
185 native_display
, EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE
, false);
187 return GetPlatformANGLEDisplay(
188 native_display
, EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE
, false);
191 return EGL_NO_DISPLAY
;
195 const char* DisplayTypeString(DisplayType display_type
) {
196 switch (display_type
) {
200 return "SwiftShader";
219 void GetEGLInitDisplays(bool supports_angle_d3d
,
220 bool supports_angle_opengl
,
221 const base::CommandLine
* command_line
,
222 std::vector
<DisplayType
>* init_displays
) {
223 // SwiftShader does not use the platform extensions
224 if (command_line
->GetSwitchValueASCII(switches::kUseGL
) ==
225 kGLImplementationSwiftShaderName
) {
226 init_displays
->push_back(SWIFT_SHADER
);
230 std::string requested_renderer
=
231 command_line
->GetSwitchValueASCII(switches::kUseANGLE
);
233 if (supports_angle_d3d
) {
234 bool use_angle_default
=
235 !command_line
->HasSwitch(switches::kUseANGLE
) ||
236 requested_renderer
== kANGLEImplementationDefaultName
;
238 if (use_angle_default
) {
239 // Default mode for ANGLE - try D3D11, else try D3D9
240 if (!command_line
->HasSwitch(switches::kDisableD3D11
)) {
241 init_displays
->push_back(ANGLE_D3D11
);
243 init_displays
->push_back(ANGLE_D3D9
);
245 if (requested_renderer
== kANGLEImplementationD3D11Name
) {
246 init_displays
->push_back(ANGLE_D3D11
);
248 if (requested_renderer
== kANGLEImplementationD3D9Name
) {
249 init_displays
->push_back(ANGLE_D3D9
);
251 if (requested_renderer
== kANGLEImplementationWARPName
) {
252 init_displays
->push_back(ANGLE_WARP
);
257 if (supports_angle_opengl
) {
258 if (requested_renderer
== kANGLEImplementationOpenGLName
) {
259 init_displays
->push_back(ANGLE_OPENGL
);
261 if (requested_renderer
== kANGLEImplementationOpenGLESName
) {
262 init_displays
->push_back(ANGLE_OPENGLES
);
266 // If no displays are available due to missing angle extensions or invalid
267 // flags, request the default display.
268 if (init_displays
->empty()) {
269 init_displays
->push_back(DEFAULT
);
273 GLSurfaceEGL::GLSurfaceEGL() {
275 if (!g_initialized
) {
276 bool result
= GLSurfaceEGL::InitializeOneOff();
278 DCHECK(g_initialized
);
282 bool GLSurfaceEGL::InitializeOneOff() {
287 if (g_display
== EGL_NO_DISPLAY
)
290 // Choose an EGL configuration.
291 // On X this is only used for PBuffer surfaces.
292 EGLint renderable_type
= EGL_OPENGL_ES2_BIT
;
293 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
294 switches::kEnableUnsafeES3APIs
)) {
295 renderable_type
= EGL_OPENGL_ES3_BIT
;
297 const EGLint kConfigAttribs
[] = {
303 EGL_RENDERABLE_TYPE
, renderable_type
,
304 EGL_SURFACE_TYPE
, EGL_WINDOW_BIT
| EGL_PBUFFER_BIT
,
308 #if defined(USE_OZONE)
309 const EGLint
* config_attribs
= ui::OzonePlatform::GetInstance()
310 ->GetSurfaceFactoryOzone()
311 ->GetEGLSurfaceProperties(kConfigAttribs
);
313 const EGLint
* config_attribs
= kConfigAttribs
;
317 if (!eglChooseConfig(g_display
,
322 LOG(ERROR
) << "eglChooseConfig failed with error "
323 << GetLastEGLErrorString();
327 if (num_configs
== 0) {
328 LOG(ERROR
) << "No suitable EGL configs found.";
332 if (!eglChooseConfig(g_display
,
337 LOG(ERROR
) << "eglChooseConfig failed with error "
338 << GetLastEGLErrorString();
342 g_egl_extensions
= eglQueryString(g_display
, EGL_EXTENSIONS
);
343 g_egl_create_context_robustness_supported
=
344 HasEGLExtension("EGL_EXT_create_context_robustness");
345 g_egl_sync_control_supported
=
346 HasEGLExtension("EGL_CHROMIUM_sync_control");
347 g_egl_window_fixed_size_supported
=
348 HasEGLExtension("EGL_ANGLE_window_fixed_size");
350 // We always succeed beyond this point so set g_initialized here to avoid
351 // infinite recursion through CreateGLContext and GetDisplay
352 // if g_egl_surfaceless_context_supported.
353 g_initialized
= true;
354 g_terminate_pending
= false;
356 // TODO(oetuaho@nvidia.com): Surfaceless is disabled on Android as a temporary
357 // workaround, since code written for Android WebView takes different paths
358 // based on whether GL surface objects have underlying EGL surface handles,
359 // conflicting with the use of surfaceless. See https://crbug.com/382349
360 #if defined(OS_ANDROID)
361 DCHECK(!g_egl_surfaceless_context_supported
);
363 // Check if SurfacelessEGL is supported.
364 g_egl_surfaceless_context_supported
=
365 HasEGLExtension("EGL_KHR_surfaceless_context");
366 if (g_egl_surfaceless_context_supported
) {
367 // EGL_KHR_surfaceless_context is supported but ensure
368 // GL_OES_surfaceless_context is also supported. We need a current context
369 // to query for supported GL extensions.
370 scoped_refptr
<GLSurface
> surface
= new SurfacelessEGL(Size(1, 1));
371 scoped_refptr
<GLContext
> context
= GLContext::CreateGLContext(
372 NULL
, surface
.get(), PreferIntegratedGpu
);
373 if (!context
->MakeCurrent(surface
.get()))
374 g_egl_surfaceless_context_supported
= false;
376 // Ensure context supports GL_OES_surfaceless_context.
377 if (g_egl_surfaceless_context_supported
) {
378 g_egl_surfaceless_context_supported
= context
->HasExtension(
379 "GL_OES_surfaceless_context");
380 context
->ReleaseCurrent(surface
.get());
388 EGLDisplay
GLSurfaceEGL::GetDisplay() {
389 DCHECK(g_initialized
);
394 EGLDisplay
GLSurfaceEGL::GetHardwareDisplay() {
395 if (!g_initialized
) {
396 bool result
= GLSurfaceEGL::InitializeOneOff();
403 EGLNativeDisplayType
GLSurfaceEGL::GetNativeDisplay() {
404 if (!g_initialized
) {
405 bool result
= GLSurfaceEGL::InitializeOneOff();
408 return g_native_display_type
;
411 const char* GLSurfaceEGL::GetEGLExtensions() {
412 // No need for InitializeOneOff. Assume that extensions will not change
413 // after the first initialization.
414 return g_egl_extensions
;
417 bool GLSurfaceEGL::HasEGLExtension(const char* name
) {
418 return ExtensionsContain(GetEGLExtensions(), name
);
421 bool GLSurfaceEGL::IsCreateContextRobustnessSupported() {
422 return g_egl_create_context_robustness_supported
;
425 bool GLSurfaceEGL::IsEGLSurfacelessContextSupported() {
426 return g_egl_surfaceless_context_supported
;
429 void GLSurfaceEGL::DestroyAndTerminateDisplay() {
430 DCHECK(g_initialized
);
431 DCHECK_EQ(g_num_surfaces
, 1);
433 g_terminate_pending
= true;
436 GLSurfaceEGL::~GLSurfaceEGL() {
437 DCHECK_GT(g_num_surfaces
, 0) << "Bad surface count";
438 if (--g_num_surfaces
== 0 && g_terminate_pending
) {
440 g_terminate_pending
= false;
444 // InitializeDisplay is necessary because the static binding code
445 // needs a full Display init before it can query the Display extensions.
447 EGLDisplay
GLSurfaceEGL::InitializeDisplay() {
448 if (g_display
!= EGL_NO_DISPLAY
) {
452 g_native_display_type
= GetPlatformDefaultEGLNativeDisplay();
454 // If EGL_EXT_client_extensions not supported this call to eglQueryString
456 const char* client_extensions
=
457 eglQueryString(EGL_NO_DISPLAY
, EGL_EXTENSIONS
);
459 bool supports_angle_d3d
= false;
460 bool supports_angle_opengl
= false;
461 // Check for availability of ANGLE extensions.
462 if (client_extensions
&&
463 ExtensionsContain(client_extensions
, "EGL_ANGLE_platform_angle")) {
465 ExtensionsContain(client_extensions
, "EGL_ANGLE_platform_angle_d3d");
466 supports_angle_opengl
=
467 ExtensionsContain(client_extensions
, "EGL_ANGLE_platform_angle_opengl");
470 std::vector
<DisplayType
> init_displays
;
471 GetEGLInitDisplays(supports_angle_d3d
, supports_angle_opengl
,
472 base::CommandLine::ForCurrentProcess(), &init_displays
);
474 for (size_t disp_index
= 0; disp_index
< init_displays
.size(); ++disp_index
) {
475 DisplayType display_type
= init_displays
[disp_index
];
477 GetDisplayFromType(display_type
, g_native_display_type
);
478 if (display
== EGL_NO_DISPLAY
) {
479 LOG(ERROR
) << "EGL display query failed with error "
480 << GetLastEGLErrorString();
483 if (!eglInitialize(display
, nullptr, nullptr)) {
484 bool is_last
= disp_index
== init_displays
.size() - 1;
486 LOG(ERROR
) << "eglInitialize " << DisplayTypeString(display_type
)
487 << " failed with error " << GetLastEGLErrorString()
488 << (is_last
? "" : ", trying next display type");
498 NativeViewGLSurfaceEGL::NativeViewGLSurfaceEGL(EGLNativeWindowType window
)
501 supports_post_sub_buffer_(false),
505 #if defined(OS_ANDROID)
507 ANativeWindow_acquire(window
);
511 vsync_override_
= false;
512 swap_generation_
= 0;
514 if (GetClientRect(window_
, &windowRect
))
515 size_
= gfx::Rect(windowRect
).size();
519 bool NativeViewGLSurfaceEGL::Initialize() {
520 return Initialize(nullptr);
523 bool NativeViewGLSurfaceEGL::Initialize(
524 scoped_ptr
<VSyncProvider
> sync_provider
) {
528 LOG(ERROR
) << "Trying to create surface with invalid display.";
532 std::vector
<EGLint
> egl_window_attributes
;
534 if (g_egl_window_fixed_size_supported
) {
535 egl_window_attributes
.push_back(EGL_FIXED_SIZE_ANGLE
);
536 egl_window_attributes
.push_back(EGL_TRUE
);
537 egl_window_attributes
.push_back(EGL_WIDTH
);
538 egl_window_attributes
.push_back(size_
.width());
539 egl_window_attributes
.push_back(EGL_HEIGHT
);
540 egl_window_attributes
.push_back(size_
.height());
543 if (gfx::g_driver_egl
.ext
.b_EGL_NV_post_sub_buffer
) {
544 egl_window_attributes
.push_back(EGL_POST_SUB_BUFFER_SUPPORTED_NV
);
545 egl_window_attributes
.push_back(EGL_TRUE
);
548 egl_window_attributes
.push_back(EGL_NONE
);
549 // Create a surface for the native window.
550 surface_
= eglCreateWindowSurface(
551 GetDisplay(), GetConfig(), window_
, &egl_window_attributes
[0]);
554 LOG(ERROR
) << "eglCreateWindowSurface failed with error "
555 << GetLastEGLErrorString();
560 if (gfx::g_driver_egl
.ext
.b_EGL_NV_post_sub_buffer
) {
562 EGLBoolean retVal
= eglQuerySurface(
563 GetDisplay(), surface_
, EGL_POST_SUB_BUFFER_SUPPORTED_NV
, &surfaceVal
);
564 supports_post_sub_buffer_
= (surfaceVal
&& retVal
) == EGL_TRUE
;
568 vsync_provider_
.reset(sync_provider
.release());
569 else if (g_egl_sync_control_supported
)
570 vsync_provider_
.reset(new EGLSyncControlVSyncProvider(surface_
));
574 void NativeViewGLSurfaceEGL::Destroy() {
576 if (!eglDestroySurface(GetDisplay(), surface_
)) {
577 LOG(ERROR
) << "eglDestroySurface failed with error "
578 << GetLastEGLErrorString();
584 EGLConfig
NativeViewGLSurfaceEGL::GetConfig() {
585 #if !defined(USE_X11)
589 // Get a config compatible with the window
591 XWindowAttributes win_attribs
;
592 if (!XGetWindowAttributes(GetNativeDisplay(), window_
, &win_attribs
)) {
596 // Try matching the window depth with an alpha channel,
597 // because we're worried the destination alpha width could
598 // constrain blending precision.
599 const int kBufferSizeOffset
= 1;
600 const int kAlphaSizeOffset
= 3;
601 EGLint config_attribs
[] = {
607 EGL_RENDERABLE_TYPE
, EGL_OPENGL_ES2_BIT
,
608 EGL_SURFACE_TYPE
, EGL_WINDOW_BIT
| EGL_PBUFFER_BIT
,
611 config_attribs
[kBufferSizeOffset
] = win_attribs
.depth
;
614 if (!eglChooseConfig(g_display
,
619 LOG(ERROR
) << "eglChooseConfig failed with error "
620 << GetLastEGLErrorString();
626 if (!eglGetConfigAttrib(g_display
,
630 LOG(ERROR
) << "eglGetConfigAttrib failed with error "
631 << GetLastEGLErrorString();
635 if (config_depth
== win_attribs
.depth
) {
640 // Try without an alpha channel.
641 config_attribs
[kAlphaSizeOffset
] = 0;
642 if (!eglChooseConfig(g_display
,
647 LOG(ERROR
) << "eglChooseConfig failed with error "
648 << GetLastEGLErrorString();
652 if (num_configs
== 0) {
653 LOG(ERROR
) << "No suitable EGL configs found.";
661 bool NativeViewGLSurfaceEGL::IsOffscreen() {
665 gfx::SwapResult
NativeViewGLSurfaceEGL::SwapBuffers() {
666 TRACE_EVENT2("gpu", "NativeViewGLSurfaceEGL:RealSwapBuffers",
667 "width", GetSize().width(),
668 "height", GetSize().height());
671 if (swap_interval_
!= 0) {
672 // This code is a simple way of enforcing that we only vsync if one surface
673 // is swapping per frame. This provides single window cases a stable refresh
674 // while allowing multi-window cases to not slow down due to multiple syncs
675 // on a single thread. A better way to fix this problem would be to have
676 // each surface present on its own thread.
678 if (current_swap_generation_
== swap_generation_
) {
679 if (swaps_this_generation_
> 1)
680 last_multiswap_generation_
= current_swap_generation_
;
681 swaps_this_generation_
= 0;
682 current_swap_generation_
++;
685 swap_generation_
= current_swap_generation_
;
687 if (swaps_this_generation_
!= 0 ||
688 (current_swap_generation_
- last_multiswap_generation_
<
689 MULTISWAP_FRAME_VSYNC_THRESHOLD
)) {
690 // Override vsync settings and switch it off
691 if (!vsync_override_
) {
692 eglSwapInterval(GetDisplay(), 0);
693 vsync_override_
= true;
695 } else if (vsync_override_
) {
696 // Only one window swapping, so let the normal vsync setting take over
697 eglSwapInterval(GetDisplay(), swap_interval_
);
698 vsync_override_
= false;
701 swaps_this_generation_
++;
705 if (!eglSwapBuffers(GetDisplay(), surface_
)) {
706 DVLOG(1) << "eglSwapBuffers failed with error "
707 << GetLastEGLErrorString();
708 return gfx::SwapResult::SWAP_FAILED
;
711 return gfx::SwapResult::SWAP_ACK
;
714 gfx::Size
NativeViewGLSurfaceEGL::GetSize() {
717 if (!eglQuerySurface(GetDisplay(), surface_
, EGL_WIDTH
, &width
) ||
718 !eglQuerySurface(GetDisplay(), surface_
, EGL_HEIGHT
, &height
)) {
719 NOTREACHED() << "eglQuerySurface failed with error "
720 << GetLastEGLErrorString();
724 return gfx::Size(width
, height
);
727 bool NativeViewGLSurfaceEGL::Resize(const gfx::Size
& size
) {
728 if (size
== GetSize())
733 scoped_ptr
<ui::ScopedMakeCurrent
> scoped_make_current
;
734 GLContext
* current_context
= GLContext::GetCurrent();
736 current_context
&& current_context
->IsCurrent(this);
738 scoped_make_current
.reset(
739 new ui::ScopedMakeCurrent(current_context
, this));
740 current_context
->ReleaseCurrent(this);
746 LOG(ERROR
) << "Failed to resize window.";
753 bool NativeViewGLSurfaceEGL::Recreate() {
756 LOG(ERROR
) << "Failed to create surface.";
762 EGLSurface
NativeViewGLSurfaceEGL::GetHandle() {
766 bool NativeViewGLSurfaceEGL::SupportsPostSubBuffer() {
767 return supports_post_sub_buffer_
;
770 gfx::SwapResult
NativeViewGLSurfaceEGL::PostSubBuffer(int x
,
774 DCHECK(supports_post_sub_buffer_
);
775 if (!eglPostSubBufferNV(GetDisplay(), surface_
, x
, y
, width
, height
)) {
776 DVLOG(1) << "eglPostSubBufferNV failed with error "
777 << GetLastEGLErrorString();
778 return gfx::SwapResult::SWAP_FAILED
;
780 return gfx::SwapResult::SWAP_ACK
;
783 VSyncProvider
* NativeViewGLSurfaceEGL::GetVSyncProvider() {
784 return vsync_provider_
.get();
787 void NativeViewGLSurfaceEGL::OnSetSwapInterval(int interval
) {
788 swap_interval_
= interval
;
791 NativeViewGLSurfaceEGL::~NativeViewGLSurfaceEGL() {
793 #if defined(OS_ANDROID)
795 ANativeWindow_release(window_
);
799 PbufferGLSurfaceEGL::PbufferGLSurfaceEGL(const gfx::Size
& size
)
802 // Some implementations of Pbuffer do not support having a 0 size. For such
803 // cases use a (1, 1) surface.
804 if (size_
.GetArea() == 0)
808 bool PbufferGLSurfaceEGL::Initialize() {
809 EGLSurface old_surface
= surface_
;
811 EGLDisplay display
= GetDisplay();
813 LOG(ERROR
) << "Trying to create surface with invalid display.";
817 // Allocate the new pbuffer surface before freeing the old one to ensure
818 // they have different addresses. If they have the same address then a
819 // future call to MakeCurrent might early out because it appears the current
820 // context and surface have not changed.
821 const EGLint pbuffer_attribs
[] = {
822 EGL_WIDTH
, size_
.width(),
823 EGL_HEIGHT
, size_
.height(),
827 EGLSurface new_surface
= eglCreatePbufferSurface(display
,
831 LOG(ERROR
) << "eglCreatePbufferSurface failed with error "
832 << GetLastEGLErrorString();
837 eglDestroySurface(display
, old_surface
);
839 surface_
= new_surface
;
843 void PbufferGLSurfaceEGL::Destroy() {
845 if (!eglDestroySurface(GetDisplay(), surface_
)) {
846 LOG(ERROR
) << "eglDestroySurface failed with error "
847 << GetLastEGLErrorString();
853 EGLConfig
PbufferGLSurfaceEGL::GetConfig() {
857 bool PbufferGLSurfaceEGL::IsOffscreen() {
861 gfx::SwapResult
PbufferGLSurfaceEGL::SwapBuffers() {
862 NOTREACHED() << "Attempted to call SwapBuffers on a PbufferGLSurfaceEGL.";
863 return gfx::SwapResult::SWAP_FAILED
;
866 gfx::Size
PbufferGLSurfaceEGL::GetSize() {
870 bool PbufferGLSurfaceEGL::Resize(const gfx::Size
& size
) {
874 scoped_ptr
<ui::ScopedMakeCurrent
> scoped_make_current
;
875 GLContext
* current_context
= GLContext::GetCurrent();
877 current_context
&& current_context
->IsCurrent(this);
879 scoped_make_current
.reset(
880 new ui::ScopedMakeCurrent(current_context
, this));
886 LOG(ERROR
) << "Failed to resize pbuffer.";
893 EGLSurface
PbufferGLSurfaceEGL::GetHandle() {
897 void* PbufferGLSurfaceEGL::GetShareHandle() {
898 #if defined(OS_ANDROID)
902 if (!gfx::g_driver_egl
.ext
.b_EGL_ANGLE_query_surface_pointer
)
905 if (!gfx::g_driver_egl
.ext
.b_EGL_ANGLE_surface_d3d_texture_2d_share_handle
)
909 if (!eglQuerySurfacePointerANGLE(g_display
,
911 EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE
,
920 PbufferGLSurfaceEGL::~PbufferGLSurfaceEGL() {
924 SurfacelessEGL::SurfacelessEGL(const gfx::Size
& size
)
928 bool SurfacelessEGL::Initialize() {
932 void SurfacelessEGL::Destroy() {
935 EGLConfig
SurfacelessEGL::GetConfig() {
939 bool SurfacelessEGL::IsOffscreen() {
943 bool SurfacelessEGL::IsSurfaceless() const {
947 gfx::SwapResult
SurfacelessEGL::SwapBuffers() {
948 LOG(ERROR
) << "Attempted to call SwapBuffers with SurfacelessEGL.";
949 return gfx::SwapResult::SWAP_FAILED
;
952 gfx::Size
SurfacelessEGL::GetSize() {
956 bool SurfacelessEGL::Resize(const gfx::Size
& size
) {
961 EGLSurface
SurfacelessEGL::GetHandle() {
962 return EGL_NO_SURFACE
;
965 void* SurfacelessEGL::GetShareHandle() {
969 SurfacelessEGL::~SurfacelessEGL() {