struct client *client;
struct wl_surface *surface;
struct surface *screenshot = NULL;
- struct surface *reference_good = NULL;
- struct surface *reference_bad = NULL;
+ pixman_image_t *reference_good = NULL;
+ pixman_image_t *reference_bad = NULL;
struct rectangle clip;
const char *fname;
bool match = false;
/* Load good reference image */
fname = screenshot_reference_filename("internal-screenshot-good", 0);
printf("Loading good reference image %s\n", fname);
- reference_good = load_surface_from_png(fname);
+ reference_good = load_image_from_png(fname);
assert(reference_good);
/* Load bad reference image */
fname = screenshot_reference_filename("internal-screenshot-bad", 0);
printf("Loading bad reference image %s\n", fname);
- reference_bad = load_surface_from_png(fname);
+ reference_bad = load_image_from_png(fname);
assert(reference_bad);
/* Test check_images_match() without a clip.
* We expect this to fail since we use a bad reference image
*/
match = check_images_match(screenshot->buffer->image,
- reference_bad->buffer->image, NULL);
+ reference_bad, NULL);
printf("Screenshot %s reference image\n", match? "equal to" : "different from");
assert(!match);
- buffer_destroy(reference_bad->buffer);
- free(reference_bad);
+ pixman_image_unref(reference_bad);
/* Test check_images_match() with clip.
* Alpha-blending and other effects can cause irrelevant discrepancies, so look only
clip.height = 100;
printf("Clip: %d,%d %d x %d\n", clip.x, clip.y, clip.width, clip.height);
match = check_images_match(screenshot->buffer->image,
- reference_good->buffer->image,
- &clip);
+ reference_good, &clip);
printf("Screenshot %s reference image in clipped area\n", match? "matches" : "doesn't match");
- buffer_destroy(reference_good->buffer);
- free(reference_good);
+ pixman_image_unref(reference_good);
/* Test dumping of non-matching images */
if (!match || dump_all_images) {
return filename;
}
+struct format_map_entry {
+ cairo_format_t cairo;
+ pixman_format_code_t pixman;
+};
+
+static const struct format_map_entry format_map[] = {
+ { CAIRO_FORMAT_ARGB32, PIXMAN_a8r8g8b8 },
+ { CAIRO_FORMAT_RGB24, PIXMAN_x8r8g8b8 },
+ { CAIRO_FORMAT_A8, PIXMAN_a8 },
+ { CAIRO_FORMAT_RGB16_565, PIXMAN_r5g6b5 },
+};
+
+static pixman_format_code_t
+format_cairo2pixman(cairo_format_t fmt)
+{
+ unsigned i;
+
+ for (i = 0; i < ARRAY_LENGTH(format_map); i++)
+ if (format_map[i].cairo == fmt)
+ return format_map[i].pixman;
+
+ assert(0 && "unknown Cairo pixel format");
+}
+
/**
* Compute the ROI for image comparisons
*
return true;
}
-/** load_surface_from_png()
+static pixman_image_t *
+image_convert_to_a8r8g8b8(pixman_image_t *image)
+{
+ pixman_image_t *ret;
+ int width;
+ int height;
+
+ if (pixman_image_get_format(image) == PIXMAN_a8r8g8b8)
+ return pixman_image_ref(image);
+
+ width = pixman_image_get_width(image);
+ height = pixman_image_get_height(image);
+
+ ret = pixman_image_create_bits_no_clear(PIXMAN_a8r8g8b8, width, height,
+ NULL, 0);
+ assert(ret);
+
+ pixman_image_composite32(PIXMAN_OP_SRC, image, NULL, ret,
+ 0, 0, 0, 0, 0, 0, width, height);
+
+ return ret;
+}
+
+static void
+destroy_cairo_surface(pixman_image_t *image, void *data)
+{
+ cairo_surface_t *surface = data;
+
+ cairo_surface_destroy(surface);
+}
+
+/**
+ * Load an image from a PNG file
*
* Reads a PNG image from disk using the given filename (and path)
- * and returns as a freshly allocated weston test surface.
+ * and returns as a Pixman image. Use pixman_image_unref() to free it.
+ *
+ * The returned image is always in PIXMAN_a8r8g8b8 format.
*
- * @returns weston test surface with image, which should be free'd
- * when no longer used; or, NULL in case of error.
+ * @returns Pixman image, or NULL in case of error.
*/
-struct surface *
-load_surface_from_png(const char *fname)
+pixman_image_t *
+load_image_from_png(const char *fname)
{
- struct surface *reference;
+ pixman_image_t *image;
+ pixman_image_t *converted;
+ cairo_format_t cairo_fmt;
+ pixman_format_code_t pixman_fmt;
cairo_surface_t *reference_cairo_surface;
cairo_status_t status;
- size_t source_data_size;
- int bpp;
+ int width;
+ int height;
int stride;
+ void *data;
reference_cairo_surface = cairo_image_surface_create_from_png(fname);
+ cairo_surface_flush(reference_cairo_surface);
status = cairo_surface_status(reference_cairo_surface);
if (status != CAIRO_STATUS_SUCCESS) {
printf("Could not open %s: %s\n", fname, cairo_status_to_string(status));
return NULL;
}
- /* Disguise the cairo surface in a weston test surface */
- reference = zalloc(sizeof *reference);
- if (reference == NULL) {
- perror("zalloc reference");
- cairo_surface_destroy(reference_cairo_surface);
- return NULL;
- }
- reference->width = cairo_image_surface_get_width(reference_cairo_surface);
- reference->height = cairo_image_surface_get_height(reference_cairo_surface);
- stride = cairo_image_surface_get_stride(reference_cairo_surface);
- source_data_size = stride * reference->height;
+ cairo_fmt = cairo_image_surface_get_format(reference_cairo_surface);
+ pixman_fmt = format_cairo2pixman(cairo_fmt);
- /* Check that the file's stride matches our assumption */
- bpp = 4;
- if (stride != bpp * reference->width) {
- printf("Mismatched stride for screenshot reference image %s\n", fname);
- cairo_surface_destroy(reference_cairo_surface);
- free(reference);
- return NULL;
- }
+ width = cairo_image_surface_get_width(reference_cairo_surface);
+ height = cairo_image_surface_get_height(reference_cairo_surface);
+ stride = cairo_image_surface_get_stride(reference_cairo_surface);
+ data = cairo_image_surface_get_data(reference_cairo_surface);
- /* Allocate new buffer for our weston reference, and copy the data from
- the cairo surface so we can destroy it */
+ /* The Cairo surface will own the data, so we keep it around. */
+ image = pixman_image_create_bits_no_clear(pixman_fmt,
+ width, height, data, stride);
+ assert(image);
- reference->buffer = xzalloc(sizeof *reference->buffer);
- reference->buffer->image = pixman_image_create_bits(PIXMAN_a8r8g8b8,
- reference->width,
- reference->height,
- NULL, 0);
- assert(reference->buffer->image);
+ pixman_image_set_destroy_function(image, destroy_cairo_surface,
+ reference_cairo_surface);
- memcpy(pixman_image_get_data(reference->buffer->image),
- cairo_image_surface_get_data(reference_cairo_surface),
- source_data_size);
+ converted = image_convert_to_a8r8g8b8(image);
+ pixman_image_unref(image);
- cairo_surface_destroy(reference_cairo_surface);
- return reference;
+ return converted;
}
/** create_screenshot_surface()