mirror of
https://github.com/hyprwm/xdg-desktop-portal-hyprland.git
synced 2024-12-26 03:19:48 +01:00
screencast: send damage via pw
This commit is contained in:
parent
7fc2e78581
commit
a7b7880172
4 changed files with 75 additions and 10 deletions
|
@ -63,7 +63,8 @@ struct xdpw_frame {
|
|||
bool y_invert;
|
||||
uint64_t tv_sec;
|
||||
uint32_t tv_nsec;
|
||||
struct xdpw_frame_damage damage;
|
||||
struct xdpw_frame_damage damage[4];
|
||||
uint32_t damage_count;
|
||||
struct xdpw_buffer *xdpw_buffer;
|
||||
struct pw_buffer *pw_buffer;
|
||||
};
|
||||
|
@ -228,6 +229,8 @@ uint32_t xdpw_format_drm_fourcc_from_wl_shm(enum wl_shm_format format);
|
|||
enum spa_video_format xdpw_format_pw_from_drm_fourcc(uint32_t format);
|
||||
enum spa_video_format xdpw_format_pw_strip_alpha(enum spa_video_format format);
|
||||
|
||||
struct xdpw_frame_damage merge_damage(struct xdpw_frame_damage *damage1, struct xdpw_frame_damage *damage2);
|
||||
|
||||
enum xdpw_chooser_types get_chooser_type(const char *chooser_type);
|
||||
const char *chooser_type_str(enum xdpw_chooser_types chooser_type);
|
||||
#endif /* SCREENCAST_COMMON_H */
|
||||
|
|
|
@ -316,9 +316,18 @@ fixate_format:
|
|||
SPA_PARAM_META_type, SPA_POD_Id(SPA_META_Header),
|
||||
SPA_PARAM_META_size, SPA_POD_Int(sizeof(struct spa_meta_header)));
|
||||
|
||||
pw_stream_update_params(stream, params, 2);
|
||||
params[2] = spa_pod_builder_add_object(&b[2].b,
|
||||
SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
|
||||
SPA_PARAM_META_type, SPA_POD_Id(SPA_META_VideoDamage),
|
||||
SPA_PARAM_META_size, SPA_POD_CHOICE_RANGE_Int(
|
||||
sizeof(struct spa_meta_region) * 4,
|
||||
sizeof(struct spa_meta_region) * 1,
|
||||
sizeof(struct spa_meta_region) * 4));
|
||||
|
||||
pw_stream_update_params(stream, params, 3);
|
||||
spa_pod_dynamic_builder_clean(&b[0]);
|
||||
spa_pod_dynamic_builder_clean(&b[1]);
|
||||
spa_pod_dynamic_builder_clean(&b[2]);
|
||||
}
|
||||
|
||||
static void pwr_handle_stream_add_buffer(void *data, struct pw_buffer *buffer) {
|
||||
|
@ -438,6 +447,38 @@ void xdpw_pwr_enqueue_buffer(struct xdpw_screencast_instance *cast) {
|
|||
logprint(TRACE, "pipewire: timestamp %"PRId64, h->pts);
|
||||
}
|
||||
|
||||
struct spa_meta *damage;
|
||||
if ((damage = spa_buffer_find_meta(spa_buf, SPA_META_VideoDamage))) {
|
||||
struct spa_region *d_region = spa_meta_first(damage);
|
||||
uint32_t damage_counter = 0;
|
||||
do {
|
||||
if (damage_counter >= cast->current_frame.damage_count) {
|
||||
*d_region = SPA_REGION(0, 0, 0, 0);
|
||||
logprint(TRACE, "pipewire: end damage %u %u,%u (%ux%u)", damage_counter,
|
||||
d_region->position.x, d_region->position.y, d_region->size.width, d_region->size.height);
|
||||
break;
|
||||
}
|
||||
*d_region = SPA_REGION(cast->current_frame.damage[damage_counter].x,
|
||||
cast->current_frame.damage[damage_counter].y,
|
||||
cast->current_frame.damage[damage_counter].width,
|
||||
cast->current_frame.damage[damage_counter].height);
|
||||
logprint(TRACE, "pipewire: damage %u %u,%u (%ux%u)", damage_counter,
|
||||
d_region->position.x, d_region->position.y, d_region->size.width, d_region->size.height);
|
||||
damage_counter++;
|
||||
} while (spa_meta_check(d_region + 1, damage) && d_region++);
|
||||
|
||||
if (damage_counter < cast->current_frame.damage_count) {
|
||||
struct xdpw_frame_damage damage =
|
||||
{d_region->position.x, d_region->position.x, d_region->size.width, d_region->size.height};
|
||||
for (; damage_counter < cast->current_frame.damage_count; damage_counter++) {
|
||||
damage = merge_damage(&damage, &cast->current_frame.damage[damage_counter]);
|
||||
}
|
||||
*d_region = SPA_REGION(damage.x, damage.y, damage.width, damage.height);
|
||||
logprint(TRACE, "pipewire: collected damage %u %u,%u (%ux%u)", damage_counter,
|
||||
d_region->position.x, d_region->position.y, d_region->size.width, d_region->size.height);
|
||||
}
|
||||
}
|
||||
|
||||
if (buffer_corrupt) {
|
||||
for (uint32_t plane = 0; plane < spa_buf->n_datas; plane++) {
|
||||
d[plane].chunk->flags = SPA_CHUNK_FLAG_CORRUPTED;
|
||||
|
|
|
@ -410,3 +410,17 @@ const char *chooser_type_str(enum xdpw_chooser_types chooser_type) {
|
|||
fprintf(stderr, "Could not find chooser type %d\n", chooser_type);
|
||||
abort();
|
||||
}
|
||||
|
||||
struct xdpw_frame_damage merge_damage(struct xdpw_frame_damage *damage1, struct xdpw_frame_damage *damage2) {
|
||||
struct xdpw_frame_damage damage;
|
||||
uint32_t x0, y0;
|
||||
damage.x = damage1->x < damage2->y ? damage1->x : damage2->x;
|
||||
damage.y = damage1->y < damage2->y ? damage1->y : damage2->y;
|
||||
|
||||
x0 = damage1->x + damage1->width < damage2->x + damage2->width ? damage2->x + damage2->width : damage1->x + damage1->width;
|
||||
y0 = damage1->y + damage1->height < damage2->y + damage2->height ? damage2->y + damage2->height : damage1->y + damage1->height;
|
||||
damage.width = x0 - damage.x;
|
||||
damage.height = y0 - damage.y;
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
|
|
@ -284,6 +284,7 @@ static void wlr_frame_buffer_done(void *data, struct zwlr_screencopy_frame_v1 *f
|
|||
return;
|
||||
}
|
||||
|
||||
cast->current_frame.damage_count = 0;
|
||||
zwlr_screencopy_frame_v1_copy_with_damage(frame, cast->current_frame.xdpw_buffer->buffer);
|
||||
logprint(TRACE, "wlroots: frame copied");
|
||||
|
||||
|
@ -308,10 +309,13 @@ static void wlr_frame_damage(void *data, struct zwlr_screencopy_frame_v1 *frame,
|
|||
|
||||
logprint(TRACE, "wlroots: damage event handler");
|
||||
|
||||
cast->current_frame.damage.x = x;
|
||||
cast->current_frame.damage.y = y;
|
||||
cast->current_frame.damage.width = width;
|
||||
cast->current_frame.damage.height = height;
|
||||
logprint(TRACE, "wlroots: damage %"PRIu32": %"PRIu32",%"PRIu32"x%"PRIu32",%"PRIu32, cast->current_frame.damage_count, x, y, width, height);
|
||||
struct xdpw_frame_damage damage = {x, y, width, height};
|
||||
if (cast->current_frame.damage_count < 4) {
|
||||
cast->current_frame.damage[cast->current_frame.damage_count++] = damage;
|
||||
} else {
|
||||
cast->current_frame.damage[3] = merge_damage(&cast->current_frame.damage[3], &damage);
|
||||
}
|
||||
}
|
||||
|
||||
static void wlr_frame_ready(void *data, struct zwlr_screencopy_frame_v1 *frame, uint32_t tv_sec_hi, uint32_t tv_sec_lo, uint32_t tv_nsec) {
|
||||
|
@ -463,10 +467,13 @@ static void hyprland_frame_damage(void *data, struct hyprland_toplevel_export_fr
|
|||
|
||||
logprint(TRACE, "hyprland: damage event handler");
|
||||
|
||||
cast->current_frame.damage.x = x;
|
||||
cast->current_frame.damage.y = y;
|
||||
cast->current_frame.damage.width = width;
|
||||
cast->current_frame.damage.height = height;
|
||||
logprint(TRACE, "hyprland: damage %"PRIu32": %"PRIu32",%"PRIu32"x%"PRIu32",%"PRIu32, cast->current_frame.damage_count, x, y, width, height);
|
||||
struct xdpw_frame_damage damage = {x, y, width, height};
|
||||
if (cast->current_frame.damage_count < 4) {
|
||||
cast->current_frame.damage[cast->current_frame.damage_count++] = damage;
|
||||
} else {
|
||||
cast->current_frame.damage[3] = merge_damage(&cast->current_frame.damage[3], &damage);
|
||||
}
|
||||
}
|
||||
|
||||
static void hyprland_frame_ready(void *data, struct hyprland_toplevel_export_frame_v1 *frame, uint32_t tv_sec_hi, uint32_t tv_sec_lo,
|
||||
|
|
Loading…
Reference in a new issue