[Spice-commits] 2 commits - common/sw_canvas.c

Alexander Larsson alexl at kemper.freedesktop.org
Tue Aug 31 05:01:56 PDT 2010


 common/sw_canvas.c |  156 +++++++++++++----------------------------------------
 1 file changed, 40 insertions(+), 116 deletions(-)

New commits:
commit 012e54bf9f47a4b3085f2933f0dd3a05f919b2a4
Author: Alexander Larsson <alexl at redhat.com>
Date:   Tue Aug 31 12:07:31 2010 +0200

    Fix scaling with large magnification
    
    When scaling part of an image we need to specify the source
    coordinates in transformed coordinates. For large magnifications this
    means we will get pretty large values.
    
    Now, if e.g. src_x * transform is larger than 32765, then the
    coordinate ends up outside the pixman 16bit image size, so the
    rendering will not work.
    
    The fix is to make the src_x/y offset part of the transformation.
    This means its automatically transformed by the correct scaling, and
    the coordinates passed into pixman are not (typically) over 16bit.

diff --git a/common/sw_canvas.c b/common/sw_canvas.c
index a92cff6..f579b4c 100644
--- a/common/sw_canvas.c
+++ b/common/sw_canvas.c
@@ -454,7 +454,6 @@ static void __scale_image(SpiceCanvas *spice_canvas,
     SwCanvas *canvas = (SwCanvas *)spice_canvas;
     pixman_transform_t transform;
     pixman_fixed_t fsx, fsy;
-    int scaled_src_x, scaled_src_y;
 
     fsx = ((pixman_fixed_48_16_t) src_width * 65536) / dest_width;
     fsy = ((pixman_fixed_48_16_t) src_height * 65536) / dest_height;
@@ -462,6 +461,9 @@ static void __scale_image(SpiceCanvas *spice_canvas,
     pixman_image_set_clip_region32(canvas->image, region);
 
     pixman_transform_init_scale(&transform, fsx, fsy);
+    pixman_transform_translate(&transform, NULL,
+			       pixman_int_to_fixed (src_x),
+			       pixman_int_to_fixed (src_y));
 
     pixman_image_set_transform(src, &transform);
     pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
@@ -472,12 +474,9 @@ static void __scale_image(SpiceCanvas *spice_canvas,
                             PIXMAN_FILTER_NEAREST : PIXMAN_FILTER_GOOD,
                             NULL, 0);
 
-    scaled_src_x = ((pixman_fixed_48_16_t)src_x * 65536 + fsx/2 ) / fsx;
-    scaled_src_y = ((pixman_fixed_48_16_t)src_y * 65536 + fsy/2 ) / fsy;
-
     pixman_image_composite32(PIXMAN_OP_SRC,
                              src, NULL, canvas->image,
-                             scaled_src_x, scaled_src_y, /* src */
+                             0, 0, /* src */
                              0, 0, /* mask */
                              dest_x, dest_y, /* dst */
                              dest_width, dest_height);
@@ -530,7 +529,6 @@ static void __scale_image_rop(SpiceCanvas *spice_canvas,
     pixman_box32_t *rects;
     int n_rects, i;
     pixman_fixed_t fsx, fsy;
-    int scaled_src_x, scaled_src_y;
 
     fsx = ((pixman_fixed_48_16_t) src_width * 65536) / dest_width;
     fsy = ((pixman_fixed_48_16_t) src_height * 65536) / dest_height;
@@ -544,6 +542,9 @@ static void __scale_image_rop(SpiceCanvas *spice_canvas,
     pixman_image_set_clip_region32(scaled, region);
 
     pixman_transform_init_scale(&transform, fsx, fsy);
+    pixman_transform_translate(&transform, NULL,
+			       pixman_int_to_fixed (src_x),
+			       pixman_int_to_fixed (src_y));
 
     pixman_image_set_transform(src, &transform);
     pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
@@ -554,12 +555,9 @@ static void __scale_image_rop(SpiceCanvas *spice_canvas,
                             PIXMAN_FILTER_NEAREST : PIXMAN_FILTER_GOOD,
                             NULL, 0);
 
-    scaled_src_x = ((pixman_fixed_48_16_t)src_x * 65536 + fsx/2 ) / fsx;
-    scaled_src_y = ((pixman_fixed_48_16_t)src_y * 65536 + fsy/2 ) / fsy;
-
     pixman_image_composite32(PIXMAN_OP_SRC,
                              src, NULL, scaled,
-                             scaled_src_x, scaled_src_y, /* src */
+                             0, 0, /* src */
                              0, 0, /* mask */
                              0, 0, /* dst */
                              dest_width,
@@ -729,7 +727,6 @@ static void __blend_scale_image(SpiceCanvas *spice_canvas,
     pixman_transform_t transform;
     pixman_image_t *mask, *dest;
     pixman_fixed_t fsx, fsy;
-    int scaled_src_x, scaled_src_y;
 
     fsx = ((pixman_fixed_48_16_t) src_width * 65536) / dest_width;
     fsy = ((pixman_fixed_48_16_t) src_height * 65536) / dest_height;
@@ -739,6 +736,9 @@ static void __blend_scale_image(SpiceCanvas *spice_canvas,
     pixman_image_set_clip_region32(dest, region);
 
     pixman_transform_init_scale(&transform, fsx, fsy);
+    pixman_transform_translate(&transform, NULL,
+			       pixman_int_to_fixed (src_x),
+			       pixman_int_to_fixed (src_y));
 
     mask = NULL;
     if (overall_alpha != 0xff) {
@@ -756,12 +756,9 @@ static void __blend_scale_image(SpiceCanvas *spice_canvas,
                             PIXMAN_FILTER_NEAREST : PIXMAN_FILTER_GOOD,
                             NULL, 0);
 
-    scaled_src_x = ((pixman_fixed_48_16_t)src_x * 65536 + fsx/2 ) / fsx;
-    scaled_src_y = ((pixman_fixed_48_16_t)src_y * 65536 + fsy/2 ) / fsy;
-
     pixman_image_composite32(PIXMAN_OP_OVER,
                              src, mask, dest,
-                             scaled_src_x, scaled_src_y, /* src */
+                             0, 0, /* src */
                              0, 0, /* mask */
                              dest_x, dest_y, /* dst */
                              dest_width, dest_height);
@@ -888,7 +885,6 @@ static void __colorkey_scale_image(SpiceCanvas *spice_canvas,
     pixman_box32_t *rects;
     int n_rects, i;
     pixman_fixed_t fsx, fsy;
-    int scaled_src_x, scaled_src_y;
 
     fsx = ((pixman_fixed_48_16_t) src_width * 65536) / dest_width;
     fsy = ((pixman_fixed_48_16_t) src_height * 65536) / dest_height;
@@ -902,6 +898,9 @@ static void __colorkey_scale_image(SpiceCanvas *spice_canvas,
     pixman_image_set_clip_region32(scaled, region);
 
     pixman_transform_init_scale(&transform, fsx, fsy);
+    pixman_transform_translate(&transform, NULL,
+			       pixman_int_to_fixed (src_x),
+			       pixman_int_to_fixed (src_y));
 
     pixman_image_set_transform(src, &transform);
     pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
@@ -909,12 +908,9 @@ static void __colorkey_scale_image(SpiceCanvas *spice_canvas,
                             PIXMAN_FILTER_NEAREST,
                             NULL, 0);
 
-    scaled_src_x = ((pixman_fixed_48_16_t)src_x * 65536 + fsx/2 ) / fsx;
-    scaled_src_y = ((pixman_fixed_48_16_t)src_y * 65536 + fsy/2 ) / fsy;
-
     pixman_image_composite32(PIXMAN_OP_SRC,
                              src, NULL, scaled,
-                             scaled_src_x, scaled_src_y, /* src */
+                             0, 0, /* src */
                              0, 0, /* mask */
                              0, 0, /* dst */
                              dest_width,
commit 2e860b5b4a0ca4558b1978d8325628fb0081e74f
Author: Alexander Larsson <alexl at redhat.com>
Date:   Tue Aug 31 11:48:13 2010 +0200

    Revert "Fix scaling with large magnification"
    
    This reverts commit e13be77f33609cb3fdae354ce1f2686ae865f9e0.

diff --git a/common/sw_canvas.c b/common/sw_canvas.c
index 0d4367e..a92cff6 100644
--- a/common/sw_canvas.c
+++ b/common/sw_canvas.c
@@ -441,54 +441,6 @@ static void blit_image_rop_from_surface(SpiceCanvas *spice_canvas,
 }
 
 
-/* This creates a sub-image of an image (only works for pure subsets).
- *  This is required when scaling an image so that we can specify a low
- * scaled_src_x/y value. Otherwise we can easily extend past the
- * limit on src_x (16bit signed) resulting in black being drawn
- */
-static pixman_image_t *create_sub_image(pixman_image_t *src,
-					int x, int y,
-					int width, int height,
-					int *sub_x, int *sub_y)
-{
-    char *data;
-    int w, h, stride, bpp;
-    pixman_format_code_t format;
-
-    *sub_x = 0;
-    *sub_y = 0;
-
-    w = pixman_image_get_width(src);
-    h = pixman_image_get_height(src);
-    if (x == 0 && y == 0 &&
-        width == w && height == h) {
-        return pixman_image_ref(src);
-    }
-
-    data = (char *)pixman_image_get_data(src);
-    stride = pixman_image_get_stride(src);
-    format = spice_pixman_image_get_format(src);
-
-    bpp = PIXMAN_FORMAT_BPP(format);
-    if (bpp == 1) {
-        *sub_x = x % 8;
-        width += x % 8;
-        x = x / 8;
-        bpp = 1;
-    } else if (bpp == 4) {
-        *sub_x = x % 2;
-        width += x % 2;
-        x = x / 2;
-        bpp = 1;
-    } else {
-        bpp = bpp / 8;
-    }
-
-    return pixman_image_create_bits (format,
-                                     width, height,
-                                     (uint32_t *)(data + stride * y + bpp * x),
-                                     stride);
-}
 
 static void __scale_image(SpiceCanvas *spice_canvas,
                           pixman_region32_t *region,
@@ -503,8 +455,6 @@ static void __scale_image(SpiceCanvas *spice_canvas,
     pixman_transform_t transform;
     pixman_fixed_t fsx, fsy;
     int scaled_src_x, scaled_src_y;
-    pixman_image_t *sub_src;
-    int sub_src_x, sub_src_y;
 
     fsx = ((pixman_fixed_48_16_t) src_width * 65536) / dest_width;
     fsy = ((pixman_fixed_48_16_t) src_height * 65536) / dest_height;
@@ -513,31 +463,27 @@ static void __scale_image(SpiceCanvas *spice_canvas,
 
     pixman_transform_init_scale(&transform, fsx, fsy);
 
-    sub_src = create_sub_image(src,
-                               src_x, src_y,
-                               src_width, src_height,
-                               &sub_src_x, &sub_src_y);
-
-    pixman_image_set_transform(sub_src, &transform);
-    pixman_image_set_repeat(sub_src, PIXMAN_REPEAT_NONE);
+    pixman_image_set_transform(src, &transform);
+    pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
     ASSERT(scale_mode == SPICE_IMAGE_SCALE_MODE_INTERPOLATE ||
            scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST);
-    pixman_image_set_filter(sub_src,
+    pixman_image_set_filter(src,
                             (scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST) ?
                             PIXMAN_FILTER_NEAREST : PIXMAN_FILTER_GOOD,
                             NULL, 0);
 
-    scaled_src_x = ((pixman_fixed_48_16_t)sub_src_x * 65536 + fsx/2 ) / fsx;
-    scaled_src_y = ((pixman_fixed_48_16_t)sub_src_y * 65536 + fsy/2 ) / fsy;
+    scaled_src_x = ((pixman_fixed_48_16_t)src_x * 65536 + fsx/2 ) / fsx;
+    scaled_src_y = ((pixman_fixed_48_16_t)src_y * 65536 + fsy/2 ) / fsy;
 
     pixman_image_composite32(PIXMAN_OP_SRC,
-                             sub_src, NULL, canvas->image,
+                             src, NULL, canvas->image,
                              scaled_src_x, scaled_src_y, /* src */
                              0, 0, /* mask */
                              dest_x, dest_y, /* dst */
                              dest_width, dest_height);
 
-    pixman_image_unref(sub_src);
+    pixman_transform_init_identity(&transform);
+    pixman_image_set_transform(src, &transform);
 
     pixman_image_set_clip_region32(canvas->image, NULL);
 }
@@ -585,8 +531,6 @@ static void __scale_image_rop(SpiceCanvas *spice_canvas,
     int n_rects, i;
     pixman_fixed_t fsx, fsy;
     int scaled_src_x, scaled_src_y;
-    pixman_image_t *sub_src;
-    int sub_src_x, sub_src_y;
 
     fsx = ((pixman_fixed_48_16_t) src_width * 65536) / dest_width;
     fsy = ((pixman_fixed_48_16_t) src_height * 65536) / dest_height;
@@ -601,32 +545,28 @@ static void __scale_image_rop(SpiceCanvas *spice_canvas,
 
     pixman_transform_init_scale(&transform, fsx, fsy);
 
-    sub_src = create_sub_image(src,
-                               src_x, src_y,
-                               src_width, src_height,
-                               &sub_src_x, &sub_src_y);
-
-    pixman_image_set_transform(sub_src, &transform);
-    pixman_image_set_repeat(sub_src, PIXMAN_REPEAT_NONE);
+    pixman_image_set_transform(src, &transform);
+    pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
     ASSERT(scale_mode == SPICE_IMAGE_SCALE_MODE_INTERPOLATE ||
            scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST);
-    pixman_image_set_filter(sub_src,
+    pixman_image_set_filter(src,
                             (scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST) ?
                             PIXMAN_FILTER_NEAREST : PIXMAN_FILTER_GOOD,
                             NULL, 0);
 
-    scaled_src_x = ((pixman_fixed_48_16_t)sub_src_x * 65536 + fsx/2 ) / fsx;
-    scaled_src_y = ((pixman_fixed_48_16_t)sub_src_y * 65536 + fsy/2 ) / fsy;
+    scaled_src_x = ((pixman_fixed_48_16_t)src_x * 65536 + fsx/2 ) / fsx;
+    scaled_src_y = ((pixman_fixed_48_16_t)src_y * 65536 + fsy/2 ) / fsy;
 
     pixman_image_composite32(PIXMAN_OP_SRC,
-                             sub_src, NULL, scaled,
+                             src, NULL, scaled,
                              scaled_src_x, scaled_src_y, /* src */
                              0, 0, /* mask */
                              0, 0, /* dst */
                              dest_width,
                              dest_height);
 
-    pixman_image_unref(sub_src);
+    pixman_transform_init_identity(&transform);
+    pixman_image_set_transform(src, &transform);
 
     /* Translate back */
     pixman_region32_translate(region, dest_x, dest_y);
@@ -790,8 +730,6 @@ static void __blend_scale_image(SpiceCanvas *spice_canvas,
     pixman_image_t *mask, *dest;
     pixman_fixed_t fsx, fsy;
     int scaled_src_x, scaled_src_y;
-    pixman_image_t *sub_src;
-    int sub_src_x, sub_src_y;
 
     fsx = ((pixman_fixed_48_16_t) src_width * 65536) / dest_width;
     fsy = ((pixman_fixed_48_16_t) src_height * 65536) / dest_height;
@@ -809,25 +747,20 @@ static void __blend_scale_image(SpiceCanvas *spice_canvas,
         mask = pixman_image_create_solid_fill(&color);
     }
 
-    sub_src = create_sub_image(src,
-                               src_x, src_y,
-                               src_width, src_height,
-                               &sub_src_x, &sub_src_y);
-
-    pixman_image_set_transform(sub_src, &transform);
-    pixman_image_set_repeat(sub_src, PIXMAN_REPEAT_NONE);
+    pixman_image_set_transform(src, &transform);
+    pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
     ASSERT(scale_mode == SPICE_IMAGE_SCALE_MODE_INTERPOLATE ||
            scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST);
-    pixman_image_set_filter(sub_src,
+    pixman_image_set_filter(src,
                             (scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST) ?
                             PIXMAN_FILTER_NEAREST : PIXMAN_FILTER_GOOD,
                             NULL, 0);
 
-    scaled_src_x = ((pixman_fixed_48_16_t)sub_src_x * 65536 + fsx/2 ) / fsx;
-    scaled_src_y = ((pixman_fixed_48_16_t)sub_src_y * 65536 + fsy/2 ) / fsy;
+    scaled_src_x = ((pixman_fixed_48_16_t)src_x * 65536 + fsx/2 ) / fsx;
+    scaled_src_y = ((pixman_fixed_48_16_t)src_y * 65536 + fsy/2 ) / fsy;
 
     pixman_image_composite32(PIXMAN_OP_OVER,
-                             sub_src, mask, dest,
+                             src, mask, dest,
                              scaled_src_x, scaled_src_y, /* src */
                              0, 0, /* mask */
                              dest_x, dest_y, /* dst */
@@ -838,7 +771,8 @@ static void __blend_scale_image(SpiceCanvas *spice_canvas,
         clear_dest_alpha(dest, dest_x, dest_y, dest_width, dest_height);
     }
 
-    pixman_image_unref(sub_src);
+    pixman_transform_init_identity(&transform);
+    pixman_image_set_transform(src, &transform);
 
     if (mask) {
         pixman_image_unref(mask);
@@ -955,8 +889,6 @@ static void __colorkey_scale_image(SpiceCanvas *spice_canvas,
     int n_rects, i;
     pixman_fixed_t fsx, fsy;
     int scaled_src_x, scaled_src_y;
-    pixman_image_t *sub_src;
-    int sub_src_x, sub_src_y;
 
     fsx = ((pixman_fixed_48_16_t) src_width * 65536) / dest_width;
     fsy = ((pixman_fixed_48_16_t) src_height * 65536) / dest_height;
@@ -971,29 +903,25 @@ static void __colorkey_scale_image(SpiceCanvas *spice_canvas,
 
     pixman_transform_init_scale(&transform, fsx, fsy);
 
-    sub_src = create_sub_image(src,
-                               src_x, src_y,
-                               src_width, src_height,
-                               &sub_src_x, &sub_src_y);
-
-    pixman_image_set_transform(sub_src, &transform);
-    pixman_image_set_repeat(sub_src, PIXMAN_REPEAT_NONE);
-    pixman_image_set_filter(sub_src,
+    pixman_image_set_transform(src, &transform);
+    pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
+    pixman_image_set_filter(src,
                             PIXMAN_FILTER_NEAREST,
                             NULL, 0);
 
-    scaled_src_x = ((pixman_fixed_48_16_t)sub_src_x * 65536 + fsx/2 ) / fsx;
-    scaled_src_y = ((pixman_fixed_48_16_t)sub_src_y * 65536 + fsy/2 ) / fsy;
+    scaled_src_x = ((pixman_fixed_48_16_t)src_x * 65536 + fsx/2 ) / fsx;
+    scaled_src_y = ((pixman_fixed_48_16_t)src_y * 65536 + fsy/2 ) / fsy;
 
     pixman_image_composite32(PIXMAN_OP_SRC,
-                             sub_src, NULL, scaled,
+                             src, NULL, scaled,
                              scaled_src_x, scaled_src_y, /* src */
                              0, 0, /* mask */
                              0, 0, /* dst */
                              dest_width,
                              dest_height);
 
-    pixman_image_unref(sub_src);
+    pixman_transform_init_identity(&transform);
+    pixman_image_set_transform(src, &transform);
 
     /* Translate back */
     pixman_region32_translate(region, dest_x, dest_y);


More information about the Spice-commits mailing list