summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonas Karlman <jonas@kwiboo.se>2023-10-25 16:15:31 +0000
committerJonas Karlman <jonas@kwiboo.se>2023-10-30 12:25:09 +0000
commitde88f74df911362ddd7988b2b5b9df4d8c19251f (patch)
tree759a4bc34ee198d4cb39c28ea3f68e02b3bd5fe9
parent8a933c778a0eb36526bf3fc8a289e25add9ff8b0 (diff)
modetest: add support for DRM_FORMAT_NV{15,20,30}
Add smpte and tiles pattern for 10-bit NV15, NV20 and NV30 pixel formats based on the existing pattern for NV12 with colors simply scaled from 8-bit to 10-bit. These pixel formats are typically used by video decoder and display pipeline on Rockchip SoCs, e.g. on RK322X, RK3288, RK3328 and RK3399 the video decoder produce 10-bit video frames in NV15 and NV20 format. NV20 and NV30 pixel formats was added in drm-misc commit 728c15b4b5f3 ("drm/fourcc: Add NV20 and NV30 YUV formats"). This can be tested/validated on Rockchip SoCs with drm-misc commit d4b384228562 ("drm/rockchip: vop: Add NV15, NV20 and NV30 support"). Signed-off-by: Jonas Karlman <jonas@kwiboo.se> Reviewed-by: Christopher Obbard <chris.obbard@collabora.com> Tested-by: Christopher Obbard <chris.obbard@collabora.com> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
-rw-r--r--include/drm/drm_fourcc.h2
-rw-r--r--tests/modetest/buffers.c12
-rw-r--r--tests/util/format.c3
-rw-r--r--tests/util/pattern.c218
4 files changed, 225 insertions, 10 deletions
diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h
index 6b6235f7..9b250480 100644
--- a/include/drm/drm_fourcc.h
+++ b/include/drm/drm_fourcc.h
@@ -323,6 +323,8 @@ extern "C" {
* index 1 = Cr:Cb plane, [39:0] Cr1:Cb1:Cr0:Cb0 little endian
*/
#define DRM_FORMAT_NV15 fourcc_code('N', 'V', '1', '5') /* 2x2 subsampled Cr:Cb plane */
+#define DRM_FORMAT_NV20 fourcc_code('N', 'V', '2', '0') /* 2x1 subsampled Cr:Cb plane */
+#define DRM_FORMAT_NV30 fourcc_code('N', 'V', '3', '0') /* non-subsampled Cr:Cb plane */
/*
* 2 plane YCbCr MSB aligned
diff --git a/tests/modetest/buffers.c b/tests/modetest/buffers.c
index 65f1cfb3..cc34ba47 100644
--- a/tests/modetest/buffers.c
+++ b/tests/modetest/buffers.c
@@ -148,6 +148,12 @@ bo_create(int fd, unsigned int format,
bpp = 8;
break;
+ case DRM_FORMAT_NV15:
+ case DRM_FORMAT_NV20:
+ case DRM_FORMAT_NV30:
+ bpp = 10;
+ break;
+
case DRM_FORMAT_ARGB4444:
case DRM_FORMAT_XRGB4444:
case DRM_FORMAT_ABGR4444:
@@ -212,6 +218,7 @@ bo_create(int fd, unsigned int format,
switch (format) {
case DRM_FORMAT_NV12:
case DRM_FORMAT_NV21:
+ case DRM_FORMAT_NV15:
case DRM_FORMAT_YUV420:
case DRM_FORMAT_YVU420:
virtual_height = height * 3 / 2;
@@ -219,11 +226,13 @@ bo_create(int fd, unsigned int format,
case DRM_FORMAT_NV16:
case DRM_FORMAT_NV61:
+ case DRM_FORMAT_NV20:
virtual_height = height * 2;
break;
case DRM_FORMAT_NV24:
case DRM_FORMAT_NV42:
+ case DRM_FORMAT_NV30:
virtual_height = height * 3;
break;
@@ -263,6 +272,8 @@ bo_create(int fd, unsigned int format,
case DRM_FORMAT_NV21:
case DRM_FORMAT_NV16:
case DRM_FORMAT_NV61:
+ case DRM_FORMAT_NV15:
+ case DRM_FORMAT_NV20:
offsets[0] = 0;
handles[0] = bo->handle;
pitches[0] = bo->pitch;
@@ -276,6 +287,7 @@ bo_create(int fd, unsigned int format,
case DRM_FORMAT_NV24:
case DRM_FORMAT_NV42:
+ case DRM_FORMAT_NV30:
offsets[0] = 0;
handles[0] = bo->handle;
pitches[0] = bo->pitch;
diff --git a/tests/util/format.c b/tests/util/format.c
index b99cc9c3..1fb7979b 100644
--- a/tests/util/format.c
+++ b/tests/util/format.c
@@ -56,6 +56,9 @@ static const struct util_format_info format_info[] = {
{ DRM_FORMAT_NV61, "NV61", MAKE_YUV_INFO(YUV_YCrCb, 2, 1, 2) },
{ DRM_FORMAT_NV24, "NV24", MAKE_YUV_INFO(YUV_YCbCr, 1, 1, 2) },
{ DRM_FORMAT_NV42, "NV42", MAKE_YUV_INFO(YUV_YCrCb, 1, 1, 2) },
+ { DRM_FORMAT_NV15, "NV15", MAKE_YUV_INFO(YUV_YCbCr, 2, 2, 2) },
+ { DRM_FORMAT_NV20, "NV20", MAKE_YUV_INFO(YUV_YCbCr, 2, 1, 2) },
+ { DRM_FORMAT_NV30, "NV30", MAKE_YUV_INFO(YUV_YCbCr, 1, 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) },
diff --git a/tests/util/pattern.c b/tests/util/pattern.c
index f69c5206..f9ef2b81 100644
--- a/tests/util/pattern.c
+++ b/tests/util/pattern.c
@@ -260,6 +260,148 @@ static void fill_smpte_yuv_planar(const struct util_yuv_info *yuv,
}
}
+static void write_pixels_10bpp(unsigned char *mem,
+ unsigned short a,
+ unsigned short b,
+ unsigned short c,
+ unsigned short d)
+{
+ mem[0] = (a & 0xff);
+ mem[1] = ((a >> 8) & 0x3) | ((b & 0x3f) << 2);
+ mem[2] = ((b >> 6) & 0xf) | ((c & 0xf) << 4);
+ mem[3] = ((c >> 4) & 0x3f) | ((d & 0x3) << 6);
+ mem[4] = ((d >> 2) & 0xff);
+}
+
+static void fill_smpte_yuv_planar_10bpp(const struct util_yuv_info *yuv,
+ unsigned char *y_mem,
+ unsigned char *uv_mem,
+ unsigned int width,
+ unsigned int height,
+ unsigned int stride)
+{
+ const struct color_yuv colors_top[] = {
+ MAKE_YUV_601(192, 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 xstep = cs * xsub;
+ unsigned int x;
+ unsigned int y;
+
+ /* Luma */
+ for (y = 0; y < height * 6 / 9; ++y) {
+ for (x = 0; x < width; x += 4)
+ write_pixels_10bpp(&y_mem[(x * 5) / 4],
+ colors_top[(x+0) * 7 / width].y << 2,
+ colors_top[(x+1) * 7 / width].y << 2,
+ colors_top[(x+2) * 7 / width].y << 2,
+ colors_top[(x+3) * 7 / width].y << 2);
+ y_mem += stride;
+ }
+
+ for (; y < height * 7 / 9; ++y) {
+ for (x = 0; x < width; x += 4)
+ write_pixels_10bpp(&y_mem[(x * 5) / 4],
+ colors_middle[(x+0) * 7 / width].y << 2,
+ colors_middle[(x+1) * 7 / width].y << 2,
+ colors_middle[(x+2) * 7 / width].y << 2,
+ colors_middle[(x+3) * 7 / width].y << 2);
+ y_mem += stride;
+ }
+
+ for (; y < height; ++y) {
+ for (x = 0; x < width * 5 / 7; x += 4)
+ write_pixels_10bpp(&y_mem[(x * 5) / 4],
+ colors_bottom[(x+0) * 4 / (width * 5 / 7)].y << 2,
+ colors_bottom[(x+1) * 4 / (width * 5 / 7)].y << 2,
+ colors_bottom[(x+2) * 4 / (width * 5 / 7)].y << 2,
+ colors_bottom[(x+3) * 4 / (width * 5 / 7)].y << 2);
+ for (; x < width * 6 / 7; x += 4)
+ write_pixels_10bpp(&y_mem[(x * 5) / 4],
+ colors_bottom[((x+0) - width * 5 / 7) * 3 / (width / 7) + 4].y << 2,
+ colors_bottom[((x+1) - width * 5 / 7) * 3 / (width / 7) + 4].y << 2,
+ colors_bottom[((x+2) - width * 5 / 7) * 3 / (width / 7) + 4].y << 2,
+ colors_bottom[((x+3) - width * 5 / 7) * 3 / (width / 7) + 4].y << 2);
+ for (; x < width; x += 4)
+ write_pixels_10bpp(&y_mem[(x * 5) / 4],
+ colors_bottom[7].y << 2,
+ colors_bottom[7].y << 2,
+ colors_bottom[7].y << 2,
+ colors_bottom[7].y << 2);
+ y_mem += stride;
+ }
+
+ /* Chroma */
+ for (y = 0; y < height * 6 / 9; y += ysub) {
+ for (x = 0; x < width; x += xstep)
+ write_pixels_10bpp(&uv_mem[(x * 5) / xstep],
+ colors_top[(x+0) * 7 / width].u << 2,
+ colors_top[(x+0) * 7 / width].v << 2,
+ colors_top[(x+xsub) * 7 / width].u << 2,
+ colors_top[(x+xsub) * 7 / width].v << 2);
+ uv_mem += stride * cs / xsub;
+ }
+
+ for (; y < height * 7 / 9; y += ysub) {
+ for (x = 0; x < width; x += xstep)
+ write_pixels_10bpp(&uv_mem[(x * 5) / xstep],
+ colors_middle[(x+0) * 7 / width].u << 2,
+ colors_middle[(x+0) * 7 / width].v << 2,
+ colors_middle[(x+xsub) * 7 / width].u << 2,
+ colors_middle[(x+xsub) * 7 / width].v << 2);
+ uv_mem += stride * cs / xsub;
+ }
+
+ for (; y < height; y += ysub) {
+ for (x = 0; x < width * 5 / 7; x += xstep)
+ write_pixels_10bpp(&uv_mem[(x * 5) / xstep],
+ colors_bottom[(x+0) * 4 / (width * 5 / 7)].u << 2,
+ colors_bottom[(x+0) * 4 / (width * 5 / 7)].v << 2,
+ colors_bottom[(x+xsub) * 4 / (width * 5 / 7)].u << 2,
+ colors_bottom[(x+xsub) * 4 / (width * 5 / 7)].v << 2);
+ for (; x < width * 6 / 7; x += xstep)
+ write_pixels_10bpp(&uv_mem[(x * 5) / xstep],
+ colors_bottom[((x+0) - width * 5 / 7) * 3 / (width / 7) + 4].u << 2,
+ colors_bottom[((x+0) - width * 5 / 7) * 3 / (width / 7) + 4].v << 2,
+ colors_bottom[((x+xsub) - width * 5 / 7) * 3 / (width / 7) + 4].u << 2,
+ colors_bottom[((x+xsub) - width * 5 / 7) * 3 / (width / 7) + 4].v << 2);
+ for (; x < width; x += xstep)
+ write_pixels_10bpp(&uv_mem[(x * 5) / xstep],
+ colors_bottom[7].u << 2,
+ colors_bottom[7].v << 2,
+ colors_bottom[7].u << 2,
+ colors_bottom[7].v << 2);
+ uv_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)
@@ -1051,6 +1193,13 @@ static void fill_smpte(const struct util_format_info *info, void *planes[3],
return fill_smpte_yuv_planar(&info->yuv, planes[0], u, v,
width, height, stride);
+ case DRM_FORMAT_NV15:
+ case DRM_FORMAT_NV20:
+ case DRM_FORMAT_NV30:
+ return fill_smpte_yuv_planar_10bpp(&info->yuv, planes[0],
+ planes[1], width, height,
+ stride);
+
case DRM_FORMAT_YUV420:
return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[1],
planes[2], width, height, stride);
@@ -1182,6 +1331,18 @@ static void make_pwetty(void *data, unsigned int width, unsigned int height,
#endif
}
+static struct color_yuv make_tiles_yuv_color(unsigned int x, unsigned int y,
+ unsigned int width)
+{
+ 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);
+ return color;
+}
+
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,
@@ -1196,12 +1357,8 @@ static void fill_tiles_yuv_planar(const struct util_format_info *info,
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);
+ make_tiles_yuv_color(x, y, width);
y_mem[x] = color.y;
u_mem[x/xsub*cs] = color.u;
@@ -1216,6 +1373,45 @@ static void fill_tiles_yuv_planar(const struct util_format_info *info,
}
}
+static void fill_tiles_yuv_planar_10bpp(const struct util_format_info *info,
+ unsigned char *y_mem,
+ unsigned char *uv_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 xstep = cs * xsub;
+ unsigned int x;
+ unsigned int y;
+
+ for (y = 0; y < height; ++y) {
+ for (x = 0; x < width; x += 4) {
+ struct color_yuv a = make_tiles_yuv_color(x+0, y, width);
+ struct color_yuv b = make_tiles_yuv_color(x+1, y, width);
+ struct color_yuv c = make_tiles_yuv_color(x+2, y, width);
+ struct color_yuv d = make_tiles_yuv_color(x+3, y, width);
+
+ write_pixels_10bpp(&y_mem[(x * 5) / 4],
+ a.y << 2, b.y << 2, c.y << 2, d.y << 2);
+ }
+ y_mem += stride;
+ }
+ for (y = 0; y < height; y += ysub) {
+ for (x = 0; x < width; x += xstep) {
+ struct color_yuv a = make_tiles_yuv_color(x+0, y, width);
+ struct color_yuv b = make_tiles_yuv_color(x+xsub, y, width);
+
+ write_pixels_10bpp(&uv_mem[(x * 5) / xstep],
+ a.u << 2, a.v << 2, b.u << 2, b.v << 2);
+ }
+ uv_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)
@@ -1230,12 +1426,8 @@ static void fill_tiles_yuv_packed(const struct util_format_info *info,
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);
+ make_tiles_yuv_color(x, y, width);
y_mem[2*x] = color.y;
c_mem[2*x+u] = color.u;
@@ -1373,6 +1565,12 @@ static void fill_tiles(const struct util_format_info *info, void *planes[3],
return fill_tiles_yuv_planar(info, planes[0], u, v,
width, height, stride);
+ case DRM_FORMAT_NV15:
+ case DRM_FORMAT_NV20:
+ case DRM_FORMAT_NV30:
+ return fill_tiles_yuv_planar_10bpp(info, planes[0], planes[1],
+ width, height, stride);
+
case DRM_FORMAT_YUV420:
return fill_tiles_yuv_planar(info, planes[0], planes[1],
planes[2], width, height, stride);