[PATCH weston 7/7] Add support for having different GBM formats for different outputs

Neil Roberts neil at linux.intel.com
Fri Mar 7 10:05:50 PST 2014


The gbm-format configuration option can now be specified per-output as
well as in the core config section. If it is not specified it will
default to the format specified in the core section. The
EGL_MESA_configless_context extension is required for this to work. If
this extension is available it will create a context without an
EGLConfig and then it will potentially use a different EGLConfig for
each output.

The gl-renderer interface has been changed so that it takes the EGL
attributes and visual ID in the create_output function as well as in
the create function.
---
 src/compositor-drm.c     |  65 ++++++++++++++++-------
 src/compositor-fbdev.c   |   4 +-
 src/compositor-wayland.c |   4 +-
 src/compositor-x11.c     |   4 +-
 src/gl-renderer.c        | 134 +++++++++++++++++++++++++++++------------------
 src/gl-renderer.h        |   4 +-
 6 files changed, 141 insertions(+), 74 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index e45f47d..3f584a6 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -147,6 +147,7 @@ struct drm_output {
 	drmModeCrtcPtr original_crtc;
 	struct drm_edid edid;
 	drmModePropertyPtr dpms_prop;
+	uint32_t format;
 
 	int vblank_pending;
 	int page_flip_pending;
@@ -420,8 +421,6 @@ static uint32_t
 drm_output_check_scanout_format(struct drm_output *output,
 				struct weston_surface *es, struct gbm_bo *bo)
 {
-	struct drm_compositor *c =
-		(struct drm_compositor *) output->base.compositor;
 	uint32_t format;
 	pixman_region32_t r;
 
@@ -442,7 +441,7 @@ drm_output_check_scanout_format(struct drm_output *output,
 		pixman_region32_fini(&r);
 	}
 
-	if (c->format == format)
+	if (output->format == format)
 		return format;
 
 	return 0;
@@ -507,7 +506,7 @@ drm_output_render_gl(struct drm_output *output, pixman_region32_t *damage)
 		return;
 	}
 
-	output->next = drm_fb_get_from_bo(bo, c, c->format);
+	output->next = drm_fb_get_from_bo(bo, c, output->format);
 	if (!output->next) {
 		weston_log("failed to get drm_fb for bo\n");
 		gbm_surface_release_buffer(output->surface, bo);
@@ -1528,12 +1527,13 @@ find_crtc_for_connector(struct drm_compositor *ec,
 static int
 drm_output_init_egl(struct drm_output *output, struct drm_compositor *ec)
 {
+	EGLint format = output->format;
 	int i, flags;
 
 	output->surface = gbm_surface_create(ec->gbm,
 					     output->base.current_mode->width,
 					     output->base.current_mode->height,
-					     ec->format,
+					     format,
 					     GBM_BO_USE_SCANOUT |
 					     GBM_BO_USE_RENDERING);
 	if (!output->surface) {
@@ -1541,7 +1541,9 @@ drm_output_init_egl(struct drm_output *output, struct drm_compositor *ec)
 		return -1;
 	}
 
-	if (gl_renderer->output_create(&output->base, output->surface) < 0) {
+	if (gl_renderer->output_create(&output->base, output->surface,
+				       gl_renderer->opaque_attribs,
+				       &format) < 0) {
 		weston_log("failed to create gl renderer output state\n");
 		gbm_surface_destroy(output->surface);
 		return -1;
@@ -1853,6 +1855,35 @@ setup_output_seat_constraint(struct drm_compositor *ec,
 }
 
 static int
+get_gbm_format_from_section(struct weston_config_section *section,
+			    uint32_t default_value,
+			    uint32_t *format)
+{
+	char *s;
+	int ret = 0;
+
+	weston_config_section_get_string(section,
+					 "gbm-format", &s, NULL);
+
+	if (s == NULL)
+		*format = default_value;
+	else if (strcmp(s, "xrgb8888") == 0)
+		*format = GBM_FORMAT_XRGB8888;
+	else if (strcmp(s, "rgb565") == 0)
+		*format = GBM_FORMAT_RGB565;
+	else if (strcmp(s, "xrgb2101010") == 0)
+		*format = GBM_FORMAT_XRGB2101010;
+	else {
+		weston_log("fatal: unrecognized pixel format: %s\n", s);
+		ret = -1;
+	}
+
+	free(s);
+
+	return ret;
+}
+
+static int
 create_output_for_connector(struct drm_compositor *ec,
 			    drmModeRes *resources,
 			    drmModeConnector *connector,
@@ -1919,6 +1950,11 @@ create_output_for_connector(struct drm_compositor *ec,
 	transform = parse_transform(s, output->base.name);
 	free(s);
 
+	if (get_gbm_format_from_section(section,
+					ec->format,
+					&output->format) == -1)
+		output->format = ec->format;
+
 	weston_config_section_get_string(section, "seat", &s, "");
 	setup_output_seat_constraint(ec, &output->base, s);
 	free(s);
@@ -2663,7 +2699,6 @@ drm_compositor_create(struct wl_display *display,
 	struct udev_device *drm_device;
 	struct wl_event_loop *loop;
 	const char *path;
-	char *s;
 	uint32_t key;
 
 	weston_log("initializing drm backend\n");
@@ -2677,20 +2712,10 @@ drm_compositor_create(struct wl_display *display,
 	ec->sprites_are_broken = 1;
 
 	section = weston_config_get_section(config, "core", NULL, NULL);
-	weston_config_section_get_string(section,
-					 "gbm-format", &s, "xrgb8888");
-	if (strcmp(s, "xrgb8888") == 0)
-		ec->format = GBM_FORMAT_XRGB8888;
-	else if (strcmp(s, "rgb565") == 0)
-		ec->format = GBM_FORMAT_RGB565;
-	else if (strcmp(s, "xrgb2101010") == 0)
-		ec->format = GBM_FORMAT_XRGB2101010;
-	else {
-		weston_log("fatal: unrecognized pixel format: %s\n", s);
-		free(s);
+	if (get_gbm_format_from_section(section,
+					GBM_FORMAT_XRGB8888,
+					&ec->format) == -1)
 		goto err_base;
-	}
-	free(s);
 
 	ec->use_pixman = param->use_pixman;
 
diff --git a/src/compositor-fbdev.c b/src/compositor-fbdev.c
index 0d96269..d1013e8 100644
--- a/src/compositor-fbdev.c
+++ b/src/compositor-fbdev.c
@@ -628,7 +628,9 @@ fbdev_output_create(struct fbdev_compositor *compositor,
 	} else {
 		setenv("HYBRIS_EGLPLATFORM", "wayland", 1);
 		if (gl_renderer->output_create(&output->base,
-					(EGLNativeWindowType)NULL) < 0) {
+					       (EGLNativeWindowType)NULL,
+					       gl_renderer->opaque_attribs,
+					       NULL) < 0) {
 			weston_log("gl_renderer_output_create failed.\n");
 			goto out_shadow_surface;
 		}
diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c
index 899c329..238946b 100644
--- a/src/compositor-wayland.c
+++ b/src/compositor-wayland.c
@@ -593,7 +593,9 @@ wayland_output_init_gl_renderer(struct wayland_output *output)
 	}
 
 	if (gl_renderer->output_create(&output->base,
-			output->gl.egl_window) < 0)
+				       output->gl.egl_window,
+				       gl_renderer->alpha_attribs,
+				       NULL) < 0)
 		goto cleanup_window;
 
 	return 0;
diff --git a/src/compositor-x11.c b/src/compositor-x11.c
index 6b5eb64..125875e 100644
--- a/src/compositor-x11.c
+++ b/src/compositor-x11.c
@@ -889,7 +889,9 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y,
 		}
 	} else {
 		ret = gl_renderer->output_create(&output->base,
-						 (EGLNativeWindowType) output->window);
+						 (EGLNativeWindowType) output->window,
+						 gl_renderer->opaque_attribs,
+						 NULL);
 		if (ret < 0)
 			return NULL;
 	}
diff --git a/src/gl-renderer.c b/src/gl-renderer.c
index 868fdb7..29d96f3 100644
--- a/src/gl-renderer.c
+++ b/src/gl-renderer.c
@@ -139,6 +139,8 @@ struct gl_renderer {
 
 	int has_egl_buffer_age;
 
+	int has_configless_context;
+
 	struct gl_shader texture_shader_rgba;
 	struct gl_shader texture_shader_rgbx;
 	struct gl_shader texture_shader_egl_external;
@@ -1658,6 +1660,51 @@ log_egl_config_info(EGLDisplay egldpy, EGLConfig eglconfig)
 		weston_log_continue(" unknown\n");
 }
 
+static int
+egl_choose_config(struct gl_renderer *gr, const EGLint *attribs,
+		  const EGLint *visual_id,
+		  EGLConfig *config_out)
+{
+	EGLint count = 0;
+	EGLint matched = 0;
+	EGLConfig *configs;
+	int i;
+
+	if (!eglGetConfigs(gr->egl_display, NULL, 0, &count) || count < 1)
+		return -1;
+
+	configs = calloc(count, sizeof *configs);
+	if (!configs)
+		return -1;
+
+	if (!eglChooseConfig(gr->egl_display, attribs, configs,
+			      count, &matched))
+		goto out;
+
+	for (i = 0; i < matched; ++i) {
+		EGLint id;
+
+		if (visual_id) {
+			if (!eglGetConfigAttrib(gr->egl_display,
+					configs[i], EGL_NATIVE_VISUAL_ID,
+					&id))
+				continue;
+
+			if (id != 0 && id != *visual_id)
+				continue;
+		}
+
+		*config_out = configs[i];
+
+		free(configs);
+		return 0;
+	}
+
+out:
+	free(configs);
+	return -1;
+}
+
 static void
 gl_renderer_output_set_border(struct weston_output *output,
 			      enum gl_renderer_border_side side,
@@ -1689,19 +1736,37 @@ gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface);
 
 static int
 gl_renderer_output_create(struct weston_output *output,
-				    EGLNativeWindowType window)
+			  EGLNativeWindowType window,
+			  const EGLint *attribs,
+			  const EGLint *visual_id)
 {
 	struct weston_compositor *ec = output->compositor;
 	struct gl_renderer *gr = get_renderer(ec);
-	struct gl_output_state *go = calloc(1, sizeof *go);
+	struct gl_output_state *go;
+	EGLConfig egl_config;
 	int i;
 
+	if (egl_choose_config(gr, attribs, visual_id, &egl_config) == -1) {
+		weston_log("failed to choose EGL config for output\n");
+		return -1;
+	}
+
+	if (egl_config != gr->egl_config &&
+	    !gr->has_configless_context) {
+		weston_log("attempted to use a different EGL config for an "
+			   "output but EGL_MESA_configless_context is not "
+			   "supported\n");
+		return -1;
+	}
+
+	go = calloc(1, sizeof *go);
+
 	if (!go)
 		return -1;
 
 	go->egl_surface =
 		eglCreateWindowSurface(gr->egl_display,
-				       gr->egl_config,
+				       egl_config,
 				       window, NULL);
 
 	if (go->egl_surface == EGL_NO_SURFACE) {
@@ -1721,6 +1786,8 @@ gl_renderer_output_create(struct weston_output *output,
 
 	output->renderer_state = go;
 
+	log_egl_config_info(gr->egl_display, egl_config);
+
 	return 0;
 }
 
@@ -1775,50 +1842,6 @@ gl_renderer_destroy(struct weston_compositor *ec)
 }
 
 static int
-egl_choose_config(struct gl_renderer *gr, const EGLint *attribs,
-	const EGLint *visual_id)
-{
-	EGLint count = 0;
-	EGLint matched = 0;
-	EGLConfig *configs;
-	int i;
-
-	if (!eglGetConfigs(gr->egl_display, NULL, 0, &count) || count < 1)
-		return -1;
-
-	configs = calloc(count, sizeof *configs);
-	if (!configs)
-		return -1;
-
-	if (!eglChooseConfig(gr->egl_display, attribs, configs,
-			      count, &matched))
-		goto out;
-
-	for (i = 0; i < matched; ++i) {
-		EGLint id;
-
-		if (visual_id) {
-			if (!eglGetConfigAttrib(gr->egl_display,
-					configs[i], EGL_NATIVE_VISUAL_ID,
-					&id))
-				continue;
-
-			if (id != 0 && id != *visual_id)
-				continue;
-		}
-
-		gr->egl_config = configs[i];
-
-		free(configs);
-		return 0;
-	}
-
-out:
-	free(configs);
-	return -1;
-}
-
-static int
 gl_renderer_setup_egl_extensions(struct weston_compositor *ec)
 {
 	struct gl_renderer *gr = get_renderer(ec);
@@ -1864,6 +1887,11 @@ gl_renderer_setup_egl_extensions(struct weston_compositor *ec)
 			   "supported. Performance could be affected.\n");
 #endif
 
+#ifdef EGL_MESA_configless_context
+	if (strstr(extensions, "EGL_MESA_configless_context"))
+		gr->has_configless_context = 1;
+#endif
+
 	return 0;
 }
 
@@ -1917,7 +1945,7 @@ gl_renderer_create(struct weston_compositor *ec, EGLNativeDisplayType display,
 		goto err_egl;
 	}
 
-	if (egl_choose_config(gr, attribs, visual_id) < 0) {
+	if (egl_choose_config(gr, attribs, visual_id, &gr->egl_config) < 0) {
 		weston_log("failed to choose EGL config\n");
 		goto err_egl;
 	}
@@ -2021,6 +2049,7 @@ gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
 {
 	struct gl_renderer *gr = get_renderer(ec);
 	const char *extensions;
+	EGLConfig context_config;
 	EGLBoolean ret;
 
 	static const EGLint context_attribs[] = {
@@ -2034,9 +2063,14 @@ gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
 		return -1;
 	}
 
-	log_egl_config_info(gr->egl_display, gr->egl_config);
+	context_config = gr->egl_config;
+
+#ifdef EGL_MESA_configless_context
+	if (gr->has_configless_context)
+		context_config = EGL_NO_CONFIG_MESA;
+#endif
 
-	gr->egl_context = eglCreateContext(gr->egl_display, gr->egl_config,
+	gr->egl_context = eglCreateContext(gr->egl_display, context_config,
 					   EGL_NO_CONTEXT, context_attribs);
 	if (gr->egl_context == NULL) {
 		weston_log("failed to create context\n");
diff --git a/src/gl-renderer.h b/src/gl-renderer.h
index dcdf69d..db42f6c 100644
--- a/src/gl-renderer.h
+++ b/src/gl-renderer.h
@@ -58,7 +58,9 @@ struct gl_renderer_interface {
 	EGLDisplay (*display)(struct weston_compositor *ec);
 
 	int (*output_create)(struct weston_output *output,
-			     EGLNativeWindowType window);
+			     EGLNativeWindowType window,
+			     const EGLint *attribs,
+			     const EGLint *visual_id);
 
 	void (*output_destroy)(struct weston_output *output);
 
-- 
1.8.5.3



More information about the wayland-devel mailing list