Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1310)

Unified Diff: ui/ozone/platform/dri/hardware_display_controller.cc

Issue 821023003: [Ozone-DRI] Listen for swap events (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@async-swap
Patch Set: . Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ui/ozone/platform/dri/hardware_display_controller.cc
diff --git a/ui/ozone/platform/dri/hardware_display_controller.cc b/ui/ozone/platform/dri/hardware_display_controller.cc
index 275467db9ea95903a584fd3aca813dfa5f42e0f4..d23365aa27089f0eb9919d4f88a36ef32468b8f8 100644
--- a/ui/ozone/platform/dri/hardware_display_controller.cc
+++ b/ui/ozone/platform/dri/hardware_display_controller.cc
@@ -22,28 +22,14 @@
namespace ui {
-namespace {
-
-// DRM callback on page flip events. This callback is triggered after the
-// page flip has happened and the backbuffer is now the new frontbuffer
-// The old frontbuffer is no longer used by the hardware and can be used for
-// future draw operations.
-//
-// |device| will contain a reference to the |ScanoutSurface| object which
-// the event belongs to.
-//
-// TODO(dnicoara) When we have a FD handler for the DRM calls in the message
-// loop, we can move this function in the handler.
-void HandlePageFlipEvent(int fd,
- unsigned int frame,
- unsigned int seconds,
- unsigned int useconds,
- void* controller) {
- static_cast<CrtcController*>(controller)
- ->OnPageFlipEvent(frame, seconds, useconds);
-}
-
-} // namespace
+HardwareDisplayController::PageFlipRequest::PageFlipRequest(
+ const OverlayPlaneList& planes,
+ const base::Closure& callback)
+ : planes(planes), callback(callback) {
+}
+
+HardwareDisplayController::PageFlipRequest::~PageFlipRequest() {
+}
HardwareDisplayController::HardwareDisplayController(
scoped_ptr<CrtcController> controller)
@@ -55,20 +41,31 @@ HardwareDisplayController::HardwareDisplayController(
HardwareDisplayController::~HardwareDisplayController() {
// Reset the cursor.
UnsetCursor();
+ ClearPendingRequests();
}
bool HardwareDisplayController::Modeset(const OverlayPlane& primary,
drmModeModeInfo mode) {
TRACE_EVENT0("dri", "HDC::Modeset");
+ LOG(ERROR) << "modeset";
alexst (slow to review) 2015/01/09 03:55:46 Debug message.
dnicoara 2015/01/09 15:08:24 Removed.
DCHECK(primary.buffer.get());
bool status = true;
for (size_t i = 0; i < crtc_controllers_.size(); ++i)
status &= crtc_controllers_[i]->Modeset(primary, mode);
- current_planes_ = std::vector<OverlayPlane>(1, primary);
- pending_planes_.clear();
is_disabled_ = false;
mode_ = mode;
+
+ current_planes_ = std::vector<OverlayPlane>(1, primary);
+ pending_planes_.clear();
+ ClearPendingRequests();
+
+ // Because a page flip is pending we need to leave some state for the
+ // callback. We use the modeset state since it is the only valid state.
+ if (HasPendingPageFlips())
+ requests_.push_back(
+ PageFlipRequest(current_planes_, base::Bind(&base::DoNothing)));
+
return status;
}
@@ -92,59 +89,30 @@ void HardwareDisplayController::QueueOverlayPlane(const OverlayPlane& plane) {
pending_planes_.push_back(plane);
}
-bool HardwareDisplayController::SchedulePageFlip() {
- DCHECK(!pending_planes_.empty());
+bool HardwareDisplayController::SchedulePageFlip(
+ const base::Closure& callback) {
+ TRACE_EVENT0("dri", "HDC::SchedulePageFlip");
- if (is_disabled_)
+ // Ignore requests with no planes to schedule.
+ if (pending_planes_.empty()) {
+ callback.Run();
return true;
-
- std::sort(pending_planes_.begin(), pending_planes_.end(),
- [](const OverlayPlane& l, const OverlayPlane& r) {
- return l.z_order < r.z_order;
- });
-
- bool status = true;
- for (size_t i = 0; i < crtc_controllers_.size(); ++i) {
- status &= crtc_controllers_[i]->SchedulePageFlip(
- owned_hardware_planes_.get(crtc_controllers_[i]->drm()),
- pending_planes_);
}
- for (const auto& planes : owned_hardware_planes_) {
- if (!planes.first->plane_manager()->Commit(planes.second)) {
- status = false;
- }
- }
-
- return status;
-}
-
-void HardwareDisplayController::WaitForPageFlipEvent() {
- TRACE_EVENT0("dri", "HDC::WaitForPageFlipEvent");
+ requests_.push_back(PageFlipRequest(pending_planes_, callback));
+ pending_planes_.clear();
- drmEventContext drm_event;
- drm_event.version = DRM_EVENT_CONTEXT_VERSION;
- drm_event.page_flip_handler = HandlePageFlipEvent;
- drm_event.vblank_handler = NULL;
+ // A request is being serviced right now.
+ if (HasPendingPageFlips())
+ return true;
- bool has_pending_page_flips = false;
- // Wait for the page-flips to complete.
- for (size_t i = 0; i < crtc_controllers_.size(); ++i) {
- // In mirror mode the page flip callbacks can happen in different order than
- // scheduled, so we need to make sure that the event for the current CRTC is
- // processed before moving to the next CRTC.
- while (crtc_controllers_[i]->page_flip_pending()) {
- has_pending_page_flips = true;
- crtc_controllers_[i]->drm()->HandleEvent(drm_event);
- }
- }
+ bool status = ActualSchedulePageFlip();
- // In case there are no pending pageflips do not replace the current planes
- // since they are still being used.
- if (has_pending_page_flips)
- current_planes_.swap(pending_planes_);
+ // No page flip event on failure so discard failed request.
+ if (!status)
+ requests_.pop_front();
- pending_planes_.clear();
+ return status;
}
bool HardwareDisplayController::SetCursor(
@@ -183,6 +151,7 @@ void HardwareDisplayController::AddCrtc(scoped_ptr<CrtcController> controller) {
owned_hardware_planes_.add(
controller->drm(),
scoped_ptr<HardwareDisplayPlaneList>(new HardwareDisplayPlaneList()));
+ controller->AddObserver(this);
crtc_controllers_.push_back(controller.release());
}
@@ -193,9 +162,6 @@ scoped_ptr<CrtcController> HardwareDisplayController::RemoveCrtc(
if ((*it)->crtc() == crtc) {
scoped_ptr<CrtcController> controller(*it);
crtc_controllers_.weak_erase(it);
- // Release any planes this crtc might own.
- HardwareDisplayPlaneManager::ResetPlanes(
- owned_hardware_planes_.find(controller->drm())->second, crtc);
// Remove entry from |owned_hardware_planes_| iff no other crtcs share it.
bool found = false;
for (ScopedVector<CrtcController>::iterator it =
@@ -208,6 +174,14 @@ scoped_ptr<CrtcController> HardwareDisplayController::RemoveCrtc(
}
if (!found)
owned_hardware_planes_.erase(controller->drm());
+
+ controller->RemoveObserver(this);
+ // If a display configuration happens mid page flip we want to make sure
+ // the HDC won't wait for an event from a CRTC that is no longer
+ // associated with it.
+ if (controller->page_flip_pending())
+ OnPageFlipEvent();
+
return controller.Pass();
}
}
@@ -244,4 +218,85 @@ uint64_t HardwareDisplayController::GetTimeOfLastFlip() const {
return time;
}
+void HardwareDisplayController::OnPageFlipEvent() {
+ TRACE_EVENT0("dri", "HDC::OnPageFlipEvent");
+ if (HasPendingPageFlips())
+ return;
+
+ // If a CRTC was moved between HDCs while page-flipping, it will report a page
+ // flip without any scheduled requests.
+ if (!requests_.empty())
+ ProcessPageFlipRequest();
+
+ if (requests_.empty())
+ return;
+
+ bool status = ActualSchedulePageFlip();
+ if (!status) {
+ PageFlipRequest request = requests_.front();
+ requests_.pop_front();
+
+ // Normally the caller would handle the error call, but because we're in a
+ // delayed schedule the initial SchedulePageFlip() already returned true,
+ // this we need to run the callback.
+ request.callback.Run();
+ }
+}
+
+bool HardwareDisplayController::HasPendingPageFlips() const {
+ for (size_t i = 0; i < crtc_controllers_.size(); ++i)
+ if (crtc_controllers_[i]->page_flip_pending())
+ return true;
+
+ return false;
+}
+
+bool HardwareDisplayController::ActualSchedulePageFlip() {
+ TRACE_EVENT0("dri", "HDC::ActualSchedulePageFlip");
+ DCHECK(!requests_.empty());
+
+ if (is_disabled_) {
+ ProcessPageFlipRequest();
+ return true;
+ }
+
+ OverlayPlaneList pending_planes = requests_.front().planes;
+ std::sort(pending_planes.begin(), pending_planes.end(),
+ [](const OverlayPlane& l, const OverlayPlane& r) {
+ return l.z_order < r.z_order;
+ });
+
+ bool status = true;
+ for (size_t i = 0; i < crtc_controllers_.size(); ++i) {
+ status &= crtc_controllers_[i]->SchedulePageFlip(
+ owned_hardware_planes_.get(crtc_controllers_[i]->drm()),
+ pending_planes);
+ }
+
+ for (const auto& planes : owned_hardware_planes_) {
+ if (!planes.first->plane_manager()->Commit(planes.second)) {
+ status = false;
+ }
+ }
+
+ return status;
+}
+
+void HardwareDisplayController::ProcessPageFlipRequest() {
+ DCHECK(!requests_.empty());
+ PageFlipRequest request = requests_.front();
+ requests_.pop_front();
+
+ current_planes_.swap(request.planes);
+ request.callback.Run();
+}
+
+void HardwareDisplayController::ClearPendingRequests() {
+ while (!requests_.empty()) {
+ PageFlipRequest request = requests_.front();
+ requests_.pop_front();
+ request.callback.Run();
+ }
+}
+
} // namespace ui

Powered by Google App Engine
This is Rietveld 408576698