[igt-dev] [PATCH i-g-t v5] tests/kms_ccs: CCS Clear Color test
Mika Kahola
mika.kahola at intel.com
Wed Sep 16 08:41:45 UTC 2020
The patch proposes a method to test CCS with clear color
capability.
The test paints a solid color on primary fb and a small sprite fb.
These are cleared with fast clear feature. A crc is captured and
compared against the reference.
Clear Color testing is performed with Clear Color DRM format modifier
and with YUV format only.
v2: Modify _gen9_render_copyfunc to support fast clear (Matt)
Enable fast clear bit on 3D sequence (Matt)
Add helper function to figure out clear color modifier (Matt)
v3: Remove unrelated line additions/removes
v4: Fast clear with color (Imre)
v5: Write raw 32-bit color values to register (Imre)
Require 32-bit color format
Signed-off-by: Mika Kahola <mika.kahola at intel.com>
---
lib/gen8_render.h | 1 +
lib/intel_batchbuffer.c | 10 ++++++
lib/intel_batchbuffer.h | 7 ++++
lib/rendercopy.h | 6 ++++
lib/rendercopy_gen9.c | 62 ++++++++++++++++++++++++++++------
tests/kms_ccs.c | 75 ++++++++++++++++++++++++++++++++++++++---
6 files changed, 146 insertions(+), 15 deletions(-)
diff --git a/lib/gen8_render.h b/lib/gen8_render.h
index 31dc01bc..1b0f527e 100644
--- a/lib/gen8_render.h
+++ b/lib/gen8_render.h
@@ -26,6 +26,7 @@
# define GEN8_VS_FLOATING_POINT_MODE_ALTERNATE (1 << 16)
+#define GEN8_3DSTATE_FAST_CLEAR_ENABLE (1 << 8)
#define GEN8_3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP \
GEN4_3D(3, 0, 0x21)
#define GEN8_3DSTATE_PS_BLEND GEN4_3D(3, 0, 0x4d)
diff --git a/lib/intel_batchbuffer.c b/lib/intel_batchbuffer.c
index 99c2e148..c63a2199 100644
--- a/lib/intel_batchbuffer.c
+++ b/lib/intel_batchbuffer.c
@@ -1094,6 +1094,16 @@ igt_vebox_copyfunc_t igt_get_vebox_copyfunc(int devid)
return copy;
}
+igt_render_clearfunc_t igt_get_render_clearfunc(int devid)
+{
+ igt_render_clearfunc_t clear = NULL;
+
+ if (IS_GEN12(devid))
+ clear = gen12_render_clearfunc;
+
+ return clear;
+}
+
/**
* igt_get_media_fillfunc:
* @devid: pci device id
diff --git a/lib/intel_batchbuffer.h b/lib/intel_batchbuffer.h
index a69fffd8..de285586 100644
--- a/lib/intel_batchbuffer.h
+++ b/lib/intel_batchbuffer.h
@@ -368,6 +368,13 @@ typedef void (*igt_vebox_copyfunc_t)(struct intel_batchbuffer *batch,
igt_vebox_copyfunc_t igt_get_vebox_copyfunc(int devid);
+typedef void (*igt_render_clearfunc_t)(struct intel_batchbuffer *batch,
+ drm_intel_context *context,
+ const struct igt_buf *dst, unsigned int dst_x, unsigned int dst_y,
+ unsigned int width, unsigned int height,
+ uint32_t r, uint32_t g, uint32_t b);
+igt_render_clearfunc_t igt_get_render_clearfunc(int devid);
+
/**
* igt_fillfunc_t:
* @i915: drm fd
diff --git a/lib/rendercopy.h b/lib/rendercopy.h
index e0577cac..31dc6265 100644
--- a/lib/rendercopy.h
+++ b/lib/rendercopy.h
@@ -23,6 +23,12 @@ static inline void emit_vertex_normalized(struct intel_batchbuffer *batch,
OUT_BATCH(u.ui);
}
+void gen12_render_clearfunc(struct intel_batchbuffer *batch,
+ drm_intel_context *context,
+ const struct igt_buf *dst, unsigned int dst_x, unsigned int dst_y,
+ unsigned int width, unsigned int height,
+ uint32_t r, uint32_t g, uint32_t b);
+
void gen12_render_copyfunc(struct intel_batchbuffer *batch,
drm_intel_context *context,
const struct igt_buf *src, unsigned src_x, unsigned src_y,
diff --git a/lib/rendercopy_gen9.c b/lib/rendercopy_gen9.c
index 85ae4cab..c13f6307 100644
--- a/lib/rendercopy_gen9.c
+++ b/lib/rendercopy_gen9.c
@@ -303,7 +303,9 @@ gen8_bind_surfaces(struct intel_batchbuffer *batch,
offset, 8);
binding_table[0] = gen8_bind_buf(batch, dst, 1);
- binding_table[1] = gen8_bind_buf(batch, src, 0);
+
+ if (src != NULL)
+ binding_table[1] = gen8_bind_buf(batch, src, 0);
return offset;
}
@@ -370,16 +372,25 @@ gen7_fill_vertex_buffer_data(struct intel_batchbuffer *batch,
start = batch->ptr;
emit_vertex_2s(batch, dst_x + width, dst_y + height);
- emit_vertex_normalized(batch, src_x + width, igt_buf_width(src));
- emit_vertex_normalized(batch, src_y + height, igt_buf_height(src));
+
+ if (src != NULL) {
+ emit_vertex_normalized(batch, src_x + width, igt_buf_width(src));
+ emit_vertex_normalized(batch, src_y + height, igt_buf_height(src));
+ }
emit_vertex_2s(batch, dst_x, dst_y + height);
- emit_vertex_normalized(batch, src_x, igt_buf_width(src));
- emit_vertex_normalized(batch, src_y + height, igt_buf_height(src));
+
+ if (src != NULL) {
+ emit_vertex_normalized(batch, src_x, igt_buf_width(src));
+ emit_vertex_normalized(batch, src_y + height, igt_buf_height(src));
+ }
emit_vertex_2s(batch, dst_x, dst_y);
- emit_vertex_normalized(batch, src_x, igt_buf_width(src));
- emit_vertex_normalized(batch, src_y, igt_buf_height(src));
+
+ if (src != NULL) {
+ emit_vertex_normalized(batch, src_x, igt_buf_width(src));
+ emit_vertex_normalized(batch, src_y, igt_buf_height(src));
+ }
offset = intel_batchbuffer_subdata_offset(batch, start);
annotation_add_state(&aub_annotations, AUB_TRACE_VERTEX_BUFFER,
@@ -843,7 +854,7 @@ gen8_emit_sf(struct intel_batchbuffer *batch)
}
static void
-gen8_emit_ps(struct intel_batchbuffer *batch, uint32_t kernel) {
+gen8_emit_ps(struct intel_batchbuffer *batch, uint32_t kernel, bool fast_clear) {
const int max_threads = 63;
OUT_BATCH(GEN6_3DSTATE_WM | (2 - 2));
@@ -871,6 +882,10 @@ gen8_emit_ps(struct intel_batchbuffer *batch, uint32_t kernel) {
2 << GEN6_3DSTATE_WM_BINDING_TABLE_ENTRY_COUNT_SHIFT);
OUT_BATCH(0); /* scratch space stuff */
OUT_BATCH(0); /* scratch hi */
+
+ if (fast_clear)
+ OUT_BATCH(GEN8_3DSTATE_FAST_CLEAR_ENABLE);
+
OUT_BATCH((max_threads - 1) << GEN8_3DSTATE_PS_MAX_THREADS_SHIFT |
GEN6_3DSTATE_WM_16_DISPATCH_ENABLE);
OUT_BATCH(6 << GEN6_3DSTATE_WM_DISPATCH_START_GRF_0_SHIFT);
@@ -1005,8 +1020,11 @@ void _gen9_render_copyfunc(struct intel_batchbuffer *batch,
uint32_t vertex_buffer;
uint32_t batch_end;
uint32_t aux_pgtable_state;
+ bool fast_clear = src != NULL ? false : true;
+
+ if (src != NULL)
+ igt_assert(src->bpp == dst->bpp);
- igt_assert(src->bpp == dst->bpp);
intel_batchbuffer_flush_with_context(batch, context);
intel_batchbuffer_align(batch, 8);
@@ -1073,7 +1091,7 @@ void _gen9_render_copyfunc(struct intel_batchbuffer *batch,
gen8_emit_sf(batch);
- gen8_emit_ps(batch, ps_kernel_off);
+ gen8_emit_ps(batch, ps_kernel_off, fast_clear);
OUT_BATCH(GEN7_3DSTATE_BINDING_TABLE_POINTERS_PS);
OUT_BATCH(ps_binding_table);
@@ -1153,3 +1171,27 @@ void gen12_render_copyfunc(struct intel_batchbuffer *batch,
gen12_aux_pgtable_cleanup(&pgtable_info);
}
+
+void gen12_render_clearfunc(struct intel_batchbuffer *batch,
+ drm_intel_context *context,
+ const struct igt_buf *dst, unsigned int dst_x, unsigned int dst_y,
+ unsigned int width, unsigned int height,
+ uint32_t r, uint32_t g, uint32_t b)
+{
+ struct aux_pgtable_info pgtable_info = { };
+
+ gen12_aux_pgtable_init(&pgtable_info, batch->bufmgr, NULL, dst);
+
+ dst->data[dst->bo->offset64 + dst->cc.offset + 0 ] = r;
+ dst->data[dst->bo->offset64 + dst->cc.offset + 4 ] = b;
+ dst->data[dst->bo->offset64 + dst->cc.offset + 8 ] = g;
+ dst->data[dst->bo->offset64 + dst->cc.offset + 12] = 0xffffffff;
+
+ _gen9_render_copyfunc(batch, context, NULL, 0, 0,
+ width, height, dst, dst_x, dst_y,
+ pgtable_info.pgtable_bo,
+ gen12_render_copy,
+ sizeof(gen12_render_copy));
+
+ gen12_aux_pgtable_cleanup(&pgtable_info);
+}
diff --git a/tests/kms_ccs.c b/tests/kms_ccs.c
index 53abecce..80f892f6 100644
--- a/tests/kms_ccs.c
+++ b/tests/kms_ccs.c
@@ -50,10 +50,12 @@ enum test_fb_flags {
FB_MISALIGN_AUX_STRIDE = 1 << 2,
FB_SMALL_AUX_STRIDE = 1 << 3,
FB_ZERO_AUX_STRIDE = 1 << 4,
+ FB_CLEAR_COLOR = 1 << 5,
};
typedef struct {
int drm_fd;
+ int devid;
igt_display_t display;
igt_output_t *output;
enum pipe pipe;
@@ -62,6 +64,9 @@ typedef struct {
igt_pipe_crc_t *pipe_crc;
uint32_t format;
uint64_t ccs_modifier;
+ struct igt_fb primary_fb;
+ igt_plane_t *primary;
+ igt_render_clearfunc_t fast_clear;
} data_t;
static const struct {
@@ -120,6 +125,16 @@ static void addfb_init(struct igt_fb *fb, struct drm_mode_fb_cmd2 *f)
}
}
+static bool is_ccs_cc_modifier(uint64_t modifier)
+{
+ switch (modifier) {
+ case LOCAL_I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
+ return true;
+ default:
+ return false;
+ }
+}
+
/*
* The CCS planes of compressed framebuffers contain non-zero bytes if the
* engine compressed effectively the framebuffer. The actual encoding of these
@@ -290,6 +305,17 @@ static igt_plane_t *compatible_main_plane(data_t *data)
return igt_output_get_plane_type(data->output, DRM_PLANE_TYPE_PRIMARY);
}
+static void scratch_buf_init(data_t *data, drm_intel_bo *drmibo,
+ struct igt_buf *igtbo)
+{
+ igtbo->bo = drmibo;
+ igtbo->surface[0].stride = data->primary_fb.strides[0];
+ igtbo->tiling = data->primary_fb.modifier;
+ igtbo->surface[0].size = data->primary_fb.size;
+ igtbo->bpp = data->primary_fb.plane_bpp[0];
+}
+
+
static bool try_config(data_t *data, enum test_fb_flags fb_flags,
igt_crc_t *crc)
{
@@ -299,6 +325,11 @@ static bool try_config(data_t *data, enum test_fb_flags fb_flags,
int fb_width = drm_mode->hdisplay;
enum igt_commit_style commit;
struct igt_fb fb, fb_sprite;
+ drm_intel_bufmgr *bufmgr = NULL;
+ drm_intel_bo *drmibo;
+ struct intel_batchbuffer *batch;
+ struct igt_buf igtbo;
+ drm_intel_context *ctx;
int ret;
if (data->display.is_atomic)
@@ -349,6 +380,30 @@ static bool try_config(data_t *data, enum test_fb_flags fb_flags,
if (data->flags & TEST_BAD_ROTATION_90)
igt_plane_set_rotation(primary, IGT_ROTATION_90);
+ if (fb_flags & FB_CLEAR_COLOR) {
+ drmibo = gem_handle_to_libdrm_bo(bufmgr, data->drm_fd, "",
+ data->primary_fb.gem_handle);
+ igt_assert(drmibo);
+
+ igt_skip_on(data->primary_fb.plane_bpp[0] != 32);
+
+ scratch_buf_init(data, drmibo, &igtbo);
+
+ batch = intel_batchbuffer_alloc(bufmgr, data->devid);
+ igt_assert(batch);
+
+ ctx = drm_intel_gem_context_create(bufmgr);
+ igt_assert(ctx);
+
+ /* use fast clear */
+ data->fast_clear(batch, ctx, &igtbo, 0, 0,
+ data->primary_fb.width,
+ data->primary_fb.height,
+ colors[0].r*UINT32_MAX,
+ colors[0].g*UINT32_MAX,
+ colors[0].b*UINT32_MAX);
+ }
+
ret = igt_display_try_commit2(display, commit);
if (data->flags & TEST_BAD_ROTATION_90) {
igt_assert_eq(ret, -EINVAL);
@@ -386,10 +441,18 @@ static int test_ccs(data_t *data)
if (data->flags & TEST_CRC) {
data->pipe_crc = igt_pipe_crc_new(data->drm_fd, data->pipe, INTEL_PIPE_CRC_SOURCE_AUTO);
- if (try_config(data, fb_flags | FB_COMPRESSED, &ref_crc) &&
- try_config(data, fb_flags, &crc)) {
- igt_assert_crc_equal(&crc, &ref_crc);
- valid_tests++;
+ if (is_ccs_cc_modifier(data->ccs_modifier)) {
+ if (try_config(data, fb_flags | FB_COMPRESSED, &ref_crc) &&
+ try_config(data, fb_flags | FB_COMPRESSED | FB_CLEAR_COLOR, &crc)) {
+ igt_assert_crc_equal(&crc, &ref_crc);
+ valid_tests++;
+ }
+ } else {
+ if (try_config(data, fb_flags | FB_COMPRESSED, &ref_crc) &&
+ try_config(data, fb_flags, &crc)) {
+ igt_assert_crc_equal(&crc, &ref_crc);
+ valid_tests++;
+ }
}
igt_pipe_crc_free(data->pipe_crc);
@@ -471,11 +534,13 @@ igt_main_args("c", NULL, help_str, opt_handler, NULL)
igt_fixture {
data.drm_fd = drm_open_driver_master(DRIVER_INTEL);
- igt_require(intel_gen(intel_get_drm_devid(data.drm_fd)) >= 9);
+ data.devid = intel_gen(intel_get_drm_devid(data.drm_fd));
+ igt_require(data.devid >= 9);
kmstest_set_vt_graphics_mode();
igt_require_pipe_crc(data.drm_fd);
igt_display_require(&data.display, data.drm_fd);
+ data.fast_clear = igt_get_render_clearfunc(data.devid);
}
for_each_pipe_static(pipe) {
--
2.25.1
More information about the igt-dev
mailing list