Turn on gpu_info_collector_unittests.
[chromium-blink-merge.git] / ui / gl / gl_surface_ozone.cc
blob064c5c62e3b481b48c938c52d267a525426816b0
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"
7 #include "base/bind.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_linux_dma_buffer.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/surface_factory_ozone.h"
27 #include "ui/ozone/public/surface_ozone_egl.h"
29 namespace gfx {
31 namespace {
33 void WaitForFence(EGLDisplay display, EGLSyncKHR fence) {
34 eglClientWaitSyncKHR(display, fence, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
35 EGL_FOREVER_KHR);
38 // A thin wrapper around GLSurfaceEGL that owns the EGLNativeWindow
39 class GL_EXPORT GLSurfaceOzoneEGL : public NativeViewGLSurfaceEGL {
40 public:
41 GLSurfaceOzoneEGL(scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
42 AcceleratedWidget widget);
44 // GLSurface:
45 bool Initialize() override;
46 bool Resize(const gfx::Size& size) override;
47 bool SwapBuffers() override;
48 bool ScheduleOverlayPlane(int z_order,
49 OverlayTransform transform,
50 GLImage* image,
51 const Rect& bounds_rect,
52 const RectF& crop_rect) override;
54 private:
55 using NativeViewGLSurfaceEGL::Initialize;
57 ~GLSurfaceOzoneEGL() override;
59 bool ReinitializeNativeSurface();
61 // The native surface. Deleting this is allowed to free the EGLNativeWindow.
62 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface_;
63 AcceleratedWidget widget_;
65 DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneEGL);
68 GLSurfaceOzoneEGL::GLSurfaceOzoneEGL(
69 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
70 AcceleratedWidget widget)
71 : NativeViewGLSurfaceEGL(ozone_surface->GetNativeWindow()),
72 ozone_surface_(ozone_surface.Pass()),
73 widget_(widget) {
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))
84 return false;
87 return NativeViewGLSurfaceEGL::Resize(size);
90 bool GLSurfaceOzoneEGL::SwapBuffers() {
91 if (!NativeViewGLSurfaceEGL::SwapBuffers())
92 return false;
94 return ozone_surface_->OnSwapBuffers();
97 bool GLSurfaceOzoneEGL::ScheduleOverlayPlane(int z_order,
98 OverlayTransform transform,
99 GLImage* image,
100 const Rect& bounds_rect,
101 const RectF& crop_rect) {
102 return image->ScheduleOverlayPlane(widget_, z_order, transform, bounds_rect,
103 crop_rect);
106 GLSurfaceOzoneEGL::~GLSurfaceOzoneEGL() {
107 Destroy(); // EGL surface must be destroyed before SurfaceOzone
110 bool GLSurfaceOzoneEGL::ReinitializeNativeSurface() {
111 scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current;
112 GLContext* current_context = GLContext::GetCurrent();
113 bool was_current = current_context && current_context->IsCurrent(this);
114 if (was_current) {
115 scoped_make_current.reset(new ui::ScopedMakeCurrent(current_context, this));
118 Destroy();
119 ozone_surface_ = ui::SurfaceFactoryOzone::GetInstance()
120 ->CreateEGLSurfaceForWidget(widget_)
121 .Pass();
122 if (!ozone_surface_) {
123 LOG(ERROR) << "Failed to create native surface.";
124 return false;
127 window_ = ozone_surface_->GetNativeWindow();
128 if (!Initialize()) {
129 LOG(ERROR) << "Failed to initialize.";
130 return false;
133 return true;
136 class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL {
137 public:
138 GLSurfaceOzoneSurfaceless(scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
139 AcceleratedWidget widget);
141 // GLSurface:
142 bool Initialize() override;
143 bool Resize(const gfx::Size& size) override;
144 bool SwapBuffers() override;
145 bool ScheduleOverlayPlane(int z_order,
146 OverlayTransform transform,
147 GLImage* image,
148 const Rect& bounds_rect,
149 const RectF& crop_rect) override;
150 bool IsOffscreen() override;
151 VSyncProvider* GetVSyncProvider() override;
152 bool SupportsPostSubBuffer() override;
153 bool PostSubBuffer(int x, int y, int width, int height) override;
154 bool SwapBuffersAsync(const SwapCompletionCallback& callback) override;
155 bool PostSubBufferAsync(int x,
156 int y,
157 int width,
158 int height,
159 const SwapCompletionCallback& callback) override;
161 protected:
162 struct Overlay {
163 Overlay(int z_order,
164 OverlayTransform transform,
165 GLImage* image,
166 const Rect& bounds_rect,
167 const RectF& crop_rect);
169 bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget) const;
171 int z_order;
172 OverlayTransform transform;
173 scoped_refptr<GLImage> image;
174 Rect bounds_rect;
175 RectF crop_rect;
178 struct PendingFrame {
179 PendingFrame();
181 bool ScheduleOverlayPlanes(gfx::AcceleratedWidget widget);
183 bool ready;
184 std::vector<Overlay> overlays;
185 SwapCompletionCallback callback;
188 ~GLSurfaceOzoneSurfaceless() override;
190 void SubmitFrame();
192 EGLSyncKHR InsertFence();
193 void FenceRetired(EGLSyncKHR fence, PendingFrame* frame);
195 void SwapCompleted(const SwapCompletionCallback& callback);
197 // The native surface. Deleting this is allowed to free the EGLNativeWindow.
198 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface_;
199 AcceleratedWidget widget_;
200 scoped_ptr<VSyncProvider> vsync_provider_;
201 ScopedVector<PendingFrame> unsubmitted_frames_;
202 bool has_implicit_external_sync_;
203 bool last_swap_buffers_result_;
204 bool swap_buffers_pending_;
206 base::WeakPtrFactory<GLSurfaceOzoneSurfaceless> weak_factory_;
208 DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfaceless);
211 GLSurfaceOzoneSurfaceless::Overlay::Overlay(int z_order,
212 OverlayTransform transform,
213 GLImage* image,
214 const Rect& bounds_rect,
215 const RectF& crop_rect)
216 : z_order(z_order),
217 transform(transform),
218 image(image),
219 bounds_rect(bounds_rect),
220 crop_rect(crop_rect) {
223 bool GLSurfaceOzoneSurfaceless::Overlay::ScheduleOverlayPlane(
224 gfx::AcceleratedWidget widget) const {
225 return image->ScheduleOverlayPlane(widget, z_order, transform, bounds_rect,
226 crop_rect);
229 GLSurfaceOzoneSurfaceless::PendingFrame::PendingFrame() : ready(false) {
232 bool GLSurfaceOzoneSurfaceless::PendingFrame::ScheduleOverlayPlanes(
233 gfx::AcceleratedWidget widget) {
234 for (const auto& overlay : overlays)
235 if (!overlay.ScheduleOverlayPlane(widget))
236 return false;
237 return true;
240 GLSurfaceOzoneSurfaceless::GLSurfaceOzoneSurfaceless(
241 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
242 AcceleratedWidget widget)
243 : SurfacelessEGL(gfx::Size()),
244 ozone_surface_(ozone_surface.Pass()),
245 widget_(widget),
246 has_implicit_external_sync_(
247 HasEGLExtension("EGL_ARM_implicit_external_sync")),
248 last_swap_buffers_result_(true),
249 swap_buffers_pending_(false),
250 weak_factory_(this) {
251 unsubmitted_frames_.push_back(new PendingFrame());
254 bool GLSurfaceOzoneSurfaceless::Initialize() {
255 if (!SurfacelessEGL::Initialize())
256 return false;
257 vsync_provider_ = ozone_surface_->CreateVSyncProvider();
258 if (!vsync_provider_)
259 return false;
260 return true;
262 bool GLSurfaceOzoneSurfaceless::Resize(const gfx::Size& size) {
263 if (!ozone_surface_->ResizeNativeWindow(size))
264 return false;
266 return SurfacelessEGL::Resize(size);
268 bool GLSurfaceOzoneSurfaceless::SwapBuffers() {
269 glFlush();
270 // TODO: the following should be replaced by a per surface flush as it gets
271 // implemented in GL drivers.
272 if (has_implicit_external_sync_) {
273 EGLSyncKHR fence = InsertFence();
274 if (!fence)
275 return false;
277 EGLDisplay display = GetDisplay();
278 WaitForFence(display, fence);
279 eglDestroySyncKHR(display, fence);
280 } else if (ozone_surface_->IsUniversalDisplayLinkDevice()) {
281 glFinish();
284 unsubmitted_frames_.back()->ScheduleOverlayPlanes(widget_);
285 unsubmitted_frames_.back()->overlays.clear();
287 return ozone_surface_->OnSwapBuffers();
289 bool GLSurfaceOzoneSurfaceless::ScheduleOverlayPlane(int z_order,
290 OverlayTransform transform,
291 GLImage* image,
292 const Rect& bounds_rect,
293 const RectF& crop_rect) {
294 unsubmitted_frames_.back()->overlays.push_back(
295 Overlay(z_order, transform, image, bounds_rect, crop_rect));
296 return true;
298 bool GLSurfaceOzoneSurfaceless::IsOffscreen() {
299 return false;
301 VSyncProvider* GLSurfaceOzoneSurfaceless::GetVSyncProvider() {
302 return vsync_provider_.get();
304 bool GLSurfaceOzoneSurfaceless::SupportsPostSubBuffer() {
305 return true;
307 bool GLSurfaceOzoneSurfaceless::PostSubBuffer(int x,
308 int y,
309 int width,
310 int height) {
311 // The actual sub buffer handling is handled at higher layers.
312 SwapBuffers();
313 return true;
315 bool GLSurfaceOzoneSurfaceless::SwapBuffersAsync(
316 const SwapCompletionCallback& callback) {
317 // If last swap failed, don't try to schedule new ones.
318 if (!last_swap_buffers_result_)
319 return false;
321 glFlush();
323 base::Closure surface_swap_callback =
324 base::Bind(&GLSurfaceOzoneSurfaceless::SwapCompleted,
325 weak_factory_.GetWeakPtr(), callback);
327 PendingFrame* frame = unsubmitted_frames_.back();
328 frame->callback = surface_swap_callback;
329 unsubmitted_frames_.push_back(new PendingFrame());
331 // TODO: the following should be replaced by a per surface flush as it gets
332 // implemented in GL drivers.
333 if (has_implicit_external_sync_) {
334 EGLSyncKHR fence = InsertFence();
335 if (!fence)
336 return false;
338 base::Closure fence_wait_task =
339 base::Bind(&WaitForFence, GetDisplay(), fence);
341 base::Closure fence_retired_callback =
342 base::Bind(&GLSurfaceOzoneSurfaceless::FenceRetired,
343 weak_factory_.GetWeakPtr(), fence, frame);
345 base::WorkerPool::PostTaskAndReply(FROM_HERE, fence_wait_task,
346 fence_retired_callback, false);
347 return true;
348 } else if (ozone_surface_->IsUniversalDisplayLinkDevice()) {
349 glFinish();
352 frame->ready = true;
353 SubmitFrame();
354 return last_swap_buffers_result_;
356 bool GLSurfaceOzoneSurfaceless::PostSubBufferAsync(
357 int x,
358 int y,
359 int width,
360 int height,
361 const SwapCompletionCallback& callback) {
362 return SwapBuffersAsync(callback);
365 GLSurfaceOzoneSurfaceless::~GLSurfaceOzoneSurfaceless() {
366 Destroy(); // EGL surface must be destroyed before SurfaceOzone
369 void GLSurfaceOzoneSurfaceless::SubmitFrame() {
370 DCHECK(!unsubmitted_frames_.empty());
372 if (unsubmitted_frames_.front()->ready && !swap_buffers_pending_) {
373 scoped_ptr<PendingFrame> frame(unsubmitted_frames_.front());
374 unsubmitted_frames_.weak_erase(unsubmitted_frames_.begin());
375 swap_buffers_pending_ = true;
377 last_swap_buffers_result_ =
378 frame->ScheduleOverlayPlanes(widget_) &&
379 ozone_surface_->OnSwapBuffersAsync(frame->callback);
383 EGLSyncKHR GLSurfaceOzoneSurfaceless::InsertFence() {
384 const EGLint attrib_list[] = {EGL_SYNC_CONDITION_KHR,
385 EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM,
386 EGL_NONE};
387 return eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR, attrib_list);
390 void GLSurfaceOzoneSurfaceless::FenceRetired(EGLSyncKHR fence,
391 PendingFrame* frame) {
392 eglDestroySyncKHR(GetDisplay(), fence);
393 frame->ready = true;
394 SubmitFrame();
397 void GLSurfaceOzoneSurfaceless::SwapCompleted(
398 const SwapCompletionCallback& callback) {
399 callback.Run();
400 swap_buffers_pending_ = false;
402 SubmitFrame();
405 // This provides surface-like semantics implemented through surfaceless.
406 // A framebuffer is bound automatically.
407 class GL_EXPORT GLSurfaceOzoneSurfacelessSurfaceImpl
408 : public GLSurfaceOzoneSurfaceless {
409 public:
410 GLSurfaceOzoneSurfacelessSurfaceImpl(
411 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
412 AcceleratedWidget widget);
414 // GLSurface:
415 unsigned int GetBackingFrameBufferObject() override;
416 bool OnMakeCurrent(GLContext* context) override;
417 bool Resize(const gfx::Size& size) override;
418 bool SupportsPostSubBuffer() override;
419 bool SwapBuffers() override;
420 bool SwapBuffersAsync(const SwapCompletionCallback& callback) override;
421 void Destroy() override;
423 private:
424 class SurfaceImage : public GLImageLinuxDMABuffer {
425 public:
426 SurfaceImage(const gfx::Size& size, unsigned internalformat);
428 bool Initialize(scoped_refptr<ui::NativePixmap> pixmap,
429 gfx::GpuMemoryBuffer::Format format);
430 bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
431 int z_order,
432 gfx::OverlayTransform transform,
433 const gfx::Rect& bounds_rect,
434 const gfx::RectF& crop_rect) override;
436 private:
437 ~SurfaceImage() override;
439 scoped_refptr<ui::NativePixmap> pixmap_;
442 ~GLSurfaceOzoneSurfacelessSurfaceImpl() override;
444 void BindFramebuffer();
445 bool CreatePixmaps();
447 GLuint fbo_;
448 GLuint textures_[2];
449 scoped_refptr<GLImage> images_[2];
450 int current_surface_;
451 DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfacelessSurfaceImpl);
454 GLSurfaceOzoneSurfacelessSurfaceImpl::SurfaceImage::SurfaceImage(
455 const gfx::Size& size,
456 unsigned internalformat)
457 : GLImageLinuxDMABuffer(size, internalformat) {
460 bool GLSurfaceOzoneSurfacelessSurfaceImpl::SurfaceImage::Initialize(
461 scoped_refptr<ui::NativePixmap> pixmap,
462 gfx::GpuMemoryBuffer::Format format) {
463 base::FileDescriptor handle(pixmap->GetDmaBufFd(), false);
464 if (!GLImageLinuxDMABuffer::Initialize(handle, format,
465 pixmap->GetDmaBufPitch()))
466 return false;
467 pixmap_ = pixmap;
468 return true;
470 bool GLSurfaceOzoneSurfacelessSurfaceImpl::SurfaceImage::ScheduleOverlayPlane(
471 gfx::AcceleratedWidget widget,
472 int z_order,
473 gfx::OverlayTransform transform,
474 const gfx::Rect& bounds_rect,
475 const gfx::RectF& crop_rect) {
476 return ui::SurfaceFactoryOzone::GetInstance()->ScheduleOverlayPlane(
477 widget, z_order, transform, pixmap_, bounds_rect, crop_rect);
480 GLSurfaceOzoneSurfacelessSurfaceImpl::SurfaceImage::~SurfaceImage() {
483 GLSurfaceOzoneSurfacelessSurfaceImpl::GLSurfaceOzoneSurfacelessSurfaceImpl(
484 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
485 AcceleratedWidget widget)
486 : GLSurfaceOzoneSurfaceless(ozone_surface.Pass(), widget),
487 fbo_(0),
488 current_surface_(0) {
489 for (auto& texture : textures_)
490 texture = 0;
493 unsigned int
494 GLSurfaceOzoneSurfacelessSurfaceImpl::GetBackingFrameBufferObject() {
495 return fbo_;
498 bool GLSurfaceOzoneSurfacelessSurfaceImpl::OnMakeCurrent(GLContext* context) {
499 if (!fbo_) {
500 glGenFramebuffersEXT(1, &fbo_);
501 if (!fbo_)
502 return false;
503 glGenTextures(arraysize(textures_), textures_);
504 if (!CreatePixmaps())
505 return false;
507 BindFramebuffer();
508 glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_);
509 return SurfacelessEGL::OnMakeCurrent(context);
512 bool GLSurfaceOzoneSurfacelessSurfaceImpl::Resize(const gfx::Size& size) {
513 if (size == GetSize())
514 return true;
515 return GLSurfaceOzoneSurfaceless::Resize(size) && CreatePixmaps();
518 bool GLSurfaceOzoneSurfacelessSurfaceImpl::SupportsPostSubBuffer() {
519 return false;
522 bool GLSurfaceOzoneSurfacelessSurfaceImpl::SwapBuffers() {
523 if (!images_[current_surface_]->ScheduleOverlayPlane(
524 widget_, 0, OverlayTransform::OVERLAY_TRANSFORM_NONE,
525 gfx::Rect(GetSize()), gfx::RectF(1, 1)))
526 return false;
527 if (!GLSurfaceOzoneSurfaceless::SwapBuffers())
528 return false;
529 current_surface_ ^= 1;
530 BindFramebuffer();
531 return true;
534 bool GLSurfaceOzoneSurfacelessSurfaceImpl::SwapBuffersAsync(
535 const SwapCompletionCallback& callback) {
536 if (!images_[current_surface_]->ScheduleOverlayPlane(
537 widget_, 0, OverlayTransform::OVERLAY_TRANSFORM_NONE,
538 gfx::Rect(GetSize()), gfx::RectF(1, 1)))
539 return false;
540 if (!GLSurfaceOzoneSurfaceless::SwapBuffersAsync(callback))
541 return false;
542 current_surface_ ^= 1;
543 BindFramebuffer();
544 return true;
547 void GLSurfaceOzoneSurfacelessSurfaceImpl::Destroy() {
548 GLContext* current_context = GLContext::GetCurrent();
549 DCHECK(current_context && current_context->IsCurrent(this));
550 glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
551 if (fbo_) {
552 glDeleteTextures(arraysize(textures_), textures_);
553 for (auto& texture : textures_)
554 texture = 0;
555 glDeleteFramebuffersEXT(1, &fbo_);
556 fbo_ = 0;
558 for (auto image : images_) {
559 if (image)
560 image->Destroy(true);
564 GLSurfaceOzoneSurfacelessSurfaceImpl::~GLSurfaceOzoneSurfacelessSurfaceImpl() {
565 DCHECK(!fbo_);
566 for (size_t i = 0; i < arraysize(textures_); i++)
567 DCHECK(!textures_[i]) << "texture " << i << " not released";
570 void GLSurfaceOzoneSurfacelessSurfaceImpl::BindFramebuffer() {
571 ScopedFrameBufferBinder fb(fbo_);
572 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
573 textures_[current_surface_], 0);
576 bool GLSurfaceOzoneSurfacelessSurfaceImpl::CreatePixmaps() {
577 if (!fbo_)
578 return true;
579 for (size_t i = 0; i < arraysize(textures_); i++) {
580 scoped_refptr<ui::NativePixmap> pixmap =
581 ui::SurfaceFactoryOzone::GetInstance()->CreateNativePixmap(
582 widget_, GetSize(), ui::SurfaceFactoryOzone::BGRA_8888,
583 ui::SurfaceFactoryOzone::SCANOUT);
584 if (!pixmap)
585 return false;
586 scoped_refptr<SurfaceImage> image =
587 new SurfaceImage(GetSize(), GL_BGRA_EXT);
588 if (!image->Initialize(pixmap, gfx::GpuMemoryBuffer::Format::BGRA_8888))
589 return false;
590 images_[i] = image;
591 // Bind image to texture.
592 ScopedTextureBinder binder(GL_TEXTURE_2D, textures_[i]);
593 if (!images_[i]->BindTexImage(GL_TEXTURE_2D))
594 return false;
596 return true;
599 } // namespace
601 // static
602 bool GLSurface::InitializeOneOffInternal() {
603 switch (GetGLImplementation()) {
604 case kGLImplementationEGLGLES2:
605 if (!GLSurfaceEGL::InitializeOneOff()) {
606 LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
607 return false;
610 return true;
611 case kGLImplementationOSMesaGL:
612 case kGLImplementationMockGL:
613 return true;
614 default:
615 return false;
619 // static
620 scoped_refptr<GLSurface> GLSurface::CreateSurfacelessViewGLSurface(
621 gfx::AcceleratedWidget window) {
622 if (GetGLImplementation() == kGLImplementationEGLGLES2 &&
623 window != kNullAcceleratedWidget &&
624 GLSurfaceEGL::IsEGLSurfacelessContextSupported() &&
625 ui::SurfaceFactoryOzone::GetInstance()->CanShowPrimaryPlaneAsOverlay()) {
626 scoped_ptr<ui::SurfaceOzoneEGL> surface_ozone =
627 ui::SurfaceFactoryOzone::GetInstance()
628 ->CreateSurfacelessEGLSurfaceForWidget(window);
629 if (!surface_ozone)
630 return nullptr;
631 scoped_refptr<GLSurface> surface;
632 surface = new GLSurfaceOzoneSurfaceless(surface_ozone.Pass(), window);
633 if (surface->Initialize())
634 return surface;
637 return nullptr;
640 // static
641 scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface(
642 gfx::AcceleratedWidget window) {
643 if (GetGLImplementation() == kGLImplementationOSMesaGL) {
644 scoped_refptr<GLSurface> surface(new GLSurfaceOSMesaHeadless());
645 if (!surface->Initialize())
646 return NULL;
647 return surface;
649 DCHECK(GetGLImplementation() == kGLImplementationEGLGLES2);
650 if (window != kNullAcceleratedWidget) {
651 scoped_refptr<GLSurface> surface;
652 if (GLSurfaceEGL::IsEGLSurfacelessContextSupported() &&
653 ui::SurfaceFactoryOzone::GetInstance()
654 ->CanShowPrimaryPlaneAsOverlay()) {
655 scoped_ptr<ui::SurfaceOzoneEGL> surface_ozone =
656 ui::SurfaceFactoryOzone::GetInstance()
657 ->CreateSurfacelessEGLSurfaceForWidget(window);
658 if (!surface_ozone)
659 return NULL;
660 surface = new GLSurfaceOzoneSurfacelessSurfaceImpl(surface_ozone.Pass(),
661 window);
662 } else {
663 scoped_ptr<ui::SurfaceOzoneEGL> surface_ozone =
664 ui::SurfaceFactoryOzone::GetInstance()->CreateEGLSurfaceForWidget(
665 window);
666 if (!surface_ozone)
667 return NULL;
669 surface = new GLSurfaceOzoneEGL(surface_ozone.Pass(), window);
671 if (!surface->Initialize())
672 return NULL;
673 return surface;
674 } else {
675 scoped_refptr<GLSurface> surface = new GLSurfaceStub();
676 if (surface->Initialize())
677 return surface;
679 return NULL;
682 // static
683 scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
684 const gfx::Size& size) {
685 switch (GetGLImplementation()) {
686 case kGLImplementationOSMesaGL: {
687 scoped_refptr<GLSurface> surface(
688 new GLSurfaceOSMesa(OSMesaSurfaceFormatBGRA, size));
689 if (!surface->Initialize())
690 return NULL;
692 return surface;
694 case kGLImplementationEGLGLES2: {
695 scoped_refptr<GLSurface> surface;
696 if (GLSurfaceEGL::IsEGLSurfacelessContextSupported() &&
697 (size.width() == 0 && size.height() == 0)) {
698 surface = new SurfacelessEGL(size);
699 } else
700 surface = new PbufferGLSurfaceEGL(size);
702 if (!surface->Initialize())
703 return NULL;
704 return surface;
706 case kGLImplementationMockGL:
707 return new GLSurfaceStub;
708 default:
709 NOTREACHED();
710 return NULL;
714 EGLNativeDisplayType GetPlatformDefaultEGLNativeDisplay() {
715 return ui::SurfaceFactoryOzone::GetInstance()->GetNativeDisplay();
718 } // namespace gfx