[PATCH 2/5] drm: port the drm backend to the new init api

Bryce Harrington bryce at osg.samsung.com
Wed Apr 13 04:34:28 UTC 2016


On Wed, Apr 06, 2016 at 11:37:57AM +0300, Pekka Paalanen wrote:
> On Wed,  9 Mar 2016 16:49:29 -0800
> Bryce Harrington <bryce at osg.samsung.com> wrote:
> 
> > From: Giulio Camuffo <giuliocamuffo at gmail.com>
> > 
> > Signed-off-by: Bryce Harrington <bryce at osg.samsung.com>
> > Reviewed-by: Quentin Glidic <sardemff7+git at sardemff7.net>
> > Acked-by: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
> > ---
> > v4: Update to current trunk
> >     - Add missing param doc for mode in drm_output_choose_initial_mode
> >     - Rebase to account for code changes by 91880f1e to make vt
> >       switching configurable.
> > 
> >  Makefile.am          |   3 +
> >  src/compositor-drm.c | 196 ++++++++++++++++++---------------------------------
> >  src/compositor.h     |   2 -
> >  src/main.c           |  94 +++++++++++++++++++++++-
> >  4 files changed, 165 insertions(+), 130 deletions(-)
> 
> Hi Giulio and Bryce,
> 
> I'm sorry it has taken so long for me to come back to this.
> 
> > diff --git a/Makefile.am b/Makefile.am
> > index fe08d94..9330f0e 100644
> > --- a/Makefile.am
> > +++ b/Makefile.am
> > @@ -72,6 +72,7 @@ weston_SOURCES =					\
> >  	src/log.c					\
> >  	src/compositor.c				\
> >  	src/compositor.h				\
> > +	src/compositor-drm.h				\
> >  	src/input.c					\
> >  	src/data-device.c				\
> >  	src/screenshooter.c				\
> > @@ -207,6 +208,7 @@ westonincludedir = $(includedir)/weston
> >  westoninclude_HEADERS =				\
> >  	src/version.h				\
> >  	src/compositor.h			\
> > +	src/compositor-drm.h			\
> >  	src/timeline-object.h			\
> >  	shared/matrix.h				\
> >  	shared/config-parser.h			\
> > @@ -276,6 +278,7 @@ drm_backend_la_CFLAGS =				\
> >  	$(AM_CFLAGS)
> >  drm_backend_la_SOURCES =			\
> >  	src/compositor-drm.c			\
> > +	src/compositor-drm.h			\
> >  	$(INPUT_BACKEND_SOURCES)		\
> >  	shared/helpers.h			\
> >  	shared/timespec-util.h			\
> > diff --git a/src/compositor-drm.c b/src/compositor-drm.c
> > index e01f6b9..111c882 100644
> > --- a/src/compositor-drm.c
> > +++ b/src/compositor-drm.c
> 
> > @@ -2185,30 +2162,45 @@ get_gbm_format_from_section(struct weston_config_section *section,
> >   * Find the most suitable mode to use for initial setup (or reconfiguration on
> >   * hotplug etc) for a DRM output.
> >   *
> > + * @param backend The DRM backend object
> >   * @param output DRM output to choose mode for
> > - * @param kind Strategy and preference to use when choosing mode
> > - * @param width Desired width for this output
> > - * @param height Desired height for this output
> > + * @param mode Controls how to select the mode
> > + * @param config Desired configuration for the output
> >   * @param current_mode Mode currently being displayed on this output
> > - * @param modeline Manually-entered mode (may be NULL)
> >   * @returns A mode from the output's mode list, or NULL if none available
> >   */
> >  static struct drm_mode *
> > -drm_output_choose_initial_mode(struct drm_output *output,
> > -			       enum output_config kind,
> > -			       int width, int height,
> > -			       const drmModeModeInfo *current_mode,
> > -			       const drmModeModeInfo *modeline)
> > +drm_output_choose_initial_mode(struct drm_backend *backend,
> > +			       struct drm_output *output,
> > +			       enum weston_drm_backend_output_mode mode,
> > +			       struct weston_drm_backend_output_config *config,
> > +			       const drmModeModeInfo *current_mode)
> >  {
> >  	struct drm_mode *preferred = NULL;
> >  	struct drm_mode *current = NULL;
> >  	struct drm_mode *configured = NULL;
> >  	struct drm_mode *best = NULL;
> >  	struct drm_mode *drm_mode;
> > +	drmModeModeInfo modeline;
> > +	int32_t width, height;
> > +
> > +	if (mode == WESTON_DRM_BACKEND_OUTPUT_PREFERRED && config->modeline) {
> > +		if (sscanf(config->modeline, "%dx%d", &width, &height) != 2) {
> > +			width = -1;
> > +
> > +			if (parse_modeline(config->modeline, &modeline) == 0) {
> > +				configured = drm_output_add_mode(output, &modeline);
> > +				if (!configured)
> > +					return NULL;
> > +			} else {
> > +				weston_log("Invalid modeline \"%s\" for output %s\n",
> > +					   config->modeline, output->base.name);
> > +			}
> > +		}
> > +	}
> 
> Hmm, this logic above looks a little odd to me. If mode=PREFERRED means
> the user wants the preferred mode, why would it look at modeline at all?
> 
> Is this changing the meaning of modeline to override the PREFERRED
> setting?
> 
> Maybe this is an API refactorization artifact, since originally we got
> a single config file key "mode" which determined several arguments used
> here, so if the caller (main) keeps working the same way as before, it
> is impossible to have both mode=PREFERRED and modeline set at the same
> time.
> 
> Am I missing something?
> 
> If this to add a new feature of being able to add custom modes without
> actually setting them? If so, I would split that into a separate patch,
> since it's a new feature and not about just porting to the new API. And
> in that case one might also want to set multiple new custom modes, so
> this isn't even a sufficient API to my understanding.
> 
> I would think that if mode=PREFERRED, we get the EDID mode tagged as
> preferred, period. If mode=MODELINE (I forget what the alternatives
> actually were), then we inspect the modeline argument and set that.

I agree that this naming is confusing, since preferred has a very
specific meaning in relation to modesetting, and this is overloading
it.  Perhaps WESTON_DRM_BACKEND_OUTPUT_MODESET or something would be
better, to just indicate that we're expecting a mode set to be done
here.

But I'm fine with letting this be followup work, as pq suggests.

> >  	wl_list_for_each_reverse(drm_mode, &output->base.mode_list, base.link) {
> > -		if (kind == OUTPUT_CONFIG_MODE &&
> > -		    width == drm_mode->base.width &&
> > +		if (width == drm_mode->base.width &&
> >  		    height == drm_mode->base.height)
> 
> Width and height used possibly uninitialized.

I'll initialize them to 0.  Although, I suspect if they are 0, maybe
there needs to be a bail out or something.  Again though, fine to leave
for followup, it probably won't adversely affect normal operation.
 
> >  			configured = drm_mode;
> >  
> 
> 
> >  WL_EXPORT int
> >  backend_init(struct weston_compositor *compositor, int *argc, char *argv[],
> > -	     struct weston_config *config,
> > -	     struct weston_backend_config *config_base)
> > +             struct weston_config *wc,
> > +             struct weston_backend_config *config_base)
> >  {
> >  	struct drm_backend *b;
> > -	struct drm_parameters param = { 0, };
> > -
> > -	const struct weston_option drm_options[] = {
> > -		{ WESTON_OPTION_INTEGER, "connector", 0, &param.connector },
> > -		{ WESTON_OPTION_STRING, "seat", 0, &param.seat_id },
> > -		{ WESTON_OPTION_INTEGER, "tty", 0, &param.tty },
> > -		{ WESTON_OPTION_BOOLEAN, "current-mode", 0, &option_current_mode },
> > -		{ WESTON_OPTION_BOOLEAN, "use-pixman", 0, &param.use_pixman },
> > -	};
> > -
> > -	param.seat_id = default_seat;
> > -
> > -	parse_options(drm_options, ARRAY_LENGTH(drm_options), argc, argv);
> > +	struct weston_drm_backend_config *config =
> > +				(struct weston_drm_backend_config *)config_base;
> 
> The patch to add struct versioning should affect the code here, so I'd
> rather see the drm-specific parts of that patch squashed into this one.

I actually preferred to keep this initial introduction of the config
struct versioning as a separate commit since it's a distinctly separate
change, and future backend implementers might find it easier to study
the change in isolation to the rest of the drm backend changes.  For
subsequent backends I don't think there's any need to have it broken
out, though.  If you're insistent that it must be squashed, I can do
that, but my preference would be for it to be added as a separate
change.
 
> >  
> > -	b = drm_backend_create(compositor, &param, argc, argv, config);
> > +	b = drm_backend_create(compositor, config);
> >  	if (b == NULL)
> >  		return -1;
> >  	return 0;
> > diff --git a/src/compositor.h b/src/compositor.h
> > index 794a1b0..30462cf 100644
> > --- a/src/compositor.h
> > +++ b/src/compositor.h
> > @@ -673,8 +673,6 @@ enum weston_capability {
> >   */
> >  struct weston_backend_output_config {
> >  	uint32_t transform;
> > -	uint32_t width;
> > -	uint32_t height;
> >  	uint32_t scale;
> >  };
> >  
> > diff --git a/src/main.c b/src/main.c
> > index 43de354..66c054e 100644
> > --- a/src/main.c
> > +++ b/src/main.c
> > @@ -47,6 +47,8 @@
> >  #include "git-version.h"
> >  #include "version.h"
> >  
> > +#include "compositor-drm.h"
> > +
> >  static struct wl_list child_process_list;
> >  static struct weston_compositor *segv_compositor;
> >  
> > @@ -670,13 +672,101 @@ load_backend_new(struct weston_compositor *compositor, const char *backend,
> >  	return backend_init(compositor, NULL, NULL, NULL, config_base);
> >  }
> >  
> > +struct drm_config {
> > +	struct weston_drm_backend_config base;
> > +	bool use_current_mode;
> > +};
> > +
> > +static enum weston_drm_backend_output_mode
> > +drm_configure_output(struct weston_compositor *c,
> > +		     struct weston_drm_backend_config *backend_config,
> > +		     const char *name,
> > +		     struct weston_drm_backend_output_config *config)
> > +{
> > +	struct drm_config *drm_config = (struct drm_config *)backend_config;
> 
> I think this cast will break when introducing the struct versioning.
> 
> struct drm_config is a main.c thing, but the backend will not be
> storing the main-passed pointer as is. Instead the backend will copy
> the set part of the passed in struct weston_drm_backend_config
> into it's own version of the struct and fill unset fields with
> defaults. This happens when main.c has been complied with an older
> definition of struct weston_drm_backend_config than what the backend
> itself uses.
> 
> Callbacks like this will need to carry an explicit void *user_data,
> unless you rely on the user_data of weston_compositor.

I felt the drm_config structure was a bit extraneous so just moved
use_current_mode into weston_drm_backend_config and refactored the code
to use that structure directly, without the need for any casting, and it
simplified the code a bit.  So hopefully I've eliminated this problem
entirely, but you'll want to re-review.
 
> > +	struct weston_config *wc = weston_compositor_get_user_data(c);
> > +	struct weston_config_section *section;
> > +	char *s;
> > +	int scale;
> > +	enum weston_drm_backend_output_mode mode =
> > +				WESTON_DRM_BACKEND_OUTPUT_PREFERRED;
> > +
> > +	section = weston_config_get_section(wc, "output", "name", name);
> > +	weston_config_section_get_string(section, "mode", &s, "preferred");
> > +	if (strcmp(s, "off") == 0) {
> > +		free(s);
> > +		return WESTON_DRM_BACKEND_OUTPUT_OFF;
> > +	}
> > +
> > +	if (drm_config->use_current_mode || strcmp(s, "current") == 0) {
> > +		mode = WESTON_DRM_BACKEND_OUTPUT_CURRENT;
> > +	} else if (strcmp(s, "preferred") != 0) {
> > +		config->modeline = s;
> > +		s = NULL;
> > +	}
> > +	free(s);
> > +
> > +	weston_config_section_get_int(section, "scale", &scale, 1);
> > +	config->base.scale = scale >= 1 ? scale : 1;
> > +	weston_config_section_get_string(section, "transform", &s, "normal");
> > +	if (weston_parse_transform(s, &config->base.transform) < 0)
> > +		weston_log("Invalid transform \"%s\" for output %s\n",
> > +			   s, name);
> > +	free(s);
> > +
> > +	weston_config_section_get_string(section,
> > +					 "gbm-format", &config->format, NULL);
> > +	weston_config_section_get_string(section, "seat", &config->seat, "");
> > +	return mode;
> > +}
> > +
> > +static int
> > +load_drm_backend(struct weston_compositor *c, const char *backend,
> > +		 int *argc, char **argv, struct weston_config *wc)
> > +{
> > +	struct drm_config *config;
> > +	struct weston_config_section *section;
> > +	int ret = 0;
> > +
> > +	config = zalloc(sizeof *config);
> > +	if (!config)
> > +		return -1;
> 
> This function will be affected by the struct versioning too.

The subsequent patch adds the versioning, although later in the routine
than here.

> > +	const struct weston_option options[] = {
> > +		{ WESTON_OPTION_INTEGER, "connector", 0, &config->base.connector },
> > +		{ WESTON_OPTION_STRING, "seat", 0, &config->base.seat_id },
> > +		{ WESTON_OPTION_INTEGER, "tty", 0, &config->base.tty },
> > +		{ WESTON_OPTION_BOOLEAN, "current-mode", 0,
> > +					 &config->use_current_mode },
> > +		{ WESTON_OPTION_BOOLEAN, "use-pixman", 0, &config->base.use_pixman },
> > +	};
> 
> Mixed declarations and code.

Hmm, I'm not sure best how to address this.  Options is being
initialized with pointers that are created by the zalloc, so I don't
think I can just separate the declaration from the initialization.  Does
options need to be changed to be dynamically allocated as well?

Bryce


More information about the wayland-devel mailing list