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

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: 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), ignore_page_flip_event_(false) {
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 // A request is being serviced right now.
dnicoara 2015/04/23 15:34:56 Remove comment since it's inconsistent.
67 DCHECK(!HasPendingPageFlips());
68 DCHECK(!is_disabled_);
69
91 // Ignore requests with no planes to schedule. 70 // Ignore requests with no planes to schedule.
92 if (plane_list.empty()) { 71 if (plane_list.empty()) {
93 callback.Run(); 72 callback.Run();
94 return true; 73 return true;
95 } 74 }
96 75
97 requests_.push_back(PageFlipRequest(plane_list, is_sync, callback)); 76 scoped_refptr<PageFlipRequest> page_flip_request =
77 new PageFlipRequest(crtc_controllers_.size(), callback);
98 78
99 // A request is being serviced right now. 79 OverlayPlaneList pending_planes = plane_list;
100 if (HasPendingPageFlips()) 80 std::sort(pending_planes.begin(), pending_planes.end(),
101 return true; 81 [](const OverlayPlane& l, const OverlayPlane& r) {
82 return l.z_order < r.z_order;
83 });
102 84
103 bool status = ActualSchedulePageFlip(); 85 bool status = true;
86 for (size_t i = 0; i < crtc_controllers_.size(); ++i) {
87 status &= crtc_controllers_[i]->SchedulePageFlip(
88 owned_hardware_planes_.get(crtc_controllers_[i]->drm().get()),
89 pending_planes, page_flip_request);
90 }
104 91
105 // No page flip event on failure so discard failed request. 92 for (const auto& planes : owned_hardware_planes_) {
106 if (!status) 93 if (!planes.first->plane_manager()->Commit(planes.second, is_sync)) {
107 requests_.pop_front(); 94 status = false;
95 }
96 }
108 97
109 return status; 98 return status;
110 } 99 }
111 100
112 bool HardwareDisplayController::SetCursor( 101 bool HardwareDisplayController::SetCursor(
113 const scoped_refptr<ScanoutBuffer>& buffer) { 102 const scoped_refptr<ScanoutBuffer>& buffer) {
114 bool status = true; 103 bool status = true;
115 104
116 if (is_disabled_) 105 if (is_disabled_)
117 return true; 106 return true;
(...skipping 20 matching lines...) Expand all
138 for (size_t i = 0; i < crtc_controllers_.size(); ++i) 127 for (size_t i = 0; i < crtc_controllers_.size(); ++i)
139 status &= crtc_controllers_[i]->MoveCursor(location); 128 status &= crtc_controllers_[i]->MoveCursor(location);
140 129
141 return status; 130 return status;
142 } 131 }
143 132
144 void HardwareDisplayController::AddCrtc(scoped_ptr<CrtcController> controller) { 133 void HardwareDisplayController::AddCrtc(scoped_ptr<CrtcController> controller) {
145 owned_hardware_planes_.add( 134 owned_hardware_planes_.add(
146 controller->drm().get(), 135 controller->drm().get(),
147 scoped_ptr<HardwareDisplayPlaneList>(new HardwareDisplayPlaneList())); 136 scoped_ptr<HardwareDisplayPlaneList>(new HardwareDisplayPlaneList()));
148 controller->AddObserver(this);
149 crtc_controllers_.push_back(controller.release()); 137 crtc_controllers_.push_back(controller.release());
150 } 138 }
151 139
152 scoped_ptr<CrtcController> HardwareDisplayController::RemoveCrtc( 140 scoped_ptr<CrtcController> HardwareDisplayController::RemoveCrtc(
153 const scoped_refptr<DrmDevice>& drm, 141 const scoped_refptr<DrmDevice>& drm,
154 uint32_t crtc) { 142 uint32_t crtc) {
155 for (ScopedVector<CrtcController>::iterator it = crtc_controllers_.begin(); 143 for (ScopedVector<CrtcController>::iterator it = crtc_controllers_.begin();
156 it != crtc_controllers_.end(); ++it) { 144 it != crtc_controllers_.end(); ++it) {
157 if ((*it)->drm() == drm && (*it)->crtc() == crtc) { 145 if ((*it)->drm() == drm && (*it)->crtc() == crtc) {
158 scoped_ptr<CrtcController> controller(*it); 146 scoped_ptr<CrtcController> controller(*it);
159 crtc_controllers_.weak_erase(it); 147 crtc_controllers_.weak_erase(it);
160 // Remove entry from |owned_hardware_planes_| iff no other crtcs share it. 148 // Remove entry from |owned_hardware_planes_| iff no other crtcs share it.
161 bool found = false; 149 bool found = false;
162 for (ScopedVector<CrtcController>::iterator it = 150 for (ScopedVector<CrtcController>::iterator it =
163 crtc_controllers_.begin(); 151 crtc_controllers_.begin();
164 it != crtc_controllers_.end(); ++it) { 152 it != crtc_controllers_.end(); ++it) {
165 if ((*it)->drm() == controller->drm()) { 153 if ((*it)->drm() == controller->drm()) {
166 found = true; 154 found = true;
167 break; 155 break;
168 } 156 }
169 } 157 }
170 if (!found) 158 if (!found)
171 owned_hardware_planes_.erase(controller->drm().get()); 159 owned_hardware_planes_.erase(controller->drm().get());
172 160
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(); 161 return controller.Pass();
181 } 162 }
182 } 163 }
183 164
184 return nullptr; 165 return nullptr;
185 } 166 }
186 167
187 bool HardwareDisplayController::HasCrtc(const scoped_refptr<DrmDevice>& drm, 168 bool HardwareDisplayController::HasCrtc(const scoped_refptr<DrmDevice>& drm,
188 uint32_t crtc) const { 169 uint32_t crtc) const {
189 for (size_t i = 0; i < crtc_controllers_.size(); ++i) 170 for (size_t i = 0; i < crtc_controllers_.size(); ++i)
(...skipping 18 matching lines...) Expand all
208 189
209 uint64_t HardwareDisplayController::GetTimeOfLastFlip() const { 190 uint64_t HardwareDisplayController::GetTimeOfLastFlip() const {
210 uint64_t time = 0; 191 uint64_t time = 0;
211 for (size_t i = 0; i < crtc_controllers_.size(); ++i) 192 for (size_t i = 0; i < crtc_controllers_.size(); ++i)
212 if (time < crtc_controllers_[i]->time_of_last_flip()) 193 if (time < crtc_controllers_[i]->time_of_last_flip())
213 time = crtc_controllers_[i]->time_of_last_flip(); 194 time = crtc_controllers_[i]->time_of_last_flip();
214 195
215 return time; 196 return time;
216 } 197 }
217 198
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() 199 scoped_refptr<DrmDevice> HardwareDisplayController::GetAllocationDrmDevice()
257 const { 200 const {
258 DCHECK(!crtc_controllers_.empty()); 201 DCHECK(!crtc_controllers_.empty());
259 // TODO(dnicoara) When we support mirroring across DRM devices, figure out 202 // TODO(dnicoara) When we support mirroring across DRM devices, figure out
260 // which device should be used for allocations. 203 // which device should be used for allocations.
261 return crtc_controllers_[0]->drm(); 204 return crtc_controllers_[0]->drm();
262 } 205 }
263 206
264 bool HardwareDisplayController::HasPendingPageFlips() const { 207 bool HardwareDisplayController::HasPendingPageFlips() const {
dnicoara 2015/04/23 15:34:56 Lets just remove this since it is being used for a
265 for (size_t i = 0; i < crtc_controllers_.size(); ++i) 208 for (size_t i = 0; i < crtc_controllers_.size(); ++i)
266 if (crtc_controllers_[i]->page_flip_pending()) 209 if (crtc_controllers_[i]->page_flip_pending())
267 return true; 210 return true;
268 211
269 return false; 212 return false;
270 } 213 }
271 214
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 215 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698