| Index: ui/ozone/platform/drm/gpu/screen_manager.cc
|
| diff --git a/ui/ozone/platform/drm/gpu/screen_manager.cc b/ui/ozone/platform/drm/gpu/screen_manager.cc
|
| index 72a14a1f17f7a65de3e9fb9a7a7a5bbadcbd7e61..2aba0d96029143a830fdc988c379c8a975f406ff 100644
|
| --- a/ui/ozone/platform/drm/gpu/screen_manager.cc
|
| +++ b/ui/ozone/platform/drm/gpu/screen_manager.cc
|
| @@ -65,6 +65,18 @@ void FillModesetBuffer(const scoped_refptr<DrmDevice>& drm,
|
| modeset_buffer.canvas()->drawImage(image.get(), 0, 0, &paint);
|
| }
|
|
|
| +CrtcController* GetCrtcController(HardwareDisplayController* controller,
|
| + const scoped_refptr<DrmDevice>& drm,
|
| + uint32_t crtc) {
|
| + for (CrtcController* crtc_controller : controller->crtc_controllers()) {
|
| + if (crtc_controller->crtc() == crtc)
|
| + return crtc_controller;
|
| + }
|
| +
|
| + NOTREACHED();
|
| + return nullptr;
|
| +}
|
| +
|
| } // namespace
|
|
|
| ScreenManager::ScreenManager(ScanoutBufferGenerator* buffer_generator)
|
| @@ -133,9 +145,10 @@ bool ScreenManager::ActualConfigureDisplayController(
|
| << ") doesn't exist.";
|
|
|
| HardwareDisplayController* controller = *it;
|
| + CrtcController* crtc_controller = GetCrtcController(controller, drm, crtc);
|
| // If nothing changed just enable the controller. Note, we perform an exact
|
| // comparison on the mode since the refresh rate may have changed.
|
| - if (SameMode(mode, controller->get_mode()) &&
|
| + if (SameMode(mode, crtc_controller->mode()) &&
|
| origin == controller->origin()) {
|
| if (controller->IsDisabled()) {
|
| HardwareDisplayControllers::iterator mirror =
|
| @@ -143,12 +156,11 @@ bool ScreenManager::ActualConfigureDisplayController(
|
| // If there is an active controller at the same location then start mirror
|
| // mode.
|
| if (mirror != controllers_.end())
|
| - return HandleMirrorMode(it, mirror, drm, crtc, connector);
|
| + return HandleMirrorMode(it, mirror, drm, crtc, connector, mode);
|
| }
|
|
|
| // Just re-enable the controller to re-use the current state.
|
| - return EnableController(controller, controller->origin(),
|
| - controller->get_mode());
|
| + return EnableController(controller);
|
| }
|
|
|
| // Either the mode or the location of the display changed, so exit mirror
|
| @@ -166,9 +178,9 @@ bool ScreenManager::ActualConfigureDisplayController(
|
| FindActiveDisplayControllerByLocation(modeset_bounds);
|
| // Handle mirror mode.
|
| if (mirror != controllers_.end() && it != mirror)
|
| - return HandleMirrorMode(it, mirror, drm, crtc, connector);
|
| + return HandleMirrorMode(it, mirror, drm, crtc, connector, mode);
|
|
|
| - return EnableController(controller, origin, mode);
|
| + return ModesetController(controller, origin, mode);
|
| }
|
|
|
| bool ScreenManager::DisableDisplayController(
|
| @@ -256,9 +268,20 @@ bool ScreenManager::HandleMirrorMode(
|
| HardwareDisplayControllers::iterator mirror,
|
| const scoped_refptr<DrmDevice>& drm,
|
| uint32_t crtc,
|
| - uint32_t connector) {
|
| - (*mirror)->AddCrtc((*original)->RemoveCrtc(drm, crtc));
|
| - if (EnableController(*mirror, (*mirror)->origin(), (*mirror)->get_mode())) {
|
| + uint32_t connector,
|
| + const drmModeModeInfo& mode) {
|
| + gfx::Point last_origin = (*original)->origin();
|
| + // There should only be one CRTC in this controller.
|
| + drmModeModeInfo last_mode = (*original)->crtc_controllers()[0]->mode();
|
| +
|
| + // Modeset the CRTC with its mode in the original controller so that only this
|
| + // CRTC is affected by the mode. Otherwise it could apply a mode with the same
|
| + // resolution and refresh rate but with different timings to the other CRTC.
|
| + // TODO(dnicoara): This is hacky, instead the DrmDisplay and CrtcController
|
| + // should be merged and picking the mode should be done properly within
|
| + // HardwareDisplayController.
|
| + if (ModesetController(*original, (*mirror)->origin(), mode)) {
|
| + (*mirror)->AddCrtc((*original)->RemoveCrtc(drm, crtc));
|
| controllers_.erase(original);
|
| return true;
|
| }
|
| @@ -268,8 +291,7 @@ bool ScreenManager::HandleMirrorMode(
|
| // When things go wrong revert back to the previous configuration since
|
| // it is expected that the configuration would not have changed if
|
| // things fail.
|
| - (*original)->AddCrtc((*mirror)->RemoveCrtc(drm, crtc));
|
| - EnableController(*original, (*original)->origin(), (*original)->get_mode());
|
| + ModesetController(*original, last_origin, last_mode);
|
| return false;
|
| }
|
|
|
| @@ -303,42 +325,56 @@ void ScreenManager::UpdateControllerToWindowMapping() {
|
| // If we're moving windows between controllers modeset the controller
|
| // otherwise the controller may be waiting for a page flip while the window
|
| // tries to schedule another buffer.
|
| - if (should_enable)
|
| - EnableController(controller, controller->origin(),
|
| - controller->get_mode());
|
| + if (should_enable) {
|
| + EnableController(controller);
|
| + }
|
| }
|
| }
|
|
|
| -bool ScreenManager::EnableController(HardwareDisplayController* controller,
|
| - const gfx::Point& origin,
|
| - const drmModeModeInfo& mode) {
|
| - DCHECK(!controller->crtc_controllers().empty());
|
| - gfx::Rect rect(origin, gfx::Size(mode.hdisplay, mode.vdisplay));
|
| - controller->set_origin(origin);
|
| -
|
| - DrmWindow* window = FindWindowAt(rect);
|
| +OverlayPlane ScreenManager::GetModesetBuffer(
|
| + HardwareDisplayController* controller,
|
| + const gfx::Rect& bounds) {
|
| + DrmWindow* window = FindWindowAt(bounds);
|
| if (window) {
|
| const OverlayPlane* primary = window->GetLastModesetBuffer();
|
| - if (primary) {
|
| - if (!controller->Modeset(*primary, mode)) {
|
| - LOG(ERROR) << "Failed to modeset controller";
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| - }
|
| + if (primary && primary->buffer->GetSize() == bounds.size())
|
| + return *primary;
|
| }
|
|
|
| scoped_refptr<DrmDevice> drm = controller->GetAllocationDrmDevice();
|
| scoped_refptr<ScanoutBuffer> buffer =
|
| - buffer_generator_->Create(drm, rect.size());
|
| + buffer_generator_->Create(drm, bounds.size());
|
| if (!buffer) {
|
| LOG(ERROR) << "Failed to create scanout buffer";
|
| - return false;
|
| + return OverlayPlane(nullptr, 0, gfx::OVERLAY_TRANSFORM_INVALID, gfx::Rect(),
|
| + gfx::RectF());
|
| }
|
|
|
| FillModesetBuffer(drm, controller, buffer.get());
|
| - if (!controller->Modeset(OverlayPlane(buffer), mode)) {
|
| + return OverlayPlane(buffer);
|
| +}
|
| +
|
| +bool ScreenManager::EnableController(HardwareDisplayController* controller) {
|
| + DCHECK(!controller->crtc_controllers().empty());
|
| + gfx::Rect rect(controller->origin(), controller->GetModeSize());
|
| + OverlayPlane plane = GetModesetBuffer(controller, rect);
|
| + if (!plane.buffer || !controller->Enable(plane)) {
|
| + LOG(ERROR) << "Failed to enable controller";
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool ScreenManager::ModesetController(HardwareDisplayController* controller,
|
| + const gfx::Point& origin,
|
| + const drmModeModeInfo& mode) {
|
| + DCHECK(!controller->crtc_controllers().empty());
|
| + gfx::Rect rect(origin, gfx::Size(mode.hdisplay, mode.vdisplay));
|
| + controller->set_origin(origin);
|
| +
|
| + OverlayPlane plane = GetModesetBuffer(controller, rect);
|
| + if (!plane.buffer || !controller->Modeset(plane, mode)) {
|
| LOG(ERROR) << "Failed to modeset controller";
|
| return false;
|
| }
|
|
|