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/drm/gpu/screen_manager.h" | 5 #include "ui/ozone/platform/drm/gpu/screen_manager.h" |
6 | 6 |
7 #include <xf86drmMode.h> | 7 #include <xf86drmMode.h> |
8 | 8 |
9 #include "third_party/skia/include/core/SkCanvas.h" | 9 #include "third_party/skia/include/core/SkCanvas.h" |
10 #include "ui/gfx/geometry/point.h" | 10 #include "ui/gfx/geometry/point.h" |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 return; | 58 return; |
59 } | 59 } |
60 | 60 |
61 skia::RefPtr<SkImage> image = saved_buffer.image(); | 61 skia::RefPtr<SkImage> image = saved_buffer.image(); |
62 SkPaint paint; | 62 SkPaint paint; |
63 // Copy the source buffer. Do not perform any blending. | 63 // Copy the source buffer. Do not perform any blending. |
64 paint.setXfermodeMode(SkXfermode::kSrc_Mode); | 64 paint.setXfermodeMode(SkXfermode::kSrc_Mode); |
65 modeset_buffer.canvas()->drawImage(image.get(), 0, 0, &paint); | 65 modeset_buffer.canvas()->drawImage(image.get(), 0, 0, &paint); |
66 } | 66 } |
67 | 67 |
| 68 CrtcController* GetCrtcController(HardwareDisplayController* controller, |
| 69 const scoped_refptr<DrmDevice>& drm, |
| 70 uint32_t crtc) { |
| 71 for (CrtcController* crtc_controller : controller->crtc_controllers()) { |
| 72 if (crtc_controller->crtc() == crtc) |
| 73 return crtc_controller; |
| 74 } |
| 75 |
| 76 NOTREACHED(); |
| 77 return nullptr; |
| 78 } |
| 79 |
68 } // namespace | 80 } // namespace |
69 | 81 |
70 ScreenManager::ScreenManager(ScanoutBufferGenerator* buffer_generator) | 82 ScreenManager::ScreenManager(ScanoutBufferGenerator* buffer_generator) |
71 : buffer_generator_(buffer_generator) { | 83 : buffer_generator_(buffer_generator) { |
72 } | 84 } |
73 | 85 |
74 ScreenManager::~ScreenManager() { | 86 ScreenManager::~ScreenManager() { |
75 DCHECK(window_map_.empty()); | 87 DCHECK(window_map_.empty()); |
76 } | 88 } |
77 | 89 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
126 uint32_t connector, | 138 uint32_t connector, |
127 const gfx::Point& origin, | 139 const gfx::Point& origin, |
128 const drmModeModeInfo& mode) { | 140 const drmModeModeInfo& mode) { |
129 gfx::Rect modeset_bounds(origin.x(), origin.y(), mode.hdisplay, | 141 gfx::Rect modeset_bounds(origin.x(), origin.y(), mode.hdisplay, |
130 mode.vdisplay); | 142 mode.vdisplay); |
131 HardwareDisplayControllers::iterator it = FindDisplayController(drm, crtc); | 143 HardwareDisplayControllers::iterator it = FindDisplayController(drm, crtc); |
132 DCHECK(controllers_.end() != it) << "Display controller (crtc=" << crtc | 144 DCHECK(controllers_.end() != it) << "Display controller (crtc=" << crtc |
133 << ") doesn't exist."; | 145 << ") doesn't exist."; |
134 | 146 |
135 HardwareDisplayController* controller = *it; | 147 HardwareDisplayController* controller = *it; |
| 148 CrtcController* crtc_controller = GetCrtcController(controller, drm, crtc); |
136 // If nothing changed just enable the controller. Note, we perform an exact | 149 // If nothing changed just enable the controller. Note, we perform an exact |
137 // comparison on the mode since the refresh rate may have changed. | 150 // comparison on the mode since the refresh rate may have changed. |
138 if (SameMode(mode, controller->get_mode()) && | 151 if (SameMode(mode, crtc_controller->mode()) && |
139 origin == controller->origin()) { | 152 origin == controller->origin()) { |
140 if (controller->IsDisabled()) { | 153 if (controller->IsDisabled()) { |
141 HardwareDisplayControllers::iterator mirror = | 154 HardwareDisplayControllers::iterator mirror = |
142 FindActiveDisplayControllerByLocation(modeset_bounds); | 155 FindActiveDisplayControllerByLocation(modeset_bounds); |
143 // If there is an active controller at the same location then start mirror | 156 // If there is an active controller at the same location then start mirror |
144 // mode. | 157 // mode. |
145 if (mirror != controllers_.end()) | 158 if (mirror != controllers_.end()) |
146 return HandleMirrorMode(it, mirror, drm, crtc, connector); | 159 return HandleMirrorMode(it, mirror, drm, crtc, connector, mode); |
147 } | 160 } |
148 | 161 |
149 // Just re-enable the controller to re-use the current state. | 162 // Just re-enable the controller to re-use the current state. |
150 return EnableController(controller, controller->origin(), | 163 return EnableController(controller); |
151 controller->get_mode()); | |
152 } | 164 } |
153 | 165 |
154 // Either the mode or the location of the display changed, so exit mirror | 166 // Either the mode or the location of the display changed, so exit mirror |
155 // mode and configure the display independently. If the caller still wants | 167 // mode and configure the display independently. If the caller still wants |
156 // mirror mode, subsequent calls configuring the other controllers will | 168 // mirror mode, subsequent calls configuring the other controllers will |
157 // restore mirror mode. | 169 // restore mirror mode. |
158 if (controller->IsMirrored()) { | 170 if (controller->IsMirrored()) { |
159 controller = new HardwareDisplayController( | 171 controller = new HardwareDisplayController( |
160 controller->RemoveCrtc(drm, crtc), controller->origin()); | 172 controller->RemoveCrtc(drm, crtc), controller->origin()); |
161 controllers_.push_back(controller); | 173 controllers_.push_back(controller); |
162 it = controllers_.end() - 1; | 174 it = controllers_.end() - 1; |
163 } | 175 } |
164 | 176 |
165 HardwareDisplayControllers::iterator mirror = | 177 HardwareDisplayControllers::iterator mirror = |
166 FindActiveDisplayControllerByLocation(modeset_bounds); | 178 FindActiveDisplayControllerByLocation(modeset_bounds); |
167 // Handle mirror mode. | 179 // Handle mirror mode. |
168 if (mirror != controllers_.end() && it != mirror) | 180 if (mirror != controllers_.end() && it != mirror) |
169 return HandleMirrorMode(it, mirror, drm, crtc, connector); | 181 return HandleMirrorMode(it, mirror, drm, crtc, connector, mode); |
170 | 182 |
171 return EnableController(controller, origin, mode); | 183 return ModesetController(controller, origin, mode); |
172 } | 184 } |
173 | 185 |
174 bool ScreenManager::DisableDisplayController( | 186 bool ScreenManager::DisableDisplayController( |
175 const scoped_refptr<DrmDevice>& drm, | 187 const scoped_refptr<DrmDevice>& drm, |
176 uint32_t crtc) { | 188 uint32_t crtc) { |
177 HardwareDisplayControllers::iterator it = FindDisplayController(drm, crtc); | 189 HardwareDisplayControllers::iterator it = FindDisplayController(drm, crtc); |
178 if (it != controllers_.end()) { | 190 if (it != controllers_.end()) { |
179 HardwareDisplayController* controller = *it; | 191 HardwareDisplayController* controller = *it; |
180 if (controller->IsMirrored()) { | 192 if (controller->IsMirrored()) { |
181 controller = new HardwareDisplayController( | 193 controller = new HardwareDisplayController( |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 } | 261 } |
250 | 262 |
251 return controllers_.end(); | 263 return controllers_.end(); |
252 } | 264 } |
253 | 265 |
254 bool ScreenManager::HandleMirrorMode( | 266 bool ScreenManager::HandleMirrorMode( |
255 HardwareDisplayControllers::iterator original, | 267 HardwareDisplayControllers::iterator original, |
256 HardwareDisplayControllers::iterator mirror, | 268 HardwareDisplayControllers::iterator mirror, |
257 const scoped_refptr<DrmDevice>& drm, | 269 const scoped_refptr<DrmDevice>& drm, |
258 uint32_t crtc, | 270 uint32_t crtc, |
259 uint32_t connector) { | 271 uint32_t connector, |
260 (*mirror)->AddCrtc((*original)->RemoveCrtc(drm, crtc)); | 272 const drmModeModeInfo& mode) { |
261 if (EnableController(*mirror, (*mirror)->origin(), (*mirror)->get_mode())) { | 273 gfx::Point last_origin = (*original)->origin(); |
| 274 // There should only be one CRTC in this controller. |
| 275 drmModeModeInfo last_mode = (*original)->crtc_controllers()[0]->mode(); |
| 276 |
| 277 // Modeset the CRTC with its mode in the original controller so that only this |
| 278 // CRTC is affected by the mode. Otherwise it could apply a mode with the same |
| 279 // resolution and refresh rate but with different timings to the other CRTC. |
| 280 // TODO(dnicoara): This is hacky, instead the DrmDisplay and CrtcController |
| 281 // should be merged and picking the mode should be done properly within |
| 282 // HardwareDisplayController. |
| 283 if (ModesetController(*original, (*mirror)->origin(), mode)) { |
| 284 (*mirror)->AddCrtc((*original)->RemoveCrtc(drm, crtc)); |
262 controllers_.erase(original); | 285 controllers_.erase(original); |
263 return true; | 286 return true; |
264 } | 287 } |
265 | 288 |
266 LOG(ERROR) << "Failed to switch to mirror mode"; | 289 LOG(ERROR) << "Failed to switch to mirror mode"; |
267 | 290 |
268 // When things go wrong revert back to the previous configuration since | 291 // When things go wrong revert back to the previous configuration since |
269 // it is expected that the configuration would not have changed if | 292 // it is expected that the configuration would not have changed if |
270 // things fail. | 293 // things fail. |
271 (*original)->AddCrtc((*mirror)->RemoveCrtc(drm, crtc)); | 294 ModesetController(*original, last_origin, last_mode); |
272 EnableController(*original, (*original)->origin(), (*original)->get_mode()); | |
273 return false; | 295 return false; |
274 } | 296 } |
275 | 297 |
276 void ScreenManager::UpdateControllerToWindowMapping() { | 298 void ScreenManager::UpdateControllerToWindowMapping() { |
277 std::map<DrmWindow*, HardwareDisplayController*> window_to_controller_map; | 299 std::map<DrmWindow*, HardwareDisplayController*> window_to_controller_map; |
278 // First create a unique mapping between a window and a controller. Note, a | 300 // First create a unique mapping between a window and a controller. Note, a |
279 // controller may be associated with at most 1 window. | 301 // controller may be associated with at most 1 window. |
280 for (HardwareDisplayController* controller : controllers_) { | 302 for (HardwareDisplayController* controller : controllers_) { |
281 if (controller->IsDisabled()) | 303 if (controller->IsDisabled()) |
282 continue; | 304 continue; |
(...skipping 13 matching lines...) Expand all Loading... |
296 if (it != window_to_controller_map.end()) | 318 if (it != window_to_controller_map.end()) |
297 controller = it->second; | 319 controller = it->second; |
298 | 320 |
299 bool should_enable = | 321 bool should_enable = |
300 controller && pair.second->GetController() != controller; | 322 controller && pair.second->GetController() != controller; |
301 pair.second->SetController(controller); | 323 pair.second->SetController(controller); |
302 | 324 |
303 // If we're moving windows between controllers modeset the controller | 325 // If we're moving windows between controllers modeset the controller |
304 // otherwise the controller may be waiting for a page flip while the window | 326 // otherwise the controller may be waiting for a page flip while the window |
305 // tries to schedule another buffer. | 327 // tries to schedule another buffer. |
306 if (should_enable) | 328 if (should_enable) { |
307 EnableController(controller, controller->origin(), | 329 EnableController(controller); |
308 controller->get_mode()); | 330 } |
309 } | 331 } |
310 } | 332 } |
311 | 333 |
312 bool ScreenManager::EnableController(HardwareDisplayController* controller, | 334 OverlayPlane ScreenManager::GetModesetBuffer( |
313 const gfx::Point& origin, | 335 HardwareDisplayController* controller, |
314 const drmModeModeInfo& mode) { | 336 const gfx::Rect& bounds) { |
| 337 DrmWindow* window = FindWindowAt(bounds); |
| 338 if (window) { |
| 339 const OverlayPlane* primary = window->GetLastModesetBuffer(); |
| 340 if (primary && primary->buffer->GetSize() == bounds.size()) |
| 341 return *primary; |
| 342 } |
| 343 |
| 344 scoped_refptr<DrmDevice> drm = controller->GetAllocationDrmDevice(); |
| 345 scoped_refptr<ScanoutBuffer> buffer = |
| 346 buffer_generator_->Create(drm, bounds.size()); |
| 347 if (!buffer) { |
| 348 LOG(ERROR) << "Failed to create scanout buffer"; |
| 349 return OverlayPlane(nullptr, 0, gfx::OVERLAY_TRANSFORM_INVALID, gfx::Rect(), |
| 350 gfx::RectF()); |
| 351 } |
| 352 |
| 353 FillModesetBuffer(drm, controller, buffer.get()); |
| 354 return OverlayPlane(buffer); |
| 355 } |
| 356 |
| 357 bool ScreenManager::EnableController(HardwareDisplayController* controller) { |
| 358 DCHECK(!controller->crtc_controllers().empty()); |
| 359 gfx::Rect rect(controller->origin(), controller->GetModeSize()); |
| 360 OverlayPlane plane = GetModesetBuffer(controller, rect); |
| 361 if (!plane.buffer || !controller->Enable(plane)) { |
| 362 LOG(ERROR) << "Failed to enable controller"; |
| 363 return false; |
| 364 } |
| 365 |
| 366 return true; |
| 367 } |
| 368 |
| 369 bool ScreenManager::ModesetController(HardwareDisplayController* controller, |
| 370 const gfx::Point& origin, |
| 371 const drmModeModeInfo& mode) { |
315 DCHECK(!controller->crtc_controllers().empty()); | 372 DCHECK(!controller->crtc_controllers().empty()); |
316 gfx::Rect rect(origin, gfx::Size(mode.hdisplay, mode.vdisplay)); | 373 gfx::Rect rect(origin, gfx::Size(mode.hdisplay, mode.vdisplay)); |
317 controller->set_origin(origin); | 374 controller->set_origin(origin); |
318 | 375 |
319 DrmWindow* window = FindWindowAt(rect); | 376 OverlayPlane plane = GetModesetBuffer(controller, rect); |
320 if (window) { | 377 if (!plane.buffer || !controller->Modeset(plane, mode)) { |
321 const OverlayPlane* primary = window->GetLastModesetBuffer(); | |
322 if (primary) { | |
323 if (!controller->Modeset(*primary, mode)) { | |
324 LOG(ERROR) << "Failed to modeset controller"; | |
325 return false; | |
326 } | |
327 | |
328 return true; | |
329 } | |
330 } | |
331 | |
332 scoped_refptr<DrmDevice> drm = controller->GetAllocationDrmDevice(); | |
333 scoped_refptr<ScanoutBuffer> buffer = | |
334 buffer_generator_->Create(drm, rect.size()); | |
335 if (!buffer) { | |
336 LOG(ERROR) << "Failed to create scanout buffer"; | |
337 return false; | |
338 } | |
339 | |
340 FillModesetBuffer(drm, controller, buffer.get()); | |
341 if (!controller->Modeset(OverlayPlane(buffer), mode)) { | |
342 LOG(ERROR) << "Failed to modeset controller"; | 378 LOG(ERROR) << "Failed to modeset controller"; |
343 return false; | 379 return false; |
344 } | 380 } |
345 | 381 |
346 return true; | 382 return true; |
347 } | 383 } |
348 | 384 |
349 DrmWindow* ScreenManager::FindWindowAt(const gfx::Rect& bounds) const { | 385 DrmWindow* ScreenManager::FindWindowAt(const gfx::Rect& bounds) const { |
350 for (auto pair : window_map_) { | 386 for (auto pair : window_map_) { |
351 if (pair.second->bounds() == bounds) | 387 if (pair.second->bounds() == bounds) |
352 return pair.second; | 388 return pair.second; |
353 } | 389 } |
354 | 390 |
355 return nullptr; | 391 return nullptr; |
356 } | 392 } |
357 | 393 |
358 } // namespace ui | 394 } // namespace ui |
OLD | NEW |