[1/2] pixman: Add support for argb/xrgb float formats, v3.

Submitted by Maarten Lankhorst on Aug. 1, 2018, 12:41 p.m.

Details

Message ID 20180801124134.27779-2-maarten.lankhorst@linux.intel.com
State New
Series "Add float support to pixman"
Headers show

Commit Message

Maarten Lankhorst Aug. 1, 2018, 12:41 p.m.
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.

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.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
---
 pixman/pixman-access.c     | 128 ++++++++++++++++++++++++++++++++++++-
 pixman/pixman-bits-image.c |   3 +
 pixman/pixman-image.c      |   4 ++
 pixman/pixman.h            |  32 ++++++----
 4 files changed, 155 insertions(+), 12 deletions(-)

Patch hide | download patch | download mbox

diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c
index 4f0642d77785..10fa049becf4 100644
--- a/pixman/pixman-access.c
+++ b/pixman/pixman-access.c
@@ -642,6 +642,48 @@  fetch_scanline_a2r10g10b10_float (bits_image_t *  image,
 }
 
 /* Expects a float buffer */
+#ifndef PIXMAN_FB_ACCESSORS
+static void
+fetch_scanline_rgb_float_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_rgba_float_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_rgb_float_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_rgba_float_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_rgba_float_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_rgb_float_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_rgba_float_float,
+      fetch_pixel_generic_lossy_32, fetch_pixel_rgba_float_float,
+      NULL, store_scanline_rgba_float_float },
+
+    { PIXMAN_rgb_float,
+      NULL, fetch_scanline_rgb_float_float,
+      fetch_pixel_generic_lossy_32, fetch_pixel_rgb_float_float,
+      NULL, store_scanline_rgb_float_float },
+#endif
+
     { PIXMAN_a2r10g10b10,
       NULL, fetch_scanline_a2r10g10b10_float,
       fetch_pixel_generic_lossy_32, fetch_pixel_a2r10g10b10_float,
diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index dcdcc69946de..9fb91ff5831d 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -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;
diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c
index 681864eb7d17..7a851e221992 100644
--- a/pixman/pixman-image.c
+++ b/pixman/pixman-image.c
@@ -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;
 
diff --git a/pixman/pixman.h b/pixman/pixman.h
index 509ba5e534a8..c9bf4faa80d4 100644
--- a/pixman/pixman.h
+++ b/pixman/pixman.h
@@ -647,19 +647,24 @@  struct pixman_indexed
  * sample implementation allows only packed RGB and GBR
  * representations for data to simplify software rendering,
  */
-#define PIXMAN_FORMAT(bpp,type,a,r,g,b)	(((bpp) << 24) |  \
+#define PIXMAN_FORMAT_PACKC(val) ((val) <= 10 ? (val) : \
+				 (val) == 32 ? 11 : 0)
+#define PIXMAN_FORMAT_UNPACKC(val) ((val) <= 10 ? (val) : \
+				    (val) == 11 ? 32 : 0)
+
+#define PIXMAN_FORMAT(bpp,type,a,r,g,b)	((((uint32_t)(bpp)) << 24) |  \
 					 ((type) << 16) | \
-					 ((a) << 12) |	  \
-					 ((r) << 8) |	  \
-					 ((g) << 4) |	  \
-					 ((b)))
+					 (PIXMAN_FORMAT_PACKC(a) << 12) |	  \
+					 (PIXMAN_FORMAT_PACKC(r) << 8) |	  \
+					 (PIXMAN_FORMAT_PACKC(g) << 4) |	  \
+					 (PIXMAN_FORMAT_PACKC(b)))
 
-#define PIXMAN_FORMAT_BPP(f)	(((f) >> 24)       )
+#define PIXMAN_FORMAT_BPP(f)	(((uint32_t)(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_A(f)	PIXMAN_FORMAT_UNPACKC(((f) >> 12) & 0x0f)
+#define PIXMAN_FORMAT_R(f)	PIXMAN_FORMAT_UNPACKC(((f) >>  8) & 0x0f)
+#define PIXMAN_FORMAT_G(f)	PIXMAN_FORMAT_UNPACKC(((f) >>  4) & 0x0f)
+#define PIXMAN_FORMAT_B(f)	PIXMAN_FORMAT_UNPACKC(((f) >>  0) & 0x0f)
 #define PIXMAN_FORMAT_RGB(f)	(((f)      ) & 0xfff)
 #define PIXMAN_FORMAT_VIS(f)	(((f)      ) & 0xffff)
 #define PIXMAN_FORMAT_DEPTH(f)	(PIXMAN_FORMAT_A(f) +	\
@@ -685,8 +690,13 @@  struct pixman_indexed
 	 PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_BGRA ||	\
 	 PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_RGBA)
 
-/* 32bpp formats */
 typedef enum {
+/* 128bpp formats */
+    PIXMAN_rgba_float =	PIXMAN_FORMAT(128,PIXMAN_TYPE_ARGB,32,32,32,32),
+/* 96bpp formats */
+    PIXMAN_rgb_float =	PIXMAN_FORMAT(96,PIXMAN_TYPE_ARGB,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),

Comments

Bryce Harrington Aug. 3, 2018, 5:01 a.m.
On Wed, Aug 01, 2018 at 02:41:33PM +0200, Maarten Lankhorst wrote:
> 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.
> 
> 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.
> 
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> ---
>  pixman/pixman-access.c     | 128 ++++++++++++++++++++++++++++++++++++-
>  pixman/pixman-bits-image.c |   3 +
>  pixman/pixman-image.c      |   4 ++
>  pixman/pixman.h            |  32 ++++++----
>  4 files changed, 155 insertions(+), 12 deletions(-)
> 
> diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c
> index 4f0642d77785..10fa049becf4 100644
> --- a/pixman/pixman-access.c
> +++ b/pixman/pixman-access.c
> @@ -642,6 +642,48 @@ fetch_scanline_a2r10g10b10_float (bits_image_t *  image,
>  }
>  
>  /* Expects a float buffer */
> +#ifndef PIXMAN_FB_ACCESSORS
> +static void
> +fetch_scanline_rgb_float_float (bits_image_t   *image,

Just out of curiosity, why are these routines named with float twice?

Bryce

> +				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_rgba_float_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_rgb_float_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_rgba_float_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_rgba_float_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_rgb_float_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_rgba_float_float,
> +      fetch_pixel_generic_lossy_32, fetch_pixel_rgba_float_float,
> +      NULL, store_scanline_rgba_float_float },
> +
> +    { PIXMAN_rgb_float,
> +      NULL, fetch_scanline_rgb_float_float,
> +      fetch_pixel_generic_lossy_32, fetch_pixel_rgb_float_float,
> +      NULL, store_scanline_rgb_float_float },
> +#endif
> +
>      { PIXMAN_a2r10g10b10,
>        NULL, fetch_scanline_a2r10g10b10_float,
>        fetch_pixel_generic_lossy_32, fetch_pixel_a2r10g10b10_float,
> diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
> index dcdcc69946de..9fb91ff5831d 100644
> --- a/pixman/pixman-bits-image.c
> +++ b/pixman/pixman-bits-image.c
> @@ -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;
> diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c
> index 681864eb7d17..7a851e221992 100644
> --- a/pixman/pixman-image.c
> +++ b/pixman/pixman-image.c
> @@ -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;
>  
> diff --git a/pixman/pixman.h b/pixman/pixman.h
> index 509ba5e534a8..c9bf4faa80d4 100644
> --- a/pixman/pixman.h
> +++ b/pixman/pixman.h
> @@ -647,19 +647,24 @@ struct pixman_indexed
>   * sample implementation allows only packed RGB and GBR
>   * representations for data to simplify software rendering,
>   */
> -#define PIXMAN_FORMAT(bpp,type,a,r,g,b)	(((bpp) << 24) |  \
> +#define PIXMAN_FORMAT_PACKC(val) ((val) <= 10 ? (val) : \
> +				 (val) == 32 ? 11 : 0)
> +#define PIXMAN_FORMAT_UNPACKC(val) ((val) <= 10 ? (val) : \
> +				    (val) == 11 ? 32 : 0)
> +
> +#define PIXMAN_FORMAT(bpp,type,a,r,g,b)	((((uint32_t)(bpp)) << 24) |  \
>  					 ((type) << 16) | \
> -					 ((a) << 12) |	  \
> -					 ((r) << 8) |	  \
> -					 ((g) << 4) |	  \
> -					 ((b)))
> +					 (PIXMAN_FORMAT_PACKC(a) << 12) |	  \
> +					 (PIXMAN_FORMAT_PACKC(r) << 8) |	  \
> +					 (PIXMAN_FORMAT_PACKC(g) << 4) |	  \
> +					 (PIXMAN_FORMAT_PACKC(b)))
>  
> -#define PIXMAN_FORMAT_BPP(f)	(((f) >> 24)       )
> +#define PIXMAN_FORMAT_BPP(f)	(((uint32_t)(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_A(f)	PIXMAN_FORMAT_UNPACKC(((f) >> 12) & 0x0f)
> +#define PIXMAN_FORMAT_R(f)	PIXMAN_FORMAT_UNPACKC(((f) >>  8) & 0x0f)
> +#define PIXMAN_FORMAT_G(f)	PIXMAN_FORMAT_UNPACKC(((f) >>  4) & 0x0f)
> +#define PIXMAN_FORMAT_B(f)	PIXMAN_FORMAT_UNPACKC(((f) >>  0) & 0x0f)
>  #define PIXMAN_FORMAT_RGB(f)	(((f)      ) & 0xfff)
>  #define PIXMAN_FORMAT_VIS(f)	(((f)      ) & 0xffff)
>  #define PIXMAN_FORMAT_DEPTH(f)	(PIXMAN_FORMAT_A(f) +	\
> @@ -685,8 +690,13 @@ struct pixman_indexed
>  	 PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_BGRA ||	\
>  	 PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_RGBA)
>  
> -/* 32bpp formats */
>  typedef enum {
> +/* 128bpp formats */
> +    PIXMAN_rgba_float =	PIXMAN_FORMAT(128,PIXMAN_TYPE_ARGB,32,32,32,32),
> +/* 96bpp formats */
> +    PIXMAN_rgb_float =	PIXMAN_FORMAT(96,PIXMAN_TYPE_ARGB,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),
> -- 
> 2.18.0
> 
> _______________________________________________
> Pixman mailing list
> Pixman@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/pixman
Maarten Lankhorst Aug. 3, 2018, 11:02 a.m.
Op 03-08-18 om 07:01 schreef Bryce Harrington:
> On Wed, Aug 01, 2018 at 02:41:33PM +0200, Maarten Lankhorst wrote:
>> 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.
>>
>> 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.
>>
>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
>> ---
>>  pixman/pixman-access.c     | 128 ++++++++++++++++++++++++++++++++++++-
>>  pixman/pixman-bits-image.c |   3 +
>>  pixman/pixman-image.c      |   4 ++
>>  pixman/pixman.h            |  32 ++++++----
>>  4 files changed, 155 insertions(+), 12 deletions(-)
>>
>> diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c
>> index 4f0642d77785..10fa049becf4 100644
>> --- a/pixman/pixman-access.c
>> +++ b/pixman/pixman-access.c
>> @@ -642,6 +642,48 @@ fetch_scanline_a2r10g10b10_float (bits_image_t *  image,
>>  }
>>  
>>  /* Expects a float buffer */
>> +#ifndef PIXMAN_FB_ACCESSORS
>> +static void
>> +fetch_scanline_rgb_float_float (bits_image_t   *image,
> Just out of curiosity, why are these routines named with float twice?
>
> Bryce
All the fetch/store functions are named fetch_scanline_<format>_float, with format being rgb_float
that gave a double float.

~Maarten
Chris Wilson Oct. 3, 2018, 8:44 a.m.
Quoting Maarten Lankhorst (2018-08-03 12:02:38)
> Op 03-08-18 om 07:01 schreef Bryce Harrington:
> > On Wed, Aug 01, 2018 at 02:41:33PM +0200, Maarten Lankhorst wrote:
> >> 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.
> >>
> >> 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.
> >>
> >> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> >> ---
> >>  pixman/pixman-access.c     | 128 ++++++++++++++++++++++++++++++++++++-
> >>  pixman/pixman-bits-image.c |   3 +
> >>  pixman/pixman-image.c      |   4 ++
> >>  pixman/pixman.h            |  32 ++++++----
> >>  4 files changed, 155 insertions(+), 12 deletions(-)
> >>
> >> diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c
> >> index 4f0642d77785..10fa049becf4 100644
> >> --- a/pixman/pixman-access.c
> >> +++ b/pixman/pixman-access.c
> >> @@ -642,6 +642,48 @@ fetch_scanline_a2r10g10b10_float (bits_image_t *  image,
> >>  }
> >>  
> >>  /* Expects a float buffer */
> >> +#ifndef PIXMAN_FB_ACCESSORS
> >> +static void
> >> +fetch_scanline_rgb_float_float (bits_image_t   *image,
> > Just out of curiosity, why are these routines named with float twice?
> >
> > Bryce
> All the fetch/store functions are named fetch_scanline_<format>_float, with format being rgb_float
> that gave a double float.

Would it be consistent with elsewhere to call it rgbaf? We trade one
confusion (float_float) for another (rgba, f).
-Chris
Chris Wilson Oct. 3, 2018, 8:47 a.m.
Quoting Maarten Lankhorst (2018-08-01 13:41:33)
> 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.
> 
> 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.
> 
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> ---
>  pixman/pixman-access.c     | 128 ++++++++++++++++++++++++++++++++++++-
>  pixman/pixman-bits-image.c |   3 +
>  pixman/pixman-image.c      |   4 ++
>  pixman/pixman.h            |  32 ++++++----
>  4 files changed, 155 insertions(+), 12 deletions(-)
> 
> diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c
> index 4f0642d77785..10fa049becf4 100644
> --- a/pixman/pixman-access.c
> +++ b/pixman/pixman-access.c
> @@ -642,6 +642,48 @@ fetch_scanline_a2r10g10b10_float (bits_image_t *  image,
>  }
>  
>  /* Expects a float buffer */
> +#ifndef PIXMAN_FB_ACCESSORS
> +static void
> +fetch_scanline_rgb_float_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;

rowstride is in bytes, is it not?
-Chris
Chris Wilson Oct. 3, 2018, 8:56 a.m.
Quoting Chris Wilson (2018-10-03 09:47:47)
> Quoting Maarten Lankhorst (2018-08-01 13:41:33)
> > 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.
> > 
> > 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.
> > 
> > Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> > ---
> >  pixman/pixman-access.c     | 128 ++++++++++++++++++++++++++++++++++++-
> >  pixman/pixman-bits-image.c |   3 +
> >  pixman/pixman-image.c      |   4 ++
> >  pixman/pixman.h            |  32 ++++++----
> >  4 files changed, 155 insertions(+), 12 deletions(-)
> > 
> > diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c
> > index 4f0642d77785..10fa049becf4 100644
> > --- a/pixman/pixman-access.c
> > +++ b/pixman/pixman-access.c
> > @@ -642,6 +642,48 @@ fetch_scanline_a2r10g10b10_float (bits_image_t *  image,
> >  }
> >  
> >  /* Expects a float buffer */
> > +#ifndef PIXMAN_FB_ACCESSORS
> > +static void
> > +fetch_scanline_rgb_float_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;
> 
> rowstride is in bytes, is it not?

No, it's in units of uint32_t.
-Chris
Chris Wilson Oct. 3, 2018, 9:11 a.m.
Quoting Maarten Lankhorst (2018-08-01 13:41:33)
> diff --git a/pixman/pixman.h b/pixman/pixman.h
> index 509ba5e534a8..c9bf4faa80d4 100644
> --- a/pixman/pixman.h
> +++ b/pixman/pixman.h
> @@ -647,19 +647,24 @@ struct pixman_indexed
>   * sample implementation allows only packed RGB and GBR
>   * representations for data to simplify software rendering,
>   */
> -#define PIXMAN_FORMAT(bpp,type,a,r,g,b)        (((bpp) << 24) |  \
> +#define PIXMAN_FORMAT_PACKC(val) ((val) <= 10 ? (val) : \
> +                                (val) == 32 ? 11 : 0)
> +#define PIXMAN_FORMAT_UNPACKC(val) ((val) <= 10 ? (val) : \
> +                                   (val) == 11 ? 32 : 0)

We have 4bits, why not reserve 0xf for float32? Certainly you
want space for

#define PIXMAN_FORMAT_PACKED_FLOAT16 0xb
#define PIXMAN_FORMAT_PACKED_FLOAT32 0xc
#define PIXMAN_FORMAT_PACKED_FLOAT64 0xd

I just wonder if we may have 12bpc one day as well, so leaving 0xc clear
has some some appeal.
-Chris
Siarhei Siamashka Oct. 29, 2018, 8:16 a.m.
On Wed, 03 Oct 2018 10:11:46 +0100
Chris Wilson <chris@chris-wilson.co.uk> wrote:

> Quoting Maarten Lankhorst (2018-08-01 13:41:33)
> > diff --git a/pixman/pixman.h b/pixman/pixman.h
> > index 509ba5e534a8..c9bf4faa80d4 100644
> > --- a/pixman/pixman.h
> > +++ b/pixman/pixman.h
> > @@ -647,19 +647,24 @@ struct pixman_indexed
> >   * sample implementation allows only packed RGB and GBR
> >   * representations for data to simplify software rendering,
> >   */
> > -#define PIXMAN_FORMAT(bpp,type,a,r,g,b)        (((bpp) << 24) |  \
> > +#define PIXMAN_FORMAT_PACKC(val) ((val) <= 10 ? (val) : \
> > +                                (val) == 32 ? 11 : 0)
> > +#define PIXMAN_FORMAT_UNPACKC(val) ((val) <= 10 ? (val) : \
> > +                                   (val) == 11 ? 32 : 0)  
> 
> We have 4bits, why not reserve 0xf for float32? Certainly you
> want space for
> 
> #define PIXMAN_FORMAT_PACKED_FLOAT16 0xb
> #define PIXMAN_FORMAT_PACKED_FLOAT32 0xc
> #define PIXMAN_FORMAT_PACKED_FLOAT64 0xd
> 
> I just wonder if we may have 12bpc one day as well, so leaving 0xc clear
> has some some appeal.

We could probably also try to do something like this:

/*
 * While the protocol is generous in format support, the
 * sample implementation allows only packed RGB and GBR
 * representations for data to simplify software rendering,
 *
 * Bit 23 selects the granularity of channel color depth
 *  0: 1-bit granularity (allows up to 15 bits per channel)
 *  1: 1-byte granularity (allows up to 120 bits per channel)
 */
#define PIXMAN_FORMAT(bpp,type,a,r,g,b)	\
	(((bpp) << 24) |  \
	((type) << 16) | \
	(((a) < 16) ? ((a) << 12) : (((a / 8) << 12) | (1 << 23))) | \
	(((r) < 16) ? ((r) << 8)  : (((r / 8) << 8)  | (1 << 23))) | \
	(((g) < 16) ? ((g) << 4)  : (((g / 8) << 4)  | (1 << 23))) | \
	(((b) < 16) ? ((b))       : (((b / 8))       | (1 << 23))))

/* 0 for 1-bit granularity and 3 for 1-byte granularity */
#define PIXMAN_FORMAT_CHANDEPTH_SHIFT(f) \
	((((f) >> 23) & 1) | ((((f) >> 23) & 1) << 1))

#define PIXMAN_FORMAT_A(f) \
	((((f) >> 12) & 0x0f) << PIXMAN_FORMAT_CHANDEPTH_SHIFT(f))
#define PIXMAN_FORMAT_R(f) \
	((((f) >>  8) & 0x0f) << PIXMAN_FORMAT_CHANDEPTH_SHIFT(f))
#define PIXMAN_FORMAT_G(f) \
	((((f) >>  4) & 0x0f) << PIXMAN_FORMAT_CHANDEPTH_SHIFT(f))
#define PIXMAN_FORMAT_B(f) \
	((((f)      ) & 0x0f) << PIXMAN_FORMAT_CHANDEPTH_SHIFT(f))

#define PIXMAN_FORMAT_BPP(f)	(((uint32_t)(f)) >> 24)
#define PIXMAN_FORMAT_TYPE(f)	(((f) >> 16) & 0x7f)
#define PIXMAN_FORMAT_RGB(f)	(((f)      ) & 0xfff)
#define PIXMAN_FORMAT_VIS(f)	(((f)      ) & 0xffff)
#define PIXMAN_FORMAT_DEPTH(f)	(PIXMAN_FORMAT_A(f) +	\
				 PIXMAN_FORMAT_R(f) +	\
				 PIXMAN_FORMAT_G(f) +	\
				 PIXMAN_FORMAT_B(f))


Right now the format type occupies 8 bits. The highest bit could be
repurposed as a flag for storing channel depth as bytes instead
of bits. This way 16-bit and 64-bit per color component will be
also supported. The limitation of this approach is that the depth
of every color component has to be a multiple of 8 bits if any of
them is 16 bits or larger.

I don't feel very comfortable about the fact that some applications
are using the PIXMAN_FORMAT_A/R/G/B macros and this code gets compiled
as part of these application binaries.

Are there any other interesting >32bpp formats that we may need
to support in the future?
Maarten Lankhorst Oct. 29, 2018, 9:18 a.m.
Op 29-10-18 om 09:16 schreef Siarhei Siamashka:
> On Wed, 03 Oct 2018 10:11:46 +0100
> Chris Wilson <chris@chris-wilson.co.uk> wrote:
>
>> Quoting Maarten Lankhorst (2018-08-01 13:41:33)
>>> diff --git a/pixman/pixman.h b/pixman/pixman.h
>>> index 509ba5e534a8..c9bf4faa80d4 100644
>>> --- a/pixman/pixman.h
>>> +++ b/pixman/pixman.h
>>> @@ -647,19 +647,24 @@ struct pixman_indexed
>>>   * sample implementation allows only packed RGB and GBR
>>>   * representations for data to simplify software rendering,
>>>   */
>>> -#define PIXMAN_FORMAT(bpp,type,a,r,g,b)        (((bpp) << 24) |  \
>>> +#define PIXMAN_FORMAT_PACKC(val) ((val) <= 10 ? (val) : \
>>> +                                (val) == 32 ? 11 : 0)
>>> +#define PIXMAN_FORMAT_UNPACKC(val) ((val) <= 10 ? (val) : \
>>> +                                   (val) == 11 ? 32 : 0)  
>> We have 4bits, why not reserve 0xf for float32? Certainly you
>> want space for
>>
>> #define PIXMAN_FORMAT_PACKED_FLOAT16 0xb
>> #define PIXMAN_FORMAT_PACKED_FLOAT32 0xc
>> #define PIXMAN_FORMAT_PACKED_FLOAT64 0xd
>>
>> I just wonder if we may have 12bpc one day as well, so leaving 0xc clear
>> has some some appeal.
> We could probably also try to do something like this:
>
> /*
>  * While the protocol is generous in format support, the
>  * sample implementation allows only packed RGB and GBR
>  * representations for data to simplify software rendering,
>  *
>  * Bit 23 selects the granularity of channel color depth
>  *  0: 1-bit granularity (allows up to 15 bits per channel)
>  *  1: 1-byte granularity (allows up to 120 bits per channel)
>  */
> #define PIXMAN_FORMAT(bpp,type,a,r,g,b)	\
> 	(((bpp) << 24) |  \
> 	((type) << 16) | \
> 	(((a) < 16) ? ((a) << 12) : (((a / 8) << 12) | (1 << 23))) | \
> 	(((r) < 16) ? ((r) << 8)  : (((r / 8) << 8)  | (1 << 23))) | \
> 	(((g) < 16) ? ((g) << 4)  : (((g / 8) << 4)  | (1 << 23))) | \
> 	(((b) < 16) ? ((b))       : (((b / 8))       | (1 << 23))))
>
> /* 0 for 1-bit granularity and 3 for 1-byte granularity */
> #define PIXMAN_FORMAT_CHANDEPTH_SHIFT(f) \
> 	((((f) >> 23) & 1) | ((((f) >> 23) & 1) << 1))
I would use 2 bits then, 6 is still plenty for the rest of the type.

Perhaps make a separate PIXMAN_FORMAT_TYPE_RGBA_FLOAT and PIXMAN_FORMAT_TYPE_RGB_FLOAT?

> #define PIXMAN_FORMAT_A(f) \
> 	((((f) >> 12) & 0x0f) << PIXMAN_FORMAT_CHANDEPTH_SHIFT(f))
> #define PIXMAN_FORMAT_R(f) \
> 	((((f) >>  8) & 0x0f) << PIXMAN_FORMAT_CHANDEPTH_SHIFT(f))
> #define PIXMAN_FORMAT_G(f) \
> 	((((f) >>  4) & 0x0f) << PIXMAN_FORMAT_CHANDEPTH_SHIFT(f))
> #define PIXMAN_FORMAT_B(f) \
> 	((((f)      ) & 0x0f) << PIXMAN_FORMAT_CHANDEPTH_SHIFT(f))
>
> #define PIXMAN_FORMAT_BPP(f)	(((uint32_t)(f)) >> 24)
> #define PIXMAN_FORMAT_TYPE(f)	(((f) >> 16) & 0x7f)
> #define PIXMAN_FORMAT_RGB(f)	(((f)      ) & 0xfff)
> #define PIXMAN_FORMAT_VIS(f)	(((f)      ) & 0xffff)
> #define PIXMAN_FORMAT_DEPTH(f)	(PIXMAN_FORMAT_A(f) +	\
> 				 PIXMAN_FORMAT_R(f) +	\
> 				 PIXMAN_FORMAT_G(f) +	\
> 				 PIXMAN_FORMAT_B(f))
>
>
> Right now the format type occupies 8 bits. The highest bit could be
> repurposed as a flag for storing channel depth as bytes instead
> of bits. This way 16-bit and 64-bit per color component will be
> also supported. The limitation of this approach is that the depth
> of every color component has to be a multiple of 8 bits if any of
> them is 16 bits or larger.
>
> I don't feel very comfortable about the fact that some applications
> are using the PIXMAN_FORMAT_A/R/G/B macros and this code gets compiled
> as part of these application binaries.
>
> Are there any other interesting >32bpp formats that we may need
> to support in the future?
>
Doubt it, pixman doesn't have that accuracy currently, but F16 might be interesting at some point..

~Maarten
Bill Spitzak Oct. 29, 2018, 5:06 p.m.
I think an indicator for float can double as indicating the size is
multiplied by 8. All float formats I am familiar with take a mulitple of 8
bits, including an 8-bit format that is sometimes used in CG.


On Mon, Oct 29, 2018 at 2:18 AM Maarten Lankhorst <
maarten.lankhorst@linux.intel.com> wrote:

> Op 29-10-18 om 09:16 schreef Siarhei Siamashka:
> > On Wed, 03 Oct 2018 10:11:46 +0100
> > Chris Wilson <chris@chris-wilson.co.uk> wrote:
> >
> >> Quoting Maarten Lankhorst (2018-08-01 13:41:33)
> >>> diff --git a/pixman/pixman.h b/pixman/pixman.h
> >>> index 509ba5e534a8..c9bf4faa80d4 100644
> >>> --- a/pixman/pixman.h
> >>> +++ b/pixman/pixman.h
> >>> @@ -647,19 +647,24 @@ struct pixman_indexed
> >>>   * sample implementation allows only packed RGB and GBR
> >>>   * representations for data to simplify software rendering,
> >>>   */
> >>> -#define PIXMAN_FORMAT(bpp,type,a,r,g,b)        (((bpp) << 24) |  \
> >>> +#define PIXMAN_FORMAT_PACKC(val) ((val) <= 10 ? (val) : \
> >>> +                                (val) == 32 ? 11 : 0)
> >>> +#define PIXMAN_FORMAT_UNPACKC(val) ((val) <= 10 ? (val) : \
> >>> +                                   (val) == 11 ? 32 : 0)
> >> We have 4bits, why not reserve 0xf for float32? Certainly you
> >> want space for
> >>
> >> #define PIXMAN_FORMAT_PACKED_FLOAT16 0xb
> >> #define PIXMAN_FORMAT_PACKED_FLOAT32 0xc
> >> #define PIXMAN_FORMAT_PACKED_FLOAT64 0xd
> >>
> >> I just wonder if we may have 12bpc one day as well, so leaving 0xc clear
> >> has some some appeal.
> > We could probably also try to do something like this:
> >
> > /*
> >  * While the protocol is generous in format support, the
> >  * sample implementation allows only packed RGB and GBR
> >  * representations for data to simplify software rendering,
> >  *
> >  * Bit 23 selects the granularity of channel color depth
> >  *  0: 1-bit granularity (allows up to 15 bits per channel)
> >  *  1: 1-byte granularity (allows up to 120 bits per channel)
> >  */
> > #define PIXMAN_FORMAT(bpp,type,a,r,g,b)       \
> >       (((bpp) << 24) |  \
> >       ((type) << 16) | \
> >       (((a) < 16) ? ((a) << 12) : (((a / 8) << 12) | (1 << 23))) | \
> >       (((r) < 16) ? ((r) << 8)  : (((r / 8) << 8)  | (1 << 23))) | \
> >       (((g) < 16) ? ((g) << 4)  : (((g / 8) << 4)  | (1 << 23))) | \
> >       (((b) < 16) ? ((b))       : (((b / 8))       | (1 << 23))))
> >
> > /* 0 for 1-bit granularity and 3 for 1-byte granularity */
> > #define PIXMAN_FORMAT_CHANDEPTH_SHIFT(f) \
> >       ((((f) >> 23) & 1) | ((((f) >> 23) & 1) << 1))
> I would use 2 bits then, 6 is still plenty for the rest of the type.
>
> Perhaps make a separate PIXMAN_FORMAT_TYPE_RGBA_FLOAT and
> PIXMAN_FORMAT_TYPE_RGB_FLOAT?
>
> > #define PIXMAN_FORMAT_A(f) \
> >       ((((f) >> 12) & 0x0f) << PIXMAN_FORMAT_CHANDEPTH_SHIFT(f))
> > #define PIXMAN_FORMAT_R(f) \
> >       ((((f) >>  8) & 0x0f) << PIXMAN_FORMAT_CHANDEPTH_SHIFT(f))
> > #define PIXMAN_FORMAT_G(f) \
> >       ((((f) >>  4) & 0x0f) << PIXMAN_FORMAT_CHANDEPTH_SHIFT(f))
> > #define PIXMAN_FORMAT_B(f) \
> >       ((((f)      ) & 0x0f) << PIXMAN_FORMAT_CHANDEPTH_SHIFT(f))
> >
> > #define PIXMAN_FORMAT_BPP(f)  (((uint32_t)(f)) >> 24)
> > #define PIXMAN_FORMAT_TYPE(f) (((f) >> 16) & 0x7f)
> > #define PIXMAN_FORMAT_RGB(f)  (((f)      ) & 0xfff)
> > #define PIXMAN_FORMAT_VIS(f)  (((f)      ) & 0xffff)
> > #define PIXMAN_FORMAT_DEPTH(f)        (PIXMAN_FORMAT_A(f) +   \
> >                                PIXMAN_FORMAT_R(f) +   \
> >                                PIXMAN_FORMAT_G(f) +   \
> >                                PIXMAN_FORMAT_B(f))
> >
> >
> > Right now the format type occupies 8 bits. The highest bit could be
> > repurposed as a flag for storing channel depth as bytes instead
> > of bits. This way 16-bit and 64-bit per color component will be
> > also supported. The limitation of this approach is that the depth
> > of every color component has to be a multiple of 8 bits if any of
> > them is 16 bits or larger.
> >
> > I don't feel very comfortable about the fact that some applications
> > are using the PIXMAN_FORMAT_A/R/G/B macros and this code gets compiled
> > as part of these application binaries.
> >
> > Are there any other interesting >32bpp formats that we may need
> > to support in the future?
> >
> Doubt it, pixman doesn't have that accuracy currently, but F16 might be
> interesting at some point..
>
> ~Maarten
>
> _______________________________________________
> Pixman mailing list
> Pixman@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/pixman
>