Atomic: Notify Watcher to observe device fd
[chromium-blink-merge.git] / ui / ozone / platform / drm / gpu / crtc_controller.cc
blob34ec0668fac31c61643a358ba42a7e87ca88e409
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/crtc_controller.h"
7 #include "base/logging.h"
8 #include "base/time/time.h"
9 #include "ui/ozone/platform/drm/gpu/drm_device.h"
10 #include "ui/ozone/platform/drm/gpu/page_flip_request.h"
11 #include "ui/ozone/platform/drm/gpu/scanout_buffer.h"
13 namespace ui {
15 CrtcController::CrtcController(const scoped_refptr<DrmDevice>& drm,
16 uint32_t crtc,
17 uint32_t connector)
18 : drm_(drm),
19 overlay_plane_manager_(nullptr),
20 crtc_(crtc),
21 connector_(connector) {}
23 CrtcController::~CrtcController() {
24 if (!is_disabled_) {
25 SetCursor(nullptr);
26 drm_->DisableCrtc(crtc_);
27 SignalPageFlipRequest();
31 bool CrtcController::Modeset(const OverlayPlane& plane, drmModeModeInfo mode) {
32 if (!drm_->SetCrtc(crtc_, plane.buffer->GetFramebufferId(),
33 std::vector<uint32_t>(1, connector_), &mode)) {
34 PLOG(ERROR) << "Failed to modeset: crtc=" << crtc_
35 << " connector=" << connector_
36 << " framebuffer_id=" << plane.buffer->GetFramebufferId()
37 << " mode=" << mode.hdisplay << "x" << mode.vdisplay << "@"
38 << mode.vrefresh;
39 return false;
42 mode_ = mode;
43 pending_planes_.clear();
44 is_disabled_ = false;
46 // drmModeSetCrtc has an immediate effect, so we can assume that the current
47 // planes have been updated. However if a page flip is still pending, set the
48 // pending planes to the same values so that the callback keeps the correct
49 // state.
50 current_planes_ = std::vector<OverlayPlane>(1, plane);
51 if (page_flip_request_.get())
52 pending_planes_ = current_planes_;
54 ResetCursor();
56 return true;
59 bool CrtcController::Disable() {
60 if (is_disabled_)
61 return true;
63 is_disabled_ = true;
64 return drm_->DisableCrtc(crtc_);
67 bool CrtcController::SchedulePageFlip(
68 HardwareDisplayPlaneList* plane_list,
69 const OverlayPlaneList& overlays,
70 bool test_only,
71 scoped_refptr<PageFlipRequest> page_flip_request) {
72 DCHECK(!page_flip_request_.get() || test_only);
73 DCHECK(!is_disabled_);
74 const OverlayPlane* primary = OverlayPlane::GetPrimaryPlane(overlays);
75 if (!primary) {
76 LOG(ERROR) << "No primary plane to display on crtc " << crtc_;
77 page_flip_request->Signal(gfx::SwapResult::SWAP_ACK);
78 return true;
80 DCHECK(primary->buffer.get());
82 if (primary->buffer->GetSize() != gfx::Size(mode_.hdisplay, mode_.vdisplay)) {
83 VLOG(2) << "Trying to pageflip a buffer with the wrong size. Expected "
84 << mode_.hdisplay << "x" << mode_.vdisplay << " got "
85 << primary->buffer->GetSize().ToString() << " for"
86 << " crtc=" << crtc_ << " connector=" << connector_;
87 page_flip_request->Signal(gfx::SwapResult::SWAP_ACK);
88 return true;
91 if (!drm_->plane_manager()->AssignOverlayPlanes(plane_list, overlays, crtc_,
92 this)) {
93 PLOG(ERROR) << "Failed to assign overlay planes for crtc " << crtc_;
94 page_flip_request->Signal(gfx::SwapResult::SWAP_FAILED);
95 return false;
98 if (test_only) {
99 page_flip_request->Signal(gfx::SwapResult::SWAP_ACK);
100 } else {
101 pending_planes_ = overlays;
102 page_flip_request_ = page_flip_request;
105 return true;
108 void CrtcController::PageFlipFailed() {
109 pending_planes_.clear();
110 SignalPageFlipRequest();
113 void CrtcController::OnPageFlipEvent(unsigned int frame,
114 unsigned int seconds,
115 unsigned int useconds) {
116 time_of_last_flip_ =
117 static_cast<uint64_t>(seconds) * base::Time::kMicrosecondsPerSecond +
118 useconds;
120 current_planes_.clear();
121 current_planes_.swap(pending_planes_);
123 SignalPageFlipRequest();
126 bool CrtcController::SetCursor(const scoped_refptr<ScanoutBuffer>& buffer) {
127 DCHECK(!is_disabled_ || !buffer);
128 cursor_buffer_ = buffer;
130 return ResetCursor();
133 bool CrtcController::MoveCursor(const gfx::Point& location) {
134 DCHECK(!is_disabled_);
135 return drm_->MoveCursor(crtc_, location);
138 bool CrtcController::ResetCursor() {
139 uint32_t handle = 0;
140 gfx::Size size;
142 if (cursor_buffer_) {
143 handle = cursor_buffer_->GetHandle();
144 size = cursor_buffer_->GetSize();
147 bool status = drm_->SetCursor(crtc_, handle, size);
148 if (!status) {
149 PLOG(ERROR) << "drmModeSetCursor: device " << drm_->device_path().value()
150 << " crtc " << crtc_ << " handle " << handle << " size "
151 << size.ToString();
154 return status;
157 void CrtcController::SignalPageFlipRequest() {
158 if (page_flip_request_.get()) {
159 // If another frame is queued up and available immediately, calling Signal()
160 // may result in a call to SchedulePageFlip(), which will override
161 // page_flip_request_ and possibly release the ref. Stash previous request
162 // locally to avoid deleting the object we are making a call on.
163 scoped_refptr<PageFlipRequest> last_request;
164 last_request.swap(page_flip_request_);
165 last_request->Signal(gfx::SwapResult::SWAP_ACK);
169 } // namespace ui