Allow to add additional modes to outputs #1095
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-1 for wlr_output_add_mode
. Use wlr_output_set_custom_mode
instead.
@emersion set_custom_mode seems to set the current mode. I'd like to be able to add several additional modes to the list of available modes and select from them at a later point: This can be useful if you e.g. want to drive a projector at a conference. See e.g.: https://wiki.debconf.org/wiki/DebConf19/Advice_for_presenters#xrandr_hints for how to prepare for a talk. I'd be great if something like this would be possible with wlroots at some point. |
Hmm. I'm not sure I like this. What's the upside of doing this instead of setting the mode you want? Also this modeline parsing is very meh. And: what should this do on non-DRM backends? |
backend/drm/drm.c
Outdated
else if (strcasecmp(vsync, "-vsync") == 0) | ||
mode->flags |= DRM_MODE_FLAG_NVSYNC; | ||
else | ||
return false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
braces are mandatory
backend/drm/drm.c
Outdated
&mode->vdisplay, | ||
&mode->vsync_start, | ||
&mode->vsync_end, | ||
&mode->vtotal, hsync, vsync) != 11) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here too
backend/drm/drm.c
Outdated
else | ||
return false; | ||
|
||
snprintf(mode->name, sizeof mode->name, "%dx%d@%.3f", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sizeof(...)
Rather than trying to bubble this through the wlr_output interface I think it would be better for users hoping to set this to use grab drm.h and use some DRM-specific function. |
@emersion the upside of being able to add modes is that you can set them in advance (without running them) and a GUI can later on offer them for activation (see swaywm/wlr-protocols#15). It will also appear in the list of available modes returned by wl_output so even without it if we allow to switch a compositor to cycle through a list of available modes this would be in there (so e.g. a sysadmin can set the modes for a user to use at a later point - we'll likely want a wlr_output_remove_mode at a later point to remove a mode that is supported by an output from the list of available modes). Non-drm backends can simply ignore the unused parameters and use x@ to add to the list of available modes. I'm also not sure what's so bad about the modeline parsing. We're shifting around Vesa modes implicitly in drm_mode all the time. The alternative would be to fill drmModeModeInfo and pass that around and leave the parsing to the compositor. |
@SirCmpwn you mean adding a drm_connector_add_mode to drm.h ? We could do that but other backends would miss out then (see above) and I think we need add_mode / remove_mode functions functions to give fine enough control to the user. |
I really don't understand why adding mode is so important when you can set any custom mode. A client that lets the user choose a mode for an output can also offer to set a custom mode and remember a list of previously used custom modes. You can also make your compositor do this job of remembering additional custom modes and exposing them through an output management protocol.
Exposing modes in wl_output was a mistake in the Wayland protocol design - we only do so for user convenience and debugging. GNOME only exposes the current mode for instance.
Remember that not all outputs support modes - all outputs except the DRM ones will have zero modes. This function will be a no-op on these backends, as adding a mode to the list would mark the output as supporting modes.
It's not convenient for an API. If you want to programmatically add a new mode you need to format a string that'll get parsed anyway right after. Strings are fine in the config file, not in a library API.
I think he meant getting the DRM connector handle from the |
Yeah I could do that but I think proper mode handling should be part of a compositor library. If that's not the case that's ok and every compositor can do this by itself but..
...that only works if I can rely on adding a mode always stays as simple as:
with a filled in drm_mode. Is that the case?
Regarding modeline parsing
I agree here and that's why I talked about drmModeModeInfo above. We can pass around the parameters as separate variables but I don't think that's a much better API either. Third way would be to just pass in width, height and refresh and then make up the rest to fill drmModeModeInfo. |
That's not what I meant. @agx had the right idea, I want a function in |
I'm okay with the DRM-specific function. This function could take a Still not convinced it's really useful, but this design makes it acceptable to me.
Some outputs are spec'ed to support modes, in which case the compositor will stick to the modes advertised by the output when modesetting. Some other outputs can have any size, thus don't support modes (ie. modes don't make sense on them): this is the case of all backends except DRM. Outputs support modes if the list of modes is not empty. Adding modes to the headless backend would break this design. |
FWIW headless currently defines and uses |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NAK, modeline strings are stupid and don't belong in any sort of a proper API!
Duplicate libdrm API if you have to, but seriously, modelines are legacy and should be eliminated. Leave parsing to whatever messed up tool wants to use string modelines.
I don't get it.
It's never called, but it's exposed via the output interface ( |
Made this drm specific. I moved the modeline parsing to rootston so it does not clutter the wlroots API (yet?). However we could move parse_modeline into drm.c as well allowing compositors to parse modelines and get a xf86ModeModeInfo back. If this looks better I'd have to guard the places with #ifdef linux in rooston which is the downside of not having it all in drm.c |
Looking better.
Does BSD's drm implementation not support custom modes? |
Ah...forgot about libdrm on FreeBSD. So it will have xf86ModeModeInfo as well. |
backend/drm/drm.c
Outdated
} | ||
|
||
assert(modeinfo); | ||
memcpy (&mode->drm_mode, modeinfo, sizeof(*modeinfo)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style: no space before (
The DRM backend part LGTM. @ascent12 Thoughts? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aside for the extremely minor style things, overall it looks fine.
I'll try test this myself later today.
wl_list_insert(&conn->output.modes, &mode->wlr_mode.link); | ||
return true; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are extra blank lines on both sides of this function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bump
backend/drm/drm.c
Outdated
@@ -566,6 +566,31 @@ static bool drm_connector_set_mode(struct wlr_output *output, | |||
return false; | |||
} | |||
|
|||
|
|||
bool wlr_drm_connector_add_mode(struct wlr_output *output, drmModeModeInfo *modeinfo) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
modeinfo can be const.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bump
Hi,
On Thu, Jul 05, 2018 at 01:36:57PM -0700, emersion wrote:
Style: no space before (
Fixed. Thanks for having a look.
|
rootston/output.c
Outdated
@@ -841,6 +842,10 @@ void handle_new_output(struct wl_listener *listener, void *data) { | |||
roots_config_get_output(config, wlr_output); | |||
if (output_config) { | |||
if (output_config->enable) { | |||
struct roots_output_mode_config *mode_config; | |||
wl_list_for_each(mode_config, &output_config->modes, link) { | |||
wlr_drm_connector_add_mode(wlr_output, &mode_config->info); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to check that the wlr_output
is a DRM output.
rootston/config.c
Outdated
if (parse_modeline(value, &mode->info)) { | ||
wl_list_insert(&oc->modes, &mode->link); | ||
} else { | ||
free (mode); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra space here
backend/drm/drm.c
Outdated
@@ -566,6 +566,31 @@ static bool drm_connector_set_mode(struct wlr_output *output, | |||
return false; | |||
} | |||
|
|||
|
|||
bool wlr_drm_connector_add_mode(struct wlr_output *output, drmModeModeInfo *modeinfo) { |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
Hi,
On Fri, Jul 06, 2018 at 04:47:51AM -0700, emersion wrote:
@emersion commented on this pull request.
--------------------------------------------------------------------------
In [1]backend/drm/drm.c:
> @@ -566,6 +566,31 @@ static bool drm_connector_set_mode(struct wlr_output *output,
return false;
}
+
+bool wlr_drm_connector_add_mode(struct wlr_output *output, drmModeModeInfo *modeinfo) {
Maybe we should ensure that the type is DRM_MODE_TYPE_USERDEF?
We're defining tht mode so we're setting it as DRM_MODE_TYPE_USERDEF,
what would we check, that it doesn't match an existing mode?
|
You set |
Hi,
On Fri, Jul 06, 2018 at 06:25:34AM -0700, emersion wrote:
We're defining tht mode so we're setting it as DRM_MODE_TYPE_USERDEF,
what would we check, that it doesn't match an existing mode?
You set DRM_MODE_TYPE_USERDEF in rootston. That means API users can add a
mode with this flag set to something else. We should probably forbid that.
Good point! I've fixed that. While doing that I'm wondering if it
wouldn't be better to return 0 in case of success and < 0 in case of
error so we can distinguish parsing errors from OOM? I mostly used bool
since other APIs seem to do so as well.
|
backend/drm/drm.c
Outdated
struct wlr_drm_mode *mode = calloc(1, sizeof(*mode)); | ||
|
||
assert(modeinfo); | ||
if (!mode || modeinfo->type != DRM_MODE_TYPE_USERDEF) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This leaks mode
in case modeinfo->type
is incorrect. We can probably move the modeinfo->type
check before allocating.
I think using bools is fine |
Hi,
On Fri, Jul 06, 2018 at 04:09:15AM -0700, emersion wrote:
@emersion commented on this pull request.
--------------------------------------------------------------------------
In [1]rootston/output.c:
> @@ -841,6 +842,10 @@ void handle_new_output(struct wl_listener *listener, void *data) {
roots_config_get_output(config, wlr_output);
if (output_config) {
if (output_config->enable) {
+ struct roots_output_mode_config *mode_config;
+ wl_list_for_each(mode_config, &output_config->modes, link) {
+ wlr_drm_connector_add_mode(wlr_output, &mode_config->info);
This needs to check that the wlr_output is a DRM output.
Anoher good point. We're not keeping track of that yet, do we? I'd
rather not look at wlr_output->name.
|
We can probably use |
Hi,
On Fri, Jul 06, 2018 at 07:05:38AM -0700, emersion wrote:
Anoher good point. We're not keeping track of that yet, do we? I'd
rather not look at wlr_output->name.
We can probably use wlr_output_is_drm
Did not spot the wlr_foo_is_bar pattern by looking at the impl
yet. Fixed as well as the leak. Thanks!
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
LGTM but I'd like to see @ascent12's comments addressed |
rootston/output.c
Outdated
wlr_drm_connector_add_mode(wlr_output, &mode_config->info); | ||
} | ||
} else { | ||
if (wl_list_length(&output_config->modes)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you're going to update this PR, here's a nitpick: it's better to use wl_list_empty
here instead of wl_list_length
because it is constant time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ping?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems github hates me. Seems the PR updated now correctly.
Hi,
On Fri, Jul 06, 2018 at 11:18:33AM -0700, Drew DeVault wrote:
LGTM but I'd like to see ***@***.***'s comments addressed
Missed these initially, fixed now.
|
Hi,
On Fri, Jul 06, 2018 at 06:19:48PM +0000, emersion wrote:
@emersion commented on this pull request.
--------------------------------------------------------------------------
In [1]rootston/output.c:
> @@ -841,6 +842,17 @@ void handle_new_output(struct wl_listener *listener, void *data) {
roots_config_get_output(config, wlr_output);
if (output_config) {
if (output_config->enable) {
+ struct roots_output_mode_config *mode_config;
+
+ if (wlr_output_is_drm(wlr_output)) {
+ wl_list_for_each(mode_config, &output_config->modes, link) {
+ wlr_drm_connector_add_mode(wlr_output, &mode_config->info);
+ }
+ } else {
+ if (wl_list_length(&output_config->modes)) {
If you're going to update this PR, here's a nitpick: it's better to use
wl_list_empty here instead of wl_list_length because it is constant time.
Fixed as well. Thanks.
|
Hmm, are you missing a |
This allows to add additional modes to the list of available video modes using VESA Coordinated Video Timing information. Closes swaywm#1080
Hi,
On Sat, Jul 07, 2018 at 03:05:58AM -0700, emersion wrote:
Hmm, are you missing a git push? It seems that the parameter is not const
and wl_list_length is still used?
Pused again, I've found another user of wl_list_length which I fixed as
well. I didn't see a comment about const having const xf86ModeModeinfo *
is a good thing.
|
This allows to pass custom modes.
Thanks! |
This adds support for adding additional modes to an output. This can be useful when a user wants to define custom modes (similar to xrandr --newmode).
This will become more even more interestin when we want to allow clients to add custom modes e.g. via
swaywm/wlr-protocols#15
Fixes #1080