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/ozone/platform/drm/gpu/gbm_surface.h"
10 #include "base/logging.h"
11 #include "ui/ozone/platform/drm/gpu/drm_buffer.h"
12 #include "ui/ozone/platform/drm/gpu/drm_window.h"
13 #include "ui/ozone/platform/drm/gpu/gbm_buffer_base.h"
14 #include "ui/ozone/platform/drm/gpu/gbm_device.h"
15 #include "ui/ozone/platform/drm/gpu/hardware_display_controller.h"
16 #include "ui/ozone/platform/drm/gpu/scanout_buffer.h"
22 class GbmSurfaceBuffer
: public GbmBufferBase
{
24 static scoped_refptr
<GbmSurfaceBuffer
> CreateBuffer(
25 const scoped_refptr
<DrmDevice
>& drm
,
27 static scoped_refptr
<GbmSurfaceBuffer
> GetBuffer(gbm_bo
* buffer
);
30 GbmSurfaceBuffer(const scoped_refptr
<DrmDevice
>& drm
, gbm_bo
* bo
);
31 ~GbmSurfaceBuffer() override
;
33 static void Destroy(gbm_bo
* buffer
, void* data
);
35 // This buffer is special and is released by GBM at any point in time (as
36 // long as it isn't being used). Since GBM should be the only one to
37 // release this buffer, keep a self-reference in order to keep this alive.
38 // When GBM calls Destroy(..) the self-reference will dissapear and this will
40 scoped_refptr
<GbmSurfaceBuffer
> self_
;
42 DISALLOW_COPY_AND_ASSIGN(GbmSurfaceBuffer
);
45 GbmSurfaceBuffer::GbmSurfaceBuffer(const scoped_refptr
<DrmDevice
>& drm
,
47 : GbmBufferBase(drm
, bo
, true) {
48 if (GetFramebufferId()) {
50 gbm_bo_set_user_data(bo
, this, GbmSurfaceBuffer::Destroy
);
54 GbmSurfaceBuffer::~GbmSurfaceBuffer() {
58 scoped_refptr
<GbmSurfaceBuffer
> GbmSurfaceBuffer::CreateBuffer(
59 const scoped_refptr
<DrmDevice
>& drm
,
61 scoped_refptr
<GbmSurfaceBuffer
> scoped_buffer(
62 new GbmSurfaceBuffer(drm
, buffer
));
63 if (!scoped_buffer
->GetFramebufferId())
70 scoped_refptr
<GbmSurfaceBuffer
> GbmSurfaceBuffer::GetBuffer(gbm_bo
* buffer
) {
71 return scoped_refptr
<GbmSurfaceBuffer
>(
72 static_cast<GbmSurfaceBuffer
*>(gbm_bo_get_user_data(buffer
)));
76 void GbmSurfaceBuffer::Destroy(gbm_bo
* buffer
, void* data
) {
77 GbmSurfaceBuffer
* scoped_buffer
= static_cast<GbmSurfaceBuffer
*>(data
);
78 scoped_buffer
->self_
= NULL
;
83 GbmSurface::GbmSurface(DrmWindow
* window_delegate
,
84 const scoped_refptr
<GbmDevice
>& gbm
)
85 : GbmSurfaceless(window_delegate
, NULL
),
87 native_surface_(NULL
),
88 current_buffer_(NULL
),
92 GbmSurface::~GbmSurface() {
94 gbm_surface_release_buffer(native_surface_
, current_buffer_
);
97 gbm_surface_destroy(native_surface_
);
100 bool GbmSurface::Initialize() {
101 // If we're initializing the surface without a controller (possible on startup
102 // where the surface creation can happen before the native window delegate
103 // IPCs arrive), initialize the size to a valid value such that surface
104 // creation doesn't fail.
105 gfx::Size
size(1, 1);
106 if (window_delegate_
->GetController()) {
107 size
= window_delegate_
->GetController()->GetModeSize();
109 // TODO(dnicoara) Check underlying system support for pixel format.
110 native_surface_
= gbm_surface_create(
111 gbm_
->device(), size
.width(), size
.height(), GBM_BO_FORMAT_XRGB8888
,
112 GBM_BO_USE_SCANOUT
| GBM_BO_USE_RENDERING
);
114 if (!native_surface_
)
121 intptr_t GbmSurface::GetNativeWindow() {
122 DCHECK(native_surface_
);
123 return reinterpret_cast<intptr_t>(native_surface_
);
126 bool GbmSurface::ResizeNativeWindow(const gfx::Size
& viewport_size
) {
127 if (size_
== viewport_size
)
133 bool GbmSurface::OnSwapBuffers() {
134 return OnSwapBuffersAsync(base::Bind(&base::DoNothing
));
137 bool GbmSurface::OnSwapBuffersAsync(const SwapCompletionCallback
& callback
) {
138 DCHECK(native_surface_
);
140 gbm_bo
* pending_buffer
= gbm_surface_lock_front_buffer(native_surface_
);
141 scoped_refptr
<GbmSurfaceBuffer
> primary
=
142 GbmSurfaceBuffer::GetBuffer(pending_buffer
);
143 if (!primary
.get()) {
144 primary
= GbmSurfaceBuffer::CreateBuffer(gbm_
, pending_buffer
);
145 if (!primary
.get()) {
146 LOG(ERROR
) << "Failed to associate the buffer with the controller";
152 // The primary buffer is a special case.
153 if (window_delegate_
->GetController())
154 window_delegate_
->GetController()->QueueOverlayPlane(OverlayPlane(primary
));
156 if (!GbmSurfaceless::OnSwapBuffersAsync(
157 base::Bind(&GbmSurface::OnSwapBuffersCallback
,
158 weak_factory_
.GetWeakPtr(), callback
, pending_buffer
))) {
166 void GbmSurface::OnSwapBuffersCallback(const SwapCompletionCallback
& callback
,
167 gbm_bo
* pending_buffer
) {
168 // If there was a frontbuffer, it is no longer active. Release it back to GBM.
170 gbm_surface_release_buffer(native_surface_
, current_buffer_
);
172 current_buffer_
= pending_buffer
;