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

Side by Side Diff: ui/ozone/platform/drm/gpu/hardware_display_controller.cc

Issue 1091253003: [ozone] Keep the queue of surfaceless buffers inside gl_surface_ozone (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: unittests Created 5 years, 8 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 unified diff | Download patch
OLDNEW
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/drm/gpu/hardware_display_controller.h" 5 #include "ui/ozone/platform/drm/gpu/hardware_display_controller.h"
6 6
7 #include <drm.h> 7 #include <drm.h>
8 #include <string.h> 8 #include <string.h>
9 #include <xf86drm.h> 9 #include <xf86drm.h>
10 10
11 #include "base/basictypes.h" 11 #include "base/basictypes.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/trace_event/trace_event.h" 13 #include "base/trace_event/trace_event.h"
14 #include "third_party/skia/include/core/SkCanvas.h" 14 #include "third_party/skia/include/core/SkCanvas.h"
15 #include "ui/gfx/geometry/point.h" 15 #include "ui/gfx/geometry/point.h"
16 #include "ui/gfx/geometry/size.h" 16 #include "ui/gfx/geometry/size.h"
17 #include "ui/ozone/platform/drm/gpu/crtc_controller.h" 17 #include "ui/ozone/platform/drm/gpu/crtc_controller.h"
18 #include "ui/ozone/platform/drm/gpu/drm_buffer.h" 18 #include "ui/ozone/platform/drm/gpu/drm_buffer.h"
19 #include "ui/ozone/platform/drm/gpu/drm_device.h" 19 #include "ui/ozone/platform/drm/gpu/drm_device.h"
20 #include "ui/ozone/platform/drm/gpu/page_flip_request.h"
20 #include "ui/ozone/public/native_pixmap.h" 21 #include "ui/ozone/public/native_pixmap.h"
21 22
22 namespace ui { 23 namespace ui {
23 24
24 HardwareDisplayController::PageFlipRequest::PageFlipRequest(
25 const OverlayPlaneList& planes,
26 bool is_sync,
27 const base::Closure& callback)
28 : planes(planes), is_sync(is_sync), callback(callback) {
29 }
30
31 HardwareDisplayController::PageFlipRequest::~PageFlipRequest() {
32 }
33
34 HardwareDisplayController::HardwareDisplayController( 25 HardwareDisplayController::HardwareDisplayController(
35 scoped_ptr<CrtcController> controller) 26 scoped_ptr<CrtcController> controller)
36 : is_disabled_(true) { 27 : is_disabled_(true) {
37 memset(&mode_, 0, sizeof(mode_)); 28 memset(&mode_, 0, sizeof(mode_));
38 AddCrtc(controller.Pass()); 29 AddCrtc(controller.Pass());
39 } 30 }
40 31
41 HardwareDisplayController::~HardwareDisplayController() { 32 HardwareDisplayController::~HardwareDisplayController() {
42 // Reset the cursor. 33 // Reset the cursor.
43 UnsetCursor(); 34 UnsetCursor();
44 ClearPendingRequests();
45 } 35 }
46 36
47 bool HardwareDisplayController::Modeset(const OverlayPlane& primary, 37 bool HardwareDisplayController::Modeset(const OverlayPlane& primary,
48 drmModeModeInfo mode) { 38 drmModeModeInfo mode) {
49 TRACE_EVENT0("drm", "HDC::Modeset"); 39 TRACE_EVENT0("drm", "HDC::Modeset");
50 DCHECK(primary.buffer.get()); 40 DCHECK(primary.buffer.get());
51 bool status = true; 41 bool status = true;
52 for (size_t i = 0; i < crtc_controllers_.size(); ++i) 42 for (size_t i = 0; i < crtc_controllers_.size(); ++i)
53 status &= crtc_controllers_[i]->Modeset(primary, mode); 43 status &= crtc_controllers_[i]->Modeset(primary, mode);
54 44
55 is_disabled_ = false; 45 is_disabled_ = false;
56 mode_ = mode; 46 mode_ = mode;
57 47
58 current_planes_ = std::vector<OverlayPlane>(1, primary);
59 ClearPendingRequests();
60
61 // Because a page flip is pending we need to leave some state for the
62 // callback. We use the modeset state since it is the only valid state.
63 if (HasPendingPageFlips())
64 requests_.push_back(
65 PageFlipRequest(current_planes_, false, base::Bind(&base::DoNothing)));
66
67 return status; 48 return status;
68 } 49 }
69 50
70 void HardwareDisplayController::Disable() { 51 void HardwareDisplayController::Disable() {
71 TRACE_EVENT0("drm", "HDC::Disable"); 52 TRACE_EVENT0("drm", "HDC::Disable");
72 for (size_t i = 0; i < crtc_controllers_.size(); ++i) 53 for (size_t i = 0; i < crtc_controllers_.size(); ++i)
73 crtc_controllers_[i]->Disable(); 54 crtc_controllers_[i]->Disable();
74 55
75 // Don't hold onto any requests because we don't track fron buffer while
76 // disabled.
77 while (requests_.size())
78 ProcessPageFlipRequest();
79
80 current_planes_.clear();
81 56
82 is_disabled_ = true; 57 is_disabled_ = true;
83 } 58 }
84 59
85 bool HardwareDisplayController::SchedulePageFlip( 60 bool HardwareDisplayController::SchedulePageFlip(
86 const OverlayPlaneList& plane_list, 61 const OverlayPlaneList& plane_list,
87 bool is_sync, 62 bool is_sync,
88 const base::Closure& callback) { 63 const base::Closure& callback) {
89 TRACE_EVENT0("drm", "HDC::SchedulePageFlip"); 64 TRACE_EVENT0("drm", "HDC::SchedulePageFlip");
90 65
66 DCHECK(!is_disabled_);
67
91 // Ignore requests with no planes to schedule. 68 // Ignore requests with no planes to schedule.
92 if (plane_list.empty()) { 69 if (plane_list.empty()) {
93 callback.Run(); 70 callback.Run();
94 return true; 71 return true;
95 } 72 }
96 73
97 requests_.push_back(PageFlipRequest(plane_list, is_sync, callback)); 74 scoped_refptr<PageFlipRequest> page_flip_request =
75 new PageFlipRequest(crtc_controllers_.size(), callback);
98 76
99 // A request is being serviced right now. 77 OverlayPlaneList pending_planes = plane_list;
100 if (HasPendingPageFlips()) 78 std::sort(pending_planes.begin(), pending_planes.end(),
101 return true; 79 [](const OverlayPlane& l, const OverlayPlane& r) {
80 return l.z_order < r.z_order;
81 });
102 82
103 bool status = ActualSchedulePageFlip(); 83 bool status = true;
84 for (size_t i = 0; i < crtc_controllers_.size(); ++i) {
85 status &= crtc_controllers_[i]->SchedulePageFlip(
86 owned_hardware_planes_.get(crtc_controllers_[i]->drm().get()),
87 pending_planes, page_flip_request);
88 }
104 89
105 // No page flip event on failure so discard failed request. 90 for (const auto& planes : owned_hardware_planes_) {
106 if (!status) 91 if (!planes.first->plane_manager()->Commit(planes.second, is_sync)) {
107 requests_.pop_front(); 92 status = false;
93 }
94 }
108 95
109 return status; 96 return status;
110 } 97 }
111 98
112 bool HardwareDisplayController::SetCursor( 99 bool HardwareDisplayController::SetCursor(
113 const scoped_refptr<ScanoutBuffer>& buffer) { 100 const scoped_refptr<ScanoutBuffer>& buffer) {
114 bool status = true; 101 bool status = true;
115 102
116 if (is_disabled_) 103 if (is_disabled_)
117 return true; 104 return true;
(...skipping 20 matching lines...) Expand all
138 for (size_t i = 0; i < crtc_controllers_.size(); ++i) 125 for (size_t i = 0; i < crtc_controllers_.size(); ++i)
139 status &= crtc_controllers_[i]->MoveCursor(location); 126 status &= crtc_controllers_[i]->MoveCursor(location);
140 127
141 return status; 128 return status;
142 } 129 }
143 130
144 void HardwareDisplayController::AddCrtc(scoped_ptr<CrtcController> controller) { 131 void HardwareDisplayController::AddCrtc(scoped_ptr<CrtcController> controller) {
145 owned_hardware_planes_.add( 132 owned_hardware_planes_.add(
146 controller->drm().get(), 133 controller->drm().get(),
147 scoped_ptr<HardwareDisplayPlaneList>(new HardwareDisplayPlaneList())); 134 scoped_ptr<HardwareDisplayPlaneList>(new HardwareDisplayPlaneList()));
148 controller->AddObserver(this);
149 crtc_controllers_.push_back(controller.release()); 135 crtc_controllers_.push_back(controller.release());
150 } 136 }
151 137
152 scoped_ptr<CrtcController> HardwareDisplayController::RemoveCrtc( 138 scoped_ptr<CrtcController> HardwareDisplayController::RemoveCrtc(
153 const scoped_refptr<DrmDevice>& drm, 139 const scoped_refptr<DrmDevice>& drm,
154 uint32_t crtc) { 140 uint32_t crtc) {
155 for (ScopedVector<CrtcController>::iterator it = crtc_controllers_.begin(); 141 for (ScopedVector<CrtcController>::iterator it = crtc_controllers_.begin();
156 it != crtc_controllers_.end(); ++it) { 142 it != crtc_controllers_.end(); ++it) {
157 if ((*it)->drm() == drm && (*it)->crtc() == crtc) { 143 if ((*it)->drm() == drm && (*it)->crtc() == crtc) {
158 scoped_ptr<CrtcController> controller(*it); 144 scoped_ptr<CrtcController> controller(*it);
159 crtc_controllers_.weak_erase(it); 145 crtc_controllers_.weak_erase(it);
160 // Remove entry from |owned_hardware_planes_| iff no other crtcs share it. 146 // Remove entry from |owned_hardware_planes_| iff no other crtcs share it.
161 bool found = false; 147 bool found = false;
162 for (ScopedVector<CrtcController>::iterator it = 148 for (ScopedVector<CrtcController>::iterator it =
163 crtc_controllers_.begin(); 149 crtc_controllers_.begin();
164 it != crtc_controllers_.end(); ++it) { 150 it != crtc_controllers_.end(); ++it) {
165 if ((*it)->drm() == controller->drm()) { 151 if ((*it)->drm() == controller->drm()) {
166 found = true; 152 found = true;
167 break; 153 break;
168 } 154 }
169 } 155 }
170 if (!found) 156 if (!found)
171 owned_hardware_planes_.erase(controller->drm().get()); 157 owned_hardware_planes_.erase(controller->drm().get());
172 158
173 controller->RemoveObserver(this);
174 // If a display configuration happens mid page flip we want to make sure
175 // the HDC won't wait for an event from a CRTC that is no longer
176 // associated with it.
177 if (controller->page_flip_pending())
178 OnPageFlipEvent();
179
180 return controller.Pass(); 159 return controller.Pass();
181 } 160 }
182 } 161 }
183 162
184 return nullptr; 163 return nullptr;
185 } 164 }
186 165
187 bool HardwareDisplayController::HasCrtc(const scoped_refptr<DrmDevice>& drm, 166 bool HardwareDisplayController::HasCrtc(const scoped_refptr<DrmDevice>& drm,
188 uint32_t crtc) const { 167 uint32_t crtc) const {
189 for (size_t i = 0; i < crtc_controllers_.size(); ++i) 168 for (size_t i = 0; i < crtc_controllers_.size(); ++i)
(...skipping 18 matching lines...) Expand all
208 187
209 uint64_t HardwareDisplayController::GetTimeOfLastFlip() const { 188 uint64_t HardwareDisplayController::GetTimeOfLastFlip() const {
210 uint64_t time = 0; 189 uint64_t time = 0;
211 for (size_t i = 0; i < crtc_controllers_.size(); ++i) 190 for (size_t i = 0; i < crtc_controllers_.size(); ++i)
212 if (time < crtc_controllers_[i]->time_of_last_flip()) 191 if (time < crtc_controllers_[i]->time_of_last_flip())
213 time = crtc_controllers_[i]->time_of_last_flip(); 192 time = crtc_controllers_[i]->time_of_last_flip();
214 193
215 return time; 194 return time;
216 } 195 }
217 196
218 void HardwareDisplayController::OnPageFlipEvent() {
219 TRACE_EVENT0("drm", "HDC::OnPageFlipEvent");
220 // OnPageFlipEvent() needs to handle 2 cases:
221 // 1) Normal page flips in which case:
222 // a) HasPendingPageFlips() may return false if we're in mirror mode and
223 // one of the CRTCs hasn't finished page flipping. In this case we want
224 // to wait for all the CRTCs.
225 // b) HasPendingPageFlips() returns true in which case all CRTCs are ready
226 // for the next request. In this case we expect that |requests_| isn't
227 // empty.
228 // 2) A CRTC was added while it was page flipping. In this case a modeset
229 // must be performed. Modesetting clears all pending requests, however the
230 // CRTCs will honor the scheduled page flip. Thus we need to handle page
231 // flip events with no requests.
232
233 if (HasPendingPageFlips())
234 return;
235
236 if (!requests_.empty())
237 ProcessPageFlipRequest();
238
239 // ProcessPageFlipRequest() consumes a request.
240 if (requests_.empty())
241 return;
242
243 // At this point we still have requests pending, so schedule the next request.
244 bool status = ActualSchedulePageFlip();
245 if (!status) {
246 PageFlipRequest request = requests_.front();
247 requests_.pop_front();
248
249 // Normally the caller would handle the error call, but because we're in a
250 // delayed schedule the initial SchedulePageFlip() already returned true,
251 // thus we need to run the callback.
252 request.callback.Run();
253 }
254 }
255
256 scoped_refptr<DrmDevice> HardwareDisplayController::GetAllocationDrmDevice() 197 scoped_refptr<DrmDevice> HardwareDisplayController::GetAllocationDrmDevice()
257 const { 198 const {
258 DCHECK(!crtc_controllers_.empty()); 199 DCHECK(!crtc_controllers_.empty());
259 // TODO(dnicoara) When we support mirroring across DRM devices, figure out 200 // TODO(dnicoara) When we support mirroring across DRM devices, figure out
260 // which device should be used for allocations. 201 // which device should be used for allocations.
261 return crtc_controllers_[0]->drm(); 202 return crtc_controllers_[0]->drm();
262 } 203 }
263 204
264 bool HardwareDisplayController::HasPendingPageFlips() const {
265 for (size_t i = 0; i < crtc_controllers_.size(); ++i)
266 if (crtc_controllers_[i]->page_flip_pending())
267 return true;
268
269 return false;
270 }
271
272 bool HardwareDisplayController::ActualSchedulePageFlip() {
273 TRACE_EVENT0("drm", "HDC::ActualSchedulePageFlip");
274 DCHECK(!requests_.empty());
275
276 if (is_disabled_) {
277 ProcessPageFlipRequest();
278 return true;
279 }
280
281 OverlayPlaneList pending_planes = requests_.front().planes;
282 std::sort(pending_planes.begin(), pending_planes.end(),
283 [](const OverlayPlane& l, const OverlayPlane& r) {
284 return l.z_order < r.z_order;
285 });
286
287 bool status = true;
288 for (size_t i = 0; i < crtc_controllers_.size(); ++i) {
289 status &= crtc_controllers_[i]->SchedulePageFlip(
290 owned_hardware_planes_.get(crtc_controllers_[i]->drm().get()),
291 pending_planes);
292 }
293
294 bool is_sync = requests_.front().is_sync;
295 for (const auto& planes : owned_hardware_planes_) {
296 if (!planes.first->plane_manager()->Commit(planes.second, is_sync)) {
297 status = false;
298 }
299 }
300
301 return status;
302 }
303
304 void HardwareDisplayController::ProcessPageFlipRequest() {
305 DCHECK(!requests_.empty());
306 PageFlipRequest request = requests_.front();
307 requests_.pop_front();
308
309 current_planes_.swap(request.planes);
310 request.callback.Run();
311 }
312
313 void HardwareDisplayController::ClearPendingRequests() {
314 while (!requests_.empty()) {
315 PageFlipRequest request = requests_.front();
316 requests_.pop_front();
317 request.callback.Run();
318 }
319 }
320
321 } // namespace ui 205 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698