1 // Copyright 2018 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.
4 
5 #include "ui/ozone/platform/drm/gpu/drm_framebuffer.h"
6 
7 #include <utility>
8 
9 #include "base/logging.h"
10 #include "ui/gfx/buffer_format_util.h"
11 #include "ui/gfx/linux/drm_util_linux.h"
12 #include "ui/gfx/linux/gbm_buffer.h"
13 #include "ui/ozone/platform/drm/common/drm_util.h"
14 #include "ui/ozone/platform/drm/gpu/drm_device.h"
15 
16 namespace ui {
17 
18 DrmFramebuffer::AddFramebufferParams::AddFramebufferParams() = default;
19 DrmFramebuffer::AddFramebufferParams::AddFramebufferParams(
20     const AddFramebufferParams& other) = default;
21 DrmFramebuffer::AddFramebufferParams::~AddFramebufferParams() = default;
22 
23 // static
AddFramebuffer(scoped_refptr<DrmDevice> drm_device,DrmFramebuffer::AddFramebufferParams params)24 scoped_refptr<DrmFramebuffer> DrmFramebuffer::AddFramebuffer(
25     scoped_refptr<DrmDevice> drm_device,
26     DrmFramebuffer::AddFramebufferParams params) {
27   uint64_t modifiers[4] = {0};
28   if (params.modifier != DRM_FORMAT_MOD_INVALID) {
29     for (size_t i = 0; i < params.num_planes; ++i)
30       modifiers[i] = params.modifier;
31   }
32 
33   const auto fourcc_format = GetBufferFormatFromFourCCFormat(params.format);
34   const uint32_t opaque_format =
35       GetFourCCFormatForOpaqueFramebuffer(fourcc_format);
36   // Intel Display Controller won't support AR/B30 framebuffers, only XR/B30,
37   // but that doesn't matter because anyway those two bits of alpha are useless;
38   // use the opaque directly in this case.
39   const bool force_opaque = AlphaBitsForBufferFormat(fourcc_format) == 2;
40 
41   const auto drm_format = force_opaque ? opaque_format : params.format;
42 
43   uint32_t framebuffer_id = 0;
44   if (!drm_device->AddFramebuffer2(params.width, params.height, drm_format,
45                                    params.handles, params.strides,
46                                    params.offsets, modifiers, &framebuffer_id,
47                                    params.flags)) {
48     DPLOG(WARNING) << "AddFramebuffer2";
49     return nullptr;
50   }
51 
52   uint32_t opaque_framebuffer_id = 0;
53   if (opaque_format != drm_format &&
54       !drm_device->AddFramebuffer2(params.width, params.height, opaque_format,
55                                    params.handles, params.strides,
56                                    params.offsets, modifiers,
57                                    &opaque_framebuffer_id, params.flags)) {
58     DPLOG(WARNING) << "AddFramebuffer2";
59     drm_device->RemoveFramebuffer(framebuffer_id);
60     return nullptr;
61   }
62 
63   return base::MakeRefCounted<DrmFramebuffer>(
64       std::move(drm_device), framebuffer_id, drm_format, opaque_framebuffer_id,
65       opaque_format, params.modifier, params.preferred_modifiers,
66       gfx::Size(params.width, params.height));
67 }
68 
69 // static
AddFramebuffer(scoped_refptr<DrmDevice> drm,const GbmBuffer * buffer,const gfx::Size & framebuffer_size,std::vector<uint64_t> preferred_modifiers)70 scoped_refptr<DrmFramebuffer> DrmFramebuffer::AddFramebuffer(
71     scoped_refptr<DrmDevice> drm,
72     const GbmBuffer* buffer,
73     const gfx::Size& framebuffer_size,
74     std::vector<uint64_t> preferred_modifiers) {
75   DCHECK(gfx::Rect(buffer->GetSize()).Contains(gfx::Rect(framebuffer_size)));
76   AddFramebufferParams params;
77   params.format = buffer->GetFormat();
78   params.modifier = buffer->GetFormatModifier();
79   params.width = framebuffer_size.width();
80   params.height = framebuffer_size.height();
81   params.num_planes = buffer->GetNumPlanes();
82   params.preferred_modifiers = preferred_modifiers;
83   for (size_t i = 0; i < params.num_planes; ++i) {
84     params.handles[i] = buffer->GetPlaneHandle(i);
85     params.strides[i] = buffer->GetPlaneStride(i);
86     params.offsets[i] = buffer->GetPlaneOffset(i);
87   }
88 
89   // AddFramebuffer2 only considers the modifiers if addfb_flags has
90   // DRM_MODE_FB_MODIFIERS set. We only set that when we've created
91   // a bo with modifiers, otherwise, we rely on the "no modifiers"
92   // behavior doing the right thing.
93   params.flags = 0;
94   if (drm->allow_addfb2_modifiers() &&
95       params.modifier != DRM_FORMAT_MOD_INVALID)
96     params.flags |= DRM_MODE_FB_MODIFIERS;
97 
98   return AddFramebuffer(std::move(drm), params);
99 }
100 
DrmFramebuffer(scoped_refptr<DrmDevice> drm_device,uint32_t framebuffer_id,uint32_t framebuffer_pixel_format,uint32_t opaque_framebuffer_id,uint32_t opaque_framebuffer_pixel_format,uint64_t format_modifier,std::vector<uint64_t> modifiers,const gfx::Size & size)101 DrmFramebuffer::DrmFramebuffer(scoped_refptr<DrmDevice> drm_device,
102                                uint32_t framebuffer_id,
103                                uint32_t framebuffer_pixel_format,
104                                uint32_t opaque_framebuffer_id,
105                                uint32_t opaque_framebuffer_pixel_format,
106                                uint64_t format_modifier,
107                                std::vector<uint64_t> modifiers,
108                                const gfx::Size& size)
109     : drm_device_(std::move(drm_device)),
110       framebuffer_id_(framebuffer_id),
111       framebuffer_pixel_format_(framebuffer_pixel_format),
112       opaque_framebuffer_id_(opaque_framebuffer_id),
113       opaque_framebuffer_pixel_format_(opaque_framebuffer_pixel_format),
114       format_modifier_(format_modifier),
115       preferred_modifiers_(modifiers),
116       size_(size) {}
117 
~DrmFramebuffer()118 DrmFramebuffer::~DrmFramebuffer() {
119   if (!drm_device_->RemoveFramebuffer(framebuffer_id_))
120     PLOG(WARNING) << "RemoveFramebuffer";
121   if (opaque_framebuffer_id_ &&
122       !drm_device_->RemoveFramebuffer(opaque_framebuffer_id_))
123     PLOG(WARNING) << "RemoveFramebuffer";
124 }
125 
126 }  // namespace ui
127