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_buffer.h"
12 #include "base/logging.h"
13 #include "base/trace_event/trace_event.h"
14 #include "ui/gfx/geometry/size_conversions.h"
15 #include "ui/ozone/platform/drm/gpu/drm_window.h"
16 #include "ui/ozone/platform/drm/gpu/gbm_device.h"
22 int GetGbmFormatFromBufferFormat(SurfaceFactoryOzone::BufferFormat fmt
) {
24 case SurfaceFactoryOzone::BGRA_8888
:
25 return GBM_BO_FORMAT_ARGB8888
;
26 case SurfaceFactoryOzone::RGBX_8888
:
27 return GBM_BO_FORMAT_XRGB8888
;
36 GbmBuffer::GbmBuffer(const scoped_refptr
<GbmDevice
>& gbm
,
39 : GbmBufferBase(gbm
, bo
, scanout
) {
42 GbmBuffer::~GbmBuffer() {
48 scoped_refptr
<GbmBuffer
> GbmBuffer::CreateBuffer(
49 const scoped_refptr
<GbmDevice
>& gbm
,
50 SurfaceFactoryOzone::BufferFormat format
,
51 const gfx::Size
& size
,
53 TRACE_EVENT2("drm", "GbmBuffer::CreateBuffer", "device",
54 gbm
->device_path().value(), "size", size
.ToString());
55 unsigned flags
= GBM_BO_USE_RENDERING
;
57 flags
|= GBM_BO_USE_SCANOUT
;
58 gbm_bo
* bo
= gbm_bo_create(gbm
->device(), size
.width(), size
.height(),
59 GetGbmFormatFromBufferFormat(format
), flags
);
63 scoped_refptr
<GbmBuffer
> buffer(new GbmBuffer(gbm
, bo
, scanout
));
64 if (scanout
&& !buffer
->GetFramebufferId())
70 GbmPixmap::GbmPixmap(const scoped_refptr
<GbmBuffer
>& buffer
,
71 ScreenManager
* screen_manager
)
72 : buffer_(buffer
), screen_manager_(screen_manager
) {
75 bool GbmPixmap::Initialize() {
76 // We want to use the GBM API because it's going to call into libdrm
77 // which might do some optimizations on buffer allocation,
78 // especially when sharing buffers via DMABUF.
79 dma_buf_
= gbm_bo_get_fd(buffer_
->bo());
81 PLOG(ERROR
) << "Failed to export buffer to dma_buf";
87 void GbmPixmap::SetScalingCallback(const ScalingCallback
& scaling_callback
) {
88 scaling_callback_
= scaling_callback
;
91 scoped_refptr
<NativePixmap
> GbmPixmap::GetScaledPixmap(gfx::Size new_size
) {
92 return scaling_callback_
.Run(new_size
);
95 GbmPixmap::~GbmPixmap() {
100 void* GbmPixmap::GetEGLClientBuffer() {
104 int GbmPixmap::GetDmaBufFd() {
108 int GbmPixmap::GetDmaBufPitch() {
109 return gbm_bo_get_stride(buffer_
->bo());
112 bool GbmPixmap::ScheduleOverlayPlane(gfx::AcceleratedWidget widget
,
114 gfx::OverlayTransform plane_transform
,
115 const gfx::Rect
& display_bounds
,
116 const gfx::RectF
& crop_rect
) {
117 gfx::Size required_size
;
119 ShouldApplyScaling(display_bounds
, crop_rect
, &required_size
)) {
120 scoped_refptr
<NativePixmap
> scaled_pixmap
= GetScaledPixmap(required_size
);
122 return scaled_pixmap
->ScheduleOverlayPlane(
123 widget
, plane_z_order
, plane_transform
, display_bounds
, crop_rect
);
129 screen_manager_
->GetWindow(widget
)->QueueOverlayPlane(OverlayPlane(
130 buffer_
, plane_z_order
, plane_transform
, display_bounds
, crop_rect
));
134 bool GbmPixmap::ShouldApplyScaling(const gfx::Rect
& display_bounds
,
135 const gfx::RectF
& crop_rect
,
136 gfx::Size
* required_size
) {
137 if (crop_rect
.width() == 0 || crop_rect
.height() == 0) {
138 PLOG(ERROR
) << "ShouldApplyScaling passed zero scaling target.";
142 gfx::Size pixmap_size
= buffer_
->GetSize();
143 // If the required size is not integer-sized, round it to the next integer.
144 *required_size
= gfx::ToCeiledSize(
145 gfx::SizeF(display_bounds
.width() / crop_rect
.width(),
146 display_bounds
.height() / crop_rect
.height()));
147 return pixmap_size
!= *required_size
;