Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / ui / gl / gl_surface_egl.cc
blob61c3c055bd0a573a3d541fd34c6ec054d7bf1507
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>
9 #endif
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"
26 #if defined(USE_X11)
27 extern "C" {
28 #include <X11/Xlib.h>
30 #endif
32 #if defined (USE_OZONE)
33 #include "ui/ozone/public/surface_factory_ozone.h"
34 #endif
36 #if !defined(EGL_FIXED_SIZE_ANGLE)
37 #define EGL_FIXED_SIZE_ANGLE 0x3201
38 #endif
40 #if !defined(EGL_OPENGL_ES3_BIT)
41 #define EGL_OPENGL_ES3_BIT 0x00000040
42 #endif
44 #if defined(OS_WIN)
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 #endif // defined(OS_WIN)
68 using ui::GetLastEGLErrorString;
70 namespace gfx {
72 #if defined(OS_WIN)
73 unsigned int NativeViewGLSurfaceEGL::current_swap_generation_ = 0;
74 unsigned int NativeViewGLSurfaceEGL::swaps_this_generation_ = 0;
75 unsigned int NativeViewGLSurfaceEGL::last_multiswap_generation_ = 0;
77 const unsigned int MULTISWAP_FRAME_VSYNC_THRESHOLD = 60;
78 #endif
80 namespace {
82 EGLConfig g_config;
83 EGLDisplay g_display;
84 EGLNativeDisplayType g_native_display_type;
86 // In the Cast environment, we need to destroy the EGLNativeDisplayType and
87 // EGLDisplay returned by the GPU platform when we switch to an external app
88 // which will temporarily own all screen and GPU resources.
89 // Even though Chromium is still in the background.
90 // As such, it must be reinitialized each time we come back to the foreground.
91 bool g_initialized = false;
92 int g_num_surfaces = 0;
93 bool g_terminate_pending = false;
95 const char* g_egl_extensions = NULL;
96 bool g_egl_create_context_robustness_supported = false;
97 bool g_egl_sync_control_supported = false;
98 bool g_egl_window_fixed_size_supported = false;
99 bool g_egl_surfaceless_context_supported = false;
101 class EGLSyncControlVSyncProvider
102 : public gfx::SyncControlVSyncProvider {
103 public:
104 explicit EGLSyncControlVSyncProvider(EGLSurface surface)
105 : SyncControlVSyncProvider(),
106 surface_(surface) {
109 ~EGLSyncControlVSyncProvider() override {}
111 protected:
112 bool GetSyncValues(int64* system_time,
113 int64* media_stream_counter,
114 int64* swap_buffer_counter) override {
115 uint64 u_system_time, u_media_stream_counter, u_swap_buffer_counter;
116 bool result = eglGetSyncValuesCHROMIUM(
117 g_display, surface_, &u_system_time,
118 &u_media_stream_counter, &u_swap_buffer_counter) == EGL_TRUE;
119 if (result) {
120 *system_time = static_cast<int64>(u_system_time);
121 *media_stream_counter = static_cast<int64>(u_media_stream_counter);
122 *swap_buffer_counter = static_cast<int64>(u_swap_buffer_counter);
124 return result;
127 bool GetMscRate(int32* numerator, int32* denominator) override {
128 return false;
131 private:
132 EGLSurface surface_;
134 DISALLOW_COPY_AND_ASSIGN(EGLSyncControlVSyncProvider);
137 void DeinitializeEgl() {
138 if (g_initialized) {
139 g_initialized = false;
140 eglTerminate(g_display);
144 } // namespace
146 GLSurfaceEGL::GLSurfaceEGL() {
147 ++g_num_surfaces;
148 if (!g_initialized) {
149 bool result = GLSurfaceEGL::InitializeOneOff();
150 DCHECK(result);
151 DCHECK(g_initialized);
155 bool GLSurfaceEGL::InitializeOneOff() {
156 if (g_initialized)
157 return true;
159 g_native_display_type = GetPlatformDefaultEGLNativeDisplay();
161 #if defined(OS_WIN)
162 g_display = GetPlatformDisplay(g_native_display_type);
163 #else
164 g_display = eglGetDisplay(g_native_display_type);
165 #endif
167 if (!g_display) {
168 LOG(ERROR) << "eglGetDisplay failed with error " << GetLastEGLErrorString();
169 return false;
172 if (!eglInitialize(g_display, NULL, NULL)) {
173 LOG(ERROR) << "eglInitialize failed with error " << GetLastEGLErrorString();
174 return false;
177 // Choose an EGL configuration.
178 // On X this is only used for PBuffer surfaces.
179 EGLint renderable_type = EGL_OPENGL_ES2_BIT;
180 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
181 switches::kEnableUnsafeES3APIs)) {
182 renderable_type = EGL_OPENGL_ES3_BIT;
184 const EGLint kConfigAttribs[] = {
185 EGL_BUFFER_SIZE, 32,
186 EGL_ALPHA_SIZE, 8,
187 EGL_BLUE_SIZE, 8,
188 EGL_GREEN_SIZE, 8,
189 EGL_RED_SIZE, 8,
190 EGL_RENDERABLE_TYPE, renderable_type,
191 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
192 EGL_NONE
195 #if defined(USE_OZONE)
196 const EGLint* config_attribs =
197 ui::SurfaceFactoryOzone::GetInstance()->GetEGLSurfaceProperties(
198 kConfigAttribs);
199 #else
200 const EGLint* config_attribs = kConfigAttribs;
201 #endif
203 EGLint num_configs;
204 if (!eglChooseConfig(g_display,
205 config_attribs,
206 NULL,
208 &num_configs)) {
209 LOG(ERROR) << "eglChooseConfig failed with error "
210 << GetLastEGLErrorString();
211 return false;
214 if (num_configs == 0) {
215 LOG(ERROR) << "No suitable EGL configs found.";
216 return false;
219 if (!eglChooseConfig(g_display,
220 config_attribs,
221 &g_config,
223 &num_configs)) {
224 LOG(ERROR) << "eglChooseConfig failed with error "
225 << GetLastEGLErrorString();
226 return false;
229 g_egl_extensions = eglQueryString(g_display, EGL_EXTENSIONS);
230 g_egl_create_context_robustness_supported =
231 HasEGLExtension("EGL_EXT_create_context_robustness");
232 g_egl_sync_control_supported =
233 HasEGLExtension("EGL_CHROMIUM_sync_control");
234 g_egl_window_fixed_size_supported =
235 HasEGLExtension("EGL_ANGLE_window_fixed_size");
237 // We always succeed beyond this point so set g_initialized here to avoid
238 // infinite recursion through CreateGLContext and GetDisplay
239 // if g_egl_surfaceless_context_supported.
240 g_initialized = true;
241 g_terminate_pending = false;
243 // TODO(oetuaho@nvidia.com): Surfaceless is disabled on Android as a temporary
244 // workaround, since code written for Android WebView takes different paths
245 // based on whether GL surface objects have underlying EGL surface handles,
246 // conflicting with the use of surfaceless. See https://crbug.com/382349
247 #if defined(OS_ANDROID)
248 DCHECK(!g_egl_surfaceless_context_supported);
249 #else
250 // Check if SurfacelessEGL is supported.
251 g_egl_surfaceless_context_supported =
252 HasEGLExtension("EGL_KHR_surfaceless_context");
253 if (g_egl_surfaceless_context_supported) {
254 // EGL_KHR_surfaceless_context is supported but ensure
255 // GL_OES_surfaceless_context is also supported. We need a current context
256 // to query for supported GL extensions.
257 scoped_refptr<GLSurface> surface = new SurfacelessEGL(Size(1, 1));
258 scoped_refptr<GLContext> context = GLContext::CreateGLContext(
259 NULL, surface.get(), PreferIntegratedGpu);
260 if (!context->MakeCurrent(surface.get()))
261 g_egl_surfaceless_context_supported = false;
263 // Ensure context supports GL_OES_surfaceless_context.
264 if (g_egl_surfaceless_context_supported) {
265 g_egl_surfaceless_context_supported = context->HasExtension(
266 "GL_OES_surfaceless_context");
267 context->ReleaseCurrent(surface.get());
270 #endif
272 return true;
275 EGLDisplay GLSurfaceEGL::GetDisplay() {
276 DCHECK(g_initialized);
277 return g_display;
280 // static
281 EGLDisplay GLSurfaceEGL::GetHardwareDisplay() {
282 if (!g_initialized) {
283 bool result = GLSurfaceEGL::InitializeOneOff();
284 DCHECK(result);
286 return g_display;
289 // static
290 EGLNativeDisplayType GLSurfaceEGL::GetNativeDisplay() {
291 if (!g_initialized) {
292 bool result = GLSurfaceEGL::InitializeOneOff();
293 DCHECK(result);
295 return g_native_display_type;
298 const char* GLSurfaceEGL::GetEGLExtensions() {
299 // No need for InitializeOneOff. Assume that extensions will not change
300 // after the first initialization.
301 return g_egl_extensions;
304 bool GLSurfaceEGL::HasEGLExtension(const char* name) {
305 return ExtensionsContain(GetEGLExtensions(), name);
308 bool GLSurfaceEGL::IsCreateContextRobustnessSupported() {
309 return g_egl_create_context_robustness_supported;
312 bool GLSurfaceEGL::IsEGLSurfacelessContextSupported() {
313 return g_egl_surfaceless_context_supported;
316 void GLSurfaceEGL::DestroyAndTerminateDisplay() {
317 DCHECK(g_initialized);
318 DCHECK_EQ(g_num_surfaces, 1);
319 Destroy();
320 g_terminate_pending = true;
323 GLSurfaceEGL::~GLSurfaceEGL() {
324 DCHECK_GT(g_num_surfaces, 0) << "Bad surface count";
325 if (--g_num_surfaces == 0 && g_terminate_pending) {
326 DeinitializeEgl();
327 g_terminate_pending = false;
331 #if defined(OS_WIN)
332 static const EGLint kDisplayAttribsWarp[] {
333 EGL_PLATFORM_ANGLE_TYPE_ANGLE,
334 EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
336 EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE,
337 EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE,
339 EGL_NONE
342 // static
343 EGLDisplay GLSurfaceEGL::GetPlatformDisplay(
344 EGLNativeDisplayType native_display) {
345 if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseWarp)) {
346 // Check for availability of WARP via ANGLE extension.
347 bool supports_warp = false;
348 const char* no_display_extensions = eglQueryString(EGL_NO_DISPLAY,
349 EGL_EXTENSIONS);
350 // If EGL_EXT_client_extensions not supported this call to eglQueryString
351 // will return NULL.
352 if (no_display_extensions)
353 supports_warp =
354 ExtensionsContain(no_display_extensions, "ANGLE_platform_angle") &&
355 ExtensionsContain(no_display_extensions, "ANGLE_platform_angle_d3d");
357 if (!supports_warp)
358 return NULL;
360 return eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, native_display,
361 kDisplayAttribsWarp);
364 return eglGetDisplay(native_display);
366 #endif
368 NativeViewGLSurfaceEGL::NativeViewGLSurfaceEGL(EGLNativeWindowType window)
369 : window_(window),
370 surface_(NULL),
371 supports_post_sub_buffer_(false),
372 config_(NULL),
373 size_(1, 1),
374 swap_interval_(1) {
375 #if defined(OS_ANDROID)
376 if (window)
377 ANativeWindow_acquire(window);
378 #endif
380 #if defined(OS_WIN)
381 vsync_override_ = false;
382 swap_generation_ = 0;
383 RECT windowRect;
384 if (GetClientRect(window_, &windowRect))
385 size_ = gfx::Rect(windowRect).size();
386 #endif
389 bool NativeViewGLSurfaceEGL::Initialize() {
390 return Initialize(nullptr);
393 bool NativeViewGLSurfaceEGL::Initialize(
394 scoped_ptr<VSyncProvider> sync_provider) {
395 DCHECK(!surface_);
397 if (!GetDisplay()) {
398 LOG(ERROR) << "Trying to create surface with invalid display.";
399 return false;
402 std::vector<EGLint> egl_window_attributes;
404 if (g_egl_window_fixed_size_supported) {
405 egl_window_attributes.push_back(EGL_FIXED_SIZE_ANGLE);
406 egl_window_attributes.push_back(EGL_TRUE);
407 egl_window_attributes.push_back(EGL_WIDTH);
408 egl_window_attributes.push_back(size_.width());
409 egl_window_attributes.push_back(EGL_HEIGHT);
410 egl_window_attributes.push_back(size_.height());
413 if (gfx::g_driver_egl.ext.b_EGL_NV_post_sub_buffer) {
414 egl_window_attributes.push_back(EGL_POST_SUB_BUFFER_SUPPORTED_NV);
415 egl_window_attributes.push_back(EGL_TRUE);
418 egl_window_attributes.push_back(EGL_NONE);
419 // Create a surface for the native window.
420 surface_ = eglCreateWindowSurface(
421 GetDisplay(), GetConfig(), window_, &egl_window_attributes[0]);
423 if (!surface_) {
424 LOG(ERROR) << "eglCreateWindowSurface failed with error "
425 << GetLastEGLErrorString();
426 Destroy();
427 return false;
430 if (gfx::g_driver_egl.ext.b_EGL_NV_post_sub_buffer) {
431 EGLint surfaceVal;
432 EGLBoolean retVal = eglQuerySurface(
433 GetDisplay(), surface_, EGL_POST_SUB_BUFFER_SUPPORTED_NV, &surfaceVal);
434 supports_post_sub_buffer_ = (surfaceVal && retVal) == EGL_TRUE;
437 if (sync_provider)
438 vsync_provider_.reset(sync_provider.release());
439 else if (g_egl_sync_control_supported)
440 vsync_provider_.reset(new EGLSyncControlVSyncProvider(surface_));
441 return true;
444 void NativeViewGLSurfaceEGL::Destroy() {
445 if (surface_) {
446 if (!eglDestroySurface(GetDisplay(), surface_)) {
447 LOG(ERROR) << "eglDestroySurface failed with error "
448 << GetLastEGLErrorString();
450 surface_ = NULL;
454 EGLConfig NativeViewGLSurfaceEGL::GetConfig() {
455 #if !defined(USE_X11)
456 return g_config;
457 #else
458 if (!config_) {
459 // Get a config compatible with the window
460 DCHECK(window_);
461 XWindowAttributes win_attribs;
462 if (!XGetWindowAttributes(GetNativeDisplay(), window_, &win_attribs)) {
463 return NULL;
466 // Try matching the window depth with an alpha channel,
467 // because we're worried the destination alpha width could
468 // constrain blending precision.
469 const int kBufferSizeOffset = 1;
470 const int kAlphaSizeOffset = 3;
471 EGLint config_attribs[] = {
472 EGL_BUFFER_SIZE, ~0,
473 EGL_ALPHA_SIZE, 8,
474 EGL_BLUE_SIZE, 8,
475 EGL_GREEN_SIZE, 8,
476 EGL_RED_SIZE, 8,
477 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
478 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
479 EGL_NONE
481 config_attribs[kBufferSizeOffset] = win_attribs.depth;
483 EGLint num_configs;
484 if (!eglChooseConfig(g_display,
485 config_attribs,
486 &config_,
488 &num_configs)) {
489 LOG(ERROR) << "eglChooseConfig failed with error "
490 << GetLastEGLErrorString();
491 return NULL;
494 if (num_configs) {
495 EGLint config_depth;
496 if (!eglGetConfigAttrib(g_display,
497 config_,
498 EGL_BUFFER_SIZE,
499 &config_depth)) {
500 LOG(ERROR) << "eglGetConfigAttrib failed with error "
501 << GetLastEGLErrorString();
502 return NULL;
505 if (config_depth == win_attribs.depth) {
506 return config_;
510 // Try without an alpha channel.
511 config_attribs[kAlphaSizeOffset] = 0;
512 if (!eglChooseConfig(g_display,
513 config_attribs,
514 &config_,
516 &num_configs)) {
517 LOG(ERROR) << "eglChooseConfig failed with error "
518 << GetLastEGLErrorString();
519 return NULL;
522 if (num_configs == 0) {
523 LOG(ERROR) << "No suitable EGL configs found.";
524 return NULL;
527 return config_;
528 #endif
531 bool NativeViewGLSurfaceEGL::IsOffscreen() {
532 return false;
535 bool NativeViewGLSurfaceEGL::SwapBuffers() {
536 TRACE_EVENT2("gpu", "NativeViewGLSurfaceEGL:RealSwapBuffers",
537 "width", GetSize().width(),
538 "height", GetSize().height());
540 #if defined(OS_WIN)
541 if (swap_interval_ != 0) {
542 // This code is a simple way of enforcing that we only vsync if one surface
543 // is swapping per frame. This provides single window cases a stable refresh
544 // while allowing multi-window cases to not slow down due to multiple syncs
545 // on a single thread. A better way to fix this problem would be to have
546 // each surface present on its own thread.
548 if (current_swap_generation_ == swap_generation_) {
549 if (swaps_this_generation_ > 1)
550 last_multiswap_generation_ = current_swap_generation_;
551 swaps_this_generation_ = 0;
552 current_swap_generation_++;
555 swap_generation_ = current_swap_generation_;
557 if (swaps_this_generation_ != 0 ||
558 (current_swap_generation_ - last_multiswap_generation_ <
559 MULTISWAP_FRAME_VSYNC_THRESHOLD)) {
560 // Override vsync settings and switch it off
561 if (!vsync_override_) {
562 eglSwapInterval(GetDisplay(), 0);
563 vsync_override_ = true;
565 } else if (vsync_override_) {
566 // Only one window swapping, so let the normal vsync setting take over
567 eglSwapInterval(GetDisplay(), swap_interval_);
568 vsync_override_ = false;
571 swaps_this_generation_++;
573 #endif
575 if (!eglSwapBuffers(GetDisplay(), surface_)) {
576 DVLOG(1) << "eglSwapBuffers failed with error "
577 << GetLastEGLErrorString();
578 return false;
581 return true;
584 gfx::Size NativeViewGLSurfaceEGL::GetSize() {
585 EGLint width;
586 EGLint height;
587 if (!eglQuerySurface(GetDisplay(), surface_, EGL_WIDTH, &width) ||
588 !eglQuerySurface(GetDisplay(), surface_, EGL_HEIGHT, &height)) {
589 NOTREACHED() << "eglQuerySurface failed with error "
590 << GetLastEGLErrorString();
591 return gfx::Size();
594 return gfx::Size(width, height);
597 bool NativeViewGLSurfaceEGL::Resize(const gfx::Size& size) {
598 if (size == GetSize())
599 return true;
601 size_ = size;
603 scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current;
604 GLContext* current_context = GLContext::GetCurrent();
605 bool was_current =
606 current_context && current_context->IsCurrent(this);
607 if (was_current) {
608 scoped_make_current.reset(
609 new ui::ScopedMakeCurrent(current_context, this));
610 current_context->ReleaseCurrent(this);
613 Destroy();
615 if (!Initialize()) {
616 LOG(ERROR) << "Failed to resize window.";
617 return false;
620 return true;
623 bool NativeViewGLSurfaceEGL::Recreate() {
624 Destroy();
625 if (!Initialize()) {
626 LOG(ERROR) << "Failed to create surface.";
627 return false;
629 return true;
632 EGLSurface NativeViewGLSurfaceEGL::GetHandle() {
633 return surface_;
636 bool NativeViewGLSurfaceEGL::SupportsPostSubBuffer() {
637 return supports_post_sub_buffer_;
640 bool NativeViewGLSurfaceEGL::PostSubBuffer(
641 int x, int y, int width, int height) {
642 DCHECK(supports_post_sub_buffer_);
643 if (!eglPostSubBufferNV(GetDisplay(), surface_, x, y, width, height)) {
644 DVLOG(1) << "eglPostSubBufferNV failed with error "
645 << GetLastEGLErrorString();
646 return false;
648 return true;
651 VSyncProvider* NativeViewGLSurfaceEGL::GetVSyncProvider() {
652 return vsync_provider_.get();
655 void NativeViewGLSurfaceEGL::OnSetSwapInterval(int interval) {
656 swap_interval_ = interval;
659 NativeViewGLSurfaceEGL::~NativeViewGLSurfaceEGL() {
660 Destroy();
661 #if defined(OS_ANDROID)
662 if (window_)
663 ANativeWindow_release(window_);
664 #endif
667 PbufferGLSurfaceEGL::PbufferGLSurfaceEGL(const gfx::Size& size)
668 : size_(size),
669 surface_(NULL) {
670 // Some implementations of Pbuffer do not support having a 0 size. For such
671 // cases use a (1, 1) surface.
672 if (size_.GetArea() == 0)
673 size_.SetSize(1, 1);
676 bool PbufferGLSurfaceEGL::Initialize() {
677 EGLSurface old_surface = surface_;
679 EGLDisplay display = GetDisplay();
680 if (!display) {
681 LOG(ERROR) << "Trying to create surface with invalid display.";
682 return false;
685 // Allocate the new pbuffer surface before freeing the old one to ensure
686 // they have different addresses. If they have the same address then a
687 // future call to MakeCurrent might early out because it appears the current
688 // context and surface have not changed.
689 const EGLint pbuffer_attribs[] = {
690 EGL_WIDTH, size_.width(),
691 EGL_HEIGHT, size_.height(),
692 EGL_NONE
695 EGLSurface new_surface = eglCreatePbufferSurface(display,
696 GetConfig(),
697 pbuffer_attribs);
698 if (!new_surface) {
699 LOG(ERROR) << "eglCreatePbufferSurface failed with error "
700 << GetLastEGLErrorString();
701 return false;
704 if (old_surface)
705 eglDestroySurface(display, old_surface);
707 surface_ = new_surface;
708 return true;
711 void PbufferGLSurfaceEGL::Destroy() {
712 if (surface_) {
713 if (!eglDestroySurface(GetDisplay(), surface_)) {
714 LOG(ERROR) << "eglDestroySurface failed with error "
715 << GetLastEGLErrorString();
717 surface_ = NULL;
721 EGLConfig PbufferGLSurfaceEGL::GetConfig() {
722 return g_config;
725 bool PbufferGLSurfaceEGL::IsOffscreen() {
726 return true;
729 bool PbufferGLSurfaceEGL::SwapBuffers() {
730 NOTREACHED() << "Attempted to call SwapBuffers on a PbufferGLSurfaceEGL.";
731 return false;
734 gfx::Size PbufferGLSurfaceEGL::GetSize() {
735 return size_;
738 bool PbufferGLSurfaceEGL::Resize(const gfx::Size& size) {
739 if (size == size_)
740 return true;
742 scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current;
743 GLContext* current_context = GLContext::GetCurrent();
744 bool was_current =
745 current_context && current_context->IsCurrent(this);
746 if (was_current) {
747 scoped_make_current.reset(
748 new ui::ScopedMakeCurrent(current_context, this));
751 size_ = size;
753 if (!Initialize()) {
754 LOG(ERROR) << "Failed to resize pbuffer.";
755 return false;
758 return true;
761 EGLSurface PbufferGLSurfaceEGL::GetHandle() {
762 return surface_;
765 void* PbufferGLSurfaceEGL::GetShareHandle() {
766 #if defined(OS_ANDROID)
767 NOTREACHED();
768 return NULL;
769 #else
770 if (!gfx::g_driver_egl.ext.b_EGL_ANGLE_query_surface_pointer)
771 return NULL;
773 if (!gfx::g_driver_egl.ext.b_EGL_ANGLE_surface_d3d_texture_2d_share_handle)
774 return NULL;
776 void* handle;
777 if (!eglQuerySurfacePointerANGLE(g_display,
778 GetHandle(),
779 EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE,
780 &handle)) {
781 return NULL;
784 return handle;
785 #endif
788 PbufferGLSurfaceEGL::~PbufferGLSurfaceEGL() {
789 Destroy();
792 SurfacelessEGL::SurfacelessEGL(const gfx::Size& size)
793 : size_(size) {
796 bool SurfacelessEGL::Initialize() {
797 return true;
800 void SurfacelessEGL::Destroy() {
803 EGLConfig SurfacelessEGL::GetConfig() {
804 return g_config;
807 bool SurfacelessEGL::IsOffscreen() {
808 return true;
811 bool SurfacelessEGL::IsSurfaceless() const {
812 return true;
815 bool SurfacelessEGL::SwapBuffers() {
816 LOG(ERROR) << "Attempted to call SwapBuffers with SurfacelessEGL.";
817 return false;
820 gfx::Size SurfacelessEGL::GetSize() {
821 return size_;
824 bool SurfacelessEGL::Resize(const gfx::Size& size) {
825 size_ = size;
826 return true;
829 EGLSurface SurfacelessEGL::GetHandle() {
830 return EGL_NO_SURFACE;
833 void* SurfacelessEGL::GetShareHandle() {
834 return NULL;
837 SurfacelessEGL::~SurfacelessEGL() {
840 } // namespace gfx