All of lore.kernel.org
 help / color / mirror / Atom feed
* [igt-dev] [PATCH i-g-t] igt/tests/kms_dp_tiled_display.c : kms test file for display port tiled displays
@ 2019-07-17 18:02 Madhumitha Tolakanahalli Pradeep
  2019-07-17 18:35 ` [igt-dev] ✗ Fi.CI.BAT: failure for " Patchwork
                   ` (2 more replies)
  0 siblings, 3 replies; 18+ messages in thread
From: Madhumitha Tolakanahalli Pradeep @ 2019-07-17 18:02 UTC (permalink / raw)
  To: igt-dev; +Cc: Manasi Navare, Petri Latvala

This test validates the tiled DP displays to display a test pattern seamlessly
across the two tiles. It validates the transcoder port sync feature on i915 to
get a tearfree tiled display output.

Related kernel work patches -> https://patchwork.freedesktop.org/series/59837/#rev4.
This test can eventually be extended to cover tiled display support on other connector
types.

Cc: Manasi Navare <manasi.d.navare@intel.com>
Cc: Petri Latvala <petri.latvala@intel.com>
Signed-off-by: Madhumitha Tolakanahalli Pradeep <madhumitha.tolakanahalli.pradeep@intel.com>
---
 tests/Makefile.sources       |   1 +
 tests/kms_dp_tiled_display.c | 239 +++++++++++++++++++++++++++++++++++
 tests/meson.build            |   1 +
 3 files changed, 241 insertions(+)
 create mode 100644 tests/kms_dp_tiled_display.c

diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index 250dbd33..e9373941 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -40,6 +40,7 @@ TESTS_progs = \
 	kms_cursor_edge_walk \
 	kms_cursor_legacy \
 	kms_dp_dsc \
+	kms_dp_tiled_display \
 	kms_draw_crc \
 	kms_fbcon_fbt \
 	kms_fence_pin_leak \
diff --git a/tests/kms_dp_tiled_display.c b/tests/kms_dp_tiled_display.c
new file mode 100644
index 00000000..af644573
--- /dev/null
+++ b/tests/kms_dp_tiled_display.c
@@ -0,0 +1,239 @@
+/*
+ * Copyright © 2018 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.
+ *
+ * Authors:
+ *  Madhumitha Tolakanahalli Pradeep
+ *      <madhumitha.tolakanahalli.pradeep@intel.com>
+ *
+ * Display Port Tiled Display Test
+ * This test parses the tile information of the connectors that have TILE
+ * property set, sets up the framebuffer with correct offsets corresponding to
+ * the tile offsets and does an atomic modeset with two CRTCs for two
+ * connectors.
+ *
+ * This test currently supports only horizontally tiled displays, in line with
+ * the displays supported by the kernel at the moment.
+ */
+
+#include "drm_mode.h"
+#include "drm_fourcc.h"
+#include "igt.h"
+
+typedef struct {
+    int drm_fd;
+    int num_h_tiles;
+    igt_display_t *display;
+    enum igt_commit_style commit;
+} data_t;
+
+typedef struct {
+    igt_output_t *output;
+    igt_tile_info_t *tile;
+    igt_fb_t fb_test_pattern;
+    drmModeConnectorPtr connector;
+    enum pipe pipe;
+    enum igt_commit_style commit;
+} data_connector_t;
+
+static inline int drm_property_is_tile(drmModePropertyPtr prop)
+{
+	return(strcmp(prop->name ? prop->name : "", "TILE")? 0 : 1);
+}
+
+static void get_number_of_h_tiles(data_t *data)
+{
+    int i;
+    drmModeRes *res;
+    drmModeConnector *connector;
+    drmModePropertyPtr prop;
+    drmModePropertyBlobPtr blob;
+    igt_tile_info_t tile;
+
+    igt_require(res = drmModeGetResources(data->drm_fd));
+
+    for(i = 0; i < res->count_connectors; i++)
+    {
+        connector = drmModeGetConnectorCurrent(data->drm_fd, \
+                                               res->connectors[i]);
+
+        if(!((connector->connection == DRM_MODE_CONNECTED) &&
+            (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort)))
+                continue;
+
+        for(i = 0; i < connector->count_props; i++)
+        {
+            prop = drmModeGetProperty(data->drm_fd, connector->props[i]);
+
+            if(!(drm_property_is_tile(prop) &&
+                drm_property_type_is(prop, DRM_MODE_PROP_BLOB)))
+                continue;
+
+            blob = drmModeGetPropertyBlob(data->drm_fd, \
+                                          connector->prop_values[i]);
+
+            if(!blob)
+                break;
+
+            igt_parse_connector_tile_blob(blob, &tile);
+            data->num_h_tiles = tile.num_h_tile;
+            break;
+        }
+    }
+}
+
+static int set_test_pattern_fb(data_t *data, data_connector_t *conn_data)
+{
+    int i;
+    int count = 0;
+    bool is_tile = false;
+    enum pipe pipe;
+    igt_tile_info_t tile;
+    igt_output_t *output;
+    igt_plane_t *primary;
+    drmModePropertyPtr prop;
+    drmModePropertyBlobPtr blob;
+
+    for_each_connected_output(data->display, output)
+    {
+        is_tile = false;
+
+        conn_data[count].connector = drmModeGetConnector(data->display->drm_fd, \
+                                                         output->id);
+
+        if(!(conn_data[count].connector->connector_type ==
+                        DRM_MODE_CONNECTOR_DisplayPort))
+            continue;
+
+        /* Parse through each connector property */
+        for(i = 0; i < conn_data[count].connector->count_props; i++)
+        {
+            prop = drmModeGetProperty(data->display->drm_fd, \
+                                      conn_data[count].connector->props[i]);
+
+            if(!((drm_property_is_tile(prop) &&
+                drm_property_type_is(prop, DRM_MODE_PROP_BLOB))))
+                continue;
+
+            blob = drmModeGetPropertyBlob(data->display->drm_fd, \
+                            conn_data[count].connector->prop_values[i]);
+
+            if(!blob)
+                break;
+
+            igt_parse_connector_tile_blob(blob, &tile);
+            conn_data[count].tile = &tile;
+            is_tile = true;
+            break;
+        }
+
+        if(!is_tile)
+            continue;
+
+        output = igt_output_from_connector(data->display, \
+                                           conn_data[count].connector);
+
+        for_each_pipe(data->display, pipe)
+        {
+            igt_debug("Current PIPE is %d\n", pipe);
+
+            if((count > 0) && (pipe == conn_data[count-1].pipe))
+                continue;
+
+            if(igt_pipe_connector_valid(pipe, output)) {
+                conn_data[count].pipe = pipe;
+                conn_data[count].output = output;
+
+                igt_output_set_pipe(conn_data[count].output, \
+                                    conn_data[count].pipe);
+
+                igt_create_pattern_fb(data->drm_fd,\
+                                    (conn_data[count].tile->tile_h_size *\
+                                     data->num_h_tiles),\
+                                     conn_data[count].tile->tile_v_size,\
+                                     DRM_FORMAT_XBGR8888,\
+                                     LOCAL_DRM_FORMAT_MOD_NONE,\
+                                     &conn_data[count].fb_test_pattern);
+
+                primary = igt_output_get_plane_type(conn_data[count].output,\
+                                                    DRM_PLANE_TYPE_PRIMARY);
+
+                igt_plane_set_fb(primary, &conn_data[count].fb_test_pattern);
+
+                igt_fb_set_size(&conn_data[count].fb_test_pattern, primary,\
+                                conn_data[count].tile->tile_h_size,\
+                                conn_data[count].tile->tile_v_size);
+
+                igt_fb_set_position(&conn_data[count].fb_test_pattern, \
+                                    primary,\
+                                    (conn_data[count].tile->tile_h_size *\
+                                    conn_data[count].tile->tile_h_loc),
+                                    (conn_data[count].tile->tile_v_size *\
+                                    conn_data[count].tile->tile_v_loc));
+
+                igt_plane_set_size(primary,\
+                                   conn_data[count].tile->tile_h_size,\
+                                   conn_data[count].tile->tile_v_size);
+
+                break;
+            }
+        }
+        count++;
+    }
+
+    return count;
+}
+
+igt_main
+{
+    igt_display_t display;
+    data_t data = {};
+    data_connector_t *conn_data;
+
+    igt_fixture {
+        data.drm_fd = drm_open_driver_master(DRIVER_ANY);
+        kmstest_set_vt_graphics_mode();
+        igt_display_require(&display, data.drm_fd);
+        data.display = &display;
+
+        get_number_of_h_tiles(&data);
+        igt_debug("Number of Horizontal Tiles: %d\n", data.num_h_tiles);
+        data.commit = data.display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY;
+    }
+
+    if(data.num_h_tiles > 0)
+        conn_data = (data_connector_t *)malloc(data.num_h_tiles * \
+                                                sizeof(data_connector_t));
+    igt_assert(conn_data);
+
+    igt_subtest_f("basic-test-pattern") {
+        igt_skip_on(!data.num_h_tiles);
+        set_test_pattern_fb(&data, conn_data);
+        igt_display_commit2(data.display, data.commit);
+    }
+
+    igt_fixture {
+        if(data.num_h_tiles > 0)
+            free(conn_data);
+        kmstest_restore_vt_mode();
+        igt_display_fini(data.display);
+    }
+}
diff --git a/tests/meson.build b/tests/meson.build
index 34a74025..6a6e9ce9 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -25,6 +25,7 @@ test_progs = [
 	'kms_cursor_edge_walk',
 	'kms_cursor_legacy',
 	'kms_dp_dsc',
+	'kms_dp_tiled_display',
 	'kms_draw_crc',
 	'kms_fbcon_fbt',
 	'kms_fence_pin_leak',
-- 
2.17.1

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [igt-dev] ✗ Fi.CI.BAT: failure for igt/tests/kms_dp_tiled_display.c : kms test file for display port tiled displays
  2019-07-17 18:02 [igt-dev] [PATCH i-g-t] igt/tests/kms_dp_tiled_display.c : kms test file for display port tiled displays Madhumitha Tolakanahalli Pradeep
@ 2019-07-17 18:35 ` Patchwork
  2019-07-17 18:56 ` [igt-dev] ✗ GitLab.Pipeline: warning " Patchwork
  2019-07-18  6:43 ` [igt-dev] [PATCH i-g-t] " Ser, Simon
  2 siblings, 0 replies; 18+ messages in thread
From: Patchwork @ 2019-07-17 18:35 UTC (permalink / raw)
  To: Madhumitha Tolakanahalli Pradeep; +Cc: igt-dev

== Series Details ==

Series: igt/tests/kms_dp_tiled_display.c : kms test file for display port tiled displays
URL   : https://patchwork.freedesktop.org/series/63830/
State : failure

== Summary ==

IGT patchset build failed on latest successful build
6038ace76016d8892f4d13aef5301f71ca1a6e2d tests/kms_chamelium: add a test checking modes

../tests/kms_dp_tiled_display.c: In function ‘get_number_of_h_tiles’:
../tests/kms_dp_tiled_display.c:69:5: error: unknown type name ‘igt_tile_info_t’; did you mean ‘snd_timer_info_t’?
     igt_tile_info_t tile;
     ^~~~~~~~~~~~~~~
     snd_timer_info_t
../tests/kms_dp_tiled_display.c:96:13: error: implicit declaration of function ‘igt_parse_connector_tile_blob’; did you mean ‘igt_pipe_connector_valid’? [-Werror=implicit-function-declaration]
             igt_parse_connector_tile_blob(blob, &tile);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
             igt_pipe_connector_valid
../tests/kms_dp_tiled_display.c:96:13: warning: nested extern declaration of ‘igt_parse_connector_tile_blob’ [-Wnested-externs]
../tests/kms_dp_tiled_display.c:97:37: error: request for member ‘num_h_tile’ in something not a structure or union
             data->num_h_tiles = tile.num_h_tile;
                                     ^
../tests/kms_dp_tiled_display.c: In function ‘set_test_pattern_fb’:
../tests/kms_dp_tiled_display.c:109:5: error: unknown type name ‘igt_tile_info_t’; did you mean ‘snd_timer_info_t’?
     igt_tile_info_t tile;
     ^~~~~~~~~~~~~~~
     snd_timer_info_t
../tests/kms_dp_tiled_display.c:169:59: error: request for member ‘tile_h_size’ in something not a structure or union
                                     (conn_data[count].tile->tile_h_size *\
                                                           ^~
../tests/kms_dp_tiled_display.c:171:59: error: request for member ‘tile_v_size’ in something not a structure or union
                                      conn_data[count].tile->tile_v_size,\
                                                           ^~
../tests/kms_dp_tiled_display.c:182:54: error: request for member ‘tile_h_size’ in something not a structure or union
                                 conn_data[count].tile->tile_h_size,\
                                                      ^~
../tests/kms_dp_tiled_display.c:183:54: error: request for member ‘tile_v_size’ in something not a structure or union
                                 conn_data[count].tile->tile_v_size);
                                                      ^~
../tests/kms_dp_tiled_display.c:187:59: error: request for member ‘tile_h_size’ in something not a structure or union
                                     (conn_data[count].tile->tile_h_size *\
                                                           ^~
../tests/kms_dp_tiled_display.c:188:58: error: request for member ‘tile_h_loc’ in something not a structure or union
                                     conn_data[count].tile->tile_h_loc),
                                                          ^~
../tests/kms_dp_tiled_display.c:189:59: error: request for member ‘tile_v_size’ in something not a structure or union
                                     (conn_data[count].tile->tile_v_size *\
                                                           ^~
../tests/kms_dp_tiled_display.c:190:58: error: request for member ‘tile_v_loc’ in something not a structure or union
                                     conn_data[count].tile->tile_v_loc));
                                                          ^~
../tests/kms_dp_tiled_display.c:193:57: error: request for member ‘tile_h_size’ in something not a structure or union
                                    conn_data[count].tile->tile_h_size,\
                                                         ^~
../tests/kms_dp_tiled_display.c:194:57: error: request for member ‘tile_v_size’ in something not a structure or union
                                    conn_data[count].tile->tile_v_size);
                                                         ^~
cc1: some warnings being treated as errors
ninja: build stopped: subcommand failed.

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [igt-dev] ✗ GitLab.Pipeline: warning for igt/tests/kms_dp_tiled_display.c : kms test file for display port tiled displays
  2019-07-17 18:02 [igt-dev] [PATCH i-g-t] igt/tests/kms_dp_tiled_display.c : kms test file for display port tiled displays Madhumitha Tolakanahalli Pradeep
  2019-07-17 18:35 ` [igt-dev] ✗ Fi.CI.BAT: failure for " Patchwork
@ 2019-07-17 18:56 ` Patchwork
  2019-07-18  6:43 ` [igt-dev] [PATCH i-g-t] " Ser, Simon
  2 siblings, 0 replies; 18+ messages in thread
From: Patchwork @ 2019-07-17 18:56 UTC (permalink / raw)
  To: Madhumitha Tolakanahalli Pradeep; +Cc: igt-dev

== Series Details ==

Series: igt/tests/kms_dp_tiled_display.c : kms test file for display port tiled displays
URL   : https://patchwork.freedesktop.org/series/63830/
State : warning

== Summary ==

Pipeline status: FAILED.

See https://gitlab.freedesktop.org/gfx-ci/igt-ci-tags/pipelines/49480 for more details.

== Logs ==

For more details see: https://gitlab.freedesktop.org/gfx-ci/igt-ci-tags/pipelines/49480
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [igt-dev] [PATCH i-g-t] igt/tests/kms_dp_tiled_display.c : kms test file for display port tiled displays
  2019-07-17 18:02 [igt-dev] [PATCH i-g-t] igt/tests/kms_dp_tiled_display.c : kms test file for display port tiled displays Madhumitha Tolakanahalli Pradeep
  2019-07-17 18:35 ` [igt-dev] ✗ Fi.CI.BAT: failure for " Patchwork
  2019-07-17 18:56 ` [igt-dev] ✗ GitLab.Pipeline: warning " Patchwork
@ 2019-07-18  6:43 ` Ser, Simon
  2019-07-30 19:21   ` Manasi Navare
  2019-07-31  0:42   ` Tolakanahalli Pradeep, Madhumitha
  2 siblings, 2 replies; 18+ messages in thread
From: Ser, Simon @ 2019-07-18  6:43 UTC (permalink / raw)
  To: igt-dev, Tolakanahalli Pradeep, Madhumitha
  Cc: Navare, Manasi D, Latvala, Petri

Thanks for your patch! Here are some comments.

Style: we use tabs for indentation, not spaces.

On Wed, 2019-07-17 at 11:02 -0700, Madhumitha Tolakanahalli Pradeep wrote:
> This test validates the tiled DP displays to display a test pattern seamlessly
> across the two tiles. It validates the transcoder port sync feature on i915 to
> get a tearfree tiled display output.
> 
> Related kernel work patches -> https://patchwork.freedesktop.org/series/59837/#rev4.
> This test can eventually be extended to cover tiled display support on other connector
> types.
> 
> Cc: Manasi Navare <manasi.d.navare@intel.com>
> Cc: Petri Latvala <petri.latvala@intel.com>
> Signed-off-by: Madhumitha Tolakanahalli Pradeep <madhumitha.tolakanahalli.pradeep@intel.com>

Next time, can you send both patches in one go? It's not possible to
check whether this test actually passes CI, since build fails (see the
two automated failure replies).

To learn how to use git-send-email, you can read:
https://git-send-email.io/

> ---
>  tests/Makefile.sources       |   1 +
>  tests/kms_dp_tiled_display.c | 239 +++++++++++++++++++++++++++++++++++
>  tests/meson.build            |   1 +
>  3 files changed, 241 insertions(+)
>  create mode 100644 tests/kms_dp_tiled_display.c
> 
> diff --git a/tests/Makefile.sources b/tests/Makefile.sources
> index 250dbd33..e9373941 100644
> --- a/tests/Makefile.sources
> +++ b/tests/Makefile.sources
> @@ -40,6 +40,7 @@ TESTS_progs = \
>  	kms_cursor_edge_walk \
>  	kms_cursor_legacy \
>  	kms_dp_dsc \
> +	kms_dp_tiled_display \
>  	kms_draw_crc \
>  	kms_fbcon_fbt \
>  	kms_fence_pin_leak \
> diff --git a/tests/kms_dp_tiled_display.c b/tests/kms_dp_tiled_display.c
> new file mode 100644
> index 00000000..af644573
> --- /dev/null
> +++ b/tests/kms_dp_tiled_display.c
> @@ -0,0 +1,239 @@
> +/*
> + * Copyright © 2018 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.
> + *
> + * Authors:
> + *  Madhumitha Tolakanahalli Pradeep
> + *      <madhumitha.tolakanahalli.pradeep@intel.com>
> + *
> + * Display Port Tiled Display Test
> + * This test parses the tile information of the connectors that have TILE
> + * property set, sets up the framebuffer with correct offsets corresponding to
> + * the tile offsets and does an atomic modeset with two CRTCs for two
> + * connectors.
> + *
> + * This test currently supports only horizontally tiled displays, in line with
> + * the displays supported by the kernel at the moment.
> + */
> +
> +#include "drm_mode.h"
> +#include "drm_fourcc.h"
> +#include "igt.h"
> +
> +typedef struct {
> +    int drm_fd;
> +    int num_h_tiles;
> +    igt_display_t *display;
> +    enum igt_commit_style commit;
> +} data_t;
> +
> +typedef struct {
> +    igt_output_t *output;
> +    igt_tile_info_t *tile;
> +    igt_fb_t fb_test_pattern;
> +    drmModeConnectorPtr connector;
> +    enum pipe pipe;
> +    enum igt_commit_style commit;
> +} data_connector_t;
> +
> +static inline int drm_property_is_tile(drmModePropertyPtr prop)

I wouldn't personally use `inline`. The compiler is smarter than humans
to decide whether or not a function should be inlined.

> +{
> +	return(strcmp(prop->name ? prop->name : "", "TILE")? 0 : 1);

Style: unnecessary parentheses, missing space before `?`.

> +}
> +
> +static void get_number_of_h_tiles(data_t *data)

What if multiple tiles are connected? Shouldn't we use tile_group_id?

> +{
> +    int i;
> +    drmModeRes *res;
> +    drmModeConnector *connector;
> +    drmModePropertyPtr prop;
> +    drmModePropertyBlobPtr blob;
> +    igt_tile_info_t tile;
> +
> +    igt_require(res = drmModeGetResources(data->drm_fd));

This should probably be igt_assert.

> +    for(i = 0; i < res->count_connectors; i++)
> +    {

Style: no newline before `{` (only for functions, applies to the whole
patch).

> +        connector = drmModeGetConnectorCurrent(data->drm_fd, \

Style: unnecessary `\`.

We could igt_assert(connector).

> +                                               res->connectors[i]);
> +
> +        if(!((connector->connection == DRM_MODE_CONNECTED) &&
> +            (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort)))
> +                continue;

Style: we can invert this condition to make clearer.

> +
> +        for(i = 0; i < connector->count_props; i++)
> +        {
> +            prop = drmModeGetProperty(data->drm_fd, connector->props[i]);

We could igt_assert(prop)

We need to free it at some point.

> +            if(!(drm_property_is_tile(prop) &&

Style: missing space after if keyword (applies to the whole patch).

> +                drm_property_type_is(prop, DRM_MODE_PROP_BLOB)))

I'd move this check into drm_property_is_tile.

> +                continue;
> +
> +            blob = drmModeGetPropertyBlob(data->drm_fd, \
> +                                          connector->prop_values[i]);
> +
> +            if(!blob)
> +                break;
> +            igt_parse_connector_tile_blob(blob, &tile);
> +            data->num_h_tiles = tile.num_h_tile;
> +            break;
> +        }
> +    }
> +}
> +
> +static int set_test_pattern_fb(data_t *data, data_connector_t *conn_data)
> +{
> +    int i;
> +    int count = 0;
> +    bool is_tile = false;
> +    enum pipe pipe;
> +    igt_tile_info_t tile;
> +    igt_output_t *output;
> +    igt_plane_t *primary;
> +    drmModePropertyPtr prop;
> +    drmModePropertyBlobPtr blob;
> +
> +    for_each_connected_output(data->display, output)
> +    {
> +        is_tile = false;
> +
> +        conn_data[count].connector = drmModeGetConnector(data->display->drm_fd, \
> +                                                         output->id);
> +
> +        if(!(conn_data[count].connector->connector_type ==
> +                        DRM_MODE_CONNECTOR_DisplayPort))
> +            continue;
> +
> +        /* Parse through each connector property */
> +        for(i = 0; i < conn_data[count].connector->count_props; i++)
> +        {
> +            prop = drmModeGetProperty(data->display->drm_fd, \
> +                                      conn_data[count].connector->props[i]);
> +
> +            if(!((drm_property_is_tile(prop) &&
> +                drm_property_type_is(prop, DRM_MODE_PROP_BLOB))))
> +                continue;
> +
> +            blob = drmModeGetPropertyBlob(data->display->drm_fd, \
> +                            conn_data[count].connector->prop_values[i]);
> +
> +            if(!blob)
> +                break;
> +
> +            igt_parse_connector_tile_blob(blob, &tile);
> +            conn_data[count].tile = &tile;
> +            is_tile = true;
> +            break;
> +        }

I feel like this whole block above is duplicated. Could be extracted
into a function, e.g.

    bool connector_get_tile(drmModeConnectorRes *conn, igt_tile_info_t *tile_info)

> +        if(!is_tile)
> +            continue;
> +
> +        output = igt_output_from_connector(data->display, \
> +                                           conn_data[count].connector);

Style: unnecessary `\`. Applies to the whole patch.

> +
> +        for_each_pipe(data->display, pipe)
> +        {
> +            igt_debug("Current PIPE is %d\n", pipe);
> +
> +            if((count > 0) && (pipe == conn_data[count-1].pipe))
> +                continue;

Style: unnecessary parentheses.

> +            if(igt_pipe_connector_valid(pipe, output)) {
> +                conn_data[count].pipe = pipe;
> +                conn_data[count].output = output;
> +
> +                igt_output_set_pipe(conn_data[count].output, \
> +                                    conn_data[count].pipe);
> +
> +                igt_create_pattern_fb(data->drm_fd,\
> +                                    (conn_data[count].tile->tile_h_size *\
> +                                     data->num_h_tiles),\
> +                                     conn_data[count].tile->tile_v_size,\
> +                                     DRM_FORMAT_XBGR8888,\
> +                                     LOCAL_DRM_FORMAT_MOD_NONE,\
> +                                     &conn_data[count].fb_test_pattern);
> +
> +                primary = igt_output_get_plane_type(conn_data[count].output,\
> +                                                    DRM_PLANE_TYPE_PRIMARY);
> +
> +                igt_plane_set_fb(primary, &conn_data[count].fb_test_pattern);
> +
> +                igt_fb_set_size(&conn_data[count].fb_test_pattern, primary,\
> +                                conn_data[count].tile->tile_h_size,\
> +                                conn_data[count].tile->tile_v_size);
> +
> +                igt_fb_set_position(&conn_data[count].fb_test_pattern, \
> +                                    primary,\
> +                                    (conn_data[count].tile->tile_h_size *\
> +                                    conn_data[count].tile->tile_h_loc),
> +                                    (conn_data[count].tile->tile_v_size *\
> +                                    conn_data[count].tile->tile_v_loc));
> +
> +                igt_plane_set_size(primary,\
> +                                   conn_data[count].tile->tile_h_size,\
> +                                   conn_data[count].tile->tile_v_size);
> +
> +                break;
> +            }
> +        }
> +        count++;
> +    }
> +
> +    return count;
> +}
> +
> +igt_main
> +{
> +    igt_display_t display;
> +    data_t data = {};
> +    data_connector_t *conn_data;
> +
> +    igt_fixture {
> +        data.drm_fd = drm_open_driver_master(DRIVER_ANY);
> +        kmstest_set_vt_graphics_mode();
> +        igt_display_require(&display, data.drm_fd);
> +        data.display = &display;
> +
> +        get_number_of_h_tiles(&data);
> +        igt_debug("Number of Horizontal Tiles: %d\n", data.num_h_tiles);
> +        data.commit = data.display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY;
> +    }
> +
> +    if(data.num_h_tiles > 0)
> +        conn_data = (data_connector_t *)malloc(data.num_h_tiles * \
> +                                                sizeof(data_connector_t));

No need for this cast, unnecessary `\`.

> +    igt_assert(conn_data);

This check reads garbage from the stack if data.num_h_tiles == 0.

> +    igt_subtest_f("basic-test-pattern") {

No need for the _f suffix.

This subtest is missing a description. Could you add one? For more
information, see:
https://drm.pages.freedesktop.org/igt-gpu-tools/igt-gpu-tools-Core.html#igt-describe

> +        igt_skip_on(!data.num_h_tiles);
> +        set_test_pattern_fb(&data, conn_data);
> +        igt_display_commit2(data.display, data.commit);

I'm not sure I understand what this test checks. It does a commit on
all tiled connectors, but doesn't check anything afterwards. Maybe it
should check the pageflip serial and timings?

> +    }
> +
> +    igt_fixture {
> +        if(data.num_h_tiles > 0)
> +            free(conn_data);

If conn_data was initialized to NULL, no need for the check, because
free(NULL) is a no-op.

> +        kmstest_restore_vt_mode();
> +        igt_display_fini(data.display);
> +    }
> +}
> diff --git a/tests/meson.build b/tests/meson.build
> index 34a74025..6a6e9ce9 100644
> --- a/tests/meson.build
> +++ b/tests/meson.build
> @@ -25,6 +25,7 @@ test_progs = [
>  	'kms_cursor_edge_walk',
>  	'kms_cursor_legacy',
>  	'kms_dp_dsc',
> +	'kms_dp_tiled_display',
>  	'kms_draw_crc',
>  	'kms_fbcon_fbt',
>  	'kms_fence_pin_leak',
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [igt-dev] [PATCH i-g-t] igt/tests/kms_dp_tiled_display.c : kms test file for display port tiled displays
  2019-07-18  6:43 ` [igt-dev] [PATCH i-g-t] " Ser, Simon
@ 2019-07-30 19:21   ` Manasi Navare
  2019-07-31  7:25     ` Ser, Simon
  2019-07-31  0:42   ` Tolakanahalli Pradeep, Madhumitha
  1 sibling, 1 reply; 18+ messages in thread
From: Manasi Navare @ 2019-07-30 19:21 UTC (permalink / raw)
  To: Ser, Simon; +Cc: igt-dev, Latvala, Petri

On Wed, Jul 17, 2019 at 11:43:48PM -0700, Ser, Simon wrote:
> Thanks for your patch! Here are some comments.
> 
> Style: we use tabs for indentation, not spaces.
> 
> On Wed, 2019-07-17 at 11:02 -0700, Madhumitha Tolakanahalli Pradeep wrote:
> > This test validates the tiled DP displays to display a test pattern seamlessly
> > across the two tiles. It validates the transcoder port sync feature on i915 to
> > get a tearfree tiled display output.
> > 
> > Related kernel work patches -> https://patchwork.freedesktop.org/series/59837/#rev4.
> > This test can eventually be extended to cover tiled display support on other connector
> > types.
> > 
> > Cc: Manasi Navare <manasi.d.navare@intel.com>
> > Cc: Petri Latvala <petri.latvala@intel.com>
> > Signed-off-by: Madhumitha Tolakanahalli Pradeep <madhumitha.tolakanahalli.pradeep@intel.com>
> 
> Next time, can you send both patches in one go? It's not possible to
> check whether this test actually passes CI, since build fails (see the
> two automated failure replies).

Yes please send this as a series with 1st patch that defines the tile parser
and second with the actual test that uses it

> 
> To learn how to use git-send-email, you can read:
> https://git-send-email.io/
> 
> > ---
> >  tests/Makefile.sources       |   1 +
> >  tests/kms_dp_tiled_display.c | 239 +++++++++++++++++++++++++++++++++++
> >  tests/meson.build            |   1 +
> >  3 files changed, 241 insertions(+)
> >  create mode 100644 tests/kms_dp_tiled_display.c
> > 
> > diff --git a/tests/Makefile.sources b/tests/Makefile.sources
> > index 250dbd33..e9373941 100644
> > --- a/tests/Makefile.sources
> > +++ b/tests/Makefile.sources
> > @@ -40,6 +40,7 @@ TESTS_progs = \
> >  	kms_cursor_edge_walk \
> >  	kms_cursor_legacy \
> >  	kms_dp_dsc \
> > +	kms_dp_tiled_display \
> >  	kms_draw_crc \
> >  	kms_fbcon_fbt \
> >  	kms_fence_pin_leak \
> > diff --git a/tests/kms_dp_tiled_display.c b/tests/kms_dp_tiled_display.c
> > new file mode 100644
> > index 00000000..af644573
> > --- /dev/null
> > +++ b/tests/kms_dp_tiled_display.c
> > @@ -0,0 +1,239 @@
> > +/*
> > + * Copyright © 2018 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.
> > + *
> > + * Authors:
> > + *  Madhumitha Tolakanahalli Pradeep
> > + *      <madhumitha.tolakanahalli.pradeep@intel.com>
> > + *
> > + * Display Port Tiled Display Test
> > + * This test parses the tile information of the connectors that have TILE
> > + * property set, sets up the framebuffer with correct offsets corresponding to
> > + * the tile offsets and does an atomic modeset with two CRTCs for two
> > + * connectors.
> > + *
> > + * This test currently supports only horizontally tiled displays, in line with
> > + * the displays supported by the kernel at the moment.
> > + */
> > +
> > +#include "drm_mode.h"
> > +#include "drm_fourcc.h"
> > +#include "igt.h"
> > +
> > +typedef struct {
> > +    int drm_fd;
> > +    int num_h_tiles;
> > +    igt_display_t *display;
> > +    enum igt_commit_style commit;
> > +} data_t;
> > +
> > +typedef struct {
> > +    igt_output_t *output;
> > +    igt_tile_info_t *tile;
> > +    igt_fb_t fb_test_pattern;
> > +    drmModeConnectorPtr connector;
> > +    enum pipe pipe;
> > +    enum igt_commit_style commit;
> > +} data_connector_t;
> > +
> > +static inline int drm_property_is_tile(drmModePropertyPtr prop)
> 
> I wouldn't personally use `inline`. The compiler is smarter than humans
> to decide whether or not a function should be inlined.
> 
> > +{
> > +	return(strcmp(prop->name ? prop->name : "", "TILE")? 0 : 1);
> 
> Style: unnecessary parentheses, missing space before `?`.
> 
> > +}
> > +
> > +static void get_number_of_h_tiles(data_t *data)
> 
> What if multiple tiles are connected? Shouldn't we use tile_group_id?

Yes there could be multiple monitors with tiles so use tile_group_id to check
that the tile belongs to the same group and then use num_h_tiles

> 
> > +{
> > +    int i;
> > +    drmModeRes *res;
> > +    drmModeConnector *connector;
> > +    drmModePropertyPtr prop;
> > +    drmModePropertyBlobPtr blob;
> > +    igt_tile_info_t tile;
> > +
> > +    igt_require(res = drmModeGetResources(data->drm_fd));
> 
> This should probably be igt_assert.
> 
> > +    for(i = 0; i < res->count_connectors; i++)
> > +    {
> 
> Style: no newline before `{` (only for functions, applies to the whole
> patch).
> 
> > +        connector = drmModeGetConnectorCurrent(data->drm_fd, \
> 
> Style: unnecessary `\`.
> 
> We could igt_assert(connector).
> 
> > +                                               res->connectors[i]);
> > +
> > +        if(!((connector->connection == DRM_MODE_CONNECTED) &&
> > +            (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort)))
> > +                continue;
> 
> Style: we can invert this condition to make clearer.

But wouldnt that add additional nesting?

> 
> > +
> > +        for(i = 0; i < connector->count_props; i++)
> > +        {
> > +            prop = drmModeGetProperty(data->drm_fd, connector->props[i]);
> 
> We could igt_assert(prop)
> 
> We need to free it at some point.
> 
> > +            if(!(drm_property_is_tile(prop) &&
> 
> Style: missing space after if keyword (applies to the whole patch).
> 
> > +                drm_property_type_is(prop, DRM_MODE_PROP_BLOB)))
> 
> I'd move this check into drm_property_is_tile.
> 
> > +                continue;
> > +
> > +            blob = drmModeGetPropertyBlob(data->drm_fd, \
> > +                                          connector->prop_values[i]);
> > +
> > +            if(!blob)
> > +                break;
> > +            igt_parse_connector_tile_blob(blob, &tile);
> > +            data->num_h_tiles = tile.num_h_tile;
> > +            break;
> > +        }
> > +    }
> > +}
> > +
> > +static int set_test_pattern_fb(data_t *data, data_connector_t *conn_data)
> > +{
> > +    int i;
> > +    int count = 0;
> > +    bool is_tile = false;
> > +    enum pipe pipe;
> > +    igt_tile_info_t tile;
> > +    igt_output_t *output;
> > +    igt_plane_t *primary;
> > +    drmModePropertyPtr prop;
> > +    drmModePropertyBlobPtr blob;
> > +
> > +    for_each_connected_output(data->display, output)
> > +    {
> > +        is_tile = false;
> > +
> > +        conn_data[count].connector = drmModeGetConnector(data->display->drm_fd, \
> > +                                                         output->id);
> > +
> > +        if(!(conn_data[count].connector->connector_type ==
> > +                        DRM_MODE_CONNECTOR_DisplayPort))
> > +            continue;
> > +
> > +        /* Parse through each connector property */
> > +        for(i = 0; i < conn_data[count].connector->count_props; i++)
> > +        {
> > +            prop = drmModeGetProperty(data->display->drm_fd, \
> > +                                      conn_data[count].connector->props[i]);
> > +
> > +            if(!((drm_property_is_tile(prop) &&
> > +                drm_property_type_is(prop, DRM_MODE_PROP_BLOB))))
> > +                continue;
> > +
> > +            blob = drmModeGetPropertyBlob(data->display->drm_fd, \
> > +                            conn_data[count].connector->prop_values[i]);
> > +
> > +            if(!blob)
> > +                break;
> > +
> > +            igt_parse_connector_tile_blob(blob, &tile);
> > +            conn_data[count].tile = &tile;
> > +            is_tile = true;
> > +            break;
> > +        }
> 
> I feel like this whole block above is duplicated. Could be extracted
> into a function, e.g.
> 
>     bool connector_get_tile(drmModeConnectorRes *conn, igt_tile_info_t *tile_info)
> 
> > +        if(!is_tile)
> > +            continue;
> > +
> > +        output = igt_output_from_connector(data->display, \
> > +                                           conn_data[count].connector);
> 
> Style: unnecessary `\`. Applies to the whole patch.
> 
> > +
> > +        for_each_pipe(data->display, pipe)
> > +        {
> > +            igt_debug("Current PIPE is %d\n", pipe);
> > +
> > +            if((count > 0) && (pipe == conn_data[count-1].pipe))
> > +                continue;
> 
> Style: unnecessary parentheses.
> 
> > +            if(igt_pipe_connector_valid(pipe, output)) {
> > +                conn_data[count].pipe = pipe;
> > +                conn_data[count].output = output;
> > +
> > +                igt_output_set_pipe(conn_data[count].output, \
> > +                                    conn_data[count].pipe);
> > +
> > +                igt_create_pattern_fb(data->drm_fd,\
> > +                                    (conn_data[count].tile->tile_h_size *\
> > +                                     data->num_h_tiles),\
> > +                                     conn_data[count].tile->tile_v_size,\
> > +                                     DRM_FORMAT_XBGR8888,\
> > +                                     LOCAL_DRM_FORMAT_MOD_NONE,\
> > +                                     &conn_data[count].fb_test_pattern);
> > +
> > +                primary = igt_output_get_plane_type(conn_data[count].output,\
> > +                                                    DRM_PLANE_TYPE_PRIMARY);
> > +
> > +                igt_plane_set_fb(primary, &conn_data[count].fb_test_pattern);
> > +
> > +                igt_fb_set_size(&conn_data[count].fb_test_pattern, primary,\
> > +                                conn_data[count].tile->tile_h_size,\
> > +                                conn_data[count].tile->tile_v_size);
> > +
> > +                igt_fb_set_position(&conn_data[count].fb_test_pattern, \
> > +                                    primary,\
> > +                                    (conn_data[count].tile->tile_h_size *\
> > +                                    conn_data[count].tile->tile_h_loc),
> > +                                    (conn_data[count].tile->tile_v_size *\
> > +                                    conn_data[count].tile->tile_v_loc));
> > +
> > +                igt_plane_set_size(primary,\
> > +                                   conn_data[count].tile->tile_h_size,\
> > +                                   conn_data[count].tile->tile_v_size);
> > +
> > +                break;
> > +            }
> > +        }
> > +        count++;
> > +    }
> > +
> > +    return count;
> > +}
> > +
> > +igt_main
> > +{
> > +    igt_display_t display;
> > +    data_t data = {};
> > +    data_connector_t *conn_data;
> > +
> > +    igt_fixture {
> > +        data.drm_fd = drm_open_driver_master(DRIVER_ANY);
> > +        kmstest_set_vt_graphics_mode();
> > +        igt_display_require(&display, data.drm_fd);
> > +        data.display = &display;
> > +
> > +        get_number_of_h_tiles(&data);
> > +        igt_debug("Number of Horizontal Tiles: %d\n", data.num_h_tiles);
> > +        data.commit = data.display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY;
> > +    }
> > +
> > +    if(data.num_h_tiles > 0)
> > +        conn_data = (data_connector_t *)malloc(data.num_h_tiles * \
> > +                                                sizeof(data_connector_t));
> 
> No need for this cast, unnecessary `\`.
> 
> > +    igt_assert(conn_data);
> 
> This check reads garbage from the stack if data.num_h_tiles == 0.

This check should possibly be inside the same if

> 
> > +    igt_subtest_f("basic-test-pattern") {
> 
> No need for the _f suffix.
> 
> This subtest is missing a description. Could you add one? For more
> information, see:
> https://drm.pages.freedesktop.org/igt-gpu-tools/igt-gpu-tools-Core.html#igt-describe
> 
> > +        igt_skip_on(!data.num_h_tiles);
> > +        set_test_pattern_fb(&data, conn_data);
> > +        igt_display_commit2(data.display, data.commit);
> 
> I'm not sure I understand what this test checks. It does a commit on
> all tiled connectors, but doesn't check anything afterwards. Maybe it
> should check the pageflip serial and timings?

This is so far a manual test where we just look at the pattern and make sure no artifacts
and auto testing just make sure the commit did not fail, any better idea to check if the
page_flip timeouts didnt occur or not sure if we can do crc checks to ensure no artifacts?
Any ideas/suggestions?

Manasi

> 
> > +    }
> > +
> > +    igt_fixture {
> > +        if(data.num_h_tiles > 0)
> > +            free(conn_data);
> 
> If conn_data was initialized to NULL, no need for the check, because
> free(NULL) is a no-op.
> 
> > +        kmstest_restore_vt_mode();
> > +        igt_display_fini(data.display);
> > +    }
> > +}
> > diff --git a/tests/meson.build b/tests/meson.build
> > index 34a74025..6a6e9ce9 100644
> > --- a/tests/meson.build
> > +++ b/tests/meson.build
> > @@ -25,6 +25,7 @@ test_progs = [
> >  	'kms_cursor_edge_walk',
> >  	'kms_cursor_legacy',
> >  	'kms_dp_dsc',
> > +	'kms_dp_tiled_display',
> >  	'kms_draw_crc',
> >  	'kms_fbcon_fbt',
> >  	'kms_fence_pin_leak',
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [igt-dev] [PATCH i-g-t] igt/tests/kms_dp_tiled_display.c : kms test file for display port tiled displays
  2019-07-18  6:43 ` [igt-dev] [PATCH i-g-t] " Ser, Simon
  2019-07-30 19:21   ` Manasi Navare
@ 2019-07-31  0:42   ` Tolakanahalli Pradeep, Madhumitha
  2019-07-31  8:15     ` Ser, Simon
  1 sibling, 1 reply; 18+ messages in thread
From: Tolakanahalli Pradeep, Madhumitha @ 2019-07-31  0:42 UTC (permalink / raw)
  To: igt-dev, Ser, Simon; +Cc: Navare, Manasi D, Latvala, Petri

Thank you very much for your comments, Simon.

Thanks for pointing out the style realted issues, I have them
fixed (tabs, `\` etc).

On Thu, 2019-07-18 at 07:43 +0100, Ser, Simon wrote:
> Thanks for your patch! Here are some comments.
> 
> Style: we use tabs for indentation, not spaces.
> 
> On Wed, 2019-07-17 at 11:02 -0700, Madhumitha Tolakanahalli Pradeep
> wrote:
> > This test validates the tiled DP displays to display a test pattern
> > seamlessly
> > across the two tiles. It validates the transcoder port sync feature
> > on i915 to
> > get a tearfree tiled display output.
> > 
> > Related kernel work patches -> 
> > https://patchwork.freedesktop.org/series/59837/#rev4.
> > This test can eventually be extended to cover tiled display support
> > on other connector
> > types.
> > 
> > Cc: Manasi Navare <manasi.d.navare@intel.com>
> > Cc: Petri Latvala <petri.latvala@intel.com>
> > Signed-off-by: Madhumitha Tolakanahalli Pradeep <
> > madhumitha.tolakanahalli.pradeep@intel.com>
> 
> Next time, can you send both patches in one go? It's not possible to
> check whether this test actually passes CI, since build fails (see
> the
> two automated failure replies).

My apologies, I shall keep that in mind for the next time.

> To learn how to use git-send-email, you can read:
> https://git-send-email.io/
> 
> > ---
> >  tests/Makefile.sources       |   1 +
> >  tests/kms_dp_tiled_display.c | 239
> > +++++++++++++++++++++++++++++++++++
> >  tests/meson.build            |   1 +
> >  3 files changed, 241 insertions(+)
> >  create mode 100644 tests/kms_dp_tiled_display.c
> > 
> > diff --git a/tests/Makefile.sources b/tests/Makefile.sources
> > index 250dbd33..e9373941 100644
> > --- a/tests/Makefile.sources
> > +++ b/tests/Makefile.sources
> > @@ -40,6 +40,7 @@ TESTS_progs = \
> >  	kms_cursor_edge_walk \
> >  	kms_cursor_legacy \
> >  	kms_dp_dsc \
> > +	kms_dp_tiled_display \
> >  	kms_draw_crc \
> >  	kms_fbcon_fbt \
> >  	kms_fence_pin_leak \
> > diff --git a/tests/kms_dp_tiled_display.c
> > b/tests/kms_dp_tiled_display.c
> > new file mode 100644
> > index 00000000..af644573
> > --- /dev/null
> > +++ b/tests/kms_dp_tiled_display.c
> > @@ -0,0 +1,239 @@
> > +/*
> > + * Copyright © 2018 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.
> > + *
> > + * Authors:
> > + *  Madhumitha Tolakanahalli Pradeep
> > + *      <madhumitha.tolakanahalli.pradeep@intel.com>
> > + *
> > + * Display Port Tiled Display Test
> > + * This test parses the tile information of the connectors that
> > have TILE
> > + * property set, sets up the framebuffer with correct offsets
> > corresponding to
> > + * the tile offsets and does an atomic modeset with two CRTCs for
> > two
> > + * connectors.
> > + *
> > + * This test currently supports only horizontally tiled displays,
> > in line with
> > + * the displays supported by the kernel at the moment.
> > + */
> > +
> > +#include "drm_mode.h"
> > +#include "drm_fourcc.h"
> > +#include "igt.h"
> > +
> > +typedef struct {
> > +    int drm_fd;
> > +    int num_h_tiles;
> > +    igt_display_t *display;
> > +    enum igt_commit_style commit;
> > +} data_t;
> > +
> > +typedef struct {
> > +    igt_output_t *output;
> > +    igt_tile_info_t *tile;
> > +    igt_fb_t fb_test_pattern;
> > +    drmModeConnectorPtr connector;
> > +    enum pipe pipe;
> > +    enum igt_commit_style commit;
> > +} data_connector_t;
> > +
> > +static inline int drm_property_is_tile(drmModePropertyPtr prop)
> 
> I wouldn't personally use `inline`. The compiler is smarter than
> humans
> to decide whether or not a function should be inlined.
> 

Makes sense, I shall remove 'inline'.

> > +{
> > +	return(strcmp(prop->name ? prop->name : "", "TILE")? 0 : 1);
> 
> Style: unnecessary parentheses, missing space before `?`.
> 
> > +}
> > +
> > +static void get_number_of_h_tiles(data_t *data)
> 
> What if multiple tiles are connected? Shouldn't we use tile_group_id?

Currently, the hardware does not support displays that are connected to
multiple tiles. Only connectors with the same tile_group_id are
supported for tiled monitors. 
I was thinking of adding a check for making sure both the connected DP
connectors belong to the same tile group as that make the test more
robust. Any suggestions for the same?

> 
> 
> > +{
> > +    int i;
> > +    drmModeRes *res;
> > +    drmModeConnector *connector;
> > +    drmModePropertyPtr prop;
> > +    drmModePropertyBlobPtr blob;
> > +    igt_tile_info_t tile;
> > +
> > +    igt_require(res = drmModeGetResources(data->drm_fd));
> 
> This should probably be igt_assert.

Yes, makes sense. I shall update it for rev2.

> 
> > +    for(i = 0; i < res->count_connectors; i++)
> > +    {
> 
> Style: no newline before `{` (only for functions, applies to the
> whole
> patch).
> 
> > +        connector = drmModeGetConnectorCurrent(data->drm_fd, \
> 
> Style: unnecessary `\`.
> 
> We could igt_assert(connector).

Yes, makes sense. I shall update it for rev2.

> 
> > +                                               res-
> > >connectors[i]);
> > +
> > +        if(!((connector->connection == DRM_MODE_CONNECTED) &&
> > +            (connector->connector_type ==
> > DRM_MODE_CONNECTOR_DisplayPort)))
> > +                continue;
> 
> Style: we can invert this condition to make clearer.

This was done to reduce nesting. Would you suggest we do otherwise?

> 
> > +
> > +        for(i = 0; i < connector->count_props; i++)
> > +        {
> > +            prop = drmModeGetProperty(data->drm_fd, connector-
> > >props[i]);
> 
> We could igt_assert(prop)

Yes, makes sense. I shall update it for rev2.

> We need to free it at some point.

'prop' is a local pointer that isnt dynamically allocated. Not too sure
why that would need free-ing. Could you please provide more clarity on
the above comment?

> 
> > +            if(!(drm_property_is_tile(prop) &&
> 
> Style: missing space after if keyword (applies to the whole patch).
> 
> > +                drm_property_type_is(prop, DRM_MODE_PROP_BLOB)))
> 
> I'd move this check into drm_property_is_tile.

Yes, makes sense. I shall update it for rev2.

> 
> > +                continue;
> > +
> > +            blob = drmModeGetPropertyBlob(data->drm_fd, \
> > +                                          connector-
> > >prop_values[i]);
> > +
> > +            if(!blob)
> > +                break;
> > +            igt_parse_connector_tile_blob(blob, &tile);
> > +            data->num_h_tiles = tile.num_h_tile;
> > +            break;
> > +        }
> > +    }
> > +}
> > +
> > +static int set_test_pattern_fb(data_t *data, data_connector_t
> > *conn_data)
> > +{
> > +    int i;
> > +    int count = 0;
> > +    bool is_tile = false;
> > +    enum pipe pipe;
> > +    igt_tile_info_t tile;
> > +    igt_output_t *output;
> > +    igt_plane_t *primary;
> > +    drmModePropertyPtr prop;
> > +    drmModePropertyBlobPtr blob;
> > +
> > +    for_each_connected_output(data->display, output)
> > +    {
> > +        is_tile = false;
> > +
> > +        conn_data[count].connector = drmModeGetConnector(data-
> > >display->drm_fd, \
> > +                                                         output-
> > >id);
> > +
> > +        if(!(conn_data[count].connector->connector_type ==
> > +                        DRM_MODE_CONNECTOR_DisplayPort))
> > +            continue;
> > +
> > +        /* Parse through each connector property */
> > +        for(i = 0; i < conn_data[count].connector->count_props;
> > i++)
> > +        {
> > +            prop = drmModeGetProperty(data->display->drm_fd, \
> > +                                      conn_data[count].connector-
> > >props[i]);
> > +
> > +            if(!((drm_property_is_tile(prop) &&
> > +                drm_property_type_is(prop, DRM_MODE_PROP_BLOB))))
> > +                continue;
> > +
> > +            blob = drmModeGetPropertyBlob(data->display->drm_fd, \
> > +                            conn_data[count].connector-
> > >prop_values[i]);
> > +
> > +            if(!blob)
> > +                break;
> > +
> > +            igt_parse_connector_tile_blob(blob, &tile);
> > +            conn_data[count].tile = &tile;
> > +            is_tile = true;
> > +            break;
> > +        }
> 
> I feel like this whole block above is duplicated. Could be extracted
> into a function, e.g.

I was contemplating on that too, shall do it for rev2.

>     bool connector_get_tile(drmModeConnectorRes *conn,
> igt_tile_info_t *tile_info)
> 
> > +        if(!is_tile)
> > +            continue;
> > +
> > +        output = igt_output_from_connector(data->display, \
> > +                                           conn_data[count].connec
> > tor);
> 
> Style: unnecessary `\`. Applies to the whole patch.
> 
> > +
> > +        for_each_pipe(data->display, pipe)
> > +        {
> > +            igt_debug("Current PIPE is %d\n", pipe);
> > +
> > +            if((count > 0) && (pipe == conn_data[count-1].pipe))
> > +                continue;
> 
> Style: unnecessary parentheses.
> 
> > +            if(igt_pipe_connector_valid(pipe, output)) {
> > +                conn_data[count].pipe = pipe;
> > +                conn_data[count].output = output;
> > +
> > +                igt_output_set_pipe(conn_data[count].output, \
> > +                                    conn_data[count].pipe);
> > +
> > +                igt_create_pattern_fb(data->drm_fd,\
> > +                                    (conn_data[count].tile-
> > >tile_h_size *\
> > +                                     data->num_h_tiles),\
> > +                                     conn_data[count].tile-
> > >tile_v_size,\
> > +                                     DRM_FORMAT_XBGR8888,\
> > +                                     LOCAL_DRM_FORMAT_MOD_NONE,\
> > +                                     &conn_data[count].fb_test_pat
> > tern);
> > +
> > +                primary =
> > igt_output_get_plane_type(conn_data[count].output,\
> > +                                                    DRM_PLANE_TYPE
> > _PRIMARY);
> > +
> > +                igt_plane_set_fb(primary,
> > &conn_data[count].fb_test_pattern);
> > +
> > +                igt_fb_set_size(&conn_data[count].fb_test_pattern,
> > primary,\
> > +                                conn_data[count].tile-
> > >tile_h_size,\
> > +                                conn_data[count].tile-
> > >tile_v_size);
> > +
> > +                igt_fb_set_position(&conn_data[count].fb_test_patt
> > ern, \
> > +                                    primary,\
> > +                                    (conn_data[count].tile-
> > >tile_h_size *\
> > +                                    conn_data[count].tile-
> > >tile_h_loc),
> > +                                    (conn_data[count].tile-
> > >tile_v_size *\
> > +                                    conn_data[count].tile-
> > >tile_v_loc));
> > +
> > +                igt_plane_set_size(primary,\
> > +                                   conn_data[count].tile-
> > >tile_h_size,\
> > +                                   conn_data[count].tile-
> > >tile_v_size);
> > +
> > +                break;
> > +            }
> > +        }
> > +        count++;
> > +    }
> > +
> > +    return count;
> > +}
> > +
> > +igt_main
> > +{
> > +    igt_display_t display;
> > +    data_t data = {};
> > +    data_connector_t *conn_data;
> > +
> > +    igt_fixture {
> > +        data.drm_fd = drm_open_driver_master(DRIVER_ANY);
> > +        kmstest_set_vt_graphics_mode();
> > +        igt_display_require(&display, data.drm_fd);
> > +        data.display = &display;
> > +
> > +        get_number_of_h_tiles(&data);
> > +        igt_debug("Number of Horizontal Tiles: %d\n",
> > data.num_h_tiles);
> > +        data.commit = data.display->is_atomic ? COMMIT_ATOMIC :
> > COMMIT_LEGACY;
> > +    }
> > +
> > +    if(data.num_h_tiles > 0)
> > +        conn_data = (data_connector_t *)malloc(data.num_h_tiles *
> > \
> > +                                                sizeof(data_connec
> > tor_t));
> 
> No need for this cast, unnecessary `\`.
> 
> > +    igt_assert(conn_data);
> 
> This check reads garbage from the stack if data.num_h_tiles == 0.

I moved the assert to igt_subtest block after igt_skip_on so that if
data.num_h_tiles == 0, assert would not be performed.

> 
> > +    igt_subtest_f("basic-test-pattern") {
> 
> No need for the _f suffix.

Yes, makes sense. I shall update it for rev2.

> 
> This subtest is missing a description. Could you add one? For more
> information, see:
> 
https://drm.pages.freedesktop.org/igt-gpu-tools/igt-gpu-tools-Core.html#igt-describe

I shall add a description.


> 
> > +        igt_skip_on(!data.num_h_tiles);
> > +        set_test_pattern_fb(&data, conn_data);
> > +        igt_display_commit2(data.display, data.commit);
> 
> I'm not sure I understand what this test checks. It does a commit on
> all tiled connectors, but doesn't check anything afterwards. Maybe it
> should check the pageflip serial and timings?

This test was meant to make sure the transcoder port sync feature was
working without any offsets in the two tiles of the display. Any
suggestions/resources for how to test pageflips?

> 
> > +    }
> > +
> > +    igt_fixture {
> > +        if(data.num_h_tiles > 0)
> > +            free(conn_data);
> 
> If conn_data was initialized to NULL, no need for the check, because
> free(NULL) is a no-op.

Yes, makes sense. I shall update it for rev2.

> 
> > +        kmstest_restore_vt_mode();
> > +        igt_display_fini(data.display);
> > +    }
> > +}
> > diff --git a/tests/meson.build b/tests/meson.build
> > index 34a74025..6a6e9ce9 100644
> > --- a/tests/meson.build
> > +++ b/tests/meson.build
> > @@ -25,6 +25,7 @@ test_progs = [
> >  	'kms_cursor_edge_walk',
> >  	'kms_cursor_legacy',
> >  	'kms_dp_dsc',
> > +	'kms_dp_tiled_display',
> >  	'kms_draw_crc',
> >  	'kms_fbcon_fbt',
> >  	'kms_fence_pin_leak',
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [igt-dev] [PATCH i-g-t] igt/tests/kms_dp_tiled_display.c : kms test file for display port tiled displays
  2019-07-30 19:21   ` Manasi Navare
@ 2019-07-31  7:25     ` Ser, Simon
  2019-07-31 17:13       ` Manasi Navare
  0 siblings, 1 reply; 18+ messages in thread
From: Ser, Simon @ 2019-07-31  7:25 UTC (permalink / raw)
  To: martin.peres, Navare, Manasi D; +Cc: igt-dev, Latvala, Petri

On Tue, 2019-07-30 at 12:21 -0700, Manasi Navare wrote:
> On Wed, Jul 17, 2019 at 11:43:48PM -0700, Ser, Simon wrote:
> > Thanks for your patch! Here are some comments.
> > 
> > Style: we use tabs for indentation, not spaces.
> > 
> > On Wed, 2019-07-17 at 11:02 -0700, Madhumitha Tolakanahalli Pradeep wrote:
> > > This test validates the tiled DP displays to display a test pattern seamlessly
> > > across the two tiles. It validates the transcoder port sync feature on i915 to
> > > get a tearfree tiled display output.
> > > 
> > > Related kernel work patches -> https://patchwork.freedesktop.org/series/59837/#rev4.
> > > This test can eventually be extended to cover tiled display support on other connector
> > > types.
> > > 
> > > Cc: Manasi Navare <manasi.d.navare@intel.com>
> > > Cc: Petri Latvala <petri.latvala@intel.com>
> > > Signed-off-by: Madhumitha Tolakanahalli Pradeep <madhumitha.tolakanahalli.pradeep@intel.com>
> > 
> > Next time, can you send both patches in one go? It's not possible to
> > check whether this test actually passes CI, since build fails (see the
> > two automated failure replies).
> 
> Yes please send this as a series with 1st patch that defines the tile parser
> and second with the actual test that uses it
> 
> > To learn how to use git-send-email, you can read:
> > https://git-send-email.io/
> > 
> > > ---
> > >  tests/Makefile.sources       |   1 +
> > >  tests/kms_dp_tiled_display.c | 239 +++++++++++++++++++++++++++++++++++
> > >  tests/meson.build            |   1 +
> > >  3 files changed, 241 insertions(+)
> > >  create mode 100644 tests/kms_dp_tiled_display.c
> > > 
> > > diff --git a/tests/Makefile.sources b/tests/Makefile.sources
> > > index 250dbd33..e9373941 100644
> > > --- a/tests/Makefile.sources
> > > +++ b/tests/Makefile.sources
> > > @@ -40,6 +40,7 @@ TESTS_progs = \
> > >  	kms_cursor_edge_walk \
> > >  	kms_cursor_legacy \
> > >  	kms_dp_dsc \
> > > +	kms_dp_tiled_display \
> > >  	kms_draw_crc \
> > >  	kms_fbcon_fbt \
> > >  	kms_fence_pin_leak \
> > > diff --git a/tests/kms_dp_tiled_display.c b/tests/kms_dp_tiled_display.c
> > > new file mode 100644
> > > index 00000000..af644573
> > > --- /dev/null
> > > +++ b/tests/kms_dp_tiled_display.c
> > > @@ -0,0 +1,239 @@
> > > +/*
> > > + * Copyright © 2018 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.
> > > + *
> > > + * Authors:
> > > + *  Madhumitha Tolakanahalli Pradeep
> > > + *      <madhumitha.tolakanahalli.pradeep@intel.com>
> > > + *
> > > + * Display Port Tiled Display Test
> > > + * This test parses the tile information of the connectors that have TILE
> > > + * property set, sets up the framebuffer with correct offsets corresponding to
> > > + * the tile offsets and does an atomic modeset with two CRTCs for two
> > > + * connectors.
> > > + *
> > > + * This test currently supports only horizontally tiled displays, in line with
> > > + * the displays supported by the kernel at the moment.
> > > + */
> > > +
> > > +#include "drm_mode.h"
> > > +#include "drm_fourcc.h"
> > > +#include "igt.h"
> > > +
> > > +typedef struct {
> > > +    int drm_fd;
> > > +    int num_h_tiles;
> > > +    igt_display_t *display;
> > > +    enum igt_commit_style commit;
> > > +} data_t;
> > > +
> > > +typedef struct {
> > > +    igt_output_t *output;
> > > +    igt_tile_info_t *tile;
> > > +    igt_fb_t fb_test_pattern;
> > > +    drmModeConnectorPtr connector;
> > > +    enum pipe pipe;
> > > +    enum igt_commit_style commit;
> > > +} data_connector_t;
> > > +
> > > +static inline int drm_property_is_tile(drmModePropertyPtr prop)
> > 
> > I wouldn't personally use `inline`. The compiler is smarter than humans
> > to decide whether or not a function should be inlined.
> > 
> > > +{
> > > +	return(strcmp(prop->name ? prop->name : "", "TILE")? 0 : 1);
> > 
> > Style: unnecessary parentheses, missing space before `?`.
> > 
> > > +}
> > > +
> > > +static void get_number_of_h_tiles(data_t *data)
> > 
> > What if multiple tiles are connected? Shouldn't we use tile_group_id?
> 
> Yes there could be multiple monitors with tiles so use tile_group_id to check
> that the tile belongs to the same group and then use num_h_tiles
> 
> > > +{
> > > +    int i;
> > > +    drmModeRes *res;
> > > +    drmModeConnector *connector;
> > > +    drmModePropertyPtr prop;
> > > +    drmModePropertyBlobPtr blob;
> > > +    igt_tile_info_t tile;
> > > +
> > > +    igt_require(res = drmModeGetResources(data->drm_fd));
> > 
> > This should probably be igt_assert.
> > 
> > > +    for(i = 0; i < res->count_connectors; i++)
> > > +    {
> > 
> > Style: no newline before `{` (only for functions, applies to the whole
> > patch).
> > 
> > > +        connector = drmModeGetConnectorCurrent(data->drm_fd, \
> > 
> > Style: unnecessary `\`.
> > 
> > We could igt_assert(connector).
> > 
> > > +                                               res->connectors[i]);
> > > +
> > > +        if(!((connector->connection == DRM_MODE_CONNECTED) &&
> > > +            (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort)))
> > > +                continue;
> > 
> > Style: we can invert this condition to make clearer.
> 
> But wouldnt that add additional nesting?

I mean, this could be re-written as:

    if (connector->connection != DRM_MODE_CONNECTED ||
        connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort)

> > > +
> > > +        for(i = 0; i < connector->count_props; i++)
> > > +        {
> > > +            prop = drmModeGetProperty(data->drm_fd, connector->props[i]);
> > 
> > We could igt_assert(prop)
> > 
> > We need to free it at some point.
> > 
> > > +            if(!(drm_property_is_tile(prop) &&
> > 
> > Style: missing space after if keyword (applies to the whole patch).
> > 
> > > +                drm_property_type_is(prop, DRM_MODE_PROP_BLOB)))
> > 
> > I'd move this check into drm_property_is_tile.
> > 
> > > +                continue;
> > > +
> > > +            blob = drmModeGetPropertyBlob(data->drm_fd, \
> > > +                                          connector->prop_values[i]);
> > > +
> > > +            if(!blob)
> > > +                break;
> > > +            igt_parse_connector_tile_blob(blob, &tile);
> > > +            data->num_h_tiles = tile.num_h_tile;
> > > +            break;
> > > +        }
> > > +    }
> > > +}
> > > +
> > > +static int set_test_pattern_fb(data_t *data, data_connector_t *conn_data)
> > > +{
> > > +    int i;
> > > +    int count = 0;
> > > +    bool is_tile = false;
> > > +    enum pipe pipe;
> > > +    igt_tile_info_t tile;
> > > +    igt_output_t *output;
> > > +    igt_plane_t *primary;
> > > +    drmModePropertyPtr prop;
> > > +    drmModePropertyBlobPtr blob;
> > > +
> > > +    for_each_connected_output(data->display, output)
> > > +    {
> > > +        is_tile = false;
> > > +
> > > +        conn_data[count].connector = drmModeGetConnector(data->display->drm_fd, \
> > > +                                                         output->id);
> > > +
> > > +        if(!(conn_data[count].connector->connector_type ==
> > > +                        DRM_MODE_CONNECTOR_DisplayPort))
> > > +            continue;
> > > +
> > > +        /* Parse through each connector property */
> > > +        for(i = 0; i < conn_data[count].connector->count_props; i++)
> > > +        {
> > > +            prop = drmModeGetProperty(data->display->drm_fd, \
> > > +                                      conn_data[count].connector->props[i]);
> > > +
> > > +            if(!((drm_property_is_tile(prop) &&
> > > +                drm_property_type_is(prop, DRM_MODE_PROP_BLOB))))
> > > +                continue;
> > > +
> > > +            blob = drmModeGetPropertyBlob(data->display->drm_fd, \
> > > +                            conn_data[count].connector->prop_values[i]);
> > > +
> > > +            if(!blob)
> > > +                break;
> > > +
> > > +            igt_parse_connector_tile_blob(blob, &tile);
> > > +            conn_data[count].tile = &tile;
> > > +            is_tile = true;
> > > +            break;
> > > +        }
> > 
> > I feel like this whole block above is duplicated. Could be extracted
> > into a function, e.g.
> > 
> >     bool connector_get_tile(drmModeConnectorRes *conn, igt_tile_info_t *tile_info)
> > 
> > > +        if(!is_tile)
> > > +            continue;
> > > +
> > > +        output = igt_output_from_connector(data->display, \
> > > +                                           conn_data[count].connector);
> > 
> > Style: unnecessary `\`. Applies to the whole patch.
> > 
> > > +
> > > +        for_each_pipe(data->display, pipe)
> > > +        {
> > > +            igt_debug("Current PIPE is %d\n", pipe);
> > > +
> > > +            if((count > 0) && (pipe == conn_data[count-1].pipe))
> > > +                continue;
> > 
> > Style: unnecessary parentheses.
> > 
> > > +            if(igt_pipe_connector_valid(pipe, output)) {
> > > +                conn_data[count].pipe = pipe;
> > > +                conn_data[count].output = output;
> > > +
> > > +                igt_output_set_pipe(conn_data[count].output, \
> > > +                                    conn_data[count].pipe);
> > > +
> > > +                igt_create_pattern_fb(data->drm_fd,\
> > > +                                    (conn_data[count].tile->tile_h_size *\
> > > +                                     data->num_h_tiles),\
> > > +                                     conn_data[count].tile->tile_v_size,\
> > > +                                     DRM_FORMAT_XBGR8888,\
> > > +                                     LOCAL_DRM_FORMAT_MOD_NONE,\
> > > +                                     &conn_data[count].fb_test_pattern);
> > > +
> > > +                primary = igt_output_get_plane_type(conn_data[count].output,\
> > > +                                                    DRM_PLANE_TYPE_PRIMARY);
> > > +
> > > +                igt_plane_set_fb(primary, &conn_data[count].fb_test_pattern);
> > > +
> > > +                igt_fb_set_size(&conn_data[count].fb_test_pattern, primary,\
> > > +                                conn_data[count].tile->tile_h_size,\
> > > +                                conn_data[count].tile->tile_v_size);
> > > +
> > > +                igt_fb_set_position(&conn_data[count].fb_test_pattern, \
> > > +                                    primary,\
> > > +                                    (conn_data[count].tile->tile_h_size *\
> > > +                                    conn_data[count].tile->tile_h_loc),
> > > +                                    (conn_data[count].tile->tile_v_size *\
> > > +                                    conn_data[count].tile->tile_v_loc));
> > > +
> > > +                igt_plane_set_size(primary,\
> > > +                                   conn_data[count].tile->tile_h_size,\
> > > +                                   conn_data[count].tile->tile_v_size);
> > > +
> > > +                break;
> > > +            }
> > > +        }
> > > +        count++;
> > > +    }
> > > +
> > > +    return count;
> > > +}
> > > +
> > > +igt_main
> > > +{
> > > +    igt_display_t display;
> > > +    data_t data = {};
> > > +    data_connector_t *conn_data;
> > > +
> > > +    igt_fixture {
> > > +        data.drm_fd = drm_open_driver_master(DRIVER_ANY);
> > > +        kmstest_set_vt_graphics_mode();
> > > +        igt_display_require(&display, data.drm_fd);
> > > +        data.display = &display;
> > > +
> > > +        get_number_of_h_tiles(&data);
> > > +        igt_debug("Number of Horizontal Tiles: %d\n", data.num_h_tiles);
> > > +        data.commit = data.display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY;
> > > +    }
> > > +
> > > +    if(data.num_h_tiles > 0)
> > > +        conn_data = (data_connector_t *)malloc(data.num_h_tiles * \
> > > +                                                sizeof(data_connector_t));
> > 
> > No need for this cast, unnecessary `\`.
> > 
> > > +    igt_assert(conn_data);
> > 
> > This check reads garbage from the stack if data.num_h_tiles == 0.
> 
> This check should possibly be inside the same if
> 
> > > +    igt_subtest_f("basic-test-pattern") {
> > 
> > No need for the _f suffix.
> > 
> > This subtest is missing a description. Could you add one? For more
> > information, see:
> > https://drm.pages.freedesktop.org/igt-gpu-tools/igt-gpu-tools-Core.html#igt-describe
> > 
> > > +        igt_skip_on(!data.num_h_tiles);
> > > +        set_test_pattern_fb(&data, conn_data);
> > > +        igt_display_commit2(data.display, data.commit);
> > 
> > I'm not sure I understand what this test checks. It does a commit on
> > all tiled connectors, but doesn't check anything afterwards. Maybe it
> > should check the pageflip serial and timings?
> 
> This is so far a manual test where we just look at the pattern and make sure no artifacts
> and auto testing just make sure the commit did not fail, any better idea to check if the
> page_flip timeouts didnt occur or not sure if we can do crc checks to ensure no artifacts?
> Any ideas/suggestions?

To be honest I'm not a fan of manual testing.

As I understand it, tiled displays must be updated in sync so that you
don't get tearing. If one display is page-flipped before the other,
there will be tearing in the middle of the tiled screen. Am I reading
the commit message correctly?

If so, maybe we can check the page-flip timings and make sure they are
equal?

A CRC check might be a good idea too, to make sure bandwidth isn't an
issue.

CC'ing Martin in case he has better ideas.

> Manasi
> 
> > > +    }
> > > +
> > > +    igt_fixture {
> > > +        if(data.num_h_tiles > 0)
> > > +            free(conn_data);
> > 
> > If conn_data was initialized to NULL, no need for the check, because
> > free(NULL) is a no-op.
> > 
> > > +        kmstest_restore_vt_mode();
> > > +        igt_display_fini(data.display);
> > > +    }
> > > +}
> > > diff --git a/tests/meson.build b/tests/meson.build
> > > index 34a74025..6a6e9ce9 100644
> > > --- a/tests/meson.build
> > > +++ b/tests/meson.build
> > > @@ -25,6 +25,7 @@ test_progs = [
> > >  	'kms_cursor_edge_walk',
> > >  	'kms_cursor_legacy',
> > >  	'kms_dp_dsc',
> > > +	'kms_dp_tiled_display',
> > >  	'kms_draw_crc',
> > >  	'kms_fbcon_fbt',
> > >  	'kms_fence_pin_leak',
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [igt-dev] [PATCH i-g-t] igt/tests/kms_dp_tiled_display.c : kms test file for display port tiled displays
  2019-07-31  0:42   ` Tolakanahalli Pradeep, Madhumitha
@ 2019-07-31  8:15     ` Ser, Simon
  0 siblings, 0 replies; 18+ messages in thread
From: Ser, Simon @ 2019-07-31  8:15 UTC (permalink / raw)
  To: igt-dev, Tolakanahalli Pradeep, Madhumitha
  Cc: Navare, Manasi D, Latvala, Petri

On Tue, 2019-07-30 at 17:42 -0700, Tolakanahalli Pradeep, Madhumitha wrote:
> Thank you very much for your comments, Simon.
> 
> Thanks for pointing out the style realted issues, I have them
> fixed (tabs, `\` etc).
> 
> On Thu, 2019-07-18 at 07:43 +0100, Ser, Simon wrote:
> > Thanks for your patch! Here are some comments.
> > 
> > Style: we use tabs for indentation, not spaces.
> > 
> > On Wed, 2019-07-17 at 11:02 -0700, Madhumitha Tolakanahalli Pradeep
> > wrote:
> > > This test validates the tiled DP displays to display a test pattern
> > > seamlessly
> > > across the two tiles. It validates the transcoder port sync feature
> > > on i915 to
> > > get a tearfree tiled display output.
> > > 
> > > Related kernel work patches -> 
> > > https://patchwork.freedesktop.org/series/59837/#rev4.
> > > This test can eventually be extended to cover tiled display support
> > > on other connector
> > > types.
> > > 
> > > Cc: Manasi Navare <manasi.d.navare@intel.com>
> > > Cc: Petri Latvala <petri.latvala@intel.com>
> > > Signed-off-by: Madhumitha Tolakanahalli Pradeep <
> > > madhumitha.tolakanahalli.pradeep@intel.com>
> > 
> > Next time, can you send both patches in one go? It's not possible to
> > check whether this test actually passes CI, since build fails (see
> > the
> > two automated failure replies).
> 
> My apologies, I shall keep that in mind for the next time.
> 
> > To learn how to use git-send-email, you can read:
> > https://git-send-email.io/
> > 
> > > ---
> > >  tests/Makefile.sources       |   1 +
> > >  tests/kms_dp_tiled_display.c | 239
> > > +++++++++++++++++++++++++++++++++++
> > >  tests/meson.build            |   1 +
> > >  3 files changed, 241 insertions(+)
> > >  create mode 100644 tests/kms_dp_tiled_display.c
> > > 
> > > diff --git a/tests/Makefile.sources b/tests/Makefile.sources
> > > index 250dbd33..e9373941 100644
> > > --- a/tests/Makefile.sources
> > > +++ b/tests/Makefile.sources
> > > @@ -40,6 +40,7 @@ TESTS_progs = \
> > >  	kms_cursor_edge_walk \
> > >  	kms_cursor_legacy \
> > >  	kms_dp_dsc \
> > > +	kms_dp_tiled_display \
> > >  	kms_draw_crc \
> > >  	kms_fbcon_fbt \
> > >  	kms_fence_pin_leak \
> > > diff --git a/tests/kms_dp_tiled_display.c
> > > b/tests/kms_dp_tiled_display.c
> > > new file mode 100644
> > > index 00000000..af644573
> > > --- /dev/null
> > > +++ b/tests/kms_dp_tiled_display.c
> > > @@ -0,0 +1,239 @@
> > > +/*
> > > + * Copyright © 2018 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.
> > > + *
> > > + * Authors:
> > > + *  Madhumitha Tolakanahalli Pradeep
> > > + *      <madhumitha.tolakanahalli.pradeep@intel.com>
> > > + *
> > > + * Display Port Tiled Display Test
> > > + * This test parses the tile information of the connectors that
> > > have TILE
> > > + * property set, sets up the framebuffer with correct offsets
> > > corresponding to
> > > + * the tile offsets and does an atomic modeset with two CRTCs for
> > > two
> > > + * connectors.
> > > + *
> > > + * This test currently supports only horizontally tiled displays,
> > > in line with
> > > + * the displays supported by the kernel at the moment.
> > > + */
> > > +
> > > +#include "drm_mode.h"
> > > +#include "drm_fourcc.h"
> > > +#include "igt.h"
> > > +
> > > +typedef struct {
> > > +    int drm_fd;
> > > +    int num_h_tiles;
> > > +    igt_display_t *display;
> > > +    enum igt_commit_style commit;
> > > +} data_t;
> > > +
> > > +typedef struct {
> > > +    igt_output_t *output;
> > > +    igt_tile_info_t *tile;
> > > +    igt_fb_t fb_test_pattern;
> > > +    drmModeConnectorPtr connector;
> > > +    enum pipe pipe;
> > > +    enum igt_commit_style commit;
> > > +} data_connector_t;
> > > +
> > > +static inline int drm_property_is_tile(drmModePropertyPtr prop)
> > 
> > I wouldn't personally use `inline`. The compiler is smarter than
> > humans
> > to decide whether or not a function should be inlined.
> > 
> 
> Makes sense, I shall remove 'inline'.
> 
> > > +{
> > > +	return(strcmp(prop->name ? prop->name : "", "TILE")? 0 : 1);
> > 
> > Style: unnecessary parentheses, missing space before `?`.
> > 
> > > +}
> > > +
> > > +static void get_number_of_h_tiles(data_t *data)
> > 
> > What if multiple tiles are connected? Shouldn't we use tile_group_id?
> 
> Currently, the hardware does not support displays that are connected to
> multiple tiles. Only connectors with the same tile_group_id are
> supported for tiled monitors. 
> I was thinking of adding a check for making sure both the connected DP
> connectors belong to the same tile group as that make the test more
> robust. Any suggestions for the same?

Yes. (See Manasi's reply)

> > 
> > > +{
> > > +    int i;
> > > +    drmModeRes *res;
> > > +    drmModeConnector *connector;
> > > +    drmModePropertyPtr prop;
> > > +    drmModePropertyBlobPtr blob;
> > > +    igt_tile_info_t tile;
> > > +
> > > +    igt_require(res = drmModeGetResources(data->drm_fd));
> > 
> > This should probably be igt_assert.
> 
> Yes, makes sense. I shall update it for rev2.
> 
> > > +    for(i = 0; i < res->count_connectors; i++)
> > > +    {
> > 
> > Style: no newline before `{` (only for functions, applies to the
> > whole
> > patch).
> > 
> > > +        connector = drmModeGetConnectorCurrent(data->drm_fd, \
> > 
> > Style: unnecessary `\`.
> > 
> > We could igt_assert(connector).
> 
> Yes, makes sense. I shall update it for rev2.
> 
> > > +                                               res-
> > > > connectors[i]);
> > > +
> > > +        if(!((connector->connection == DRM_MODE_CONNECTED) &&
> > > +            (connector->connector_type ==
> > > DRM_MODE_CONNECTOR_DisplayPort)))
> > > +                continue;
> > 
> > Style: we can invert this condition to make clearer.
> 
> This was done to reduce nesting. Would you suggest we do otherwise?

(See my reply to Manasi)

> > > +
> > > +        for(i = 0; i < connector->count_props; i++)
> > > +        {
> > > +            prop = drmModeGetProperty(data->drm_fd, connector-
> > > > props[i]);
> > 
> > We could igt_assert(prop)
> 
> Yes, makes sense. I shall update it for rev2.
> 
> > We need to free it at some point.
> 
> 'prop' is a local pointer that isnt dynamically allocated. Not too sure
> why that would need free-ing. Could you please provide more clarity on
> the above comment?

drmModeGetProperty allocates on the heap.

<rant>
This is somehow hidden because libdrm had the brilliant idea to
introduce drmModePropertyPtr, which is a type definition for
drmModePropertyRes *. I really don't get what's the point of
drmModePropertyPtr. Its only purpose seems to confuse people.
drmModePropertyRes * is much clearer since we don't have to learn about
a libdrm-specific unidiomatic naming convention to know it's a pointer.
It's clear a function returning thing * allocates something that needs
to be free'd, it's not clear if the function returns otherThing.
Personally I just ignore libdrm weird definitions and just use
drmModePropertyRes *.
</rant>

Anyway, drmModeFreeProperty will free prop.

> > > +            if(!(drm_property_is_tile(prop) &&
> > 
> > Style: missing space after if keyword (applies to the whole patch).
> > 
> > > +                drm_property_type_is(prop, DRM_MODE_PROP_BLOB)))
> > 
> > I'd move this check into drm_property_is_tile.
> 
> Yes, makes sense. I shall update it for rev2.
> 
> > > +                continue;
> > > +
> > > +            blob = drmModeGetPropertyBlob(data->drm_fd, \
> > > +                                          connector-
> > > > prop_values[i]);
> > > +
> > > +            if(!blob)
> > > +                break;
> > > +            igt_parse_connector_tile_blob(blob, &tile);
> > > +            data->num_h_tiles = tile.num_h_tile;
> > > +            break;
> > > +        }
> > > +    }
> > > +}
> > > +
> > > +static int set_test_pattern_fb(data_t *data, data_connector_t
> > > *conn_data)
> > > +{
> > > +    int i;
> > > +    int count = 0;
> > > +    bool is_tile = false;
> > > +    enum pipe pipe;
> > > +    igt_tile_info_t tile;
> > > +    igt_output_t *output;
> > > +    igt_plane_t *primary;
> > > +    drmModePropertyPtr prop;
> > > +    drmModePropertyBlobPtr blob;
> > > +
> > > +    for_each_connected_output(data->display, output)
> > > +    {
> > > +        is_tile = false;
> > > +
> > > +        conn_data[count].connector = drmModeGetConnector(data-
> > > > display->drm_fd, \
> > > +                                                         output-
> > > > id);
> > > +
> > > +        if(!(conn_data[count].connector->connector_type ==
> > > +                        DRM_MODE_CONNECTOR_DisplayPort))
> > > +            continue;
> > > +
> > > +        /* Parse through each connector property */
> > > +        for(i = 0; i < conn_data[count].connector->count_props;
> > > i++)
> > > +        {
> > > +            prop = drmModeGetProperty(data->display->drm_fd, \
> > > +                                      conn_data[count].connector-
> > > > props[i]);
> > > +
> > > +            if(!((drm_property_is_tile(prop) &&
> > > +                drm_property_type_is(prop, DRM_MODE_PROP_BLOB))))
> > > +                continue;
> > > +
> > > +            blob = drmModeGetPropertyBlob(data->display->drm_fd, \
> > > +                            conn_data[count].connector-
> > > > prop_values[i]);
> > > +
> > > +            if(!blob)
> > > +                break;
> > > +
> > > +            igt_parse_connector_tile_blob(blob, &tile);
> > > +            conn_data[count].tile = &tile;
> > > +            is_tile = true;
> > > +            break;
> > > +        }
> > 
> > I feel like this whole block above is duplicated. Could be extracted
> > into a function, e.g.
> 
> I was contemplating on that too, shall do it for rev2.
> 
> >     bool connector_get_tile(drmModeConnectorRes *conn,
> > igt_tile_info_t *tile_info)
> > 
> > > +        if(!is_tile)
> > > +            continue;
> > > +
> > > +        output = igt_output_from_connector(data->display, \
> > > +                                           conn_data[count].connec
> > > tor);
> > 
> > Style: unnecessary `\`. Applies to the whole patch.
> > 
> > > +
> > > +        for_each_pipe(data->display, pipe)
> > > +        {
> > > +            igt_debug("Current PIPE is %d\n", pipe);
> > > +
> > > +            if((count > 0) && (pipe == conn_data[count-1].pipe))
> > > +                continue;
> > 
> > Style: unnecessary parentheses.
> > 
> > > +            if(igt_pipe_connector_valid(pipe, output)) {
> > > +                conn_data[count].pipe = pipe;
> > > +                conn_data[count].output = output;
> > > +
> > > +                igt_output_set_pipe(conn_data[count].output, \
> > > +                                    conn_data[count].pipe);
> > > +
> > > +                igt_create_pattern_fb(data->drm_fd,\
> > > +                                    (conn_data[count].tile-
> > > > tile_h_size *\
> > > +                                     data->num_h_tiles),\
> > > +                                     conn_data[count].tile-
> > > > tile_v_size,\
> > > +                                     DRM_FORMAT_XBGR8888,\
> > > +                                     LOCAL_DRM_FORMAT_MOD_NONE,\
> > > +                                     &conn_data[count].fb_test_pat
> > > tern);
> > > +
> > > +                primary =
> > > igt_output_get_plane_type(conn_data[count].output,\
> > > +                                                    DRM_PLANE_TYPE
> > > _PRIMARY);
> > > +
> > > +                igt_plane_set_fb(primary,
> > > &conn_data[count].fb_test_pattern);
> > > +
> > > +                igt_fb_set_size(&conn_data[count].fb_test_pattern,
> > > primary,\
> > > +                                conn_data[count].tile-
> > > > tile_h_size,\
> > > +                                conn_data[count].tile-
> > > > tile_v_size);
> > > +
> > > +                igt_fb_set_position(&conn_data[count].fb_test_patt
> > > ern, \
> > > +                                    primary,\
> > > +                                    (conn_data[count].tile-
> > > > tile_h_size *\
> > > +                                    conn_data[count].tile-
> > > > tile_h_loc),
> > > +                                    (conn_data[count].tile-
> > > > tile_v_size *\
> > > +                                    conn_data[count].tile-
> > > > tile_v_loc));
> > > +
> > > +                igt_plane_set_size(primary,\
> > > +                                   conn_data[count].tile-
> > > > tile_h_size,\
> > > +                                   conn_data[count].tile-
> > > > tile_v_size);
> > > +
> > > +                break;
> > > +            }
> > > +        }
> > > +        count++;
> > > +    }
> > > +
> > > +    return count;
> > > +}
> > > +
> > > +igt_main
> > > +{
> > > +    igt_display_t display;
> > > +    data_t data = {};
> > > +    data_connector_t *conn_data;
> > > +
> > > +    igt_fixture {
> > > +        data.drm_fd = drm_open_driver_master(DRIVER_ANY);
> > > +        kmstest_set_vt_graphics_mode();
> > > +        igt_display_require(&display, data.drm_fd);
> > > +        data.display = &display;
> > > +
> > > +        get_number_of_h_tiles(&data);
> > > +        igt_debug("Number of Horizontal Tiles: %d\n",
> > > data.num_h_tiles);
> > > +        data.commit = data.display->is_atomic ? COMMIT_ATOMIC :
> > > COMMIT_LEGACY;
> > > +    }
> > > +
> > > +    if(data.num_h_tiles > 0)
> > > +        conn_data = (data_connector_t *)malloc(data.num_h_tiles *
> > > \
> > > +                                                sizeof(data_connec
> > > tor_t));
> > 
> > No need for this cast, unnecessary `\`.
> > 
> > > +    igt_assert(conn_data);
> > 
> > This check reads garbage from the stack if data.num_h_tiles == 0.
> 
> I moved the assert to igt_subtest block after igt_skip_on so that if
> data.num_h_tiles == 0, assert would not be performed.
> 
> > > +    igt_subtest_f("basic-test-pattern") {
> > 
> > No need for the _f suffix.
> 
> Yes, makes sense. I shall update it for rev2.
> 
> > This subtest is missing a description. Could you add one? For more
> > information, see:
> > 
> https://drm.pages.freedesktop.org/igt-gpu-tools/igt-gpu-tools-Core.html#igt-describe
> 
> I shall add a description.
> 
> 
> > > +        igt_skip_on(!data.num_h_tiles);
> > > +        set_test_pattern_fb(&data, conn_data);
> > > +        igt_display_commit2(data.display, data.commit);
> > 
> > I'm not sure I understand what this test checks. It does a commit on
> > all tiled connectors, but doesn't check anything afterwards. Maybe it
> > should check the pageflip serial and timings?
> 
> This test was meant to make sure the transcoder port sync feature was
> working without any offsets in the two tiles of the display. Any
> suggestions/resources for how to test pageflips?

(See the discussion with Manasi)

> > > +    }
> > > +
> > > +    igt_fixture {
> > > +        if(data.num_h_tiles > 0)
> > > +            free(conn_data);
> > 
> > If conn_data was initialized to NULL, no need for the check, because
> > free(NULL) is a no-op.
> 
> Yes, makes sense. I shall update it for rev2.
> 
> > > +        kmstest_restore_vt_mode();
> > > +        igt_display_fini(data.display);
> > > +    }
> > > +}
> > > diff --git a/tests/meson.build b/tests/meson.build
> > > index 34a74025..6a6e9ce9 100644
> > > --- a/tests/meson.build
> > > +++ b/tests/meson.build
> > > @@ -25,6 +25,7 @@ test_progs = [
> > >  	'kms_cursor_edge_walk',
> > >  	'kms_cursor_legacy',
> > >  	'kms_dp_dsc',
> > > +	'kms_dp_tiled_display',
> > >  	'kms_draw_crc',
> > >  	'kms_fbcon_fbt',
> > >  	'kms_fence_pin_leak',
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [igt-dev] [PATCH i-g-t] igt/tests/kms_dp_tiled_display.c : kms test file for display port tiled displays
  2019-07-31  7:25     ` Ser, Simon
@ 2019-07-31 17:13       ` Manasi Navare
  2019-08-01  7:41         ` Ser, Simon
  0 siblings, 1 reply; 18+ messages in thread
From: Manasi Navare @ 2019-07-31 17:13 UTC (permalink / raw)
  To: Ser, Simon; +Cc: igt-dev, Latvala, Petri

On Wed, Jul 31, 2019 at 12:25:09AM -0700, Ser, Simon wrote:
> On Tue, 2019-07-30 at 12:21 -0700, Manasi Navare wrote:
> > On Wed, Jul 17, 2019 at 11:43:48PM -0700, Ser, Simon wrote:
> > > Thanks for your patch! Here are some comments.
> > > 
> > > Style: we use tabs for indentation, not spaces.
> > > 
> > > On Wed, 2019-07-17 at 11:02 -0700, Madhumitha Tolakanahalli Pradeep wrote:
> > > > This test validates the tiled DP displays to display a test pattern seamlessly
> > > > across the two tiles. It validates the transcoder port sync feature on i915 to
> > > > get a tearfree tiled display output.
> > > > 
> > > > Related kernel work patches -> https://patchwork.freedesktop.org/series/59837/#rev4.
> > > > This test can eventually be extended to cover tiled display support on other connector
> > > > types.
> > > > 
> > > > Cc: Manasi Navare <manasi.d.navare@intel.com>
> > > > Cc: Petri Latvala <petri.latvala@intel.com>
> > > > Signed-off-by: Madhumitha Tolakanahalli Pradeep <madhumitha.tolakanahalli.pradeep@intel.com>
> > > 
> > > Next time, can you send both patches in one go? It's not possible to
> > > check whether this test actually passes CI, since build fails (see the
> > > two automated failure replies).
> > 
> > Yes please send this as a series with 1st patch that defines the tile parser
> > and second with the actual test that uses it
> > 
> > > To learn how to use git-send-email, you can read:
> > > https://git-send-email.io/
> > > 
> > > > ---
> > > >  tests/Makefile.sources       |   1 +
> > > >  tests/kms_dp_tiled_display.c | 239 +++++++++++++++++++++++++++++++++++
> > > >  tests/meson.build            |   1 +
> > > >  3 files changed, 241 insertions(+)
> > > >  create mode 100644 tests/kms_dp_tiled_display.c
> > > > 
> > > > diff --git a/tests/Makefile.sources b/tests/Makefile.sources
> > > > index 250dbd33..e9373941 100644
> > > > --- a/tests/Makefile.sources
> > > > +++ b/tests/Makefile.sources
> > > > @@ -40,6 +40,7 @@ TESTS_progs = \
> > > >  	kms_cursor_edge_walk \
> > > >  	kms_cursor_legacy \
> > > >  	kms_dp_dsc \
> > > > +	kms_dp_tiled_display \
> > > >  	kms_draw_crc \
> > > >  	kms_fbcon_fbt \
> > > >  	kms_fence_pin_leak \
> > > > diff --git a/tests/kms_dp_tiled_display.c b/tests/kms_dp_tiled_display.c
> > > > new file mode 100644
> > > > index 00000000..af644573
> > > > --- /dev/null
> > > > +++ b/tests/kms_dp_tiled_display.c
> > > > @@ -0,0 +1,239 @@
> > > > +/*
> > > > + * Copyright © 2018 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.
> > > > + *
> > > > + * Authors:
> > > > + *  Madhumitha Tolakanahalli Pradeep
> > > > + *      <madhumitha.tolakanahalli.pradeep@intel.com>
> > > > + *
> > > > + * Display Port Tiled Display Test
> > > > + * This test parses the tile information of the connectors that have TILE
> > > > + * property set, sets up the framebuffer with correct offsets corresponding to
> > > > + * the tile offsets and does an atomic modeset with two CRTCs for two
> > > > + * connectors.
> > > > + *
> > > > + * This test currently supports only horizontally tiled displays, in line with
> > > > + * the displays supported by the kernel at the moment.
> > > > + */
> > > > +
> > > > +#include "drm_mode.h"
> > > > +#include "drm_fourcc.h"
> > > > +#include "igt.h"
> > > > +
> > > > +typedef struct {
> > > > +    int drm_fd;
> > > > +    int num_h_tiles;
> > > > +    igt_display_t *display;
> > > > +    enum igt_commit_style commit;
> > > > +} data_t;
> > > > +
> > > > +typedef struct {
> > > > +    igt_output_t *output;
> > > > +    igt_tile_info_t *tile;
> > > > +    igt_fb_t fb_test_pattern;
> > > > +    drmModeConnectorPtr connector;
> > > > +    enum pipe pipe;
> > > > +    enum igt_commit_style commit;
> > > > +} data_connector_t;
> > > > +
> > > > +static inline int drm_property_is_tile(drmModePropertyPtr prop)
> > > 
> > > I wouldn't personally use `inline`. The compiler is smarter than humans
> > > to decide whether or not a function should be inlined.
> > > 
> > > > +{
> > > > +	return(strcmp(prop->name ? prop->name : "", "TILE")? 0 : 1);
> > > 
> > > Style: unnecessary parentheses, missing space before `?`.
> > > 
> > > > +}
> > > > +
> > > > +static void get_number_of_h_tiles(data_t *data)
> > > 
> > > What if multiple tiles are connected? Shouldn't we use tile_group_id?
> > 
> > Yes there could be multiple monitors with tiles so use tile_group_id to check
> > that the tile belongs to the same group and then use num_h_tiles

But actually the current hardware like Madhumitha mentioned only supports one tile group,
if we have to support multiple tile groups then we would need to malloc the array of structures
for the connectors associated with separate tile groups and then have a separate subtest for
tile group 1 tile group 2 etc. This logic will not get tested right now due to HW constraint.

So the idea is for the IGT to check the tile group id but only support 1 tile group so far
and leave the room for further extending it to multiple tiles instead of over complicating
the logic now.

Does that make sense or do you think we should already add the subtests for multiple tile groups?


> > 
> > > > +{
> > > > +    int i;
> > > > +    drmModeRes *res;
> > > > +    drmModeConnector *connector;
> > > > +    drmModePropertyPtr prop;
> > > > +    drmModePropertyBlobPtr blob;
> > > > +    igt_tile_info_t tile;
> > > > +
> > > > +    igt_require(res = drmModeGetResources(data->drm_fd));
> > > 
> > > This should probably be igt_assert.
> > > 
> > > > +    for(i = 0; i < res->count_connectors; i++)
> > > > +    {
> > > 
> > > Style: no newline before `{` (only for functions, applies to the whole
> > > patch).
> > > 
> > > > +        connector = drmModeGetConnectorCurrent(data->drm_fd, \
> > > 
> > > Style: unnecessary `\`.
> > > 
> > > We could igt_assert(connector).
> > > 
> > > > +                                               res->connectors[i]);
> > > > +
> > > > +        if(!((connector->connection == DRM_MODE_CONNECTED) &&
> > > > +            (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort)))
> > > > +                continue;
> > > 
> > > Style: we can invert this condition to make clearer.
> > 
> > But wouldnt that add additional nesting?
> 
> I mean, this could be re-written as:
> 
>     if (connector->connection != DRM_MODE_CONNECTED ||
>         connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort)

Oh yes that makes perfect sense!

> 
> > > > +
> > > > +        for(i = 0; i < connector->count_props; i++)
> > > > +        {
> > > > +            prop = drmModeGetProperty(data->drm_fd, connector->props[i]);
> > > 
> > > We could igt_assert(prop)
> > > 
> > > We need to free it at some point.
> > > 
> > > > +            if(!(drm_property_is_tile(prop) &&
> > > 
> > > Style: missing space after if keyword (applies to the whole patch).
> > > 
> > > > +                drm_property_type_is(prop, DRM_MODE_PROP_BLOB)))
> > > 
> > > I'd move this check into drm_property_is_tile.
> > > 
> > > > +                continue;
> > > > +
> > > > +            blob = drmModeGetPropertyBlob(data->drm_fd, \
> > > > +                                          connector->prop_values[i]);
> > > > +
> > > > +            if(!blob)
> > > > +                break;
> > > > +            igt_parse_connector_tile_blob(blob, &tile);
> > > > +            data->num_h_tiles = tile.num_h_tile;
> > > > +            break;
> > > > +        }
> > > > +    }
> > > > +}
> > > > +
> > > > +static int set_test_pattern_fb(data_t *data, data_connector_t *conn_data)
> > > > +{
> > > > +    int i;
> > > > +    int count = 0;
> > > > +    bool is_tile = false;
> > > > +    enum pipe pipe;
> > > > +    igt_tile_info_t tile;
> > > > +    igt_output_t *output;
> > > > +    igt_plane_t *primary;
> > > > +    drmModePropertyPtr prop;
> > > > +    drmModePropertyBlobPtr blob;
> > > > +
> > > > +    for_each_connected_output(data->display, output)
> > > > +    {
> > > > +        is_tile = false;
> > > > +
> > > > +        conn_data[count].connector = drmModeGetConnector(data->display->drm_fd, \
> > > > +                                                         output->id);
> > > > +
> > > > +        if(!(conn_data[count].connector->connector_type ==
> > > > +                        DRM_MODE_CONNECTOR_DisplayPort))
> > > > +            continue;
> > > > +
> > > > +        /* Parse through each connector property */
> > > > +        for(i = 0; i < conn_data[count].connector->count_props; i++)
> > > > +        {
> > > > +            prop = drmModeGetProperty(data->display->drm_fd, \
> > > > +                                      conn_data[count].connector->props[i]);
> > > > +
> > > > +            if(!((drm_property_is_tile(prop) &&
> > > > +                drm_property_type_is(prop, DRM_MODE_PROP_BLOB))))
> > > > +                continue;
> > > > +
> > > > +            blob = drmModeGetPropertyBlob(data->display->drm_fd, \
> > > > +                            conn_data[count].connector->prop_values[i]);
> > > > +
> > > > +            if(!blob)
> > > > +                break;
> > > > +
> > > > +            igt_parse_connector_tile_blob(blob, &tile);
> > > > +            conn_data[count].tile = &tile;
> > > > +            is_tile = true;
> > > > +            break;
> > > > +        }
> > > 
> > > I feel like this whole block above is duplicated. Could be extracted
> > > into a function, e.g.
> > > 
> > >     bool connector_get_tile(drmModeConnectorRes *conn, igt_tile_info_t *tile_info)
> > > 
> > > > +        if(!is_tile)
> > > > +            continue;
> > > > +
> > > > +        output = igt_output_from_connector(data->display, \
> > > > +                                           conn_data[count].connector);
> > > 
> > > Style: unnecessary `\`. Applies to the whole patch.
> > > 
> > > > +
> > > > +        for_each_pipe(data->display, pipe)
> > > > +        {
> > > > +            igt_debug("Current PIPE is %d\n", pipe);
> > > > +
> > > > +            if((count > 0) && (pipe == conn_data[count-1].pipe))
> > > > +                continue;
> > > 
> > > Style: unnecessary parentheses.
> > > 
> > > > +            if(igt_pipe_connector_valid(pipe, output)) {
> > > > +                conn_data[count].pipe = pipe;
> > > > +                conn_data[count].output = output;
> > > > +
> > > > +                igt_output_set_pipe(conn_data[count].output, \
> > > > +                                    conn_data[count].pipe);
> > > > +
> > > > +                igt_create_pattern_fb(data->drm_fd,\
> > > > +                                    (conn_data[count].tile->tile_h_size *\
> > > > +                                     data->num_h_tiles),\
> > > > +                                     conn_data[count].tile->tile_v_size,\
> > > > +                                     DRM_FORMAT_XBGR8888,\
> > > > +                                     LOCAL_DRM_FORMAT_MOD_NONE,\
> > > > +                                     &conn_data[count].fb_test_pattern);
> > > > +
> > > > +                primary = igt_output_get_plane_type(conn_data[count].output,\
> > > > +                                                    DRM_PLANE_TYPE_PRIMARY);
> > > > +
> > > > +                igt_plane_set_fb(primary, &conn_data[count].fb_test_pattern);
> > > > +
> > > > +                igt_fb_set_size(&conn_data[count].fb_test_pattern, primary,\
> > > > +                                conn_data[count].tile->tile_h_size,\
> > > > +                                conn_data[count].tile->tile_v_size);
> > > > +
> > > > +                igt_fb_set_position(&conn_data[count].fb_test_pattern, \
> > > > +                                    primary,\
> > > > +                                    (conn_data[count].tile->tile_h_size *\
> > > > +                                    conn_data[count].tile->tile_h_loc),
> > > > +                                    (conn_data[count].tile->tile_v_size *\
> > > > +                                    conn_data[count].tile->tile_v_loc));
> > > > +
> > > > +                igt_plane_set_size(primary,\
> > > > +                                   conn_data[count].tile->tile_h_size,\
> > > > +                                   conn_data[count].tile->tile_v_size);
> > > > +
> > > > +                break;
> > > > +            }
> > > > +        }
> > > > +        count++;
> > > > +    }
> > > > +
> > > > +    return count;
> > > > +}
> > > > +
> > > > +igt_main
> > > > +{
> > > > +    igt_display_t display;
> > > > +    data_t data = {};
> > > > +    data_connector_t *conn_data;
> > > > +
> > > > +    igt_fixture {
> > > > +        data.drm_fd = drm_open_driver_master(DRIVER_ANY);
> > > > +        kmstest_set_vt_graphics_mode();
> > > > +        igt_display_require(&display, data.drm_fd);
> > > > +        data.display = &display;
> > > > +
> > > > +        get_number_of_h_tiles(&data);
> > > > +        igt_debug("Number of Horizontal Tiles: %d\n", data.num_h_tiles);
> > > > +        data.commit = data.display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY;
> > > > +    }
> > > > +
> > > > +    if(data.num_h_tiles > 0)
> > > > +        conn_data = (data_connector_t *)malloc(data.num_h_tiles * \
> > > > +                                                sizeof(data_connector_t));
> > > 
> > > No need for this cast, unnecessary `\`.
> > > 
> > > > +    igt_assert(conn_data);
> > > 
> > > This check reads garbage from the stack if data.num_h_tiles == 0.
> > 
> > This check should possibly be inside the same if
> > 
> > > > +    igt_subtest_f("basic-test-pattern") {
> > > 
> > > No need for the _f suffix.
> > > 
> > > This subtest is missing a description. Could you add one? For more
> > > information, see:
> > > https://drm.pages.freedesktop.org/igt-gpu-tools/igt-gpu-tools-Core.html#igt-describe
> > > 
> > > > +        igt_skip_on(!data.num_h_tiles);
> > > > +        set_test_pattern_fb(&data, conn_data);
> > > > +        igt_display_commit2(data.display, data.commit);
> > > 
> > > I'm not sure I understand what this test checks. It does a commit on
> > > all tiled connectors, but doesn't check anything afterwards. Maybe it
> > > should check the pageflip serial and timings?
> > 
> > This is so far a manual test where we just look at the pattern and make sure no artifacts
> > and auto testing just make sure the commit did not fail, any better idea to check if the
> > page_flip timeouts didnt occur or not sure if we can do crc checks to ensure no artifacts?
> > Any ideas/suggestions?
> 
> To be honest I'm not a fan of manual testing.
> 
> As I understand it, tiled displays must be updated in sync so that you
> don't get tearing. If one display is page-flipped before the other,
> there will be tearing in the middle of the tiled screen. Am I reading
> the commit message correctly?

Yes there would be tearing if one tile page flipped before the other
and the HW prevents this from happening by synchronizing the two vblanks
from the two ports.

If there an example of igt where we can check the vblank timing or page flip timings
to add this check?

Manasi

> 
> If so, maybe we can check the page-flip timings and make sure they are
> equal?
> 
> A CRC check might be a good idea too, to make sure bandwidth isn't an
> issue.
> 
> CC'ing Martin in case he has better ideas.
> 
> > Manasi
> > 
> > > > +    }
> > > > +
> > > > +    igt_fixture {
> > > > +        if(data.num_h_tiles > 0)
> > > > +            free(conn_data);
> > > 
> > > If conn_data was initialized to NULL, no need for the check, because
> > > free(NULL) is a no-op.
> > > 
> > > > +        kmstest_restore_vt_mode();
> > > > +        igt_display_fini(data.display);
> > > > +    }
> > > > +}
> > > > diff --git a/tests/meson.build b/tests/meson.build
> > > > index 34a74025..6a6e9ce9 100644
> > > > --- a/tests/meson.build
> > > > +++ b/tests/meson.build
> > > > @@ -25,6 +25,7 @@ test_progs = [
> > > >  	'kms_cursor_edge_walk',
> > > >  	'kms_cursor_legacy',
> > > >  	'kms_dp_dsc',
> > > > +	'kms_dp_tiled_display',
> > > >  	'kms_draw_crc',
> > > >  	'kms_fbcon_fbt',
> > > >  	'kms_fence_pin_leak',
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [igt-dev] [PATCH i-g-t] igt/tests/kms_dp_tiled_display.c : kms test file for display port tiled displays
  2019-07-31 17:13       ` Manasi Navare
@ 2019-08-01  7:41         ` Ser, Simon
  2019-08-01 17:38           ` Manasi Navare
  0 siblings, 1 reply; 18+ messages in thread
From: Ser, Simon @ 2019-08-01  7:41 UTC (permalink / raw)
  To: Navare, Manasi D; +Cc: igt-dev, Latvala, Petri

On Wed, 2019-07-31 at 10:13 -0700, Manasi Navare wrote:
> On Wed, Jul 31, 2019 at 12:25:09AM -0700, Ser, Simon wrote:
> > On Tue, 2019-07-30 at 12:21 -0700, Manasi Navare wrote:
> > > On Wed, Jul 17, 2019 at 11:43:48PM -0700, Ser, Simon wrote:
> > > > Thanks for your patch! Here are some comments.
> > > > 
> > > > Style: we use tabs for indentation, not spaces.
> > > > 
> > > > On Wed, 2019-07-17 at 11:02 -0700, Madhumitha Tolakanahalli Pradeep wrote:
> > > > > This test validates the tiled DP displays to display a test pattern seamlessly
> > > > > across the two tiles. It validates the transcoder port sync feature on i915 to
> > > > > get a tearfree tiled display output.
> > > > > 
> > > > > Related kernel work patches -> https://patchwork.freedesktop.org/series/59837/#rev4.
> > > > > This test can eventually be extended to cover tiled display support on other connector
> > > > > types.
> > > > > 
> > > > > Cc: Manasi Navare <manasi.d.navare@intel.com>
> > > > > Cc: Petri Latvala <petri.latvala@intel.com>
> > > > > Signed-off-by: Madhumitha Tolakanahalli Pradeep <madhumitha.tolakanahalli.pradeep@intel.com>
> > > > 
> > > > Next time, can you send both patches in one go? It's not possible to
> > > > check whether this test actually passes CI, since build fails (see the
> > > > two automated failure replies).
> > > 
> > > Yes please send this as a series with 1st patch that defines the tile parser
> > > and second with the actual test that uses it
> > > 
> > > > To learn how to use git-send-email, you can read:
> > > > https://git-send-email.io/
> > > > 
> > > > > ---
> > > > >  tests/Makefile.sources       |   1 +
> > > > >  tests/kms_dp_tiled_display.c | 239 +++++++++++++++++++++++++++++++++++
> > > > >  tests/meson.build            |   1 +
> > > > >  3 files changed, 241 insertions(+)
> > > > >  create mode 100644 tests/kms_dp_tiled_display.c
> > > > > 
> > > > > diff --git a/tests/Makefile.sources b/tests/Makefile.sources
> > > > > index 250dbd33..e9373941 100644
> > > > > --- a/tests/Makefile.sources
> > > > > +++ b/tests/Makefile.sources
> > > > > @@ -40,6 +40,7 @@ TESTS_progs = \
> > > > >  	kms_cursor_edge_walk \
> > > > >  	kms_cursor_legacy \
> > > > >  	kms_dp_dsc \
> > > > > +	kms_dp_tiled_display \
> > > > >  	kms_draw_crc \
> > > > >  	kms_fbcon_fbt \
> > > > >  	kms_fence_pin_leak \
> > > > > diff --git a/tests/kms_dp_tiled_display.c b/tests/kms_dp_tiled_display.c
> > > > > new file mode 100644
> > > > > index 00000000..af644573
> > > > > --- /dev/null
> > > > > +++ b/tests/kms_dp_tiled_display.c
> > > > > @@ -0,0 +1,239 @@
> > > > > +/*
> > > > > + * Copyright © 2018 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.
> > > > > + *
> > > > > + * Authors:
> > > > > + *  Madhumitha Tolakanahalli Pradeep
> > > > > + *      <madhumitha.tolakanahalli.pradeep@intel.com>
> > > > > + *
> > > > > + * Display Port Tiled Display Test
> > > > > + * This test parses the tile information of the connectors that have TILE
> > > > > + * property set, sets up the framebuffer with correct offsets corresponding to
> > > > > + * the tile offsets and does an atomic modeset with two CRTCs for two
> > > > > + * connectors.
> > > > > + *
> > > > > + * This test currently supports only horizontally tiled displays, in line with
> > > > > + * the displays supported by the kernel at the moment.
> > > > > + */
> > > > > +
> > > > > +#include "drm_mode.h"
> > > > > +#include "drm_fourcc.h"
> > > > > +#include "igt.h"
> > > > > +
> > > > > +typedef struct {
> > > > > +    int drm_fd;
> > > > > +    int num_h_tiles;
> > > > > +    igt_display_t *display;
> > > > > +    enum igt_commit_style commit;
> > > > > +} data_t;
> > > > > +
> > > > > +typedef struct {
> > > > > +    igt_output_t *output;
> > > > > +    igt_tile_info_t *tile;
> > > > > +    igt_fb_t fb_test_pattern;
> > > > > +    drmModeConnectorPtr connector;
> > > > > +    enum pipe pipe;
> > > > > +    enum igt_commit_style commit;
> > > > > +} data_connector_t;
> > > > > +
> > > > > +static inline int drm_property_is_tile(drmModePropertyPtr prop)
> > > > 
> > > > I wouldn't personally use `inline`. The compiler is smarter than humans
> > > > to decide whether or not a function should be inlined.
> > > > 
> > > > > +{
> > > > > +	return(strcmp(prop->name ? prop->name : "", "TILE")? 0 : 1);
> > > > 
> > > > Style: unnecessary parentheses, missing space before `?`.
> > > > 
> > > > > +}
> > > > > +
> > > > > +static void get_number_of_h_tiles(data_t *data)
> > > > 
> > > > What if multiple tiles are connected? Shouldn't we use tile_group_id?
> > > 
> > > Yes there could be multiple monitors with tiles so use tile_group_id to check
> > > that the tile belongs to the same group and then use num_h_tiles
> 
> But actually the current hardware like Madhumitha mentioned only supports one tile group,
> if we have to support multiple tile groups then we would need to malloc the array of structures
> for the connectors associated with separate tile groups and then have a separate subtest for
> tile group 1 tile group 2 etc. This logic will not get tested right now due to HW constraint.
> 
> So the idea is for the IGT to check the tile group id but only support 1 tile group so far
> and leave the room for further extending it to multiple tiles instead of over complicating
> the logic now.
> 
> Does that make sense or do you think we should already add the subtests for multiple tile groups?

That makes perfect sense to me, support for multiple tile groups can be
left as a TODO for later.

Incremental patches are way easier to review than one-patch-that-
implements-all-features-at-once. :)

> > > > > +{
> > > > > +    int i;
> > > > > +    drmModeRes *res;
> > > > > +    drmModeConnector *connector;
> > > > > +    drmModePropertyPtr prop;
> > > > > +    drmModePropertyBlobPtr blob;
> > > > > +    igt_tile_info_t tile;
> > > > > +
> > > > > +    igt_require(res = drmModeGetResources(data->drm_fd));
> > > > 
> > > > This should probably be igt_assert.
> > > > 
> > > > > +    for(i = 0; i < res->count_connectors; i++)
> > > > > +    {
> > > > 
> > > > Style: no newline before `{` (only for functions, applies to the whole
> > > > patch).
> > > > 
> > > > > +        connector = drmModeGetConnectorCurrent(data->drm_fd, \
> > > > 
> > > > Style: unnecessary `\`.
> > > > 
> > > > We could igt_assert(connector).
> > > > 
> > > > > +                                               res->connectors[i]);
> > > > > +
> > > > > +        if(!((connector->connection == DRM_MODE_CONNECTED) &&
> > > > > +            (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort)))
> > > > > +                continue;
> > > > 
> > > > Style: we can invert this condition to make clearer.
> > > 
> > > But wouldnt that add additional nesting?
> > 
> > I mean, this could be re-written as:
> > 
> >     if (connector->connection != DRM_MODE_CONNECTED ||
> >         connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort)
> 
> Oh yes that makes perfect sense!
> 
> > > > > +
> > > > > +        for(i = 0; i < connector->count_props; i++)
> > > > > +        {
> > > > > +            prop = drmModeGetProperty(data->drm_fd, connector->props[i]);
> > > > 
> > > > We could igt_assert(prop)
> > > > 
> > > > We need to free it at some point.
> > > > 
> > > > > +            if(!(drm_property_is_tile(prop) &&
> > > > 
> > > > Style: missing space after if keyword (applies to the whole patch).
> > > > 
> > > > > +                drm_property_type_is(prop, DRM_MODE_PROP_BLOB)))
> > > > 
> > > > I'd move this check into drm_property_is_tile.
> > > > 
> > > > > +                continue;
> > > > > +
> > > > > +            blob = drmModeGetPropertyBlob(data->drm_fd, \
> > > > > +                                          connector->prop_values[i]);
> > > > > +
> > > > > +            if(!blob)
> > > > > +                break;
> > > > > +            igt_parse_connector_tile_blob(blob, &tile);
> > > > > +            data->num_h_tiles = tile.num_h_tile;
> > > > > +            break;
> > > > > +        }
> > > > > +    }
> > > > > +}
> > > > > +
> > > > > +static int set_test_pattern_fb(data_t *data, data_connector_t *conn_data)
> > > > > +{
> > > > > +    int i;
> > > > > +    int count = 0;
> > > > > +    bool is_tile = false;
> > > > > +    enum pipe pipe;
> > > > > +    igt_tile_info_t tile;
> > > > > +    igt_output_t *output;
> > > > > +    igt_plane_t *primary;
> > > > > +    drmModePropertyPtr prop;
> > > > > +    drmModePropertyBlobPtr blob;
> > > > > +
> > > > > +    for_each_connected_output(data->display, output)
> > > > > +    {
> > > > > +        is_tile = false;
> > > > > +
> > > > > +        conn_data[count].connector = drmModeGetConnector(data->display->drm_fd, \
> > > > > +                                                         output->id);
> > > > > +
> > > > > +        if(!(conn_data[count].connector->connector_type ==
> > > > > +                        DRM_MODE_CONNECTOR_DisplayPort))
> > > > > +            continue;
> > > > > +
> > > > > +        /* Parse through each connector property */
> > > > > +        for(i = 0; i < conn_data[count].connector->count_props; i++)
> > > > > +        {
> > > > > +            prop = drmModeGetProperty(data->display->drm_fd, \
> > > > > +                                      conn_data[count].connector->props[i]);
> > > > > +
> > > > > +            if(!((drm_property_is_tile(prop) &&
> > > > > +                drm_property_type_is(prop, DRM_MODE_PROP_BLOB))))
> > > > > +                continue;
> > > > > +
> > > > > +            blob = drmModeGetPropertyBlob(data->display->drm_fd, \
> > > > > +                            conn_data[count].connector->prop_values[i]);
> > > > > +
> > > > > +            if(!blob)
> > > > > +                break;
> > > > > +
> > > > > +            igt_parse_connector_tile_blob(blob, &tile);
> > > > > +            conn_data[count].tile = &tile;
> > > > > +            is_tile = true;
> > > > > +            break;
> > > > > +        }
> > > > 
> > > > I feel like this whole block above is duplicated. Could be extracted
> > > > into a function, e.g.
> > > > 
> > > >     bool connector_get_tile(drmModeConnectorRes *conn, igt_tile_info_t *tile_info)
> > > > 
> > > > > +        if(!is_tile)
> > > > > +            continue;
> > > > > +
> > > > > +        output = igt_output_from_connector(data->display, \
> > > > > +                                           conn_data[count].connector);
> > > > 
> > > > Style: unnecessary `\`. Applies to the whole patch.
> > > > 
> > > > > +
> > > > > +        for_each_pipe(data->display, pipe)
> > > > > +        {
> > > > > +            igt_debug("Current PIPE is %d\n", pipe);
> > > > > +
> > > > > +            if((count > 0) && (pipe == conn_data[count-1].pipe))
> > > > > +                continue;
> > > > 
> > > > Style: unnecessary parentheses.
> > > > 
> > > > > +            if(igt_pipe_connector_valid(pipe, output)) {
> > > > > +                conn_data[count].pipe = pipe;
> > > > > +                conn_data[count].output = output;
> > > > > +
> > > > > +                igt_output_set_pipe(conn_data[count].output, \
> > > > > +                                    conn_data[count].pipe);
> > > > > +
> > > > > +                igt_create_pattern_fb(data->drm_fd,\
> > > > > +                                    (conn_data[count].tile->tile_h_size *\
> > > > > +                                     data->num_h_tiles),\
> > > > > +                                     conn_data[count].tile->tile_v_size,\
> > > > > +                                     DRM_FORMAT_XBGR8888,\
> > > > > +                                     LOCAL_DRM_FORMAT_MOD_NONE,\
> > > > > +                                     &conn_data[count].fb_test_pattern);
> > > > > +
> > > > > +                primary = igt_output_get_plane_type(conn_data[count].output,\
> > > > > +                                                    DRM_PLANE_TYPE_PRIMARY);
> > > > > +
> > > > > +                igt_plane_set_fb(primary, &conn_data[count].fb_test_pattern);
> > > > > +
> > > > > +                igt_fb_set_size(&conn_data[count].fb_test_pattern, primary,\
> > > > > +                                conn_data[count].tile->tile_h_size,\
> > > > > +                                conn_data[count].tile->tile_v_size);
> > > > > +
> > > > > +                igt_fb_set_position(&conn_data[count].fb_test_pattern, \
> > > > > +                                    primary,\
> > > > > +                                    (conn_data[count].tile->tile_h_size *\
> > > > > +                                    conn_data[count].tile->tile_h_loc),
> > > > > +                                    (conn_data[count].tile->tile_v_size *\
> > > > > +                                    conn_data[count].tile->tile_v_loc));
> > > > > +
> > > > > +                igt_plane_set_size(primary,\
> > > > > +                                   conn_data[count].tile->tile_h_size,\
> > > > > +                                   conn_data[count].tile->tile_v_size);
> > > > > +
> > > > > +                break;
> > > > > +            }
> > > > > +        }
> > > > > +        count++;
> > > > > +    }
> > > > > +
> > > > > +    return count;
> > > > > +}
> > > > > +
> > > > > +igt_main
> > > > > +{
> > > > > +    igt_display_t display;
> > > > > +    data_t data = {};
> > > > > +    data_connector_t *conn_data;
> > > > > +
> > > > > +    igt_fixture {
> > > > > +        data.drm_fd = drm_open_driver_master(DRIVER_ANY);
> > > > > +        kmstest_set_vt_graphics_mode();
> > > > > +        igt_display_require(&display, data.drm_fd);
> > > > > +        data.display = &display;
> > > > > +
> > > > > +        get_number_of_h_tiles(&data);
> > > > > +        igt_debug("Number of Horizontal Tiles: %d\n", data.num_h_tiles);
> > > > > +        data.commit = data.display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY;
> > > > > +    }
> > > > > +
> > > > > +    if(data.num_h_tiles > 0)
> > > > > +        conn_data = (data_connector_t *)malloc(data.num_h_tiles * \
> > > > > +                                                sizeof(data_connector_t));
> > > > 
> > > > No need for this cast, unnecessary `\`.
> > > > 
> > > > > +    igt_assert(conn_data);
> > > > 
> > > > This check reads garbage from the stack if data.num_h_tiles == 0.
> > > 
> > > This check should possibly be inside the same if
> > > 
> > > > > +    igt_subtest_f("basic-test-pattern") {
> > > > 
> > > > No need for the _f suffix.
> > > > 
> > > > This subtest is missing a description. Could you add one? For more
> > > > information, see:
> > > > https://drm.pages.freedesktop.org/igt-gpu-tools/igt-gpu-tools-Core.html#igt-describe
> > > > 
> > > > > +        igt_skip_on(!data.num_h_tiles);
> > > > > +        set_test_pattern_fb(&data, conn_data);
> > > > > +        igt_display_commit2(data.display, data.commit);
> > > > 
> > > > I'm not sure I understand what this test checks. It does a commit on
> > > > all tiled connectors, but doesn't check anything afterwards. Maybe it
> > > > should check the pageflip serial and timings?
> > > 
> > > This is so far a manual test where we just look at the pattern and make sure no artifacts
> > > and auto testing just make sure the commit did not fail, any better idea to check if the
> > > page_flip timeouts didnt occur or not sure if we can do crc checks to ensure no artifacts?
> > > Any ideas/suggestions?
> > 
> > To be honest I'm not a fan of manual testing.
> > 
> > As I understand it, tiled displays must be updated in sync so that you
> > don't get tearing. If one display is page-flipped before the other,
> > there will be tearing in the middle of the tiled screen. Am I reading
> > the commit message correctly?
> 
> Yes there would be tearing if one tile page flipped before the other
> and the HW prevents this from happening by synchronizing the two vblanks
> from the two ports.
> 
> If there an example of igt where we can check the vblank timing or page flip timings
> to add this check?

I believe tests in kms_flip do a similar check. The page_flip_handler
function handles the page flip event (which is given the flip timestamp
and sequence number). check_state verifies that the timestamp is close
enough to what we expect (in our atomic check, maybe we can compare
with strict equality).

Since we're dealing with multiple CRTCs, it may be a good idea to use
drmEventContext.version = 3 with page_flip_handler2 so that we also get
the CRTC in the page flip handler. Version 3 is a core DRM feature, all
drivers support it given a recent enough kernel.

Rough pseudo-code:

	/* When committing buffer, request a page flip */
	drmModeAtomicCommit(fd, req, DRM_MODE_ATOMIC_NONBLOCK |
			    DRM_MODE_PAGE_FLIP_EVENT, data);

	static void page_flip_handler(int fd, unsigned seq,
				      unsigned tv_sec,
				      unsigned tv_usec,
				      unsigned crtc_id, void *data)
	{
		/* Compare params with the other page flip */
	}

	/* When we get POLLIN in the DRM FD */
	drmEventContext event = {
		.version = 3,
		.page_flip_handler2 = page_flip_handler,
	};
	drmHandleEvent(fd, &event);

> Manasi
> 
> > If so, maybe we can check the page-flip timings and make sure they are
> > equal?
> > 
> > A CRC check might be a good idea too, to make sure bandwidth isn't an
> > issue.
> > 
> > CC'ing Martin in case he has better ideas.
> > 
> > > Manasi
> > > 
> > > > > +    }
> > > > > +
> > > > > +    igt_fixture {
> > > > > +        if(data.num_h_tiles > 0)
> > > > > +            free(conn_data);
> > > > 
> > > > If conn_data was initialized to NULL, no need for the check, because
> > > > free(NULL) is a no-op.
> > > > 
> > > > > +        kmstest_restore_vt_mode();
> > > > > +        igt_display_fini(data.display);
> > > > > +    }
> > > > > +}
> > > > > diff --git a/tests/meson.build b/tests/meson.build
> > > > > index 34a74025..6a6e9ce9 100644
> > > > > --- a/tests/meson.build
> > > > > +++ b/tests/meson.build
> > > > > @@ -25,6 +25,7 @@ test_progs = [
> > > > >  	'kms_cursor_edge_walk',
> > > > >  	'kms_cursor_legacy',
> > > > >  	'kms_dp_dsc',
> > > > > +	'kms_dp_tiled_display',
> > > > >  	'kms_draw_crc',
> > > > >  	'kms_fbcon_fbt',
> > > > >  	'kms_fence_pin_leak',
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [igt-dev] [PATCH i-g-t] igt/tests/kms_dp_tiled_display.c : kms test file for display port tiled displays
  2019-08-01  7:41         ` Ser, Simon
@ 2019-08-01 17:38           ` Manasi Navare
  2019-08-02  1:09             ` Tolakanahalli Pradeep, Madhumitha
  2019-08-08  1:10             ` Tolakanahalli Pradeep, Madhumitha
  0 siblings, 2 replies; 18+ messages in thread
From: Manasi Navare @ 2019-08-01 17:38 UTC (permalink / raw)
  To: Ser, Simon; +Cc: igt-dev, Latvala, Petri

Thank Simon for all your inputs. Please find some of my questions below:

On Thu, Aug 01, 2019 at 12:41:37AM -0700, Ser, Simon wrote:
> On Wed, 2019-07-31 at 10:13 -0700, Manasi Navare wrote:
> > On Wed, Jul 31, 2019 at 12:25:09AM -0700, Ser, Simon wrote:
> > > On Tue, 2019-07-30 at 12:21 -0700, Manasi Navare wrote:
> > > > On Wed, Jul 17, 2019 at 11:43:48PM -0700, Ser, Simon wrote:
> > > > > Thanks for your patch! Here are some comments.
> > > > > 
> > > > > Style: we use tabs for indentation, not spaces.
> > > > > 
> > > > > On Wed, 2019-07-17 at 11:02 -0700, Madhumitha Tolakanahalli Pradeep wrote:
> > > > > > This test validates the tiled DP displays to display a test pattern seamlessly
> > > > > > across the two tiles. It validates the transcoder port sync feature on i915 to
> > > > > > get a tearfree tiled display output.
> > > > > > 
> > > > > > Related kernel work patches -> https://patchwork.freedesktop.org/series/59837/#rev4.
> > > > > > This test can eventually be extended to cover tiled display support on other connector
> > > > > > types.
> > > > > > 
> > > > > > Cc: Manasi Navare <manasi.d.navare@intel.com>
> > > > > > Cc: Petri Latvala <petri.latvala@intel.com>
> > > > > > Signed-off-by: Madhumitha Tolakanahalli Pradeep <madhumitha.tolakanahalli.pradeep@intel.com>
> > > > > 
> > > > > Next time, can you send both patches in one go? It's not possible to
> > > > > check whether this test actually passes CI, since build fails (see the
> > > > > two automated failure replies).
> > > > 
> > > > Yes please send this as a series with 1st patch that defines the tile parser
> > > > and second with the actual test that uses it
> > > > 
> > > > > To learn how to use git-send-email, you can read:
> > > > > https://git-send-email.io/
> > > > > 
> > > > > > ---
> > > > > >  tests/Makefile.sources       |   1 +
> > > > > >  tests/kms_dp_tiled_display.c | 239 +++++++++++++++++++++++++++++++++++
> > > > > >  tests/meson.build            |   1 +
> > > > > >  3 files changed, 241 insertions(+)
> > > > > >  create mode 100644 tests/kms_dp_tiled_display.c
> > > > > > 
> > > > > > diff --git a/tests/Makefile.sources b/tests/Makefile.sources
> > > > > > index 250dbd33..e9373941 100644
> > > > > > --- a/tests/Makefile.sources
> > > > > > +++ b/tests/Makefile.sources
> > > > > > @@ -40,6 +40,7 @@ TESTS_progs = \
> > > > > >  	kms_cursor_edge_walk \
> > > > > >  	kms_cursor_legacy \
> > > > > >  	kms_dp_dsc \
> > > > > > +	kms_dp_tiled_display \
> > > > > >  	kms_draw_crc \
> > > > > >  	kms_fbcon_fbt \
> > > > > >  	kms_fence_pin_leak \
> > > > > > diff --git a/tests/kms_dp_tiled_display.c b/tests/kms_dp_tiled_display.c
> > > > > > new file mode 100644
> > > > > > index 00000000..af644573
> > > > > > --- /dev/null
> > > > > > +++ b/tests/kms_dp_tiled_display.c
> > > > > > @@ -0,0 +1,239 @@
> > > > > > +/*
> > > > > > + * Copyright © 2018 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.
> > > > > > + *
> > > > > > + * Authors:
> > > > > > + *  Madhumitha Tolakanahalli Pradeep
> > > > > > + *      <madhumitha.tolakanahalli.pradeep@intel.com>
> > > > > > + *
> > > > > > + * Display Port Tiled Display Test
> > > > > > + * This test parses the tile information of the connectors that have TILE
> > > > > > + * property set, sets up the framebuffer with correct offsets corresponding to
> > > > > > + * the tile offsets and does an atomic modeset with two CRTCs for two
> > > > > > + * connectors.
> > > > > > + *
> > > > > > + * This test currently supports only horizontally tiled displays, in line with
> > > > > > + * the displays supported by the kernel at the moment.
> > > > > > + */
> > > > > > +
> > > > > > +#include "drm_mode.h"
> > > > > > +#include "drm_fourcc.h"
> > > > > > +#include "igt.h"
> > > > > > +
> > > > > > +typedef struct {
> > > > > > +    int drm_fd;
> > > > > > +    int num_h_tiles;
> > > > > > +    igt_display_t *display;
> > > > > > +    enum igt_commit_style commit;
> > > > > > +} data_t;
> > > > > > +
> > > > > > +typedef struct {
> > > > > > +    igt_output_t *output;
> > > > > > +    igt_tile_info_t *tile;
> > > > > > +    igt_fb_t fb_test_pattern;
> > > > > > +    drmModeConnectorPtr connector;
> > > > > > +    enum pipe pipe;
> > > > > > +    enum igt_commit_style commit;
> > > > > > +} data_connector_t;
> > > > > > +
> > > > > > +static inline int drm_property_is_tile(drmModePropertyPtr prop)
> > > > > 
> > > > > I wouldn't personally use `inline`. The compiler is smarter than humans
> > > > > to decide whether or not a function should be inlined.
> > > > > 
> > > > > > +{
> > > > > > +	return(strcmp(prop->name ? prop->name : "", "TILE")? 0 : 1);
> > > > > 
> > > > > Style: unnecessary parentheses, missing space before `?`.
> > > > > 
> > > > > > +}
> > > > > > +
> > > > > > +static void get_number_of_h_tiles(data_t *data)
> > > > > 
> > > > > What if multiple tiles are connected? Shouldn't we use tile_group_id?
> > > > 
> > > > Yes there could be multiple monitors with tiles so use tile_group_id to check
> > > > that the tile belongs to the same group and then use num_h_tiles
> > 
> > But actually the current hardware like Madhumitha mentioned only supports one tile group,
> > if we have to support multiple tile groups then we would need to malloc the array of structures
> > for the connectors associated with separate tile groups and then have a separate subtest for
> > tile group 1 tile group 2 etc. This logic will not get tested right now due to HW constraint.
> > 
> > So the idea is for the IGT to check the tile group id but only support 1 tile group so far
> > and leave the room for further extending it to multiple tiles instead of over complicating
> > the logic now.
> > 
> > Does that make sense or do you think we should already add the subtests for multiple tile groups?
> 
> That makes perfect sense to me, support for multiple tile groups can be
> left as a TODO for later.
> 
> Incremental patches are way easier to review than one-patch-that-
> implements-all-features-at-once. :)

Great so we will keep the implemnetation to 1 tile group id for now

> 
> > > > > > +{
> > > > > > +    int i;
> > > > > > +    drmModeRes *res;
> > > > > > +    drmModeConnector *connector;
> > > > > > +    drmModePropertyPtr prop;
> > > > > > +    drmModePropertyBlobPtr blob;
> > > > > > +    igt_tile_info_t tile;
> > > > > > +
> > > > > > +    igt_require(res = drmModeGetResources(data->drm_fd));
> > > > > 
> > > > > This should probably be igt_assert.
> > > > > 
> > > > > > +    for(i = 0; i < res->count_connectors; i++)
> > > > > > +    {
> > > > > 
> > > > > Style: no newline before `{` (only for functions, applies to the whole
> > > > > patch).
> > > > > 
> > > > > > +        connector = drmModeGetConnectorCurrent(data->drm_fd, \
> > > > > 
> > > > > Style: unnecessary `\`.
> > > > > 
> > > > > We could igt_assert(connector).
> > > > > 
> > > > > > +                                               res->connectors[i]);
> > > > > > +
> > > > > > +        if(!((connector->connection == DRM_MODE_CONNECTED) &&
> > > > > > +            (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort)))
> > > > > > +                continue;
> > > > > 
> > > > > Style: we can invert this condition to make clearer.
> > > > 
> > > > But wouldnt that add additional nesting?
> > > 
> > > I mean, this could be re-written as:
> > > 
> > >     if (connector->connection != DRM_MODE_CONNECTED ||
> > >         connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort)
> > 
> > Oh yes that makes perfect sense!
> > 
> > > > > > +
> > > > > > +        for(i = 0; i < connector->count_props; i++)
> > > > > > +        {
> > > > > > +            prop = drmModeGetProperty(data->drm_fd, connector->props[i]);
> > > > > 
> > > > > We could igt_assert(prop)
> > > > > 
> > > > > We need to free it at some point.
> > > > > 
> > > > > > +            if(!(drm_property_is_tile(prop) &&
> > > > > 
> > > > > Style: missing space after if keyword (applies to the whole patch).
> > > > > 
> > > > > > +                drm_property_type_is(prop, DRM_MODE_PROP_BLOB)))
> > > > > 
> > > > > I'd move this check into drm_property_is_tile.
> > > > > 
> > > > > > +                continue;
> > > > > > +
> > > > > > +            blob = drmModeGetPropertyBlob(data->drm_fd, \
> > > > > > +                                          connector->prop_values[i]);
> > > > > > +
> > > > > > +            if(!blob)
> > > > > > +                break;
> > > > > > +            igt_parse_connector_tile_blob(blob, &tile);
> > > > > > +            data->num_h_tiles = tile.num_h_tile;
> > > > > > +            break;
> > > > > > +        }
> > > > > > +    }
> > > > > > +}
> > > > > > +
> > > > > > +static int set_test_pattern_fb(data_t *data, data_connector_t *conn_data)
> > > > > > +{
> > > > > > +    int i;
> > > > > > +    int count = 0;
> > > > > > +    bool is_tile = false;
> > > > > > +    enum pipe pipe;
> > > > > > +    igt_tile_info_t tile;
> > > > > > +    igt_output_t *output;
> > > > > > +    igt_plane_t *primary;
> > > > > > +    drmModePropertyPtr prop;
> > > > > > +    drmModePropertyBlobPtr blob;
> > > > > > +
> > > > > > +    for_each_connected_output(data->display, output)
> > > > > > +    {
> > > > > > +        is_tile = false;
> > > > > > +
> > > > > > +        conn_data[count].connector = drmModeGetConnector(data->display->drm_fd, \
> > > > > > +                                                         output->id);
> > > > > > +
> > > > > > +        if(!(conn_data[count].connector->connector_type ==
> > > > > > +                        DRM_MODE_CONNECTOR_DisplayPort))
> > > > > > +            continue;
> > > > > > +
> > > > > > +        /* Parse through each connector property */
> > > > > > +        for(i = 0; i < conn_data[count].connector->count_props; i++)
> > > > > > +        {
> > > > > > +            prop = drmModeGetProperty(data->display->drm_fd, \
> > > > > > +                                      conn_data[count].connector->props[i]);
> > > > > > +
> > > > > > +            if(!((drm_property_is_tile(prop) &&
> > > > > > +                drm_property_type_is(prop, DRM_MODE_PROP_BLOB))))
> > > > > > +                continue;
> > > > > > +
> > > > > > +            blob = drmModeGetPropertyBlob(data->display->drm_fd, \
> > > > > > +                            conn_data[count].connector->prop_values[i]);
> > > > > > +
> > > > > > +            if(!blob)
> > > > > > +                break;
> > > > > > +
> > > > > > +            igt_parse_connector_tile_blob(blob, &tile);
> > > > > > +            conn_data[count].tile = &tile;
> > > > > > +            is_tile = true;
> > > > > > +            break;
> > > > > > +        }
> > > > > 
> > > > > I feel like this whole block above is duplicated. Could be extracted
> > > > > into a function, e.g.
> > > > > 
> > > > >     bool connector_get_tile(drmModeConnectorRes *conn, igt_tile_info_t *tile_info)
> > > > > 
> > > > > > +        if(!is_tile)
> > > > > > +            continue;
> > > > > > +
> > > > > > +        output = igt_output_from_connector(data->display, \
> > > > > > +                                           conn_data[count].connector);
> > > > > 
> > > > > Style: unnecessary `\`. Applies to the whole patch.
> > > > > 
> > > > > > +
> > > > > > +        for_each_pipe(data->display, pipe)
> > > > > > +        {
> > > > > > +            igt_debug("Current PIPE is %d\n", pipe);
> > > > > > +
> > > > > > +            if((count > 0) && (pipe == conn_data[count-1].pipe))
> > > > > > +                continue;
> > > > > 
> > > > > Style: unnecessary parentheses.
> > > > > 
> > > > > > +            if(igt_pipe_connector_valid(pipe, output)) {
> > > > > > +                conn_data[count].pipe = pipe;
> > > > > > +                conn_data[count].output = output;
> > > > > > +
> > > > > > +                igt_output_set_pipe(conn_data[count].output, \
> > > > > > +                                    conn_data[count].pipe);
> > > > > > +
> > > > > > +                igt_create_pattern_fb(data->drm_fd,\
> > > > > > +                                    (conn_data[count].tile->tile_h_size *\
> > > > > > +                                     data->num_h_tiles),\
> > > > > > +                                     conn_data[count].tile->tile_v_size,\
> > > > > > +                                     DRM_FORMAT_XBGR8888,\
> > > > > > +                                     LOCAL_DRM_FORMAT_MOD_NONE,\
> > > > > > +                                     &conn_data[count].fb_test_pattern);
> > > > > > +
> > > > > > +                primary = igt_output_get_plane_type(conn_data[count].output,\
> > > > > > +                                                    DRM_PLANE_TYPE_PRIMARY);
> > > > > > +
> > > > > > +                igt_plane_set_fb(primary, &conn_data[count].fb_test_pattern);
> > > > > > +
> > > > > > +                igt_fb_set_size(&conn_data[count].fb_test_pattern, primary,\
> > > > > > +                                conn_data[count].tile->tile_h_size,\
> > > > > > +                                conn_data[count].tile->tile_v_size);
> > > > > > +
> > > > > > +                igt_fb_set_position(&conn_data[count].fb_test_pattern, \
> > > > > > +                                    primary,\
> > > > > > +                                    (conn_data[count].tile->tile_h_size *\
> > > > > > +                                    conn_data[count].tile->tile_h_loc),
> > > > > > +                                    (conn_data[count].tile->tile_v_size *\
> > > > > > +                                    conn_data[count].tile->tile_v_loc));
> > > > > > +
> > > > > > +                igt_plane_set_size(primary,\
> > > > > > +                                   conn_data[count].tile->tile_h_size,\
> > > > > > +                                   conn_data[count].tile->tile_v_size);
> > > > > > +
> > > > > > +                break;
> > > > > > +            }
> > > > > > +        }
> > > > > > +        count++;
> > > > > > +    }
> > > > > > +
> > > > > > +    return count;
> > > > > > +}
> > > > > > +
> > > > > > +igt_main
> > > > > > +{
> > > > > > +    igt_display_t display;
> > > > > > +    data_t data = {};
> > > > > > +    data_connector_t *conn_data;
> > > > > > +
> > > > > > +    igt_fixture {
> > > > > > +        data.drm_fd = drm_open_driver_master(DRIVER_ANY);
> > > > > > +        kmstest_set_vt_graphics_mode();
> > > > > > +        igt_display_require(&display, data.drm_fd);
> > > > > > +        data.display = &display;
> > > > > > +
> > > > > > +        get_number_of_h_tiles(&data);
> > > > > > +        igt_debug("Number of Horizontal Tiles: %d\n", data.num_h_tiles);
> > > > > > +        data.commit = data.display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY;
> > > > > > +    }
> > > > > > +
> > > > > > +    if(data.num_h_tiles > 0)
> > > > > > +        conn_data = (data_connector_t *)malloc(data.num_h_tiles * \
> > > > > > +                                                sizeof(data_connector_t));
> > > > > 
> > > > > No need for this cast, unnecessary `\`.
> > > > > 
> > > > > > +    igt_assert(conn_data);
> > > > > 
> > > > > This check reads garbage from the stack if data.num_h_tiles == 0.
> > > > 
> > > > This check should possibly be inside the same if
> > > > 
> > > > > > +    igt_subtest_f("basic-test-pattern") {
> > > > > 
> > > > > No need for the _f suffix.
> > > > > 
> > > > > This subtest is missing a description. Could you add one? For more
> > > > > information, see:
> > > > > https://drm.pages.freedesktop.org/igt-gpu-tools/igt-gpu-tools-Core.html#igt-describe
> > > > > 
> > > > > > +        igt_skip_on(!data.num_h_tiles);
> > > > > > +        set_test_pattern_fb(&data, conn_data);
> > > > > > +        igt_display_commit2(data.display, data.commit);
> > > > > 
> > > > > I'm not sure I understand what this test checks. It does a commit on
> > > > > all tiled connectors, but doesn't check anything afterwards. Maybe it
> > > > > should check the pageflip serial and timings?
> > > > 
> > > > This is so far a manual test where we just look at the pattern and make sure no artifacts
> > > > and auto testing just make sure the commit did not fail, any better idea to check if the
> > > > page_flip timeouts didnt occur or not sure if we can do crc checks to ensure no artifacts?
> > > > Any ideas/suggestions?
> > > 
> > > To be honest I'm not a fan of manual testing.
> > > 
> > > As I understand it, tiled displays must be updated in sync so that you
> > > don't get tearing. If one display is page-flipped before the other,
> > > there will be tearing in the middle of the tiled screen. Am I reading
> > > the commit message correctly?
> > 
> > Yes there would be tearing if one tile page flipped before the other
> > and the HW prevents this from happening by synchronizing the two vblanks
> > from the two ports.
> > 
> > If there an example of igt where we can check the vblank timing or page flip timings
> > to add this check?
> 
> I believe tests in kms_flip do a similar check. The page_flip_handler
> function handles the page flip event (which is given the flip timestamp
> and sequence number). check_state verifies that the timestamp is close
> enough to what we expect (in our atomic check, maybe we can compare
> with strict equality).
> 
> Since we're dealing with multiple CRTCs, it may be a good idea to use
> drmEventContext.version = 3 with page_flip_handler2 so that we also get
> the CRTC in the page flip handler. Version 3 is a core DRM feature, all
> drivers support it given a recent enough kernel.
> 
> Rough pseudo-code:
> 
> 	/* When committing buffer, request a page flip */
> 	drmModeAtomicCommit(fd, req, DRM_MODE_ATOMIC_NONBLOCK |
> 			    DRM_MODE_PAGE_FLIP_EVENT, data);

Here we do the modese with igt_display_commit2 call that then calls drmModeAtomicCommit but
doesnt call it with Page flip, do we have another igt helper that does a atomic commit with
page flip event?

Can we not just do atomic commit and get vblank events so for two crtcs we get two events and compare
the timestamp and make sure they are close enough?

Manasi

> 
> 	static void page_flip_handler(int fd, unsigned seq,
> 				      unsigned tv_sec,
> 				      unsigned tv_usec,
> 				      unsigned crtc_id, void *data)
> 	{
> 		/* Compare params with the other page flip */
> 	}
> 
> 	/* When we get POLLIN in the DRM FD */
> 	drmEventContext event = {
> 		.version = 3,
> 		.page_flip_handler2 = page_flip_handler,
> 	};
> 	drmHandleEvent(fd, &event);
> 
> > Manasi
> > 
> > > If so, maybe we can check the page-flip timings and make sure they are
> > > equal?
> > > 
> > > A CRC check might be a good idea too, to make sure bandwidth isn't an
> > > issue.
> > > 
> > > CC'ing Martin in case he has better ideas.
> > > 
> > > > Manasi
> > > > 
> > > > > > +    }
> > > > > > +
> > > > > > +    igt_fixture {
> > > > > > +        if(data.num_h_tiles > 0)
> > > > > > +            free(conn_data);
> > > > > 
> > > > > If conn_data was initialized to NULL, no need for the check, because
> > > > > free(NULL) is a no-op.
> > > > > 
> > > > > > +        kmstest_restore_vt_mode();
> > > > > > +        igt_display_fini(data.display);
> > > > > > +    }
> > > > > > +}
> > > > > > diff --git a/tests/meson.build b/tests/meson.build
> > > > > > index 34a74025..6a6e9ce9 100644
> > > > > > --- a/tests/meson.build
> > > > > > +++ b/tests/meson.build
> > > > > > @@ -25,6 +25,7 @@ test_progs = [
> > > > > >  	'kms_cursor_edge_walk',
> > > > > >  	'kms_cursor_legacy',
> > > > > >  	'kms_dp_dsc',
> > > > > > +	'kms_dp_tiled_display',
> > > > > >  	'kms_draw_crc',
> > > > > >  	'kms_fbcon_fbt',
> > > > > >  	'kms_fence_pin_leak',
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [igt-dev] [PATCH i-g-t] igt/tests/kms_dp_tiled_display.c : kms test file for display port tiled displays
  2019-08-01 17:38           ` Manasi Navare
@ 2019-08-02  1:09             ` Tolakanahalli Pradeep, Madhumitha
  2019-08-08  1:10             ` Tolakanahalli Pradeep, Madhumitha
  1 sibling, 0 replies; 18+ messages in thread
From: Tolakanahalli Pradeep, Madhumitha @ 2019-08-02  1:09 UTC (permalink / raw)
  To: Navare, Manasi D, Ser, Simon; +Cc: igt-dev, Latvala, Petri

Thank you for the great inputs, Manasi and Simon


On Thu, 2019-08-01 at 10:38 -0700, Manasi Navare wrote:
> Thank Simon for all your inputs. Please find some of my questions
> below:
> 
> On Thu, Aug 01, 2019 at 12:41:37AM -0700, Ser, Simon wrote:
> > On Wed, 2019-07-31 at 10:13 -0700, Manasi Navare wrote:
> > > On Wed, Jul 31, 2019 at 12:25:09AM -0700, Ser, Simon wrote:
> > > > On Tue, 2019-07-30 at 12:21 -0700, Manasi Navare wrote:
> > > > > On Wed, Jul 17, 2019 at 11:43:48PM -0700, Ser, Simon wrote:
> > > > > > Thanks for your patch! Here are some comments.
> > > > > > 
> > > > > > Style: we use tabs for indentation, not spaces.
> > > > > > 
> > > > > > On Wed, 2019-07-17 at 11:02 -0700, Madhumitha Tolakanahalli
> > > > > > Pradeep wrote:
> > > > > > > This test validates the tiled DP displays to display a
> > > > > > > test pattern seamlessly
> > > > > > > across the two tiles. It validates the transcoder port
> > > > > > > sync feature on i915 to
> > > > > > > get a tearfree tiled display output.
> > > > > > > 
> > > > > > > Related kernel work patches -> 
> > > > > > > https://patchwork.freedesktop.org/series/59837/#rev4.
> > > > > > > This test can eventually be extended to cover tiled
> > > > > > > display support on other connector
> > > > > > > types.
> > > > > > > 
> > > > > > > Cc: Manasi Navare <manasi.d.navare@intel.com>
> > > > > > > Cc: Petri Latvala <petri.latvala@intel.com>
> > > > > > > Signed-off-by: Madhumitha Tolakanahalli Pradeep <
> > > > > > > madhumitha.tolakanahalli.pradeep@intel.com>
> > > > > > 
> > > > > > Next time, can you send both patches in one go? It's not
> > > > > > possible to
> > > > > > check whether this test actually passes CI, since build
> > > > > > fails (see the
> > > > > > two automated failure replies).
> > > > > 
> > > > > Yes please send this as a series with 1st patch that defines
> > > > > the tile parser
> > > > > and second with the actual test that uses it
> > > > > 
> > > > > > To learn how to use git-send-email, you can read:
> > > > > > https://git-send-email.io/
> > > > > > 
> > > > > > > ---
> > > > > > >  tests/Makefile.sources       |   1 +
> > > > > > >  tests/kms_dp_tiled_display.c | 239
> > > > > > > +++++++++++++++++++++++++++++++++++
> > > > > > >  tests/meson.build            |   1 +
> > > > > > >  3 files changed, 241 insertions(+)
> > > > > > >  create mode 100644 tests/kms_dp_tiled_display.c
> > > > > > > 
> > > > > > > diff --git a/tests/Makefile.sources
> > > > > > > b/tests/Makefile.sources
> > > > > > > index 250dbd33..e9373941 100644
> > > > > > > --- a/tests/Makefile.sources
> > > > > > > +++ b/tests/Makefile.sources
> > > > > > > @@ -40,6 +40,7 @@ TESTS_progs = \
> > > > > > >  	kms_cursor_edge_walk \
> > > > > > >  	kms_cursor_legacy \
> > > > > > >  	kms_dp_dsc \
> > > > > > > +	kms_dp_tiled_display \
> > > > > > >  	kms_draw_crc \
> > > > > > >  	kms_fbcon_fbt \
> > > > > > >  	kms_fence_pin_leak \
> > > > > > > diff --git a/tests/kms_dp_tiled_display.c
> > > > > > > b/tests/kms_dp_tiled_display.c
> > > > > > > new file mode 100644
> > > > > > > index 00000000..af644573
> > > > > > > --- /dev/null
> > > > > > > +++ b/tests/kms_dp_tiled_display.c
> > > > > > > @@ -0,0 +1,239 @@
> > > > > > > +/*
> > > > > > > + * Copyright © 2018 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.
> > > > > > > + *
> > > > > > > + * Authors:
> > > > > > > + *  Madhumitha Tolakanahalli Pradeep
> > > > > > > + *      <madhumitha.tolakanahalli.pradeep@intel.com>
> > > > > > > + *
> > > > > > > + * Display Port Tiled Display Test
> > > > > > > + * This test parses the tile information of the
> > > > > > > connectors that have TILE
> > > > > > > + * property set, sets up the framebuffer with correct
> > > > > > > offsets corresponding to
> > > > > > > + * the tile offsets and does an atomic modeset with two
> > > > > > > CRTCs for two
> > > > > > > + * connectors.
> > > > > > > + *
> > > > > > > + * This test currently supports only horizontally tiled
> > > > > > > displays, in line with
> > > > > > > + * the displays supported by the kernel at the moment.
> > > > > > > + */
> > > > > > > +
> > > > > > > +#include "drm_mode.h"
> > > > > > > +#include "drm_fourcc.h"
> > > > > > > +#include "igt.h"
> > > > > > > +
> > > > > > > +typedef struct {
> > > > > > > +    int drm_fd;
> > > > > > > +    int num_h_tiles;
> > > > > > > +    igt_display_t *display;
> > > > > > > +    enum igt_commit_style commit;
> > > > > > > +} data_t;
> > > > > > > +
> > > > > > > +typedef struct {
> > > > > > > +    igt_output_t *output;
> > > > > > > +    igt_tile_info_t *tile;
> > > > > > > +    igt_fb_t fb_test_pattern;
> > > > > > > +    drmModeConnectorPtr connector;
> > > > > > > +    enum pipe pipe;
> > > > > > > +    enum igt_commit_style commit;
> > > > > > > +} data_connector_t;
> > > > > > > +
> > > > > > > +static inline int
> > > > > > > drm_property_is_tile(drmModePropertyPtr prop)
> > > > > > 
> > > > > > I wouldn't personally use `inline`. The compiler is smarter
> > > > > > than humans
> > > > > > to decide whether or not a function should be inlined.
> > > > > > 
> > > > > > > +{
> > > > > > > +	return(strcmp(prop->name ? prop->name : "", "TILE")? 0
> > > > > > > : 1);
> > > > > > 
> > > > > > Style: unnecessary parentheses, missing space before `?`.
> > > > > > 
> > > > > > > +}
> > > > > > > +
> > > > > > > +static void get_number_of_h_tiles(data_t *data)
> > > > > > 
> > > > > > What if multiple tiles are connected? Shouldn't we use
> > > > > > tile_group_id?
> > > > > 
> > > > > Yes there could be multiple monitors with tiles so use
> > > > > tile_group_id to check
> > > > > that the tile belongs to the same group and then use
> > > > > num_h_tiles
> > > 
> > > But actually the current hardware like Madhumitha mentioned only
> > > supports one tile group,
> > > if we have to support multiple tile groups then we would need to
> > > malloc the array of structures
> > > for the connectors associated with separate tile groups and then
> > > have a separate subtest for
> > > tile group 1 tile group 2 etc. This logic will not get tested
> > > right now due to HW constraint.
> > > 
> > > So the idea is for the IGT to check the tile group id but only
> > > support 1 tile group so far
> > > and leave the room for further extending it to multiple tiles
> > > instead of over complicating
> > > the logic now.
> > > 
> > > Does that make sense or do you think we should already add the
> > > subtests for multiple tile groups?
> > 
> > That makes perfect sense to me, support for multiple tile groups
> > can be
> > left as a TODO for later.
> > 
> > Incremental patches are way easier to review than one-patch-that-
> > implements-all-features-at-once. :)
> 
> Great so we will keep the implemnetation to 1 tile group id for now
> 
> > 
> > > > > > > +{
> > > > > > > +    int i;
> > > > > > > +    drmModeRes *res;
> > > > > > > +    drmModeConnector *connector;
> > > > > > > +    drmModePropertyPtr prop;
> > > > > > > +    drmModePropertyBlobPtr blob;
> > > > > > > +    igt_tile_info_t tile;
> > > > > > > +
> > > > > > > +    igt_require(res = drmModeGetResources(data-
> > > > > > > >drm_fd));
> > > > > > 
> > > > > > This should probably be igt_assert.
> > > > > > 
> > > > > > > +    for(i = 0; i < res->count_connectors; i++)
> > > > > > > +    {
> > > > > > 
> > > > > > Style: no newline before `{` (only for functions, applies
> > > > > > to the whole
> > > > > > patch).
> > > > > > 
> > > > > > > +        connector = drmModeGetConnectorCurrent(data-
> > > > > > > >drm_fd, \
> > > > > > 
> > > > > > Style: unnecessary `\`.
> > > > > > 
> > > > > > We could igt_assert(connector).
> > > > > > 
> > > > > > > +                                               res-
> > > > > > > >connectors[i]);
> > > > > > > +
> > > > > > > +        if(!((connector->connection ==
> > > > > > > DRM_MODE_CONNECTED) &&
> > > > > > > +            (connector->connector_type ==
> > > > > > > DRM_MODE_CONNECTOR_DisplayPort)))
> > > > > > > +                continue;
> > > > > > 
> > > > > > Style: we can invert this condition to make clearer.
> > > > > 
> > > > > But wouldnt that add additional nesting?
> > > > 
> > > > I mean, this could be re-written as:
> > > > 
> > > >     if (connector->connection != DRM_MODE_CONNECTED ||
> > > >         connector->connector_type !=
> > > > DRM_MODE_CONNECTOR_DisplayPort)
> > > 
> > > Oh yes that makes perfect sense!
> > > 
> > > > > > > +
> > > > > > > +        for(i = 0; i < connector->count_props; i++)
> > > > > > > +        {
> > > > > > > +            prop = drmModeGetProperty(data->drm_fd,
> > > > > > > connector->props[i]);
> > > > > > 
> > > > > > We could igt_assert(prop)
> > > > > > 
> > > > > > We need to free it at some point.
> > > > > > 
> > > > > > > +            if(!(drm_property_is_tile(prop) &&
> > > > > > 
> > > > > > Style: missing space after if keyword (applies to the whole
> > > > > > patch).
> > > > > > 
> > > > > > > +                drm_property_type_is(prop,
> > > > > > > DRM_MODE_PROP_BLOB)))
> > > > > > 
> > > > > > I'd move this check into drm_property_is_tile.
> > > > > > 
> > > > > > > +                continue;
> > > > > > > +
> > > > > > > +            blob = drmModeGetPropertyBlob(data->drm_fd,
> > > > > > > \
> > > > > > > +                                          connector-
> > > > > > > >prop_values[i]);
> > > > > > > +
> > > > > > > +            if(!blob)
> > > > > > > +                break;
> > > > > > > +            igt_parse_connector_tile_blob(blob, &tile);
> > > > > > > +            data->num_h_tiles = tile.num_h_tile;
> > > > > > > +            break;
> > > > > > > +        }
> > > > > > > +    }
> > > > > > > +}
> > > > > > > +
> > > > > > > +static int set_test_pattern_fb(data_t *data,
> > > > > > > data_connector_t *conn_data)
> > > > > > > +{
> > > > > > > +    int i;
> > > > > > > +    int count = 0;
> > > > > > > +    bool is_tile = false;
> > > > > > > +    enum pipe pipe;
> > > > > > > +    igt_tile_info_t tile;
> > > > > > > +    igt_output_t *output;
> > > > > > > +    igt_plane_t *primary;
> > > > > > > +    drmModePropertyPtr prop;
> > > > > > > +    drmModePropertyBlobPtr blob;
> > > > > > > +
> > > > > > > +    for_each_connected_output(data->display, output)
> > > > > > > +    {
> > > > > > > +        is_tile = false;
> > > > > > > +
> > > > > > > +        conn_data[count].connector =
> > > > > > > drmModeGetConnector(data->display->drm_fd, \
> > > > > > > +                                                        
> > > > > > >  output->id);
> > > > > > > +
> > > > > > > +        if(!(conn_data[count].connector->connector_type
> > > > > > > ==
> > > > > > > +                        DRM_MODE_CONNECTOR_DisplayPort))
> > > > > > > +            continue;
> > > > > > > +
> > > > > > > +        /* Parse through each connector property */
> > > > > > > +        for(i = 0; i < conn_data[count].connector-
> > > > > > > >count_props; i++)
> > > > > > > +        {
> > > > > > > +            prop = drmModeGetProperty(data->display-
> > > > > > > >drm_fd, \
> > > > > > > +                                      conn_data[count].c
> > > > > > > onnector->props[i]);
> > > > > > > +
> > > > > > > +            if(!((drm_property_is_tile(prop) &&
> > > > > > > +                drm_property_type_is(prop,
> > > > > > > DRM_MODE_PROP_BLOB))))
> > > > > > > +                continue;
> > > > > > > +
> > > > > > > +            blob = drmModeGetPropertyBlob(data->display-
> > > > > > > >drm_fd, \
> > > > > > > +                            conn_data[count].connector-
> > > > > > > >prop_values[i]);
> > > > > > > +
> > > > > > > +            if(!blob)
> > > > > > > +                break;
> > > > > > > +
> > > > > > > +            igt_parse_connector_tile_blob(blob, &tile);
> > > > > > > +            conn_data[count].tile = &tile;
> > > > > > > +            is_tile = true;
> > > > > > > +            break;
> > > > > > > +        }
> > > > > > 
> > > > > > I feel like this whole block above is duplicated. Could be
> > > > > > extracted
> > > > > > into a function, e.g.
> > > > > > 
> > > > > >     bool connector_get_tile(drmModeConnectorRes *conn,
> > > > > > igt_tile_info_t *tile_info)
> > > > > > 
> > > > > > > +        if(!is_tile)
> > > > > > > +            continue;
> > > > > > > +
> > > > > > > +        output = igt_output_from_connector(data-
> > > > > > > >display, \
> > > > > > > +                                           conn_data[cou
> > > > > > > nt].connector);
> > > > > > 
> > > > > > Style: unnecessary `\`. Applies to the whole patch.
> > > > > > 
> > > > > > > +
> > > > > > > +        for_each_pipe(data->display, pipe)
> > > > > > > +        {
> > > > > > > +            igt_debug("Current PIPE is %d\n", pipe);
> > > > > > > +
> > > > > > > +            if((count > 0) && (pipe == conn_data[count-
> > > > > > > 1].pipe))
> > > > > > > +                continue;
> > > > > > 
> > > > > > Style: unnecessary parentheses.
> > > > > > 
> > > > > > > +            if(igt_pipe_connector_valid(pipe, output)) {
> > > > > > > +                conn_data[count].pipe = pipe;
> > > > > > > +                conn_data[count].output = output;
> > > > > > > +
> > > > > > > +                igt_output_set_pipe(conn_data[count].out
> > > > > > > put, \
> > > > > > > +                                    conn_data[count].pip
> > > > > > > e);
> > > > > > > +
> > > > > > > +                igt_create_pattern_fb(data->drm_fd,\
> > > > > > > +                                    (conn_data[count].ti
> > > > > > > le->tile_h_size *\
> > > > > > > +                                     data-
> > > > > > > >num_h_tiles),\
> > > > > > > +                                     conn_data[count].ti
> > > > > > > le->tile_v_size,\
> > > > > > > +                                     DRM_FORMAT_XBGR8888
> > > > > > > ,\
> > > > > > > +                                     LOCAL_DRM_FORMAT_MO
> > > > > > > D_NONE,\
> > > > > > > +                                     &conn_data[count].f
> > > > > > > b_test_pattern);
> > > > > > > +
> > > > > > > +                primary =
> > > > > > > igt_output_get_plane_type(conn_data[count].output,\
> > > > > > > +                                                    DRM_
> > > > > > > PLANE_TYPE_PRIMARY);
> > > > > > > +
> > > > > > > +                igt_plane_set_fb(primary,
> > > > > > > &conn_data[count].fb_test_pattern);
> > > > > > > +
> > > > > > > +                igt_fb_set_size(&conn_data[count].fb_tes
> > > > > > > t_pattern, primary,\
> > > > > > > +                                conn_data[count].tile-
> > > > > > > >tile_h_size,\
> > > > > > > +                                conn_data[count].tile-
> > > > > > > >tile_v_size);
> > > > > > > +
> > > > > > > +                igt_fb_set_position(&conn_data[count].fb
> > > > > > > _test_pattern, \
> > > > > > > +                                    primary,\
> > > > > > > +                                    (conn_data[count].ti
> > > > > > > le->tile_h_size *\
> > > > > > > +                                    conn_data[count].til
> > > > > > > e->tile_h_loc),
> > > > > > > +                                    (conn_data[count].ti
> > > > > > > le->tile_v_size *\
> > > > > > > +                                    conn_data[count].til
> > > > > > > e->tile_v_loc));
> > > > > > > +
> > > > > > > +                igt_plane_set_size(primary,\
> > > > > > > +                                   conn_data[count].tile
> > > > > > > ->tile_h_size,\
> > > > > > > +                                   conn_data[count].tile
> > > > > > > ->tile_v_size);
> > > > > > > +
> > > > > > > +                break;
> > > > > > > +            }
> > > > > > > +        }
> > > > > > > +        count++;
> > > > > > > +    }
> > > > > > > +
> > > > > > > +    return count;
> > > > > > > +}
> > > > > > > +
> > > > > > > +igt_main
> > > > > > > +{
> > > > > > > +    igt_display_t display;
> > > > > > > +    data_t data = {};
> > > > > > > +    data_connector_t *conn_data;
> > > > > > > +
> > > > > > > +    igt_fixture {
> > > > > > > +        data.drm_fd =
> > > > > > > drm_open_driver_master(DRIVER_ANY);
> > > > > > > +        kmstest_set_vt_graphics_mode();
> > > > > > > +        igt_display_require(&display, data.drm_fd);
> > > > > > > +        data.display = &display;
> > > > > > > +
> > > > > > > +        get_number_of_h_tiles(&data);
> > > > > > > +        igt_debug("Number of Horizontal Tiles: %d\n",
> > > > > > > data.num_h_tiles);
> > > > > > > +        data.commit = data.display->is_atomic ?
> > > > > > > COMMIT_ATOMIC : COMMIT_LEGACY;
> > > > > > > +    }
> > > > > > > +
> > > > > > > +    if(data.num_h_tiles > 0)
> > > > > > > +        conn_data = (data_connector_t
> > > > > > > *)malloc(data.num_h_tiles * \
> > > > > > > +                                                sizeof(d
> > > > > > > ata_connector_t));
> > > > > > 
> > > > > > No need for this cast, unnecessary `\`.
> > > > > > 
> > > > > > > +    igt_assert(conn_data);
> > > > > > 
> > > > > > This check reads garbage from the stack if data.num_h_tiles
> > > > > > == 0.
> > > > > 
> > > > > This check should possibly be inside the same if
> > > > > 
> > > > > > > +    igt_subtest_f("basic-test-pattern") {
> > > > > > 
> > > > > > No need for the _f suffix.
> > > > > > 
> > > > > > This subtest is missing a description. Could you add one?
> > > > > > For more
> > > > > > information, see:
> > > > > > 
https://drm.pages.freedesktop.org/igt-gpu-tools/igt-gpu-tools-Core.html#igt-describe
> > > > > > 
> > > > > > > +        igt_skip_on(!data.num_h_tiles);
> > > > > > > +        set_test_pattern_fb(&data, conn_data);
> > > > > > > +        igt_display_commit2(data.display, data.commit);
> > > > > > 
> > > > > > I'm not sure I understand what this test checks. It does a
> > > > > > commit on
> > > > > > all tiled connectors, but doesn't check anything
> > > > > > afterwards. Maybe it
> > > > > > should check the pageflip serial and timings?
> > > > > 
> > > > > This is so far a manual test where we just look at the
> > > > > pattern and make sure no artifacts
> > > > > and auto testing just make sure the commit did not fail, any
> > > > > better idea to check if the
> > > > > page_flip timeouts didnt occur or not sure if we can do crc
> > > > > checks to ensure no artifacts?
> > > > > Any ideas/suggestions?
> > > > 
> > > > To be honest I'm not a fan of manual testing.
> > > > 
> > > > As I understand it, tiled displays must be updated in sync so
> > > > that you
> > > > don't get tearing. If one display is page-flipped before the
> > > > other,
> > > > there will be tearing in the middle of the tiled screen. Am I
> > > > reading
> > > > the commit message correctly?
> > > 
> > > Yes there would be tearing if one tile page flipped before the
> > > other
> > > and the HW prevents this from happening by synchronizing the two
> > > vblanks
> > > from the two ports.
> > > 
> > > If there an example of igt where we can check the vblank timing
> > > or page flip timings
> > > to add this check?
> > 
> > I believe tests in kms_flip do a similar check. The
> > page_flip_handler
> > function handles the page flip event (which is given the flip
> > timestamp
> > and sequence number). check_state verifies that the timestamp is
> > close
> > enough to what we expect (in our atomic check, maybe we can compare
> > with strict equality).
> > 
> > Since we're dealing with multiple CRTCs, it may be a good idea to
> > use
> > drmEventContext.version = 3 with page_flip_handler2 so that we also
> > get
> > the CRTC in the page flip handler. Version 3 is a core DRM feature,
> > all
> > drivers support it given a recent enough kernel.
> > 
> > Rough pseudo-code:
> > 
> > 	/* When committing buffer, request a page flip */
> > 	drmModeAtomicCommit(fd, req, DRM_MODE_ATOMIC_NONBLOCK |
> > 			    DRM_MODE_PAGE_FLIP_EVENT, data);
> 
> Here we do the modese with igt_display_commit2 call that then calls
> drmModeAtomicCommit but
> doesnt call it with Page flip, do we have another igt helper that
> does a atomic commit with
> page flip event?
> 

I was looking at adding a check for Page Flip event and verifying
Timestamps.
Looks like igt_display_commit_atomic() with DRM_MODE_PAGE_FLIP_EVENT
flag allows us to perfrom a commit and with a page flip event.
Please do let me know if there is a better way to do this.

Madhumitha


> Can we not just do atomic commit and get vblank events so for two
> crtcs we get two events and compare
> the timestamp and make sure they are close enough?
> 
> Manasi
> 
> > 
> > 	static void page_flip_handler(int fd, unsigned seq,
> > 				      unsigned tv_sec,
> > 				      unsigned tv_usec,
> > 				      unsigned crtc_id, void *data)
> > 	{
> > 		/* Compare params with the other page flip */
> > 	}
> > 
> > 	/* When we get POLLIN in the DRM FD */
> > 	drmEventContext event = {
> > 		.version = 3,
> > 		.page_flip_handler2 = page_flip_handler,
> > 	};
> > 	drmHandleEvent(fd, &event);
> > 
> > > Manasi
> > > 
> > > > If so, maybe we can check the page-flip timings and make sure
> > > > they are
> > > > equal?
> > > > 
> > > > A CRC check might be a good idea too, to make sure bandwidth
> > > > isn't an
> > > > issue.
> > > > 
> > > > CC'ing Martin in case he has better ideas.
> > > > 
> > > > > Manasi
> > > > > 
> > > > > > > +    }
> > > > > > > +
> > > > > > > +    igt_fixture {
> > > > > > > +        if(data.num_h_tiles > 0)
> > > > > > > +            free(conn_data);
> > > > > > 
> > > > > > If conn_data was initialized to NULL, no need for the
> > > > > > check, because
> > > > > > free(NULL) is a no-op.
> > > > > > 
> > > > > > > +        kmstest_restore_vt_mode();
> > > > > > > +        igt_display_fini(data.display);
> > > > > > > +    }
> > > > > > > +}
> > > > > > > diff --git a/tests/meson.build b/tests/meson.build
> > > > > > > index 34a74025..6a6e9ce9 100644
> > > > > > > --- a/tests/meson.build
> > > > > > > +++ b/tests/meson.build
> > > > > > > @@ -25,6 +25,7 @@ test_progs = [
> > > > > > >  	'kms_cursor_edge_walk',
> > > > > > >  	'kms_cursor_legacy',
> > > > > > >  	'kms_dp_dsc',
> > > > > > > +	'kms_dp_tiled_display',
> > > > > > >  	'kms_draw_crc',
> > > > > > >  	'kms_fbcon_fbt',
> > > > > > >  	'kms_fence_pin_leak',
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [igt-dev] [PATCH i-g-t] igt/tests/kms_dp_tiled_display.c : kms test file for display port tiled displays
  2019-08-01 17:38           ` Manasi Navare
  2019-08-02  1:09             ` Tolakanahalli Pradeep, Madhumitha
@ 2019-08-08  1:10             ` Tolakanahalli Pradeep, Madhumitha
  2019-08-14 13:43               ` Ser, Simon
  1 sibling, 1 reply; 18+ messages in thread
From: Tolakanahalli Pradeep, Madhumitha @ 2019-08-08  1:10 UTC (permalink / raw)
  To: Navare, Manasi D, Ser, Simon; +Cc: igt-dev, Latvala, Petri

On Thu, 2019-08-01 at 10:38 -0700, Manasi Navare wrote:
> Thank Simon for all your inputs. Please find some of my questions
> below:
> 
> On Thu, Aug 01, 2019 at 12:41:37AM -0700, Ser, Simon wrote:
> > On Wed, 2019-07-31 at 10:13 -0700, Manasi Navare wrote:
> > > On Wed, Jul 31, 2019 at 12:25:09AM -0700, Ser, Simon wrote:
> > > > On Tue, 2019-07-30 at 12:21 -0700, Manasi Navare wrote:
> > > > > On Wed, Jul 17, 2019 at 11:43:48PM -0700, Ser, Simon wrote:
> > > > > > Thanks for your patch! Here are some comments.
> > > > > > 
> > > > > > Style: we use tabs for indentation, not spaces.
> > > > > > 
> > > > > > On Wed, 2019-07-17 at 11:02 -0700, Madhumitha Tolakanahalli
> > > > > > Pradeep wrote:
> > > > > > > This test validates the tiled DP displays to display a
> > > > > > > test pattern seamlessly
> > > > > > > across the two tiles. It validates the transcoder port
> > > > > > > sync feature on i915 to
> > > > > > > get a tearfree tiled display output.
> > > > > > > 
> > > > > > > Related kernel work patches -> 
> > > > > > > https://patchwork.freedesktop.org/series/59837/#rev4.
> > > > > > > This test can eventually be extended to cover tiled
> > > > > > > display support on other connector
> > > > > > > types.
> > > > > > > 
> > > > > > > Cc: Manasi Navare <manasi.d.navare@intel.com>
> > > > > > > Cc: Petri Latvala <petri.latvala@intel.com>
> > > > > > > Signed-off-by: Madhumitha Tolakanahalli Pradeep <
> > > > > > > madhumitha.tolakanahalli.pradeep@intel.com>
> > > > > > 
> > > > > > Next time, can you send both patches in one go? It's not
> > > > > > possible to
> > > > > > check whether this test actually passes CI, since build
> > > > > > fails (see the
> > > > > > two automated failure replies).
> > > > > 
> > > > > Yes please send this as a series with 1st patch that defines
> > > > > the tile parser
> > > > > and second with the actual test that uses it
> > > > > 
> > > > > > To learn how to use git-send-email, you can read:
> > > > > > https://git-send-email.io/
> > > > > > 
> > > > > > > ---
> > > > > > >  tests/Makefile.sources       |   1 +
> > > > > > >  tests/kms_dp_tiled_display.c | 239
> > > > > > > +++++++++++++++++++++++++++++++++++
> > > > > > >  tests/meson.build            |   1 +
> > > > > > >  3 files changed, 241 insertions(+)
> > > > > > >  create mode 100644 tests/kms_dp_tiled_display.c
> > > > > > > 
> > > > > > > diff --git a/tests/Makefile.sources
> > > > > > > b/tests/Makefile.sources
> > > > > > > index 250dbd33..e9373941 100644
> > > > > > > --- a/tests/Makefile.sources
> > > > > > > +++ b/tests/Makefile.sources
> > > > > > > @@ -40,6 +40,7 @@ TESTS_progs = \
> > > > > > >  	kms_cursor_edge_walk \
> > > > > > >  	kms_cursor_legacy \
> > > > > > >  	kms_dp_dsc \
> > > > > > > +	kms_dp_tiled_display \
> > > > > > >  	kms_draw_crc \
> > > > > > >  	kms_fbcon_fbt \
> > > > > > >  	kms_fence_pin_leak \
> > > > > > > diff --git a/tests/kms_dp_tiled_display.c
> > > > > > > b/tests/kms_dp_tiled_display.c
> > > > > > > new file mode 100644
> > > > > > > index 00000000..af644573
> > > > > > > --- /dev/null
> > > > > > > +++ b/tests/kms_dp_tiled_display.c
> > > > > > > @@ -0,0 +1,239 @@
> > > > > > > +/*
> > > > > > > + * Copyright © 2018 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.
> > > > > > > + *
> > > > > > > + * Authors:
> > > > > > > + *  Madhumitha Tolakanahalli Pradeep
> > > > > > > + *      <madhumitha.tolakanahalli.pradeep@intel.com>
> > > > > > > + *
> > > > > > > + * Display Port Tiled Display Test
> > > > > > > + * This test parses the tile information of the
> > > > > > > connectors that have TILE
> > > > > > > + * property set, sets up the framebuffer with correct
> > > > > > > offsets corresponding to
> > > > > > > + * the tile offsets and does an atomic modeset with two
> > > > > > > CRTCs for two
> > > > > > > + * connectors.
> > > > > > > + *
> > > > > > > + * This test currently supports only horizontally tiled
> > > > > > > displays, in line with
> > > > > > > + * the displays supported by the kernel at the moment.
> > > > > > > + */
> > > > > > > +
> > > > > > > +#include "drm_mode.h"
> > > > > > > +#include "drm_fourcc.h"
> > > > > > > +#include "igt.h"
> > > > > > > +
> > > > > > > +typedef struct {
> > > > > > > +    int drm_fd;
> > > > > > > +    int num_h_tiles;
> > > > > > > +    igt_display_t *display;
> > > > > > > +    enum igt_commit_style commit;
> > > > > > > +} data_t;
> > > > > > > +
> > > > > > > +typedef struct {
> > > > > > > +    igt_output_t *output;
> > > > > > > +    igt_tile_info_t *tile;
> > > > > > > +    igt_fb_t fb_test_pattern;
> > > > > > > +    drmModeConnectorPtr connector;
> > > > > > > +    enum pipe pipe;
> > > > > > > +    enum igt_commit_style commit;
> > > > > > > +} data_connector_t;
> > > > > > > +
> > > > > > > +static inline int
> > > > > > > drm_property_is_tile(drmModePropertyPtr prop)
> > > > > > 
> > > > > > I wouldn't personally use `inline`. The compiler is smarter
> > > > > > than humans
> > > > > > to decide whether or not a function should be inlined.
> > > > > > 
> > > > > > > +{
> > > > > > > +	return(strcmp(prop->name ? prop->name : "", "TILE")? 0
> > > > > > > : 1);
> > > > > > 
> > > > > > Style: unnecessary parentheses, missing space before `?`.
> > > > > > 
> > > > > > > +}
> > > > > > > +
> > > > > > > +static void get_number_of_h_tiles(data_t *data)
> > > > > > 
> > > > > > What if multiple tiles are connected? Shouldn't we use
> > > > > > tile_group_id?
> > > > > 
> > > > > Yes there could be multiple monitors with tiles so use
> > > > > tile_group_id to check
> > > > > that the tile belongs to the same group and then use
> > > > > num_h_tiles
> > > 
> > > But actually the current hardware like Madhumitha mentioned only
> > > supports one tile group,
> > > if we have to support multiple tile groups then we would need to
> > > malloc the array of structures
> > > for the connectors associated with separate tile groups and then
> > > have a separate subtest for
> > > tile group 1 tile group 2 etc. This logic will not get tested
> > > right now due to HW constraint.
> > > 
> > > So the idea is for the IGT to check the tile group id but only
> > > support 1 tile group so far
> > > and leave the room for further extending it to multiple tiles
> > > instead of over complicating
> > > the logic now.
> > > 
> > > Does that make sense or do you think we should already add the
> > > subtests for multiple tile groups?
> > 
> > That makes perfect sense to me, support for multiple tile groups
> > can be
> > left as a TODO for later.
> > 
> > Incremental patches are way easier to review than one-patch-that-
> > implements-all-features-at-once. :)
> 
> Great so we will keep the implemnetation to 1 tile group id for now
> 
> > 
> > > > > > > +{
> > > > > > > +    int i;
> > > > > > > +    drmModeRes *res;
> > > > > > > +    drmModeConnector *connector;
> > > > > > > +    drmModePropertyPtr prop;
> > > > > > > +    drmModePropertyBlobPtr blob;
> > > > > > > +    igt_tile_info_t tile;
> > > > > > > +
> > > > > > > +    igt_require(res = drmModeGetResources(data-
> > > > > > > >drm_fd));
> > > > > > 
> > > > > > This should probably be igt_assert.
> > > > > > 
> > > > > > > +    for(i = 0; i < res->count_connectors; i++)
> > > > > > > +    {
> > > > > > 
> > > > > > Style: no newline before `{` (only for functions, applies
> > > > > > to the whole
> > > > > > patch).
> > > > > > 
> > > > > > > +        connector = drmModeGetConnectorCurrent(data-
> > > > > > > >drm_fd, \
> > > > > > 
> > > > > > Style: unnecessary `\`.
> > > > > > 
> > > > > > We could igt_assert(connector).
> > > > > > 
> > > > > > > +                                               res-
> > > > > > > >connectors[i]);
> > > > > > > +
> > > > > > > +        if(!((connector->connection ==
> > > > > > > DRM_MODE_CONNECTED) &&
> > > > > > > +            (connector->connector_type ==
> > > > > > > DRM_MODE_CONNECTOR_DisplayPort)))
> > > > > > > +                continue;
> > > > > > 
> > > > > > Style: we can invert this condition to make clearer.
> > > > > 
> > > > > But wouldnt that add additional nesting?
> > > > 
> > > > I mean, this could be re-written as:
> > > > 
> > > >     if (connector->connection != DRM_MODE_CONNECTED ||
> > > >         connector->connector_type !=
> > > > DRM_MODE_CONNECTOR_DisplayPort)
> > > 
> > > Oh yes that makes perfect sense!
> > > 
> > > > > > > +
> > > > > > > +        for(i = 0; i < connector->count_props; i++)
> > > > > > > +        {
> > > > > > > +            prop = drmModeGetProperty(data->drm_fd,
> > > > > > > connector->props[i]);
> > > > > > 
> > > > > > We could igt_assert(prop)
> > > > > > 
> > > > > > We need to free it at some point.
> > > > > > 
> > > > > > > +            if(!(drm_property_is_tile(prop) &&
> > > > > > 
> > > > > > Style: missing space after if keyword (applies to the whole
> > > > > > patch).
> > > > > > 
> > > > > > > +                drm_property_type_is(prop,
> > > > > > > DRM_MODE_PROP_BLOB)))
> > > > > > 
> > > > > > I'd move this check into drm_property_is_tile.
> > > > > > 
> > > > > > > +                continue;
> > > > > > > +
> > > > > > > +            blob = drmModeGetPropertyBlob(data->drm_fd,
> > > > > > > \
> > > > > > > +                                          connector-
> > > > > > > >prop_values[i]);
> > > > > > > +
> > > > > > > +            if(!blob)
> > > > > > > +                break;
> > > > > > > +            igt_parse_connector_tile_blob(blob, &tile);
> > > > > > > +            data->num_h_tiles = tile.num_h_tile;
> > > > > > > +            break;
> > > > > > > +        }
> > > > > > > +    }
> > > > > > > +}
> > > > > > > +
> > > > > > > +static int set_test_pattern_fb(data_t *data,
> > > > > > > data_connector_t *conn_data)
> > > > > > > +{
> > > > > > > +    int i;
> > > > > > > +    int count = 0;
> > > > > > > +    bool is_tile = false;
> > > > > > > +    enum pipe pipe;
> > > > > > > +    igt_tile_info_t tile;
> > > > > > > +    igt_output_t *output;
> > > > > > > +    igt_plane_t *primary;
> > > > > > > +    drmModePropertyPtr prop;
> > > > > > > +    drmModePropertyBlobPtr blob;
> > > > > > > +
> > > > > > > +    for_each_connected_output(data->display, output)
> > > > > > > +    {
> > > > > > > +        is_tile = false;
> > > > > > > +
> > > > > > > +        conn_data[count].connector =
> > > > > > > drmModeGetConnector(data->display->drm_fd, \
> > > > > > > +                                                        
> > > > > > >  output->id);
> > > > > > > +
> > > > > > > +        if(!(conn_data[count].connector->connector_type
> > > > > > > ==
> > > > > > > +                        DRM_MODE_CONNECTOR_DisplayPort))
> > > > > > > +            continue;
> > > > > > > +
> > > > > > > +        /* Parse through each connector property */
> > > > > > > +        for(i = 0; i < conn_data[count].connector-
> > > > > > > >count_props; i++)
> > > > > > > +        {
> > > > > > > +            prop = drmModeGetProperty(data->display-
> > > > > > > >drm_fd, \
> > > > > > > +                                      conn_data[count].c
> > > > > > > onnector->props[i]);
> > > > > > > +
> > > > > > > +            if(!((drm_property_is_tile(prop) &&
> > > > > > > +                drm_property_type_is(prop,
> > > > > > > DRM_MODE_PROP_BLOB))))
> > > > > > > +                continue;
> > > > > > > +
> > > > > > > +            blob = drmModeGetPropertyBlob(data->display-
> > > > > > > >drm_fd, \
> > > > > > > +                            conn_data[count].connector-
> > > > > > > >prop_values[i]);
> > > > > > > +
> > > > > > > +            if(!blob)
> > > > > > > +                break;
> > > > > > > +
> > > > > > > +            igt_parse_connector_tile_blob(blob, &tile);
> > > > > > > +            conn_data[count].tile = &tile;
> > > > > > > +            is_tile = true;
> > > > > > > +            break;
> > > > > > > +        }
> > > > > > 
> > > > > > I feel like this whole block above is duplicated. Could be
> > > > > > extracted
> > > > > > into a function, e.g.
> > > > > > 
> > > > > >     bool connector_get_tile(drmModeConnectorRes *conn,
> > > > > > igt_tile_info_t *tile_info)
> > > > > > 
> > > > > > > +        if(!is_tile)
> > > > > > > +            continue;
> > > > > > > +
> > > > > > > +        output = igt_output_from_connector(data-
> > > > > > > >display, \
> > > > > > > +                                           conn_data[cou
> > > > > > > nt].connector);
> > > > > > 
> > > > > > Style: unnecessary `\`. Applies to the whole patch.
> > > > > > 
> > > > > > > +
> > > > > > > +        for_each_pipe(data->display, pipe)
> > > > > > > +        {
> > > > > > > +            igt_debug("Current PIPE is %d\n", pipe);
> > > > > > > +
> > > > > > > +            if((count > 0) && (pipe == conn_data[count-
> > > > > > > 1].pipe))
> > > > > > > +                continue;
> > > > > > 
> > > > > > Style: unnecessary parentheses.
> > > > > > 
> > > > > > > +            if(igt_pipe_connector_valid(pipe, output)) {
> > > > > > > +                conn_data[count].pipe = pipe;
> > > > > > > +                conn_data[count].output = output;
> > > > > > > +
> > > > > > > +                igt_output_set_pipe(conn_data[count].out
> > > > > > > put, \
> > > > > > > +                                    conn_data[count].pip
> > > > > > > e);
> > > > > > > +
> > > > > > > +                igt_create_pattern_fb(data->drm_fd,\
> > > > > > > +                                    (conn_data[count].ti
> > > > > > > le->tile_h_size *\
> > > > > > > +                                     data-
> > > > > > > >num_h_tiles),\
> > > > > > > +                                     conn_data[count].ti
> > > > > > > le->tile_v_size,\
> > > > > > > +                                     DRM_FORMAT_XBGR8888
> > > > > > > ,\
> > > > > > > +                                     LOCAL_DRM_FORMAT_MO
> > > > > > > D_NONE,\
> > > > > > > +                                     &conn_data[count].f
> > > > > > > b_test_pattern);
> > > > > > > +
> > > > > > > +                primary =
> > > > > > > igt_output_get_plane_type(conn_data[count].output,\
> > > > > > > +                                                    DRM_
> > > > > > > PLANE_TYPE_PRIMARY);
> > > > > > > +
> > > > > > > +                igt_plane_set_fb(primary,
> > > > > > > &conn_data[count].fb_test_pattern);
> > > > > > > +
> > > > > > > +                igt_fb_set_size(&conn_data[count].fb_tes
> > > > > > > t_pattern, primary,\
> > > > > > > +                                conn_data[count].tile-
> > > > > > > >tile_h_size,\
> > > > > > > +                                conn_data[count].tile-
> > > > > > > >tile_v_size);
> > > > > > > +
> > > > > > > +                igt_fb_set_position(&conn_data[count].fb
> > > > > > > _test_pattern, \
> > > > > > > +                                    primary,\
> > > > > > > +                                    (conn_data[count].ti
> > > > > > > le->tile_h_size *\
> > > > > > > +                                    conn_data[count].til
> > > > > > > e->tile_h_loc),
> > > > > > > +                                    (conn_data[count].ti
> > > > > > > le->tile_v_size *\
> > > > > > > +                                    conn_data[count].til
> > > > > > > e->tile_v_loc));
> > > > > > > +
> > > > > > > +                igt_plane_set_size(primary,\
> > > > > > > +                                   conn_data[count].tile
> > > > > > > ->tile_h_size,\
> > > > > > > +                                   conn_data[count].tile
> > > > > > > ->tile_v_size);
> > > > > > > +
> > > > > > > +                break;
> > > > > > > +            }
> > > > > > > +        }
> > > > > > > +        count++;
> > > > > > > +    }
> > > > > > > +
> > > > > > > +    return count;
> > > > > > > +}
> > > > > > > +
> > > > > > > +igt_main
> > > > > > > +{
> > > > > > > +    igt_display_t display;
> > > > > > > +    data_t data = {};
> > > > > > > +    data_connector_t *conn_data;
> > > > > > > +
> > > > > > > +    igt_fixture {
> > > > > > > +        data.drm_fd =
> > > > > > > drm_open_driver_master(DRIVER_ANY);
> > > > > > > +        kmstest_set_vt_graphics_mode();
> > > > > > > +        igt_display_require(&display, data.drm_fd);
> > > > > > > +        data.display = &display;
> > > > > > > +
> > > > > > > +        get_number_of_h_tiles(&data);
> > > > > > > +        igt_debug("Number of Horizontal Tiles: %d\n",
> > > > > > > data.num_h_tiles);
> > > > > > > +        data.commit = data.display->is_atomic ?
> > > > > > > COMMIT_ATOMIC : COMMIT_LEGACY;
> > > > > > > +    }
> > > > > > > +
> > > > > > > +    if(data.num_h_tiles > 0)
> > > > > > > +        conn_data = (data_connector_t
> > > > > > > *)malloc(data.num_h_tiles * \
> > > > > > > +                                                sizeof(d
> > > > > > > ata_connector_t));
> > > > > > 
> > > > > > No need for this cast, unnecessary `\`.
> > > > > > 
> > > > > > > +    igt_assert(conn_data);
> > > > > > 
> > > > > > This check reads garbage from the stack if data.num_h_tiles
> > > > > > == 0.
> > > > > 
> > > > > This check should possibly be inside the same if
> > > > > 
> > > > > > > +    igt_subtest_f("basic-test-pattern") {
> > > > > > 
> > > > > > No need for the _f suffix.
> > > > > > 
> > > > > > This subtest is missing a description. Could you add one?
> > > > > > For more
> > > > > > information, see:
> > > > > > 
https://drm.pages.freedesktop.org/igt-gpu-tools/igt-gpu-tools-Core.html#igt-describe
> > > > > > 
> > > > > > > +        igt_skip_on(!data.num_h_tiles);
> > > > > > > +        set_test_pattern_fb(&data, conn_data);
> > > > > > > +        igt_display_commit2(data.display, data.commit);
> > > > > > 
> > > > > > I'm not sure I understand what this test checks. It does a
> > > > > > commit on
> > > > > > all tiled connectors, but doesn't check anything
> > > > > > afterwards. Maybe it
> > > > > > should check the pageflip serial and timings?
> > > > > 
> > > > > This is so far a manual test where we just look at the
> > > > > pattern and make sure no artifacts
> > > > > and auto testing just make sure the commit did not fail, any
> > > > > better idea to check if the
> > > > > page_flip timeouts didnt occur or not sure if we can do crc
> > > > > checks to ensure no artifacts?
> > > > > Any ideas/suggestions?
> > > > 
> > > > To be honest I'm not a fan of manual testing.
> > > > 
> > > > As I understand it, tiled displays must be updated in sync so
> > > > that you
> > > > don't get tearing. If one display is page-flipped before the
> > > > other,
> > > > there will be tearing in the middle of the tiled screen. Am I
> > > > reading
> > > > the commit message correctly?
> > > 
> > > Yes there would be tearing if one tile page flipped before the
> > > other
> > > and the HW prevents this from happening by synchronizing the two
> > > vblanks
> > > from the two ports.
> > > 
> > > If there an example of igt where we can check the vblank timing
> > > or page flip timings
> > > to add this check?
> > 
> > I believe tests in kms_flip do a similar check. The
> > page_flip_handler
> > function handles the page flip event (which is given the flip
> > timestamp
> > and sequence number). check_state verifies that the timestamp is
> > close
> > enough to what we expect (in our atomic check, maybe we can compare
> > with strict equality).
> > 
> > Since we're dealing with multiple CRTCs, it may be a good idea to
> > use
> > drmEventContext.version = 3 with page_flip_handler2 so that we also
> > get
> > the CRTC in the page flip handler. Version 3 is a core DRM feature,
> > all
> > drivers support it given a recent enough kernel.
> > 
> > Rough pseudo-code:
> > 
> > 	/* When committing buffer, request a page flip */
> > 	drmModeAtomicCommit(fd, req, DRM_MODE_ATOMIC_NONBLOCK |
> > 			    DRM_MODE_PAGE_FLIP_EVENT, data);
> 
> Here we do the modese with igt_display_commit2 call that then calls
> drmModeAtomicCommit but
> doesnt call it with Page flip, do we have another igt helper that
> does a atomic commit with
> page flip event?
> 
> Can we not just do atomic commit and get vblank events so for two
> crtcs we get two events and compare
> the timestamp and make sure they are close enough?
> 
> Manasi
> 
> > 
> > 	static void page_flip_handler(int fd, unsigned seq,
> > 				      unsigned tv_sec,
> > 				      unsigned tv_usec,
> > 				      unsigned crtc_id, void *data)
> > 	{
> > 		/* Compare params with the other page flip */
> > 	}
> > 
> > 	/* When we get POLLIN in the DRM FD */
> > 	drmEventContext event = {
> > 		.version = 3,
> > 		.page_flip_handler2 = page_flip_handler,
> > 	};
> > 	drmHandleEvent(fd, &event);
> > 

I was trying to implement the above code with igt_display_commit2.
Looks like I'm timing out while poll-ing for POLLIN.

Is there something I could be doing wrong? According to my
understanding, igt_display_commit2 should cause a page-flip event
right?


Madhumitha


> > > Manasi
> > > 
> > > > If so, maybe we can check the page-flip timings and make sure
> > > > they are
> > > > equal?
> > > > 
> > > > A CRC check might be a good idea too, to make sure bandwidth
> > > > isn't an
> > > > issue.
> > > > 
> > > > CC'ing Martin in case he has better ideas.
> > > > 
> > > > > Manasi
> > > > > 
> > > > > > > +    }
> > > > > > > +
> > > > > > > +    igt_fixture {
> > > > > > > +        if(data.num_h_tiles > 0)
> > > > > > > +            free(conn_data);
> > > > > > 
> > > > > > If conn_data was initialized to NULL, no need for the
> > > > > > check, because
> > > > > > free(NULL) is a no-op.
> > > > > > 
> > > > > > > +        kmstest_restore_vt_mode();
> > > > > > > +        igt_display_fini(data.display);
> > > > > > > +    }
> > > > > > > +}
> > > > > > > diff --git a/tests/meson.build b/tests/meson.build
> > > > > > > index 34a74025..6a6e9ce9 100644
> > > > > > > --- a/tests/meson.build
> > > > > > > +++ b/tests/meson.build
> > > > > > > @@ -25,6 +25,7 @@ test_progs = [
> > > > > > >  	'kms_cursor_edge_walk',
> > > > > > >  	'kms_cursor_legacy',
> > > > > > >  	'kms_dp_dsc',
> > > > > > > +	'kms_dp_tiled_display',
> > > > > > >  	'kms_draw_crc',
> > > > > > >  	'kms_fbcon_fbt',
> > > > > > >  	'kms_fence_pin_leak',
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [igt-dev] [PATCH i-g-t] igt/tests/kms_dp_tiled_display.c : kms test file for display port tiled displays
  2019-08-08  1:10             ` Tolakanahalli Pradeep, Madhumitha
@ 2019-08-14 13:43               ` Ser, Simon
  2019-08-14 22:05                 ` Tolakanahalli Pradeep, Madhumitha
  0 siblings, 1 reply; 18+ messages in thread
From: Ser, Simon @ 2019-08-14 13:43 UTC (permalink / raw)
  To: Tolakanahalli Pradeep, Madhumitha, Navare, Manasi D
  Cc: igt-dev, Latvala, Petri

On Wed, 2019-08-07 at 18:10 -0700, Tolakanahalli Pradeep, Madhumitha wrote:
> > > I believe tests in kms_flip do a similar check. The
> > > page_flip_handler
> > > function handles the page flip event (which is given the flip
> > > timestamp
> > > and sequence number). check_state verifies that the timestamp is
> > > close
> > > enough to what we expect (in our atomic check, maybe we can compare
> > > with strict equality).
> > > 
> > > Since we're dealing with multiple CRTCs, it may be a good idea to
> > > use
> > > drmEventContext.version = 3 with page_flip_handler2 so that we also
> > > get
> > > the CRTC in the page flip handler. Version 3 is a core DRM feature,
> > > all
> > > drivers support it given a recent enough kernel.
> > > 
> > > Rough pseudo-code:
> > > 
> > > 	/* When committing buffer, request a page flip */
> > > 	drmModeAtomicCommit(fd, req, DRM_MODE_ATOMIC_NONBLOCK |
> > > 			    DRM_MODE_PAGE_FLIP_EVENT, data);
> > 
> > Here we do the modese with igt_display_commit2 call that then calls
> > drmModeAtomicCommit but
> > doesnt call it with Page flip, do we have another igt helper that
> > does a atomic commit with
> > page flip event?
> > 
> > Can we not just do atomic commit and get vblank events so for two
> > crtcs we get two events and compare
> > the timestamp and make sure they are close enough?

I believe doing an atomic commit with DRM_MODE_PAGE_FLIP_EVENT as
Madhumitha suggested should be enough.

> > Manasi
> > 
> > > 	static void page_flip_handler(int fd, unsigned seq,
> > > 				      unsigned tv_sec,
> > > 				      unsigned tv_usec,
> > > 				      unsigned crtc_id, void *data)
> > > 	{
> > > 		/* Compare params with the other page flip */
> > > 	}
> > > 
> > > 	/* When we get POLLIN in the DRM FD */
> > > 	drmEventContext event = {
> > > 		.version = 3,
> > > 		.page_flip_handler2 = page_flip_handler,
> > > 	};
> > > 	drmHandleEvent(fd, &event);
> > > 
> 
> I was trying to implement the above code with igt_display_commit2.
> Looks like I'm timing out while poll-ing for POLLIN.
> 
> Is there something I could be doing wrong? According to my
> understanding, igt_display_commit2 should cause a page-flip event
> right?

Hmm. Yeah, it should work, assuming you use DRM_MODE_PAGE_FLIP_EVENT
when doing the atomic commit. Can you push your code somewhere (e.g. on
a GitLab fork) so that I can have a look?
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [igt-dev] [PATCH i-g-t] igt/tests/kms_dp_tiled_display.c : kms test file for display port tiled displays
  2019-08-14 13:43               ` Ser, Simon
@ 2019-08-14 22:05                 ` Tolakanahalli Pradeep, Madhumitha
  2019-08-15 11:30                   ` Ser, Simon
  0 siblings, 1 reply; 18+ messages in thread
From: Tolakanahalli Pradeep, Madhumitha @ 2019-08-14 22:05 UTC (permalink / raw)
  To: Navare, Manasi D, Ser, Simon; +Cc: igt-dev, Latvala, Petri

On Wed, 2019-08-14 at 14:43 +0100, Ser, Simon wrote:
> On Wed, 2019-08-07 at 18:10 -0700, Tolakanahalli Pradeep, Madhumitha
> wrote:
> > > > I believe tests in kms_flip do a similar check. The
> > > > page_flip_handler
> > > > function handles the page flip event (which is given the flip
> > > > timestamp
> > > > and sequence number). check_state verifies that the timestamp
> > > > is
> > > > close
> > > > enough to what we expect (in our atomic check, maybe we can
> > > > compare
> > > > with strict equality).
> > > > 
> > > > Since we're dealing with multiple CRTCs, it may be a good idea
> > > > to
> > > > use
> > > > drmEventContext.version = 3 with page_flip_handler2 so that we
> > > > also
> > > > get
> > > > the CRTC in the page flip handler. Version 3 is a core DRM
> > > > feature,
> > > > all
> > > > drivers support it given a recent enough kernel.
> > > > 
> > > > Rough pseudo-code:
> > > > 
> > > > 	/* When committing buffer, request a page flip */
> > > > 	drmModeAtomicCommit(fd, req, DRM_MODE_ATOMIC_NONBLOCK |
> > > > 			    DRM_MODE_PAGE_FLIP_EVENT, data);
> > > 
> > > Here we do the modese with igt_display_commit2 call that then
> > > calls
> > > drmModeAtomicCommit but
> > > doesnt call it with Page flip, do we have another igt helper that
> > > does a atomic commit with
> > > page flip event?
> > > 
> > > Can we not just do atomic commit and get vblank events so for two
> > > crtcs we get two events and compare
> > > the timestamp and make sure they are close enough?
> 
> I believe doing an atomic commit with DRM_MODE_PAGE_FLIP_EVENT as
> Madhumitha suggested should be enough.

Looks like using DRM_MODE_PAGE_FLIP_EVENT is giving me a errno 22,
invalid argument.

> 
> > > Manasi
> > > 
> > > > 	static void page_flip_handler(int fd, unsigned seq,
> > > > 				      unsigned tv_sec,
> > > > 				      unsigned tv_usec,
> > > > 				      unsigned crtc_id, void
> > > > *data)
> > > > 	{
> > > > 		/* Compare params with the other page flip */
> > > > 	}
> > > > 
> > > > 	/* When we get POLLIN in the DRM FD */
> > > > 	drmEventContext event = {
> > > > 		.version = 3,
> > > > 		.page_flip_handler2 = page_flip_handler,
> > > > 	};
> > > > 	drmHandleEvent(fd, &event);
> > > > 
> > 
> > I was trying to implement the above code with igt_display_commit2.
> > Looks like I'm timing out while poll-ing for POLLIN.
> > 
> > Is there something I could be doing wrong? According to my
> > understanding, igt_display_commit2 should cause a page-flip event
> > right?
> 
> Hmm. Yeah, it should work, assuming you use DRM_MODE_PAGE_FLIP_EVENT
> when doing the atomic commit. Can you push your code somewhere (e.g.
> on
> a GitLab fork) so that I can have a look?


Sure!
Here is the link to my forked repository. The commit and polling is in
igt_main().
https://gitlab.freedesktop.org/mtolakan/igt-gpu-tools
My suspicion is the commit is not asynchronous, which is why I am unble
to capture the page flip event. Please do let me know what you think,
thanks!

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [igt-dev] [PATCH i-g-t] igt/tests/kms_dp_tiled_display.c : kms test file for display port tiled displays
  2019-08-14 22:05                 ` Tolakanahalli Pradeep, Madhumitha
@ 2019-08-15 11:30                   ` Ser, Simon
  2019-08-17  0:01                     ` Tolakanahalli Pradeep, Madhumitha
  0 siblings, 1 reply; 18+ messages in thread
From: Ser, Simon @ 2019-08-15 11:30 UTC (permalink / raw)
  To: Tolakanahalli Pradeep, Madhumitha, Navare, Manasi D
  Cc: igt-dev, Latvala, Petri

wOn Wed, 2019-08-14 at 15:05 -0700, Tolakanahalli Pradeep, Madhumitha wrote:
> On Wed, 2019-08-14 at 14:43 +0100, Ser, Simon wrote:
> > On Wed, 2019-08-07 at 18:10 -0700, Tolakanahalli Pradeep, Madhumitha
> > wrote:
> > > > > I believe tests in kms_flip do a similar check. The
> > > > > page_flip_handler
> > > > > function handles the page flip event (which is given the flip
> > > > > timestamp
> > > > > and sequence number). check_state verifies that the timestamp
> > > > > is
> > > > > close
> > > > > enough to what we expect (in our atomic check, maybe we can
> > > > > compare
> > > > > with strict equality).
> > > > > 
> > > > > Since we're dealing with multiple CRTCs, it may be a good idea
> > > > > to
> > > > > use
> > > > > drmEventContext.version = 3 with page_flip_handler2 so that we
> > > > > also
> > > > > get
> > > > > the CRTC in the page flip handler. Version 3 is a core DRM
> > > > > feature,
> > > > > all
> > > > > drivers support it given a recent enough kernel.
> > > > > 
> > > > > Rough pseudo-code:
> > > > > 
> > > > > 	/* When committing buffer, request a page flip */
> > > > > 	drmModeAtomicCommit(fd, req, DRM_MODE_ATOMIC_NONBLOCK |
> > > > > 			    DRM_MODE_PAGE_FLIP_EVENT, data);
> > > > 
> > > > Here we do the modese with igt_display_commit2 call that then
> > > > calls
> > > > drmModeAtomicCommit but
> > > > doesnt call it with Page flip, do we have another igt helper that
> > > > does a atomic commit with
> > > > page flip event?
> > > > 
> > > > Can we not just do atomic commit and get vblank events so for two
> > > > crtcs we get two events and compare
> > > > the timestamp and make sure they are close enough?
> > 
> > I believe doing an atomic commit with DRM_MODE_PAGE_FLIP_EVENT as
> > Madhumitha suggested should be enough.
> 
> Looks like using DRM_MODE_PAGE_FLIP_EVENT is giving me a errno 22,
> invalid argument.

Have you tried DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK?

Enabling verbose dmesg DRM logging can help figuring out why the kernel
sends "invalid ar"EINVAL:

    echo 0x00 | sudo tee /sys/module/drm/parameters/debug

> > > > Manasi
> > > > 
> > > > > 	static void page_flip_handler(int fd, unsigned seq,
> > > > > 				      unsigned tv_sec,
> > > > > 				      unsigned tv_usec,
> > > > > 				      unsigned crtc_id, void
> > > > > *data)
> > > > > 	{
> > > > > 		/* Compare params with the other page flip */
> > > > > 	}
> > > > > 
> > > > > 	/* When we get POLLIN in the DRM FD */
> > > > > 	drmEventContext event = {
> > > > > 		.version = 3,
> > > > > 		.page_flip_handler2 = page_flip_handler,
> > > > > 	};
> > > > > 	drmHandleEvent(fd, &event);
> > > > > 
> > > 
> > > I was trying to implement the above code with igt_display_commit2.
> > > Looks like I'm timing out while poll-ing for POLLIN.
> > > 
> > > Is there something I could be doing wrong? According to my
> > > understanding, igt_display_commit2 should cause a page-flip event
> > > right?
> > 
> > Hmm. Yeah, it should work, assuming you use DRM_MODE_PAGE_FLIP_EVENT
> > when doing the atomic commit. Can you push your code somewhere (e.g.
> > on
> > a GitLab fork) so that I can have a look?
> 
> Sure!
> Here is the link to my forked repository. The commit and polling is in
> igt_main().
> https://gitlab.freedesktop.org/mtolakan/igt-gpu-tools
> My suspicion is the commit is not asynchronous, which is why I am unble
> to capture the page flip event. Please do let me know what you think,
> thanks!
> 
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [igt-dev] [PATCH i-g-t] igt/tests/kms_dp_tiled_display.c : kms test file for display port tiled displays
  2019-08-15 11:30                   ` Ser, Simon
@ 2019-08-17  0:01                     ` Tolakanahalli Pradeep, Madhumitha
  2019-08-19 14:50                       ` Ser, Simon
  0 siblings, 1 reply; 18+ messages in thread
From: Tolakanahalli Pradeep, Madhumitha @ 2019-08-17  0:01 UTC (permalink / raw)
  To: Navare, Manasi D, Ser, Simon; +Cc: igt-dev, Latvala, Petri

On Thu, 2019-08-15 at 12:30 +0100, Ser, Simon wrote:
> wOn Wed, 2019-08-14 at 15:05 -0700, Tolakanahalli Pradeep, Madhumitha
> wrote:
> > On Wed, 2019-08-14 at 14:43 +0100, Ser, Simon wrote:
> > > On Wed, 2019-08-07 at 18:10 -0700, Tolakanahalli Pradeep,
> > > Madhumitha
> > > wrote:
> > > > > > I believe tests in kms_flip do a similar check. The
> > > > > > page_flip_handler
> > > > > > function handles the page flip event (which is given the
> > > > > > flip
> > > > > > timestamp
> > > > > > and sequence number). check_state verifies that the
> > > > > > timestamp
> > > > > > is
> > > > > > close
> > > > > > enough to what we expect (in our atomic check, maybe we can
> > > > > > compare
> > > > > > with strict equality).
> > > > > > 
> > > > > > Since we're dealing with multiple CRTCs, it may be a good
> > > > > > idea
> > > > > > to
> > > > > > use
> > > > > > drmEventContext.version = 3 with page_flip_handler2 so that
> > > > > > we
> > > > > > also
> > > > > > get
> > > > > > the CRTC in the page flip handler. Version 3 is a core DRM
> > > > > > feature,
> > > > > > all
> > > > > > drivers support it given a recent enough kernel.
> > > > > > 
> > > > > > Rough pseudo-code:
> > > > > > 
> > > > > > 	/* When committing buffer, request a page flip */
> > > > > > 	drmModeAtomicCommit(fd, req, DRM_MODE_ATOMIC_NONBLOCK |
> > > > > > 			    DRM_MODE_PAGE_FLIP_EVENT, data);
> > > > > 
> > > > > Here we do the modese with igt_display_commit2 call that then
> > > > > calls
> > > > > drmModeAtomicCommit but
> > > > > doesnt call it with Page flip, do we have another igt helper
> > > > > that
> > > > > does a atomic commit with
> > > > > page flip event?
> > > > > 
> > > > > Can we not just do atomic commit and get vblank events so for
> > > > > two
> > > > > crtcs we get two events and compare
> > > > > the timestamp and make sure they are close enough?
> > > 
> > > I believe doing an atomic commit with DRM_MODE_PAGE_FLIP_EVENT as
> > > Madhumitha suggested should be enough.
> > 
> > Looks like using DRM_MODE_PAGE_FLIP_EVENT is giving me a errno 22,
> > invalid argument.
> 
> Have you tried DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK?
> 
> Enabling verbose dmesg DRM logging can help figuring out why the
> kernel
> sends "invalid ar"EINVAL:
> 
>     echo 0x00 | sudo tee /sys/module/drm/parameters/debug


Yes, I did try a commit with DRM_MODE_PAGE_FLIP_EVENT |
DRM_MODE_ATOMIC_NONBLOCK but IGT would not let me use them in
combination and the test failed with errno 22.
The cause of ret = -22 was the commit was failing in
drm_atomic_check_only(). Corresponding dmesg logs -
[drm:drm_atomic_check_only] [CRTC:189:pipe C] requesting event but off
[drm:drm_atomic_check_only] [CRTC:189:pipe C] atomic core check failed

I was able to get igt_display_commit2 to work with
DRM_MODE_ATOMIC_NONBLOCK and DRM_MODE_ATOMIC_ALLOW_MODESET (more like a
hacky way where I modified igt_kms.c and passed these flags). I was
able to get a successful non-atomic commit (dmesg mentioned "non-atomic 
commit" too). However, poll() always timed out. Here's 
my implementation for poll().

https://gitlab.freedesktop.org/mtolakan/igt-gpu-tools

Am I missing something trivial? Would really appreciate any
suggestions.

> 
> > > > > Manasi
> > > > > 
> > > > > > 	static void page_flip_handler(int fd, unsigned seq,
> > > > > > 				      unsigned tv_sec,
> > > > > > 				      unsigned tv_usec,
> > > > > > 				      unsigned crtc_id, void
> > > > > > *data)
> > > > > > 	{
> > > > > > 		/* Compare params with the other page flip */
> > > > > > 	}
> > > > > > 
> > > > > > 	/* When we get POLLIN in the DRM FD */
> > > > > > 	drmEventContext event = {
> > > > > > 		.version = 3,
> > > > > > 		.page_flip_handler2 = page_flip_handler,
> > > > > > 	};
> > > > > > 	drmHandleEvent(fd, &event);
> > > > > > 
> > > > 
> > > > I was trying to implement the above code with
> > > > igt_display_commit2.
> > > > Looks like I'm timing out while poll-ing for POLLIN.
> > > > 
> > > > Is there something I could be doing wrong? According to my
> > > > understanding, igt_display_commit2 should cause a page-flip
> > > > event
> > > > right?
> > > 
> > > Hmm. Yeah, it should work, assuming you use
> > > DRM_MODE_PAGE_FLIP_EVENT
> > > when doing the atomic commit. Can you push your code somewhere
> > > (e.g.
> > > on
> > > a GitLab fork) so that I can have a look?
> > 
> > Sure!
> > Here is the link to my forked repository. The commit and polling is
> > in
> > igt_main().
> > https://gitlab.freedesktop.org/mtolakan/igt-gpu-tools
> > My suspicion is the commit is not asynchronous, which is why I am
> > unble
> > to capture the page flip event. Please do let me know what you
> > think,
> > thanks!
> > 
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [igt-dev] [PATCH i-g-t] igt/tests/kms_dp_tiled_display.c : kms test file for display port tiled displays
  2019-08-17  0:01                     ` Tolakanahalli Pradeep, Madhumitha
@ 2019-08-19 14:50                       ` Ser, Simon
  0 siblings, 0 replies; 18+ messages in thread
From: Ser, Simon @ 2019-08-19 14:50 UTC (permalink / raw)
  To: Tolakanahalli Pradeep, Madhumitha, Navare, Manasi D
  Cc: igt-dev, Latvala, Petri

On Fri, 2019-08-16 at 17:01 -0700, Tolakanahalli Pradeep, Madhumitha wrote:
> On Thu, 2019-08-15 at 12:30 +0100, Ser, Simon wrote:
> > wOn Wed, 2019-08-14 at 15:05 -0700, Tolakanahalli Pradeep, Madhumitha
> > wrote:
> > > On Wed, 2019-08-14 at 14:43 +0100, Ser, Simon wrote:
> > > > On Wed, 2019-08-07 at 18:10 -0700, Tolakanahalli Pradeep,
> > > > Madhumitha
> > > > wrote:
> > > > > > > I believe tests in kms_flip do a similar check. The
> > > > > > > page_flip_handler
> > > > > > > function handles the page flip event (which is given the
> > > > > > > flip
> > > > > > > timestamp
> > > > > > > and sequence number). check_state verifies that the
> > > > > > > timestamp
> > > > > > > is
> > > > > > > close
> > > > > > > enough to what we expect (in our atomic check, maybe we can
> > > > > > > compare
> > > > > > > with strict equality).
> > > > > > > 
> > > > > > > Since we're dealing with multiple CRTCs, it may be a good
> > > > > > > idea
> > > > > > > to
> > > > > > > use
> > > > > > > drmEventContext.version = 3 with page_flip_handler2 so that
> > > > > > > we
> > > > > > > also
> > > > > > > get
> > > > > > > the CRTC in the page flip handler. Version 3 is a core DRM
> > > > > > > feature,
> > > > > > > all
> > > > > > > drivers support it given a recent enough kernel.
> > > > > > > 
> > > > > > > Rough pseudo-code:
> > > > > > > 
> > > > > > > 	/* When committing buffer, request a page flip */
> > > > > > > 	drmModeAtomicCommit(fd, req, DRM_MODE_ATOMIC_NONBLOCK |
> > > > > > > 			    DRM_MODE_PAGE_FLIP_EVENT, data);
> > > > > > 
> > > > > > Here we do the modese with igt_display_commit2 call that then
> > > > > > calls
> > > > > > drmModeAtomicCommit but
> > > > > > doesnt call it with Page flip, do we have another igt helper
> > > > > > that
> > > > > > does a atomic commit with
> > > > > > page flip event?
> > > > > > 
> > > > > > Can we not just do atomic commit and get vblank events so for
> > > > > > two
> > > > > > crtcs we get two events and compare
> > > > > > the timestamp and make sure they are close enough?
> > > > 
> > > > I believe doing an atomic commit with DRM_MODE_PAGE_FLIP_EVENT as
> > > > Madhumitha suggested should be enough.
> > > 
> > > Looks like using DRM_MODE_PAGE_FLIP_EVENT is giving me a errno 22,
> > > invalid argument.
> > 
> > Have you tried DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK?
> > 
> > Enabling verbose dmesg DRM logging can help figuring out why the
> > kernel
> > sends "invalid ar"EINVAL:
> > 
> >     echo 0x00 | sudo tee /sys/module/drm/parameters/debug
> 
> Yes, I did try a commit with DRM_MODE_PAGE_FLIP_EVENT |
> DRM_MODE_ATOMIC_NONBLOCK but IGT would not let me use them in
> combination and the test failed with errno 22.
> The cause of ret = -22 was the commit was failing in
> drm_atomic_check_only(). Corresponding dmesg logs -
> [drm:drm_atomic_check_only] [CRTC:189:pipe C] requesting event but off
> [drm:drm_atomic_check_only] [CRTC:189:pipe C] atomic core check failed
> 
> I was able to get igt_display_commit2 to work with
> DRM_MODE_ATOMIC_NONBLOCK and DRM_MODE_ATOMIC_ALLOW_MODESET (more like a
> hacky way where I modified igt_kms.c and passed these flags). I was
> able to get a successful non-atomic commit (dmesg mentioned "non-atomic 
> commit" too). However, poll() always timed out. Here's 
> my implementation for poll().
> 
> https://gitlab.freedesktop.org/mtolakan/igt-gpu-tools
> 
> Am I missing something trivial? Would really appreciate any
> suggestions.

Hi,

Your test is hard to run for me, because I don't have a tiled display.
It would be nice to generate a tiled display setup with Chamelium, by
generating an EDID with the appropriate DisplayID. Maybe I'll have a
stab at adding basic property tests with Chamelium.

To make sure page-flips on multiple outputs in a single atomic commit
works, I implemented a very basic IGT test:
https://sr.ht/5OqA.c

It works properly on my machine. Maybe it can help you figure out
what's wrong.

Maybe this test could be added to kms_flip. I don't think we have it
already (we only test cloned connectors from what I understand).

Simon

> > > > > > Manasi
> > > > > > 
> > > > > > > 	static void page_flip_handler(int fd, unsigned seq,
> > > > > > > 				      unsigned tv_sec,
> > > > > > > 				      unsigned tv_usec,
> > > > > > > 				      unsigned crtc_id, void
> > > > > > > *data)
> > > > > > > 	{
> > > > > > > 		/* Compare params with the other page flip */
> > > > > > > 	}
> > > > > > > 
> > > > > > > 	/* When we get POLLIN in the DRM FD */
> > > > > > > 	drmEventContext event = {
> > > > > > > 		.version = 3,
> > > > > > > 		.page_flip_handler2 = page_flip_handler,
> > > > > > > 	};
> > > > > > > 	drmHandleEvent(fd, &event);
> > > > > > > 
> > > > > 
> > > > > I was trying to implement the above code with
> > > > > igt_display_commit2.
> > > > > Looks like I'm timing out while poll-ing for POLLIN.
> > > > > 
> > > > > Is there something I could be doing wrong? According to my
> > > > > understanding, igt_display_commit2 should cause a page-flip
> > > > > event
> > > > > right?
> > > > 
> > > > Hmm. Yeah, it should work, assuming you use
> > > > DRM_MODE_PAGE_FLIP_EVENT
> > > > when doing the atomic commit. Can you push your code somewhere
> > > > (e.g.
> > > > on
> > > > a GitLab fork) so that I can have a look?
> > > 
> > > Sure!
> > > Here is the link to my forked repository. The commit and polling is
> > > in
> > > igt_main().
> > > https://gitlab.freedesktop.org/mtolakan/igt-gpu-tools
> > > My suspicion is the commit is not asynchronous, which is why I am
> > > unble
> > > to capture the page flip event. Please do let me know what you
> > > think,
> > > thanks!
> > > 
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2019-08-19 14:50 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-17 18:02 [igt-dev] [PATCH i-g-t] igt/tests/kms_dp_tiled_display.c : kms test file for display port tiled displays Madhumitha Tolakanahalli Pradeep
2019-07-17 18:35 ` [igt-dev] ✗ Fi.CI.BAT: failure for " Patchwork
2019-07-17 18:56 ` [igt-dev] ✗ GitLab.Pipeline: warning " Patchwork
2019-07-18  6:43 ` [igt-dev] [PATCH i-g-t] " Ser, Simon
2019-07-30 19:21   ` Manasi Navare
2019-07-31  7:25     ` Ser, Simon
2019-07-31 17:13       ` Manasi Navare
2019-08-01  7:41         ` Ser, Simon
2019-08-01 17:38           ` Manasi Navare
2019-08-02  1:09             ` Tolakanahalli Pradeep, Madhumitha
2019-08-08  1:10             ` Tolakanahalli Pradeep, Madhumitha
2019-08-14 13:43               ` Ser, Simon
2019-08-14 22:05                 ` Tolakanahalli Pradeep, Madhumitha
2019-08-15 11:30                   ` Ser, Simon
2019-08-17  0:01                     ` Tolakanahalli Pradeep, Madhumitha
2019-08-19 14:50                       ` Ser, Simon
2019-07-31  0:42   ` Tolakanahalli Pradeep, Madhumitha
2019-07-31  8:15     ` Ser, Simon

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.