Skip to content

Commit

Permalink
Merge #2469
Browse files Browse the repository at this point in the history
2469: wlr-screencopy-v1: send .damage event when required r=AlanGriffiths a=wmww

The `.copy_with_damage` request still isn't implemented fully (it does not wait for there to be damage or report the damaged area of the screen), but with this change it works well enough for wayvnc to work (albeit with higher than needed CPU load)

Co-authored-by: Sophie Winter <wm@wmww.sh>
  • Loading branch information
bors[bot] and wmww committed Jun 14, 2022
2 parents 85db055 + 1ada3ba commit d7826d3
Showing 1 changed file with 52 additions and 29 deletions.
81 changes: 52 additions & 29 deletions src/server/frontend_wayland/wlr_screencopy_v1.cpp
Expand Up @@ -62,11 +62,11 @@ class WlrScreencopyManagerV1
WlrScreencopyManagerV1(wl_resource* resource, std::shared_ptr<WlrScreencopyV1Ctx> const& ctx);

private:
void capture_output(struct wl_resource* frame, int32_t overlay_cursor, struct wl_resource* output) override;
void capture_output(wl_resource* frame, int32_t overlay_cursor, wl_resource* output) override;
void capture_output_region(
struct wl_resource* frame,
wl_resource* frame,
int32_t overlay_cursor,
struct wl_resource* output,
wl_resource* output,
int32_t x, int32_t y,
int32_t width, int32_t height) override;

Expand All @@ -83,10 +83,13 @@ class WlrScreencopyFrameV1
geometry::Rectangle const& area);

private:
void capture(wl_resource* buffer, bool send_damage);
void report_result(std::optional<time::Timestamp> captured_time, bool send_damage);

/// From wayland::WlrScreencopyFrameV1
/// @{
void copy(struct wl_resource* buffer) override;
void copy_with_damage(struct wl_resource* buffer) override;
void copy(wl_resource* buffer) override;
void copy_with_damage(wl_resource* buffer) override;
/// @}

std::shared_ptr<WlrScreencopyV1Ctx> const ctx;
Expand Down Expand Up @@ -132,19 +135,19 @@ mf::WlrScreencopyManagerV1::WlrScreencopyManagerV1(
}

void mf::WlrScreencopyManagerV1::capture_output(
struct wl_resource* frame,
wl_resource* frame,
int32_t overlay_cursor,
struct wl_resource* output)
wl_resource* output)
{
(void)overlay_cursor;
auto const extents = OutputGlobal::from_or_throw(output).current_config().extents();
new WlrScreencopyFrameV1{frame, ctx, extents};
}

void mf::WlrScreencopyManagerV1::capture_output_region(
struct wl_resource* frame,
wl_resource* frame,
int32_t overlay_cursor,
struct wl_resource* output,
wl_resource* output,
int32_t x, int32_t y,
int32_t width, int32_t height)
{
Expand All @@ -171,7 +174,7 @@ mf::WlrScreencopyFrameV1::WlrScreencopyFrameV1(
send_buffer_done_event_if_supported();
}

void mf::WlrScreencopyFrameV1::copy(struct wl_resource* buffer)
void mf::WlrScreencopyFrameV1::capture(wl_resource* buffer, bool send_damage)
{
auto const graphics_buffer = ctx->allocator->buffer_from_shm(buffer, ctx->wayland_executor, [](){});
if (graphics_buffer->pixel_format() != mir_pixel_format_argb_8888)
Expand Down Expand Up @@ -208,34 +211,54 @@ void mf::WlrScreencopyFrameV1::copy(struct wl_resource* buffer)
{
BOOST_THROW_EXCEPTION(std::logic_error("Failed to get write-mappable buffer out of Wayland SHM buffer"));
}
// TODO: if send_damage is true, do not capture until scene has changed
ctx->screen_shooter->capture(std::move(target), area,
[wayland_executor=ctx->wayland_executor, self=mw::make_weak(this)](std::optional<time::Timestamp> captured_time)
[wayland_executor=ctx->wayland_executor, send_damage, self=mw::make_weak(this)]
(std::optional<time::Timestamp> captured_time)
{
wayland_executor->spawn([self, captured_time]()
wayland_executor->spawn([self, captured_time, send_damage]()
{
if (self)
{
if (captured_time)
{
self.value().send_flags_event(Flags::y_invert);

WaylandTimespec const timespec{captured_time.value()};
self.value().send_ready_event(
timespec.tv_sec_hi,
timespec.tv_sec_lo,
timespec.tv_nsec);
}
else
{
self.value().send_failed_event();
}
self.value().report_result(captured_time, send_damage);
}
});
});
}

void mf::WlrScreencopyFrameV1::copy_with_damage(struct wl_resource* buffer)
void mf::WlrScreencopyFrameV1::report_result(std::optional<time::Timestamp> captured_time, bool send_damage)
{
if (captured_time)
{
send_flags_event(Flags::y_invert);

if (send_damage)
{
send_damage_event(
area.top_left.x.as_uint32_t(),
area.top_left.y.as_uint32_t(),
area.size.width.as_uint32_t(),
area.size.height.as_uint32_t());
}

WaylandTimespec const timespec{captured_time.value()};
send_ready_event(
timespec.tv_sec_hi,
timespec.tv_sec_lo,
timespec.tv_nsec);
}
else
{
send_failed_event();
}
}

void mf::WlrScreencopyFrameV1::copy(wl_resource* buffer)
{
capture(buffer, false);
}

void mf::WlrScreencopyFrameV1::copy_with_damage(wl_resource* buffer)
{
// TODO
copy(buffer);
capture(buffer, true);
}

0 comments on commit d7826d3

Please sign in to comment.