summaryrefslogtreecommitdiff
path: root/Build/source/libs/pixman/pixman-src/pixman/pixman-bits-image.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/pixman/pixman-src/pixman/pixman-bits-image.c')
-rw-r--r--Build/source/libs/pixman/pixman-src/pixman/pixman-bits-image.c177
1 files changed, 161 insertions, 16 deletions
diff --git a/Build/source/libs/pixman/pixman-src/pixman/pixman-bits-image.c b/Build/source/libs/pixman/pixman-src/pixman/pixman-bits-image.c
index 564789e9c68..4cfabe318ae 100644
--- a/Build/source/libs/pixman/pixman-src/pixman/pixman-bits-image.c
+++ b/Build/source/libs/pixman/pixman-src/pixman/pixman-bits-image.c
@@ -35,6 +35,7 @@
#include "pixman-private.h"
#include "pixman-combine32.h"
#include "pixman-inlines.h"
+#include "dither/blue-noise-64x64.h"
/* Fetch functions */
@@ -190,8 +191,8 @@ bits_image_fetch_pixel_bilinear_float (bits_image_t *image,
*ret = bilinear_interpolation_float (tl, tr, bl, br, distx, disty);
}
-static force_inline void accum_32(int *satot, int *srtot,
- int *sgtot, int *sbtot,
+static force_inline void accum_32(unsigned int *satot, unsigned int *srtot,
+ unsigned int *sgtot, unsigned int *sbtot,
const void *p, pixman_fixed_t f)
{
uint32_t pixel = *(uint32_t *)p;
@@ -202,8 +203,9 @@ static force_inline void accum_32(int *satot, int *srtot,
*satot += (int)ALPHA_8 (pixel) * f;
}
-static force_inline void reduce_32(int satot, int srtot,
- int sgtot, int sbtot, void *p)
+static force_inline void reduce_32(unsigned int satot, unsigned int srtot,
+ unsigned int sgtot, unsigned int sbtot,
+ void *p)
{
uint32_t *ret = p;
@@ -220,8 +222,8 @@ static force_inline void reduce_32(int satot, int srtot,
*ret = ((satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot));
}
-static force_inline void accum_float(int *satot, int *srtot,
- int *sgtot, int *sbtot,
+static force_inline void accum_float(unsigned int *satot, unsigned int *srtot,
+ unsigned int *sgtot, unsigned int *sbtot,
const void *p, pixman_fixed_t f)
{
const argb_t *pixel = p;
@@ -232,8 +234,8 @@ static force_inline void accum_float(int *satot, int *srtot,
*sbtot += pixel->b * f;
}
-static force_inline void reduce_float(int satot, int srtot,
- int sgtot, int sbtot,
+static force_inline void reduce_float(unsigned int satot, unsigned int srtot,
+ unsigned int sgtot, unsigned int sbtot,
void *p)
{
argb_t *ret = p;
@@ -244,12 +246,13 @@ static force_inline void reduce_float(int satot, int srtot,
ret->b = CLIP (sbtot / 65536.f, 0.f, 1.f);
}
-typedef void (* accumulate_pixel_t) (int *satot, int *srtot,
- int *sgtot, int *sbtot,
+typedef void (* accumulate_pixel_t) (unsigned int *satot, unsigned int *srtot,
+ unsigned int *sgtot, unsigned int *sbtot,
const void *pixel, pixman_fixed_t f);
-typedef void (* reduce_pixel_t) (int satot, int srtot,
- int sgtot, int sbtot, void *out);
+typedef void (* reduce_pixel_t) (unsigned int satot, unsigned int srtot,
+ unsigned int sgtot, unsigned int sbtot,
+ void *out);
static force_inline void
bits_image_fetch_pixel_convolution (bits_image_t *image,
@@ -269,7 +272,7 @@ bits_image_fetch_pixel_convolution (bits_image_t *image,
pixman_repeat_t repeat_mode = image->common.repeat;
int width = image->width;
int height = image->height;
- int srtot, sgtot, sbtot, satot;
+ unsigned int srtot, sgtot, sbtot, satot;
params += 2;
@@ -338,7 +341,7 @@ bits_image_fetch_pixel_separable_convolution (bits_image_t *image,
int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1;
int y_off = ((cheight << 16) - pixman_fixed_1) >> 1;
pixman_fixed_t *y_params;
- int srtot, sgtot, sbtot, satot;
+ unsigned int srtot, sgtot, sbtot, satot;
int32_t x1, x2, y1, y2;
int32_t px, py;
int i, j;
@@ -432,29 +435,38 @@ bits_image_fetch_pixel_filtered (bits_image_t *image,
case PIXMAN_FILTER_CONVOLUTION:
if (wide)
+ {
bits_image_fetch_pixel_convolution (image, x, y,
get_pixel, out,
accum_float,
reduce_float);
+ }
else
+ {
bits_image_fetch_pixel_convolution (image, x, y,
get_pixel, out,
accum_32, reduce_32);
+ }
break;
case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
if (wide)
+ {
bits_image_fetch_pixel_separable_convolution (image, x, y,
get_pixel, out,
accum_float,
reduce_float);
+ }
else
+ {
bits_image_fetch_pixel_separable_convolution (image, x, y,
get_pixel, out,
accum_32, reduce_32);
+ }
break;
default:
+ assert (0);
break;
}
}
@@ -662,8 +674,8 @@ __bits_image_fetch_general (pixman_iter_t *iter,
{
if (w != 0)
{
- x0 = ((pixman_fixed_48_16_t)x << 16) / w;
- y0 = ((pixman_fixed_48_16_t)y << 16) / w;
+ x0 = ((uint64_t)x << 16) / w;
+ y0 = ((uint64_t)y << 16) / w;
}
else
{
@@ -1039,6 +1051,119 @@ dest_write_back_narrow (pixman_iter_t *iter)
iter->y++;
}
+static const float
+dither_factor_blue_noise_64 (int x, int y)
+{
+ float m = dither_blue_noise_64x64[((y & 0x3f) << 6) | (x & 0x3f)];
+ return m * (1. / 4096.f) + (1. / 8192.f);
+}
+
+static const float
+dither_factor_bayer_8 (int x, int y)
+{
+ uint32_t m;
+
+ y ^= x;
+
+ /* Compute reverse(interleave(xor(x mod n, y mod n), x mod n))
+ * Here n = 8 and `mod n` is the bottom 3 bits.
+ */
+ m = ((y & 0x1) << 5) | ((x & 0x1) << 4) |
+ ((y & 0x2) << 2) | ((x & 0x2) << 1) |
+ ((y & 0x4) >> 1) | ((x & 0x4) >> 2);
+
+ /* m is in range [0, 63]. We scale it to [0, 63.0f/64.0f], then
+ * shift it to to [1.0f/128.0f, 127.0f/128.0f] so that 0 < d < 1.
+ * This ensures exact values are not changed by dithering.
+ */
+ return (float)(m) * (1 / 64.0f) + (1.0f / 128.0f);
+}
+
+typedef float (* dither_factor_t)(int x, int y);
+
+static force_inline float
+dither_apply_channel (float f, float d, float s)
+{
+ /* float_to_unorm splits the [0, 1] segment in (1 << n_bits)
+ * subsections of equal length; however unorm_to_float does not
+ * map to the center of those sections. In fact, pixel value u is
+ * mapped to:
+ *
+ * u u u 1
+ * -------------- = ---------- + -------------- * ----------
+ * 2^n_bits - 1 2^n_bits 2^n_bits - 1 2^n_bits
+ *
+ * Hence if f = u / (2^n_bits - 1) is exactly representable on a
+ * n_bits palette, all the numbers between
+ *
+ * u
+ * ---------- = f - f * 2^n_bits = f + (0 - f) * 2^n_bits
+ * 2^n_bits
+ *
+ * and
+ *
+ * u + 1
+ * ---------- = f - (f - 1) * 2^n_bits = f + (1 - f) * 2^n_bits
+ * 2^n_bits
+ *
+ * are also mapped back to u.
+ *
+ * Hence the following calculation ensures that we add as much
+ * noise as possible without perturbing values which are exactly
+ * representable in the target colorspace. Note that this corresponds to
+ * mixing the original color with noise with a ratio of `1 / 2^n_bits`.
+ */
+ return f + (d - f) * s;
+}
+
+static force_inline float
+dither_compute_scale (int n_bits)
+{
+ // No dithering for wide formats
+ if (n_bits == 0 || n_bits >= 32)
+ return 0.f;
+
+ return 1.f / (float)(1 << n_bits);
+}
+
+static const uint32_t *
+dither_apply_ordered (pixman_iter_t *iter, dither_factor_t factor)
+{
+ bits_image_t *image = &iter->image->bits;
+ int x = iter->x + image->dither_offset_x;
+ int y = iter->y + image->dither_offset_y;
+ int width = iter->width;
+ argb_t *buffer = (argb_t *)iter->buffer;
+
+ pixman_format_code_t format = image->format;
+ int a_size = PIXMAN_FORMAT_A (format);
+ int r_size = PIXMAN_FORMAT_R (format);
+ int g_size = PIXMAN_FORMAT_G (format);
+ int b_size = PIXMAN_FORMAT_B (format);
+
+ float a_scale = dither_compute_scale (a_size);
+ float r_scale = dither_compute_scale (r_size);
+ float g_scale = dither_compute_scale (g_size);
+ float b_scale = dither_compute_scale (b_size);
+
+ int i;
+ float d;
+
+ for (i = 0; i < width; ++i)
+ {
+ d = factor (x + i, y);
+
+ buffer->a = dither_apply_channel (buffer->a, d, a_scale);
+ buffer->r = dither_apply_channel (buffer->r, d, r_scale);
+ buffer->g = dither_apply_channel (buffer->g, d, g_scale);
+ buffer->b = dither_apply_channel (buffer->b, d, b_scale);
+
+ buffer++;
+ }
+
+ return iter->buffer;
+}
+
static void
dest_write_back_wide (pixman_iter_t *iter)
{
@@ -1048,6 +1173,23 @@ dest_write_back_wide (pixman_iter_t *iter)
int width = iter->width;
const uint32_t *buffer = iter->buffer;
+ switch (image->dither)
+ {
+ case PIXMAN_DITHER_NONE:
+ break;
+
+ case PIXMAN_DITHER_GOOD:
+ case PIXMAN_DITHER_BEST:
+ case PIXMAN_DITHER_ORDERED_BLUE_NOISE_64:
+ buffer = dither_apply_ordered (iter, dither_factor_blue_noise_64);
+ break;
+
+ case PIXMAN_DITHER_FAST:
+ case PIXMAN_DITHER_ORDERED_BAYER_8:
+ buffer = dither_apply_ordered (iter, dither_factor_bayer_8);
+ break;
+ }
+
image->store_scanline_float (image, x, y, width, buffer);
if (image->common.alpha_map)
@@ -1163,6 +1305,9 @@ _pixman_bits_image_init (pixman_image_t * image,
image->bits.height = height;
image->bits.bits = bits;
image->bits.free_me = free_me;
+ image->bits.dither = PIXMAN_DITHER_NONE;
+ image->bits.dither_offset_x = 0;
+ image->bits.dither_offset_y = 0;
image->bits.read_func = NULL;
image->bits.write_func = NULL;
image->bits.rowstride = rowstride;