Skip to content

Commit

Permalink
Adding a check for a crtc mismatch instead of just rectangle comparing
Browse files Browse the repository at this point in the history
  • Loading branch information
mattkae committed Sep 8, 2023
1 parent 6898e53 commit 804453b
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 43 deletions.
29 changes: 10 additions & 19 deletions src/platforms/gbm-kms/server/kms/display_buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<mgg::CPUAddressableFB>(
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());
Expand Down
7 changes: 6 additions & 1 deletion src/platforms/gbm-kms/server/kms/kms_output.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
41 changes: 20 additions & 21 deletions src/platforms/gbm-kms/server/kms/real_kms_output.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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]);
Expand All @@ -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()
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion src/platforms/gbm-kms/server/kms/real_kms_output.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion tests/unit-tests/platforms/gbm-kms/kms/mock_kms_output.h
Original file line number Diff line number Diff line change
Expand Up @@ -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());

Expand Down

0 comments on commit 804453b

Please sign in to comment.