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_controller.h"
11 #include "base/basictypes.h"
12 #include "base/logging.h"
13 #include "base/trace_event/trace_event.h"
14 #include "third_party/skia/include/core/SkCanvas.h"
15 #include "ui/gfx/geometry/point.h"
16 #include "ui/gfx/geometry/size.h"
17 #include "ui/gfx/swap_result.h"
18 #include "ui/ozone/platform/drm/gpu/crtc_controller.h"
19 #include "ui/ozone/platform/drm/gpu/drm_buffer.h"
20 #include "ui/ozone/platform/drm/gpu/drm_device.h"
21 #include "ui/ozone/platform/drm/gpu/page_flip_request.h"
22 #include "ui/ozone/public/native_pixmap.h"
26 HardwareDisplayController::HardwareDisplayController(
27 scoped_ptr
<CrtcController
> controller
,
28 const gfx::Point
& origin
)
30 mode_(controller
->mode()),
31 is_disabled_(controller
->is_disabled()) {
32 AddCrtc(controller
.Pass());
35 HardwareDisplayController::~HardwareDisplayController() {
40 bool HardwareDisplayController::Modeset(const OverlayPlane
& primary
,
41 drmModeModeInfo mode
) {
42 TRACE_EVENT0("drm", "HDC::Modeset");
43 DCHECK(primary
.buffer
.get());
45 for (size_t i
= 0; i
< crtc_controllers_
.size(); ++i
)
46 status
&= crtc_controllers_
[i
]->Modeset(primary
, mode
);
54 void HardwareDisplayController::Disable() {
55 TRACE_EVENT0("drm", "HDC::Disable");
56 for (size_t i
= 0; i
< crtc_controllers_
.size(); ++i
)
57 crtc_controllers_
[i
]->Disable();
63 bool HardwareDisplayController::SchedulePageFlip(
64 const OverlayPlaneList
& plane_list
,
67 const PageFlipCallback
& callback
) {
68 TRACE_EVENT0("drm", "HDC::SchedulePageFlip");
70 DCHECK(!is_disabled_
);
72 // Ignore requests with no planes to schedule.
73 if (plane_list
.empty()) {
74 callback
.Run(gfx::SwapResult::SWAP_ACK
);
78 scoped_refptr
<PageFlipRequest
> page_flip_request
=
79 new PageFlipRequest(crtc_controllers_
.size(), callback
);
81 OverlayPlaneList pending_planes
= plane_list
;
82 std::sort(pending_planes
.begin(), pending_planes
.end(),
83 [](const OverlayPlane
& l
, const OverlayPlane
& r
) {
84 return l
.z_order
< r
.z_order
;
86 if (pending_planes
.front().z_order
!= 0)
89 for (const auto& planes
: owned_hardware_planes_
)
90 planes
.first
->plane_manager()->BeginFrame(planes
.second
);
93 for (size_t i
= 0; i
< crtc_controllers_
.size(); ++i
) {
94 status
&= crtc_controllers_
[i
]->SchedulePageFlip(
95 owned_hardware_planes_
.get(crtc_controllers_
[i
]->drm().get()),
96 pending_planes
, test_only
, page_flip_request
);
99 for (const auto& planes
: owned_hardware_planes_
) {
100 if (!planes
.first
->plane_manager()->Commit(planes
.second
, is_sync
,
109 bool HardwareDisplayController::SetCursor(
110 const scoped_refptr
<ScanoutBuffer
>& buffer
) {
116 for (size_t i
= 0; i
< crtc_controllers_
.size(); ++i
)
117 status
&= crtc_controllers_
[i
]->SetCursor(buffer
);
122 bool HardwareDisplayController::UnsetCursor() {
124 for (size_t i
= 0; i
< crtc_controllers_
.size(); ++i
)
125 status
&= crtc_controllers_
[i
]->SetCursor(nullptr);
130 bool HardwareDisplayController::MoveCursor(const gfx::Point
& location
) {
135 for (size_t i
= 0; i
< crtc_controllers_
.size(); ++i
)
136 status
&= crtc_controllers_
[i
]->MoveCursor(location
);
141 void HardwareDisplayController::AddCrtc(scoped_ptr
<CrtcController
> controller
) {
142 owned_hardware_planes_
.add(
143 controller
->drm().get(),
144 scoped_ptr
<HardwareDisplayPlaneList
>(new HardwareDisplayPlaneList()));
145 crtc_controllers_
.push_back(controller
.Pass());
148 scoped_ptr
<CrtcController
> HardwareDisplayController::RemoveCrtc(
149 const scoped_refptr
<DrmDevice
>& drm
,
151 for (ScopedVector
<CrtcController
>::iterator it
= crtc_controllers_
.begin();
152 it
!= crtc_controllers_
.end(); ++it
) {
153 if ((*it
)->drm() == drm
&& (*it
)->crtc() == crtc
) {
154 scoped_ptr
<CrtcController
> controller(*it
);
155 crtc_controllers_
.weak_erase(it
);
156 // Remove entry from |owned_hardware_planes_| iff no other crtcs share it.
158 for (ScopedVector
<CrtcController
>::iterator it
=
159 crtc_controllers_
.begin();
160 it
!= crtc_controllers_
.end(); ++it
) {
161 if ((*it
)->drm() == controller
->drm()) {
167 owned_hardware_planes_
.erase(controller
->drm().get());
169 return controller
.Pass();
176 bool HardwareDisplayController::HasCrtc(const scoped_refptr
<DrmDevice
>& drm
,
177 uint32_t crtc
) const {
178 for (size_t i
= 0; i
< crtc_controllers_
.size(); ++i
)
179 if (crtc_controllers_
[i
]->drm() == drm
&&
180 crtc_controllers_
[i
]->crtc() == crtc
)
186 bool HardwareDisplayController::IsMirrored() const {
187 return crtc_controllers_
.size() > 1;
190 bool HardwareDisplayController::IsDisabled() const {
194 gfx::Size
HardwareDisplayController::GetModeSize() const {
195 return gfx::Size(mode_
.hdisplay
, mode_
.vdisplay
);
198 uint64_t HardwareDisplayController::GetTimeOfLastFlip() const {
200 for (size_t i
= 0; i
< crtc_controllers_
.size(); ++i
)
201 if (time
< crtc_controllers_
[i
]->time_of_last_flip())
202 time
= crtc_controllers_
[i
]->time_of_last_flip();
207 scoped_refptr
<DrmDevice
> HardwareDisplayController::GetAllocationDrmDevice()
209 DCHECK(!crtc_controllers_
.empty());
210 // TODO(dnicoara) When we support mirroring across DRM devices, figure out
211 // which device should be used for allocations.
212 return crtc_controllers_
[0]->drm();