[Pixman] [PATCH 4/4] Add fetchers and storers for FPU-based implementation.

Dmitri Vorobiev dmitri.vorobiev at movial.com
Tue Sep 21 05:17:48 PDT 2010


From: Jonathan Morton <jonathan.morton at movial.com>

This patch adds fetchers and storers for use in the floating-point
paths further on.
---
 pixman/Makefile.am           |    5 +-
 pixman/pixman-access-float.c |  272 +++++++++++++++
 pixman/pixman-access-float.h |  789 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1064 insertions(+), 2 deletions(-)
 create mode 100644 pixman/pixman-access-float.c
 create mode 100644 pixman/pixman-access-float.h

diff --git a/pixman/Makefile.am b/pixman/Makefile.am
index 4b1768c..c6714ec 100644
--- a/pixman/Makefile.am
+++ b/pixman/Makefile.am
@@ -126,8 +126,9 @@ endif
 # float code
 if USE_FLOAT
 noinst_LTLIBRARIES += libpixman-float.la
-libpixman_float_la_SOURCES = \
-	pixman-float.c
+libpixman_float_la_SOURCES =	\
+	pixman-float.c		\
+	pixman-access-float.c
 libpixman_float_la_CFLAGS = $(DEP_CFLAGS)
 libpixman_float_la_LIBADD = $(DEP_LIBS)
 libpixman_1_la_LIBADD += libpixman-float.la
diff --git a/pixman/pixman-access-float.c b/pixman/pixman-access-float.c
new file mode 100644
index 0000000..adedc57
--- /dev/null
+++ b/pixman/pixman-access-float.c
@@ -0,0 +1,272 @@
+/*
+ * Copyright © 2010 Movial Creative Technologies Oy
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "pixman-access-float.h"
+
+float _int_conversion_table[65536*2];
+
+static int table_initialised = FALSE;
+
+void _pixman_float_init_table (void)
+{
+    int entry, bits;
+
+    if (table_initialised)
+	return;
+
+    for (bits = 1; bits <= 16; bits++)
+	for (entry = 0; entry < (1 << bits); entry++)
+	    int_conversion[16-bits][entry] = ((float) entry) / (float)((1 << bits) - 1);
+
+    table_initialised = TRUE;
+}
+
+#define SCANLINE_FETCH_FUNC(code)						\
+static void fetch_scanline_## code (const pixman_image_t *image, 		\
+	const int x, const int y, const int width, pixel_float_t *buffer) 	\
+{										\
+    int i;									\
+    const bits_image_t *bits = &(image->bits);					\
+    void *line = get_scanline_pointer(bits, y);					\
+    for (i = 0; i < width; i++)							\
+	buffer[i] = fetch_pixel_## code ##_ptr(bits, line, x+i);		\
+}
+
+#define SCANLINE_FETCH_ALPHA_FUNC(code)						\
+static void fetch_scanline_alpha_## code (const pixman_image_t *image,		\
+	const int x, const int y, const int width, float *buffer)		\
+{										\
+    int i;									\
+    const bits_image_t *bits = &(image->bits);					\
+    void *line = get_scanline_pointer(bits, y);					\
+    for (i = 0; i < width; i++)							\
+	buffer[i] = fetch_pixel_alpha_## code ##_ptr(bits, line, x+i);		\
+}
+
+#define SCANLINE_STORE_FUNC(code)						\
+static void store_scanline_## code (const bits_image_t *image,			\
+	const int x, const int y, const int width, const pixel_float_t *buffer)	\
+{										\
+    int i;									\
+    void *line = get_scanline_pointer(image, y);				\
+    for (i = 0; i < width; i++)							\
+	store_pixel_## code ##_ptr(image, line, x+i, buffer[i]);		\
+}
+
+#define FETCHERS(code, size)	\
+SCANLINE_FETCH_FUNC(code)	\
+SCANLINE_FETCH_ALPHA_FUNC(code)
+
+#define FETCHERS_AND_STORERS(code, size)	\
+SCANLINE_FETCH_FUNC(code)			\
+SCANLINE_FETCH_ALPHA_FUNC(code)			\
+SCANLINE_STORE_FUNC(code)
+
+FETCHERS_AND_STORERS(a8r8g8b8, _32)
+FETCHERS_AND_STORERS(x8r8g8b8, _32)
+FETCHERS_AND_STORERS(a8b8g8r8, _32)
+FETCHERS_AND_STORERS(x8b8g8r8, _32)
+FETCHERS_AND_STORERS(b8g8r8a8, _32)
+FETCHERS_AND_STORERS(b8g8r8x8, _32)
+FETCHERS_AND_STORERS(r8g8b8, _24)
+FETCHERS_AND_STORERS(b8g8r8, _24)
+FETCHERS_AND_STORERS(r5g6b5, _16)
+FETCHERS_AND_STORERS(b5g6r5, _16)
+FETCHERS_AND_STORERS(a1r5g5b5, _16)
+FETCHERS_AND_STORERS(x1r5g5b5, _16)
+FETCHERS_AND_STORERS(a4r4g4b4, _16)
+FETCHERS_AND_STORERS(x4r4g4b4, _16)
+FETCHERS_AND_STORERS(a4b4g4r4, _16)
+FETCHERS_AND_STORERS(x4b4g4r4, _16)
+FETCHERS_AND_STORERS(a8, _8)
+FETCHERS_AND_STORERS(r3g3b2, _8)
+FETCHERS_AND_STORERS(b2g3r3, _8)
+FETCHERS_AND_STORERS(a2r2g2b2, _8)
+FETCHERS_AND_STORERS(a2b2g2r2, _8)
+FETCHERS(c8, _8)
+FETCHERS_AND_STORERS(g8, _8)
+FETCHERS(x4c4, _8)
+FETCHERS(x4g4, _8)
+FETCHERS_AND_STORERS(x4a4, _8)
+FETCHERS_AND_STORERS(a4, _4)
+FETCHERS_AND_STORERS(r1g2b1, _4)
+FETCHERS_AND_STORERS(b1g2r1, _4)
+FETCHERS_AND_STORERS(a1r1g1b1, _4)
+FETCHERS_AND_STORERS(a1b1g1r1, _4)
+FETCHERS_AND_STORERS(c4, _4)
+FETCHERS_AND_STORERS(g4, _4)
+FETCHERS_AND_STORERS(a1, _1)
+FETCHERS_AND_STORERS(g1, _1)
+FETCHERS_AND_STORERS(a2r10g10b10, _32)
+FETCHERS_AND_STORERS(x2r10g10b10, _32)
+FETCHERS_AND_STORERS(a2b10g10r10, _32)
+FETCHERS_AND_STORERS(x2b10g10r10, _32)
+
+FETCHERS_AND_STORERS(any, XX)
+
+/* these formats have their own custom pixel fetchers */
+//SCANLINE_FETCH_FUNC(yuy2)
+//SCANLINE_FETCH_FUNC(yv12)
+//SCANLINE_FETCH_ALPHA_FUNC(yuy2)
+//SCANLINE_FETCH_ALPHA_FUNC(yv12)
+
+typedef struct
+{
+    pixman_format_code_t		format;
+    fetch_scanline_float_t		fetch_scanline;
+    fetch_scanline_alpha_float_t	fetch_scanline_alpha;
+    store_scanline_float_t		store_scanline;
+    fetch_pixel_float_t			fetch_pixel;
+    store_pixel_float_t			store_pixel;
+} format_info_t;
+
+
+#undef FETCHERS
+#undef FETCHERS_AND_STORERS
+
+#define FETCHERS(format, size) {	\
+    PIXMAN_ ## format,			\
+    fetch_scanline_ ## format,		\
+    fetch_scanline_alpha_ ## format,	\
+    NULL,				\
+    fetch_pixel_ ## format, NULL	\
+},
+
+#define FETCHERS_AND_STORERS(format, size) {	\
+    PIXMAN_ ## format,				\
+    fetch_scanline_ ## format,			\
+    fetch_scanline_alpha_ ## format,		\
+    store_scanline_ ## format,			\
+    fetch_pixel_ ## format,			\
+    store_pixel_ ## format 			\
+},
+
+format_info_t float_accessors[] =
+{
+    FETCHERS_AND_STORERS(a8r8g8b8, _32)
+    FETCHERS_AND_STORERS(x8r8g8b8, _32)
+    FETCHERS_AND_STORERS(a8b8g8r8, _32)
+    FETCHERS_AND_STORERS(x8b8g8r8, _32)
+    FETCHERS_AND_STORERS(b8g8r8a8, _32)
+    FETCHERS_AND_STORERS(b8g8r8x8, _32)
+    FETCHERS_AND_STORERS(r8g8b8, _24)
+    FETCHERS_AND_STORERS(b8g8r8, _24)
+    FETCHERS_AND_STORERS(r5g6b5, _16)
+    FETCHERS_AND_STORERS(b5g6r5, _16)
+    FETCHERS_AND_STORERS(a1r5g5b5, _16)
+    FETCHERS_AND_STORERS(x1r5g5b5, _16)
+    FETCHERS_AND_STORERS(a4r4g4b4, _16)
+    FETCHERS_AND_STORERS(x4r4g4b4, _16)
+    FETCHERS_AND_STORERS(a4b4g4r4, _16)
+    FETCHERS_AND_STORERS(x4b4g4r4, _16)
+    FETCHERS_AND_STORERS(a8, _8)
+    FETCHERS_AND_STORERS(r3g3b2, _8)
+    FETCHERS_AND_STORERS(b2g3r3, _8)
+    FETCHERS_AND_STORERS(a2r2g2b2, _8)
+    FETCHERS_AND_STORERS(a2b2g2r2, _8)
+    FETCHERS(c8, _8)
+    FETCHERS_AND_STORERS(g8, _8)
+    FETCHERS(x4c4, _8)
+    FETCHERS(x4g4, _8)
+    FETCHERS_AND_STORERS(x4a4, _8)
+    FETCHERS_AND_STORERS(a4, _4)
+    FETCHERS_AND_STORERS(r1g2b1, _4)
+    FETCHERS_AND_STORERS(b1g2r1, _4)
+    FETCHERS_AND_STORERS(a1r1g1b1, _4)
+    FETCHERS_AND_STORERS(a1b1g1r1, _4)
+    FETCHERS_AND_STORERS(c4, _4)
+    FETCHERS_AND_STORERS(g4, _4)
+    FETCHERS_AND_STORERS(a1, _1)
+    FETCHERS_AND_STORERS(g1, _1)
+    FETCHERS_AND_STORERS(a2r10g10b10, _32)
+    FETCHERS_AND_STORERS(x2r10g10b10, _32)
+    FETCHERS_AND_STORERS(a2b10g10r10, _32)
+    FETCHERS_AND_STORERS(x2b10g10r10, _32)
+
+    FETCHERS_AND_STORERS(any, XX)
+};
+
+fetch_scanline_float_t _pixman_float_lookup_scanline_fetcher(pixman_format_code_t format)
+{
+    int i;
+
+    _pixman_float_init_table();
+
+    for (i = 0; float_accessors[i].format != PIXMAN_any; i++)
+	if (float_accessors[i].format == format)
+	    return float_accessors[i].fetch_scanline;
+
+    return NULL;
+}
+
+fetch_scanline_alpha_float_t _pixman_float_lookup_scanline_alpha_fetcher(pixman_format_code_t format)
+{
+    int i;
+
+    _pixman_float_init_table();
+
+    for (i = 0; float_accessors[i].format != PIXMAN_any; i++)
+	if (float_accessors[i].format == format)
+	    return float_accessors[i].fetch_scanline_alpha;
+
+    return NULL;
+}
+
+store_scanline_float_t _pixman_float_lookup_scanline_storer(pixman_format_code_t format)
+{
+    int i;
+
+    _pixman_float_init_table();
+
+    for (i = 0; float_accessors[i].format != PIXMAN_any; i++)
+	if (float_accessors[i].format == format)
+	    return float_accessors[i].store_scanline;
+
+    return NULL;
+}
+
+fetch_pixel_float_t _pixman_float_lookup_pixel_fetcher(pixman_format_code_t format)
+{
+    int i;
+
+    _pixman_float_init_table();
+
+    for (i = 0; float_accessors[i].format != PIXMAN_any; i++)
+	if (float_accessors[i].format == format)
+	    return float_accessors[i].fetch_pixel;
+
+    return NULL;
+}
+
+store_pixel_float_t _pixman_float_lookup_pixel_storer(pixman_format_code_t format)
+{
+    int i;
+
+    _pixman_float_init_table();
+
+    for (i = 0; float_accessors[i].format != PIXMAN_any; i++)
+	if (float_accessors[i].format == format)
+	    return float_accessors[i].store_pixel;
+
+    return NULL;
+}
diff --git a/pixman/pixman-access-float.h b/pixman/pixman-access-float.h
new file mode 100644
index 0000000..3f382ea
--- /dev/null
+++ b/pixman/pixman-access-float.h
@@ -0,0 +1,789 @@
+/*
+ * Copyright © 2010 Movial Creative Technologies Oy
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <assert.h>
+
+#include "pixman-private.h"
+#include "pixman-accessor.h"
+
+typedef void (*fetch_scanline_float_t) (
+		const pixman_image_t *image,
+		const int             x,
+		const int             y,
+		const int             width,
+		pixel_float_t  *buffer );
+
+typedef void (*fetch_scanline_alpha_float_t) (
+		const pixman_image_t *image,
+		const int             x,
+		const int             y,
+		const int             width,
+		float          *buffer );
+
+typedef pixel_float_t (*fetch_pixel_float_t) (
+		const bits_image_t *image,
+		const int           x,
+		const int           y);
+
+typedef void (*store_scanline_float_t) (
+		const bits_image_t   *image,
+		const int             x,
+		const int             y,
+		const int             width,
+		const pixel_float_t  *values);
+
+typedef void (*store_pixel_float_t) (
+		const bits_image_t *image,
+		const int           x,
+		const int           y,
+		const pixel_float_t value);
+
+/* int_conversion[16-bits][entry] == ((float) entry) / (float)((1 << bits) - 1) */
+extern float _int_conversion_table[65536*2];
+
+static float *int_conversion[17] = {
+    _int_conversion_table + 65536, /* 16 bits */
+    _int_conversion_table + 32768,
+    _int_conversion_table + 16384,
+    _int_conversion_table +  8192,
+    _int_conversion_table +  4096,
+    _int_conversion_table +  2048,
+    _int_conversion_table +  1024, /* 10 bits */
+    _int_conversion_table +   512,
+    _int_conversion_table +   256, /* 8 bits */
+    _int_conversion_table +   128,
+    _int_conversion_table +    64,
+    _int_conversion_table +    32,
+    _int_conversion_table +    16,
+    _int_conversion_table +     8,
+    _int_conversion_table +     4,
+    _int_conversion_table +     2, /* 1 bit */
+    _int_conversion_table          /* 0 bits, for safety */
+};
+
+/*
+ * Fetch and store pixels from normal fixed-point pixel formats
+ * to intermediate floating-point format.
+ */
+
+static force_inline float
+pixel_to_gray(const pixel_float_t in)
+{
+    return in.r * (153.0f / 512.0f) + in.g * (301.0f / 512.0f) + in.b * (58.0f / 512.0f);
+}
+
+static force_inline uint32_t
+build_pixel_a(const pixel_float_t value, const pixman_format_code_t format)
+{
+    const uint32_t a_max = (1 << PIXMAN_FORMAT_A(format)) - 1;
+    uint32_t a = (uint32_t) (value.a * (float) a_max + 0.5f);
+
+    if(a > a_max)
+	a = a_max;
+
+    return a;
+}
+
+static force_inline uint32_t
+build_pixel_gray(const pixel_float_t value, const pixman_format_code_t format)
+{
+    const uint32_t g_max = (1 << PIXMAN_FORMAT_BPP(format)) - 1;
+    uint32_t g = (uint32_t) (pixel_to_gray(value) * (float) g_max + 0.5f);
+
+    if (g > g_max)
+	g = g_max;
+
+    return g;
+}
+
+static force_inline uint32_t
+build_pixel_argb(const pixel_float_t value, const pixman_format_code_t format)
+{
+    const uint32_t a_max = (1 << PIXMAN_FORMAT_A(format)) - 1;
+    const uint32_t r_max = (1 << PIXMAN_FORMAT_R(format)) - 1;
+    const uint32_t g_max = (1 << PIXMAN_FORMAT_G(format)) - 1;
+    const uint32_t b_max = (1 << PIXMAN_FORMAT_B(format)) - 1;
+
+    uint32_t a = (uint32_t) (value.a * (float) a_max + 0.5f);
+    uint32_t r = (uint32_t) (value.r * (float) r_max + 0.5f);
+    uint32_t g = (uint32_t) (value.g * (float) g_max + 0.5f);
+    uint32_t b = (uint32_t) (value.b * (float) b_max + 0.5f);
+
+    const uint32_t g_shift = PIXMAN_FORMAT_B(format);
+    const uint32_t r_shift = PIXMAN_FORMAT_G(format) + g_shift;
+    const uint32_t a_shift = PIXMAN_FORMAT_R(format) + r_shift;
+
+    if (a > a_max)
+	a = a_max;
+
+    if (r > r_max)
+	r = r_max;
+
+    if (g > g_max)
+	g = g_max;
+
+    if (b > b_max)
+	b = b_max;
+
+    return (a << a_shift) | (r << r_shift) | (g << g_shift) | b;
+}
+
+static force_inline uint32_t
+build_pixel_abgr(const pixel_float_t value, const pixman_format_code_t format)
+{
+    const uint32_t a_max = (1 << PIXMAN_FORMAT_A(format)) - 1;
+    const uint32_t r_max = (1 << PIXMAN_FORMAT_R(format)) - 1;
+    const uint32_t g_max = (1 << PIXMAN_FORMAT_G(format)) - 1;
+    const uint32_t b_max = (1 << PIXMAN_FORMAT_B(format)) - 1;
+
+    uint32_t a = (uint32_t) (value.a * (float) a_max + 0.5f);
+    uint32_t r = (uint32_t) (value.r * (float) r_max + 0.5f);
+    uint32_t g = (uint32_t) (value.g * (float) g_max + 0.5f);
+    uint32_t b = (uint32_t) (value.b * (float) b_max + 0.5f);
+
+    const uint32_t g_shift = PIXMAN_FORMAT_R(format);
+    const uint32_t b_shift = PIXMAN_FORMAT_G(format) + g_shift;
+    const uint32_t a_shift = PIXMAN_FORMAT_B(format) + b_shift;
+
+    if (a > a_max)
+	a = a_max;
+
+    if (r > r_max)
+	r = r_max;
+
+    if (g > g_max)
+	g = g_max;
+
+    if (b > b_max)
+	b = b_max;
+
+    return (a << a_shift) | (b << b_shift) | (g << g_shift) | r;
+}
+
+static force_inline uint32_t
+build_pixel_bgra(const pixel_float_t value, const pixman_format_code_t format)
+{
+    const uint32_t a_max = (1 << PIXMAN_FORMAT_A(format)) - 1;
+    const uint32_t r_max = (1 << PIXMAN_FORMAT_R(format)) - 1;
+    const uint32_t g_max = (1 << PIXMAN_FORMAT_G(format)) - 1;
+    const uint32_t b_max = (1 << PIXMAN_FORMAT_B(format)) - 1;
+
+    uint32_t a = (uint32_t) (value.a * (float) a_max + 0.5f);
+    uint32_t r = (uint32_t) (value.r * (float) r_max + 0.5f);
+    uint32_t g = (uint32_t) (value.g * (float) g_max + 0.5f);
+    uint32_t b = (uint32_t) (value.b * (float) b_max + 0.5f);
+
+    const uint32_t r_shift = PIXMAN_FORMAT_A(format);
+    const uint32_t g_shift = PIXMAN_FORMAT_R(format) + r_shift;
+    const uint32_t b_shift = PIXMAN_FORMAT_G(format) + g_shift;
+
+    if (a > a_max)
+	a = a_max;
+
+    if (r > r_max)
+	r = r_max;
+
+    if (g > g_max)
+	g = g_max;
+
+    if (b > b_max)
+	b = b_max;
+
+    return (b << b_shift) | (g << g_shift) | (r << r_shift) | a;
+}
+
+static force_inline uint32_t
+build_pixel_generic(const pixel_float_t value, const pixman_format_code_t format)
+{
+    if (PIXMAN_FORMAT_TYPE(format) == PIXMAN_TYPE_A)
+	return build_pixel_a(value, format);
+
+    if (PIXMAN_FORMAT_TYPE(format) == PIXMAN_TYPE_ARGB)
+	return build_pixel_argb(value, format);
+
+    if (PIXMAN_FORMAT_TYPE(format) == PIXMAN_TYPE_ABGR)
+	return build_pixel_abgr(value, format);
+
+    if (PIXMAN_FORMAT_TYPE(format) == PIXMAN_TYPE_BGRA)
+	return build_pixel_bgra(value, format);
+
+    if (PIXMAN_FORMAT_TYPE(format) == PIXMAN_TYPE_GRAY)
+	return build_pixel_gray(value, format);
+
+    assert(!"Can't handle this format yet!");
+    return 0;
+}
+
+static force_inline pixel_float_t
+decode_pixel_a(const uint32_t in, const pixman_format_code_t format)
+{
+    uint32_t a_max = (1 << PIXMAN_FORMAT_A(format)) - 1;
+    pixel_float_t out = {
+	a: int_conversion[16-PIXMAN_FORMAT_A(format)][in & a_max],
+	r:0,
+	g:0,
+	b:0
+    };
+    return out;
+}
+
+static force_inline pixel_float_t
+decode_pixel_gray(const uint32_t in, const pixman_format_code_t format)
+{
+    float gray = int_conversion[16-PIXMAN_FORMAT_BPP(format)][in];
+    pixel_float_t out = {
+	a:1,
+	r:gray,
+	g:gray,
+	b:gray
+    };
+    return out;
+}
+
+static force_inline pixel_float_t
+decode_pixel_argb(const uint32_t in, const pixman_format_code_t format)
+{
+    uint32_t a_max = (1 << PIXMAN_FORMAT_A(format)) - 1;
+    uint32_t r_max = (1 << PIXMAN_FORMAT_R(format)) - 1;
+    uint32_t g_max = (1 << PIXMAN_FORMAT_G(format)) - 1;
+    uint32_t b_max = (1 << PIXMAN_FORMAT_B(format)) - 1;
+
+    uint32_t g_shift = PIXMAN_FORMAT_B(format);
+    uint32_t r_shift = PIXMAN_FORMAT_G(format) + g_shift;
+    uint32_t a_shift = PIXMAN_FORMAT_R(format) + r_shift;
+
+    pixel_float_t out;
+
+    if (PIXMAN_FORMAT_A(format))
+	out.a = int_conversion[16-PIXMAN_FORMAT_A(format)][(in >> a_shift) & a_max];
+    else
+	out.a = 1.0f;
+
+    out.r = int_conversion[16-PIXMAN_FORMAT_R(format)][(in >> r_shift) & r_max];
+    out.g = int_conversion[16-PIXMAN_FORMAT_G(format)][(in >> g_shift) & g_max];
+    out.b = int_conversion[16-PIXMAN_FORMAT_B(format)][(in           ) & b_max];
+
+    return out;
+}
+
+static force_inline pixel_float_t
+decode_pixel_abgr(const uint32_t in, const pixman_format_code_t format)
+{
+    uint32_t a_max = (1 << PIXMAN_FORMAT_A(format)) - 1;
+    uint32_t r_max = (1 << PIXMAN_FORMAT_R(format)) - 1;
+    uint32_t g_max = (1 << PIXMAN_FORMAT_G(format)) - 1;
+    uint32_t b_max = (1 << PIXMAN_FORMAT_B(format)) - 1;
+
+    uint32_t g_shift = PIXMAN_FORMAT_R(format);
+    uint32_t b_shift = PIXMAN_FORMAT_G(format) + g_shift;
+    uint32_t a_shift = PIXMAN_FORMAT_B(format) + b_shift;
+
+    pixel_float_t out;
+
+    if (PIXMAN_FORMAT_A(format))
+	out.a = int_conversion[16-PIXMAN_FORMAT_A(format)][(in >> a_shift) & a_max];
+    else
+	out.a = 1.0f;
+
+    out.b = int_conversion[16-PIXMAN_FORMAT_B(format)][(in >> b_shift) & b_max];
+    out.g = int_conversion[16-PIXMAN_FORMAT_G(format)][(in >> g_shift) & g_max];
+    out.r = int_conversion[16-PIXMAN_FORMAT_R(format)][(in           ) & r_max];
+
+    return out;
+}
+
+static force_inline pixel_float_t
+decode_pixel_bgra(const uint32_t in, const pixman_format_code_t format)
+{
+    uint32_t a_max = (1 << PIXMAN_FORMAT_A(format)) - 1;
+    uint32_t r_max = (1 << PIXMAN_FORMAT_R(format)) - 1;
+    uint32_t g_max = (1 << PIXMAN_FORMAT_G(format)) - 1;
+    uint32_t b_max = (1 << PIXMAN_FORMAT_B(format)) - 1;
+
+    uint32_t r_shift = PIXMAN_FORMAT_A(format);
+    uint32_t g_shift = PIXMAN_FORMAT_R(format) + r_shift;
+    uint32_t b_shift = PIXMAN_FORMAT_G(format) + g_shift;
+
+    pixel_float_t out;
+
+    if (PIXMAN_FORMAT_A(format))
+	out.a = int_conversion[16-PIXMAN_FORMAT_A(format)][in & a_max];
+    else
+	out.a = 1.0f;
+
+    out.r = int_conversion[16-PIXMAN_FORMAT_R(format)][(in >> r_shift) & r_max];
+    out.g = int_conversion[16-PIXMAN_FORMAT_G(format)][(in >> g_shift) & g_max];
+    out.b = int_conversion[16-PIXMAN_FORMAT_B(format)][(in >> b_shift) & b_max];
+
+    return out;
+}
+
+static force_inline pixel_float_t
+decode_pixel_generic(const uint32_t in, const pixman_format_code_t format)
+{
+    if (PIXMAN_FORMAT_TYPE(format) == PIXMAN_TYPE_A)
+	return decode_pixel_a(in, format);
+
+    if (PIXMAN_FORMAT_TYPE(format) == PIXMAN_TYPE_ARGB)
+	return decode_pixel_argb(in, format);
+
+    if (PIXMAN_FORMAT_TYPE(format) == PIXMAN_TYPE_ABGR)
+	return decode_pixel_abgr(in, format);
+
+    if (PIXMAN_FORMAT_TYPE(format) == PIXMAN_TYPE_BGRA)
+	return decode_pixel_bgra(in, format);
+
+    if (PIXMAN_FORMAT_TYPE(format) == PIXMAN_TYPE_GRAY)
+	return decode_pixel_gray(in, format);
+
+    {
+	pixel_float_t out = {a:1,r:0,g:0,b:0};
+	assert(!"Can't handle this format yet!");
+	return out;
+    }
+}
+
+static force_inline void*
+get_scanline_pointer(const bits_image_t *image, const int y)
+{
+    return image->bits + y * image->rowstride;
+}
+
+static force_inline pixel_float_t
+fetch_pixel_generic_24(const uint8_t *line, const int x, const pixman_format_code_t format)
+{
+    pixel_float_t out = {a:1, r:0, g:0, b:0};
+    uint8_t in1 = line[x*3+0];
+    uint8_t in2 = line[x*3+1];
+    uint8_t in3 = line[x*3+2];
+
+    /* Only bother supporting two defined formats for now */
+#ifdef WORDS_BIGENDIAN
+    if (format == PIXMAN_r8g8b8)
+#else
+    if (format == PIXMAN_b8g8r8)
+#endif
+    {
+	out.r = int_conversion[8][in1];
+	out.g = int_conversion[8][in2];
+	out.b = int_conversion[8][in3];
+    }
+
+#ifdef WORDS_BIGENDIAN
+    if (format == PIXMAN_b8g8r8)
+#else
+    if(format == PIXMAN_r8g8b8)
+#endif
+    {
+	out.r = int_conversion[8][in3];
+	out.g = int_conversion[8][in2];
+	out.b = int_conversion[8][in1];
+    }
+
+    if (format != PIXMAN_b8g8r8 && format != PIXMAN_r8g8b8)
+	assert(!"Can't handle this format yet!");
+
+    return out;
+}
+
+static force_inline void
+store_pixel_generic_24(uint8_t *line, const int x, const pixel_float_t value, const pixman_format_code_t format)
+{
+    uint8_t *p = line + x*3;
+
+    /* Only bother supporting two defined formats for now */
+#ifdef WORDS_BIGENDIAN
+    if (format == PIXMAN_r8g8b8)
+#else
+    if (format == PIXMAN_b8g8r8)
+#endif
+    {
+	p[0] = (uint8_t)(value.r * 255.0f + 0.5f);
+	p[1] = (uint8_t)(value.g * 255.0f + 0.5f);
+	p[2] = (uint8_t)(value.b * 255.0f + 0.5f);
+    }
+
+#ifdef WORDS_BIGENDIAN
+    if (format == PIXMAN_b8g8r8)
+#else
+    if (format == PIXMAN_r8g8b8)
+#endif
+    {
+	p[0] = (uint8_t)(value.b * 255.0f + 0.5f);
+	p[1] = (uint8_t)(value.g * 255.0f + 0.5f);
+	p[2] = (uint8_t)(value.r * 255.0f + 0.5f);
+    }
+
+    if (format != PIXMAN_b8g8r8 && format != PIXMAN_r8g8b8)
+	assert(!"Can't handle this format yet!");
+}
+
+static force_inline uint32_t
+fetch_pixel_generic_4(const uint8_t *line, const int x)
+{
+    uint8_t in = line[x >> 1];
+
+#ifdef WORDS_BIGENDIAN
+    if (x & 1)
+	in &= 0xF;
+    else
+	in >>= 4;
+#else
+    if (x & 1)
+	in >>= 4;
+    else
+	in &= 0xF;
+#endif
+
+    return in;
+}
+
+static force_inline void
+store_pixel_generic_4(uint8_t *line, const int x, const uint32_t value)
+{
+    uint8_t *p = line + (x >> 1);
+#ifdef WORDS_BIGENDIAN
+    int shift = ((~x) & 1) << 2;
+#else
+    int shift = (x & 1) << 2;
+#endif
+
+    *p = (*p & ~(0xf << shift)) | (value << shift);
+}
+
+static force_inline pixel_float_t
+fetch_pixel_generic_1(const uint8_t *line, const int x, const pixman_format_code_t format)
+{
+    pixel_float_t out = {a:1, r:0, g:0, b:0};
+    uint8_t in = line[x >> 3];
+
+#ifdef WORDS_BIGENDIAN
+    in &= 1 << (x & 7);
+#else
+    in = (in >> (x & 7)) & 1;
+#endif
+
+    if (format == PIXMAN_a1)
+	out.a = in ? 1.0f : 0.0f;
+    else if (format == PIXMAN_g1)
+	out.r = out.g = out.b = in ? 1.0f : 0.0f;
+    else
+	assert(!"Can't handle this format yet!");
+
+    return out;
+}
+
+static force_inline void
+store_pixel_generic_1(uint8_t *line, const int x, const pixel_float_t value, const pixman_format_code_t format)
+{
+    uint8_t *p = line + (x >> 8);
+    float t = (format == PIXMAN_a1) ? value.a : pixel_to_gray(value);
+
+#ifdef WORDS_BIGENDIAN
+    int shift = 7 - (x & 7);
+#else
+    int shift = (x & 7);
+#endif
+
+    assert(format == PIXMAN_a1 || format == PIXMAN_g1);
+
+    if (t >= 0.5f)
+	*p |= 1 << shift;
+    else
+	*p &= ~(1 << shift);
+}
+
+static inline pixel_float_t
+fetch_pixel_yuy2_ptr(const bits_image_t *image, const uint8_t *bits, const int x)
+{
+    float Y = int_conversion[8][bits[x << 1]] - int_conversion[8][16];
+    float U = int_conversion[8][bits[((x << 1) & (~3)) + 1]] - int_conversion[8][128];
+    float V = int_conversion[8][bits[((x << 1) & (~3)) + 3]] - int_conversion[8][128];
+    pixel_float_t out = {
+	r: (1.164f * Y + 1.596f * V),
+	g: (1.164f * Y - 0.813f * V - 0.391f * U),
+	b: (1.164f * Y + 2.018f * U),
+	a: 1.0f
+    };
+
+    return out;
+}
+
+static inline pixel_float_t
+fetch_pixel_yv12(const bits_image_t *image, const int x, const int y)
+{
+    int stride = image->rowstride;
+    int offset0 = stride < 0 ? ((-stride) >> 1) * ((image->height - 1) >> 1) - stride : stride * image->height;
+    int offset1 = stride < 0 ? offset0 + ((-stride) >> 1) * ((image->height) >> 1) : offset0 + (offset0 >> 2);
+    uint8_t *y_line = (uint8_t*)(image->bits + stride * y);
+    uint8_t *u_line = (uint8_t*)(image->bits + offset1 + (stride >> 1) * (y >> 1));
+    uint8_t *v_line = (uint8_t*)(image->bits + offset0 + (stride >> 1) * (y >> 1));
+    float Y = int_conversion[8][y_line[x]] - int_conversion[8][16];
+    float U = int_conversion[8][u_line[x >> 1]] - int_conversion[8][128];
+    float V = int_conversion[8][v_line[x >> 1]] - int_conversion[8][128];
+    pixel_float_t out = {
+	r: (1.164f * Y + 1.596f * V),
+	g: (1.164f * Y - 0.813f * V - 0.391f * U),
+	b: (1.164f * Y + 2.018f * U),
+	a: 1.0f
+    };
+
+    return out;
+}
+
+static force_inline pixel_float_t
+fetch_pixel_generic_ptr(const bits_image_t *image, const void *line, const int x, const pixman_format_code_t format)
+{
+    uint32_t in;
+
+    if (PIXMAN_FORMAT_BPP(format) == 32)
+	in = ((uint32_t*) line)[x];
+    else if (PIXMAN_FORMAT_BPP(format) == 16)
+	in = ((uint16_t*) line)[x];
+    else if (PIXMAN_FORMAT_BPP(format) == 8)
+	in = ((uint8_t*) line)[x];
+    else if (PIXMAN_FORMAT_BPP(format) == 4)
+	in = fetch_pixel_generic_4(line, x);
+    else if (PIXMAN_FORMAT_BPP(format) == 24)
+	return fetch_pixel_generic_24(line, x, format);
+    else {
+	pixel_float_t out = {a:1, r:0, g:0, b:0};
+	assert(!"Can't handle this format yet!");
+	return out;
+    }
+
+    if(PIXMAN_FORMAT_TYPE(format) == PIXMAN_TYPE_COLOR)
+	return decode_pixel_argb(image->indexed->rgba[in], PIXMAN_a8r8g8b8);
+
+    return decode_pixel_generic(in, format);
+}
+
+static force_inline pixel_float_t
+fetch_pixel_generic(const bits_image_t *image, const int x, const int y, const pixman_format_code_t format)
+{
+    const void* line = get_scanline_pointer(image, y);
+
+    if (format == PIXMAN_yv12)
+	return fetch_pixel_yv12(image, x, y);
+
+    if (format == PIXMAN_yuy2)
+	return fetch_pixel_yuy2_ptr(image, line, x);
+
+    if (PIXMAN_FORMAT_BPP(format) == 24)
+	return fetch_pixel_generic_24(line, x, format);
+
+    if (PIXMAN_FORMAT_BPP(format) == 1)
+	return fetch_pixel_generic_1(line, x, format);
+
+    if (PIXMAN_FORMAT_TYPE(format) != PIXMAN_TYPE_A &&
+	PIXMAN_FORMAT_TYPE(format) != PIXMAN_TYPE_ARGB &&
+	PIXMAN_FORMAT_TYPE(format) != PIXMAN_TYPE_ABGR &&
+	PIXMAN_FORMAT_TYPE(format) != PIXMAN_TYPE_BGRA &&
+	PIXMAN_FORMAT_TYPE(format) != PIXMAN_TYPE_GRAY &&
+	PIXMAN_FORMAT_TYPE(format) != PIXMAN_TYPE_COLOR)
+    {
+	pixel_float_t out = {a:1, r:0, g:0, b:0};
+	assert(!"Can't handle this format yet!");
+	return out;
+    }
+
+    return fetch_pixel_generic_ptr(image, line, x, format);
+}
+
+static force_inline float
+fetch_pixel_alpha_generic(const bits_image_t *image, const int x, const int y, const pixman_format_code_t format)
+{
+    if (!PIXMAN_FORMAT_A(format) && PIXMAN_FORMAT_TYPE(format) != PIXMAN_TYPE_COLOR)
+	return 1.0f;
+
+    return fetch_pixel_generic(image, x, y, format).a;
+}
+
+static force_inline void
+store_pixel_generic_ptr(void *line, const int x, const pixel_float_t value, const pixman_format_code_t format)
+{
+    uint32_t out = build_pixel_generic(value, format);
+
+    if (PIXMAN_FORMAT_BPP(format) == 32)
+	((uint32_t*) line)[x] = out;
+    else if (PIXMAN_FORMAT_BPP(format) == 24)
+	store_pixel_generic_24(line, x, value, format);
+    else if (PIXMAN_FORMAT_BPP(format) == 16)
+	((uint16_t*) line)[x] = out;
+    else if (PIXMAN_FORMAT_BPP(format) == 8)
+	((uint8_t*) line)[x] = out;
+    else if (PIXMAN_FORMAT_BPP(format) == 4)
+	store_pixel_generic_4(line, x, out);
+    else if (PIXMAN_FORMAT_BPP(format) == 1)
+	store_pixel_generic_1(line, x, value, format);
+    else
+	assert(!"Can't handle this format yet!");
+}
+
+static force_inline void
+store_pixel_generic(const bits_image_t *image, const int x, const int y, const pixel_float_t value, const pixman_format_code_t format)
+{
+    if (PIXMAN_FORMAT_TYPE(format) == PIXMAN_TYPE_A ||
+		    PIXMAN_FORMAT_TYPE(format) == PIXMAN_TYPE_ARGB ||
+		    PIXMAN_FORMAT_TYPE(format) == PIXMAN_TYPE_ABGR ||
+		    PIXMAN_FORMAT_TYPE(format) == PIXMAN_TYPE_BGRA ||
+		    PIXMAN_FORMAT_TYPE(format) == PIXMAN_TYPE_GRAY )
+    {
+	void *line = get_scanline_pointer(image, y);
+	store_pixel_generic_ptr(line, x, value, format);
+    } else {
+	assert(!"Can't handle this format yet!");
+    }
+}
+
+#define PIXEL_FETCH_FUNC(code) 						\
+static inline pixel_float_t						\
+fetch_pixel_## code (const bits_image_t *image,				\
+		const int x, const int y)				\
+{									\
+    return fetch_pixel_generic(image, x, y, PIXMAN_## code );		\
+}									\
+									\
+static inline pixel_float_t						\
+fetch_pixel_## code ##_ptr (const bits_image_t *image,			\
+		const void *line, const int x)				\
+{									\
+    return fetch_pixel_generic_ptr(image, line, x, PIXMAN_## code );	\
+}
+
+#define ALPHA_FETCH_FUNC(code)						\
+static inline float							\
+fetch_pixel_alpha_## code (const bits_image_t *image,			\
+		const int x, const int y)				\
+{									\
+    return fetch_pixel_## code(image, x, y).a;				\
+}									\
+									\
+static inline float							\
+fetch_pixel_alpha_## code ##_ptr (const bits_image_t *image,		\
+	       const void *line, const int x)				\
+{									\
+    return fetch_pixel_## code ##_ptr(image, line, x).a;		\
+}
+
+#define PIXEL_STORE_FUNC(code)						\
+static inline void							\
+store_pixel_## code (const bits_image_t *image,				\
+		const int x, const int y, const pixel_float_t value)	\
+{									\
+    void *line = get_scanline_pointer(image, y);			\
+    return store_pixel_generic_ptr(line, x, value, PIXMAN_## code );	\
+}									\
+static inline void							\
+store_pixel_## code ##_ptr (const bits_image_t *image,			\
+		void *line, const int x, const pixel_float_t value)	\
+{									\
+    return store_pixel_generic_ptr(line, x, value, PIXMAN_## code );	\
+}
+
+#define FETCHERS(code)			\
+PIXEL_FETCH_FUNC(code)			\
+ALPHA_FETCH_FUNC(code)
+
+#define FETCHERS_AND_STORERS(code)	\
+PIXEL_FETCH_FUNC(code)			\
+ALPHA_FETCH_FUNC(code)			\
+PIXEL_STORE_FUNC(code)
+
+FETCHERS_AND_STORERS(a8r8g8b8)
+FETCHERS_AND_STORERS(x8r8g8b8)
+FETCHERS_AND_STORERS(a8b8g8r8)
+FETCHERS_AND_STORERS(x8b8g8r8)
+FETCHERS_AND_STORERS(b8g8r8a8)
+FETCHERS_AND_STORERS(b8g8r8x8)
+FETCHERS_AND_STORERS(r8g8b8)
+FETCHERS_AND_STORERS(b8g8r8)
+FETCHERS_AND_STORERS(r5g6b5)
+FETCHERS_AND_STORERS(b5g6r5)
+FETCHERS_AND_STORERS(a1r5g5b5)
+FETCHERS_AND_STORERS(x1r5g5b5)
+FETCHERS_AND_STORERS(a4r4g4b4)
+FETCHERS_AND_STORERS(x4r4g4b4)
+FETCHERS_AND_STORERS(a4b4g4r4)
+FETCHERS_AND_STORERS(x4b4g4r4)
+FETCHERS_AND_STORERS(a8)
+FETCHERS_AND_STORERS(r3g3b2)
+FETCHERS_AND_STORERS(b2g3r3)
+FETCHERS_AND_STORERS(a2r2g2b2)
+FETCHERS_AND_STORERS(a2b2g2r2)
+FETCHERS(c8)
+FETCHERS_AND_STORERS(g8)
+FETCHERS(x4c4)
+FETCHERS(x4g4)
+FETCHERS_AND_STORERS(x4a4)
+FETCHERS_AND_STORERS(a4)
+FETCHERS_AND_STORERS(r1g2b1)
+FETCHERS_AND_STORERS(b1g2r1)
+FETCHERS_AND_STORERS(a1r1g1b1)
+FETCHERS_AND_STORERS(a1b1g1r1)
+FETCHERS_AND_STORERS(c4)
+FETCHERS_AND_STORERS(g4)
+FETCHERS_AND_STORERS(a1)
+FETCHERS_AND_STORERS(g1)
+FETCHERS_AND_STORERS(a2r10g10b10)
+FETCHERS_AND_STORERS(x2r10g10b10)
+FETCHERS_AND_STORERS(a2b10g10r10)
+FETCHERS_AND_STORERS(x2b10g10r10)
+
+#undef FETCHERS
+#undef FETCHERS_AND_STORERS
+
+static pixel_float_t fetch_pixel_any (const bits_image_t *image, const int x, const int y)
+{
+    return fetch_pixel_generic(image, x, y, image->format);
+}
+
+static pixel_float_t fetch_pixel_any_ptr (const bits_image_t *image, const void *line, const int x)
+{
+    return fetch_pixel_generic_ptr(image, line, x, image->format);
+}
+
+static float fetch_pixel_alpha_any (const bits_image_t *image, const int x, const int y)
+{
+    return fetch_pixel_any(image, x, y).a;
+}
+
+static float fetch_pixel_alpha_any_ptr (const bits_image_t *image, const void *line, const int x)
+{
+    return fetch_pixel_any_ptr(image, line, x).a;
+}
+
+static void store_pixel_any (const bits_image_t *image, const int x, const int y, const pixel_float_t value)
+{
+    void *line = get_scanline_pointer(image, y);
+    return store_pixel_generic_ptr(line, x, value, image->format);
+}
+
+static void store_pixel_any_ptr (const bits_image_t *image, void *line, const int x, const pixel_float_t value)
+{
+    return store_pixel_generic_ptr(line, x, value, image->format);
+}
-- 
1.6.3.3



More information about the Pixman mailing list