pixman-renderer: track damage in weston_renderbuffer

Add a damage region to struct weston_renderbuffer and use it to replace
the previous_damage tracking in the drm backend.

Keep renderbuffers on a list in struct pixman_output_state and use it
to accumulate damage on all renderbuffers during repaint_output.
Now renderbuffers have to be created when pixman output state already
exists.
Reorder renderer output state and renderbuffer creation accordingly.

With this, pixman_renderer_output_set_hw_extra_damage() can be removed.

This can not yet replace the external damage tracking in the VNC
backend, which needsto know the accumulated damage that is not returned
from repaint_output.

Signed-off-by: Philipp Zabel <philipp.zabel@gmail.com>
This commit is contained in:
Philipp Zabel 2023-01-11 23:34:39 +01:00 committed by Daniel Stone
parent 6757bae0f3
commit 4d96635a3f
7 changed files with 50 additions and 54 deletions

View file

@ -595,7 +595,6 @@ struct drm_output {
struct drm_fb *dumb[2];
struct weston_renderbuffer *renderbuffer[2];
int current_image;
pixman_region32_t previous_damage;
struct vaapi_recorder *recorder;
struct wl_listener recorder_frame_listener;

View file

@ -343,14 +343,9 @@ drm_output_render_pixman(struct drm_output_state *state,
output->current_image ^= 1;
pixman_renderer_output_set_hw_extra_damage(&output->base,
&output->previous_damage);
ec->renderer->repaint_output(&output->base, damage,
output->renderbuffer[output->current_image]);
pixman_region32_copy(&output->previous_damage, damage);
return drm_fb_ref(output->dumb[output->current_image]);
}
@ -1203,6 +1198,9 @@ drm_output_init_pixman(struct drm_output *output, struct drm_backend *b)
return -1;
}
if (pixman->output_create(&output->base, &options) < 0)
goto err;
/* FIXME error checking */
for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
output->dumb[i] = drm_fb_create_dumb(device, w, h, format);
@ -1216,17 +1214,16 @@ drm_output_init_pixman(struct drm_output *output, struct drm_backend *b)
output->dumb[i]->strides[0]);
if (!output->renderbuffer[i])
goto err;
}
if (pixman->output_create(&output->base, &options) < 0)
goto err;
pixman_region32_init_rect(&output->renderbuffer[i]->damage,
output->base.x, output->base.y,
output->base.width,
output->base.height);
}
weston_log("DRM: output %s %s shadow framebuffer.\n", output->base.name,
b->use_pixman_shadow ? "uses" : "does not use");
pixman_region32_init_rect(&output->previous_damage,
output->base.x, output->base.y, output->base.width, output->base.height);
return 0;
err:
@ -1239,6 +1236,7 @@ err:
output->dumb[i] = NULL;
output->renderbuffer[i] = NULL;
}
pixman->output_destroy(&output->base);
return -1;
}
@ -1258,15 +1256,14 @@ drm_output_fini_pixman(struct drm_output *output)
drm_plane_reset_state(output->scanout_plane);
}
renderer->pixman->output_destroy(&output->base);
pixman_region32_fini(&output->previous_damage);
for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
renderer->pixman->renderbuffer_destroy(output->renderbuffer[i]);
drm_fb_unref(output->dumb[i]);
output->dumb[i] = NULL;
output->renderbuffer[i] = NULL;
}
renderer->pixman->output_destroy(&output->base);
}
static void

View file

@ -192,8 +192,8 @@ headless_output_disable_pixman(struct headless_output *output)
{
struct weston_renderer *renderer = output->base.compositor->renderer;
renderer->pixman->output_destroy(&output->base);
renderer->pixman->renderbuffer_destroy(output->renderbuffer);
renderer->pixman->output_destroy(&output->base);
}
static int
@ -306,15 +306,15 @@ headless_output_enable_pixman(struct headless_output *output)
pixman = output->base.compositor->renderer->pixman;
pfmt = pixel_format_get_info(headless_formats[0]);
if (pixman->output_create(&output->base, &options) < 0)
return -1;
output->renderbuffer =
pixman->create_image_no_clear(&output->base,
pfmt->pixman_format,
output->base.current_mode->width,
output->base.current_mode->height);
if (!output->renderbuffer)
return -1;
if (pixman->output_create(&output->base, &options) < 0)
goto err_renderer;
weston_output_update_capture_info(&output->base,
@ -326,7 +326,7 @@ headless_output_enable_pixman(struct headless_output *output)
return 0;
err_renderer:
pixman->renderbuffer_destroy(output->renderbuffer);
pixman->output_destroy(&output->base);
return -1;
}

View file

@ -481,6 +481,10 @@ rdp_output_enable(struct weston_output *base)
b = output->backend;
if (renderer->pixman->output_create(&output->base, &options) < 0) {
return -1;
}
output->renderbuffer =
pixman->create_image_from_ptr(&output->base, PIXMAN_x8r8g8b8,
output->base.current_mode->width,
@ -489,11 +493,7 @@ rdp_output_enable(struct weston_output *base)
output->base.current_mode->width * 4);
if (output->renderbuffer == NULL) {
weston_log("Failed to create surface for frame buffer.\n");
return -1;
}
if (renderer->pixman->output_create(&output->base, &options) < 0) {
renderer->pixman->renderbuffer_destroy(output->renderbuffer);
renderer->pixman->output_destroy(&output->base);
return -1;
}

View file

@ -48,6 +48,8 @@
struct weston_renderbuffer {
pixman_image_t *image;
pixman_region32_t damage;
struct wl_list link;
};
struct weston_renderer_options {

View file

@ -48,8 +48,8 @@ struct pixman_output_state {
const struct pixel_format_info *shadow_format;
pixman_image_t *hw_buffer;
const struct pixel_format_info *hw_format;
pixman_region32_t *hw_extra_damage;
struct weston_size fb_size;
struct wl_list renderbuffer_list;
};
struct pixman_surface_state {
@ -627,7 +627,7 @@ pixman_renderer_repaint_output(struct weston_output *output,
struct weston_renderbuffer *renderbuffer)
{
struct pixman_output_state *po = get_output_state(output);
pixman_region32_t hw_damage;
struct weston_renderbuffer *rb;
assert(renderbuffer);
@ -636,33 +636,26 @@ pixman_renderer_repaint_output(struct weston_output *output,
assert(output->from_blend_to_output_by_backend ||
output->color_outcome->from_blend_to_output == NULL);
if (!po->hw_buffer) {
po->hw_extra_damage = NULL;
if (!po->hw_buffer)
return;
}
pixman_region32_init(&hw_damage);
if (po->hw_extra_damage) {
pixman_region32_union(&hw_damage,
po->hw_extra_damage, output_damage);
po->hw_extra_damage = NULL;
} else {
pixman_region32_copy(&hw_damage, output_damage);
}
/* Accumulate damage in all renderbuffers */
wl_list_for_each(rb, &po->renderbuffer_list, link)
pixman_region32_union(&rb->damage, &rb->damage, output_damage);
if (po->shadow_image) {
repaint_surfaces(output, output_damage);
pixman_renderer_do_capture_tasks(output,
WESTON_OUTPUT_CAPTURE_SOURCE_BLENDING,
po->shadow_image, po->shadow_format);
copy_to_hw_buffer(output, &hw_damage);
copy_to_hw_buffer(output, &renderbuffer->damage);
} else {
repaint_surfaces(output, &hw_damage);
repaint_surfaces(output, &renderbuffer->damage);
}
pixman_renderer_do_capture_tasks(output,
WESTON_OUTPUT_CAPTURE_SOURCE_FRAMEBUFFER,
po->hw_buffer, po->hw_format);
pixman_region32_fini(&hw_damage);
pixman_region32_clear(&renderbuffer->damage);
wl_signal_emit(&output->frame_signal, output_damage);
@ -1063,15 +1056,6 @@ pixman_renderer_output_set_buffer(struct weston_output *output,
po->hw_format);
}
WL_EXPORT void
pixman_renderer_output_set_hw_extra_damage(struct weston_output *output,
pixman_region32_t *extra_damage)
{
struct pixman_output_state *po = get_output_state(output);
po->hw_extra_damage = extra_damage;
}
static int
pixman_renderer_output_create(struct weston_output *output,
const struct pixman_renderer_output_options *options)
@ -1099,6 +1083,8 @@ pixman_renderer_output_create(struct weston_output *output,
return -1;
}
wl_list_init(&po->renderbuffer_list);
return 0;
}
@ -1116,6 +1102,8 @@ pixman_renderer_output_destroy(struct weston_output *output)
po->shadow_image = NULL;
po->hw_buffer = NULL;
assert(wl_list_empty(&po->renderbuffer_list));
free(po);
}
@ -1124,8 +1112,11 @@ pixman_renderer_create_image_from_ptr(struct weston_output *output,
pixman_format_code_t format, int width,
int height, uint32_t *ptr, int rowstride)
{
struct pixman_output_state *po = get_output_state(output);
struct weston_renderbuffer *renderbuffer;
assert(po);
renderbuffer = xzalloc(sizeof(*renderbuffer));
renderbuffer->image = pixman_image_create_bits(format, width, height,
@ -1135,6 +1126,9 @@ pixman_renderer_create_image_from_ptr(struct weston_output *output,
return NULL;
}
pixman_region32_init(&renderbuffer->damage);
wl_list_insert(&po->renderbuffer_list, &renderbuffer->link);
return renderbuffer;
}
@ -1143,8 +1137,11 @@ pixman_renderer_create_image_no_clear(struct weston_output *output,
pixman_format_code_t format, int width,
int height)
{
struct pixman_output_state *po = get_output_state(output);
struct weston_renderbuffer *renderbuffer;
assert(po);
renderbuffer = xzalloc(sizeof(*renderbuffer));
renderbuffer->image =
@ -1155,13 +1152,18 @@ pixman_renderer_create_image_no_clear(struct weston_output *output,
return NULL;
}
pixman_region32_init(&renderbuffer->damage);
wl_list_insert(&po->renderbuffer_list, &renderbuffer->link);
return renderbuffer;
}
static void
pixman_renderer_renderbuffer_destroy(struct weston_renderbuffer *renderbuffer)
{
wl_list_remove(&renderbuffer->link);
pixman_image_unref(renderbuffer->image);
pixman_region32_fini(&renderbuffer->damage);
free(renderbuffer);
}

View file

@ -40,10 +40,6 @@ struct pixman_renderer_output_options {
struct weston_size fb_size;
};
void
pixman_renderer_output_set_hw_extra_damage(struct weston_output *output,
pixman_region32_t *extra_damage);
struct pixman_renderer_interface {
int (*output_create)(struct weston_output *output,
const struct pixman_renderer_output_options *options);