Commit b8395cc5 authored by Mark Yacoub's avatar Mark Yacoub Committed by Commit Bot

Disable all removed displays together.

When multiples displays are removed at the same time, commit a disable
modeset of all them together instead of each separately.
This should prevent unplugged MST connectors from being in zombie mode.

BUG=b/172069469, b/169386252
TEST=unplug and replug 2 connectors on MST hub, ScreenManagerTest.CheckMultipleControllersAfterBeingRemoved

Change-Id: If24f9016462b9c69633148202641f7ba6bae9114
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2512550
Commit-Queue: Mark Yacoub <markyacoub@google.com>
Reviewed-by: default avatarDaniel Nicoara <dnicoara@chromium.org>
Cr-Commit-Position: refs/heads/master@{#823623}
parent 7b389f1d
...@@ -36,13 +36,6 @@ CrtcController::~CrtcController() { ...@@ -36,13 +36,6 @@ CrtcController::~CrtcController() {
plane->set_in_use(false); plane->set_in_use(false);
} }
} }
// Disable CRTC controller.
CommitRequest commit_request;
commit_request.push_back(
CrtcCommitRequest::DisableCrtcRequest(crtc_, connector_));
drm_->plane_manager()->Commit(std::move(commit_request),
DRM_MODE_ATOMIC_ALLOW_MODESET);
} }
} }
......
...@@ -336,15 +336,18 @@ DrmDisplay* DrmGpuDisplayManager::FindDisplay(int64_t display_id) { ...@@ -336,15 +336,18 @@ DrmDisplay* DrmGpuDisplayManager::FindDisplay(int64_t display_id) {
void DrmGpuDisplayManager::NotifyScreenManager( void DrmGpuDisplayManager::NotifyScreenManager(
const std::vector<std::unique_ptr<DrmDisplay>>& new_displays, const std::vector<std::unique_ptr<DrmDisplay>>& new_displays,
const std::vector<std::unique_ptr<DrmDisplay>>& old_displays) const { const std::vector<std::unique_ptr<DrmDisplay>>& old_displays) const {
ScreenManager::CrtcsWithDrmList controllers_to_remove;
for (const auto& old_display : old_displays) { for (const auto& old_display : old_displays) {
auto it = std::find_if(new_displays.begin(), new_displays.end(), auto it = std::find_if(new_displays.begin(), new_displays.end(),
DisplayComparator(old_display.get())); DisplayComparator(old_display.get()));
if (it == new_displays.end()) { if (it == new_displays.end()) {
screen_manager_->RemoveDisplayController(old_display->drm(), controllers_to_remove.emplace_back(old_display->crtc(),
old_display->crtc()); old_display->drm());
} }
} }
if (!controllers_to_remove.empty())
screen_manager_->RemoveDisplayControllers(controllers_to_remove);
for (const auto& new_display : new_displays) { for (const auto& new_display : new_displays) {
auto it = std::find_if(old_displays.begin(), old_displays.end(), auto it = std::find_if(old_displays.begin(), old_displays.end(),
......
...@@ -173,17 +173,54 @@ void ScreenManager::AddDisplayController(const scoped_refptr<DrmDevice>& drm, ...@@ -173,17 +173,54 @@ void ScreenManager::AddDisplayController(const scoped_refptr<DrmDevice>& drm,
std::make_unique<CrtcController>(drm, crtc, connector), gfx::Point())); std::make_unique<CrtcController>(drm, crtc, connector), gfx::Point()));
} }
void ScreenManager::RemoveDisplayController(const scoped_refptr<DrmDevice>& drm, void ScreenManager::RemoveDisplayControllers(
uint32_t crtc) { const CrtcsWithDrmList& controllers_to_remove) {
HardwareDisplayControllers::iterator it = FindDisplayController(drm, crtc); // Split them to different lists unique to each DRM Device.
if (it != controllers_.end()) { base::flat_map<scoped_refptr<DrmDevice>, CrtcsWithDrmList>
controllers_for_drm_devices;
for (const auto& controller : controllers_to_remove) {
auto drm = controller.second;
auto it = controllers_for_drm_devices.find(drm);
if (it == controllers_for_drm_devices.end()) {
controllers_for_drm_devices.insert(
std::make_pair(drm, CrtcsWithDrmList()));
}
controllers_for_drm_devices[drm].emplace_back(controller);
}
bool should_update_controllers_to_window_mapping = false;
for (const auto& controllers_on_drm : controllers_for_drm_devices) {
CrtcsWithDrmList controllers_to_remove = controllers_on_drm.second;
CommitRequest commit_request;
auto drm = controllers_on_drm.first;
for (const auto& controller : controllers_to_remove) {
uint32_t crtc_id = controller.first;
auto it = FindDisplayController(drm, crtc_id);
if (it == controllers_.end())
continue;
bool is_mirrored = (*it)->IsMirrored(); bool is_mirrored = (*it)->IsMirrored();
(*it)->RemoveCrtc(drm, crtc);
std::unique_ptr<CrtcController> crtc = (*it)->RemoveCrtc(drm, crtc_id);
if (crtc->is_enabled()) {
commit_request.push_back(CrtcCommitRequest::DisableCrtcRequest(
crtc->crtc(), crtc->connector()));
}
if (!is_mirrored) { if (!is_mirrored) {
controllers_.erase(it); controllers_.erase(it);
UpdateControllerToWindowMapping(); should_update_controllers_to_window_mapping = true;
} }
} }
if (!commit_request.empty()) {
drm->plane_manager()->Commit(std::move(commit_request),
DRM_MODE_ATOMIC_ALLOW_MODESET);
}
}
if (should_update_controllers_to_window_mapping)
UpdateControllerToWindowMapping();
} }
base::flat_map<int64_t, bool> ScreenManager::ConfigureDisplayControllers( base::flat_map<int64_t, bool> ScreenManager::ConfigureDisplayControllers(
......
...@@ -31,6 +31,9 @@ class DrmWindow; ...@@ -31,6 +31,9 @@ class DrmWindow;
// Responsible for keeping track of active displays and configuring them. // Responsible for keeping track of active displays and configuring them.
class ScreenManager { class ScreenManager {
public: public:
using CrtcsWithDrmList =
std::vector<std::pair<uint32_t, const scoped_refptr<DrmDevice>>>;
struct ControllerConfigParams { struct ControllerConfigParams {
ControllerConfigParams(int64_t display_id, ControllerConfigParams(int64_t display_id,
scoped_refptr<DrmDevice> drm, scoped_refptr<DrmDevice> drm,
...@@ -60,10 +63,9 @@ class ScreenManager { ...@@ -60,10 +63,9 @@ class ScreenManager {
uint32_t crtc, uint32_t crtc,
uint32_t connector); uint32_t connector);
// Remove a display controller from the list of active controllers. The // Remove display controllers from the list of active controllers. The
// controller is removed since it was disconnected. // controllers are removed since they were disconnected.
void RemoveDisplayController(const scoped_refptr<DrmDevice>& drm, void RemoveDisplayControllers(const CrtcsWithDrmList& controllers_to_remove);
uint32_t crtc);
// Enables/Disables the display controller based on if a mode exists. // Enables/Disables the display controller based on if a mode exists.
base::flat_map<int64_t, bool> ConfigureDisplayControllers( base::flat_map<int64_t, bool> ConfigureDisplayControllers(
......
...@@ -299,10 +299,40 @@ TEST_F(ScreenManagerTest, CheckControllerAfterItIsRemoved) { ...@@ -299,10 +299,40 @@ TEST_F(ScreenManagerTest, CheckControllerAfterItIsRemoved) {
EXPECT_TRUE(screen_manager_->GetDisplayController(GetPrimaryBounds())); EXPECT_TRUE(screen_manager_->GetDisplayController(GetPrimaryBounds()));
screen_manager_->RemoveDisplayController(drm_, kPrimaryCrtc); ScreenManager::CrtcsWithDrmList controllers_to_remove;
controllers_to_remove.emplace_back(kPrimaryCrtc, drm_);
screen_manager_->RemoveDisplayControllers(controllers_to_remove);
EXPECT_FALSE(screen_manager_->GetDisplayController(GetPrimaryBounds())); EXPECT_FALSE(screen_manager_->GetDisplayController(GetPrimaryBounds()));
} }
TEST_F(ScreenManagerTest, CheckMultipleControllersAfterBeingRemoved) {
InitializeDrmStateWithDefault(drm_.get());
screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
screen_manager_->AddDisplayController(drm_, kSecondaryCrtc,
kSecondaryConnector);
ScreenManager::ControllerConfigsList controllers_to_enable;
controllers_to_enable.emplace_back(
kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
GetPrimaryBounds().origin(),
std::make_unique<drmModeModeInfo>(kDefaultMode));
controllers_to_enable.emplace_back(
kSecondaryDisplayId, drm_, kSecondaryCrtc, kSecondaryConnector,
GetSecondaryBounds().origin(),
std::make_unique<drmModeModeInfo>(kDefaultMode));
screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
ScreenManager::CrtcsWithDrmList controllers_to_remove;
controllers_to_remove.emplace_back(kPrimaryCrtc, drm_);
controllers_to_remove.emplace_back(kSecondaryCrtc, drm_);
screen_manager_->RemoveDisplayControllers(controllers_to_remove);
EXPECT_FALSE(screen_manager_->GetDisplayController(GetPrimaryBounds()));
EXPECT_FALSE(screen_manager_->GetDisplayController(GetSecondaryBounds()));
}
TEST_F(ScreenManagerTest, CheckDuplicateConfiguration) { TEST_F(ScreenManagerTest, CheckDuplicateConfiguration) {
InitializeDrmStateWithDefault(drm_.get(), /*is_atomic*/ false); InitializeDrmStateWithDefault(drm_.get(), /*is_atomic*/ false);
...@@ -517,7 +547,9 @@ TEST_F(ScreenManagerTest, MonitorGoneInMirrorMode) { ...@@ -517,7 +547,9 @@ TEST_F(ScreenManagerTest, MonitorGoneInMirrorMode) {
std::make_unique<drmModeModeInfo>(secondary_mode)); std::make_unique<drmModeModeInfo>(secondary_mode));
screen_manager_->ConfigureDisplayControllers(controllers_to_enable); screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
screen_manager_->RemoveDisplayController(drm_, kSecondaryCrtc); ScreenManager::CrtcsWithDrmList controllers_to_remove;
controllers_to_remove.emplace_back(kSecondaryCrtc, drm_);
screen_manager_->RemoveDisplayControllers(controllers_to_remove);
ui::HardwareDisplayController* controller = ui::HardwareDisplayController* controller =
screen_manager_->GetDisplayController(GetPrimaryBounds()); screen_manager_->GetDisplayController(GetPrimaryBounds());
...@@ -855,7 +887,9 @@ TEST_F(ScreenManagerTest, ShouldDissociateWindowOnControllerRemoval) { ...@@ -855,7 +887,9 @@ TEST_F(ScreenManagerTest, ShouldDissociateWindowOnControllerRemoval) {
EXPECT_TRUE(screen_manager_->GetWindow(window_id)->GetController()); EXPECT_TRUE(screen_manager_->GetWindow(window_id)->GetController());
screen_manager_->RemoveDisplayController(drm_, kPrimaryCrtc); ScreenManager::CrtcsWithDrmList controllers_to_remove;
controllers_to_remove.emplace_back(kPrimaryCrtc, drm_);
screen_manager_->RemoveDisplayControllers(controllers_to_remove);
EXPECT_FALSE(screen_manager_->GetWindow(window_id)->GetController()); EXPECT_FALSE(screen_manager_->GetWindow(window_id)->GetController());
...@@ -1063,7 +1097,9 @@ TEST_F(ScreenManagerTest, ShouldNotHardwareMirrorDifferentDrmDevices) { ...@@ -1063,7 +1097,9 @@ TEST_F(ScreenManagerTest, ShouldNotHardwareMirrorDifferentDrmDevices) {
// Disconnect first display. Second display moves to origin. // Disconnect first display. Second display moves to origin.
{ {
screen_manager.RemoveDisplayController(drm_device1, kCrtc1); ScreenManager::CrtcsWithDrmList controllers_to_remove;
controllers_to_remove.emplace_back(kCrtc1, drm_device1);
screen_manager.RemoveDisplayControllers(controllers_to_remove);
ScreenManager::ControllerConfigsList controllers_to_enable; ScreenManager::ControllerConfigsList controllers_to_enable;
std::unique_ptr<drmModeModeInfo> secondary_mode = std::unique_ptr<drmModeModeInfo> secondary_mode =
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment