From: Thierry Reding treding@nvidia.com
Some of the helpers, such as the pattern drawing helpers or the format lookup helpers, have potential to be reused. Move them into a separate library to make it easier to share them.
Acked-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Signed-off-by: Thierry Reding treding@nvidia.com --- CleanSpec.mk | 1 + configure.ac | 1 + tests/Makefile.am | 2 +- tests/modeprint/Makefile.am | 1 + tests/modeprint/modeprint.c | 2 +- tests/modetest/Android.mk | 1 + tests/modetest/Makefile.am | 8 +- tests/modetest/buffers.c | 961 +------------------------------------------- tests/modetest/buffers.h | 12 +- tests/modetest/cursor.c | 4 +- tests/modetest/modetest.c | 25 +- tests/proptest/Makefile.am | 4 +- tests/proptest/proptest.c | 3 +- tests/util/Android.mk | 39 ++ tests/util/Makefile.am | 13 + tests/util/Makefile.sources | 6 + tests/util/common.h | 33 ++ tests/util/format.c | 120 ++++++ tests/util/format.h | 65 +++ tests/util/pattern.c | 870 +++++++++++++++++++++++++++++++++++++++ tests/util/pattern.h | 39 ++ tests/vbltest/Makefile.am | 1 + tests/vbltest/vbltest.c | 2 +- 23 files changed, 1223 insertions(+), 990 deletions(-) create mode 100644 tests/util/Android.mk create mode 100644 tests/util/Makefile.am create mode 100644 tests/util/Makefile.sources create mode 100644 tests/util/common.h create mode 100644 tests/util/format.c create mode 100644 tests/util/format.h create mode 100644 tests/util/pattern.c create mode 100644 tests/util/pattern.h
diff --git a/CleanSpec.mk b/CleanSpec.mk index 8e23cd25d26d..28a11db4e7b0 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -1,3 +1,4 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/include/libdrm) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/include/freedreno) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libdrm_*intermediates) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libdrm_*intermediates) diff --git a/configure.ac b/configure.ac index b929d36a28c5..ca6cbf4eaa62 100644 --- a/configure.ac +++ b/configure.ac @@ -507,6 +507,7 @@ AC_CONFIG_FILES([ tests/exynos/Makefile tests/tegra/Makefile tests/nouveau/Makefile + tests/util/Makefile man/Makefile libdrm.pc]) AC_OUTPUT diff --git a/tests/Makefile.am b/tests/Makefile.am index c53f4af67111..7ffc076f16d7 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = modeprint proptest modetest vbltest +SUBDIRS = util modeprint proptest modetest vbltest
if HAVE_LIBKMS SUBDIRS += kmstest diff --git a/tests/modeprint/Makefile.am b/tests/modeprint/Makefile.am index 895805fd32e8..601dbc964290 100644 --- a/tests/modeprint/Makefile.am +++ b/tests/modeprint/Makefile.am @@ -1,6 +1,7 @@ AM_CFLAGS = \ $(WARN_CFLAGS)\ -I$(top_srcdir)/include/drm \ + -I$(top_srcdir)/tests \ -I$(top_srcdir)
if HAVE_INSTALL_TESTS diff --git a/tests/modeprint/modeprint.c b/tests/modeprint/modeprint.c index 5e953f71f646..0d854103c5ae 100644 --- a/tests/modeprint/modeprint.c +++ b/tests/modeprint/modeprint.c @@ -41,7 +41,7 @@ #include "xf86drm.h" #include "xf86drmMode.h"
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) +#include "util/common.h"
int current; int connectors; diff --git a/tests/modetest/Android.mk b/tests/modetest/Android.mk index 0fdfe6856bd6..e616558fd690 100644 --- a/tests/modetest/Android.mk +++ b/tests/modetest/Android.mk @@ -8,5 +8,6 @@ LOCAL_SRC_FILES := $(MODETEST_FILES) LOCAL_MODULE := modetest
LOCAL_SHARED_LIBRARIES := libdrm +LOCAL_STATIC_LIBRARIES := libdrm_util
include $(BUILD_EXECUTABLE) diff --git a/tests/modetest/Makefile.am b/tests/modetest/Makefile.am index 93820fac7395..25ce372fc303 100644 --- a/tests/modetest/Makefile.am +++ b/tests/modetest/Makefile.am @@ -4,6 +4,7 @@ AM_CFLAGS = $(filter-out -Wpointer-arith, $(WARN_CFLAGS))
AM_CFLAGS += \ -I$(top_srcdir)/include/drm \ + -I$(top_srcdir)/tests \ -I$(top_srcdir)
if HAVE_INSTALL_TESTS @@ -18,11 +19,8 @@ modetest_SOURCES = $(MODETEST_FILES)
modetest_LDADD = \ $(top_builddir)/libdrm.la \ + $(top_builddir)/tests/util/libutil.la \ + $(CAIRO_LIBS) \ -lpthread
-if HAVE_CAIRO -AM_CFLAGS += $(CAIRO_CFLAGS) -modetest_LDADD += $(CAIRO_LIBS) -endif - EXTRA_DIST = Android.mk diff --git a/tests/modetest/buffers.c b/tests/modetest/buffers.c index ebb14ef8bedb..4fd310b9b00b 100644 --- a/tests/modetest/buffers.c +++ b/tests/modetest/buffers.c @@ -44,13 +44,6 @@
#include "buffers.h"
-#ifdef HAVE_CAIRO -#include <math.h> -#include <cairo.h> -#endif - -#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) - struct bo { int fd; @@ -62,956 +55,6 @@ struct bo };
/* ----------------------------------------------------------------------------- - * Formats - */ - -struct color_component { - unsigned int length; - unsigned int offset; -}; - -struct rgb_info { - struct color_component red; - struct color_component green; - struct color_component blue; - struct color_component alpha; -}; - -enum yuv_order { - YUV_YCbCr = 1, - YUV_YCrCb = 2, - YUV_YC = 4, - YUV_CY = 8, -}; - -struct yuv_info { - enum yuv_order order; - unsigned int xsub; - unsigned int ysub; - unsigned int chroma_stride; -}; - -struct format_info { - unsigned int format; - const char *name; - const struct rgb_info rgb; - const struct yuv_info yuv; -}; - -#define MAKE_RGB_INFO(rl, ro, gl, go, bl, bo, al, ao) \ - .rgb = { { (rl), (ro) }, { (gl), (go) }, { (bl), (bo) }, { (al), (ao) } } - -#define MAKE_YUV_INFO(order, xsub, ysub, chroma_stride) \ - .yuv = { (order), (xsub), (ysub), (chroma_stride) } - -static const struct format_info format_info[] = { - /* YUV packed */ - { DRM_FORMAT_UYVY, "UYVY", MAKE_YUV_INFO(YUV_YCbCr | YUV_CY, 2, 2, 2) }, - { DRM_FORMAT_VYUY, "VYUY", MAKE_YUV_INFO(YUV_YCrCb | YUV_CY, 2, 2, 2) }, - { DRM_FORMAT_YUYV, "YUYV", MAKE_YUV_INFO(YUV_YCbCr | YUV_YC, 2, 2, 2) }, - { DRM_FORMAT_YVYU, "YVYU", MAKE_YUV_INFO(YUV_YCrCb | YUV_YC, 2, 2, 2) }, - /* YUV semi-planar */ - { DRM_FORMAT_NV12, "NV12", MAKE_YUV_INFO(YUV_YCbCr, 2, 2, 2) }, - { DRM_FORMAT_NV21, "NV21", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 2) }, - { DRM_FORMAT_NV16, "NV16", MAKE_YUV_INFO(YUV_YCbCr, 2, 1, 2) }, - { DRM_FORMAT_NV61, "NV61", MAKE_YUV_INFO(YUV_YCrCb, 2, 1, 2) }, - /* YUV planar */ - { DRM_FORMAT_YUV420, "YU12", MAKE_YUV_INFO(YUV_YCbCr, 2, 2, 1) }, - { DRM_FORMAT_YVU420, "YV12", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 1) }, - /* RGB16 */ - { DRM_FORMAT_ARGB4444, "AR12", MAKE_RGB_INFO(4, 8, 4, 4, 4, 0, 4, 12) }, - { DRM_FORMAT_XRGB4444, "XR12", MAKE_RGB_INFO(4, 8, 4, 4, 4, 0, 0, 0) }, - { DRM_FORMAT_ABGR4444, "AB12", MAKE_RGB_INFO(4, 0, 4, 4, 4, 8, 4, 12) }, - { DRM_FORMAT_XBGR4444, "XB12", MAKE_RGB_INFO(4, 0, 4, 4, 4, 8, 0, 0) }, - { DRM_FORMAT_RGBA4444, "RA12", MAKE_RGB_INFO(4, 12, 4, 8, 4, 4, 4, 0) }, - { DRM_FORMAT_RGBX4444, "RX12", MAKE_RGB_INFO(4, 12, 4, 8, 4, 4, 0, 0) }, - { DRM_FORMAT_BGRA4444, "BA12", MAKE_RGB_INFO(4, 4, 4, 8, 4, 12, 4, 0) }, - { DRM_FORMAT_BGRX4444, "BX12", MAKE_RGB_INFO(4, 4, 4, 8, 4, 12, 0, 0) }, - { DRM_FORMAT_ARGB1555, "AR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 1, 15) }, - { DRM_FORMAT_XRGB1555, "XR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 0, 0) }, - { DRM_FORMAT_ABGR1555, "AB15", MAKE_RGB_INFO(5, 0, 5, 5, 5, 10, 1, 15) }, - { DRM_FORMAT_XBGR1555, "XB15", MAKE_RGB_INFO(5, 0, 5, 5, 5, 10, 0, 0) }, - { DRM_FORMAT_RGBA5551, "RA15", MAKE_RGB_INFO(5, 11, 5, 6, 5, 1, 1, 0) }, - { DRM_FORMAT_RGBX5551, "RX15", MAKE_RGB_INFO(5, 11, 5, 6, 5, 1, 0, 0) }, - { DRM_FORMAT_BGRA5551, "BA15", MAKE_RGB_INFO(5, 1, 5, 6, 5, 11, 1, 0) }, - { DRM_FORMAT_BGRX5551, "BX15", MAKE_RGB_INFO(5, 1, 5, 6, 5, 11, 0, 0) }, - { DRM_FORMAT_RGB565, "RG16", MAKE_RGB_INFO(5, 11, 6, 5, 5, 0, 0, 0) }, - { DRM_FORMAT_BGR565, "BG16", MAKE_RGB_INFO(5, 0, 6, 5, 5, 11, 0, 0) }, - /* RGB24 */ - { DRM_FORMAT_BGR888, "BG24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 0, 0) }, - { DRM_FORMAT_RGB888, "RG24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) }, - /* RGB32 */ - { DRM_FORMAT_ARGB8888, "AR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 8, 24) }, - { DRM_FORMAT_XRGB8888, "XR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) }, - { DRM_FORMAT_ABGR8888, "AB24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 8, 24) }, - { DRM_FORMAT_XBGR8888, "XB24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 0, 0) }, - { DRM_FORMAT_RGBA8888, "RA24", MAKE_RGB_INFO(8, 24, 8, 16, 8, 8, 8, 0) }, - { DRM_FORMAT_RGBX8888, "RX24", MAKE_RGB_INFO(8, 24, 8, 16, 8, 8, 0, 0) }, - { DRM_FORMAT_BGRA8888, "BA24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 8, 0) }, - { DRM_FORMAT_BGRX8888, "BX24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 0, 0) }, - { DRM_FORMAT_ARGB2101010, "AR30", MAKE_RGB_INFO(10, 20, 10, 10, 10, 0, 2, 30) }, - { DRM_FORMAT_XRGB2101010, "XR30", MAKE_RGB_INFO(10, 20, 10, 10, 10, 0, 0, 0) }, - { DRM_FORMAT_ABGR2101010, "AB30", MAKE_RGB_INFO(10, 0, 10, 10, 10, 20, 2, 30) }, - { DRM_FORMAT_XBGR2101010, "XB30", MAKE_RGB_INFO(10, 0, 10, 10, 10, 20, 0, 0) }, - { DRM_FORMAT_RGBA1010102, "RA30", MAKE_RGB_INFO(10, 22, 10, 12, 10, 2, 2, 0) }, - { DRM_FORMAT_RGBX1010102, "RX30", MAKE_RGB_INFO(10, 22, 10, 12, 10, 2, 0, 0) }, - { DRM_FORMAT_BGRA1010102, "BA30", MAKE_RGB_INFO(10, 2, 10, 12, 10, 22, 2, 0) }, - { DRM_FORMAT_BGRX1010102, "BX30", MAKE_RGB_INFO(10, 2, 10, 12, 10, 22, 0, 0) }, -}; - -unsigned int format_fourcc(const char *name) -{ - unsigned int i; - for (i = 0; i < ARRAY_SIZE(format_info); i++) { - if (!strcmp(format_info[i].name, name)) - return format_info[i].format; - } - return 0; -} - -/* ----------------------------------------------------------------------------- - * Test patterns - */ - -struct color_rgb24 { - unsigned int value:24; -} __attribute__((__packed__)); - -struct color_yuv { - unsigned char y; - unsigned char u; - unsigned char v; -}; - -#define MAKE_YUV_601_Y(r, g, b) \ - ((( 66 * (r) + 129 * (g) + 25 * (b) + 128) >> 8) + 16) -#define MAKE_YUV_601_U(r, g, b) \ - (((-38 * (r) - 74 * (g) + 112 * (b) + 128) >> 8) + 128) -#define MAKE_YUV_601_V(r, g, b) \ - (((112 * (r) - 94 * (g) - 18 * (b) + 128) >> 8) + 128) - -#define MAKE_YUV_601(r, g, b) \ - { .y = MAKE_YUV_601_Y(r, g, b), \ - .u = MAKE_YUV_601_U(r, g, b), \ - .v = MAKE_YUV_601_V(r, g, b) } - -#define MAKE_RGBA(rgb, r, g, b, a) \ - ((((r) >> (8 - (rgb)->red.length)) << (rgb)->red.offset) | \ - (((g) >> (8 - (rgb)->green.length)) << (rgb)->green.offset) | \ - (((b) >> (8 - (rgb)->blue.length)) << (rgb)->blue.offset) | \ - (((a) >> (8 - (rgb)->alpha.length)) << (rgb)->alpha.offset)) - -#define MAKE_RGB24(rgb, r, g, b) \ - { .value = MAKE_RGBA(rgb, r, g, b, 0) } - -static void -fill_smpte_yuv_planar(const struct yuv_info *yuv, - unsigned char *y_mem, unsigned char *u_mem, - unsigned char *v_mem, unsigned int width, - unsigned int height, unsigned int stride) -{ - const struct color_yuv colors_top[] = { - MAKE_YUV_601(191, 192, 192), /* grey */ - MAKE_YUV_601(192, 192, 0), /* yellow */ - MAKE_YUV_601(0, 192, 192), /* cyan */ - MAKE_YUV_601(0, 192, 0), /* green */ - MAKE_YUV_601(192, 0, 192), /* magenta */ - MAKE_YUV_601(192, 0, 0), /* red */ - MAKE_YUV_601(0, 0, 192), /* blue */ - }; - const struct color_yuv colors_middle[] = { - MAKE_YUV_601(0, 0, 192), /* blue */ - MAKE_YUV_601(19, 19, 19), /* black */ - MAKE_YUV_601(192, 0, 192), /* magenta */ - MAKE_YUV_601(19, 19, 19), /* black */ - MAKE_YUV_601(0, 192, 192), /* cyan */ - MAKE_YUV_601(19, 19, 19), /* black */ - MAKE_YUV_601(192, 192, 192), /* grey */ - }; - const struct color_yuv colors_bottom[] = { - MAKE_YUV_601(0, 33, 76), /* in-phase */ - MAKE_YUV_601(255, 255, 255), /* super white */ - MAKE_YUV_601(50, 0, 106), /* quadrature */ - MAKE_YUV_601(19, 19, 19), /* black */ - MAKE_YUV_601(9, 9, 9), /* 3.5% */ - MAKE_YUV_601(19, 19, 19), /* 7.5% */ - MAKE_YUV_601(29, 29, 29), /* 11.5% */ - MAKE_YUV_601(19, 19, 19), /* black */ - }; - unsigned int cs = yuv->chroma_stride; - unsigned int xsub = yuv->xsub; - unsigned int ysub = yuv->ysub; - unsigned int x; - unsigned int y; - - /* Luma */ - for (y = 0; y < height * 6 / 9; ++y) { - for (x = 0; x < width; ++x) - y_mem[x] = colors_top[x * 7 / width].y; - y_mem += stride; - } - - for (; y < height * 7 / 9; ++y) { - for (x = 0; x < width; ++x) - y_mem[x] = colors_middle[x * 7 / width].y; - y_mem += stride; - } - - for (; y < height; ++y) { - for (x = 0; x < width * 5 / 7; ++x) - y_mem[x] = colors_bottom[x * 4 / (width * 5 / 7)].y; - for (; x < width * 6 / 7; ++x) - y_mem[x] = colors_bottom[(x - width * 5 / 7) * 3 - / (width / 7) + 4].y; - for (; x < width; ++x) - y_mem[x] = colors_bottom[7].y; - y_mem += stride; - } - - /* Chroma */ - for (y = 0; y < height / ysub * 6 / 9; ++y) { - for (x = 0; x < width; x += xsub) { - u_mem[x*cs/xsub] = colors_top[x * 7 / width].u; - v_mem[x*cs/xsub] = colors_top[x * 7 / width].v; - } - u_mem += stride * cs / xsub; - v_mem += stride * cs / xsub; - } - - for (; y < height / ysub * 7 / 9; ++y) { - for (x = 0; x < width; x += xsub) { - u_mem[x*cs/xsub] = colors_middle[x * 7 / width].u; - v_mem[x*cs/xsub] = colors_middle[x * 7 / width].v; - } - u_mem += stride * cs / xsub; - v_mem += stride * cs / xsub; - } - - for (; y < height / ysub; ++y) { - for (x = 0; x < width * 5 / 7; x += xsub) { - u_mem[x*cs/xsub] = - colors_bottom[x * 4 / (width * 5 / 7)].u; - v_mem[x*cs/xsub] = - colors_bottom[x * 4 / (width * 5 / 7)].v; - } - for (; x < width * 6 / 7; x += xsub) { - u_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) * - 3 / (width / 7) + 4].u; - v_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) * - 3 / (width / 7) + 4].v; - } - for (; x < width; x += xsub) { - u_mem[x*cs/xsub] = colors_bottom[7].u; - v_mem[x*cs/xsub] = colors_bottom[7].v; - } - u_mem += stride * cs / xsub; - v_mem += stride * cs / xsub; - } -} - -static void -fill_smpte_yuv_packed(const struct yuv_info *yuv, unsigned char *mem, - unsigned int width, unsigned int height, - unsigned int stride) -{ - const struct color_yuv colors_top[] = { - MAKE_YUV_601(191, 192, 192), /* grey */ - MAKE_YUV_601(192, 192, 0), /* yellow */ - MAKE_YUV_601(0, 192, 192), /* cyan */ - MAKE_YUV_601(0, 192, 0), /* green */ - MAKE_YUV_601(192, 0, 192), /* magenta */ - MAKE_YUV_601(192, 0, 0), /* red */ - MAKE_YUV_601(0, 0, 192), /* blue */ - }; - const struct color_yuv colors_middle[] = { - MAKE_YUV_601(0, 0, 192), /* blue */ - MAKE_YUV_601(19, 19, 19), /* black */ - MAKE_YUV_601(192, 0, 192), /* magenta */ - MAKE_YUV_601(19, 19, 19), /* black */ - MAKE_YUV_601(0, 192, 192), /* cyan */ - MAKE_YUV_601(19, 19, 19), /* black */ - MAKE_YUV_601(192, 192, 192), /* grey */ - }; - const struct color_yuv colors_bottom[] = { - MAKE_YUV_601(0, 33, 76), /* in-phase */ - MAKE_YUV_601(255, 255, 255), /* super white */ - MAKE_YUV_601(50, 0, 106), /* quadrature */ - MAKE_YUV_601(19, 19, 19), /* black */ - MAKE_YUV_601(9, 9, 9), /* 3.5% */ - MAKE_YUV_601(19, 19, 19), /* 7.5% */ - MAKE_YUV_601(29, 29, 29), /* 11.5% */ - MAKE_YUV_601(19, 19, 19), /* black */ - }; - unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1; - unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1; - unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0; - unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0; - unsigned int x; - unsigned int y; - - /* Luma */ - for (y = 0; y < height * 6 / 9; ++y) { - for (x = 0; x < width; ++x) - y_mem[2*x] = colors_top[x * 7 / width].y; - y_mem += stride; - } - - for (; y < height * 7 / 9; ++y) { - for (x = 0; x < width; ++x) - y_mem[2*x] = colors_middle[x * 7 / width].y; - y_mem += stride; - } - - for (; y < height; ++y) { - for (x = 0; x < width * 5 / 7; ++x) - y_mem[2*x] = colors_bottom[x * 4 / (width * 5 / 7)].y; - for (; x < width * 6 / 7; ++x) - y_mem[2*x] = colors_bottom[(x - width * 5 / 7) * 3 - / (width / 7) + 4].y; - for (; x < width; ++x) - y_mem[2*x] = colors_bottom[7].y; - y_mem += stride; - } - - /* Chroma */ - for (y = 0; y < height * 6 / 9; ++y) { - for (x = 0; x < width; x += 2) { - c_mem[2*x+u] = colors_top[x * 7 / width].u; - c_mem[2*x+v] = colors_top[x * 7 / width].v; - } - c_mem += stride; - } - - for (; y < height * 7 / 9; ++y) { - for (x = 0; x < width; x += 2) { - c_mem[2*x+u] = colors_middle[x * 7 / width].u; - c_mem[2*x+v] = colors_middle[x * 7 / width].v; - } - c_mem += stride; - } - - for (; y < height; ++y) { - for (x = 0; x < width * 5 / 7; x += 2) { - c_mem[2*x+u] = colors_bottom[x * 4 / (width * 5 / 7)].u; - c_mem[2*x+v] = colors_bottom[x * 4 / (width * 5 / 7)].v; - } - for (; x < width * 6 / 7; x += 2) { - c_mem[2*x+u] = colors_bottom[(x - width * 5 / 7) * - 3 / (width / 7) + 4].u; - c_mem[2*x+v] = colors_bottom[(x - width * 5 / 7) * - 3 / (width / 7) + 4].v; - } - for (; x < width; x += 2) { - c_mem[2*x+u] = colors_bottom[7].u; - c_mem[2*x+v] = colors_bottom[7].v; - } - c_mem += stride; - } -} - -static void -fill_smpte_rgb16(const struct rgb_info *rgb, unsigned char *mem, - unsigned int width, unsigned int height, unsigned int stride) -{ - const uint16_t colors_top[] = { - MAKE_RGBA(rgb, 192, 192, 192, 255), /* grey */ - MAKE_RGBA(rgb, 192, 192, 0, 255), /* yellow */ - MAKE_RGBA(rgb, 0, 192, 192, 255), /* cyan */ - MAKE_RGBA(rgb, 0, 192, 0, 255), /* green */ - MAKE_RGBA(rgb, 192, 0, 192, 255), /* magenta */ - MAKE_RGBA(rgb, 192, 0, 0, 255), /* red */ - MAKE_RGBA(rgb, 0, 0, 192, 255), /* blue */ - }; - const uint16_t colors_middle[] = { - MAKE_RGBA(rgb, 0, 0, 192, 127), /* blue */ - MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ - MAKE_RGBA(rgb, 192, 0, 192, 127), /* magenta */ - MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ - MAKE_RGBA(rgb, 0, 192, 192, 127), /* cyan */ - MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ - MAKE_RGBA(rgb, 192, 192, 192, 127), /* grey */ - }; - const uint16_t colors_bottom[] = { - MAKE_RGBA(rgb, 0, 33, 76, 255), /* in-phase */ - MAKE_RGBA(rgb, 255, 255, 255, 255), /* super white */ - MAKE_RGBA(rgb, 50, 0, 106, 255), /* quadrature */ - MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ - MAKE_RGBA(rgb, 9, 9, 9, 255), /* 3.5% */ - MAKE_RGBA(rgb, 19, 19, 19, 255), /* 7.5% */ - MAKE_RGBA(rgb, 29, 29, 29, 255), /* 11.5% */ - MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ - }; - unsigned int x; - unsigned int y; - - for (y = 0; y < height * 6 / 9; ++y) { - for (x = 0; x < width; ++x) - ((uint16_t *)mem)[x] = colors_top[x * 7 / width]; - mem += stride; - } - - for (; y < height * 7 / 9; ++y) { - for (x = 0; x < width; ++x) - ((uint16_t *)mem)[x] = colors_middle[x * 7 / width]; - mem += stride; - } - - for (; y < height; ++y) { - for (x = 0; x < width * 5 / 7; ++x) - ((uint16_t *)mem)[x] = - colors_bottom[x * 4 / (width * 5 / 7)]; - for (; x < width * 6 / 7; ++x) - ((uint16_t *)mem)[x] = - colors_bottom[(x - width * 5 / 7) * 3 - / (width / 7) + 4]; - for (; x < width; ++x) - ((uint16_t *)mem)[x] = colors_bottom[7]; - mem += stride; - } -} - -static void -fill_smpte_rgb24(const struct rgb_info *rgb, void *mem, - unsigned int width, unsigned int height, unsigned int stride) -{ - const struct color_rgb24 colors_top[] = { - MAKE_RGB24(rgb, 192, 192, 192), /* grey */ - MAKE_RGB24(rgb, 192, 192, 0), /* yellow */ - MAKE_RGB24(rgb, 0, 192, 192), /* cyan */ - MAKE_RGB24(rgb, 0, 192, 0), /* green */ - MAKE_RGB24(rgb, 192, 0, 192), /* magenta */ - MAKE_RGB24(rgb, 192, 0, 0), /* red */ - MAKE_RGB24(rgb, 0, 0, 192), /* blue */ - }; - const struct color_rgb24 colors_middle[] = { - MAKE_RGB24(rgb, 0, 0, 192), /* blue */ - MAKE_RGB24(rgb, 19, 19, 19), /* black */ - MAKE_RGB24(rgb, 192, 0, 192), /* magenta */ - MAKE_RGB24(rgb, 19, 19, 19), /* black */ - MAKE_RGB24(rgb, 0, 192, 192), /* cyan */ - MAKE_RGB24(rgb, 19, 19, 19), /* black */ - MAKE_RGB24(rgb, 192, 192, 192), /* grey */ - }; - const struct color_rgb24 colors_bottom[] = { - MAKE_RGB24(rgb, 0, 33, 76), /* in-phase */ - MAKE_RGB24(rgb, 255, 255, 255), /* super white */ - MAKE_RGB24(rgb, 50, 0, 106), /* quadrature */ - MAKE_RGB24(rgb, 19, 19, 19), /* black */ - MAKE_RGB24(rgb, 9, 9, 9), /* 3.5% */ - MAKE_RGB24(rgb, 19, 19, 19), /* 7.5% */ - MAKE_RGB24(rgb, 29, 29, 29), /* 11.5% */ - MAKE_RGB24(rgb, 19, 19, 19), /* black */ - }; - unsigned int x; - unsigned int y; - - for (y = 0; y < height * 6 / 9; ++y) { - for (x = 0; x < width; ++x) - ((struct color_rgb24 *)mem)[x] = - colors_top[x * 7 / width]; - mem += stride; - } - - for (; y < height * 7 / 9; ++y) { - for (x = 0; x < width; ++x) - ((struct color_rgb24 *)mem)[x] = - colors_middle[x * 7 / width]; - mem += stride; - } - - for (; y < height; ++y) { - for (x = 0; x < width * 5 / 7; ++x) - ((struct color_rgb24 *)mem)[x] = - colors_bottom[x * 4 / (width * 5 / 7)]; - for (; x < width * 6 / 7; ++x) - ((struct color_rgb24 *)mem)[x] = - colors_bottom[(x - width * 5 / 7) * 3 - / (width / 7) + 4]; - for (; x < width; ++x) - ((struct color_rgb24 *)mem)[x] = colors_bottom[7]; - mem += stride; - } -} - -static void -fill_smpte_rgb32(const struct rgb_info *rgb, unsigned char *mem, - unsigned int width, unsigned int height, unsigned int stride) -{ - const uint32_t colors_top[] = { - MAKE_RGBA(rgb, 192, 192, 192, 255), /* grey */ - MAKE_RGBA(rgb, 192, 192, 0, 255), /* yellow */ - MAKE_RGBA(rgb, 0, 192, 192, 255), /* cyan */ - MAKE_RGBA(rgb, 0, 192, 0, 255), /* green */ - MAKE_RGBA(rgb, 192, 0, 192, 255), /* magenta */ - MAKE_RGBA(rgb, 192, 0, 0, 255), /* red */ - MAKE_RGBA(rgb, 0, 0, 192, 255), /* blue */ - }; - const uint32_t colors_middle[] = { - MAKE_RGBA(rgb, 0, 0, 192, 127), /* blue */ - MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ - MAKE_RGBA(rgb, 192, 0, 192, 127), /* magenta */ - MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ - MAKE_RGBA(rgb, 0, 192, 192, 127), /* cyan */ - MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ - MAKE_RGBA(rgb, 192, 192, 192, 127), /* grey */ - }; - const uint32_t colors_bottom[] = { - MAKE_RGBA(rgb, 0, 33, 76, 255), /* in-phase */ - MAKE_RGBA(rgb, 255, 255, 255, 255), /* super white */ - MAKE_RGBA(rgb, 50, 0, 106, 255), /* quadrature */ - MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ - MAKE_RGBA(rgb, 9, 9, 9, 255), /* 3.5% */ - MAKE_RGBA(rgb, 19, 19, 19, 255), /* 7.5% */ - MAKE_RGBA(rgb, 29, 29, 29, 255), /* 11.5% */ - MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ - }; - unsigned int x; - unsigned int y; - - for (y = 0; y < height * 6 / 9; ++y) { - for (x = 0; x < width; ++x) - ((uint32_t *)mem)[x] = colors_top[x * 7 / width]; - mem += stride; - } - - for (; y < height * 7 / 9; ++y) { - for (x = 0; x < width; ++x) - ((uint32_t *)mem)[x] = colors_middle[x * 7 / width]; - mem += stride; - } - - for (; y < height; ++y) { - for (x = 0; x < width * 5 / 7; ++x) - ((uint32_t *)mem)[x] = - colors_bottom[x * 4 / (width * 5 / 7)]; - for (; x < width * 6 / 7; ++x) - ((uint32_t *)mem)[x] = - colors_bottom[(x - width * 5 / 7) * 3 - / (width / 7) + 4]; - for (; x < width; ++x) - ((uint32_t *)mem)[x] = colors_bottom[7]; - mem += stride; - } -} - -static void -fill_smpte(const struct format_info *info, void *planes[3], unsigned int width, - unsigned int height, unsigned int stride) -{ - unsigned char *u, *v; - - switch (info->format) { - case DRM_FORMAT_UYVY: - case DRM_FORMAT_VYUY: - case DRM_FORMAT_YUYV: - case DRM_FORMAT_YVYU: - return fill_smpte_yuv_packed(&info->yuv, planes[0], width, - height, stride); - - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV21: - case DRM_FORMAT_NV16: - case DRM_FORMAT_NV61: - u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1; - v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1; - return fill_smpte_yuv_planar(&info->yuv, planes[0], u, v, - width, height, stride); - - case DRM_FORMAT_YUV420: - return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[1], - planes[2], width, height, stride); - - case DRM_FORMAT_YVU420: - return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[2], - planes[1], width, height, stride); - - case DRM_FORMAT_ARGB4444: - case DRM_FORMAT_XRGB4444: - case DRM_FORMAT_ABGR4444: - case DRM_FORMAT_XBGR4444: - case DRM_FORMAT_RGBA4444: - case DRM_FORMAT_RGBX4444: - case DRM_FORMAT_BGRA4444: - case DRM_FORMAT_BGRX4444: - case DRM_FORMAT_RGB565: - case DRM_FORMAT_BGR565: - case DRM_FORMAT_ARGB1555: - case DRM_FORMAT_XRGB1555: - case DRM_FORMAT_ABGR1555: - case DRM_FORMAT_XBGR1555: - case DRM_FORMAT_RGBA5551: - case DRM_FORMAT_RGBX5551: - case DRM_FORMAT_BGRA5551: - case DRM_FORMAT_BGRX5551: - return fill_smpte_rgb16(&info->rgb, planes[0], - width, height, stride); - - case DRM_FORMAT_BGR888: - case DRM_FORMAT_RGB888: - return fill_smpte_rgb24(&info->rgb, planes[0], - width, height, stride); - case DRM_FORMAT_ARGB8888: - case DRM_FORMAT_XRGB8888: - case DRM_FORMAT_ABGR8888: - case DRM_FORMAT_XBGR8888: - case DRM_FORMAT_RGBA8888: - case DRM_FORMAT_RGBX8888: - case DRM_FORMAT_BGRA8888: - case DRM_FORMAT_BGRX8888: - case DRM_FORMAT_ARGB2101010: - case DRM_FORMAT_XRGB2101010: - case DRM_FORMAT_ABGR2101010: - case DRM_FORMAT_XBGR2101010: - case DRM_FORMAT_RGBA1010102: - case DRM_FORMAT_RGBX1010102: - case DRM_FORMAT_BGRA1010102: - case DRM_FORMAT_BGRX1010102: - return fill_smpte_rgb32(&info->rgb, planes[0], - width, height, stride); - } -} - -/* swap these for big endian.. */ -#define RED 2 -#define GREEN 1 -#define BLUE 0 - -static void -make_pwetty(void *data, int width, int height, int stride, uint32_t format) -{ -#ifdef HAVE_CAIRO - cairo_surface_t *surface; - cairo_t *cr; - int x, y; - cairo_format_t cairo_format; - - /* we can ignore the order of R,G,B channels */ - switch (format) { - case DRM_FORMAT_XRGB8888: - case DRM_FORMAT_ARGB8888: - case DRM_FORMAT_XBGR8888: - case DRM_FORMAT_ABGR8888: - cairo_format = CAIRO_FORMAT_ARGB32; - break; - case DRM_FORMAT_RGB565: - case DRM_FORMAT_BGR565: - cairo_format = CAIRO_FORMAT_RGB16_565; - break; - default: - return; - } - - surface = cairo_image_surface_create_for_data(data, - cairo_format, - width, height, - stride); - cr = cairo_create(surface); - cairo_surface_destroy(surface); - - cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE); - for (x = 0; x < width; x += 250) - for (y = 0; y < height; y += 250) { - char buf[64]; - - 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); -#endif -} - -static void -fill_tiles_yuv_planar(const struct format_info *info, - unsigned char *y_mem, unsigned char *u_mem, - unsigned char *v_mem, unsigned int width, - unsigned int height, unsigned int stride) -{ - const struct yuv_info *yuv = &info->yuv; - unsigned int cs = yuv->chroma_stride; - unsigned int xsub = yuv->xsub; - unsigned int ysub = yuv->ysub; - unsigned int x; - unsigned int y; - - for (y = 0; y < height; ++y) { - for (x = 0; x < width; ++x) { - div_t d = div(x+y, width); - uint32_t rgb32 = 0x00130502 * (d.quot >> 6) - + 0x000a1120 * (d.rem >> 6); - struct color_yuv color = - MAKE_YUV_601((rgb32 >> 16) & 0xff, - (rgb32 >> 8) & 0xff, rgb32 & 0xff); - - y_mem[x] = color.y; - u_mem[x/xsub*cs] = color.u; - v_mem[x/xsub*cs] = color.v; - } - - y_mem += stride; - if ((y + 1) % ysub == 0) { - u_mem += stride * cs / xsub; - v_mem += stride * cs / xsub; - } - } -} - -static void -fill_tiles_yuv_packed(const struct format_info *info, unsigned char *mem, - unsigned int width, unsigned int height, - unsigned int stride) -{ - const struct yuv_info *yuv = &info->yuv; - unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1; - unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1; - unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0; - unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0; - unsigned int x; - unsigned int y; - - for (y = 0; y < height; ++y) { - for (x = 0; x < width; x += 2) { - div_t d = div(x+y, width); - uint32_t rgb32 = 0x00130502 * (d.quot >> 6) - + 0x000a1120 * (d.rem >> 6); - struct color_yuv color = - MAKE_YUV_601((rgb32 >> 16) & 0xff, - (rgb32 >> 8) & 0xff, rgb32 & 0xff); - - y_mem[2*x] = color.y; - c_mem[2*x+u] = color.u; - y_mem[2*x+2] = color.y; - c_mem[2*x+v] = color.v; - } - - y_mem += stride; - c_mem += stride; - } -} - -static void -fill_tiles_rgb16(const struct format_info *info, unsigned char *mem, - unsigned int width, unsigned int height, unsigned int stride) -{ - const struct rgb_info *rgb = &info->rgb; - unsigned char *mem_base = mem; - unsigned int x, y; - - for (y = 0; y < height; ++y) { - for (x = 0; x < width; ++x) { - div_t d = div(x+y, width); - uint32_t rgb32 = 0x00130502 * (d.quot >> 6) - + 0x000a1120 * (d.rem >> 6); - uint16_t color = - MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff, - (rgb32 >> 8) & 0xff, rgb32 & 0xff, - 255); - - ((uint16_t *)mem)[x] = color; - } - mem += stride; - } - - make_pwetty(mem_base, width, height, stride, info->format); -} - -static void -fill_tiles_rgb24(const struct format_info *info, unsigned char *mem, - unsigned int width, unsigned int height, unsigned int stride) -{ - const struct rgb_info *rgb = &info->rgb; - unsigned int x, y; - - for (y = 0; y < height; ++y) { - for (x = 0; x < width; ++x) { - div_t d = div(x+y, width); - uint32_t rgb32 = 0x00130502 * (d.quot >> 6) - + 0x000a1120 * (d.rem >> 6); - struct color_rgb24 color = - MAKE_RGB24(rgb, (rgb32 >> 16) & 0xff, - (rgb32 >> 8) & 0xff, rgb32 & 0xff); - - ((struct color_rgb24 *)mem)[x] = color; - } - mem += stride; - } -} - -static void -fill_tiles_rgb32(const struct format_info *info, unsigned char *mem, - unsigned int width, unsigned int height, unsigned int stride) -{ - const struct rgb_info *rgb = &info->rgb; - unsigned char *mem_base = mem; - unsigned int x, y; - - for (y = 0; y < height; ++y) { - for (x = 0; x < width; ++x) { - div_t d = div(x+y, width); - uint32_t rgb32 = 0x00130502 * (d.quot >> 6) - + 0x000a1120 * (d.rem >> 6); - uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255; - uint32_t color = - MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff, - (rgb32 >> 8) & 0xff, rgb32 & 0xff, - alpha); - - ((uint32_t *)mem)[x] = color; - } - mem += stride; - } - - make_pwetty(mem_base, width, height, stride, info->format); -} - -static void -fill_tiles(const struct format_info *info, void *planes[3], unsigned int width, - unsigned int height, unsigned int stride) -{ - unsigned char *u, *v; - - switch (info->format) { - case DRM_FORMAT_UYVY: - case DRM_FORMAT_VYUY: - case DRM_FORMAT_YUYV: - case DRM_FORMAT_YVYU: - return fill_tiles_yuv_packed(info, planes[0], - width, height, stride); - - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV21: - case DRM_FORMAT_NV16: - case DRM_FORMAT_NV61: - u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1; - v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1; - return fill_tiles_yuv_planar(info, planes[0], u, v, - width, height, stride); - - case DRM_FORMAT_YUV420: - return fill_tiles_yuv_planar(info, planes[0], planes[1], - planes[2], width, height, stride); - - case DRM_FORMAT_YVU420: - return fill_tiles_yuv_planar(info, planes[0], planes[2], - planes[1], width, height, stride); - - case DRM_FORMAT_ARGB4444: - case DRM_FORMAT_XRGB4444: - case DRM_FORMAT_ABGR4444: - case DRM_FORMAT_XBGR4444: - case DRM_FORMAT_RGBA4444: - case DRM_FORMAT_RGBX4444: - case DRM_FORMAT_BGRA4444: - case DRM_FORMAT_BGRX4444: - case DRM_FORMAT_RGB565: - case DRM_FORMAT_BGR565: - case DRM_FORMAT_ARGB1555: - case DRM_FORMAT_XRGB1555: - case DRM_FORMAT_ABGR1555: - case DRM_FORMAT_XBGR1555: - case DRM_FORMAT_RGBA5551: - case DRM_FORMAT_RGBX5551: - case DRM_FORMAT_BGRA5551: - case DRM_FORMAT_BGRX5551: - return fill_tiles_rgb16(info, planes[0], - width, height, stride); - - case DRM_FORMAT_BGR888: - case DRM_FORMAT_RGB888: - return fill_tiles_rgb24(info, planes[0], - width, height, stride); - case DRM_FORMAT_ARGB8888: - case DRM_FORMAT_XRGB8888: - case DRM_FORMAT_ABGR8888: - case DRM_FORMAT_XBGR8888: - case DRM_FORMAT_RGBA8888: - case DRM_FORMAT_RGBX8888: - case DRM_FORMAT_BGRA8888: - case DRM_FORMAT_BGRX8888: - case DRM_FORMAT_ARGB2101010: - case DRM_FORMAT_XRGB2101010: - case DRM_FORMAT_ABGR2101010: - case DRM_FORMAT_XBGR2101010: - case DRM_FORMAT_RGBA1010102: - case DRM_FORMAT_RGBX1010102: - case DRM_FORMAT_BGRA1010102: - case DRM_FORMAT_BGRX1010102: - return fill_tiles_rgb32(info, planes[0], - width, height, stride); - } -} - -static void -fill_plain(const struct format_info *info, void *planes[3], unsigned int width, - unsigned int height, unsigned int stride) -{ - memset(planes[0], 0x77, stride * height); -} - -/* - * fill_pattern - Fill a buffer with a test pattern - * @format: Pixel format - * @pattern: Test pattern - * @buffer: Buffer memory - * @width: Width in pixels - * @height: Height in pixels - * @stride: Line stride (pitch) in bytes - * - * Fill the buffer with the test pattern specified by the pattern parameter. - * Supported formats vary depending on the selected pattern. - */ -static void -fill_pattern(unsigned int format, enum fill_pattern pattern, void *planes[3], - unsigned int width, unsigned int height, unsigned int stride) -{ - const struct format_info *info = NULL; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(format_info); ++i) { - if (format_info[i].format == format) { - info = &format_info[i]; - break; - } - } - - if (info == NULL) - return; - - switch (pattern) { - case PATTERN_TILES: - return fill_tiles(info, planes, width, height, stride); - - case PATTERN_SMPTE: - return fill_smpte(info, planes, width, height, stride); - - case PATTERN_PLAIN: - return fill_plain(info, planes, width, height, stride); - - default: - printf("Error: unsupported test pattern %u.\n", pattern); - break; - } -} - -/* ----------------------------------------------------------------------------- * Buffers management */
@@ -1086,7 +129,7 @@ struct bo * bo_create(int fd, unsigned int format, unsigned int width, unsigned int height, unsigned int handles[4], unsigned int pitches[4], - unsigned int offsets[4], enum fill_pattern pattern) + unsigned int offsets[4], enum util_fill_pattern pattern) { unsigned int virtual_height; struct bo *bo; @@ -1280,7 +323,7 @@ bo_create(int fd, unsigned int format, break; }
- fill_pattern(format, pattern, planes, width, height, pitches[0]); + util_fill_pattern(format, pattern, planes, width, height, pitches[0]); bo_unmap(bo);
return bo; diff --git a/tests/modetest/buffers.h b/tests/modetest/buffers.h index ad73d0e4ba73..7f95396b4403 100644 --- a/tests/modetest/buffers.h +++ b/tests/modetest/buffers.h @@ -27,20 +27,14 @@ #ifndef __BUFFERS_H__ #define __BUFFERS_H__
-struct bo; +#include "util/pattern.h"
-enum fill_pattern { - PATTERN_TILES = 0, - PATTERN_PLAIN = 1, - PATTERN_SMPTE = 2, -}; +struct bo;
struct bo *bo_create(int fd, unsigned int format, unsigned int width, unsigned int height, unsigned int handles[4], unsigned int pitches[4], - unsigned int offsets[4], enum fill_pattern pattern); + unsigned int offsets[4], enum util_fill_pattern pattern); void bo_destroy(struct bo *bo);
-unsigned int format_fourcc(const char *name); - #endif diff --git a/tests/modetest/cursor.c b/tests/modetest/cursor.c index d8a19bd2237e..6de82a4a719f 100644 --- a/tests/modetest/cursor.c +++ b/tests/modetest/cursor.c @@ -40,11 +40,11 @@ #include "xf86drm.h" #include "xf86drmMode.h"
+#include "util/common.h" + #include "buffers.h" #include "cursor.h"
-#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) - struct cursor { int fd; uint32_t bo_handle; diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index 3b01918d1adc..361c6da9016f 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -37,6 +37,7 @@ * TODO: use cairo to write the mode info on the selected output once * the mode has been programmed, along with possible test patterns. */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -59,6 +60,10 @@ #include "xf86drmMode.h" #include "drm_fourcc.h"
+#include "util/common.h" +#include "util/format.h" +#include "util/pattern.h" + #include "buffers.h" #include "cursor.h"
@@ -116,7 +121,6 @@ struct device { } mode; };
-#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) static inline int64_t U642I64(uint64_t val) { return (int64_t)*((int64_t *)&val); @@ -1047,7 +1051,7 @@ static int set_plane(struct device *dev, struct plane_arg *p) p->w, p->h, p->format_str, plane_id);
plane_bo = bo_create(dev->fd, p->fourcc, p->w, p->h, handles, - pitches, offsets, PATTERN_TILES); + pitches, offsets, UTIL_PATTERN_TILES); if (plane_bo == NULL) return -1;
@@ -1123,8 +1127,9 @@ static void set_mode(struct device *dev, struct pipe_arg *pipes, unsigned int co dev->mode.height = pipe->mode->vdisplay; }
- bo = bo_create(dev->fd, pipes[0].fourcc, dev->mode.width, dev->mode.height, - handles, pitches, offsets, PATTERN_SMPTE); + bo = bo_create(dev->fd, pipes[0].fourcc, dev->mode.width, + dev->mode.height, handles, pitches, offsets, + UTIL_PATTERN_SMPTE); if (bo == NULL) return;
@@ -1202,7 +1207,7 @@ static void set_cursors(struct device *dev, struct pipe_arg *pipes, unsigned int * translucent alpha */ bo = bo_create(dev->fd, DRM_FORMAT_ARGB8888, cw, ch, handles, pitches, - offsets, PATTERN_PLAIN); + offsets, UTIL_PATTERN_PLAIN); if (bo == NULL) return;
@@ -1241,9 +1246,9 @@ static void test_page_flip(struct device *dev, struct pipe_arg *pipes, unsigned unsigned int i; int ret;
- other_bo = bo_create(dev->fd, pipes[0].fourcc, - dev->mode.width, dev->mode.height, - handles, pitches, offsets, PATTERN_PLAIN); + other_bo = bo_create(dev->fd, pipes[0].fourcc, dev->mode.width, + dev->mode.height, handles, pitches, offsets, + UTIL_PATTERN_PLAIN); if (other_bo == NULL) return;
@@ -1391,7 +1396,7 @@ static int parse_connector(struct pipe_arg *pipe, const char *arg) pipe->format_str[4] = '\0'; }
- pipe->fourcc = format_fourcc(pipe->format_str); + pipe->fourcc = util_format_fourcc(pipe->format_str); if (pipe->fourcc == 0) { fprintf(stderr, "unknown format %s\n", pipe->format_str); return -1; @@ -1444,7 +1449,7 @@ static int parse_plane(struct plane_arg *plane, const char *p) strcpy(plane->format_str, "XR24"); }
- plane->fourcc = format_fourcc(plane->format_str); + plane->fourcc = util_format_fourcc(plane->format_str); if (plane->fourcc == 0) { fprintf(stderr, "unknown format %s\n", plane->format_str); return -EINVAL; diff --git a/tests/proptest/Makefile.am b/tests/proptest/Makefile.am index 0594e02e9904..142882066485 100644 --- a/tests/proptest/Makefile.am +++ b/tests/proptest/Makefile.am @@ -1,6 +1,7 @@ AM_CFLAGS = \ $(WARN_CFLAGS)\ -I$(top_srcdir)/include/drm \ + -I$(top_srcdir)/tests \ -I$(top_srcdir)
if HAVE_INSTALL_TESTS @@ -14,4 +15,5 @@ endif proptest_SOURCES = \ proptest.c proptest_LDADD = \ - $(top_builddir)/libdrm.la + $(top_builddir)/libdrm.la \ + $(top_builddir)/tests/util/libutil.la diff --git a/tests/proptest/proptest.c b/tests/proptest/proptest.c index b9296bdb6e3b..b6e00cfcfc4f 100644 --- a/tests/proptest/proptest.c +++ b/tests/proptest/proptest.c @@ -35,7 +35,8 @@ #include "xf86drm.h" #include "xf86drmMode.h"
-#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +#include "util/common.h" + static inline int64_t U642I64(uint64_t val) { return (int64_t)*((int64_t *)&val); diff --git a/tests/util/Android.mk b/tests/util/Android.mk new file mode 100644 index 000000000000..73bc6805f16c --- /dev/null +++ b/tests/util/Android.mk @@ -0,0 +1,39 @@ +# +# Copyright © 2015 NVIDIA Corporation +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +include $(LOCAL_PATH)/Makefile.sources + +LOCAL_MODULE := libdrm_util +LOCAL_MODULE_TAGS := optional + +LOCAL_SHARED_LIBRARIES := libdrm + +LOCAL_SRC_FILES := $(UTIL_FILES) + +# avoid name clashes by requiring users to include util/*.h +LOCAL_EXPORT_C_INCLUDE_DIRS := $(dir $(LOCAL_PATH)) + +include $(BUILD_STATIC_LIBRARY) diff --git a/tests/util/Makefile.am b/tests/util/Makefile.am new file mode 100644 index 000000000000..f8e0b1712cd2 --- /dev/null +++ b/tests/util/Makefile.am @@ -0,0 +1,13 @@ +include Makefile.sources + +noinst_LTLIBRARIES = \ + libutil.la + +libutil_la_CPPFLAGS = \ + -I$(top_srcdir)/include/drm \ + -I$(top_srcdir) + +libutil_la_CFLAGS = \ + $(CAIRO_CFLAGS) + +libutil_la_SOURCES = $(UTIL_FILES) diff --git a/tests/util/Makefile.sources b/tests/util/Makefile.sources new file mode 100644 index 000000000000..e91fa722650f --- /dev/null +++ b/tests/util/Makefile.sources @@ -0,0 +1,6 @@ +UTIL_FILES := \ + common.h \ + format.c \ + format.h \ + pattern.c \ + pattern.h diff --git a/tests/util/common.h b/tests/util/common.h new file mode 100644 index 000000000000..5d572c2dd003 --- /dev/null +++ b/tests/util/common.h @@ -0,0 +1,33 @@ +/* + * Copyright 2008 Tungsten Graphics + * Jakob Bornecrantz jakob@tungstengraphics.com + * Copyright 2008 Intel Corporation + * Jesse Barnes jesse.barnes@intel.com + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef UTIL_COMMON_H +#define UTIL_COMMON_H + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#endif + +#endif /* UTIL_COMMON_H */ diff --git a/tests/util/format.c b/tests/util/format.c new file mode 100644 index 000000000000..043cfe7f1eaf --- /dev/null +++ b/tests/util/format.c @@ -0,0 +1,120 @@ +/* + * Copyright 2008 Tungsten Graphics + * Jakob Bornecrantz jakob@tungstengraphics.com + * Copyright 2008 Intel Corporation + * Jesse Barnes jesse.barnes@intel.com + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include <drm_fourcc.h> + +#include "common.h" +#include "format.h" + +#define MAKE_RGB_INFO(rl, ro, gl, go, bl, bo, al, ao) \ + .rgb = { { (rl), (ro) }, { (gl), (go) }, { (bl), (bo) }, { (al), (ao) } } + +#define MAKE_YUV_INFO(order, xsub, ysub, chroma_stride) \ + .yuv = { (order), (xsub), (ysub), (chroma_stride) } + +static const struct util_format_info format_info[] = { + /* YUV packed */ + { DRM_FORMAT_UYVY, "UYVY", MAKE_YUV_INFO(YUV_YCbCr | YUV_CY, 2, 2, 2) }, + { DRM_FORMAT_VYUY, "VYUY", MAKE_YUV_INFO(YUV_YCrCb | YUV_CY, 2, 2, 2) }, + { DRM_FORMAT_YUYV, "YUYV", MAKE_YUV_INFO(YUV_YCbCr | YUV_YC, 2, 2, 2) }, + { DRM_FORMAT_YVYU, "YVYU", MAKE_YUV_INFO(YUV_YCrCb | YUV_YC, 2, 2, 2) }, + /* YUV semi-planar */ + { DRM_FORMAT_NV12, "NV12", MAKE_YUV_INFO(YUV_YCbCr, 2, 2, 2) }, + { DRM_FORMAT_NV21, "NV21", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 2) }, + { DRM_FORMAT_NV16, "NV16", MAKE_YUV_INFO(YUV_YCbCr, 2, 1, 2) }, + { DRM_FORMAT_NV61, "NV61", MAKE_YUV_INFO(YUV_YCrCb, 2, 1, 2) }, + /* YUV planar */ + { DRM_FORMAT_YUV420, "YU12", MAKE_YUV_INFO(YUV_YCbCr, 2, 2, 1) }, + { DRM_FORMAT_YVU420, "YV12", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 1) }, + /* RGB16 */ + { DRM_FORMAT_ARGB4444, "AR12", MAKE_RGB_INFO(4, 8, 4, 4, 4, 0, 4, 12) }, + { DRM_FORMAT_XRGB4444, "XR12", MAKE_RGB_INFO(4, 8, 4, 4, 4, 0, 0, 0) }, + { DRM_FORMAT_ABGR4444, "AB12", MAKE_RGB_INFO(4, 0, 4, 4, 4, 8, 4, 12) }, + { DRM_FORMAT_XBGR4444, "XB12", MAKE_RGB_INFO(4, 0, 4, 4, 4, 8, 0, 0) }, + { DRM_FORMAT_RGBA4444, "RA12", MAKE_RGB_INFO(4, 12, 4, 8, 4, 4, 4, 0) }, + { DRM_FORMAT_RGBX4444, "RX12", MAKE_RGB_INFO(4, 12, 4, 8, 4, 4, 0, 0) }, + { DRM_FORMAT_BGRA4444, "BA12", MAKE_RGB_INFO(4, 4, 4, 8, 4, 12, 4, 0) }, + { DRM_FORMAT_BGRX4444, "BX12", MAKE_RGB_INFO(4, 4, 4, 8, 4, 12, 0, 0) }, + { DRM_FORMAT_ARGB1555, "AR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 1, 15) }, + { DRM_FORMAT_XRGB1555, "XR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 0, 0) }, + { DRM_FORMAT_ABGR1555, "AB15", MAKE_RGB_INFO(5, 0, 5, 5, 5, 10, 1, 15) }, + { DRM_FORMAT_XBGR1555, "XB15", MAKE_RGB_INFO(5, 0, 5, 5, 5, 10, 0, 0) }, + { DRM_FORMAT_RGBA5551, "RA15", MAKE_RGB_INFO(5, 11, 5, 6, 5, 1, 1, 0) }, + { DRM_FORMAT_RGBX5551, "RX15", MAKE_RGB_INFO(5, 11, 5, 6, 5, 1, 0, 0) }, + { DRM_FORMAT_BGRA5551, "BA15", MAKE_RGB_INFO(5, 1, 5, 6, 5, 11, 1, 0) }, + { DRM_FORMAT_BGRX5551, "BX15", MAKE_RGB_INFO(5, 1, 5, 6, 5, 11, 0, 0) }, + { DRM_FORMAT_RGB565, "RG16", MAKE_RGB_INFO(5, 11, 6, 5, 5, 0, 0, 0) }, + { DRM_FORMAT_BGR565, "BG16", MAKE_RGB_INFO(5, 0, 6, 5, 5, 11, 0, 0) }, + /* RGB24 */ + { DRM_FORMAT_BGR888, "BG24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 0, 0) }, + { DRM_FORMAT_RGB888, "RG24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) }, + /* RGB32 */ + { DRM_FORMAT_ARGB8888, "AR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 8, 24) }, + { DRM_FORMAT_XRGB8888, "XR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) }, + { DRM_FORMAT_ABGR8888, "AB24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 8, 24) }, + { DRM_FORMAT_XBGR8888, "XB24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 0, 0) }, + { DRM_FORMAT_RGBA8888, "RA24", MAKE_RGB_INFO(8, 24, 8, 16, 8, 8, 8, 0) }, + { DRM_FORMAT_RGBX8888, "RX24", MAKE_RGB_INFO(8, 24, 8, 16, 8, 8, 0, 0) }, + { DRM_FORMAT_BGRA8888, "BA24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 8, 0) }, + { DRM_FORMAT_BGRX8888, "BX24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 0, 0) }, + { DRM_FORMAT_ARGB2101010, "AR30", MAKE_RGB_INFO(10, 20, 10, 10, 10, 0, 2, 30) }, + { DRM_FORMAT_XRGB2101010, "XR30", MAKE_RGB_INFO(10, 20, 10, 10, 10, 0, 0, 0) }, + { DRM_FORMAT_ABGR2101010, "AB30", MAKE_RGB_INFO(10, 0, 10, 10, 10, 20, 2, 30) }, + { DRM_FORMAT_XBGR2101010, "XB30", MAKE_RGB_INFO(10, 0, 10, 10, 10, 20, 0, 0) }, + { DRM_FORMAT_RGBA1010102, "RA30", MAKE_RGB_INFO(10, 22, 10, 12, 10, 2, 2, 0) }, + { DRM_FORMAT_RGBX1010102, "RX30", MAKE_RGB_INFO(10, 22, 10, 12, 10, 2, 0, 0) }, + { DRM_FORMAT_BGRA1010102, "BA30", MAKE_RGB_INFO(10, 2, 10, 12, 10, 22, 2, 0) }, + { DRM_FORMAT_BGRX1010102, "BX30", MAKE_RGB_INFO(10, 2, 10, 12, 10, 22, 0, 0) }, +}; + +uint32_t util_format_fourcc(const char *name) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(format_info); i++) + if (!strcmp(format_info[i].name, name)) + return format_info[i].format; + + return 0; +} + +const struct util_format_info *util_format_info_find(uint32_t format) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(format_info); i++) + if (format_info[i].format == format) + return &format_info[i]; + + return NULL; +} diff --git a/tests/util/format.h b/tests/util/format.h new file mode 100644 index 000000000000..2ce1c021fd78 --- /dev/null +++ b/tests/util/format.h @@ -0,0 +1,65 @@ +/* + * Copyright 2008 Tungsten Graphics + * Jakob Bornecrantz jakob@tungstengraphics.com + * Copyright 2008 Intel Corporation + * Jesse Barnes jesse.barnes@intel.com + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef UTIL_FORMAT_H +#define UTIL_FORMAT_H + +struct util_color_component { + unsigned int length; + unsigned int offset; +}; + +struct util_rgb_info { + struct util_color_component red; + struct util_color_component green; + struct util_color_component blue; + struct util_color_component alpha; +}; + +enum util_yuv_order { + YUV_YCbCr = 1, + YUV_YCrCb = 2, + YUV_YC = 4, + YUV_CY = 8, +}; + +struct util_yuv_info { + enum util_yuv_order order; + unsigned int xsub; + unsigned int ysub; + unsigned int chroma_stride; +}; + +struct util_format_info { + uint32_t format; + const char *name; + const struct util_rgb_info rgb; + const struct util_yuv_info yuv; +}; + +uint32_t util_format_fourcc(const char *name); +const struct util_format_info *util_format_info_find(uint32_t format); + +#endif /* UTIL_FORMAT_H */ diff --git a/tests/util/pattern.c b/tests/util/pattern.c new file mode 100644 index 000000000000..00b08a8cb8eb --- /dev/null +++ b/tests/util/pattern.c @@ -0,0 +1,870 @@ +/* + * Copyright 2008 Tungsten Graphics + * Jakob Bornecrantz jakob@tungstengraphics.com + * Copyright 2008 Intel Corporation + * Jesse Barnes jesse.barnes@intel.com + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <drm_fourcc.h> + +#ifdef HAVE_CAIRO +#include <cairo.h> +#include <math.h> +#endif + +#include "format.h" +#include "pattern.h" + +struct color_rgb24 { + unsigned int value:24; +} __attribute__((__packed__)); + +struct color_yuv { + unsigned char y; + unsigned char u; + unsigned char v; +}; + +#define MAKE_YUV_601_Y(r, g, b) \ + ((( 66 * (r) + 129 * (g) + 25 * (b) + 128) >> 8) + 16) +#define MAKE_YUV_601_U(r, g, b) \ + (((-38 * (r) - 74 * (g) + 112 * (b) + 128) >> 8) + 128) +#define MAKE_YUV_601_V(r, g, b) \ + (((112 * (r) - 94 * (g) - 18 * (b) + 128) >> 8) + 128) + +#define MAKE_YUV_601(r, g, b) \ + { .y = MAKE_YUV_601_Y(r, g, b), \ + .u = MAKE_YUV_601_U(r, g, b), \ + .v = MAKE_YUV_601_V(r, g, b) } + +#define MAKE_RGBA(rgb, r, g, b, a) \ + ((((r) >> (8 - (rgb)->red.length)) << (rgb)->red.offset) | \ + (((g) >> (8 - (rgb)->green.length)) << (rgb)->green.offset) | \ + (((b) >> (8 - (rgb)->blue.length)) << (rgb)->blue.offset) | \ + (((a) >> (8 - (rgb)->alpha.length)) << (rgb)->alpha.offset)) + +#define MAKE_RGB24(rgb, r, g, b) \ + { .value = MAKE_RGBA(rgb, r, g, b, 0) } + +static void fill_smpte_yuv_planar(const struct util_yuv_info *yuv, + unsigned char *y_mem, unsigned char *u_mem, + unsigned char *v_mem, unsigned int width, + unsigned int height, unsigned int stride) +{ + const struct color_yuv colors_top[] = { + MAKE_YUV_601(191, 192, 192), /* grey */ + MAKE_YUV_601(192, 192, 0), /* yellow */ + MAKE_YUV_601(0, 192, 192), /* cyan */ + MAKE_YUV_601(0, 192, 0), /* green */ + MAKE_YUV_601(192, 0, 192), /* magenta */ + MAKE_YUV_601(192, 0, 0), /* red */ + MAKE_YUV_601(0, 0, 192), /* blue */ + }; + const struct color_yuv colors_middle[] = { + MAKE_YUV_601(0, 0, 192), /* blue */ + MAKE_YUV_601(19, 19, 19), /* black */ + MAKE_YUV_601(192, 0, 192), /* magenta */ + MAKE_YUV_601(19, 19, 19), /* black */ + MAKE_YUV_601(0, 192, 192), /* cyan */ + MAKE_YUV_601(19, 19, 19), /* black */ + MAKE_YUV_601(192, 192, 192), /* grey */ + }; + const struct color_yuv colors_bottom[] = { + MAKE_YUV_601(0, 33, 76), /* in-phase */ + MAKE_YUV_601(255, 255, 255), /* super white */ + MAKE_YUV_601(50, 0, 106), /* quadrature */ + MAKE_YUV_601(19, 19, 19), /* black */ + MAKE_YUV_601(9, 9, 9), /* 3.5% */ + MAKE_YUV_601(19, 19, 19), /* 7.5% */ + MAKE_YUV_601(29, 29, 29), /* 11.5% */ + MAKE_YUV_601(19, 19, 19), /* black */ + }; + unsigned int cs = yuv->chroma_stride; + unsigned int xsub = yuv->xsub; + unsigned int ysub = yuv->ysub; + unsigned int x; + unsigned int y; + + /* Luma */ + for (y = 0; y < height * 6 / 9; ++y) { + for (x = 0; x < width; ++x) + y_mem[x] = colors_top[x * 7 / width].y; + y_mem += stride; + } + + for (; y < height * 7 / 9; ++y) { + for (x = 0; x < width; ++x) + y_mem[x] = colors_middle[x * 7 / width].y; + y_mem += stride; + } + + for (; y < height; ++y) { + for (x = 0; x < width * 5 / 7; ++x) + y_mem[x] = colors_bottom[x * 4 / (width * 5 / 7)].y; + for (; x < width * 6 / 7; ++x) + y_mem[x] = colors_bottom[(x - width * 5 / 7) * 3 + / (width / 7) + 4].y; + for (; x < width; ++x) + y_mem[x] = colors_bottom[7].y; + y_mem += stride; + } + + /* Chroma */ + for (y = 0; y < height / ysub * 6 / 9; ++y) { + for (x = 0; x < width; x += xsub) { + u_mem[x*cs/xsub] = colors_top[x * 7 / width].u; + v_mem[x*cs/xsub] = colors_top[x * 7 / width].v; + } + u_mem += stride * cs / xsub; + v_mem += stride * cs / xsub; + } + + for (; y < height / ysub * 7 / 9; ++y) { + for (x = 0; x < width; x += xsub) { + u_mem[x*cs/xsub] = colors_middle[x * 7 / width].u; + v_mem[x*cs/xsub] = colors_middle[x * 7 / width].v; + } + u_mem += stride * cs / xsub; + v_mem += stride * cs / xsub; + } + + for (; y < height / ysub; ++y) { + for (x = 0; x < width * 5 / 7; x += xsub) { + u_mem[x*cs/xsub] = + colors_bottom[x * 4 / (width * 5 / 7)].u; + v_mem[x*cs/xsub] = + colors_bottom[x * 4 / (width * 5 / 7)].v; + } + for (; x < width * 6 / 7; x += xsub) { + u_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) * + 3 / (width / 7) + 4].u; + v_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) * + 3 / (width / 7) + 4].v; + } + for (; x < width; x += xsub) { + u_mem[x*cs/xsub] = colors_bottom[7].u; + v_mem[x*cs/xsub] = colors_bottom[7].v; + } + u_mem += stride * cs / xsub; + v_mem += stride * cs / xsub; + } +} + +static void fill_smpte_yuv_packed(const struct util_yuv_info *yuv, void *mem, + unsigned int width, unsigned int height, + unsigned int stride) +{ + const struct color_yuv colors_top[] = { + MAKE_YUV_601(191, 192, 192), /* grey */ + MAKE_YUV_601(192, 192, 0), /* yellow */ + MAKE_YUV_601(0, 192, 192), /* cyan */ + MAKE_YUV_601(0, 192, 0), /* green */ + MAKE_YUV_601(192, 0, 192), /* magenta */ + MAKE_YUV_601(192, 0, 0), /* red */ + MAKE_YUV_601(0, 0, 192), /* blue */ + }; + const struct color_yuv colors_middle[] = { + MAKE_YUV_601(0, 0, 192), /* blue */ + MAKE_YUV_601(19, 19, 19), /* black */ + MAKE_YUV_601(192, 0, 192), /* magenta */ + MAKE_YUV_601(19, 19, 19), /* black */ + MAKE_YUV_601(0, 192, 192), /* cyan */ + MAKE_YUV_601(19, 19, 19), /* black */ + MAKE_YUV_601(192, 192, 192), /* grey */ + }; + const struct color_yuv colors_bottom[] = { + MAKE_YUV_601(0, 33, 76), /* in-phase */ + MAKE_YUV_601(255, 255, 255), /* super white */ + MAKE_YUV_601(50, 0, 106), /* quadrature */ + MAKE_YUV_601(19, 19, 19), /* black */ + MAKE_YUV_601(9, 9, 9), /* 3.5% */ + MAKE_YUV_601(19, 19, 19), /* 7.5% */ + MAKE_YUV_601(29, 29, 29), /* 11.5% */ + MAKE_YUV_601(19, 19, 19), /* black */ + }; + unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1; + unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1; + unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0; + unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0; + unsigned int x; + unsigned int y; + + /* Luma */ + for (y = 0; y < height * 6 / 9; ++y) { + for (x = 0; x < width; ++x) + y_mem[2*x] = colors_top[x * 7 / width].y; + y_mem += stride; + } + + for (; y < height * 7 / 9; ++y) { + for (x = 0; x < width; ++x) + y_mem[2*x] = colors_middle[x * 7 / width].y; + y_mem += stride; + } + + for (; y < height; ++y) { + for (x = 0; x < width * 5 / 7; ++x) + y_mem[2*x] = colors_bottom[x * 4 / (width * 5 / 7)].y; + for (; x < width * 6 / 7; ++x) + y_mem[2*x] = colors_bottom[(x - width * 5 / 7) * 3 + / (width / 7) + 4].y; + for (; x < width; ++x) + y_mem[2*x] = colors_bottom[7].y; + y_mem += stride; + } + + /* Chroma */ + for (y = 0; y < height * 6 / 9; ++y) { + for (x = 0; x < width; x += 2) { + c_mem[2*x+u] = colors_top[x * 7 / width].u; + c_mem[2*x+v] = colors_top[x * 7 / width].v; + } + c_mem += stride; + } + + for (; y < height * 7 / 9; ++y) { + for (x = 0; x < width; x += 2) { + c_mem[2*x+u] = colors_middle[x * 7 / width].u; + c_mem[2*x+v] = colors_middle[x * 7 / width].v; + } + c_mem += stride; + } + + for (; y < height; ++y) { + for (x = 0; x < width * 5 / 7; x += 2) { + c_mem[2*x+u] = colors_bottom[x * 4 / (width * 5 / 7)].u; + c_mem[2*x+v] = colors_bottom[x * 4 / (width * 5 / 7)].v; + } + for (; x < width * 6 / 7; x += 2) { + c_mem[2*x+u] = colors_bottom[(x - width * 5 / 7) * + 3 / (width / 7) + 4].u; + c_mem[2*x+v] = colors_bottom[(x - width * 5 / 7) * + 3 / (width / 7) + 4].v; + } + for (; x < width; x += 2) { + c_mem[2*x+u] = colors_bottom[7].u; + c_mem[2*x+v] = colors_bottom[7].v; + } + c_mem += stride; + } +} + +static void fill_smpte_rgb16(const struct util_rgb_info *rgb, void *mem, + unsigned int width, unsigned int height, + unsigned int stride) +{ + const uint16_t colors_top[] = { + MAKE_RGBA(rgb, 192, 192, 192, 255), /* grey */ + MAKE_RGBA(rgb, 192, 192, 0, 255), /* yellow */ + MAKE_RGBA(rgb, 0, 192, 192, 255), /* cyan */ + MAKE_RGBA(rgb, 0, 192, 0, 255), /* green */ + MAKE_RGBA(rgb, 192, 0, 192, 255), /* magenta */ + MAKE_RGBA(rgb, 192, 0, 0, 255), /* red */ + MAKE_RGBA(rgb, 0, 0, 192, 255), /* blue */ + }; + const uint16_t colors_middle[] = { + MAKE_RGBA(rgb, 0, 0, 192, 127), /* blue */ + MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ + MAKE_RGBA(rgb, 192, 0, 192, 127), /* magenta */ + MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ + MAKE_RGBA(rgb, 0, 192, 192, 127), /* cyan */ + MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ + MAKE_RGBA(rgb, 192, 192, 192, 127), /* grey */ + }; + const uint16_t colors_bottom[] = { + MAKE_RGBA(rgb, 0, 33, 76, 255), /* in-phase */ + MAKE_RGBA(rgb, 255, 255, 255, 255), /* super white */ + MAKE_RGBA(rgb, 50, 0, 106, 255), /* quadrature */ + MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ + MAKE_RGBA(rgb, 9, 9, 9, 255), /* 3.5% */ + MAKE_RGBA(rgb, 19, 19, 19, 255), /* 7.5% */ + MAKE_RGBA(rgb, 29, 29, 29, 255), /* 11.5% */ + MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ + }; + unsigned int x; + unsigned int y; + + for (y = 0; y < height * 6 / 9; ++y) { + for (x = 0; x < width; ++x) + ((uint16_t *)mem)[x] = colors_top[x * 7 / width]; + mem += stride; + } + + for (; y < height * 7 / 9; ++y) { + for (x = 0; x < width; ++x) + ((uint16_t *)mem)[x] = colors_middle[x * 7 / width]; + mem += stride; + } + + for (; y < height; ++y) { + for (x = 0; x < width * 5 / 7; ++x) + ((uint16_t *)mem)[x] = + colors_bottom[x * 4 / (width * 5 / 7)]; + for (; x < width * 6 / 7; ++x) + ((uint16_t *)mem)[x] = + colors_bottom[(x - width * 5 / 7) * 3 + / (width / 7) + 4]; + for (; x < width; ++x) + ((uint16_t *)mem)[x] = colors_bottom[7]; + mem += stride; + } +} + +static void fill_smpte_rgb24(const struct util_rgb_info *rgb, void *mem, + unsigned int width, unsigned int height, + unsigned int stride) +{ + const struct color_rgb24 colors_top[] = { + MAKE_RGB24(rgb, 192, 192, 192), /* grey */ + MAKE_RGB24(rgb, 192, 192, 0), /* yellow */ + MAKE_RGB24(rgb, 0, 192, 192), /* cyan */ + MAKE_RGB24(rgb, 0, 192, 0), /* green */ + MAKE_RGB24(rgb, 192, 0, 192), /* magenta */ + MAKE_RGB24(rgb, 192, 0, 0), /* red */ + MAKE_RGB24(rgb, 0, 0, 192), /* blue */ + }; + const struct color_rgb24 colors_middle[] = { + MAKE_RGB24(rgb, 0, 0, 192), /* blue */ + MAKE_RGB24(rgb, 19, 19, 19), /* black */ + MAKE_RGB24(rgb, 192, 0, 192), /* magenta */ + MAKE_RGB24(rgb, 19, 19, 19), /* black */ + MAKE_RGB24(rgb, 0, 192, 192), /* cyan */ + MAKE_RGB24(rgb, 19, 19, 19), /* black */ + MAKE_RGB24(rgb, 192, 192, 192), /* grey */ + }; + const struct color_rgb24 colors_bottom[] = { + MAKE_RGB24(rgb, 0, 33, 76), /* in-phase */ + MAKE_RGB24(rgb, 255, 255, 255), /* super white */ + MAKE_RGB24(rgb, 50, 0, 106), /* quadrature */ + MAKE_RGB24(rgb, 19, 19, 19), /* black */ + MAKE_RGB24(rgb, 9, 9, 9), /* 3.5% */ + MAKE_RGB24(rgb, 19, 19, 19), /* 7.5% */ + MAKE_RGB24(rgb, 29, 29, 29), /* 11.5% */ + MAKE_RGB24(rgb, 19, 19, 19), /* black */ + }; + unsigned int x; + unsigned int y; + + for (y = 0; y < height * 6 / 9; ++y) { + for (x = 0; x < width; ++x) + ((struct color_rgb24 *)mem)[x] = + colors_top[x * 7 / width]; + mem += stride; + } + + for (; y < height * 7 / 9; ++y) { + for (x = 0; x < width; ++x) + ((struct color_rgb24 *)mem)[x] = + colors_middle[x * 7 / width]; + mem += stride; + } + + for (; y < height; ++y) { + for (x = 0; x < width * 5 / 7; ++x) + ((struct color_rgb24 *)mem)[x] = + colors_bottom[x * 4 / (width * 5 / 7)]; + for (; x < width * 6 / 7; ++x) + ((struct color_rgb24 *)mem)[x] = + colors_bottom[(x - width * 5 / 7) * 3 + / (width / 7) + 4]; + for (; x < width; ++x) + ((struct color_rgb24 *)mem)[x] = colors_bottom[7]; + mem += stride; + } +} + +static void fill_smpte_rgb32(const struct util_rgb_info *rgb, void *mem, + unsigned int width, unsigned int height, + unsigned int stride) +{ + const uint32_t colors_top[] = { + MAKE_RGBA(rgb, 192, 192, 192, 255), /* grey */ + MAKE_RGBA(rgb, 192, 192, 0, 255), /* yellow */ + MAKE_RGBA(rgb, 0, 192, 192, 255), /* cyan */ + MAKE_RGBA(rgb, 0, 192, 0, 255), /* green */ + MAKE_RGBA(rgb, 192, 0, 192, 255), /* magenta */ + MAKE_RGBA(rgb, 192, 0, 0, 255), /* red */ + MAKE_RGBA(rgb, 0, 0, 192, 255), /* blue */ + }; + const uint32_t colors_middle[] = { + MAKE_RGBA(rgb, 0, 0, 192, 127), /* blue */ + MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ + MAKE_RGBA(rgb, 192, 0, 192, 127), /* magenta */ + MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ + MAKE_RGBA(rgb, 0, 192, 192, 127), /* cyan */ + MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ + MAKE_RGBA(rgb, 192, 192, 192, 127), /* grey */ + }; + const uint32_t colors_bottom[] = { + MAKE_RGBA(rgb, 0, 33, 76, 255), /* in-phase */ + MAKE_RGBA(rgb, 255, 255, 255, 255), /* super white */ + MAKE_RGBA(rgb, 50, 0, 106, 255), /* quadrature */ + MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ + MAKE_RGBA(rgb, 9, 9, 9, 255), /* 3.5% */ + MAKE_RGBA(rgb, 19, 19, 19, 255), /* 7.5% */ + MAKE_RGBA(rgb, 29, 29, 29, 255), /* 11.5% */ + MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ + }; + unsigned int x; + unsigned int y; + + for (y = 0; y < height * 6 / 9; ++y) { + for (x = 0; x < width; ++x) + ((uint32_t *)mem)[x] = colors_top[x * 7 / width]; + mem += stride; + } + + for (; y < height * 7 / 9; ++y) { + for (x = 0; x < width; ++x) + ((uint32_t *)mem)[x] = colors_middle[x * 7 / width]; + mem += stride; + } + + for (; y < height; ++y) { + for (x = 0; x < width * 5 / 7; ++x) + ((uint32_t *)mem)[x] = + colors_bottom[x * 4 / (width * 5 / 7)]; + for (; x < width * 6 / 7; ++x) + ((uint32_t *)mem)[x] = + colors_bottom[(x - width * 5 / 7) * 3 + / (width / 7) + 4]; + for (; x < width; ++x) + ((uint32_t *)mem)[x] = colors_bottom[7]; + mem += stride; + } +} + +static void fill_smpte(const struct util_format_info *info, void *planes[3], + unsigned int width, unsigned int height, + unsigned int stride) +{ + unsigned char *u, *v; + + switch (info->format) { + case DRM_FORMAT_UYVY: + case DRM_FORMAT_VYUY: + case DRM_FORMAT_YUYV: + case DRM_FORMAT_YVYU: + return fill_smpte_yuv_packed(&info->yuv, planes[0], width, + height, stride); + + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV21: + case DRM_FORMAT_NV16: + case DRM_FORMAT_NV61: + u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1; + v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1; + return fill_smpte_yuv_planar(&info->yuv, planes[0], u, v, + width, height, stride); + + case DRM_FORMAT_YUV420: + return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[1], + planes[2], width, height, stride); + + case DRM_FORMAT_YVU420: + return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[2], + planes[1], width, height, stride); + + case DRM_FORMAT_ARGB4444: + case DRM_FORMAT_XRGB4444: + case DRM_FORMAT_ABGR4444: + case DRM_FORMAT_XBGR4444: + case DRM_FORMAT_RGBA4444: + case DRM_FORMAT_RGBX4444: + case DRM_FORMAT_BGRA4444: + case DRM_FORMAT_BGRX4444: + case DRM_FORMAT_RGB565: + case DRM_FORMAT_BGR565: + case DRM_FORMAT_ARGB1555: + case DRM_FORMAT_XRGB1555: + case DRM_FORMAT_ABGR1555: + case DRM_FORMAT_XBGR1555: + case DRM_FORMAT_RGBA5551: + case DRM_FORMAT_RGBX5551: + case DRM_FORMAT_BGRA5551: + case DRM_FORMAT_BGRX5551: + return fill_smpte_rgb16(&info->rgb, planes[0], + width, height, stride); + + case DRM_FORMAT_BGR888: + case DRM_FORMAT_RGB888: + return fill_smpte_rgb24(&info->rgb, planes[0], + width, height, stride); + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_RGBA8888: + case DRM_FORMAT_RGBX8888: + case DRM_FORMAT_BGRA8888: + case DRM_FORMAT_BGRX8888: + case DRM_FORMAT_ARGB2101010: + case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_ABGR2101010: + case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_RGBA1010102: + case DRM_FORMAT_RGBX1010102: + case DRM_FORMAT_BGRA1010102: + case DRM_FORMAT_BGRX1010102: + return fill_smpte_rgb32(&info->rgb, planes[0], + width, height, stride); + } +} + +/* swap these for big endian.. */ +#define RED 2 +#define GREEN 1 +#define BLUE 0 + +static void make_pwetty(void *data, unsigned int width, unsigned int height, + unsigned int stride, uint32_t format) +{ +#ifdef HAVE_CAIRO + cairo_surface_t *surface; + cairo_t *cr; + int x, y; + cairo_format_t cairo_format; + + /* we can ignore the order of R,G,B channels */ + switch (format) { + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_ABGR8888: + cairo_format = CAIRO_FORMAT_ARGB32; + break; + case DRM_FORMAT_RGB565: + case DRM_FORMAT_BGR565: + cairo_format = CAIRO_FORMAT_RGB16_565; + break; + default: + return; + } + + surface = cairo_image_surface_create_for_data(data, + cairo_format, + width, height, + stride); + cr = cairo_create(surface); + cairo_surface_destroy(surface); + + cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE); + for (x = 0; x < width; x += 250) + for (y = 0; y < height; y += 250) { + char buf[64]; + + 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); +#endif +} + +static void fill_tiles_yuv_planar(const struct util_format_info *info, + unsigned char *y_mem, unsigned char *u_mem, + unsigned char *v_mem, unsigned int width, + unsigned int height, unsigned int stride) +{ + const struct util_yuv_info *yuv = &info->yuv; + unsigned int cs = yuv->chroma_stride; + unsigned int xsub = yuv->xsub; + unsigned int ysub = yuv->ysub; + unsigned int x; + unsigned int y; + + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + div_t d = div(x+y, width); + uint32_t rgb32 = 0x00130502 * (d.quot >> 6) + + 0x000a1120 * (d.rem >> 6); + struct color_yuv color = + MAKE_YUV_601((rgb32 >> 16) & 0xff, + (rgb32 >> 8) & 0xff, rgb32 & 0xff); + + y_mem[x] = color.y; + u_mem[x/xsub*cs] = color.u; + v_mem[x/xsub*cs] = color.v; + } + + y_mem += stride; + if ((y + 1) % ysub == 0) { + u_mem += stride * cs / xsub; + v_mem += stride * cs / xsub; + } + } +} + +static void fill_tiles_yuv_packed(const struct util_format_info *info, + void *mem, unsigned int width, + unsigned int height, unsigned int stride) +{ + const struct util_yuv_info *yuv = &info->yuv; + unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1; + unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1; + unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0; + unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0; + unsigned int x; + unsigned int y; + + for (y = 0; y < height; ++y) { + for (x = 0; x < width; x += 2) { + div_t d = div(x+y, width); + uint32_t rgb32 = 0x00130502 * (d.quot >> 6) + + 0x000a1120 * (d.rem >> 6); + struct color_yuv color = + MAKE_YUV_601((rgb32 >> 16) & 0xff, + (rgb32 >> 8) & 0xff, rgb32 & 0xff); + + y_mem[2*x] = color.y; + c_mem[2*x+u] = color.u; + y_mem[2*x+2] = color.y; + c_mem[2*x+v] = color.v; + } + + y_mem += stride; + c_mem += stride; + } +} + +static void fill_tiles_rgb16(const struct util_format_info *info, void *mem, + unsigned int width, unsigned int height, + unsigned int stride) +{ + const struct util_rgb_info *rgb = &info->rgb; + void *mem_base = mem; + unsigned int x, y; + + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + div_t d = div(x+y, width); + uint32_t rgb32 = 0x00130502 * (d.quot >> 6) + + 0x000a1120 * (d.rem >> 6); + uint16_t color = + MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff, + (rgb32 >> 8) & 0xff, rgb32 & 0xff, + 255); + + ((uint16_t *)mem)[x] = color; + } + mem += stride; + } + + make_pwetty(mem_base, width, height, stride, info->format); +} + +static void fill_tiles_rgb24(const struct util_format_info *info, void *mem, + unsigned int width, unsigned int height, + unsigned int stride) +{ + const struct util_rgb_info *rgb = &info->rgb; + unsigned int x, y; + + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + div_t d = div(x+y, width); + uint32_t rgb32 = 0x00130502 * (d.quot >> 6) + + 0x000a1120 * (d.rem >> 6); + struct color_rgb24 color = + MAKE_RGB24(rgb, (rgb32 >> 16) & 0xff, + (rgb32 >> 8) & 0xff, rgb32 & 0xff); + + ((struct color_rgb24 *)mem)[x] = color; + } + mem += stride; + } +} + +static void fill_tiles_rgb32(const struct util_format_info *info, void *mem, + unsigned int width, unsigned int height, + unsigned int stride) +{ + const struct util_rgb_info *rgb = &info->rgb; + void *mem_base = mem; + unsigned int x, y; + + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + div_t d = div(x+y, width); + uint32_t rgb32 = 0x00130502 * (d.quot >> 6) + + 0x000a1120 * (d.rem >> 6); + uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255; + uint32_t color = + MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff, + (rgb32 >> 8) & 0xff, rgb32 & 0xff, + alpha); + + ((uint32_t *)mem)[x] = color; + } + mem += stride; + } + + make_pwetty(mem_base, width, height, stride, info->format); +} + +static void fill_tiles(const struct util_format_info *info, void *planes[3], + unsigned int width, unsigned int height, + unsigned int stride) +{ + unsigned char *u, *v; + + switch (info->format) { + case DRM_FORMAT_UYVY: + case DRM_FORMAT_VYUY: + case DRM_FORMAT_YUYV: + case DRM_FORMAT_YVYU: + return fill_tiles_yuv_packed(info, planes[0], + width, height, stride); + + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV21: + case DRM_FORMAT_NV16: + case DRM_FORMAT_NV61: + u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1; + v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1; + return fill_tiles_yuv_planar(info, planes[0], u, v, + width, height, stride); + + case DRM_FORMAT_YUV420: + return fill_tiles_yuv_planar(info, planes[0], planes[1], + planes[2], width, height, stride); + + case DRM_FORMAT_YVU420: + return fill_tiles_yuv_planar(info, planes[0], planes[2], + planes[1], width, height, stride); + + case DRM_FORMAT_ARGB4444: + case DRM_FORMAT_XRGB4444: + case DRM_FORMAT_ABGR4444: + case DRM_FORMAT_XBGR4444: + case DRM_FORMAT_RGBA4444: + case DRM_FORMAT_RGBX4444: + case DRM_FORMAT_BGRA4444: + case DRM_FORMAT_BGRX4444: + case DRM_FORMAT_RGB565: + case DRM_FORMAT_BGR565: + case DRM_FORMAT_ARGB1555: + case DRM_FORMAT_XRGB1555: + case DRM_FORMAT_ABGR1555: + case DRM_FORMAT_XBGR1555: + case DRM_FORMAT_RGBA5551: + case DRM_FORMAT_RGBX5551: + case DRM_FORMAT_BGRA5551: + case DRM_FORMAT_BGRX5551: + return fill_tiles_rgb16(info, planes[0], + width, height, stride); + + case DRM_FORMAT_BGR888: + case DRM_FORMAT_RGB888: + return fill_tiles_rgb24(info, planes[0], + width, height, stride); + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_RGBA8888: + case DRM_FORMAT_RGBX8888: + case DRM_FORMAT_BGRA8888: + case DRM_FORMAT_BGRX8888: + case DRM_FORMAT_ARGB2101010: + case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_ABGR2101010: + case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_RGBA1010102: + case DRM_FORMAT_RGBX1010102: + case DRM_FORMAT_BGRA1010102: + case DRM_FORMAT_BGRX1010102: + return fill_tiles_rgb32(info, planes[0], + width, height, stride); + } +} + +static void fill_plain(const struct util_format_info *info, void *planes[3], + unsigned int width, unsigned int height, + unsigned int stride) +{ + memset(planes[0], 0x77, stride * height); +} + +/* + * util_fill_pattern - Fill a buffer with a test pattern + * @format: Pixel format + * @pattern: Test pattern + * @planes: Array of buffers + * @width: Width in pixels + * @height: Height in pixels + * @stride: Line stride (pitch) in bytes + * + * Fill the buffers with the test pattern specified by the pattern parameter. + * Supported formats vary depending on the selected pattern. + */ +void util_fill_pattern(uint32_t format, enum util_fill_pattern pattern, + void *planes[3], unsigned int width, + unsigned int height, unsigned int stride) +{ + const struct util_format_info *info; + + info = util_format_info_find(format); + if (info == NULL) + return; + + switch (pattern) { + case UTIL_PATTERN_TILES: + return fill_tiles(info, planes, width, height, stride); + + case UTIL_PATTERN_SMPTE: + return fill_smpte(info, planes, width, height, stride); + + case UTIL_PATTERN_PLAIN: + return fill_plain(info, planes, width, height, stride); + + default: + printf("Error: unsupported test pattern %u.\n", pattern); + break; + } +} diff --git a/tests/util/pattern.h b/tests/util/pattern.h new file mode 100644 index 000000000000..d5c4260cc6ed --- /dev/null +++ b/tests/util/pattern.h @@ -0,0 +1,39 @@ +/* + * Copyright 2008 Tungsten Graphics + * Jakob Bornecrantz jakob@tungstengraphics.com + * Copyright 2008 Intel Corporation + * Jesse Barnes jesse.barnes@intel.com + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef UTIL_PATTERN_H +#define UTIL_PATTERN_H + +enum util_fill_pattern { + UTIL_PATTERN_TILES, + UTIL_PATTERN_PLAIN, + UTIL_PATTERN_SMPTE, +}; + +void util_fill_pattern(uint32_t format, enum util_fill_pattern pattern, + void *planes[3], unsigned int width, + unsigned int height, unsigned int stride); + +#endif /* UTIL_PATTERN_H */ diff --git a/tests/vbltest/Makefile.am b/tests/vbltest/Makefile.am index 4d87887a5686..182e3b6d271c 100644 --- a/tests/vbltest/Makefile.am +++ b/tests/vbltest/Makefile.am @@ -1,6 +1,7 @@ AM_CFLAGS = \ $(WARN_CFLAGS)\ -I$(top_srcdir)/include/drm \ + -I$(top_srcdir)/tests \ -I$(top_srcdir)
if HAVE_INSTALL_TESTS diff --git a/tests/vbltest/vbltest.c b/tests/vbltest/vbltest.c index e27f45c1b9c1..de93e7702b26 100644 --- a/tests/vbltest/vbltest.c +++ b/tests/vbltest/vbltest.c @@ -54,7 +54,7 @@ #include "xf86drm.h" #include "xf86drmMode.h"
-#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +#include "util/common.h"
extern char *optarg; extern int optind, opterr, optopt;
From: Thierry Reding treding@nvidia.com
These tables are duplicated in several places, so move them into libutil so that they can be shared.
Acked-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Signed-off-by: Thierry Reding treding@nvidia.com --- tests/modetest/modetest.c | 68 +++--------------------- tests/proptest/proptest.c | 41 +-------------- tests/util/Makefile.sources | 2 + tests/util/kms.c | 122 ++++++++++++++++++++++++++++++++++++++++++++ tests/util/kms.h | 33 ++++++++++++ 5 files changed, 165 insertions(+), 101 deletions(-) create mode 100644 tests/util/kms.c create mode 100644 tests/util/kms.h
diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index 361c6da9016f..0e009d87fdee 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -62,6 +62,7 @@
#include "util/common.h" #include "util/format.h" +#include "util/kms.h" #include "util/pattern.h"
#include "buffers.h" @@ -126,64 +127,6 @@ static inline int64_t U642I64(uint64_t val) return (int64_t)*((int64_t *)&val); }
-struct type_name { - int type; - const char *name; -}; - -#define type_name_fn(res) \ -const char * res##_str(int type) { \ - unsigned int i; \ - for (i = 0; i < ARRAY_SIZE(res##_names); i++) { \ - if (res##_names[i].type == type) \ - return res##_names[i].name; \ - } \ - return "(invalid)"; \ -} - -struct type_name encoder_type_names[] = { - { DRM_MODE_ENCODER_NONE, "none" }, - { DRM_MODE_ENCODER_DAC, "DAC" }, - { DRM_MODE_ENCODER_TMDS, "TMDS" }, - { DRM_MODE_ENCODER_LVDS, "LVDS" }, - { DRM_MODE_ENCODER_TVDAC, "TVDAC" }, - { DRM_MODE_ENCODER_VIRTUAL, "Virtual" }, - { DRM_MODE_ENCODER_DSI, "DSI" }, - { DRM_MODE_ENCODER_DPMST, "DPMST" }, -}; - -static type_name_fn(encoder_type) - -struct type_name connector_status_names[] = { - { DRM_MODE_CONNECTED, "connected" }, - { DRM_MODE_DISCONNECTED, "disconnected" }, - { DRM_MODE_UNKNOWNCONNECTION, "unknown" }, -}; - -static type_name_fn(connector_status) - -struct type_name connector_type_names[] = { - { DRM_MODE_CONNECTOR_Unknown, "unknown" }, - { DRM_MODE_CONNECTOR_VGA, "VGA" }, - { DRM_MODE_CONNECTOR_DVII, "DVI-I" }, - { DRM_MODE_CONNECTOR_DVID, "DVI-D" }, - { DRM_MODE_CONNECTOR_DVIA, "DVI-A" }, - { DRM_MODE_CONNECTOR_Composite, "composite" }, - { DRM_MODE_CONNECTOR_SVIDEO, "s-video" }, - { DRM_MODE_CONNECTOR_LVDS, "LVDS" }, - { DRM_MODE_CONNECTOR_Component, "component" }, - { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" }, - { DRM_MODE_CONNECTOR_DisplayPort, "DP" }, - { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" }, - { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" }, - { DRM_MODE_CONNECTOR_TV, "TV" }, - { DRM_MODE_CONNECTOR_eDP, "eDP" }, - { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" }, - { DRM_MODE_CONNECTOR_DSI, "DSI" }, -}; - -static type_name_fn(connector_type) - #define bit_name_fn(res) \ const char * res##_str(int type) { \ unsigned int i; \ @@ -243,7 +186,7 @@ static void dump_encoders(struct device *dev) printf("%d\t%d\t%s\t0x%08x\t0x%08x\n", encoder->encoder_id, encoder->crtc_id, - encoder_type_str(encoder->encoder_type), + util_lookup_encoder_type_name(encoder->encoder_type), encoder->possible_crtcs, encoder->possible_clones); } @@ -387,7 +330,7 @@ static void dump_connectors(struct device *dev) printf("%d\t%d\t%s\t%-15s\t%dx%d\t\t%d\t", connector->connector_id, connector->encoder_id, - connector_status_str(connector->connection), + util_lookup_connector_status_name(connector->connection), _connector->name, connector->mmWidth, connector->mmHeight, connector->count_modes); @@ -611,10 +554,11 @@ static struct resources *get_resources(struct device *dev) /* Set the name of all connectors based on the type name and the per-type ID. */ for (i = 0; i < res->res->count_connectors; i++) { struct connector *connector = &res->connectors[i]; + drmModeConnector *conn = connector->connector;
asprintf(&connector->name, "%s-%u", - connector_type_str(connector->connector->connector_type), - connector->connector->connector_type_id); + util_lookup_connector_type_name(conn->connector_type), + conn->connector_type_id); }
#define get_properties(_res, __res, type, Type) \ diff --git a/tests/proptest/proptest.c b/tests/proptest/proptest.c index b6e00cfcfc4f..11eb6e88cef5 100644 --- a/tests/proptest/proptest.c +++ b/tests/proptest/proptest.c @@ -36,6 +36,7 @@ #include "xf86drmMode.h"
#include "util/common.h" +#include "util/kms.h"
static inline int64_t U642I64(uint64_t val) { @@ -45,44 +46,6 @@ static inline int64_t U642I64(uint64_t val) int fd; drmModeResPtr res = NULL;
-static const char *connector_type_str(uint32_t type) -{ - switch (type) { - case DRM_MODE_CONNECTOR_Unknown: - return "Unknown"; - case DRM_MODE_CONNECTOR_VGA: - return "VGA"; - case DRM_MODE_CONNECTOR_DVII: - return "DVI-I"; - case DRM_MODE_CONNECTOR_DVID: - return "DVI-D"; - case DRM_MODE_CONNECTOR_DVIA: - return "DVI-A"; - case DRM_MODE_CONNECTOR_Composite: - return "Composite"; - case DRM_MODE_CONNECTOR_SVIDEO: - return "SVIDEO"; - case DRM_MODE_CONNECTOR_LVDS: - return "LVDS"; - case DRM_MODE_CONNECTOR_Component: - return "Component"; - case DRM_MODE_CONNECTOR_9PinDIN: - return "9PinDin"; - case DRM_MODE_CONNECTOR_DisplayPort: - return "DisplayPort"; - case DRM_MODE_CONNECTOR_HDMIA: - return "HDMI-A"; - case DRM_MODE_CONNECTOR_HDMIB: - return "HDMI-B"; - case DRM_MODE_CONNECTOR_TV: - return "TV"; - case DRM_MODE_CONNECTOR_eDP: - return "eDP"; - default: - return "Invalid"; - } -} - /* dump_blob and dump_prop shamelessly copied from ../modetest/modetest.c */ static void dump_blob(uint32_t blob_id) @@ -226,7 +189,7 @@ static void listConnectorProperties(void) }
printf("Connector %u (%s-%u)\n", c->connector_id, - connector_type_str(c->connector_type), + util_lookup_connector_type_name(c->connector_type), c->connector_type_id);
listObjectProperties(c->connector_id, diff --git a/tests/util/Makefile.sources b/tests/util/Makefile.sources index e91fa722650f..e5f851136dd4 100644 --- a/tests/util/Makefile.sources +++ b/tests/util/Makefile.sources @@ -2,5 +2,7 @@ UTIL_FILES := \ common.h \ format.c \ format.h \ + kms.c \ + kms.h \ pattern.c \ pattern.h diff --git a/tests/util/kms.c b/tests/util/kms.c new file mode 100644 index 000000000000..687b3c3c1cf3 --- /dev/null +++ b/tests/util/kms.c @@ -0,0 +1,122 @@ +/* + * Copyright 2008 Tungsten Graphics + * Jakob Bornecrantz jakob@tungstengraphics.com + * Copyright 2008 Intel Corporation + * Jesse Barnes jesse.barnes@intel.com + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/* + * This fairly simple test program dumps output in a similar format to the + * "xrandr" tool everyone knows & loves. It's necessarily slightly different + * since the kernel separates outputs into encoder and connector structures, + * each with their own unique ID. The program also allows test testing of the + * memory management and mode setting APIs by allowing the user to specify a + * connector and mode to use for mode setting. If all works as expected, a + * blue background should be painted on the monitor attached to the specified + * connector after the selected mode is set. + * + * TODO: use cairo to write the mode info on the selected output once + * the mode has been programmed, along with possible test patterns. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdint.h> +#include <stdlib.h> + +#include "xf86drmMode.h" + +#include "common.h" + +struct type_name { + unsigned int type; + const char *name; +}; + +static const char *util_lookup_type_name(unsigned int type, + const struct type_name *table, + unsigned int count) +{ + unsigned int i; + + for (i = 0; i < count; i++) + if (table[i].type == type) + return table[i].name; + + return NULL; +} + +static const struct type_name encoder_type_names[] = { + { DRM_MODE_ENCODER_NONE, "none" }, + { DRM_MODE_ENCODER_DAC, "DAC" }, + { DRM_MODE_ENCODER_TMDS, "TMDS" }, + { DRM_MODE_ENCODER_LVDS, "LVDS" }, + { DRM_MODE_ENCODER_TVDAC, "TVDAC" }, + { DRM_MODE_ENCODER_VIRTUAL, "Virtual" }, + { DRM_MODE_ENCODER_DSI, "DSI" }, + { DRM_MODE_ENCODER_DPMST, "DPMST" }, +}; + +const char *util_lookup_encoder_type_name(unsigned int type) +{ + return util_lookup_type_name(type, encoder_type_names, + ARRAY_SIZE(encoder_type_names)); +} + +static const struct type_name connector_status_names[] = { + { DRM_MODE_CONNECTED, "connected" }, + { DRM_MODE_DISCONNECTED, "disconnected" }, + { DRM_MODE_UNKNOWNCONNECTION, "unknown" }, +}; + +const char *util_lookup_connector_status_name(unsigned int status) +{ + return util_lookup_type_name(status, connector_status_names, + ARRAY_SIZE(connector_status_names)); +} + +static const struct type_name connector_type_names[] = { + { DRM_MODE_CONNECTOR_Unknown, "unknown" }, + { DRM_MODE_CONNECTOR_VGA, "VGA" }, + { DRM_MODE_CONNECTOR_DVII, "DVI-I" }, + { DRM_MODE_CONNECTOR_DVID, "DVI-D" }, + { DRM_MODE_CONNECTOR_DVIA, "DVI-A" }, + { DRM_MODE_CONNECTOR_Composite, "composite" }, + { DRM_MODE_CONNECTOR_SVIDEO, "s-video" }, + { DRM_MODE_CONNECTOR_LVDS, "LVDS" }, + { DRM_MODE_CONNECTOR_Component, "component" }, + { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" }, + { DRM_MODE_CONNECTOR_DisplayPort, "DP" }, + { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" }, + { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" }, + { DRM_MODE_CONNECTOR_TV, "TV" }, + { DRM_MODE_CONNECTOR_eDP, "eDP" }, + { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" }, + { DRM_MODE_CONNECTOR_DSI, "DSI" }, +}; + +const char *util_lookup_connector_type_name(unsigned int type) +{ + return util_lookup_type_name(type, connector_type_names, + ARRAY_SIZE(connector_type_names)); +} diff --git a/tests/util/kms.h b/tests/util/kms.h new file mode 100644 index 000000000000..fa9ab69983ac --- /dev/null +++ b/tests/util/kms.h @@ -0,0 +1,33 @@ +/* + * Copyright 2008 Tungsten Graphics + * Jakob Bornecrantz jakob@tungstengraphics.com + * Copyright 2008 Intel Corporation + * Jesse Barnes jesse.barnes@intel.com + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef UTIL_KMS_H +#define UTIL_KMS_H + +const char *util_lookup_encoder_type_name(unsigned int type); +const char *util_lookup_connector_status_name(unsigned int type); +const char *util_lookup_connector_type_name(unsigned int type); + +#endif /* UTIL_KMS_H */
From: Thierry Reding treding@nvidia.com
Signed-off-by: Thierry Reding treding@nvidia.com --- tests/proptest/Android.mk | 13 +++++++++++++ tests/proptest/Makefile.am | 6 ++++-- tests/proptest/Makefile.sources | 2 ++ 3 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 tests/proptest/Android.mk create mode 100644 tests/proptest/Makefile.sources
diff --git a/tests/proptest/Android.mk b/tests/proptest/Android.mk new file mode 100644 index 000000000000..d0ab5c92775a --- /dev/null +++ b/tests/proptest/Android.mk @@ -0,0 +1,13 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +include $(LOCAL_PATH)/Makefile.sources + +LOCAL_SRC_FILES := $(PROPTEST_FILES) + +LOCAL_MODULE := proptest + +LOCAL_SHARED_LIBRARIES := libdrm +LOCAL_STATIC_LIBRARIES := libdrm_util + +include $(BUILD_EXECUTABLE) diff --git a/tests/proptest/Makefile.am b/tests/proptest/Makefile.am index 142882066485..3fde46bececd 100644 --- a/tests/proptest/Makefile.am +++ b/tests/proptest/Makefile.am @@ -1,3 +1,5 @@ +include Makefile.sources + AM_CFLAGS = \ $(WARN_CFLAGS)\ -I$(top_srcdir)/include/drm \ @@ -12,8 +14,8 @@ noinst_PROGRAMS = \ proptest endif
-proptest_SOURCES = \ - proptest.c +proptest_SOURCES = $(PROPTEST_FILES) + proptest_LDADD = \ $(top_builddir)/libdrm.la \ $(top_builddir)/tests/util/libutil.la diff --git a/tests/proptest/Makefile.sources b/tests/proptest/Makefile.sources new file mode 100644 index 000000000000..446110d685d5 --- /dev/null +++ b/tests/proptest/Makefile.sources @@ -0,0 +1,2 @@ +PROPTEST_FILES := \ + proptest.c
From: Thierry Reding treding@nvidia.com
This library contains abstractions for KMS that help remove the need for a lot of boilerplate in KMS test programs.
Signed-off-by: Thierry Reding treding@nvidia.com --- configure.ac | 1 + tests/Makefile.am | 2 +- tests/kms/Makefile.am | 20 ++++ tests/kms/libkms-test-crtc.c | 47 ++++++++ tests/kms/libkms-test-device.c | 218 ++++++++++++++++++++++++++++++++++++ tests/kms/libkms-test-framebuffer.c | 157 ++++++++++++++++++++++++++ tests/kms/libkms-test-plane.c | 139 +++++++++++++++++++++++ tests/kms/libkms-test-screen.c | 92 +++++++++++++++ tests/kms/libkms-test.h | 120 ++++++++++++++++++++ 9 files changed, 795 insertions(+), 1 deletion(-) create mode 100644 tests/kms/Makefile.am create mode 100644 tests/kms/libkms-test-crtc.c create mode 100644 tests/kms/libkms-test-device.c create mode 100644 tests/kms/libkms-test-framebuffer.c create mode 100644 tests/kms/libkms-test-plane.c create mode 100644 tests/kms/libkms-test-screen.c create mode 100644 tests/kms/libkms-test.h
diff --git a/configure.ac b/configure.ac index ca6cbf4eaa62..0c66dfc62a4c 100644 --- a/configure.ac +++ b/configure.ac @@ -499,6 +499,7 @@ AC_CONFIG_FILES([ tests/Makefile tests/modeprint/Makefile tests/modetest/Makefile + tests/kms/Makefile tests/kmstest/Makefile tests/proptest/Makefile tests/radeon/Makefile diff --git a/tests/Makefile.am b/tests/Makefile.am index 7ffc076f16d7..58feb1236b66 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = util modeprint proptest modetest vbltest +SUBDIRS = util kms modeprint proptest modetest vbltest
if HAVE_LIBKMS SUBDIRS += kmstest diff --git a/tests/kms/Makefile.am b/tests/kms/Makefile.am new file mode 100644 index 000000000000..da4642184504 --- /dev/null +++ b/tests/kms/Makefile.am @@ -0,0 +1,20 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/include/drm \ + -I$(top_srcdir)/tests \ + -I$(top_srcdir) + +AM_CFLAGS = \ + $(WARN_CFLAGS) + +noinst_LTLIBRARIES = libkms-test.la + +libkms_test_la_SOURCES = \ + libkms-test.h \ + libkms-test-crtc.c \ + libkms-test-device.c \ + libkms-test-framebuffer.c \ + libkms-test-plane.c \ + libkms-test-screen.c + +libkms_test_la_LIBADD = \ + $(top_builddir)/libdrm.la diff --git a/tests/kms/libkms-test-crtc.c b/tests/kms/libkms-test-crtc.c new file mode 100644 index 000000000000..3adb4903919f --- /dev/null +++ b/tests/kms/libkms-test-crtc.c @@ -0,0 +1,47 @@ +/* + * Copyright © 2014 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "libkms-test.h" + +struct kms_crtc *kms_crtc_create(struct kms_device *device, uint32_t id) +{ + struct kms_crtc *crtc; + + crtc = calloc(1, sizeof(*crtc)); + if (!crtc) + return NULL; + + crtc->device = device; + crtc->id = id; + + return crtc; +} + +void kms_crtc_free(struct kms_crtc *crtc) +{ + free(crtc); +} diff --git a/tests/kms/libkms-test-device.c b/tests/kms/libkms-test-device.c new file mode 100644 index 000000000000..53c7349b89ab --- /dev/null +++ b/tests/kms/libkms-test-device.c @@ -0,0 +1,218 @@ +/* + * Copyright © 2014 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include "util/common.h" +#include "libkms-test.h" + +static const char *const connector_names[] = { + "Unknown", + "VGA", + "DVI-I", + "DVI-D", + "DVI-A", + "Composite", + "SVIDEO", + "LVDS", + "Component", + "9PinDIN", + "DisplayPort", + "HDMI-A", + "HDMI-B", + "TV", + "eDP", + "Virtual", + "DSI", +}; + +static void kms_device_probe_screens(struct kms_device *device) +{ + unsigned int counts[ARRAY_SIZE(connector_names)]; + struct kms_screen *screen; + drmModeRes *res; + int i; + + memset(counts, 0, sizeof(counts)); + + res = drmModeGetResources(device->fd); + if (!res) + return; + + device->screens = calloc(res->count_connectors, sizeof(screen)); + if (!device->screens) + return; + + for (i = 0; i < res->count_connectors; i++) { + unsigned int *count; + const char *type; + int len; + + screen = kms_screen_create(device, res->connectors[i]); + if (!screen) + continue; + + /* assign a unique name to this screen */ + type = connector_names[screen->type]; + count = &counts[screen->type]; + + len = snprintf(NULL, 0, "%s-%u", type, *count); + + screen->name = malloc(len + 1); + if (!screen->name) { + free(screen); + continue; + } + + snprintf(screen->name, len + 1, "%s-%u", type, *count); + (*count)++; + + device->screens[i] = screen; + device->num_screens++; + } + + drmModeFreeResources(res); +} + +static void kms_device_probe_crtcs(struct kms_device *device) +{ + struct kms_crtc *crtc; + drmModeRes *res; + int i; + + res = drmModeGetResources(device->fd); + if (!res) + return; + + device->crtcs = calloc(res->count_crtcs, sizeof(crtc)); + if (!device->crtcs) + return; + + for (i = 0; i < res->count_crtcs; i++) { + crtc = kms_crtc_create(device, res->crtcs[i]); + if (!crtc) + continue; + + device->crtcs[i] = crtc; + device->num_crtcs++; + } + + drmModeFreeResources(res); +} + +static void kms_device_probe_planes(struct kms_device *device) +{ + struct kms_plane *plane; + drmModePlaneRes *res; + unsigned int i; + + res = drmModeGetPlaneResources(device->fd); + if (!res) + return; + + device->planes = calloc(res->count_planes, sizeof(plane)); + if (!device->planes) + return; + + for (i = 0; i < res->count_planes; i++) { + plane = kms_plane_create(device, res->planes[i]); + if (!plane) + continue; + + device->planes[i] = plane; + device->num_planes++; + } + + drmModeFreePlaneResources(res); +} + +static void kms_device_probe(struct kms_device *device) +{ + kms_device_probe_screens(device); + kms_device_probe_crtcs(device); + kms_device_probe_planes(device); +} + +struct kms_device *kms_device_open(int fd) +{ + struct kms_device *device; + + device = calloc(1, sizeof(*device)); + if (!device) + return NULL; + + device->fd = fd; + + kms_device_probe(device); + + return device; +} + +void kms_device_close(struct kms_device *device) +{ + unsigned int i; + + for (i = 0; i < device->num_planes; i++) + kms_plane_free(device->planes[i]); + + free(device->planes); + + for (i = 0; i < device->num_crtcs; i++) + kms_crtc_free(device->crtcs[i]); + + free(device->crtcs); + + for (i = 0; i < device->num_screens; i++) + kms_screen_free(device->screens[i]); + + free(device->screens); + + if (device->fd >= 0) + close(device->fd); + + free(device); +} + +struct kms_plane *kms_device_find_plane_by_type(struct kms_device *device, + uint32_t type, + unsigned int index) +{ + unsigned int i; + + for (i = 0; i < device->num_planes; i++) { + if (device->planes[i]->type == type) { + if (index == 0) + return device->planes[i]; + + index--; + } + } + + return NULL; +} diff --git a/tests/kms/libkms-test-framebuffer.c b/tests/kms/libkms-test-framebuffer.c new file mode 100644 index 000000000000..c9e5ad3c250d --- /dev/null +++ b/tests/kms/libkms-test-framebuffer.c @@ -0,0 +1,157 @@ +/* + * Copyright © 2014 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <string.h> + +#include <sys/mman.h> + +#include <drm_fourcc.h> + +#include "xf86drm.h" + +#include "libkms-test.h" + +struct kms_framebuffer *kms_framebuffer_create(struct kms_device *device, + unsigned int width, + unsigned int height, + uint32_t format) +{ + uint32_t handles[4], pitches[4], offsets[4]; + struct drm_mode_create_dumb args; + struct kms_framebuffer *fb; + int err; + + fb = calloc(1, sizeof(*fb)); + if (!fb) + return NULL; + + fb->device = device; + fb->width = width; + fb->height = height; + fb->format = format; + + memset(&args, 0, sizeof(args)); + args.width = width; + args.height = height; + + switch (format) { + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_RGBA8888: + args.bpp = 32; + break; + + default: + free(fb); + return NULL; + } + + err = drmIoctl(device->fd, DRM_IOCTL_MODE_CREATE_DUMB, &args); + if (err < 0) { + free(fb); + return NULL; + } + + fb->handle = args.handle; + fb->pitch = args.pitch; + fb->size = args.size; + + handles[0] = fb->handle; + pitches[0] = fb->pitch; + offsets[0] = 0; + + err = drmModeAddFB2(device->fd, width, height, format, handles, + pitches, offsets, &fb->id, 0); + if (err < 0) { + kms_framebuffer_free(fb); + return NULL; + } + + return fb; +} + +void kms_framebuffer_free(struct kms_framebuffer *fb) +{ + struct kms_device *device = fb->device; + struct drm_mode_destroy_dumb args; + int err; + + if (fb->id) { + err = drmModeRmFB(device->fd, fb->id); + if (err < 0) { + /* not much we can do now */ + } + } + + memset(&args, 0, sizeof(args)); + args.handle = fb->handle; + + err = drmIoctl(device->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &args); + if (err < 0) { + /* not much we can do now */ + } + + free(fb); +} + +int kms_framebuffer_map(struct kms_framebuffer *fb, void **ptrp) +{ + struct kms_device *device = fb->device; + struct drm_mode_map_dumb args; + void *ptr; + int err; + + if (fb->ptr) { + *ptrp = fb->ptr; + return 0; + } + + memset(&args, 0, sizeof(args)); + args.handle = fb->handle; + + err = drmIoctl(device->fd, DRM_IOCTL_MODE_MAP_DUMB, &args); + if (err < 0) + return -errno; + + ptr = mmap(0, fb->size, PROT_READ | PROT_WRITE, MAP_SHARED, + device->fd, args.offset); + if (ptr == MAP_FAILED) + return -errno; + + *ptrp = fb->ptr = ptr; + + return 0; +} + +void kms_framebuffer_unmap(struct kms_framebuffer *fb) +{ + if (fb->ptr) { + munmap(fb->ptr, fb->size); + fb->ptr = NULL; + } +} diff --git a/tests/kms/libkms-test-plane.c b/tests/kms/libkms-test-plane.c new file mode 100644 index 000000000000..8eb78af1dcc7 --- /dev/null +++ b/tests/kms/libkms-test-plane.c @@ -0,0 +1,139 @@ +/* + * Copyright © 2014 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <string.h> + +#include "libkms-test.h" + +static int kms_plane_probe(struct kms_plane *plane) +{ + struct kms_device *device = plane->device; + drmModeObjectPropertiesPtr props; + drmModePlane *p; + unsigned int i; + + p = drmModeGetPlane(device->fd, plane->id); + if (!p) + return -ENODEV; + + /* TODO: allow dynamic assignment to CRTCs */ + if (p->crtc_id == 0) { + for (i = 0; i < device->num_crtcs; i++) { + if (p->possible_crtcs & (1 << i)) { + p->crtc_id = device->crtcs[i]->id; + break; + } + } + } + + for (i = 0; i < device->num_crtcs; i++) { + if (device->crtcs[i]->id == p->crtc_id) { + plane->crtc = device->crtcs[i]; + break; + } + } + + plane->formats = calloc(p->count_formats, sizeof(uint32_t)); + if (!plane->formats) + return -ENOMEM; + + for (i = 0; i < p->count_formats; i++) + plane->formats[i] = p->formats[i]; + + plane->num_formats = p->count_formats; + + drmModeFreePlane(p); + + props = drmModeObjectGetProperties(device->fd, plane->id, + DRM_MODE_OBJECT_PLANE); + if (!props) + return -ENODEV; + + for (i = 0; i < props->count_props; i++) { + drmModePropertyPtr prop; + + prop = drmModeGetProperty(device->fd, props->props[i]); + if (prop) { + if (strcmp(prop->name, "type") == 0) + plane->type = props->prop_values[i]; + + drmModeFreeProperty(prop); + } + } + + drmModeFreeObjectProperties(props); + + return 0; +} + +struct kms_plane *kms_plane_create(struct kms_device *device, uint32_t id) +{ + struct kms_plane *plane; + + plane = calloc(1, sizeof(*plane)); + if (!plane) + return NULL; + + plane->device = device; + plane->id = id; + + kms_plane_probe(plane); + + return plane; +} + +void kms_plane_free(struct kms_plane *plane) +{ + free(plane); +} + +int kms_plane_set(struct kms_plane *plane, struct kms_framebuffer *fb, + unsigned int x, unsigned int y) +{ + struct kms_device *device = plane->device; + int err; + + err = drmModeSetPlane(device->fd, plane->id, plane->crtc->id, fb->id, + 0, x, y, fb->width, fb->height, 0 << 16, + 0 << 16, fb->width << 16, fb->height << 16); + if (err < 0) + return -errno; + + return 0; +} + +bool kms_plane_supports_format(struct kms_plane *plane, uint32_t format) +{ + unsigned int i; + + for (i = 0; i < plane->num_formats; i++) + if (plane->formats[i] == format) + return true; + + return false; +} diff --git a/tests/kms/libkms-test-screen.c b/tests/kms/libkms-test-screen.c new file mode 100644 index 000000000000..336902228090 --- /dev/null +++ b/tests/kms/libkms-test-screen.c @@ -0,0 +1,92 @@ +/* + * Copyright © 2014 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <string.h> + +#include "libkms-test.h" + +static void kms_screen_probe(struct kms_screen *screen) +{ + struct kms_device *device = screen->device; + drmModeConnector *con; + + con = drmModeGetConnector(device->fd, screen->id); + if (!con) + return; + + screen->type = con->connector_type; + + if (con->connection == DRM_MODE_CONNECTED) + screen->connected = true; + else + screen->connected = false; + + memcpy(&screen->mode, &con->modes[0], sizeof(drmModeModeInfo)); + screen->width = screen->mode.hdisplay; + screen->height = screen->mode.vdisplay; + + drmModeFreeConnector(con); +} + +struct kms_screen *kms_screen_create(struct kms_device *device, uint32_t id) +{ + struct kms_screen *screen; + + screen = calloc(1, sizeof(*screen)); + if (!screen) + return NULL; + + screen->device = device; + screen->id = id; + + kms_screen_probe(screen); + + return screen; +} + +void kms_screen_free(struct kms_screen *screen) +{ + if (screen) + free(screen->name); + + free(screen); +} + +int kms_screen_set(struct kms_screen *screen, struct kms_crtc *crtc, + struct kms_framebuffer *fb) +{ + struct kms_device *device = screen->device; + int err; + + err = drmModeSetCrtc(device->fd, crtc->id, fb->id, 0, 0, &screen->id, + 1, &screen->mode); + if (err < 0) + return -errno; + + return 0; +} diff --git a/tests/kms/libkms-test.h b/tests/kms/libkms-test.h new file mode 100644 index 000000000000..7b1d02e9aa0a --- /dev/null +++ b/tests/kms/libkms-test.h @@ -0,0 +1,120 @@ +/* + * Copyright © 2014 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef LIBKMS_TEST_H +#define LIBKMS_TEST_H + +#include <stdbool.h> +#include <stdint.h> +#include <stdlib.h> + +#include <xf86drmMode.h> + +struct kms_device { + int fd; + + struct kms_screen **screens; + unsigned int num_screens; + + struct kms_crtc **crtcs; + unsigned int num_crtcs; + + struct kms_plane **planes; + unsigned int num_planes; +}; + +struct kms_device *kms_device_open(int fd); +void kms_device_close(struct kms_device *device); + +struct kms_plane *kms_device_find_plane_by_type(struct kms_device *device, + uint32_t type, + unsigned int index); + +struct kms_crtc { + struct kms_device *device; + uint32_t id; +}; + +struct kms_crtc *kms_crtc_create(struct kms_device *device, uint32_t id); +void kms_crtc_free(struct kms_crtc *crtc); + +struct kms_framebuffer { + struct kms_device *device; + + unsigned int width; + unsigned int height; + unsigned int pitch; + uint32_t format; + size_t size; + + uint32_t handle; + uint32_t id; + + void *ptr; +}; + +struct kms_framebuffer *kms_framebuffer_create(struct kms_device *device, + unsigned int width, + unsigned int height, + uint32_t format); +void kms_framebuffer_free(struct kms_framebuffer *fb); +int kms_framebuffer_map(struct kms_framebuffer *fb, void **ptrp); +void kms_framebuffer_unmap(struct kms_framebuffer *fb); + +struct kms_screen { + struct kms_device *device; + bool connected; + uint32_t type; + uint32_t id; + + unsigned int width; + unsigned int height; + char *name; + + drmModeModeInfo mode; +}; + +struct kms_screen *kms_screen_create(struct kms_device *device, uint32_t id); +void kms_screen_free(struct kms_screen *screen); + +int kms_screen_set(struct kms_screen *screen, struct kms_crtc *crtc, + struct kms_framebuffer *fb); + +struct kms_plane { + struct kms_device *device; + struct kms_crtc *crtc; + unsigned int type; + uint32_t id; + + uint32_t *formats; + unsigned int num_formats; +}; + +struct kms_plane *kms_plane_create(struct kms_device *device, uint32_t id); +void kms_plane_free(struct kms_plane *plane); + +int kms_plane_set(struct kms_plane *plane, struct kms_framebuffer *fb, + unsigned int x, unsigned int y); +bool kms_plane_supports_format(struct kms_plane *plane, uint32_t format); + +#endif
From: Thierry Reding treding@nvidia.com
This test program sets a mode and framebuffer on a connector and cycles through all CRTCs, moving the connector to each of them in turn. This is useful to verify that CRTC stealing is properly handled in the DRM core and drivers.
Signed-off-by: Thierry Reding treding@nvidia.com --- tests/kms/Makefile.am | 11 ++++ tests/kms/kms-steal-crtc.c | 161 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 172 insertions(+) create mode 100644 tests/kms/kms-steal-crtc.c
diff --git a/tests/kms/Makefile.am b/tests/kms/Makefile.am index da4642184504..f28b729c068c 100644 --- a/tests/kms/Makefile.am +++ b/tests/kms/Makefile.am @@ -18,3 +18,14 @@ libkms_test_la_SOURCES = \
libkms_test_la_LIBADD = \ $(top_builddir)/libdrm.la + +if HAVE_INSTALL_TESTS +bin_PROGRAMS = \ + kms-steal-crtc +else +noinst_PROGRAMS = \ + kms-steal-crtc +endif + +kms_steal_crtc_SOURCES = kms-steal-crtc.c +kms_steal_crtc_LDADD = libkms-test.la ../util/libutil.la $(CAIRO_LIBS) diff --git a/tests/kms/kms-steal-crtc.c b/tests/kms/kms-steal-crtc.c new file mode 100644 index 000000000000..2f7f327edc16 --- /dev/null +++ b/tests/kms/kms-steal-crtc.c @@ -0,0 +1,161 @@ +/* + * Copyright © 2014 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include <drm_fourcc.h> + +#include "util/pattern.h" +#include "libkms-test.h" + +static void signal_handler(int signum) +{ +} + +int main(int argc, char *argv[]) +{ + struct kms_framebuffer *fb; + struct kms_screen *screen; + struct kms_device *device; + unsigned int index = 0; + struct sigaction sa; + int fd, err; + void *ptr; + + if (argc < 2) { + fprintf(stderr, "usage: %s DEVICE\n", argv[0]); + return 1; + } + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = signal_handler; + + err = sigaction(SIGINT, &sa, NULL); + if (err < 0) { + fprintf(stderr, "sigaction() failed: %m\n"); + return 1; + } + + fd = open(argv[1], O_RDWR); + if (fd < 0) { + fprintf(stderr, "open() failed: %m\n"); + return 1; + } + + device = kms_device_open(fd); + if (!device) { + fprintf(stderr, "kms_device_open() failed: %m\n"); + return 1; + } + + if (device->num_screens < 1) { + fprintf(stderr, "no screens found\n"); + kms_device_close(device); + close(fd); + return 1; + } + + /* TODO: allow command-line to override */ + screen = device->screens[0]; + + printf("Using screen %s, resolution %ux%u\n", screen->name, + screen->width, screen->height); + + fb = kms_framebuffer_create(device, screen->width, screen->height, + DRM_FORMAT_XRGB8888); + if (!fb) { + fprintf(stderr, "kms_framebuffer_create() failed\n"); + return 1; + } + + err = kms_framebuffer_map(fb, &ptr); + if (err < 0) { + fprintf(stderr, "kms_framebuffer_map() failed: %d\n", err); + return 1; + } + + util_fill_pattern(fb->format, UTIL_PATTERN_SMPTE, &ptr, fb->width, + fb->height, fb->pitch); + + kms_framebuffer_unmap(fb); + + err = kms_screen_set(screen, device->crtcs[index++], fb); + if (err < 0) { + fprintf(stderr, "kms_screen_set() failed: %d\n", err); + return 1; + } + + while (true) { + int nfds = STDIN_FILENO + 1; + struct timeval timeout; + fd_set fds; + + memset(&timeout, 0, sizeof(timeout)); + timeout.tv_sec = 5; + timeout.tv_usec = 0; + + FD_ZERO(&fds); + FD_SET(STDIN_FILENO, &fds); + + err = select(nfds, &fds, NULL, NULL, &timeout); + if (err < 0) { + if (errno == EINTR) + break; + + fprintf(stderr, "select() failed: %d\n", errno); + break; + } + + if (err > 0) { + if (FD_ISSET(STDIN_FILENO, &fds)) + break; + } + + /* switch CRTC */ + if (index >= device->num_crtcs) + index = 0; + + err = kms_screen_set(screen, device->crtcs[index], fb); + if (err < 0) { + fprintf(stderr, "kms_screen_set() failed: %d\n", err); + break; + } + + index++; + } + + kms_framebuffer_free(fb); + kms_device_close(device); + close(fd); + + return 0; +}
From: Thierry Reding treding@nvidia.com
This small program allows universal planes to be tested. Currently this isn't very flexible because it allows only the first plane of a given type to be tested on the first CRTC. However it should be simple to extend this with some additional command-line arguments.
Signed-off-by: Thierry Reding treding@nvidia.com --- tests/kms/Makefile.am | 9 +- tests/kms/kms-universal-planes.c | 358 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 365 insertions(+), 2 deletions(-) create mode 100644 tests/kms/kms-universal-planes.c
diff --git a/tests/kms/Makefile.am b/tests/kms/Makefile.am index f28b729c068c..6645af7acae7 100644 --- a/tests/kms/Makefile.am +++ b/tests/kms/Makefile.am @@ -21,11 +21,16 @@ libkms_test_la_LIBADD = \
if HAVE_INSTALL_TESTS bin_PROGRAMS = \ - kms-steal-crtc + kms-steal-crtc \ + kms-universal-planes else noinst_PROGRAMS = \ - kms-steal-crtc + kms-steal-crtc \ + kms-universal-planes endif
kms_steal_crtc_SOURCES = kms-steal-crtc.c kms_steal_crtc_LDADD = libkms-test.la ../util/libutil.la $(CAIRO_LIBS) + +kms_universal_planes_SOURCES = kms-universal-planes.c +kms_universal_planes_LDADD = libkms-test.la $(CAIRO_LIBS) diff --git a/tests/kms/kms-universal-planes.c b/tests/kms/kms-universal-planes.c new file mode 100644 index 000000000000..9151231ff860 --- /dev/null +++ b/tests/kms/kms-universal-planes.c @@ -0,0 +1,358 @@ +/* + * Copyright © 2014 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <fcntl.h> +#include <getopt.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include <drm_fourcc.h> +#include "xf86drm.h" + +#include "util/common.h" +#include "libkms-test.h" + +static const uint32_t formats[] = { + DRM_FORMAT_XRGB8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_RGBA8888, +}; + +static uint32_t choose_format(struct kms_plane *plane) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(formats); i++) + if (kms_plane_supports_format(plane, formats[i])) + return formats[i]; + + return 0; +} + +static void prepare_framebuffer(struct kms_framebuffer *fb, bool invert) +{ + const unsigned int block_size = 16; + uint32_t colors[2]; + unsigned int i, j; + uint32_t *buf; + void *ptr; + int err; + + switch (fb->format) { + case DRM_FORMAT_XRGB8888: + printf("using XRGB8888 format\n"); + /* XXRRGGBB */ + colors[0] = 0xffff0000; + colors[1] = 0xff0000ff; + break; + + case DRM_FORMAT_XBGR8888: + printf("using XBGR8888 format\n"); + /* XXBBGGRR */ + colors[0] = 0xff0000ff; + colors[1] = 0xffff0000; + break; + + case DRM_FORMAT_RGBA8888: + printf("using RGBA8888 format\n"); + /* RRGGBBAA */ + colors[0] = 0xff0000ff; + colors[1] = 0x0000ffff; + break; + + default: + colors[0] = 0xffffffff; + colors[1] = 0xffffffff; + break; + } + + err = kms_framebuffer_map(fb, &ptr); + if (err < 0) { + fprintf(stderr, "kms_framebuffer_map() failed: %s\n", + strerror(-err)); + return; + } + + buf = ptr; + + for (j = 0; j < fb->height; j++) { + for (i = 0; i < fb->width; i++) { + unsigned int color = (j / block_size) ^ + (i / block_size); + + if (invert) + color ^= color; + + *buf++ = colors[color & 1]; + } + } + + kms_framebuffer_unmap(fb); +} + +int main(int argc, char *argv[]) +{ + static const char opts[] = "chopv"; + static struct option options[] = { + { "cursor", 0, 0, 'c' }, + { "help", 0, 0, 'h' }, + { "overlay", 0, 0, 'o' }, + { "primary", 0, 0, 'p' }, + { "verbose", 0, 0, 'v' }, + { 0, 0, 0, 0 }, + }; + struct kms_framebuffer *cursor = NULL; + struct kms_framebuffer *root = NULL; + struct kms_framebuffer *fb = NULL; + struct kms_device *device; + bool use_overlay = false; + bool use_primary = false; + struct kms_plane *plane; + bool use_cursor = false; + bool verbose = false; + unsigned int i; + int opt, idx; + int fd, err; + + while ((opt = getopt_long(argc, argv, opts, options, &idx)) != -1) { + switch (opt) { + case 'c': + use_cursor = true; + break; + + case 'h': + break; + + case 'o': + use_overlay = true; + break; + + case 'p': + use_primary = true; + break; + + case 'v': + verbose = true; + break; + + default: + printf("unknown option "%c"\n", opt); + return 1; + } + } + + if (optind >= argc) { + fprintf(stderr, "usage: %s [options] DEVICE\n", argv[0]); + return 1; + } + + fd = open(argv[optind], O_RDWR); + if (fd < 0) { + fprintf(stderr, "open() failed: %m\n"); + return 1; + } + + err = drmSetClientCap(fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); + if (err < 0) { + fprintf(stderr, "drmSetClientCap() failed: %d\n", err); + return 1; + } + + device = kms_device_open(fd); + if (!device) + return 1; + + if (verbose) { + printf("Screens: %u\n", device->num_screens); + + for (i = 0; i < device->num_screens; i++) { + struct kms_screen *screen = device->screens[i]; + const char *status = "disconnected"; + + if (screen->connected) + status = "connected"; + + printf(" %u: %x\n", i, screen->id); + printf(" Status: %s\n", status); + printf(" Name: %s\n", screen->name); + printf(" Resolution: %ux%u\n", screen->width, + screen->height); + } + + printf("Planes: %u\n", device->num_planes); + + for (i = 0; i < device->num_planes; i++) { + struct kms_plane *plane = device->planes[i]; + const char *type = NULL; + + switch (plane->type) { + case DRM_PLANE_TYPE_OVERLAY: + type = "overlay"; + break; + + case DRM_PLANE_TYPE_PRIMARY: + type = "primary"; + break; + + case DRM_PLANE_TYPE_CURSOR: + type = "cursor"; + break; + } + + printf(" %u: %p\n", i, plane); + printf(" ID: %x\n", plane->id); + printf(" CRTC: %x\n", plane->crtc->id); + printf(" Type: %x (%s)\n", plane->type, type); + } + } + + if (use_cursor) { + unsigned int x, y; + uint32_t format; + + plane = kms_device_find_plane_by_type(device, + DRM_PLANE_TYPE_CURSOR, + 0); + if (!plane) { + fprintf(stderr, "no cursor plane found\n"); + return 1; + } + + format = choose_format(plane); + if (!format) { + fprintf(stderr, "no matching format found\n"); + return 1; + } + + cursor = kms_framebuffer_create(device, 32, 32, format); + if (!cursor) { + fprintf(stderr, "failed to create cursor buffer\n"); + return 1; + } + + prepare_framebuffer(cursor, false); + + x = (device->screens[0]->width - cursor->width) / 2; + y = (device->screens[0]->height - cursor->height) / 2; + + kms_plane_set(plane, cursor, x, y); + } + + if (use_overlay) { + uint32_t format; + + plane = kms_device_find_plane_by_type(device, + DRM_PLANE_TYPE_OVERLAY, + 0); + if (!plane) { + fprintf(stderr, "no overlay plane found\n"); + return 1; + } + + format = choose_format(plane); + if (!format) { + fprintf(stderr, "no matching format found\n"); + return 1; + } + + fb = kms_framebuffer_create(device, 320, 240, format); + if (!fb) + return 1; + + prepare_framebuffer(fb, false); + + kms_plane_set(plane, fb, 0, 0); + } + + if (use_primary) { + unsigned int x, y; + uint32_t format; + + plane = kms_device_find_plane_by_type(device, + DRM_PLANE_TYPE_PRIMARY, + 0); + if (!plane) { + fprintf(stderr, "no primary plane found\n"); + return 1; + } + + format = choose_format(plane); + if (!format) { + fprintf(stderr, "no matching format found\n"); + return 1; + } + + root = kms_framebuffer_create(device, 640, 480, format); + if (!root) + return 1; + + prepare_framebuffer(root, true); + + x = (device->screens[0]->width - root->width) / 2; + y = (device->screens[0]->height - root->height) / 2; + + kms_plane_set(plane, root, x, y); + } + + while (1) { + struct timeval timeout = { 1, 0 }; + fd_set fds; + + FD_ZERO(&fds); + FD_SET(STDIN_FILENO, &fds); + + err = select(STDIN_FILENO + 1, &fds, NULL, NULL, &timeout); + if (err < 0) { + fprintf(stderr, "select() failed: %m\n"); + break; + } + + /* timeout */ + if (err == 0) + continue; + + if (FD_ISSET(STDIN_FILENO, &fds)) + break; + } + + if (cursor) + kms_framebuffer_free(cursor); + + if (root) + kms_framebuffer_free(root); + + if (fb) + kms_framebuffer_free(fb); + + kms_device_close(device); + close(fd); + + return 0; +}
From: Thierry Reding treding@nvidia.com
The new function util_open() encapsulates the standard method employed by tests to open a device or module. There is a verbatim copy of this in almost all test programs, with slight variations in the list of modules. Moving this code into a common helper allows code reuse and makes tests more consistent.
Signed-off-by: Thierry Reding treding@nvidia.com --- tests/util/kms.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/util/kms.h | 2 ++ 2 files changed, 57 insertions(+)
diff --git a/tests/util/kms.c b/tests/util/kms.c index 687b3c3c1cf3..57b0191b2655 100644 --- a/tests/util/kms.c +++ b/tests/util/kms.c @@ -41,9 +41,13 @@ #include "config.h" #endif
+#include <errno.h> #include <stdint.h> +#include <stdio.h> #include <stdlib.h> +#include <string.h>
+#include "xf86drm.h" #include "xf86drmMode.h"
#include "common.h" @@ -120,3 +124,54 @@ const char *util_lookup_connector_type_name(unsigned int type) return util_lookup_type_name(type, connector_type_names, ARRAY_SIZE(connector_type_names)); } + +static const char * const modules[] = { + "i915", + "radeon", + "nouveau", + "vmwgfx", + "omapdrm", + "exynos", + "tilcdc", + "msm", + "sti", + "tegra", + "imx-drm", + "rockchip", + "atmel-hlcdc", +}; + +int util_open(const char *device, const char *module) +{ + int fd; + + if (module) { + fd = drmOpen(module, device); + if (fd < 0) { + fprintf(stderr, "failed to open device '%s': %s\n", + module, strerror(errno)); + return -errno; + } + } else { + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(modules); i++) { + printf("trying to open device '%s'...", modules[i]); + + fd = drmOpen(modules[i], device); + if (fd < 0) { + printf("failed\n"); + } else { + printf("done\n"); + break; + } + } + + if (fd < 0) { + fprintf(stderr, "no device found\n"); + return -ENODEV; + } + } + + return fd; +} diff --git a/tests/util/kms.h b/tests/util/kms.h index fa9ab69983ac..dde2ed2c5636 100644 --- a/tests/util/kms.h +++ b/tests/util/kms.h @@ -30,4 +30,6 @@ const char *util_lookup_encoder_type_name(unsigned int type); const char *util_lookup_connector_status_name(unsigned int type); const char *util_lookup_connector_type_name(unsigned int type);
+int util_open(const char *device, const char *module); + #endif /* UTIL_KMS_H */
From: Thierry Reding treding@nvidia.com
Use the new util_open() helper instead of open-coding the method for finding a usable device.
Signed-off-by: Thierry Reding treding@nvidia.com --- tests/modetest/modetest.c | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-)
diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index 0e009d87fdee..22e3e81bd3cc 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -1503,7 +1503,6 @@ int main(int argc, char **argv) int drop_master = 0; int test_vsync = 0; int test_cursor = 0; - const char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "exynos", "tilcdc", "msm", "sti", "tegra", "imx-drm", "rockchip", "atmel-hlcdc" }; char *device = NULL; char *module = NULL; unsigned int i; @@ -1604,29 +1603,9 @@ int main(int argc, char **argv) if (!args) encoders = connectors = crtcs = planes = framebuffers = 1;
- if (module) { - dev.fd = drmOpen(module, device); - if (dev.fd < 0) { - fprintf(stderr, "failed to open device '%s'.\n", module); - return 1; - } - } else { - for (i = 0; i < ARRAY_SIZE(modules); i++) { - printf("trying to open device '%s'...", modules[i]); - dev.fd = drmOpen(modules[i], device); - if (dev.fd < 0) { - printf("failed.\n"); - } else { - printf("success.\n"); - break; - } - } - - if (dev.fd < 0) { - fprintf(stderr, "no device found.\n"); - return 1; - } - } + dev.fd = util_open(module, device); + if (dev.fd < 0) + return -1;
if (test_vsync && !page_flipping_supported()) { fprintf(stderr, "page flipping not supported by drm.\n");
From: Thierry Reding treding@nvidia.com
Use the new util_open() helper instead of open-coding the method for finding a usable device. While at it, make the command-line interface more consistent with that of modetest by adding the -D and -M options.
Signed-off-by: Thierry Reding treding@nvidia.com --- tests/proptest/proptest.c | 60 ++++++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 22 deletions(-)
diff --git a/tests/proptest/proptest.c b/tests/proptest/proptest.c index 11eb6e88cef5..24c634569f2f 100644 --- a/tests/proptest/proptest.c +++ b/tests/proptest/proptest.c @@ -27,6 +27,7 @@
#include <assert.h> #include <errno.h> +#include <getopt.h> #include <inttypes.h> #include <stdlib.h> #include <stdio.h> @@ -232,28 +233,32 @@ static int setProperty(char *argv[]) uint32_t obj_id, obj_type, prop_id; uint64_t value;
- obj_id = atoi(argv[1]); + obj_id = atoi(argv[0]);
- if (!strcmp(argv[2], "connector")) { + if (!strcmp(argv[1], "connector")) { obj_type = DRM_MODE_OBJECT_CONNECTOR; - } else if (!strcmp(argv[2], "crtc")) { + } else if (!strcmp(argv[1], "crtc")) { obj_type = DRM_MODE_OBJECT_CRTC; } else { fprintf(stderr, "Invalid object type.\n"); return 1; }
- prop_id = atoi(argv[3]); - value = atoll(argv[4]); + prop_id = atoi(argv[2]); + value = atoll(argv[3]);
return drmModeObjectSetProperty(fd, obj_id, obj_type, prop_id, value); }
-static void printUsage(void) +static void usage(const char *program) { printf("Usage:\n" -" proptest\n" -" proptest [obj id] [obj type] [prop id] [value]\n" +" %s [options]\n" +" %s [options] [obj id] [obj type] [prop id] [value]\n" +"\n" +"options:\n" +" -D DEVICE use the given device\n" +" -M MODULE use the given driver\n" "\n" "The first form just prints all the existing properties. The second one is\n" "used to set the value of a specified property. The object type can be one of\n" @@ -262,26 +267,37 @@ static void printUsage(void) "\n" "Example:\n" " proptest 7 connector 2 1\n" -"will set property 2 of connector 7 to 1\n"); +"will set property 2 of connector 7 to 1\n", program, program); }
int main(int argc, char *argv[]) { - const char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "msm", "rockchip" }; - unsigned int i, ret = 0; + static const char optstr[] = "D:M:"; + int c, args, ret = 0; + char *device = NULL; + char *module = NULL; + + while ((c = getopt(argc, argv, optstr)) != -1) { + switch (c) { + case 'D': + device = optarg; + break; + + case 'M': + module = optarg; + break;
- for (i = 0; i < ARRAY_SIZE(modules); i++){ - fd = drmOpen(modules[i], NULL); - if (fd >= 0) { - printf("Module %s loaded.\n", modules[i]); + default: + usage(argv[0]); break; } }
- if (i == ARRAY_SIZE(modules)) { - fprintf(stderr, "Failed to load drm modules.\n"); + args = argc - optind; + + fd = util_open(module, device); + if (fd < 0) return 1; - }
res = drmModeGetResources(fd); if (!res) { @@ -291,12 +307,12 @@ int main(int argc, char *argv[]) goto done; }
- if (argc < 2) { + if (args < 1) { listAllProperties(); - } else if (argc == 5) { - ret = setProperty(argv); + } else if (args == 4) { + ret = setProperty(&argv[optind]); } else { - printUsage(); + usage(argv[0]); ret = 1; }
From: Thierry Reding treding@nvidia.com
Use the new util_open() helper instead of open-coding the method for finding a usable device. While at it, this adds -D and -M command-line options to vbltest to make its usage more consistent with its siblings modetest and proptest.
Signed-off-by: Thierry Reding treding@nvidia.com --- tests/vbltest/Makefile.am | 3 ++- tests/vbltest/vbltest.c | 38 ++++++++++++++++++-------------------- 2 files changed, 20 insertions(+), 21 deletions(-)
diff --git a/tests/vbltest/Makefile.am b/tests/vbltest/Makefile.am index 182e3b6d271c..276afad55716 100644 --- a/tests/vbltest/Makefile.am +++ b/tests/vbltest/Makefile.am @@ -15,4 +15,5 @@ endif vbltest_SOURCES = \ vbltest.c vbltest_LDADD = \ - $(top_builddir)/libdrm.la + $(top_builddir)/libdrm.la \ + $(top_builddir)/tests/util/libutil.la diff --git a/tests/vbltest/vbltest.c b/tests/vbltest/vbltest.c index de93e7702b26..60badf1174de 100644 --- a/tests/vbltest/vbltest.c +++ b/tests/vbltest/vbltest.c @@ -55,10 +55,11 @@ #include "xf86drmMode.h"
#include "util/common.h" +#include "util/kms.h"
extern char *optarg; extern int optind, opterr, optopt; -static char optstr[] = "s"; +static char optstr[] = "D:M:s";
int secondary = 0;
@@ -97,16 +98,19 @@ static void vblank_handler(int fd, unsigned int frame, unsigned int sec,
static void usage(char *name) { - fprintf(stderr, "usage: %s [-s]\n", name); - fprintf(stderr, "\t-s\tuse secondary pipe\n"); + fprintf(stderr, "usage: %s [-DMs]\n", name); + fprintf(stderr, "\n"); + fprintf(stderr, "options:\n"); + fprintf(stderr, " -D DEVICE open the given device\n"); + fprintf(stderr, " -M MODULE open the given module\n"); + fprintf(stderr, " -s use secondary pipe\n"); exit(0); }
int main(int argc, char **argv) { - unsigned i; + const char *device = NULL, *module = NULL; int c, fd, ret; - const char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "exynos", "omapdrm", "tilcdc", "msm", "tegra", "imx-drm" , "rockchip" }; drmVBlank vbl; drmEventContext evctx; struct vbl_info handler_info; @@ -114,6 +118,12 @@ int main(int argc, char **argv) opterr = 0; while ((c = getopt(argc, argv, optstr)) != -1) { switch (c) { + case 'D': + device = optarg; + break; + case 'M': + module = optarg; + break; case 's': secondary = 1; break; @@ -123,21 +133,9 @@ int main(int argc, char **argv) } }
- for (i = 0; i < ARRAY_SIZE(modules); i++) { - printf("trying to load module %s...", modules[i]); - fd = drmOpen(modules[i], NULL); - if (fd < 0) { - printf("failed.\n"); - } else { - printf("success.\n"); - break; - } - } - - if (i == ARRAY_SIZE(modules)) { - fprintf(stderr, "failed to load any modules, aborting.\n"); - return -1; - } + fd = util_open(module, device); + if (fd < 0) + return 1;
/* Get current count first */ vbl.request.type = DRM_VBLANK_RELATIVE;
Hi Thierry, all,
On 9 December 2015 at 17:37, Thierry Reding thierry.reding@gmail.com wrote:
From: Thierry Reding treding@nvidia.com
Some of the helpers, such as the pattern drawing helpers or the format lookup helpers, have potential to be reused. Move them into a separate library to make it easier to share them.
Acked-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Signed-off-by: Thierry Reding treding@nvidia.com
CleanSpec.mk | 1 + configure.ac | 1 + tests/Makefile.am | 2 +- tests/modeprint/Makefile.am | 1 + tests/modeprint/modeprint.c | 2 +- tests/modetest/Android.mk | 1 + tests/modetest/Makefile.am | 8 +- tests/modetest/buffers.c | 961 +------------------------------------------- tests/modetest/buffers.h | 12 +- tests/modetest/cursor.c | 4 +- tests/modetest/modetest.c | 25 +- tests/proptest/Makefile.am | 4 +- tests/proptest/proptest.c | 3 +- tests/util/Android.mk | 39 ++ tests/util/Makefile.am | 13 + tests/util/Makefile.sources | 6 + tests/util/common.h | 33 ++ tests/util/format.c | 120 ++++++ tests/util/format.h | 65 +++ tests/util/pattern.c | 870 +++++++++++++++++++++++++++++++++++++++ tests/util/pattern.h | 39 ++ tests/vbltest/Makefile.am | 1 + tests/vbltest/vbltest.c | 2 +- 23 files changed, 1223 insertions(+), 990 deletions(-) create mode 100644 tests/util/Android.mk create mode 100644 tests/util/Makefile.am create mode 100644 tests/util/Makefile.sources create mode 100644 tests/util/common.h create mode 100644 tests/util/format.c create mode 100644 tests/util/format.h create mode 100644 tests/util/pattern.c create mode 100644 tests/util/pattern.h
As mentioned on IRC, although there might be some minor nitpicks I'd rather the series in those in and fix them later. Mostly to avoid the long gap until you get the chance to respin things, but also to spare Tomi (and others) the need to reinvent them :-)
So barring any serious objections, I'd vote for getting these soonish. Perhaps mid next week ?
Thanks Emil
On Sat, Dec 12, 2015 at 03:26:09PM +0000, Emil Velikov wrote:
Hi Thierry, all,
On 9 December 2015 at 17:37, Thierry Reding thierry.reding@gmail.com wrote:
From: Thierry Reding treding@nvidia.com
Some of the helpers, such as the pattern drawing helpers or the format lookup helpers, have potential to be reused. Move them into a separate library to make it easier to share them.
Acked-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Signed-off-by: Thierry Reding treding@nvidia.com
CleanSpec.mk | 1 + configure.ac | 1 + tests/Makefile.am | 2 +- tests/modeprint/Makefile.am | 1 + tests/modeprint/modeprint.c | 2 +- tests/modetest/Android.mk | 1 + tests/modetest/Makefile.am | 8 +- tests/modetest/buffers.c | 961 +------------------------------------------- tests/modetest/buffers.h | 12 +- tests/modetest/cursor.c | 4 +- tests/modetest/modetest.c | 25 +- tests/proptest/Makefile.am | 4 +- tests/proptest/proptest.c | 3 +- tests/util/Android.mk | 39 ++ tests/util/Makefile.am | 13 + tests/util/Makefile.sources | 6 + tests/util/common.h | 33 ++ tests/util/format.c | 120 ++++++ tests/util/format.h | 65 +++ tests/util/pattern.c | 870 +++++++++++++++++++++++++++++++++++++++ tests/util/pattern.h | 39 ++ tests/vbltest/Makefile.am | 1 + tests/vbltest/vbltest.c | 2 +- 23 files changed, 1223 insertions(+), 990 deletions(-) create mode 100644 tests/util/Android.mk create mode 100644 tests/util/Makefile.am create mode 100644 tests/util/Makefile.sources create mode 100644 tests/util/common.h create mode 100644 tests/util/format.c create mode 100644 tests/util/format.h create mode 100644 tests/util/pattern.c create mode 100644 tests/util/pattern.h
As mentioned on IRC, although there might be some minor nitpicks I'd rather the series in those in and fix them later. Mostly to avoid the long gap until you get the chance to respin things, but also to spare Tomi (and others) the need to reinvent them :-)
I don't mind doing another round if you point out the nitpicks. I'm hopeful that I'll get around to respinning sooner this time. =)
Thierry
On 14 December 2015 at 08:12, Thierry Reding thierry.reding@gmail.com wrote:
On Sat, Dec 12, 2015 at 03:26:09PM +0000, Emil Velikov wrote:
Hi Thierry, all,
On 9 December 2015 at 17:37, Thierry Reding thierry.reding@gmail.com wrote:
From: Thierry Reding treding@nvidia.com
Some of the helpers, such as the pattern drawing helpers or the format lookup helpers, have potential to be reused. Move them into a separate library to make it easier to share them.
Acked-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Signed-off-by: Thierry Reding treding@nvidia.com
CleanSpec.mk | 1 + configure.ac | 1 + tests/Makefile.am | 2 +- tests/modeprint/Makefile.am | 1 + tests/modeprint/modeprint.c | 2 +- tests/modetest/Android.mk | 1 + tests/modetest/Makefile.am | 8 +- tests/modetest/buffers.c | 961 +------------------------------------------- tests/modetest/buffers.h | 12 +- tests/modetest/cursor.c | 4 +- tests/modetest/modetest.c | 25 +- tests/proptest/Makefile.am | 4 +- tests/proptest/proptest.c | 3 +- tests/util/Android.mk | 39 ++ tests/util/Makefile.am | 13 + tests/util/Makefile.sources | 6 + tests/util/common.h | 33 ++ tests/util/format.c | 120 ++++++ tests/util/format.h | 65 +++ tests/util/pattern.c | 870 +++++++++++++++++++++++++++++++++++++++ tests/util/pattern.h | 39 ++ tests/vbltest/Makefile.am | 1 + tests/vbltest/vbltest.c | 2 +- 23 files changed, 1223 insertions(+), 990 deletions(-) create mode 100644 tests/util/Android.mk create mode 100644 tests/util/Makefile.am create mode 100644 tests/util/Makefile.sources create mode 100644 tests/util/common.h create mode 100644 tests/util/format.c create mode 100644 tests/util/format.h create mode 100644 tests/util/pattern.c create mode 100644 tests/util/pattern.h
As mentioned on IRC, although there might be some minor nitpicks I'd rather the series in those in and fix them later. Mostly to avoid the long gap until you get the chance to respin things, but also to spare Tomi (and others) the need to reinvent them :-)
I don't mind doing another round if you point out the nitpicks. I'm hopeful that I'll get around to respinning sooner this time. =)
The only thing that I've noticed was a lack of teardown in most/all error paths. Which is ... both very low priority and almost impossible to get right/test. If you want to sort those, but all means please do. Alternatively we'll get them some day ;-)
Thanks Emil
dri-devel@lists.freedesktop.org