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