Discussion:
[Pixman] [PATCH 0/2] Add float support to pixman
Maarten Lankhorst
2018-08-01 12:41:32 UTC
Permalink
New version, with better checks to pixel accessors and alignment. Also
some small tweaks, and making stress-test work with the changes.
Hopefully we can move forward and finalize the bitstream format, so
we can start exposing it in pixman.

Maarten Lankhorst (2):
pixman: Add support for argb/xrgb float formats, v3.
pixman: Add tests for xrgb/argb formats.

pixman/pixman-access.c | 128 ++++++++++++++++++++++++++++++++++++-
pixman/pixman-bits-image.c | 3 +
pixman/pixman-image.c | 4 ++
pixman/pixman.h | 32 ++++++----
test/alphamap.c | 73 +++++++++++++++------
test/stress-test.c | 75 ++++++++++++++++------
test/utils.c | 76 ++++++++++++++++++++++
test/utils.h | 2 +
8 files changed, 341 insertions(+), 52 deletions(-)
--
2.18.0
Maarten Lankhorst
2018-08-01 12:41:34 UTC
Permalink
Signed-off-by: Maarten Lankhorst <***@linux.intel.com>
---
test/alphamap.c | 73 +++++++++++++++++++++++++++++++-------------
test/stress-test.c | 75 +++++++++++++++++++++++++++++++++------------
test/utils.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++
test/utils.h | 2 ++
4 files changed, 186 insertions(+), 40 deletions(-)

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)
{
- 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/stress-test.c b/test/stress-test.c
index 85d12932c9aa..6b4f7d606f72 100644
--- a/test/stress-test.c
+++ b/test/stress-test.c
@@ -11,6 +11,8 @@

static const pixman_format_code_t image_formats[] =
{
+ PIXMAN_rgba_float,
+ PIXMAN_rgb_float,
PIXMAN_a8r8g8b8,
PIXMAN_x8r8g8b8,
PIXMAN_r5g6b5,
@@ -100,6 +102,14 @@ get_size (void)
}
}

+static uint32_t
+real_reader (const void *src, int size);
+
+static void *xor_ptr(const void *ptr)
+{
+ return (void *)(((intptr_t)ptr) ^ (intptr_t)0x8000000080000000);
+}
+
static void
destroy (pixman_image_t *image, void *data)
{
@@ -114,6 +124,9 @@ destroy (pixman_image_t *image, void *data)
if (image->bits.rowstride < 0)
bits -= (- image->bits.rowstride * (image->bits.height - 1));

+ if (image->bits.read_func == real_reader)
+ bits = xor_ptr(bits);
+
fence_free (bits);
}
}
@@ -124,6 +137,7 @@ destroy (pixman_image_t *image, void *data)
static uint32_t
real_reader (const void *src, int size)
{
+ src = xor_ptr(src);
switch (size)
{
case 1:
@@ -141,6 +155,7 @@ real_reader (const void *src, int size)
static void
real_writer (void *src, uint32_t value, int size)
{
+ src = xor_ptr(src);
switch (size)
{
case 1:
@@ -247,9 +262,20 @@ create_random_bits_image (alpha_preference_t alpha_preference)
pixman_filter_t filter;
pixman_fixed_t *coefficients = NULL;
int n_coefficients = 0;
+ int align_add, align_mask;

/* format */
format = random_format (alpha_preference);
+ switch (PIXMAN_FORMAT_BPP (format)) {
+ case 128:
+ align_mask = 15;
+ align_add = align_mask + prng_rand_n (65);
+ break;
+ default:
+ align_mask = 3;
+ align_add = align_mask + prng_rand_n (17);
+ break;
+ }

indexed = NULL;
if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR)
@@ -291,9 +317,12 @@ create_random_bits_image (alpha_preference_t alpha_preference)
{
default:
case 0:
- stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8 + prng_rand_n (17);
- stride = (stride + 3) & (~3);
- bits = (uint32_t *)make_random_bytes (height * stride);
+ stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8;
+ stride = (stride + align_add) & (~align_mask);
+ if (format == PIXMAN_rgb_float || format == PIXMAN_rgba_float)
+ bits = (uint32_t *)make_random_floats (height * stride);
+ else
+ bits = (uint32_t *)make_random_bytes (height * stride);
break;

case 1:
@@ -302,8 +331,8 @@ create_random_bits_image (alpha_preference_t alpha_preference)
break;

case 2: /* Zero-filled */
- stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8 + prng_rand_n (17);
- stride = (stride + 3) & (~3);
+ stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8;
+ stride = (stride + align_add) & (~align_mask);
bits = fence_malloc (height * stride);
if (!bits)
return NULL;
@@ -311,8 +340,8 @@ create_random_bits_image (alpha_preference_t alpha_preference)
break;

case 3: /* Filled with 0xFF */
- stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8 + prng_rand_n (17);
- stride = (stride + 3) & (~3);
+ stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8;
+ stride = (stride + align_add) & (~align_mask);
bits = fence_malloc (height * stride);
if (!bits)
return NULL;
@@ -320,27 +349,35 @@ create_random_bits_image (alpha_preference_t alpha_preference)
break;

case 4: /* bits is a bad pointer, has read/write functions */
- stride = 232;
- bits = (void *)0x01;
- read_func = fake_reader;
- write_func = fake_writer;
- break;
+ if (PIXMAN_FORMAT_BPP (format) <= 32) {
+ stride = 232;
+ bits = (void *)0x01;
+ read_func = fake_reader;
+ write_func = fake_writer;
+ break;
+ }

case 5: /* bits is a real pointer, has read/write functions */
- stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8 + prng_rand_n (17);
- stride = (stride + 3) & (~3);
+ stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8;
+ stride = (stride + align_add) & (~align_mask);
bits = fence_malloc (height * stride);
if (!bits)
return NULL;
memset (bits, 0xff, height * stride);
- read_func = real_reader;
- write_func = real_writer;
+ if (PIXMAN_FORMAT_BPP (format) <= 32) {
+ bits = xor_ptr(bits);
+ read_func = real_reader;
+ write_func = real_writer;
+ }
break;

case 6: /* bits is a real pointer, stride is negative */
- stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8 + prng_rand_n (17);
- stride = (stride + 3) & (~3);
- bits = (uint32_t *)make_random_bytes (height * stride);
+ stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8;
+ stride = (stride + align_add) & (~align_mask);
+ if (format == PIXMAN_rgb_float || format == PIXMAN_rgba_float)
+ bits = (uint32_t *)make_random_floats (height * stride);
+ else
+ bits = (uint32_t *)make_random_bytes (height * stride);
if (!bits)
return NULL;
bits += ((height - 1) * stride) / 4;
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
--
2.18.0
Maarten Lankhorst
2018-08-27 12:39:24 UTC
Permalink
Hey,
Post by Maarten Lankhorst
---
test/alphamap.c | 73 +++++++++++++++++++++++++++++++-------------
test/stress-test.c | 75 +++++++++++++++++++++++++++++++++------------
test/utils.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++
test/utils.h | 2 ++
4 files changed, 186 insertions(+), 40 deletions(-)
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)
{
- 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/stress-test.c b/test/stress-test.c
index 85d12932c9aa..6b4f7d606f72 100644
--- a/test/stress-test.c
+++ b/test/stress-test.c
@@ -11,6 +11,8 @@
static const pixman_format_code_t image_formats[] =
{
+ PIXMAN_rgba_float,
+ PIXMAN_rgb_float,
PIXMAN_a8r8g8b8,
PIXMAN_x8r8g8b8,
PIXMAN_r5g6b5,
@@ -100,6 +102,14 @@ get_size (void)
}
}
+static uint32_t
+real_reader (const void *src, int size);
+
+static void *xor_ptr(const void *ptr)
+{
+ return (void *)(((intptr_t)ptr) ^ (intptr_t)0x8000000080000000);
+}
+
static void
destroy (pixman_image_t *image, void *data)
{
@@ -114,6 +124,9 @@ destroy (pixman_image_t *image, void *data)
if (image->bits.rowstride < 0)
bits -= (- image->bits.rowstride * (image->bits.height - 1));
+ if (image->bits.read_func == real_reader)
+ bits = xor_ptr(bits);
+
fence_free (bits);
}
}
@@ -124,6 +137,7 @@ destroy (pixman_image_t *image, void *data)
static uint32_t
real_reader (const void *src, int size)
{
+ src = xor_ptr(src);
switch (size)
{
@@ -141,6 +155,7 @@ real_reader (const void *src, int size)
static void
real_writer (void *src, uint32_t value, int size)
{
+ src = xor_ptr(src);
switch (size)
{
@@ -247,9 +262,20 @@ create_random_bits_image (alpha_preference_t alpha_preference)
pixman_filter_t filter;
pixman_fixed_t *coefficients = NULL;
int n_coefficients = 0;
+ int align_add, align_mask;
/* format */
format = random_format (alpha_preference);
+ switch (PIXMAN_FORMAT_BPP (format)) {
+ align_mask = 15;
+ align_add = align_mask + prng_rand_n (65);
+ break;
+ align_mask = 3;
+ align_add = align_mask + prng_rand_n (17);
+ break;
+ }
indexed = NULL;
if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR)
@@ -291,9 +317,12 @@ create_random_bits_image (alpha_preference_t alpha_preference)
{
- stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8 + prng_rand_n (17);
- stride = (stride + 3) & (~3);
- bits = (uint32_t *)make_random_bytes (height * stride);
+ stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8;
+ stride = (stride + align_add) & (~align_mask);
+ if (format == PIXMAN_rgb_float || format == PIXMAN_rgba_float)
+ bits = (uint32_t *)make_random_floats (height * stride);
+ else
+ bits = (uint32_t *)make_random_bytes (height * stride);
break;
@@ -302,8 +331,8 @@ create_random_bits_image (alpha_preference_t alpha_preference)
break;
case 2: /* Zero-filled */
- stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8 + prng_rand_n (17);
- stride = (stride + 3) & (~3);
+ stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8;
+ stride = (stride + align_add) & (~align_mask);
bits = fence_malloc (height * stride);
if (!bits)
return NULL;
@@ -311,8 +340,8 @@ create_random_bits_image (alpha_preference_t alpha_preference)
break;
case 3: /* Filled with 0xFF */
- stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8 + prng_rand_n (17);
- stride = (stride + 3) & (~3);
+ stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8;
+ stride = (stride + align_add) & (~align_mask);
bits = fence_malloc (height * stride);
if (!bits)
return NULL;
@@ -320,27 +349,35 @@ create_random_bits_image (alpha_preference_t alpha_preference)
break;
case 4: /* bits is a bad pointer, has read/write functions */
- stride = 232;
- bits = (void *)0x01;
- read_func = fake_reader;
- write_func = fake_writer;
- break;
+ if (PIXMAN_FORMAT_BPP (format) <= 32) {
+ stride = 232;
+ bits = (void *)0x01;
+ read_func = fake_reader;
+ write_func = fake_writer;
+ break;
+ }
case 5: /* bits is a real pointer, has read/write functions */
- stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8 + prng_rand_n (17);
- stride = (stride + 3) & (~3);
+ stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8;
+ stride = (stride + align_add) & (~align_mask);
bits = fence_malloc (height * stride);
if (!bits)
return NULL;
memset (bits, 0xff, height * stride);
- read_func = real_reader;
- write_func = real_writer;
+ if (PIXMAN_FORMAT_BPP (format) <= 32) {
+ bits = xor_ptr(bits);
+ read_func = real_reader;
+ write_func = real_writer;
+ }
break;
case 6: /* bits is a real pointer, stride is negative */
- stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8 + prng_rand_n (17);
- stride = (stride + 3) & (~3);
- bits = (uint32_t *)make_random_bytes (height * stride);
+ stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8;
+ stride = (stride + align_add) & (~align_mask);
+ if (format == PIXMAN_rgb_float || format == PIXMAN_rgba_float)
+ bits = (uint32_t *)make_random_floats (height * stride);
+ else
+ bits = (uint32_t *)make_random_bytes (height * stride);
if (!bits)
return NULL;
bits += ((height - 1) * stride) / 4;
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))
{
@@ -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
There hasn't been any movement on reviewing this series since i posted this.

Can I assume there are no objections, and I can push this to pixman next week?

~Maarten
Siarhei Siamashka
2018-09-03 04:40:54 UTC
Permalink
On Mon, 27 Aug 2018 14:39:24 +0200
Post by Maarten Lankhorst
There hasn't been any movement on reviewing this series since i posted this.
Sorry for the delay, I'll review it later today or tomorrow.
Post by Maarten Lankhorst
Can I assume there are no objections, and I can push this to pixman next week?
It would be great if your patches first got an approval in the form of
Acked-by or Reviewed-by from at least one person other than you.
--
Best regards,
Siarhei Siamashka
Maarten Lankhorst
2018-09-10 12:58:50 UTC
Permalink
Post by Siarhei Siamashka
On Mon, 27 Aug 2018 14:39:24 +0200
Post by Maarten Lankhorst
There hasn't been any movement on reviewing this series since i posted this.
Sorry for the delay, I'll review it later today or tomorrow.
Thanks, would be nice to finally have it reviewed. :)
Post by Siarhei Siamashka
Post by Maarten Lankhorst
Can I assume there are no objections, and I can push this to pixman next week?
It would be great if your patches first got an approval in the form of
Acked-by or Reviewed-by from at least one person other than you.
Agreed. But if nobody is stepping forward then it's really hard to do so.

Cheers,

~Maarten
Bryce Harrington
2018-09-19 23:57:39 UTC
Permalink
Post by Maarten Lankhorst
Post by Siarhei Siamashka
On Mon, 27 Aug 2018 14:39:24 +0200
Post by Maarten Lankhorst
There hasn't been any movement on reviewing this series since i posted this.
Sorry for the delay, I'll review it later today or tomorrow.
Thanks, would be nice to finally have it reviewed. :)
Post by Siarhei Siamashka
Post by Maarten Lankhorst
Can I assume there are no objections, and I can push this to pixman next week?
It would be great if your patches first got an approval in the form of
Acked-by or Reviewed-by from at least one person other than you.
Agreed. But if nobody is stepping forward then it's really hard to do so.
Cheers,
~Maarten
Marc and Maarten, both of you are in the same situation, waiting on code
reviews of your patches. Could I suggest that the two of you review
each other's patches and trade r-b's?

Bryce
Chris Wilson
2018-10-26 10:37:40 UTC
Permalink
Quoting Maarten Lankhorst (2018-08-01 13:41:34)
Reviewed-by: Chris Wilson <***@chris-wilson.co.uk>
-Chris
Maarten Lankhorst
2018-08-01 12:41:33 UTC
Permalink
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 <***@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;
+ 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
Bryce Harrington
2018-08-03 05:01:53 UTC
Permalink
Post by Maarten Lankhorst
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.
- Use RGBA 128 bits and RGB 96 bits memory layouts, to better match the opengl format.
- Add asserts in accessor and for strides to force alignment.
- Move test changes to their own commit.
---
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
Post by Maarten Lankhorst
+ 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
https://lists.freedesktop.org/mailman/listinfo/pixman
Maarten Lankhorst
2018-08-03 11:02:38 UTC
Permalink
Post by Bryce Harrington
Post by Maarten Lankhorst
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.
- Use RGBA 128 bits and RGB 96 bits memory layouts, to better match the opengl format.
- Add asserts in accessor and for strides to force alignment.
- Move test changes to their own commit.
---
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
2018-10-03 08:44:46 UTC
Permalink
Quoting Maarten Lankhorst (2018-08-03 12:02:38)
Post by Maarten Lankhorst
Post by Bryce Harrington
Post by Maarten Lankhorst
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.
- Use RGBA 128 bits and RGB 96 bits memory layouts, to better match the opengl format.
- Add asserts in accessor and for strides to force alignment.
- Move test changes to their own commit.
---
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
2018-10-03 08:47:47 UTC
Permalink
Quoting Maarten Lankhorst (2018-08-01 13:41:33)
Post by Maarten Lankhorst
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.
- Use RGBA 128 bits and RGB 96 bits memory layouts, to better match the opengl format.
- Add asserts in accessor and for strides to force alignment.
- Move test changes to their own commit.
---
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
2018-10-03 08:56:45 UTC
Permalink
Quoting Chris Wilson (2018-10-03 09:47:47)
Post by Chris Wilson
Quoting Maarten Lankhorst (2018-08-01 13:41:33)
Post by Maarten Lankhorst
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.
- Use RGBA 128 bits and RGB 96 bits memory layouts, to better match the opengl format.
- Add asserts in accessor and for strides to force alignment.
- Move test changes to their own commit.
---
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
2018-10-03 09:11:46 UTC
Permalink
Quoting Maarten Lankhorst (2018-08-01 13:41:33)
Post by Maarten Lankhorst
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
Maarten Lankhorst
2018-10-25 11:25:15 UTC
Permalink
Post by Chris Wilson
Quoting Maarten Lankhorst (2018-08-01 13:41:33)
Post by Maarten Lankhorst
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
I don't think we support double precision in pixman yet, but here's v4. :)

Apply with --scissors
------8<------------------------------------
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.
Changes since v3:
- Define 32bpc as PIXMAN_FORMAT_PACKED_C32
- Rename pixman accessors from rgb*_float_float to rgb*f_float

Signed-off-by: Maarten Lankhorst <***@linux.intel.com>

diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c
index 4f0642d77785..8dfd35f45063 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_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,
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..978dc8c2d4a8 100644
--- a/pixman/pixman.h
+++ b/pixman/pixman.h
@@ -647,19 +647,27 @@ 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_PACKED_C32 0xf
+
+#define PIXMAN_FORMAT_PACKC(val) ((val) == 32 ? \
+ PIXMAN_FORMAT_PACKED_C32 : \
+ (val))
+#define PIXMAN_FORMAT_UNPACKC(val) ((val) == PIXMAN_FORMAT_PACKED_C32 ? \
+ 32 : (val))
+
+#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 +693,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),
Chris Wilson
2018-10-26 10:28:08 UTC
Permalink
This post might be inappropriate. Click to display it.
Siarhei Siamashka
2018-10-29 08:16:47 UTC
Permalink
On Wed, 03 Oct 2018 10:11:46 +0100
Post by Chris Wilson
Quoting Maarten Lankhorst (2018-08-01 13:41:33)
Post by Maarten Lankhorst
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?
--
Best regards,
Siarhei Siamashka
Maarten Lankhorst
2018-10-29 09:18:47 UTC
Permalink
Post by Siarhei Siamashka
On Wed, 03 Oct 2018 10:11:46 +0100
Post by Chris Wilson
Quoting Maarten Lankhorst (2018-08-01 13:41:33)
Post by Maarten Lankhorst
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.
/*
* 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?
Post by Siarhei Siamashka
#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
2018-10-29 17:06:19 UTC
Permalink
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 <
Post by Maarten Lankhorst
Post by Siarhei Siamashka
On Wed, 03 Oct 2018 10:11:46 +0100
Post by Chris Wilson
Quoting Maarten Lankhorst (2018-08-01 13:41:33)
Post by Maarten Lankhorst
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.
/*
* 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?
Post by Siarhei Siamashka
#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
https://lists.freedesktop.org/mailman/listinfo/pixman
Maarten Lankhorst
2018-10-31 11:20:44 UTC
Permalink
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.
What about this, then?

----------------->8------------
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.
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 <***@linux.intel.com>
Reviewed-by: Chris Wilson <***@chris-wilson.co.uk> #v4
---
pixman/pixman-access.c | 128 ++++++++++++++++++++++++++++++++++++-
pixman/pixman-bits-image.c | 3 +
pixman/pixman-image.c | 4 ++
pixman/pixman.c | 5 ++
pixman/pixman.h | 35 +++++++---
5 files changed, 166 insertions(+), 9 deletions(-)

diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c
index 4f0642d77785..8dfd35f45063 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_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,
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.c b/pixman/pixman.c
index f932eac3c1b6..c09b5280831f 100644
--- a/pixman/pixman.c
+++ b/pixman/pixman.c
@@ -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 ||
diff --git a/pixman/pixman.h b/pixman/pixman.h
index 509ba5e534a8..04d7504729e2 100644
--- a/pixman/pixman.h
+++ b/pixman/pixman.h
@@ -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),
--
2.19.1
Bill Spitzak
2018-10-31 19:04:55 UTC
Permalink
I don't like the fact that the design which allows the rgba to be different
sizes cannot make them vary between float and decimal. The main reason is
so that an integer for Alpha can be supported. I think maybe there should
be a bit that changes the interpretation of the bit widths to a 16-valued
type enumeration. For n-bit integers use n-1 as now, but remove the unusual
ones and replace them with floating point and signed types. Use a lookup
table to get type + width. I really don't think there are more than 16 of
them:

8, 16, 32, 64 bit unsigned
8, 16, 32, 64 bit float
this set leaves 8 unused values, which maybe could be allocated in the
future for signed types or 128-bit types. You could also provide a few more
unsigned widths (1,2,4,10,12?)
Maarten Lankhorst
2018-11-01 11:54:23 UTC
Permalink
Post by Bill Spitzak
8, 16, 32, 64 bit unsigned
8, 16, 32, 64 bit float
this set leaves 8 unused values, which maybe could be allocated in the future for signed types or 128-bit types. You could also provide a few more unsigned widths (1,2,4,10,12?)
I'm not aware of any format that has a different type for float alpha and colors.. In any case
that's probably what you should put in the type info.

~Maarten

Loading...