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