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>
This commit is contained in:
Chris Wilson 2013-12-30 17:48:43 +00:00
parent 9d6cfa6b59
commit 164d9d26ac
11 changed files with 48 additions and 37 deletions

View File

@ -368,31 +368,43 @@ static cairo_format_t drm_format_to_cairo(uint32_t drm_format)
abort(); 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; struct kmstest_fb *fb = arg;
cairo_format_t cformat; munmap(cairo_image_surface_get_data(fb->cairo_surface), fb->size);
void *fb_ptr;
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);
return surface;
} }
static cairo_t *create_cairo_ctx(int fd, struct kmstest_fb *fb) cairo_surface_t *kmstest_get_cairo_surface(int fd, struct kmstest_fb *fb)
{ {
cairo_t *cr; if (fb->cairo_surface == NULL) {
cairo_surface_t *surface; 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);
surface = create_image_surface(fd, fb); cairo_surface_set_user_data(fb->cairo_surface,
(cairo_user_data_key_t *)kmstest_get_cairo_surface,
fb, __kmstest_destroy_cairo_surface);
}
gem_set_domain(fd, fb->gem_handle,
I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
igt_assert(cairo_surface_status(fb->cairo_surface) == CAIRO_STATUS_SUCCESS);
return cairo_surface_reference(fb->cairo_surface);
}
cairo_t *kmstest_get_cairo_ctx(int fd, struct kmstest_fb *fb)
{
cairo_surface_t *surface;
cairo_t *cr;
surface = kmstest_get_cairo_surface(fd, fb);
cr = cairo_create(surface); cr = cairo_create(surface);
cairo_surface_destroy(surface); cairo_surface_destroy(surface);
igt_assert(cairo_status(cr) == CAIRO_STATUS_SUCCESS);
return cr; return cr;
} }
@ -401,28 +413,16 @@ void kmstest_write_fb(int fd, struct kmstest_fb *fb, const char *filename)
cairo_surface_t *surface; cairo_surface_t *surface;
cairo_status_t status; 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); status = cairo_surface_write_to_png(surface, filename);
assert(status == CAIRO_STATUS_SUCCESS);
cairo_surface_destroy(surface); cairo_surface_destroy(surface);
}
cairo_t *kmstest_get_cairo_ctx(int fd, struct kmstest_fb *fb) igt_assert(status == CAIRO_STATUS_SUCCESS);
{
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;
} }
void kmstest_remove_fb(int fd, struct kmstest_fb *fb) void kmstest_remove_fb(int fd, struct kmstest_fb *fb)
{ {
if (fb->cairo_ctx) cairo_surface_destroy(fb->cairo_surface);
cairo_destroy(fb->cairo_ctx);
do_or_die(drmModeRmFB(fd, fb->fb_id)); do_or_die(drmModeRmFB(fd, fb->fb_id));
gem_close(fd, fb->gem_handle); gem_close(fd, fb->gem_handle);
} }

View File

@ -54,7 +54,7 @@ struct kmstest_fb {
unsigned stride; unsigned stride;
unsigned tiling; unsigned tiling;
unsigned size; unsigned size;
cairo_t *cairo_ctx; cairo_surface_t *cairo_surface;
}; };
enum kmstest_text_align { enum kmstest_text_align {
@ -77,6 +77,7 @@ unsigned int kmstest_create_fb2(int fd, int width, int height, uint32_t format,
bool tiled, struct kmstest_fb *fb); bool tiled, struct kmstest_fb *fb);
void kmstest_remove_fb(int fd, struct kmstest_fb *fb_info); void kmstest_remove_fb(int fd, struct kmstest_fb *fb_info);
cairo_t *kmstest_get_cairo_ctx(int fd, struct kmstest_fb *fb); cairo_t *kmstest_get_cairo_ctx(int fd, struct kmstest_fb *fb);
cairo_surface_t *kmstest_get_cairo_surface(int fd, struct kmstest_fb *fb);
void kmstest_paint_color(cairo_t *cr, int x, int y, int w, int h, void kmstest_paint_color(cairo_t *cr, int x, int y, int w, int h,
double r, double g, double b); double r, double g, double b);
void kmstest_paint_color_alpha(cairo_t *cr, int x, int y, int w, int h, void kmstest_paint_color_alpha(cairo_t *cr, int x, int y, int w, int h,

View File

@ -87,6 +87,7 @@ connector_set_mode(data_t *data, connector_t *connector, drmModeModeInfo *mode)
kmstest_paint_color(cr, 0, 0, mode->hdisplay, mode->vdisplay, kmstest_paint_color(cr, 0, 0, mode->hdisplay, mode->vdisplay,
0.0, 0.0, 0.0); 0.0, 0.0, 0.0);
igt_assert(cairo_status(cr) == 0); igt_assert(cairo_status(cr) == 0);
cairo_destroy(cr);
#if 0 #if 0
fprintf(stdout, "Using pipe %c, %dx%d\n", pipe_name(config->pipe), fprintf(stdout, "Using pipe %c, %dx%d\n", pipe_name(config->pipe),

View File

@ -105,6 +105,7 @@ static uint32_t create_fb(data_t *data,
cr = kmstest_get_cairo_ctx(data->drm_fd, fb); cr = kmstest_get_cairo_ctx(data->drm_fd, fb);
kmstest_paint_color(cr, 0, 0, w, h, r, g, b); kmstest_paint_color(cr, 0, 0, w, h, r, g, b);
igt_assert(cairo_status(cr) == 0); igt_assert(cairo_status(cr) == 0);
cairo_destroy(cr);
return fb_id; return fb_id;
} }

View File

@ -1003,6 +1003,7 @@ static void paint_flip_mode(struct kmstest_fb *fb, bool odd_frame)
cairo_fill(cr); cairo_fill(cr);
igt_assert(!cairo_status(cr)); igt_assert(!cairo_status(cr));
cairo_destroy(cr);
} }
static int static int

View File

@ -100,6 +100,7 @@ connector_set_mode(data_t *data, connector_t *connector, drmModeModeInfo *mode)
kmstest_paint_color(cr, 0, 0, mode->hdisplay, mode->vdisplay, kmstest_paint_color(cr, 0, 0, mode->hdisplay, mode->vdisplay,
0.0, 1.0, 0.0); 0.0, 1.0, 0.0);
igt_assert(cairo_status(cr) == 0); igt_assert(cairo_status(cr) == 0);
cairo_destroy(cr);
#if 0 #if 0
fprintf(stdout, "Using pipe %c, %dx%d\n", pipe_name(config->pipe), fprintf(stdout, "Using pipe %c, %dx%d\n", pipe_name(config->pipe),

View File

@ -55,8 +55,6 @@ static int paint_fb(struct kmstest_fb *fb, const char *test_name,
cairo_t *cr; cairo_t *cr;
cr = kmstest_get_cairo_ctx(drm_fd, fb); cr = kmstest_get_cairo_ctx(drm_fd, fb);
if (!cr)
return -1;
kmstest_paint_color_gradient(cr, 0, 0, fb->width, fb->height, 1, 1, 1); kmstest_paint_color_gradient(cr, 0, 0, fb->width, fb->height, 1, 1, 1);
kmstest_paint_test_pattern(cr, fb->width, fb->height); kmstest_paint_test_pattern(cr, fb->width, fb->height);
@ -69,6 +67,8 @@ static int paint_fb(struct kmstest_fb *fb, const char *test_name,
kmstest_cairo_printf_line(cr, align_hcenter, 10, "%s", mode_format_str); kmstest_cairo_printf_line(cr, align_hcenter, 10, "%s", mode_format_str);
kmstest_cairo_printf_line(cr, align_hcenter, 10, "%s", cconf_str); kmstest_cairo_printf_line(cr, align_hcenter, 10, "%s", cconf_str);
cairo_destroy(cr);
return 0; return 0;
} }

View File

@ -151,8 +151,6 @@ static int paint_fb(struct kmstest_fb *fb, const char *test_name,
int i; int i;
cr = kmstest_get_cairo_ctx(drm_fd, fb); cr = kmstest_get_cairo_ctx(drm_fd, fb);
if (!cr)
return -1;
kmstest_paint_test_pattern(cr, fb->width, fb->height); kmstest_paint_test_pattern(cr, fb->width, fb->height);
@ -176,6 +174,8 @@ static int paint_fb(struct kmstest_fb *fb, const char *test_name,
crtc_str[i]); crtc_str[i]);
} }
cairo_destroy(cr);
return 0; return 0;
} }

View File

@ -97,6 +97,8 @@ static uint32_t create_fb(int drm_fd, int width, int height)
&fb); &fb);
cr = kmstest_get_cairo_ctx(drm_fd, &fb); cr = kmstest_get_cairo_ctx(drm_fd, &fb);
kmstest_paint_test_pattern(cr, width, height); kmstest_paint_test_pattern(cr, width, height);
cairo_destroy(cr);
return buffer_id; return buffer_id;
} }

View File

@ -280,6 +280,8 @@ static struct scanout_fb *create_fb(struct mode_set_data *data, int width,
cr = kmstest_get_cairo_ctx(drm_fd, &fb); cr = kmstest_get_cairo_ctx(drm_fd, &fb);
kmstest_paint_test_pattern(cr, width, height); kmstest_paint_test_pattern(cr, width, height);
cairo_destroy(cr);
return fb_info; return fb_info;
} }

View File

@ -507,6 +507,8 @@ static uint32_t create_stereo_fb(drmModeModeInfo *mode, struct kmstest_fb *fb)
layout.right.x, layout.right.y, layout.right.x, layout.right.y,
layout.right.width, layout.right.height); layout.right.width, layout.right.height);
cairo_destroy(cr);
{ {
char buffer[64]; char buffer[64];