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