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