aboutsummaryrefslogtreecommitdiff
path: root/pixman
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2012-12-10 08:55:36 +0100
committermarha <marha@users.sourceforge.net>2012-12-10 08:55:36 +0100
commita0124a5e8e70979d2c24ef55285da989fdad766a (patch)
tree5cea5c9804a8edf67bc7260e0851a20d21324547 /pixman
parent514b4afb64ccbf8e954270105ed5064272a2be68 (diff)
parent0328076efb5ff6e62152c09e38d0d11f7931d07b (diff)
downloadvcxsrv-a0124a5e8e70979d2c24ef55285da989fdad766a.tar.gz
vcxsrv-a0124a5e8e70979d2c24ef55285da989fdad766a.tar.bz2
vcxsrv-a0124a5e8e70979d2c24ef55285da989fdad766a.zip
Merge remote-tracking branch 'origin/released'
* origin/released: fontconfig libX11 mesa pixman git update 10 dec 2012 Conflicts: fontconfig/src/fcxml.c
Diffstat (limited to 'pixman')
-rw-r--r--pixman/configure.ac2
-rw-r--r--pixman/demos/Makefile.am11
-rw-r--r--pixman/demos/conical-test.c134
-rw-r--r--pixman/demos/gtk-utils.c66
-rw-r--r--pixman/demos/gtk-utils.h3
-rw-r--r--pixman/demos/scale.c431
-rw-r--r--pixman/demos/scale.ui302
-rw-r--r--pixman/demos/zone_plate.pngbin0 -> 228732 bytes
-rw-r--r--pixman/pixman/Makefile.sources1
-rw-r--r--pixman/pixman/pixman-bits-image.c285
-rw-r--r--pixman/pixman/pixman-filter.c340
-rw-r--r--pixman/pixman/pixman-image.c22
-rw-r--r--pixman/pixman/pixman-private.h1
-rw-r--r--pixman/pixman/pixman.c8
-rw-r--r--pixman/pixman/pixman.h50
-rw-r--r--pixman/pixman/rounding.txt33
-rw-r--r--pixman/test/Makefile.sources3
-rw-r--r--pixman/test/affine-test.c111
-rw-r--r--pixman/test/alpha-loop.c11
-rw-r--r--pixman/test/alphamap.c2
-rw-r--r--pixman/test/blitters-test.c60
-rw-r--r--pixman/test/combiner-test.c4
-rw-r--r--pixman/test/composite-traps-test.c58
-rw-r--r--pixman/test/composite.c12
-rw-r--r--pixman/test/glyph-test.c94
-rw-r--r--pixman/test/prng-test.c172
-rw-r--r--pixman/test/region-contains-test.c28
-rw-r--r--pixman/test/region-test.c10
-rw-r--r--pixman/test/rotate-test.c14
-rw-r--r--pixman/test/scaling-helpers-test.c9
-rw-r--r--pixman/test/scaling-test.c129
-rw-r--r--pixman/test/stress-test.c112
-rw-r--r--pixman/test/utils-prng.c238
-rw-r--r--pixman/test/utils-prng.h168
-rw-r--r--pixman/test/utils.c25
-rw-r--r--pixman/test/utils.h58
36 files changed, 2618 insertions, 389 deletions
diff --git a/pixman/configure.ac b/pixman/configure.ac
index 45b709dcf..81f068d9c 100644
--- a/pixman/configure.ac
+++ b/pixman/configure.ac
@@ -860,7 +860,7 @@ AC_CACHE_VAL(ac_cv_tls, [
#error OpenBSD has broken __thread support
#endif
-int $kw test;], [], ac_cv_tls=$kw)
+int $kw test;], [], [ac_cv_tls=$kw; break])
done
])
AC_MSG_RESULT($ac_cv_tls)
diff --git a/pixman/demos/Makefile.am b/pixman/demos/Makefile.am
index f324f5f5b..3f2a3fad6 100644
--- a/pixman/demos/Makefile.am
+++ b/pixman/demos/Makefile.am
@@ -6,7 +6,8 @@ AM_LDFLAGS = $(OPENMP_CFLAGS)
LDADD = $(top_builddir)/pixman/libpixman-1.la -lm $(GTK_LIBS) $(PNG_LIBS)
INCLUDES = -I$(top_srcdir)/pixman -I$(top_builddir)/pixman $(GTK_CFLAGS) $(PNG_CFLAGS)
-GTK_UTILS = gtk-utils.c gtk-utils.h ../test/utils.c ../test/utils.h
+GTK_UTILS = gtk-utils.c gtk-utils.h ../test/utils.c ../test/utils.h \
+ ../test/utils-prng.c ../test/utils-prng.h
DEMOS = \
clip-test \
@@ -14,6 +15,7 @@ DEMOS = \
composite-test \
gradient-test \
radial-test \
+ conical-test \
alpha-test \
screen-test \
convolution-test \
@@ -22,9 +24,10 @@ DEMOS = \
quad2quad \
checkerboard \
srgb-trap-test \
- srgb-test
+ srgb-test \
+ scale
-EXTRA_DIST = parrot.c parrot.jpg
+EXTRA_DIST = parrot.c parrot.jpg scale.ui
gradient_test_SOURCES = gradient-test.c $(GTK_UTILS)
alpha_test_SOURCES = alpha-test.c $(GTK_UTILS)
@@ -35,10 +38,12 @@ trap_test_SOURCES = trap-test.c $(GTK_UTILS)
screen_test_SOURCES = screen-test.c $(GTK_UTILS)
convolution_test_SOURCES = convolution-test.c $(GTK_UTILS)
radial_test_SOURCES = radial-test.c $(GTK_UTILS)
+conical_test_SOURCES = conical-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)
srgb_trap_test_SOURCES = srgb-trap-test.c $(GTK_UTILS)
+scale_SOURCES = scale.c $(GTK_UTILS)
noinst_PROGRAMS = $(DEMOS)
diff --git a/pixman/demos/conical-test.c b/pixman/demos/conical-test.c
new file mode 100644
index 000000000..1e08e42f7
--- /dev/null
+++ b/pixman/demos/conical-test.c
@@ -0,0 +1,134 @@
+#include "../test/utils.h"
+#include "gtk-utils.h"
+
+#define SIZE 128
+#define GRADIENTS_PER_ROW 7
+#define NUM_ROWS ((NUM_GRADIENTS + GRADIENTS_PER_ROW - 1) / GRADIENTS_PER_ROW)
+#define WIDTH (SIZE * GRADIENTS_PER_ROW)
+#define HEIGHT (SIZE * NUM_ROWS)
+#define NUM_GRADIENTS 35
+
+#define double_to_color(x) \
+ (((uint32_t) ((x)*65536)) - (((uint32_t) ((x)*65536)) >> 16))
+
+#define PIXMAN_STOP(offset,r,g,b,a) \
+ { pixman_double_to_fixed (offset), \
+ { \
+ double_to_color (r), \
+ double_to_color (g), \
+ double_to_color (b), \
+ double_to_color (a) \
+ } \
+ }
+
+
+static const pixman_gradient_stop_t stops[] = {
+ PIXMAN_STOP (0.25, 1, 0, 0, 0.7),
+ PIXMAN_STOP (0.5, 1, 1, 0, 0.7),
+ PIXMAN_STOP (0.75, 0, 1, 0, 0.7),
+ PIXMAN_STOP (1.0, 0, 0, 1, 0.7)
+};
+
+#define NUM_STOPS (sizeof (stops) / sizeof (stops[0]))
+
+static pixman_image_t *
+create_conical (int index)
+{
+ pixman_point_fixed_t c;
+ double angle;
+
+ c.x = pixman_double_to_fixed (0);
+ c.y = pixman_double_to_fixed (0);
+
+ angle = (0.5 / NUM_GRADIENTS + index / (double)NUM_GRADIENTS) * 720 - 180;
+
+ return pixman_image_create_conical_gradient (
+ &c, pixman_double_to_fixed (angle), stops, NUM_STOPS);
+}
+
+#define CHECK_SIZE 25
+
+static void
+fill_checkerboard (pixman_image_t *image, int width, int height)
+{
+#define C1 0xaaaa
+#define C2 0x8888
+
+ pixman_color_t check1 = { C1, C1, C1, 0xffff };
+ pixman_color_t check2 = { C2, C2, C2, 0xffff };
+ pixman_image_t *c1, *c2;
+ int i, j;
+
+ c1 = pixman_image_create_solid_fill (&check1);
+ c2 = pixman_image_create_solid_fill (&check2);
+
+ for (j = 0; j < height; j += CHECK_SIZE)
+ {
+ for (i = 0; i < width; i += CHECK_SIZE)
+ {
+ pixman_image_t *src;
+
+ if ((((i / CHECK_SIZE) ^ (j / CHECK_SIZE)) & 1) == 0)
+ src = c1;
+ else
+ src = c2;
+
+ pixman_image_composite32 (PIXMAN_OP_SRC, src, NULL, image,
+ 0, 0, 0, 0, i, j,
+ CHECK_SIZE, CHECK_SIZE);
+ }
+ }
+}
+
+int
+main (int argc, char **argv)
+{
+ pixman_transform_t transform;
+ pixman_image_t *src_img, *dest_img;
+ int i;
+
+ enable_divbyzero_exceptions ();
+
+ dest_img = pixman_image_create_bits (PIXMAN_a8r8g8b8,
+ WIDTH, HEIGHT,
+ NULL, 0);
+
+ fill_checkerboard (dest_img, WIDTH, HEIGHT);
+
+ pixman_transform_init_identity (&transform);
+
+ pixman_transform_translate (NULL, &transform,
+ pixman_double_to_fixed (0.5),
+ pixman_double_to_fixed (0.5));
+
+ pixman_transform_scale (NULL, &transform,
+ pixman_double_to_fixed (SIZE),
+ pixman_double_to_fixed (SIZE));
+ pixman_transform_translate (NULL, &transform,
+ pixman_double_to_fixed (0.5),
+ pixman_double_to_fixed (0.5));
+
+ for (i = 0; i < NUM_GRADIENTS; i++)
+ {
+ int column = i % GRADIENTS_PER_ROW;
+ int row = i / GRADIENTS_PER_ROW;
+
+ src_img = create_conical (i);
+ pixman_image_set_repeat (src_img, PIXMAN_REPEAT_NORMAL);
+
+ pixman_image_set_transform (src_img, &transform);
+
+ pixman_image_composite32 (
+ PIXMAN_OP_OVER, src_img, NULL,dest_img,
+ 0, 0, 0, 0, column * SIZE, row * SIZE,
+ SIZE, SIZE);
+
+ pixman_image_unref (src_img);
+ }
+
+ show_image (dest_img);
+
+ pixman_image_unref (dest_img);
+
+ return 0;
+}
diff --git a/pixman/demos/gtk-utils.c b/pixman/demos/gtk-utils.c
index 8291a1ed2..d7e946ded 100644
--- a/pixman/demos/gtk-utils.c
+++ b/pixman/demos/gtk-utils.c
@@ -3,6 +3,72 @@
#include "../test/utils.h"
#include "gtk-utils.h"
+pixman_image_t *
+pixman_image_from_file (const char *filename, pixman_format_code_t format)
+{
+ GdkPixbuf *pixbuf;
+ pixman_image_t *image;
+ int width, height;
+ uint32_t *data, *d;
+ uint8_t *gdk_data;
+ int n_channels;
+ int j, i;
+ int stride;
+
+ if (!(pixbuf = gdk_pixbuf_new_from_file (filename, NULL)))
+ return NULL;
+
+ image = NULL;
+
+ width = gdk_pixbuf_get_width (pixbuf);
+ height = gdk_pixbuf_get_height (pixbuf);
+ n_channels = gdk_pixbuf_get_n_channels (pixbuf);
+ gdk_data = gdk_pixbuf_get_pixels (pixbuf);
+ stride = gdk_pixbuf_get_rowstride (pixbuf);
+
+ if (!(data = malloc (width * height * sizeof (uint32_t))))
+ goto out;
+
+ d = data;
+ for (j = 0; j < height; ++j)
+ {
+ uint8_t *gdk_line = gdk_data;
+
+ for (i = 0; i < width; ++i)
+ {
+ int r, g, b, a;
+ uint32_t pixel;
+
+ r = gdk_line[0];
+ g = gdk_line[1];
+ b = gdk_line[2];
+
+ if (n_channels == 4)
+ a = gdk_line[3];
+ else
+ a = 0xff;
+
+ r = (r * a + 127) / 255;
+ g = (g * a + 127) / 255;
+ b = (b * a + 127) / 255;
+
+ pixel = (a << 24) | (r << 16) | (g << 8) | b;
+
+ *d++ = pixel;
+ gdk_line += n_channels;
+ }
+
+ gdk_data += stride;
+ }
+
+ image = pixman_image_create_bits (
+ format, width, height, data, width * 4);
+
+out:
+ g_object_unref (pixbuf);
+ return image;
+}
+
GdkPixbuf *
pixbuf_from_argb32 (uint32_t *bits,
int width,
diff --git a/pixman/demos/gtk-utils.h b/pixman/demos/gtk-utils.h
index 55cb7018a..36be4def6 100644
--- a/pixman/demos/gtk-utils.h
+++ b/pixman/demos/gtk-utils.h
@@ -6,6 +6,9 @@
void show_image (pixman_image_t *image);
+pixman_image_t *
+pixman_image_from_file (const char *filename, pixman_format_code_t format);
+
GdkPixbuf *pixbuf_from_argb32 (uint32_t *bits,
int width,
int height,
diff --git a/pixman/demos/scale.c b/pixman/demos/scale.c
new file mode 100644
index 000000000..9100ff72a
--- /dev/null
+++ b/pixman/demos/scale.c
@@ -0,0 +1,431 @@
+/*
+ * Copyright 2012, Red Hat, Inc.
+ * Copyright 2012, Soren Sandmann
+ *
+ * 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.
+ *
+ * Author: Soren Sandmann <soren.sandmann@gmail.com>
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <math.h>
+#include <gtk/gtk.h>
+#include <pixman.h>
+#include <stdlib.h>
+#include "gtk-utils.h"
+
+typedef struct
+{
+ GtkBuilder * builder;
+ pixman_image_t * original;
+ GtkAdjustment * scale_x_adjustment;
+ GtkAdjustment * scale_y_adjustment;
+ GtkAdjustment * rotate_adjustment;
+ int scaled_width;
+ int scaled_height;
+} app_t;
+
+static GtkWidget *
+get_widget (app_t *app, const char *name)
+{
+ GtkWidget *widget = GTK_WIDGET (gtk_builder_get_object (app->builder, name));
+
+ if (!widget)
+ g_error ("Widget %s not found\n", name);
+
+ return widget;
+}
+
+static double
+min4 (double a, double b, double c, double d)
+{
+ double m1, m2;
+
+ m1 = MIN (a, b);
+ m2 = MIN (c, d);
+ return MIN (m1, m2);
+}
+
+static double
+max4 (double a, double b, double c, double d)
+{
+ double m1, m2;
+
+ m1 = MAX (a, b);
+ m2 = MAX (c, d);
+ return MAX (m1, m2);
+}
+
+static void
+compute_extents (pixman_f_transform_t *trans, double *sx, double *sy)
+{
+ double min_x, max_x, min_y, max_y;
+ pixman_f_vector_t v[4] =
+ {
+ { { 1, 1, 1 } },
+ { { -1, 1, 1 } },
+ { { -1, -1, 1 } },
+ { { 1, -1, 1 } },
+ };
+
+ pixman_f_transform_point (trans, &v[0]);
+ pixman_f_transform_point (trans, &v[1]);
+ pixman_f_transform_point (trans, &v[2]);
+ pixman_f_transform_point (trans, &v[3]);
+
+ min_x = min4 (v[0].v[0], v[1].v[0], v[2].v[0], v[3].v[0]);
+ max_x = max4 (v[0].v[0], v[1].v[0], v[2].v[0], v[3].v[0]);
+ min_y = min4 (v[0].v[1], v[1].v[1], v[2].v[1], v[3].v[1]);
+ max_y = max4 (v[0].v[1], v[1].v[1], v[2].v[1], v[3].v[1]);
+
+ *sx = (max_x - min_x) / 2.0;
+ *sy = (max_y - min_y) / 2.0;
+}
+
+typedef struct
+{
+ char name [20];
+ pixman_kernel_t value;
+} named_int_t;
+
+static const named_int_t filters[] =
+{
+ { "Box", PIXMAN_KERNEL_BOX },
+ { "Impulse", PIXMAN_KERNEL_IMPULSE },
+ { "Linear", PIXMAN_KERNEL_LINEAR },
+ { "Cubic", PIXMAN_KERNEL_CUBIC },
+ { "Lanczos2", PIXMAN_KERNEL_LANCZOS2 },
+ { "Lanczos3", PIXMAN_KERNEL_LANCZOS3 },
+ { "Lanczos3 Stretched", PIXMAN_KERNEL_LANCZOS3_STRETCHED },
+ { "Gaussian", PIXMAN_KERNEL_GAUSSIAN },
+};
+
+static const named_int_t repeats[] =
+{
+ { "None", PIXMAN_REPEAT_NONE },
+ { "Normal", PIXMAN_REPEAT_NORMAL },
+ { "Reflect", PIXMAN_REPEAT_REFLECT },
+ { "Pad", PIXMAN_REPEAT_PAD },
+};
+
+static pixman_kernel_t
+get_value (app_t *app, const named_int_t table[], const char *box_name)
+{
+ GtkComboBox *box = GTK_COMBO_BOX (get_widget (app, box_name));
+
+ return table[gtk_combo_box_get_active (box)].value;
+}
+
+static void
+copy_to_counterpart (app_t *app, GObject *object)
+{
+ static const char *xy_map[] =
+ {
+ "reconstruct_x_combo_box", "reconstruct_y_combo_box",
+ "sample_x_combo_box", "sample_y_combo_box",
+ "scale_x_adjustment", "scale_y_adjustment",
+ };
+ GObject *counterpart = NULL;
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (xy_map); i += 2)
+ {
+ GObject *x = gtk_builder_get_object (app->builder, xy_map[i]);
+ GObject *y = gtk_builder_get_object (app->builder, xy_map[i + 1]);
+
+ if (object == x)
+ counterpart = y;
+ if (object == y)
+ counterpart = x;
+ }
+
+ if (!counterpart)
+ return;
+
+ if (GTK_IS_COMBO_BOX (counterpart))
+ {
+ gtk_combo_box_set_active (
+ GTK_COMBO_BOX (counterpart),
+ gtk_combo_box_get_active (
+ GTK_COMBO_BOX (object)));
+ }
+ else if (GTK_IS_ADJUSTMENT (counterpart))
+ {
+ gtk_adjustment_set_value (
+ GTK_ADJUSTMENT (counterpart),
+ gtk_adjustment_get_value (
+ GTK_ADJUSTMENT (object)));
+ }
+}
+
+static double
+to_scale (double v)
+{
+ return pow (1.15, v);
+}
+
+static void
+rescale (GtkWidget *may_be_null, app_t *app)
+{
+ pixman_f_transform_t ftransform;
+ pixman_transform_t transform;
+ double new_width, new_height;
+ double fscale_x, fscale_y;
+ double rotation;
+ pixman_fixed_t *params;
+ int n_params;
+ double sx, sy;
+
+ pixman_f_transform_init_identity (&ftransform);
+
+ if (may_be_null && gtk_toggle_button_get_active (
+ GTK_TOGGLE_BUTTON (get_widget (app, "lock_checkbutton"))))
+ {
+ copy_to_counterpart (app, G_OBJECT (may_be_null));
+ }
+
+ fscale_x = gtk_adjustment_get_value (app->scale_x_adjustment);
+ fscale_y = gtk_adjustment_get_value (app->scale_y_adjustment);
+ rotation = gtk_adjustment_get_value (app->rotate_adjustment);
+
+ fscale_x = to_scale (fscale_x);
+ fscale_y = to_scale (fscale_y);
+
+ new_width = pixman_image_get_width (app->original) * fscale_x;
+ new_height = pixman_image_get_height (app->original) * fscale_y;
+
+ pixman_f_transform_scale (&ftransform, NULL, fscale_x, fscale_y);
+
+ pixman_f_transform_translate (&ftransform, NULL, - new_width / 2.0, - new_height / 2.0);
+
+ rotation = (rotation / 360.0) * 2 * M_PI;
+ pixman_f_transform_rotate (&ftransform, NULL, cos (rotation), sin (rotation));
+
+ pixman_f_transform_translate (&ftransform, NULL, new_width / 2.0, new_height / 2.0);
+
+ pixman_f_transform_invert (&ftransform, &ftransform);
+
+ compute_extents (&ftransform, &sx, &sy);
+
+ pixman_transform_from_pixman_f_transform (&transform, &ftransform);
+ pixman_image_set_transform (app->original, &transform);
+
+ params = pixman_filter_create_separable_convolution (
+ &n_params,
+ sx * 65536.0 + 0.5,
+ sy * 65536.0 + 0.5,
+ get_value (app, filters, "reconstruct_x_combo_box"),
+ get_value (app, filters, "reconstruct_y_combo_box"),
+ get_value (app, filters, "sample_x_combo_box"),
+ get_value (app, filters, "sample_y_combo_box"),
+ 4, 4);
+
+ pixman_image_set_filter (app->original, PIXMAN_FILTER_SEPARABLE_CONVOLUTION, params, n_params);
+
+ pixman_image_set_repeat (
+ app->original, get_value (app, repeats, "repeat_combo_box"));
+
+ free (params);
+
+ app->scaled_width = ceil (new_width);
+ app->scaled_height = ceil (new_height);
+
+ gtk_widget_set_size_request (
+ get_widget (app, "drawing_area"), new_width + 0.5, new_height + 0.5);
+
+ gtk_widget_queue_draw (
+ get_widget (app, "drawing_area"));
+}
+
+static gboolean
+on_expose (GtkWidget *da, GdkEvent *event, gpointer data)
+{
+ app_t *app = data;
+ GdkRectangle *area = &event->expose.area;
+ cairo_surface_t *surface;
+ pixman_image_t *tmp;
+ cairo_t *cr;
+ uint32_t *pixels;
+
+ pixels = calloc (1, area->width * area->height * 4);
+ tmp = pixman_image_create_bits (
+ PIXMAN_a8r8g8b8, area->width, area->height, pixels, area->width * 4);
+
+ if (area->x < app->scaled_width && area->y < app->scaled_height)
+ {
+ pixman_image_composite (
+ PIXMAN_OP_SRC,
+ app->original, NULL, tmp,
+ area->x, area->y, 0, 0, 0, 0,
+ app->scaled_width - area->x, app->scaled_height - area->y);
+ }
+
+ surface = cairo_image_surface_create_for_data (
+ (uint8_t *)pixels, CAIRO_FORMAT_ARGB32,
+ area->width, area->height, area->width * 4);
+
+ cr = gdk_cairo_create (da->window);
+
+ cairo_set_source_surface (cr, surface, area->x, area->y);
+
+ cairo_paint (cr);
+
+ cairo_destroy (cr);
+ cairo_surface_destroy (surface);
+ free (pixels);
+ pixman_image_unref (tmp);
+
+ return TRUE;
+}
+
+static void
+set_up_combo_box (app_t *app, const char *box_name,
+ int n_entries, const named_int_t table[])
+{
+ GtkWidget *widget = get_widget (app, box_name);
+ GtkListStore *model;
+ GtkCellRenderer *cell;
+ int i;
+
+ model = gtk_list_store_new (1, G_TYPE_STRING);
+
+ cell = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (widget), cell, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (widget), cell,
+ "text", 0,
+ NULL);
+
+ gtk_combo_box_set_model (GTK_COMBO_BOX (widget), GTK_TREE_MODEL (model));
+
+ for (i = 0; i < n_entries; ++i)
+ {
+ const named_int_t *info = &(table[i]);
+ GtkTreeIter iter;
+
+ gtk_list_store_append (model, &iter);
+ gtk_list_store_set (model, &iter, 0, info->name, -1);
+ }
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
+
+ g_signal_connect (widget, "changed", G_CALLBACK (rescale), app);
+}
+
+static void
+set_up_filter_box (app_t *app, const char *box_name)
+{
+ set_up_combo_box (app, box_name, G_N_ELEMENTS (filters), filters);
+}
+
+static char *
+format_value (GtkWidget *widget, double value)
+{
+ return g_strdup_printf ("%.4f", to_scale (value));
+}
+
+static app_t *
+app_new (pixman_image_t *original)
+{
+ GtkWidget *widget;
+ app_t *app = g_malloc (sizeof *app);
+ GError *err = NULL;
+
+ app->builder = gtk_builder_new ();
+ app->original = original;
+
+ if (!gtk_builder_add_from_file (app->builder, "scale.ui", &err))
+ g_error ("Could not read file scale.ui: %s", err->message);
+
+ app->scale_x_adjustment =
+ GTK_ADJUSTMENT (gtk_builder_get_object (app->builder, "scale_x_adjustment"));
+ app->scale_y_adjustment =
+ GTK_ADJUSTMENT (gtk_builder_get_object (app->builder, "scale_y_adjustment"));
+ app->rotate_adjustment =
+ GTK_ADJUSTMENT (gtk_builder_get_object (app->builder, "rotate_adjustment"));
+
+ g_signal_connect (app->scale_x_adjustment, "value_changed", G_CALLBACK (rescale), app);
+ g_signal_connect (app->scale_y_adjustment, "value_changed", G_CALLBACK (rescale), app);
+ g_signal_connect (app->rotate_adjustment, "value_changed", G_CALLBACK (rescale), app);
+
+ widget = get_widget (app, "scale_x_scale");
+ gtk_scale_add_mark (GTK_SCALE (widget), 0.0, GTK_POS_LEFT, NULL);
+ g_signal_connect (widget, "format_value", G_CALLBACK (format_value), app);
+ widget = get_widget (app, "scale_y_scale");
+ gtk_scale_add_mark (GTK_SCALE (widget), 0.0, GTK_POS_LEFT, NULL);
+ g_signal_connect (widget, "format_value", G_CALLBACK (format_value), app);
+ widget = get_widget (app, "rotate_scale");
+ gtk_scale_add_mark (GTK_SCALE (widget), 0.0, GTK_POS_LEFT, NULL);
+
+ widget = get_widget (app, "drawing_area");
+ g_signal_connect (widget, "expose_event", G_CALLBACK (on_expose), app);
+
+ set_up_filter_box (app, "reconstruct_x_combo_box");
+ set_up_filter_box (app, "reconstruct_y_combo_box");
+ set_up_filter_box (app, "sample_x_combo_box");
+ set_up_filter_box (app, "sample_y_combo_box");
+
+ set_up_combo_box (
+ app, "repeat_combo_box", G_N_ELEMENTS (repeats), repeats);
+
+ g_signal_connect (
+ gtk_builder_get_object (app->builder, "lock_checkbutton"),
+ "toggled", G_CALLBACK (rescale), app);
+
+ rescale (NULL, app);
+
+ return app;
+}
+
+int
+main (int argc, char **argv)
+{
+ GtkWidget *window;
+ pixman_image_t *image;
+ app_t *app;
+
+ gtk_init (&argc, &argv);
+
+ if (argc < 2)
+ {
+ printf ("%s <image file>\n", argv[0]);
+ return -1;
+ }
+
+ if (!(image = pixman_image_from_file (argv[1], PIXMAN_a8r8g8b8)))
+ {
+ printf ("Could not load image \"%s\"\n", argv[1]);
+ return -1;
+ }
+
+ app = app_new (image);
+
+ window = get_widget (app, "main");
+
+ g_signal_connect (window, "delete_event", G_CALLBACK (gtk_main_quit), NULL);
+
+ gtk_window_set_default_size (GTK_WINDOW (window), 1024, 768);
+
+ gtk_widget_show_all (window);
+
+ gtk_main ();
+
+ return 0;
+}
diff --git a/pixman/demos/scale.ui b/pixman/demos/scale.ui
new file mode 100644
index 000000000..f7c0c805f
--- /dev/null
+++ b/pixman/demos/scale.ui
@@ -0,0 +1,302 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 2.12 -->
+ <!-- interface-naming-policy toplevel-contextual -->
+ <object class="GtkAdjustment" id="rotate_adjustment">
+ <property name="lower">-180</property>
+ <property name="upper">190</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ <property name="page_size">10</property>
+ </object>
+ <object class="GtkAdjustment" id="scale_y_adjustment">
+ <property name="lower">-32</property>
+ <property name="upper">42</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ <property name="page_size">10</property>
+ </object>
+ <object class="GtkAdjustment" id="scale_x_adjustment">
+ <property name="lower">-32</property>
+ <property name="upper">42</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ <property name="page_size">10</property>
+ </object>
+ <object class="GtkWindow" id="main">
+ <child>
+ <object class="GtkHBox" id="u">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkViewport" id="viewport1">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkDrawingArea" id="drawing_area">
+ <property name="visible">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="box1">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkHBox" id="box2">
+ <property name="visible">True</property>
+ <property name="homogeneous">True</property>
+ <child>
+ <object class="GtkVBox" id="box3">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Scale X&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVScale" id="scale_x_scale">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">scale_x_adjustment</property>
+ <property name="fill_level">32</property>
+ <property name="value_pos">right</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="box4">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Scale Y&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVScale" id="scale_y_scale">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">scale_y_adjustment</property>
+ <property name="fill_level">32</property>
+ <property name="value_pos">right</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="box5">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Rotate&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVScale" id="rotate_scale">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">rotate_adjustment</property>
+ <property name="fill_level">180</property>
+ <property name="value_pos">right</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="padding">6</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="box6">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkCheckButton"
+ id="lock_checkbutton">
+ <property name="label" translatable="yes">Lock X and Y Dimensions</property>
+ <property name="xalign">0.0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">6</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkTable" id="grid1">
+ <property name="visible">True</property>
+ <property name="column_spacing">8</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">&lt;b&gt;Reconstruct X:&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">&lt;b&gt;Reconstruct Y:&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">&lt;b&gt;Sample X:&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label7">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">&lt;b&gt;Sample Y:&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label8">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">&lt;b&gt;Repeat:&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="reconstruct_x_combo_box">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="reconstruct_y_combo_box">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="sample_x_combo_box">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="sample_y_combo_box">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="repeat_combo_box">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="padding">6</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/pixman/demos/zone_plate.png b/pixman/demos/zone_plate.png
new file mode 100644
index 000000000..519291d6d
--- /dev/null
+++ b/pixman/demos/zone_plate.png
Binary files differ
diff --git a/pixman/pixman/Makefile.sources b/pixman/pixman/Makefile.sources
index 5351fb03d..c624eb9a8 100644
--- a/pixman/pixman/Makefile.sources
+++ b/pixman/pixman/Makefile.sources
@@ -6,6 +6,7 @@ libpixman_sources = \
pixman-combine32.c \
pixman-combine-float.c \
pixman-conical-gradient.c \
+ pixman-filter.c \
pixman-x86.c \
pixman-mips.c \
pixman-arm.c \
diff --git a/pixman/pixman/pixman-bits-image.c b/pixman/pixman/pixman-bits-image.c
index 7787ef1b8..86d80c3f5 100644
--- a/pixman/pixman/pixman-bits-image.c
+++ b/pixman/pixman/pixman-bits-image.c
@@ -426,6 +426,104 @@ bits_image_fetch_pixel_convolution (bits_image_t *image,
return ((satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot));
}
+static uint32_t
+bits_image_fetch_pixel_separable_convolution (bits_image_t *image,
+ pixman_fixed_t x,
+ pixman_fixed_t y,
+ get_pixel_t get_pixel)
+{
+ pixman_fixed_t *params = image->common.filter_params;
+ pixman_repeat_t repeat_mode = image->common.repeat;
+ int width = image->width;
+ int height = image->height;
+ int cwidth = pixman_fixed_to_int (params[0]);
+ int cheight = pixman_fixed_to_int (params[1]);
+ int x_phase_bits = pixman_fixed_to_int (params[2]);
+ int y_phase_bits = pixman_fixed_to_int (params[3]);
+ int x_phase_shift = 16 - x_phase_bits;
+ int y_phase_shift = 16 - y_phase_bits;
+ 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;
+ int32_t x1, x2, y1, y2;
+ int32_t px, py;
+ int i, j;
+
+ /* Round x and y to the middle of the closest phase before continuing. This
+ * ensures that the convolution matrix is aligned right, since it was
+ * positioned relative to a particular phase (and not relative to whatever
+ * exact fraction we happen to get here).
+ */
+ x = ((x >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1);
+ y = ((y >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1);
+
+ px = (x & 0xffff) >> x_phase_shift;
+ py = (y & 0xffff) >> y_phase_shift;
+
+ y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight;
+
+ x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
+ y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
+ x2 = x1 + cwidth;
+ y2 = y1 + cheight;
+
+ srtot = sgtot = sbtot = satot = 0;
+
+ for (i = y1; i < y2; ++i)
+ {
+ pixman_fixed_48_16_t fy = *y_params++;
+ pixman_fixed_t *x_params = params + 4 + px * cwidth;
+
+ if (fy)
+ {
+ for (j = x1; j < x2; ++j)
+ {
+ pixman_fixed_t fx = *x_params++;
+ int rx = j;
+ int ry = i;
+
+ if (fx)
+ {
+ pixman_fixed_t f;
+ uint32_t pixel;
+
+ if (repeat_mode != PIXMAN_REPEAT_NONE)
+ {
+ repeat (repeat_mode, &rx, width);
+ repeat (repeat_mode, &ry, height);
+
+ pixel = get_pixel (image, rx, ry, FALSE);
+ }
+ else
+ {
+ pixel = get_pixel (image, rx, ry, TRUE);
+ }
+
+ f = (fy * fx + 0x8000) >> 16;
+
+ srtot += (int)RED_8 (pixel) * f;
+ sgtot += (int)GREEN_8 (pixel) * f;
+ sbtot += (int)BLUE_8 (pixel) * f;
+ satot += (int)ALPHA_8 (pixel) * f;
+ }
+ }
+ }
+ }
+
+ satot = (satot + 0x8000) >> 16;
+ srtot = (srtot + 0x8000) >> 16;
+ sgtot = (sgtot + 0x8000) >> 16;
+ sbtot = (sbtot + 0x8000) >> 16;
+
+ satot = CLIP (satot, 0, 0xff);
+ srtot = CLIP (srtot, 0, 0xff);
+ sgtot = CLIP (sgtot, 0, 0xff);
+ sbtot = CLIP (sbtot, 0, 0xff);
+
+ return ((satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot));
+}
+
static force_inline uint32_t
bits_image_fetch_pixel_filtered (bits_image_t *image,
pixman_fixed_t x,
@@ -449,6 +547,10 @@ bits_image_fetch_pixel_filtered (bits_image_t *image,
return bits_image_fetch_pixel_convolution (image, x, y, get_pixel);
break;
+ case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
+ return bits_image_fetch_pixel_separable_convolution (image, x, y, get_pixel);
+ break;
+
default:
break;
}
@@ -618,11 +720,155 @@ bits_image_fetch_general (pixman_iter_t *iter,
return buffer;
}
-static const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
-
typedef uint32_t (* convert_pixel_t) (const uint8_t *row, int x);
static force_inline void
+bits_image_fetch_separable_convolution_affine (pixman_image_t * image,
+ int offset,
+ int line,
+ int width,
+ uint32_t * buffer,
+ const uint32_t * mask,
+
+ convert_pixel_t convert_pixel,
+ pixman_format_code_t format,
+ pixman_repeat_t repeat_mode)
+{
+ bits_image_t *bits = &image->bits;
+ pixman_fixed_t *params = image->common.filter_params;
+ int cwidth = pixman_fixed_to_int (params[0]);
+ int cheight = pixman_fixed_to_int (params[1]);
+ int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1;
+ int y_off = ((cheight << 16) - pixman_fixed_1) >> 1;
+ int x_phase_bits = pixman_fixed_to_int (params[2]);
+ int y_phase_bits = pixman_fixed_to_int (params[3]);
+ int x_phase_shift = 16 - x_phase_bits;
+ int y_phase_shift = 16 - y_phase_bits;
+ pixman_fixed_t vx, vy;
+ pixman_fixed_t ux, uy;
+ pixman_vector_t v;
+ int k;
+
+ /* reference point is the center of the pixel */
+ v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
+ v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
+ v.vector[2] = pixman_fixed_1;
+
+ if (!pixman_transform_point_3d (image->common.transform, &v))
+ return;
+
+ ux = image->common.transform->matrix[0][0];
+ uy = image->common.transform->matrix[1][0];
+
+ vx = v.vector[0];
+ vy = v.vector[1];
+
+ for (k = 0; k < width; ++k)
+ {
+ pixman_fixed_t *y_params;
+ int satot, srtot, sgtot, sbtot;
+ pixman_fixed_t x, y;
+ int32_t x1, x2, y1, y2;
+ int32_t px, py;
+ int i, j;
+
+ if (mask && !mask[k])
+ goto next;
+
+ /* Round x and y to the middle of the closest phase before continuing. This
+ * ensures that the convolution matrix is aligned right, since it was
+ * positioned relative to a particular phase (and not relative to whatever
+ * exact fraction we happen to get here).
+ */
+ x = ((vx >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1);
+ y = ((vy >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1);
+
+ px = (x & 0xffff) >> x_phase_shift;
+ py = (y & 0xffff) >> y_phase_shift;
+
+ x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
+ y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
+ x2 = x1 + cwidth;
+ y2 = y1 + cheight;
+
+ satot = srtot = sgtot = sbtot = 0;
+
+ y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight;
+
+ for (i = y1; i < y2; ++i)
+ {
+ pixman_fixed_t fy = *y_params++;
+
+ if (fy)
+ {
+ pixman_fixed_t *x_params = params + 4 + px * cwidth;
+
+ for (j = x1; j < x2; ++j)
+ {
+ pixman_fixed_t fx = *x_params++;
+ int rx = j;
+ int ry = i;
+
+ if (fx)
+ {
+ pixman_fixed_t f;
+ uint32_t pixel, mask;
+ uint8_t *row;
+
+ mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
+
+ if (repeat_mode != PIXMAN_REPEAT_NONE)
+ {
+ repeat (repeat_mode, &rx, bits->width);
+ repeat (repeat_mode, &ry, bits->height);
+
+ row = (uint8_t *)bits->bits + bits->rowstride * 4 * ry;
+ pixel = convert_pixel (row, rx) | mask;
+ }
+ else
+ {
+ if (rx < 0 || ry < 0 || rx >= bits->width || ry >= bits->height)
+ {
+ pixel = 0;
+ }
+ else
+ {
+ row = (uint8_t *)bits->bits + bits->rowstride * 4 * ry;
+ pixel = convert_pixel (row, rx) | mask;
+ }
+ }
+
+ f = ((pixman_fixed_32_32_t)fx * fy + 0x8000) >> 16;
+ srtot += (int)RED_8 (pixel) * f;
+ sgtot += (int)GREEN_8 (pixel) * f;
+ sbtot += (int)BLUE_8 (pixel) * f;
+ satot += (int)ALPHA_8 (pixel) * f;
+ }
+ }
+ }
+ }
+
+ satot = (satot + 0x8000) >> 16;
+ srtot = (srtot + 0x8000) >> 16;
+ sgtot = (sgtot + 0x8000) >> 16;
+ sbtot = (sbtot + 0x8000) >> 16;
+
+ satot = CLIP (satot, 0, 0xff);
+ srtot = CLIP (srtot, 0, 0xff);
+ sgtot = CLIP (sgtot, 0, 0xff);
+ sbtot = CLIP (sbtot, 0, 0xff);
+
+ buffer[k] = (satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot << 0);
+
+ next:
+ vx += ux;
+ vy += uy;
+ }
+}
+
+static const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+static force_inline void
bits_image_fetch_bilinear_affine (pixman_image_t * image,
int offset,
int line,
@@ -871,6 +1117,23 @@ convert_r5g6b5 (const uint8_t *row, int x)
return CONVERT_0565_TO_0888 (*((uint16_t *)row + x));
}
+#define MAKE_SEPARABLE_CONVOLUTION_FETCHER(name, format, repeat_mode) \
+ static uint32_t * \
+ bits_image_fetch_separable_convolution_affine_ ## name (pixman_iter_t *iter, \
+ const uint32_t * mask) \
+ { \
+ bits_image_fetch_separable_convolution_affine ( \
+ iter->image, \
+ iter->x, iter->y++, \
+ iter->width, \
+ iter->buffer, mask, \
+ convert_ ## format, \
+ PIXMAN_ ## format, \
+ repeat_mode); \
+ \
+ return iter->buffer; \
+ }
+
#define MAKE_BILINEAR_FETCHER(name, format, repeat_mode) \
static uint32_t * \
bits_image_fetch_bilinear_affine_ ## name (pixman_iter_t *iter, \
@@ -903,7 +1166,8 @@ convert_r5g6b5 (const uint8_t *row, int x)
#define MAKE_FETCHERS(name, format, repeat_mode) \
MAKE_NEAREST_FETCHER (name, format, repeat_mode) \
- MAKE_BILINEAR_FETCHER (name, format, repeat_mode)
+ MAKE_BILINEAR_FETCHER (name, format, repeat_mode) \
+ MAKE_SEPARABLE_CONVOLUTION_FETCHER (name, format, repeat_mode)
MAKE_FETCHERS (pad_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_PAD)
MAKE_FETCHERS (none_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_NONE)
@@ -1153,6 +1417,20 @@ static const fetcher_info_t fetcher_info[] =
FAST_PATH_AFFINE_TRANSFORM | \
FAST_PATH_NEAREST_FILTER)
+#define GENERAL_SEPARABLE_CONVOLUTION_FLAGS \
+ (FAST_PATH_NO_ALPHA_MAP | \
+ FAST_PATH_NO_ACCESSORS | \
+ FAST_PATH_HAS_TRANSFORM | \
+ FAST_PATH_AFFINE_TRANSFORM | \
+ FAST_PATH_SEPARABLE_CONVOLUTION_FILTER)
+
+#define SEPARABLE_CONVOLUTION_AFFINE_FAST_PATH(name, format, repeat) \
+ { PIXMAN_ ## format, \
+ GENERAL_SEPARABLE_CONVOLUTION_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \
+ bits_image_fetch_separable_convolution_affine_ ## name, \
+ _pixman_image_get_scanline_generic_float \
+ },
+
#define BILINEAR_AFFINE_FAST_PATH(name, format, repeat) \
{ PIXMAN_ ## format, \
GENERAL_BILINEAR_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \
@@ -1168,6 +1446,7 @@ static const fetcher_info_t fetcher_info[] =
},
#define AFFINE_FAST_PATHS(name, format, repeat) \
+ SEPARABLE_CONVOLUTION_AFFINE_FAST_PATH(name, format, repeat) \
BILINEAR_AFFINE_FAST_PATH(name, format, repeat) \
NEAREST_AFFINE_FAST_PATH(name, format, repeat)
diff --git a/pixman/pixman/pixman-filter.c b/pixman/pixman/pixman-filter.c
new file mode 100644
index 000000000..c9d2dc74c
--- /dev/null
+++ b/pixman/pixman/pixman-filter.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright 2012, Red Hat, Inc.
+ * Copyright 2012, Soren Sandmann
+ *
+ * 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.
+ *
+ * Author: Soren Sandmann <soren.sandmann@gmail.com>
+ */
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <assert.h>
+#include <config.h>
+#include "pixman-private.h"
+
+typedef double (* kernel_func_t) (double x);
+
+typedef struct
+{
+ pixman_kernel_t kernel;
+ kernel_func_t func;
+ double width;
+} filter_info_t;
+
+static double
+impulse_kernel (double x)
+{
+ return (x == 0.0)? 1.0 : 0.0;
+}
+
+static double
+box_kernel (double x)
+{
+ return 1;
+}
+
+static double
+linear_kernel (double x)
+{
+ return 1 - fabs (x);
+}
+
+static double
+gaussian_kernel (double x)
+{
+#define SQRT2 (1.4142135623730950488016887242096980785696718753769480)
+#define SIGMA (SQRT2 / 2.0)
+
+ return exp (- x * x / (2 * SIGMA * SIGMA)) / (SIGMA * sqrt (2.0 * M_PI));
+}
+
+static double
+sinc (double x)
+{
+ if (x == 0.0)
+ return 1.0;
+ else
+ return sin (M_PI * x) / (M_PI * x);
+}
+
+static double
+lanczos (double x, int n)
+{
+ return sinc (x) * sinc (x * (1.0 / n));
+}
+
+static double
+lanczos2_kernel (double x)
+{
+ return lanczos (x, 2);
+}
+
+static double
+lanczos3_kernel (double x)
+{
+ return lanczos (x, 3);
+}
+
+static double
+nice_kernel (double x)
+{
+ return lanczos3_kernel (x * 0.75);
+}
+
+static double
+general_cubic (double x, double B, double C)
+{
+ double ax = fabs(x);
+
+ if (ax < 1)
+ {
+ return ((12 - 9 * B - 6 * C) * ax * ax * ax +
+ (-18 + 12 * B + 6 * C) * ax * ax + (6 - 2 * B)) / 6;
+ }
+ else if (ax >= 1 && ax < 2)
+ {
+ return ((-B - 6 * C) * ax * ax * ax +
+ (6 * B + 30 * C) * ax * ax + (-12 * B - 48 * C) *
+ ax + (8 * B + 24 * C)) / 6;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+static double
+cubic_kernel (double x)
+{
+ /* This is the Mitchell-Netravali filter.
+ *
+ * (0.0, 0.5) would give us the Catmull-Rom spline,
+ * but that one seems to be indistinguishable from Lanczos2.
+ */
+ return general_cubic (x, 1/3.0, 1/3.0);
+}
+
+static const filter_info_t filters[] =
+{
+ { PIXMAN_KERNEL_IMPULSE, impulse_kernel, 0.0 },
+ { PIXMAN_KERNEL_BOX, box_kernel, 1.0 },
+ { PIXMAN_KERNEL_LINEAR, linear_kernel, 2.0 },
+ { PIXMAN_KERNEL_CUBIC, cubic_kernel, 4.0 },
+ { PIXMAN_KERNEL_GAUSSIAN, gaussian_kernel, 6 * SIGMA },
+ { PIXMAN_KERNEL_LANCZOS2, lanczos2_kernel, 4.0 },
+ { PIXMAN_KERNEL_LANCZOS3, lanczos3_kernel, 6.0 },
+ { PIXMAN_KERNEL_LANCZOS3_STRETCHED, nice_kernel, 8.0 },
+};
+
+/* This function scales @kernel2 by @scale, then
+ * aligns @x1 in @kernel1 with @x2 in @kernel2 and
+ * and integrates the product of the kernels across @width.
+ *
+ * This function assumes that the intervals are within
+ * the kernels in question. E.g., the caller must not
+ * try to integrate a linear kernel ouside of [-1:1]
+ */
+static double
+integral (pixman_kernel_t kernel1, double x1,
+ pixman_kernel_t kernel2, double scale, double x2,
+ double width)
+{
+ /* If the integration interval crosses zero, break it into
+ * two separate integrals. This ensures that filters such
+ * as LINEAR that are not differentiable at 0 will still
+ * integrate properly.
+ */
+ if (x1 < 0 && x1 + width > 0)
+ {
+ return
+ integral (kernel1, x1, kernel2, scale, x2, - x1) +
+ integral (kernel1, 0, kernel2, scale, x2 - x1, width + x1);
+ }
+ else if (x2 < 0 && x2 + width > 0)
+ {
+ return
+ integral (kernel1, x1, kernel2, scale, x2, - x2) +
+ integral (kernel1, x1 - x2, kernel2, scale, 0, width + x2);
+ }
+ else if (kernel1 == PIXMAN_KERNEL_IMPULSE)
+ {
+ assert (width == 0.0);
+ return filters[kernel2].func (x2 * scale);
+ }
+ else if (kernel2 == PIXMAN_KERNEL_IMPULSE)
+ {
+ assert (width == 0.0);
+ return filters[kernel1].func (x1);
+ }
+ else
+ {
+ /* Integration via Simpson's rule */
+#define N_SEGMENTS 128
+#define SAMPLE(a1, a2) \
+ (filters[kernel1].func ((a1)) * filters[kernel2].func ((a2) * scale))
+
+ double s = 0.0;
+ double h = width / (double)N_SEGMENTS;
+ int i;
+
+ s = SAMPLE (x1, x2);
+
+ for (i = 1; i < N_SEGMENTS; i += 2)
+ {
+ double a1 = x1 + h * i;
+ double a2 = x2 + h * i;
+
+ s += 2 * SAMPLE (a1, a2);
+
+ if (i >= 2 && i < N_SEGMENTS - 1)
+ s += 4 * SAMPLE (a1, a2);
+ }
+
+ s += SAMPLE (x1 + width, x2 + width);
+
+ return h * s * (1.0 / 3.0);
+ }
+}
+
+static pixman_fixed_t *
+create_1d_filter (int *width,
+ pixman_kernel_t reconstruct,
+ pixman_kernel_t sample,
+ double scale,
+ int n_phases)
+{
+ pixman_fixed_t *params, *p;
+ double step;
+ double size;
+ int i;
+
+ size = scale * filters[sample].width + filters[reconstruct].width;
+ *width = ceil (size);
+
+ p = params = malloc (*width * n_phases * sizeof (pixman_fixed_t));
+
+ step = 1.0 / n_phases;
+
+ for (i = 0; i < n_phases; ++i)
+ {
+ double frac = step / 2.0 + i * step;
+ pixman_fixed_t new_total;
+ int x, x1, x2;
+ double total;
+
+ /* Sample convolution of reconstruction and sampling
+ * filter. See rounding.txt regarding the rounding
+ * and sample positions.
+ */
+
+ x1 = ceil (frac - *width / 2.0 - 0.5);
+ x2 = x1 + *width;
+
+ total = 0;
+ for (x = x1; x < x2; ++x)
+ {
+ double pos = x + 0.5 - frac;
+ double rlow = - filters[reconstruct].width / 2.0;
+ double rhigh = rlow + filters[reconstruct].width;
+ double slow = pos - scale * filters[sample].width / 2.0;
+ double shigh = slow + scale * filters[sample].width;
+ double c = 0.0;
+ double ilow, ihigh;
+
+ if (rhigh >= slow && rlow <= shigh)
+ {
+ ilow = MAX (slow, rlow);
+ ihigh = MIN (shigh, rhigh);
+
+ c = integral (reconstruct, ilow,
+ sample, 1.0 / scale, ilow - pos,
+ ihigh - ilow);
+ }
+
+ total += c;
+ *p++ = (pixman_fixed_t)(c * 65535.0 + 0.5);
+ }
+
+ /* Normalize */
+ p -= *width;
+ total = 1 / total;
+ new_total = 0;
+ for (x = x1; x < x2; ++x)
+ {
+ pixman_fixed_t t = (*p) * total + 0.5;
+
+ new_total += t;
+ *p++ = t;
+ }
+
+ if (new_total != pixman_fixed_1)
+ *(p - *width / 2) += (pixman_fixed_1 - new_total);
+ }
+
+ return params;
+}
+
+/* Create the parameter list for a SEPARABLE_CONVOLUTION filter
+ * with the given kernels and scale parameters
+ */
+PIXMAN_EXPORT pixman_fixed_t *
+pixman_filter_create_separable_convolution (int *n_values,
+ pixman_fixed_t scale_x,
+ pixman_fixed_t scale_y,
+ pixman_kernel_t reconstruct_x,
+ pixman_kernel_t reconstruct_y,
+ pixman_kernel_t sample_x,
+ pixman_kernel_t sample_y,
+ int subsample_bits_x,
+ int subsample_bits_y)
+{
+ double sx = fabs (pixman_fixed_to_double (scale_x));
+ double sy = fabs (pixman_fixed_to_double (scale_y));
+ pixman_fixed_t *horz, *vert, *params;
+ int subsample_x, subsample_y;
+ int width, height;
+
+ subsample_x = (1 << subsample_bits_x);
+ subsample_y = (1 << subsample_bits_y);
+
+ horz = create_1d_filter (&width, reconstruct_x, sample_x, sx, subsample_x);
+ vert = create_1d_filter (&height, reconstruct_y, sample_y, sy, subsample_y);
+
+ *n_values = 4 + width * subsample_x + height * subsample_y;
+
+ params = malloc (*n_values * sizeof (pixman_fixed_t));
+
+ params[0] = pixman_int_to_fixed (width);
+ params[1] = pixman_int_to_fixed (height);
+ params[2] = pixman_int_to_fixed (subsample_bits_x);
+ params[3] = pixman_int_to_fixed (subsample_bits_y);
+
+ memcpy (params + 4, horz,
+ width * subsample_x * sizeof (pixman_fixed_t));
+ memcpy (params + 4 + width * subsample_x, vert,
+ height * subsample_y * sizeof (pixman_fixed_t));
+
+ free (horz);
+ free (vert);
+
+ return params;
+}
diff --git a/pixman/pixman/pixman-image.c b/pixman/pixman/pixman-image.c
index d9c303441..6f076d5c6 100644
--- a/pixman/pixman/pixman-image.c
+++ b/pixman/pixman/pixman-image.c
@@ -373,6 +373,10 @@ compute_image_info (pixman_image_t *image)
case PIXMAN_FILTER_CONVOLUTION:
break;
+ case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
+ flags |= FAST_PATH_SEPARABLE_CONVOLUTION_FILTER;
+ break;
+
default:
flags |= FAST_PATH_NO_CONVOLUTION_FILTER;
break;
@@ -515,8 +519,9 @@ compute_image_info (pixman_image_t *image)
* if all channels are opaque, so we simply turn it off
* unconditionally for those images.
*/
- if (image->common.alpha_map ||
- image->common.filter == PIXMAN_FILTER_CONVOLUTION ||
+ if (image->common.alpha_map ||
+ image->common.filter == PIXMAN_FILTER_CONVOLUTION ||
+ image->common.filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION ||
image->common.component_alpha)
{
flags &= ~(FAST_PATH_IS_OPAQUE | FAST_PATH_SAMPLES_OPAQUE);
@@ -679,6 +684,19 @@ pixman_image_set_filter (pixman_image_t * image,
if (params == common->filter_params && filter == common->filter)
return TRUE;
+ if (filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION)
+ {
+ int width = pixman_fixed_to_int (params[0]);
+ int height = pixman_fixed_to_int (params[1]);
+ int x_phase_bits = pixman_fixed_to_int (params[2]);
+ int y_phase_bits = pixman_fixed_to_int (params[3]);
+ int n_x_phases = (1 << x_phase_bits);
+ int n_y_phases = (1 << y_phase_bits);
+
+ return_val_if_fail (
+ n_params == 4 + n_x_phases * width + n_y_phases * height, FALSE);
+ }
+
new_params = NULL;
if (params)
{
diff --git a/pixman/pixman/pixman-private.h b/pixman/pixman/pixman-private.h
index c0a6bc0a5..99125a17e 100644
--- a/pixman/pixman/pixman-private.h
+++ b/pixman/pixman/pixman-private.h
@@ -687,6 +687,7 @@ _pixman_iter_get_scanline_noop (pixman_iter_t *iter, const uint32_t *mask);
#define FAST_PATH_SAMPLES_COVER_CLIP_NEAREST (1 << 23)
#define FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR (1 << 24)
#define FAST_PATH_BITS_IMAGE (1 << 25)
+#define FAST_PATH_SEPARABLE_CONVOLUTION_FILTER (1 << 26)
#define FAST_PATH_PAD_REPEAT \
(FAST_PATH_NO_NONE_REPEAT | \
diff --git a/pixman/pixman/pixman.c b/pixman/pixman/pixman.c
index e0ccd87d8..0661f41b0 100644
--- a/pixman/pixman/pixman.c
+++ b/pixman/pixman/pixman.c
@@ -455,6 +455,14 @@ analyze_extent (pixman_image_t *image,
height = params[1];
break;
+ case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
+ params = image->common.filter_params;
+ x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1);
+ y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1);
+ width = params[0];
+ height = params[1];
+ break;
+
case PIXMAN_FILTER_GOOD:
case PIXMAN_FILTER_BEST:
case PIXMAN_FILTER_BILINEAR:
diff --git a/pixman/pixman/pixman.h b/pixman/pixman/pixman.h
index 33ebf3f64..7ff9fb52a 100644
--- a/pixman/pixman/pixman.h
+++ b/pixman/pixman/pixman.h
@@ -292,7 +292,28 @@ typedef enum
PIXMAN_FILTER_BEST,
PIXMAN_FILTER_NEAREST,
PIXMAN_FILTER_BILINEAR,
- PIXMAN_FILTER_CONVOLUTION
+ PIXMAN_FILTER_CONVOLUTION,
+
+ /* The SEPARABLE_CONVOLUTION filter takes the following parameters:
+ *
+ * width: integer given as 16.16 fixpoint number
+ * height: integer given as 16.16 fixpoint number
+ * x_phase_bits: integer given as 16.16 fixpoint
+ * y_phase_bits: integer given as 16.16 fixpoint
+ * xtables: (1 << x_phase_bits) tables of size width
+ * ytables: (1 << y_phase_bits) tables of size height
+ *
+ * When sampling at (x, y), the location is first rounded to one of
+ * n_x_phases * n_y_phases subpixel positions. These subpixel positions
+ * determine an xtable and a ytable to use.
+ *
+ * Conceptually a width x height matrix is then formed in which each entry
+ * is the product of the corresponding entries in the x and y tables.
+ * This matrix is then aligned with the image pixels such that its center
+ * is as close as possible to the subpixel location chosen earlier. Then
+ * the image is convolved with the matrix and the resulting pixel returned.
+ */
+ PIXMAN_FILTER_SEPARABLE_CONVOLUTION
} pixman_filter_t;
typedef enum
@@ -810,6 +831,33 @@ int pixman_image_get_height (pixman_image_t
int pixman_image_get_stride (pixman_image_t *image); /* in bytes */
int pixman_image_get_depth (pixman_image_t *image);
pixman_format_code_t pixman_image_get_format (pixman_image_t *image);
+
+typedef enum
+{
+ PIXMAN_KERNEL_IMPULSE,
+ PIXMAN_KERNEL_BOX,
+ PIXMAN_KERNEL_LINEAR,
+ PIXMAN_KERNEL_CUBIC,
+ PIXMAN_KERNEL_GAUSSIAN,
+ PIXMAN_KERNEL_LANCZOS2,
+ PIXMAN_KERNEL_LANCZOS3,
+ PIXMAN_KERNEL_LANCZOS3_STRETCHED /* Jim Blinn's 'nice' filter */
+} pixman_kernel_t;
+
+/* Create the parameter list for a SEPARABLE_CONVOLUTION filter
+ * with the given kernels and scale parameters.
+ */
+pixman_fixed_t *
+pixman_filter_create_separable_convolution (int *n_values,
+ pixman_fixed_t scale_x,
+ pixman_fixed_t scale_y,
+ pixman_kernel_t reconstruct_x,
+ pixman_kernel_t reconstruct_y,
+ pixman_kernel_t sample_x,
+ pixman_kernel_t sample_y,
+ int subsample_bits_x,
+ int subsample_bits_y);
+
pixman_bool_t pixman_image_fill_rectangles (pixman_op_t op,
pixman_image_t *image,
const pixman_color_t *color,
diff --git a/pixman/pixman/rounding.txt b/pixman/pixman/rounding.txt
index 1a19f450f..b52b08439 100644
--- a/pixman/pixman/rounding.txt
+++ b/pixman/pixman/rounding.txt
@@ -132,3 +132,36 @@ And so the final formula for the index k of x0 in the image is:
Computing the result is then simply a matter of convolving all the
pixels starting at k with all the samples in the matrix.
+
+
+--- SEPARABLE_CONVOLUTION
+
+For this filter, x is first rounded to one of n regularly spaced
+subpixel positions. This subpixel position determines which of n
+convolution matrices is being used.
+
+Then, as in a regular convolution filter, the first pixel to be used
+is determined:
+
+ k = floor (x - (width - 1) / 2.0 - e)
+
+and then the image pixels starting there are convolved with the chosen
+matrix. If we write x = xi + frac, where xi is an integer, we get
+
+ k = xi + floor (frac - (width - 1) / 2.0 - e)
+
+so the location of k relative to x is given by:
+
+ (k + 0.5 - x) = xi + floor (frac - (width - 1) / 2.0 - e) + 0.5 - x
+
+ = floor (frac - (width - 1) / 2.0 - e) + 0.5 - frac
+
+which means the contents of the matrix corresponding to (frac) should
+contain width samplings of the function, with the first sample at:
+
+ floor (frac - (width - 1) / 2.0 - e) + 0.5 - frac
+
+This filter is called separable because each of the k x k convolution
+matrices is specified with two k-wide vectors, one for each dimension,
+where each entry in the matrix is computed as the product of the
+corresponding entries in the vectors.
diff --git a/pixman/test/Makefile.sources b/pixman/test/Makefile.sources
index 077897161..8c0b505df 100644
--- a/pixman/test/Makefile.sources
+++ b/pixman/test/Makefile.sources
@@ -1,5 +1,6 @@
# Tests (sorted by expected completion time)
TESTPROGRAMS = \
+ prng-test \
a1-trap-test \
pdf-op-test \
region-test \
@@ -33,8 +34,10 @@ BENCHMARKS = \
# Utility functions
libutils_sources = \
utils.c \
+ utils-prng.c \
$(NULL)
libutils_headers = \
utils.h \
+ utils-prng.h \
$(NULL)
diff --git a/pixman/test/affine-test.c b/pixman/test/affine-test.c
index daa86c81d..f60ec14eb 100644
--- a/pixman/test/affine-test.c
+++ b/pixman/test/affine-test.c
@@ -48,18 +48,18 @@ test_composite (int testnum,
uint32_t crc32;
FLOAT_REGS_CORRUPTION_DETECTOR_START ();
- lcg_srand (testnum);
+ prng_srand (testnum);
- src_bpp = (lcg_rand_n (2) == 0) ? 2 : 4;
- dst_bpp = (lcg_rand_n (2) == 0) ? 2 : 4;
- op = (lcg_rand_n (2) == 0) ? PIXMAN_OP_SRC : PIXMAN_OP_OVER;
+ src_bpp = (prng_rand_n (2) == 0) ? 2 : 4;
+ dst_bpp = (prng_rand_n (2) == 0) ? 2 : 4;
+ op = (prng_rand_n (2) == 0) ? PIXMAN_OP_SRC : PIXMAN_OP_OVER;
- src_width = lcg_rand_n (MAX_SRC_WIDTH) + 1;
- src_height = lcg_rand_n (MAX_SRC_HEIGHT) + 1;
- dst_width = lcg_rand_n (MAX_DST_WIDTH) + 1;
- dst_height = lcg_rand_n (MAX_DST_HEIGHT) + 1;
- src_stride = src_width * src_bpp + lcg_rand_n (MAX_STRIDE) * src_bpp;
- dst_stride = dst_width * dst_bpp + lcg_rand_n (MAX_STRIDE) * dst_bpp;
+ src_width = prng_rand_n (MAX_SRC_WIDTH) + 1;
+ src_height = prng_rand_n (MAX_SRC_HEIGHT) + 1;
+ dst_width = prng_rand_n (MAX_DST_WIDTH) + 1;
+ dst_height = prng_rand_n (MAX_DST_HEIGHT) + 1;
+ src_stride = src_width * src_bpp + prng_rand_n (MAX_STRIDE) * src_bpp;
+ dst_stride = dst_width * dst_bpp + prng_rand_n (MAX_STRIDE) * dst_bpp;
if (src_stride & 3)
src_stride += 2;
@@ -67,26 +67,23 @@ test_composite (int testnum,
if (dst_stride & 3)
dst_stride += 2;
- src_x = -(src_width / 4) + lcg_rand_n (src_width * 3 / 2);
- src_y = -(src_height / 4) + lcg_rand_n (src_height * 3 / 2);
- dst_x = -(dst_width / 4) + lcg_rand_n (dst_width * 3 / 2);
- dst_y = -(dst_height / 4) + lcg_rand_n (dst_height * 3 / 2);
- w = lcg_rand_n (dst_width * 3 / 2 - dst_x);
- h = lcg_rand_n (dst_height * 3 / 2 - dst_y);
+ src_x = -(src_width / 4) + prng_rand_n (src_width * 3 / 2);
+ src_y = -(src_height / 4) + prng_rand_n (src_height * 3 / 2);
+ dst_x = -(dst_width / 4) + prng_rand_n (dst_width * 3 / 2);
+ dst_y = -(dst_height / 4) + prng_rand_n (dst_height * 3 / 2);
+ w = prng_rand_n (dst_width * 3 / 2 - dst_x);
+ h = prng_rand_n (dst_height * 3 / 2 - dst_y);
srcbuf = (uint32_t *)malloc (src_stride * src_height);
dstbuf = (uint32_t *)malloc (dst_stride * dst_height);
- for (i = 0; i < src_stride * src_height; i++)
- *((uint8_t *)srcbuf + i) = lcg_rand_n (256);
+ prng_randmemset (srcbuf, src_stride * src_height, 0);
+ prng_randmemset (dstbuf, dst_stride * dst_height, 0);
- for (i = 0; i < dst_stride * dst_height; i++)
- *((uint8_t *)dstbuf + i) = lcg_rand_n (256);
-
- src_fmt = src_bpp == 4 ? (lcg_rand_n (2) == 0 ?
+ src_fmt = src_bpp == 4 ? (prng_rand_n (2) == 0 ?
PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8) : PIXMAN_r5g6b5;
- dst_fmt = dst_bpp == 4 ? (lcg_rand_n (2) == 0 ?
+ dst_fmt = dst_bpp == 4 ? (prng_rand_n (2) == 0 ?
PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8) : PIXMAN_r5g6b5;
src_img = pixman_image_create_bits (
@@ -100,29 +97,29 @@ test_composite (int testnum,
pixman_transform_init_identity (&transform);
- if (lcg_rand_n (3) > 0)
+ if (prng_rand_n (3) > 0)
{
- scale_x = -65536 * 3 + lcg_rand_N (65536 * 6);
- if (lcg_rand_n (2))
- scale_y = -65536 * 3 + lcg_rand_N (65536 * 6);
+ scale_x = -65536 * 3 + prng_rand_n (65536 * 6);
+ if (prng_rand_n (2))
+ scale_y = -65536 * 3 + prng_rand_n (65536 * 6);
else
scale_y = scale_x;
pixman_transform_init_scale (&transform, scale_x, scale_y);
}
- if (lcg_rand_n (3) > 0)
+ if (prng_rand_n (3) > 0)
{
- translate_x = -65536 * 3 + lcg_rand_N (6 * 65536);
- if (lcg_rand_n (2))
- translate_y = -65536 * 3 + lcg_rand_N (6 * 65536);
+ translate_x = -65536 * 3 + prng_rand_n (6 * 65536);
+ if (prng_rand_n (2))
+ translate_y = -65536 * 3 + prng_rand_n (6 * 65536);
else
translate_y = translate_x;
pixman_transform_translate (&transform, NULL, translate_x, translate_y);
}
- if (lcg_rand_n (4) > 0)
+ if (prng_rand_n (4) > 0)
{
int c, s, tx = 0, ty = 0;
- switch (lcg_rand_n (4))
+ switch (prng_rand_n (4))
{
case 0:
/* 90 degrees */
@@ -145,32 +142,32 @@ test_composite (int testnum,
break;
default:
/* arbitrary rotation */
- c = lcg_rand_N (2 * 65536) - 65536;
- s = lcg_rand_N (2 * 65536) - 65536;
+ c = prng_rand_n (2 * 65536) - 65536;
+ s = prng_rand_n (2 * 65536) - 65536;
break;
}
pixman_transform_rotate (&transform, NULL, c, s);
pixman_transform_translate (&transform, NULL, tx, ty);
}
- if (lcg_rand_n (8) == 0)
+ if (prng_rand_n (8) == 0)
{
/* Flip random bits */
int maxflipcount = 8;
while (maxflipcount--)
{
- int i = lcg_rand_n (2);
- int j = lcg_rand_n (3);
- int bitnum = lcg_rand_n (32);
+ int i = prng_rand_n (2);
+ int j = prng_rand_n (3);
+ int bitnum = prng_rand_n (32);
transform.matrix[i][j] ^= 1 << bitnum;
- if (lcg_rand_n (2))
+ if (prng_rand_n (2))
break;
}
}
pixman_image_set_transform (src_img, &transform);
- switch (lcg_rand_n (4))
+ switch (prng_rand_n (4))
{
case 0:
repeat = PIXMAN_REPEAT_NONE;
@@ -193,7 +190,7 @@ test_composite (int testnum,
}
pixman_image_set_repeat (src_img, repeat);
- if (lcg_rand_n (2))
+ if (prng_rand_n (2))
pixman_image_set_filter (src_img, PIXMAN_FILTER_NEAREST, NULL, 0);
else
pixman_image_set_filter (src_img, PIXMAN_FILTER_BILINEAR, NULL, 0);
@@ -220,19 +217,19 @@ test_composite (int testnum,
printf ("w=%d, h=%d\n", w, h);
}
- if (lcg_rand_n (8) == 0)
+ if (prng_rand_n (8) == 0)
{
pixman_box16_t clip_boxes[2];
- int n = lcg_rand_n (2) + 1;
+ int n = prng_rand_n (2) + 1;
for (i = 0; i < n; i++)
{
- clip_boxes[i].x1 = lcg_rand_n (src_width);
- clip_boxes[i].y1 = lcg_rand_n (src_height);
+ clip_boxes[i].x1 = prng_rand_n (src_width);
+ clip_boxes[i].y1 = prng_rand_n (src_height);
clip_boxes[i].x2 =
- clip_boxes[i].x1 + lcg_rand_n (src_width - clip_boxes[i].x1);
+ clip_boxes[i].x1 + prng_rand_n (src_width - clip_boxes[i].x1);
clip_boxes[i].y2 =
- clip_boxes[i].y1 + lcg_rand_n (src_height - clip_boxes[i].y1);
+ clip_boxes[i].y1 + prng_rand_n (src_height - clip_boxes[i].y1);
if (verbose)
{
@@ -248,18 +245,18 @@ test_composite (int testnum,
pixman_region_fini (&clip);
}
- if (lcg_rand_n (8) == 0)
+ if (prng_rand_n (8) == 0)
{
pixman_box16_t clip_boxes[2];
- int n = lcg_rand_n (2) + 1;
+ int n = prng_rand_n (2) + 1;
for (i = 0; i < n; i++)
{
- clip_boxes[i].x1 = lcg_rand_n (dst_width);
- clip_boxes[i].y1 = lcg_rand_n (dst_height);
+ clip_boxes[i].x1 = prng_rand_n (dst_width);
+ clip_boxes[i].y1 = prng_rand_n (dst_height);
clip_boxes[i].x2 =
- clip_boxes[i].x1 + lcg_rand_n (dst_width - clip_boxes[i].x1);
+ clip_boxes[i].x1 + prng_rand_n (dst_width - clip_boxes[i].x1);
clip_boxes[i].y2 =
- clip_boxes[i].y1 + lcg_rand_n (dst_height - clip_boxes[i].y1);
+ clip_boxes[i].y1 + prng_rand_n (dst_height - clip_boxes[i].y1);
if (verbose)
{
@@ -310,11 +307,11 @@ test_composite (int testnum,
}
#if BILINEAR_INTERPOLATION_BITS == 8
-#define CHECKSUM 0x344413F0
+#define CHECKSUM 0x97097336
#elif BILINEAR_INTERPOLATION_BITS == 7
-#define CHECKSUM 0xC8181A76
+#define CHECKSUM 0x31D2DC21
#elif BILINEAR_INTERPOLATION_BITS == 4
-#define CHECKSUM 0xD672A457
+#define CHECKSUM 0x8B925154
#else
#define CHECKSUM 0x00000000
#endif
diff --git a/pixman/test/alpha-loop.c b/pixman/test/alpha-loop.c
index e4d90a988..eca761537 100644
--- a/pixman/test/alpha-loop.c
+++ b/pixman/test/alpha-loop.c
@@ -8,9 +8,14 @@
int
main (int argc, char **argv)
{
- uint8_t *alpha = make_random_bytes (WIDTH * HEIGHT);
- uint32_t *src = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * 4);
- uint32_t *dest = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * 4);
+ uint8_t *alpha;
+ uint32_t *src, *dest;
+
+ prng_srand (0);
+
+ alpha = make_random_bytes (WIDTH * HEIGHT);
+ src = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * 4);
+ dest = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * 4);
pixman_image_t *a = pixman_image_create_bits (PIXMAN_a8, WIDTH, HEIGHT, (uint32_t *)alpha, WIDTH);
pixman_image_t *d = pixman_image_create_bits (PIXMAN_a8r8g8b8, WIDTH, HEIGHT, dest, WIDTH * 4);
diff --git a/pixman/test/alphamap.c b/pixman/test/alphamap.c
index 0c5757ea3..1a6fca55a 100644
--- a/pixman/test/alphamap.c
+++ b/pixman/test/alphamap.c
@@ -307,6 +307,8 @@ main (int argc, char **argv)
{
int i, j, a, b, x, y;
+ prng_srand (0);
+
for (i = 0; i < ARRAY_LENGTH (formats); ++i)
{
for (j = 0; j < ARRAY_LENGTH (formats); ++j)
diff --git a/pixman/test/blitters-test.c b/pixman/test/blitters-test.c
index 30d69124c..9bde99c62 100644
--- a/pixman/test/blitters-test.c
+++ b/pixman/test/blitters-test.c
@@ -25,7 +25,7 @@ create_random_image (pixman_format_code_t *allowed_formats,
int max_extra_stride,
pixman_format_code_t *used_fmt)
{
- int n = 0, i, width, height, stride;
+ int n = 0, width, height, stride;
pixman_format_code_t fmt;
uint32_t *buf;
pixman_image_t *img;
@@ -33,28 +33,20 @@ create_random_image (pixman_format_code_t *allowed_formats,
while (allowed_formats[n] != PIXMAN_null)
n++;
- if (n > N_MOST_LIKELY_FORMATS && lcg_rand_n (4) != 0)
+ if (n > N_MOST_LIKELY_FORMATS && prng_rand_n (4) != 0)
n = N_MOST_LIKELY_FORMATS;
- fmt = allowed_formats[lcg_rand_n (n)];
+ fmt = allowed_formats[prng_rand_n (n)];
- width = lcg_rand_n (max_width) + 1;
- height = lcg_rand_n (max_height) + 1;
+ width = prng_rand_n (max_width) + 1;
+ height = prng_rand_n (max_height) + 1;
stride = (width * PIXMAN_FORMAT_BPP (fmt) + 7) / 8 +
- lcg_rand_n (max_extra_stride + 1);
+ prng_rand_n (max_extra_stride + 1);
stride = (stride + 3) & ~3;
/* do the allocation */
buf = aligned_malloc (64, stride * height);
- /* initialize image with random data */
- for (i = 0; i < stride * height; i++)
- {
- /* generation is biased to having more 0 or 255 bytes as
- * they are more likely to be special-cased in code
- */
- *((uint8_t *)buf + i) = lcg_rand_n (4) ? lcg_rand_n (256) :
- (lcg_rand_n (2) ? 0 : 255);
- }
+ prng_randmemset (buf, stride * height, RANDMEMSET_MORE_00_AND_FF);
img = pixman_image_create_bits (fmt, width, height, buf, stride);
@@ -67,7 +59,7 @@ create_random_image (pixman_format_code_t *allowed_formats,
pixman_image_set_indexed (img, &(y_palette[PIXMAN_FORMAT_BPP (fmt)]));
}
- if (lcg_rand_n (16) == 0)
+ if (prng_rand_n (16) == 0)
pixman_image_set_filter (img, PIXMAN_FILTER_BILINEAR, NULL, 0);
image_endian_swap (img);
@@ -251,11 +243,11 @@ test_composite (int testnum, int verbose)
if (max_extra_stride > 8)
max_extra_stride = 8;
- lcg_srand (testnum);
+ prng_srand (testnum);
- op = op_list[lcg_rand_n (ARRAY_LENGTH (op_list))];
+ op = op_list[prng_rand_n (ARRAY_LENGTH (op_list))];
- if (lcg_rand_n (8))
+ if (prng_rand_n (8))
{
/* normal image */
src_img = create_random_image (img_fmt_list, max_width, max_height,
@@ -284,10 +276,10 @@ test_composite (int testnum, int verbose)
dstbuf = pixman_image_get_data (dst_img);
srcbuf = pixman_image_get_data (src_img);
- src_x = lcg_rand_n (src_width);
- src_y = lcg_rand_n (src_height);
- dst_x = lcg_rand_n (dst_width);
- dst_y = lcg_rand_n (dst_height);
+ src_x = prng_rand_n (src_width);
+ src_y = prng_rand_n (src_height);
+ dst_x = prng_rand_n (dst_width);
+ dst_y = prng_rand_n (dst_height);
mask_img = NULL;
mask_fmt = PIXMAN_null;
@@ -296,10 +288,10 @@ test_composite (int testnum, int verbose)
maskbuf = NULL;
if ((src_fmt == PIXMAN_x8r8g8b8 || src_fmt == PIXMAN_x8b8g8r8) &&
- (lcg_rand_n (4) == 0))
+ (prng_rand_n (4) == 0))
{
/* PIXBUF */
- mask_fmt = lcg_rand_n (2) ? PIXMAN_a8r8g8b8 : PIXMAN_a8b8g8r8;
+ mask_fmt = prng_rand_n (2) ? PIXMAN_a8r8g8b8 : PIXMAN_a8b8g8r8;
mask_img = pixman_image_create_bits (mask_fmt,
src_width,
src_height,
@@ -309,9 +301,9 @@ test_composite (int testnum, int verbose)
mask_y = src_y;
maskbuf = srcbuf;
}
- else if (lcg_rand_n (2))
+ else if (prng_rand_n (2))
{
- if (lcg_rand_n (2))
+ if (prng_rand_n (2))
{
mask_img = create_random_image (mask_fmt_list, max_width, max_height,
max_extra_stride, &mask_fmt);
@@ -324,16 +316,16 @@ test_composite (int testnum, int verbose)
pixman_image_set_repeat (mask_img, PIXMAN_REPEAT_NORMAL);
}
- if (lcg_rand_n (2))
+ if (prng_rand_n (2))
pixman_image_set_component_alpha (mask_img, 1);
- mask_x = lcg_rand_n (pixman_image_get_width (mask_img));
- mask_y = lcg_rand_n (pixman_image_get_height (mask_img));
+ mask_x = prng_rand_n (pixman_image_get_width (mask_img));
+ mask_y = prng_rand_n (pixman_image_get_height (mask_img));
}
- w = lcg_rand_n (dst_width - dst_x + 1);
- h = lcg_rand_n (dst_height - dst_y + 1);
+ w = prng_rand_n (dst_width - dst_x + 1);
+ h = prng_rand_n (dst_height - dst_y + 1);
if (verbose)
{
@@ -390,6 +382,8 @@ main (int argc, const char *argv[])
{
int i;
+ prng_srand (0);
+
for (i = 1; i <= 8; i++)
{
initialize_palette (&(rgb_palette[i]), i, TRUE);
@@ -397,6 +391,6 @@ main (int argc, const char *argv[])
}
return fuzzer_test_main("blitters", 2000000,
- 0x46136E0A,
+ 0xD8265D5E,
test_composite, argc, argv);
}
diff --git a/pixman/test/combiner-test.c b/pixman/test/combiner-test.c
index c438ae62e..01f63a56e 100644
--- a/pixman/test/combiner-test.c
+++ b/pixman/test/combiner-test.c
@@ -67,7 +67,7 @@ static const pixman_op_t op_list[] =
static float
rand_float (void)
{
- uint32_t u = lcg_rand_u32();
+ uint32_t u = prng_rand();
return *(float *)&u;
}
@@ -123,7 +123,7 @@ main ()
impl = _pixman_internal_only_get_implementation();
- lcg_srand (0);
+ prng_srand (0);
for (i = 0; i < ARRAY_LENGTH (op_list); ++i)
{
diff --git a/pixman/test/composite-traps-test.c b/pixman/test/composite-traps-test.c
index 9fc94a4d6..2983eae83 100644
--- a/pixman/test/composite-traps-test.c
+++ b/pixman/test/composite-traps-test.c
@@ -26,7 +26,7 @@ static pixman_op_t operators[] =
};
#define RANDOM_ELT(array) \
- ((array)[lcg_rand_n(ARRAY_LENGTH((array)))])
+ ((array)[prng_rand_n(ARRAY_LENGTH((array)))])
static void
destroy_bits (pixman_image_t *image, void *data)
@@ -37,7 +37,7 @@ destroy_bits (pixman_image_t *image, void *data)
static pixman_fixed_t
random_fixed (int n)
{
- return lcg_rand_N (n << 16);
+ return prng_rand_n (n << 16);
}
/*
@@ -75,17 +75,17 @@ test_composite (int testnum,
FLOAT_REGS_CORRUPTION_DETECTOR_START ();
- lcg_srand (testnum);
+ prng_srand (testnum);
op = RANDOM_ELT (operators);
mask_format = RANDOM_ELT (mask_formats);
/* Create source image */
- if (lcg_rand_n (4) == 0)
+ if (prng_rand_n (4) == 0)
{
src_img = pixman_image_create_solid_fill (
- &(colors[lcg_rand_n (ARRAY_LENGTH (colors))]));
+ &(colors[prng_rand_n (ARRAY_LENGTH (colors))]));
src_x = 10;
src_y = 234;
@@ -94,13 +94,13 @@ test_composite (int testnum,
{
pixman_format_code_t src_format = RANDOM_ELT(formats);
int src_bpp = (PIXMAN_FORMAT_BPP (src_format) + 7) / 8;
- int src_width = lcg_rand_n (MAX_SRC_WIDTH) + 1;
- int src_height = lcg_rand_n (MAX_SRC_HEIGHT) + 1;
- int src_stride = src_width * src_bpp + lcg_rand_n (MAX_STRIDE) * src_bpp;
+ int src_width = prng_rand_n (MAX_SRC_WIDTH) + 1;
+ int src_height = prng_rand_n (MAX_SRC_HEIGHT) + 1;
+ int src_stride = src_width * src_bpp + prng_rand_n (MAX_STRIDE) * src_bpp;
uint32_t *bits;
- src_x = -(src_width / 4) + lcg_rand_n (src_width * 3 / 2);
- src_y = -(src_height / 4) + lcg_rand_n (src_height * 3 / 2);
+ src_x = -(src_width / 4) + prng_rand_n (src_width * 3 / 2);
+ src_y = -(src_height / 4) + prng_rand_n (src_height * 3 / 2);
src_stride = (src_stride + 3) & ~3;
@@ -111,19 +111,19 @@ test_composite (int testnum,
pixman_image_set_destroy_function (src_img, destroy_bits, bits);
- if (lcg_rand_n (8) == 0)
+ if (prng_rand_n (8) == 0)
{
pixman_box16_t clip_boxes[2];
- int n = lcg_rand_n (2) + 1;
+ int n = prng_rand_n (2) + 1;
for (i = 0; i < n; i++)
{
- clip_boxes[i].x1 = lcg_rand_n (src_width);
- clip_boxes[i].y1 = lcg_rand_n (src_height);
+ clip_boxes[i].x1 = prng_rand_n (src_width);
+ clip_boxes[i].y1 = prng_rand_n (src_height);
clip_boxes[i].x2 =
- clip_boxes[i].x1 + lcg_rand_n (src_width - clip_boxes[i].x1);
+ clip_boxes[i].x1 + prng_rand_n (src_width - clip_boxes[i].x1);
clip_boxes[i].y2 =
- clip_boxes[i].y1 + lcg_rand_n (src_height - clip_boxes[i].y1);
+ clip_boxes[i].y1 + prng_rand_n (src_height - clip_boxes[i].y1);
if (verbose)
{
@@ -146,15 +146,15 @@ test_composite (int testnum,
{
dst_format = RANDOM_ELT(formats);
dst_bpp = (PIXMAN_FORMAT_BPP (dst_format) + 7) / 8;
- dst_width = lcg_rand_n (MAX_DST_WIDTH) + 1;
- dst_height = lcg_rand_n (MAX_DST_HEIGHT) + 1;
- dst_stride = dst_width * dst_bpp + lcg_rand_n (MAX_STRIDE) * dst_bpp;
+ dst_width = prng_rand_n (MAX_DST_WIDTH) + 1;
+ dst_height = prng_rand_n (MAX_DST_HEIGHT) + 1;
+ dst_stride = dst_width * dst_bpp + prng_rand_n (MAX_STRIDE) * dst_bpp;
dst_stride = (dst_stride + 3) & ~3;
dst_bits = (uint32_t *)make_random_bytes (dst_stride * dst_height);
- dst_x = -(dst_width / 4) + lcg_rand_n (dst_width * 3 / 2);
- dst_y = -(dst_height / 4) + lcg_rand_n (dst_height * 3 / 2);
+ dst_x = -(dst_width / 4) + prng_rand_n (dst_width * 3 / 2);
+ dst_y = -(dst_height / 4) + prng_rand_n (dst_height * 3 / 2);
dst_img = pixman_image_create_bits (
dst_format, dst_width, dst_height, dst_bits, dst_stride);
@@ -166,7 +166,7 @@ test_composite (int testnum,
{
int i;
- n_traps = lcg_rand_n (25);
+ n_traps = prng_rand_n (25);
traps = fence_malloc (n_traps * sizeof (pixman_trapezoid_t));
for (i = 0; i < n_traps; ++i)
@@ -186,18 +186,18 @@ test_composite (int testnum,
}
}
- if (lcg_rand_n (8) == 0)
+ if (prng_rand_n (8) == 0)
{
pixman_box16_t clip_boxes[2];
- int n = lcg_rand_n (2) + 1;
+ int n = prng_rand_n (2) + 1;
for (i = 0; i < n; i++)
{
- clip_boxes[i].x1 = lcg_rand_n (dst_width);
- clip_boxes[i].y1 = lcg_rand_n (dst_height);
+ clip_boxes[i].x1 = prng_rand_n (dst_width);
+ clip_boxes[i].y1 = prng_rand_n (dst_height);
clip_boxes[i].x2 =
- clip_boxes[i].x1 + lcg_rand_n (dst_width - clip_boxes[i].x1);
+ clip_boxes[i].x1 + prng_rand_n (dst_width - clip_boxes[i].x1);
clip_boxes[i].y2 =
- clip_boxes[i].y1 + lcg_rand_n (dst_height - clip_boxes[i].y1);
+ clip_boxes[i].y1 + prng_rand_n (dst_height - clip_boxes[i].y1);
if (verbose)
{
@@ -251,6 +251,6 @@ test_composite (int testnum,
int
main (int argc, const char *argv[])
{
- return fuzzer_test_main("composite traps", 40000, 0x33BFAA55,
+ return fuzzer_test_main("composite traps", 40000, 0x749BCC57,
test_composite, argc, argv);
}
diff --git a/pixman/test/composite.c b/pixman/test/composite.c
index 2930fb75b..09752c5c7 100644
--- a/pixman/test/composite.c
+++ b/pixman/test/composite.c
@@ -725,19 +725,19 @@ image_fini (image_t *info)
static int
random_size (void)
{
- return lcg_rand_n (ARRAY_LENGTH (sizes));
+ return prng_rand_n (ARRAY_LENGTH (sizes));
}
static int
random_color (void)
{
- return lcg_rand_n (ARRAY_LENGTH (colors));
+ return prng_rand_n (ARRAY_LENGTH (colors));
}
static int
random_format (void)
{
- return lcg_rand_n (ARRAY_LENGTH (formats));
+ return prng_rand_n (ARRAY_LENGTH (formats));
}
static pixman_bool_t
@@ -748,15 +748,15 @@ run_test (uint32_t seed)
int ca;
int ok;
- lcg_srand (seed);
+ prng_srand (seed);
image_init (&dst, random_color(), random_format(), 1);
image_init (&src, random_color(), random_format(), random_size());
image_init (&mask, random_color(), random_format(), random_size());
- op = &(operators [lcg_rand_n (ARRAY_LENGTH (operators))]);
+ op = &(operators [prng_rand_n (ARRAY_LENGTH (operators))]);
- ca = lcg_rand_n (3);
+ ca = prng_rand_n (3);
switch (ca)
{
diff --git a/pixman/test/glyph-test.c b/pixman/test/glyph-test.c
index 501cc2e6f..1811add73 100644
--- a/pixman/test/glyph-test.c
+++ b/pixman/test/glyph-test.c
@@ -107,7 +107,7 @@ random_format (const pixman_format_code_t *formats)
i = 0;
while (formats[i] != PIXMAN_null)
++i;
- return formats[lcg_rand_n (i)];
+ return formats[prng_rand_n (i)];
}
static pixman_image_t *
@@ -122,27 +122,27 @@ create_image (int max_size, const pixman_format_code_t *formats, uint32_t flags)
int i;
pixman_image_destroy_func_t destroy;
- if ((flags & ALLOW_SOLID) && lcg_rand_n (4) == 0)
+ if ((flags & ALLOW_SOLID) && prng_rand_n (4) == 0)
{
pixman_color_t color;
- color.alpha = lcg_rand_u32();
- color.red = lcg_rand_u32();
- color.green = lcg_rand_u32();
- color.blue = lcg_rand_u32();
+ color.alpha = prng_rand();
+ color.red = prng_rand();
+ color.green = prng_rand();
+ color.blue = prng_rand();
return pixman_image_create_solid_fill (&color);
}
- width = lcg_rand_n (max_size) + 1;
- height = lcg_rand_n (max_size) + 1;
+ width = prng_rand_n (max_size) + 1;
+ height = prng_rand_n (max_size) + 1;
format = random_format (formats);
bpp = PIXMAN_FORMAT_BPP (format);
- stride = (width * bpp + 7) / 8 + lcg_rand_n (17);
+ stride = (width * bpp + 7) / 8 + prng_rand_n (17);
stride = (stride + 3) & ~3;
- if (lcg_rand_n (64) == 0)
+ if (prng_rand_n (64) == 0)
{
if (!(data = (uint32_t *)make_random_bytes (stride * height)))
{
@@ -153,34 +153,28 @@ create_image (int max_size, const pixman_format_code_t *formats, uint32_t flags)
}
else
{
- uint8_t *d8;
-
data = malloc (stride * height);
-
- d8 = (uint8_t *)data;
- for (i = 0; i < height * stride; ++i)
- d8[i] = lcg_rand_n (256);
-
+ prng_randmemset (data, height * stride, 0);
destroy = destroy_malloced;
}
image = pixman_image_create_bits (format, width, height, data, stride);
pixman_image_set_destroy_function (image, destroy, data);
- if ((flags & ALLOW_CLIPPED) && lcg_rand_n (8) == 0)
+ if ((flags & ALLOW_CLIPPED) && prng_rand_n (8) == 0)
{
pixman_box16_t clip_boxes[8];
pixman_region16_t clip;
- int n = lcg_rand_n (8) + 1;
+ int n = prng_rand_n (8) + 1;
for (i = 0; i < n; i++)
{
- clip_boxes[i].x1 = lcg_rand_n (width);
- clip_boxes[i].y1 = lcg_rand_n (height);
+ clip_boxes[i].x1 = prng_rand_n (width);
+ clip_boxes[i].y1 = prng_rand_n (height);
clip_boxes[i].x2 =
- clip_boxes[i].x1 + lcg_rand_n (width - clip_boxes[i].x1);
+ clip_boxes[i].x1 + prng_rand_n (width - clip_boxes[i].x1);
clip_boxes[i].y2 =
- clip_boxes[i].y1 + lcg_rand_n (height - clip_boxes[i].y1);
+ clip_boxes[i].y1 + prng_rand_n (height - clip_boxes[i].y1);
}
pixman_region_init_rects (&clip, clip_boxes, n);
@@ -188,27 +182,27 @@ create_image (int max_size, const pixman_format_code_t *formats, uint32_t flags)
pixman_region_fini (&clip);
}
- if ((flags & ALLOW_SOURCE_CLIPPING) && lcg_rand_n (4) == 0)
+ if ((flags & ALLOW_SOURCE_CLIPPING) && prng_rand_n (4) == 0)
{
pixman_image_set_source_clipping (image, TRUE);
pixman_image_set_has_client_clip (image, TRUE);
}
- if ((flags & ALLOW_ALPHA_MAP) && lcg_rand_n (16) == 0)
+ if ((flags & ALLOW_ALPHA_MAP) && prng_rand_n (16) == 0)
{
pixman_image_t *alpha_map;
int alpha_x, alpha_y;
- alpha_x = lcg_rand_n (width);
- alpha_y = lcg_rand_n (height);
+ alpha_x = prng_rand_n (width);
+ alpha_y = prng_rand_n (height);
alpha_map =
create_image (max_size, formats, (flags & ~(ALLOW_ALPHA_MAP | ALLOW_SOLID)));
pixman_image_set_alpha_map (image, alpha_map, alpha_x, alpha_y);
pixman_image_unref (alpha_map);
}
- if ((flags & ALLOW_REPEAT) && lcg_rand_n (2) == 0)
- pixman_image_set_repeat (image, lcg_rand_n (4));
+ if ((flags & ALLOW_REPEAT) && prng_rand_n (2) == 0)
+ pixman_image_set_repeat (image, prng_rand_n (4));
image_endian_swap (image);
@@ -230,7 +224,7 @@ test_glyphs (int testnum, int verbose)
int n_glyphs, i;
pixman_glyph_cache_t *cache;
- lcg_srand (testnum);
+ prng_srand (testnum);
cache = pixman_glyph_cache_create ();
@@ -245,13 +239,13 @@ test_glyphs (int testnum, int verbose)
pixman_glyph_cache_freeze (cache);
- n_glyphs = lcg_rand_n (MAX_GLYPHS);
+ n_glyphs = prng_rand_n (MAX_GLYPHS);
for (i = 0; i < n_glyphs; ++i)
glyph_images[i] = create_image (32, glyph_formats, 0);
for (i = 0; i < 4 * n_glyphs; ++i)
{
- int g = lcg_rand_n (n_glyphs);
+ int g = prng_rand_n (n_glyphs);
pixman_image_t *glyph_img = glyph_images[g];
void *key1 = KEY1 (glyph_img);
void *key2 = KEY2 (glyph_img);
@@ -264,21 +258,21 @@ test_glyphs (int testnum, int verbose)
}
glyphs[i].glyph = glyph;
- glyphs[i].x = lcg_rand_n (128);
- glyphs[i].y = lcg_rand_n (128);
+ glyphs[i].x = prng_rand_n (128);
+ glyphs[i].y = prng_rand_n (128);
}
- if (lcg_rand_n (2) == 0)
+ if (prng_rand_n (2) == 0)
{
- int src_x = lcg_rand_n (300) - 150;
- int src_y = lcg_rand_n (300) - 150;
- int mask_x = lcg_rand_n (64) - 32;
- int mask_y = lcg_rand_n (64) - 32;
- int dest_x = lcg_rand_n (64) - 32;
- int dest_y = lcg_rand_n (64) - 32;
- int width = lcg_rand_n (64);
- int height = lcg_rand_n (64);
- pixman_op_t op = operators[lcg_rand_n (ARRAY_LENGTH (operators))];
+ int src_x = prng_rand_n (300) - 150;
+ int src_y = prng_rand_n (300) - 150;
+ int mask_x = prng_rand_n (64) - 32;
+ int mask_y = prng_rand_n (64) - 32;
+ int dest_x = prng_rand_n (64) - 32;
+ int dest_y = prng_rand_n (64) - 32;
+ int width = prng_rand_n (64);
+ int height = prng_rand_n (64);
+ pixman_op_t op = operators[prng_rand_n (ARRAY_LENGTH (operators))];
pixman_format_code_t format = random_format (glyph_formats);
pixman_composite_glyphs (
@@ -292,11 +286,11 @@ test_glyphs (int testnum, int verbose)
}
else
{
- pixman_op_t op = operators[lcg_rand_n (ARRAY_LENGTH (operators))];
- int src_x = lcg_rand_n (300) - 150;
- int src_y = lcg_rand_n (300) - 150;
- int dest_x = lcg_rand_n (64) - 32;
- int dest_y = lcg_rand_n (64) - 32;
+ pixman_op_t op = operators[prng_rand_n (ARRAY_LENGTH (operators))];
+ int src_x = prng_rand_n (300) - 150;
+ int src_y = prng_rand_n (300) - 150;
+ int dest_x = prng_rand_n (64) - 32;
+ int dest_y = prng_rand_n (64) - 32;
pixman_composite_glyphs_no_mask (
op, source, dest,
@@ -333,6 +327,6 @@ int
main (int argc, const char *argv[])
{
return fuzzer_test_main ("glyph", 30000,
- 0x79E74996,
+ 0xFA478A79,
test_glyphs, argc, argv);
}
diff --git a/pixman/test/prng-test.c b/pixman/test/prng-test.c
new file mode 100644
index 000000000..0a3ad5e8f
--- /dev/null
+++ b/pixman/test/prng-test.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright © 2012 Siarhei Siamashka <siarhei.siamashka@gmail.com>
+ *
+ * Based on the public domain implementation of small noncryptographic PRNG
+ * authored by Bob Jenkins: http://burtleburtle.net/bob/rand/smallprng.html
+ *
+ * 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 <assert.h>
+#include <stdlib.h>
+#include "utils-prng.h"
+#include "utils.h"
+
+/* The original code from http://www.burtleburtle.net/bob/rand/smallprng.html */
+
+typedef uint32_t u4;
+typedef struct ranctx { u4 a; u4 b; u4 c; u4 d; } ranctx;
+
+#define rot(x,k) (((x)<<(k))|((x)>>(32-(k))))
+u4 ranval( ranctx *x ) {
+ u4 e = x->a - rot(x->b, 27);
+ x->a = x->b ^ rot(x->c, 17);
+ x->b = x->c + x->d;
+ x->c = x->d + e;
+ x->d = e + x->a;
+ return x->d;
+}
+
+void raninit( ranctx *x, u4 seed ) {
+ u4 i;
+ x->a = 0xf1ea5eed, x->b = x->c = x->d = seed;
+ for (i=0; i<20; ++i) {
+ (void)ranval(x);
+ }
+}
+
+/*****************************************************************************/
+
+#define BUFSIZE (8 * 1024 * 1024)
+#define N 50
+
+void bench (void)
+{
+ double t1, t2;
+ int i;
+ prng_t prng;
+ uint8_t *buf = aligned_malloc (16, BUFSIZE + 1);
+
+ prng_srand_r (&prng, 1234);
+ t1 = gettime();
+ for (i = 0; i < N; i++)
+ prng_randmemset_r (&prng, buf, BUFSIZE, 0);
+ t2 = gettime();
+ printf ("aligned randmemset : %.2f MB/s\n",
+ (double)BUFSIZE * N / 1000000. / (t2 - t1));
+
+ t1 = gettime();
+ for (i = 0; i < N; i++)
+ prng_randmemset_r (&prng, buf + 1, BUFSIZE, 0);
+ t2 = gettime();
+ printf ("unaligned randmemset : %.2f MB/s\n",
+ (double)BUFSIZE * N / 1000000. / (t2 - t1));
+
+ t1 = gettime();
+ for (i = 0; i < N; i++)
+ {
+ prng_randmemset_r (&prng, buf, BUFSIZE, RANDMEMSET_MORE_00_AND_FF);
+ }
+ t2 = gettime ();
+ printf ("aligned randmemset (more 00 and FF) : %.2f MB/s\n",
+ (double)BUFSIZE * N / 1000000. / (t2 - t1));
+
+ t1 = gettime();
+ for (i = 0; i < N; i++)
+ {
+ prng_randmemset_r (&prng, buf + 1, BUFSIZE, RANDMEMSET_MORE_00_AND_FF);
+ }
+ t2 = gettime ();
+ printf ("unaligned randmemset (more 00 and FF) : %.2f MB/s\n",
+ (double)BUFSIZE * N / 1000000. / (t2 - t1));
+
+ free (buf);
+}
+
+#define SMALLBUFSIZE 100
+
+int main (int argc, char *argv[])
+{
+ const uint32_t ref_crc[RANDMEMSET_MORE_00_AND_FF + 1] =
+ {
+ 0xBA06763D, 0x103FC550, 0x8B59ABA5, 0xD82A0F39
+ };
+ uint32_t crc1, crc2;
+ uint32_t ref, seed, seed0, seed1, seed2, seed3;
+ prng_rand_128_data_t buf;
+ uint8_t *bytebuf = aligned_malloc(16, SMALLBUFSIZE + 1);
+ ranctx x;
+ prng_t prng;
+ prng_randmemset_flags_t flags;
+
+ if (argc > 1 && strcmp(argv[1], "-bench") == 0)
+ {
+ bench ();
+ return 0;
+ }
+
+ /* basic test */
+ raninit (&x, 0);
+ prng_srand_r (&prng, 0);
+ assert (ranval (&x) == prng_rand_r (&prng));
+
+ /* test for simd code */
+ seed = 0;
+ prng_srand_r (&prng, seed);
+ seed0 = (seed = seed * 1103515245 + 12345);
+ seed1 = (seed = seed * 1103515245 + 12345);
+ seed2 = (seed = seed * 1103515245 + 12345);
+ seed3 = (seed = seed * 1103515245 + 12345);
+ prng_rand_128_r (&prng, &buf);
+
+ raninit (&x, seed0);
+ ref = ranval (&x);
+ assert (ref == buf.w[0]);
+
+ raninit (&x, seed1);
+ ref = ranval (&x);
+ assert (ref == buf.w[1]);
+
+ raninit (&x, seed2);
+ ref = ranval (&x);
+ assert (ref == buf.w[2]);
+
+ raninit (&x, seed3);
+ ref = ranval (&x);
+ assert (ref == buf.w[3]);
+
+ /* test for randmemset */
+ for (flags = 0; flags <= RANDMEMSET_MORE_00_AND_FF; flags++)
+ {
+ prng_srand_r (&prng, 1234);
+ prng_randmemset_r (&prng, bytebuf, 16, flags);
+ prng_randmemset_r (&prng, bytebuf + 16, SMALLBUFSIZE - 17, flags);
+ crc1 = compute_crc32 (0, bytebuf, SMALLBUFSIZE - 1);
+ prng_srand_r (&prng, 1234);
+ prng_randmemset_r (&prng, bytebuf + 1, SMALLBUFSIZE - 1, flags);
+ crc2 = compute_crc32 (0, bytebuf + 1, SMALLBUFSIZE - 1);
+ assert (ref_crc[flags] == crc1);
+ assert (ref_crc[flags] == crc2);
+ }
+
+ free (bytebuf);
+
+ return 0;
+}
diff --git a/pixman/test/region-contains-test.c b/pixman/test/region-contains-test.c
index 9524e2888..096e65179 100644
--- a/pixman/test/region-contains-test.c
+++ b/pixman/test/region-contains-test.c
@@ -9,16 +9,16 @@ make_random_region (pixman_region32_t *region)
pixman_region32_init (region);
- n_boxes = lcg_rand_n (64);
+ n_boxes = prng_rand_n (64);
while (n_boxes--)
{
int32_t x, y;
uint32_t w, h;
- x = (int32_t)lcg_rand_u32() >> 2;
- y = (int32_t)lcg_rand_u32() >> 2;
- w = lcg_rand_u32() >> 2;
- h = lcg_rand_u32() >> 2;
+ x = (int32_t)prng_rand() >> 2;
+ y = (int32_t)prng_rand() >> 2;
+ w = prng_rand() >> 2;
+ h = prng_rand() >> 2;
pixman_region32_union_rect (region, region, x, y, w, h);
}
@@ -37,12 +37,12 @@ random_coord (pixman_region32_t *region, pixman_bool_t x)
int n_boxes;
int begin, end;
- if (lcg_rand_n (14))
+ if (prng_rand_n (14))
{
bb = pixman_region32_rectangles (region, &n_boxes);
if (n_boxes == 0)
goto use_extent;
- b = bb + lcg_rand_n (n_boxes);
+ b = bb + prng_rand_n (n_boxes);
}
else
{
@@ -62,12 +62,12 @@ random_coord (pixman_region32_t *region, pixman_bool_t x)
end = b->y2;
}
- switch (lcg_rand_n (5))
+ switch (prng_rand_n (5))
{
case 0:
- return begin - lcg_rand_u32();
+ return begin - prng_rand();
case 1:
- return end + lcg_rand_u32 ();
+ return end + prng_rand ();
case 2:
return end;
case 3:
@@ -111,14 +111,14 @@ test_region_contains_rectangle (int i, int verbose)
pixman_region32_t region;
uint32_t r, r1, r2, r3, r4, crc32;
- lcg_srand (i);
+ prng_srand (i);
make_random_region (&region);
box.x1 = random_coord (&region, TRUE);
- box.x2 = box.x1 + lcg_rand_u32 ();
+ box.x2 = box.x1 + prng_rand ();
box.y1 = random_coord (&region, FALSE);
- box.y2 = box.y1 + lcg_rand_u32 ();
+ box.y2 = box.y1 + prng_rand ();
if (verbose)
{
@@ -163,7 +163,7 @@ main (int argc, const char *argv[])
{
return fuzzer_test_main ("region_contains",
1000000,
- 0xD2BF8C73,
+ 0x548E0F3F,
test_region_contains_rectangle,
argc, argv);
}
diff --git a/pixman/test/region-test.c b/pixman/test/region-test.c
index 9d5a41eb9..bfc219bc7 100644
--- a/pixman/test/region-test.c
+++ b/pixman/test/region-test.c
@@ -32,6 +32,8 @@ main ()
0xffff
};
+ prng_srand (0);
+
/* This used to go into an infinite loop before pixman-region.c
* was fixed to not use explict "short" variables
*/
@@ -91,10 +93,10 @@ main ()
/* Add some random rectangles */
for (j = 0; j < 64; j++)
pixman_region32_union_rect (&r1, &r1,
- lcg_rand_n (image_size),
- lcg_rand_n (image_size),
- lcg_rand_n (25),
- lcg_rand_n (25));
+ prng_rand_n (image_size),
+ prng_rand_n (image_size),
+ prng_rand_n (25),
+ prng_rand_n (25));
/* Clip to image size */
pixman_region32_init_rect (&r2, 0, 0, image_size, image_size);
diff --git a/pixman/test/rotate-test.c b/pixman/test/rotate-test.c
index a0488ef22..9d2a620cb 100644
--- a/pixman/test/rotate-test.c
+++ b/pixman/test/rotate-test.c
@@ -43,13 +43,13 @@ static const pixman_transform_t transforms[] =
};
#define RANDOM_FORMAT() \
- (formats[lcg_rand_n (ARRAY_LENGTH (formats))])
+ (formats[prng_rand_n (ARRAY_LENGTH (formats))])
#define RANDOM_OP() \
- (ops[lcg_rand_n (ARRAY_LENGTH (ops))])
+ (ops[prng_rand_n (ARRAY_LENGTH (ops))])
#define RANDOM_TRANSFORM() \
- (&(transforms[lcg_rand_n (ARRAY_LENGTH (transforms))]))
+ (&(transforms[prng_rand_n (ARRAY_LENGTH (transforms))]))
static void
on_destroy (pixman_image_t *image, void *data)
@@ -63,10 +63,8 @@ make_image (void)
pixman_format_code_t format = RANDOM_FORMAT();
uint32_t *bytes = malloc (WIDTH * HEIGHT * 4);
pixman_image_t *image;
- int i;
- for (i = 0; i < WIDTH * HEIGHT * 4; ++i)
- ((uint8_t *)bytes)[i] = lcg_rand_n (256);
+ prng_randmemset (bytes, WIDTH * HEIGHT * 4, 0);
image = pixman_image_create_bits (
format, WIDTH, HEIGHT, bytes, WIDTH * 4);
@@ -86,7 +84,7 @@ test_transform (int testnum, int verbose)
pixman_image_t *src, *dest;
uint32_t crc;
- lcg_srand (testnum);
+ prng_srand (testnum);
src = make_image ();
dest = make_image ();
@@ -108,6 +106,6 @@ int
main (int argc, const char *argv[])
{
return fuzzer_test_main ("rotate", 15000,
- 0x5236FD9F,
+ 0xECF5E426,
test_transform, argc, argv);
}
diff --git a/pixman/test/scaling-helpers-test.c b/pixman/test/scaling-helpers-test.c
index 33ec47c85..cd5ace0b2 100644
--- a/pixman/test/scaling-helpers-test.c
+++ b/pixman/test/scaling-helpers-test.c
@@ -52,14 +52,15 @@ int
main (void)
{
int i;
+ prng_srand (0);
for (i = 0; i < 10000; i++)
{
int32_t left_pad1, left_tz1, width1, right_tz1, right_pad1;
int32_t left_pad2, left_tz2, width2, right_tz2, right_pad2;
- pixman_fixed_t vx = lcg_rand_N(10000 << 16) - (3000 << 16);
- int32_t width = lcg_rand_N(10000);
- int32_t source_image_width = lcg_rand_N(10000) + 1;
- pixman_fixed_t unit_x = lcg_rand_N(10 << 16) + 1;
+ pixman_fixed_t vx = prng_rand_n(10000 << 16) - (3000 << 16);
+ int32_t width = prng_rand_n(10000);
+ int32_t source_image_width = prng_rand_n(10000) + 1;
+ pixman_fixed_t unit_x = prng_rand_n(10 << 16) + 1;
width1 = width2 = width;
bilinear_pad_repeat_get_scanline_bounds_ref (source_image_width,
diff --git a/pixman/test/scaling-test.c b/pixman/test/scaling-test.c
index 035410333..64c12dd7c 100644
--- a/pixman/test/scaling-test.c
+++ b/pixman/test/scaling-test.c
@@ -26,7 +26,7 @@ get_format (int bpp)
{
if (bpp == 4)
{
- switch (lcg_rand_n (4))
+ switch (prng_rand_n (4))
{
default:
case 0:
@@ -80,11 +80,11 @@ test_composite (int testnum,
uint32_t crc32;
FLOAT_REGS_CORRUPTION_DETECTOR_START ();
- lcg_srand (testnum);
+ prng_srand (testnum);
- src_bpp = (lcg_rand_n (2) == 0) ? 2 : 4;
- dst_bpp = (lcg_rand_n (2) == 0) ? 2 : 4;
- switch (lcg_rand_n (3))
+ src_bpp = (prng_rand_n (2) == 0) ? 2 : 4;
+ dst_bpp = (prng_rand_n (2) == 0) ? 2 : 4;
+ switch (prng_rand_n (3))
{
case 0:
op = PIXMAN_OP_SRC;
@@ -97,24 +97,24 @@ test_composite (int testnum,
break;
}
- src_width = lcg_rand_n (MAX_SRC_WIDTH) + 1;
- src_height = lcg_rand_n (MAX_SRC_HEIGHT) + 1;
+ src_width = prng_rand_n (MAX_SRC_WIDTH) + 1;
+ src_height = prng_rand_n (MAX_SRC_HEIGHT) + 1;
- if (lcg_rand_n (2))
+ if (prng_rand_n (2))
{
- mask_width = lcg_rand_n (MAX_SRC_WIDTH) + 1;
- mask_height = lcg_rand_n (MAX_SRC_HEIGHT) + 1;
+ mask_width = prng_rand_n (MAX_SRC_WIDTH) + 1;
+ mask_height = prng_rand_n (MAX_SRC_HEIGHT) + 1;
}
else
{
mask_width = mask_height = 1;
}
- dst_width = lcg_rand_n (MAX_DST_WIDTH) + 1;
- dst_height = lcg_rand_n (MAX_DST_HEIGHT) + 1;
- src_stride = src_width * src_bpp + lcg_rand_n (MAX_STRIDE) * src_bpp;
- mask_stride = mask_width * mask_bpp + lcg_rand_n (MAX_STRIDE) * mask_bpp;
- dst_stride = dst_width * dst_bpp + lcg_rand_n (MAX_STRIDE) * dst_bpp;
+ dst_width = prng_rand_n (MAX_DST_WIDTH) + 1;
+ dst_height = prng_rand_n (MAX_DST_HEIGHT) + 1;
+ src_stride = src_width * src_bpp + prng_rand_n (MAX_STRIDE) * src_bpp;
+ mask_stride = mask_width * mask_bpp + prng_rand_n (MAX_STRIDE) * mask_bpp;
+ dst_stride = dst_width * dst_bpp + prng_rand_n (MAX_STRIDE) * dst_bpp;
if (src_stride & 3)
src_stride += 2;
@@ -127,27 +127,22 @@ test_composite (int testnum,
if (dst_stride & 3)
dst_stride += 2;
- src_x = -(src_width / 4) + lcg_rand_n (src_width * 3 / 2);
- src_y = -(src_height / 4) + lcg_rand_n (src_height * 3 / 2);
- mask_x = -(mask_width / 4) + lcg_rand_n (mask_width * 3 / 2);
- mask_y = -(mask_height / 4) + lcg_rand_n (mask_height * 3 / 2);
- dst_x = -(dst_width / 4) + lcg_rand_n (dst_width * 3 / 2);
- dst_y = -(dst_height / 4) + lcg_rand_n (dst_height * 3 / 2);
- w = lcg_rand_n (dst_width * 3 / 2 - dst_x);
- h = lcg_rand_n (dst_height * 3 / 2 - dst_y);
+ src_x = -(src_width / 4) + prng_rand_n (src_width * 3 / 2);
+ src_y = -(src_height / 4) + prng_rand_n (src_height * 3 / 2);
+ mask_x = -(mask_width / 4) + prng_rand_n (mask_width * 3 / 2);
+ mask_y = -(mask_height / 4) + prng_rand_n (mask_height * 3 / 2);
+ dst_x = -(dst_width / 4) + prng_rand_n (dst_width * 3 / 2);
+ dst_y = -(dst_height / 4) + prng_rand_n (dst_height * 3 / 2);
+ w = prng_rand_n (dst_width * 3 / 2 - dst_x);
+ h = prng_rand_n (dst_height * 3 / 2 - dst_y);
srcbuf = (uint32_t *)malloc (src_stride * src_height);
maskbuf = (uint32_t *)malloc (mask_stride * mask_height);
dstbuf = (uint32_t *)malloc (dst_stride * dst_height);
- for (i = 0; i < src_stride * src_height; i++)
- *((uint8_t *)srcbuf + i) = lcg_rand_n (256);
-
- for (i = 0; i < mask_stride * mask_height; i++)
- *((uint8_t *)maskbuf + i) = lcg_rand_n (256);
-
- for (i = 0; i < dst_stride * dst_height; i++)
- *((uint8_t *)dstbuf + i) = lcg_rand_n (256);
+ prng_randmemset (srcbuf, src_stride * src_height, 0);
+ prng_randmemset (maskbuf, mask_stride * mask_height, 0);
+ prng_randmemset (dstbuf, dst_stride * dst_height, 0);
src_fmt = get_format (src_bpp);
dst_fmt = get_format (dst_bpp);
@@ -164,29 +159,29 @@ test_composite (int testnum,
image_endian_swap (src_img);
image_endian_swap (dst_img);
- if (lcg_rand_n (4) > 0)
+ if (prng_rand_n (4) > 0)
{
- scale_x = -32768 * 3 + lcg_rand_N (65536 * 5);
- scale_y = -32768 * 3 + lcg_rand_N (65536 * 5);
- translate_x = lcg_rand_N (65536);
- translate_y = lcg_rand_N (65536);
+ scale_x = -32768 * 3 + prng_rand_n (65536 * 5);
+ scale_y = -32768 * 3 + prng_rand_n (65536 * 5);
+ translate_x = prng_rand_n (65536);
+ translate_y = prng_rand_n (65536);
pixman_transform_init_scale (&transform, scale_x, scale_y);
pixman_transform_translate (&transform, NULL, translate_x, translate_y);
pixman_image_set_transform (src_img, &transform);
}
- if (lcg_rand_n (2) > 0)
+ if (prng_rand_n (2) > 0)
{
- mask_scale_x = -32768 * 3 + lcg_rand_N (65536 * 5);
- mask_scale_y = -32768 * 3 + lcg_rand_N (65536 * 5);
- mask_translate_x = lcg_rand_N (65536);
- mask_translate_y = lcg_rand_N (65536);
+ mask_scale_x = -32768 * 3 + prng_rand_n (65536 * 5);
+ mask_scale_y = -32768 * 3 + prng_rand_n (65536 * 5);
+ mask_translate_x = prng_rand_n (65536);
+ mask_translate_y = prng_rand_n (65536);
pixman_transform_init_scale (&transform, mask_scale_x, mask_scale_y);
pixman_transform_translate (&transform, NULL, mask_translate_x, mask_translate_y);
pixman_image_set_transform (mask_img, &transform);
}
- switch (lcg_rand_n (4))
+ switch (prng_rand_n (4))
{
case 0:
mask_repeat = PIXMAN_REPEAT_NONE;
@@ -209,7 +204,7 @@ test_composite (int testnum,
}
pixman_image_set_repeat (mask_img, mask_repeat);
- switch (lcg_rand_n (4))
+ switch (prng_rand_n (4))
{
case 0:
repeat = PIXMAN_REPEAT_NONE;
@@ -232,12 +227,12 @@ test_composite (int testnum,
}
pixman_image_set_repeat (src_img, repeat);
- if (lcg_rand_n (2))
+ if (prng_rand_n (2))
pixman_image_set_filter (src_img, PIXMAN_FILTER_NEAREST, NULL, 0);
else
pixman_image_set_filter (src_img, PIXMAN_FILTER_BILINEAR, NULL, 0);
- if (lcg_rand_n (2))
+ if (prng_rand_n (2))
pixman_image_set_filter (mask_img, PIXMAN_FILTER_NEAREST, NULL, 0);
else
pixman_image_set_filter (mask_img, PIXMAN_FILTER_BILINEAR, NULL, 0);
@@ -256,19 +251,19 @@ test_composite (int testnum,
printf ("w=%d, h=%d\n", w, h);
}
- if (lcg_rand_n (8) == 0)
+ if (prng_rand_n (8) == 0)
{
pixman_box16_t clip_boxes[2];
- int n = lcg_rand_n (2) + 1;
+ int n = prng_rand_n (2) + 1;
for (i = 0; i < n; i++)
{
- clip_boxes[i].x1 = lcg_rand_n (src_width);
- clip_boxes[i].y1 = lcg_rand_n (src_height);
+ clip_boxes[i].x1 = prng_rand_n (src_width);
+ clip_boxes[i].y1 = prng_rand_n (src_height);
clip_boxes[i].x2 =
- clip_boxes[i].x1 + lcg_rand_n (src_width - clip_boxes[i].x1);
+ clip_boxes[i].x1 + prng_rand_n (src_width - clip_boxes[i].x1);
clip_boxes[i].y2 =
- clip_boxes[i].y1 + lcg_rand_n (src_height - clip_boxes[i].y1);
+ clip_boxes[i].y1 + prng_rand_n (src_height - clip_boxes[i].y1);
if (verbose)
{
@@ -284,19 +279,19 @@ test_composite (int testnum,
pixman_region_fini (&clip);
}
- if (lcg_rand_n (8) == 0)
+ if (prng_rand_n (8) == 0)
{
pixman_box16_t clip_boxes[2];
- int n = lcg_rand_n (2) + 1;
+ int n = prng_rand_n (2) + 1;
for (i = 0; i < n; i++)
{
- clip_boxes[i].x1 = lcg_rand_n (mask_width);
- clip_boxes[i].y1 = lcg_rand_n (mask_height);
+ clip_boxes[i].x1 = prng_rand_n (mask_width);
+ clip_boxes[i].y1 = prng_rand_n (mask_height);
clip_boxes[i].x2 =
- clip_boxes[i].x1 + lcg_rand_n (mask_width - clip_boxes[i].x1);
+ clip_boxes[i].x1 + prng_rand_n (mask_width - clip_boxes[i].x1);
clip_boxes[i].y2 =
- clip_boxes[i].y1 + lcg_rand_n (mask_height - clip_boxes[i].y1);
+ clip_boxes[i].y1 + prng_rand_n (mask_height - clip_boxes[i].y1);
if (verbose)
{
@@ -312,18 +307,18 @@ test_composite (int testnum,
pixman_region_fini (&clip);
}
- if (lcg_rand_n (8) == 0)
+ if (prng_rand_n (8) == 0)
{
pixman_box16_t clip_boxes[2];
- int n = lcg_rand_n (2) + 1;
+ int n = prng_rand_n (2) + 1;
for (i = 0; i < n; i++)
{
- clip_boxes[i].x1 = lcg_rand_n (dst_width);
- clip_boxes[i].y1 = lcg_rand_n (dst_height);
+ clip_boxes[i].x1 = prng_rand_n (dst_width);
+ clip_boxes[i].y1 = prng_rand_n (dst_height);
clip_boxes[i].x2 =
- clip_boxes[i].x1 + lcg_rand_n (dst_width - clip_boxes[i].x1);
+ clip_boxes[i].x1 + prng_rand_n (dst_width - clip_boxes[i].x1);
clip_boxes[i].y2 =
- clip_boxes[i].y1 + lcg_rand_n (dst_height - clip_boxes[i].y1);
+ clip_boxes[i].y1 + prng_rand_n (dst_height - clip_boxes[i].y1);
if (verbose)
{
@@ -337,7 +332,7 @@ test_composite (int testnum,
pixman_region_fini (&clip);
}
- if (lcg_rand_n (2) == 0)
+ if (prng_rand_n (2) == 0)
pixman_image_composite (op, src_img, NULL, dst_img,
src_x, src_y, 0, 0, dst_x, dst_y, w, h);
else
@@ -380,11 +375,11 @@ test_composite (int testnum,
}
#if BILINEAR_INTERPOLATION_BITS == 8
-#define CHECKSUM 0x107B67ED
+#define CHECKSUM 0x9096E6B6
#elif BILINEAR_INTERPOLATION_BITS == 7
-#define CHECKSUM 0x30EC0CF0
+#define CHECKSUM 0xCE8EC6BA
#elif BILINEAR_INTERPOLATION_BITS == 4
-#define CHECKSUM 0x87B496BC
+#define CHECKSUM 0xAB1D39BE
#else
#define CHECKSUM 0x00000000
#endif
diff --git a/pixman/test/stress-test.c b/pixman/test/stress-test.c
index 059250dd4..ee55c21ea 100644
--- a/pixman/test/stress-test.c
+++ b/pixman/test/stress-test.c
@@ -74,7 +74,7 @@ static pixman_filter_t filters[] =
static int
get_size (void)
{
- switch (lcg_rand_n (28))
+ switch (prng_rand_n (28))
{
case 0:
return 1;
@@ -84,10 +84,10 @@ get_size (void)
default:
case 2:
- return lcg_rand_n (100);
+ return prng_rand_n (100);
case 4:
- return lcg_rand_n (2000) + 1000;
+ return prng_rand_n (2000) + 1000;
case 5:
return 65535;
@@ -96,7 +96,7 @@ get_size (void)
return 65536;
case 7:
- return lcg_rand_N (64000) + 63000;
+ return prng_rand_n (64000) + 63000;
}
}
@@ -164,7 +164,7 @@ real_writer (void *src, uint32_t value, int size)
static uint32_t
fake_reader (const void *src, int size)
{
- uint32_t r = lcg_rand_u32 ();
+ uint32_t r = prng_rand ();
assert (size == 1 || size == 2 || size == 4);
@@ -182,16 +182,16 @@ log_rand (void)
{
uint32_t mask;
- mask = (1 << lcg_rand_n (10)) - 1;
+ mask = (1 << prng_rand_n (10)) - 1;
- return (lcg_rand_u32 () & mask) - (mask >> 1);
+ return (prng_rand () & mask) - (mask >> 1);
}
static int32_t
rand_x (pixman_image_t *image)
{
if (image->type == BITS)
- return lcg_rand_n (image->bits.width);
+ return prng_rand_n (image->bits.width);
else
return log_rand ();
}
@@ -200,7 +200,7 @@ static int32_t
rand_y (pixman_image_t *image)
{
if (image->type == BITS)
- return lcg_rand_n (image->bits.height);
+ return prng_rand_n (image->bits.height);
else
return log_rand ();
}
@@ -220,7 +220,7 @@ create_random_bits_image (void)
int n_coefficients = 0;
/* format */
- format = image_formats[lcg_rand_n (ARRAY_LENGTH (image_formats))];
+ format = image_formats[prng_rand_n (ARRAY_LENGTH (image_formats))];
indexed = NULL;
if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR)
@@ -246,7 +246,7 @@ create_random_bits_image (void)
while ((uint64_t)width * height > 200000)
{
- if (lcg_rand_n(2) == 0)
+ if (prng_rand_n(2) == 0)
height = 200000 / width;
else
width = 200000 / height;
@@ -258,11 +258,11 @@ create_random_bits_image (void)
width = 1;
/* bits */
- switch (lcg_rand_n (7))
+ switch (prng_rand_n (7))
{
default:
case 0:
- stride = width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17);
+ stride = width * PIXMAN_FORMAT_BPP (format) + prng_rand_n (17);
stride = (stride + 3) & (~3);
bits = (uint32_t *)make_random_bytes (height * stride);
break;
@@ -273,7 +273,7 @@ create_random_bits_image (void)
break;
case 2: /* Zero-filled */
- stride = width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17);
+ stride = width * PIXMAN_FORMAT_BPP (format) + prng_rand_n (17);
stride = (stride + 3) & (~3);
bits = fence_malloc (height * stride);
if (!bits)
@@ -282,7 +282,7 @@ create_random_bits_image (void)
break;
case 3: /* Filled with 0xFF */
- stride = width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17);
+ stride = width * PIXMAN_FORMAT_BPP (format) + prng_rand_n (17);
stride = (stride + 3) & (~3);
bits = fence_malloc (height * stride);
if (!bits)
@@ -298,7 +298,7 @@ create_random_bits_image (void)
break;
case 5: /* bits is a real pointer, has read/write functions */
- stride = width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17);
+ stride = width * PIXMAN_FORMAT_BPP (format) + prng_rand_n (17);
stride = (stride + 3) & (~3);
bits = fence_malloc (height * stride);
if (!bits)
@@ -309,7 +309,7 @@ create_random_bits_image (void)
break;
case 6: /* bits is a real pointer, stride is negative */
- stride = (width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17));
+ stride = (width * PIXMAN_FORMAT_BPP (format) + prng_rand_n (17));
stride = (stride + 3) & (~3);
bits = (uint32_t *)make_random_bytes (height * stride);
if (!bits)
@@ -320,11 +320,11 @@ create_random_bits_image (void)
}
/* Filter */
- filter = filters[lcg_rand_n (ARRAY_LENGTH (filters))];
+ filter = filters[prng_rand_n (ARRAY_LENGTH (filters))];
if (filter == PIXMAN_FILTER_CONVOLUTION)
{
- int width = lcg_rand_n (3);
- int height = lcg_rand_n (4);
+ int width = prng_rand_n (3);
+ int height = prng_rand_n (4);
n_coefficients = width * height + 2;
coefficients = malloc (n_coefficients * sizeof (pixman_fixed_t));
@@ -334,7 +334,7 @@ create_random_bits_image (void)
int i;
for (i = 0; i < width * height; ++i)
- coefficients[i + 2] = lcg_rand_u32();
+ coefficients[i + 2] = prng_rand();
coefficients[0] = width << 16;
coefficients[1] = height << 16;
@@ -380,11 +380,11 @@ set_general_properties (pixman_image_t *image, pixman_bool_t allow_alpha_map)
/* Set properties that are generic to all images */
/* Repeat */
- repeat = repeats[lcg_rand_n (ARRAY_LENGTH (repeats))];
+ repeat = repeats[prng_rand_n (ARRAY_LENGTH (repeats))];
pixman_image_set_repeat (image, repeat);
/* Alpha map */
- if (allow_alpha_map && lcg_rand_n (4) == 0)
+ if (allow_alpha_map && prng_rand_n (4) == 0)
{
pixman_image_t *alpha_map;
int16_t x, y;
@@ -405,17 +405,17 @@ set_general_properties (pixman_image_t *image, pixman_bool_t allow_alpha_map)
}
/* Component alpha */
- pixman_image_set_component_alpha (image, lcg_rand_n (3) == 0);
+ pixman_image_set_component_alpha (image, prng_rand_n (3) == 0);
/* Clip region */
- if (lcg_rand_n (8) < 2)
+ if (prng_rand_n (8) < 2)
{
pixman_region32_t region;
int i, n_rects;
pixman_region32_init (&region);
- switch (lcg_rand_n (12))
+ switch (prng_rand_n (12))
{
case 0:
n_rects = 0;
@@ -434,7 +434,7 @@ set_general_properties (pixman_image_t *image, pixman_bool_t allow_alpha_map)
break;
default:
- n_rects = lcg_rand_n (100);
+ n_rects = prng_rand_n (100);
break;
}
@@ -452,7 +452,7 @@ set_general_properties (pixman_image_t *image, pixman_bool_t allow_alpha_map)
&region, &region, x, y, width, height);
}
- if (image->type == BITS && lcg_rand_n (8) != 0)
+ if (image->type == BITS && prng_rand_n (8) != 0)
{
uint32_t width, height;
int x, y;
@@ -463,10 +463,10 @@ set_general_properties (pixman_image_t *image, pixman_bool_t allow_alpha_map)
*/
for (i = 0; i < 5; ++i)
{
- x = lcg_rand_n (2 * image->bits.width) - image->bits.width;
- y = lcg_rand_n (2 * image->bits.height) - image->bits.height;
- width = lcg_rand_n (image->bits.width) - x + 10;
- height = lcg_rand_n (image->bits.height) - y + 10;
+ x = prng_rand_n (2 * image->bits.width) - image->bits.width;
+ y = prng_rand_n (2 * image->bits.height) - image->bits.height;
+ width = prng_rand_n (image->bits.width) - x + 10;
+ height = prng_rand_n (image->bits.height) - y + 10;
if (width + x < x)
width = INT32_MAX - x;
@@ -484,13 +484,13 @@ set_general_properties (pixman_image_t *image, pixman_bool_t allow_alpha_map)
}
/* Whether source clipping is enabled */
- pixman_image_set_source_clipping (image, !!lcg_rand_n (2));
+ pixman_image_set_source_clipping (image, !!prng_rand_n (2));
/* Client clip */
- pixman_image_set_has_client_clip (image, !!lcg_rand_n (2));
+ pixman_image_set_has_client_clip (image, !!prng_rand_n (2));
/* Transform */
- if (lcg_rand_n (5) < 2)
+ if (prng_rand_n (5) < 2)
{
pixman_transform_t xform;
int i, j, k;
@@ -504,39 +504,39 @@ set_general_properties (pixman_image_t *image, pixman_bool_t allow_alpha_map)
for (k = 0; k < 3; ++k)
{
- switch (lcg_rand_n (4))
+ switch (prng_rand_n (4))
{
case 0:
/* rotation */
- c = lcg_rand_N (2 * 65536) - 65536;
- s = lcg_rand_N (2 * 65536) - 65536;
+ c = prng_rand_n (2 * 65536) - 65536;
+ s = prng_rand_n (2 * 65536) - 65536;
pixman_transform_rotate (&xform, NULL, c, s);
break;
case 1:
/* translation */
- tx = lcg_rand_u32();
- ty = lcg_rand_u32();
+ tx = prng_rand();
+ ty = prng_rand();
pixman_transform_translate (&xform, NULL, tx, ty);
break;
case 2:
/* scale */
- sx = lcg_rand_u32();
- sy = lcg_rand_u32();
+ sx = prng_rand();
+ sy = prng_rand();
pixman_transform_scale (&xform, NULL, sx, sy);
break;
case 3:
- if (lcg_rand_n (16) == 0)
+ if (prng_rand_n (16) == 0)
{
/* random */
for (i = 0; i < 3; ++i)
for (j = 0; j < 3; ++j)
- xform.matrix[i][j] = lcg_rand_u32();
+ xform.matrix[i][j] = prng_rand();
break;
}
- else if (lcg_rand_n (16) == 0)
+ else if (prng_rand_n (16) == 0)
{
/* zero */
memset (&xform, 0, sizeof xform);
@@ -554,10 +554,10 @@ random_color (void)
{
pixman_color_t color =
{
- lcg_rand() & 0xffff,
- lcg_rand() & 0xffff,
- lcg_rand() & 0xffff,
- lcg_rand() & 0xffff,
+ prng_rand() & 0xffff,
+ prng_rand() & 0xffff,
+ prng_rand() & 0xffff,
+ prng_rand() & 0xffff,
};
return color;
@@ -581,7 +581,7 @@ create_random_stops (int *n_stops)
int i;
pixman_gradient_stop_t *stops;
- *n_stops = lcg_rand_n (50) + 1;
+ *n_stops = prng_rand_n (50) + 1;
step = pixman_fixed_1 / *n_stops;
@@ -646,8 +646,8 @@ create_random_radial_image (void)
inner_c = create_random_point();
outer_c = create_random_point();
- inner_r = lcg_rand();
- outer_r = lcg_rand();
+ inner_r = prng_rand();
+ outer_r = prng_rand();
stops = create_random_stops (&n_stops);
@@ -672,7 +672,7 @@ create_random_conical_image (void)
pixman_image_t *result;
c = create_random_point();
- angle = lcg_rand();
+ angle = prng_rand();
stops = create_random_stops (&n_stops);
@@ -691,7 +691,7 @@ create_random_image (void)
{
pixman_image_t *result;
- switch (lcg_rand_n (5))
+ switch (prng_rand_n (5))
{
default:
case 0:
@@ -793,7 +793,7 @@ run_test (uint32_t seed, pixman_bool_t verbose, uint32_t mod)
printf ("Seed 0x%08x\n", seed);
}
- lcg_srand (seed);
+ prng_srand (seed);
source = create_random_image ();
mask = create_random_image ();
@@ -803,7 +803,7 @@ run_test (uint32_t seed, pixman_bool_t verbose, uint32_t mod)
{
set_general_properties (dest, TRUE);
- op = op_list [lcg_rand_n (ARRAY_LENGTH (op_list))];
+ op = op_list [prng_rand_n (ARRAY_LENGTH (op_list))];
pixman_image_composite32 (op,
source, mask, dest,
diff --git a/pixman/test/utils-prng.c b/pixman/test/utils-prng.c
new file mode 100644
index 000000000..7c2dd6a9a
--- /dev/null
+++ b/pixman/test/utils-prng.c
@@ -0,0 +1,238 @@
+/*
+ * Copyright © 2012 Siarhei Siamashka <siarhei.siamashka@gmail.com>
+ *
+ * Based on the public domain implementation of small noncryptographic PRNG
+ * authored by Bob Jenkins: http://burtleburtle.net/bob/rand/smallprng.html
+ *
+ * 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 "utils.h"
+#include "utils-prng.h"
+
+void smallprng_srand_r (smallprng_t *x, uint32_t seed)
+{
+ uint32_t i;
+ x->a = 0xf1ea5eed, x->b = x->c = x->d = seed;
+ for (i = 0; i < 20; ++i)
+ smallprng_rand_r (x);
+}
+
+/*
+ * Set a 32-bit seed for PRNG
+ *
+ * LCG is used here for generating independent seeds for different
+ * smallprng instances (in the case if smallprng is also used for
+ * generating these seeds, "Big Crush" test from TestU01 detects
+ * some problems in the glued 'prng_rand_128_r' output data).
+ * Actually we might be even better using some cryptographic
+ * hash for this purpose, but LCG seems to be also enough for
+ * passing "Big Crush".
+ */
+void prng_srand_r (prng_t *x, uint32_t seed)
+{
+#ifdef GCC_VECTOR_EXTENSIONS_SUPPORTED
+ int i;
+ prng_rand_128_data_t dummy;
+ smallprng_srand_r (&x->p0, seed);
+ x->a[0] = x->a[1] = x->a[2] = x->a[3] = 0xf1ea5eed;
+ x->b[0] = x->c[0] = x->d[0] = (seed = seed * 1103515245 + 12345);
+ x->b[1] = x->c[1] = x->d[1] = (seed = seed * 1103515245 + 12345);
+ x->b[2] = x->c[2] = x->d[2] = (seed = seed * 1103515245 + 12345);
+ x->b[3] = x->c[3] = x->d[3] = (seed = seed * 1103515245 + 12345);
+ for (i = 0; i < 20; ++i)
+ prng_rand_128_r (x, &dummy);
+#else
+ smallprng_srand_r (&x->p0, seed);
+ smallprng_srand_r (&x->p1, (seed = seed * 1103515245 + 12345));
+ smallprng_srand_r (&x->p2, (seed = seed * 1103515245 + 12345));
+ smallprng_srand_r (&x->p3, (seed = seed * 1103515245 + 12345));
+ smallprng_srand_r (&x->p4, (seed = seed * 1103515245 + 12345));
+#endif
+}
+
+static force_inline void
+store_rand_128_data (void *addr, prng_rand_128_data_t *d, int aligned)
+{
+#ifdef GCC_VECTOR_EXTENSIONS_SUPPORTED
+ if (aligned)
+ {
+ *(uint8x16 *)addr = d->vb;
+ return;
+ }
+#endif
+ /* we could try something better for unaligned writes (packed attribute),
+ * but GCC is not very reliable: http://gcc.gnu.org/PR55454 */
+ memcpy (addr, d, 16);
+}
+
+/*
+ * Helper function and the actual code for "prng_randmemset_r" function
+ */
+static force_inline void
+randmemset_internal (prng_t *prng,
+ uint8_t *buf,
+ size_t size,
+ prng_randmemset_flags_t flags,
+ int aligned)
+{
+ prng_t local_prng = *prng;
+ prng_rand_128_data_t randdata;
+
+ while (size >= 16)
+ {
+ prng_rand_128_data_t t;
+ if (flags == 0)
+ {
+ prng_rand_128_r (&local_prng, &randdata);
+ }
+ else
+ {
+ prng_rand_128_r (&local_prng, &t);
+ prng_rand_128_r (&local_prng, &randdata);
+#ifdef GCC_VECTOR_EXTENSIONS_SUPPORTED
+ if (flags & RANDMEMSET_MORE_FF)
+ {
+ const uint8x16 const_C0 =
+ {
+ 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
+ 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0
+ };
+ randdata.vb |= (t.vb >= const_C0);
+ }
+ if (flags & RANDMEMSET_MORE_00)
+ {
+ const uint8x16 const_40 =
+ {
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40
+ };
+ randdata.vb &= (t.vb >= const_40);
+ }
+#else
+ #define PROCESS_ONE_LANE(i) \
+ if (flags & RANDMEMSET_MORE_FF) \
+ { \
+ uint32_t mask_ff = (t.w[i] & (t.w[i] << 1)) & 0x80808080; \
+ mask_ff |= mask_ff >> 1; \
+ mask_ff |= mask_ff >> 2; \
+ mask_ff |= mask_ff >> 4; \
+ randdata.w[i] |= mask_ff; \
+ } \
+ if (flags & RANDMEMSET_MORE_00) \
+ { \
+ uint32_t mask_00 = (t.w[i] | (t.w[i] << 1)) & 0x80808080; \
+ mask_00 |= mask_00 >> 1; \
+ mask_00 |= mask_00 >> 2; \
+ mask_00 |= mask_00 >> 4; \
+ randdata.w[i] &= mask_00; \
+ }
+
+ PROCESS_ONE_LANE (0)
+ PROCESS_ONE_LANE (1)
+ PROCESS_ONE_LANE (2)
+ PROCESS_ONE_LANE (3)
+#endif
+ }
+ if (is_little_endian ())
+ {
+ store_rand_128_data (buf, &randdata, aligned);
+ buf += 16;
+ }
+ else
+ {
+#ifdef GCC_VECTOR_EXTENSIONS_SUPPORTED
+ const uint8x16 bswap_shufflemask =
+ {
+ 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12
+ };
+ randdata.vb = __builtin_shuffle (randdata.vb, bswap_shufflemask);
+ store_rand_128_data (buf, &randdata, aligned);
+ buf += 16;
+#else
+ uint8_t t1, t2, t3, t4;
+ #define STORE_ONE_LANE(i) \
+ t1 = randdata.b[i * 4 + 3]; \
+ t2 = randdata.b[i * 4 + 2]; \
+ t3 = randdata.b[i * 4 + 1]; \
+ t4 = randdata.b[i * 4 + 0]; \
+ *buf++ = t1; \
+ *buf++ = t2; \
+ *buf++ = t3; \
+ *buf++ = t4;
+
+ STORE_ONE_LANE (0)
+ STORE_ONE_LANE (1)
+ STORE_ONE_LANE (2)
+ STORE_ONE_LANE (3)
+#endif
+ }
+ size -= 16;
+ }
+ while (size > 0)
+ {
+ uint8_t randbyte = prng_rand_r (&local_prng) & 0xFF;
+ if (flags != 0)
+ {
+ uint8_t t = prng_rand_r (&local_prng) & 0xFF;
+ if ((flags & RANDMEMSET_MORE_FF) && (t >= 0xC0))
+ randbyte = 0xFF;
+ if ((flags & RANDMEMSET_MORE_00) && (t < 0x40))
+ randbyte = 0x00;
+ }
+ *buf++ = randbyte;
+ size--;
+ }
+ *prng = local_prng;
+}
+
+/*
+ * Fill memory buffer with random data. Flags argument may be used
+ * to tweak some statistics properties:
+ * RANDMEMSET_MORE_00 - set ~25% of bytes to 0x00
+ * RANDMEMSET_MORE_FF - set ~25% of bytes to 0xFF
+ */
+void prng_randmemset_r (prng_t *prng,
+ void *voidbuf,
+ size_t size,
+ prng_randmemset_flags_t flags)
+{
+ uint8_t *buf = (uint8_t *)voidbuf;
+ if ((uintptr_t)buf & 15)
+ {
+ /* unaligned buffer */
+ if (flags == 0)
+ randmemset_internal (prng, buf, size, 0, 0);
+ else if (flags == RANDMEMSET_MORE_00_AND_FF)
+ randmemset_internal (prng, buf, size, RANDMEMSET_MORE_00_AND_FF, 0);
+ else
+ randmemset_internal (prng, buf, size, flags, 0);
+ }
+ else
+ {
+ /* aligned buffer */
+ if (flags == 0)
+ randmemset_internal (prng, buf, size, 0, 1);
+ else if (flags == RANDMEMSET_MORE_00_AND_FF)
+ randmemset_internal (prng, buf, size, RANDMEMSET_MORE_00_AND_FF, 1);
+ else
+ randmemset_internal (prng, buf, size, flags, 1);
+ }
+}
diff --git a/pixman/test/utils-prng.h b/pixman/test/utils-prng.h
new file mode 100644
index 000000000..285107f08
--- /dev/null
+++ b/pixman/test/utils-prng.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright © 2012 Siarhei Siamashka <siarhei.siamashka@gmail.com>
+ *
+ * Based on the public domain implementation of small noncryptographic PRNG
+ * authored by Bob Jenkins: http://burtleburtle.net/bob/rand/smallprng.html
+ *
+ * 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.
+ */
+
+#ifndef __UTILS_PRNG_H__
+#define __UTILS_PRNG_H__
+
+/*
+ * This file provides a fast SIMD-optimized noncryptographic PRNG (pseudorandom
+ * number generator), with the output good enough to pass "Big Crush" tests
+ * from TestU01 (http://en.wikipedia.org/wiki/TestU01).
+ *
+ * SIMD code uses http://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html
+ * which is a GCC specific extension. There is also a slower alternative
+ * code path, which should work with any C compiler.
+ *
+ * The "prng_t" structure keeps the internal state of the random number
+ * generator. It is possible to have multiple instances of the random number
+ * generator active at the same time, in this case each of them needs to have
+ * its own "prng_t". All the functions take a pointer to "prng_t"
+ * as the first argument.
+ *
+ * Functions:
+ *
+ * ----------------------------------------------------------------------------
+ * void prng_srand_r (prng_t *prng, uint32_t seed);
+ *
+ * Initialize the pseudorandom number generator. The sequence of preudorandom
+ * numbers is deterministic and only depends on "seed". Any two generators
+ * initialized with the same seed will produce exactly the same sequence.
+ *
+ * ----------------------------------------------------------------------------
+ * uint32_t prng_rand_r (prng_t *prng);
+ *
+ * Generate a single uniformly distributed 32-bit pseudorandom value.
+ *
+ * ----------------------------------------------------------------------------
+ * void prng_randmemset_r (prng_t *prng,
+ * void *buffer,
+ * size_t size,
+ * prng_randmemset_flags_t flags);
+ *
+ * Fills the memory buffer "buffer" with "size" bytes of pseudorandom data.
+ * The "flags" argument may be used to tweak some statistics properties:
+ * RANDMEMSET_MORE_00 - set ~25% of bytes to 0x00
+ * RANDMEMSET_MORE_FF - set ~25% of bytes to 0xFF
+ * The flags can be combined. This allows a bit better simulation of typical
+ * pixel data, which normally contains a lot of fully transparent or fully
+ * opaque pixels.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pixman-private.h"
+
+/*****************************************************************************/
+
+#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
+#define GCC_VECTOR_EXTENSIONS_SUPPORTED
+typedef uint32_t uint32x4 __attribute__ ((vector_size(16)));
+typedef uint8_t uint8x16 __attribute__ ((vector_size(16)));
+#endif
+
+typedef struct
+{
+ uint32_t a, b, c, d;
+} smallprng_t;
+
+typedef struct
+{
+#ifdef GCC_VECTOR_EXTENSIONS_SUPPORTED
+ uint32x4 a, b, c, d;
+#else
+ smallprng_t p1, p2, p3, p4;
+#endif
+ smallprng_t p0;
+} prng_t;
+
+typedef union
+{
+ uint8_t b[16];
+ uint32_t w[4];
+#ifdef GCC_VECTOR_EXTENSIONS_SUPPORTED
+ uint8x16 vb;
+ uint32x4 vw;
+#endif
+} prng_rand_128_data_t;
+
+/*****************************************************************************/
+
+static force_inline uint32_t
+smallprng_rand_r (smallprng_t *x)
+{
+ uint32_t e = x->a - ((x->b << 27) + (x->b >> (32 - 27)));
+ x->a = x->b ^ ((x->c << 17) ^ (x->c >> (32 - 17)));
+ x->b = x->c + x->d;
+ x->c = x->d + e;
+ x->d = e + x->a;
+ return x->d;
+}
+
+/* Generate 4 bytes (32-bits) of random data */
+static force_inline uint32_t
+prng_rand_r (prng_t *x)
+{
+ return smallprng_rand_r (&x->p0);
+}
+
+/* Generate 16 bytes (128-bits) of random data */
+static force_inline void
+prng_rand_128_r (prng_t *x, prng_rand_128_data_t *data)
+{
+#ifdef GCC_VECTOR_EXTENSIONS_SUPPORTED
+ uint32x4 e = x->a - ((x->b << 27) + (x->b >> (32 - 27)));
+ x->a = x->b ^ ((x->c << 17) ^ (x->c >> (32 - 17)));
+ x->b = x->c + x->d;
+ x->c = x->d + e;
+ x->d = e + x->a;
+ data->vw = x->d;
+#else
+ data->w[0] = smallprng_rand_r (&x->p1);
+ data->w[1] = smallprng_rand_r (&x->p2);
+ data->w[2] = smallprng_rand_r (&x->p3);
+ data->w[3] = smallprng_rand_r (&x->p4);
+#endif
+}
+
+typedef enum
+{
+ RANDMEMSET_MORE_00 = 1, /* ~25% chance for 0x00 bytes */
+ RANDMEMSET_MORE_FF = 2, /* ~25% chance for 0xFF bytes */
+ RANDMEMSET_MORE_00_AND_FF = (RANDMEMSET_MORE_00 | RANDMEMSET_MORE_FF)
+} prng_randmemset_flags_t;
+
+/* Set the 32-bit seed for PRNG */
+void prng_srand_r (prng_t *prng, uint32_t seed);
+
+/* Fill memory buffer with random data */
+void prng_randmemset_r (prng_t *prng,
+ void *buffer,
+ size_t size,
+ prng_randmemset_flags_t flags);
+
+#endif
diff --git a/pixman/test/utils.c b/pixman/test/utils.c
index c887a6db9..66c8dcb89 100644
--- a/pixman/test/utils.c
+++ b/pixman/test/utils.c
@@ -27,10 +27,11 @@
#include <png.h>
#endif
-/* Random number seed
+/* Random number generator state
*/
-uint32_t lcg_seed;
+prng_t prng_state_data;
+prng_t *prng_state;
/*----------------------------------------------------------------------------*\
* CRC-32 version 2.0.0 by Craig Bruce, 2006-04-29.
@@ -237,14 +238,6 @@ compute_crc32_for_image (uint32_t crc32,
return crc32;
}
-pixman_bool_t
-is_little_endian (void)
-{
- volatile uint16_t endian_check_var = 0x1234;
-
- return (*(volatile uint8_t *)&endian_check_var == 0x34);
-}
-
/* perform endian conversion of pixel data
*/
void
@@ -431,13 +424,11 @@ uint8_t *
make_random_bytes (int n_bytes)
{
uint8_t *bytes = fence_malloc (n_bytes);
- int i;
if (!bytes)
return NULL;
- for (i = 0; i < n_bytes; ++i)
- bytes[i] = lcg_rand () & 0xff;
+ prng_randmemset (bytes, n_bytes, 0);
return bytes;
}
@@ -689,9 +680,9 @@ get_random_seed (void)
{
union { double d; uint32_t u32; } t;
t.d = gettime();
- lcg_srand (t.u32);
+ prng_srand (t.u32);
- return lcg_rand_u32 ();
+ return prng_rand ();
}
#ifdef HAVE_SIGACTION
@@ -785,7 +776,7 @@ initialize_palette (pixman_indexed_t *palette, uint32_t depth, int is_rgb)
uint32_t mask = (1 << depth) - 1;
for (i = 0; i < 32768; ++i)
- palette->ent[i] = lcg_rand() & mask;
+ palette->ent[i] = prng_rand() & mask;
memset (palette->rgba, 0, sizeof (palette->rgba));
@@ -805,7 +796,7 @@ initialize_palette (pixman_indexed_t *palette, uint32_t depth, int is_rgb)
{
uint32_t old_idx;
- rgba24 = lcg_rand();
+ rgba24 = prng_rand();
i15 = CONVERT_15 (rgba24, is_rgb);
old_idx = palette->ent[i15];
diff --git a/pixman/test/utils.h b/pixman/test/utils.h
index f7ea34c5f..78cf0d16d 100644
--- a/pixman/test/utils.h
+++ b/pixman/test/utils.h
@@ -4,6 +4,7 @@
#include <assert.h>
#include "pixman-private.h" /* For 'inline' definition */
+#include "utils-prng.h"
#define ARRAY_LENGTH(A) ((int) (sizeof (A) / sizeof ((A) [0])))
@@ -11,49 +12,44 @@
* taken from POSIX.1-2001 example
*/
-extern uint32_t lcg_seed;
+extern prng_t prng_state_data;
+extern prng_t *prng_state;
#ifdef USE_OPENMP
-#pragma omp threadprivate(lcg_seed)
+#pragma omp threadprivate(prng_state_data)
+#pragma omp threadprivate(prng_state)
#endif
static inline uint32_t
-lcg_rand (void)
+prng_rand (void)
{
- lcg_seed = lcg_seed * 1103515245 + 12345;
- return ((uint32_t)(lcg_seed / 65536) % 32768);
+ return prng_rand_r (prng_state);
}
static inline void
-lcg_srand (uint32_t seed)
+prng_srand (uint32_t seed)
{
- lcg_seed = seed;
+ if (!prng_state)
+ {
+ /* Without setting a seed, PRNG does not work properly (is just
+ * returning zeros). So we only initialize the pointer here to
+ * make sure that 'prng_srand' is always called before any
+ * other 'prng_*' function. The wrongdoers violating this order
+ * will get a segfault. */
+ prng_state = &prng_state_data;
+ }
+ prng_srand_r (prng_state, seed);
}
static inline uint32_t
-lcg_rand_n (int max)
+prng_rand_n (int max)
{
- return lcg_rand () % max;
+ return prng_rand () % max;
}
-static inline uint32_t
-lcg_rand_N (int max)
-{
- uint32_t lo = lcg_rand ();
- uint32_t hi = lcg_rand () << 15;
- return (lo | hi) % max;
-}
-
-static inline uint32_t
-lcg_rand_u32 (void)
+static inline void
+prng_randmemset (void *buffer, size_t size, prng_randmemset_flags_t flags)
{
- /* This uses the 10/11 most significant bits from the 3 lcg results
- * (and mixes them with the low from the adjacent one).
- */
- uint32_t lo = lcg_rand() >> -(32 - 15 - 11 * 2);
- uint32_t mid = lcg_rand() << (32 - 15 - 11 * 1);
- uint32_t hi = lcg_rand() << (32 - 15 - 11 * 0);
-
- return (hi ^ mid ^ lo);
+ prng_randmemset_r (prng_state, buffer, size, flags);
}
/* CRC 32 computation
@@ -69,8 +65,12 @@ compute_crc32_for_image (uint32_t in_crc32,
/* Returns TRUE if running on a little endian system
*/
-pixman_bool_t
-is_little_endian (void);
+static force_inline pixman_bool_t
+is_little_endian (void)
+{
+ unsigned long endian_check_var = 1;
+ return *(unsigned char *)&endian_check_var == 1;
+}
/* perform endian conversion of pixel data
*/