1 // Copyright 2014 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.
5 #include "ui/gl/gl_surface.h"
8 #include "base/callback.h"
9 #include "base/location.h"
10 #include "base/logging.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/memory/scoped_vector.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/threading/worker_pool.h"
15 #include "ui/gfx/native_widget_types.h"
16 #include "ui/gl/gl_context.h"
17 #include "ui/gl/gl_image.h"
18 #include "ui/gl/gl_image_ozone_native_pixmap.h"
19 #include "ui/gl/gl_implementation.h"
20 #include "ui/gl/gl_surface_egl.h"
21 #include "ui/gl/gl_surface_osmesa.h"
22 #include "ui/gl/gl_surface_stub.h"
23 #include "ui/gl/scoped_binders.h"
24 #include "ui/gl/scoped_make_current.h"
25 #include "ui/ozone/public/native_pixmap.h"
26 #include "ui/ozone/public/ozone_platform.h"
27 #include "ui/ozone/public/surface_factory_ozone.h"
28 #include "ui/ozone/public/surface_ozone_egl.h"
34 void WaitForFence(EGLDisplay display
, EGLSyncKHR fence
) {
35 eglClientWaitSyncKHR(display
, fence
, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR
,
39 // A thin wrapper around GLSurfaceEGL that owns the EGLNativeWindow.
40 class GL_EXPORT GLSurfaceOzoneEGL
: public NativeViewGLSurfaceEGL
{
42 GLSurfaceOzoneEGL(scoped_ptr
<ui::SurfaceOzoneEGL
> ozone_surface
,
43 AcceleratedWidget widget
);
46 bool Initialize() override
;
47 bool Resize(const gfx::Size
& size
) override
;
48 gfx::SwapResult
SwapBuffers() override
;
49 bool ScheduleOverlayPlane(int z_order
,
50 OverlayTransform transform
,
52 const Rect
& bounds_rect
,
53 const RectF
& crop_rect
) override
;
56 using NativeViewGLSurfaceEGL::Initialize
;
58 ~GLSurfaceOzoneEGL() override
;
60 bool ReinitializeNativeSurface();
62 // The native surface. Deleting this is allowed to free the EGLNativeWindow.
63 scoped_ptr
<ui::SurfaceOzoneEGL
> ozone_surface_
;
64 AcceleratedWidget widget_
;
66 DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneEGL
);
69 GLSurfaceOzoneEGL::GLSurfaceOzoneEGL(
70 scoped_ptr
<ui::SurfaceOzoneEGL
> ozone_surface
,
71 AcceleratedWidget widget
)
72 : NativeViewGLSurfaceEGL(ozone_surface
->GetNativeWindow()),
73 ozone_surface_(ozone_surface
.Pass()),
76 bool GLSurfaceOzoneEGL::Initialize() {
77 return Initialize(ozone_surface_
->CreateVSyncProvider());
80 bool GLSurfaceOzoneEGL::Resize(const gfx::Size
& size
) {
81 if (!ozone_surface_
->ResizeNativeWindow(size
)) {
82 if (!ReinitializeNativeSurface() ||
83 !ozone_surface_
->ResizeNativeWindow(size
))
87 return NativeViewGLSurfaceEGL::Resize(size
);
90 gfx::SwapResult
GLSurfaceOzoneEGL::SwapBuffers() {
91 gfx::SwapResult result
= NativeViewGLSurfaceEGL::SwapBuffers();
92 if (result
!= gfx::SwapResult::SWAP_ACK
)
95 return ozone_surface_
->OnSwapBuffers() ? gfx::SwapResult::SWAP_ACK
96 : gfx::SwapResult::SWAP_FAILED
;
99 bool GLSurfaceOzoneEGL::ScheduleOverlayPlane(int z_order
,
100 OverlayTransform transform
,
102 const Rect
& bounds_rect
,
103 const RectF
& crop_rect
) {
104 return image
->ScheduleOverlayPlane(widget_
, z_order
, transform
, bounds_rect
,
108 GLSurfaceOzoneEGL::~GLSurfaceOzoneEGL() {
109 Destroy(); // The EGL surface must be destroyed before SurfaceOzone.
112 bool GLSurfaceOzoneEGL::ReinitializeNativeSurface() {
113 scoped_ptr
<ui::ScopedMakeCurrent
> scoped_make_current
;
114 GLContext
* current_context
= GLContext::GetCurrent();
115 bool was_current
= current_context
&& current_context
->IsCurrent(this);
117 scoped_make_current
.reset(new ui::ScopedMakeCurrent(current_context
, this));
121 ozone_surface_
= ui::OzonePlatform::GetInstance()
122 ->GetSurfaceFactoryOzone()
123 ->CreateEGLSurfaceForWidget(widget_
);
124 if (!ozone_surface_
) {
125 LOG(ERROR
) << "Failed to create native surface.";
129 window_
= ozone_surface_
->GetNativeWindow();
131 LOG(ERROR
) << "Failed to initialize.";
138 class GL_EXPORT GLSurfaceOzoneSurfaceless
: public SurfacelessEGL
{
140 GLSurfaceOzoneSurfaceless(scoped_ptr
<ui::SurfaceOzoneEGL
> ozone_surface
,
141 AcceleratedWidget widget
);
144 bool Initialize() override
;
145 bool Resize(const gfx::Size
& size
) override
;
146 gfx::SwapResult
SwapBuffers() override
;
147 bool ScheduleOverlayPlane(int z_order
,
148 OverlayTransform transform
,
150 const Rect
& bounds_rect
,
151 const RectF
& crop_rect
) override
;
152 bool IsOffscreen() override
;
153 VSyncProvider
* GetVSyncProvider() override
;
154 bool SupportsPostSubBuffer() override
;
155 gfx::SwapResult
PostSubBuffer(int x
, int y
, int width
, int height
) override
;
156 bool SwapBuffersAsync(const SwapCompletionCallback
& callback
) override
;
157 bool PostSubBufferAsync(int x
,
161 const SwapCompletionCallback
& callback
) override
;
166 OverlayTransform transform
,
168 const Rect
& bounds_rect
,
169 const RectF
& crop_rect
);
171 bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget
) const;
174 OverlayTransform transform
;
175 scoped_refptr
<GLImage
> image
;
180 struct PendingFrame
{
183 bool ScheduleOverlayPlanes(gfx::AcceleratedWidget widget
);
186 std::vector
<Overlay
> overlays
;
187 SwapCompletionCallback callback
;
190 ~GLSurfaceOzoneSurfaceless() override
;
194 EGLSyncKHR
InsertFence();
195 void FenceRetired(EGLSyncKHR fence
, PendingFrame
* frame
);
197 void SwapCompleted(const SwapCompletionCallback
& callback
,
198 gfx::SwapResult result
);
200 // The native surface. Deleting this is allowed to free the EGLNativeWindow.
201 scoped_ptr
<ui::SurfaceOzoneEGL
> ozone_surface_
;
202 AcceleratedWidget widget_
;
203 scoped_ptr
<VSyncProvider
> vsync_provider_
;
204 ScopedVector
<PendingFrame
> unsubmitted_frames_
;
205 bool has_implicit_external_sync_
;
206 bool last_swap_buffers_result_
;
207 bool swap_buffers_pending_
;
209 base::WeakPtrFactory
<GLSurfaceOzoneSurfaceless
> weak_factory_
;
211 DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfaceless
);
214 GLSurfaceOzoneSurfaceless::Overlay::Overlay(int z_order
,
215 OverlayTransform transform
,
217 const Rect
& bounds_rect
,
218 const RectF
& crop_rect
)
220 transform(transform
),
222 bounds_rect(bounds_rect
),
223 crop_rect(crop_rect
) {}
225 bool GLSurfaceOzoneSurfaceless::Overlay::ScheduleOverlayPlane(
226 gfx::AcceleratedWidget widget
) const {
227 return image
->ScheduleOverlayPlane(widget
, z_order
, transform
, bounds_rect
,
231 GLSurfaceOzoneSurfaceless::PendingFrame::PendingFrame() : ready(false) {}
233 bool GLSurfaceOzoneSurfaceless::PendingFrame::ScheduleOverlayPlanes(
234 gfx::AcceleratedWidget widget
) {
235 for (const auto& overlay
: overlays
)
236 if (!overlay
.ScheduleOverlayPlane(widget
))
241 GLSurfaceOzoneSurfaceless::GLSurfaceOzoneSurfaceless(
242 scoped_ptr
<ui::SurfaceOzoneEGL
> ozone_surface
,
243 AcceleratedWidget widget
)
244 : SurfacelessEGL(gfx::Size()),
245 ozone_surface_(ozone_surface
.Pass()),
247 has_implicit_external_sync_(
248 HasEGLExtension("EGL_ARM_implicit_external_sync")),
249 last_swap_buffers_result_(true),
250 swap_buffers_pending_(false),
251 weak_factory_(this) {
252 unsubmitted_frames_
.push_back(new PendingFrame());
255 bool GLSurfaceOzoneSurfaceless::Initialize() {
256 if (!SurfacelessEGL::Initialize())
258 vsync_provider_
= ozone_surface_
->CreateVSyncProvider();
259 if (!vsync_provider_
)
264 bool GLSurfaceOzoneSurfaceless::Resize(const gfx::Size
& size
) {
265 if (!ozone_surface_
->ResizeNativeWindow(size
))
268 return SurfacelessEGL::Resize(size
);
271 gfx::SwapResult
GLSurfaceOzoneSurfaceless::SwapBuffers() {
273 // TODO: the following should be replaced by a per surface flush as it gets
274 // implemented in GL drivers.
275 if (has_implicit_external_sync_
) {
276 EGLSyncKHR fence
= InsertFence();
278 return SwapResult::SWAP_FAILED
;
280 EGLDisplay display
= GetDisplay();
281 WaitForFence(display
, fence
);
282 eglDestroySyncKHR(display
, fence
);
283 } else if (ozone_surface_
->IsUniversalDisplayLinkDevice()) {
287 unsubmitted_frames_
.back()->ScheduleOverlayPlanes(widget_
);
288 unsubmitted_frames_
.back()->overlays
.clear();
290 return ozone_surface_
->OnSwapBuffers() ? gfx::SwapResult::SWAP_ACK
291 : gfx::SwapResult::SWAP_FAILED
;
294 bool GLSurfaceOzoneSurfaceless::ScheduleOverlayPlane(int z_order
,
295 OverlayTransform transform
,
297 const Rect
& bounds_rect
,
298 const RectF
& crop_rect
) {
299 unsubmitted_frames_
.back()->overlays
.push_back(
300 Overlay(z_order
, transform
, image
, bounds_rect
, crop_rect
));
304 bool GLSurfaceOzoneSurfaceless::IsOffscreen() {
308 VSyncProvider
* GLSurfaceOzoneSurfaceless::GetVSyncProvider() {
309 return vsync_provider_
.get();
312 bool GLSurfaceOzoneSurfaceless::SupportsPostSubBuffer() {
316 gfx::SwapResult
GLSurfaceOzoneSurfaceless::PostSubBuffer(int x
,
320 // The actual sub buffer handling is handled at higher layers.
322 return gfx::SwapResult::SWAP_ACK
;
325 bool GLSurfaceOzoneSurfaceless::SwapBuffersAsync(
326 const SwapCompletionCallback
& callback
) {
327 // If last swap failed, don't try to schedule new ones.
328 if (!last_swap_buffers_result_
)
333 SwapCompletionCallback surface_swap_callback
=
334 base::Bind(&GLSurfaceOzoneSurfaceless::SwapCompleted
,
335 weak_factory_
.GetWeakPtr(), callback
);
337 PendingFrame
* frame
= unsubmitted_frames_
.back();
338 frame
->callback
= surface_swap_callback
;
339 unsubmitted_frames_
.push_back(new PendingFrame());
341 // TODO: the following should be replaced by a per surface flush as it gets
342 // implemented in GL drivers.
343 if (has_implicit_external_sync_
) {
344 EGLSyncKHR fence
= InsertFence();
348 base::Closure fence_wait_task
=
349 base::Bind(&WaitForFence
, GetDisplay(), fence
);
351 base::Closure fence_retired_callback
=
352 base::Bind(&GLSurfaceOzoneSurfaceless::FenceRetired
,
353 weak_factory_
.GetWeakPtr(), fence
, frame
);
355 base::WorkerPool::PostTaskAndReply(FROM_HERE
, fence_wait_task
,
356 fence_retired_callback
, false);
358 } else if (ozone_surface_
->IsUniversalDisplayLinkDevice()) {
364 return last_swap_buffers_result_
;
367 bool GLSurfaceOzoneSurfaceless::PostSubBufferAsync(
372 const SwapCompletionCallback
& callback
) {
373 return SwapBuffersAsync(callback
);
376 GLSurfaceOzoneSurfaceless::~GLSurfaceOzoneSurfaceless() {
377 Destroy(); // The EGL surface must be destroyed before SurfaceOzone.
380 void GLSurfaceOzoneSurfaceless::SubmitFrame() {
381 DCHECK(!unsubmitted_frames_
.empty());
383 if (unsubmitted_frames_
.front()->ready
&& !swap_buffers_pending_
) {
384 scoped_ptr
<PendingFrame
> frame(unsubmitted_frames_
.front());
385 unsubmitted_frames_
.weak_erase(unsubmitted_frames_
.begin());
386 swap_buffers_pending_
= true;
388 last_swap_buffers_result_
=
389 frame
->ScheduleOverlayPlanes(widget_
) &&
390 ozone_surface_
->OnSwapBuffersAsync(frame
->callback
);
394 EGLSyncKHR
GLSurfaceOzoneSurfaceless::InsertFence() {
395 const EGLint attrib_list
[] = {EGL_SYNC_CONDITION_KHR
,
396 EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM
,
398 return eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR
, attrib_list
);
401 void GLSurfaceOzoneSurfaceless::FenceRetired(EGLSyncKHR fence
,
402 PendingFrame
* frame
) {
403 eglDestroySyncKHR(GetDisplay(), fence
);
408 void GLSurfaceOzoneSurfaceless::SwapCompleted(
409 const SwapCompletionCallback
& callback
,
410 gfx::SwapResult result
) {
411 callback
.Run(result
);
412 swap_buffers_pending_
= false;
417 // This provides surface-like semantics implemented through surfaceless.
418 // A framebuffer is bound automatically.
419 class GL_EXPORT GLSurfaceOzoneSurfacelessSurfaceImpl
420 : public GLSurfaceOzoneSurfaceless
{
422 GLSurfaceOzoneSurfacelessSurfaceImpl(
423 scoped_ptr
<ui::SurfaceOzoneEGL
> ozone_surface
,
424 AcceleratedWidget widget
);
427 unsigned int GetBackingFrameBufferObject() override
;
428 bool OnMakeCurrent(GLContext
* context
) override
;
429 bool Resize(const gfx::Size
& size
) override
;
430 bool SupportsPostSubBuffer() override
;
431 gfx::SwapResult
SwapBuffers() override
;
432 bool SwapBuffersAsync(const SwapCompletionCallback
& callback
) override
;
433 void Destroy() override
;
434 bool IsSurfaceless() const override
;
437 ~GLSurfaceOzoneSurfacelessSurfaceImpl() override
;
439 void BindFramebuffer();
440 bool CreatePixmaps();
442 scoped_refptr
<GLContext
> context_
;
445 scoped_refptr
<GLImage
> images_
[2];
446 int current_surface_
;
447 DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfacelessSurfaceImpl
);
450 GLSurfaceOzoneSurfacelessSurfaceImpl::GLSurfaceOzoneSurfacelessSurfaceImpl(
451 scoped_ptr
<ui::SurfaceOzoneEGL
> ozone_surface
,
452 AcceleratedWidget widget
)
453 : GLSurfaceOzoneSurfaceless(ozone_surface
.Pass(), widget
),
456 current_surface_(0) {
457 for (auto& texture
: textures_
)
462 GLSurfaceOzoneSurfacelessSurfaceImpl::GetBackingFrameBufferObject() {
466 bool GLSurfaceOzoneSurfacelessSurfaceImpl::OnMakeCurrent(GLContext
* context
) {
467 DCHECK(!context_
|| context
== context_
);
470 glGenFramebuffersEXT(1, &fbo_
);
473 glGenTextures(arraysize(textures_
), textures_
);
474 if (!CreatePixmaps())
478 glBindFramebufferEXT(GL_FRAMEBUFFER
, fbo_
);
479 return SurfacelessEGL::OnMakeCurrent(context
);
482 bool GLSurfaceOzoneSurfacelessSurfaceImpl::Resize(const gfx::Size
& size
) {
483 if (size
== GetSize())
485 return GLSurfaceOzoneSurfaceless::Resize(size
) && CreatePixmaps();
488 bool GLSurfaceOzoneSurfacelessSurfaceImpl::SupportsPostSubBuffer() {
492 gfx::SwapResult
GLSurfaceOzoneSurfacelessSurfaceImpl::SwapBuffers() {
493 if (!images_
[current_surface_
]->ScheduleOverlayPlane(
494 widget_
, 0, OverlayTransform::OVERLAY_TRANSFORM_NONE
,
495 gfx::Rect(GetSize()), gfx::RectF(1, 1)))
496 return gfx::SwapResult::SWAP_FAILED
;
497 gfx::SwapResult result
= GLSurfaceOzoneSurfaceless::SwapBuffers();
498 if (result
!= gfx::SwapResult::SWAP_ACK
)
500 current_surface_
^= 1;
502 return gfx::SwapResult::SWAP_ACK
;
505 bool GLSurfaceOzoneSurfacelessSurfaceImpl::SwapBuffersAsync(
506 const SwapCompletionCallback
& callback
) {
507 if (!images_
[current_surface_
]->ScheduleOverlayPlane(
508 widget_
, 0, OverlayTransform::OVERLAY_TRANSFORM_NONE
,
509 gfx::Rect(GetSize()), gfx::RectF(1, 1)))
511 if (!GLSurfaceOzoneSurfaceless::SwapBuffersAsync(callback
))
513 current_surface_
^= 1;
518 void GLSurfaceOzoneSurfacelessSurfaceImpl::Destroy() {
521 ui::ScopedMakeCurrent
context(context_
.get(), this);
522 glBindFramebufferEXT(GL_FRAMEBUFFER
, 0);
524 glDeleteTextures(arraysize(textures_
), textures_
);
525 for (auto& texture
: textures_
)
527 glDeleteFramebuffersEXT(1, &fbo_
);
530 for (auto image
: images_
) {
532 image
->Destroy(true);
536 bool GLSurfaceOzoneSurfacelessSurfaceImpl::IsSurfaceless() const {
540 GLSurfaceOzoneSurfacelessSurfaceImpl::~GLSurfaceOzoneSurfacelessSurfaceImpl() {
542 for (size_t i
= 0; i
< arraysize(textures_
); i
++)
543 DCHECK(!textures_
[i
]) << "texture " << i
<< " not released";
546 void GLSurfaceOzoneSurfacelessSurfaceImpl::BindFramebuffer() {
547 ScopedFrameBufferBinder
fb(fbo_
);
548 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
, GL_TEXTURE_2D
,
549 textures_
[current_surface_
], 0);
552 bool GLSurfaceOzoneSurfacelessSurfaceImpl::CreatePixmaps() {
555 for (size_t i
= 0; i
< arraysize(textures_
); i
++) {
556 scoped_refptr
<ui::NativePixmap
> pixmap
=
557 ui::OzonePlatform::GetInstance()
558 ->GetSurfaceFactoryOzone()
559 ->CreateNativePixmap(widget_
, GetSize(),
560 gfx::BufferFormat::BGRA_8888
,
561 gfx::BufferUsage::SCANOUT
);
564 scoped_refptr
<GLImageOzoneNativePixmap
> image
=
565 new GLImageOzoneNativePixmap(GetSize(), GL_BGRA_EXT
);
566 if (!image
->Initialize(pixmap
.get(), gfx::BufferFormat::BGRA_8888
))
569 // Bind image to texture.
570 ScopedTextureBinder
binder(GL_TEXTURE_2D
, textures_
[i
]);
571 if (!images_
[i
]->BindTexImage(GL_TEXTURE_2D
))
577 scoped_refptr
<GLSurface
> CreateViewGLSurfaceOzone(
578 gfx::AcceleratedWidget window
) {
579 scoped_ptr
<ui::SurfaceOzoneEGL
> surface_ozone
=
580 ui::OzonePlatform::GetInstance()
581 ->GetSurfaceFactoryOzone()
582 ->CreateEGLSurfaceForWidget(window
);
585 scoped_refptr
<GLSurface
> surface
=
586 new GLSurfaceOzoneEGL(surface_ozone
.Pass(), window
);
587 if (!surface
->Initialize())
592 scoped_refptr
<GLSurface
> CreateViewGLSurfaceOzoneSurfacelessSurfaceImpl(
593 gfx::AcceleratedWidget window
) {
594 scoped_ptr
<ui::SurfaceOzoneEGL
> surface_ozone
=
595 ui::OzonePlatform::GetInstance()
596 ->GetSurfaceFactoryOzone()
597 ->CreateSurfacelessEGLSurfaceForWidget(window
);
600 scoped_refptr
<GLSurface
> surface
=
601 new GLSurfaceOzoneSurfacelessSurfaceImpl(surface_ozone
.Pass(), window
);
602 if (!surface
->Initialize())
610 bool GLSurface::InitializeOneOffInternal() {
611 switch (GetGLImplementation()) {
612 case kGLImplementationEGLGLES2
:
613 if (!GLSurfaceEGL::InitializeOneOff()) {
614 LOG(ERROR
) << "GLSurfaceEGL::InitializeOneOff failed.";
619 case kGLImplementationOSMesaGL
:
620 case kGLImplementationMockGL
:
628 scoped_refptr
<GLSurface
> GLSurface::CreateSurfacelessViewGLSurface(
629 gfx::AcceleratedWidget window
) {
630 if (GetGLImplementation() == kGLImplementationEGLGLES2
&&
631 window
!= kNullAcceleratedWidget
&&
632 GLSurfaceEGL::IsEGLSurfacelessContextSupported()) {
633 scoped_ptr
<ui::SurfaceOzoneEGL
> surface_ozone
=
634 ui::OzonePlatform::GetInstance()
635 ->GetSurfaceFactoryOzone()
636 ->CreateSurfacelessEGLSurfaceForWidget(window
);
639 scoped_refptr
<GLSurface
> surface
;
640 surface
= new GLSurfaceOzoneSurfaceless(surface_ozone
.Pass(), window
);
641 if (surface
->Initialize())
649 scoped_refptr
<GLSurface
> GLSurface::CreateViewGLSurface(
650 gfx::AcceleratedWidget window
) {
651 if (GetGLImplementation() == kGLImplementationOSMesaGL
) {
652 scoped_refptr
<GLSurface
> surface(new GLSurfaceOSMesaHeadless());
653 if (!surface
->Initialize())
657 DCHECK(GetGLImplementation() == kGLImplementationEGLGLES2
);
658 if (window
!= kNullAcceleratedWidget
) {
659 scoped_refptr
<GLSurface
> surface
;
660 if (GLSurfaceEGL::IsEGLSurfacelessContextSupported())
661 surface
= CreateViewGLSurfaceOzoneSurfacelessSurfaceImpl(window
);
663 surface
= CreateViewGLSurfaceOzone(window
);
666 scoped_refptr
<GLSurface
> surface
= new GLSurfaceStub();
667 if (surface
->Initialize())
674 scoped_refptr
<GLSurface
> GLSurface::CreateOffscreenGLSurface(
675 const gfx::Size
& size
) {
676 switch (GetGLImplementation()) {
677 case kGLImplementationOSMesaGL
: {
678 scoped_refptr
<GLSurface
> surface(
679 new GLSurfaceOSMesa(OSMesaSurfaceFormatBGRA
, size
));
680 if (!surface
->Initialize())
685 case kGLImplementationEGLGLES2
: {
686 scoped_refptr
<GLSurface
> surface
;
687 if (GLSurfaceEGL::IsEGLSurfacelessContextSupported() &&
688 (size
.width() == 0 && size
.height() == 0)) {
689 surface
= new SurfacelessEGL(size
);
691 surface
= new PbufferGLSurfaceEGL(size
);
693 if (!surface
->Initialize())
697 case kGLImplementationMockGL
:
698 return new GLSurfaceStub
;
705 EGLNativeDisplayType
GetPlatformDefaultEGLNativeDisplay() {
706 return ui::OzonePlatform::GetInstance()
707 ->GetSurfaceFactoryOzone()
708 ->GetNativeDisplay();