thanks! I've pushed to a branch on my github tree, in case you want to double check that I'm not missing anything:
git://github.com/robclark/libdrm.git modetest branch will do some sanity testing a bit later, and if that looks ok and no one objects, I can push to fd.o BR, -R On Fri, Jul 20, 2012 at 9:37 AM, Laurent Pinchart <laurent.pinchart at ideasonboard.com> wrote: > As the modeset test application is often referred to as an example of > the KMS API usage, move test pattern generation and buffer allocation to > a separate file to keep it simple and clear. > > Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com> > --- > tests/modetest/Makefile.am | 2 +- > tests/modetest/buffers.c | 1021 > ++++++++++++++++++++++++++++++++++++++++++++ > tests/modetest/buffers.h | 45 ++ > tests/modetest/modetest.c | 987 +------------------------------------------ > 4 files changed, 1068 insertions(+), 987 deletions(-) > create mode 100644 tests/modetest/buffers.c > create mode 100644 tests/modetest/buffers.h > > Hi Rob, > > Something like this ? > > diff --git a/tests/modetest/Makefile.am b/tests/modetest/Makefile.am > index 2191242..35754a2 100644 > --- a/tests/modetest/Makefile.am > +++ b/tests/modetest/Makefile.am > @@ -8,7 +8,7 @@ noinst_PROGRAMS = \ > modetest > > modetest_SOURCES = \ > - modetest.c > + buffers.c modetest.c > modetest_LDADD = \ > $(top_builddir)/libdrm.la \ > $(top_builddir)/libkms/libkms.la \ > diff --git a/tests/modetest/buffers.c b/tests/modetest/buffers.c > new file mode 100644 > index 0000000..5086381 > --- /dev/null > +++ b/tests/modetest/buffers.c > @@ -0,0 +1,1021 @@ > +/* > + * DRM based mode setting test program > + * Copyright 2008 Tungsten Graphics > + * Jakob Bornecrantz <jakob at tungstengraphics.com> > + * Copyright 2008 Intel Corporation > + * Jesse Barnes <jesse.barnes at 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. > + */ > + > +#include "config.h" > + > +#include <assert.h> > +#include <errno.h> > +#include <stdio.h> > +#include <stdlib.h> > +#include <stdint.h> > +#include <string.h> > + > +#include "drm_fourcc.h" > +#include "libkms.h" > + > +#include "buffers.h" > + > +#ifdef HAVE_CAIRO > +#include <math.h> > +#include <cairo.h> > +#endif > + > +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) > + > +/* > ----------------------------------------------------------------------------- > + * 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, bl, bo, gl, go, al, ao) \ > + .rgb = { { (rl), (ro) }, { (bl), (bo) }, { (gl), (go) }, { (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_YVU420, "YV12", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 1) }, > + /* RGB16 */ > + { 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_RGB565, "RG16", MAKE_RGB_INFO(5, 11, 6, 5, 5, 0, 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_BGRA8888, "BA24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 8, > 0) }, > + { DRM_FORMAT_XRGB8888, "XR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) > }, > + { DRM_FORMAT_BGRX8888, "BX24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 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 * 2; > + } > + > + 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 * 2; > + } > + > + 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 * 2; > + } > + > + /* 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 * 2; > + } > + > + 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 * 2; > + } > + > + 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 * 2; > + } > +} > + > +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, 255), /* blue */ > + MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ > + MAKE_RGBA(rgb, 192, 0, 192, 255), /* magenta */ > + MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ > + MAKE_RGBA(rgb, 0, 192, 192, 255), /* cyan */ > + MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ > + MAKE_RGBA(rgb, 192, 192, 192, 255), /* 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, 255), /* blue */ > + MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ > + MAKE_RGBA(rgb, 192, 0, 192, 255), /* magenta */ > + MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ > + MAKE_RGBA(rgb, 0, 192, 192, 255), /* cyan */ > + MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ > + MAKE_RGBA(rgb, 192, 192, 192, 255), /* 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_YVU420: > + return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[1], > + planes[2], width, height, > stride); > + > + case DRM_FORMAT_RGB565: > + case DRM_FORMAT_ARGB1555: > + case DRM_FORMAT_XRGB1555: > + 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_BGRA8888: > + case DRM_FORMAT_XRGB8888: > + case DRM_FORMAT_BGRX8888: > + 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) > +{ > +#ifdef HAVE_CAIRO > + cairo_surface_t *surface; > + cairo_t *cr; > + int x, y; > + > + surface = cairo_image_surface_create_for_data(data, > + CAIRO_FORMAT_ARGB32, > + 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 yuv_info *yuv, > + unsigned char *y_mem, unsigned char *u_mem, > + unsigned char *v_mem, unsigned int width, > + unsigned int height, unsigned int stride) > +{ > + 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 yuv_info *yuv, unsigned char *mem, > + unsigned int width, unsigned int height, > + unsigned int stride) > +{ > + 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 rgb_info *rgb, unsigned char *mem, > + unsigned int width, unsigned int height, unsigned int stride) > +{ > + 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; > + } > +} > + > +static void > +fill_tiles_rgb24(const struct rgb_info *rgb, unsigned char *mem, > + unsigned int width, unsigned int height, unsigned int stride) > +{ > + 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 rgb_info *rgb, unsigned char *mem, > + unsigned int width, unsigned int height, unsigned int stride) > +{ > + 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 color = > + MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff, > + (rgb32 >> 8) & 0xff, rgb32 & 0xff, > + 255); > + > + ((uint32_t *)mem)[x] = color; > + } > + mem += stride; > + } > + > + make_pwetty(mem_base, width, height, stride); > +} > + > +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->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_tiles_yuv_planar(&info->yuv, planes[0], u, v, > + width, height, stride); > + > + case DRM_FORMAT_YVU420: > + return fill_tiles_yuv_planar(&info->yuv, planes[0], planes[1], > + planes[2], width, height, > stride); > + > + case DRM_FORMAT_RGB565: > + case DRM_FORMAT_ARGB1555: > + case DRM_FORMAT_XRGB1555: > + return fill_tiles_rgb16(&info->rgb, planes[0], > + width, height, stride); > + case DRM_FORMAT_BGR888: > + case DRM_FORMAT_RGB888: > + return fill_tiles_rgb24(&info->rgb, planes[0], > + width, height, stride); > + case DRM_FORMAT_ARGB8888: > + case DRM_FORMAT_BGRA8888: > + case DRM_FORMAT_XRGB8888: > + case DRM_FORMAT_BGRX8888: > + return fill_tiles_rgb32(&info->rgb, 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 > + */ > + > +static struct kms_bo * > +allocate_buffer(struct kms_driver *kms, > + int width, int height, int *stride) > +{ > + struct kms_bo *bo; > + unsigned bo_attribs[] = { > + KMS_WIDTH, 0, > + KMS_HEIGHT, 0, > + KMS_BO_TYPE, KMS_BO_TYPE_SCANOUT_X8R8G8B8, > + KMS_TERMINATE_PROP_LIST > + }; > + int ret; > + > + bo_attribs[1] = width; > + bo_attribs[3] = height; > + > + ret = kms_bo_create(kms, bo_attribs, &bo); > + if (ret) { > + fprintf(stderr, "failed to alloc buffer: %s\n", > + strerror(-ret)); > + return NULL; > + } > + > + ret = kms_bo_get_prop(bo, KMS_PITCH, stride); > + if (ret) { > + fprintf(stderr, "failed to retreive buffer stride: %s\n", > + strerror(-ret)); > + kms_bo_destroy(&bo); > + return NULL; > + } > + > + return bo; > +} > + > +struct kms_bo * > +create_test_buffer(struct kms_driver *kms, unsigned int format, > + int width, int height, int handles[4], > + int pitches[4], int offsets[4], enum fill_pattern pattern) > +{ > + struct kms_bo *bo; > + int ret, stride; > + void *planes[3]; > + void *virtual; > + > + bo = allocate_buffer(kms, width, height, &pitches[0]); > + if (!bo) > + return NULL; > + > + ret = kms_bo_map(bo, &virtual); > + if (ret) { > + fprintf(stderr, "failed to map buffer: %s\n", > + strerror(-ret)); > + kms_bo_destroy(&bo); > + return NULL; > + } > + > + /* just testing a limited # of formats to test single > + * and multi-planar path.. would be nice to add more.. > + */ > + switch (format) { > + case DRM_FORMAT_UYVY: > + case DRM_FORMAT_VYUY: > + case DRM_FORMAT_YUYV: > + case DRM_FORMAT_YVYU: > + pitches[0] = width * 2; > + offsets[0] = 0; > + kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]); > + > + planes[0] = virtual; > + break; > + > + case DRM_FORMAT_NV12: > + case DRM_FORMAT_NV21: > + case DRM_FORMAT_NV16: > + case DRM_FORMAT_NV61: > + pitches[0] = width; > + offsets[0] = 0; > + kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]); > + pitches[1] = width; > + offsets[1] = width * height; > + kms_bo_get_prop(bo, KMS_HANDLE, &handles[1]); > + > + planes[0] = virtual; > + planes[1] = virtual + offsets[1]; > + break; > + > + case DRM_FORMAT_YVU420: > + pitches[0] = width; > + offsets[0] = 0; > + kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]); > + pitches[1] = width / 2; > + offsets[1] = width * height; > + kms_bo_get_prop(bo, KMS_HANDLE, &handles[1]); > + pitches[2] = width / 2; > + offsets[2] = offsets[1] + (width * height) / 4; > + kms_bo_get_prop(bo, KMS_HANDLE, &handles[2]); > + > + planes[0] = virtual; > + planes[1] = virtual + offsets[1]; > + planes[2] = virtual + offsets[2]; > + break; > + > + case DRM_FORMAT_RGB565: > + case DRM_FORMAT_ARGB1555: > + case DRM_FORMAT_XRGB1555: > + pitches[0] = width * 2; > + offsets[0] = 0; > + kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]); > + > + planes[0] = virtual; > + break; > + > + case DRM_FORMAT_BGR888: > + case DRM_FORMAT_RGB888: > + pitches[0] = width * 3; > + offsets[0] = 0; > + kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]); > + > + planes[0] = virtual; > + break; > + > + case DRM_FORMAT_ARGB8888: > + case DRM_FORMAT_BGRA8888: > + case DRM_FORMAT_XRGB8888: > + case DRM_FORMAT_BGRX8888: > + pitches[0] = width * 4; > + offsets[0] = 0; > + kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]); > + > + planes[0] = virtual; > + break; > + } > + > + fill_pattern(format, pattern, planes, width, height, pitches[0]); > + kms_bo_unmap(bo); > + > + return bo; > +} > diff --git a/tests/modetest/buffers.h b/tests/modetest/buffers.h > new file mode 100644 > index 0000000..2b15ce5 > --- /dev/null > +++ b/tests/modetest/buffers.h > @@ -0,0 +1,45 @@ > +/* > + * DRM based mode setting test program > + * Copyright 2008 Tungsten Graphics > + * Jakob Bornecrantz <jakob at tungstengraphics.com> > + * Copyright 2008 Intel Corporation > + * Jesse Barnes <jesse.barnes at 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 __BUFFERS_H__ > +#define __BUFFERS_H__ > + > +struct kms_bo; > +struct kms_driver; > + > +enum fill_pattern { > + PATTERN_TILES = 0, > + PATTERN_PLAIN = 1, > + PATTERN_SMPTE = 2, > +}; > + > +struct kms_bo *create_test_buffer(struct kms_driver *kms, unsigned int > format, > + int width, int height, int handles[4], int pitches[4], > + int offsets[4], enum fill_pattern pattern); > + > +unsigned int format_fourcc(const char *name); > + > +#endif > diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c > index 3ed39b7..3e74008 100644 > --- a/tests/modetest/modetest.c > +++ b/tests/modetest/modetest.c > @@ -55,10 +55,7 @@ > #include "drm_fourcc.h" > #include "libkms.h" > > -#ifdef HAVE_CAIRO > -#include <math.h> > -#include <cairo.h> > -#endif > +#include "buffers.h" > > drmModeRes *resources; > int fd, modes; > @@ -584,988 +581,6 @@ connector_find_mode(struct connector *c) > > } > > -/* > ----------------------------------------------------------------------------- > - * 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, bl, bo, gl, go, al, ao) \ > - .rgb = { { (rl), (ro) }, { (bl), (bo) }, { (gl), (go) }, { (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_YVU420, "YV12", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 1) }, > - /* RGB16 */ > - { 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_RGB565, "RG16", MAKE_RGB_INFO(5, 11, 6, 5, 5, 0, 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_BGRA8888, "BA24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 8, > 0) }, > - { DRM_FORMAT_XRGB8888, "XR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) > }, > - { DRM_FORMAT_BGRX8888, "BX24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 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 > - */ > - > -enum fill_pattern { > - PATTERN_TILES = 0, > - PATTERN_PLAIN = 1, > - PATTERN_SMPTE = 2, > -}; > - > -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 * 2; > - } > - > - 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 * 2; > - } > - > - 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 * 2; > - } > - > - /* 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 * 2; > - } > - > - 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 * 2; > - } > - > - 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 * 2; > - } > -} > - > -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, 255), /* blue */ > - MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ > - MAKE_RGBA(rgb, 192, 0, 192, 255), /* magenta */ > - MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ > - MAKE_RGBA(rgb, 0, 192, 192, 255), /* cyan */ > - MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ > - MAKE_RGBA(rgb, 192, 192, 192, 255), /* 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, 255), /* blue */ > - MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ > - MAKE_RGBA(rgb, 192, 0, 192, 255), /* magenta */ > - MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ > - MAKE_RGBA(rgb, 0, 192, 192, 255), /* cyan */ > - MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ > - MAKE_RGBA(rgb, 192, 192, 192, 255), /* 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_YVU420: > - return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[1], > - planes[2], width, height, > stride); > - > - case DRM_FORMAT_RGB565: > - case DRM_FORMAT_ARGB1555: > - case DRM_FORMAT_XRGB1555: > - 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_BGRA8888: > - case DRM_FORMAT_XRGB8888: > - case DRM_FORMAT_BGRX8888: > - 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) > -{ > -#ifdef HAVE_CAIRO > - cairo_surface_t *surface; > - cairo_t *cr; > - int x, y; > - > - surface = cairo_image_surface_create_for_data(data, > - CAIRO_FORMAT_ARGB32, > - 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 yuv_info *yuv, > - unsigned char *y_mem, unsigned char *u_mem, > - unsigned char *v_mem, unsigned int width, > - unsigned int height, unsigned int stride) > -{ > - 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 yuv_info *yuv, unsigned char *mem, > - unsigned int width, unsigned int height, > - unsigned int stride) > -{ > - 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 rgb_info *rgb, unsigned char *mem, > - unsigned int width, unsigned int height, unsigned int stride) > -{ > - 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; > - } > -} > - > -static void > -fill_tiles_rgb24(const struct rgb_info *rgb, unsigned char *mem, > - unsigned int width, unsigned int height, unsigned int stride) > -{ > - 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 rgb_info *rgb, unsigned char *mem, > - unsigned int width, unsigned int height, unsigned int stride) > -{ > - 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 color = > - MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff, > - (rgb32 >> 8) & 0xff, rgb32 & 0xff, > - 255); > - > - ((uint32_t *)mem)[x] = color; > - } > - mem += stride; > - } > - > - make_pwetty(mem_base, width, height, stride); > -} > - > -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->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_tiles_yuv_planar(&info->yuv, planes[0], u, v, > - width, height, stride); > - > - case DRM_FORMAT_YVU420: > - return fill_tiles_yuv_planar(&info->yuv, planes[0], planes[1], > - planes[2], width, height, > stride); > - > - case DRM_FORMAT_RGB565: > - case DRM_FORMAT_ARGB1555: > - case DRM_FORMAT_XRGB1555: > - return fill_tiles_rgb16(&info->rgb, planes[0], > - width, height, stride); > - case DRM_FORMAT_BGR888: > - case DRM_FORMAT_RGB888: > - return fill_tiles_rgb24(&info->rgb, planes[0], > - width, height, stride); > - case DRM_FORMAT_ARGB8888: > - case DRM_FORMAT_BGRA8888: > - case DRM_FORMAT_XRGB8888: > - case DRM_FORMAT_BGRX8888: > - return fill_tiles_rgb32(&info->rgb, 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 > - */ > - > -static struct kms_bo * > -allocate_buffer(struct kms_driver *kms, > - int width, int height, int *stride) > -{ > - struct kms_bo *bo; > - unsigned bo_attribs[] = { > - KMS_WIDTH, 0, > - KMS_HEIGHT, 0, > - KMS_BO_TYPE, KMS_BO_TYPE_SCANOUT_X8R8G8B8, > - KMS_TERMINATE_PROP_LIST > - }; > - int ret; > - > - bo_attribs[1] = width; > - bo_attribs[3] = height; > - > - ret = kms_bo_create(kms, bo_attribs, &bo); > - if (ret) { > - fprintf(stderr, "failed to alloc buffer: %s\n", > - strerror(-ret)); > - return NULL; > - } > - > - ret = kms_bo_get_prop(bo, KMS_PITCH, stride); > - if (ret) { > - fprintf(stderr, "failed to retreive buffer stride: %s\n", > - strerror(-ret)); > - kms_bo_destroy(&bo); > - return NULL; > - } > - > - return bo; > -} > - > -static struct kms_bo * > -create_test_buffer(struct kms_driver *kms, unsigned int format, > - int width, int height, int handles[4], > - int pitches[4], int offsets[4], enum fill_pattern pattern) > -{ > - struct kms_bo *bo; > - int ret, stride; > - void *planes[3]; > - void *virtual; > - > - bo = allocate_buffer(kms, width, height, &pitches[0]); > - if (!bo) > - return NULL; > - > - ret = kms_bo_map(bo, &virtual); > - if (ret) { > - fprintf(stderr, "failed to map buffer: %s\n", > - strerror(-ret)); > - kms_bo_destroy(&bo); > - return NULL; > - } > - > - /* just testing a limited # of formats to test single > - * and multi-planar path.. would be nice to add more.. > - */ > - switch (format) { > - case DRM_FORMAT_UYVY: > - case DRM_FORMAT_VYUY: > - case DRM_FORMAT_YUYV: > - case DRM_FORMAT_YVYU: > - pitches[0] = width * 2; > - offsets[0] = 0; > - kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]); > - > - planes[0] = virtual; > - break; > - > - case DRM_FORMAT_NV12: > - case DRM_FORMAT_NV21: > - case DRM_FORMAT_NV16: > - case DRM_FORMAT_NV61: > - pitches[0] = width; > - offsets[0] = 0; > - kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]); > - pitches[1] = width; > - offsets[1] = width * height; > - kms_bo_get_prop(bo, KMS_HANDLE, &handles[1]); > - > - planes[0] = virtual; > - planes[1] = virtual + offsets[1]; > - break; > - > - case DRM_FORMAT_YVU420: > - pitches[0] = width; > - offsets[0] = 0; > - kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]); > - pitches[1] = width / 2; > - offsets[1] = width * height; > - kms_bo_get_prop(bo, KMS_HANDLE, &handles[1]); > - pitches[2] = width / 2; > - offsets[2] = offsets[1] + (width * height) / 4; > - kms_bo_get_prop(bo, KMS_HANDLE, &handles[2]); > - > - planes[0] = virtual; > - planes[1] = virtual + offsets[1]; > - planes[2] = virtual + offsets[2]; > - break; > - > - case DRM_FORMAT_RGB565: > - case DRM_FORMAT_ARGB1555: > - case DRM_FORMAT_XRGB1555: > - pitches[0] = width * 2; > - offsets[0] = 0; > - kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]); > - > - planes[0] = virtual; > - break; > - > - case DRM_FORMAT_BGR888: > - case DRM_FORMAT_RGB888: > - pitches[0] = width * 3; > - offsets[0] = 0; > - kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]); > - > - planes[0] = virtual; > - break; > - > - case DRM_FORMAT_ARGB8888: > - case DRM_FORMAT_BGRA8888: > - case DRM_FORMAT_XRGB8888: > - case DRM_FORMAT_BGRX8888: > - pitches[0] = width * 4; > - offsets[0] = 0; > - kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]); > - > - planes[0] = virtual; > - break; > - } > - > - fill_pattern(format, pattern, planes, width, height, pitches[0]); > - kms_bo_unmap(bo); > - > - return bo; > -} > - > /* > -------------------------------------------------------------------------- */ > > void > -- > Regards, > > Laurent Pinchart > > _______________________________________________ > dri-devel mailing list > dri-devel at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel