From: "José Expósito" <jose.exposito89@gmail.com>
To: Louis Chauvet <louis.chauvet@bootlin.com>
Cc: hamohammed.sa@gmail.com, simona@ffwll.ch, melissa.srw@gmail.com,
maarten.lankhorst@linux.intel.com, mripard@kernel.org,
tzimmermann@suse.de, airlied@gmail.com,
dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 07/13] drm/vkms: Allow to configure multiple planes
Date: Tue, 11 Feb 2025 11:43:23 +0100 [thread overview]
Message-ID: <Z6spy81Xa-Aoz-HZ@fedora> (raw)
In-Reply-To: <Z5uDI0QiP2UWGzI8@louis-chauvet-laptop>
On Thu, Jan 30, 2025 at 02:48:19PM +0100, Louis Chauvet wrote:
> On 29/01/25 - 12:00, José Expósito wrote:
> > Add a list of planes to vkms_config and create as many planes as
> > configured during output initialization.
> >
> > For backwards compatibility, add one primary plane and, if configured,
> > one cursor plane and NUM_OVERLAY_PLANES planes to the default
> > configuration.
> >
> > Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> > Signed-off-by: José Expósito <jose.exposito89@gmail.com>
>
> Co-developped-by: Louis Chauvet <louis.chauvet@bootlin.com>
> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> Signed-off-by: José Expósito <jose.exposito89@gmail.com>
>
> [...]
>
> > diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
>
> [...]
>
> > +static void vkms_config_test_get_planes(struct kunit *test)
> > +{
> > + struct vkms_config *config;
> > + struct vkms_config_plane *plane_cfg1, *plane_cfg2;
> > + struct vkms_config_plane **array;
> > + size_t length;
> > +
> > + config = vkms_config_create("test");
> > + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
> > +
> > + array = vkms_config_get_planes(config, &length);
> > + KUNIT_ASSERT_EQ(test, length, 0);
> > + KUNIT_ASSERT_NULL(test, array);
> > +
> > + plane_cfg1 = vkms_config_add_plane(config);
> > + array = vkms_config_get_planes(config, &length);
> > + KUNIT_ASSERT_EQ(test, length, 1);
> > + KUNIT_ASSERT_PTR_EQ(test, array[0], plane_cfg1);
> > + kfree(array);
> > +
> > + plane_cfg2 = vkms_config_add_plane(config);
> > + array = vkms_config_get_planes(config, &length);
> > + KUNIT_ASSERT_EQ(test, length, 2);
> > + KUNIT_ASSERT_PTR_EQ(test, array[0], plane_cfg1);
> > + KUNIT_ASSERT_PTR_EQ(test, array[1], plane_cfg2);
> > + kfree(array);
> > +
> > + vkms_config_destroy_plane(plane_cfg1);
> > + array = vkms_config_get_planes(config, &length);
> > + KUNIT_ASSERT_EQ(test, length, 1);
> > + KUNIT_ASSERT_PTR_EQ(test, array[0], plane_cfg2);
> > + kfree(array);
> > +
> > + vkms_config_destroy(config);
> > +}
>
> In this test I have the feeling that vkms_config_get_planes always returns
> a predictable order. It is maybe trivial here, but I would prefer to shows
> that the order is not stable, for example:
>
> bool plane_cfg1_found = false;
> bool plane_cfg2_found = false;
>
> vkms_config_for_each_plane(config, plane_cfg) {
> if (plane_cfg == plane_cfg1)
> plane_cfg1_found = true;
> else if (plane_cfg == plane_cfg2)
> plane_cfg2_found = true;
> else
> KUNIT_FAILS("Unexpected plane");
> }
>
> KUNIT_ASSERT(test, plane_cfg1_found);
> KUNIT_ASSERT(test, plane_cfg2_found);
>
> [...]
>
> > +static void vkms_config_test_valid_plane_number(struct kunit *test)
> > +{
> > + struct vkms_config *config;
> > + struct vkms_config_plane *plane_cfg;
> > + int n;
> > +
> > + config = vkms_config_default_create(false, false, false);
> > + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
> > +
> > + /* Invalid: No planes */
> > + plane_cfg = list_first_entry(&config->planes, typeof(*plane_cfg), link);
> > + vkms_config_destroy_plane(plane_cfg);
> > + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
> > +
> > + /* Invalid: Too many planes */
> > + for (n = 0; n <= 32; n++)
> > + vkms_config_add_plane(config);
> > +
> > + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
> > +
> > + vkms_config_destroy(config);
> > +}
>
> For this function, the naming is a bit strange, it says
> "valid_plane_number", but you test only invalid plane number.
The reason for this naming is that it tests the valid_plane_number()
function called by vkms_config_is_valid(). The applies for the other
valid_* tests.
However, I don't mind changing its name to so it reflects the test
rather than the tested function.
Changed in v2.
>
> Can you rename it to vkms_config_test_invalid_plane_number?
>
> [...]
>
> > diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
>
> [...]
>
> > +struct vkms_config_plane **vkms_config_get_planes(const struct vkms_config *config,
> > + size_t *out_length)
> > +{
> > + struct vkms_config_plane **array;
> > + struct vkms_config_plane *plane_cfg;
> > + size_t length;
> > + int n = 0;
> > +
> > + length = list_count_nodes((struct list_head *)&config->planes);
> > + if (length == 0) {
> > + *out_length = length;
> > + return NULL;
> > + }
> > +
> > + array = kmalloc_array(length, sizeof(*array), GFP_KERNEL);
> > + if (!array)
> > + return ERR_PTR(-ENOMEM);
> > +
> > + list_for_each_entry(plane_cfg, &config->planes, link) {
> > + array[n] = plane_cfg;
> > + n++;
> > + }
> > +
> > + *out_length = length;
> > + return array;
> > +}
>
> To join the comment on the test, I am not a big fan of creating a new list
> to return to the caller, for three reasons:
> - the caller needs to manage an other pointer;
> - the caller needs to understand that the content of the array is only
> valid if: the config is not freed, nobody else removed anything from the
> planes;
> - the caller may think this list always have the same order if he looks at
> the tests.
>
> I would prefer a simple macro to do an iteration over the config->planes
> list: (I did not test this macro, but you have this idea)
>
> #define vkms_config_iter_plane(config, plane_cfg) \
> list_for_each_entry((plane_cfg), &(config).planes, link)
>
> This way:
> - no new pointer to manage;
> - if one day we have concurency issue, we just have to protect config, not
> config+all the planes;
> - there is no expected order.
>
> [...]
>
> > bool vkms_config_is_valid(struct vkms_config *config)
> > {
> > + if (!valid_plane_number(config))
> > + return false;
> > +
> > + if (!valid_plane_type(config))
> > + return false;
> > +
> > return true;
> > }
>
> I really like the idea to split the validation function, way simpler!
>
> [...]
>
> > +void vkms_config_destroy_plane(struct vkms_config_plane *plane_cfg)
> > +{
> > + list_del(&plane_cfg->link);
> > + kfree(plane_cfg);
> > +}
>
> I would prefer a "standard" function pair, i.e.: add/remove or
> create/destroy, not add/destroy.
>
> For me it should be create/destroy, you create the plane by using a
> config, so it is clear it will be attached to it.
>
> If you choose add/remove, you should explains in the documentation that
> remove is also doing kfree.
>
> [...]
>
> > diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c
>
> [...]
>
> > @@ -11,61 +11,63 @@ int vkms_output_init(struct vkms_device *vkmsdev)
> > struct vkms_connector *connector;
> > struct drm_encoder *encoder;
> > struct vkms_output *output;
> > - struct vkms_plane *primary, *overlay, *cursor = NULL;
> > - int ret;
> > + struct vkms_plane *primary = NULL, *cursor = NULL;
> > + struct vkms_config_plane **plane_cfgs = NULL;
> > + size_t n_planes;
> > + int ret = 0;
> > int writeback;
> > unsigned int n;
>
> I think it could be interesting to have a vkms_config_is_valid call here.
> It will avoid raising DRM errors or create unexpected devices.
>
> It will also garantee in a later patch that
> vkms_config_crtc_get_primary_plane is a valid pointer.
>
> > - /*
> > - * Initialize used plane. One primary plane is required to perform the composition.
> > - *
> > - * The overlay and cursor planes are not mandatory, but can be used to perform complex
> > - * composition.
> > - */
> > - primary = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_PRIMARY);
> > - if (IS_ERR(primary))
> > - return PTR_ERR(primary);
> > + plane_cfgs = vkms_config_get_planes(vkmsdev->config, &n_planes);
> > + if (IS_ERR(plane_cfgs))
> > + return PTR_ERR(plane_cfgs);
>
> If you agree on the iterator implementation, this code could be simplified
> a lot.
>
> > - if (vkmsdev->config->cursor) {
> > - cursor = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_CURSOR);
> > - if (IS_ERR(cursor))
> > - return PTR_ERR(cursor);
> > + for (n = 0; n < n_planes; n++) {
> > + struct vkms_config_plane *plane_cfg;
> > + enum drm_plane_type type;
> > +
> > + plane_cfg = plane_cfgs[n];
> > + type = vkms_config_plane_get_type(plane_cfg);
> > +
> > + plane_cfg->plane = vkms_plane_init(vkmsdev, type);
>
> Can we pass plane_cfg in vkms_plane_init? This way we don't have to
> touch vkms_output_init when adding new vkms_config_plane members.
While it'll be required once we allow to configure more parameters, I don't
think we need it right now. To keep things as simple as possible, I'd prefer to
delay it until required.
Thanks,
Jose
> > + if (IS_ERR(plane_cfg->plane)) {
> > + DRM_DEV_ERROR(dev->dev, "Failed to init vkms plane\n");
> > + ret = PTR_ERR(plane_cfg->plane);
> > + goto err_free;
> > + }
> > +
> > + if (type == DRM_PLANE_TYPE_PRIMARY)
> > + primary = plane_cfg->plane;
> > + else if (type == DRM_PLANE_TYPE_CURSOR)
> > + cursor = plane_cfg->plane;
> > }
>
> [...]
next prev parent reply other threads:[~2025-02-11 10:43 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-01-29 11:00 [PATCH 00/13] drm/vkms: Allow to configure device José Expósito
2025-01-29 11:00 ` [PATCH 01/13] drm/vkms: Extract vkms_connector header José Expósito
2025-01-30 13:48 ` Louis Chauvet
2025-02-11 10:37 ` José Expósito
2025-01-29 11:00 ` [PATCH 02/13] drm/vkms: Add KUnit test scaffolding José Expósito
2025-01-30 13:48 ` Louis Chauvet
2025-01-29 11:00 ` [PATCH 03/13] drm/vkms: Extract vkms_config header José Expósito
2025-01-30 13:48 ` Louis Chauvet
2025-02-11 10:39 ` José Expósito
2025-01-29 11:00 ` [PATCH 04/13] drm/vkms: Move default_config creation to its own function José Expósito
2025-01-30 13:48 ` Louis Chauvet
2025-01-29 11:00 ` [PATCH 05/13] drm/vkms: Set device name from vkms_config José Expósito
2025-01-30 13:48 ` Louis Chauvet
2025-01-29 11:00 ` [PATCH 06/13] drm/vkms: Add a validation function for VKMS configuration José Expósito
2025-01-30 13:48 ` Louis Chauvet
2025-01-29 11:00 ` [PATCH 07/13] drm/vkms: Allow to configure multiple planes José Expósito
2025-01-30 13:48 ` Louis Chauvet
2025-02-11 10:43 ` José Expósito [this message]
2025-02-12 14:10 ` Louis Chauvet
2025-01-29 11:00 ` [PATCH 08/13] drm/vkms: Allow to configure multiple CRTCs José Expósito
2025-01-30 13:48 ` Louis Chauvet
2025-02-11 10:44 ` José Expósito
2025-02-12 14:12 ` Louis Chauvet
2025-02-13 15:26 ` José Expósito
2025-01-29 11:00 ` [PATCH 09/13] drm/vkms: Allow to attach planes and CRTCs José Expósito
2025-01-30 13:48 ` Louis Chauvet
2025-02-11 10:47 ` José Expósito
2025-02-12 14:10 ` Louis Chauvet
2025-02-13 15:32 ` José Expósito
2025-01-29 11:00 ` [PATCH 10/13] drm/vkms: Allow to configure multiple encoders José Expósito
2025-01-30 13:48 ` Louis Chauvet
2025-01-29 11:00 ` [PATCH 11/13] drm/vkms: Allow to attach encoders and CRTCs José Expósito
2025-01-30 13:48 ` Louis Chauvet
2025-01-29 11:00 ` [PATCH 12/13] drm/vkms: Allow to configure multiple connectors José Expósito
2025-01-30 13:48 ` Louis Chauvet
2025-01-29 11:00 ` [PATCH 13/13] drm/vkms: Allow to attach connectors and encoders José Expósito
2025-01-30 13:48 ` Louis Chauvet
2025-01-30 13:48 ` [PATCH 00/13] drm/vkms: Allow to configure device Louis Chauvet
2025-01-31 9:31 ` José Expósito
2025-01-31 13:02 ` Louis Chauvet
2025-01-31 17:13 ` José Expósito
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Z6spy81Xa-Aoz-HZ@fedora \
--to=jose.exposito89@gmail.com \
--cc=airlied@gmail.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=hamohammed.sa@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=louis.chauvet@bootlin.com \
--cc=maarten.lankhorst@linux.intel.com \
--cc=melissa.srw@gmail.com \
--cc=mripard@kernel.org \
--cc=simona@ffwll.ch \
--cc=tzimmermann@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.