Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / ui / gl / gl_surface_egl.cc
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 // This include must be here so that the includes provided transitively
6 // by gl_surface_egl.h don't make it impossible to compile this code.
7 #include "third_party/mesa/src/include/GL/osmesa.h"
8
9 #include "ui/gl/gl_surface_egl.h"
10
11 #if defined(OS_ANDROID)
12 #include <android/native_window_jni.h>
13 #include "base/android/sys_utils.h"
14 #endif
15
16 #include "base/command_line.h"
17 #include "base/debug/trace_event.h"
18 #include "base/logging.h"
19 #include "base/memory/scoped_ptr.h"
20 #include "base/message_loop/message_loop.h"
21 #include "build/build_config.h"
22 #include "ui/gl/egl_util.h"
23 #include "ui/gl/gl_context.h"
24 #include "ui/gl/gl_implementation.h"
25 #include "ui/gl/gl_surface_osmesa.h"
26 #include "ui/gl/gl_surface_stub.h"
27 #include "ui/gl/gl_switches.h"
28 #include "ui/gl/scoped_make_current.h"
29 #include "ui/gl/sync_control_vsync_provider.h"
30
31 #if defined(USE_X11)
32 extern "C" {
33 #include <X11/Xlib.h>
34 }
35 #endif
36
37 #if defined (USE_OZONE)
38 #include "ui/gfx/ozone/surface_factory_ozone.h"
39 #endif
40
41 // From ANGLE's egl/eglext.h.
42 #if !defined(EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE)
43 #define EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE \
44     reinterpret_cast<EGLNativeDisplayType>(-2)
45 #endif
46 #if !defined(EGL_FIXED_SIZE_ANGLE)
47 #define EGL_FIXED_SIZE_ANGLE 0x3201
48 #endif
49
50 using ui::GetLastEGLErrorString;
51
52 namespace gfx {
53
54 namespace {
55
56 EGLConfig g_config;
57 EGLDisplay g_display;
58 EGLNativeDisplayType g_native_display;
59
60 const char* g_egl_extensions = NULL;
61 bool g_egl_create_context_robustness_supported = false;
62 bool g_egl_sync_control_supported = false;
63 bool g_egl_window_fixed_size_supported = false;
64 bool g_egl_surfaceless_context_supported = false;
65
66 class EGLSyncControlVSyncProvider
67     : public gfx::SyncControlVSyncProvider {
68  public:
69   explicit EGLSyncControlVSyncProvider(EGLSurface surface)
70       : SyncControlVSyncProvider(),
71         surface_(surface) {
72   }
73
74   virtual ~EGLSyncControlVSyncProvider() { }
75
76  protected:
77   virtual bool GetSyncValues(int64* system_time,
78                              int64* media_stream_counter,
79                              int64* swap_buffer_counter) OVERRIDE {
80     uint64 u_system_time, u_media_stream_counter, u_swap_buffer_counter;
81     bool result = eglGetSyncValuesCHROMIUM(
82         g_display, surface_, &u_system_time,
83         &u_media_stream_counter, &u_swap_buffer_counter) == EGL_TRUE;
84     if (result) {
85       *system_time = static_cast<int64>(u_system_time);
86       *media_stream_counter = static_cast<int64>(u_media_stream_counter);
87       *swap_buffer_counter = static_cast<int64>(u_swap_buffer_counter);
88     }
89     return result;
90   }
91
92   virtual bool GetMscRate(int32* numerator, int32* denominator) OVERRIDE {
93     return false;
94   }
95
96  private:
97   EGLSurface surface_;
98
99   DISALLOW_COPY_AND_ASSIGN(EGLSyncControlVSyncProvider);
100 };
101
102 bool ValidateEglConfig(EGLDisplay display,
103                        const EGLint* config_attribs,
104                        EGLint* num_configs) {
105   if (!eglChooseConfig(display,
106                        config_attribs,
107                        NULL,
108                        0,
109                        num_configs)) {
110     LOG(ERROR) << "eglChooseConfig failed with error "
111                << GetLastEGLErrorString();
112     return false;
113   }
114   if (*num_configs == 0) {
115     LOG(ERROR) << "No suitable EGL configs found.";
116     return false;
117   }
118   return true;
119 }
120
121 }  // namespace
122
123 GLSurfaceEGL::GLSurfaceEGL() {}
124
125 bool GLSurfaceEGL::InitializeOneOff() {
126   static bool initialized = false;
127   if (initialized)
128     return true;
129
130 #if defined(USE_X11)
131   g_native_display = base::MessagePumpForUI::GetDefaultXDisplay();
132 #elif defined(OS_WIN)
133   g_native_display = EGL_DEFAULT_DISPLAY;
134   if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableD3D11) &&
135       CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableD3D11)) {
136     g_native_display = EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE;
137   }
138 #elif defined(USE_OZONE)
139   gfx::SurfaceFactoryOzone* surface_factory =
140       gfx::SurfaceFactoryOzone::GetInstance();
141   if (surface_factory->InitializeHardware() !=
142       gfx::SurfaceFactoryOzone::INITIALIZED) {
143     LOG(ERROR) << "OZONE failed to initialize hardware";
144     return false;
145   }
146   g_native_display = surface_factory->GetNativeDisplay();
147 #else
148   g_native_display = EGL_DEFAULT_DISPLAY;
149 #endif
150   g_display = eglGetDisplay(g_native_display);
151   if (!g_display) {
152     LOG(ERROR) << "eglGetDisplay failed with error " << GetLastEGLErrorString();
153     return false;
154   }
155
156   if (!eglInitialize(g_display, NULL, NULL)) {
157     LOG(ERROR) << "eglInitialize failed with error " << GetLastEGLErrorString();
158     return false;
159   }
160
161   // Choose an EGL configuration.
162   // On X this is only used for PBuffer surfaces.
163   static EGLint config_attribs_8888[] = {
164     EGL_BUFFER_SIZE, 32,
165     EGL_ALPHA_SIZE, 8,
166     EGL_BLUE_SIZE, 8,
167     EGL_GREEN_SIZE, 8,
168     EGL_RED_SIZE, 8,
169     EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
170     EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
171     EGL_NONE
172   };
173
174 #if defined(OS_ANDROID)
175   static EGLint config_attribs_565[] = {
176     EGL_BUFFER_SIZE, 16,
177     EGL_BLUE_SIZE, 5,
178     EGL_GREEN_SIZE, 6,
179     EGL_RED_SIZE, 5,
180     EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
181     EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
182     EGL_NONE
183   };
184 #endif
185   EGLint* choose_attributes = config_attribs_8888;
186
187 #if defined(OS_ANDROID)
188   if (base::android::SysUtils::IsLowEndDevice()) {
189     choose_attributes = config_attribs_565;
190   }
191 #endif
192
193 #if defined(USE_OZONE)
194   const EGLint* config_attribs =
195       surface_factory->GetEGLSurfaceProperties(choose_attributes);
196 #else
197   const EGLint* config_attribs = choose_attributes;
198 #endif
199
200   EGLint num_configs;
201   EGLint config_size = 1;
202   EGLConfig* config_data = &g_config;
203   // Validate if there are any configs for given atrribs.
204   if (!ValidateEglConfig(g_display,
205                          config_attribs,
206                          &num_configs)) {
207     return false;
208   }
209
210 #if defined(OS_ANDROID)
211   scoped_ptr<EGLConfig[]> matching_configs(new EGLConfig[num_configs]);
212   if (base::android::SysUtils::IsLowEndDevice()) {
213     config_size = num_configs;
214     config_data = matching_configs.get();
215   }
216 #endif
217
218   if (!eglChooseConfig(g_display,
219                        config_attribs,
220                        config_data,
221                        config_size,
222                        &num_configs)) {
223     LOG(ERROR) << "eglChooseConfig failed with error "
224                << GetLastEGLErrorString();
225     return false;
226   }
227
228 #if defined(OS_ANDROID)
229   if (base::android::SysUtils::IsLowEndDevice()) {
230     // Because of the EGL config sort order, we have to iterate
231     // through all of them (it'll put higher sum(R,G,B) bits
232     // first with the above attribs).
233     bool match_found = false;
234     for (int i = 0; i < num_configs; i++) {
235       EGLBoolean success;
236       EGLint red, green, blue;
237       // Read the relevent attributes of the EGLConfig.
238       success = eglGetConfigAttrib(g_display, matching_configs[i],
239                                    EGL_RED_SIZE, &red);
240       success &= eglGetConfigAttrib(g_display, matching_configs[i],
241                                     EGL_BLUE_SIZE, &blue);
242       success &= eglGetConfigAttrib(g_display, matching_configs[i],
243                                     EGL_GREEN_SIZE, &green);
244       if ((success == EGL_TRUE) && (red == 5) &&
245           (green == 6) && (blue == 5)) {
246         g_config = matching_configs[i];
247         match_found = true;
248         break;
249       }
250     }
251     if (!match_found) {
252       // To fall back to default 32 bit format, choose with
253       // the right attributes again.
254       if (!ValidateEglConfig(g_display,
255                              config_attribs_8888,
256                              &num_configs)) {
257         return false;
258       }
259       if (!eglChooseConfig(g_display,
260                            config_attribs_8888,
261                            &g_config,
262                            1,
263                            &num_configs)) {
264         LOG(ERROR) << "eglChooseConfig failed with error "
265                    << GetLastEGLErrorString();
266         return false;
267       }
268     }
269   }
270
271 #endif
272
273   g_egl_extensions = eglQueryString(g_display, EGL_EXTENSIONS);
274   g_egl_create_context_robustness_supported =
275       HasEGLExtension("EGL_EXT_create_context_robustness");
276   g_egl_sync_control_supported =
277       HasEGLExtension("EGL_CHROMIUM_sync_control");
278   g_egl_window_fixed_size_supported =
279       HasEGLExtension("EGL_ANGLE_window_fixed_size");
280
281   // Check if SurfacelessEGL is supported.
282   g_egl_surfaceless_context_supported =
283       HasEGLExtension("EGL_KHR_surfaceless_context");
284   if (g_egl_surfaceless_context_supported) {
285     // EGL_KHR_surfaceless_context is supported but ensure
286     // GL_OES_surfaceless_context is also supported. We need a current context
287     // to query for supported GL extensions.
288     scoped_refptr<GLSurface> surface = new SurfacelessEGL(Size(1, 1));
289     scoped_refptr<GLContext> context = GLContext::CreateGLContext(
290       NULL, surface.get(), PreferIntegratedGpu);
291     if (!context->MakeCurrent(surface.get()))
292       g_egl_surfaceless_context_supported = false;
293
294     // Ensure context supports GL_OES_surfaceless_context.
295     if (g_egl_surfaceless_context_supported) {
296       g_egl_surfaceless_context_supported = context->HasExtension(
297           "GL_OES_surfaceless_context");
298       context->ReleaseCurrent(surface.get());
299     }
300   }
301
302   initialized = true;
303
304   return true;
305 }
306
307 EGLDisplay GLSurfaceEGL::GetDisplay() {
308   return g_display;
309 }
310
311 EGLDisplay GLSurfaceEGL::GetHardwareDisplay() {
312   return g_display;
313 }
314
315 EGLNativeDisplayType GLSurfaceEGL::GetNativeDisplay() {
316   return g_native_display;
317 }
318
319 const char* GLSurfaceEGL::GetEGLExtensions() {
320   return g_egl_extensions;
321 }
322
323 bool GLSurfaceEGL::HasEGLExtension(const char* name) {
324   return ExtensionsContain(GetEGLExtensions(), name);
325 }
326
327 bool GLSurfaceEGL::IsCreateContextRobustnessSupported() {
328   return g_egl_create_context_robustness_supported;
329 }
330
331 GLSurfaceEGL::~GLSurfaceEGL() {}
332
333 NativeViewGLSurfaceEGL::NativeViewGLSurfaceEGL(gfx::AcceleratedWidget window)
334     : window_(window),
335       surface_(NULL),
336       supports_post_sub_buffer_(false),
337       config_(NULL),
338       size_(1, 1) {
339 #if defined(OS_ANDROID)
340   if (window)
341     ANativeWindow_acquire(window);
342 #endif
343 }
344
345 bool NativeViewGLSurfaceEGL::Initialize() {
346   return Initialize(scoped_ptr<VSyncProvider>());
347 }
348
349 bool NativeViewGLSurfaceEGL::Initialize(
350     scoped_ptr<VSyncProvider> sync_provider) {
351   DCHECK(!surface_);
352
353   if (window_ == kNullAcceleratedWidget) {
354     LOG(ERROR) << "Trying to create surface without window.";
355     return false;
356   }
357
358   if (!GetDisplay()) {
359     LOG(ERROR) << "Trying to create surface with invalid display.";
360     return false;
361   }
362
363   std::vector<EGLint> egl_window_attributes;
364
365   if (g_egl_window_fixed_size_supported) {
366     egl_window_attributes.push_back(EGL_FIXED_SIZE_ANGLE);
367     egl_window_attributes.push_back(EGL_TRUE);
368     egl_window_attributes.push_back(EGL_WIDTH);
369     egl_window_attributes.push_back(size_.width());
370     egl_window_attributes.push_back(EGL_HEIGHT);
371     egl_window_attributes.push_back(size_.height());
372   }
373
374   if (gfx::g_driver_egl.ext.b_EGL_NV_post_sub_buffer) {
375     egl_window_attributes.push_back(EGL_POST_SUB_BUFFER_SUPPORTED_NV);
376     egl_window_attributes.push_back(EGL_TRUE);
377   }
378
379   egl_window_attributes.push_back(EGL_NONE);
380   // Create a surface for the native window.
381   surface_ = eglCreateWindowSurface(
382       GetDisplay(), GetConfig(), window_, &egl_window_attributes[0]);
383
384   if (!surface_) {
385     LOG(ERROR) << "eglCreateWindowSurface failed with error "
386                << GetLastEGLErrorString();
387     Destroy();
388     return false;
389   }
390
391   EGLint surfaceVal;
392   EGLBoolean retVal = eglQuerySurface(GetDisplay(),
393                                       surface_,
394                                       EGL_POST_SUB_BUFFER_SUPPORTED_NV,
395                                       &surfaceVal);
396   supports_post_sub_buffer_ = (surfaceVal && retVal) == EGL_TRUE;
397
398   if (sync_provider)
399     vsync_provider_.reset(sync_provider.release());
400   else if (g_egl_sync_control_supported)
401     vsync_provider_.reset(new EGLSyncControlVSyncProvider(surface_));
402   return true;
403 }
404
405 void NativeViewGLSurfaceEGL::Destroy() {
406   if (surface_) {
407     if (!eglDestroySurface(GetDisplay(), surface_)) {
408       LOG(ERROR) << "eglDestroySurface failed with error "
409                  << GetLastEGLErrorString();
410     }
411     surface_ = NULL;
412   }
413 }
414
415 EGLConfig NativeViewGLSurfaceEGL::GetConfig() {
416 #if !defined(USE_X11)
417   return g_config;
418 #else
419   if (!config_) {
420     // Get a config compatible with the window
421     DCHECK(window_);
422     XWindowAttributes win_attribs;
423     if (!XGetWindowAttributes(GetNativeDisplay(), window_, &win_attribs)) {
424       return NULL;
425     }
426
427     // Try matching the window depth with an alpha channel,
428     // because we're worried the destination alpha width could
429     // constrain blending precision.
430     const int kBufferSizeOffset = 1;
431     const int kAlphaSizeOffset = 3;
432     EGLint config_attribs[] = {
433       EGL_BUFFER_SIZE, ~0,
434       EGL_ALPHA_SIZE, 8,
435       EGL_BLUE_SIZE, 8,
436       EGL_GREEN_SIZE, 8,
437       EGL_RED_SIZE, 8,
438       EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
439       EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
440       EGL_NONE
441     };
442     config_attribs[kBufferSizeOffset] = win_attribs.depth;
443
444     EGLint num_configs;
445     if (!eglChooseConfig(g_display,
446                          config_attribs,
447                          &config_,
448                          1,
449                          &num_configs)) {
450       LOG(ERROR) << "eglChooseConfig failed with error "
451                  << GetLastEGLErrorString();
452       return NULL;
453     }
454
455     if (num_configs) {
456       EGLint config_depth;
457       if (!eglGetConfigAttrib(g_display,
458                               config_,
459                               EGL_BUFFER_SIZE,
460                               &config_depth)) {
461         LOG(ERROR) << "eglGetConfigAttrib failed with error "
462                    << GetLastEGLErrorString();
463         return NULL;
464       }
465
466       if (config_depth == win_attribs.depth) {
467         return config_;
468       }
469     }
470
471     // Try without an alpha channel.
472     config_attribs[kAlphaSizeOffset] = 0;
473     if (!eglChooseConfig(g_display,
474                          config_attribs,
475                          &config_,
476                          1,
477                          &num_configs)) {
478       LOG(ERROR) << "eglChooseConfig failed with error "
479                  << GetLastEGLErrorString();
480       return NULL;
481     }
482
483     if (num_configs == 0) {
484       LOG(ERROR) << "No suitable EGL configs found.";
485       return NULL;
486     }
487   }
488   return config_;
489 #endif
490 }
491
492 bool NativeViewGLSurfaceEGL::IsOffscreen() {
493   return false;
494 }
495
496 bool NativeViewGLSurfaceEGL::SwapBuffers() {
497   TRACE_EVENT2("gpu", "NativeViewGLSurfaceEGL:RealSwapBuffers",
498       "width", GetSize().width(),
499       "height", GetSize().height());
500
501   if (!eglSwapBuffers(GetDisplay(), surface_)) {
502     DVLOG(1) << "eglSwapBuffers failed with error "
503              << GetLastEGLErrorString();
504     return false;
505   }
506
507   return true;
508 }
509
510 gfx::Size NativeViewGLSurfaceEGL::GetSize() {
511   EGLint width;
512   EGLint height;
513   if (!eglQuerySurface(GetDisplay(), surface_, EGL_WIDTH, &width) ||
514       !eglQuerySurface(GetDisplay(), surface_, EGL_HEIGHT, &height)) {
515     NOTREACHED() << "eglQuerySurface failed with error "
516                  << GetLastEGLErrorString();
517     return gfx::Size();
518   }
519
520   return gfx::Size(width, height);
521 }
522
523 bool NativeViewGLSurfaceEGL::Resize(const gfx::Size& size) {
524   if (size == GetSize())
525     return true;
526
527   size_ = size;
528
529   scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current;
530   GLContext* current_context = GLContext::GetCurrent();
531   bool was_current =
532       current_context && current_context->IsCurrent(this);
533   if (was_current) {
534     scoped_make_current.reset(
535         new ui::ScopedMakeCurrent(current_context, this));
536     current_context->ReleaseCurrent(this);
537   }
538
539   Destroy();
540
541   if (!Initialize()) {
542     LOG(ERROR) << "Failed to resize window.";
543     return false;
544   }
545
546   return true;
547 }
548
549 bool NativeViewGLSurfaceEGL::Recreate() {
550   Destroy();
551   if (!Initialize()) {
552     LOG(ERROR) << "Failed to create surface.";
553     return false;
554   }
555   return true;
556 }
557
558 EGLSurface NativeViewGLSurfaceEGL::GetHandle() {
559   return surface_;
560 }
561
562 std::string NativeViewGLSurfaceEGL::GetExtensions() {
563   std::string extensions = GLSurface::GetExtensions();
564   if (supports_post_sub_buffer_) {
565     extensions += extensions.empty() ? "" : " ";
566     extensions += "GL_CHROMIUM_post_sub_buffer";
567   }
568   return extensions;
569 }
570
571 bool NativeViewGLSurfaceEGL::PostSubBuffer(
572     int x, int y, int width, int height) {
573   DCHECK(supports_post_sub_buffer_);
574   if (!eglPostSubBufferNV(GetDisplay(), surface_, x, y, width, height)) {
575     DVLOG(1) << "eglPostSubBufferNV failed with error "
576              << GetLastEGLErrorString();
577     return false;
578   }
579   return true;
580 }
581
582 VSyncProvider* NativeViewGLSurfaceEGL::GetVSyncProvider() {
583   return vsync_provider_.get();
584 }
585
586 NativeViewGLSurfaceEGL::~NativeViewGLSurfaceEGL() {
587   Destroy();
588 #if defined(OS_ANDROID)
589   if (window_)
590     ANativeWindow_release(window_);
591 #endif
592 }
593
594 void NativeViewGLSurfaceEGL::SetHandle(EGLSurface surface) {
595   surface_ = surface;
596 }
597
598 PbufferGLSurfaceEGL::PbufferGLSurfaceEGL(const gfx::Size& size)
599     : size_(size),
600       surface_(NULL) {
601 }
602
603 bool PbufferGLSurfaceEGL::Initialize() {
604   EGLSurface old_surface = surface_;
605
606   EGLDisplay display = GetDisplay();
607   if (!display) {
608     LOG(ERROR) << "Trying to create surface with invalid display.";
609     return false;
610   }
611
612   if (size_.GetArea() == 0) {
613     LOG(ERROR) << "Error: surface has zero area "
614                << size_.width() << " x " << size_.height();
615     return false;
616   }
617
618   // Allocate the new pbuffer surface before freeing the old one to ensure
619   // they have different addresses. If they have the same address then a
620   // future call to MakeCurrent might early out because it appears the current
621   // context and surface have not changed.
622   const EGLint pbuffer_attribs[] = {
623     EGL_WIDTH, size_.width(),
624     EGL_HEIGHT, size_.height(),
625     EGL_NONE
626   };
627
628   EGLSurface new_surface = eglCreatePbufferSurface(display,
629                                                    GetConfig(),
630                                                    pbuffer_attribs);
631   if (!new_surface) {
632     LOG(ERROR) << "eglCreatePbufferSurface failed with error "
633                << GetLastEGLErrorString();
634     return false;
635   }
636
637   if (old_surface)
638     eglDestroySurface(display, old_surface);
639
640   surface_ = new_surface;
641   return true;
642 }
643
644 void PbufferGLSurfaceEGL::Destroy() {
645   if (surface_) {
646     if (!eglDestroySurface(GetDisplay(), surface_)) {
647       LOG(ERROR) << "eglDestroySurface failed with error "
648                  << GetLastEGLErrorString();
649     }
650     surface_ = NULL;
651   }
652 }
653
654 EGLConfig PbufferGLSurfaceEGL::GetConfig() {
655   return g_config;
656 }
657
658 bool PbufferGLSurfaceEGL::IsOffscreen() {
659   return true;
660 }
661
662 bool PbufferGLSurfaceEGL::SwapBuffers() {
663   NOTREACHED() << "Attempted to call SwapBuffers on a PbufferGLSurfaceEGL.";
664   return false;
665 }
666
667 gfx::Size PbufferGLSurfaceEGL::GetSize() {
668   return size_;
669 }
670
671 bool PbufferGLSurfaceEGL::Resize(const gfx::Size& size) {
672   if (size == size_)
673     return true;
674
675   scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current;
676   GLContext* current_context = GLContext::GetCurrent();
677   bool was_current =
678       current_context && current_context->IsCurrent(this);
679   if (was_current) {
680     scoped_make_current.reset(
681         new ui::ScopedMakeCurrent(current_context, this));
682   }
683
684   size_ = size;
685
686   if (!Initialize()) {
687     LOG(ERROR) << "Failed to resize pbuffer.";
688     return false;
689   }
690
691   return true;
692 }
693
694 EGLSurface PbufferGLSurfaceEGL::GetHandle() {
695   return surface_;
696 }
697
698 void* PbufferGLSurfaceEGL::GetShareHandle() {
699 #if defined(OS_ANDROID)
700   NOTREACHED();
701   return NULL;
702 #else
703   if (!gfx::g_driver_egl.ext.b_EGL_ANGLE_query_surface_pointer)
704     return NULL;
705
706   if (!gfx::g_driver_egl.ext.b_EGL_ANGLE_surface_d3d_texture_2d_share_handle)
707     return NULL;
708
709   void* handle;
710   if (!eglQuerySurfacePointerANGLE(g_display,
711                                    GetHandle(),
712                                    EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE,
713                                    &handle)) {
714     return NULL;
715   }
716
717   return handle;
718 #endif
719 }
720
721 PbufferGLSurfaceEGL::~PbufferGLSurfaceEGL() {
722   Destroy();
723 }
724
725 SurfacelessEGL::SurfacelessEGL(const gfx::Size& size)
726     : size_(size) {
727 }
728
729 bool SurfacelessEGL::Initialize() {
730   return true;
731 }
732
733 void SurfacelessEGL::Destroy() {
734 }
735
736 EGLConfig SurfacelessEGL::GetConfig() {
737   return g_config;
738 }
739
740 bool SurfacelessEGL::IsOffscreen() {
741   return true;
742 }
743
744 bool SurfacelessEGL::SwapBuffers() {
745   LOG(ERROR) << "Attempted to call SwapBuffers with SurfacelessEGL.";
746   return false;
747 }
748
749 gfx::Size SurfacelessEGL::GetSize() {
750   return size_;
751 }
752
753 bool SurfacelessEGL::Resize(const gfx::Size& size) {
754   size_ = size;
755   return true;
756 }
757
758 EGLSurface SurfacelessEGL::GetHandle() {
759   return EGL_NO_SURFACE;
760 }
761
762 void* SurfacelessEGL::GetShareHandle() {
763   return NULL;
764 }
765
766 SurfacelessEGL::~SurfacelessEGL() {
767 }
768
769 #if defined(ANDROID) || defined(USE_OZONE)
770
771 // A thin subclass of |GLSurfaceOSMesa| that can be used in place
772 // of a native hardware-provided surface when a native surface
773 // provider is not available.
774 class GLSurfaceOSMesaHeadless : public GLSurfaceOSMesa {
775  public:
776   explicit GLSurfaceOSMesaHeadless(gfx::AcceleratedWidget window);
777
778   virtual bool IsOffscreen() OVERRIDE;
779   virtual bool SwapBuffers() OVERRIDE;
780
781  protected:
782   virtual ~GLSurfaceOSMesaHeadless();
783
784  private:
785
786   DISALLOW_COPY_AND_ASSIGN(GLSurfaceOSMesaHeadless);
787 };
788
789 bool GLSurfaceOSMesaHeadless::IsOffscreen() { return false; }
790
791 bool GLSurfaceOSMesaHeadless::SwapBuffers() { return true; }
792
793 GLSurfaceOSMesaHeadless::GLSurfaceOSMesaHeadless(gfx::AcceleratedWidget window)
794     : GLSurfaceOSMesa(OSMESA_BGRA, gfx::Size(1, 1)) {
795   DCHECK(window);
796 }
797
798 GLSurfaceOSMesaHeadless::~GLSurfaceOSMesaHeadless() { Destroy(); }
799
800 // static
801 bool GLSurface::InitializeOneOffInternal() {
802   switch (GetGLImplementation()) {
803     case kGLImplementationEGLGLES2:
804       if (!GLSurfaceEGL::InitializeOneOff()) {
805         LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
806         return false;
807       }
808     default:
809       break;
810   }
811   return true;
812 }
813
814 // static
815 scoped_refptr<GLSurface>
816 GLSurface::CreateViewGLSurface(gfx::AcceleratedWidget window) {
817
818   if (GetGLImplementation() == kGLImplementationOSMesaGL) {
819     scoped_refptr<GLSurface> surface(new GLSurfaceOSMesaHeadless(window));
820     if (!surface->Initialize())
821       return NULL;
822     return surface;
823   }
824   DCHECK(GetGLImplementation() == kGLImplementationEGLGLES2);
825   if (window) {
826     scoped_refptr<NativeViewGLSurfaceEGL> surface;
827     scoped_ptr<VSyncProvider> sync_provider;
828 #if defined(USE_OZONE)
829     window = gfx::SurfaceFactoryOzone::GetInstance()->RealizeAcceleratedWidget(
830         window);
831     sync_provider =
832         gfx::SurfaceFactoryOzone::GetInstance()->CreateVSyncProvider(window);
833 #endif
834     surface = new NativeViewGLSurfaceEGL(window);
835     if(surface->Initialize(sync_provider.Pass()))
836       return surface;
837   } else {
838     scoped_refptr<GLSurface> surface = new GLSurfaceStub();
839     if (surface->Initialize())
840       return surface;
841   }
842   return NULL;
843 }
844
845 // static
846 scoped_refptr<GLSurface>
847 GLSurface::CreateOffscreenGLSurface(const gfx::Size& size) {
848   switch (GetGLImplementation()) {
849     case kGLImplementationOSMesaGL: {
850       scoped_refptr<GLSurface> surface(new GLSurfaceOSMesa(1, size));
851       if (!surface->Initialize())
852         return NULL;
853
854       return surface;
855     }
856     case kGLImplementationEGLGLES2: {
857       scoped_refptr<GLSurface> surface;
858       if (g_egl_surfaceless_context_supported &&
859          (size.width() == 1 && size.height() == 1)) {
860         surface = new SurfacelessEGL(size);
861       } else
862         surface = new PbufferGLSurfaceEGL(size);
863
864       if (!surface->Initialize())
865         return NULL;
866       return surface;
867     }
868     default:
869       NOTREACHED();
870       return NULL;
871   }
872 }
873
874 #endif
875
876 }  // namespace gfx