pixman: Branch 'master' - 7 commits

Søren Sandmann Pedersen sandmann at kemper.freedesktop.org
Thu Jun 12 21:26:42 PDT 2008


 pixman/pixman-access.c      |  288 ++++++++++++++++++++++++++++++++++++++++++++
 pixman/pixman-compose.c     |  131 +++++++++++++++++---
 pixman/pixman-private.h     |   26 +++
 pixman/pixman-source.c      |   28 ++++
 pixman/pixman-transformed.c |  102 +++++++++++++++
 pixman/pixman-utils.c       |    2 
 pixman/pixman.h             |    4 
 7 files changed, 565 insertions(+), 16 deletions(-)

New commits:
commit b1c70c4e6435d7f15751111828c381feb1d139cf
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date:   Fri Jun 13 00:25:45 2008 -0400

    Move PIXMAN_FORMAT_16BPC to pixman-private.h

diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index fa1311d..3bbf641 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -647,6 +647,10 @@ union pixman_image
     } while (0)
 
 
+#define PIXMAN_FORMAT_16BPC(f)	(PIXMAN_FORMAT_A(f) > 8 || \
+				 PIXMAN_FORMAT_R(f) > 8 || \
+				 PIXMAN_FORMAT_G(f) > 8 || \
+				 PIXMAN_FORMAT_B(f) > 8)
 /*
  * Edges
  */
diff --git a/pixman/pixman.h b/pixman/pixman.h
index 10871a3..f60534b 100644
--- a/pixman/pixman.h
+++ b/pixman/pixman.h
@@ -495,10 +495,6 @@ struct pixman_indexed
 				 PIXMAN_FORMAT_R(f) +	\
 				 PIXMAN_FORMAT_G(f) +	\
 				 PIXMAN_FORMAT_B(f))
-#define PIXMAN_FORMAT_16BPC(f)	(PIXMAN_FORMAT_A(f) > 8 || \
-				 PIXMAN_FORMAT_R(f) > 8 || \
-				 PIXMAN_FORMAT_G(f) > 8 || \
-				 PIXMAN_FORMAT_B(f) > 8)
 
 #define PIXMAN_TYPE_OTHER	0
 #define PIXMAN_TYPE_A		1
commit 7fa966df0ee781fa486715710f389b148c11d36e
Author: Aaron Plattner <aplattner at nvidia.com>
Date:   Fri Jun 6 23:02:51 2008 -0700

    Decide based on the image formats whether we need wide compositing.
    
    Signed-off-by: Søren Sandmann Pedersen <sandmann at redhat.com>

diff --git a/pixman/pixman-compose.c b/pixman/pixman-compose.c
index 812e70d..c583ea6 100644
--- a/pixman/pixman-compose.c
+++ b/pixman/pixman-compose.c
@@ -549,7 +549,13 @@ void
 pixman_composite_rect_general (const FbComposeData *data)
 {
     uint32_t _scanline_buffer[SCANLINE_BUFFER_LENGTH * 3];
-    const int wide = 0;
+    const pixman_format_code_t srcFormat = data->src->type == BITS ? data->src->bits.format : 0;
+    const pixman_format_code_t maskFormat = data->mask && data->mask->type == BITS ? data->mask->bits.format : 0;
+    const pixman_format_code_t destFormat = data->dest->type == BITS ? data->dest->bits.format : 0;
+    const int srcWide = PIXMAN_FORMAT_16BPC(srcFormat);
+    const int maskWide = data->mask && PIXMAN_FORMAT_16BPC(maskFormat);
+    const int destWide = PIXMAN_FORMAT_16BPC(destFormat);
+    const int wide = srcWide || maskWide || destWide;
     const int Bpp = wide ? 8 : 4;
     uint8_t *scanline_buffer = (uint8_t*)_scanline_buffer;
     uint8_t *src_buffer, *mask_buffer, *dest_buffer;
commit 7cb735c9c0fa55ae1f4d8d13da9f33e3da2ae8fe
Author: Aaron Plattner <aplattner at nvidia.com>
Date:   Fri Jun 6 19:40:25 2008 -0700

    Take the source format into account in pixman_expand.
    
    Extract the original bits of the source image for each component and then
    replicate up to 16 bits to fill the wide components.  Make sure to hard-code the
    alpha value to 1 if the source format didn't have alpha.
    
    Signed-off-by: Søren Sandmann Pedersen <sandmann at redhat.com>

diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c
index 29ddcb3..ec187d3 100644
--- a/pixman/pixman-access.c
+++ b/pixman/pixman-access.c
@@ -1879,30 +1879,70 @@ storeProc64 ACCESS(pixman_storeProcForPicture64) (bits_image_t * pict)
 
 #ifndef PIXMAN_FB_ACCESSORS
 /*
+ * Helper routine to expand a color component from 0 < n <= 8 bits to 16 bits by
+ * replication.
+ */
+static inline uint64_t expand16(const uint8_t val, int nbits)
+{
+    // Start out with the high bit of val in the high bit of result.
+    uint16_t result = (uint16_t)val << (16 - nbits);
+
+    if (nbits == 0)
+        return 0;
+
+    // Copy the bits in result, doubling the number of bits each time, until we
+    // fill all 16 bits.
+    while (nbits < 16) {
+        result |= result >> nbits;
+        nbits *= 2;
+    }
+
+    return result;
+}
+
+/*
  * This function expands images from ARGB8 format to ARGB16.  To preserve
  * precision, it needs to know the original source format.  For example, if the
  * source was PIXMAN_x1r5g5b5 and the red component contained bits 12345, then
  * the expanded value is 12345123.  To correctly expand this to 16 bits, it
  * should be 1234512345123451 and not 1234512312345123.
- *
- * XXX[AGP]: For now, this just does naïve byte replication.
  */
 void pixman_expand(uint64_t *dst, const uint32_t *src,
                    pixman_format_code_t format, int width)
 {
+    /*
+     * Determine the sizes of each component and the masks and shifts required
+     * to extract them from the source pixel.
+     */
+    const int a_size = PIXMAN_FORMAT_A(format),
+              r_size = PIXMAN_FORMAT_R(format),
+              g_size = PIXMAN_FORMAT_G(format),
+              b_size = PIXMAN_FORMAT_B(format);
+    const int a_shift = 32 - a_size,
+              r_shift = 24 - r_size,
+              g_shift = 16 - g_size,
+              b_shift =  8 - b_size;
+    const uint8_t a_mask = ~(~0 << a_size),
+                  r_mask = ~(~0 << r_size),
+                  g_mask = ~(~0 << g_size),
+                  b_mask = ~(~0 << b_size);
     int i;
 
     /* Start at the end so that we can do the expansion in place when src == dst */
     for (i = width - 1; i >= 0; i--)
     {
-        const uint8_t a = src[i] >> 24,
-                      r = src[i] >> 16,
-                      g = src[i] >> 8,
-                      b = src[i];
-        dst[i] = (uint64_t)a << 56 | (uint64_t) a << 48 |
-                 (uint64_t)r << 40 | (uint64_t) r << 32 |
-                 (uint64_t)g << 24 | (uint64_t) g << 16 |
-                 (uint64_t)b << 8 | (uint64_t)b;
+        const uint32_t pixel = src[i];
+        // Extract the components.
+        const uint8_t a = (pixel >> a_shift) & a_mask,
+                      r = (pixel >> r_shift) & r_mask,
+                      g = (pixel >> g_shift) & g_mask,
+                      b = (pixel >> b_shift) & b_mask;
+        const uint64_t a16 = a_size ? expand16(a, a_size) : 0xffff,
+                       r16 = expand16(r, r_size),
+                       g16 = expand16(g, g_size),
+                       b16 = expand16(b, b_size);
+
+        dst[i] = a16 << 48 | r16 << 32 | g16 << 16 | b16;
     }
 }
 
commit c0d98e96605c6d03f4b02f337f2f5827165bb092
Author: Aaron Plattner <aplattner at nvidia.com>
Date:   Fri Jun 6 18:51:48 2008 -0700

    Make expansion and contraction loops clearer.
    
    Signed-off-by: Søren Sandmann Pedersen <sandmann at redhat.com>

diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c
index d5d3952..29ddcb3 100644
--- a/pixman/pixman-access.c
+++ b/pixman/pixman-access.c
@@ -1890,17 +1890,19 @@ storeProc64 ACCESS(pixman_storeProcForPicture64) (bits_image_t * pict)
 void pixman_expand(uint64_t *dst, const uint32_t *src,
                    pixman_format_code_t format, int width)
 {
+    int i;
+
     /* Start at the end so that we can do the expansion in place when src == dst */
-    for (width--; width >= 0; width--)
+    for (i = width - 1; i >= 0; i--)
     {
-        const uint8_t a = src[width] >> 24,
-                      r = src[width] >> 16,
-                      g = src[width] >> 8,
-                      b = src[width];
-        dst[width] = (uint64_t)a << 56 | (uint64_t) a << 48 |
-                     (uint64_t)r << 40 | (uint64_t) r << 32 |
-                     (uint64_t)g << 24 | (uint64_t) g << 16 |
-                     (uint64_t)b << 8 | (uint64_t)b;
+        const uint8_t a = src[i] >> 24,
+                      r = src[i] >> 16,
+                      g = src[i] >> 8,
+                      b = src[i];
+        dst[i] = (uint64_t)a << 56 | (uint64_t) a << 48 |
+                 (uint64_t)r << 40 | (uint64_t) r << 32 |
+                 (uint64_t)g << 24 | (uint64_t) g << 16 |
+                 (uint64_t)b << 8 | (uint64_t)b;
     }
 }
 
@@ -1910,15 +1912,17 @@ void pixman_expand(uint64_t *dst, const uint32_t *src,
  */
 void pixman_contract(uint32_t *dst, const uint64_t *src, int width)
 {
+    int i;
+
     /* Start at the beginning so that we can do the contraction in place when
      * src == dst */
-    for (width--; width >= 0; width--, src++, dst++)
+    for (i = 0; i < width; i++)
     {
-        const uint8_t a = *src >> 56,
-                      r = *src >> 40,
-                      g = *src >> 24,
-                      b = *src >> 8;
-        *dst = a << 24 | r << 16 | g << 8 | b;
+        const uint8_t a = src[i] >> 56,
+                      r = src[i] >> 40,
+                      g = src[i] >> 24,
+                      b = src[i] >> 8;
+        dst[i] = a << 24 | r << 16 | g << 8 | b;
     }
 }
 #endif // PIXMAN_FB_ACCESSORS
commit fc0b28bf6af81428b7ac045614eea97fbf9c4a70
Author: Aaron Plattner <aplattner at nvidia.com>
Date:   Fri Jun 6 18:05:15 2008 -0700

    Add wide source picture, external alpha, and transformed image routines.
    
    The wide external alpha path should work correctly with wide formats.  The wide
    transformed fetch code for now just does a 32-bit fetch and then expands, which
    will lose precision.  Source pictures, for now, are evaluated at depth 32 and
    then are expanded to depth 64.  We could get higher precision by evaluating them
    directly at depth 64, but this should be good enough for now.
    
    Signed-off-by: Søren Sandmann Pedersen <sandmann at redhat.com>

diff --git a/pixman/pixman-compose.c b/pixman/pixman-compose.c
index c5773eb..812e70d 100644
--- a/pixman/pixman-compose.c
+++ b/pixman/pixman-compose.c
@@ -174,6 +174,62 @@ typedef void (*scanStoreProc)(pixman_image_t *, int, int, int, uint32_t *);
 typedef void (*scanFetchProc)(pixman_image_t *, int, int, int, uint32_t *,
 			      uint32_t *, uint32_t);
 
+static inline scanFetchProc get_fetch_source_pict(const int wide)
+{
+    if (wide)
+	return (scanFetchProc)pixmanFetchSourcePict64;
+    else
+	return (scanFetchProc)pixmanFetchSourcePict;
+}
+
+static inline scanFetchProc get_fetch_solid(const int wide)
+{
+    if (wide)
+	return (scanFetchProc)fbFetchSolid64;
+    else
+	return (scanFetchProc)fbFetchSolid;
+}
+
+static inline scanFetchProc get_fetch(const int wide)
+{
+    if (wide)
+	return (scanFetchProc)fbFetch64;
+    else
+	return (scanFetchProc)fbFetch;
+}
+
+static inline scanFetchProc get_fetch_external_alpha(const int wide)
+{
+    if (wide)
+	return (scanFetchProc)ACCESS(fbFetchExternalAlpha64);
+    else
+	return (scanFetchProc)ACCESS(fbFetchExternalAlpha);
+}
+
+static inline scanFetchProc get_fetch_transformed(const int wide)
+{
+    if (wide)
+	return (scanFetchProc)ACCESS(fbFetchTransformed64);
+    else
+	return (scanFetchProc)ACCESS(fbFetchTransformed);
+}
+
+static inline scanStoreProc get_store(const int wide)
+{
+    if (wide)
+	return (scanStoreProc)fbStore64;
+    else
+	return (scanStoreProc)fbStore;
+}
+
+static inline scanStoreProc get_store_external_alpha(const int wide)
+{
+    if (wide)
+	return (scanStoreProc)ACCESS(fbStoreExternalAlpha64);
+    else
+	return (scanStoreProc)ACCESS(fbStoreExternalAlpha);
+}
+
 #ifndef PIXMAN_FB_ACCESSORS
 static
 #endif
@@ -195,7 +251,7 @@ PIXMAN_COMPOSITE_RECT_GENERAL (const FbComposeData *data,
         fetchSrc = NULL;
     else if (IS_SOURCE_IMAGE (data->src))
     {
-	fetchSrc = (scanFetchProc)pixmanFetchSourcePict;
+	fetchSrc = get_fetch_source_pict(wide);
 	srcClass = SourcePictureClassify ((source_image_t *)data->src,
 					  data->xSrc, data->ySrc,
 					  data->width, data->height);
@@ -206,25 +262,23 @@ PIXMAN_COMPOSITE_RECT_GENERAL (const FbComposeData *data,
 
 	if (bits->common.alpha_map)
 	{
-	    // TODO: Need wide external alpha routine.
-	    fetchSrc = (scanFetchProc)ACCESS(fbFetchExternalAlpha);
+	    fetchSrc = get_fetch_external_alpha(wide);
 	}
 	else if ((bits->common.repeat == PIXMAN_REPEAT_NORMAL || bits->common.repeat == PIXMAN_REPEAT_PAD) &&
 		 bits->width == 1 &&
 		 bits->height == 1)
 	{
-	    fetchSrc = wide ? (scanFetchProc)fbFetchSolid64 : (scanFetchProc)fbFetchSolid;
+	    fetchSrc = get_fetch_solid(wide);
 	    srcClass = SOURCE_IMAGE_CLASS_HORIZONTAL;
 	}
 	else if (!bits->common.transform && bits->common.filter != PIXMAN_FILTER_CONVOLUTION
                 && bits->common.repeat != PIXMAN_REPEAT_PAD)
 	{
-	    fetchSrc = wide ? (scanFetchProc)fbFetch64 : (scanFetchProc)fbFetch;
+	    fetchSrc = get_fetch(wide);
 	}
 	else
 	{
-	    // TODO: Need wide transformed fetch.
-	    fetchSrc = (scanFetchProc)ACCESS(fbFetchTransformed);
+	    fetchSrc = get_fetch_transformed(wide);
 	}
     }
 
@@ -247,37 +301,34 @@ PIXMAN_COMPOSITE_RECT_GENERAL (const FbComposeData *data,
 
 	    if (bits->common.alpha_map)
 	    {
-		// TODO: Need wide external alpha routine.
-		fetchMask = (scanFetchProc)ACCESS(fbFetchExternalAlpha);
+		fetchMask = get_fetch_external_alpha(wide);
 	    }
 	    else if ((bits->common.repeat == PIXMAN_REPEAT_NORMAL || bits->common.repeat == PIXMAN_REPEAT_PAD) &&
 		     bits->width == 1 && bits->height == 1)
 	    {
-		fetchMask = wide ? (scanFetchProc)fbFetchSolid64 : (scanFetchProc)fbFetchSolid;
+		fetchMask = get_fetch_solid(wide);
 		maskClass = SOURCE_IMAGE_CLASS_HORIZONTAL;
 	    }
 	    else if (!bits->common.transform && bits->common.filter != PIXMAN_FILTER_CONVOLUTION
                     && bits->common.repeat != PIXMAN_REPEAT_PAD)
-		fetchMask = wide ? (scanFetchProc)fbFetch64 : (scanFetchProc)fbFetch;
+		fetchMask = get_fetch(wide);
 	    else
-		// TODO: Need wide transformed fetch.
-		fetchMask = (scanFetchProc)ACCESS(fbFetchTransformed);
+		fetchMask = get_fetch_transformed(wide);
 	}
     }
 
     if (data->dest->common.alpha_map)
     {
-	// TODO: Need wide external alpha routine.
-	fetchDest = (scanFetchProc)ACCESS(fbFetchExternalAlpha);
-	store = (scanStoreProc)ACCESS(fbStoreExternalAlpha);
+	fetchDest = get_fetch_external_alpha(wide);
+	store = get_store_external_alpha(wide);
 
 	if (data->op == PIXMAN_OP_CLEAR || data->op == PIXMAN_OP_SRC)
 	    fetchDest = NULL;
     }
     else
     {
-	fetchDest = wide ? (scanFetchProc)fbFetch64 : (scanFetchProc)fbFetch;
-	store = wide ? (scanStoreProc)fbStore64 : (scanStoreProc)fbStore;
+	fetchDest = get_fetch(wide);
+	store = get_store(wide);
 
 	switch (data->op)
 	{
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index 5a2f89e..fa1311d 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -219,6 +219,8 @@ void pixman_contract(uint32_t *dst, const uint64_t *src, int width);
 
 void pixmanFetchSourcePict(source_image_t *, int x, int y, int width,
                            uint32_t *buffer, uint32_t *mask, uint32_t maskBits);
+void pixmanFetchSourcePict64(source_image_t *, int x, int y, int width,
+                             uint64_t *buffer, uint64_t *mask, uint32_t maskBits);
 
 void fbFetchTransformed(bits_image_t *, int x, int y, int width,
                         uint32_t *buffer, uint32_t *mask, uint32_t maskBits);
@@ -236,6 +238,22 @@ void fbFetchExternalAlpha_accessors(bits_image_t *, int x, int y, int width,
                                     uint32_t *buffer, uint32_t *mask,
                                     uint32_t maskBits);
 
+void fbFetchTransformed64(bits_image_t *, int x, int y, int width,
+                          uint64_t *buffer, uint64_t *mask, uint32_t maskBits);
+void fbStoreExternalAlpha64(bits_image_t *, int x, int y, int width,
+                            uint64_t *buffer);
+void fbFetchExternalAlpha64(bits_image_t *, int x, int y, int width,
+                            uint64_t *buffer, uint64_t *mask, uint32_t maskBits);
+
+void fbFetchTransformed64_accessors(bits_image_t *, int x, int y, int width,
+                                    uint64_t *buffer, uint64_t *mask,
+                                    uint32_t maskBits);
+void fbStoreExternalAlpha64_accessors(bits_image_t *, int x, int y, int width,
+                                      uint64_t *buffer);
+void fbFetchExternalAlpha64_accessors(bits_image_t *, int x, int y, int width,
+                                      uint64_t *buffer, uint64_t *mask,
+                                      uint32_t maskBits);
+
 /* end */
 
 typedef enum
@@ -469,6 +487,7 @@ union pixman_image
 			 (uint32_t) ((uint8_t) ((t) | (0 - ((t) >> 8)))) << (i))
 
 #define div_255(x) (((x) + 0x80 + (((x) + 0x80) >> 8)) >> 8)
+#define div_65535(x) (((x) + 0x8000 + (((x) + 0x8000) >> 16)) >> 16)
 
 #define MOD(a,b) ((a) < 0 ? ((b) - ((-(a) - 1) % (b))) - 1 : (a) % (b))
 
diff --git a/pixman/pixman-source.c b/pixman/pixman-source.c
index a5a4235..6a640fa 100644
--- a/pixman/pixman-source.c
+++ b/pixman/pixman-source.c
@@ -27,6 +27,7 @@
 #include <config.h>
 #endif
 
+#include <stdlib.h>
 #include <math.h>
 
 #include "pixman-private.h"
@@ -679,3 +680,30 @@ void pixmanFetchSourcePict(source_image_t * pict, int x, int y, int width,
         }
     }
 }
+
+/*
+ * For now, just evaluate the source picture at 32bpp and expand.  We could
+ * produce smoother gradients by evaluating them at higher color depth, but
+ * that's a project for the future.
+ */
+void pixmanFetchSourcePict64(source_image_t * pict, int x, int y, int width,
+                             uint64_t *buffer, uint64_t *mask, uint32_t maskBits)
+{
+    uint32_t *mask8 = NULL;
+
+    // Contract the mask image, if one exists, so that the 32-bit fetch function
+    // can use it.
+    if (mask) {
+        mask8 = pixman_malloc_ab(width, sizeof(uint32_t));
+        pixman_contract(mask8, mask, width);
+    }
+
+    // Fetch the source image into the first half of buffer.
+    pixmanFetchSourcePict(pict, x, y, width, (uint32_t*)buffer, mask8,
+                          maskBits);
+
+    // Expand from 32bpp to 64bpp in place.
+    pixman_expand(buffer, (uint32_t*)buffer, PIXMAN_a8r8g8b8, width);
+
+    free(mask8);
+}
diff --git a/pixman/pixman-transformed.c b/pixman/pixman-transformed.c
index cff1ba2..9f566bf 100644
--- a/pixman/pixman-transformed.c
+++ b/pixman/pixman-transformed.c
@@ -2,6 +2,7 @@
  *
  * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
  *             2005 Lars Knoll & Zack Rusin, Trolltech
+ *             2008 Aaron Plattner, NVIDIA Corporation
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -36,6 +37,11 @@
 #define Green(x) (((x) >> 8) & 0xff)
 #define Blue(x) ((x) & 0xff)
 
+#define Alpha64(x) ((x) >> 48)
+#define Red64(x) (((x) >> 32) & 0xffff)
+#define Green64(x) (((x) >> 16) & 0xffff)
+#define Blue64(x) ((x) & 0xffff)
+
 /*
  * Fetch from region strategies
  */
@@ -632,6 +638,30 @@ ACCESS(fbFetchTransformed)(bits_image_t * pict, int x, int y, int width,
     }
 }
 
+void
+ACCESS(fbFetchTransformed64)(bits_image_t * pict, int x, int y, int width,
+                             uint64_t *buffer, uint64_t *mask, uint32_t maskBits)
+{
+    // TODO: Don't lose precision for wide pictures!
+    uint32_t *mask8 = NULL;
+
+    // Contract the mask image, if one exists, so that the 32-bit fetch function
+    // can use it.
+    if (mask) {
+        mask8 = pixman_malloc_ab(width, sizeof(uint32_t));
+        pixman_contract(mask8, mask, width);
+    }
+
+    // Fetch the image into the first half of buffer.
+    ACCESS(fbFetchTransformed)(pict, x, y, width, (uint32_t*)buffer, mask8,
+                               maskBits);
+
+    // Expand from 32bpp to 64bpp in place.
+    pixman_expand(buffer, (uint32_t*)buffer, pict->format, width);
+
+    free(mask8);
+}
+
 #define SCANLINE_BUFFER_LENGTH 2048
 
 void
@@ -670,6 +700,45 @@ ACCESS(fbFetchExternalAlpha)(bits_image_t * pict, int x, int y, int width,
 }
 
 void
+ACCESS(fbFetchExternalAlpha64)(bits_image_t * pict, int x, int y, int width,
+                               uint64_t *buffer, uint64_t *mask,
+                               uint32_t maskBits)
+{
+    int i;
+    uint64_t _alpha_buffer[SCANLINE_BUFFER_LENGTH];
+    uint64_t *alpha_buffer = _alpha_buffer;
+    uint64_t maskBits64;
+
+    if (!pict->common.alpha_map) {
+        ACCESS(fbFetchTransformed64) (pict, x, y, width, buffer, mask, maskBits);
+	return;
+    }
+    if (width > SCANLINE_BUFFER_LENGTH)
+        alpha_buffer = (uint64_t *) pixman_malloc_ab (width, sizeof(uint64_t));
+
+    ACCESS(fbFetchTransformed64)(pict, x, y, width, buffer, mask, maskBits);
+    ACCESS(fbFetchTransformed64)((bits_image_t *)pict->common.alpha_map, x - pict->common.alpha_origin.x,
+                                 y - pict->common.alpha_origin.y, width,
+                                 alpha_buffer, mask, maskBits);
+
+    pixman_expand(&maskBits64, &maskBits, PIXMAN_a8r8g8b8, 1);
+
+    for (i = 0; i < width; ++i) {
+        if (!mask || mask[i] & maskBits64)
+	{
+	    int64_t a = alpha_buffer[i]>>48;
+	    *(buffer + i) = (a << 48)
+		| (div_65535(Red64(*(buffer + i)) * a) << 32)
+		| (div_65535(Green64(*(buffer + i)) * a) << 16)
+		| (div_65535(Blue64(*(buffer + i)) * a));
+	}
+    }
+
+    if (alpha_buffer != _alpha_buffer)
+        free(alpha_buffer);
+}
+
+void
 ACCESS(fbStoreExternalAlpha)(bits_image_t * pict, int x, int y, int width,
                              uint32_t *buffer)
 {
@@ -710,3 +779,36 @@ ACCESS(fbStoreExternalAlpha)(bits_image_t * pict, int x, int y, int width,
 	   alpha_bits, buffer, ax - pict->common.alpha_origin.x, width, aindexed);
 }
 
+void
+ACCESS(fbStoreExternalAlpha64)(bits_image_t * pict, int x, int y, int width,
+                               uint64_t *buffer)
+{
+    uint32_t *bits, *alpha_bits;
+    int32_t stride, astride;
+    int ax, ay;
+    storeProc64 store;
+    storeProc64 astore;
+    const pixman_indexed_t * indexed = pict->indexed;
+    const pixman_indexed_t * aindexed;
+
+    store = ACCESS(pixman_storeProcForPicture64)(pict);
+    astore = ACCESS(pixman_storeProcForPicture64)(pict->common.alpha_map);
+    aindexed = pict->common.alpha_map->indexed;
+
+    ax = x;
+    ay = y;
+
+    bits = pict->bits;
+    stride = pict->rowstride;
+
+    alpha_bits = pict->common.alpha_map->bits;
+    astride = pict->common.alpha_map->rowstride;
+
+    bits       += y*stride;
+    alpha_bits += (ay - pict->common.alpha_origin.y)*astride;
+
+
+    store((pixman_image_t *)pict, bits, buffer, x, width, indexed);
+    astore((pixman_image_t *)pict->common.alpha_map,
+	   alpha_bits, buffer, ax - pict->common.alpha_origin.x, width, aindexed);
+}
commit 42a3a2d6fc8d3e521c6914ff8fb89f1fbc673e28
Author: Aaron Plattner <aplattner at nvidia.com>
Date:   Fri Jun 6 15:45:17 2008 -0700

    Add wide fetch/store functions.
    
    Use the narrow ones and expand/contract where necessary.  Still need wide paths
    for fancy pictures, but this gets the basic stuff working.
    
    Signed-off-by: Søren Sandmann Pedersen <sandmann at redhat.com>

diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c
index 5609421..d5d3952 100644
--- a/pixman/pixman-access.c
+++ b/pixman/pixman-access.c
@@ -2,6 +2,7 @@
  *
  * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
  *             2005 Lars Knoll & Zack Rusin, Trolltech
+ *             2008 Aaron Plattner, NVIDIA Corporation
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -27,7 +28,9 @@
 #include <config.h>
 #endif
 
+#include <stdlib.h>
 #include <string.h>
+#include <assert.h>
 
 #include "pixman-private.h"
 
@@ -117,6 +120,52 @@ fbFetch_x8b8g8r8 (bits_image_t *pict, int x, int y, int width, uint32_t *buffer)
 }
 
 static FASTCALL void
+fbFetch_a2b10g10r10 (bits_image_t *pict, int x, int y, int width, uint64_t *buffer)
+{
+    const uint32_t *bits = pict->bits + y*pict->rowstride;
+    const uint32_t *pixel = bits + x;
+    const uint32_t *end = pixel + width;
+    while (pixel < end) {
+        uint32_t p = READ(pict, pixel++);
+        uint64_t a = p >> 30;
+        uint64_t b = (p >> 20) & 0x3ff;
+        uint64_t g = (p >> 10) & 0x3ff;
+        uint64_t r = p & 0x3ff;
+
+        r = r << 6 | r >> 4;
+        g = g << 6 | g >> 4;
+        b = b << 6 | b >> 4;
+
+        a <<= 62;
+        a |= a >> 2;
+        a |= a >> 4;
+        a |= a >> 8;
+
+        *buffer++ = a << 48 | r << 32 | g << 16 | b;
+    }
+}
+
+static FASTCALL void
+fbFetch_x2b10g10r10 (bits_image_t *pict, int x, int y, int width, uint64_t *buffer)
+{
+    const uint32_t *bits = pict->bits + y*pict->rowstride;
+    const uint32_t *pixel = (uint32_t *)bits + x;
+    const uint32_t *end = pixel + width;
+    while (pixel < end) {
+        uint32_t p = READ(pict, pixel++);
+        uint64_t b = (p >> 20) & 0x3ff;
+        uint64_t g = (p >> 10) & 0x3ff;
+        uint64_t r = p & 0x3ff;
+
+        r = r << 6 | r >> 4;
+        g = g << 6 | g >> 4;
+        b = b << 6 | b >> 4;
+
+        *buffer++ = 0xffffULL << 48 | r << 32 | g << 16 | b;
+    }
+}
+
+static FASTCALL void
 fbFetch_r8g8b8 (bits_image_t *pict, int x, int y, int width, uint32_t *buffer)
 {
     const uint32_t *bits = pict->bits + y*pict->rowstride;
@@ -644,6 +693,9 @@ fetchProc32 ACCESS(pixman_fetchProcForPicture32) (bits_image_t * pict)
     case PIXMAN_x8r8g8b8: return fbFetch_x8r8g8b8;
     case PIXMAN_a8b8g8r8: return fbFetch_a8b8g8r8;
     case PIXMAN_x8b8g8r8: return fbFetch_x8b8g8r8;
+    /* These two require wide compositing */
+    case PIXMAN_a2b10g10r10: return NULL;
+    case PIXMAN_x2b10g10r10: return NULL;
 
         /* 24bpp formats */
     case PIXMAN_r8g8b8: return fbFetch_r8g8b8;
@@ -693,8 +745,66 @@ fetchProc32 ACCESS(pixman_fetchProcForPicture32) (bits_image_t * pict)
     return NULL;
 }
 
+static FASTCALL void
+fbFetch64_generic (bits_image_t *pict, int x, int y, int width, uint64_t *buffer)
+{
+    fetchProc32 fetch32 = ACCESS(pixman_fetchProcForPicture32) (pict);
+
+    // Fetch the pixels into the first half of buffer and then expand them in
+    // place.
+    fetch32(pict, x, y, width, (uint32_t*)buffer);
+    pixman_expand(buffer, (uint32_t*)buffer, pict->format, width);
+}
+
+fetchProc64 ACCESS(pixman_fetchProcForPicture64) (bits_image_t * pict)
+{
+    switch(pict->format) {
+    case PIXMAN_a2b10g10r10: return fbFetch_a2b10g10r10;
+    case PIXMAN_x2b10g10r10: return fbFetch_x2b10g10r10;
+    default: return fbFetch64_generic;
+    }
+}
+
 /**************************** Pixel wise fetching *****************************/
 
+static FASTCALL uint64_t
+fbFetchPixel_a2b10g10r10 (bits_image_t *pict, int offset, int line)
+{
+    uint32_t *bits = pict->bits + line*pict->rowstride;
+    uint32_t p = READ(pict, bits + offset);
+    uint64_t a = p >> 30;
+    uint64_t b = (p >> 20) & 0x3ff;
+    uint64_t g = (p >> 10) & 0x3ff;
+    uint64_t r = p & 0x3ff;
+
+    r = r << 6 | r >> 4;
+    g = g << 6 | g >> 4;
+    b = b << 6 | b >> 4;
+
+    a <<= 62;
+    a |= a >> 2;
+    a |= a >> 4;
+    a |= a >> 8;
+
+    return a << 48 | r << 32 | g << 16 | b;
+}
+
+static FASTCALL uint64_t
+fbFetchPixel_x2b10g10r10 (bits_image_t *pict, int offset, int line)
+{
+    uint32_t *bits = pict->bits + line*pict->rowstride;
+    uint32_t p = READ(pict, bits + offset);
+    uint64_t b = (p >> 20) & 0x3ff;
+    uint64_t g = (p >> 10) & 0x3ff;
+    uint64_t r = p & 0x3ff;
+
+    r = r << 6 | r >> 4;
+    g = g << 6 | g >> 4;
+    b = b << 6 | b >> 4;
+
+    return 0xffffULL << 48 | r << 32 | g << 16 | b;
+}
+
 static FASTCALL uint32_t
 fbFetchPixel_a8r8g8b8 (bits_image_t *pict, int offset, int line)
 {
@@ -1155,6 +1265,9 @@ fetchPixelProc32 ACCESS(pixman_fetchPixelProcForPicture32) (bits_image_t * pict)
     case PIXMAN_x8r8g8b8: return fbFetchPixel_x8r8g8b8;
     case PIXMAN_a8b8g8r8: return fbFetchPixel_a8b8g8r8;
     case PIXMAN_x8b8g8r8: return fbFetchPixel_x8b8g8r8;
+    /* These two require wide compositing */
+    case PIXMAN_a2b10g10r10: return NULL;
+    case PIXMAN_x2b10g10r10: return NULL;
 
         /* 24bpp formats */
     case PIXMAN_r8g8b8: return fbFetchPixel_r8g8b8;
@@ -1204,12 +1317,62 @@ fetchPixelProc32 ACCESS(pixman_fetchPixelProcForPicture32) (bits_image_t * pict)
     return NULL;
 }
 
+static FASTCALL uint64_t
+fbFetchPixel64_generic (bits_image_t *pict, int offset, int line)
+{
+    fetchPixelProc32 fetchPixel32 = ACCESS(pixman_fetchPixelProcForPicture32) (pict);
+    uint32_t argb8Pixel = fetchPixel32(pict, offset, line);
+    uint64_t argb16Pixel;
+
+    pixman_expand(&argb16Pixel, &argb8Pixel, pict->format, 1);
+
+    return argb16Pixel;
+}
+
+fetchPixelProc64 ACCESS(pixman_fetchPixelProcForPicture64) (bits_image_t * pict)
+{
+    switch(pict->format) {
+    case PIXMAN_a2b10g10r10: return fbFetchPixel_a2b10g10r10;
+    case PIXMAN_x2b10g10r10: return fbFetchPixel_x2b10g10r10;
+    default: return fbFetchPixel64_generic;
+    }
+}
+
 /*********************************** Store ************************************/
 
 #define Splita(v)	uint32_t	a = ((v) >> 24), r = ((v) >> 16) & 0xff, g = ((v) >> 8) & 0xff, b = (v) & 0xff
 #define Split(v)	uint32_t	r = ((v) >> 16) & 0xff, g = ((v) >> 8) & 0xff, b = (v) & 0xff
 
 static FASTCALL void
+fbStore_a2b10g10r10 (pixman_image_t *image,
+		     uint32_t *bits, const uint64_t *values, int x, int width, const pixman_indexed_t * indexed)
+{
+    int i;
+    uint32_t *pixel = bits + x;
+    for (i = 0; i < width; ++i) {
+        WRITE(image, pixel++,
+            ((values[i] >> 32) & 0xc0000000) | // A
+            ((values[i] >> 38) & 0x3ff) |      // R
+            ((values[i] >> 12) & 0xffc00) |    // G
+            ((values[i] << 14) & 0x3ff00000)); // B
+    }
+}
+
+static FASTCALL void
+fbStore_x2b10g10r10 (pixman_image_t *image,
+		     uint32_t *bits, const uint64_t *values, int x, int width, const pixman_indexed_t * indexed)
+{
+    int i;
+    uint32_t *pixel = bits + x;
+    for (i = 0; i < width; ++i) {
+        WRITE(image, pixel++,
+            ((values[i] >> 38) & 0x3ff) |      // R
+            ((values[i] >> 12) & 0xffc00) |    // G
+            ((values[i] << 14) & 0x3ff00000)); // B
+    }
+}
+
+static FASTCALL void
 fbStore_a8r8g8b8 (pixman_image_t *image,
 		  uint32_t *bits, const uint32_t *values, int x, int width, const pixman_indexed_t * indexed)
 {
@@ -1679,6 +1842,41 @@ storeProc32 ACCESS(pixman_storeProcForPicture32) (bits_image_t * pict)
     }
 }
 
+/*
+ * Contracts a 64bpp image to 32bpp and then stores it using a regular 32-bit
+ * store proc.
+ */
+static FASTCALL void
+fbStore64_generic (pixman_image_t *image,
+		   uint32_t *bits, const uint64_t *values, int x, int width, const pixman_indexed_t * indexed)
+{
+    bits_image_t *pict = (bits_image_t*)image;
+    storeProc32 store32 = ACCESS(pixman_storeProcForPicture32) (pict);
+    uint32_t *argb8Pixels;
+
+    assert(image->common.type == BITS);
+    assert(store32);
+
+    argb8Pixels = malloc(sizeof(uint32_t) * width);
+    if (!argb8Pixels) return;
+
+    // Contract the scanline.  We could do this in place if values weren't
+    // const.
+    pixman_contract(argb8Pixels, values, width);
+    store32(image, bits, argb8Pixels, x, width, indexed);
+
+    free(argb8Pixels);
+}
+
+storeProc64 ACCESS(pixman_storeProcForPicture64) (bits_image_t * pict)
+{
+    switch(pict->format) {
+    case PIXMAN_a2b10g10r10: return fbStore_a2b10g10r10;
+    case PIXMAN_x2b10g10r10: return fbStore_x2b10g10r10;
+    default: return fbStore64_generic;
+    }
+}
+
 #ifndef PIXMAN_FB_ACCESSORS
 /*
  * This function expands images from ARGB8 format to ARGB16.  To preserve
diff --git a/pixman/pixman-compose.c b/pixman/pixman-compose.c
index 616fbc4..c5773eb 100644
--- a/pixman/pixman-compose.c
+++ b/pixman/pixman-compose.c
@@ -2,6 +2,7 @@
  *
  * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
  *             2005 Lars Knoll & Zack Rusin, Trolltech
+ *             2008 Aaron Plattner, NVIDIA Corporation
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -114,6 +115,19 @@ static void fbFetchSolid(bits_image_t * pict, int x, int y, int width, uint32_t
 	*(buffer++) = color;
 }
 
+static void fbFetchSolid64(bits_image_t * pict, int x, int y, int width, uint64_t *buffer, void *unused, uint32_t unused2)
+{
+    uint64_t color;
+    uint64_t *end;
+    fetchPixelProc64 fetch = ACCESS(pixman_fetchPixelProcForPicture64)(pict);
+
+    color = fetch(pict, 0, 0);
+
+    end = buffer + width;
+    while (buffer < end)
+	*(buffer++) = color;
+}
+
 static void fbFetch(bits_image_t * pict, int x, int y, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits)
 {
     fetchProc32 fetch = ACCESS(pixman_fetchProcForPicture32)(pict);
@@ -121,6 +135,13 @@ static void fbFetch(bits_image_t * pict, int x, int y, int width, uint32_t *buff
     fetch(pict, x, y, width, buffer);
 }
 
+static void fbFetch64(bits_image_t * pict, int x, int y, int width, uint64_t *buffer, void *unused, uint32_t unused2)
+{
+    fetchProc64 fetch = ACCESS(pixman_fetchProcForPicture64)(pict);
+
+    fetch(pict, x, y, width, buffer);
+}
+
 static void
 fbStore(bits_image_t * pict, int x, int y, int width, uint32_t *buffer)
 {
@@ -135,6 +156,20 @@ fbStore(bits_image_t * pict, int x, int y, int width, uint32_t *buffer)
     store((pixman_image_t *)pict, bits, buffer, x, width, indexed);
 }
 
+static void
+fbStore64(bits_image_t * pict, int x, int y, int width, uint64_t *buffer)
+{
+    uint32_t *bits;
+    int32_t stride;
+    storeProc64 store = ACCESS(pixman_storeProcForPicture64)(pict);
+    const pixman_indexed_t * indexed = pict->indexed;
+
+    bits = pict->bits;
+    stride = pict->rowstride;
+    bits += y*stride;
+    store((pixman_image_t *)pict, bits, buffer, x, width, indexed);
+}
+
 typedef void (*scanStoreProc)(pixman_image_t *, int, int, int, uint32_t *);
 typedef void (*scanFetchProc)(pixman_image_t *, int, int, int, uint32_t *,
 			      uint32_t *, uint32_t);
@@ -171,22 +206,24 @@ PIXMAN_COMPOSITE_RECT_GENERAL (const FbComposeData *data,
 
 	if (bits->common.alpha_map)
 	{
+	    // TODO: Need wide external alpha routine.
 	    fetchSrc = (scanFetchProc)ACCESS(fbFetchExternalAlpha);
 	}
 	else if ((bits->common.repeat == PIXMAN_REPEAT_NORMAL || bits->common.repeat == PIXMAN_REPEAT_PAD) &&
 		 bits->width == 1 &&
 		 bits->height == 1)
 	{
-	    fetchSrc = (scanFetchProc)fbFetchSolid;
+	    fetchSrc = wide ? (scanFetchProc)fbFetchSolid64 : (scanFetchProc)fbFetchSolid;
 	    srcClass = SOURCE_IMAGE_CLASS_HORIZONTAL;
 	}
 	else if (!bits->common.transform && bits->common.filter != PIXMAN_FILTER_CONVOLUTION
                 && bits->common.repeat != PIXMAN_REPEAT_PAD)
 	{
-	    fetchSrc = (scanFetchProc)fbFetch;
+	    fetchSrc = wide ? (scanFetchProc)fbFetch64 : (scanFetchProc)fbFetch;
 	}
 	else
 	{
+	    // TODO: Need wide transformed fetch.
 	    fetchSrc = (scanFetchProc)ACCESS(fbFetchTransformed);
 	}
     }
@@ -210,24 +247,27 @@ PIXMAN_COMPOSITE_RECT_GENERAL (const FbComposeData *data,
 
 	    if (bits->common.alpha_map)
 	    {
+		// TODO: Need wide external alpha routine.
 		fetchMask = (scanFetchProc)ACCESS(fbFetchExternalAlpha);
 	    }
 	    else if ((bits->common.repeat == PIXMAN_REPEAT_NORMAL || bits->common.repeat == PIXMAN_REPEAT_PAD) &&
 		     bits->width == 1 && bits->height == 1)
 	    {
-		fetchMask = (scanFetchProc)fbFetchSolid;
+		fetchMask = wide ? (scanFetchProc)fbFetchSolid64 : (scanFetchProc)fbFetchSolid;
 		maskClass = SOURCE_IMAGE_CLASS_HORIZONTAL;
 	    }
 	    else if (!bits->common.transform && bits->common.filter != PIXMAN_FILTER_CONVOLUTION
                     && bits->common.repeat != PIXMAN_REPEAT_PAD)
-		fetchMask = (scanFetchProc)fbFetch;
+		fetchMask = wide ? (scanFetchProc)fbFetch64 : (scanFetchProc)fbFetch;
 	    else
+		// TODO: Need wide transformed fetch.
 		fetchMask = (scanFetchProc)ACCESS(fbFetchTransformed);
 	}
     }
 
     if (data->dest->common.alpha_map)
     {
+	// TODO: Need wide external alpha routine.
 	fetchDest = (scanFetchProc)ACCESS(fbFetchExternalAlpha);
 	store = (scanStoreProc)ACCESS(fbStoreExternalAlpha);
 
@@ -236,8 +276,8 @@ PIXMAN_COMPOSITE_RECT_GENERAL (const FbComposeData *data,
     }
     else
     {
-	fetchDest = (scanFetchProc)fbFetch;
-	store = (scanStoreProc)fbStore;
+	fetchDest = wide ? (scanFetchProc)fbFetch64 : (scanFetchProc)fbFetch;
+	store = wide ? (scanStoreProc)fbStore64 : (scanStoreProc)fbStore;
 
 	switch (data->op)
 	{
@@ -251,7 +291,11 @@ PIXMAN_COMPOSITE_RECT_GENERAL (const FbComposeData *data,
 	    switch (data->dest->bits.format) {
 	    case PIXMAN_a8r8g8b8:
 	    case PIXMAN_x8r8g8b8:
-		store = NULL;
+		// Skip the store step and composite directly into the
+		// destination if the output format of the compose func matches
+		// the destination format.
+		if (!wide)
+		    store = NULL;
 		break;
 	    default:
 		break;
diff --git a/pixman/pixman-utils.c b/pixman/pixman-utils.c
index ed6c255..f013ae7 100644
--- a/pixman/pixman-utils.c
+++ b/pixman/pixman-utils.c
@@ -467,6 +467,8 @@ pixman_format_supported_destination (pixman_format_code_t format)
 {
     switch (format) {
     /* 32 bpp formats */
+    case PIXMAN_a2b10g10r10:
+    case PIXMAN_x2b10g10r10:
     case PIXMAN_a8r8g8b8:
     case PIXMAN_x8r8g8b8:
     case PIXMAN_a8b8g8r8:
diff --git a/pixman/pixman.h b/pixman/pixman.h
index 78dee13..10871a3 100644
--- a/pixman/pixman.h
+++ b/pixman/pixman.h
@@ -517,7 +517,9 @@ typedef enum {
     PIXMAN_x8r8g8b8 =	PIXMAN_FORMAT(32,PIXMAN_TYPE_ARGB,0,8,8,8),
     PIXMAN_a8b8g8r8 =	PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,8,8,8,8),
     PIXMAN_x8b8g8r8 =	PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,0,8,8,8),
-    
+    PIXMAN_x2b10g10r10 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,0,10,10,10),
+    PIXMAN_a2b10g10r10 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,2,10,10,10),
+
 /* 24bpp formats */
     PIXMAN_r8g8b8 =	PIXMAN_FORMAT(24,PIXMAN_TYPE_ARGB,0,8,8,8),
     PIXMAN_b8g8r8 =	PIXMAN_FORMAT(24,PIXMAN_TYPE_ABGR,0,8,8,8),
commit 7591d3f1d7e0884f9362018edf720724095cf380
Author: Aaron Plattner <aplattner at nvidia.com>
Date:   Fri Jun 6 15:30:52 2008 -0700

    Add expand and contract functions to convert between ARGB8 and ARGB16.
    
    The expansion function isn't quite correct, but gives reasonable results.
    
    Signed-off-by: Søren Sandmann Pedersen <sandmann at redhat.com>

diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c
index 29b846c..5609421 100644
--- a/pixman/pixman-access.c
+++ b/pixman/pixman-access.c
@@ -1678,3 +1678,49 @@ storeProc32 ACCESS(pixman_storeProcForPicture32) (bits_image_t * pict)
         return NULL;
     }
 }
+
+#ifndef PIXMAN_FB_ACCESSORS
+/*
+ * This function expands images from ARGB8 format to ARGB16.  To preserve
+ * precision, it needs to know the original source format.  For example, if the
+ * source was PIXMAN_x1r5g5b5 and the red component contained bits 12345, then
+ * the expanded value is 12345123.  To correctly expand this to 16 bits, it
+ * should be 1234512345123451 and not 1234512312345123.
+ *
+ * XXX[AGP]: For now, this just does naïve byte replication.
+ */
+void pixman_expand(uint64_t *dst, const uint32_t *src,
+                   pixman_format_code_t format, int width)
+{
+    /* Start at the end so that we can do the expansion in place when src == dst */
+    for (width--; width >= 0; width--)
+    {
+        const uint8_t a = src[width] >> 24,
+                      r = src[width] >> 16,
+                      g = src[width] >> 8,
+                      b = src[width];
+        dst[width] = (uint64_t)a << 56 | (uint64_t) a << 48 |
+                     (uint64_t)r << 40 | (uint64_t) r << 32 |
+                     (uint64_t)g << 24 | (uint64_t) g << 16 |
+                     (uint64_t)b << 8 | (uint64_t)b;
+    }
+}
+
+/*
+ * Contracting is easier than expanding.  We just need to truncate the
+ * components.
+ */
+void pixman_contract(uint32_t *dst, const uint64_t *src, int width)
+{
+    /* Start at the beginning so that we can do the contraction in place when
+     * src == dst */
+    for (width--; width >= 0; width--, src++, dst++)
+    {
+        const uint8_t a = *src >> 56,
+                      r = *src >> 40,
+                      g = *src >> 24,
+                      b = *src >> 8;
+        *dst = a << 24 | r << 16 | g << 8 | b;
+    }
+}
+#endif // PIXMAN_FB_ACCESSORS
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index 0ea0cb3..5a2f89e 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -214,6 +214,9 @@ fetchProc64 pixman_fetchProcForPicture64_accessors (bits_image_t *);
 fetchPixelProc64 pixman_fetchPixelProcForPicture64_accessors (bits_image_t *);
 storeProc64 pixman_storeProcForPicture64_accessors (bits_image_t *);
 
+void pixman_expand(uint64_t *dst, const uint32_t *src, pixman_format_code_t, int width);
+void pixman_contract(uint32_t *dst, const uint64_t *src, int width);
+
 void pixmanFetchSourcePict(source_image_t *, int x, int y, int width,
                            uint32_t *buffer, uint32_t *mask, uint32_t maskBits);
 
diff --git a/pixman/pixman.h b/pixman/pixman.h
index 7f74594..78dee13 100644
--- a/pixman/pixman.h
+++ b/pixman/pixman.h
@@ -495,6 +495,10 @@ struct pixman_indexed
 				 PIXMAN_FORMAT_R(f) +	\
 				 PIXMAN_FORMAT_G(f) +	\
 				 PIXMAN_FORMAT_B(f))
+#define PIXMAN_FORMAT_16BPC(f)	(PIXMAN_FORMAT_A(f) > 8 || \
+				 PIXMAN_FORMAT_R(f) > 8 || \
+				 PIXMAN_FORMAT_G(f) > 8 || \
+				 PIXMAN_FORMAT_B(f) > 8)
 
 #define PIXMAN_TYPE_OTHER	0
 #define PIXMAN_TYPE_A		1


More information about the xorg-commit mailing list