Add checkasm coverage for the XYZ12LE to RGB48LE path via the
ctx->xyz12Torgb48 hook. Integrate the test into the build and runner,
exercise a variety of widths/heights, compare against the C reference,
and benchmark when width is multiple of 4.

This improves test coverage for the new function pointer in preparation
for architecture-specific implementations in subsequent commits.

Signed-off-by: Arpad Panyik <[email protected]>
---
 tests/checkasm/Makefile     |   1 +
 tests/checkasm/checkasm.c   |   1 +
 tests/checkasm/checkasm.h   |   1 +
 tests/checkasm/sw_xyz2rgb.c | 112 ++++++++++++++++++++++++++++++++++++
 4 files changed, 115 insertions(+)
 create mode 100644 tests/checkasm/sw_xyz2rgb.c

diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile
index 6636bc7774..6d2e2b6e22 100644
--- a/tests/checkasm/Makefile
+++ b/tests/checkasm/Makefile
@@ -80,6 +80,7 @@ SWSCALEOBJS                             += sw_gbrp.o          
  \
                                            sw_range_convert.o   \
                                            sw_rgb.o             \
                                            sw_scale.o           \
+                                           sw_xyz2rgb.o         \
                                            sw_yuv2rgb.o         \
                                            sw_yuv2yuv.o
 
diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c
index 20d8f19757..e9251bfb35 100644
--- a/tests/checkasm/checkasm.c
+++ b/tests/checkasm/checkasm.c
@@ -324,6 +324,7 @@ static const struct {
     { "sw_range_convert", checkasm_check_sw_range_convert },
     { "sw_rgb", checkasm_check_sw_rgb },
     { "sw_scale", checkasm_check_sw_scale },
+    { "sw_xyz2rgb", checkasm_check_sw_xyz2rgb },
     { "sw_yuv2rgb", checkasm_check_sw_yuv2rgb },
     { "sw_yuv2yuv", checkasm_check_sw_yuv2yuv },
     { "sw_ops", checkasm_check_sw_ops },
diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h
index 45cd23cac4..9935b37d7d 100644
--- a/tests/checkasm/checkasm.h
+++ b/tests/checkasm/checkasm.h
@@ -138,6 +138,7 @@ void checkasm_check_sw_gbrp(void);
 void checkasm_check_sw_range_convert(void);
 void checkasm_check_sw_rgb(void);
 void checkasm_check_sw_scale(void);
+void checkasm_check_sw_xyz2rgb(void);
 void checkasm_check_sw_yuv2rgb(void);
 void checkasm_check_sw_yuv2yuv(void);
 void checkasm_check_sw_ops(void);
diff --git a/tests/checkasm/sw_xyz2rgb.c b/tests/checkasm/sw_xyz2rgb.c
new file mode 100644
index 0000000000..82e6f94983
--- /dev/null
+++ b/tests/checkasm/sw_xyz2rgb.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2025 Arpad Panyik <[email protected]>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <string.h>
+
+#include "libavutil/intreadwrite.h"
+#include "libavutil/mem_internal.h"
+#include "libavutil/pixdesc.h"
+#include "libavutil/pixfmt.h"
+
+#include "libswscale/swscale.h"
+#include "libswscale/swscale_internal.h"
+
+#include "checkasm.h"
+
+#define NUM_LINES 4
+#define MAX_LINE_SIZE 1920
+
+#define randomize_buffers(buf, size)      \
+    do {                                  \
+        for (int j = 0; j < size; j += 4) \
+            AV_WN32(buf + j, rnd());      \
+    } while (0)
+
+static void check_xyz12Torgb48le(void)
+{
+    const int src_pix_fmt = AV_PIX_FMT_XYZ12LE;
+    const int dst_pix_fmt = AV_PIX_FMT_RGB48LE;
+    const AVPixFmtDescriptor *dst_desc = av_pix_fmt_desc_get(dst_pix_fmt);
+    const AVPixFmtDescriptor *src_desc = av_pix_fmt_desc_get(src_pix_fmt);
+
+    static const int input_sizes[] = {1, 2, 3, 4, 5, 6, 7, 8, 16, 17, 21, 31, 
32,
+                                      64, 128, 256, 512, 1024, MAX_LINE_SIZE};
+
+    declare_func(void, const SwsContext *, uint8_t *, int, const uint8_t *,
+                 int, int, int);
+
+    LOCAL_ALIGNED_8(uint8_t, src,     [6 * MAX_LINE_SIZE * NUM_LINES]);
+    LOCAL_ALIGNED_8(uint8_t, dst_ref, [6 * MAX_LINE_SIZE * NUM_LINES]);
+    LOCAL_ALIGNED_8(uint8_t, dst_new, [6 * MAX_LINE_SIZE * NUM_LINES]);
+
+    randomize_buffers(src,  MAX_LINE_SIZE * NUM_LINES);
+
+    for (int height = 1; height <= NUM_LINES; height++) {
+        for (int isi = 0; isi < FF_ARRAY_ELEMS(input_sizes); isi++) {
+            SwsContext *sws;
+            SwsInternal *c;
+            int log_level;
+            int width = input_sizes[isi];
+            const int srcStride = 6 * MAX_LINE_SIZE;
+            const int dstStride = 6 * MAX_LINE_SIZE;
+
+            // Override log level to prevent spamming of the message:
+            // "No accelerated colorspace conversion found from %s to %s"
+            log_level = av_log_get_level();
+            av_log_set_level(AV_LOG_ERROR);
+            sws = sws_getContext(width, height, src_pix_fmt,
+                                 width, height, dst_pix_fmt,
+                                 0, NULL, NULL, NULL);
+            av_log_set_level(log_level);
+            if (!sws)
+                fail();
+
+            c = sws_internal(sws);
+            if (check_func(c->xyz12Torgb48, "%s_%s_%dx%d", src_desc->name,
+                           dst_desc->name, width, height)) {
+                memset(dst_ref, 0xFF, MAX_LINE_SIZE * NUM_LINES);
+                memset(dst_new, 0xFF, MAX_LINE_SIZE * NUM_LINES);
+
+                call_ref((const SwsContext*)c, dst_ref, dstStride, src,
+                         srcStride, width, height);
+                call_new((const SwsContext*)c, dst_new, dstStride, src,
+                         srcStride, width, height);
+
+                if (memcmp(dst_ref, dst_new, MAX_LINE_SIZE * NUM_LINES))
+                    fail();
+
+                if (!(width & 3) && height == NUM_LINES) {
+                    bench_new((const SwsContext*)c, dst_new, dstStride,
+                              src, srcStride, width, height);
+                }
+            }
+            sws_freeContext(sws);
+        }
+    }
+}
+
+#undef NUM_LINES
+#undef MAX_LINE_SIZE
+
+void checkasm_check_sw_xyz2rgb(void)
+{
+    check_xyz12Torgb48le();
+    report("xyz12Torgb48le");
+}
-- 
2.43.0

>From 40b5ca592c9cdbe41edb14621e397f28e0bc6fd2 Mon Sep 17 00:00:00 2001
From: Arpad Panyik <[email protected]>
Date: Wed, 26 Nov 2025 09:27:51 +0000
Subject: [PATCH 2/3] checkasm: Add xyz12Torgb48le test

Add checkasm coverage for the XYZ12LE to RGB48LE path via the
ctx->xyz12Torgb48 hook. Integrate the test into the build and runner,
exercise a variety of widths/heights, compare against the C reference,
and benchmark when width is multiple of 4.

This improves test coverage for the new function pointer in preparation
for architecture-specific implementations in subsequent commits.

Signed-off-by: Arpad Panyik <[email protected]>
---
 tests/checkasm/Makefile     |   1 +
 tests/checkasm/checkasm.c   |   1 +
 tests/checkasm/checkasm.h   |   1 +
 tests/checkasm/sw_xyz2rgb.c | 112 ++++++++++++++++++++++++++++++++++++
 4 files changed, 115 insertions(+)
 create mode 100644 tests/checkasm/sw_xyz2rgb.c

diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile
index 6636bc7774..6d2e2b6e22 100644
--- a/tests/checkasm/Makefile
+++ b/tests/checkasm/Makefile
@@ -80,6 +80,7 @@ SWSCALEOBJS                             += sw_gbrp.o            \
                                            sw_range_convert.o   \
                                            sw_rgb.o             \
                                            sw_scale.o           \
+                                           sw_xyz2rgb.o         \
                                            sw_yuv2rgb.o         \
                                            sw_yuv2yuv.o
 
diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c
index 20d8f19757..e9251bfb35 100644
--- a/tests/checkasm/checkasm.c
+++ b/tests/checkasm/checkasm.c
@@ -324,6 +324,7 @@ static const struct {
     { "sw_range_convert", checkasm_check_sw_range_convert },
     { "sw_rgb", checkasm_check_sw_rgb },
     { "sw_scale", checkasm_check_sw_scale },
+    { "sw_xyz2rgb", checkasm_check_sw_xyz2rgb },
     { "sw_yuv2rgb", checkasm_check_sw_yuv2rgb },
     { "sw_yuv2yuv", checkasm_check_sw_yuv2yuv },
     { "sw_ops", checkasm_check_sw_ops },
diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h
index 45cd23cac4..9935b37d7d 100644
--- a/tests/checkasm/checkasm.h
+++ b/tests/checkasm/checkasm.h
@@ -138,6 +138,7 @@ void checkasm_check_sw_gbrp(void);
 void checkasm_check_sw_range_convert(void);
 void checkasm_check_sw_rgb(void);
 void checkasm_check_sw_scale(void);
+void checkasm_check_sw_xyz2rgb(void);
 void checkasm_check_sw_yuv2rgb(void);
 void checkasm_check_sw_yuv2yuv(void);
 void checkasm_check_sw_ops(void);
diff --git a/tests/checkasm/sw_xyz2rgb.c b/tests/checkasm/sw_xyz2rgb.c
new file mode 100644
index 0000000000..82e6f94983
--- /dev/null
+++ b/tests/checkasm/sw_xyz2rgb.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2025 Arpad Panyik <[email protected]>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <string.h>
+
+#include "libavutil/intreadwrite.h"
+#include "libavutil/mem_internal.h"
+#include "libavutil/pixdesc.h"
+#include "libavutil/pixfmt.h"
+
+#include "libswscale/swscale.h"
+#include "libswscale/swscale_internal.h"
+
+#include "checkasm.h"
+
+#define NUM_LINES 4
+#define MAX_LINE_SIZE 1920
+
+#define randomize_buffers(buf, size)      \
+    do {                                  \
+        for (int j = 0; j < size; j += 4) \
+            AV_WN32(buf + j, rnd());      \
+    } while (0)
+
+static void check_xyz12Torgb48le(void)
+{
+    const int src_pix_fmt = AV_PIX_FMT_XYZ12LE;
+    const int dst_pix_fmt = AV_PIX_FMT_RGB48LE;
+    const AVPixFmtDescriptor *dst_desc = av_pix_fmt_desc_get(dst_pix_fmt);
+    const AVPixFmtDescriptor *src_desc = av_pix_fmt_desc_get(src_pix_fmt);
+
+    static const int input_sizes[] = {1, 2, 3, 4, 5, 6, 7, 8, 16, 17, 21, 31, 32,
+                                      64, 128, 256, 512, 1024, MAX_LINE_SIZE};
+
+    declare_func(void, const SwsContext *, uint8_t *, int, const uint8_t *,
+                 int, int, int);
+
+    LOCAL_ALIGNED_8(uint8_t, src,     [6 * MAX_LINE_SIZE * NUM_LINES]);
+    LOCAL_ALIGNED_8(uint8_t, dst_ref, [6 * MAX_LINE_SIZE * NUM_LINES]);
+    LOCAL_ALIGNED_8(uint8_t, dst_new, [6 * MAX_LINE_SIZE * NUM_LINES]);
+
+    randomize_buffers(src,  MAX_LINE_SIZE * NUM_LINES);
+
+    for (int height = 1; height <= NUM_LINES; height++) {
+        for (int isi = 0; isi < FF_ARRAY_ELEMS(input_sizes); isi++) {
+            SwsContext *sws;
+            SwsInternal *c;
+            int log_level;
+            int width = input_sizes[isi];
+            const int srcStride = 6 * MAX_LINE_SIZE;
+            const int dstStride = 6 * MAX_LINE_SIZE;
+
+            // Override log level to prevent spamming of the message:
+            // "No accelerated colorspace conversion found from %s to %s"
+            log_level = av_log_get_level();
+            av_log_set_level(AV_LOG_ERROR);
+            sws = sws_getContext(width, height, src_pix_fmt,
+                                 width, height, dst_pix_fmt,
+                                 0, NULL, NULL, NULL);
+            av_log_set_level(log_level);
+            if (!sws)
+                fail();
+
+            c = sws_internal(sws);
+            if (check_func(c->xyz12Torgb48, "%s_%s_%dx%d", src_desc->name,
+                           dst_desc->name, width, height)) {
+                memset(dst_ref, 0xFF, MAX_LINE_SIZE * NUM_LINES);
+                memset(dst_new, 0xFF, MAX_LINE_SIZE * NUM_LINES);
+
+                call_ref((const SwsContext*)c, dst_ref, dstStride, src,
+                         srcStride, width, height);
+                call_new((const SwsContext*)c, dst_new, dstStride, src,
+                         srcStride, width, height);
+
+                if (memcmp(dst_ref, dst_new, MAX_LINE_SIZE * NUM_LINES))
+                    fail();
+
+                if (!(width & 3) && height == NUM_LINES) {
+                    bench_new((const SwsContext*)c, dst_new, dstStride,
+                              src, srcStride, width, height);
+                }
+            }
+            sws_freeContext(sws);
+        }
+    }
+}
+
+#undef NUM_LINES
+#undef MAX_LINE_SIZE
+
+void checkasm_check_sw_xyz2rgb(void)
+{
+    check_xyz12Torgb48le();
+    report("xyz12Torgb48le");
+}
-- 
2.43.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to