pixman: Add support for argb/xrgb float formats, v5.
authorMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Wed, 30 May 2018 14:07:10 +0000 (16:07 +0200)
committerMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Tue, 6 Nov 2018 13:24:05 +0000 (14:24 +0100)
Pixman is already using the floating point formats internally, expose
this capability in case someone wants to support higher bit per
component formats.

This is useful for igt which depends on cairo to do the rendering.
It can use it to convert floats internally to planar Y'CbCr formats,
or to F16.

We add a new type PIXMAN_TYPE_RGBA_FLOAT for this format, which is an
all float array of R, G, B, and A. Formats that use mixed float/int
RGBA aren't supported, and will probably need their own type.

Changes since v1:
- Use RGBA 128 bits and RGB 96 bits memory layouts, to better match the opengl format.
Changes since v2:
- Add asserts in accessor and for strides to force alignment.
- Move test changes to their own commit.
Changes since v3:
- Define 32bpc as PIXMAN_FORMAT_PACKED_C32
- Rename pixman accessors from rgb*_float_float to rgb*f_float
Changes since v4:
- Create a new PIXMAN_FORMAT_BYTE for fitting up to 64 bits per component.
  (based on Siarhei Siamashka's suggestion)
- Use new format type PIXMAN_TYPE_RGBA_FLOAT

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> #v4
[mlankhorst: Fix missing braces in PIXMAN_FORMAT_RESHIFT macro]

pixman/pixman-access.c
pixman/pixman-bits-image.c
pixman/pixman-image.c
pixman/pixman.c
pixman/pixman.h

index 4f0642d7778563aef43ded06a0fefe0fc170f576..8dfd35f45063cde8fda6b6ff75e13c58e8bcbff0 100644 (file)
@@ -642,6 +642,48 @@ fetch_scanline_a2r10g10b10_float (bits_image_t *  image,
 }
 
 /* Expects a float buffer */
+#ifndef PIXMAN_FB_ACCESSORS
+static void
+fetch_scanline_rgbf_float (bits_image_t   *image,
+                          int             x,
+                          int             y,
+                          int             width,
+                          uint32_t *      b,
+                          const uint32_t *mask)
+{
+    const float *bits = (float *)image->bits + y * image->rowstride;
+    const float *pixel = bits + x * 3;
+    argb_t *buffer = (argb_t *)b;
+
+    for (; width--; buffer++) {
+       buffer->r = *pixel++;
+       buffer->g = *pixel++;
+       buffer->b = *pixel++;
+       buffer->a = 1.f;
+    }
+}
+
+static void
+fetch_scanline_rgbaf_float (bits_image_t   *image,
+                           int             x,
+                           int             y,
+                           int             width,
+                           uint32_t *      b,
+                           const uint32_t *mask)
+{
+    const float *bits = (float *)image->bits + y * image->rowstride;
+    const float *pixel = bits + x * 4;
+    argb_t *buffer = (argb_t *)b;
+
+    for (; width--; buffer++) {
+       buffer->r = *pixel++;
+       buffer->g = *pixel++;
+       buffer->b = *pixel++;
+       buffer->a = *pixel++;
+    }
+}
+#endif
+
 static void
 fetch_scanline_x2r10g10b10_float (bits_image_t   *image,
                                  int             x,
@@ -805,6 +847,40 @@ fetch_scanline_yv12 (bits_image_t   *image,
 
 /**************************** Pixel wise fetching *****************************/
 
+#ifndef PIXMAN_FB_ACCESSORS
+static argb_t
+fetch_pixel_rgbf_float (bits_image_t *image,
+                       int         offset,
+                       int         line)
+{
+    float *bits = (float *)image->bits + line * image->rowstride;
+    argb_t argb;
+
+    argb.r = bits[offset * 3];
+    argb.g = bits[offset * 3 + 1];
+    argb.b = bits[offset * 3 + 2];
+    argb.a = 1.f;
+
+    return argb;
+}
+
+static argb_t
+fetch_pixel_rgbaf_float (bits_image_t *image,
+                        int        offset,
+                        int        line)
+{
+    float *bits = (float *)image->bits + line * image->rowstride;
+    argb_t argb;
+
+    argb.r = bits[offset * 4];
+    argb.g = bits[offset * 4 + 1];
+    argb.b = bits[offset * 4 + 2];
+    argb.a = bits[offset * 4 + 3];
+
+    return argb;
+}
+#endif
+
 static argb_t
 fetch_pixel_x2r10g10b10_float (bits_image_t *image,
                               int         offset,
@@ -962,6 +1038,45 @@ fetch_pixel_yv12 (bits_image_t *image,
 
 /*********************************** Store ************************************/
 
+#ifndef PIXMAN_FB_ACCESSORS
+static void
+store_scanline_rgbaf_float (bits_image_t *  image,
+                           int             x,
+                           int             y,
+                           int             width,
+                           const uint32_t *v)
+{
+    float *bits = (float *)image->bits + image->rowstride * y + 4 * x;
+    const argb_t *values = (argb_t *)v;
+
+    for (; width; width--, values++)
+    {
+       *bits++ = values->r;
+       *bits++ = values->g;
+       *bits++ = values->b;
+       *bits++ = values->a;
+    }
+}
+
+static void
+store_scanline_rgbf_float (bits_image_t *  image,
+                          int             x,
+                          int             y,
+                          int             width,
+                          const uint32_t *v)
+{
+    float *bits = (float *)image->bits + image->rowstride * y + 3 * x;
+    const argb_t *values = (argb_t *)v;
+
+    for (; width; width--, values++)
+    {
+       *bits++ = values->r;
+       *bits++ = values->g;
+       *bits++ = values->b;
+    }
+}
+#endif
+
 static void
 store_scanline_a2r10g10b10_float (bits_image_t *  image,
                                  int             x,
@@ -1351,7 +1466,18 @@ static const format_info_t accessors[] =
     FORMAT_INFO (g1),
     
 /* Wide formats */
-    
+#ifndef PIXMAN_FB_ACCESSORS
+    { PIXMAN_rgba_float,
+      NULL, fetch_scanline_rgbaf_float,
+      fetch_pixel_generic_lossy_32, fetch_pixel_rgbaf_float,
+      NULL, store_scanline_rgbaf_float },
+
+    { PIXMAN_rgb_float,
+      NULL, fetch_scanline_rgbf_float,
+      fetch_pixel_generic_lossy_32, fetch_pixel_rgbf_float,
+      NULL, store_scanline_rgbf_float },
+#endif
+
     { PIXMAN_a2r10g10b10,
       NULL, fetch_scanline_a2r10g10b10_float,
       fetch_pixel_generic_lossy_32, fetch_pixel_a2r10g10b10_float,
index dcdcc69946dede2bb9967bfa81edb481a1e965ad..9fb91ff5831df6b6892d3010e4b42ad45a50f02a 100644 (file)
@@ -948,6 +948,9 @@ _pixman_bits_image_init (pixman_image_t *     image,
 {
     uint32_t *free_me = NULL;
 
+    if (PIXMAN_FORMAT_BPP (format) == 128)
+       return_val_if_fail(!(rowstride % 4), FALSE);
+
     if (!bits && width && height)
     {
        int rowstride_bytes;
index 681864eb7d17f743204827a60012b20984e589aa..7a851e2219921d49c013349fbe971a437087b02e 100644 (file)
@@ -842,6 +842,10 @@ pixman_image_set_accessors (pixman_image_t *           image,
 
     if (image->type == BITS)
     {
+       /* Accessors only work for <= 32 bpp. */
+       if (PIXMAN_FORMAT_BPP(image->bits.format) > 32)
+           return_if_fail (!read_func && !write_func);
+
        image->bits.read_func = read_func;
        image->bits.write_func = write_func;
 
index f932eac3c1b6fbf82033c5aa4a5c8c80484d5837..c09b5280831faa177640e7030ad452ffdc936e0d 100644 (file)
@@ -777,6 +777,11 @@ color_to_pixel (const pixman_color_t *color,
 {
     uint32_t c = color_to_uint32 (color);
 
+    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_RGBA_FLOAT)
+    {
+       return FALSE;
+    }
+
     if (!(format == PIXMAN_a8r8g8b8     ||
           format == PIXMAN_x8r8g8b8     ||
           format == PIXMAN_a8b8g8r8     ||
index 509ba5e534a80e285b308dae7cfc8ff3f3d3ce15..d644589d614c0967455bce5a874619abd975727a 100644 (file)
@@ -654,12 +654,24 @@ struct pixman_indexed
                                         ((g) << 4) |     \
                                         ((b)))
 
-#define PIXMAN_FORMAT_BPP(f)   (((f) >> 24)       )
-#define PIXMAN_FORMAT_TYPE(f)  (((f) >> 16) & 0xff)
-#define PIXMAN_FORMAT_A(f)     (((f) >> 12) & 0x0f)
-#define PIXMAN_FORMAT_R(f)     (((f) >>  8) & 0x0f)
-#define PIXMAN_FORMAT_G(f)     (((f) >>  4) & 0x0f)
-#define PIXMAN_FORMAT_B(f)     (((f)      ) & 0x0f)
+#define PIXMAN_FORMAT_BYTE(bpp,type,a,r,g,b) \
+       (((bpp >> 3) << 24) | \
+       (3 << 22) | ((type) << 16) | \
+       ((a >> 3) << 12) | \
+       ((r >> 3) << 8) | \
+       ((g >> 3) << 4) | \
+       ((b >> 3)))
+
+#define PIXMAN_FORMAT_RESHIFT(val, ofs, num) \
+       (((val >> (ofs)) & ((1 << (num)) - 1)) << ((val >> 22) & 3))
+
+#define PIXMAN_FORMAT_BPP(f)   PIXMAN_FORMAT_RESHIFT(f, 24, 8)
+#define PIXMAN_FORMAT_SHIFT(f) ((uint32_t)((f >> 22) & 3))
+#define PIXMAN_FORMAT_TYPE(f)  (((f) >> 16) & 0x3f)
+#define PIXMAN_FORMAT_A(f)     PIXMAN_FORMAT_RESHIFT(f, 12, 4)
+#define PIXMAN_FORMAT_R(f)     PIXMAN_FORMAT_RESHIFT(f, 8, 4)
+#define PIXMAN_FORMAT_G(f)     PIXMAN_FORMAT_RESHIFT(f, 4, 4)
+#define PIXMAN_FORMAT_B(f)     PIXMAN_FORMAT_RESHIFT(f, 0, 4)
 #define PIXMAN_FORMAT_RGB(f)   (((f)      ) & 0xfff)
 #define PIXMAN_FORMAT_VIS(f)   (((f)      ) & 0xffff)
 #define PIXMAN_FORMAT_DEPTH(f) (PIXMAN_FORMAT_A(f) +   \
@@ -678,15 +690,22 @@ struct pixman_indexed
 #define PIXMAN_TYPE_BGRA       8
 #define PIXMAN_TYPE_RGBA       9
 #define PIXMAN_TYPE_ARGB_SRGB  10
+#define PIXMAN_TYPE_RGBA_FLOAT 11
 
 #define PIXMAN_FORMAT_COLOR(f)                         \
        (PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_ARGB ||   \
         PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_ABGR ||   \
         PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_BGRA ||   \
-        PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_RGBA)
+        PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_RGBA ||   \
+        PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_RGBA_FLOAT)
 
-/* 32bpp formats */
 typedef enum {
+/* 128bpp formats */
+    PIXMAN_rgba_float =        PIXMAN_FORMAT_BYTE(128,PIXMAN_TYPE_RGBA_FLOAT,32,32,32,32),
+/* 96bpp formats */
+    PIXMAN_rgb_float = PIXMAN_FORMAT_BYTE(96,PIXMAN_TYPE_RGBA_FLOAT,0,32,32,32),
+
+/* 32bpp formats */
     PIXMAN_a8r8g8b8 =   PIXMAN_FORMAT(32,PIXMAN_TYPE_ARGB,8,8,8,8),
     PIXMAN_x8r8g8b8 =   PIXMAN_FORMAT(32,PIXMAN_TYPE_ARGB,0,8,8,8),
     PIXMAN_a8b8g8r8 =   PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,8,8,8,8),