summaryrefslogtreecommitdiff
path: root/lib/igt_kms.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2013-12-30 17:48:43 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2013-12-31 12:30:30 +0000
commit164d9d26ac33029287a24fbed549e3a2858d5d51 (patch)
tree717c811f7481611406b794ad82d6a5c1446360a3 /lib/igt_kms.c
parent9d6cfa6b59d0c22cf772ca71069f9e5f3e53d055 (diff)
kmstest: Fix up lifetimes of cairo objects
cairo_t is the short lived drawing context, whereas cairo_surface_t is the heavyweight object that persists and is also tied to underlying GEM objects. So make the kmstest API reflect the different weights and fix the lifetime and underlying object reference leaks. Based on the fix by Paulo Zanoni. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'lib/igt_kms.c')
-rw-r--r--lib/igt_kms.c58
1 files changed, 29 insertions, 29 deletions
diff --git a/lib/igt_kms.c b/lib/igt_kms.c
index 57795b16..3960d24f 100644
--- a/lib/igt_kms.c
+++ b/lib/igt_kms.c
@@ -368,31 +368,43 @@ static cairo_format_t drm_format_to_cairo(uint32_t drm_format)
abort();
}
-static cairo_surface_t *create_image_surface(int fd, struct kmstest_fb *fb)
+static void __kmstest_destroy_cairo_surface(void *arg)
{
- cairo_surface_t *surface;
- cairo_format_t cformat;
- void *fb_ptr;
+ struct kmstest_fb *fb = arg;
+ munmap(cairo_image_surface_get_data(fb->cairo_surface), fb->size);
+}
+
+cairo_surface_t *kmstest_get_cairo_surface(int fd, struct kmstest_fb *fb)
+{
+ if (fb->cairo_surface == NULL) {
+ fb->cairo_surface =
+ cairo_image_surface_create_for_data(gem_mmap(fd, fb->gem_handle, fb->size, PROT_READ | PROT_WRITE),
+ drm_format_to_cairo(fb->drm_format),
+ fb->width, fb->height, fb->stride);
+
+ cairo_surface_set_user_data(fb->cairo_surface,
+ (cairo_user_data_key_t *)kmstest_get_cairo_surface,
+ fb, __kmstest_destroy_cairo_surface);
+ }
- cformat = drm_format_to_cairo(fb->drm_format);
- fb_ptr = gem_mmap(fd, fb->gem_handle, fb->size, PROT_READ | PROT_WRITE);
- surface = cairo_image_surface_create_for_data((unsigned char *)fb_ptr,
- cformat, fb->width,
- fb->height, fb->stride);
- assert(surface);
+ gem_set_domain(fd, fb->gem_handle,
+ I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
- return surface;
+ igt_assert(cairo_surface_status(fb->cairo_surface) == CAIRO_STATUS_SUCCESS);
+ return cairo_surface_reference(fb->cairo_surface);
}
-static cairo_t *create_cairo_ctx(int fd, struct kmstest_fb *fb)
+cairo_t *kmstest_get_cairo_ctx(int fd, struct kmstest_fb *fb)
{
- cairo_t *cr;
cairo_surface_t *surface;
+ cairo_t *cr;
- surface = create_image_surface(fd, fb);
+ surface = kmstest_get_cairo_surface(fd, fb);
cr = cairo_create(surface);
cairo_surface_destroy(surface);
+ igt_assert(cairo_status(cr) == CAIRO_STATUS_SUCCESS);
+
return cr;
}
@@ -401,28 +413,16 @@ void kmstest_write_fb(int fd, struct kmstest_fb *fb, const char *filename)
cairo_surface_t *surface;
cairo_status_t status;
- surface = create_image_surface(fd, fb);
+ surface = kmstest_get_cairo_surface(fd, fb);
status = cairo_surface_write_to_png(surface, filename);
- assert(status == CAIRO_STATUS_SUCCESS);
cairo_surface_destroy(surface);
-}
-
-cairo_t *kmstest_get_cairo_ctx(int fd, struct kmstest_fb *fb)
-{
-
- if (!fb->cairo_ctx)
- fb->cairo_ctx = create_cairo_ctx(fd, fb);
-
- gem_set_domain(fd, fb->gem_handle, I915_GEM_DOMAIN_CPU,
- I915_GEM_DOMAIN_CPU);
- return fb->cairo_ctx;
+ igt_assert(status == CAIRO_STATUS_SUCCESS);
}
void kmstest_remove_fb(int fd, struct kmstest_fb *fb)
{
- if (fb->cairo_ctx)
- cairo_destroy(fb->cairo_ctx);
+ cairo_surface_destroy(fb->cairo_surface);
do_or_die(drmModeRmFB(fd, fb->fb_id));
gem_close(fd, fb->gem_handle);
}