what a huge patch... but hopefully I haven' t missed anything. Feel free to use Reviewed-by: Rodrigo Vivi <rodrigo.vivi at gmail.com> On Fri, May 31, 2013 at 6:23 AM, Imre Deak <imre.deak at intel.com> wrote: > Factor out parts that will be used by an upcoming patch adding > kmstest_create_fb2. > > Also call the fb paint functions directly, there is not much > point in passing a function pointer for that. > > Signed-off-by: Imre Deak <imre.deak at intel.com> > --- > lib/drmtest.c | 176 ++++++++++++++++++++++++++++++++-------------------- > lib/drmtest.h | 15 +++-- > tests/kms_flip.c | 30 +++++---- > tests/testdisplay.c | 15 +++-- > 4 files changed, 147 insertions(+), 89 deletions(-) > > diff --git a/lib/drmtest.c b/lib/drmtest.c > index 7368077..a551e7c 100644 > --- a/lib/drmtest.c > +++ b/lib/drmtest.c > @@ -39,6 +39,7 @@ > #include <getopt.h> > #include <stdlib.h> > #include <linux/kd.h> > +#include <drm/drm_fourcc.h> > > #include "drmtest.h" > #include "i915_drm.h" > @@ -788,16 +789,14 @@ void drmtest_cleanup_aperture_trashers(void) > } > > /* helpers to create nice-looking framebuffers */ > -static cairo_surface_t * > -paint_allocate_surface(int fd, int width, int height, int depth, int bpp, > - bool tiled, > - struct kmstest_fb *fb_info) > +static int create_bo_for_fb(int fd, int width, int height, int bpp, > + bool tiled, uint32_t *gem_handle_ret, > + unsigned *size_ret, unsigned *stride_ret) > { > - cairo_format_t format; > struct drm_i915_gem_set_tiling set_tiling; > + uint32_t gem_handle; > int size; > unsigned stride; > - uint32_t *fb_ptr; > > if (tiled) { > int v; > @@ -823,49 +822,24 @@ paint_allocate_surface(int fd, int width, int height, int depth, int bpp, > size = stride * height; > } > > - switch (depth) { > - case 16: > - format = CAIRO_FORMAT_RGB16_565; > - break; > - case 24: > - format = CAIRO_FORMAT_RGB24; > - break; > -#if 0 > - case 30: > - format = CAIRO_FORMAT_RGB30; > - break; > -#endif > - case 32: > - format = CAIRO_FORMAT_ARGB32; > - break; > - default: > - fprintf(stderr, "bad depth %d\n", depth); > - return NULL; > - } > - > - assert (bpp >= depth); > - > - fb_info->gem_handle = gem_create(fd, size); > + gem_handle = gem_create(fd, size); > > if (tiled) { > - set_tiling.handle = fb_info->gem_handle; > + set_tiling.handle = gem_handle; > set_tiling.tiling_mode = I915_TILING_X; > set_tiling.stride = stride; > if (ioctl(fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling)) { > fprintf(stderr, "set tiling failed: %s (stride=%d, size=%d)\n", > strerror(errno), stride, size); > - return NULL; > + return -1; > } > } > > - fb_ptr = gem_mmap(fd, fb_info->gem_handle, size, PROT_READ | PROT_WRITE); > - > - fb_info->stride = stride; > - fb_info->size = size; > + *stride_ret = stride; > + *size_ret = size; > + *gem_handle_ret = gem_handle; > > - return cairo_image_surface_create_for_data((unsigned char *)fb_ptr, > - format, width, height, > - stride); > + return 0; > } > > static void > @@ -981,23 +955,8 @@ paint_marker(cairo_t *cr, int x, int y) > kmstest_cairo_printf_line(cr, align, 0, "(%d, %d)", x, y); > } > > -unsigned int kmstest_create_fb(int fd, int width, int height, int bpp, > - int depth, bool tiled, > - struct kmstest_fb *fb_info, > - kmstest_paint_func paint_func, > - void *func_arg) > +void kmstest_paint_test_pattern(cairo_t *cr, int width, int height) > { > - cairo_surface_t *surface; > - cairo_status_t status; > - cairo_t *cr; > - unsigned int fb_id; > - > - surface = paint_allocate_surface(fd, width, height, depth, bpp, > - tiled, fb_info); > - assert(surface); > - > - cr = cairo_create(surface); > - > paint_test_patterns(cr, width, height); > > cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE); > @@ -1008,27 +967,112 @@ unsigned int kmstest_create_fb(int fd, int width, int height, int bpp, > paint_marker(cr, 0, height); > paint_marker(cr, width, height); > > - if (paint_func) > - paint_func(cr, width, height, func_arg); > + assert(!cairo_status(cr)); > +} > + > +#define DF(did, cid, _bpp, _depth) \ > + { DRM_FORMAT_##did, CAIRO_FORMAT_##cid, # did, _bpp, _depth } > +static struct format_desc_struct { > + uint32_t drm_id; > + cairo_format_t cairo_id; > + const char *name; > + int bpp; > + int depth; > +} format_desc[] = { > + DF(RGB565, RGB16_565, 16, 16), > + DF(RGB888, INVALID, 24, 24), > + DF(XRGB8888, RGB24, 32, 24), > + DF(XRGB2101010, RGB30, 32, 30), > + DF(ARGB8888, ARGB32, 32, 32), > +}; > +#undef DF > + > +#define for_each_format(f) \ > + for (f = format_desc; f - format_desc < ARRAY_SIZE(format_desc); f++) > + > +static uint32_t bpp_depth_to_drm_format(int bpp, int depth) > +{ > + struct format_desc_struct *f; > + > + for_each_format(f) > + if (f->bpp == bpp && f->depth == depth) > + return f->drm_id; > + > + abort(); > +} > + > +/* Return fb_id on success, 0 on error */ > +unsigned int kmstest_create_fb(int fd, int width, int height, int bpp, > + int depth, bool tiled, struct kmstest_fb *fb) > +{ > + memset(fb, 0, sizeof(*fb)); > > - status = cairo_status(cr); > - assert(!status); > - cairo_destroy(cr); > + if (create_bo_for_fb(fd, width, height, bpp, tiled, &fb->gem_handle, > + &fb->size, &fb->stride) < 0) > + return 0; > + > + if (drmModeAddFB(fd, width, height, depth, bpp, fb->stride, > + fb->gem_handle, &fb->fb_id) < 0) { > + gem_close(fd, fb->gem_handle); > + > + return 0; > + } > + > + fb->width = width; > + fb->height = height; > + fb->drm_format = bpp_depth_to_drm_format(bpp, depth); > + > + return fb->fb_id; > +} > + > +static cairo_format_t drm_format_to_cairo(uint32_t drm_format) > +{ > + struct format_desc_struct *f; > > - do_or_die(drmModeAddFB(fd, width, height, depth, bpp, > - fb_info->stride, > - fb_info->gem_handle, &fb_id)); > + for_each_format(f) > + if (f->drm_id == drm_format) > + return f->cairo_id; > > + abort(); > +} > + > +static cairo_t *create_cairo_ctx(int fd, struct kmstest_fb *fb) > +{ > + cairo_t *cr; > + cairo_surface_t *surface; > + cairo_format_t cformat; > + 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); > + cr = cairo_create(surface); > cairo_surface_destroy(surface); > > - fb_info->fb_id = fb_id; > + return cr; > +} > + > +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_id; > + return fb->cairo_ctx; > } > > -void kmstest_remove_fb(int fd, int fb_id) > +void kmstest_remove_fb(int fd, struct kmstest_fb *fb) > { > - do_or_die(drmModeRmFB(fd, fb_id)); > + if (fb->cairo_ctx) > + cairo_destroy(fb->cairo_ctx); > + do_or_die(drmModeRmFB(fd, fb->fb_id)); > + gem_close(fd, fb->gem_handle); > } > > struct type_name { > diff --git a/lib/drmtest.h b/lib/drmtest.h > index 89ded11..218914f 100644 > --- a/lib/drmtest.h > +++ b/lib/drmtest.h > @@ -119,8 +119,13 @@ void kmstest_free_connector_config(struct kmstest_connector_config *config); > struct kmstest_fb { > uint32_t fb_id; > uint32_t gem_handle; > + uint32_t drm_format; > + int width; > + int height; > + int depth; > unsigned stride; > unsigned size; > + cairo_t *cairo_ctx; > }; > > enum kmstest_text_align { > @@ -136,14 +141,12 @@ int kmstest_cairo_printf_line(cairo_t *cr, enum kmstest_text_align align, > double yspacing, const char *fmt, ...) > __attribute__((format (printf, 4, 5))); > > -typedef void (*kmstest_paint_func)(cairo_t *cr, int width, int height, void *priv); > - > unsigned int kmstest_create_fb(int fd, int width, int height, int bpp, > int depth, bool tiled, > - struct kmstest_fb *fb_info, > - kmstest_paint_func paint_func, > - void *func_arg); > -void kmstest_remove_fb(int fd, int fb_id); > + 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); > +void kmstest_paint_test_pattern(cairo_t *cr, int width, int height); > void kmstest_dump_mode(drmModeModeInfo *mode); > int kmstest_get_pipe_from_crtc_id(int fd, int crtc_id); > const char *kmstest_encoder_type_str(int type); > diff --git a/tests/kms_flip.c b/tests/kms_flip.c > index c9b3d8a..aeeaace 100644 > --- a/tests/kms_flip.c > +++ b/tests/kms_flip.c > @@ -844,10 +844,13 @@ static void connector_find_preferred_mode(uint32_t connector_id, int crtc_idx, > o->mode_valid = 1; > } > > -static void > -paint_flip_mode(cairo_t *cr, int width, int height, void *priv) > +static void paint_flip_mode(struct kmstest_fb *fb, bool odd_frame) > { > - bool odd_frame = (bool) priv; > + cairo_t *cr = kmstest_get_cairo_ctx(drm_fd, fb); > + int width = fb->width; > + int height = fb->height; > + > + kmstest_paint_test_pattern(cr, width, height); > > if (odd_frame) > cairo_rectangle(cr, width/4, height/2, width/4, height/8); > @@ -856,6 +859,8 @@ paint_flip_mode(cairo_t *cr, int width, int height, void *priv) > > cairo_set_source_rgb(cr, 1, 1, 1); > cairo_fill(cr); > + > + assert(!cairo_status(cr)); > } > > static int > @@ -991,20 +996,21 @@ static void run_test_on_crtc(struct test_output *o, int crtc_idx, int duration) > o->fb_width *= 2; > > o->fb_ids[0] = kmstest_create_fb(drm_fd, o->fb_width, o->fb_height, > - o->bpp, o->depth, false, &o->fb_info[0], > - paint_flip_mode, (void *)false); > + o->bpp, o->depth, false, &o->fb_info[0]); > o->fb_ids[1] = kmstest_create_fb(drm_fd, o->fb_width, o->fb_height, > - o->bpp, o->depth, false, &o->fb_info[1], > - paint_flip_mode, (void *)true); > + o->bpp, o->depth, false, &o->fb_info[1]); > o->fb_ids[2] = kmstest_create_fb(drm_fd, o->fb_width, o->fb_height, > - o->bpp, o->depth, true, &o->fb_info[2], > - paint_flip_mode, (void *)true); > + o->bpp, o->depth, true, &o->fb_info[2]); > > if (!o->fb_ids[0] || !o->fb_ids[1] || !o->fb_ids[2]) { > fprintf(stderr, "failed to create fbs\n"); > exit(3); > } > > + paint_flip_mode(&o->fb_info[0], false); > + paint_flip_mode(&o->fb_info[1], true); > + paint_flip_mode(&o->fb_info[2], true); > + > set_y_tiling(o, 2); > > kmstest_dump_mode(&o->mode); > @@ -1044,9 +1050,9 @@ static void run_test_on_crtc(struct test_output *o, int crtc_idx, int duration) > fprintf(stdout, "\n%s on crtc %d, connector %d: PASSED\n\n", > o->test_name, o->crtc, o->id); > > - kmstest_remove_fb(drm_fd, o->fb_ids[2]); > - kmstest_remove_fb(drm_fd, o->fb_ids[1]); > - kmstest_remove_fb(drm_fd, o->fb_ids[0]); > + kmstest_remove_fb(drm_fd, &o->fb_info[2]); > + kmstest_remove_fb(drm_fd, &o->fb_info[1]); > + kmstest_remove_fb(drm_fd, &o->fb_info[0]); > > last_connector = NULL; > > diff --git a/tests/testdisplay.c b/tests/testdisplay.c > index 4470339..5ece921 100644 > --- a/tests/testdisplay.c > +++ b/tests/testdisplay.c > @@ -258,15 +258,18 @@ static void paint_image(cairo_t *cr, const char *file) > cairo_surface_destroy(image); > } > > -static void > -paint_output_info(cairo_t *cr, int l_width, int l_height, void *priv) > +static void paint_output_info(struct connector *c, struct kmstest_fb *fb) > { > - struct connector *c = priv; > + cairo_t *cr = kmstest_get_cairo_ctx(drm_fd, fb); > + int l_width = fb->width; > + int l_height = fb->height; > double str_width; > double x, y, top_y; > double max_width; > int i; > > + kmstest_paint_test_pattern(cr, l_width, l_height); > + > cairo_select_font_face(cr, "Helvetica", > CAIRO_FONT_SLANT_NORMAL, > CAIRO_FONT_WEIGHT_NORMAL); > @@ -308,6 +311,8 @@ paint_output_info(cairo_t *cr, int l_width, int l_height, void *priv) > > if (qr_code) > paint_image(cr, "./pass.png"); > + > + assert(!cairo_status(cr)); > } > > static void sighandler(int signo) > @@ -362,8 +367,8 @@ set_mode(struct connector *c) > height = c->mode.vdisplay; > > fb_id = kmstest_create_fb(drm_fd, width, height, bpp, depth, > - enable_tiling, &fb_info, > - paint_output_info, c); > + enable_tiling, &fb_info); > + paint_output_info(c, &fb_info); > > fb_ptr = gem_mmap(drm_fd, fb_info.gem_handle, > fb_info.size, PROT_READ | PROT_WRITE); > -- > 1.8.1.2 > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/intel-gfx -- Rodrigo Vivi Blog: http://blog.vivi.eng.br