lib/igt_fb: Add igt_put_cairo_ctx as counter to igt_get_cairo_ctx

This will allow support for NV12 in the future, where igt_get_cairo_ctx
will return a RGB image to draw with, which will be converted in
igt_put_cairo_ctx so tests don't have to add special support for NV12.

This is the same as cairo_destroy + checking for errors, but not all
tests use this correctly so it's better to have a single handler for it.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
diff --git a/lib/igt_fb.c b/lib/igt_fb.c
index ded639e..39a83ba 100644
--- a/lib/igt_fb.c
+++ b/lib/igt_fb.c
@@ -771,8 +771,7 @@
 
 	cr = igt_get_cairo_ctx(fd, fb);
 	igt_paint_color(cr, 0, 0, width, height, r, g, b);
-	igt_assert(cairo_status(cr) == 0);
-	cairo_destroy(cr);
+	igt_put_cairo_ctx(fd, fb, cr);
 
 	return fb_id;
 }
@@ -809,8 +808,7 @@
 
 	cr = igt_get_cairo_ctx(fd, fb);
 	igt_paint_test_pattern(cr, width, height);
-	igt_assert(cairo_status(cr) == 0);
-	cairo_destroy(cr);
+	igt_put_cairo_ctx(fd, fb, cr);
 
 	return fb_id;
 }
@@ -853,8 +851,7 @@
 	cr = igt_get_cairo_ctx(fd, fb);
 	igt_paint_color(cr, 0, 0, width, height, r, g, b);
 	igt_paint_test_pattern(cr, width, height);
-	igt_assert(cairo_status(cr) == 0);
-	cairo_destroy(cr);
+	igt_put_cairo_ctx(fd, fb, cr);
 
 	return fb_id;
 }
@@ -897,8 +894,7 @@
 
 	cr = igt_get_cairo_ctx(fd, fb);
 	igt_paint_image(cr, filename, 0, 0, width, height);
-	igt_assert(cairo_status(cr) == 0);
-	cairo_destroy(cr);
+	igt_put_cairo_ctx(fd, fb, cr);
 
 	return fb_id;
 }
@@ -998,7 +994,7 @@
 			layout.right.x, layout.right.y,
 			layout.right.width, layout.right.height);
 
-	cairo_destroy(cr);
+	igt_put_cairo_ctx(drm_fd, &fb, cr);
 
 	return fb_id;
 }
@@ -1206,7 +1202,7 @@
  *
  * This initializes a cairo surface for @fb and then allocates a drawing context
  * for it. The return cairo drawing context should be released by calling
- * cairo_destroy(). This also sets a default font for drawing text on
+ * igt_put_cairo_ctx(). This also sets a default font for drawing text on
  * framebuffers.
  *
  * Returns:
@@ -1230,6 +1226,24 @@
 }
 
 /**
+ * igt_put_cairo_ctx:
+ * @fd: open i915 drm file descriptor
+ * @fb: pointer to an #igt_fb structure
+ * @cr: the cairo context returned by igt_get_cairo_ctx.
+ *
+ * This releases the cairo surface @cr returned by igt_get_cairo_ctx()
+ * for @fb, and writes the changes out to the framebuffer if cairo doesn't
+ * have native support for the format.
+ */
+void igt_put_cairo_ctx(int fd, struct igt_fb *fb, cairo_t *cr)
+{
+	cairo_status_t ret = cairo_status(cr);
+	igt_assert_f(ret == CAIRO_STATUS_SUCCESS, "Cairo failed to draw with %s\n", cairo_status_to_string(ret));
+
+	cairo_destroy(cr);
+}
+
+/**
  * igt_remove_fb:
  * @fd: open i915 drm file descriptor
  * @fb: pointer to an #igt_fb structure
diff --git a/lib/igt_fb.h b/lib/igt_fb.h
index d30a734..3004f06 100644
--- a/lib/igt_fb.h
+++ b/lib/igt_fb.h
@@ -131,6 +131,7 @@
 cairo_surface_t *igt_get_cairo_surface(int fd, struct igt_fb *fb);
 cairo_surface_t *igt_cairo_image_surface_create_from_png(const char *filename);
 cairo_t *igt_get_cairo_ctx(int fd, struct igt_fb *fb);
+void igt_put_cairo_ctx(int fd, struct igt_fb *fb, cairo_t *cr);
 void igt_paint_color(cairo_t *cr, int x, int y, int w, int h,
 			 double r, double g, double b);
 void igt_paint_color_alpha(cairo_t *cr, int x, int y, int w, int h,
diff --git a/tests/kms_chv_cursor_fail.c b/tests/kms_chv_cursor_fail.c
index 3e74df1..1bcf846 100644
--- a/tests/kms_chv_cursor_fail.c
+++ b/tests/kms_chv_cursor_fail.c
@@ -87,8 +87,7 @@
 	else
 		igt_paint_color_alpha(cr, 0, 0, data->fb.width, data->fb.height,
 				      0.0, 0.0, 0.0, 0.0);
-	igt_assert(cairo_status(cr) == 0);
-	cairo_destroy(cr);
+	igt_put_cairo_ctx(data->drm_fd, &data->fb, cr);
 }
 
 static void cursor_move(data_t *data, int x, int y, int i)
diff --git a/tests/kms_color.c b/tests/kms_color.c
index 3b0a888..dc4fcce 100644
--- a/tests/kms_color.c
+++ b/tests/kms_color.c
@@ -86,7 +86,7 @@
 					       colors[i].b);
 	}
 
-	cairo_destroy(cr);
+	igt_put_cairo_ctx(data->drm_fd, fb, cr);
 }
 
 static void paint_rectangles(data_t *data,
@@ -103,7 +103,7 @@
 				colors[i].r, colors[i].g, colors[i].b);
 	}
 
-	cairo_destroy(cr);
+	igt_put_cairo_ctx(data->drm_fd, fb, cr);
 }
 
 static double *generate_table(uint32_t lut_size, double exp)
diff --git a/tests/kms_concurrent.c b/tests/kms_concurrent.c
index 3b2e601..283acf8 100644
--- a/tests/kms_concurrent.c
+++ b/tests/kms_concurrent.c
@@ -148,8 +148,7 @@
 				rect_w[i], rect_h[i], 0.0, 0.0, 0.0);
 	}
 
-	igt_assert(cairo_status(cr) == 0);
-	cairo_destroy(cr);
+	igt_put_cairo_ctx(data->drm_fd, &data->fb[primary->index], cr);
 }
 
 static void
diff --git a/tests/kms_crtc_background_color.c b/tests/kms_crtc_background_color.c
index e99c67b..6407e19 100644
--- a/tests/kms_crtc_background_color.c
+++ b/tests/kms_crtc_background_color.c
@@ -69,7 +69,7 @@
 	b = (double) ((background & 0xFF0000) >> 16) / 255.0;
 	igt_paint_color_alpha(cr, 0, 0, w, h, r, g, b, alpha);
 
-	cairo_destroy(cr);
+	igt_put_cairo_ctx(data->gfx_fd, &data->fb, cr);
 }
 
 static void prepare_crtc(data_t *data, igt_output_t *output, enum pipe pipe,
diff --git a/tests/kms_cursor_crc.c b/tests/kms_cursor_crc.c
index 4c5e00c..a164839 100644
--- a/tests/kms_cursor_crc.c
+++ b/tests/kms_cursor_crc.c
@@ -141,13 +141,16 @@
 	igt_pipe_crc_t *pipe_crc = data->pipe_crc;
 	igt_crc_t crc, ref_crc;
 	igt_plane_t *cursor;
-	cairo_t *cr = igt_get_cairo_ctx(data->drm_fd, &data->primary_fb);
+	cairo_t *cr;
 	int ret = 0;
 
 	igt_print_activity();
 
 	/* Hardware test */
+	cr = igt_get_cairo_ctx(data->drm_fd, &data->primary_fb);
 	igt_paint_test_pattern(cr, data->screenw, data->screenh);
+	igt_put_cairo_ctx(data->drm_fd, &data->primary_fb, cr);
+
 	cursor_enable(data);
 	cursor = igt_output_get_plane_type(data->output, DRM_PLANE_TYPE_CURSOR);
 	igt_plane_set_position(cursor, x, y);
@@ -190,7 +193,9 @@
 	igt_display_commit(display);
 
 	/* Now render the same in software and collect crc */
+	cr = igt_get_cairo_ctx(data->drm_fd, &data->primary_fb);
 	draw_cursor(cr, x, y, data->curw, data->curh);
+	igt_put_cairo_ctx(data->drm_fd, &data->primary_fb, cr);
 	igt_display_commit(display);
 
 	igt_wait_for_vblank(data->drm_fd, data->pipe);
@@ -198,20 +203,25 @@
 	igt_assert_crc_equal(&crc, &ref_crc);
 
 	/* Clear screen afterwards */
+	cr = igt_get_cairo_ctx(data->drm_fd, &data->primary_fb);
 	igt_paint_color(cr, 0, 0, data->screenw, data->screenh, 0.0, 0.0, 0.0);
+	igt_put_cairo_ctx(data->drm_fd, &data->primary_fb, cr);
 }
 
 static void do_fail_test(data_t *data, int x, int y, int expect)
 {
 	igt_display_t *display = &data->display;
 	igt_plane_t *cursor;
-	cairo_t *cr = igt_get_cairo_ctx(data->drm_fd, &data->primary_fb);
+	cairo_t *cr;
 	int ret;
 
 	igt_print_activity();
 
 	/* Hardware test */
+	cr = igt_get_cairo_ctx(data->drm_fd, &data->primary_fb);
 	igt_paint_test_pattern(cr, data->screenw, data->screenh);
+	igt_put_cairo_ctx(data->drm_fd, &data->primary_fb, cr);
+
 	cursor_enable(data);
 	cursor = igt_output_get_plane_type(data->output, DRM_PLANE_TYPE_CURSOR);
 	igt_plane_set_position(cursor, x, y);
@@ -446,7 +456,7 @@
 
 	cr = igt_get_cairo_ctx(data->drm_fd, &data->fb);
 	draw_cursor(cr, 0, 0, cur_w, cur_h);
-	igt_assert(cairo_status(cr) == 0);
+	igt_put_cairo_ctx(data->drm_fd, &data->fb, cr);
 }
 
 static bool has_nonsquare_cursors(uint32_t devid)
@@ -486,6 +496,7 @@
 	/* Use a solid white rectangle as the cursor */
 	cr = igt_get_cairo_ctx(data->drm_fd, &data->fb);
 	igt_paint_color_alpha(cr, 0, 0, cursor_max_size, cursor_max_size, 1.0, 1.0, 1.0, 1.0);
+	igt_put_cairo_ctx(data->drm_fd, &data->fb, cr);
 
 	/* Hardware test loop */
 	cursor_enable(data);
@@ -501,16 +512,20 @@
 	}
 	cursor_disable(data);
 	/* Software test loop */
-	cr = igt_get_cairo_ctx(data->drm_fd, &data->primary_fb);
 	for (i = 0, size = cursor_max_size; size >= 64; size /= 2, i++) {
 		/* Now render the same in software and collect crc */
+		cr = igt_get_cairo_ctx(data->drm_fd, &data->primary_fb);
 		igt_paint_color_alpha(cr, 0, 0, size, size, 1.0, 1.0, 1.0, 1.0);
+		igt_put_cairo_ctx(data->drm_fd, &data->primary_fb, cr);
+
 		igt_display_commit(display);
 		igt_wait_for_vblank(data->drm_fd, data->pipe);
 		igt_pipe_crc_collect_crc(pipe_crc, &ref_crc);
 		/* Clear screen afterwards */
+		cr = igt_get_cairo_ctx(data->drm_fd, &data->primary_fb);
 		igt_paint_color(cr, 0, 0, data->screenw, data->screenh,
 				0.0, 0.0, 0.0);
+		igt_put_cairo_ctx(data->drm_fd, &data->primary_fb, cr);
 		igt_assert_crc_equal(&crc[i], &ref_crc);
 	}
 }
diff --git a/tests/kms_flip.c b/tests/kms_flip.c
index 710ea52..b43e771 100644
--- a/tests/kms_flip.c
+++ b/tests/kms_flip.c
@@ -976,8 +976,7 @@
 	cairo_set_source_rgb(cr, 1, 1, 1);
 	cairo_fill(cr);
 
-	igt_assert(!cairo_status(cr));
-	cairo_destroy(cr);
+	igt_put_cairo_ctx(drm_fd, fb, cr);
 }
 
 static int
diff --git a/tests/kms_mmap_write_crc.c b/tests/kms_mmap_write_crc.c
index dd44ce9..279d0f6 100644
--- a/tests/kms_mmap_write_crc.c
+++ b/tests/kms_mmap_write_crc.c
@@ -92,7 +92,7 @@
 
 	cr = igt_get_cairo_ctx(data->drm_fd, fb);
 	igt_paint_test_pattern(cr, fb->width, fb->height);
-	cairo_destroy(cr);
+	igt_put_cairo_ctx(data->drm_fd, fb, cr);
 
 	/* flip to it to make it UC/WC and fully flushed */
 	igt_plane_set_fb(data->primary, fb);
@@ -135,7 +135,7 @@
 	 * fully flushed */
 	cr = igt_get_cairo_ctx(data->drm_fd, fb);
 	igt_paint_test_pattern(cr, fb->width, fb->height);
-	cairo_destroy(cr);
+	igt_put_cairo_ctx(data->drm_fd, fb, cr);
 
 	igt_plane_set_fb(data->primary, fb);
 	igt_display_commit(display);
diff --git a/tests/kms_plane.c b/tests/kms_plane.c
index 9672763..54bcffc 100644
--- a/tests/kms_plane.c
+++ b/tests/kms_plane.c
@@ -138,8 +138,7 @@
 	igt_paint_color(cr, 0, 0, mode->hdisplay, mode->vdisplay,
 			    0.0, 1.0, 0.0);
 	igt_paint_color(cr, rect_x, rect_y, rect_w, rect_h, 0.0, 0.0, 0.0);
-	igt_assert(cairo_status(cr) == 0);
-	cairo_destroy(cr);
+	igt_put_cairo_ctx(data->drm_fd, fb, cr);
 }
 
 enum {
@@ -279,8 +278,7 @@
 			mode->hdisplay, mode->vdisplay,
 			0.0, 0.0, 1.0);
 
-	igt_assert(cairo_status(cr) == 0);
-	cairo_destroy(cr);
+	igt_put_cairo_ctx(data->drm_fd, fb, cr);
 }
 
 enum {
@@ -436,8 +434,7 @@
 				0.0, 1.0, 0.0);
 		if (width >= 164 && height >= 164)
 			igt_paint_color(cr, 100, 100, 64, 64, 0.0, 0.0, 0.0);
-		igt_assert(cairo_status(cr) == 0);
-		cairo_destroy(cr);
+		igt_put_cairo_ctx(data->drm_fd, &fb, cr);
 
 		igt_plane_set_fb(plane, &fb);
 		igt_display_commit2(&data->display, COMMIT_UNIVERSAL);
diff --git a/tests/kms_plane_multiple.c b/tests/kms_plane_multiple.c
index aea59df..95b7138 100644
--- a/tests/kms_plane_multiple.c
+++ b/tests/kms_plane_multiple.c
@@ -173,8 +173,7 @@
 				rect_w[i], rect_h[i], 0.0, 0.0, 0.0);
 		}
 
-	igt_assert(cairo_status(cr) == 0);
-	cairo_destroy(cr);
+	igt_put_cairo_ctx(data->drm_fd, &data->fb[primary->index], cr);
 }
 
 
diff --git a/tests/kms_plane_scaling.c b/tests/kms_plane_scaling.c
index c8283a3..d32f344 100644
--- a/tests/kms_plane_scaling.c
+++ b/tests/kms_plane_scaling.c
@@ -120,8 +120,7 @@
 
 	cr = igt_get_cairo_ctx(d->drm_fd, fb);
 	igt_paint_color(cr, 0, 0, fb->width, fb->height, 0.0, 1.0, 0.0);
-	igt_assert(cairo_status(cr) == 0);
-	cairo_destroy(cr);
+	igt_put_cairo_ctx(d->drm_fd, fb, cr);
 }
 
 static void check_scaling_pipe_plane_rot(data_t *d, igt_plane_t *plane,
diff --git a/tests/kms_psr_sink_crc.c b/tests/kms_psr_sink_crc.c
index 26cf434..2b60acf 100644
--- a/tests/kms_psr_sink_crc.c
+++ b/tests/kms_psr_sink_crc.c
@@ -91,7 +91,7 @@
 
 	cr = igt_get_cairo_ctx(data->drm_fd, &data->fb_white);
 	igt_paint_color_alpha(cr, 0, 0, 64, 64, 1.0, 1.0, 1.0, 1.0);
-	igt_assert(cairo_status(cr) == 0);
+	igt_put_cairo_ctx(data->drm_fd, &data->fb_white, cr);
 }
 
 
diff --git a/tests/kms_rotation_crc.c b/tests/kms_rotation_crc.c
index 799cf11..5b190a0 100644
--- a/tests/kms_rotation_crc.c
+++ b/tests/kms_rotation_crc.c
@@ -120,7 +120,7 @@
 	igt_paint_color(cr, 0, h / 2, w / 2, h / 2, RGB_COLOR(bl));
 	igt_paint_color(cr, w / 2, h / 2, w / 2, h / 2, RGB_COLOR(br));
 
-	cairo_destroy(cr);
+	igt_put_cairo_ctx(data->gfx_fd, fb, cr);
 }
 
 static void prepare_crtc(data_t *data, igt_output_t *output, enum pipe pipe,
diff --git a/tests/kms_setmode.c b/tests/kms_setmode.c
index 206d360..06241b1 100644
--- a/tests/kms_setmode.c
+++ b/tests/kms_setmode.c
@@ -161,7 +161,7 @@
 					  crtc_str[i]);
 	}
 
-	cairo_destroy(cr);
+	igt_put_cairo_ctx(drm_fd, fb, cr);
 
 	return 0;
 }
diff --git a/tests/testdisplay.c b/tests/testdisplay.c
index b0156c5..0ff98a2 100644
--- a/tests/testdisplay.c
+++ b/tests/testdisplay.c
@@ -227,9 +227,7 @@
 	cairo_set_source_rgb(cr, .8, .8, .8);
 	cairo_fill(cr);
 
-	igt_assert(!cairo_status(cr));
-
-	cairo_destroy(cr);
+	igt_put_cairo_ctx(drm_fd, fb_info, cr);
 }
 
 static void paint_image(cairo_t *cr, const char *file)
@@ -294,9 +292,7 @@
 	if (qr_code)
 		paint_image(cr, "pass.png");
 
-	igt_assert(!cairo_status(cr));
-
-	cairo_destroy(cr);
+	igt_put_cairo_ctx(drm_fd, fb, cr);
 }
 
 static void sighandler(int signo)