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