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
pixman-region16.c \
pixman-region32.c \
pixman-solid-fill.c \
+ pixman-srgb.c \
pixman-timer.c \
pixman-trap.c \
pixman-utils.c \
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
--- /dev/null
+#!/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";
+
#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 + \
break;
case PIXMAN_TYPE_ARGB:
+ case PIXMAN_TYPE_ARGB_SRGB:
*b = 0;
*g = *b + PIXMAN_FORMAT_B (format);
*r = *g + PIXMAN_FORMAT_G (format);
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.
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),
}
/* 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) |
(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))
#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 */
case PIXMAN_a2r10g10b10:
case PIXMAN_x2r10g10b10:
case PIXMAN_a8r8g8b8:
+ case PIXMAN_a8r8g8b8_sRGB:
case PIXMAN_x8r8g8b8:
case PIXMAN_a8b8g8r8:
case PIXMAN_x8b8g8r8:
#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 || \
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),