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/logging.h"
8 #include "base/memory/ref_counted.h"
9 #include "ui/gfx/native_widget_types.h"
10 #include "ui/gl/gl_context.h"
11 #include "ui/gl/gl_image.h"
12 #include "ui/gl/gl_implementation.h"
13 #include "ui/gl/gl_surface_egl.h"
14 #include "ui/gl/gl_surface_osmesa.h"
15 #include "ui/gl/gl_surface_stub.h"
16 #include "ui/gl/scoped_make_current.h"
17 #include "ui/ozone/public/surface_factory_ozone.h"
18 #include "ui/ozone/public/surface_ozone_egl.h"
24 // A thin wrapper around GLSurfaceEGL that owns the EGLNativeWindow
25 class GL_EXPORT GLSurfaceOzoneEGL
: public NativeViewGLSurfaceEGL
{
27 GLSurfaceOzoneEGL(scoped_ptr
<ui::SurfaceOzoneEGL
> ozone_surface
,
28 AcceleratedWidget widget
)
29 : NativeViewGLSurfaceEGL(ozone_surface
->GetNativeWindow()),
30 ozone_surface_(ozone_surface
.Pass()),
33 bool Initialize() override
{
34 return Initialize(ozone_surface_
->CreateVSyncProvider());
36 bool Resize(const gfx::Size
& size
) override
{
37 if (!ozone_surface_
->ResizeNativeWindow(size
)) {
38 if (!ReinitializeNativeSurface() ||
39 !ozone_surface_
->ResizeNativeWindow(size
))
43 return NativeViewGLSurfaceEGL::Resize(size
);
45 bool SwapBuffers() override
{
46 if (!NativeViewGLSurfaceEGL::SwapBuffers())
49 return ozone_surface_
->OnSwapBuffers();
51 bool ScheduleOverlayPlane(int z_order
,
52 OverlayTransform transform
,
54 const Rect
& bounds_rect
,
55 const RectF
& crop_rect
) override
{
56 return image
->ScheduleOverlayPlane(
57 widget_
, z_order
, transform
, bounds_rect
, crop_rect
);
61 using NativeViewGLSurfaceEGL::Initialize
;
63 ~GLSurfaceOzoneEGL() override
{
64 Destroy(); // EGL surface must be destroyed before SurfaceOzone
67 bool ReinitializeNativeSurface() {
68 scoped_ptr
<ui::ScopedMakeCurrent
> scoped_make_current
;
69 GLContext
* current_context
= GLContext::GetCurrent();
71 current_context
&& current_context
->IsCurrent(this);
73 scoped_make_current
.reset(
74 new ui::ScopedMakeCurrent(current_context
, this));
79 ui::SurfaceFactoryOzone::GetInstance()->CreateEGLSurfaceForWidget(
81 if (!ozone_surface_
) {
82 LOG(ERROR
) << "Failed to create native surface.";
86 window_
= ozone_surface_
->GetNativeWindow();
88 LOG(ERROR
) << "Failed to initialize.";
95 // The native surface. Deleting this is allowed to free the EGLNativeWindow.
96 scoped_ptr
<ui::SurfaceOzoneEGL
> ozone_surface_
;
97 AcceleratedWidget widget_
;
99 DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneEGL
);
102 class GL_EXPORT GLSurfaceOzoneSurfaceless
: public SurfacelessEGL
{
104 GLSurfaceOzoneSurfaceless(scoped_ptr
<ui::SurfaceOzoneEGL
> ozone_surface
,
105 AcceleratedWidget widget
)
106 : SurfacelessEGL(gfx::Size()),
107 ozone_surface_(ozone_surface
.Pass()),
110 bool Initialize() override
{
111 if (!SurfacelessEGL::Initialize())
113 vsync_provider_
= ozone_surface_
->CreateVSyncProvider();
114 if (!vsync_provider_
)
118 bool Resize(const gfx::Size
& size
) override
{
119 if (!ozone_surface_
->ResizeNativeWindow(size
))
122 return SurfacelessEGL::Resize(size
);
124 bool SwapBuffers() override
{
125 // TODO: this should be replaced by a fence when supported by the driver.
127 return ozone_surface_
->OnSwapBuffers();
129 bool ScheduleOverlayPlane(int z_order
,
130 OverlayTransform transform
,
132 const Rect
& bounds_rect
,
133 const RectF
& crop_rect
) override
{
134 return image
->ScheduleOverlayPlane(
135 widget_
, z_order
, transform
, bounds_rect
, crop_rect
);
137 bool IsOffscreen() override
{ return false; }
138 VSyncProvider
* GetVSyncProvider() override
{ return vsync_provider_
.get(); }
139 bool SupportsPostSubBuffer() override
{ return true; }
140 bool PostSubBuffer(int x
, int y
, int width
, int height
) override
{
141 // The actual sub buffer handling is handled at higher layers.
145 bool SwapBuffersAsync(const SwapCompletionCallback
& callback
) override
{
146 // TODO: this should be replaced by a fence when supported by the driver.
148 return ozone_surface_
->OnSwapBuffersAsync(callback
);
150 bool PostSubBufferAsync(int x
,
154 const SwapCompletionCallback
& callback
) override
{
155 return SwapBuffersAsync(callback
);
159 ~GLSurfaceOzoneSurfaceless() override
{
160 Destroy(); // EGL surface must be destroyed before SurfaceOzone
163 // The native surface. Deleting this is allowed to free the EGLNativeWindow.
164 scoped_ptr
<ui::SurfaceOzoneEGL
> ozone_surface_
;
165 AcceleratedWidget widget_
;
166 scoped_ptr
<VSyncProvider
> vsync_provider_
;
168 DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfaceless
);
174 bool GLSurface::InitializeOneOffInternal() {
175 switch (GetGLImplementation()) {
176 case kGLImplementationEGLGLES2
:
177 if (!GLSurfaceEGL::InitializeOneOff()) {
178 LOG(ERROR
) << "GLSurfaceEGL::InitializeOneOff failed.";
183 case kGLImplementationOSMesaGL
:
184 case kGLImplementationMockGL
:
192 scoped_refptr
<GLSurface
> GLSurface::CreateViewGLSurface(
193 gfx::AcceleratedWidget window
) {
194 if (GetGLImplementation() == kGLImplementationOSMesaGL
) {
195 scoped_refptr
<GLSurface
> surface(new GLSurfaceOSMesaHeadless());
196 if (!surface
->Initialize())
200 DCHECK(GetGLImplementation() == kGLImplementationEGLGLES2
);
201 if (window
!= kNullAcceleratedWidget
) {
202 scoped_refptr
<GLSurface
> surface
;
203 if (GLSurfaceEGL::IsEGLSurfacelessContextSupported() &&
204 ui::SurfaceFactoryOzone::GetInstance()
205 ->CanShowPrimaryPlaneAsOverlay()) {
206 scoped_ptr
<ui::SurfaceOzoneEGL
> surface_ozone
=
207 ui::SurfaceFactoryOzone::GetInstance()
208 ->CreateSurfacelessEGLSurfaceForWidget(window
);
211 surface
= new GLSurfaceOzoneSurfaceless(surface_ozone
.Pass(), window
);
213 scoped_ptr
<ui::SurfaceOzoneEGL
> surface_ozone
=
214 ui::SurfaceFactoryOzone::GetInstance()->CreateEGLSurfaceForWidget(
219 surface
= new GLSurfaceOzoneEGL(surface_ozone
.Pass(), window
);
221 if (!surface
->Initialize())
225 scoped_refptr
<GLSurface
> surface
= new GLSurfaceStub();
226 if (surface
->Initialize())
233 scoped_refptr
<GLSurface
> GLSurface::CreateOffscreenGLSurface(
234 const gfx::Size
& size
) {
235 switch (GetGLImplementation()) {
236 case kGLImplementationOSMesaGL
: {
237 scoped_refptr
<GLSurface
> surface(
238 new GLSurfaceOSMesa(OSMesaSurfaceFormatBGRA
, size
));
239 if (!surface
->Initialize())
244 case kGLImplementationEGLGLES2
: {
245 scoped_refptr
<GLSurface
> surface
;
246 if (GLSurfaceEGL::IsEGLSurfacelessContextSupported() &&
247 (size
.width() == 0 && size
.height() == 0)) {
248 surface
= new SurfacelessEGL(size
);
250 surface
= new PbufferGLSurfaceEGL(size
);
252 if (!surface
->Initialize())
262 EGLNativeDisplayType
GetPlatformDefaultEGLNativeDisplay() {
263 return ui::SurfaceFactoryOzone::GetInstance()->GetNativeDisplay();