[PATCH i-g-t] tests/kms_prime: Add xe support
Kamil Konieczny
kamil.konieczny at linux.intel.com
Wed Jun 25 10:50:25 UTC 2025
Hi Santhosh,
On 2025-06-25 at 11:25:13 +0530, Santhosh Reddy Guddati wrote:
Please keep original author of this patch unless you will make
a big rewrite.
> Add buffer creation, mapping, and BLT copy support for Xe GPUs.
> Update scratch buffer and framebuffer preparation to handle Xe dGPU.
> Extend import logic to use BLT copy for Xe dGPU importers.
> Add basic modeset path for Xe dGPU with VRAM-backed buffers.
> Improve test coverage for hybrid and discrete GPU scenarios.
>
> This work is a continuation of:
> https://patchwork.freedesktop.org/series/128045/
>
Add here Cc: for current Bhanu e-mail:
Cc: Bhanuprakash Modem <bhanuprakash.modem at gmail.com>
Also:
Cc: Anshuman Gupta <anshuman.gupta at intel.com>
Cc: Karthik B S <karthik.b.s at intel.com>
Cc: Matthew Auld <matthew.auld at intel.com>
> Signed-off-by: Santhosh Reddy Guddati <santhosh.reddy.guddati at intel.com>
> Signed-off-by: Bhanuprakash Modem <bhanuprakash.modem at intel.com>
> Signed-off-by: Nidhi Gupta <nidhi1.gupta at intel.com>
> ---
> tests/kms_prime.c | 202 +++++++++++++++++++++++++++++++++++++++++-----
> 1 file changed, 184 insertions(+), 18 deletions(-)
>
> diff --git a/tests/kms_prime.c b/tests/kms_prime.c
> index 1d011327c..dc28d29b3 100644
> --- a/tests/kms_prime.c
> +++ b/tests/kms_prime.c
> @@ -39,6 +39,14 @@
> #include <sys/ioctl.h>
> #include <time.h>
>
> +#include <xe/xe_ioctl.h>
This should be:
#include "xe/xe_ioctl.h"
Also all these "xe/" headers should be placed below after
"intel_" ones.
> +#include "xe/xe_query.h"
> +#include "xe/xe_util.h"
> +
> +#include <intel_blt.h>
Should be:
#include "intel_blt.h"
> +#include "intel_pat.h"
> +#include "intel_common.h"
> +
Here place "xe/...h" headers.
> /**
> * SUBTEST: D3hot
> * Description: Validate pci state of dGPU when dGPU is idle and scanout is on iGPU
> @@ -128,24 +136,64 @@ static igt_output_t *setup_display(int importer_fd, igt_display_t *display,
> return output;
> }
>
> +static uint32_t *prepare_xe_dgfx_scratch(int exporter_fd, struct dumb_bo *scratch)
> +{
> + uint64_t bo_size;
> + uint32_t *ptr;
> + struct blt_copy_data ex_blt = {};
> + struct blt_copy_object *src = NULL;
> + uint32_t region;
> +
> + region = DRM_XE_MEM_REGION_CLASS_VRAM;
> + bo_size = xe_bb_size(exporter_fd, SZ_4K);
> +
> + igt_info("Preparing scratch buffer for DGfx exporter\n");
> +
> + xe_bo_create(exporter_fd, 0, bo_size, region, DRM_XE_GEM_CREATE_FLAG_NEEDS_VISIBLE_VRAM |
> + DRM_XE_GEM_CREATE_FLAG_SCANOUT);
> + blt_copy_init(exporter_fd, &ex_blt);
> + src = blt_create_object(&ex_blt, region,
> + scratch->width, scratch->height,
> + scratch->bpp, 0, T_LINEAR,
> + COMPRESSION_DISABLED, 0, true);
> + scratch->handle = src->handle;
> + scratch->size = src->size;
> + scratch->pitch = src->pitch;
> + ptr = kmstest_dumb_map_buffer(exporter_fd, scratch->handle,
> + scratch->size, PROT_WRITE);
> + return ptr;
> +}
> +
> static void prepare_scratch(int exporter_fd, struct dumb_bo *scratch,
> drmModeModeInfo *mode, uint32_t color)
> {
> uint32_t *ptr;
> + bool is_dgfx;
> +
> + is_dgfx = is_intel_dgfx(exporter_fd);
>
> scratch->width = mode->hdisplay;
> scratch->height = mode->vdisplay;
> scratch->bpp = 32;
>
> - if (!is_i915_device(exporter_fd)) {
> - scratch->handle = kmstest_dumb_create(exporter_fd,
> - ALIGN(scratch->width, 256),
> - scratch->height, scratch->bpp,
> - &scratch->pitch, &scratch->size);
> -
> - ptr = kmstest_dumb_map_buffer(exporter_fd, scratch->handle,
> - scratch->size, PROT_WRITE);
> - } else {
> + if (is_xe_device(exporter_fd)) {
> + if (is_dgfx) {
> + ptr = prepare_xe_dgfx_scratch(exporter_fd, scratch);
> + if (ptr == MAP_FAILED) {
> + igt_info("Failed to map scratch buffer\n");
> + return;
> + }
> + } else {
> + printf("Creating scratch buffer for color %#08x\n", color);
Use igt_info(), no "printf" in tests.
> + scratch->handle = kmstest_dumb_create(exporter_fd,
> + scratch->width,
> + scratch->height, scratch->bpp,
> + &scratch->pitch, &scratch->size);
> +
> + ptr = kmstest_dumb_map_buffer(exporter_fd, scratch->handle,
> + scratch->size, PROT_WRITE | PROT_READ);
> + }
> + } else if (is_i915_device(exporter_fd)) {
These are rewritng logic, please make it in separate patch and sent
separatly.
> struct igt_fb fb;
>
> igt_init_fb(&fb, exporter_fd, mode->hdisplay, mode->vdisplay,
> @@ -165,6 +213,14 @@ static void prepare_scratch(int exporter_fd, struct dumb_bo *scratch,
>
> ptr = gem_mmap__device_coherent(exporter_fd, scratch->handle, 0, scratch->size,
> PROT_WRITE | PROT_READ);
> + } else {
> + scratch->handle = kmstest_dumb_create(exporter_fd,
> + ALIGN(scratch->width, 256),
> + scratch->height, scratch->bpp,
> + &scratch->pitch, &scratch->size);
> +
> + ptr = kmstest_dumb_map_buffer(exporter_fd, scratch->handle,
> + scratch->size, PROT_WRITE);
> }
>
> for (size_t idx = 0; idx < scratch->size / sizeof(*ptr); ++idx)
> @@ -184,7 +240,7 @@ static void prepare_fb(int importer_fd, struct dumb_bo *scratch, struct igt_fb *
> }
>
> static void import_fb(int importer_fd, struct igt_fb *fb,
> - int dmabuf_fd, uint32_t pitch)
> + int dmabuf_fd, struct dumb_bo *scratch)
Same here, these should go in separate patch.
After that a new logic for Xe could be added in second patch,
add also there to Cc e-mails for developers sending comments
on this patch, at least Karthik, Matthew Auld and Anshuman Gupta.
Regards,
Kamil
> {
> uint32_t offsets[4] = {}, pitches[4] = {}, handles[4] = {}, temp_buf_handle;
> int ret;
> @@ -197,13 +253,17 @@ static void import_fb(int importer_fd, struct igt_fb *fb,
> igt_info("Importer is dGPU\n");
> temp_buf_handle = prime_fd_to_handle(importer_fd, dmabuf_fd);
> igt_assert(temp_buf_handle > 0);
> - fb->gem_handle = igt_create_bo_with_dimensions(importer_fd, fb->width, fb->height,
> - fb->drm_format, fb->modifier, pitch, &fb_size, NULL, NULL);
> + fb->gem_handle = igt_create_bo_with_dimensions(importer_fd, fb->width,
> + fb->height, fb->drm_format,
> + fb->modifier, scratch->pitch,
> + &fb_size, NULL, NULL);
> igt_assert(fb->gem_handle > 0);
>
> igt_blitter_src_copy(importer_fd, ahnd, 0, NULL, temp_buf_handle,
> - 0, pitch, fb->modifier, 0, 0, fb_size, fb->width,
> - fb->height, 32, fb->gem_handle, 0, pitch, fb->modifier,
> + 0, scratch->pitch, fb->modifier,
> + 0, 0, fb_size, fb->width,
> + fb->height, 32, fb->gem_handle,
> + 0, scratch->pitch, fb->modifier,
> 0, 0, fb_size);
>
> gem_sync(importer_fd, fb->gem_handle);
> @@ -212,12 +272,83 @@ static void import_fb(int importer_fd, struct igt_fb *fb,
> } else {
> fb->gem_handle = prime_fd_to_handle(importer_fd, dmabuf_fd);
> }
> + } else if (is_xe_device(importer_fd)) {
> + if (is_intel_dgfx(importer_fd)) {
> + uint64_t ahnd;
> + uint32_t vm, exec_queue;
> + intel_ctx_t *ctx;
> + struct blt_copy_object *src = NULL, *dst = NULL;
> + struct blt_copy_data im_blt = {0};
> + uint32_t bb;
> +
> + struct drm_xe_engine_class_instance inst = {
> + .engine_class = DRM_XE_ENGINE_CLASS_COPY,
> + };
> +
> + igt_info("importer is dGPU xe\n");
> + vm = xe_vm_create(importer_fd, 0, 0);
> + exec_queue = xe_exec_queue_create(importer_fd, vm, &inst, 0);
> + ctx = intel_ctx_xe(importer_fd, vm, exec_queue, 0, 0, 0);
> + ahnd = intel_allocator_open_full(importer_fd, ctx->vm, 0, 0,
> + INTEL_ALLOCATOR_SIMPLE,
> + ALLOC_STRATEGY_LOW_TO_HIGH, 0);
> +
> + // Import the dmabuf as a handle
> + temp_buf_handle = prime_fd_to_handle(importer_fd, dmabuf_fd);
> + igt_assert(temp_buf_handle > 0);
> +
> + igt_init_fb(fb, importer_fd, scratch->width, scratch->height,
> + DRM_FORMAT_XRGB8888, DRM_FORMAT_MOD_LINEAR,
> + IGT_COLOR_YCBCR_BT709, IGT_COLOR_YCBCR_LIMITED_RANGE);
> +
> + igt_calc_fb_size(fb);
> +
> + fb->gem_handle = xe_bo_create(importer_fd, 0, fb->size,
> + vram_if_possible(importer_fd, 0), 0);
> + igt_require(fb->gem_handle);
> +
> + blt_copy_init(importer_fd, &im_blt);
> +
> + src = blt_create_object(&im_blt, vram_if_possible(importer_fd, 0),
> + scratch->width, scratch->height, 32, 0,
> + T_LINEAR, COMPRESSION_DISABLED, 0, true);
> + blt_set_object(src, temp_buf_handle, scratch->size,
> + vram_if_possible(importer_fd, 0), 0,
> + DEFAULT_PAT_INDEX,
> + T_LINEAR, COMPRESSION_DISABLED, 0);
> +
> + dst = blt_create_object(&im_blt, vram_if_possible(importer_fd, 0),
> + scratch->width, scratch->height, 32, 0,
> + T_LINEAR, COMPRESSION_DISABLED, 0, true);
> + blt_set_object(dst, fb->gem_handle, fb->size,
> + vram_if_possible(importer_fd, 0), 0,
> + DEFAULT_PAT_INDEX,
> + T_LINEAR, COMPRESSION_DISABLED, 0);
> +
> + im_blt.color_depth = CD_32bit;
> + blt_set_copy_object(&im_blt.src, src);
> + blt_set_copy_object(&im_blt.dst, dst);
> +
> + bb = xe_bo_create(importer_fd, 0, fb->size,
> + vram_if_possible(importer_fd, 0), 0);
> +
> + blt_set_batch(&im_blt.bb, bb, fb->size, vram_if_possible(importer_fd, 0));
> + blt_fast_copy(importer_fd, ctx, NULL, ahnd, &im_blt);
> +
> + put_offset(ahnd, dst->handle);
> + put_offset(ahnd, src->handle);
> + put_offset(ahnd, bb);
> + intel_allocator_bind(ahnd, 0, 0);
> + put_ahnd(ahnd);
> + } else {
> + fb->gem_handle = prime_fd_to_handle(importer_fd, dmabuf_fd);
> + }
> } else {
> fb->gem_handle = prime_fd_to_handle(importer_fd, dmabuf_fd);
> }
>
> handles[0] = fb->gem_handle;
> - pitches[0] = pitch;
> + pitches[0] = scratch->pitch;
> offsets[0] = 0;
>
> ret = drmModeAddFB2(importer_fd, fb->width, fb->height,
> @@ -252,7 +383,6 @@ static void collect_crc_for_fb(int importer_fd, struct igt_fb *fb, igt_display_t
> info->str = igt_crc_to_string(&info->crc);
> igt_debug("CRC through '%s' method for %#08x is %s\n",
> info->name, color, info->str);
> - igt_remove_fb(importer_fd, fb);
> }
>
> static void test_crc(int exporter_fd, int importer_fd)
> @@ -284,7 +414,7 @@ static void test_crc(int exporter_fd, int importer_fd)
> gem_close(exporter_fd, scratch.handle);
>
> prepare_fb(importer_fd, &scratch, &fb);
> - import_fb(importer_fd, &fb, dmabuf_fd, scratch.pitch);
> + import_fb(importer_fd, &fb, dmabuf_fd, &scratch);
> close(dmabuf_fd);
>
> colors[i].prime_crc.name = "prime";
> @@ -320,7 +450,7 @@ static void test_crc(int exporter_fd, int importer_fd)
> }
> crc_equal = igt_check_crc_equal(&colors[i].prime_crc.crc,
> &colors[j].direct_crc.crc);
> - igt_assert_f(!crc_equal, "CRC should be different");
> + igt_assert_f(!crc_equal, "CRC should be different\n");
> }
> }
> igt_display_fini(&display);
> @@ -333,6 +463,9 @@ static void test_basic_modeset(int drm_fd)
> enum pipe pipe;
> drmModeModeInfo *mode;
> struct igt_fb fb;
> + uint32_t bo;
> + int ret;
> + uint32_t offsets[4] = { 0 };
>
> igt_device_set_master(drm_fd);
> igt_display_require(&display, drm_fd);
> @@ -341,6 +474,39 @@ static void test_basic_modeset(int drm_fd)
> mode = igt_output_get_mode(output);
> igt_assert(mode);
>
> + if (is_xe_device(drm_fd) && xe_has_vram(drm_fd)) {
> + uint32_t strides[4] = { ALIGN(mode->hdisplay * 4, 64) };
> +
> + igt_info("Doing modeset on discrete\n");
> +
> + igt_init_fb(&fb, drm_fd, mode->hdisplay, mode->vdisplay,
> + DRM_FORMAT_XRGB8888, DRM_FORMAT_MOD_NONE,
> + IGT_COLOR_YCBCR_BT709, IGT_COLOR_YCBCR_LIMITED_RANGE);
> + igt_calc_fb_size(&fb);
> +
> + bo = xe_bo_create(drm_fd, 0, fb.size, vram_if_possible(drm_fd, 0), 0);
> + igt_require(bo);
> +
> + ret = __kms_addfb(drm_fd, bo,
> + mode->hdisplay, mode->vdisplay,
> + DRM_FORMAT_XRGB8888,
> + DRM_FORMAT_MOD_LINEAR,
> + strides, offsets, 1,
> + DRM_MODE_FB_MODIFIERS, &fb.fb_id);
> +
> + igt_assert_eq(ret, 0);
> +
> + set_fb(&fb, &display, output);
> + gem_close(drm_fd, bo);
> +
> + cairo_surface_destroy(fb.cairo_surface);
> + do_or_die(drmModeRmFB(drm_fd, fb.fb_id));
> +
> + igt_display_fini(&display);
> + igt_info("Modeset on discrete done\n");
> + return;
> + }
> +
> igt_create_pattern_fb(drm_fd, mode->hdisplay, mode->vdisplay, DRM_FORMAT_XRGB8888,
> DRM_FORMAT_MOD_LINEAR, &fb);
>
> --
> 2.34.1
>
More information about the igt-dev
mailing list