surface: Flesh out handling viewport 75/281275/1 accepted/tizen/unified/20220919.021619
authorSeunghun Lee <shiin.lee@samsung.com>
Thu, 25 Aug 2022 07:21:46 +0000 (16:21 +0900)
committerTizen Window System <tizen.windowsystem@gmail.com>
Thu, 15 Sep 2022 06:16:03 +0000 (15:16 +0900)
Change-Id: Ida32b06ea9b1f2aa38f9dc552c2fb318daa4fa77

src/surface/surface.c

index 526f572..4c5a853 100644 (file)
@@ -683,16 +683,22 @@ surface_state_viewport_src_size(struct ds_surface_state *state,
         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
@@ -711,8 +717,30 @@ surface_finalize_pending(struct ds_surface *surface)
         }
     }
 
-    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,
@@ -738,6 +766,8 @@ surface_update_damage(pixman_region32_t *buffer_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) {
@@ -750,7 +780,20 @@ surface_update_damage(pixman_region32_t *buffer_damage,
         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),