Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wlr-screencopy-v1: send .damage event when required #2469

Merged
merged 3 commits into from Jun 14, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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);
}