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/hardware_display_plane_manager.h"
12 #include "base/logging.h"
13 #include "ui/gfx/geometry/rect.h"
14 #include "ui/ozone/platform/drm/gpu/crtc_controller.h"
15 #include "ui/ozone/platform/drm/gpu/drm_device.h"
16 #include "ui/ozone/platform/drm/gpu/hardware_display_controller.h"
17 #include "ui/ozone/platform/drm/gpu/scanout_buffer.h"
18 #include "ui/ozone/public/ozone_switches.h"
23 const float kFixedPointScaleValue
= 65536.0f
;
27 HardwareDisplayPlaneList::HardwareDisplayPlaneList() : committed(false) {
29 HardwareDisplayPlaneList::~HardwareDisplayPlaneList() {
30 for (auto* plane
: plane_list
) {
31 plane
->set_in_use(false);
32 plane
->set_owning_crtc(0);
34 for (auto* plane
: old_plane_list
) {
35 plane
->set_in_use(false);
36 plane
->set_owning_crtc(0);
40 HardwareDisplayPlaneList::PageFlipInfo::PageFlipInfo(uint32_t crtc_id
,
43 : crtc_id(crtc_id
), framebuffer(framebuffer
), crtc(crtc
) {
46 HardwareDisplayPlaneList::PageFlipInfo::~PageFlipInfo() {
49 HardwareDisplayPlaneList::PageFlipInfo::Plane::Plane(int plane
,
51 const gfx::Rect
& bounds
,
52 const gfx::Rect
& src_rect
)
54 framebuffer(framebuffer
),
59 HardwareDisplayPlaneList::PageFlipInfo::Plane::~Plane() {
62 HardwareDisplayPlaneManager::HardwareDisplayPlaneManager() : drm_(nullptr) {
65 HardwareDisplayPlaneManager::~HardwareDisplayPlaneManager() {
68 bool HardwareDisplayPlaneManager::Initialize(DrmDevice
* drm
) {
70 ScopedDrmResourcesPtr
resources(drmModeGetResources(drm
->get_fd()));
72 PLOG(ERROR
) << "Failed to get resources";
76 ScopedDrmPlaneResPtr
plane_resources(drmModeGetPlaneResources(drm
->get_fd()));
77 if (!plane_resources
) {
78 PLOG(ERROR
) << "Failed to get plane resources";
83 for (int i
= 0; i
< resources
->count_crtcs
; ++i
) {
84 crtcs_
.push_back(resources
->crtcs
[i
]);
87 uint32_t num_planes
= plane_resources
->count_planes
;
88 std::set
<uint32_t> plane_ids
;
89 for (uint32_t i
= 0; i
< num_planes
; ++i
) {
90 ScopedDrmPlanePtr
drm_plane(
91 drmModeGetPlane(drm
->get_fd(), plane_resources
->planes
[i
]));
93 PLOG(ERROR
) << "Failed to get plane " << i
;
96 plane_ids
.insert(drm_plane
->plane_id
);
97 scoped_ptr
<HardwareDisplayPlane
> plane(
98 CreatePlane(drm_plane
->plane_id
, drm_plane
->possible_crtcs
));
99 if (plane
->Initialize(drm
))
100 planes_
.push_back(plane
.release());
103 // crbug.com/464085: if driver reports no primary planes for a crtc, create a
104 // dummy plane for which we can assign exactly one overlay.
105 // TODO(dnicoara): refactor this to simplify AssignOverlayPlanes and move
106 // this workaround into HardwareDisplayPlaneLegacy.
107 for (int i
= 0; i
< resources
->count_crtcs
; ++i
) {
108 if (plane_ids
.find(resources
->crtcs
[i
] - 1) == plane_ids
.end()) {
109 scoped_ptr
<HardwareDisplayPlane
> dummy_plane(
110 CreatePlane(resources
->crtcs
[i
] - 1, (1 << i
)));
111 dummy_plane
->set_is_dummy(true);
112 if (dummy_plane
->Initialize(drm
))
113 planes_
.push_back(dummy_plane
.release());
117 std::sort(planes_
.begin(), planes_
.end(),
118 [](HardwareDisplayPlane
* l
, HardwareDisplayPlane
* r
) {
119 return l
->plane_id() < r
->plane_id();
124 scoped_ptr
<HardwareDisplayPlane
> HardwareDisplayPlaneManager::CreatePlane(
126 uint32_t possible_crtcs
) {
127 return scoped_ptr
<HardwareDisplayPlane
>(
128 new HardwareDisplayPlane(plane_id
, possible_crtcs
));
131 HardwareDisplayPlane
* HardwareDisplayPlaneManager::FindNextUnusedPlane(
133 uint32_t crtc_index
) {
134 for (size_t i
= *index
; i
< planes_
.size(); ++i
) {
135 auto plane
= planes_
[i
];
136 if (!plane
->in_use() && plane
->CanUseForCrtc(crtc_index
)) {
144 int HardwareDisplayPlaneManager::LookupCrtcIndex(uint32_t crtc_id
) {
145 for (size_t i
= 0; i
< crtcs_
.size(); ++i
)
146 if (crtcs_
[i
] == crtc_id
)
151 bool HardwareDisplayPlaneManager::AssignOverlayPlanes(
152 HardwareDisplayPlaneList
* plane_list
,
153 const OverlayPlaneList
& overlay_list
,
155 CrtcController
* crtc
) {
156 // If we had previously committed this set, mark all owned planes as free.
157 if (plane_list
->committed
) {
158 plane_list
->committed
= false;
159 for (auto* plane
: plane_list
->old_plane_list
) {
160 plane
->set_in_use(false);
164 int crtc_index
= LookupCrtcIndex(crtc_id
);
165 if (crtc_index
< 0) {
166 LOG(ERROR
) << "Cannot find crtc " << crtc_id
;
170 size_t plane_idx
= 0;
171 for (const auto& plane
: overlay_list
) {
172 HardwareDisplayPlane
* hw_plane
=
173 FindNextUnusedPlane(&plane_idx
, crtc_index
);
175 LOG(ERROR
) << "Failed to find a free plane for crtc " << crtc_id
;
179 gfx::Rect fixed_point_rect
;
180 if (!hw_plane
->is_dummy()) {
181 const gfx::Size
& size
= plane
.buffer
->GetSize();
182 gfx::RectF crop_rect
= plane
.crop_rect
;
183 crop_rect
.Scale(size
.width(), size
.height());
185 // This returns a number in 16.16 fixed point, required by the DRM overlay
187 auto to_fixed_point
=
188 [](double v
) -> uint32_t { return v
* kFixedPointScaleValue
; };
189 fixed_point_rect
= gfx::Rect(to_fixed_point(crop_rect
.x()),
190 to_fixed_point(crop_rect
.y()),
191 to_fixed_point(crop_rect
.width()),
192 to_fixed_point(crop_rect
.height()));
195 plane_list
->plane_list
.push_back(hw_plane
);
196 hw_plane
->set_owning_crtc(crtc_id
);
197 if (SetPlaneData(plane_list
, hw_plane
, plane
, crtc_id
, fixed_point_rect
,
199 hw_plane
->set_in_use(true);
207 void HardwareDisplayPlaneManager::ResetPlanes(
208 HardwareDisplayPlaneList
* plane_list
,
210 std::vector
<HardwareDisplayPlane
*> planes
;
211 planes
.swap(plane_list
->old_plane_list
);
212 for (auto* plane
: planes
) {
213 if (plane
->owning_crtc() == crtc_id
) {
214 plane
->set_owning_crtc(0);
215 plane
->set_in_use(false);
217 plane_list
->old_plane_list
.push_back(plane
);