lib: add igt_wait()
PATCH 1/7 lib: add igt_wait()
From: Paulo Zanoni <[email protected]>
Just a little helper for code that needs to wait for a certain condition to happen. It has the nice advantage that it can survive the signal helper.
Despite the callers added in this patch, there is another that will go in a separate patch, and another in a new IGT test file that I plan to push later.
v2: Check COND again before returning in case we hit the timeout.
--- lib/igt_aux.c | 18 +----------------- lib/igt_aux.h | 43 +++++++++++++++++++++++++++++++++++++++++++ tests/pm_rpm.c | 28 +++++----------------------- 3 files changed, 49 insertions(+), 40 deletions(-)
lib/igt_aux.c +1 -17
@@ -556,29 +556,13 @@ enum igt_runtime_pm_status igt_get_runtime_pm_status(void)* Waits until for the driver to switch to into the desired runtime PM status, * with a 10 second timeout. * -* Some subtests call this function while the signal helper is active, so we -* can't assume each usleep() call will sleep for 100ms. -* * Returns: * True if the desired runtime PM status was attained, false if the operation * timed out. */ bool igt_wait_for_pm_status (enum igt_runtime_pm_status status) { -struct timeval start, end, diff; - -igt_assert (gettimeofday (&start,NULL ) ==0 ); -do { -if (igt_get_runtime_pm_status () == status) -return true; - -usleep (100 *1000 ); - -igt_assert (gettimeofday (&end,NULL ) ==0 ); -timersub (&end, &start, &diff); - }while (diff.tv_sec <10 ); - -return false; +return igt_wait (igt_get_runtime_pm_status () == status,10000 ,100 ); }/* Functions with prefix kmstest_ independent of cairo library are pulled out
lib/igt_aux.h +43 -0
53 lines not on this page · raw message
tests/pm_rpm.c +5 -23
@@ -153,24 +153,16 @@ static uint64_t get_residency(uint32_t type)static bool pc8_plus_residency_changed (unsigned int timeout_sec) { -unsigned int i;uint64_t res_pc8, res_pc9, res_pc10; -int to_sleep =100 *1000 ; res_pc8 =get_residency (MSR_PC8_RES ); res_pc9 =get_residency (MSR_PC9_RES ); res_pc10 =get_residency (MSR_PC10_RES ); -for (i =0 ; i < timeout_sec *1000 *1000 ; i += to_sleep) { -if (res_pc8 !=get_residency (MSR_PC8_RES ) || - res_pc9 !=get_residency (MSR_PC9_RES ) || - res_pc10 !=get_residency (MSR_PC10_RES )) { -return true; - } -usleep (to_sleep); - } - -return false; +return igt_wait (res_pc8 !=get_residency (MSR_PC8_RES ) || + res_pc9 !=get_residency (MSR_PC9_RES ) || + res_pc10 !=get_residency (MSR_PC10_RES ), + timeout_sec *1000 ,100 ); }static enum pc8_status get_pc8_status (void )
@@ -191,17 +183,7 @@ static enum pc8_status get_pc8_status(void)static bool wait_for_pc8_status (enum pc8_status status) { -int i; -int hundred_ms =100 *1000 , ten_s =10 *1000 *1000 ; - -for (i =0 ; i < ten_s; i += hundred_ms) { -if (get_pc8_status () == status) -return true; - -usleep (hundred_ms); - } - -return false; +return igt_wait (get_pc8_status () == status,10000 ,100 ); }static bool wait_for_suspended (void )
Signature · 6 lines
2.1.4 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
PATCH 2/7 tests/kms_fb_crc: call gem_sync() instead of gem_bo_busy()
From: Paulo Zanoni <[email protected]>
The way kms_fbc_crc works is that it does an operation that may trigger/invalidate/update FBC, then it sleeps for 300ms to wait for FBC to kick in again, then it calls "igt_assert(fbc_enabled())".
This was causing problems where the BLT test would eventually fail in the fbc_eanbled() assertion.
With the recent FBC move to front buffer rendering tracking, if we don't call gem_sync() after submitting render and blt commands, it may take much more than 300ms for FBC to be reenabled:i915_gem_execbuffer2() indirectly calls intel_fb_obj_invalidate(), which disables FBC, and then it is only reenabled when i915_gem_retire_work_handler() happens and indirectly calls intel_frontbuffer_flush(). Notice that while FBC is not yet enabled, the screen contents are correct, so this shouldn't really be a "bug".
The gem_sync() call will make sure the long waits don't happen. With this, 300ms should be much more than enough: either we wait about 50ms for FBC to be re-enabled - intel_enable_fbc() uses a delayed work - or it's instantaneous - on the cases where we just do the nuke.
--- tests/kms_fbc_crc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
tests/kms_fbc_crc.c +2 -2
@@ -122,7 +122,7 @@ static void fill_blt(data_t *data,intel_batchbuffer_flush (batch);intel_batchbuffer_free (batch); -gem_bo_busy (data->drm_fd, handle); +gem_sync (data->drm_fd, handle); }static void scratch_buf_init (struct igt_buf *buf,drm_intel_bo *bo)
@@ -187,7 +187,7 @@ static void fill_render(data_t *data, uint32_t handle,intel_batchbuffer_free (batch); -gem_bo_busy (data->drm_fd, handle); +gem_sync (data->drm_fd, handle); }static bool fbc_enabled (data_t *data)
Signature · 6 lines
2.1.4 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 2/7] tests/kms_fb_crc: call gem_sync() instead of gem_bo_busy()
Quoted 18 lines · Paulo Zanoni
From: Paulo Zanoni <[email protected]>
The way
kms_fbc_crcworks is that it does an operation that may trigger/invalidate/update FBC, then it sleeps for 300ms to wait for FBC to kick in again, then it calls "igt_assert(fbc_enabled())".This was causing problems where the BLT test would eventually fail in the
fbc_eanbled()assertion.With the recent FBC move to front buffer rendering tracking, if we don't call
gem_sync()after submitting render and blt commands, it may take much more than 300ms for FBC to be reenabled:i915_gem_execbuffer2()indirectly callsintel_fb_obj_invalidate(), which disables FBC, and then it is only reenabled wheni915_gem_retire_work_handler()happens and indirectly callsintel_frontbuffer_flush(). Notice that while FBC is not yet enabled, the screen contents are correct, so this shouldn't really be a "bug".
Quoted 6 lines
The
gem_sync()call will make sure the long waits don't happen. With this, 300ms should be much more than enough: either we wait about 50ms for FBC to be re-enabled -intel_enable_fbc()uses a delayed work - or it's instantaneous - on the cases where we just do the nuke.Signed-off-by Paulo Zanoni <[email protected]>
Hm maybe we should have 2 subtests: One with the bo_busy which only checks that the screen contents is right. And then after a longer delay checks that fbc gets reentered eventually. One with the gem_sync which also makes sure fbc gets reentered more timely.
-Daniel
Quoted 33 lines
--- tests/kms_fbc_crc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)tests/kms_fbc_crc.c +2
-2@@ -122,7 +122,7 @@ static void fill_blt(data_t *data,intel_batchbuffer_flush (batch);intel_batchbuffer_free (batch); -gem_bo_busy (data->drm_fd, handle); +gem_sync (data->drm_fd, handle); }static void scratch_buf_init (struct igt_buf *buf,drm_intel_bo *bo)@@ -187,7 +187,7 @@ static void fill_render(data_t *data, uint32_t handle,intel_batchbuffer_free (batch); -gem_bo_busy (data->drm_fd, handle); +gem_sync (data->drm_fd, handle); }static bool fbc_enabled (data_t *data)Signature · 6 lines
2.1.4 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 7 lines
Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
PATCH 3/7 tests/kms_fbc_crc: add wait_for_fbc_enabled()
In reply to Paulo ZanoniFrom: Paulo Zanoni <[email protected]>
The code has a common pattern of "wait 300ms, then check if FBC is enabled". Most of the time FBC is enabled in either 50ms or 0ms, so introduce wait_for_fbc_enabled(), which can return much earlier if FBC is actually enabled before the 300ms timeout.
--- tests/kms_fbc_crc.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-)
tests/kms_fbc_crc.c +10 -9
@@ -28,6 +28,7 @@#include <string.h> #include "drmtest.h" +#include "igt_aux.h" #include "igt_debugfs.h" #include "igt_kms.h" #include "intel_chipset.h"
@@ -203,6 +204,11 @@ static bool fbc_enabled(data_t *data)return strstr (str,"FBC enabled" ) !=NULL ; } +static bool wait_for_fbc_enabled (data_t *data) +{ +return igt_wait (fbc_enabled (data),300 ,30 ); +} +static void test_crc (data_t *data,enum test_mode mode) {uint32_t crtc_id = data->output->config.crtc->crtc_id;
@@ -216,9 +222,8 @@ static void test_crc(data_t *data, enum test_mode mode) handle = data->handle[1 ];igt_assert (drmModePageFlip (data->drm_fd, crtc_id, data->fb_id[1 ],0 ,NULL ) ==0 ); -usleep (300000 ); -igt_assert (fbc_enabled (data)); +igt_assert (wait_for_fbc_enabled (data)); }switch (mode) {
@@ -277,9 +282,7 @@ static void test_crc(data_t *data, enum test_mode mode)* Allow time for FBC to kick in again if it * got disabled during dirtyfb or page flip. */ -usleep (300000 ); - -igt_assert (fbc_enabled (data)); +igt_assert (wait_for_fbc_enabled (data));igt_pipe_crc_start (pipe_crc);igt_pipe_crc_get_crcs (pipe_crc,1 , &crcs);
@@ -338,9 +341,8 @@ static bool prepare_test(data_t *data, enum test_mode test_mode)/* scanout = fb[1] */ igt_plane_set_fb (data->primary, &data->fb[1 ]);igt_display_commit (display); -usleep (300000 ); -if (!fbc_enabled (data)) { +if (!wait_for_fbc_enabled (data)) {igt_info ("FBC not enabled\n" );igt_plane_set_fb (data->primary,NULL );
@@ -388,9 +390,8 @@ static bool prepare_test(data_t *data, enum test_mode test_mode)/* scanout = fb[0] */ igt_plane_set_fb (data->primary, &data->fb[0 ]);igt_display_commit (display); -usleep (300000 ); -igt_assert (fbc_enabled (data)); +igt_assert (wait_for_fbc_enabled (data));if (test_mode ==TEST_CONTEXT || test_mode ==TEST_PAGE_FLIP_AND_CONTEXT ) {/*
Signature · 6 lines
2.1.4 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 3/7] tests/kms_fbc_crc: add wait_for_fbc_enabled()
Quoted 8 lines · Paulo Zanoni
From: Paulo Zanoni <[email protected]>
The code has a common pattern of "wait 300ms, then check if FBC is enabled". Most of the time FBC is enabled in either 50ms or 0ms, so introduce
wait_for_fbc_enabled(), which can return much earlier if FBC is actually enabled before the 300ms timeout.Signed-off-by Paulo Zanoni <[email protected]>
If we go with my suggestion in the previous mail this would need a configurable timeout - with just gem_bo_busy we'd need a 2second timeout or similar.
-Daniel
Quoted 79 lines
--- tests/kms_fbc_crc.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-)tests/kms_fbc_crc.c +10
-9@@ -28,6 +28,7 @@#include <string.h> #include "drmtest.h" +#include "igt_aux.h" #include "igt_debugfs.h" #include "igt_kms.h" #include "intel_chipset.h" @@ -203,6 +204,11 @@ static bool fbc_enabled(data_t *data)return strstr (str,"FBC enabled" ) !=NULL ; } +static bool wait_for_fbc_enabled (data_t *data) +{ +return igt_wait (fbc_enabled (data),300 ,30 ); +} +static void test_crc (data_t *data,enum test_mode mode) {uint32_t crtc_id = data->output->config.crtc->crtc_id;@@ -216,9 +222,8 @@ static void test_crc(data_t *data, enum test_mode mode) handle = data->handle[1 ];igt_assert (drmModePageFlip (data->drm_fd, crtc_id, data->fb_id[1 ],0 ,NULL ) ==0 ); -usleep (300000 ); -igt_assert (fbc_enabled (data)); +igt_assert (wait_for_fbc_enabled (data)); }switch (mode) {@@ -277,9 +282,7 @@ static void test_crc(data_t *data, enum test_mode mode)* Allow time for FBC to kick in again if it * got disabled during dirtyfb or page flip. */ -usleep (300000 ); - -igt_assert (fbc_enabled (data)); +igt_assert (wait_for_fbc_enabled (data));igt_pipe_crc_start (pipe_crc);igt_pipe_crc_get_crcs (pipe_crc,1 , &crcs);@@ -338,9 +341,8 @@ static bool prepare_test(data_t *data, enum test_mode test_mode)/* scanout = fb[1] */ igt_plane_set_fb (data->primary, &data->fb[1 ]);igt_display_commit (display); -usleep (300000 ); -if (!fbc_enabled (data)) { +if (!wait_for_fbc_enabled (data)) {igt_info ("FBC not enabled\n" );igt_plane_set_fb (data->primary,NULL );@@ -388,9 +390,8 @@ static bool prepare_test(data_t *data, enum test_mode test_mode)/* scanout = fb[0] */ igt_plane_set_fb (data->primary, &data->fb[0 ]);igt_display_commit (display); -usleep (300000 ); -igt_assert (fbc_enabled (data)); +igt_assert (wait_for_fbc_enabled (data));if (test_mode ==TEST_CONTEXT || test_mode ==TEST_PAGE_FLIP_AND_CONTEXT ) {/* Signature · 6 lines
2.1.4 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 7 lines
Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
PATCH 4/7 tests/kms_fbc_crc: also gem_sync() on exec_nop()
In reply to Paulo ZanoniFrom: Paulo Zanoni <[email protected]>
When we're doing the context subtest, at the end of prepare_test() we exec a single nop batch on the front buffer, which invalidates FBC. With the new frontbuffer tracking scheme it may take a while for FBC to be reenabled, so we end up failing the first fbc_enabled() assertion inside test_crc().
Other possible implementations:
- Call gem_sync() at the specific prepare_test() point, not at every exec_nop() call.
- Change the fbc_enabled() assertion to wait_for_fbc_enabled() and give it a bigger timeout value.
--- tests/kms_fbc_crc.c | 2 ++ 1 file changed, 2 insertions(+)
tests/kms_fbc_crc.c +2 -0
@@ -155,6 +155,8 @@ static void exec_nop(data_t *data, uint32_t handle, drm_intel_context *context)intel_batchbuffer_flush_with_context (batch, context);intel_batchbuffer_free (batch); + +gem_sync (data->drm_fd, handle); } static void fill_render(data_t *data, uint32_t handle,
Signature · 6 lines
2.1.4 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
PATCH 5/7 tests/kms_fbc_crc: use igt_pipe_crc_collect_crc()
In reply to Paulo ZanoniFrom: Paulo Zanoni <[email protected]>
Instead of its hardcoded implementation.
--- tests/kms_fbc_crc.c | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-)
tests/kms_fbc_crc.c +7 -22
@@ -215,7 +215,7 @@ static void test_crc(data_t *data, enum test_mode mode) {uint32_t crtc_id = data->output->config.crtc->crtc_id;igt_pipe_crc_t *pipe_crc = data->pipe_crc; -igt_crc_t *crcs =NULL ; +igt_crc_t crc;uint32_t handle = data->handle[0 ];igt_assert (fbc_enabled (data));
@@ -271,14 +271,11 @@ static void test_crc(data_t *data, enum test_mode mode)igt_wait_for_vblank (data->drm_fd, data->pipe);igt_wait_for_vblank (data->drm_fd, data->pipe); -igt_pipe_crc_start (pipe_crc); -igt_pipe_crc_get_crcs (pipe_crc,1 , &crcs); -igt_pipe_crc_stop (pipe_crc); +igt_pipe_crc_collect_crc (pipe_crc, &crc);if (mode ==TEST_PAGE_FLIP ) -igt_assert_crc_equal (&crcs[0 ], &data->ref_crc[1 ]); +igt_assert_crc_equal (&crc, &data->ref_crc[1 ]);else ;/* FIXME: missing reference CRCs */ -free (crcs);/* * Allow time for FBC to kick in again if it
@@ -286,14 +283,11 @@ static void test_crc(data_t *data, enum test_mode mode)*/ igt_assert (wait_for_fbc_enabled (data)); -igt_pipe_crc_start (pipe_crc); -igt_pipe_crc_get_crcs (pipe_crc,1 , &crcs); -igt_pipe_crc_stop (pipe_crc); +igt_pipe_crc_collect_crc (pipe_crc, &crc);if (mode ==TEST_PAGE_FLIP ) -igt_assert_crc_equal (&crcs[0 ], &data->ref_crc[1 ]); +igt_assert_crc_equal (&crc, &data->ref_crc[1 ]);else ;/* FIXME: missing reference CRCs */ -free (crcs); }static bool prepare_crtc (data_t *data)
@@ -320,7 +314,6 @@ static bool prepare_test(data_t *data, enum test_mode test_mode)igt_output_t *output = data->output;drmModeModeInfo *mode;igt_pipe_crc_t *pipe_crc; -igt_crc_t *crcs =NULL ; data->primary =igt_output_get_plane (data->output,IGT_PLANE_PRIMARY ); mode =igt_output_get_mode (data->output);
@@ -367,11 +360,7 @@ static bool prepare_test(data_t *data, enum test_mode test_mode)igt_wait_for_vblank (data->drm_fd, data->pipe);/* get reference crc for fb[1] */ -igt_pipe_crc_start (pipe_crc); -igt_pipe_crc_get_crcs (pipe_crc,1 , &crcs); - data->ref_crc[1 ] = crcs[0 ]; -igt_pipe_crc_stop (pipe_crc); -free (crcs); +igt_pipe_crc_collect_crc (pipe_crc, &data->ref_crc[1 ]);if (test_mode ==TEST_CONTEXT || test_mode ==TEST_PAGE_FLIP_AND_CONTEXT ) { data->ctx[0 ] =drm_intel_gem_context_create (data->bufmgr);
@@ -406,11 +395,7 @@ static bool prepare_test(data_t *data, enum test_mode test_mode)igt_wait_for_vblank (data->drm_fd, data->pipe);/* get reference crc for fb[0] */ -igt_pipe_crc_start (pipe_crc); -igt_pipe_crc_get_crcs (pipe_crc,1 , &crcs); - data->ref_crc[0 ] = crcs[0 ]; -igt_pipe_crc_stop (pipe_crc); -free (crcs); +igt_pipe_crc_collect_crc (pipe_crc, &data->ref_crc[0 ]);return true; }
Signature · 6 lines
2.1.4 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
PATCH 6/7 tests/kms_fbc_crc: remove redundant information from data_t
In reply to Paulo ZanoniFrom: Paulo Zanoni <[email protected]>
While it is nice to have shorter names for the most-accessed variables, it makes the code more difficult to read since it's not clear to the code reader whether that "gem_handle" is from some FB or something else. The reader also has to audit the code to see if, for example, the value of data->handle[0] stays consistent with data->fb[0].gem_handle all the tame or if at some point the value is replaced with something else. So remove the redundant information, making it explicit that we're using the gem handles and FB IDs of the framebuffers all the time.
--- tests/kms_fbc_crc.c | 43 +++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 24 deletions(-)
tests/kms_fbc_crc.c +19 -24
@@ -61,13 +61,11 @@ typedef struct {drm_intel_bufmgr *bufmgr;drm_intel_context *ctx[2 ];uint32_t devid; -uint32_t handle[2 ];igt_display_t display;igt_output_t *output;enum pipe pipe;igt_plane_t *primary;struct igt_fb fb[2 ]; -uint32_t fb_id[2 ]; } data_t;static const char *test_mode_str (enum test_mode mode)
@@ -216,14 +214,14 @@ static void test_crc(data_t *data, enum test_mode mode)uint32_t crtc_id = data->output->config.crtc->crtc_id;igt_pipe_crc_t *pipe_crc = data->pipe_crc;igt_crc_t crc; -uint32_t handle = data->handle[0 ]; +uint32_t handle = data->fb[0 ].gem_handle;igt_assert (fbc_enabled (data));if (mode >=TEST_PAGE_FLIP_AND_MMAP_CPU ) { - handle = data->handle[1 ]; + handle = data->fb[1 ].gem_handle;igt_assert (drmModePageFlip (data->drm_fd, crtc_id, - data->fb_id[1 ],0 ,NULL ) ==0 ); + data->fb[1 ].fb_id,0 ,NULL ) ==0 );igt_assert (wait_for_fbc_enabled (data)); }
@@ -232,7 +230,7 @@ static void test_crc(data_t *data, enum test_mode mode)void *ptr;case TEST_PAGE_FLIP :igt_assert (drmModePageFlip (data->drm_fd, crtc_id, - data->fb_id[1 ],0 ,NULL ) ==0 ); + data->fb[1 ].fb_id,0 ,NULL ) ==0 );break ;case TEST_MMAP_CPU :case TEST_PAGE_FLIP_AND_MMAP_CPU :
@@ -314,24 +312,21 @@ static bool prepare_test(data_t *data, enum test_mode test_mode)igt_output_t *output = data->output;drmModeModeInfo *mode;igt_pipe_crc_t *pipe_crc; +int rc; data->primary =igt_output_get_plane (data->output,IGT_PLANE_PRIMARY ); mode =igt_output_get_mode (data->output); - data->fb_id[0 ] =igt_create_color_fb (data->drm_fd, mode->hdisplay, mode->vdisplay, -DRM_FORMAT_XRGB8888 , -LOCAL_I915_FORMAT_MOD_X_TILED , -0.0 ,0.0 ,0.0 , &data->fb[0 ]); -igt_assert (data->fb_id[0 ]); - data->fb_id[1 ] =igt_create_color_fb (data->drm_fd, mode->hdisplay, mode->vdisplay, -DRM_FORMAT_XRGB8888 , -LOCAL_I915_FORMAT_MOD_X_TILED , -0.1 ,0.1 ,0.1 , - &data->fb[1 ]); -igt_assert (data->fb_id[1 ]); - - data->handle[0 ] = data->fb[0 ].gem_handle; - data->handle[1 ] = data->fb[1 ].gem_handle; + rc =igt_create_color_fb (data->drm_fd, mode->hdisplay, mode->vdisplay, +DRM_FORMAT_XRGB8888 , +LOCAL_I915_FORMAT_MOD_X_TILED , +0.0 ,0.0 ,0.0 , &data->fb[0 ]); +igt_assert (rc); + rc =igt_create_color_fb (data->drm_fd, mode->hdisplay, mode->vdisplay, +DRM_FORMAT_XRGB8888 , +LOCAL_I915_FORMAT_MOD_X_TILED , +0.1 ,0.1 ,0.1 , &data->fb[1 ]); +igt_assert (rc);/* scanout = fb[1] */ igt_plane_set_fb (data->primary, &data->fb[1 ]);
@@ -372,10 +367,10 @@ static bool prepare_test(data_t *data, enum test_mode test_mode)* Disable FBC RT address for both contexts * (by "rendering" to a non-scanout buffer). */ -exec_nop (data, data->handle[0 ], data->ctx[1 ]); -exec_nop (data, data->handle[0 ], data->ctx[0 ]); -exec_nop (data, data->handle[0 ], data->ctx[1 ]); -exec_nop (data, data->handle[0 ], data->ctx[0 ]); +exec_nop (data, data->fb[0 ].gem_handle, data->ctx[1 ]); +exec_nop (data, data->fb[0 ].gem_handle, data->ctx[0 ]); +exec_nop (data, data->fb[0 ].gem_handle, data->ctx[1 ]); +exec_nop (data, data->fb[0 ].gem_handle, data->ctx[0 ]); }/* scanout = fb[0] */
Signature · 6 lines
2.1.4 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
PATCH 7/7 lib: add igt_draw
In reply to Paulo ZanoniFrom: Paulo Zanoni <[email protected]>
For all those IGT tests that need an easy way to draw rectangles on buffers using different methods. Current planned users: FBC and PSR CRC tests.
There is also a lib/tests/igt_draw program to check if the library is sane.
--- lib/Makefile.sources | 2 + lib/igt_draw.c | 467 +++++++++++++++++++++++++++++++++++++++++++++ lib/igt_draw.h | 54 ++++++ lib/tests/.gitignore | 1 + lib/tests/Makefile.sources | 1 + lib/tests/igt_draw.c | 247 ++++++++++++++++++++++++ 6 files changed, 772 insertions(+) create mode 100644 lib/igt_draw.c create mode 100644 lib/igt_draw.h create mode 100644 lib/tests/igt_draw.c
lib/Makefile.sources +2 -0
@@ -52,6 +52,8 @@ libintel_tools_la_SOURCES = \ igt_fb.h \ igt_core.c \ igt_core.h \ + igt_draw.c \ + igt_draw.h \ $(NULL) .PHONY: version.h.tmp
lib/igt_draw.c new file +467 -0
467 lines not on this page · raw message
lib/igt_draw.h new file +54 -0
54 lines not on this page · raw message
lib/tests/.gitignore +1 -0
@@ -1,4 +1,5 @@ # Please keep sorted alphabetically +igt_draw igt_fork_helper igt_invalid_subtest_name igt_list_only
lib/tests/Makefile.sources +1 -0
@@ -1,4 +1,5 @@ check_PROGRAMS = \ + igt_draw \ igt_no_exit \ igt_no_exit_list_only \ igt_fork_helper \
lib/tests/igt_draw.c new file +247 -0
247 lines not on this page · raw message
Signature · 6 lines
2.1.4 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 7/7] lib: add igt_draw
Quoted 8 lines · Paulo Zanoni
From: Paulo Zanoni <[email protected]>
For all those IGT tests that need an easy way to draw rectangles on buffers using different methods. Current planned users: FBC and PSR CRC tests.
There is also a
lib/tests/igt_drawprogram to check if the library is sane.
We need to move that to tests/igt_draw. The testcase in lib/tests/* get run with make check, which must be possible as non-root on a non-intel (build) machine. If you need an gpu to run your test it must be in tests/* as a normal igt kernel test.
Wrt the library itself I'm unsure about the explicit tiling/swizzling. Your current code only works on gen5-8 and maintaining a full-blown swizzle/tiling library is real work, and means some of the tests can't be converted to this. We do have all the tiling modes encoded in the tiling tests though, so if you have a lot of time it might be useful to extract tiling helpers into the igt library which work on all generations.
I think we should at least have a fallback mode which allows us to fill an entire buffer completely (i.e. not just the hxw area) and treat it as untiled.
More comments below.
-Daniel
Quoted 333 lines
Signed-off-by Paulo Zanoni <[email protected]>--- lib/Makefile.sources | 2 + lib/igt_draw.c | 467 +++++++++++++++++++++++++++++++++++++++++++++ lib/igt_draw.h | 54 ++++++ lib/tests/.gitignore | 1 + lib/tests/Makefile.sources | 1 + lib/tests/igt_draw.c | 247 ++++++++++++++++++++++++ 6 files changed, 772 insertions(+) create mode 100644 lib/igt_draw.c create mode 100644 lib/igt_draw.h create mode 100644 lib/tests/igt_draw.clib/Makefile.sources +2
-0@@ -52,6 +52,8 @@ libintel_tools_la_SOURCES = \ igt_fb.h \ igt_core.c \ igt_core.h \ + igt_draw.c \ + igt_draw.h \ $(NULL) .PHONY: version.h.tmplib/igt_draw.c new file +300
-0@@ -0,0 +1,467 @@ +/* +* Copyright © 2015 Intel Corporation +* +* 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 (including the next +* paragraph) 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 <sys/mman.h> + +#include "igt_draw.h" + +#include "drmtest.h" +#include "intel_chipset.h" +#include "igt_core.h" +#include "igt_fb.h" +#include "ioctl_wrappers.h" + +/** +* SECTION:igt_draw +* @short_description: drawing helpers for tests +* @title: i-g-t draw +* @include: igt_draw.h +* +* This library contains some functions for drawing rectangles on buffers using +* the many different drawing methods we have. It also contains some wrappers +* that make the process easier if you have the abstract objects in hand. +* +* All functions assume the buffers are in the XRGB 8:8:8 format. +* +*/ + +/* Some internal data structures to avoid having to pass tons of parameters +* around everything. */ +struct cmd_data { +drm_intel_bufmgr *bufmgr; +drm_intel_context *context; +}; + +struct buf_data { +uint32_t handle; +uint32_t size; +uint32_t stride; +}; + +struct rect { +int x; +int y; +int w; +int h; +}; + +const char *igt_draw_get_method_name (enum igt_draw_method method) +{ +switch (method) { +case IGT_DRAW_MMAP_CPU : +return "mmap-cpu" ; +case IGT_DRAW_MMAP_GTT : +return "mmap-gtt" ; +case IGT_DRAW_PWRITE : +return "pwrite" ; +case IGT_DRAW_BLT : +return "blt" ; +case IGT_DRAW_RENDER : +return "render" ; +default : +igt_assert (false); + } +} + +static int swizzle_addr (int addr,int swizzle) +{ +int bit6; + +if (swizzle ==I915_BIT_6_SWIZZLE_9_10 ) { + bit6 = ((addr >>6 ) &1 ) ^ ((addr >>9 ) &1 ) ^ + ((addr >>10 ) &1 ); + addr &= ~(1 <<6 ); + addr |= (bit6 <<6 ); + } + +return addr; +} + +/* It's all in "pixel coordinates", so make sure you multiply/divide by the bpp +* if you need to. */ +static int linear_x_y_to_tiled_pos (int x,int y,uint32_t stride,int swizzle) +{ +int x_tile_size, y_tile_size; +int x_tile_n, y_tile_n, x_tile_off, y_tile_off; +int line_size, tile_size; +int tile_n, tile_off; +int tiled_pos, tiles_per_line; +int bpp; + + line_size = stride; + x_tile_size =512 ; + y_tile_size =8 ; + tile_size = x_tile_size * y_tile_size; + tiles_per_line = line_size / x_tile_size; + bpp =sizeof (uint32_t ); + + y_tile_n = y / y_tile_size; + y_tile_off = y % y_tile_size; + + x_tile_n = (x * bpp) / x_tile_size; + x_tile_off = (x * bpp) % x_tile_size; + + tile_n = y_tile_n * tiles_per_line + x_tile_n; + tile_off = y_tile_off * x_tile_size + x_tile_off; + tiled_pos = tile_n * tile_size + tile_off; + + tiled_pos =swizzle_addr (tiled_pos, swizzle); + +return tiled_pos / bpp; +} + +/* It's all in "pixel coordinates", so make sure you multiply/divide by the bpp +* if you need to. */ +static void tiled_pos_to_x_y_linear (int tiled_pos,uint32_t stride, +int swizzle,int *x,int *y) +{ +int tile_n, tile_off, tiles_per_line, line_size; +int x_tile_off, y_tile_off; +int x_tile_n, y_tile_n; +int x_tile_size, y_tile_size, tile_size; +int bpp; + + tiled_pos =swizzle_addr (tiled_pos, swizzle); + + line_size = stride; + x_tile_size =512 ; + y_tile_size =8 ; + tile_size = x_tile_size * y_tile_size; + tiles_per_line = line_size / x_tile_size; + bpp =sizeof (uint32_t ); + + tile_n = tiled_pos / tile_size; + tile_off = tiled_pos % tile_size; + + y_tile_off = tile_off / x_tile_size; + x_tile_off = tile_off % x_tile_size; + + x_tile_n = tile_n % tiles_per_line; + y_tile_n = tile_n / tiles_per_line; + + *x = (x_tile_n * x_tile_size + x_tile_off) / bpp; + *y = y_tile_n * y_tile_size + y_tile_off; +} + +static void draw_rect_mmap_cpu (int fd,struct buf_data *buf,struct rect *rect, +uint32_t color) +{ +uint32_t *ptr; +int x, y, pos; +uint32_t tiling, swizzle; + +gem_set_domain (fd, buf->handle,I915_GEM_DOMAIN_CPU , +I915_GEM_DOMAIN_CPU ); +gem_get_tiling (fd, buf->handle, &tiling, &swizzle); + + ptr =gem_mmap__cpu (fd, buf->handle,0 , buf->size,0 ); +igt_assert (ptr); + +for (y = rect->y; y < rect->y + rect->h; y++) { +for (x = rect->x; x < rect->x + rect->w; x++) { +if (tiling) + pos =linear_x_y_to_tiled_pos (x, y, buf->stride, + swizzle); +else + pos = (y * buf->stride /sizeof (uint32_t )) + x; + ptr[pos] = color; + } + } + +gem_sw_finish (fd, buf->handle); + +igt_assert (munmap (ptr, buf->size) ==0 ); +} + +static void draw_rect_mmap_gtt (int fd,struct buf_data *buf,struct rect *rect, +uint32_t color) +{ +uint32_t *ptr; +int x, y; + + ptr =gem_mmap__gtt (fd, buf->handle, buf->size, +PROT_READ |PROT_WRITE ); +igt_assert (ptr); + +for (y = rect->y; y < rect->y + rect->h; y++) { +int line_begin = y * buf->stride /sizeof (uint32_t ); +for (x = rect->x; x < rect->x + rect->w; x++) + ptr[line_begin + x] = color; + } + +igt_assert (munmap (ptr, buf->size) ==0 ); +} + +static void draw_rect_pwrite_untiled (int fd,struct buf_data *buf, +struct rect *rect,uint32_t color) +{ +uint32_t tmp[rect->w]; +int i, y, offset, bpp; + + bpp =sizeof (uint32_t ); + +for (i =0 ; i < rect->w; i++) + tmp[i] = color; + +for (y = rect->y; y < rect->y + rect->h; y++) { + offset = (y * buf->stride) + (rect->x * bpp); +gem_write (fd, buf->handle, offset, tmp, rect->w * bpp); + } +} + +static void draw_rect_pwrite_tiled (int fd,struct buf_data *buf, +struct rect *rect,uint32_t color, +uint32_t swizzle) +{ +int i; +int tiled_pos, bpp, x, y; +uint32_t tmp[1024 ]; +int tmp_used =0 , tmp_size =ARRAY_SIZE (tmp); +bool flush_tmp = false; +int tmp_start_pos =0 ; + + bpp =sizeof (uint32_t ); + +/* Instead of doing one pwrite per pixel, we try to group the maximum +* amount of consecutive pixels we can in a single pwrite: that's why we +* use the "tmp" variables. */ +for (i =0 ; i < tmp_size; i++) + tmp[i] = color; + +for (tiled_pos =0 ; tiled_pos < buf->size; tiled_pos += bpp) { +tiled_pos_to_x_y_linear (tiled_pos, buf->stride, swizzle, &x, &y); + +if (x >= rect->x && x < rect->x + rect->w && + y >= rect->y && y < rect->y + rect->h) { +if (tmp_used ==0 ) + tmp_start_pos = tiled_pos; + tmp_used++; + }else { + flush_tmp = true; + } + +if (tmp_used == tmp_size || (flush_tmp && tmp_used >0 )) { +gem_write (fd, buf->handle, tmp_start_pos, tmp, + tmp_used * bpp); + flush_tmp = false; + tmp_used =0 ; + } + } +} + +static void draw_rect_pwrite (int fd,struct buf_data *buf, +struct rect *rect,uint32_t color) +{ +uint32_t tiling, swizzle; + +gem_get_tiling (fd, buf->handle, &tiling, &swizzle); + +if (tiling) +draw_rect_pwrite_tiled (fd, buf, rect, color, swizzle); +else +draw_rect_pwrite_untiled (fd, buf, rect, color); +} + +static void draw_rect_blt (int fd,struct cmd_data *cmd_data, +struct buf_data *buf,struct rect *rect, +uint32_t color) +{ +drm_intel_bo *dst; +struct intel_batchbuffer *batch; +int blt_cmd_len, blt_cmd_tiling; +uint32_t devid =intel_get_drm_devid (fd); +int gen =intel_gen (devid); +uint32_t tiling, swizzle; +int pitch; + +gem_get_tiling (fd, buf->handle, &tiling, &swizzle); + + dst =gem_handle_to_libdrm_bo (cmd_data->bufmgr, fd,"" , buf->handle);
lib/igt_draw.c line 310
Quoted 10 lines
lib/igt_draw.c new file +10
-0+igt_assert (dst); + + batch =intel_batchbuffer_alloc (cmd_data->bufmgr, devid); +igt_assert (batch); + + blt_cmd_len = (gen >=8 ) ?0x5 :0x4 ; + blt_cmd_tiling = (tiling) ?XY_COLOR_BLT_TILED :0 ; + pitch = (tiling) ? buf->stride /4 : buf->stride; + +BEGIN_BATCH (6 ,1 );
This breaks on gen8 because there the relocations are 2 dwords. You need to use the magic macros for that.
Quoted 183 lines
lib/igt_draw.c new file +157
-0+OUT_BATCH (XY_COLOR_BLT_CMD_NOLEN |XY_COLOR_BLT_WRITE_ALPHA | +XY_COLOR_BLT_WRITE_RGB | blt_cmd_tiling | blt_cmd_len); +OUT_BATCH ((3 <<24 ) | (0xF0 <<16 ) | pitch); +OUT_BATCH ((rect->y <<16 ) | rect->x); +OUT_BATCH (((rect->y + rect->h) <<16 ) | (rect->x + rect->w)); +if (tiling) +OUT_RELOC_FENCED (dst,0 ,I915_GEM_DOMAIN_RENDER ,0 ); +else +OUT_RELOC (dst,0 ,I915_GEM_DOMAIN_RENDER ,0 ); +OUT_BATCH (color); +ADVANCE_BATCH (); + +intel_batchbuffer_flush (batch); +gem_sync (fd, buf->handle); +intel_batchbuffer_free (batch); +} + +static void draw_rect_render (int fd,struct cmd_data *cmd_data, +struct buf_data *buf,struct rect *rect, +uint32_t color) +{ +drm_intel_bo *src, *dst; +uint32_t devid =intel_get_drm_devid (fd); +igt_render_copyfunc_t rendercopy =igt_get_render_copyfunc (devid); +struct igt_buf src_buf, dst_buf; +struct intel_batchbuffer *batch; +uint32_t tiling, swizzle; +struct buf_data tmp; + +igt_skip_on (!rendercopy); + +gem_get_tiling (fd, buf->handle, &tiling, &swizzle); + +/* We create a temporary buffer and copy from it using rendercopy. */ + tmp.size = rect->w * rect->h *sizeof (uint32_t ); + tmp.handle =gem_create (fd, tmp.size); + tmp.stride = rect->w *sizeof (uint32_t ); +draw_rect_mmap_cpu (fd, &tmp, &(struct rect ){0 ,0 , rect->w, rect->h}, + color); + + src =gem_handle_to_libdrm_bo (cmd_data->bufmgr, fd,"" , tmp.handle); +igt_assert (src); + dst =gem_handle_to_libdrm_bo (cmd_data->bufmgr, fd,"" , buf->handle); +igt_assert (dst); + + src_buf.bo = src; + src_buf.stride = tmp.stride; + src_buf.tiling =I915_TILING_NONE ; + src_buf.size = tmp.size; + dst_buf.bo = dst; + dst_buf.stride = buf->stride; + dst_buf.tiling = tiling; + dst_buf.size = buf->size; + + batch =intel_batchbuffer_alloc (cmd_data->bufmgr, devid); +igt_assert (batch); + +rendercopy (batch, cmd_data->context, &src_buf,0 ,0 , rect->w, rect->h, + &dst_buf, rect->x, rect->y); + +gem_sync (fd, buf->handle); +intel_batchbuffer_free (batch); +gem_close (fd, tmp.handle); +} + +/** +* igt_draw_rect: +* @fd: the DRM file descriptor +* @bufmgr: the libdrm bufmgr, only required for IGT_DRAW_BLT and +* IGT_DRAW_RENDER +* @context: the context, can be NULL if you don't want to think about it +* @buf_handle: the handle of the buffer where you're going to draw to +* @buf_size: the size of the buffer +* @buf_stride: the stride of the buffer +* @method: method you're going to use to write to the buffer +* @rect_x: horizontal position on the buffer where your rectangle starts +* @rect_y: vertical position on the buffer where your rectangle starts +* @rect_w: width of the rectangle +* @rect_h: height of the rectangle +* @color: color of the rectangle +* +* This function draws a colored rectangle on the destination buffer, allowing +* you to specify the method used to draw the rectangle. We assume 32 bit pixels +* with 8 bits per color. +*/ +void igt_draw_rect (int fd,drm_intel_bufmgr *bufmgr,drm_intel_context *context, +uint32_t buf_handle,uint32_t buf_size,uint32_t buf_stride, +enum igt_draw_method method,int rect_x,int rect_y, +int rect_w,int rect_h,uint32_t color) +{ +struct cmd_data cmd_data = { + .bufmgr = bufmgr, + .context = context, + }; +struct buf_data buf = { + .handle = buf_handle, + .size = buf_size, + .stride = buf_stride, + }; +struct rect rect = { + .x = rect_x, + .y = rect_y, + .w = rect_w, + .h = rect_h, + }; + +switch (method) { +case IGT_DRAW_MMAP_CPU : +draw_rect_mmap_cpu (fd, &buf, &rect, color); +break ; +case IGT_DRAW_MMAP_GTT : +draw_rect_mmap_gtt (fd, &buf, &rect, color); +break ; +case IGT_DRAW_PWRITE : +draw_rect_pwrite (fd, &buf, &rect, color); +break ; +case IGT_DRAW_BLT : +draw_rect_blt (fd, &cmd_data, &buf, &rect, color); +break ; +case IGT_DRAW_RENDER : +draw_rect_render (fd, &cmd_data, &buf, &rect, color); +break ; +default : +igt_assert (false); +break ; + } +} + +/** +* igt_draw_rect_fb: +* +* This is exactly the same as igt_draw_rect, but you can pass an igt_fb instead +* of manually providing its details. See igt_draw_rect. +*/ +void igt_draw_rect_fb (int fd,drm_intel_bufmgr *bufmgr, +drm_intel_context *context,struct igt_fb *fb, +enum igt_draw_method method,int rect_x,int rect_y, +int rect_w,int rect_h,uint32_t color) +{ +igt_draw_rect (fd, bufmgr, context, fb->gem_handle, fb->size, fb->stride, + method, rect_x, rect_y, rect_w, rect_h, color); +} + +/** +* igt_draw_fill_fb: +* @fd: the DRM file descriptor +* @fb: the FB that is going to be filled +* @color: the color you're going to paint it +* +* This function just paints an igt_fb using the provided color. It assumes 32 +* bit pixels with 8 bit colors. +*/ +void igt_draw_fill_fb (int fd,struct igt_fb *fb,uint32_t color) +{ +igt_draw_rect_fb (fd,NULL ,NULL , fb,IGT_DRAW_MMAP_GTT , +0 ,0 , fb->width, fb->height, color); +}lib/igt_draw.h new file +20
-0@@ -0,0 +1,54 @@ +/* +* Copyright © 2015 Intel Corporation +* +* 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 (including the next +* paragraph) 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
lib/igt_draw.h line 30
Quoted 10 lines
lib/igt_draw.h new file +10
-0+* IN THE SOFTWARE. +* +*/ + +#ifndef __IGT_DRAW_H__ +#define __IGT_DRAW_H__ + +#include <intel_bufmgr.h> +#include "igt_fb.h" +
gtkdoc for this enum would be nice too I think.
Quoted 146 lines
lib/igt_draw.h new file +24
-0+enum igt_draw_method { +IGT_DRAW_MMAP_CPU , +IGT_DRAW_MMAP_GTT , +IGT_DRAW_PWRITE , +IGT_DRAW_BLT , +IGT_DRAW_RENDER , +IGT_DRAW_METHOD_COUNT , +}; + +const char *igt_draw_get_method_name (enum igt_draw_method method); + +void igt_draw_rect (int fd,drm_intel_bufmgr *bufmgr,drm_intel_context *context, +uint32_t buf_handle,uint32_t buf_size,uint32_t buf_stride, +enum igt_draw_method method,int rect_x,int rect_y, +int rect_w,int rect_h,uint32_t color); + +void igt_draw_rect_fb (int fd,drm_intel_bufmgr *bufmgr, +drm_intel_context *context,struct igt_fb *fb, +enum igt_draw_method method,int rect_x,int rect_y, +int rect_w,int rect_h,uint32_t color); + +void igt_draw_fill_fb (int fd,struct igt_fb *fb,uint32_t color); + +#endif /* __IGT_DRAW_H__ */ lib/tests/.gitignore +1
-0@@ -1,4 +1,5 @@ # Please keep sorted alphabetically +igt_draw igt_fork_helper igt_invalid_subtest_name igt_list_onlylib/tests/Makefile.sources +1
-0@@ -1,4 +1,5 @@ check_PROGRAMS = \ + igt_draw \ igt_no_exit \ igt_no_exit_list_only \ igt_fork_helper \lib/tests/igt_draw.c new file +96
-0@@ -0,0 +1,247 @@ +/* +* Copyright © 2015 Intel Corporation +* +* 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 (including the next +* paragraph) 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. +* +*/ + +/* This program tests whether the igt_draw library actually works. */ + +#include "drmtest.h" +#include "igt_aux.h" +#include "igt_draw.h" +#include "igt_debugfs.h" +#include "igt_fb.h" +#include "igt_kms.h" + +#define MAX_CONNECTORS 32 + +struct modeset_params { +uint32_t crtc_id; +uint32_t connector_id; +drmModeModeInfoPtr mode; +}; + +int drm_fd; +drmModeResPtr drm_res; +drmModeConnectorPtr drm_connectors[MAX_CONNECTORS ]; +drm_intel_bufmgr *bufmgr; +igt_pipe_crc_t *pipe_crc; + +bool has_method_base_crc = false; +igt_crc_t method_base_crc; + +struct modeset_params ms; + +static void find_modeset_params (void ) +{ +int i; +uint32_t connector_id =0 , crtc_id; +drmModeModeInfoPtr mode =NULL ; + +for (i =0 ; i < drm_res->count_connectors; i++) { +drmModeConnectorPtr c = drm_connectors[i]; + +if (c->count_modes) { + connector_id = c->connector_id; + mode = &c->modes[0 ]; +break ; + } + } +igt_require (connector_id); + + crtc_id = drm_res->crtcs[0 ]; +igt_assert (crtc_id); +igt_assert (mode); + + ms.connector_id = connector_id; + ms.crtc_id = crtc_id; + ms.mode = mode; + +} + +static void get_method_crc (enum igt_draw_method method,uint64_t tiling, +igt_crc_t *crc) +{ +struct igt_fb fb; +int rc; + +igt_create_fb (drm_fd, ms.mode->hdisplay, ms.mode->vdisplay, +DRM_FORMAT_XRGB8888 , tiling, &fb); +igt_draw_rect_fb (drm_fd, bufmgr,NULL , &fb, method, +0 ,0 , fb.width, fb.height,0xFF ); + +igt_draw_rect_fb (drm_fd, bufmgr,NULL , &fb, method, + fb.width /4 , fb.height /4 , + fb.width /2 , fb.height /2 ,0xFF00 ); +igt_draw_rect_fb (drm_fd, bufmgr,NULL , &fb, method, + fb.width /8 , fb.height /8 , + fb.width /4 , fb.height /4 ,0xFF0000 );
lib/tests/igt_draw.c line 106
Quoted 10 lines
lib/tests/igt_draw.c new file +10
-0+igt_draw_rect_fb (drm_fd, bufmgr,NULL , &fb, method, + fb.width /2 , fb.height /2 , + fb.width /3 , fb.height /3 ,0xFF00FF ); + + rc =drmModeSetCrtc (drm_fd, ms.crtc_id, fb.fb_id,0 ,0 , + &ms.connector_id,1 , ms.mode); +igt_assert (rc ==0 ); + +igt_debug_wait_for_keypress ("crc" ); +igt_pipe_crc_collect_crc (pipe_crc, crc);
Should we just move this igt_debug_wait_for_keypress into igt_pipe_crc_collect_crc?
Quoted 148 lines
lib/tests/igt_draw.c new file +141
-0+ +kmstest_unset_all_crtcs (drm_fd, drm_res); +igt_remove_fb (drm_fd, &fb); +} + +static void draw_method_subtest (enum igt_draw_method method,uint64_t tiling) +{ +igt_crc_t crc; + +kmstest_unset_all_crtcs (drm_fd, drm_res); + +find_modeset_params (); + +/* Use IGT_DRAW_MMAP_GTT on an untiled buffer as the parameter for +* comparison. Cache the value so we don't recompute it for every single +* subtest. */ +if (!has_method_base_crc) { +get_method_crc (IGT_DRAW_MMAP_GTT ,LOCAL_DRM_FORMAT_MOD_NONE , + &method_base_crc); + has_method_base_crc = true; + } + +get_method_crc (method, tiling, &crc); +igt_assert_crc_equal (&crc, &method_base_crc); +} + +static void get_fill_crc (uint64_t tiling,igt_crc_t *crc) +{ +struct igt_fb fb; +int rc; + +igt_create_fb (drm_fd, ms.mode->hdisplay, ms.mode->vdisplay, +DRM_FORMAT_XRGB8888 , tiling, &fb); + +igt_draw_fill_fb (drm_fd, &fb,0xFF ); + + rc =drmModeSetCrtc (drm_fd, ms.crtc_id, fb.fb_id,0 ,0 , + &ms.connector_id,1 , ms.mode); +igt_assert (rc ==0 ); + +igt_debug_wait_for_keypress ("crc" ); +igt_pipe_crc_collect_crc (pipe_crc, crc); + +kmstest_unset_all_crtcs (drm_fd, drm_res); +igt_remove_fb (drm_fd, &fb); +} + +static void fill_fb_subtest (void ) +{ +int rc; +struct igt_fb fb; +igt_crc_t base_crc, crc; + +kmstest_unset_all_crtcs (drm_fd, drm_res); + +find_modeset_params (); + +igt_create_fb (drm_fd, ms.mode->hdisplay, ms.mode->vdisplay, +DRM_FORMAT_XRGB8888 ,LOCAL_DRM_FORMAT_MOD_NONE , &fb); + +igt_draw_rect_fb (drm_fd, bufmgr,NULL , &fb,IGT_DRAW_MMAP_GTT , +0 ,0 , fb.width, fb.height,0xFF ); + + rc =drmModeSetCrtc (drm_fd, ms.crtc_id, fb.fb_id,0 ,0 , + &ms.connector_id,1 , ms.mode); +igt_assert (rc ==0 ); + +igt_debug_wait_for_keypress ("crc" ); +igt_pipe_crc_collect_crc (pipe_crc, &base_crc); + +get_fill_crc (LOCAL_DRM_FORMAT_MOD_NONE , &crc); +igt_assert_crc_equal (&crc, &base_crc); + +get_fill_crc (LOCAL_I915_FORMAT_MOD_X_TILED , &crc); +igt_assert_crc_equal (&crc, &base_crc); + +kmstest_unset_all_crtcs (drm_fd, drm_res); +igt_remove_fb (drm_fd, &fb); +} + +static void setup_environment (void ) +{ +int i; + + drm_fd =drm_open_any_master (); +igt_require (drm_fd >=0 ); + + drm_res =drmModeGetResources (drm_fd); +igt_assert (drm_res->count_connectors <=MAX_CONNECTORS ); + +for (i =0 ; i < drm_res->count_connectors; i++) + drm_connectors[i] =drmModeGetConnector (drm_fd, + drm_res->connectors[i]); + +kmstest_set_vt_graphics_mode (); + + bufmgr =drm_intel_bufmgr_gem_init (drm_fd,4096 ); +igt_assert (bufmgr); +drm_intel_bufmgr_gem_enable_reuse (bufmgr); + + pipe_crc =igt_pipe_crc_new (0 ,INTEL_PIPE_CRC_SOURCE_AUTO ); +} + +static void teardown_environment (void ) +{ +int i; + +igt_pipe_crc_free (pipe_crc); + +drm_intel_bufmgr_destroy (bufmgr); + +for (i =0 ; i < drm_res->count_connectors; i++) +drmModeFreeConnector (drm_connectors[i]); + +drmModeFreeResources (drm_res); +close (drm_fd); +} + +igt_main +{ +enum igt_draw_method method; + +igt_fixture +setup_environment (); + +for (method =0 ; method <IGT_DRAW_METHOD_COUNT ; method++) { +igt_subtest_f ("draw-method-%s-untiled" , + igt_draw_get_method_name(method)) +draw_method_subtest (method,LOCAL_DRM_FORMAT_MOD_NONE ); +igt_subtest_f ("draw-method-%s-tiled" , + igt_draw_get_method_name(method)) +draw_method_subtest (method, +LOCAL_I915_FORMAT_MOD_X_TILED ); + } + + igt_subtest("fill-fb") +fill_fb_subtest (); + +igt_fixture +teardown_environment (); +}Signature · 6 lines
2.1.4 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 7 lines
Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 7/7] lib: add igt_draw
2015-03-26 7:19 GMT-03:00 Daniel Vetter <[email protected]>:
Quoted 15 lines · Paulo Zanoni
Quoted 8 lines
From: Paulo Zanoni <[email protected]>
For all those IGT tests that need an easy way to draw rectangles on buffers using different methods. Current planned users: FBC and PSR CRC tests.
There is also a
lib/tests/igt_drawprogram to check if the library is sane.We need to move that to tests/igt_draw. The testcase in
lib/tests/*get run with make check, which must be possible as non-root on a non-intel (build) machine. If you need an gpu to run your test it must be in tests/* as a normal igt kernel test.
Quoted 4 lines
Wrt the library itself I'm unsure about the explicit tiling/swizzling. Your current code only works on gen5-8 and maintaining a full-blown swizzle/tiling library is real work, and means some of the tests can't be converted to this.
This would just be a problem for the tests that use it, and no test is using it yet. This is just for the cases where you want to use the CPU to write into tiled buffers.
If we start using this in a test, then we need to properly test all the affected platforms. I have some local FBC tests that use it - which I was going to submit after getting feedback on this lib -, and I don't think we'll end needing to run these tests on the older platforms.
Quoted 3 lines
We do have all the tiling modes encoded in the tiling
tests though, so if you have a lot of time it might be useful to extract tiling helpers into the igt library which work on all generations.
Can you please be more precise here? Where exactly should I look?
Quoted 4 lines
I think we should at least have a fallback mode which allows us to fill an entire buffer completely (i.e. not just the hxw area) and treat it as untiled.
That is not the goal of the library. Still, if we ever need this function, it would be easy to add.
Quoted 2 lines
More comments below.
More below too :)
Quoted 340 lines
-Daniel
Quoted 338 lines
Signed-off-by Paulo Zanoni <[email protected]>--- lib/Makefile.sources | 2 + lib/igt_draw.c | 467 +++++++++++++++++++++++++++++++++++++++++++++ lib/igt_draw.h | 54 ++++++ lib/tests/.gitignore | 1 + lib/tests/Makefile.sources | 1 + lib/tests/igt_draw.c | 247 ++++++++++++++++++++++++ 6 files changed, 772 insertions(+) create mode 100644 lib/igt_draw.c create mode 100644 lib/igt_draw.h create mode 100644 lib/tests/igt_draw.clib/Makefile.sources +2
-0@@ -52,6 +52,8 @@ libintel_tools_la_SOURCES = \ igt_fb.h \ igt_core.c \ igt_core.h \ + igt_draw.c \ + igt_draw.h \ $(NULL) .PHONY: version.h.tmplib/igt_draw.c new file +305
-0@@ -0,0 +1,467 @@ +/* +* Copyright © 2015 Intel Corporation +* +* 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 (including the next +* paragraph) 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 <sys/mman.h> + +#include "igt_draw.h" + +#include "drmtest.h" +#include "intel_chipset.h" +#include "igt_core.h" +#include "igt_fb.h" +#include "ioctl_wrappers.h" + +/** +* SECTION:igt_draw +* @short_description: drawing helpers for tests +* @title: i-g-t draw +* @include: igt_draw.h +* +* This library contains some functions for drawing rectangles on buffers using +* the many different drawing methods we have. It also contains some wrappers +* that make the process easier if you have the abstract objects in hand. +* +* All functions assume the buffers are in the XRGB 8:8:8 format. +* +*/ + +/* Some internal data structures to avoid having to pass tons of parameters +* around everything. */ +struct cmd_data { +drm_intel_bufmgr *bufmgr; +drm_intel_context *context; +}; + +struct buf_data { +uint32_t handle; +uint32_t size; +uint32_t stride; +}; + +struct rect { +int x; +int y; +int w; +int h; +}; + +const char *igt_draw_get_method_name (enum igt_draw_method method) +{ +switch (method) { +case IGT_DRAW_MMAP_CPU : +return "mmap-cpu" ; +case IGT_DRAW_MMAP_GTT : +return "mmap-gtt" ; +case IGT_DRAW_PWRITE : +return "pwrite" ; +case IGT_DRAW_BLT : +return "blt" ; +case IGT_DRAW_RENDER : +return "render" ; +default : +igt_assert (false); + } +} + +static int swizzle_addr (int addr,int swizzle) +{ +int bit6; + +if (swizzle ==I915_BIT_6_SWIZZLE_9_10 ) { + bit6 = ((addr >>6 ) &1 ) ^ ((addr >>9 ) &1 ) ^ + ((addr >>10 ) &1 ); + addr &= ~(1 <<6 ); + addr |= (bit6 <<6 ); + } + +return addr; +} + +/* It's all in "pixel coordinates", so make sure you multiply/divide by the bpp +* if you need to. */ +static int linear_x_y_to_tiled_pos (int x,int y,uint32_t stride,int swizzle) +{ +int x_tile_size, y_tile_size; +int x_tile_n, y_tile_n, x_tile_off, y_tile_off; +int line_size, tile_size; +int tile_n, tile_off; +int tiled_pos, tiles_per_line; +int bpp; + + line_size = stride; + x_tile_size =512 ; + y_tile_size =8 ; + tile_size = x_tile_size * y_tile_size; + tiles_per_line = line_size / x_tile_size; + bpp =sizeof (uint32_t ); + + y_tile_n = y / y_tile_size; + y_tile_off = y % y_tile_size; + + x_tile_n = (x * bpp) / x_tile_size; + x_tile_off = (x * bpp) % x_tile_size; + + tile_n = y_tile_n * tiles_per_line + x_tile_n; + tile_off = y_tile_off * x_tile_size + x_tile_off; + tiled_pos = tile_n * tile_size + tile_off; + + tiled_pos =swizzle_addr (tiled_pos, swizzle); + +return tiled_pos / bpp; +} + +/* It's all in "pixel coordinates", so make sure you multiply/divide by the bpp +* if you need to. */ +static void tiled_pos_to_x_y_linear (int tiled_pos,uint32_t stride, +int swizzle,int *x,int *y) +{ +int tile_n, tile_off, tiles_per_line, line_size; +int x_tile_off, y_tile_off; +int x_tile_n, y_tile_n; +int x_tile_size, y_tile_size, tile_size; +int bpp; + + tiled_pos =swizzle_addr (tiled_pos, swizzle); + + line_size = stride; + x_tile_size =512 ; + y_tile_size =8 ; + tile_size = x_tile_size * y_tile_size; + tiles_per_line = line_size / x_tile_size; + bpp =sizeof (uint32_t ); + + tile_n = tiled_pos / tile_size; + tile_off = tiled_pos % tile_size; + + y_tile_off = tile_off / x_tile_size; + x_tile_off = tile_off % x_tile_size; + + x_tile_n = tile_n % tiles_per_line; + y_tile_n = tile_n / tiles_per_line; + + *x = (x_tile_n * x_tile_size + x_tile_off) / bpp; + *y = y_tile_n * y_tile_size + y_tile_off; +} + +static void draw_rect_mmap_cpu (int fd,struct buf_data *buf,struct rect *rect, +uint32_t color) +{ +uint32_t *ptr; +int x, y, pos; +uint32_t tiling, swizzle; + +gem_set_domain (fd, buf->handle,I915_GEM_DOMAIN_CPU , +I915_GEM_DOMAIN_CPU ); +gem_get_tiling (fd, buf->handle, &tiling, &swizzle); + + ptr =gem_mmap__cpu (fd, buf->handle,0 , buf->size,0 ); +igt_assert (ptr); + +for (y = rect->y; y < rect->y + rect->h; y++) { +for (x = rect->x; x < rect->x + rect->w; x++) { +if (tiling) + pos =linear_x_y_to_tiled_pos (x, y, buf->stride, + swizzle); +else + pos = (y * buf->stride /sizeof (uint32_t )) + x; + ptr[pos] = color; + } + } + +gem_sw_finish (fd, buf->handle); + +igt_assert (munmap (ptr, buf->size) ==0 ); +} + +static void draw_rect_mmap_gtt (int fd,struct buf_data *buf,struct rect *rect, +uint32_t color) +{ +uint32_t *ptr; +int x, y; + + ptr =gem_mmap__gtt (fd, buf->handle, buf->size, +PROT_READ |PROT_WRITE ); +igt_assert (ptr); + +for (y = rect->y; y < rect->y + rect->h; y++) { +int line_begin = y * buf->stride /sizeof (uint32_t ); +for (x = rect->x; x < rect->x + rect->w; x++) + ptr[line_begin + x] = color; + } + +igt_assert (munmap (ptr, buf->size) ==0 ); +} + +static void draw_rect_pwrite_untiled (int fd,struct buf_data *buf, +struct rect *rect,uint32_t color) +{ +uint32_t tmp[rect->w]; +int i, y, offset, bpp; + + bpp =sizeof (uint32_t ); + +for (i =0 ; i < rect->w; i++) + tmp[i] = color; + +for (y = rect->y; y < rect->y + rect->h; y++) { + offset = (y * buf->stride) + (rect->x * bpp); +gem_write (fd, buf->handle, offset, tmp, rect->w * bpp); + } +} + +static void draw_rect_pwrite_tiled (int fd,struct buf_data *buf, +struct rect *rect,uint32_t color, +uint32_t swizzle) +{ +int i; +int tiled_pos, bpp, x, y; +uint32_t tmp[1024 ]; +int tmp_used =0 , tmp_size =ARRAY_SIZE (tmp); +bool flush_tmp = false; +int tmp_start_pos =0 ; + + bpp =sizeof (uint32_t ); + +/* Instead of doing one pwrite per pixel, we try to group the maximum +* amount of consecutive pixels we can in a single pwrite: that's why we +* use the "tmp" variables. */ +for (i =0 ; i < tmp_size; i++) + tmp[i] = color; + +for (tiled_pos =0 ; tiled_pos < buf->size; tiled_pos += bpp) { +tiled_pos_to_x_y_linear (tiled_pos, buf->stride, swizzle, &x, &y); + +if (x >= rect->x && x < rect->x + rect->w && + y >= rect->y && y < rect->y + rect->h) { +if (tmp_used ==0 ) + tmp_start_pos = tiled_pos; + tmp_used++; + }else { + flush_tmp = true; + } + +if (tmp_used == tmp_size || (flush_tmp && tmp_used >0 )) { +gem_write (fd, buf->handle, tmp_start_pos, tmp, + tmp_used * bpp); + flush_tmp = false; + tmp_used =0 ; + } + } +} + +static void draw_rect_pwrite (int fd,struct buf_data *buf, +struct rect *rect,uint32_t color) +{ +uint32_t tiling, swizzle; + +gem_get_tiling (fd, buf->handle, &tiling, &swizzle); + +if (tiling) +draw_rect_pwrite_tiled (fd, buf, rect, color, swizzle); +else +draw_rect_pwrite_untiled (fd, buf, rect, color); +} + +static void draw_rect_blt (int fd,struct cmd_data *cmd_data, +struct buf_data *buf,struct rect *rect, +uint32_t color) +{ +drm_intel_bo *dst; +struct intel_batchbuffer *batch; +int blt_cmd_len, blt_cmd_tiling; +uint32_t devid =intel_get_drm_devid (fd); +int gen =intel_gen (devid); +uint32_t tiling, swizzle; +int pitch; + +gem_get_tiling (fd, buf->handle, &tiling, &swizzle); + + dst =gem_handle_to_libdrm_bo (cmd_data->bufmgr, fd,"" , buf->handle); +igt_assert (dst); + + batch =intel_batchbuffer_alloc (cmd_data->bufmgr, devid); +igt_assert (batch); +
Quoted 9 lines
lib/igt_draw.c line 310
Quoted 5 lines
lib/igt_draw.c new file +5
-0+ blt_cmd_len = (gen >=8 ) ?0x5 :0x4 ; + blt_cmd_tiling = (tiling) ?XY_COLOR_BLT_TILED :0 ; + pitch = (tiling) ? buf->stride /4 : buf->stride; + +BEGIN_BATCH (6 ,1 );This breaks on gen8 because there the relocations are 2 dwords. You need to use the magic macros for that.
Please read the code again. I actually developed and tested everything on gen8 :)
Quoted 187 lines
Quoted 187 lines
lib/igt_draw.c new file +157
-0+OUT_BATCH (XY_COLOR_BLT_CMD_NOLEN |XY_COLOR_BLT_WRITE_ALPHA | +XY_COLOR_BLT_WRITE_RGB | blt_cmd_tiling | blt_cmd_len); +OUT_BATCH ((3 <<24 ) | (0xF0 <<16 ) | pitch); +OUT_BATCH ((rect->y <<16 ) | rect->x); +OUT_BATCH (((rect->y + rect->h) <<16 ) | (rect->x + rect->w)); +if (tiling) +OUT_RELOC_FENCED (dst,0 ,I915_GEM_DOMAIN_RENDER ,0 ); +else +OUT_RELOC (dst,0 ,I915_GEM_DOMAIN_RENDER ,0 ); +OUT_BATCH (color); +ADVANCE_BATCH (); + +intel_batchbuffer_flush (batch); +gem_sync (fd, buf->handle); +intel_batchbuffer_free (batch); +} + +static void draw_rect_render (int fd,struct cmd_data *cmd_data, +struct buf_data *buf,struct rect *rect, +uint32_t color) +{ +drm_intel_bo *src, *dst; +uint32_t devid =intel_get_drm_devid (fd); +igt_render_copyfunc_t rendercopy =igt_get_render_copyfunc (devid); +struct igt_buf src_buf, dst_buf; +struct intel_batchbuffer *batch; +uint32_t tiling, swizzle; +struct buf_data tmp; + +igt_skip_on (!rendercopy); + +gem_get_tiling (fd, buf->handle, &tiling, &swizzle); + +/* We create a temporary buffer and copy from it using rendercopy. */ + tmp.size = rect->w * rect->h *sizeof (uint32_t ); + tmp.handle =gem_create (fd, tmp.size); + tmp.stride = rect->w *sizeof (uint32_t ); +draw_rect_mmap_cpu (fd, &tmp, &(struct rect ){0 ,0 , rect->w, rect->h}, + color); + + src =gem_handle_to_libdrm_bo (cmd_data->bufmgr, fd,"" , tmp.handle); +igt_assert (src); + dst =gem_handle_to_libdrm_bo (cmd_data->bufmgr, fd,"" , buf->handle); +igt_assert (dst); + + src_buf.bo = src; + src_buf.stride = tmp.stride; + src_buf.tiling =I915_TILING_NONE ; + src_buf.size = tmp.size; + dst_buf.bo = dst; + dst_buf.stride = buf->stride; + dst_buf.tiling = tiling; + dst_buf.size = buf->size; + + batch =intel_batchbuffer_alloc (cmd_data->bufmgr, devid); +igt_assert (batch); + +rendercopy (batch, cmd_data->context, &src_buf,0 ,0 , rect->w, rect->h, + &dst_buf, rect->x, rect->y); + +gem_sync (fd, buf->handle); +intel_batchbuffer_free (batch); +gem_close (fd, tmp.handle); +} + +/** +* igt_draw_rect: +* @fd: the DRM file descriptor +* @bufmgr: the libdrm bufmgr, only required for IGT_DRAW_BLT and +* IGT_DRAW_RENDER +* @context: the context, can be NULL if you don't want to think about it +* @buf_handle: the handle of the buffer where you're going to draw to +* @buf_size: the size of the buffer +* @buf_stride: the stride of the buffer +* @method: method you're going to use to write to the buffer +* @rect_x: horizontal position on the buffer where your rectangle starts +* @rect_y: vertical position on the buffer where your rectangle starts +* @rect_w: width of the rectangle +* @rect_h: height of the rectangle +* @color: color of the rectangle +* +* This function draws a colored rectangle on the destination buffer, allowing +* you to specify the method used to draw the rectangle. We assume 32 bit pixels +* with 8 bits per color. +*/ +void igt_draw_rect (int fd,drm_intel_bufmgr *bufmgr,drm_intel_context *context, +uint32_t buf_handle,uint32_t buf_size,uint32_t buf_stride, +enum igt_draw_method method,int rect_x,int rect_y, +int rect_w,int rect_h,uint32_t color) +{ +struct cmd_data cmd_data = { + .bufmgr = bufmgr, + .context = context, + }; +struct buf_data buf = { + .handle = buf_handle, + .size = buf_size, + .stride = buf_stride, + }; +struct rect rect = { + .x = rect_x, + .y = rect_y, + .w = rect_w, + .h = rect_h, + }; + +switch (method) { +case IGT_DRAW_MMAP_CPU : +draw_rect_mmap_cpu (fd, &buf, &rect, color); +break ; +case IGT_DRAW_MMAP_GTT : +draw_rect_mmap_gtt (fd, &buf, &rect, color); +break ; +case IGT_DRAW_PWRITE : +draw_rect_pwrite (fd, &buf, &rect, color); +break ; +case IGT_DRAW_BLT : +draw_rect_blt (fd, &cmd_data, &buf, &rect, color); +break ; +case IGT_DRAW_RENDER : +draw_rect_render (fd, &cmd_data, &buf, &rect, color); +break ; +default : +igt_assert (false); +break ; + } +} + +/** +* igt_draw_rect_fb: +* +* This is exactly the same as igt_draw_rect, but you can pass an igt_fb instead +* of manually providing its details. See igt_draw_rect. +*/ +void igt_draw_rect_fb (int fd,drm_intel_bufmgr *bufmgr, +drm_intel_context *context,struct igt_fb *fb, +enum igt_draw_method method,int rect_x,int rect_y, +int rect_w,int rect_h,uint32_t color) +{ +igt_draw_rect (fd, bufmgr, context, fb->gem_handle, fb->size, fb->stride, + method, rect_x, rect_y, rect_w, rect_h, color); +} + +/** +* igt_draw_fill_fb: +* @fd: the DRM file descriptor +* @fb: the FB that is going to be filled +* @color: the color you're going to paint it +* +* This function just paints an igt_fb using the provided color. It assumes 32 +* bit pixels with 8 bit colors. +*/ +void igt_draw_fill_fb (int fd,struct igt_fb *fb,uint32_t color) +{ +igt_draw_rect_fb (fd,NULL ,NULL , fb,IGT_DRAW_MMAP_GTT , +0 ,0 , fb->width, fb->height, color); +}lib/igt_draw.h new file +24
-0@@ -0,0 +1,54 @@ +/* +* Copyright © 2015 Intel Corporation +* +* 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 (including the next +* paragraph) 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. +* +*/ +
Quoted 8 lines
lib/igt_draw.h line 30
Quoted 6 lines
lib/igt_draw.h new file +6
-0+#ifndef __IGT_DRAW_H__ +#define __IGT_DRAW_H__ + +#include <intel_bufmgr.h> +#include "igt_fb.h" +gtkdoc for this enum would be nice too I think.
Ok.
Quoted 152 lines
Quoted 152 lines
lib/igt_draw.h new file +24
-0+enum igt_draw_method { +IGT_DRAW_MMAP_CPU , +IGT_DRAW_MMAP_GTT , +IGT_DRAW_PWRITE , +IGT_DRAW_BLT , +IGT_DRAW_RENDER , +IGT_DRAW_METHOD_COUNT , +}; + +const char *igt_draw_get_method_name (enum igt_draw_method method); + +void igt_draw_rect (int fd,drm_intel_bufmgr *bufmgr,drm_intel_context *context, +uint32_t buf_handle,uint32_t buf_size,uint32_t buf_stride, +enum igt_draw_method method,int rect_x,int rect_y, +int rect_w,int rect_h,uint32_t color); + +void igt_draw_rect_fb (int fd,drm_intel_bufmgr *bufmgr, +drm_intel_context *context,struct igt_fb *fb, +enum igt_draw_method method,int rect_x,int rect_y, +int rect_w,int rect_h,uint32_t color); + +void igt_draw_fill_fb (int fd,struct igt_fb *fb,uint32_t color); + +#endif /* __IGT_DRAW_H__ */ lib/tests/.gitignore +1
-0@@ -1,4 +1,5 @@ # Please keep sorted alphabetically +igt_draw igt_fork_helper igt_invalid_subtest_name igt_list_onlylib/tests/Makefile.sources +1
-0@@ -1,4 +1,5 @@ check_PROGRAMS = \ + igt_draw \ igt_no_exit \ igt_no_exit_list_only \ igt_fork_helper \lib/tests/igt_draw.c new file +101
-0@@ -0,0 +1,247 @@ +/* +* Copyright © 2015 Intel Corporation +* +* 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 (including the next +* paragraph) 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. +* +*/ + +/* This program tests whether the igt_draw library actually works. */ + +#include "drmtest.h" +#include "igt_aux.h" +#include "igt_draw.h" +#include "igt_debugfs.h" +#include "igt_fb.h" +#include "igt_kms.h" + +#define MAX_CONNECTORS 32 + +struct modeset_params { +uint32_t crtc_id; +uint32_t connector_id; +drmModeModeInfoPtr mode; +}; + +int drm_fd; +drmModeResPtr drm_res; +drmModeConnectorPtr drm_connectors[MAX_CONNECTORS ]; +drm_intel_bufmgr *bufmgr; +igt_pipe_crc_t *pipe_crc; + +bool has_method_base_crc = false; +igt_crc_t method_base_crc; + +struct modeset_params ms; + +static void find_modeset_params (void ) +{ +int i; +uint32_t connector_id =0 , crtc_id; +drmModeModeInfoPtr mode =NULL ; + +for (i =0 ; i < drm_res->count_connectors; i++) { +drmModeConnectorPtr c = drm_connectors[i]; + +if (c->count_modes) { + connector_id = c->connector_id; + mode = &c->modes[0 ]; +break ; + } + } +igt_require (connector_id); + + crtc_id = drm_res->crtcs[0 ]; +igt_assert (crtc_id); +igt_assert (mode); + + ms.connector_id = connector_id; + ms.crtc_id = crtc_id; + ms.mode = mode; + +} + +static void get_method_crc (enum igt_draw_method method,uint64_t tiling, +igt_crc_t *crc) +{ +struct igt_fb fb; +int rc; + +igt_create_fb (drm_fd, ms.mode->hdisplay, ms.mode->vdisplay, +DRM_FORMAT_XRGB8888 , tiling, &fb); +igt_draw_rect_fb (drm_fd, bufmgr,NULL , &fb, method, +0 ,0 , fb.width, fb.height,0xFF ); + +igt_draw_rect_fb (drm_fd, bufmgr,NULL , &fb, method, + fb.width /4 , fb.height /4 , + fb.width /2 , fb.height /2 ,0xFF00 ); +igt_draw_rect_fb (drm_fd, bufmgr,NULL , &fb, method, + fb.width /8 , fb.height /8 , + fb.width /4 , fb.height /4 ,0xFF0000 ); +igt_draw_rect_fb (drm_fd, bufmgr,NULL , &fb, method, + fb.width /2 , fb.height /2 , + fb.width /3 , fb.height /3 ,0xFF00FF ); + + rc = drmModeSetCrtc(drm_fd, ms.crtc_id, fb.fb_id, 0, 0,
Quoted 8 lines
lib/tests/igt_draw.c line 106
Quoted 5 lines
lib/tests/igt_draw.c new file +5
-0+ &ms.connector_id, 1, ms.mode); +igt_assert (rc ==0 ); + +igt_debug_wait_for_keypress ("crc" ); +igt_pipe_crc_collect_crc (pipe_crc, crc);Should we just move this
igt_debug_wait_for_keypressintoigt_pipe_crc_collect_crc?
I think I prefer to leave these on the programs because you can then opt-out of some cases such as when you're getting the reference CRCs. It doesn't hurt to just add these to the problems, but it can be annoying if the wait is on the lib and you don't want it.
Quoted 154 lines
Quoted 145 lines
lib/tests/igt_draw.c new file +141
-1+ +kmstest_unset_all_crtcs (drm_fd, drm_res); +igt_remove_fb (drm_fd, &fb); +} + +static void draw_method_subtest (enum igt_draw_method method,uint64_t tiling) +{ +igt_crc_t crc; + +kmstest_unset_all_crtcs (drm_fd, drm_res); + +find_modeset_params (); + +/* Use IGT_DRAW_MMAP_GTT on an untiled buffer as the parameter for +* comparison. Cache the value so we don't recompute it for every single +* subtest. */ +if (!has_method_base_crc) { +get_method_crc (IGT_DRAW_MMAP_GTT ,LOCAL_DRM_FORMAT_MOD_NONE , + &method_base_crc); + has_method_base_crc = true; + } + +get_method_crc (method, tiling, &crc); +igt_assert_crc_equal (&crc, &method_base_crc); +} + +static void get_fill_crc (uint64_t tiling,igt_crc_t *crc) +{ +struct igt_fb fb; +int rc; + +igt_create_fb (drm_fd, ms.mode->hdisplay, ms.mode->vdisplay, +DRM_FORMAT_XRGB8888 , tiling, &fb); + +igt_draw_fill_fb (drm_fd, &fb,0xFF ); + + rc =drmModeSetCrtc (drm_fd, ms.crtc_id, fb.fb_id,0 ,0 , + &ms.connector_id,1 , ms.mode); +igt_assert (rc ==0 ); + +igt_debug_wait_for_keypress ("crc" ); +igt_pipe_crc_collect_crc (pipe_crc, crc); + +kmstest_unset_all_crtcs (drm_fd, drm_res); +igt_remove_fb (drm_fd, &fb); +} + +static void fill_fb_subtest (void ) +{ +int rc; +struct igt_fb fb; +igt_crc_t base_crc, crc; + +kmstest_unset_all_crtcs (drm_fd, drm_res); + +find_modeset_params (); + +igt_create_fb (drm_fd, ms.mode->hdisplay, ms.mode->vdisplay, +DRM_FORMAT_XRGB8888 ,LOCAL_DRM_FORMAT_MOD_NONE , &fb); + +igt_draw_rect_fb (drm_fd, bufmgr,NULL , &fb,IGT_DRAW_MMAP_GTT , +0 ,0 , fb.width, fb.height,0xFF ); + + rc =drmModeSetCrtc (drm_fd, ms.crtc_id, fb.fb_id,0 ,0 , + &ms.connector_id,1 , ms.mode); +igt_assert (rc ==0 ); + +igt_debug_wait_for_keypress ("crc" ); +igt_pipe_crc_collect_crc (pipe_crc, &base_crc); + +get_fill_crc (LOCAL_DRM_FORMAT_MOD_NONE , &crc); +igt_assert_crc_equal (&crc, &base_crc); + +get_fill_crc (LOCAL_I915_FORMAT_MOD_X_TILED , &crc); +igt_assert_crc_equal (&crc, &base_crc); + +kmstest_unset_all_crtcs (drm_fd, drm_res); +igt_remove_fb (drm_fd, &fb); +} + +static void setup_environment (void ) +{ +int i; + + drm_fd =drm_open_any_master (); +igt_require (drm_fd >=0 ); + + drm_res =drmModeGetResources (drm_fd); +igt_assert (drm_res->count_connectors <=MAX_CONNECTORS ); + +for (i =0 ; i < drm_res->count_connectors; i++) + drm_connectors[i] =drmModeGetConnector (drm_fd, + drm_res->connectors[i]); + +kmstest_set_vt_graphics_mode (); + + bufmgr =drm_intel_bufmgr_gem_init (drm_fd,4096 ); +igt_assert (bufmgr); +drm_intel_bufmgr_gem_enable_reuse (bufmgr); + + pipe_crc =igt_pipe_crc_new (0 ,INTEL_PIPE_CRC_SOURCE_AUTO ); +} + +static void teardown_environment (void ) +{ +int i; + +igt_pipe_crc_free (pipe_crc); + +drm_intel_bufmgr_destroy (bufmgr); + +for (i =0 ; i < drm_res->count_connectors; i++) +drmModeFreeConnector (drm_connectors[i]); + +drmModeFreeResources (drm_res); +close (drm_fd); +} + +igt_main +{ +enum igt_draw_method method; + +igt_fixture +setup_environment (); + +for (method =0 ; method <IGT_DRAW_METHOD_COUNT ; method++) { +igt_subtest_f ("draw-method-%s-untiled" , + igt_draw_get_method_name(method)) +draw_method_subtest (method,LOCAL_DRM_FORMAT_MOD_NONE ); +igt_subtest_f ("draw-method-%s-tiled" , + igt_draw_get_method_name(method)) +draw_method_subtest (method, +LOCAL_I915_FORMAT_MOD_X_TILED ); + } + + igt_subtest("fill-fb") +fill_fb_subtest (); + +igt_fixture +teardown_environment (); +} --2.1.4
Quoted 4 lines
_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
Signature · 5 lines
Paulo Zanoni _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 7/7] lib: add igt_draw
Quoted 32 lines · Paulo Zanoni
2015-03-26 7:19 GMT-03:00 Daniel Vetter <[email protected]>:
Quoted 15 lines · Paulo Zanoni
Quoted 8 lines
From: Paulo Zanoni <[email protected]>
For all those IGT tests that need an easy way to draw rectangles on buffers using different methods. Current planned users: FBC and PSR CRC tests.
There is also a
lib/tests/igt_drawprogram to check if the library is sane.We need to move that to tests/igt_draw. The testcase in
lib/tests/*get run with make check, which must be possible as non-root on a non-intel (build) machine. If you need an gpu to run your test it must be in tests/* as a normal igt kernel test.Quoted 4 lines
Wrt the library itself I'm unsure about the explicit tiling/swizzling. Your current code only works on gen5-8 and maintaining a full-blown swizzle/tiling library is real work, and means some of the tests can't be converted to this.
This would just be a problem for the tests that use it, and no test is using it yet. This is just for the cases where you want to use the CPU to write into tiled buffers.
If we start using this in a test, then we need to properly test all the affected platforms. I have some local FBC tests that use it - which I was going to submit after getting feedback on this lib -, and I don't think we'll end needing to run these tests on the older platforms.
Quoted 5 lines
Quoted 3 lines
We do have all the tiling modes encoded in the tiling
tests though, so if you have a lot of time it might be useful to extract tiling helpers into the igt library which work on all generations.Can you please be more precise here? Where exactly should I look?
gem_tiled_pread has the full-blown tiling/swizzle logic for all platforms. This is the one test we have which should work everywhere.
My concern is that by implementing a library which doesn't support everywhere we havea bit a split in the testbase which might surprise people. Imo a library function should work everywhere. If you look at the code in there compared to yours there's just 2 things missing:
- Variable tile size/height.
- Some of the more crazy swizzle modes.
Also if we have a library which works everywhere we could extend it with the new fancy gen9+ tiling modes.
Quoted 6 lines
Quoted 3 lines
I think we should at least have a fallback mode which allows us to fill an entire buffer completely (i.e. not just the hxw area) and treat it as untiled.
That is not the goal of the library. Still, if we ever need this function, it would be easy to add.
That was just meant as a fallback for buffers where you don't support the exact tiling/swizzling mode.
Quoted 356 lines
Quoted 3 lines
More comments below.
More below too :)
Quoted 340 lines
-Daniel
Quoted 338 lines
Signed-off-by Paulo Zanoni <[email protected]>--- lib/Makefile.sources | 2 + lib/igt_draw.c | 467 +++++++++++++++++++++++++++++++++++++++++++++ lib/igt_draw.h | 54 ++++++ lib/tests/.gitignore | 1 + lib/tests/Makefile.sources | 1 + lib/tests/igt_draw.c | 247 ++++++++++++++++++++++++ 6 files changed, 772 insertions(+) create mode 100644 lib/igt_draw.c create mode 100644 lib/igt_draw.h create mode 100644 lib/tests/igt_draw.clib/Makefile.sources +2
-0@@ -52,6 +52,8 @@ libintel_tools_la_SOURCES = \ igt_fb.h \ igt_core.c \ igt_core.h \ + igt_draw.c \ + igt_draw.h \ $(NULL) .PHONY: version.h.tmplib/igt_draw.c new file +305
-0@@ -0,0 +1,467 @@ +/* +* Copyright © 2015 Intel Corporation +* +* 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 (including the next +* paragraph) 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 <sys/mman.h> + +#include "igt_draw.h" + +#include "drmtest.h" +#include "intel_chipset.h" +#include "igt_core.h" +#include "igt_fb.h" +#include "ioctl_wrappers.h" + +/** +* SECTION:igt_draw +* @short_description: drawing helpers for tests +* @title: i-g-t draw +* @include: igt_draw.h +* +* This library contains some functions for drawing rectangles on buffers using +* the many different drawing methods we have. It also contains some wrappers +* that make the process easier if you have the abstract objects in hand. +* +* All functions assume the buffers are in the XRGB 8:8:8 format. +* +*/ + +/* Some internal data structures to avoid having to pass tons of parameters +* around everything. */ +struct cmd_data { +drm_intel_bufmgr *bufmgr; +drm_intel_context *context; +}; + +struct buf_data { +uint32_t handle; +uint32_t size; +uint32_t stride; +}; + +struct rect { +int x; +int y; +int w; +int h; +}; + +const char *igt_draw_get_method_name (enum igt_draw_method method) +{ +switch (method) { +case IGT_DRAW_MMAP_CPU : +return "mmap-cpu" ; +case IGT_DRAW_MMAP_GTT : +return "mmap-gtt" ; +case IGT_DRAW_PWRITE : +return "pwrite" ; +case IGT_DRAW_BLT : +return "blt" ; +case IGT_DRAW_RENDER : +return "render" ; +default : +igt_assert (false); + } +} + +static int swizzle_addr (int addr,int swizzle) +{ +int bit6; + +if (swizzle ==I915_BIT_6_SWIZZLE_9_10 ) { + bit6 = ((addr >>6 ) &1 ) ^ ((addr >>9 ) &1 ) ^ + ((addr >>10 ) &1 ); + addr &= ~(1 <<6 ); + addr |= (bit6 <<6 ); + } + +return addr; +} + +/* It's all in "pixel coordinates", so make sure you multiply/divide by the bpp +* if you need to. */ +static int linear_x_y_to_tiled_pos (int x,int y,uint32_t stride,int swizzle) +{ +int x_tile_size, y_tile_size; +int x_tile_n, y_tile_n, x_tile_off, y_tile_off; +int line_size, tile_size; +int tile_n, tile_off; +int tiled_pos, tiles_per_line; +int bpp; + + line_size = stride; + x_tile_size =512 ; + y_tile_size =8 ; + tile_size = x_tile_size * y_tile_size; + tiles_per_line = line_size / x_tile_size; + bpp =sizeof (uint32_t ); + + y_tile_n = y / y_tile_size; + y_tile_off = y % y_tile_size; + + x_tile_n = (x * bpp) / x_tile_size; + x_tile_off = (x * bpp) % x_tile_size; + + tile_n = y_tile_n * tiles_per_line + x_tile_n; + tile_off = y_tile_off * x_tile_size + x_tile_off; + tiled_pos = tile_n * tile_size + tile_off; + + tiled_pos =swizzle_addr (tiled_pos, swizzle); + +return tiled_pos / bpp; +} + +/* It's all in "pixel coordinates", so make sure you multiply/divide by the bpp +* if you need to. */ +static void tiled_pos_to_x_y_linear (int tiled_pos,uint32_t stride, +int swizzle,int *x,int *y) +{ +int tile_n, tile_off, tiles_per_line, line_size; +int x_tile_off, y_tile_off; +int x_tile_n, y_tile_n; +int x_tile_size, y_tile_size, tile_size; +int bpp; + + tiled_pos =swizzle_addr (tiled_pos, swizzle); + + line_size = stride; + x_tile_size =512 ; + y_tile_size =8 ; + tile_size = x_tile_size * y_tile_size; + tiles_per_line = line_size / x_tile_size; + bpp =sizeof (uint32_t ); + + tile_n = tiled_pos / tile_size; + tile_off = tiled_pos % tile_size; + + y_tile_off = tile_off / x_tile_size; + x_tile_off = tile_off % x_tile_size; + + x_tile_n = tile_n % tiles_per_line; + y_tile_n = tile_n / tiles_per_line; + + *x = (x_tile_n * x_tile_size + x_tile_off) / bpp; + *y = y_tile_n * y_tile_size + y_tile_off; +} + +static void draw_rect_mmap_cpu (int fd,struct buf_data *buf,struct rect *rect, +uint32_t color) +{ +uint32_t *ptr; +int x, y, pos; +uint32_t tiling, swizzle; + +gem_set_domain (fd, buf->handle,I915_GEM_DOMAIN_CPU , +I915_GEM_DOMAIN_CPU ); +gem_get_tiling (fd, buf->handle, &tiling, &swizzle); + + ptr =gem_mmap__cpu (fd, buf->handle,0 , buf->size,0 ); +igt_assert (ptr); + +for (y = rect->y; y < rect->y + rect->h; y++) { +for (x = rect->x; x < rect->x + rect->w; x++) { +if (tiling) + pos =linear_x_y_to_tiled_pos (x, y, buf->stride, + swizzle); +else + pos = (y * buf->stride /sizeof (uint32_t )) + x; + ptr[pos] = color; + } + } + +gem_sw_finish (fd, buf->handle); + +igt_assert (munmap (ptr, buf->size) ==0 ); +} + +static void draw_rect_mmap_gtt (int fd,struct buf_data *buf,struct rect *rect, +uint32_t color) +{ +uint32_t *ptr; +int x, y; + + ptr =gem_mmap__gtt (fd, buf->handle, buf->size, +PROT_READ |PROT_WRITE ); +igt_assert (ptr); + +for (y = rect->y; y < rect->y + rect->h; y++) { +int line_begin = y * buf->stride /sizeof (uint32_t ); +for (x = rect->x; x < rect->x + rect->w; x++) + ptr[line_begin + x] = color; + } + +igt_assert (munmap (ptr, buf->size) ==0 ); +} + +static void draw_rect_pwrite_untiled (int fd,struct buf_data *buf, +struct rect *rect,uint32_t color) +{ +uint32_t tmp[rect->w]; +int i, y, offset, bpp; + + bpp =sizeof (uint32_t ); + +for (i =0 ; i < rect->w; i++) + tmp[i] = color; + +for (y = rect->y; y < rect->y + rect->h; y++) { + offset = (y * buf->stride) + (rect->x * bpp); +gem_write (fd, buf->handle, offset, tmp, rect->w * bpp); + } +} + +static void draw_rect_pwrite_tiled (int fd,struct buf_data *buf, +struct rect *rect,uint32_t color, +uint32_t swizzle) +{ +int i; +int tiled_pos, bpp, x, y; +uint32_t tmp[1024 ]; +int tmp_used =0 , tmp_size =ARRAY_SIZE (tmp); +bool flush_tmp = false; +int tmp_start_pos =0 ; + + bpp =sizeof (uint32_t ); + +/* Instead of doing one pwrite per pixel, we try to group the maximum +* amount of consecutive pixels we can in a single pwrite: that's why we +* use the "tmp" variables. */ +for (i =0 ; i < tmp_size; i++) + tmp[i] = color; + +for (tiled_pos =0 ; tiled_pos < buf->size; tiled_pos += bpp) { +tiled_pos_to_x_y_linear (tiled_pos, buf->stride, swizzle, &x, &y); + +if (x >= rect->x && x < rect->x + rect->w && + y >= rect->y && y < rect->y + rect->h) { +if (tmp_used ==0 ) + tmp_start_pos = tiled_pos; + tmp_used++; + }else { + flush_tmp = true; + } + +if (tmp_used == tmp_size || (flush_tmp && tmp_used >0 )) { +gem_write (fd, buf->handle, tmp_start_pos, tmp, + tmp_used * bpp); + flush_tmp = false; + tmp_used =0 ; + } + } +} + +static void draw_rect_pwrite (int fd,struct buf_data *buf, +struct rect *rect,uint32_t color) +{ +uint32_t tiling, swizzle; + +gem_get_tiling (fd, buf->handle, &tiling, &swizzle); + +if (tiling) +draw_rect_pwrite_tiled (fd, buf, rect, color, swizzle); +else +draw_rect_pwrite_untiled (fd, buf, rect, color); +} + +static void draw_rect_blt (int fd,struct cmd_data *cmd_data, +struct buf_data *buf,struct rect *rect, +uint32_t color) +{ +drm_intel_bo *dst; +struct intel_batchbuffer *batch; +int blt_cmd_len, blt_cmd_tiling; +uint32_t devid =intel_get_drm_devid (fd); +int gen =intel_gen (devid); +uint32_t tiling, swizzle; +int pitch; + +gem_get_tiling (fd, buf->handle, &tiling, &swizzle); + + dst =gem_handle_to_libdrm_bo (cmd_data->bufmgr, fd,"" , buf->handle); +igt_assert (dst); + + batch =intel_batchbuffer_alloc (cmd_data->bufmgr, devid); +igt_assert (batch); +Quoted 9 lines
lib/igt_draw.c line 310
Quoted 5 lines
lib/igt_draw.c new file +5
-0+ blt_cmd_len = (gen >=8 ) ?0x5 :0x4 ; + blt_cmd_tiling = (tiling) ?XY_COLOR_BLT_TILED :0 ; + pitch = (tiling) ? buf->stride /4 : buf->stride; + +BEGIN_BATCH (6 ,1 );This breaks on gen8 because there the relocations are 2 dwords. You need to use the magic macros for that.
Quoted 2 lines
Please read the code again. I actually developed and tested everything on gen8 :)
Oh right I missed that OUT_RELOC uses qwords on gen8+ automatically. I still think using the same logic as with all other blitter tests would be better since blitter cmd copypaste fail has been the bane of igt.
Quoted 7 lines
Quoted 7 lines
lib/igt_draw.c line 316
Quoted 7 lines
lib/igt_draw.c new file +6
-0+OUT_BATCH (XY_COLOR_BLT_CMD_NOLEN |XY_COLOR_BLT_WRITE_ALPHA | +XY_COLOR_BLT_WRITE_RGB | blt_cmd_tiling | blt_cmd_len); +OUT_BATCH ((3 <<24 ) | (0xF0 <<16 ) | pitch); +OUT_BATCH ((rect->y <<16 ) | rect->x); +OUT_BATCH (((rect->y + rect->h) <<16 ) | (rect->x + rect->w)); +if (tiling)
btw this isn't needed OUT_RELOC_FENCED works correctly for untiled buffers. It's actually required on gen2/3 for untiled buffers if you reuse buffers (which might be the case for a library function) since OUT_RELOC does _not_ remove a stale fence if there is one.
Quoted 354 lines
Quoted 181 lines
Quoted 181 lines
lib/igt_draw.c new file +151
-0+OUT_RELOC_FENCED (dst,0 ,I915_GEM_DOMAIN_RENDER ,0 ); + else + OUT_RELOC(dst, 0, I915_GEM_DOMAIN_RENDER, 0); + OUT_BATCH(color); +ADVANCE_BATCH (); + +intel_batchbuffer_flush (batch); +gem_sync (fd, buf->handle); +intel_batchbuffer_free (batch); +} + +static void draw_rect_render (int fd,struct cmd_data *cmd_data, +struct buf_data *buf,struct rect *rect, +uint32_t color) +{ +drm_intel_bo *src, *dst; +uint32_t devid =intel_get_drm_devid (fd); +igt_render_copyfunc_t rendercopy =igt_get_render_copyfunc (devid); +struct igt_buf src_buf, dst_buf; +struct intel_batchbuffer *batch; +uint32_t tiling, swizzle; +struct buf_data tmp; + +igt_skip_on (!rendercopy); + +gem_get_tiling (fd, buf->handle, &tiling, &swizzle); + +/* We create a temporary buffer and copy from it using rendercopy. */ + tmp.size = rect->w * rect->h *sizeof (uint32_t ); + tmp.handle =gem_create (fd, tmp.size); + tmp.stride = rect->w *sizeof (uint32_t ); +draw_rect_mmap_cpu (fd, &tmp, &(struct rect ){0 ,0 , rect->w, rect->h}, + color); + + src =gem_handle_to_libdrm_bo (cmd_data->bufmgr, fd,"" , tmp.handle); +igt_assert (src); + dst =gem_handle_to_libdrm_bo (cmd_data->bufmgr, fd,"" , buf->handle); +igt_assert (dst); + + src_buf.bo = src; + src_buf.stride = tmp.stride; + src_buf.tiling =I915_TILING_NONE ; + src_buf.size = tmp.size; + dst_buf.bo = dst; + dst_buf.stride = buf->stride; + dst_buf.tiling = tiling; + dst_buf.size = buf->size; + + batch =intel_batchbuffer_alloc (cmd_data->bufmgr, devid); +igt_assert (batch); + +rendercopy (batch, cmd_data->context, &src_buf,0 ,0 , rect->w, rect->h, + &dst_buf, rect->x, rect->y); + +gem_sync (fd, buf->handle); +intel_batchbuffer_free (batch); +gem_close (fd, tmp.handle); +} + +/** +* igt_draw_rect: +* @fd: the DRM file descriptor +* @bufmgr: the libdrm bufmgr, only required for IGT_DRAW_BLT and +* IGT_DRAW_RENDER +* @context: the context, can be NULL if you don't want to think about it +* @buf_handle: the handle of the buffer where you're going to draw to +* @buf_size: the size of the buffer +* @buf_stride: the stride of the buffer +* @method: method you're going to use to write to the buffer +* @rect_x: horizontal position on the buffer where your rectangle starts +* @rect_y: vertical position on the buffer where your rectangle starts +* @rect_w: width of the rectangle +* @rect_h: height of the rectangle +* @color: color of the rectangle +* +* This function draws a colored rectangle on the destination buffer, allowing +* you to specify the method used to draw the rectangle. We assume 32 bit pixels +* with 8 bits per color. +*/ +void igt_draw_rect (int fd,drm_intel_bufmgr *bufmgr,drm_intel_context *context, +uint32_t buf_handle,uint32_t buf_size,uint32_t buf_stride, +enum igt_draw_method method,int rect_x,int rect_y, +int rect_w,int rect_h,uint32_t color) +{ +struct cmd_data cmd_data = { + .bufmgr = bufmgr, + .context = context, + }; +struct buf_data buf = { + .handle = buf_handle, + .size = buf_size, + .stride = buf_stride, + }; +struct rect rect = { + .x = rect_x, + .y = rect_y, + .w = rect_w, + .h = rect_h, + }; + +switch (method) { +case IGT_DRAW_MMAP_CPU : +draw_rect_mmap_cpu (fd, &buf, &rect, color); +break ; +case IGT_DRAW_MMAP_GTT : +draw_rect_mmap_gtt (fd, &buf, &rect, color); +break ; +case IGT_DRAW_PWRITE : +draw_rect_pwrite (fd, &buf, &rect, color); +break ; +case IGT_DRAW_BLT : +draw_rect_blt (fd, &cmd_data, &buf, &rect, color); +break ; +case IGT_DRAW_RENDER : +draw_rect_render (fd, &cmd_data, &buf, &rect, color); +break ; +default : +igt_assert (false); +break ; + } +} + +/** +* igt_draw_rect_fb: +* +* This is exactly the same as igt_draw_rect, but you can pass an igt_fb instead +* of manually providing its details. See igt_draw_rect. +*/ +void igt_draw_rect_fb (int fd,drm_intel_bufmgr *bufmgr, +drm_intel_context *context,struct igt_fb *fb, +enum igt_draw_method method,int rect_x,int rect_y, +int rect_w,int rect_h,uint32_t color) +{ +igt_draw_rect (fd, bufmgr, context, fb->gem_handle, fb->size, fb->stride, + method, rect_x, rect_y, rect_w, rect_h, color); +} + +/** +* igt_draw_fill_fb: +* @fd: the DRM file descriptor +* @fb: the FB that is going to be filled +* @color: the color you're going to paint it +* +* This function just paints an igt_fb using the provided color. It assumes 32 +* bit pixels with 8 bit colors. +*/ +void igt_draw_fill_fb (int fd,struct igt_fb *fb,uint32_t color) +{ +igt_draw_rect_fb (fd,NULL ,NULL , fb,IGT_DRAW_MMAP_GTT , +0 ,0 , fb->width, fb->height, color); +}lib/igt_draw.h new file +24
-0@@ -0,0 +1,54 @@ +/* +* Copyright © 2015 Intel Corporation +* +* 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 (including the next +* paragraph) 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. +* +*/ +Quoted 8 lines
lib/igt_draw.h line 30
Quoted 6 lines
lib/igt_draw.h new file +6
-0+#ifndef __IGT_DRAW_H__ +#define __IGT_DRAW_H__ + +#include <intel_bufmgr.h> +#include "igt_fb.h" +gtkdoc for this enum would be nice too I think.
Ok.
Quoted 152 lines
Quoted 152 lines
lib/igt_draw.h new file +24
-0+enum igt_draw_method { +IGT_DRAW_MMAP_CPU , +IGT_DRAW_MMAP_GTT , +IGT_DRAW_PWRITE , +IGT_DRAW_BLT , +IGT_DRAW_RENDER , +IGT_DRAW_METHOD_COUNT , +}; + +const char *igt_draw_get_method_name (enum igt_draw_method method); + +void igt_draw_rect (int fd,drm_intel_bufmgr *bufmgr,drm_intel_context *context, +uint32_t buf_handle,uint32_t buf_size,uint32_t buf_stride, +enum igt_draw_method method,int rect_x,int rect_y, +int rect_w,int rect_h,uint32_t color); + +void igt_draw_rect_fb (int fd,drm_intel_bufmgr *bufmgr, +drm_intel_context *context,struct igt_fb *fb, +enum igt_draw_method method,int rect_x,int rect_y, +int rect_w,int rect_h,uint32_t color); + +void igt_draw_fill_fb (int fd,struct igt_fb *fb,uint32_t color); + +#endif /* __IGT_DRAW_H__ */ lib/tests/.gitignore +1
-0@@ -1,4 +1,5 @@ # Please keep sorted alphabetically +igt_draw igt_fork_helper igt_invalid_subtest_name igt_list_onlylib/tests/Makefile.sources +1
-0@@ -1,4 +1,5 @@ check_PROGRAMS = \ + igt_draw \ igt_no_exit \ igt_no_exit_list_only \ igt_fork_helper \lib/tests/igt_draw.c new file +101
-0@@ -0,0 +1,247 @@ +/* +* Copyright © 2015 Intel Corporation +* +* 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 (including the next +* paragraph) 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. +* +*/ + +/* This program tests whether the igt_draw library actually works. */ + +#include "drmtest.h" +#include "igt_aux.h" +#include "igt_draw.h" +#include "igt_debugfs.h" +#include "igt_fb.h" +#include "igt_kms.h" + +#define MAX_CONNECTORS 32 + +struct modeset_params { +uint32_t crtc_id; +uint32_t connector_id; +drmModeModeInfoPtr mode; +}; + +int drm_fd; +drmModeResPtr drm_res; +drmModeConnectorPtr drm_connectors[MAX_CONNECTORS ]; +drm_intel_bufmgr *bufmgr; +igt_pipe_crc_t *pipe_crc; + +bool has_method_base_crc = false; +igt_crc_t method_base_crc; + +struct modeset_params ms; + +static void find_modeset_params (void ) +{ +int i; +uint32_t connector_id =0 , crtc_id; +drmModeModeInfoPtr mode =NULL ; + +for (i =0 ; i < drm_res->count_connectors; i++) { +drmModeConnectorPtr c = drm_connectors[i]; + +if (c->count_modes) { + connector_id = c->connector_id; + mode = &c->modes[0 ]; +break ; + } + } +igt_require (connector_id); + + crtc_id = drm_res->crtcs[0 ]; +igt_assert (crtc_id); +igt_assert (mode); + + ms.connector_id = connector_id; + ms.crtc_id = crtc_id; + ms.mode = mode; + +} + +static void get_method_crc (enum igt_draw_method method,uint64_t tiling, +igt_crc_t *crc) +{ +struct igt_fb fb; +int rc; + +igt_create_fb (drm_fd, ms.mode->hdisplay, ms.mode->vdisplay, +DRM_FORMAT_XRGB8888 , tiling, &fb); +igt_draw_rect_fb (drm_fd, bufmgr,NULL , &fb, method, +0 ,0 , fb.width, fb.height,0xFF ); + +igt_draw_rect_fb (drm_fd, bufmgr,NULL , &fb, method, + fb.width /4 , fb.height /4 , + fb.width /2 , fb.height /2 ,0xFF00 ); +igt_draw_rect_fb (drm_fd, bufmgr,NULL , &fb, method, + fb.width /8 , fb.height /8 , + fb.width /4 , fb.height /4 ,0xFF0000 ); +igt_draw_rect_fb (drm_fd, bufmgr,NULL , &fb, method, + fb.width /2 , fb.height /2 , + fb.width /3 , fb.height /3 ,0xFF00FF ); + + rc = drmModeSetCrtc(drm_fd, ms.crtc_id, fb.fb_id, 0, 0,Quoted 8 lines
lib/tests/igt_draw.c line 106
Quoted 5 lines
lib/tests/igt_draw.c new file +5
-0+ &ms.connector_id, 1, ms.mode); +igt_assert (rc ==0 ); + +igt_debug_wait_for_keypress ("crc" ); +igt_pipe_crc_collect_crc (pipe_crc, crc);Should we just move this
igt_debug_wait_for_keypressintoigt_pipe_crc_collect_crc?
Quoted 4 lines
I think I prefer to leave these on the programs because you can then opt-out of some cases such as when you're getting the reference CRCs. It doesn't hurt to just add these to the problems, but it can be annoying if the wait is on the lib and you don't want it.
wait_for_keypress takes a key argument, so we could just use a "crc" key. Test could then use a "check" or similar (we don't have a standard yet) - generally you don't really want to run with --interactive-debug=all anyway since that tends to stop awfully often already ;-) Also you can list multiple keywords.
So annoying waits from libraries are already taken care of, no harm in adding them.
Quoted 158 lines
Quoted 153 lines
Quoted 144 lines
lib/tests/igt_draw.c new file +141
-1+ +kmstest_unset_all_crtcs (drm_fd, drm_res); +igt_remove_fb (drm_fd, &fb); +} + +static void draw_method_subtest (enum igt_draw_method method,uint64_t tiling) +{ +igt_crc_t crc; + +kmstest_unset_all_crtcs (drm_fd, drm_res); + +find_modeset_params (); + +/* Use IGT_DRAW_MMAP_GTT on an untiled buffer as the parameter for +* comparison. Cache the value so we don't recompute it for every single +* subtest. */ +if (!has_method_base_crc) { +get_method_crc (IGT_DRAW_MMAP_GTT ,LOCAL_DRM_FORMAT_MOD_NONE , + &method_base_crc); + has_method_base_crc = true; + } + +get_method_crc (method, tiling, &crc); +igt_assert_crc_equal (&crc, &method_base_crc); +} + +static void get_fill_crc (uint64_t tiling,igt_crc_t *crc) +{ +struct igt_fb fb; +int rc; + +igt_create_fb (drm_fd, ms.mode->hdisplay, ms.mode->vdisplay, +DRM_FORMAT_XRGB8888 , tiling, &fb); + +igt_draw_fill_fb (drm_fd, &fb,0xFF ); + + rc =drmModeSetCrtc (drm_fd, ms.crtc_id, fb.fb_id,0 ,0 , + &ms.connector_id,1 , ms.mode); +igt_assert (rc ==0 ); + +igt_debug_wait_for_keypress ("crc" ); +igt_pipe_crc_collect_crc (pipe_crc, crc); + +kmstest_unset_all_crtcs (drm_fd, drm_res); +igt_remove_fb (drm_fd, &fb); +} + +static void fill_fb_subtest (void ) +{ +int rc; +struct igt_fb fb; +igt_crc_t base_crc, crc; + +kmstest_unset_all_crtcs (drm_fd, drm_res); + +find_modeset_params (); + +igt_create_fb (drm_fd, ms.mode->hdisplay, ms.mode->vdisplay, +DRM_FORMAT_XRGB8888 ,LOCAL_DRM_FORMAT_MOD_NONE , &fb); + +igt_draw_rect_fb (drm_fd, bufmgr,NULL , &fb,IGT_DRAW_MMAP_GTT , +0 ,0 , fb.width, fb.height,0xFF ); + + rc =drmModeSetCrtc (drm_fd, ms.crtc_id, fb.fb_id,0 ,0 , + &ms.connector_id,1 , ms.mode); +igt_assert (rc ==0 ); + +igt_debug_wait_for_keypress ("crc" ); +igt_pipe_crc_collect_crc (pipe_crc, &base_crc); + +get_fill_crc (LOCAL_DRM_FORMAT_MOD_NONE , &crc); +igt_assert_crc_equal (&crc, &base_crc); + +get_fill_crc (LOCAL_I915_FORMAT_MOD_X_TILED , &crc); +igt_assert_crc_equal (&crc, &base_crc); + +kmstest_unset_all_crtcs (drm_fd, drm_res); +igt_remove_fb (drm_fd, &fb); +} + +static void setup_environment (void ) +{ +int i; + + drm_fd =drm_open_any_master (); +igt_require (drm_fd >=0 ); + + drm_res =drmModeGetResources (drm_fd); +igt_assert (drm_res->count_connectors <=MAX_CONNECTORS ); + +for (i =0 ; i < drm_res->count_connectors; i++) + drm_connectors[i] =drmModeGetConnector (drm_fd, + drm_res->connectors[i]); + +kmstest_set_vt_graphics_mode (); + + bufmgr =drm_intel_bufmgr_gem_init (drm_fd,4096 ); +igt_assert (bufmgr); +drm_intel_bufmgr_gem_enable_reuse (bufmgr); + + pipe_crc =igt_pipe_crc_new (0 ,INTEL_PIPE_CRC_SOURCE_AUTO ); +} + +static void teardown_environment (void ) +{ +int i; + +igt_pipe_crc_free (pipe_crc); + +drm_intel_bufmgr_destroy (bufmgr); + +for (i =0 ; i < drm_res->count_connectors; i++) +drmModeFreeConnector (drm_connectors[i]); + +drmModeFreeResources (drm_res); +close (drm_fd); +} + +igt_main +{ +enum igt_draw_method method; + +igt_fixture +setup_environment (); + +for (method =0 ; method <IGT_DRAW_METHOD_COUNT ; method++) { +igt_subtest_f ("draw-method-%s-untiled" , + igt_draw_get_method_name(method)) +draw_method_subtest (method,LOCAL_DRM_FORMAT_MOD_NONE ); +igt_subtest_f ("draw-method-%s-tiled" , + igt_draw_get_method_name(method)) +draw_method_subtest (method, +LOCAL_I915_FORMAT_MOD_X_TILED ); + } + + igt_subtest("fill-fb") +fill_fb_subtest (); + +igt_fixture +teardown_environment (); +} --2.1.4
Quoted 4 lines
_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.chSignature · 1 line
Paulo Zanoni
Signature · 7 lines
Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 7/7] lib: add igt_draw
2015-03-31 10:07 GMT-03:00 Daniel Vetter <[email protected]>:
Quoted 49 lines · Paulo Zanoni
Quoted 32 lines
2015-03-26 7:19 GMT-03:00 Daniel Vetter <[email protected]>:
Quoted 15 lines · Paulo Zanoni
Quoted 8 lines
From: Paulo Zanoni <[email protected]>
For all those IGT tests that need an easy way to draw rectangles on buffers using different methods. Current planned users: FBC and PSR CRC tests.
There is also a
lib/tests/igt_drawprogram to check if the library is sane.We need to move that to tests/igt_draw. The testcase in
lib/tests/*get run with make check, which must be possible as non-root on a non-intel (build) machine. If you need an gpu to run your test it must be in tests/* as a normal igt kernel test.Quoted 4 lines
Wrt the library itself I'm unsure about the explicit tiling/swizzling. Your current code only works on gen5-8 and maintaining a full-blown swizzle/tiling library is real work, and means some of the tests can't be converted to this.
This would just be a problem for the tests that use it, and no test is using it yet. This is just for the cases where you want to use the CPU to write into tiled buffers.
If we start using this in a test, then we need to properly test all the affected platforms. I have some local FBC tests that use it - which I was going to submit after getting feedback on this lib -, and I don't think we'll end needing to run these tests on the older platforms.
Quoted 5 lines
Quoted 3 lines
We do have all the tiling modes encoded in the tiling
tests though, so if you have a lot of time it might be useful to extract tiling helpers into the igt library which work on all generations.Can you please be more precise here? Where exactly should I look?
gem_tiled_preadhas the full-blown tiling/swizzle logic for all platforms. This is the one test we have which should work everywhere.My concern is that by implementing a library which doesn't support everywhere we havea bit a split in the testbase which might surprise people. Imo a library function should work everywhere. If you look at the code in there compared to yours there's just 2 things missing:
- Variable tile size/height.
- Some of the more crazy swizzle modes.
Quoted 2 lines
Also if we have a library which works everywhere we could extend it with the new fancy gen9+ tiling modes.
I'll take a look at gem_tiled_pread and try to implement what is missing. I agree that supporting everything is the ideal, but I also think that we can grow this support as needed instead of all at once.
Quoted 366 lines
Quoted 7 lines
Quoted 4 lines
I think we should at least have a fallback mode which allows us to fill an entire buffer completely (i.e. not just the hxw area) and treat it as untiled.
That is not the goal of the library. Still, if we ever need this function, it would be easy to add.
That was just meant as a fallback for buffers where you don't support the exact tiling/swizzling mode.
Quoted 356 lines
Quoted 3 lines
More comments below.
More below too :)
Quoted 349 lines
-Daniel
Quoted 333 lines
Signed-off-by Paulo Zanoni <[email protected]>--- lib/Makefile.sources | 2 + lib/igt_draw.c | 467 +++++++++++++++++++++++++++++++++++++++++++++ lib/igt_draw.h | 54 ++++++ lib/tests/.gitignore | 1 + lib/tests/Makefile.sources | 1 + lib/tests/igt_draw.c | 247 ++++++++++++++++++++++++ 6 files changed, 772 insertions(+) create mode 100644 lib/igt_draw.c create mode 100644 lib/igt_draw.h create mode 100644 lib/tests/igt_draw.clib/Makefile.sources +2
-0@@ -52,6 +52,8 @@ libintel_tools_la_SOURCES = \ igt_fb.h \ igt_core.c \ igt_core.h \ + igt_draw.c \ + igt_draw.h \ $(NULL) .PHONY: version.h.tmplib/igt_draw.c new file +300
-0@@ -0,0 +1,467 @@ +/* +* Copyright © 2015 Intel Corporation +* +* 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 (including the next +* paragraph) 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 <sys/mman.h> + +#include "igt_draw.h" + +#include "drmtest.h" +#include "intel_chipset.h" +#include "igt_core.h" +#include "igt_fb.h" +#include "ioctl_wrappers.h" + +/** +* SECTION:igt_draw +* @short_description: drawing helpers for tests +* @title: i-g-t draw +* @include: igt_draw.h +* +* This library contains some functions for drawing rectangles on buffers using +* the many different drawing methods we have. It also contains some wrappers +* that make the process easier if you have the abstract objects in hand. +* +* All functions assume the buffers are in the XRGB 8:8:8 format. +* +*/ + +/* Some internal data structures to avoid having to pass tons of parameters +* around everything. */ +struct cmd_data { +drm_intel_bufmgr *bufmgr; +drm_intel_context *context; +}; + +struct buf_data { +uint32_t handle; +uint32_t size; +uint32_t stride; +}; + +struct rect { +int x; +int y; +int w; +int h; +}; + +const char *igt_draw_get_method_name (enum igt_draw_method method) +{ +switch (method) { +case IGT_DRAW_MMAP_CPU : +return "mmap-cpu" ; +case IGT_DRAW_MMAP_GTT : +return "mmap-gtt" ; +case IGT_DRAW_PWRITE : +return "pwrite" ; +case IGT_DRAW_BLT : +return "blt" ; +case IGT_DRAW_RENDER : +return "render" ; +default : +igt_assert (false); + } +} + +static int swizzle_addr (int addr,int swizzle) +{ +int bit6; + +if (swizzle ==I915_BIT_6_SWIZZLE_9_10 ) { + bit6 = ((addr >>6 ) &1 ) ^ ((addr >>9 ) &1 ) ^ + ((addr >>10 ) &1 ); + addr &= ~(1 <<6 ); + addr |= (bit6 <<6 ); + } + +return addr; +} + +/* It's all in "pixel coordinates", so make sure you multiply/divide by the bpp +* if you need to. */ +static int linear_x_y_to_tiled_pos (int x,int y,uint32_t stride,int swizzle) +{ +int x_tile_size, y_tile_size; +int x_tile_n, y_tile_n, x_tile_off, y_tile_off; +int line_size, tile_size; +int tile_n, tile_off; +int tiled_pos, tiles_per_line; +int bpp; + + line_size = stride; + x_tile_size =512 ; + y_tile_size =8 ; + tile_size = x_tile_size * y_tile_size; + tiles_per_line = line_size / x_tile_size; + bpp =sizeof (uint32_t ); + + y_tile_n = y / y_tile_size; + y_tile_off = y % y_tile_size; + + x_tile_n = (x * bpp) / x_tile_size; + x_tile_off = (x * bpp) % x_tile_size; + + tile_n = y_tile_n * tiles_per_line + x_tile_n; + tile_off = y_tile_off * x_tile_size + x_tile_off; + tiled_pos = tile_n * tile_size + tile_off; + + tiled_pos =swizzle_addr (tiled_pos, swizzle); + +return tiled_pos / bpp; +} + +/* It's all in "pixel coordinates", so make sure you multiply/divide by the bpp +* if you need to. */ +static void tiled_pos_to_x_y_linear (int tiled_pos,uint32_t stride, +int swizzle,int *x,int *y) +{ +int tile_n, tile_off, tiles_per_line, line_size; +int x_tile_off, y_tile_off; +int x_tile_n, y_tile_n; +int x_tile_size, y_tile_size, tile_size; +int bpp; + + tiled_pos =swizzle_addr (tiled_pos, swizzle); + + line_size = stride; + x_tile_size =512 ; + y_tile_size =8 ; + tile_size = x_tile_size * y_tile_size; + tiles_per_line = line_size / x_tile_size; + bpp =sizeof (uint32_t ); + + tile_n = tiled_pos / tile_size; + tile_off = tiled_pos % tile_size; + + y_tile_off = tile_off / x_tile_size; + x_tile_off = tile_off % x_tile_size; + + x_tile_n = tile_n % tiles_per_line; + y_tile_n = tile_n / tiles_per_line; + + *x = (x_tile_n * x_tile_size + x_tile_off) / bpp; + *y = y_tile_n * y_tile_size + y_tile_off; +} + +static void draw_rect_mmap_cpu (int fd,struct buf_data *buf,struct rect *rect, +uint32_t color) +{ +uint32_t *ptr; +int x, y, pos; +uint32_t tiling, swizzle; + +gem_set_domain (fd, buf->handle,I915_GEM_DOMAIN_CPU , +I915_GEM_DOMAIN_CPU ); +gem_get_tiling (fd, buf->handle, &tiling, &swizzle); + + ptr =gem_mmap__cpu (fd, buf->handle,0 , buf->size,0 ); +igt_assert (ptr); + +for (y = rect->y; y < rect->y + rect->h; y++) { +for (x = rect->x; x < rect->x + rect->w; x++) { +if (tiling) + pos =linear_x_y_to_tiled_pos (x, y, buf->stride, + swizzle); +else + pos = (y * buf->stride /sizeof (uint32_t )) + x; + ptr[pos] = color; + } + } + +gem_sw_finish (fd, buf->handle); + +igt_assert (munmap (ptr, buf->size) ==0 ); +} + +static void draw_rect_mmap_gtt (int fd,struct buf_data *buf,struct rect *rect, +uint32_t color) +{ +uint32_t *ptr; +int x, y; + + ptr =gem_mmap__gtt (fd, buf->handle, buf->size, +PROT_READ |PROT_WRITE ); +igt_assert (ptr); + +for (y = rect->y; y < rect->y + rect->h; y++) { +int line_begin = y * buf->stride /sizeof (uint32_t ); +for (x = rect->x; x < rect->x + rect->w; x++) + ptr[line_begin + x] = color; + } + +igt_assert (munmap (ptr, buf->size) ==0 ); +} + +static void draw_rect_pwrite_untiled (int fd,struct buf_data *buf, +struct rect *rect,uint32_t color) +{ +uint32_t tmp[rect->w]; +int i, y, offset, bpp; + + bpp =sizeof (uint32_t ); + +for (i =0 ; i < rect->w; i++) + tmp[i] = color; + +for (y = rect->y; y < rect->y + rect->h; y++) { + offset = (y * buf->stride) + (rect->x * bpp); +gem_write (fd, buf->handle, offset, tmp, rect->w * bpp); + } +} + +static void draw_rect_pwrite_tiled (int fd,struct buf_data *buf, +struct rect *rect,uint32_t color, +uint32_t swizzle) +{ +int i; +int tiled_pos, bpp, x, y; +uint32_t tmp[1024 ]; +int tmp_used =0 , tmp_size =ARRAY_SIZE (tmp); +bool flush_tmp = false; +int tmp_start_pos =0 ; + + bpp =sizeof (uint32_t ); + +/* Instead of doing one pwrite per pixel, we try to group the maximum +* amount of consecutive pixels we can in a single pwrite: that's why we +* use the "tmp" variables. */ +for (i =0 ; i < tmp_size; i++) + tmp[i] = color; + +for (tiled_pos =0 ; tiled_pos < buf->size; tiled_pos += bpp) { +tiled_pos_to_x_y_linear (tiled_pos, buf->stride, swizzle, &x, &y); + +if (x >= rect->x && x < rect->x + rect->w && + y >= rect->y && y < rect->y + rect->h) { +if (tmp_used ==0 ) + tmp_start_pos = tiled_pos; + tmp_used++; + }else { + flush_tmp = true; + } + +if (tmp_used == tmp_size || (flush_tmp && tmp_used >0 )) { +gem_write (fd, buf->handle, tmp_start_pos, tmp, + tmp_used * bpp); + flush_tmp = false; + tmp_used =0 ; + } + } +} + +static void draw_rect_pwrite (int fd,struct buf_data *buf, +struct rect *rect,uint32_t color) +{ +uint32_t tiling, swizzle; + +gem_get_tiling (fd, buf->handle, &tiling, &swizzle); + +if (tiling) +draw_rect_pwrite_tiled (fd, buf, rect, color, swizzle); +else +draw_rect_pwrite_untiled (fd, buf, rect, color); +} + +static void draw_rect_blt (int fd,struct cmd_data *cmd_data, +struct buf_data *buf,struct rect *rect, +uint32_t color) +{ +drm_intel_bo *dst; +struct intel_batchbuffer *batch; +int blt_cmd_len, blt_cmd_tiling; +uint32_t devid =intel_get_drm_devid (fd); +int gen =intel_gen (devid); +uint32_t tiling, swizzle; +int pitch; + +gem_get_tiling (fd, buf->handle, &tiling, &swizzle); + + dst =gem_handle_to_libdrm_bo (cmd_data->bufmgr, fd,"" , buf->handle);lib/igt_draw.c line 310
Quoted 10 lines
lib/igt_draw.c new file +10
-0+igt_assert (dst); + + batch =intel_batchbuffer_alloc (cmd_data->bufmgr, devid); +igt_assert (batch); + + blt_cmd_len = (gen >=8 ) ?0x5 :0x4 ; + blt_cmd_tiling = (tiling) ?XY_COLOR_BLT_TILED :0 ; + pitch = (tiling) ? buf->stride /4 : buf->stride; + +BEGIN_BATCH (6 ,1 );This breaks on gen8 because there the relocations are 2 dwords. You need to use the magic macros for that.
Quoted 6 lines
Quoted 2 lines
Please read the code again. I actually developed and tested everything on gen8 :)
Oh right I missed that
OUT_RELOCuses qwords on gen8+ automatically. I still think using the same logic as with all other blitter tests would be better since blitter cmd copypaste fail has been the bane of igt.
Well, this is one of the main goals of the library: use it instead of adding yet another implementation of the drawing commands...
Quoted 373 lines
Quoted 8 lines
Quoted 8 lines
lib/igt_draw.c line 316
Quoted 8 lines
lib/igt_draw.c new file +6
-0+OUT_BATCH (XY_COLOR_BLT_CMD_NOLEN |XY_COLOR_BLT_WRITE_ALPHA | +XY_COLOR_BLT_WRITE_RGB | blt_cmd_tiling | blt_cmd_len); +OUT_BATCH ((3 <<24 ) | (0xF0 <<16 ) | pitch); +OUT_BATCH ((rect->y <<16 ) | rect->x); +OUT_BATCH (((rect->y + rect->h) <<16 ) | (rect->x + rect->w)); +if (tiling)btw this isn't needed
OUT_RELOC_FENCEDworks correctly for untiled buffers. It's actually required on gen2/3 for untiled buffers if you reuse buffers (which might be the case for a library function) sinceOUT_RELOCdoes _not_ remove a stale fence if there is one.Quoted 354 lines
Quoted 181 lines
Quoted 181 lines
lib/igt_draw.c new file +151
-0+OUT_RELOC_FENCED (dst,0 ,I915_GEM_DOMAIN_RENDER ,0 ); + else + OUT_RELOC(dst, 0, I915_GEM_DOMAIN_RENDER, 0); + OUT_BATCH(color); +ADVANCE_BATCH (); + +intel_batchbuffer_flush (batch); +gem_sync (fd, buf->handle); +intel_batchbuffer_free (batch); +} + +static void draw_rect_render (int fd,struct cmd_data *cmd_data, +struct buf_data *buf,struct rect *rect, +uint32_t color) +{ +drm_intel_bo *src, *dst; +uint32_t devid =intel_get_drm_devid (fd); +igt_render_copyfunc_t rendercopy =igt_get_render_copyfunc (devid); +struct igt_buf src_buf, dst_buf; +struct intel_batchbuffer *batch; +uint32_t tiling, swizzle; +struct buf_data tmp; + +igt_skip_on (!rendercopy); + +gem_get_tiling (fd, buf->handle, &tiling, &swizzle); + +/* We create a temporary buffer and copy from it using rendercopy. */ + tmp.size = rect->w * rect->h *sizeof (uint32_t ); + tmp.handle =gem_create (fd, tmp.size); + tmp.stride = rect->w *sizeof (uint32_t ); +draw_rect_mmap_cpu (fd, &tmp, &(struct rect ){0 ,0 , rect->w, rect->h}, + color); + + src =gem_handle_to_libdrm_bo (cmd_data->bufmgr, fd,"" , tmp.handle); +igt_assert (src); + dst =gem_handle_to_libdrm_bo (cmd_data->bufmgr, fd,"" , buf->handle); +igt_assert (dst); + + src_buf.bo = src; + src_buf.stride = tmp.stride; + src_buf.tiling =I915_TILING_NONE ; + src_buf.size = tmp.size; + dst_buf.bo = dst; + dst_buf.stride = buf->stride; + dst_buf.tiling = tiling; + dst_buf.size = buf->size; + + batch =intel_batchbuffer_alloc (cmd_data->bufmgr, devid); +igt_assert (batch); + +rendercopy (batch, cmd_data->context, &src_buf,0 ,0 , rect->w, rect->h, + &dst_buf, rect->x, rect->y); + +gem_sync (fd, buf->handle); +intel_batchbuffer_free (batch); +gem_close (fd, tmp.handle); +} + +/** +* igt_draw_rect: +* @fd: the DRM file descriptor +* @bufmgr: the libdrm bufmgr, only required for IGT_DRAW_BLT and +* IGT_DRAW_RENDER +* @context: the context, can be NULL if you don't want to think about it +* @buf_handle: the handle of the buffer where you're going to draw to +* @buf_size: the size of the buffer +* @buf_stride: the stride of the buffer +* @method: method you're going to use to write to the buffer +* @rect_x: horizontal position on the buffer where your rectangle starts +* @rect_y: vertical position on the buffer where your rectangle starts +* @rect_w: width of the rectangle +* @rect_h: height of the rectangle +* @color: color of the rectangle +* +* This function draws a colored rectangle on the destination buffer, allowing +* you to specify the method used to draw the rectangle. We assume 32 bit pixels +* with 8 bits per color. +*/ +void igt_draw_rect (int fd,drm_intel_bufmgr *bufmgr,drm_intel_context *context, +uint32_t buf_handle,uint32_t buf_size,uint32_t buf_stride, +enum igt_draw_method method,int rect_x,int rect_y, +int rect_w,int rect_h,uint32_t color) +{ +struct cmd_data cmd_data = { + .bufmgr = bufmgr, + .context = context, + }; +struct buf_data buf = { + .handle = buf_handle, + .size = buf_size, + .stride = buf_stride, + }; +struct rect rect = { + .x = rect_x, + .y = rect_y, + .w = rect_w, + .h = rect_h, + }; + +switch (method) { +case IGT_DRAW_MMAP_CPU : +draw_rect_mmap_cpu (fd, &buf, &rect, color); +break ; +case IGT_DRAW_MMAP_GTT : +draw_rect_mmap_gtt (fd, &buf, &rect, color); +break ; +case IGT_DRAW_PWRITE : +draw_rect_pwrite (fd, &buf, &rect, color); +break ; +case IGT_DRAW_BLT : +draw_rect_blt (fd, &cmd_data, &buf, &rect, color); +break ; +case IGT_DRAW_RENDER : +draw_rect_render (fd, &cmd_data, &buf, &rect, color); +break ; +default : +igt_assert (false); +break ; + } +} + +/** +* igt_draw_rect_fb: +* +* This is exactly the same as igt_draw_rect, but you can pass an igt_fb instead +* of manually providing its details. See igt_draw_rect. +*/ +void igt_draw_rect_fb (int fd,drm_intel_bufmgr *bufmgr, +drm_intel_context *context,struct igt_fb *fb, +enum igt_draw_method method,int rect_x,int rect_y, +int rect_w,int rect_h,uint32_t color) +{ +igt_draw_rect (fd, bufmgr, context, fb->gem_handle, fb->size, fb->stride, + method, rect_x, rect_y, rect_w, rect_h, color); +} + +/** +* igt_draw_fill_fb: +* @fd: the DRM file descriptor +* @fb: the FB that is going to be filled +* @color: the color you're going to paint it +* +* This function just paints an igt_fb using the provided color. It assumes 32 +* bit pixels with 8 bit colors. +*/ +void igt_draw_fill_fb (int fd,struct igt_fb *fb,uint32_t color) +{ +igt_draw_rect_fb (fd,NULL ,NULL , fb,IGT_DRAW_MMAP_GTT , +0 ,0 , fb->width, fb->height, color); +}lib/igt_draw.h new file +24
-0@@ -0,0 +1,54 @@ +/* +* Copyright © 2015 Intel Corporation +* +* 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 (including the next +* paragraph) 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. +* +*/ +Quoted 8 lines
lib/igt_draw.h line 30
Quoted 6 lines
lib/igt_draw.h new file +6
-0+#ifndef __IGT_DRAW_H__ +#define __IGT_DRAW_H__ + +#include <intel_bufmgr.h> +#include "igt_fb.h" +gtkdoc for this enum would be nice too I think.
Ok.
Quoted 152 lines
Quoted 152 lines
lib/igt_draw.h new file +24
-0+enum igt_draw_method { +IGT_DRAW_MMAP_CPU , +IGT_DRAW_MMAP_GTT , +IGT_DRAW_PWRITE , +IGT_DRAW_BLT , +IGT_DRAW_RENDER , +IGT_DRAW_METHOD_COUNT , +}; + +const char *igt_draw_get_method_name (enum igt_draw_method method); + +void igt_draw_rect (int fd,drm_intel_bufmgr *bufmgr,drm_intel_context *context, +uint32_t buf_handle,uint32_t buf_size,uint32_t buf_stride, +enum igt_draw_method method,int rect_x,int rect_y, +int rect_w,int rect_h,uint32_t color); + +void igt_draw_rect_fb (int fd,drm_intel_bufmgr *bufmgr, +drm_intel_context *context,struct igt_fb *fb, +enum igt_draw_method method,int rect_x,int rect_y, +int rect_w,int rect_h,uint32_t color); + +void igt_draw_fill_fb (int fd,struct igt_fb *fb,uint32_t color); + +#endif /* __IGT_DRAW_H__ */ lib/tests/.gitignore +1
-0@@ -1,4 +1,5 @@ # Please keep sorted alphabetically +igt_draw igt_fork_helper igt_invalid_subtest_name igt_list_onlylib/tests/Makefile.sources +1
-0@@ -1,4 +1,5 @@ check_PROGRAMS = \ + igt_draw \ igt_no_exit \ igt_no_exit_list_only \ igt_fork_helper \lib/tests/igt_draw.c new file +101
-0@@ -0,0 +1,247 @@ +/* +* Copyright © 2015 Intel Corporation +* +* 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 (including the next +* paragraph) 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. +* +*/ + +/* This program tests whether the igt_draw library actually works. */ + +#include "drmtest.h" +#include "igt_aux.h" +#include "igt_draw.h" +#include "igt_debugfs.h" +#include "igt_fb.h" +#include "igt_kms.h" + +#define MAX_CONNECTORS 32 + +struct modeset_params { +uint32_t crtc_id; +uint32_t connector_id; +drmModeModeInfoPtr mode; +}; + +int drm_fd; +drmModeResPtr drm_res; +drmModeConnectorPtr drm_connectors[MAX_CONNECTORS ]; +drm_intel_bufmgr *bufmgr; +igt_pipe_crc_t *pipe_crc; + +bool has_method_base_crc = false; +igt_crc_t method_base_crc; + +struct modeset_params ms; + +static void find_modeset_params (void ) +{ +int i; +uint32_t connector_id =0 , crtc_id; +drmModeModeInfoPtr mode =NULL ; + +for (i =0 ; i < drm_res->count_connectors; i++) { +drmModeConnectorPtr c = drm_connectors[i]; + +if (c->count_modes) { + connector_id = c->connector_id; + mode = &c->modes[0 ]; +break ; + } + } +igt_require (connector_id); + + crtc_id = drm_res->crtcs[0 ]; +igt_assert (crtc_id); +igt_assert (mode); + + ms.connector_id = connector_id; + ms.crtc_id = crtc_id; + ms.mode = mode; + +} + +static void get_method_crc (enum igt_draw_method method,uint64_t tiling, +igt_crc_t *crc) +{ +struct igt_fb fb; +int rc; + +igt_create_fb (drm_fd, ms.mode->hdisplay, ms.mode->vdisplay, +DRM_FORMAT_XRGB8888 , tiling, &fb); +igt_draw_rect_fb (drm_fd, bufmgr,NULL , &fb, method, +0 ,0 , fb.width, fb.height,0xFF ); + +igt_draw_rect_fb (drm_fd, bufmgr,NULL , &fb, method, + fb.width /4 , fb.height /4 , + fb.width /2 , fb.height /2 ,0xFF00 ); +igt_draw_rect_fb (drm_fd, bufmgr,NULL , &fb, method, + fb.width /8 , fb.height /8 , + fb.width /4 , fb.height /4 ,0xFF0000 ); +igt_draw_rect_fb (drm_fd, bufmgr,NULL , &fb, method, + fb.width /2 , fb.height /2 , + fb.width /3 , fb.height /3 ,0xFF00FF ); + + rc = drmModeSetCrtc(drm_fd, ms.crtc_id, fb.fb_id, 0, 0,Quoted 8 lines
lib/tests/igt_draw.c line 106
Quoted 5 lines
lib/tests/igt_draw.c new file +5
-0+ &ms.connector_id, 1, ms.mode); +igt_assert (rc ==0 ); + +igt_debug_wait_for_keypress ("crc" ); +igt_pipe_crc_collect_crc (pipe_crc, crc);Should we just move this
igt_debug_wait_for_keypressintoigt_pipe_crc_collect_crc?Quoted 4 lines
I think I prefer to leave these on the programs because you can then opt-out of some cases such as when you're getting the reference CRCs. It doesn't hurt to just add these to the problems, but it can be annoying if the wait is on the lib and you don't want it.
Quoted 9 lines
wait_for_keypresstakes a key argument, so we could just use a "crc" key. Test could then use a "check" or similar (we don't have a standard yet) - generally you don't really want to run with --interactive-debug=all anyway since that tends to stop awfully often already ;-) Also you can list multiple keywords.So annoying waits from libraries are already taken care of, no harm in adding them.
Ok, I agree with you here now.
Quoted 163 lines
Quoted 156 lines
Quoted 144 lines
Quoted 144 lines
lib/tests/igt_draw.c new file +141
-1+ +kmstest_unset_all_crtcs (drm_fd, drm_res); +igt_remove_fb (drm_fd, &fb); +} + +static void draw_method_subtest (enum igt_draw_method method,uint64_t tiling) +{ +igt_crc_t crc; + +kmstest_unset_all_crtcs (drm_fd, drm_res); + +find_modeset_params (); + +/* Use IGT_DRAW_MMAP_GTT on an untiled buffer as the parameter for +* comparison. Cache the value so we don't recompute it for every single +* subtest. */ +if (!has_method_base_crc) { +get_method_crc (IGT_DRAW_MMAP_GTT ,LOCAL_DRM_FORMAT_MOD_NONE , + &method_base_crc); + has_method_base_crc = true; + } + +get_method_crc (method, tiling, &crc); +igt_assert_crc_equal (&crc, &method_base_crc); +} + +static void get_fill_crc (uint64_t tiling,igt_crc_t *crc) +{ +struct igt_fb fb; +int rc; + +igt_create_fb (drm_fd, ms.mode->hdisplay, ms.mode->vdisplay, +DRM_FORMAT_XRGB8888 , tiling, &fb); + +igt_draw_fill_fb (drm_fd, &fb,0xFF ); + + rc =drmModeSetCrtc (drm_fd, ms.crtc_id, fb.fb_id,0 ,0 , + &ms.connector_id,1 , ms.mode); +igt_assert (rc ==0 ); + +igt_debug_wait_for_keypress ("crc" ); +igt_pipe_crc_collect_crc (pipe_crc, crc); + +kmstest_unset_all_crtcs (drm_fd, drm_res); +igt_remove_fb (drm_fd, &fb); +} + +static void fill_fb_subtest (void ) +{ +int rc; +struct igt_fb fb; +igt_crc_t base_crc, crc; + +kmstest_unset_all_crtcs (drm_fd, drm_res); + +find_modeset_params (); + +igt_create_fb (drm_fd, ms.mode->hdisplay, ms.mode->vdisplay, +DRM_FORMAT_XRGB8888 ,LOCAL_DRM_FORMAT_MOD_NONE , &fb); + +igt_draw_rect_fb (drm_fd, bufmgr,NULL , &fb,IGT_DRAW_MMAP_GTT , +0 ,0 , fb.width, fb.height,0xFF ); + + rc =drmModeSetCrtc (drm_fd, ms.crtc_id, fb.fb_id,0 ,0 , + &ms.connector_id,1 , ms.mode); +igt_assert (rc ==0 ); + +igt_debug_wait_for_keypress ("crc" ); +igt_pipe_crc_collect_crc (pipe_crc, &base_crc); + +get_fill_crc (LOCAL_DRM_FORMAT_MOD_NONE , &crc); +igt_assert_crc_equal (&crc, &base_crc); + +get_fill_crc (LOCAL_I915_FORMAT_MOD_X_TILED , &crc); +igt_assert_crc_equal (&crc, &base_crc); + +kmstest_unset_all_crtcs (drm_fd, drm_res); +igt_remove_fb (drm_fd, &fb); +} + +static void setup_environment (void ) +{ +int i; + + drm_fd =drm_open_any_master (); +igt_require (drm_fd >=0 ); + + drm_res =drmModeGetResources (drm_fd); +igt_assert (drm_res->count_connectors <=MAX_CONNECTORS ); + +for (i =0 ; i < drm_res->count_connectors; i++) + drm_connectors[i] =drmModeGetConnector (drm_fd, + drm_res->connectors[i]); + +kmstest_set_vt_graphics_mode (); + + bufmgr =drm_intel_bufmgr_gem_init (drm_fd,4096 ); +igt_assert (bufmgr); +drm_intel_bufmgr_gem_enable_reuse (bufmgr); + + pipe_crc =igt_pipe_crc_new (0 ,INTEL_PIPE_CRC_SOURCE_AUTO ); +} + +static void teardown_environment (void ) +{ +int i; + +igt_pipe_crc_free (pipe_crc); + +drm_intel_bufmgr_destroy (bufmgr); + +for (i =0 ; i < drm_res->count_connectors; i++) +drmModeFreeConnector (drm_connectors[i]); + +drmModeFreeResources (drm_res); +close (drm_fd); +} + +igt_main +{ +enum igt_draw_method method; + +igt_fixture +setup_environment (); + +for (method =0 ; method <IGT_DRAW_METHOD_COUNT ; method++) { +igt_subtest_f ("draw-method-%s-untiled" , + igt_draw_get_method_name(method)) +draw_method_subtest (method,LOCAL_DRM_FORMAT_MOD_NONE ); +igt_subtest_f ("draw-method-%s-tiled" , + igt_draw_get_method_name(method)) +draw_method_subtest (method, +LOCAL_I915_FORMAT_MOD_X_TILED ); + } + + igt_subtest("fill-fb") +fill_fb_subtest (); + +igt_fixture +teardown_environment (); +} --2.1.4
Quoted 9 lines
Quoted 4 lines
_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.chQuoted 2 lines
--
Paulo Zanoni--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
Signature · 5 lines
Paulo Zanoni _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
PATCH 7/7 lib: add igt_draw
From: Paulo Zanoni <[email protected]>
For all those IGT tests that need an easy way to draw rectangles on buffers using different methods. Current planned users: FBC and PSR CRC tests.
There is also a tests/kms_draw_crc program to check if the library is sane.
v2: - Move the test from lib/tests to tests/ (Daniel).
- Add igt_require() to filter out the swizzling/tiling methods we don't support (Daniel).
- Simplify reloc handling on the BLT case (Daniel).
- Document enum igt_draw_method (Daniel).
- Document igt_draw_get_method_name() (Paulo).
--- lib/Makefile.sources | 2 + lib/igt_draw.c | 500 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/igt_draw.h | 63 +++++++ tests/.gitignore | 1 + tests/Makefile.sources | 1 + tests/kms_draw_crc.c | 247 ++++++++++++++++++++++++ 6 files changed, 814 insertions(+) create mode 100644 lib/igt_draw.c create mode 100644 lib/igt_draw.h create mode 100644 tests/kms_draw_crc.c
The only things suggested by Daniel and not addressed are:
- Moving the igt_debug_wait_for_keypress() calls into the CRC code. This should be a separate patch.
- Support for a fallback function for when tiling/swizzling is not supported. Function igt_draw_fill_fb() was already there and should be enough for these cases, since it uses the simple GTT mmap implementation.
lib/Makefile.sources +2 -0
@@ -52,6 +52,8 @@ libintel_tools_la_SOURCES = \ igt_fb.h \ igt_core.c \ igt_core.h \ + igt_draw.c \ + igt_draw.h \ $(NULL) .PHONY: version.h.tmp
lib/igt_draw.c new file +500 -0
500 lines not on this page · raw message
lib/igt_draw.h new file +63 -0
63 lines not on this page · raw message
tests/.gitignore +1 -0
@@ -125,6 +125,7 @@ gen7_forcewake_mt kms_3d kms_addfb kms_cursor_crc +kms_draw_crc kms_fbc_crc kms_fence_pin_leak kms_flip
tests/Makefile.sources +1 -0
@@ -69,6 +69,7 @@ TESTS_progs_M = \ gem_write_read_ring_switch \ kms_addfb \ kms_cursor_crc \ + kms_draw_crc \ kms_fbc_crc \ kms_flip \ kms_flip_event_leak \
tests/kms_draw_crc.c new file +247 -0
247 lines not on this page · raw message
Signature · 6 lines
2.1.4 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 7/7] lib: add igt_draw
Quoted 9 lines · Paulo Zanoni
From: Paulo Zanoni <[email protected]>
For all those IGT tests that need an easy way to draw rectangles on buffers using different methods. Current planned users: FBC and PSR CRC tests.
There is also a tests/kms_draw_crc program to check if the library is sane.
Quoted 6 lines
v2: - Move the test from lib/tests to tests/ (Daniel).
- Addigt_require()to filter out the swizzling/tiling methods we don't support (Daniel).
- Simplify reloc handling on the BLT case (Daniel).
- Document enumigt_draw_method(Daniel).
- Documentigt_draw_get_method_name()(Paulo).
You are already missing one draw path (mmap wc), adding the extra swizzle modes for anything but bit17 is trivial, the BLT code is an opencoded intel_copy_bo and what is with all the sync? Moving everything into the GTT write domain (i.e. manually doing cache flushes) would seem to nullify the point of using the GPU in the first place.
-Chris
Signature · 5 lines
Chris Wilson, Intel Open Source Technology Centre _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 7/7] lib: add igt_draw
2015-03-31 19:05 GMT-03:00 Chris Wilson <[email protected]>:
Quoted 10 lines · Paulo Zanoni
Quoted 9 lines
From: Paulo Zanoni <[email protected]>
For all those IGT tests that need an easy way to draw rectangles on buffers using different methods. Current planned users: FBC and PSR CRC tests.
There is also a tests/kms_draw_crc program to check if the library is sane.
Quoted 8 lines
Quoted 6 lines
v2: - Move the test from lib/tests to tests/ (Daniel).
- Addigt_require()to filter out the swizzling/tiling methods we don't support (Daniel).
- Simplify reloc handling on the BLT case (Daniel).
- Document enumigt_draw_method(Daniel).
- Documentigt_draw_get_method_name()(Paulo).You are already missing one draw path (mmap wc),
Oh, new stuff! Done.
Quoted 2 lines
adding the extra swizzle
modes for anything but bit17 is trivial,
Done.
Quoted 2 lines
the BLT code is an opencoded
intel_copy_bo
No, we do BLT fills, not copies. On the render side I used rendercopy just because I still don't know how to do a "render fill".
Quoted 3 lines
and what is with all the sync? Moving everything into the GTT write domain (i.e. manually doing cache flushes) would seem to nullify the point of using the GPU in the first place.
The idea was to just be as simple as possible for the callers, but I can remove the gem_sync()s and leave it to the callers. There's also a little explanation on patch 2: I used this lib for some FBC tests, so the syncs would allow us to not wait so much for the retire work handler. But Daniel/Ville had also suggested a test without the sync, so I guess I would have removed the sync from the library anyway when implementing the test.
Thanks for the review!
Quoted 4 lines
-Chris
--
Chris Wilson, Intel Open Source Technology Centre
Signature · 5 lines
Paulo Zanoni _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 7/7] lib: add igt_draw
Quoted 6 lines · Paulo Zanoni
2015-03-31 19:05 GMT-03:00 Chris Wilson <[email protected]>:
Quoted 2 lines
the BLT code is an opencoded
intel_copy_boNo, we do BLT fills, not copies. On the render side I used rendercopy just because I still don't know how to do a "render fill".
Ojjjjh, my mistake then. We certainly could do with an intel_bo_fill() routine as we use XY_COLOR_BLT in quite a few places now.
Quoted 9 lines
Quoted 3 lines
and what is with all the sync? Moving everything into the GTT write domain (i.e. manually doing cache flushes) would seem to nullify the point of using the GPU in the first place.
The idea was to just be as simple as possible for the callers, but I can remove the gem_sync()s and leave it to the callers. There's also a little explanation on patch 2: I used this lib for some FBC tests, so the syncs would allow us to not wait so much for the retire work handler.
Which retire work handler? Not the requests one surely? -Chris
Signature · 5 lines
Chris Wilson, Intel Open Source Technology Centre _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 7/7] lib: add igt_draw
2015-04-01 19:22 GMT-03:00 Chris Wilson <[email protected]>:
Quoted 10 lines · Paulo Zanoni
Quoted 6 lines
2015-03-31 19:05 GMT-03:00 Chris Wilson <[email protected]>:
Quoted 2 lines
the BLT code is an opencoded
intel_copy_boNo, we do BLT fills, not copies. On the render side I used rendercopy just because I still don't know how to do a "render fill".
Ojjjjh, my mistake then. We certainly could do with an
intel_bo_fill()routine as we useXY_COLOR_BLTin quite a few places now.
I just added this to my TODO list. Some of the current XY_COLOR_BLT users will become users of igt_draw, so the duplication will be reduced a little bit. Later we can create intel_bo_fill and make igt_draw call it.
Quoted 5 lines
Quoted 5 lines
Quoted 4 lines
and what is with all the sync? Moving everything into the GTT write domain (i.e. manually doing cache flushes) would seem to nullify the point of using the GPU in the first place.
Quoted 7 lines
Quoted 5 lines
The idea was to just be as simple as possible for the callers, but I can remove the gem_sync()s and leave it to the callers. There's also a little explanation on patch 2: I used this lib for some FBC tests, so the syncs would allow us to not wait so much for the retire work handler.
Which retire work handler? Not the requests one surely?
i915_gem_retire_work_handler()
Now that we use the frontbuffer tracking mechanism, when we use the BLT, FBC gets disabled (by intel_fb_obj_invalidate(), called by i915_gem_execbuffer2()). But if we don't gem_sync(), FBC only gets reenabled after i915_gem_retire_work_handler() happens and calls intel_frontbuffer_flush(). While having FBC disabled for a long time is not a bug, the gem_sync() helps reducing the many-undreds-of-milliseconds waits.
Quoted 3 lines
--
Chris Wilson, Intel Open Source Technology Centre
Signature · 5 lines
Paulo Zanoni _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
PATCH 7/7 lib: add igt_draw
From: Paulo Zanoni <[email protected]>
For all those IGT tests that need an easy way to draw rectangles on buffers using different methods. Current planned users: FBC and PSR CRC tests.
There is also a tests/kms_draw_crc program to check if the library is sane.
v2: - Move the test from lib/tests to tests/ (Daniel).
- Add igt_require() to filter out the swizzling/tiling methods we don't support (Daniel).
- Simplify reloc handling on the BLT case (Daniel).
- Document enum igt_draw_method (Daniel).
- Document igt_draw_get_method_name() (Paulo).
v3: - Add IGT_DRAW_MMAP_WC (Chris).
- Implement the other trivial swizzling methods (Chris).
- Remove the gem_sync() calls (Chris).
--- lib/Makefile.sources | 2 + lib/igt_draw.c | 562 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/igt_draw.h | 65 ++++++ tests/.gitignore | 1 + tests/Makefile.sources | 1 + tests/kms_draw_crc.c | 247 ++++++++++++++++++++++ 6 files changed, 878 insertions(+) create mode 100644 lib/igt_draw.c create mode 100644 lib/igt_draw.h create mode 100644 tests/kms_draw_crc.c
lib/Makefile.sources +2 -0
@@ -52,6 +52,8 @@ libintel_tools_la_SOURCES = \ igt_fb.h \ igt_core.c \ igt_core.h \ + igt_draw.c \ + igt_draw.h \ $(NULL) .PHONY: version.h.tmp
lib/igt_draw.c new file +562 -0
562 lines not on this page · raw message
lib/igt_draw.h new file +65 -0
65 lines not on this page · raw message
tests/.gitignore +1 -0
@@ -125,6 +125,7 @@ gen7_forcewake_mt kms_3d kms_addfb kms_cursor_crc +kms_draw_crc kms_fbc_crc kms_fence_pin_leak kms_flip
tests/Makefile.sources +1 -0
@@ -69,6 +69,7 @@ TESTS_progs_M = \ gem_write_read_ring_switch \ kms_addfb \ kms_cursor_crc \ + kms_draw_crc \ kms_fbc_crc \ kms_flip \ kms_flip_event_leak \
tests/kms_draw_crc.c new file +247 -0
247 lines not on this page · raw message
Signature · 6 lines
2.1.4 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 7/7] lib: add igt_draw
lib/igt_draw.c line 282
Quoted 11 lines · Paulo Zanoni
lib/igt_draw.c new file +11
-0+static void draw_rect_mmap_wc (int fd,struct buf_data *buf,struct rect *rect, +uint32_t color) +{ +uint32_t *ptr; +uint32_t tiling, swizzle; + +gem_get_tiling (fd, buf->handle, &tiling, &swizzle); + +/* We didn't implement suport for the older tiling methods yet. */ +if (tiling !=I915_TILING_NONE ) +igt_require (intel_gen (intel_get_drm_devid (fd)) >=5 );
But you now do! You need something like:
static void get_tiling_and_swizzle(int fd,
struct buf_data *buf, int *tiling, int *swizzle)
{
struct local_i915_gem_get_tiling_v2 {
uint32_t handle;
uint32_t tiling_mode;
uint32_t swizzle_mode;
uint32_t phys_swizzle_mode;
} tiling;#define LOCAL_IOCTL_I915_GEM_GET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_TILING, struct local_i915_gem_get_tiling_v2)
memset(&tiling, 0, sizeof(tiling)); tiling.handle = buf->handle; do_ioctl(fd, LOCAL_IOCTL_I915_GEM_GET_TILING, &tiling); igt_require(tiling.phys_swizzle == tiling.swizzle_mode || intel_gen(intel_get_drm_devid(fd)) >= 5); /* old kernel? */ *tiling = tiling.tilling_mode; *swizzle = tiling.swizzle_mode; }
Signature · 5 lines
Chris Wilson, Intel Open Source Technology Centre _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 7/7] lib: add igt_draw
Quoted 14 lines · Chris Wilson
lib/igt_draw.c line 282
Quoted 11 lines · Paulo Zanoni
lib/igt_draw.c new file +11
-0+static void draw_rect_mmap_wc (int fd,struct buf_data *buf,struct rect *rect, +uint32_t color) +{ +uint32_t *ptr; +uint32_t tiling, swizzle; + +gem_get_tiling (fd, buf->handle, &tiling, &swizzle); + +/* We didn't implement suport for the older tiling methods yet. */ +if (tiling !=I915_TILING_NONE ) +igt_require (intel_gen (intel_get_drm_devid (fd)) >=5 );But you now do!
Oh, with the exception of gen2. You need to adjust the tilesize constants there.
-Chris
Signature · 5 lines
Chris Wilson, Intel Open Source Technology Centre _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 7/7] lib: add igt_draw
In reply to Chris WilsonQuoted 14 lines · Chris Wilson
lib/igt_draw.c line 282
Quoted 11 lines · Paulo Zanoni
lib/igt_draw.c new file +11
-0+static void draw_rect_mmap_wc (int fd,struct buf_data *buf,struct rect *rect, +uint32_t color) +{ +uint32_t *ptr; +uint32_t tiling, swizzle; + +gem_get_tiling (fd, buf->handle, &tiling, &swizzle); + +/* We didn't implement suport for the older tiling methods yet. */ +if (tiling !=I915_TILING_NONE ) +igt_require (intel_gen (intel_get_drm_devid (fd)) >=5 );But you now do! You need something like:
The problem is that the kernel hides bit17 swizzling. I chatted with Paulo on irc about this and we decided just ignore them all is the simplest approach.
-Daniel
Quoted 29 lines
static void get_tiling_and_swizzle(int fd,
structbuf_data*buf, int *tiling, int *swizzle){ struct local_i915_gem_get_tiling_v2 { uint32_t handle; uint32_t tiling_mode; uint32_t swizzle_mode; uint32_t phys_swizzle_mode; } tiling;#define
LOCAL_IOCTL_I915_GEM_GET_TILINGDRM_IOWR(DRM_COMMAND_BASE+DRM_I915_GEM_GET_TILING, structlocal_i915_gem_get_tiling_v2)memset(&tiling, 0, sizeof(tiling)); tiling.handle = buf->handle; do_ioctl(fd, LOCAL_IOCTL_I915_GEM_GET_TILING, &tiling); igt_require(tiling.phys_swizzle == tiling.swizzle_mode || intel_gen(intel_get_drm_devid(fd)) >= 5); /* old kernel? */ *tiling = tiling.tilling_mode; *swizzle = tiling.swizzle_mode; }Signature · 5 lines
Chris Wilson, Intel Open Source Technology Centre _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 7 lines
Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 7/7] lib: add igt_draw
Quoted 16 lines · Daniel Vetter
Quoted 14 lines · Chris Wilson
lib/igt_draw.c line 282
Quoted 11 lines · Paulo Zanoni
lib/igt_draw.c new file +11
-0+static void draw_rect_mmap_wc (int fd,struct buf_data *buf,struct rect *rect, +uint32_t color) +{ +uint32_t *ptr; +uint32_t tiling, swizzle; + +gem_get_tiling (fd, buf->handle, &tiling, &swizzle); + +/* We didn't implement suport for the older tiling methods yet. */ +if (tiling !=I915_TILING_NONE ) +igt_require (intel_gen (intel_get_drm_devid (fd)) >=5 );But you now do! You need something like:
Quoted 3 lines
The problem is that the kernel hides bit17 swizzling. I chatted with Paulo on irc about this and we decided just ignore them all is the simplest approach.
Urm, that was the whole point of GET_TILING v2. That small function is all you need to determine when bit17 is in effect and then you get to reuse all the direct CPU methods (as they are also used by userspace) for earlier gen.
-Chris
Signature · 5 lines
Chris Wilson, Intel Open Source Technology Centre _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 7/7] lib: add igt_draw
Quoted 17 lines · Chris Wilson
Quoted 16 lines · Daniel Vetter
Quoted 14 lines · Chris Wilson
lib/igt_draw.c line 282
Quoted 11 lines · Paulo Zanoni
lib/igt_draw.c new file +11
-0+static void draw_rect_mmap_wc (int fd,struct buf_data *buf,struct rect *rect, +uint32_t color) +{ +uint32_t *ptr; +uint32_t tiling, swizzle; + +gem_get_tiling (fd, buf->handle, &tiling, &swizzle); + +/* We didn't implement suport for the older tiling methods yet. */ +if (tiling !=I915_TILING_NONE ) +igt_require (intel_gen (intel_get_drm_devid (fd)) >=5 );But you now do! You need something like:
Quoted 8 lines
Quoted 3 lines
The problem is that the kernel hides bit17 swizzling. I chatted with Paulo on irc about this and we decided just ignore them all is the simplest approach.
Urm, that was the whole point of
GET_TILINGv2. That small function is all you need to determine when bit17 is in effect and then you get to reuse all the direct CPU methods (as they are also used by userspace) for earlier gen.
Oh right completely forgot that we've added this. But imo can be added on top once we need it (it's not just gen2 but also some gen3 which need different tile dimensions).
-Daniel
Signature · 7 lines
Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 7/7] lib: add igt_draw
Quoted 22 lines · Daniel Vetter
Quoted 21 lines · Chris Wilson
Quoted 19 lines · Daniel Vetter
Quoted 14 lines · Chris Wilson
lib/igt_draw.c line 282
Quoted 11 lines · Paulo Zanoni
lib/igt_draw.c new file +11
-0+static void draw_rect_mmap_wc (int fd,struct buf_data *buf,struct rect *rect, +uint32_t color) +{ +uint32_t *ptr; +uint32_t tiling, swizzle; + +gem_get_tiling (fd, buf->handle, &tiling, &swizzle); + +/* We didn't implement suport for the older tiling methods yet. */ +if (tiling !=I915_TILING_NONE ) +igt_require (intel_gen (intel_get_drm_devid (fd)) >=5 );But you now do! You need something like:
The problem is that the kernel hides bit17 swizzling. I chatted with Paulo on irc about this and we decided just ignore them all is the simplest approach.
Quoted 8 lines
Quoted 4 lines
Urm, that was the whole point of
GET_TILINGv2. That small function is all you need to determine when bit17 is in effect and then you get to reuse all the direct CPU methods (as they are also used by userspace) for earlier gen.Oh right completely forgot that we've added this. But imo can be added on top once we need it (it's not just gen2 but also some gen3 which need different tile dimensions).
Tile size is 2048 for gen2 only right. Tile width is the same for all gen3 for tiling X (and gen2), but tiling Y width depends on subgen. Right?
Just need to check because I have code that depends on this... -Chris
Signature · 5 lines
Chris Wilson, Intel Open Source Technology Centre _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 7/7] lib: add igt_draw
Quoted 32 lines · Chris Wilson
Quoted 22 lines · Daniel Vetter
Quoted 21 lines · Chris Wilson
Quoted 19 lines · Daniel Vetter
Quoted 14 lines · Chris Wilson
lib/igt_draw.c line 282
Quoted 11 lines · Paulo Zanoni
lib/igt_draw.c new file +11
-0+static void draw_rect_mmap_wc (int fd,struct buf_data *buf,struct rect *rect, +uint32_t color) +{ +uint32_t *ptr; +uint32_t tiling, swizzle; + +gem_get_tiling (fd, buf->handle, &tiling, &swizzle); + +/* We didn't implement suport for the older tiling methods yet. */ +if (tiling !=I915_TILING_NONE ) +igt_require (intel_gen (intel_get_drm_devid (fd)) >=5 );But you now do! You need something like:
The problem is that the kernel hides bit17 swizzling. I chatted with Paulo on irc about this and we decided just ignore them all is the simplest approach.
Quoted 8 lines
Quoted 4 lines
Urm, that was the whole point of
GET_TILINGv2. That small function is all you need to determine when bit17 is in effect and then you get to reuse all the direct CPU methods (as they are also used by userspace) for earlier gen.Oh right completely forgot that we've added this. But imo can be added on top once we need it (it's not just gen2 but also some gen3 which need different tile dimensions).
Quoted 5 lines
Tile size is 2048 for gen2 only right. Tile width is the same for all gen3 for tiling X (and gen2), but tiling Y width depends on subgen. Right?
Just need to check because I have code that depends on this...
Oh right thought about Y tiling which changes on gen3. X tiling matches your description afaik - I consider gem_tiled_pread the authoritative source for this stuff.
-Daniel
Signature · 7 lines
Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 7/7] lib: add igt_draw
2015-04-07 10:44 GMT-03:00 Daniel Vetter <[email protected]>:
Quoted 37 lines · Chris Wilson
Quoted 36 lines · Daniel Vetter
Quoted 22 lines · Chris Wilson
Quoted 21 lines · Daniel Vetter
Quoted 19 lines · Chris Wilson
Quoted 6 lines · Paulo Zanoni
Quoted 5 lines
(quoted diff) +5
-0+static void draw_rect_mmap_wc(int fd, struct buf_data *buf, struct rect *rect, + uint32_t color) +{ + uint32_t *ptr; + uint32_t tiling, swizzle;Quoted 8 lines
Review
Quoted 6 lines
(quoted diff) +6
-0+ + gem_get_tiling(fd, buf->handle, &tiling, &swizzle); + + /* We didn't implement suport for the older tiling methods yet. */ + if (tiling != I915_TILING_NONE) + igt_require(intel_gen(intel_get_drm_devid(fd)) >= 5);But you now do! You need something like:
The problem is that the kernel hides bit17 swizzling. I chatted with Paulo on irc about this and we decided just ignore them all is the simplest approach.
Quoted 8 lines
Quoted 4 lines
Urm, that was the whole point of
GET_TILINGv2. That small function is all you need to determine when bit17 is in effect and then you get to reuse all the direct CPU methods (as they are also used by userspace) for earlier gen.Oh right completely forgot that we've added this. But imo can be added on top once we need it (it's not just gen2 but also some gen3 which need different tile dimensions).
Tile size is 2048 for gen2 only right. Tile width is the same for all gen3 for tiling X (and gen2), but tiling Y width depends on subgen. Right?
Quoted 5 lines
Quoted 1 line
Just need to check because I have code that depends on this...
Oh right thought about Y tiling which changes on gen3. X tiling matches your description afaik - I consider
gem_tiled_preadthe authoritative source for this stuff.
Ok, so after all this discussion, what is the conclusion here? What is required before we can merge the patch?
Notice that with this patch we still won't have anybody using the library (except for the test added by the patch), and all the users I plan to add are gen5+. Also, I created VIZ-5495 to make sure we create intel_bo_fill() at some point (and, when we do it, I suggest we just use the implementation from igt_draw.c).
I really think the improvements discussed here can be done after we merge the patch because the it's not breaking anything, AFAICS. So, can I push this? Also, after the code is on igt, it will probably be easier to discuss the possible improvements since we'll be able to send patches.
Thanks for the reviews,
Paulo
Quoted 5 lines
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
Signature · 5 lines
Paulo Zanoni _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 7/7] lib: add igt_draw
Quoted 53 lines · Paulo Zanoni
2015-04-07 10:44 GMT-03:00 Daniel Vetter <[email protected]>:
Quoted 37 lines · Chris Wilson
Quoted 36 lines · Daniel Vetter
Quoted 22 lines · Chris Wilson
Quoted 21 lines · Daniel Vetter
Quoted 19 lines · Chris Wilson
Quoted 6 lines · Paulo Zanoni
Quoted 5 lines
(quoted diff) +5
-0+static void draw_rect_mmap_wc(int fd, struct buf_data *buf, struct rect *rect, + uint32_t color) +{ + uint32_t *ptr; + uint32_t tiling, swizzle;Quoted 8 lines
Review
Quoted 6 lines
(quoted diff) +6
-0+ + gem_get_tiling(fd, buf->handle, &tiling, &swizzle); + + /* We didn't implement suport for the older tiling methods yet. */ + if (tiling != I915_TILING_NONE) + igt_require(intel_gen(intel_get_drm_devid(fd)) >= 5);But you now do! You need something like:
The problem is that the kernel hides bit17 swizzling. I chatted with Paulo on irc about this and we decided just ignore them all is the simplest approach.
Quoted 8 lines
Quoted 4 lines
Urm, that was the whole point of
GET_TILINGv2. That small function is all you need to determine when bit17 is in effect and then you get to reuse all the direct CPU methods (as they are also used by userspace) for earlier gen.Oh right completely forgot that we've added this. But imo can be added on top once we need it (it's not just gen2 but also some gen3 which need different tile dimensions).
Tile size is 2048 for gen2 only right. Tile width is the same for all gen3 for tiling X (and gen2), but tiling Y width depends on subgen. Right?
Quoted 5 lines
Quoted 1 line
Just need to check because I have code that depends on this...
Oh right thought about Y tiling which changes on gen3. X tiling matches your description afaik - I consider
gem_tiled_preadthe authoritative source for this stuff.Ok, so after all this discussion, what is the conclusion here? What is required before we can merge the patch?
Notice that with this patch we still won't have anybody using the library (except for the test added by the patch), and all the users I plan to add are gen5+. Also, I created VIZ-5495 to make sure we create
intel_bo_fill()at some point (and, when we do it, I suggest we just use the implementation fromigt_draw.c).
Quoted 5 lines
I really think the improvements discussed here can be done after we merge the patch because the it's not breaking anything, AFAICS. So, can I push this? Also, after the code is on igt, it will probably be easier to discuss the possible improvements since we'll be able to send patches.
I guess you could capture the discussion here in a TODO comment in igt_draw? But yeah I thought we've discussed this on irc and agreed that moving ahead is ok, and that extensions can be done later on. -Daniel
Signature · 7 lines
Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 7/7] lib: add igt_draw
In reply to Paulo ZanoniQuoted 32 lines · Paulo Zanoni
2015-04-01 19:22 GMT-03:00 Chris Wilson <[email protected]>:
Quoted 10 lines · Paulo Zanoni
Quoted 6 lines
2015-03-31 19:05 GMT-03:00 Chris Wilson <[email protected]>:
Quoted 2 lines
the BLT code is an opencoded
intel_copy_boNo, we do BLT fills, not copies. On the render side I used rendercopy just because I still don't know how to do a "render fill".
Ojjjjh, my mistake then. We certainly could do with an
intel_bo_fill()routine as we useXY_COLOR_BLTin quite a few places now.I just added this to my TODO list. Some of the current
XY_COLOR_BLTusers will become users ofigt_draw, so the duplication will be reduced a little bit. Later we can createintel_bo_filland makeigt_drawcall it.Quoted 5 lines
Quoted 5 lines
Quoted 4 lines
and what is with all the sync? Moving everything into the GTT write domain (i.e. manually doing cache flushes) would seem to nullify the point of using the GPU in the first place.
Quoted 7 lines
Quoted 5 lines
The idea was to just be as simple as possible for the callers, but I can remove the gem_sync()s and leave it to the callers. There's also a little explanation on patch 2: I used this lib for some FBC tests, so the syncs would allow us to not wait so much for the retire work handler.
Which retire work handler? Not the requests one surely?
i915_gem_retire_work_handler()
Quoted 7 lines
Now that we use the frontbuffer tracking mechanism, when we use the BLT, FBC gets disabled (by
intel_fb_obj_invalidate(), called byi915_gem_execbuffer2()). But if we don'tgem_sync(), FBC only gets reenabled afteri915_gem_retire_work_handler()happens and callsintel_frontbuffer_flush(). While having FBC disabled for a long time is not a bug, thegem_sync()helps reducing the many-undreds-of-milliseconds waits.
Hmm. Bad news, that side-effect of gem_sync() won't happen in future. You would need to call gem_sync() on the framebuffer to trigger the flush, but that itself would then set the framebuffer to the GTT write domain which should then invalidate the FBC again. To flush without invalidate you want set_domain(scanout, read=GTT, write=0). -Chris
Signature · 5 lines
Chris Wilson, Intel Open Source Technology Centre _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx