OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/ozone/platform/dri/hardware_display_controller.h" | 5 #include "ui/ozone/platform/dri/hardware_display_controller.h" |
6 | 6 |
7 #include <drm.h> | 7 #include <drm.h> |
8 #include <errno.h> | 8 #include <errno.h> |
9 #include <string.h> | 9 #include <string.h> |
10 #include <xf86drm.h> | 10 #include <xf86drm.h> |
11 | 11 |
12 #include "base/basictypes.h" | 12 #include "base/basictypes.h" |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/trace_event/trace_event.h" | 14 #include "base/trace_event/trace_event.h" |
15 #include "third_party/skia/include/core/SkCanvas.h" | 15 #include "third_party/skia/include/core/SkCanvas.h" |
16 #include "ui/gfx/geometry/point.h" | 16 #include "ui/gfx/geometry/point.h" |
17 #include "ui/gfx/geometry/size.h" | 17 #include "ui/gfx/geometry/size.h" |
18 #include "ui/ozone/platform/dri/crtc_controller.h" | 18 #include "ui/ozone/platform/dri/crtc_controller.h" |
19 #include "ui/ozone/platform/dri/dri_buffer.h" | 19 #include "ui/ozone/platform/dri/dri_buffer.h" |
20 #include "ui/ozone/platform/dri/dri_wrapper.h" | 20 #include "ui/ozone/platform/dri/dri_wrapper.h" |
21 #include "ui/ozone/public/native_pixmap.h" | 21 #include "ui/ozone/public/native_pixmap.h" |
22 | 22 |
23 namespace ui { | 23 namespace ui { |
24 | 24 |
25 HardwareDisplayController::PageFlipRequest::PageFlipRequest( | 25 HardwareDisplayController::PageFlipRequest::PageFlipRequest( |
26 const OverlayPlaneList& planes, | 26 const OverlayPlaneList& planes, |
27 bool is_sync, | |
27 const base::Closure& callback) | 28 const base::Closure& callback) |
28 : planes(planes), callback(callback) { | 29 : planes(planes), is_sync(is_sync), callback(callback) { |
29 } | 30 } |
30 | 31 |
31 HardwareDisplayController::PageFlipRequest::~PageFlipRequest() { | 32 HardwareDisplayController::PageFlipRequest::~PageFlipRequest() { |
32 } | 33 } |
33 | 34 |
34 HardwareDisplayController::HardwareDisplayController( | 35 HardwareDisplayController::HardwareDisplayController( |
35 scoped_ptr<CrtcController> controller) | 36 scoped_ptr<CrtcController> controller) |
36 : is_disabled_(true) { | 37 : is_disabled_(true) { |
37 memset(&mode_, 0, sizeof(mode_)); | 38 memset(&mode_, 0, sizeof(mode_)); |
38 AddCrtc(controller.Pass()); | 39 AddCrtc(controller.Pass()); |
(...skipping 17 matching lines...) Expand all Loading... | |
56 mode_ = mode; | 57 mode_ = mode; |
57 | 58 |
58 current_planes_ = std::vector<OverlayPlane>(1, primary); | 59 current_planes_ = std::vector<OverlayPlane>(1, primary); |
59 pending_planes_.clear(); | 60 pending_planes_.clear(); |
60 ClearPendingRequests(); | 61 ClearPendingRequests(); |
61 | 62 |
62 // Because a page flip is pending we need to leave some state for the | 63 // Because a page flip is pending we need to leave some state for the |
63 // callback. We use the modeset state since it is the only valid state. | 64 // callback. We use the modeset state since it is the only valid state. |
64 if (HasPendingPageFlips()) | 65 if (HasPendingPageFlips()) |
65 requests_.push_back( | 66 requests_.push_back( |
66 PageFlipRequest(current_planes_, base::Bind(&base::DoNothing))); | 67 PageFlipRequest(current_planes_, false, base::Bind(&base::DoNothing))); |
67 | 68 |
68 return status; | 69 return status; |
69 } | 70 } |
70 | 71 |
71 bool HardwareDisplayController::Enable() { | 72 bool HardwareDisplayController::Enable() { |
72 TRACE_EVENT0("dri", "HDC::Enable"); | 73 TRACE_EVENT0("dri", "HDC::Enable"); |
73 DCHECK(!current_planes_.empty()); | 74 DCHECK(!current_planes_.empty()); |
74 const OverlayPlane* primary = OverlayPlane::GetPrimaryPlane(current_planes_); | 75 const OverlayPlane* primary = OverlayPlane::GetPrimaryPlane(current_planes_); |
75 | 76 |
76 return Modeset(*primary, mode_); | 77 return Modeset(*primary, mode_); |
77 } | 78 } |
78 | 79 |
79 void HardwareDisplayController::Disable() { | 80 void HardwareDisplayController::Disable() { |
80 TRACE_EVENT0("dri", "HDC::Disable"); | 81 TRACE_EVENT0("dri", "HDC::Disable"); |
81 for (size_t i = 0; i < crtc_controllers_.size(); ++i) | 82 for (size_t i = 0; i < crtc_controllers_.size(); ++i) |
82 crtc_controllers_[i]->Disable(); | 83 crtc_controllers_[i]->Disable(); |
83 | 84 |
84 is_disabled_ = true; | 85 is_disabled_ = true; |
85 } | 86 } |
86 | 87 |
87 void HardwareDisplayController::QueueOverlayPlane(const OverlayPlane& plane) { | 88 void HardwareDisplayController::QueueOverlayPlane(const OverlayPlane& plane) { |
88 pending_planes_.push_back(plane); | 89 pending_planes_.push_back(plane); |
89 } | 90 } |
90 | 91 |
91 bool HardwareDisplayController::SchedulePageFlip( | 92 bool HardwareDisplayController::SchedulePageFlip( |
93 bool is_sync, | |
92 const base::Closure& callback) { | 94 const base::Closure& callback) { |
93 TRACE_EVENT0("dri", "HDC::SchedulePageFlip"); | 95 TRACE_EVENT0("dri", "HDC::SchedulePageFlip"); |
94 | 96 |
95 // Ignore requests with no planes to schedule. | 97 // Ignore requests with no planes to schedule. |
96 if (pending_planes_.empty()) { | 98 if (pending_planes_.empty()) { |
97 callback.Run(); | 99 callback.Run(); |
98 return true; | 100 return true; |
99 } | 101 } |
100 | 102 |
101 requests_.push_back(PageFlipRequest(pending_planes_, callback)); | 103 requests_.push_back(PageFlipRequest(pending_planes_, is_sync, callback)); |
102 pending_planes_.clear(); | 104 pending_planes_.clear(); |
103 | 105 |
104 // A request is being serviced right now. | 106 // A request is being serviced right now. |
105 if (HasPendingPageFlips()) | 107 if (HasPendingPageFlips()) |
106 return true; | 108 return true; |
107 | 109 |
108 bool status = ActualSchedulePageFlip(); | 110 bool status = ActualSchedulePageFlip(is_sync); |
109 | 111 |
110 // No page flip event on failure so discard failed request. | 112 // No page flip event on failure so discard failed request. |
111 if (!status) | 113 if (!status) |
112 requests_.pop_front(); | 114 requests_.pop_front(); |
113 | 115 |
114 return status; | 116 return status; |
115 } | 117 } |
116 | 118 |
117 bool HardwareDisplayController::SetCursor( | 119 bool HardwareDisplayController::SetCursor( |
118 const scoped_refptr<ScanoutBuffer>& buffer) { | 120 const scoped_refptr<ScanoutBuffer>& buffer) { |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
238 if (HasPendingPageFlips()) | 240 if (HasPendingPageFlips()) |
239 return; | 241 return; |
240 | 242 |
241 if (!requests_.empty()) | 243 if (!requests_.empty()) |
242 ProcessPageFlipRequest(); | 244 ProcessPageFlipRequest(); |
243 | 245 |
244 // ProcessPageFlipRequest() consumes a request. | 246 // ProcessPageFlipRequest() consumes a request. |
245 if (requests_.empty()) | 247 if (requests_.empty()) |
246 return; | 248 return; |
247 | 249 |
250 PageFlipRequest request = requests_.front(); | |
dnicoara
2015/02/27 13:58:44
Move this back in the if-statement.
llandwerlin-old
2015/02/27 14:09:04
Done.
| |
248 // At this point we still have requests pending, so schedule the next request. | 251 // At this point we still have requests pending, so schedule the next request. |
249 bool status = ActualSchedulePageFlip(); | 252 bool status = ActualSchedulePageFlip(request.is_sync); |
250 if (!status) { | 253 if (!status) { |
251 PageFlipRequest request = requests_.front(); | |
252 requests_.pop_front(); | 254 requests_.pop_front(); |
253 | 255 |
254 // Normally the caller would handle the error call, but because we're in a | 256 // Normally the caller would handle the error call, but because we're in a |
255 // delayed schedule the initial SchedulePageFlip() already returned true, | 257 // delayed schedule the initial SchedulePageFlip() already returned true, |
256 // thus we need to run the callback. | 258 // thus we need to run the callback. |
257 request.callback.Run(); | 259 request.callback.Run(); |
258 } | 260 } |
259 } | 261 } |
260 | 262 |
261 scoped_refptr<DriWrapper> HardwareDisplayController::GetAllocationDriWrapper() | 263 scoped_refptr<DriWrapper> HardwareDisplayController::GetAllocationDriWrapper() |
262 const { | 264 const { |
263 DCHECK(!crtc_controllers_.empty()); | 265 DCHECK(!crtc_controllers_.empty()); |
264 // TODO(dnicoara) When we support mirroring across DRM devices, figure out | 266 // TODO(dnicoara) When we support mirroring across DRM devices, figure out |
265 // which device should be used for allocations. | 267 // which device should be used for allocations. |
266 return crtc_controllers_[0]->drm(); | 268 return crtc_controllers_[0]->drm(); |
267 } | 269 } |
268 | 270 |
269 bool HardwareDisplayController::HasPendingPageFlips() const { | 271 bool HardwareDisplayController::HasPendingPageFlips() const { |
270 for (size_t i = 0; i < crtc_controllers_.size(); ++i) | 272 for (size_t i = 0; i < crtc_controllers_.size(); ++i) |
271 if (crtc_controllers_[i]->page_flip_pending()) | 273 if (crtc_controllers_[i]->page_flip_pending()) |
272 return true; | 274 return true; |
273 | 275 |
274 return false; | 276 return false; |
275 } | 277 } |
276 | 278 |
277 bool HardwareDisplayController::ActualSchedulePageFlip() { | 279 bool HardwareDisplayController::ActualSchedulePageFlip(bool is_sync) { |
278 TRACE_EVENT0("dri", "HDC::ActualSchedulePageFlip"); | 280 TRACE_EVENT0("dri", "HDC::ActualSchedulePageFlip"); |
279 DCHECK(!requests_.empty()); | 281 DCHECK(!requests_.empty()); |
280 | 282 |
281 if (is_disabled_) { | 283 if (is_disabled_) { |
282 ProcessPageFlipRequest(); | 284 ProcessPageFlipRequest(); |
283 return true; | 285 return true; |
284 } | 286 } |
285 | 287 |
286 OverlayPlaneList pending_planes = requests_.front().planes; | 288 OverlayPlaneList pending_planes = requests_.front().planes; |
dnicoara
2015/02/27 13:58:44
You'll want to get the is_sync flag here, from |re
llandwerlin-old
2015/02/27 14:09:04
Ah right, got it.
| |
287 std::sort(pending_planes.begin(), pending_planes.end(), | 289 std::sort(pending_planes.begin(), pending_planes.end(), |
288 [](const OverlayPlane& l, const OverlayPlane& r) { | 290 [](const OverlayPlane& l, const OverlayPlane& r) { |
289 return l.z_order < r.z_order; | 291 return l.z_order < r.z_order; |
290 }); | 292 }); |
291 | 293 |
292 bool status = true; | 294 bool status = true; |
293 for (size_t i = 0; i < crtc_controllers_.size(); ++i) { | 295 for (size_t i = 0; i < crtc_controllers_.size(); ++i) { |
294 status &= crtc_controllers_[i]->SchedulePageFlip( | 296 status &= crtc_controllers_[i]->SchedulePageFlip( |
295 owned_hardware_planes_.get(crtc_controllers_[i]->drm().get()), | 297 owned_hardware_planes_.get(crtc_controllers_[i]->drm().get()), |
296 pending_planes); | 298 pending_planes); |
297 } | 299 } |
298 | 300 |
299 for (const auto& planes : owned_hardware_planes_) { | 301 for (const auto& planes : owned_hardware_planes_) { |
300 if (!planes.first->plane_manager()->Commit(planes.second)) { | 302 if (!planes.first->plane_manager()->Commit(planes.second, is_sync)) { |
301 status = false; | 303 status = false; |
302 } | 304 } |
303 } | 305 } |
304 | 306 |
305 return status; | 307 return status; |
306 } | 308 } |
307 | 309 |
308 void HardwareDisplayController::ProcessPageFlipRequest() { | 310 void HardwareDisplayController::ProcessPageFlipRequest() { |
309 DCHECK(!requests_.empty()); | 311 DCHECK(!requests_.empty()); |
310 PageFlipRequest request = requests_.front(); | 312 PageFlipRequest request = requests_.front(); |
311 requests_.pop_front(); | 313 requests_.pop_front(); |
312 | 314 |
313 current_planes_.swap(request.planes); | 315 current_planes_.swap(request.planes); |
314 request.callback.Run(); | 316 request.callback.Run(); |
315 } | 317 } |
316 | 318 |
317 void HardwareDisplayController::ClearPendingRequests() { | 319 void HardwareDisplayController::ClearPendingRequests() { |
318 while (!requests_.empty()) { | 320 while (!requests_.empty()) { |
319 PageFlipRequest request = requests_.front(); | 321 PageFlipRequest request = requests_.front(); |
320 requests_.pop_front(); | 322 requests_.pop_front(); |
321 request.callback.Run(); | 323 request.callback.Run(); |
322 } | 324 } |
323 } | 325 } |
324 | 326 |
325 } // namespace ui | 327 } // namespace ui |
OLD | NEW |