modetest: Use cairo (if available) to paint a better pattern.
authorKristian Høgsberg <krh@redhat.com>
Tue, 3 Feb 2009 20:03:41 +0000 (15:03 -0500)
committerKristian Høgsberg <krh@redhat.com>
Tue, 3 Feb 2009 20:03:41 +0000 (15:03 -0500)
configure.ac
tests/modetest/Makefile.am
tests/modetest/modetest.c

index a842b8d..a65f79e 100644 (file)
@@ -119,6 +119,13 @@ if test "x$UDEV" = xyes; then
        AC_DEFINE(UDEV, 1, [Have UDEV support])
 fi
 
+PKG_CHECK_MODULES(CAIRO, cairo, [HAVE_CAIRO=yes], [HAVE_CAIRO=no])
+if test "x$HAVE_CAIRO" = xyes; then
+       AC_DEFINE(HAVE_CAIRO, 1, [Have cairo support])
+fi
+AM_CONDITIONAL(HAVE_CAIRO, [test "x$HAVE_CAIRO" = xyes])
+
+
 AC_SUBST(WARN_CFLAGS)
 AC_OUTPUT([
        Makefile
index b89c489..860fe06 100644 (file)
@@ -1,7 +1,8 @@
 AM_CFLAGS = \
        -I$(top_srcdir)/shared-core \
        -I$(top_srcdir)/libdrm/intel/ \
-       -I$(top_srcdir)/libdrm
+       -I$(top_srcdir)/libdrm \
+       $(CAIRO_CFLAGS)
 
 noinst_PROGRAMS = \
        modetest
@@ -10,4 +11,5 @@ modetest_SOURCES = \
        modetest.c
 modetest_LDADD = \
        $(top_builddir)/libdrm/libdrm.la \
-       $(top_builddir)/libdrm/intel/libdrm_intel.la
+       $(top_builddir)/libdrm/intel/libdrm_intel.la \
+       $(CAIRO_LIBS)
index c38908b..f1c3bf3 100644 (file)
@@ -37,6 +37,8 @@
  * TODO: use cairo to write the mode info on the selected output once
  *       the mode has been programmed, along with possible test patterns.
  */
+#include "config.h"
+
 #include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include "xf86drmMode.h"
 #include "intel_bufmgr.h"
 
+#ifdef HAVE_CAIRO
+#include <math.h>
+#include <cairo.h>
+#endif
+
 drmModeRes *resources;
 int fd, modes;
 
@@ -313,50 +320,104 @@ connector_find_mode(struct connector *c)
        }
 }
 
-static void
-set_mode(struct connector *c, int count)
+#ifdef HAVE_CAIRO
+
+static int
+create_test_buffer(drm_intel_bufmgr *bufmgr,
+                  int width, int height, int *stride_out, drm_intel_bo **bo_out)
 {
-       drmModeConnector *connector;
-       drmModeEncoder *encoder = NULL;
-       struct drm_mode_modeinfo *mode = NULL;
-       drm_intel_bufmgr *bufmgr;
        drm_intel_bo *bo;
-       unsigned int fb_id, *fb_ptr;
-       int i, j, size, ret, width, height, x;
+       unsigned int *fb_ptr;
+       int size, ret, i, stride;
        div_t d;
+       cairo_surface_t *surface;
+       cairo_t *cr;
+       char buf[64];
+       int x, y;
 
-       width = 0;
-       height = 0;
-       for (i = 0; i < count; i++) {
-               connector_find_mode(&c[i]);
-               if (c[i].mode == NULL)
-                       continue;
-               width += c[i].mode->hdisplay;
-               if (height < c[i].mode->vdisplay)
-                       height = c[i].mode->vdisplay;
+       surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
+       stride = cairo_image_surface_get_stride(surface);
+       size = stride * height;
+       fb_ptr = (unsigned int *) cairo_image_surface_get_data(surface);
+
+       /* paint the buffer with colored tiles */
+       for (i = 0; i < width * height; i++) {
+               d = div(i, width);
+               fb_ptr[i] = 0x00130502 * (d.quot >> 6) + 0x000a1120 * (d.rem >> 6);
        }
 
-       bufmgr = drm_intel_bufmgr_gem_init(fd, 2<<20);
-       if (!bufmgr) {
-               fprintf(stderr, "failed to init bufmgr: %s\n", strerror(errno));
-               return;
+       cr = cairo_create(surface);
+       cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
+       for (x = 0; x < width; x += 250)
+               for (y = 0; y < height; y += 250) {
+                       cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
+                       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);
+                       snprintf(buf, sizeof buf, "%d, %d", x, y);
+                       cairo_move_to(cr, x + 20, y + 20);
+                       cairo_text_path(cr, buf);
+                       cairo_set_source_rgb(cr, 0, 0, 0);
+                       cairo_stroke_preserve(cr);
+                       cairo_set_source_rgb(cr, 1, 1, 1);
+                       cairo_fill(cr);
+               }
+
+       cairo_destroy(cr);
+
+       bo = drm_intel_bo_alloc(bufmgr, "frontbuffer", size, 4096);
+       if (!bo) {
+               fprintf(stderr, "failed to alloc buffer: %s\n",
+                       strerror(errno));
+               return -1;
        }
 
+       drm_intel_bo_subdata(bo, 0, size, fb_ptr);
+
+       cairo_surface_destroy(surface);
+
+       *bo_out = bo;
+       *stride_out = stride;
+
+       return 0;
+}
+
+#else
+
+static int
+create_test_buffer(drm_intel_bufmgr *bufmgr,
+                  int width, int height, int *stride_out, drm_intel_bo **bo_out)
+{
+       drm_intel_bo *bo;
+       unsigned int *fb_ptr;
+       int size, ret, i, stride;
+       div_t d;
+
        /* Mode size at 32 bpp */
-       size = width * height * 4;
+       stride = width * 4;
+       size = stride * height;
 
        bo = drm_intel_bo_alloc(bufmgr, "frontbuffer", size, 4096);
        if (!bo) {
                fprintf(stderr, "failed to alloc buffer: %s\n",
                        strerror(errno));
-               return;
+               return -1;
        }
 
        ret = drm_intel_gem_bo_map_gtt(bo);
        if (ret) {
                fprintf(stderr, "failed to GTT map buffer: %s\n",
                        strerror(errno));
-               return;
+               return -1;
        }
 
        fb_ptr = bo->virtual;
@@ -366,8 +427,48 @@ set_mode(struct connector *c, int count)
                d = div(i, width);
                fb_ptr[i] = 0x00130502 * (d.quot >> 6) + 0x000a1120 * (d.rem >> 6);
        }
+       drm_intel_bo_unmap(bo);
+
+       *bo_out = bo;
+       *stride_out = stride;
+
+       return 0;
+}
+
+#endif
+
+static void
+set_mode(struct connector *c, int count)
+{
+       drmModeConnector *connector;
+       drmModeEncoder *encoder = NULL;
+       struct drm_mode_modeinfo *mode = NULL;
+       drm_intel_bufmgr *bufmgr;
+       drm_intel_bo *bo;
+       unsigned int fb_id;
+       int i, j, ret, width, height, x, stride;
+
+       width = 0;
+       height = 0;
+       for (i = 0; i < count; i++) {
+               connector_find_mode(&c[i]);
+               if (c[i].mode == NULL)
+                       continue;
+               width += c[i].mode->hdisplay;
+               if (height < c[i].mode->vdisplay)
+                       height = c[i].mode->vdisplay;
+       }
+
+       bufmgr = drm_intel_bufmgr_gem_init(fd, 2<<20);
+       if (!bufmgr) {
+               fprintf(stderr, "failed to init bufmgr: %s\n", strerror(errno));
+               return;
+       }
+
+       if (create_test_buffer(bufmgr, width, height, &stride, &bo))
+               return;
 
-       ret = drmModeAddFB(fd, width, height, 32, 32, width * 4, bo->handle,
+       ret = drmModeAddFB(fd, width, height, 32, 32, stride, bo->handle,
                           &fb_id);
        if (ret) {
                fprintf(stderr, "failed to add fb: %s\n", strerror(errno));