Home | History | Annotate | Download | only in gl
      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:
     63   explicit EGLSyncControlVSyncProvider(EGLSurface surface)
     64       : SyncControlVSyncProvider(),
     65         surface_(surface) {
     66   }
     67 
     68   virtual ~EGLSyncControlVSyncProvider() { }
     69 
     70  protected:
     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 
     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 
     98 GLSurfaceEGL::GLSurfaceEGL() {}
     99 
    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 
    215 EGLDisplay GLSurfaceEGL::GetDisplay() {
    216   return g_display;
    217 }
    218 
    219 EGLDisplay GLSurfaceEGL::GetHardwareDisplay() {
    220   return g_display;
    221 }
    222 
    223 EGLNativeDisplayType GLSurfaceEGL::GetNativeDisplay() {
    224   return g_native_display;
    225 }
    226 
    227 const char* GLSurfaceEGL::GetEGLExtensions() {
    228   return g_egl_extensions;
    229 }
    230 
    231 bool GLSurfaceEGL::HasEGLExtension(const char* name) {
    232   return ExtensionsContain(GetEGLExtensions(), name);
    233 }
    234 
    235 bool GLSurfaceEGL::IsCreateContextRobustnessSupported() {
    236   return g_egl_create_context_robustness_supported;
    237 }
    238 
    239 GLSurfaceEGL::~GLSurfaceEGL() {}
    240 
    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 
    252 bool NativeViewGLSurfaceEGL::Initialize() {
    253   return Initialize(NULL);
    254 }
    255 
    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 
    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 
    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 
    392 bool NativeViewGLSurfaceEGL::IsOffscreen() {
    393   return false;
    394 }
    395 
    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 
    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 
    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 
    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 
    452 EGLSurface NativeViewGLSurfaceEGL::GetHandle() {
    453   return surface_;
    454 }
    455 
    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 
    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 
    476 VSyncProvider* NativeViewGLSurfaceEGL::GetVSyncProvider() {
    477   return vsync_provider_.get();
    478 }
    479 
    480 NativeViewGLSurfaceEGL::~NativeViewGLSurfaceEGL() {
    481   Destroy();
    482 #if defined(OS_ANDROID)
    483   if (window_)
    484     ANativeWindow_release(window_);
    485 #endif
    486 }
    487 
    488 void NativeViewGLSurfaceEGL::SetHandle(EGLSurface surface) {
    489   surface_ = surface;
    490 }
    491 
    492 PbufferGLSurfaceEGL::PbufferGLSurfaceEGL(const gfx::Size& size)
    493     : size_(size),
    494       surface_(NULL) {
    495 }
    496 
    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 
    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 
    548 EGLConfig PbufferGLSurfaceEGL::GetConfig() {
    549   return g_config;
    550 }
    551 
    552 bool PbufferGLSurfaceEGL::IsOffscreen() {
    553   return true;
    554 }
    555 
    556 bool PbufferGLSurfaceEGL::SwapBuffers() {
    557   NOTREACHED() << "Attempted to call SwapBuffers on a PbufferGLSurfaceEGL.";
    558   return false;
    559 }
    560 
    561 gfx::Size PbufferGLSurfaceEGL::GetSize() {
    562   return size_;
    563 }
    564 
    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 
    588 EGLSurface PbufferGLSurfaceEGL::GetHandle() {
    589   return surface_;
    590 }
    591 
    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 
    615 PbufferGLSurfaceEGL::~PbufferGLSurfaceEGL() {
    616   Destroy();
    617 }
    618 
    619 SurfacelessEGL::SurfacelessEGL(const gfx::Size& size)
    620     : size_(size) {
    621 }
    622 
    623 bool SurfacelessEGL::Initialize() {
    624   return true;
    625 }
    626 
    627 void SurfacelessEGL::Destroy() {
    628 }
    629 
    630 EGLConfig SurfacelessEGL::GetConfig() {
    631   return g_config;
    632 }
    633 
    634 bool SurfacelessEGL::IsOffscreen() {
    635   return true;
    636 }
    637 
    638 bool SurfacelessEGL::SwapBuffers() {
    639   LOG(ERROR) << "Attempted to call SwapBuffers with SurfacelessEGL.";
    640   return false;
    641 }
    642 
    643 gfx::Size SurfacelessEGL::GetSize() {
    644   return size_;
    645 }
    646 
    647 bool SurfacelessEGL::Resize(const gfx::Size& size) {
    648   size_ = size;
    649   return true;
    650 }
    651 
    652 EGLSurface SurfacelessEGL::GetHandle() {
    653   return EGL_NO_SURFACE;
    654 }
    655 
    656 void* SurfacelessEGL::GetShareHandle() {
    657   return NULL;
    658 }
    659 
    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 
    683 bool GLSurfaceOSMesaHeadless::IsOffscreen() { return false; }
    684 
    685 bool GLSurfaceOSMesaHeadless::SwapBuffers() { return true; }
    686 
    687 GLSurfaceOSMesaHeadless::GLSurfaceOSMesaHeadless(gfx::AcceleratedWidget window)
    688     : GLSurfaceOSMesa(OSMESA_BGRA, gfx::Size(1, 1)) {
    689   DCHECK(window);
    690 }
    691 
    692 GLSurfaceOSMesaHeadless::~GLSurfaceOSMesaHeadless() { Destroy(); }
    693 
    694 // static
    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>
    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>
    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