return;
}
- width = state->buffer_width / state->scale;
- height = state->buffer_height / state->scale;
- if ((state->transform & WL_OUTPUT_TRANSFORM_90) != 0) {
- tmp = width;
- width = height;
- height = tmp;
+ if (state->viewport.has_src) {
+ *out_width = state->viewport.src.width;
+ *out_height = state->viewport.src.height;
}
+ else {
+ width = state->buffer_width / state->scale;
+ height = state->buffer_height / state->scale;
+ if ((state->transform & WL_OUTPUT_TRANSFORM_90) != 0) {
+ tmp = width;
+ width = height;
+ height = tmp;
+ }
- *out_width = width;
- *out_height = height;
+ *out_width = width;
+ *out_height = height;
+ }
}
static void
}
}
- surface_state_viewport_src_size(pending,
- &pending->width, &pending->height);
+ if (!pending->viewport.has_src &&
+ (pending->buffer_width % pending->scale != 0 ||
+ pending->buffer_height % pending->scale != 0)) {
+ // TODO: send WL_SURFACE_ERROR_INVALID_SIZE error once this issue is
+ // resolved:
+ // https://gitlab.freedesktop.org/wayland/wayland/-/issues/194
+ ds_dbg("Client bug: submitted a buffer whose size (%dx%d) "
+ "is not divisible by scale (%d)", pending->buffer_width,
+ pending->buffer_height, pending->scale);
+ }
+
+ if (pending->viewport.has_dst) {
+ if (pending->buffer_width == 0 && pending->buffer_height == 0) {
+ pending->width = pending->height = 0;
+ }
+ else {
+ pending->width = pending->viewport.dst_width;
+ pending->height = pending->viewport.dst_height;
+ }
+ }
+ else {
+ surface_state_viewport_src_size(pending,
+ &pending->width, &pending->height);
+ }
pixman_region32_intersect_rect(&pending->surface_damage,
&pending->surface_damage,
struct ds_surface_state *current, struct ds_surface_state *pending)
{
pixman_region32_clear(buffer_damage);
+ int src_width, src_height;
+ float scale_x, scale_y;
if (pending->width != current->width ||
pending->height != current->height) {
pixman_region32_init(&surface_damage);
pixman_region32_copy(&surface_damage, &pending->surface_damage);
- // TODO viewport
+ if (pending->viewport.has_dst) {
+ surface_state_viewport_src_size(pending, &src_width, &src_height);
+ scale_x = (float)pending->viewport.dst_width / src_width;
+ scale_y = (float)pending->viewport.dst_height / src_height;
+ ds_region_scale_xy(&surface_damage, &surface_damage,
+ 1.0 / scale_x, 1.0 / scale_y);
+ }
+
+ if (pending->viewport.has_src) {
+ // This is lossy: do a best-effort conversion
+ pixman_region32_translate(&surface_damage,
+ floor(pending->viewport.src.x),
+ floor(pending->viewport.src.y));
+ }
ds_region_transform(&surface_damage, &surface_damage,
ds_output_transform_invert(pending->transform),