From 662d73219976ca820f878f63b5222e22e17c6328 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 22 May 2012 14:37:19 +0200 Subject: lib: extract kmstest_create_fb We should get more kms tests soon, and not needing to copy-paste a nice test pattern should be useful. That establishes a firm depency of i-g-t on cairo over everything, but I don't care so much about that. Signed-Off-by: Daniel Vetter --- benchmarks/Makefile.am | 4 +- debugger/Makefile.am | 2 +- demos/Makefile.am | 4 +- lib/Makefile.am | 2 + lib/drmtest.c | 236 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/drmtest.h | 17 ++++ tests/testdisplay.c | 228 +++-------------------------------------------- tools/Makefile.am | 4 +- 8 files changed, 272 insertions(+), 225 deletions(-) diff --git a/benchmarks/Makefile.am b/benchmarks/Makefile.am index 265d8bf8..e2ad7845 100644 --- a/benchmarks/Makefile.am +++ b/benchmarks/Makefile.am @@ -6,5 +6,5 @@ bin_PROGRAMS = \ intel_upload_blit_small AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib -AM_CFLAGS = $(DRM_CFLAGS) $(CWARNFLAGS) -LDADD = $(top_builddir)/lib/libintel_tools.la $(DRM_LIBS) $(PCIACCESS_LIBS) +AM_CFLAGS = $(DRM_CFLAGS) $(CWARNFLAGS) $(CAIRO_CFLAGS) +LDADD = $(top_builddir)/lib/libintel_tools.la $(DRM_LIBS) $(PCIACCESS_LIBS) $(CAIRO_LIBS) diff --git a/debugger/Makefile.am b/debugger/Makefile.am index ac602aa6..d76e2ac6 100644 --- a/debugger/Makefile.am +++ b/debugger/Makefile.am @@ -13,4 +13,4 @@ AM_CFLAGS = \ $(PCIACCESS_CFLAGS) \ $(CWARNFLAGS) -LDADD = $(top_builddir)/lib/libintel_tools.la $(DRM_LIBS) $(PCIACCESS_LIBS) +LDADD = $(top_builddir)/lib/libintel_tools.la $(DRM_LIBS) $(PCIACCESS_LIBS) $(CAIRO_LIBS) diff --git a/demos/Makefile.am b/demos/Makefile.am index 281cfe5a..49804d79 100644 --- a/demos/Makefile.am +++ b/demos/Makefile.am @@ -3,5 +3,5 @@ bin_PROGRAMS = \ $(NULL) AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib -AM_CFLAGS = $(DRM_CFLAGS) $(PCIACCESS_CFLAGS) $(CWARNFLAGS) -LDADD = $(top_builddir)/lib/libintel_tools.la $(DRM_LIBS) $(PCIACCESS_LIBS) +AM_CFLAGS = $(DRM_CFLAGS) $(PCIACCESS_CFLAGS) $(CWARNFLAGS) $(CAIRO_CFLAGS) +LDADD = $(top_builddir)/lib/libintel_tools.la $(DRM_LIBS) $(PCIACCESS_LIBS) $(CAIRO_LIBS) diff --git a/lib/Makefile.am b/lib/Makefile.am index f9d6167d..917a1147 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -29,3 +29,5 @@ libintel_tools_la_SOURCES = \ intel_reg_map.c \ $(NULL) +LDADD = $(CAIRO_LIBS) +AM_CFLAGS += $(CAIRO_CFLAGS) diff --git a/lib/drmtest.c b/lib/drmtest.c index b6aae37b..3d348697 100644 --- a/lib/drmtest.c +++ b/lib/drmtest.c @@ -35,6 +35,9 @@ #include #include #include +#include + +#include "xf86drmMode.h" #include "drmtest.h" #include "i915_drm.h" @@ -483,3 +486,236 @@ void drmtest_cleanup_aperture_trashers(void) free(trash_bos); } + +/* 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) +{ + cairo_format_t format; + struct drm_i915_gem_set_tiling set_tiling; + int size; + unsigned stride; + uint32_t *fb_ptr; + + if (tiled) { + int v; + + /* Round the tiling up to the next power-of-two and the + * region up to the next pot fence size so that this works + * on all generations. + * + * This can still fail if the framebuffer is too large to + * be tiled. But then that failure is expected. + */ + + v = width * bpp / 8; + for (stride = 512; stride < v; stride *= 2) + ; + + v = stride * height; + for (size = 1024*1024; size < v; size *= 2) + ; + } else { + /* Scan-out has a 64 byte alignment restriction */ + stride = (width * (bpp / 8) + 63) & ~63; + 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); + + if (tiled) { + set_tiling.handle = fb_info->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; + } + } + + fb_ptr = gem_mmap(fd, fb_info->gem_handle, size, PROT_READ | PROT_WRITE); + + fb_info->stride = stride; + fb_info->size = size; + + return cairo_image_surface_create_for_data((unsigned char *)fb_ptr, + format, width, height, + stride); +} + +static void +paint_color_gradient(cairo_t *cr, int x, int y, int w, int h, + int r, int g, int b) +{ + cairo_pattern_t *pat; + + pat = cairo_pattern_create_linear(x, y, x + w, y + h); + cairo_pattern_add_color_stop_rgba(pat, 1, 0, 0, 0, 1); + cairo_pattern_add_color_stop_rgba(pat, 0, r, g, b, 1); + + cairo_rectangle(cr, x, y, w, h); + cairo_set_source(cr, pat); + cairo_fill(cr); + cairo_pattern_destroy(pat); +} + +static void +paint_test_patterns(cairo_t *cr, int width, int height) +{ + double gr_height, gr_width; + int x, y; + + y = height * 0.10; + gr_width = width * 0.75; + gr_height = height * 0.08; + x = (width / 2) - (gr_width / 2); + + paint_color_gradient(cr, x, y, gr_width, gr_height, 1, 0, 0); + + y += gr_height; + paint_color_gradient(cr, x, y, gr_width, gr_height, 0, 1, 0); + + y += gr_height; + paint_color_gradient(cr, x, y, gr_width, gr_height, 0, 0, 1); + + y += gr_height; + paint_color_gradient(cr, x, y, gr_width, gr_height, 1, 1, 1); +} + +enum corner { + topleft, + topright, + bottomleft, + bottomright, +}; + +static void +paint_marker(cairo_t *cr, int x, int y, char *str, enum corner text_location) +{ + cairo_text_extents_t extents; + int xoff, yoff; + + cairo_set_font_size(cr, 18); + cairo_text_extents(cr, str, &extents); + + switch (text_location) { + case topleft: + xoff = -20; + xoff -= extents.width; + yoff = -20; + break; + case topright: + xoff = 20; + yoff = -20; + break; + case bottomleft: + xoff = -20; + xoff -= extents.width; + yoff = 20; + break; + case bottomright: + xoff = 20; + yoff = 20; + break; + default: + xoff = 0; + yoff = 0; + } + + cairo_move_to(cr, x, y - 20); + cairo_line_to(cr, x, y + 20); + cairo_move_to(cr, x - 20, y); + cairo_line_to(cr, x + 20, y); + cairo_new_sub_path(cr); + cairo_arc(cr, x, y, 10, 0, M_PI * 2); + cairo_set_line_width(cr, 4); + cairo_set_source_rgb(cr, 0, 0, 0); + cairo_stroke_preserve(cr); + cairo_set_source_rgb(cr, 1, 1, 1); + cairo_set_line_width(cr, 2); + cairo_stroke(cr); + + cairo_move_to(cr, x + xoff, y + yoff); + cairo_text_path(cr, str); + cairo_set_source_rgb(cr, 0, 0, 0); + cairo_stroke_preserve(cr); + cairo_set_source_rgb(cr, 1, 1, 1); + cairo_fill(cr); +} + +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) +{ + cairo_surface_t *surface; + cairo_status_t status; + cairo_t *cr; + char buf[128]; + int ret; + 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); + + /* Paint corner markers */ + snprintf(buf, sizeof buf, "(%d, %d)", 0, 0); + paint_marker(cr, 0, 0, buf, bottomright); + snprintf(buf, sizeof buf, "(%d, %d)", width, 0); + paint_marker(cr, width, 0, buf, bottomleft); + snprintf(buf, sizeof buf, "(%d, %d)", 0, height); + paint_marker(cr, 0, height, buf, topright); + snprintf(buf, sizeof buf, "(%d, %d)", width, height); + paint_marker(cr, width, height, buf, topleft); + + if (paint_func) + paint_func(cr, width, height, func_arg); + + status = cairo_status(cr); + assert(!status); + cairo_destroy(cr); + + ret = drmModeAddFB(fd, width, height, depth, bpp, + fb_info->stride, + fb_info->gem_handle, &fb_id); + + assert(ret == 0); + cairo_surface_destroy(surface); + + fb_info->fb_id = fb_id; + + return fb_id; +} diff --git a/lib/drmtest.h b/lib/drmtest.h index b0940f3a..36f28255 100644 --- a/lib/drmtest.h +++ b/lib/drmtest.h @@ -31,6 +31,7 @@ #include #include #include +#include #include "xf86drm.h" #include "intel_batchbuffer.h" @@ -74,6 +75,22 @@ void drmtest_init_aperture_trashers(drm_intel_bufmgr *bufmgr); void drmtest_trash_aperture(void); void drmtest_cleanup_aperture_trashers(void); +/* helpers to create nice-looking framebuffers */ +struct kmstest_fb { + uint32_t fb_id; + uint32_t gem_handle; + unsigned stride; + unsigned size; +}; + +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); + inline static void _do_or_die(const char *function, int line, int ret) { if (ret == 0) diff --git a/tests/testdisplay.c b/tests/testdisplay.c index 6aaea7aa..5e415e34 100644 --- a/tests/testdisplay.c +++ b/tests/testdisplay.c @@ -341,100 +341,6 @@ static void connector_find_preferred_mode(struct connector *c) c->connector = connector; } -static cairo_surface_t * -allocate_surface(int fd, uint32_t *handle, int tiled) -{ - cairo_format_t format; - struct drm_i915_gem_set_tiling set_tiling; - int size; - - if (tiled) { - int v; - - /* Round the tiling up to the next power-of-two and the - * region up to the next pot fence size so that this works - * on all generations. - * - * This can still fail if the framebuffer is too large to - * be tiled. But then that failure is expected. - */ - - v = width * bpp / 8; - for (stride = 512; stride < v; stride *= 2) - ; - - v = stride * height; - for (size = 1024*1024; size < v; size *= 2) - ; - } else { - /* Scan-out has a 64 byte alignment restriction */ - stride = (width * (bpp / 8) + 63) & ~63; - 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; - } - - *handle = gem_create(fd, size); - - if (tiled) { - set_tiling.handle = *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; - } - } - - fb_ptr = gem_mmap(fd, *handle, size, PROT_READ | PROT_WRITE); - - return cairo_image_surface_create_for_data((unsigned char *)fb_ptr, - format, width, height, - stride); -} - -enum corner { - topleft, - topright, - bottomleft, - bottomright, -}; - -static void -paint_color_gradient(cairo_t *cr, int x, int y, int w, int h, - int r, int g, int b) -{ - cairo_pattern_t *pat; - - pat = cairo_pattern_create_linear(x, y, x + w, y + h); - cairo_pattern_add_color_stop_rgba(pat, 1, 0, 0, 0, 1); - cairo_pattern_add_color_stop_rgba(pat, 0, r, g, b, 1); - - cairo_rectangle(cr, x, y, w, h); - cairo_set_source(cr, pat); - cairo_fill(cr); - cairo_pattern_destroy(pat); -} - static void paint_color_key(void) { @@ -450,85 +356,9 @@ paint_color_key(void) } static void -paint_test_patterns(cairo_t *cr) -{ - double gr_height, gr_width; - int x, y; - - y = height * 0.10; - gr_width = width * 0.75; - gr_height = height * 0.08; - x = (width / 2) - (gr_width / 2); - - paint_color_gradient(cr, x, y, gr_width, gr_height, 1, 0, 0); - - y += gr_height; - paint_color_gradient(cr, x, y, gr_width, gr_height, 0, 1, 0); - - y += gr_height; - paint_color_gradient(cr, x, y, gr_width, gr_height, 0, 0, 1); - - y += gr_height; - paint_color_gradient(cr, x, y, gr_width, gr_height, 1, 1, 1); -} - -static void -paint_marker(cairo_t *cr, int x, int y, char *str, enum corner text_location) -{ - cairo_text_extents_t extents; - int xoff, yoff; - - cairo_set_font_size(cr, 18); - cairo_text_extents(cr, str, &extents); - - switch (text_location) { - case topleft: - xoff = -20; - xoff -= extents.width; - yoff = -20; - break; - case topright: - xoff = 20; - yoff = -20; - break; - case bottomleft: - xoff = -20; - xoff -= extents.width; - yoff = 20; - break; - case bottomright: - xoff = 20; - yoff = 20; - break; - default: - xoff = 0; - yoff = 0; - } - - cairo_move_to(cr, x, y - 20); - cairo_line_to(cr, x, y + 20); - cairo_move_to(cr, x - 20, y); - cairo_line_to(cr, x + 20, y); - cairo_new_sub_path(cr); - cairo_arc(cr, x, y, 10, 0, M_PI * 2); - cairo_set_line_width(cr, 4); - cairo_set_source_rgb(cr, 0, 0, 0); - cairo_stroke_preserve(cr); - cairo_set_source_rgb(cr, 1, 1, 1); - cairo_set_line_width(cr, 2); - cairo_stroke(cr); - - cairo_move_to(cr, x + xoff, y + yoff); - cairo_text_path(cr, str); - cairo_set_source_rgb(cr, 0, 0, 0); - cairo_stroke_preserve(cr); - cairo_set_source_rgb(cr, 1, 1, 1); - cairo_fill(cr); -} - -static void -paint_output_info(cairo_t *cr, struct connector *c) +paint_output_info(cairo_t *cr, int width, int height, void *priv) { + struct connector *c = priv; cairo_text_extents_t name_extents, mode_extents; char name_buf[128], mode_buf[128]; int i, x, y, modes_x, modes_y; @@ -616,8 +446,6 @@ static void set_mode(struct connector *c) { unsigned int fb_id; - int ret; - char buf[128]; int j, test_mode_num; if (depth <= 8) @@ -641,10 +469,7 @@ set_mode(struct connector *c) test_mode_num = c->connector->count_modes; for (j = 0; j < test_mode_num; j++) { - cairo_surface_t *surface; - cairo_status_t status; - cairo_t *cr; - uint32_t handle; + struct kmstest_fb fb_info; if (test_all_modes) c->mode = c->connector->modes[j]; @@ -655,49 +480,16 @@ set_mode(struct connector *c) width = c->mode.hdisplay; height = c->mode.vdisplay; - surface = allocate_surface(drm_fd, &handle, enable_tiling); - if (!surface) { - fprintf(stderr, "allocation failed %dx%d\n", width, height); - continue; - } - - cr = cairo_create(surface); - - paint_test_patterns(cr); - - cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE); - - /* Paint corner markers */ - snprintf(buf, sizeof buf, "(%d, %d)", 0, 0); - paint_marker(cr, 0, 0, buf, bottomright); - snprintf(buf, sizeof buf, "(%d, %d)", width, 0); - paint_marker(cr, width, 0, buf, bottomleft); - snprintf(buf, sizeof buf, "(%d, %d)", 0, height); - paint_marker(cr, 0, height, buf, topright); - snprintf(buf, sizeof buf, "(%d, %d)", width, height); - paint_marker(cr, width, height, buf, topleft); - - /* Paint output info */ - paint_output_info(cr, c); + fb_id = kmstest_create_fb(drm_fd, width, height, bpp, depth, + enable_tiling, &fb_info, + paint_output_info, c); + fb_ptr = gem_mmap(drm_fd, fb_info.gem_handle, + fb_info.size, PROT_READ | PROT_WRITE); + assert(fb_ptr); paint_color_key(); - status = cairo_status(cr); - cairo_destroy(cr); - if (status) - fprintf(stderr, "failed to draw pretty picture %dx%d: %s\n", - width, height, cairo_status_to_string(status)); - - ret = drmModeAddFB(drm_fd, width, height, depth, bpp, stride, - handle, &fb_id); - cairo_surface_destroy(surface); - gem_close(drm_fd, handle); - - if (ret) { - fprintf(stderr, "failed to add fb (%dx%d): %s\n", - width, height, strerror(errno)); - continue; - } + gem_close(drm_fd, fb_info.gem_handle); fprintf(stdout, "CRTS(%u):",c->crtc); dump_mode(&c->mode); diff --git a/tools/Makefile.am b/tools/Makefile.am index 058835c2..2e4128b4 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -25,8 +25,8 @@ noinst_PROGRAMS = \ dist_bin_SCRIPTS = intel_gpu_abrt AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib -AM_CFLAGS = $(DRM_CFLAGS) $(PCIACCESS_CFLAGS) $(CWARNFLAGS) -LDADD = $(top_builddir)/lib/libintel_tools.la $(DRM_LIBS) $(PCIACCESS_LIBS) +AM_CFLAGS = $(DRM_CFLAGS) $(PCIACCESS_CFLAGS) $(CWARNFLAGS) $(CAIRO_CFLAGS) +LDADD = $(top_builddir)/lib/libintel_tools.la $(DRM_LIBS) $(PCIACCESS_LIBS) $(CAIRO_LIBS) intel_dump_decode_SOURCES = \ intel_dump_decode.c -- cgit v1.2.3