From 804453ba953bf7ef6b536e498229e085112eb424 Mon Sep 17 00:00:00 2001 From: Matthew Kosarek Date: Fri, 8 Sep 2023 14:15:51 -0400 Subject: [PATCH] Adding a check for a crtc mismatch instead of just rectangle comparing --- .../gbm-kms/server/kms/display_buffer.cpp | 29 +++++-------- src/platforms/gbm-kms/server/kms/kms_output.h | 7 +++- .../gbm-kms/server/kms/real_kms_output.cpp | 41 +++++++++---------- .../gbm-kms/server/kms/real_kms_output.h | 2 +- .../platforms/gbm-kms/kms/mock_kms_output.h | 2 +- 5 files changed, 38 insertions(+), 43 deletions(-) diff --git a/src/platforms/gbm-kms/server/kms/display_buffer.cpp b/src/platforms/gbm-kms/server/kms/display_buffer.cpp index 1d723dc197d..9563923c1e6 100644 --- a/src/platforms/gbm-kms/server/kms/display_buffer.cpp +++ b/src/platforms/gbm-kms/server/kms/display_buffer.cpp @@ -63,34 +63,25 @@ mgg::DisplayBuffer::DisplayBuffer( { listener->report_successful_setup_of_native_resources(); - bool needs_crtc_set = false; + // If any of the outputs have a CRTC mismatch, we will want to set all of them + // so that they're all showing the same buffer. + bool has_crtc_mismatch = false; for (auto& output : outputs) { - try - { - geometry::Rectangle rectangle = output->get_rectangle(); - if (rectangle != area) - { - needs_crtc_set = true; - break; - } - } - catch (std::invalid_argument&) - { - needs_crtc_set = true; + has_crtc_mismatch = output->has_crtc_mismatch(); + if (has_crtc_mismatch) break; - } } - if (needs_crtc_set) + if (has_crtc_mismatch) { mir::log_info("Clearing screen due to differing encountered and target modes"); // TODO: Pull a supported format out of KMS rather than assuming XRGB8888 auto initial_fb = std::make_shared( - std::move(drm_fd), - false, - DRMFormat{DRM_FORMAT_XRGB8888}, - area.size); + std::move(drm_fd), + false, + DRMFormat{DRM_FORMAT_XRGB8888}, + area.size); auto mapping = initial_fb->map_writeable(); ::memset(mapping->data(), 24, mapping->len()); diff --git a/src/platforms/gbm-kms/server/kms/kms_output.h b/src/platforms/gbm-kms/server/kms/kms_output.h index abe6037f1a6..f68a59c6b6a 100644 --- a/src/platforms/gbm-kms/server/kms/kms_output.h +++ b/src/platforms/gbm-kms/server/kms/kms_output.h @@ -63,7 +63,12 @@ class KMSOutput virtual int max_refresh_rate() const = 0; virtual bool set_crtc(FBHandle const& fb) = 0; - virtual auto get_rectangle() -> mir::geometry::Rectangle = 0; + + /** + * Check if the pending call to set_crtc is compatible with the current state of the CRTC. + * @returns true if a set_crtc is required, otherwise false + */ + virtual bool has_crtc_mismatch() = 0; virtual void clear_crtc() = 0; virtual bool schedule_page_flip(FBHandle const& fb) = 0; virtual void wait_for_page_flip() = 0; diff --git a/src/platforms/gbm-kms/server/kms/real_kms_output.cpp b/src/platforms/gbm-kms/server/kms/real_kms_output.cpp index 7e700dacbb6..795258ff4e1 100644 --- a/src/platforms/gbm-kms/server/kms/real_kms_output.cpp +++ b/src/platforms/gbm-kms/server/kms/real_kms_output.cpp @@ -34,6 +34,22 @@ namespace mgk = mg::kms; namespace geom = mir::geometry; +namespace +{ +bool kms_modes_are_equal(drmModeModeInfo const& info1, drmModeModeInfo const& info2) +{ + return (info1.clock == info2.clock && + info1.hdisplay == info2.hdisplay && + info1.hsync_start == info2.hsync_start && + info1.hsync_end == info2.hsync_end && + info1.htotal == info2.htotal && + info1.hskew == info2.hskew && + info1.vdisplay == info2.vdisplay && + info1.vsync_start == info2.vsync_start && + info1.vsync_end == info2.vsync_end && + info1.vtotal == info2.vtotal); +} +} mgg::RealKMSOutput::RealKMSOutput( int drm_fd, @@ -140,7 +156,7 @@ bool mgg::RealKMSOutput::set_crtc(FBHandle const& fb) return false; } - auto ret = drmModeSetCrtc(drm_fd_, current_crtc->crtc_id, + auto ret = drmModeSetCrtc(drm_fd_, current_crtc->crtc_id, fb, fb_offset.dx.as_int(), fb_offset.dy.as_int(), &connector->connector_id, 1, &connector->modes[mode_index]); @@ -155,17 +171,15 @@ bool mgg::RealKMSOutput::set_crtc(FBHandle const& fb) return true; } -auto mgg::RealKMSOutput::get_rectangle() -> mir::geometry::Rectangle +bool mgg::RealKMSOutput::has_crtc_mismatch() { if (!ensure_crtc()) { mir::log_error("Output %s has no associated CRTC to get ", mgk::connector_name(connector).c_str()); - BOOST_THROW_EXCEPTION(std::invalid_argument("get_crtc: Output has no associated CRTC to get")); + return true; } - return mir::geometry::Rectangle( - mir::geometry::Point(current_crtc->x, current_crtc->y), - mir::geometry::Size(current_crtc->width, current_crtc->height)); + return !kms_modes_are_equal(current_crtc->mode, connector->modes[mode_index]); } void mgg::RealKMSOutput::clear_crtc() @@ -394,21 +408,6 @@ void mgg::RealKMSOutput::refresh_hardware_state() namespace { - -bool kms_modes_are_equal(drmModeModeInfo const& info1, drmModeModeInfo const& info2) -{ - return (info1.clock == info2.clock && - info1.hdisplay == info2.hdisplay && - info1.hsync_start == info2.hsync_start && - info1.hsync_end == info2.hsync_end && - info1.htotal == info2.htotal && - info1.hskew == info2.hskew && - info1.vdisplay == info2.vdisplay && - info1.vsync_start == info2.vsync_start && - info1.vsync_end == info2.vsync_end && - info1.vtotal == info2.vtotal); -} - double calculate_vrefresh_hz(drmModeModeInfo const& mode) { if (mode.htotal == 0 || mode.vtotal == 0) diff --git a/src/platforms/gbm-kms/server/kms/real_kms_output.h b/src/platforms/gbm-kms/server/kms/real_kms_output.h index de9a24cae75..ee9286d39ab 100644 --- a/src/platforms/gbm-kms/server/kms/real_kms_output.h +++ b/src/platforms/gbm-kms/server/kms/real_kms_output.h @@ -49,7 +49,7 @@ class RealKMSOutput : public KMSOutput int max_refresh_rate() const override; bool set_crtc(FBHandle const& fb) override; - auto get_rectangle() -> mir::geometry::Rectangle override; + bool has_crtc_mismatch() override; void clear_crtc() override; bool schedule_page_flip(FBHandle const& fb) override; void wait_for_page_flip() override; diff --git a/tests/unit-tests/platforms/gbm-kms/kms/mock_kms_output.h b/tests/unit-tests/platforms/gbm-kms/kms/mock_kms_output.h index 8db9b888672..d457d465b36 100644 --- a/tests/unit-tests/platforms/gbm-kms/kms/mock_kms_output.h +++ b/tests/unit-tests/platforms/gbm-kms/kms/mock_kms_output.h @@ -39,7 +39,7 @@ struct MockKMSOutput : public graphics::gbm::KMSOutput return set_crtc_thunk(&fb); } - MOCK_METHOD0(get_rectangle, geometry::Rectangle()); + MOCK_METHOD0(has_crtc_mismatch, bool()); MOCK_METHOD1(set_crtc_thunk, bool(graphics::gbm::FBHandle const*)); MOCK_METHOD0(clear_crtc, void());