From 177eef63df4a641e2ef68be4f3d97cf7c60a8aae Mon Sep 17 00:00:00 2001 From: Roman Gilg Date: Sat, 24 Feb 2024 10:49:55 +0100 Subject: [PATCH 1/2] refactor: use wlr_output_state API The old API has been removed from wlroots master. We guard the changes by the WLR_HAVE_NEW_PIXEL_COPY_API flag, that we reuse, so that we still maintain support for current old wlroots release. --- autotests/integration/layer_shell.cpp | 8 ++ autotests/integration/lib/setup.cpp | 16 +++ como/base/backend/wlroots/events.h | 14 ++ como/base/backend/wlroots/output.h | 126 +++++++++++++++++- como/render/backend/wlroots/egl_backend.h | 19 ++- como/render/backend/wlroots/egl_output.h | 15 +++ como/render/backend/wlroots/qpainter_output.h | 29 +++- 7 files changed, 211 insertions(+), 16 deletions(-) diff --git a/autotests/integration/layer_shell.cpp b/autotests/integration/layer_shell.cpp index 732a45d1d..482e6fd82 100644 --- a/autotests/integration/layer_shell.cpp +++ b/autotests/integration/layer_shell.cpp @@ -285,7 +285,15 @@ TEST_CASE("layer shell", "[win]") auto const output_geo = QRect(2000, 0, 1000, 500); auto wlr_out = wlr_headless_add_output( setup.base->backend.native, output_geo.width(), output_geo.height()); + +#if WLR_HAVE_NEW_PIXEL_COPY_API + wlr_output_state wlr_out_state; + wlr_output_state_init(&wlr_out_state); + wlr_output_state_set_enabled(&wlr_out_state, true); + wlr_output_commit_state(wlr_out, &wlr_out_state); +#else wlr_output_enable(wlr_out, true); +#endif QCOMPARE(setup.base->outputs.size(), 3); setup.base->all_outputs.back()->force_geometry(output_geo); diff --git a/autotests/integration/lib/setup.cpp b/autotests/integration/lib/setup.cpp index 4122ee245..1da264f99 100644 --- a/autotests/integration/lib/setup.cpp +++ b/autotests/integration/lib/setup.cpp @@ -80,7 +80,15 @@ setup::setup(std::string const& test_name, auto headless_backend = base::backend::wlroots::get_headless_backend(base->backend.native); auto out = wlr_headless_add_output(headless_backend, 1280, 1024); + +#if WLR_HAVE_NEW_PIXEL_COPY_API + wlr_output_state wlr_out_state; + wlr_output_state_init(&wlr_out_state); + wlr_output_state_set_enabled(&wlr_out_state, true); + wlr_output_commit_state(out, &wlr_out_state); +#else wlr_output_enable(out, true); +#endif try { base->mod.render = std::make_unique(*base); @@ -187,7 +195,15 @@ void setup::set_outputs(std::vector const& outputs) auto const size = output.geometry.size() * output.scale; auto out = wlr_headless_add_output(base->backend.native, size.width(), size.height()); + +#if WLR_HAVE_NEW_PIXEL_COPY_API + wlr_output_state wlr_out_state; + wlr_output_state_init(&wlr_out_state); + wlr_output_state_set_enabled(&wlr_out_state, true); + wlr_output_commit_state(out, &wlr_out_state); +#else wlr_output_enable(out, true); +#endif base->all_outputs.back()->force_geometry(output.geometry); } diff --git a/como/base/backend/wlroots/events.h b/como/base/backend/wlroots/events.h index 6f9da8f72..1df09b465 100644 --- a/como/base/backend/wlroots/events.h +++ b/como/base/backend/wlroots/events.h @@ -31,6 +31,19 @@ void add_new_output(Backend& backend, wlr_output* native) if (!wl_list_empty(&native->modes)) { auto mode = wlr_output_preferred_mode(native); +#if WLR_HAVE_NEW_PIXEL_COPY_API + wlr_output_state state; + wlr_output_state_init(&state); + wlr_output_state_set_mode(&state, mode); + wlr_output_state_set_enabled(&state, true); + + if (!wlr_output_test_state(native, &state)) { + throw std::runtime_error("wlr_output_test_state failed"); + } + if (!wlr_output_commit_state(native, &state)) { + throw std::runtime_error("wlr_output_commit_state failed"); + } +#else wlr_output_set_mode(native, mode); wlr_output_enable(native, true); if (!wlr_output_test(native)) { @@ -39,6 +52,7 @@ void add_new_output(Backend& backend, wlr_output* native) if (!wlr_output_commit(native)) { throw std::runtime_error("wlr_output_commit failed"); } +#endif } auto output = new wlroots::output(native, &backend); diff --git a/como/base/backend/wlroots/output.h b/como/base/backend/wlroots/output.h index 4236aea2e..43f027c86 100644 --- a/como/base/backend/wlroots/output.h +++ b/como/base/backend/wlroots/output.h @@ -19,6 +19,32 @@ extern "C" { namespace como::base::backend::wlroots { +#if WLR_HAVE_NEW_PIXEL_COPY_API +struct output_state { + output_state() + : native{std::make_unique()} + { + wlr_output_state_init(native.get()); + } + ~output_state() + { + wlr_output_state_finish(native.get()); + } + output_state(output_state const&) = delete; + output_state& operator=(output_state const&) = delete; + output_state(output_state&&) = default; + output_state& operator=(output_state&&) = default; + + wlr_output_state* get_native() const + { + return native.get(); + } + +private: + std::unique_ptr native; +}; +#endif + template void output_handle_destroy(wl_listener* listener, void* /*data*/) { @@ -117,6 +143,78 @@ class output : public base::wayland::output } } + int gamma_ramp_size() const override + { + return wlr_output_get_gamma_size(native); + } + +#if WLR_HAVE_NEW_PIXEL_COPY_API + void update_dpms(base::dpms_mode mode) override + { + output_state state; + wlr_output_state_set_enabled(state.get_native(), true); + + if (mode == base::dpms_mode::on) { + wlr_output_commit_state(native, state.get_native()); + wayland::output_set_dpms_on(*this, *backend->frontend); + return; + } + + if (!wlr_output_test_state(native, state.get_native())) { + qCWarning(KWIN_CORE) << "Failed test commit on disabling output for DPMS."; + return; + } + + get_render(this->render)->disable(); + wlr_output_commit_state(native, state.get_native()); + wayland::output_set_dmps_off(mode, *this, *backend->frontend); + } + + bool change_backend_state(Wrapland::Server::output_state const& state) override + { + auto wrapper_state = std::make_unique(); + wlr_output_state_set_enabled(wrapper_state->get_native(), state.enabled); + + if (state.enabled) { + set_native_mode(*native, *wrapper_state, state.mode.id); + wlr_output_state_set_transform(wrapper_state->get_native(), + static_cast(state.transform)); + wlr_output_state_set_adaptive_sync_enabled(wrapper_state->get_native(), + state.adaptive_sync); + } + + if (!wlr_output_test_state(native, wrapper_state->get_native())) { + return false; + } + + next_state = std::move(wrapper_state); + return true; + } + + bool set_gamma_ramp(gamma_ramp const& gamma) override + { + output_state state; + wlr_output_state_set_gamma_lut( + state.get_native(), gamma.size(), gamma.red(), gamma.green(), gamma.blue()); + + if (!wlr_output_test_state(native, state.get_native())) { + qCWarning(KWIN_CORE) << "Failed test commit on set gamma ramp call."; + return false; + } + if (!wlr_output_commit_state(native, state.get_native())) { + qCWarning(KWIN_CORE) << "Failed commit on set gamma ramp call."; + return false; + } + return true; + } + + void ensure_next_state() + { + if (!next_state) { + next_state = std::make_unique(); + } + } +#else void update_dpms(base::dpms_mode mode) override { auto set_on = mode == base::dpms_mode::on; @@ -152,11 +250,6 @@ class output : public base::wayland::output return wlr_output_test(native); } - int gamma_ramp_size() const override - { - return wlr_output_get_gamma_size(native); - } - bool set_gamma_ramp(gamma_ramp const& gamma) override { wlr_output_set_gamma(native, gamma.size(), gamma.red(), gamma.green(), gamma.blue()); @@ -168,13 +261,35 @@ class output : public base::wayland::output } return true; } +#endif wlr_output* native; +#if WLR_HAVE_NEW_PIXEL_COPY_API + std::unique_ptr next_state; +#endif Backend* backend; private: base::event_receiver destroy_rec; +#if WLR_HAVE_NEW_PIXEL_COPY_API + static void set_native_mode(wlr_output const& output, output_state& state, int mode_index) + { + // TODO(romangg): Determine target mode more precisly with semantic properties instead of + // index. + wlr_output_mode* wlr_mode; + auto count = 0; + + wl_list_for_each(wlr_mode, &output.modes, link) + { + if (count == mode_index) { + wlr_output_state_set_mode(state.get_native(), wlr_mode); + return; + } + count++; + } + } +#else void set_native_mode(wlr_output* output, int mode_index) { // TODO(romangg): Determine target mode more precisly with semantic properties instead of @@ -191,6 +306,7 @@ class output : public base::wayland::output count++; } } +#endif template render_t* get_render(std::unique_ptr& output) diff --git a/como/render/backend/wlroots/egl_backend.h b/como/render/backend/wlroots/egl_backend.h index 00ad67da5..0576e7bb3 100644 --- a/como/render/backend/wlroots/egl_backend.h +++ b/como/render/backend/wlroots/egl_backend.h @@ -152,9 +152,11 @@ class egl_backend : public gl::backend(output_impl).ensure_next_state(); + assert(!current_render_pass); current_render_pass = wlr_output_begin_render_pass( - native_out, &native_out->pending, &out->bufferAge, nullptr); + native_out, output_impl.next_state->get_native(), &out->bufferAge, nullptr); #else wlr_output_attach_render(native_out, &out->bufferAge); wlr_renderer_begin(backend.renderer, viewport.width(), viewport.height()); @@ -176,10 +178,11 @@ class egl_backend : public gl::backendpending.buffer), - res, - viewport); + native_fbo + = GLFramebuffer(wlr_gles2_renderer_get_buffer_fbo( + backend.renderer, output_impl.next_state->get_native()->buffer), + res, + viewport); #else native_fbo = GLFramebuffer(wlr_gles2_renderer_get_current_fbo(backend.renderer), res, viewport); @@ -252,7 +255,9 @@ class egl_backend : public gl::backendnative); +#endif return; } @@ -321,7 +326,11 @@ class egl_backend : public gl::backendnative->transform); wlr_region_transform(&damage, &damage, transform, width, height); +#if WLR_HAVE_NEW_PIXEL_COPY_API + wlr_output_state_set_damage(output->next_state->get_native(), &damage); +#else wlr_output_set_damage(output->native, &damage); +#endif pixman_region32_fini(&damage); } diff --git a/como/render/backend/wlroots/egl_output.h b/como/render/backend/wlroots/egl_output.h index 7ad07c219..da1160946 100644 --- a/como/render/backend/wlroots/egl_output.h +++ b/como/render/backend/wlroots/egl_output.h @@ -61,6 +61,20 @@ class egl_output auto& base = static_cast(out->base); out->swap_pending = true; +#if WLR_HAVE_NEW_PIXEL_COPY_API + if (!wlr_output_test_state(base.native, base.next_state->get_native())) { + qCWarning(KWIN_CORE) << "Atomic output test failed on present."; + base.next_state.reset(); + return false; + } + if (!wlr_output_commit_state(base.native, base.next_state->get_native())) { + qCWarning(KWIN_CORE) << "Atomic output commit failed on present."; + base.next_state.reset(); + return false; + } + + base.next_state.reset(); +#else if (!base.native->enabled) { wlr_output_enable(base.native, true); } @@ -74,6 +88,7 @@ class egl_output qCWarning(KWIN_CORE) << "Atomic output commit failed on present."; return false; } +#endif return true; } diff --git a/como/render/backend/wlroots/qpainter_output.h b/como/render/backend/wlroots/qpainter_output.h index bc0216823..511739431 100644 --- a/como/render/backend/wlroots/qpainter_output.h +++ b/como/render/backend/wlroots/qpainter_output.h @@ -34,14 +34,16 @@ class qpainter_output void begin_render() { - auto native_out = static_cast(output.base).native; - + auto& output_base_impl = static_cast(output.base); + auto native_out = output_base_impl.native; auto const size = output.base.geometry().size(); #if WLR_HAVE_NEW_PIXEL_COPY_API + output_base_impl.ensure_next_state(); + assert(!current_render_pass); - current_render_pass - = wlr_output_begin_render_pass(native_out, &native_out->pending, nullptr, nullptr); + current_render_pass = wlr_output_begin_render_pass( + native_out, output_base_impl.next_state->get_native(), nullptr, nullptr); #else wlr_output_attach_render(native_out, nullptr); wlr_renderer_begin(renderer, size.width(), size.height()); @@ -49,7 +51,8 @@ class qpainter_output if (!buffer || size != buffer->size()) { #if WLR_HAVE_NEW_PIXEL_COPY_API - auto img = wlr_pixman_renderer_get_buffer_image(renderer, native_out->pending.buffer); + auto img = wlr_pixman_renderer_get_buffer_image( + renderer, output_base_impl.next_state->get_native()->buffer); #else auto img = wlr_pixman_renderer_get_current_image(renderer); #endif @@ -71,7 +74,7 @@ class qpainter_output #if WLR_HAVE_NEW_PIXEL_COPY_API auto pixman_data = pixman_image_get_data( - wlr_pixman_renderer_get_buffer_image(renderer, base.native->pending.buffer)); + wlr_pixman_renderer_get_buffer_image(renderer, base.next_state->get_native()->buffer)); #else auto pixman_data = pixman_image_get_data(wlr_pixman_renderer_get_current_image(renderer)); #endif @@ -86,6 +89,19 @@ class qpainter_output output.swap_pending = true; +#if WLR_HAVE_NEW_PIXEL_COPY_API + wlr_output_state_set_enabled(base.next_state->get_native(), true); + + if (!wlr_output_test_state(base.native, base.next_state->get_native())) { + qCWarning(KWIN_CORE) << "Atomic output test failed on present."; + base.next_state.reset(); + return; + } + if (!wlr_output_commit_state(base.native, base.next_state->get_native())) { + qCWarning(KWIN_CORE) << "Atomic output commit failed on present."; + } + base.next_state.reset(); +#else if (!base.native->enabled) { wlr_output_enable(base.native, true); } @@ -99,6 +115,7 @@ class qpainter_output qCWarning(KWIN_CORE) << "Atomic output commit failed on present."; return; } +#endif } Output& output; From f232205b34fe85d633cb02c1c4d4c35742091b79 Mon Sep 17 00:00:00 2001 From: Roman Gilg Date: Sun, 25 Feb 2024 19:27:20 +0100 Subject: [PATCH 2/2] refactor: get wlroots backend with wl_event_loop On wlroots master the argument has changd. --- CMakeLists.txt | 1 + como/base/backend/wlroots/backend.h | 9 +++++++++ como/base/config-como.h.cmake | 1 + 3 files changed, 11 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index d487792a4..1dbebd6d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -218,6 +218,7 @@ if (${wlroots_VERSION} VERSION_GREATER_EQUAL 0.18) set(WLR_HAVE_SESSION_CREATE_LOOP 1) set(WLR_HAVE_UTIL_TRANSFORM_HEADER 1) set(WLR_HAVE_NEW_PIXEL_COPY_API 1) + set(WLR_HAVE_BACKEND_CREATE_WITH_LOOP 1) endif() find_package(X11) diff --git a/como/base/backend/wlroots/backend.h b/como/base/backend/wlroots/backend.h index 66866541e..1a4441c7c 100644 --- a/como/base/backend/wlroots/backend.h +++ b/como/base/backend/wlroots/backend.h @@ -48,11 +48,20 @@ class backend // TODO(romangg): Make this dependent on KWIN_CORE debug verbosity. wlr_log_init(WLR_DEBUG, nullptr); +#if WLR_HAVE_BACKEND_CREATE_WITH_LOOP + auto wlloop = wl_display_get_event_loop(frontend.server->display->native()); + if (headless) { + native = wlr_headless_backend_create(wlloop); + } else { + native = wlr_backend_autocreate(wlloop, &wlroots_session); + } +#else if (headless) { native = wlr_headless_backend_create(frontend.server->display->native()); } else { native = wlr_backend_autocreate(frontend.server->display->native(), &wlroots_session); } +#endif destroyed->receiver = this; destroyed->event.notify = handle_destroy; diff --git a/como/base/config-como.h.cmake b/como/base/config-como.h.cmake index 6ab9de510..0366fc4c8 100644 --- a/como/base/config-como.h.cmake +++ b/como/base/config-como.h.cmake @@ -19,6 +19,7 @@ #cmakedefine01 WLR_HAVE_SESSION_CREATE_LOOP #cmakedefine01 WLR_HAVE_UTIL_TRANSFORM_HEADER #cmakedefine01 WLR_HAVE_NEW_PIXEL_COPY_API +#cmakedefine01 WLR_HAVE_BACKEND_CREATE_WITH_LOOP #if HAVE_BREEZE_DECO #define BREEZE_KDECORATION_PLUGIN_ID "${BREEZE_KDECORATION_PLUGIN_ID}"