Add wide fetch/store functions.
authorAaron Plattner <aplattner@nvidia.com>
Fri, 6 Jun 2008 22:45:17 +0000 (15:45 -0700)
committerSøren Sandmann Pedersen <sandmann@redhat.com>
Fri, 13 Jun 2008 04:11:37 +0000 (00:11 -0400)
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@redhat.com>
pixman/pixman-access.c
pixman/pixman-compose.c
pixman/pixman-utils.c
pixman/pixman.h

index 5609421..d5d3952 100644 (file)
@@ -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
index 616fbc4..c5773eb 100644 (file)
@@ -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;
index ed6c255..f013ae7 100644 (file)
@@ -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:
index 78dee13..10871a3 100644 (file)
@@ -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),