static cairo_status_t _cairo_image_surface_set_filter (cairo_image_surface_t *surface, cairo_filter_t filter) { pixman_filter_t pixman_filter; switch (filter) { case CAIRO_FILTER_FAST: pixman_filter = PIXMAN_FILTER_FAST; break; case CAIRO_FILTER_GOOD: pixman_filter = PIXMAN_FILTER_GOOD; break; case CAIRO_FILTER_BEST: pixman_filter = PIXMAN_FILTER_BEST; break; case CAIRO_FILTER_NEAREST: pixman_filter = PIXMAN_FILTER_NEAREST; break; case CAIRO_FILTER_BILINEAR: pixman_filter = PIXMAN_FILTER_BILINEAR; break; default: pixman_filter = PIXMAN_FILTER_BEST; } pixman_image_set_filter (surface->pixman_image, pixman_filter); return CAIRO_STATUS_SUCCESS; }
static void pixman_image_composite_empty (pixman_implementation_t *impl, pixman_composite_info_t *info) { if (use_scaling) { pixman_image_set_filter (info->src_image, filter, NULL, 0); pixman_image_set_transform(info->src_image, &m); } pixman_image_composite (info->op, info->src_image, info->mask_image, info->dest_image, 0, 0, 0, 0, 0, 0, 1, 1); }
void _blur_image_surface (cairo_surface_t* surface, gint radius, gdouble sigma /* pass 0.0f for auto-calculation */) { pixman_fixed_t* params = NULL; gint n_params; pixman_image_t* src; gint w; gint h; gint s; gpointer p; gdouble radiusf; radiusf = fabs (radius) + 1.0f; if (sigma == 0.0f) sigma = sqrt (-(radiusf * radiusf) / (2.0f * log (1.0f / 255.0f))); w = cairo_image_surface_get_width (surface); h = cairo_image_surface_get_height (surface); s = cairo_image_surface_get_stride (surface); // create pixman image for cairo image surface p = cairo_image_surface_get_data (surface); src = pixman_image_create_bits (PIXMAN_a8r8g8b8, w, h, p, s); // attach gaussian kernel to pixman image params = create_gaussian_blur_kernel (radius, sigma, &n_params); pixman_image_set_filter (src, PIXMAN_FILTER_CONVOLUTION, params, n_params); g_free (params); // render blured image to new pixman image pixman_image_composite (PIXMAN_OP_SRC, src, NULL, src, 0, 0, 0, 0, 0, 0, w, h); pixman_image_unref (src); }
static void pixman_image_composite_wrapper (pixman_implementation_t *impl, pixman_composite_info_t *info) { if (use_scaling) { pixman_image_set_filter (info->src_image, filter, NULL, 0); pixman_image_set_transform(info->src_image, &m); } pixman_image_composite (info->op, info->src_image, info->mask_image, info->dest_image, info->src_x, info->src_y, info->mask_x, info->mask_y, info->dest_x, info->dest_y, info->width, info->height); }
static void create_image (uint32_t width, uint32_t height, pixman_format_code_t format, pixman_filter_t filter, uint32_t **bits, pixman_image_t **image) { uint32_t stride = (width * PIXMAN_FORMAT_BPP (format) + 31) / 32 * 4; *bits = aligned_malloc (PAGE_SIZE, stride * height); memset (*bits, 0xCC, stride * height); *image = pixman_image_create_bits (format, width, height, *bits, stride); pixman_image_set_repeat (*image, PIXMAN_REPEAT_NORMAL); pixman_image_set_filter (*image, filter, NULL, 0); }
static void process_image_data(struct fp_img_dev *dev, char **output, int *output_height) { //pixman stuff taken from libfprint/pixman.c, adapted for my purposes. pixman_image_t *orig, *resized; pixman_transform_t transform; struct vfs0050_dev *vfs_dev = dev->priv; struct vfs0050_line *line, *calibration_line; char *buf = malloc(vfs_dev->scanbuf_idx); int lines = vfs_dev->scanbuf_idx / VFS0050_FRAME_SIZE; int i, x, sum, last_sum, diff; int new_height; //just grab one around middle, there should be 100 calibration_line = (struct vfs0050_line *) ((char *) vfs_dev->calbuf + (50 * VFS0050_FRAME_SIZE)); new_height = 0; for (i = 0; i < lines; i++) { line = (struct vfs0050_line *) ((char *) vfs_dev->scanbuf + (i * VFS0050_FRAME_SIZE)); if (!is_noise(line)) memcpy(buf + (new_height++ * VFS0050_IMG_WIDTH), line->row, VFS0050_IMG_WIDTH); else fp_dbg("removed noise at line: %d\n", i); } orig = pixman_image_create_bits(PIXMAN_a8, VFS0050_IMG_WIDTH, new_height, (uint32_t *) buf, VFS0050_IMG_WIDTH); new_height *= VFS0050_SCALE_FACTOR; //scale for resized image resized = pixman_image_create_bits(PIXMAN_a8, VFS0050_IMG_WIDTH, new_height, NULL, VFS0050_IMG_WIDTH); pixman_transform_init_identity(&transform); pixman_transform_scale(NULL, &transform, pixman_int_to_fixed(1), pixman_double_to_fixed(0.2)); pixman_image_set_transform(orig, &transform); pixman_image_set_filter(orig, PIXMAN_FILTER_BEST, NULL, 0); pixman_image_composite32(PIXMAN_OP_SRC, orig, NULL, resized, 0, 0, 0, 0, 0, 0, VFS0050_IMG_WIDTH, new_height ); memcpy(buf, pixman_image_get_data(resized), VFS0050_IMG_WIDTH * new_height); pixman_image_unref(orig); pixman_image_unref(resized); *output_height = new_height; *output = buf; }
static void apply(JoyFilter *self, JoyBubble *widget, cairo_t *cr) { struct Private *priv = GET_PRIVATE(self); if (G_UNLIKELY(!priv->kernel || !priv->n)) { return; } gint width = joy_bubble_get_width(widget); gint height = joy_bubble_get_height(widget); cairo_surface_t *surface = cairo_get_target(cr); cairo_surface_type_t type = cairo_surface_get_type(surface); if (CAIRO_SURFACE_TYPE_IMAGE != type) { cairo_surface_t *image_surface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, width, height); cairo_t *image_cr = cairo_create(surface); cairo_set_source_surface(image_cr, surface, 0., 0.); cairo_paint(image_cr); cairo_destroy(image_cr); cairo_surface_flush(image_surface); surface = image_surface; } gint stride = cairo_image_surface_get_stride(surface); gpointer pixels = cairo_image_surface_get_data(surface); pixman_image_t *image = pixman_image_create_bits(PIXMAN_a8r8g8b8, width, height, pixels, stride); if (!image) { goto error; } if (!pixman_image_set_filter(image, PIXMAN_FILTER_CONVOLUTION, priv->kernel, priv->n)) { goto error; } pixman_image_composite(PIXMAN_OP_SRC, image, NULL, image, 0, 0, 0, 0, 0, 0, width, height); pixman_image_unref(image); if (CAIRO_SURFACE_TYPE_IMAGE != type) { cairo_set_source_surface(cr, surface, 0., 0.); cairo_paint(cr); cairo_surface_destroy(surface); } return; error: if (CAIRO_SURFACE_TYPE_IMAGE != type) { cairo_surface_destroy(surface); } }
int main (int argc, char **argv) { #define WIDTH 200 #define HEIGHT 200 #define d2f pixman_double_to_fixed uint32_t *src = malloc (WIDTH * HEIGHT * 4); uint32_t *mask = malloc (WIDTH * HEIGHT * 4); uint32_t *dest = malloc (WIDTH * HEIGHT * 4); pixman_fixed_t convolution[] = { d2f (3), d2f (3), d2f (0.5), d2f (0.5), d2f (0.5), d2f (0.5), d2f (0.5), d2f (0.5), d2f (0.5), d2f (0.5), d2f (0.5), }; pixman_image_t *simg, *mimg, *dimg; int i; for (i = 0; i < WIDTH * HEIGHT; ++i) { src[i] = 0x7f007f00; mask[i] = (i % 256) * 0x01000000; dest[i] = 0; } simg = pixman_image_create_bits (PIXMAN_a8r8g8b8, WIDTH, HEIGHT, src, WIDTH * 4); mimg = pixman_image_create_bits (PIXMAN_a8r8g8b8, WIDTH, HEIGHT, mask, WIDTH * 4); dimg = pixman_image_create_bits (PIXMAN_a8r8g8b8, WIDTH, HEIGHT, dest, WIDTH * 4); pixman_image_set_filter (mimg, PIXMAN_FILTER_CONVOLUTION, convolution, 11); pixman_image_composite (PIXMAN_OP_OVER, simg, mimg, dimg, 0, 0, 0, 0, 0, 0, WIDTH, HEIGHT); show_image (dimg); return 0; }
static cairo_status_t _cairo_image_surface_set_filter (cairo_image_surface_t *surface, cairo_filter_t filter) { pixman_filter_t pixman_filter; switch (filter) { case CAIRO_FILTER_FAST: pixman_filter = PIXMAN_FILTER_FAST; break; case CAIRO_FILTER_GOOD: pixman_filter = PIXMAN_FILTER_GOOD; break; case CAIRO_FILTER_BEST: pixman_filter = PIXMAN_FILTER_BEST; break; case CAIRO_FILTER_NEAREST: pixman_filter = PIXMAN_FILTER_NEAREST; break; case CAIRO_FILTER_BILINEAR: pixman_filter = PIXMAN_FILTER_BILINEAR; break; case CAIRO_FILTER_GAUSSIAN: /* XXX: The GAUSSIAN value has no implementation in cairo * whatsoever, so it was really a mistake to have it in the * API. We could fix this by officially deprecating it, or * else inventing semantics and providing an actual * implementation for it. */ default: pixman_filter = PIXMAN_FILTER_BEST; } if (! pixman_image_set_filter (surface->pixman_image, pixman_filter, NULL, 0)) { return _cairo_error (CAIRO_STATUS_NO_MEMORY); } return CAIRO_STATUS_SUCCESS; }
static void composite_whole(pixman_op_t op, pixman_image_t *src, pixman_image_t *mask, pixman_image_t *dest, const pixman_transform_t *transform, pixman_filter_t filter) { int32_t dest_width; int32_t dest_height; dest_width = pixman_image_get_width(dest); dest_height = pixman_image_get_height(dest); pixman_image_set_transform(src, transform); pixman_image_set_filter(src, filter, NULL, 0); pixman_image_composite32(op, src, mask, dest, 0, 0, /* src_x, src_y */ 0, 0, /* mask_x, mask_y */ 0, 0, /* dest_x, dest_y */ dest_width, dest_height); }
struct fp_img *fpi_im_resize(struct fp_img *img, unsigned int w_factor, unsigned int h_factor) { int new_width = img->width * w_factor; int new_height = img->height * h_factor; pixman_image_t *orig, *resized; pixman_transform_t transform; struct fp_img *newimg; orig = pixman_image_create_bits(PIXMAN_a8, img->width, img->height, (uint32_t *)img->data, img->width); resized = pixman_image_create_bits(PIXMAN_a8, new_width, new_height, NULL, new_width); pixman_transform_init_identity(&transform); pixman_transform_scale(NULL, &transform, pixman_int_to_fixed(w_factor), pixman_int_to_fixed(h_factor)); pixman_image_set_transform(orig, &transform); pixman_image_set_filter(orig, PIXMAN_FILTER_BILINEAR, NULL, 0); pixman_image_composite32(PIXMAN_OP_SRC, orig, /* src */ NULL, /* mask */ resized, /* dst */ 0, 0, /* src x y */ 0, 0, /* mask x y */ 0, 0, /* dst x y */ new_width, new_height /* width height */ ); newimg = fpi_img_new(new_width * new_height); newimg->width = new_width; newimg->height = new_height; newimg->flags = img->flags; memcpy(newimg->data, pixman_image_get_data(resized), new_width * new_height); pixman_image_unref(orig); pixman_image_unref(resized); return newimg; }
static cairo_status_t _cairo_gl_gradient_render (const cairo_gl_context_t *ctx, unsigned int n_stops, const cairo_gradient_stop_t *stops, void *bytes, int width) { pixman_image_t *gradient, *image; pixman_gradient_stop_t pixman_stops_stack[32]; pixman_gradient_stop_t *pixman_stops; pixman_point_fixed_t p1, p2; unsigned int i; pixman_format_code_t gradient_pixman_format; /* * Ensure that the order of the gradient's components in memory is BGRA. * This is done so that the gradient's pixel data is always suitable for * texture upload using format=GL_BGRA and type=GL_UNSIGNED_BYTE. */ if (_cairo_is_little_endian ()) gradient_pixman_format = PIXMAN_a8r8g8b8; else gradient_pixman_format = PIXMAN_b8g8r8a8; pixman_stops = pixman_stops_stack; if (unlikely (n_stops > ARRAY_LENGTH (pixman_stops_stack))) { pixman_stops = _cairo_malloc_ab (n_stops, sizeof (pixman_gradient_stop_t)); if (unlikely (pixman_stops == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); } for (i = 0; i < n_stops; i++) { pixman_stops[i].x = _cairo_fixed_16_16_from_double (stops[i].offset); pixman_stops[i].color.red = stops[i].color.red_short; pixman_stops[i].color.green = stops[i].color.green_short; pixman_stops[i].color.blue = stops[i].color.blue_short; pixman_stops[i].color.alpha = stops[i].color.alpha_short; } p1.x = _cairo_fixed_16_16_from_double (0.5); p1.y = 0; p2.x = _cairo_fixed_16_16_from_double (width - 0.5); p2.y = 0; gradient = pixman_image_create_linear_gradient (&p1, &p2, pixman_stops, n_stops); if (pixman_stops != pixman_stops_stack) free (pixman_stops); if (unlikely (gradient == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); pixman_image_set_filter (gradient, PIXMAN_FILTER_BILINEAR, NULL, 0); pixman_image_set_repeat (gradient, PIXMAN_REPEAT_PAD); image = pixman_image_create_bits (gradient_pixman_format, width, 1, bytes, sizeof(uint32_t)*width); if (unlikely (image == NULL)) { pixman_image_unref (gradient); return _cairo_error (CAIRO_STATUS_NO_MEMORY); } pixman_image_composite32 (PIXMAN_OP_SRC, gradient, NULL, image, 0, 0, 0, 0, 0, 0, width, 1); pixman_image_unref (gradient); pixman_image_unref (image); /* We need to fudge pixel 0 to hold the left-most color stop and not * the neareset stop to the zeroth pixel centre in order to correctly * populate the border color. For completeness, do both edges. */ ((uint32_t*)bytes)[0] = color_stop_to_pixel(&stops[0]); ((uint32_t*)bytes)[width-1] = color_stop_to_pixel(&stops[n_stops-1]); return CAIRO_STATUS_SUCCESS; }
static void composite_clipped(pixman_image_t *src, pixman_image_t *mask, pixman_image_t *dest, const pixman_transform_t *transform, pixman_filter_t filter, pixman_region32_t *src_clip) { int n_box; pixman_box32_t *boxes; int32_t dest_width; int32_t dest_height; int src_stride; int bitspp; pixman_format_code_t src_format; void *src_data; int i; /* Hardcoded to use PIXMAN_OP_OVER, because sampling outside of * a Pixman image produces (0,0,0,0) instead of discarding the * fragment. */ dest_width = pixman_image_get_width(dest); dest_height = pixman_image_get_height(dest); src_format = pixman_image_get_format(src); src_stride = pixman_image_get_stride(src); bitspp = PIXMAN_FORMAT_BPP(src_format); src_data = pixman_image_get_data(src); assert(src_format); /* This would be massive overdraw, except when n_box is 1. */ boxes = pixman_region32_rectangles(src_clip, &n_box); for (i = 0; i < n_box; i++) { uint8_t *ptr = src_data; pixman_image_t *boximg; pixman_transform_t adj = *transform; ptr += boxes[i].y1 * src_stride; ptr += boxes[i].x1 * bitspp / 8; boximg = pixman_image_create_bits_no_clear(src_format, boxes[i].x2 - boxes[i].x1, boxes[i].y2 - boxes[i].y1, (uint32_t *)ptr, src_stride); pixman_transform_translate(&adj, NULL, pixman_int_to_fixed(-boxes[i].x1), pixman_int_to_fixed(-boxes[i].y1)); pixman_image_set_transform(boximg, &adj); pixman_image_set_filter(boximg, filter, NULL, 0); pixman_image_composite32(PIXMAN_OP_OVER, boximg, mask, dest, 0, 0, /* src_x, src_y */ 0, 0, /* mask_x, mask_y */ 0, 0, /* dest_x, dest_y */ dest_width, dest_height); pixman_image_unref(boximg); } if (n_box > 1) { static bool warned = false; if (!warned) weston_log("Pixman-renderer warning: %dx overdraw\n", n_box); warned = true; } }
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"), gtk_adjustment_get_value (app->subsample_adjustment), gtk_adjustment_get_value (app->subsample_adjustment)); 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")); }
/* * We have a source image filled with solid color, set NORMAL or PAD repeat, * and some transform which results in nearest neighbour scaling. * * The expected result is either that the destination image filled with this solid * color or, if the transformation is such that we can't composite anything at * all, that nothing has changed in the destination. * * The surrounding memory of the source image is a different solid color so that * we are sure to get failures if we access it. */ static int run_test (int32_t dst_width, int32_t dst_height, int32_t src_width, int32_t src_height, int32_t src_x, int32_t src_y, int32_t scale_x, int32_t scale_y, pixman_filter_t filter, pixman_repeat_t repeat) { pixman_image_t * src_img; pixman_image_t * dst_img; pixman_transform_t transform; uint32_t * srcbuf; uint32_t * dstbuf; pixman_box32_t box = { 0, 0, src_width, src_height }; pixman_color_t color_cc = { 0xcccc, 0xcccc, 0xcccc, 0xcccc }; int result; int i; static const pixman_fixed_t kernel[] = { #define D(f) (pixman_double_to_fixed (f) + 0x0001) pixman_int_to_fixed (5), pixman_int_to_fixed (5), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0) }; result = 0; srcbuf = (uint32_t *)malloc ((src_width + 10) * (src_height + 10) * 4); dstbuf = (uint32_t *)malloc (dst_width * dst_height * 4); memset (srcbuf, 0x88, src_width * src_height * 4); memset (dstbuf, 0x33, dst_width * dst_height * 4); src_img = pixman_image_create_bits ( PIXMAN_a8r8g8b8, src_width, src_height, srcbuf + (src_width + 10) * 5 + 5, (src_width + 10) * 4); pixman_image_fill_boxes (PIXMAN_OP_SRC, src_img, &color_cc, 1, &box); dst_img = pixman_image_create_bits ( PIXMAN_a8r8g8b8, dst_width, dst_height, dstbuf, dst_width * 4); pixman_transform_init_scale (&transform, scale_x, scale_y); pixman_image_set_transform (src_img, &transform); pixman_image_set_repeat (src_img, repeat); if (filter == PIXMAN_FILTER_CONVOLUTION) pixman_image_set_filter (src_img, filter, kernel, 27); else pixman_image_set_filter (src_img, filter, NULL, 0); pixman_image_composite (PIXMAN_OP_SRC, src_img, NULL, dst_img, src_x, src_y, 0, 0, 0, 0, dst_width, dst_height); pixman_image_unref (src_img); pixman_image_unref (dst_img); for (i = 0; i < dst_width * dst_height; i++) { if (dstbuf[i] != 0xCCCCCCCC && dstbuf[i] != 0x33333333) { result = 1; break; } } free (srcbuf); free (dstbuf); return result; }
/* * Composite operation with pseudorandom images */ uint32_t test_composite (int testnum, int verbose) { int i; pixman_image_t * src_img; pixman_image_t * dst_img; pixman_transform_t transform; pixman_region16_t clip; int src_width, src_height; int dst_width, dst_height; int src_stride, dst_stride; int src_x, src_y; int dst_x, dst_y; int src_bpp; int dst_bpp; int w, h; pixman_fixed_t scale_x = 65536, scale_y = 65536; pixman_fixed_t translate_x = 0, translate_y = 0; int op; int repeat = 0; int src_fmt, dst_fmt; uint32_t * srcbuf; uint32_t * dstbuf; uint32_t crc32; lcg_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_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; if (src_stride & 3) src_stride += 2; 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); 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); 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 ? PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8) : PIXMAN_r5g6b5; dst_fmt = dst_bpp == 4 ? (lcg_rand_n (2) == 0 ? PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8) : PIXMAN_r5g6b5; src_img = pixman_image_create_bits ( src_fmt, src_width, src_height, srcbuf, src_stride); dst_img = pixman_image_create_bits ( dst_fmt, dst_width, dst_height, dstbuf, dst_stride); image_endian_swap (src_img, src_bpp * 8); image_endian_swap (dst_img, dst_bpp * 8); if (lcg_rand_n (8) > 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); 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); } switch (lcg_rand_n (4)) { case 0: repeat = PIXMAN_REPEAT_NONE; break; case 1: repeat = PIXMAN_REPEAT_NORMAL; break; case 2: repeat = PIXMAN_REPEAT_PAD; break; case 3: repeat = PIXMAN_REPEAT_REFLECT; break; default: break; } pixman_image_set_repeat (src_img, repeat); if (lcg_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 (verbose) { printf ("src_fmt=%08X, dst_fmt=%08X\n", src_fmt, dst_fmt); printf ("op=%d, scale_x=%d, scale_y=%d, repeat=%d\n", op, scale_x, scale_y, repeat); printf ("translate_x=%d, translate_y=%d\n", translate_x, translate_y); printf ("src_width=%d, src_height=%d, dst_width=%d, dst_height=%d\n", src_width, src_height, dst_width, dst_height); printf ("src_x=%d, src_y=%d, dst_x=%d, dst_y=%d\n", src_x, src_y, dst_x, dst_y); printf ("w=%d, h=%d\n", w, h); } if (lcg_rand_n (8) == 0) { pixman_box16_t clip_boxes[2]; int n = lcg_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].x2 = clip_boxes[i].x1 + lcg_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); if (verbose) { printf ("source clip box: [%d,%d-%d,%d]\n", clip_boxes[i].x1, clip_boxes[i].y1, clip_boxes[i].x2, clip_boxes[i].y2); } } pixman_region_init_rects (&clip, clip_boxes, n); pixman_image_set_clip_region (src_img, &clip); pixman_image_set_source_clipping (src_img, 1); pixman_region_fini (&clip); } if (lcg_rand_n (8) == 0) { pixman_box16_t clip_boxes[2]; int n = lcg_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].x2 = clip_boxes[i].x1 + lcg_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); if (verbose) { printf ("destination clip box: [%d,%d-%d,%d]\n", clip_boxes[i].x1, clip_boxes[i].y1, clip_boxes[i].x2, clip_boxes[i].y2); } } pixman_region_init_rects (&clip, clip_boxes, n); pixman_image_set_clip_region (dst_img, &clip); pixman_region_fini (&clip); } pixman_image_composite (op, src_img, NULL, dst_img, src_x, src_y, 0, 0, dst_x, dst_y, w, h); if (dst_fmt == PIXMAN_x8r8g8b8) { /* ignore unused part */ for (i = 0; i < dst_stride * dst_height / 4; i++) dstbuf[i] &= 0xFFFFFF; } image_endian_swap (dst_img, dst_bpp * 8); if (verbose) { int j; for (i = 0; i < dst_height; i++) { for (j = 0; j < dst_stride; j++) printf ("%02X ", *((uint8_t *)dstbuf + i * dst_stride + j)); printf ("\n"); } } pixman_image_unref (src_img); pixman_image_unref (dst_img); crc32 = compute_crc32 (0, dstbuf, dst_stride * dst_height); free (srcbuf); free (dstbuf); return crc32; }
/* Create random image for testing purposes */ static pixman_image_t * create_random_image (pixman_format_code_t *allowed_formats, int max_width, int max_height, int max_extra_stride, pixman_format_code_t *used_fmt) { int n = 0, width, height, stride; pixman_format_code_t fmt; uint32_t *buf; pixman_image_t *img; while (allowed_formats[n] != PIXMAN_null) n++; if (n > N_MOST_LIKELY_FORMATS && prng_rand_n (4) != 0) n = N_MOST_LIKELY_FORMATS; fmt = allowed_formats[prng_rand_n (n)]; width = prng_rand_n (max_width) + 1; height = prng_rand_n (max_height) + 1; stride = (width * PIXMAN_FORMAT_BPP (fmt) + 7) / 8 + prng_rand_n (max_extra_stride + 1); stride = (stride + 3) & ~3; /* do the allocation */ buf = aligned_malloc (64, stride * height); if (prng_rand_n (4) == 0) { /* uniform distribution */ prng_randmemset (buf, stride * height, 0); } else { /* significantly increased probability for 0x00 and 0xFF */ prng_randmemset (buf, stride * height, RANDMEMSET_MORE_00_AND_FF); } /* test negative stride */ if (prng_rand_n (4) == 0) { buf += (stride / 4) * (height - 1); stride = - stride; } img = pixman_image_create_bits (fmt, width, height, buf, stride); if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_COLOR) { pixman_image_set_indexed (img, &(rgb_palette[PIXMAN_FORMAT_BPP (fmt)])); } else if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_GRAY) { pixman_image_set_indexed (img, &(y_palette[PIXMAN_FORMAT_BPP (fmt)])); } if (prng_rand_n (16) == 0) pixman_image_set_filter (img, PIXMAN_FILTER_BILINEAR, NULL, 0); image_endian_swap (img); if (used_fmt) *used_fmt = fmt; return img; }
static void repaint_region(struct weston_view *ev, struct weston_output *output, pixman_region32_t *region, pixman_region32_t *surf_region, pixman_op_t pixman_op) { struct pixman_renderer *pr = (struct pixman_renderer *) output->compositor->renderer; struct pixman_surface_state *ps = get_surface_state(ev->surface); struct pixman_output_state *po = get_output_state(output); pixman_region32_t final_region; float view_x, view_y; pixman_transform_t transform; pixman_fixed_t fw, fh; /* The final region to be painted is the intersection of * 'region' and 'surf_region'. However, 'region' is in the global * coordinates, and 'surf_region' is in the surface-local * coordinates */ pixman_region32_init(&final_region); if (surf_region) { pixman_region32_copy(&final_region, surf_region); /* Convert from surface to global coordinates */ if (!ev->transform.enabled) { pixman_region32_translate(&final_region, ev->geometry.x, ev->geometry.y); } else { weston_view_to_global_float(ev, 0, 0, &view_x, &view_y); pixman_region32_translate(&final_region, (int)view_x, (int)view_y); } /* We need to paint the intersection */ pixman_region32_intersect(&final_region, &final_region, region); } else { /* If there is no surface region, just use the global region */ pixman_region32_copy(&final_region, region); } /* Convert from global to output coord */ region_global_to_output(output, &final_region); /* And clip to it */ pixman_image_set_clip_region32 (po->shadow_image, &final_region); /* Set up the source transformation based on the surface position, the output position/transform/scale and the client specified buffer transform/scale */ pixman_transform_init_identity(&transform); pixman_transform_scale(&transform, NULL, pixman_double_to_fixed ((double)1.0/output->current_scale), pixman_double_to_fixed ((double)1.0/output->current_scale)); fw = pixman_int_to_fixed(output->width); fh = pixman_int_to_fixed(output->height); switch (output->transform) { default: case WL_OUTPUT_TRANSFORM_NORMAL: case WL_OUTPUT_TRANSFORM_FLIPPED: break; case WL_OUTPUT_TRANSFORM_90: case WL_OUTPUT_TRANSFORM_FLIPPED_90: pixman_transform_rotate(&transform, NULL, 0, -pixman_fixed_1); pixman_transform_translate(&transform, NULL, 0, fh); break; case WL_OUTPUT_TRANSFORM_180: case WL_OUTPUT_TRANSFORM_FLIPPED_180: pixman_transform_rotate(&transform, NULL, -pixman_fixed_1, 0); pixman_transform_translate(&transform, NULL, fw, fh); break; case WL_OUTPUT_TRANSFORM_270: case WL_OUTPUT_TRANSFORM_FLIPPED_270: pixman_transform_rotate(&transform, NULL, 0, pixman_fixed_1); pixman_transform_translate(&transform, NULL, fw, 0); break; } switch (output->transform) { case WL_OUTPUT_TRANSFORM_FLIPPED: case WL_OUTPUT_TRANSFORM_FLIPPED_90: case WL_OUTPUT_TRANSFORM_FLIPPED_180: case WL_OUTPUT_TRANSFORM_FLIPPED_270: pixman_transform_scale(&transform, NULL, pixman_int_to_fixed (-1), pixman_int_to_fixed (1)); pixman_transform_translate(&transform, NULL, fw, 0); break; } pixman_transform_translate(&transform, NULL, pixman_double_to_fixed (output->x), pixman_double_to_fixed (output->y)); if (ev->transform.enabled) { /* Pixman supports only 2D transform matrix, but Weston uses 3D, * so we're omitting Z coordinate here */ pixman_transform_t surface_transform = {{ { D2F(ev->transform.matrix.d[0]), D2F(ev->transform.matrix.d[4]), D2F(ev->transform.matrix.d[12]), }, { D2F(ev->transform.matrix.d[1]), D2F(ev->transform.matrix.d[5]), D2F(ev->transform.matrix.d[13]), }, { D2F(ev->transform.matrix.d[3]), D2F(ev->transform.matrix.d[7]), D2F(ev->transform.matrix.d[15]), } }}; pixman_transform_invert(&surface_transform, &surface_transform); pixman_transform_multiply (&transform, &surface_transform, &transform); } else { pixman_transform_translate(&transform, NULL, pixman_double_to_fixed ((double)-ev->geometry.x), pixman_double_to_fixed ((double)-ev->geometry.y)); } if (ev->surface->buffer_viewport.scaler_set) { double scaler_x, scaler_y, scaler_width, scaler_height; double ratio_x, ratio_y; scaler_x = wl_fixed_to_double(ev->surface->buffer_viewport.src_x); scaler_y = wl_fixed_to_double(ev->surface->buffer_viewport.src_y); scaler_width = wl_fixed_to_double(ev->surface->buffer_viewport.src_width); scaler_height = wl_fixed_to_double(ev->surface->buffer_viewport.src_height); ratio_x = scaler_width / ev->surface->buffer_viewport.dst_width; ratio_y = scaler_height / ev->surface->buffer_viewport.dst_height; pixman_transform_scale(&transform, NULL, pixman_double_to_fixed(ratio_x), pixman_double_to_fixed(ratio_y)); pixman_transform_translate(&transform, NULL, pixman_double_to_fixed(scaler_x), pixman_double_to_fixed(scaler_y)); } pixman_transform_scale(&transform, NULL, pixman_double_to_fixed(ev->surface->buffer_viewport.scale), pixman_double_to_fixed(ev->surface->buffer_viewport.scale)); fw = pixman_int_to_fixed(pixman_image_get_width(ps->image)); fh = pixman_int_to_fixed(pixman_image_get_height(ps->image)); switch (ev->surface->buffer_viewport.transform) { case WL_OUTPUT_TRANSFORM_FLIPPED: case WL_OUTPUT_TRANSFORM_FLIPPED_90: case WL_OUTPUT_TRANSFORM_FLIPPED_180: case WL_OUTPUT_TRANSFORM_FLIPPED_270: pixman_transform_scale(&transform, NULL, pixman_int_to_fixed (-1), pixman_int_to_fixed (1)); pixman_transform_translate(&transform, NULL, fw, 0); break; } switch (ev->surface->buffer_viewport.transform) { default: case WL_OUTPUT_TRANSFORM_NORMAL: case WL_OUTPUT_TRANSFORM_FLIPPED: break; case WL_OUTPUT_TRANSFORM_90: case WL_OUTPUT_TRANSFORM_FLIPPED_90: pixman_transform_rotate(&transform, NULL, 0, pixman_fixed_1); pixman_transform_translate(&transform, NULL, fh, 0); break; case WL_OUTPUT_TRANSFORM_180: case WL_OUTPUT_TRANSFORM_FLIPPED_180: pixman_transform_rotate(&transform, NULL, -pixman_fixed_1, 0); pixman_transform_translate(&transform, NULL, fw, fh); break; case WL_OUTPUT_TRANSFORM_270: case WL_OUTPUT_TRANSFORM_FLIPPED_270: pixman_transform_rotate(&transform, NULL, 0, -pixman_fixed_1); pixman_transform_translate(&transform, NULL, 0, fw); break; } pixman_image_set_transform(ps->image, &transform); if (ev->transform.enabled || output->current_scale != ev->surface->buffer_viewport.scale) pixman_image_set_filter(ps->image, PIXMAN_FILTER_BILINEAR, NULL, 0); else pixman_image_set_filter(ps->image, PIXMAN_FILTER_NEAREST, NULL, 0); if (ps->buffer_ref.buffer) wl_shm_buffer_begin_access(ps->buffer_ref.buffer->shm_buffer); pixman_image_composite32(pixman_op, ps->image, /* src */ NULL /* mask */, po->shadow_image, /* dest */ 0, 0, /* src_x, src_y */ 0, 0, /* mask_x, mask_y */ 0, 0, /* dest_x, dest_y */ pixman_image_get_width (po->shadow_image), /* width */ pixman_image_get_height (po->shadow_image) /* height */); if (ps->buffer_ref.buffer) wl_shm_buffer_end_access(ps->buffer_ref.buffer->shm_buffer); if (pr->repaint_debug) pixman_image_composite32(PIXMAN_OP_OVER, pr->debug_color, /* src */ NULL /* mask */, po->shadow_image, /* dest */ 0, 0, /* src_x, src_y */ 0, 0, /* mask_x, mask_y */ 0, 0, /* dest_x, dest_y */ pixman_image_get_width (po->shadow_image), /* width */ pixman_image_get_height (po->shadow_image) /* height */); pixman_image_set_clip_region32 (po->shadow_image, NULL); pixman_region32_fini(&final_region); }
bool mSDLSWInit(struct mSDLRenderer* renderer) { #if !SDL_VERSION_ATLEAST(2, 0, 0) #ifdef COLOR_16_BIT SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 16, SDL_DOUBLEBUF | SDL_HWSURFACE); #else SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 32, SDL_DOUBLEBUF | SDL_HWSURFACE); #endif #endif unsigned width, height; renderer->core->desiredVideoDimensions(renderer->core, &width, &height); #if SDL_VERSION_ATLEAST(2, 0, 0) renderer->window = SDL_CreateWindow(projectName, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, renderer->viewportWidth, renderer->viewportHeight, SDL_WINDOW_OPENGL | (SDL_WINDOW_FULLSCREEN_DESKTOP * renderer->player.fullscreen)); SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight); renderer->player.window = renderer->window; renderer->sdlRenderer = SDL_CreateRenderer(renderer->window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); #ifdef COLOR_16_BIT #ifdef COLOR_5_6_5 renderer->sdlTex = SDL_CreateTexture(renderer->sdlRenderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING, width, height); #else renderer->sdlTex = SDL_CreateTexture(renderer->sdlRenderer, SDL_PIXELFORMAT_ABGR1555, SDL_TEXTUREACCESS_STREAMING, width, height); #endif #else renderer->sdlTex = SDL_CreateTexture(renderer->sdlRenderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, width, height); #endif int stride; SDL_LockTexture(renderer->sdlTex, 0, (void**) &renderer->outputBuffer, &stride); renderer->core->setVideoBuffer(renderer->core, renderer->outputBuffer, stride / BYTES_PER_PIXEL); #else SDL_Surface* surface = SDL_GetVideoSurface(); SDL_LockSurface(surface); if (renderer->ratio == 1) { renderer->core->setVideoBuffer(renderer->core, surface->pixels, surface->pitch / BYTES_PER_PIXEL); } else { #ifdef USE_PIXMAN renderer->outputBuffer = malloc(width * height * BYTES_PER_PIXEL); renderer->core->setVideoBuffer(renderer->core, renderer->outputBuffer, width); #ifdef COLOR_16_BIT #ifdef COLOR_5_6_5 pixman_format_code_t format = PIXMAN_r5g6b5; #else pixman_format_code_t format = PIXMAN_x1b5g5r5; #endif #else pixman_format_code_t format = PIXMAN_x8b8g8r8; #endif renderer->pix = pixman_image_create_bits(format, width, height, renderer->outputBuffer, width * BYTES_PER_PIXEL); renderer->screenpix = pixman_image_create_bits(format, renderer->viewportWidth, renderer->viewportHeight, surface->pixels, surface->pitch); pixman_transform_t transform; pixman_transform_init_identity(&transform); pixman_transform_scale(0, &transform, pixman_int_to_fixed(renderer->ratio), pixman_int_to_fixed(renderer->ratio)); pixman_image_set_transform(renderer->pix, &transform); pixman_image_set_filter(renderer->pix, PIXMAN_FILTER_NEAREST, 0, 0); #else return false; #endif } #endif return true; }
static void set_image_properties(pixman_image_t * image, PicturePtr pict, Bool has_clip, int *xoff, int *yoff, Bool is_alpha_map) { pixman_repeat_t repeat; pixman_filter_t filter; if (pict->transform) { /* For source images, adjust the transform to account * for the drawable offset within the pixman image, * then set the offset to 0 as it will be used * to compute positions within the transformed image. */ if (!has_clip) { struct pixman_transform adjusted; adjusted = *pict->transform; pixman_transform_translate(&adjusted, NULL, pixman_int_to_fixed(*xoff), pixman_int_to_fixed(*yoff)); pixman_image_set_transform(image, &adjusted); *xoff = 0; *yoff = 0; } else pixman_image_set_transform(image, pict->transform); } switch (pict->repeatType) { default: case RepeatNone: repeat = PIXMAN_REPEAT_NONE; break; case RepeatPad: repeat = PIXMAN_REPEAT_PAD; break; case RepeatNormal: repeat = PIXMAN_REPEAT_NORMAL; break; case RepeatReflect: repeat = PIXMAN_REPEAT_REFLECT; break; } pixman_image_set_repeat(image, repeat); /* Fetch alpha map unless 'pict' is being used * as the alpha map for this operation */ if (pict->alphaMap && !is_alpha_map) { int alpha_xoff, alpha_yoff; pixman_image_t *alpha_map = image_from_pict_internal(pict->alphaMap, FALSE, &alpha_xoff, &alpha_yoff, TRUE); pixman_image_set_alpha_map(image, alpha_map, pict->alphaOrigin.x, pict->alphaOrigin.y); free_pixman_pict(pict->alphaMap, alpha_map); } pixman_image_set_component_alpha(image, pict->componentAlpha); switch (pict->filter) { default: case PictFilterNearest: case PictFilterFast: filter = PIXMAN_FILTER_NEAREST; break; case PictFilterBilinear: case PictFilterGood: filter = PIXMAN_FILTER_BILINEAR; break; case PictFilterConvolution: filter = PIXMAN_FILTER_CONVOLUTION; break; } if (pict->pDrawable) pixman_image_set_destroy_function(image, &image_destroy, pict->pDrawable); pixman_image_set_filter(image, filter, (pixman_fixed_t *) pict->filter_params, pict->filter_nparams); pixman_image_set_source_clipping(image, TRUE); }