render/pixman: Fix source crop

Fix source crop in the pixman render backend.  It was being applied by
using a source offset as arguments to pixman_image_composite32().  But
this is wrong because the source crop should get applied before all the
other transforms, not after them (or at least this is how it works in
the other wlroots render backends).  Instead, apply the source crop as
yet another matrix transform when we're doing transforms (Or keep it the
same as previously if there's no other transforming going on).

Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3830
master
David Turner 7 months ago committed by Simon Ser
parent 061b996768
commit ee0007c0f2

@ -47,6 +47,9 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass,
return; return;
} }
pixman_op_t op = get_pixman_blending(options->blend_mode);
pixman_image_set_clip_region32(buffer->image, (pixman_region32_t *)options->clip);
struct wlr_fbox src_fbox; struct wlr_fbox src_fbox;
wlr_render_texture_options_get_src_box(options, &src_fbox); wlr_render_texture_options_get_src_box(options, &src_fbox);
struct wlr_box src_box = { struct wlr_box src_box = {
@ -71,7 +74,6 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass,
wlr_box_transform(&orig_box, &dst_box, options->transform, wlr_box_transform(&orig_box, &dst_box, options->transform,
buffer->buffer->width, buffer->buffer->height); buffer->buffer->width, buffer->buffer->height);
int32_t dest_x, dest_y, width, height;
if (options->transform != WL_OUTPUT_TRANSFORM_NORMAL || if (options->transform != WL_OUTPUT_TRANSFORM_NORMAL ||
orig_box.width != src_box.width || orig_box.width != src_box.width ||
orig_box.height != src_box.height) { orig_box.height != src_box.height) {
@ -131,23 +133,18 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass,
// corner is back at the origin. // corner is back at the origin.
pixman_transform_translate(&transform, NULL, pixman_transform_translate(&transform, NULL,
pixman_int_to_fixed(tr_x), pixman_int_to_fixed(tr_y)); pixman_int_to_fixed(tr_x), pixman_int_to_fixed(tr_y));
pixman_transform_translate(&transform, NULL, pixman_transform_translate(&transform, NULL,
-pixman_int_to_fixed(orig_box.x), -pixman_int_to_fixed(orig_box.y)); -pixman_int_to_fixed(orig_box.x), -pixman_int_to_fixed(orig_box.y));
pixman_transform_scale(&transform, NULL, pixman_transform_scale(&transform, NULL,
pixman_double_to_fixed(src_box.width / (double)orig_box.width), pixman_double_to_fixed(src_box.width / (double)orig_box.width),
pixman_double_to_fixed(src_box.height / (double)orig_box.height)); pixman_double_to_fixed(src_box.height / (double)orig_box.height));
pixman_image_set_transform(texture->image, &transform);
dest_x = dest_y = 0; // Apply the translation for source crop so the origin is now at the top-left of
width = buffer->buffer->width; // the region we're actually using. Do this last so all the other transforms
height = buffer->buffer->height; // apply on top of this.
} else { pixman_transform_translate(&transform, NULL,
pixman_image_set_transform(texture->image, NULL); pixman_int_to_fixed(src_box.x), pixman_int_to_fixed(src_box.y));
dest_x = dst_box.x;
dest_y = dst_box.y;
width = src_box.width;
height = src_box.height;
}
switch (options->filter_mode) { switch (options->filter_mode) {
case WLR_SCALE_FILTER_BILINEAR: case WLR_SCALE_FILTER_BILINEAR:
@ -158,15 +155,23 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass,
break; break;
} }
pixman_op_t op = get_pixman_blending(options->blend_mode); pixman_image_set_transform(texture->image, &transform);
pixman_image_set_clip_region32(buffer->image, (pixman_region32_t *)options->clip); // We've already applied the transforms for source crop and scaling so just
pixman_image_composite32(op, texture->image, mask, // composite over the whole output and let the transform deal with everything.
buffer->image, src_box.x, src_box.y, 0, 0, dest_x, dest_y, pixman_image_composite32(op, texture->image, mask, buffer->image,
width, height); 0, 0, 0, 0, 0, 0, buffer->buffer->width, buffer->buffer->height);
pixman_image_set_clip_region32(buffer->image, NULL);
pixman_image_set_transform(texture->image, NULL); pixman_image_set_transform(texture->image, NULL);
} else {
// No transforms or crop needed, just a straight blit from the source
pixman_image_set_transform(texture->image, NULL);
pixman_image_composite32(op, texture->image, mask, buffer->image,
src_box.x, src_box.y, 0, 0, dst_box.x, dst_box.y,
src_box.width, src_box.height);
}
pixman_image_set_clip_region32(buffer->image, NULL);
if (texture->buffer != NULL) { if (texture->buffer != NULL) {
wlr_buffer_end_data_ptr_access(texture->buffer); wlr_buffer_end_data_ptr_access(texture->buffer);

Loading…
Cancel
Save