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/dri/hardware_display_controller.h"
12 #include "base/basictypes.h"
13 #include "base/debug/trace_event.h"
14 #include "base/logging.h"
15 #include "third_party/skia/include/core/SkCanvas.h"
16 #include "ui/gfx/geometry/point.h"
17 #include "ui/gfx/geometry/size.h"
18 #include "ui/ozone/platform/dri/crtc_controller.h"
19 #include "ui/ozone/platform/dri/dri_buffer.h"
20 #include "ui/ozone/platform/dri/dri_wrapper.h"
21 #include "ui/ozone/public/native_pixmap.h"
27 // DRM callback on page flip events. This callback is triggered after the
28 // page flip has happened and the backbuffer is now the new frontbuffer
29 // The old frontbuffer is no longer used by the hardware and can be used for
30 // future draw operations.
32 // |device| will contain a reference to the |ScanoutSurface| object which
33 // the event belongs to.
35 // TODO(dnicoara) When we have a FD handler for the DRM calls in the message
36 // loop, we can move this function in the handler.
37 void HandlePageFlipEvent(int fd,
40 unsigned int useconds,
42 static_cast<CrtcController*>(controller)
43 ->OnPageFlipEvent(frame, seconds, useconds);
48 HardwareDisplayController::HardwareDisplayController(
49 scoped_ptr<CrtcController> controller)
50 : is_disabled_(true) {
51 crtc_controllers_.push_back(controller.release());
54 HardwareDisplayController::~HardwareDisplayController() {
59 bool HardwareDisplayController::Modeset(const OverlayPlane& primary,
60 drmModeModeInfo mode) {
61 TRACE_EVENT0("dri", "HDC::Modeset");
62 DCHECK(primary.buffer.get());
64 for (size_t i = 0; i < crtc_controllers_.size(); ++i)
65 status &= crtc_controllers_[i]->Modeset(primary, mode);
67 current_planes_ = std::vector<OverlayPlane>(1, primary);
68 pending_planes_.clear();
74 bool HardwareDisplayController::Enable() {
75 TRACE_EVENT0("dri", "HDC::Enable");
76 DCHECK(!current_planes_.empty());
77 OverlayPlane primary = OverlayPlane::GetPrimaryPlane(current_planes_);
78 DCHECK(primary.buffer.get());
80 for (size_t i = 0; i < crtc_controllers_.size(); ++i)
81 status &= crtc_controllers_[i]->Modeset(primary, mode_);
86 void HardwareDisplayController::Disable() {
87 TRACE_EVENT0("dri", "HDC::Disable");
88 for (size_t i = 0; i < crtc_controllers_.size(); ++i)
89 crtc_controllers_[i]->Disable();
94 void HardwareDisplayController::QueueOverlayPlane(const OverlayPlane& plane) {
95 pending_planes_.push_back(plane);
98 bool HardwareDisplayController::SchedulePageFlip() {
99 DCHECK(!pending_planes_.empty());
105 for (size_t i = 0; i < crtc_controllers_.size(); ++i)
106 status &= crtc_controllers_[i]->SchedulePageFlip(pending_planes_);
111 void HardwareDisplayController::WaitForPageFlipEvent() {
112 TRACE_EVENT0("dri", "HDC::WaitForPageFlipEvent");
114 drmEventContext drm_event;
115 drm_event.version = DRM_EVENT_CONTEXT_VERSION;
116 drm_event.page_flip_handler = HandlePageFlipEvent;
117 drm_event.vblank_handler = NULL;
119 bool has_pending_page_flips = false;
120 // Wait for the page-flips to complete.
121 for (size_t i = 0; i < crtc_controllers_.size(); ++i) {
122 // In mirror mode the page flip callbacks can happen in different order than
123 // scheduled, so we need to make sure that the event for the current CRTC is
124 // processed before moving to the next CRTC.
125 while (crtc_controllers_[i]->page_flip_pending()) {
126 has_pending_page_flips = true;
127 crtc_controllers_[i]->drm()->HandleEvent(drm_event);
131 // In case there are no pending pageflips do not replace the current planes
132 // since they are still being used.
133 if (has_pending_page_flips)
134 current_planes_.swap(pending_planes_);
136 pending_planes_.clear();
139 bool HardwareDisplayController::SetCursor(
140 const scoped_refptr<ScanoutBuffer>& buffer) {
146 for (size_t i = 0; i < crtc_controllers_.size(); ++i)
147 status &= crtc_controllers_[i]->SetCursor(buffer);
152 bool HardwareDisplayController::UnsetCursor() {
154 for (size_t i = 0; i < crtc_controllers_.size(); ++i)
155 status &= crtc_controllers_[i]->UnsetCursor();
160 bool HardwareDisplayController::MoveCursor(const gfx::Point& location) {
165 for (size_t i = 0; i < crtc_controllers_.size(); ++i)
166 status &= crtc_controllers_[i]->MoveCursor(location);
171 void HardwareDisplayController::AddCrtc(scoped_ptr<CrtcController> controller) {
172 crtc_controllers_.push_back(controller.release());
175 scoped_ptr<CrtcController> HardwareDisplayController::RemoveCrtc(
177 for (ScopedVector<CrtcController>::iterator it = crtc_controllers_.begin();
178 it != crtc_controllers_.end(); ++it) {
179 if ((*it)->crtc() == crtc) {
180 scoped_ptr<CrtcController> controller(*it);
181 crtc_controllers_.weak_erase(it);
182 return controller.Pass();
186 return scoped_ptr<CrtcController>();
189 bool HardwareDisplayController::HasCrtc(uint32_t crtc) const {
190 for (size_t i = 0; i < crtc_controllers_.size(); ++i)
191 if (crtc_controllers_[i]->crtc() == crtc)
197 bool HardwareDisplayController::IsMirrored() const {
198 return crtc_controllers_.size() > 1;
201 bool HardwareDisplayController::IsDisabled() const {
205 gfx::Size HardwareDisplayController::GetModeSize() const {
206 return gfx::Size(mode_.hdisplay, mode_.vdisplay);
209 uint64_t HardwareDisplayController::GetTimeOfLastFlip() const {
211 for (size_t i = 0; i < crtc_controllers_.size(); ++i)
212 if (time < crtc_controllers_[i]->time_of_last_flip())
213 time = crtc_controllers_[i]->time_of_last_flip();