[Pixman] [PATCH 6/8] Switch the wide pipeline over to using floating point

Søren Sandmann Pedersen sandmann at cs.au.dk
Sat Aug 25 18:45:15 PDT 2012


From: Søren Sandmann Pedersen <ssp at redhat.com>

In pixman-bits-image.c, remove bits_image_fetch_untransformed_64() and
add bits_image_fetch_untransformed_float(); change
dest_get_scanline_wide() to produce a floating point buffer,

In the gradients, change *_get_scanline_wide() to call
pixman_expand_to_float() instead of pixman_expand().

In pixman-general.c change the wide Bpp to 16 instead of 8, and
initialize the buffers to 0 to prevent NaNs from causing trouble.

In pixman-noop.c make the wide solid iterator generate floating point
pixels.

In pixman-solid-fill.c, cache a floating point pixel, and make the
wide iterator generate floating point pixels.
---
 pixman/pixman-bits-image.c       | 64 +++++++++++++++++++---------------------
 pixman/pixman-conical-gradient.c |  3 +-
 pixman/pixman-general.c          | 10 ++++++-
 pixman/pixman-implementation.c   |  4 +--
 pixman/pixman-linear-gradient.c  |  3 +-
 pixman/pixman-noop.c             |  6 ++--
 pixman/pixman-private.h          |  3 +-
 pixman/pixman-radial-gradient.c  |  3 +-
 pixman/pixman-solid-fill.c       | 10 +++++--
 9 files changed, 59 insertions(+), 47 deletions(-)

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 07353dc..81a5a6f 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -979,17 +979,17 @@ replicate_pixel_32 (bits_image_t *   bits,
 }
 
 static void
-replicate_pixel_64 (bits_image_t *   bits,
-		    int              x,
-		    int              y,
-		    int              width,
-		    uint32_t *       b)
+replicate_pixel_float (bits_image_t *   bits,
+		       int              x,
+		       int              y,
+		       int              width,
+		       uint32_t *       b)
 {
-    uint64_t color;
-    uint64_t *buffer = (uint64_t *)b;
-    uint64_t *end;
+    argb_t color;
+    argb_t *buffer = (argb_t *)b;
+    argb_t *end;
 
-    color = bits->fetch_pixel_64 (bits, x, y);
+    color = bits->fetch_pixel_float (bits, x, y);
 
     end = buffer + width;
     while (buffer < end)
@@ -1008,7 +1008,7 @@ bits_image_fetch_untransformed_repeat_none (bits_image_t *image,
 
     if (y < 0 || y >= image->height)
     {
-	memset (buffer, 0, width * (wide? 8 : 4));
+	memset (buffer, 0, width * (wide? sizeof (argb_t) : 4));
 	return;
     }
 
@@ -1016,10 +1016,10 @@ bits_image_fetch_untransformed_repeat_none (bits_image_t *image,
     {
 	w = MIN (width, -x);
 
-	memset (buffer, 0, w * (wide ? 8 : 4));
+	memset (buffer, 0, w * (wide ? sizeof (argb_t) : 4));
 
 	width -= w;
-	buffer += w * (wide? 2 : 1);
+	buffer += w * (wide? 4 : 1);
 	x += w;
     }
 
@@ -1028,16 +1028,16 @@ bits_image_fetch_untransformed_repeat_none (bits_image_t *image,
 	w = MIN (width, image->width - x);
 
 	if (wide)
-	    image->fetch_scanline_64 ((pixman_image_t *)image, x, y, w, buffer, NULL);
+	    image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL);
 	else
 	    image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
 
 	width -= w;
-	buffer += w * (wide? 2 : 1);
+	buffer += w * (wide? 4 : 1);
 	x += w;
     }
 
-    memset (buffer, 0, width * (wide ? 8 : 4));
+    memset (buffer, 0, width * (wide ? sizeof (argb_t) : 4));
 }
 
 static void
@@ -1059,7 +1059,7 @@ bits_image_fetch_untransformed_repeat_normal (bits_image_t *image,
     if (image->width == 1)
     {
 	if (wide)
-	    replicate_pixel_64 (image, 0, y, width, buffer);
+	    replicate_pixel_float (image, 0, y, width, buffer);
 	else
 	    replicate_pixel_32 (image, 0, y, width, buffer);
 
@@ -1076,7 +1076,7 @@ bits_image_fetch_untransformed_repeat_normal (bits_image_t *image,
 	w = MIN (width, image->width - x);
 
 	if (wide)
-	    image->fetch_scanline_64 ((pixman_image_t *)image, x, y, w, buffer, NULL);
+	    image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL);
 	else
 	    image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
 
@@ -1112,9 +1112,8 @@ bits_image_fetch_untransformed_32 (pixman_iter_t * iter,
 }
 
 static uint32_t *
-bits_image_fetch_untransformed_64 (pixman_iter_t * iter,
-                                   const uint32_t *mask)
-				   
+bits_image_fetch_untransformed_float (pixman_iter_t * iter,
+				      const uint32_t *mask)
 {
     pixman_image_t *image  = iter->image;
     int             x      = iter->x;
@@ -1155,8 +1154,8 @@ static const fetcher_info_t fetcher_info[] =
        FAST_PATH_NO_PAD_REPEAT			|
        FAST_PATH_NO_REFLECT_REPEAT),
       bits_image_fetch_untransformed_32,
-      bits_image_fetch_untransformed_64,
-      _pixman_image_get_scanline_generic_float
+      NULL,
+      bits_image_fetch_untransformed_float
     },
 
 #define FAST_BILINEAR_FLAGS						\
@@ -1278,7 +1277,7 @@ _pixman_bits_image_src_iter_init (pixman_image_t *image, pixman_iter_t *iter)
 	    else
 	    {
 		iter->data = info->get_scanline_32;
-		iter->get_scanline = info->get_scanline_64;
+		iter->get_scanline = info->get_scanline_float;
 	    }
 	    return;
 	}
@@ -1333,30 +1332,27 @@ dest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
     int             x      = iter->x;
     int             y      = iter->y;
     int             width  = iter->width;
-    uint64_t *	    buffer = (uint64_t *)iter->buffer;
+    argb_t *	    buffer = (argb_t *)iter->buffer;
 
-    image->fetch_scanline_64 (
+    image->fetch_scanline_float (
 	(pixman_image_t *)image, x, y, width, (uint32_t *)buffer, mask);
     if (image->common.alpha_map)
     {
-	uint64_t *alpha;
+	argb_t *alpha;
 
-	if ((alpha = malloc (width * sizeof (uint64_t))))
+	if ((alpha = malloc (width * sizeof (argb_t))))
 	{
 	    int i;
 
 	    x -= image->common.alpha_origin_x;
 	    y -= image->common.alpha_origin_y;
 
-	    image->common.alpha_map->fetch_scanline_64 (
+	    image->common.alpha_map->fetch_scanline_float (
 		(pixman_image_t *)image->common.alpha_map,
 		x, y, width, (uint32_t *)alpha, mask);
 
 	    for (i = 0; i < width; ++i)
-	    {
-		buffer[i] &= ~0xffff000000000000ULL;
-		buffer[i] |= (alpha[i] & 0xffff000000000000ULL);
-	    }
+		buffer[i].a = alpha[i].a;
 
 	    free (alpha);
 	}
@@ -1397,14 +1393,14 @@ dest_write_back_wide (pixman_iter_t *iter)
     int             width  = iter->width;
     const uint32_t *buffer = iter->buffer;
 
-    image->store_scanline_64 (image, x, y, width, buffer);
+    image->store_scanline_float (image, x, y, width, buffer);
 
     if (image->common.alpha_map)
     {
 	x -= image->common.alpha_origin_x;
 	y -= image->common.alpha_origin_y;
 
-	image->common.alpha_map->store_scanline_64 (
+	image->common.alpha_map->store_scanline_float (
 	    image->common.alpha_map, x, y, width, buffer);
     }
 
diff --git a/pixman/pixman-conical-gradient.c b/pixman/pixman-conical-gradient.c
index 8b52176..1e971fd 100644
--- a/pixman/pixman-conical-gradient.c
+++ b/pixman/pixman-conical-gradient.c
@@ -165,7 +165,8 @@ conical_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
 {
     uint32_t *buffer = conical_get_scanline_narrow (iter, NULL);
 
-    pixman_expand ((uint64_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
+    pixman_expand_to_float (
+	(argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
 
     return buffer;
 }
diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c
index a247685..58b29db 100644
--- a/pixman/pixman-general.c
+++ b/pixman/pixman-general.c
@@ -124,7 +124,7 @@ general_composite_rect  (pixman_implementation_t *imp,
     else
     {
 	narrow = 0;
-	Bpp = 8;
+	Bpp = 16;
     }
 
     if (width * Bpp > SCANLINE_BUFFER_LENGTH)
@@ -139,6 +139,14 @@ general_composite_rect  (pixman_implementation_t *imp,
     mask_buffer = src_buffer + width * Bpp;
     dest_buffer = mask_buffer + width * Bpp;
 
+    if (!narrow)
+    {
+	/* To make sure there aren't any NANs in the buffers */
+	memset (src_buffer, 0, width * Bpp);
+	memset (mask_buffer, 0, width * Bpp);
+	memset (dest_buffer, 0, width * Bpp);
+    }
+    
     /* src iter */
     src_iter_flags = narrow | op_flags[op].src;
 
diff --git a/pixman/pixman-implementation.c b/pixman/pixman-implementation.c
index 77d0906..8842b36 100644
--- a/pixman/pixman-implementation.c
+++ b/pixman/pixman-implementation.c
@@ -127,8 +127,8 @@ _pixman_implementation_lookup_combiner (pixman_implementation_t *imp,
     {
 	pixman_combine_32_func_t (*combiners[]) =
 	{
-	    (pixman_combine_32_func_t *)imp->combine_64,
-	    (pixman_combine_32_func_t *)imp->combine_64_ca,
+	    (pixman_combine_32_func_t *)imp->combine_float,
+	    (pixman_combine_32_func_t *)imp->combine_float_ca,
 	    imp->combine_32,
 	    imp->combine_32_ca,
 	};
diff --git a/pixman/pixman-linear-gradient.c b/pixman/pixman-linear-gradient.c
index 32b8ba7..e6d6884 100644
--- a/pixman/pixman-linear-gradient.c
+++ b/pixman/pixman-linear-gradient.c
@@ -227,7 +227,8 @@ linear_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
 {
     uint32_t *buffer = linear_get_scanline_narrow (iter, NULL);
 
-    pixman_expand ((uint64_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
+    pixman_expand_to_float (
+	(argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
 
     return buffer;
 }
diff --git a/pixman/pixman-noop.c b/pixman/pixman-noop.c
index 7b017e8..6fd5eeb 100644
--- a/pixman/pixman-noop.c
+++ b/pixman/pixman-noop.c
@@ -93,9 +93,9 @@ noop_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
 	}
 	else
 	{
-	    uint64_t color = bits->fetch_pixel_64 (bits, 0, 0);
-	    uint64_t *buffer = (uint64_t *)iter->buffer;
-	    uint64_t *end = buffer + iter->width;
+	    argb_t color = bits->fetch_pixel_float (bits, 0, 0);
+	    argb_t *buffer = (argb_t *)iter->buffer;
+	    argb_t *end = buffer + iter->width;
 
 	    while (buffer < end)
 		*(buffer++) = color;
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index dea3250..6230fed 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -126,9 +126,10 @@ struct solid_fill
 {
     image_common_t common;
     pixman_color_t color;
-    
+
     uint32_t	   color_32;
     uint64_t	   color_64;
+    argb_t	   color_float;
 };
 
 struct gradient
diff --git a/pixman/pixman-radial-gradient.c b/pixman/pixman-radial-gradient.c
index 715711f..39d0cb3 100644
--- a/pixman/pixman-radial-gradient.c
+++ b/pixman/pixman-radial-gradient.c
@@ -405,7 +405,8 @@ radial_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
 {
     uint32_t *buffer = radial_get_scanline_narrow (iter, NULL);
 
-    pixman_expand ((uint64_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
+    pixman_expand_to_float (
+	(argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
 
     return buffer;
 }
diff --git a/pixman/pixman-solid-fill.c b/pixman/pixman-solid-fill.c
index 8b25d5d..1b774d9 100644
--- a/pixman/pixman-solid-fill.c
+++ b/pixman/pixman-solid-fill.c
@@ -40,9 +40,9 @@ _pixman_solid_fill_iter_init (pixman_image_t *image, pixman_iter_t  *iter)
     }
     else
     {
-	uint64_t *b = (uint64_t *)iter->buffer;
-	uint64_t *e = b + iter->width;
-	uint64_t color = image->solid.color_64;
+	argb_t *b = (argb_t *)iter->buffer;
+	argb_t *e = b + iter->width;
+	argb_t color = image->solid.color_float;
 
 	while (b < e)
 	    *(b++) = color;
@@ -83,6 +83,10 @@ pixman_image_create_solid_fill (pixman_color_t *color)
     img->solid.color = *color;
     img->solid.color_32 = color_to_uint32 (color);
     img->solid.color_64 = color_to_uint64 (color);
+    img->solid.color_float.a = pixman_unorm_to_float (color->alpha, 16);
+    img->solid.color_float.r = pixman_unorm_to_float (color->red, 16);
+    img->solid.color_float.g = pixman_unorm_to_float (color->green, 16);
+    img->solid.color_float.b = pixman_unorm_to_float (color->blue, 16);
 
     return img;
 }
-- 
1.7.11.4



More information about the Pixman mailing list