aboutsummaryrefslogtreecommitdiff
path: root/pixman
diff options
context:
space:
mode:
Diffstat (limited to 'pixman')
-rw-r--r--pixman/.gitignore2
-rw-r--r--pixman/demos/Makefile.am4
-rw-r--r--pixman/demos/srgb-test.c96
-rw-r--r--pixman/pixman/Makefile.sources5
-rw-r--r--pixman/pixman/make-srgb.pl112
-rw-r--r--pixman/pixman/pixman-access.c134
-rw-r--r--pixman/pixman/pixman-image.c3
-rw-r--r--pixman/pixman/pixman-private.h15
-rw-r--r--pixman/pixman/pixman.c1
-rw-r--r--pixman/pixman/pixman.h4
-rw-r--r--pixman/test/composite.c76
-rw-r--r--pixman/test/stress-test.c1
-rw-r--r--pixman/test/utils.c36
-rw-r--r--pixman/test/utils.h6
14 files changed, 476 insertions, 19 deletions
diff --git a/pixman/.gitignore b/pixman/.gitignore
index b9853b117..a4d9f99a7 100644
--- a/pixman/.gitignore
+++ b/pixman/.gitignore
@@ -36,12 +36,14 @@ demos/gradient-test
demos/quad2quad
demos/radial-test
demos/screen-test
+demos/srgb-test
demos/trap-test
demos/tri-test
pixman/pixman-combine32.c
pixman/pixman-combine32.h
pixman/pixman-combine64.c
pixman/pixman-combine64.h
+pixman/pixman-srgb.c
pixman/pixman-version.h
test/a1-trap-test
test/affine-test
diff --git a/pixman/demos/Makefile.am b/pixman/demos/Makefile.am
index 9aac1f5e9..d8fb0dab2 100644
--- a/pixman/demos/Makefile.am
+++ b/pixman/demos/Makefile.am
@@ -20,7 +20,8 @@ DEMOS = \
trap-test \
tri-test \
quad2quad \
- checkerboard
+ checkerboard \
+ srgb-test
EXTRA_DIST = parrot.c parrot.jpg
@@ -35,6 +36,7 @@ convolution_test_SOURCES = convolution-test.c $(GTK_UTILS)
radial_test_SOURCES = radial-test.c $(GTK_UTILS)
tri_test_SOURCES = tri-test.c $(GTK_UTILS)
checkerboard_SOURCES = checkerboard.c $(GTK_UTILS)
+srgb_test_SOURCES = srgb-test.c $(GTK_UTILS)
noinst_PROGRAMS = $(DEMOS)
diff --git a/pixman/demos/srgb-test.c b/pixman/demos/srgb-test.c
new file mode 100644
index 000000000..bc073491e
--- /dev/null
+++ b/pixman/demos/srgb-test.c
@@ -0,0 +1,96 @@
+#include <math.h>
+
+#include "pixman.h"
+#include "gtk-utils.h"
+
+static uint32_t
+linear_argb_to_premult_argb (float a,
+ float r,
+ float g,
+ float b)
+{
+ r *= a;
+ g *= a;
+ b *= a;
+ return (uint32_t) (a * 255.0f + 0.5f) << 24
+ | (uint32_t) (r * 255.0f + 0.5f) << 16
+ | (uint32_t) (g * 255.0f + 0.5f) << 8
+ | (uint32_t) (b * 255.0f + 0.5f) << 0;
+}
+
+static float
+lin2srgb (float linear)
+{
+ if (linear < 0.0031308f)
+ return linear * 12.92f;
+ else
+ return 1.055f * powf (linear, 1.0f/2.4f) - 0.055f;
+}
+
+static uint32_t
+linear_argb_to_premult_srgb_argb (float a,
+ float r,
+ float g,
+ float b)
+{
+ r = lin2srgb (r * a);
+ g = lin2srgb (g * a);
+ b = lin2srgb (b * a);
+ return (uint32_t) (a * 255.0f + 0.5f) << 24
+ | (uint32_t) (r * 255.0f + 0.5f) << 16
+ | (uint32_t) (g * 255.0f + 0.5f) << 8
+ | (uint32_t) (b * 255.0f + 0.5f) << 0;
+}
+
+int
+main (int argc, char **argv)
+{
+#define WIDTH 400
+#define HEIGHT 200
+ int y, x, p;
+ float alpha;
+
+ uint32_t *dest = malloc (WIDTH * HEIGHT * 4);
+ uint32_t *src1 = malloc (WIDTH * HEIGHT * 4);
+ pixman_image_t *dest_img, *src1_img;
+
+ dest_img = pixman_image_create_bits (PIXMAN_a8r8g8b8_sRGB,
+ WIDTH, HEIGHT,
+ dest,
+ WIDTH * 4);
+ src1_img = pixman_image_create_bits (PIXMAN_a8r8g8b8,
+ WIDTH, HEIGHT,
+ src1,
+ WIDTH * 4);
+
+ for (y = 0; y < HEIGHT; y ++)
+ {
+ p = WIDTH * y;
+ for (x = 0; x < WIDTH; x ++)
+ {
+ alpha = (float) x / WIDTH;
+ src1[p + x] = linear_argb_to_premult_argb (alpha, 1, 0, 1);
+ dest[p + x] = linear_argb_to_premult_srgb_argb (1-alpha, 0, 1, 0);
+ }
+ }
+
+ pixman_image_composite (PIXMAN_OP_ADD, src1_img, NULL, dest_img,
+ 0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
+ pixman_image_unref (src1_img);
+ free (src1);
+
+ pixman_image_unref (dest_img);
+
+ /* Now that the picture has been correctly constructed,
+ * we hand it over to our support library as argb which it
+ * knows how to handle (it doesn't understand _sRGB format). */
+ dest_img = pixman_image_create_bits (PIXMAN_a8r8g8b8,
+ WIDTH, HEIGHT,
+ dest,
+ WIDTH * 4);
+ show_image (dest_img);
+ pixman_image_unref (dest_img);
+ free (dest);
+
+ return 0;
+}
diff --git a/pixman/pixman/Makefile.sources b/pixman/pixman/Makefile.sources
index 6472994c4..cf7040f33 100644
--- a/pixman/pixman/Makefile.sources
+++ b/pixman/pixman/Makefile.sources
@@ -25,6 +25,7 @@ libpixman_sources = \
pixman-region16.c \
pixman-region32.c \
pixman-solid-fill.c \
+ pixman-srgb.c \
pixman-timer.c \
pixman-trap.c \
pixman-utils.c \
@@ -46,8 +47,12 @@ BUILT_SOURCES = \
pixman-combine32.h \
pixman-combine64.c \
pixman-combine64.h \
+ pixman-srgb.c \
$(NULL)
+pixman-srgb.c: make-srgb.pl
+ $(PERL) $< > $@ || ($(RM) $@; exit 1)
+
pixman-combine32.c: pixman-combine.c.template make-combine.pl
$(PERL) $(lastword $+) 8 < $< > $@ || ($(RM) $@; exit 1)
pixman-combine32.h: pixman-combine.h.template make-combine.pl
diff --git a/pixman/pixman/make-srgb.pl b/pixman/pixman/make-srgb.pl
new file mode 100644
index 000000000..ebde2eac6
--- /dev/null
+++ b/pixman/pixman/make-srgb.pl
@@ -0,0 +1,112 @@
+#!/usr/bin/perl -w
+
+use strict;
+
+sub linear_to_srgb
+{
+ my ($c) = @_;
+
+ if ($c < 0.0031308)
+ {
+ return $c * 12.92;
+ }
+ else
+ {
+ return 1.055 * $c ** (1.0/2.4) - 0.055;
+ }
+}
+
+sub srgb_to_linear
+{
+ my ($c) = @_;
+
+ if ($c < 0.04045)
+ {
+ return $c / 12.92;
+ }
+ else
+ {
+ return (($c + 0.055) / 1.055) ** 2.4
+ }
+}
+
+my @linear_to_srgb;
+for my $linear (0 .. 4095)
+{
+ my $srgb = int(linear_to_srgb($linear / 4095.0) * 255.0 + 0.5);
+ push @linear_to_srgb, $srgb;
+}
+
+my @srgb_to_linear;
+for my $srgb (0 .. 255)
+{
+ my $linear = int(srgb_to_linear($srgb / 255.0) * 65535.0 + 0.5);
+ push @srgb_to_linear, $linear;
+}
+
+# Ensure that we have a lossless sRGB and back conversion loop.
+# some of the darkest shades need a little bias -- maximum is just
+# 5 increments out of 16. This gives us useful property with
+# least amount of error in the sRGB-to-linear table, and keeps the actual
+# table lookup in the other direction as simple as possible.
+for my $srgb (0 .. $#srgb_to_linear)
+{
+ my $add = 0;
+ while (1)
+ {
+ my $linear = $srgb_to_linear[$srgb];
+ my $srgb_lossy = $linear_to_srgb[$linear >> 4];
+ last if $srgb == $srgb_lossy;
+
+ # Add slight bias to this component until it rounds correctly
+ $srgb_to_linear[$srgb] ++;
+ $add ++;
+ }
+ die "Too many adds at $srgb" if $add > 5;
+}
+
+print <<"PROLOG";
+/* WARNING: This file is generated by $0.
+ * Please edit that file instead of this one.
+ */
+
+#include <stdint.h>
+
+#include "config.h"
+#include "pixman-private.h"
+
+PROLOG
+
+print "const uint8_t linear_to_srgb[" . @linear_to_srgb . "] =\n";
+print "{\n";
+for my $linear (0 .. $#linear_to_srgb)
+{
+ if (($linear % 10) == 0)
+ {
+ print "\t";
+ }
+ print sprintf("%d, ", $linear_to_srgb[$linear]);
+ if (($linear % 10) == 9)
+ {
+ print "\n";
+ }
+}
+print "\n};\n";
+print "\n";
+
+print "const uint16_t srgb_to_linear[" . @srgb_to_linear . "] =\n";
+print "{\n";
+for my $srgb (0 .. $#srgb_to_linear)
+{
+ if (($srgb % 10) == 0)
+ {
+ print "\t";
+ }
+ print sprintf("%d, ", $srgb_to_linear[$srgb]);
+ if (($srgb % 10) == 9)
+ {
+ print "\n";
+ }
+}
+print "\n};\n";
+
diff --git a/pixman/pixman/pixman-access.c b/pixman/pixman/pixman-access.c
index 6743887d0..9feafc49d 100644
--- a/pixman/pixman/pixman-access.c
+++ b/pixman/pixman/pixman-access.c
@@ -32,8 +32,8 @@
#include <string.h>
#include <assert.h>
-#include "pixman-private.h"
#include "pixman-accessor.h"
+#include "pixman-private.h"
#define CONVERT_RGB24_TO_Y15(s) \
(((((s) >> 16) & 0xff) * 153 + \
@@ -210,6 +210,7 @@ get_shifts (pixman_format_code_t format,
break;
case PIXMAN_TYPE_ARGB:
+ case PIXMAN_TYPE_ARGB_SRGB:
*b = 0;
*g = *b + PIXMAN_FORMAT_B (format);
*r = *g + PIXMAN_FORMAT_G (format);
@@ -1027,6 +1028,130 @@ fetch_pixel_generic_64 (bits_image_t *image,
return result;
}
+/* The 32_sRGB paths should be deleted after narrow processing
+ * is no longer invoked for formats that are considered wide.
+ * (Also see fetch_pixel_generic_lossy_32) */
+static void
+fetch_scanline_a8r8g8b8_32_sRGB (pixman_image_t *image,
+ int x,
+ int y,
+ int width,
+ uint32_t *buffer,
+ const uint32_t *mask)
+{
+ const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
+ const uint32_t *pixel = (uint32_t *)bits + x;
+ const uint32_t *end = pixel + width;
+ uint32_t tmp;
+
+ while (pixel < end)
+ {
+ tmp = READ (image, pixel++);
+ *buffer++ = (tmp >> 24) << 24
+ | (srgb_to_linear[(tmp >> 16) & 0xff] >> 8) << 16
+ | (srgb_to_linear[(tmp >> 8) & 0xff] >> 8) << 8
+ | (srgb_to_linear[(tmp >> 0) & 0xff] >> 8) << 0;
+ }
+}
+
+static void
+fetch_scanline_a8r8g8b8_64_sRGB (pixman_image_t *image,
+ int x,
+ int y,
+ int width,
+ uint32_t *b,
+ const uint32_t *mask)
+{
+ const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
+ const uint32_t *pixel = (uint32_t *)bits + x;
+ const uint32_t *end = pixel + width;
+ uint64_t *buffer = (uint64_t *)b;
+ uint32_t tmp;
+
+ while (pixel < end)
+ {
+ tmp = READ (image, pixel++);
+ *buffer++ = (uint64_t) ((tmp >> 24) * 257) << 48
+ | (uint64_t) srgb_to_linear[(tmp >> 16) & 0xff] << 32
+ | (uint64_t) srgb_to_linear[(tmp >> 8) & 0xff] << 16
+ | (uint64_t) srgb_to_linear[(tmp >> 0) & 0xff] << 0;
+ }
+}
+
+static uint32_t
+fetch_pixel_a8r8g8b8_32_sRGB (bits_image_t *image,
+ int offset,
+ int line)
+{
+ uint32_t *bits = image->bits + line * image->rowstride;
+ uint32_t tmp = READ (image, bits + offset);
+ return (tmp >> 24) << 24
+ | (srgb_to_linear[(tmp >> 16) & 0xff] >> 8) << 16
+ | (srgb_to_linear[(tmp >> 8) & 0xff] >> 8) << 8
+ | (srgb_to_linear[(tmp >> 0) & 0xff] >> 8) << 0;
+}
+
+static uint64_t
+fetch_pixel_a8r8g8b8_64_sRGB (bits_image_t *image,
+ int offset,
+ int line)
+{
+ uint32_t *bits = image->bits + line * image->rowstride;
+ uint32_t tmp = READ (image, bits + offset);
+ return (uint64_t) ((tmp >> 24) * 257) << 48
+ | (uint64_t) srgb_to_linear[(tmp >> 16) & 0xff] << 32
+ | (uint64_t) srgb_to_linear[(tmp >> 8) & 0xff] << 16
+ | (uint64_t) srgb_to_linear[(tmp >> 0) & 0xff] << 0;
+}
+
+static void
+store_scanline_a8r8g8b8_32_sRGB (bits_image_t *image,
+ int x,
+ int y,
+ int width,
+ const uint32_t *v)
+{
+ uint32_t *bits = image->bits + image->rowstride * y;
+ uint64_t *values = (uint64_t *)v;
+ uint32_t *pixel = bits + x;
+ uint64_t tmp;
+ int i;
+
+ for (i = 0; i < width; ++i)
+ {
+ tmp = values[i];
+ WRITE (image, pixel++,
+ ((uint32_t) (tmp >> 24 ) << 24)
+ | (linear_to_srgb[(tmp >> 16 << 4) & 0xfff] << 16)
+ | (linear_to_srgb[(tmp >> 8 << 4) & 0xfff] << 8)
+ | (linear_to_srgb[(tmp >> 0 << 4) & 0xfff] << 0));
+ }
+}
+
+static void
+store_scanline_a8r8g8b8_64_sRGB (bits_image_t *image,
+ int x,
+ int y,
+ int width,
+ const uint32_t *v)
+{
+ uint32_t *bits = image->bits + image->rowstride * y;
+ uint64_t *values = (uint64_t *)v;
+ uint32_t *pixel = bits + x;
+ uint64_t tmp;
+ int i;
+
+ for (i = 0; i < width; ++i)
+ {
+ tmp = values[i];
+ WRITE (image, pixel++,
+ ((uint32_t) (tmp >> 56) << 24)
+ | (linear_to_srgb[(tmp >> 36) & 0xfff] << 16)
+ | (linear_to_srgb[(tmp >> 20) & 0xfff] << 8)
+ | (linear_to_srgb[(tmp >> 4) & 0xfff] << 0));
+ }
+}
+
/*
* XXX: The transformed fetch path only works at 32-bpp so far. When all
* paths have wide versions, this can be removed.
@@ -1079,6 +1204,13 @@ static const format_info_t accessors[] =
FORMAT_INFO (r8g8b8x8),
FORMAT_INFO (x14r6g6b6),
+/* sRGB formats */
+ { PIXMAN_a8r8g8b8_sRGB,
+ fetch_scanline_a8r8g8b8_32_sRGB,
+ fetch_scanline_a8r8g8b8_64_sRGB,
+ fetch_pixel_a8r8g8b8_32_sRGB, fetch_pixel_a8r8g8b8_64_sRGB,
+ store_scanline_a8r8g8b8_32_sRGB, store_scanline_a8r8g8b8_64_sRGB },
+
/* 24bpp formats */
FORMAT_INFO (r8g8b8),
FORMAT_INFO (b8g8r8),
diff --git a/pixman/pixman/pixman-image.c b/pixman/pixman/pixman-image.c
index 8b634a7dc..15597bd61 100644
--- a/pixman/pixman/pixman-image.c
+++ b/pixman/pixman/pixman-image.c
@@ -909,7 +909,8 @@ _pixman_image_get_solid (pixman_implementation_t *imp,
}
/* If necessary, convert RGB <--> BGR. */
- if (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB)
+ if (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB
+ && PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB_SRGB)
{
result = (((result & 0xff000000) >> 0) |
((result & 0x00ff0000) >> 16) |
diff --git a/pixman/pixman/pixman-private.h b/pixman/pixman/pixman-private.h
index 4d8f64d3b..d5e6a72ee 100644
--- a/pixman/pixman/pixman-private.h
+++ b/pixman/pixman/pixman-private.h
@@ -887,7 +887,8 @@ pixman_list_move_to_front (pixman_list_t *list, pixman_link_t *link)
(PIXMAN_FORMAT_A (f) > 8 || \
PIXMAN_FORMAT_R (f) > 8 || \
PIXMAN_FORMAT_G (f) > 8 || \
- PIXMAN_FORMAT_B (f) > 8)
+ PIXMAN_FORMAT_B (f) > 8 || \
+ PIXMAN_FORMAT_TYPE (f) == PIXMAN_TYPE_ARGB_SRGB)
#ifdef WORDS_BIGENDIAN
# define SCREEN_SHIFT_LEFT(x,n) ((x) << (n))
@@ -1083,6 +1084,18 @@ void pixman_timer_register (pixman_timer_t *timer);
#endif /* PIXMAN_TIMERS */
+/* sRGB<->linear conversion tables. Linear color space is the same
+ * as sRGB but the components are in linear light (gamma 1.0).
+ *
+ * linear_to_srgb maps linear value from 0 to 4095 ([0.0, 1.0])
+ * and returns 8-bit sRGB value.
+ *
+ * srgb_to_linear maps 8-bit sRGB value to 16-bit linear value
+ * with range 0 to 65535 ([0.0, 1.0]).
+ */
+extern const uint8_t linear_to_srgb[4096];
+extern const uint16_t srgb_to_linear[256];
+
#endif /* __ASSEMBLER__ */
#endif /* PIXMAN_PRIVATE_H */
diff --git a/pixman/pixman/pixman.c b/pixman/pixman/pixman.c
index 0137c3cab..994ef388c 100644
--- a/pixman/pixman/pixman.c
+++ b/pixman/pixman/pixman.c
@@ -1017,6 +1017,7 @@ pixman_format_supported_source (pixman_format_code_t format)
case PIXMAN_a2r10g10b10:
case PIXMAN_x2r10g10b10:
case PIXMAN_a8r8g8b8:
+ case PIXMAN_a8r8g8b8_sRGB:
case PIXMAN_x8r8g8b8:
case PIXMAN_a8b8g8r8:
case PIXMAN_x8b8g8r8:
diff --git a/pixman/pixman/pixman.h b/pixman/pixman/pixman.h
index 7233ceb8a..e1cb90a7d 100644
--- a/pixman/pixman/pixman.h
+++ b/pixman/pixman/pixman.h
@@ -653,6 +653,7 @@ struct pixman_indexed
#define PIXMAN_TYPE_YV12 7
#define PIXMAN_TYPE_BGRA 8
#define PIXMAN_TYPE_RGBA 9
+#define PIXMAN_TYPE_ARGB_SRGB 10
#define PIXMAN_FORMAT_COLOR(f) \
(PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_ARGB || \
@@ -676,6 +677,9 @@ typedef enum {
PIXMAN_x2b10g10r10 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,0,10,10,10),
PIXMAN_a2b10g10r10 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,2,10,10,10),
+/* sRGB formats */
+ PIXMAN_a8r8g8b8_sRGB = PIXMAN_FORMAT(32,PIXMAN_TYPE_ARGB_SRGB,8,8,8,8),
+
/* 24bpp formats */
PIXMAN_r8g8b8 = PIXMAN_FORMAT(24,PIXMAN_TYPE_ARGB,0,8,8,8),
PIXMAN_b8g8r8 = PIXMAN_FORMAT(24,PIXMAN_TYPE_ABGR,0,8,8,8),
diff --git a/pixman/test/composite.c b/pixman/test/composite.c
index bdecd75a7..2930fb75b 100644
--- a/pixman/test/composite.c
+++ b/pixman/test/composite.c
@@ -99,6 +99,9 @@ static const format_t formats[] =
P(x2b10g10r10),
P(a2r10g10b10),
P(a2b10g10r10),
+
+ /* sRGB formats */
+ P(a8r8g8b8_sRGB),
/* 24 bpp formats */
P(r8g8b8),
@@ -524,17 +527,8 @@ composite_test (image_t *dst,
pixman_bool_t component_alpha,
int testno)
{
- pixman_color_t fill;
color_t expected, tdst, tsrc, tmsk;
pixel_checker_t checker;
- pixman_image_t *solid;
-
- /* Initialize dst */
- compute_pixman_color (dst->color, &fill);
- solid = pixman_image_create_solid_fill (&fill);
- pixman_image_composite32 (PIXMAN_OP_SRC, solid, NULL, dst->image,
- 0, 0, 0, 0, 0, 0, dst->size, dst->size);
- pixman_image_unref (solid);
if (mask)
{
@@ -553,17 +547,56 @@ composite_test (image_t *dst,
}
tdst = *dst->color;
- round_color (dst->format->format, &tdst);
-
tsrc = *src->color;
- if (src->size)
- round_color (src->format->format, &tsrc);
if (mask)
{
tmsk = *mask->color;
- if (mask->size)
+ }
+
+ /* It turns out that by construction all source, mask etc. colors are
+ * linear because they are made from fills, and fills are always in linear
+ * color space. However, if they have been converted to bitmaps, we need
+ * to simulate the sRGB approximation to pass the test cases.
+ */
+ if (src->size)
+ {
+ if (PIXMAN_FORMAT_TYPE (src->format->format) == PIXMAN_TYPE_ARGB_SRGB)
+ {
+ tsrc.r = convert_linear_to_srgb (tsrc.r);
+ tsrc.g = convert_linear_to_srgb (tsrc.g);
+ tsrc.b = convert_linear_to_srgb (tsrc.b);
+ round_color (src->format->format, &tsrc);
+ tsrc.r = convert_srgb_to_linear (tsrc.r);
+ tsrc.g = convert_srgb_to_linear (tsrc.g);
+ tsrc.b = convert_srgb_to_linear (tsrc.b);
+ }
+ else
+ {
+ round_color (src->format->format, &tsrc);
+ }
+ }
+
+ if (mask && mask->size)
+ {
+ if (PIXMAN_FORMAT_TYPE (mask->format->format) == PIXMAN_TYPE_ARGB_SRGB)
+ {
+ tmsk.r = convert_linear_to_srgb (tmsk.r);
+ tmsk.g = convert_linear_to_srgb (tmsk.g);
+ tmsk.b = convert_linear_to_srgb (tmsk.b);
round_color (mask->format->format, &tmsk);
+ tmsk.r = convert_srgb_to_linear (tmsk.r);
+ tmsk.g = convert_srgb_to_linear (tmsk.g);
+ tmsk.b = convert_srgb_to_linear (tmsk.b);
+ }
+ else
+ {
+ round_color (mask->format->format, &tmsk);
+ }
+ }
+
+ if (mask)
+ {
if (component_alpha && PIXMAN_FORMAT_R (mask->format->format) == 0)
{
/* Ax component-alpha masks expand alpha into
@@ -573,6 +606,21 @@ composite_test (image_t *dst,
}
}
+ if (PIXMAN_FORMAT_TYPE (dst->format->format) == PIXMAN_TYPE_ARGB_SRGB)
+ {
+ tdst.r = convert_linear_to_srgb (tdst.r);
+ tdst.g = convert_linear_to_srgb (tdst.g);
+ tdst.b = convert_linear_to_srgb (tdst.b);
+ round_color (dst->format->format, &tdst);
+ tdst.r = convert_srgb_to_linear (tdst.r);
+ tdst.g = convert_srgb_to_linear (tdst.g);
+ tdst.b = convert_srgb_to_linear (tdst.b);
+ }
+ else
+ {
+ round_color (dst->format->format, &tdst);
+ }
+
do_composite (op->op,
&tsrc,
mask? &tmsk : NULL,
diff --git a/pixman/test/stress-test.c b/pixman/test/stress-test.c
index 9280802bd..54ab1c5a9 100644
--- a/pixman/test/stress-test.c
+++ b/pixman/test/stress-test.c
@@ -25,6 +25,7 @@ static const pixman_format_code_t image_formats[] =
PIXMAN_x14r6g6b6,
PIXMAN_r8g8b8,
PIXMAN_b8g8r8,
+ PIXMAN_a8r8g8b8_sRGB,
PIXMAN_r5g6b5,
PIXMAN_b5g6r5,
PIXMAN_x2r10g10b10,
diff --git a/pixman/test/utils.c b/pixman/test/utils.c
index 563b33d52..85b58d038 100644
--- a/pixman/test/utils.c
+++ b/pixman/test/utils.c
@@ -1,6 +1,7 @@
#define _GNU_SOURCE
#include "utils.h"
+#include <math.h>
#include <signal.h>
#include <stdlib.h>
@@ -765,6 +766,24 @@ aligned_malloc (size_t align, size_t size)
(((c) >> 8) & 0xff) * 301 + \
(((c) ) & 0xff) * 58) >> 2))
+double
+convert_srgb_to_linear (double c)
+{
+ if (c <= 0.04045)
+ return c / 12.92;
+ else
+ return powf ((c + 0.055) / 1.055, 2.4);
+}
+
+double
+convert_linear_to_srgb (double c)
+{
+ if (c <= 0.0031308)
+ return c * 12.92;
+ else
+ return 1.055 * powf (c, 1.0/2.4) - 0.055;
+}
+
void
initialize_palette (pixman_indexed_t *palette, uint32_t depth, int is_rgb)
{
@@ -868,6 +887,7 @@ pixel_checker_init (pixel_checker_t *checker, pixman_format_code_t format)
break;
case PIXMAN_TYPE_ARGB:
+ case PIXMAN_TYPE_ARGB_SRGB:
checker->bs = 0;
checker->gs = checker->bs + PIXMAN_FORMAT_B (format);
checker->rs = checker->gs + PIXMAN_FORMAT_G (format);
@@ -968,11 +988,25 @@ pixel_checker_get_min (const pixel_checker_t *checker, color_t *color,
pixman_bool_t
pixel_checker_check (const pixel_checker_t *checker, uint32_t pixel,
- color_t *color)
+ color_t *color_in)
{
int32_t a_lo, a_hi, r_lo, r_hi, g_lo, g_hi, b_lo, b_hi;
int32_t ai, ri, gi, bi;
pixman_bool_t result;
+ color_t tmp, *color;
+
+ if (PIXMAN_FORMAT_TYPE (checker->format) == PIXMAN_TYPE_ARGB_SRGB)
+ {
+ tmp.a = color_in->a;
+ tmp.r = convert_linear_to_srgb (color_in->r);
+ tmp.g = convert_linear_to_srgb (color_in->g);
+ tmp.b = convert_linear_to_srgb (color_in->b);
+ color = &tmp;
+ }
+ else
+ {
+ color = color_in;
+ }
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);
diff --git a/pixman/test/utils.h b/pixman/test/utils.h
index ac2decd11..faf427f0a 100644
--- a/pixman/test/utils.h
+++ b/pixman/test/utils.h
@@ -163,6 +163,12 @@ write_png (pixman_image_t *image, const char *filename);
void *
aligned_malloc (size_t align, size_t size);
+double
+convert_srgb_to_linear (double component);
+
+double
+convert_linear_to_srgb (double component);
+
void
initialize_palette (pixman_indexed_t *palette, uint32_t depth, int is_rgb);