[Pixman] [PATCH v2] pixman: Add support for argb/xrgb float formats

Maarten Lankhorst maarten.lankhorst at linux.intel.com
Wed Jun 13 11:52:07 UTC 2018


Op 12-06-18 om 16:24 schreef Siarhei Siamashka:
> On Mon, 11 Jun 2018 13:34:50 +0200
> Maarten Lankhorst <maarten.lankhorst at linux.intel.com> wrote:
>
>> Pixman is already using the floating point formats internally, expose
>> this capability in case someone wants to support higher bit per
>> component formats.
> Pixman is currently using floating point formats for temporary scanline
> buffers in the cases when better accuracy is needed (primarily for
> PDF operators).
>
> But this does not automatically mean that everything is perfectly
> ready to use floating point formats for pixman images. Some work
> may be required to implement everything correctly.
Yeah noticed when running the tests that something is still clipping to the nearest 8 bit. :(


>> 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.
> Does it make sense to actually support both layouts?
Don't know, I wouldn't mind storing it as in the same layout, with alpha = 1.
>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
>> ---
>>  pixman/pixman-access.c | 128 ++++++++++++++++++++++++++++++++++++++++-
>>  pixman/pixman.h        |  36 ++++++++----
>>  test/alphamap.c        |  73 ++++++++++++++++-------
>>  test/utils.c           |  76 ++++++++++++++++++++++++
>>  test/utils.h           |   2 +
>>  5 files changed, 282 insertions(+), 33 deletions(-)
> Thanks for trying to add these new floating point image formats to at
> least one test from the pixman test suite. But we still need a much
> better test coverage.
>
> I think that making sure that at least stress-test does not fail
> would be a good start. Currently stress-test segfaults if I add
> PIXMAN_rgba_float or PIXMAN_rgb_float to the list of the tested
> formats in its source code.
>
> Updating existing tests and/or adding new tests for floating point
> formats should be preferably done in separate commits.

>> 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.h b/pixman/pixman.h
>> index 509ba5e534a8..c376278c83e7 100644
>> --- a/pixman/pixman.h
>> +++ b/pixman/pixman.h
>> @@ -647,19 +647,28 @@ 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_PACK_BPP(bpp) ((bpp) <= 64 || (bpp) == 96 ? (bpp) : \
>> +				     (bpp) == 128 ? 65 : 0)
>> +#define PIXMAN_FORMAT_UNPACK_BPP(bpp) ((bpp) <= 64 || (bpp) == 96 ? (bpp) : \
>> +				       (bpp) == 65 ? 128 : 0)
> We have 8 bits for encoding the bit depth and it should be enough
> for storing 96 and 128 directly. Maybe with a cast to unsigned
> data type.
Yeah, sign extension was calling me.
>> +#define PIXMAN_FORMAT_PACKC(val) ((val) <= 10 ? (val) : \
>> +				 (val) == 32 ? 11 : 0)
>> +#define PIXMAN_FORMAT_UNPACKC(val) ((val) <= 10 ? (val) : \
>> +				    (val) == 11 ? 32 : 0)
> I was initially not very happy about having these extra branches,
> because they potentially may affect the performance of this code:
>     https://cgit.freedesktop.org/pixman/tree/pixman/pixman-access.c?h=pixman-0.34.0#n197
>
> And it is used on the general path to fetch/store various uncommon
> image formats. This code is usually a performance bottleneck if such
> formats are used:
>
>   $ perf record ./lowlevel_blt_bench -m 1000 add_2222_2222_2222
>   $ perf report
>
>     79.52%  lowlevel-blt-be  lowlevel-blt-bench  [.] fetch_scanline_a2r2g2b2
>      8.98%  lowlevel-blt-be  lowlevel-blt-bench  [.] store_scanline_a2r2g2b2
>      4.93%  lowlevel-blt-be  lowlevel-blt-bench  [.] sse2_combine_add_u
>      1.32%  lowlevel-blt-be  lowlevel-blt-bench  [.] _pixman_implementation_iter_init
>
> But the compiler at least is able to inline everything and optimize out
> the branches. So probably it's okay.
Yeah that's the idea. :)
> I'm just trying to be careful. Because after we add these new format
> identifiers and macros to pixman.h, there will be no way to change them
> later without breaking compatibility.
Indeed, but there are too few bits to describe it in pixman. :(
>> +#define PIXMAN_FORMAT(bpp,type,a,r,g,b)	((PIXMAN_FORMAT_PACK_BPP(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)	PIXMAN_FORMAT_UNPACK_BPP((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 +694,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),
> The PIXMAN_TYPE_ARGB type does not seem like a good choice for these
> formats. Your  fetch_scanline_rgb_float_float function is doing the
> following:
>
>     for (; width--; buffer++) {
> 	buffer->r = *pixel++;
> 	buffer->g = *pixel++;
> 	buffer->b = *pixel++;
> 	buffer->a = 1.f;
>     }
>
> Such data layout can be interpreted as either RGBA or ABGR (depending
> on whether the system is big or little endian), but it can't be ARGB.
>
> Right now pixman only supports pixel formats with sizes up to 32
> bits. And pixels are always loaded or stored as 32-bit values. The
> PIXMAN_a8r8g8b8 format means that the alpha channel is located in
> the highest 8-bit part of a 32-bit integer. On little endian systems
> alpha channel has offset 3 in memory (the BGRA byte layout) and on
> big endian systems it has offset 0 in memory (the ARGB byte layout).
>
> Introducing 128-bit pixels makes everything a little bit more
> complicated. How are we going to handle big and little endian
> systems? Should we interpret it as an array of 4 float values,
> where the alpha channel has the same array index on both big and
> little endian systems?
I think that's the correct solution. This is more like a struct of 4 separate floats than a single packed value with 4 components.
>> +
>> +/* 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),
>> diff --git a/test/alphamap.c b/test/alphamap.c
>> index 4d09076fbcf3..150d33eed5b5 100644
>> --- a/test/alphamap.c
>> +++ b/test/alphamap.c
>> @@ -10,7 +10,8 @@ static const pixman_format_code_t formats[] =
>>      PIXMAN_a8r8g8b8,
>>      PIXMAN_a2r10g10b10,
>>      PIXMAN_a4r4g4b4,
>> -    PIXMAN_a8
>> +    PIXMAN_a8,
>> +    PIXMAN_rgba_float,
>>  };
>>  
>>  static const pixman_format_code_t alpha_formats[] =
>> @@ -18,7 +19,8 @@ static const pixman_format_code_t alpha_formats[] =
>>      PIXMAN_null,
>>      PIXMAN_a8,
>>      PIXMAN_a2r10g10b10,
>> -    PIXMAN_a4r4g4b4
>> +    PIXMAN_a4r4g4b4,
>> +    PIXMAN_rgba_float,
>>  };
>>  
>>  static const int origins[] =
>> @@ -41,7 +43,10 @@ make_image (pixman_format_code_t format)
>>      uint8_t bpp = PIXMAN_FORMAT_BPP (format) / 8;
>>      pixman_image_t *image;
>>  
>> -    bits = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * bpp);
>> +    if (format != PIXMAN_rgba_float)
>> +	bits = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * bpp);
>> +    else
>> +	bits = (uint32_t *)make_random_floats (WIDTH * HEIGHT * bpp);
>>  
>>      image = pixman_image_create_bits (format, WIDTH, HEIGHT, bits, WIDTH * bpp);
>>  
>> @@ -51,11 +56,11 @@ make_image (pixman_format_code_t format)
>>      return image;
>>  }
>>  
>> -static uint8_t
>> +static float
>>  get_alpha (pixman_image_t *image, int x, int y, int orig_x, int orig_y)
>>  {
>>      uint8_t *bits;
>> -    uint8_t r;
>> +    uint32_t r;
>>  
>>      if (image->common.alpha_map)
>>      {
>> @@ -69,7 +74,7 @@ get_alpha (pixman_image_t *image, int x, int y, int orig_x, int orig_y)
>>  	}
>>  	else
>>  	{
>> -	    return 0;
>> +	    return 0.f;
>>  	}
>>      }
>>  
>> @@ -78,28 +83,32 @@ get_alpha (pixman_image_t *image, int x, int y, int orig_x, int orig_y)
>>      if (image->bits.format == PIXMAN_a8)
>>      {
>>  	r = bits[y * WIDTH + x];
>> +	return r / 255.f;
>>      }
>>      else if (image->bits.format == PIXMAN_a2r10g10b10)
>>      {
>>  	r = ((uint32_t *)bits)[y * WIDTH + x] >> 30;
>> -	r |= r << 2;
>> -	r |= r << 4;
>> +	return r / 3.f;
>>      }
>>      else if (image->bits.format == PIXMAN_a8r8g8b8)
>>      {
>>  	r = ((uint32_t *)bits)[y * WIDTH + x] >> 24;
>> +	return r / 255.f;
>>      }
>>      else if (image->bits.format == PIXMAN_a4r4g4b4)
>>      {
>>  	r = ((uint16_t *)bits)[y * WIDTH + x] >> 12;
>> -	r |= r << 4;
>> +	return r / 15.f;
>> +    }
>> +    else if (image->bits.format == PIXMAN_rgba_float)
>> +    {
>> +	return ((float *)bits)[y * WIDTH * 4 + x * 4 + 3];
>>      }
>>      else
>>      {
>>  	assert (0);
>> +	return 0.f;
>>      }
>> -
>> -    return r;
>>  }
>>  
>>  static uint16_t
>> @@ -133,6 +142,11 @@ get_red (pixman_image_t *image, int x, int y, int orig_x, int orig_y)
>>  	r |= r << 4;
>>  	r |= r << 8;
>>      }
>> +    else if (image->bits.format == PIXMAN_rgba_float)
>> +    {
>> +	double tmp = ((float *)bits)[y * WIDTH * 4 + x * 4];
>> +	return tmp * 65535.;
>> +    }
>>      else
>>      {
>>  	assert (0);
>> @@ -141,6 +155,23 @@ get_red (pixman_image_t *image, int x, int y, int orig_x, int orig_y)
>>      return r;
>>  }
>>  
>> +static float get_alpha_err(pixman_format_code_t sf, pixman_format_code_t saf,
>> +			   pixman_format_code_t df, pixman_format_code_t daf)
>> +{
>> +	pixman_format_code_t s = saf != PIXMAN_null ? saf : sf;
>> +	pixman_format_code_t d = daf != PIXMAN_null ? daf : df;
>> +
>> +	/* There are cases where we go through the 8 bit compositing
>> +	 * path even with 10bpc and higher formats.
>> +	 */
>> +	if (PIXMAN_FORMAT_A(s) == PIXMAN_FORMAT_A(d))
>> +		return 1.f / 255.f;
>> +	else if (PIXMAN_FORMAT_A(s) > PIXMAN_FORMAT_A(d))
>> +		return 1.f / ((1 << PIXMAN_FORMAT_A(d)) - 1);
>> +	else
>> +		return 1.f / ((1 << PIXMAN_FORMAT_A(s)) - 1);
>> +}
>> +
>>  static int
>>  run_test (int s, int d, int sa, int da, int soff, int doff)
>>  {
>> @@ -151,15 +182,11 @@ run_test (int s, int d, int sa, int da, int soff, int doff)
>>      pixman_image_t *src, *dst, *orig_dst, *alpha, *orig_alpha;
>>      pixman_transform_t t1;
>>      int j, k;
>> -    int n_alpha_bits, n_red_bits;
>> +    int n_red_bits;
>>  
>>      soff = origins[soff];
>>      doff = origins[doff];
>>  
>> -    n_alpha_bits = PIXMAN_FORMAT_A (df);
>> -    if (daf != PIXMAN_null)
>> -	n_alpha_bits = PIXMAN_FORMAT_A (daf);
>> -
>>      n_red_bits = PIXMAN_FORMAT_R (df);
>>  
>>      /* Source */
>> @@ -211,21 +238,25 @@ run_test (int s, int d, int sa, int da, int soff, int doff)
>>      {
>>  	for (k = MAX (doff, 0); k < MIN (WIDTH, WIDTH + doff); ++k)
>>  	{
>> -	    uint8_t sa, da, oda, refa;
>> +	    float sa, da, oda, refa;
>>  	    uint16_t sr, dr, odr, refr;
>> +	    float err;
>> +
>> +	    err = get_alpha_err(sf, saf, df, daf);
>>  
>>  	    sa = get_alpha (src, k, j, soff, soff);
>>  	    da = get_alpha (dst, k, j, doff, doff);
>>  	    oda = get_alpha (orig_dst, k, j, doff, doff);
>>  
>> -	    if (sa + oda > 255)
>> -		refa = 255;
>> +	    if (sa + oda > 1.f)
>> +		refa = 1.f;
>>  	    else
>>  		refa = sa + oda;
>>  
>> -	    if (da >> (8 - n_alpha_bits) != refa >> (8 - n_alpha_bits))
>> +	    if (da - err > refa ||
>> +	        da + err < refa)
> This changes the behaviour of the alphamap test for the existing
> image formats by making the test less strict.
Yeah, perhaps we should special case float?
>>  	    {
>> -		printf ("\nWrong alpha value at (%d, %d). Should be 0x%x; got 0x%x. Source was 0x%x, original dest was 0x%x\n",
>> +		printf ("\nWrong alpha value at (%d, %d). Should be %g; got %g. Source was %g, original dest was %g\n",
>>  			k, j, refa, da, sa, oda);
>>  
>>  		printf ("src: %s, alpha: %s, origin %d %d\ndst: %s, alpha: %s, origin: %d %d\n\n",
>> diff --git a/test/utils.c b/test/utils.c
>> index f8e42a5d3f3d..4eeb068497ec 100644
>> --- a/test/utils.c
>> +++ b/test/utils.c
>> @@ -595,6 +595,21 @@ make_random_bytes (int n_bytes)
>>      return bytes;
>>  }
>>  
>> +float *
>> +make_random_floats (int n_bytes)
>> +{
>> +    uint8_t *bytes = fence_malloc (n_bytes);
>> +    float *vals = (float *)bytes;
>> +
>> +    if (!bytes)
>> +	return 0;
>> +
>> +    for (n_bytes /= 4; n_bytes; vals++, n_bytes--)
>> +	*vals = (float)rand() / (float)RAND_MAX;
>> +
>> +    return (float *)bytes;
>> +}
>> +
>>  void
>>  a8r8g8b8_to_rgba_np (uint32_t *dst, uint32_t *src, int n_pixels)
>>  {
>> @@ -1180,6 +1195,11 @@ static const format_entry_t format_list[] =
>>       * Aliases are not listed by list_formats ().
>>       */
>>  
>> +/* 128bpp formats */
>> +    ENTRY (rgba_float),
>> +/* 96bpp formats */
>> +    ENTRY (rgb_float),
>> +
>>  /* 32bpp formats */
>>      ENTRY (a8r8g8b8),
>>      ALIAS (a8r8g8b8,		"8888"),
>> @@ -1914,6 +1934,10 @@ pixel_checker_init (pixel_checker_t *checker, pixman_format_code_t format)
>>  
>>      checker->format = format;
>>  
>> +    if (format == PIXMAN_rgba_float ||
>> +	format == PIXMAN_rgb_float)
>> +	return;
>> +
>>      switch (PIXMAN_FORMAT_TYPE (format))
>>      {
>>      case PIXMAN_TYPE_A:
>> @@ -1970,10 +1994,19 @@ pixel_checker_init (pixel_checker_t *checker, pixman_format_code_t format)
>>      checker->bw = PIXMAN_FORMAT_B (format);
>>  }
>>  
>> +static void
>> +pixel_checker_require_uint32_format (const pixel_checker_t *checker)
>> +{
>> +    assert (checker->format != PIXMAN_rgba_float &&
>> +	    checker->format != PIXMAN_rgb_float);
>> +}
>> +
>>  void
>>  pixel_checker_split_pixel (const pixel_checker_t *checker, uint32_t pixel,
>>  			   int *a, int *r, int *g, int *b)
>>  {
>> +    pixel_checker_require_uint32_format(checker);
>> +
>>      *a = (pixel & checker->am) >> checker->as;
>>      *r = (pixel & checker->rm) >> checker->rs;
>>      *g = (pixel & checker->gm) >> checker->gs;
>> @@ -1987,6 +2020,8 @@ pixel_checker_get_masks (const pixel_checker_t *checker,
>>                           uint32_t              *gm,
>>                           uint32_t              *bm)
>>  {
>> +    pixel_checker_require_uint32_format(checker);
>> +
>>      if (am)
>>          *am = checker->am;
>>      if (rm)
>> @@ -2003,6 +2038,8 @@ pixel_checker_convert_pixel_to_color (const pixel_checker_t *checker,
>>  {
>>      int a, r, g, b;
>>  
>> +    pixel_checker_require_uint32_format(checker);
>> +
>>      pixel_checker_split_pixel (checker, pixel, &a, &r, &g, &b);
>>  
>>      if (checker->am == 0)
>> @@ -2078,6 +2115,8 @@ void
>>  pixel_checker_get_max (const pixel_checker_t *checker, color_t *color,
>>  		       int *am, int *rm, int *gm, int *bm)
>>  {
>> +    pixel_checker_require_uint32_format(checker);
>> +
>>      get_limits (checker, DEVIATION, color, am, rm, gm, bm);
>>  }
>>  
>> @@ -2085,6 +2124,8 @@ void
>>  pixel_checker_get_min (const pixel_checker_t *checker, color_t *color,
>>  		       int *am, int *rm, int *gm, int *bm)
>>  {
>> +    pixel_checker_require_uint32_format(checker);
>> +
>>      get_limits (checker, - DEVIATION, color, am, rm, gm, bm);
>>  }
>>  
>> @@ -2096,6 +2137,8 @@ pixel_checker_check (const pixel_checker_t *checker, uint32_t pixel,
>>      int32_t ai, ri, gi, bi;
>>      pixman_bool_t result;
>>  
>> +    pixel_checker_require_uint32_format(checker);
>> +
>>      pixel_checker_get_min (checker, color, &a_lo, &r_lo, &g_lo, &b_lo);
>>      pixel_checker_get_max (checker, color, &a_hi, &r_hi, &g_hi, &b_hi);
>>      pixel_checker_split_pixel (checker, pixel, &ai, &ri, &gi, &bi);
>> @@ -2108,3 +2151,36 @@ pixel_checker_check (const pixel_checker_t *checker, uint32_t pixel,
>>  
>>      return result;
>>  }
>> +
>> +static void
>> +color_limits (const pixel_checker_t *checker,
>> +	      double limit, const color_t *color, color_t *out)
>> +{
>> +    if (PIXMAN_FORMAT_A(checker->format))
>> +	out->a = color->a + limit;
>> +    else
>> +	out->a = 1.;
>> +
>> +    out->r = color->r + limit;
>> +    out->g = color->g + limit;
>> +    out->b = color->b + limit;
>> +}
>> +
>> +pixman_bool_t
>> +pixel_checker_check_color (const pixel_checker_t *checker,
>> +			   const color_t *actual, const color_t *reference)
>> +{
>> +    color_t min, max;
>> +    pixman_bool_t result;
>> +
>> +    color_limits(checker, -DEVIATION, reference, &min);
>> +    color_limits(checker, DEVIATION, reference, &max);
>> +
>> +    result =
>> +	actual->a >= min.a && actual->a <= max.a &&
>> +	actual->r >= min.r && actual->r <= max.r &&
>> +	actual->g >= min.g && actual->g <= max.g &&
>> +	actual->b >= min.b && actual->b <= max.b;
>> +
>> +    return result;
>> +}
>> diff --git a/test/utils.h b/test/utils.h
>> index e299d1d066ed..e5ac945ab3f8 100644
>> --- a/test/utils.h
>> +++ b/test/utils.h
>> @@ -119,6 +119,8 @@ fence_get_page_size ();
>>  /* Generate n_bytes random bytes in fence_malloced memory */
>>  uint8_t *
>>  make_random_bytes (int n_bytes);
>> +float *
>> +make_random_floats (int n_bytes);
>>  
>>  /* Return current time in seconds */
>>  double




More information about the Pixman mailing list