[PATCH v2] gles2-renderer: Provide an API for backends to use.

Kristian Høgsberg hoegsberg at gmail.com
Fri Oct 26 06:59:21 PDT 2012


On Thu, Oct 25, 2012 at 10:53:20PM +0200, John Kåre Alsaker wrote:
> This provides an new API for gles2-renderer. It allows to move most EGL initialization code and EGL surface creation into gles2-renderer, which makes compositor backends less dependent on gles2-renderer. As a side effect weston_output gets a per-renderer state which gles2-renderer uses to store the EGL surface.

I read the patch and Pekka has a lot of good points, both stylistic
and regarding the actual code changes.  However, I don't agree with
the direction of the patch.  It's *ok* for a backend to know and
depend on EGL or some other rendering API (say pixman or a custom
compositing API or whatever).  It can even depend on multiple such
APIs (for example both pixman and EGL).  A backend will always have to
do some render API specific initialization, where the backend API and
rendering API intersects.  Like eglGetDisplay, which requires backend
specific knowledge (X display, gbm device or such) and rendering API
knowledge (it's an EGL call).

The next small, self-contained step forward from where the renderer
abstraction is now, is to move the EGL types out of the core structs
and header files (that is, just compositor.h).  First step: move the
shaders out of weston_compositor.h.  Let's do that and take the rest
from there.

Kristian

> ---
>  src/compositor-android.c |  72 +++++++----------
>  src/compositor-drm.c     |  87 ++++++---------------
>  src/compositor-wayland.c |  58 +++-----------
>  src/compositor-x11.c     |  71 +++--------------
>  src/compositor.h         |  23 +++++-
>  src/gles2-renderer.c     | 197 ++++++++++++++++++++++++++++++++++++++++++-----
>  6 files changed, 265 insertions(+), 243 deletions(-)
> 
> diff --git a/src/compositor-android.c b/src/compositor-android.c
> index 3c0273a..bf14910 100644
> --- a/src/compositor-android.c
> +++ b/src/compositor-android.c
> @@ -145,6 +145,8 @@ android_output_destroy(struct weston_output *base)
>  	wl_list_remove(&output->base.link);
>  	weston_output_destroy(&output->base);
>  
> +	gles2_renderer_output_unbind(base);
> +
>  	android_framebuffer_destroy(output->fb);
>  
>  	free(output);
> @@ -319,6 +321,8 @@ android_seat_create(struct android_compositor *compositor)
>  static int
>  android_egl_choose_config(struct android_compositor *compositor,
>  			  struct android_framebuffer *fb,
> +			  EGLDisplay egl_display,
> +			  EGLConfig *egl_config,
>  			  const EGLint *attribs)
>  {
>  	EGLBoolean ret;
> @@ -332,9 +336,9 @@ android_egl_choose_config(struct android_compositor *compositor,
>  	 * surfaceflinger/DisplayHardware/DisplayHardware.cpp
>  	 */
>  
> -	compositor->base.egl_config = NULL;
> +	*egl_config = NULL;
>  
> -	ret = eglGetConfigs(compositor->base.egl_display, NULL, 0, &count);
> +	ret = eglGetConfigs(egl_display, NULL, 0, &count);
>  	if (ret == EGL_FALSE || count < 1)
>  		return -1;
>  
> @@ -342,27 +346,27 @@ android_egl_choose_config(struct android_compositor *compositor,
>  	if (!configs)
>  		return -1;
>  
> -	ret = eglChooseConfig(compositor->base.egl_display, attribs, configs,
> +	ret = eglChooseConfig(egl_display, attribs, configs,
>  			      count, &matched);
>  	if (ret == EGL_FALSE || matched < 1)
>  		goto out;
>  
>  	for (i = 0; i < matched; ++i) {
>  		EGLint id;
> -		ret = eglGetConfigAttrib(compositor->base.egl_display,
> +		ret = eglGetConfigAttrib(egl_display,
>  					 configs[i], EGL_NATIVE_VISUAL_ID,
>  					 &id);
>  		if (ret == EGL_FALSE)
>  			continue;
>  		if (id > 0 && fb->format == id) {
> -			compositor->base.egl_config = configs[i];
> +			*egl_config = configs[i];
>  			break;
>  		}
>  	}
>  
>  out:
>  	free(configs);
> -	if (!compositor->base.egl_config)
> +	if (!*egl_config)
>  		return -1;
>  
>  	return 0;
> @@ -372,7 +376,8 @@ static int
>  android_init_egl(struct android_compositor *compositor,
>  		 struct android_output *output)
>  {
> -	EGLint eglmajor, eglminor;
> +	EGLDisplay egl_display;
> +	EGLConfig egl_config;
>  	int ret;
>  
>  	static const EGLint config_attrs[] = {
> @@ -385,66 +390,41 @@ android_init_egl(struct android_compositor *compositor,
>  		EGL_NONE
>  	};
>  
> -	compositor->base.egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
> -	if (compositor->base.egl_display == EGL_NO_DISPLAY) {
> -		weston_log("Failed to create EGL display.\n");
> -		print_egl_error_state();
> -		return -1;
> -	}
> +	egl_display = gles2_renderer_init_without_config(&compositor->base, EGL_DEFAULT_DISPLAY);
>  
> -	ret = eglInitialize(compositor->base.egl_display, &eglmajor, &eglminor);
> -	if (!ret) {
> -		weston_log("Failed to initialise EGL.\n");
> +	if (egl_display == EGL_NO_DISPLAY) {
> +		weston_log("Failed to create EGL display.\n");
>  		print_egl_error_state();
>  		return -1;
>  	}
>  
> -	ret = android_egl_choose_config(compositor, output->fb, config_attrs);
> +	ret = android_egl_choose_config(compositor, output->fb, egl_display, &egl_config, config_attrs);
>  	if (ret < 0) {
>  		weston_log("Failed to find an EGL config.\n");
>  		print_egl_error_state();
>  		return -1;
>  	}
>  
> -	output->base.egl_surface =
> -		eglCreateWindowSurface(compositor->base.egl_display,
> -				       compositor->base.egl_config,
> -				       output->fb->native_window,
> -				       NULL);
> -	if (output->base.egl_surface == EGL_NO_SURFACE) {
> -		weston_log("Failed to create FB EGLSurface.\n");
> -		print_egl_error_state();
> +	gles2_renderer_select_config(&compositor->base, egl_config);
> +
> +	if (gles2_renderer_output_state_create_and_bind(&output->base, output->fb->native_window) < 0)
>  		return -1;
> -	}
>  
>  	return 0;
>  }
>  
>  static void
> -android_fini_egl(struct android_compositor *compositor)
> -{
> -	gles2_renderer_destroy(&compositor->base);
> -
> -	eglMakeCurrent(compositor->base.egl_display,
> -		       EGL_NO_SURFACE, EGL_NO_SURFACE,
> -		       EGL_NO_CONTEXT);
> -
> -	eglTerminate(compositor->base.egl_display);
> -	eglReleaseThread();
> -}
> -
> -static void
>  android_compositor_destroy(struct weston_compositor *base)
>  {
>  	struct android_compositor *compositor = to_android_compositor(base);
>  
>  	android_seat_destroy(compositor->seat);
>  
> +	gles2_renderer_destroy(base);
> +
>  	/* destroys outputs, too */
>  	weston_compositor_shutdown(&compositor->base);
>  
> -	android_fini_egl(compositor);
> -
>  	free(compositor);
>  }
>  
> @@ -478,17 +458,17 @@ android_compositor_create(struct wl_display *display, int argc, char *argv[],
>  
>  	android_compositor_add_output(compositor, output);
>  
> -	if (gles2_renderer_init(&compositor->base) < 0)
> -		goto err_egl;
> +	if (gles2_renderer_outputs_ready(&compositor->base) < 0)
> +		goto err_gles2;
>  
>  	compositor->seat = android_seat_create(compositor);
>  	if (!compositor->seat)
> -		goto err_egl;
> +		goto err_gles2;
>  
>  	return &compositor->base;
>  
> -err_egl:
> -	android_fini_egl(compositor);
> +err_gles2:
> +	gles2_renderer_destroy(&compositor->base);
>  err_output:
>  	android_output_destroy(&output->base);
>  err_compositor:
> diff --git a/src/compositor-drm.c b/src/compositor-drm.c
> index 3e75387..96a206e 100644
> --- a/src/compositor-drm.c
> +++ b/src/compositor-drm.c
> @@ -861,7 +861,7 @@ drm_output_destroy(struct weston_output *output_base)
>  	c->crtc_allocator &= ~(1 << output->crtc_id);
>  	c->connector_allocator &= ~(1 << output->connector_id);
>  
> -	eglDestroySurface(c->base.egl_display, output->base.egl_surface);
> +	gles2_renderer_output_unbind(output_base);
>  	gbm_surface_destroy(output->surface);
>  
>  	weston_plane_release(&output->fb_plane);
> @@ -907,7 +907,7 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo
>  	int ret;
>  	struct drm_compositor *ec;
>  	struct gbm_surface *surface;
> -	EGLSurface egl_surface;
> +	struct gles2_output_state *state;
>  
>  	if (output_base == NULL) {
>  		weston_log("output is NULL.\n");
> @@ -967,15 +967,10 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo
>  		return -1;
>  	}
>  
> -	egl_surface =
> -		eglCreateWindowSurface(ec->base.egl_display,
> -				       ec->base.egl_config,
> -				       surface, NULL);
> +	state = gles2_renderer_output_state_create(&ec->base, surface);
>  
> -	if (egl_surface == EGL_NO_SURFACE) {
> -		weston_log("failed to create egl surface\n");
> -		goto err;
> -	}
> +	if (!state)
> +		goto err_gbm;
>  
>  	ret = drmModeSetCrtc(ec->drm.fd,
>  			     output->crtc_id,
> @@ -983,7 +978,7 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo
>  			     &output->connector_id, 1, &drm_mode->mode_info);
>  	if (ret) {
>  		weston_log("failed to set mode\n");
> -		goto err;
> +		goto err_gles2;
>  	}
>  
>  	/* reset rendering stuff. */
> @@ -1005,10 +1000,10 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo
>  	}
>  	output->next = NULL;
>  
> -	eglDestroySurface(ec->base.egl_display, output->base.egl_surface);
> +	gles2_renderer_output_unbind(output_base);
>  	gbm_surface_destroy(output->surface);
> -	output->base.egl_surface = egl_surface;
>  	output->surface = surface;
> +	gles2_renderer_output_bind(&output->base, state);
>  
>  	/*update output*/
>  	output->base.current = &drm_mode->base;
> @@ -1016,8 +1011,9 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo
>  	weston_output_move(&output->base, output->base.x, output->base.y);
>  	return 0;
>  
> -err:
> -	eglDestroySurface(ec->base.egl_display, egl_surface);
> +err_gles2:
> +	gles2_renderer_output_state_destroy(&ec->base, state);
> +err_gbm:
>  	gbm_surface_destroy(surface);
>  	return -1;
>  }
> @@ -1039,18 +1035,8 @@ on_drm_input(int fd, uint32_t mask, void *data)
>  static int
>  init_egl(struct drm_compositor *ec, struct udev_device *device)
>  {
> -	EGLint major, minor, n;
>  	const char *filename, *sysnum;
>  	int fd;
> -	static const EGLint config_attribs[] = {
> -		EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
> -		EGL_RED_SIZE, 1,
> -		EGL_GREEN_SIZE, 1,
> -		EGL_BLUE_SIZE, 1,
> -		EGL_ALPHA_SIZE, 0,
> -		EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
> -		EGL_NONE
> -	};
>  
>  	sysnum = udev_device_get_sysnum(device);
>  	if (sysnum)
> @@ -1073,22 +1059,9 @@ init_egl(struct drm_compositor *ec, struct udev_device *device)
>  
>  	ec->drm.fd = fd;
>  	ec->gbm = gbm_create_device(ec->drm.fd);
> -	ec->base.egl_display = eglGetDisplay(ec->gbm);
> -	if (ec->base.egl_display == NULL) {
> -		weston_log("failed to create display\n");
> -		return -1;
> -	}
> -
> -	if (!eglInitialize(ec->base.egl_display, &major, &minor)) {
> -		weston_log("failed to initialize display\n");
> -		return -1;
> -	}
>  
> -	if (!eglChooseConfig(ec->base.egl_display, config_attribs,
> -			     &ec->base.egl_config, 1, &n) || n != 1) {
> -		weston_log("failed to choose config: %d\n", n);
> +	if (gles2_renderer_init(&ec->base, ec->gbm, 0) < 0)
>  		return -1;
> -	}
>  
>  	return 0;
>  }
> @@ -1445,15 +1418,13 @@ create_output_for_connector(struct drm_compositor *ec,
>  		goto err_free;
>  	}
>  
> -	output->base.egl_surface =
> -		eglCreateWindowSurface(ec->base.egl_display,
> -				       ec->base.egl_config,
> -				       output->surface,
> -				       NULL);
> -	if (output->base.egl_surface == EGL_NO_SURFACE) {
> -		weston_log("failed to create egl surface\n");
> -		goto err_surface;
> -	}
> +	weston_output_init(&output->base, &ec->base, x, y,
> +			   connector->mmWidth, connector->mmHeight,
> +			   o ? o->transform : WL_OUTPUT_TRANSFORM_NORMAL);
> +
> +	/* this requires output->base.compositor to be initialized */
> +	if (gles2_renderer_output_state_create_and_bind(&output->base, output->surface) < 0)
> +		goto err_output;
>  
>  	output->cursor_bo[0] =
>  		gbm_bo_create(ec->gbm, 64, 64, GBM_FORMAT_ARGB8888,
> @@ -1473,10 +1444,6 @@ create_output_for_connector(struct drm_compositor *ec,
>  		output->base.backlight_current = drm_get_backlight(output);
>  	}
>  
> -	weston_output_init(&output->base, &ec->base, x, y,
> -			   connector->mmWidth, connector->mmHeight,
> -			   o ? o->transform : WL_OUTPUT_TRANSFORM_NORMAL);
> -
>  	wl_list_insert(ec->base.output_list.prev, &output->base.link);
>  
>  	output->base.origin = output->base.current;
> @@ -1503,7 +1470,8 @@ create_output_for_connector(struct drm_compositor *ec,
>  
>  	return 0;
>  
> -err_surface:
> +err_output:
> +	weston_output_destroy(&output->base);
>  	gbm_surface_destroy(output->surface);
>  err_free:
>  	wl_list_for_each_safe(drm_mode, next, &output->base.mode_list,
> @@ -2039,12 +2007,6 @@ drm_destroy(struct weston_compositor *ec)
>  
>  	gles2_renderer_destroy(ec);
>  
> -	/* Work around crash in egl_dri2.c's dri2_make_current() */
> -	eglMakeCurrent(ec->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
> -		       EGL_NO_CONTEXT);
> -	eglTerminate(ec->egl_display);
> -	eglReleaseThread();
> -
>  	gbm_device_destroy(d->gbm);
>  	destroy_sprites(d);
>  	if (weston_launcher_drm_set_master(&d->base, d->drm.fd, 0) < 0)
> @@ -2238,7 +2200,7 @@ drm_compositor_create(struct wl_display *display,
>  		goto err_sprite;
>  	}
>  
> -	if (gles2_renderer_init(&ec->base) < 0)
> +	if (gles2_renderer_outputs_ready(&ec->base) < 0)
>  		goto err_egl;
>  
>  	path = NULL;
> @@ -2280,10 +2242,7 @@ err_drm_source:
>  	wl_list_for_each_safe(weston_seat, next, &ec->base.seat_list, link)
>  		evdev_input_destroy(weston_seat);
>  err_egl:
> -	eglMakeCurrent(ec->base.egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
> -		       EGL_NO_CONTEXT);
> -	eglTerminate(ec->base.egl_display);
> -	eglReleaseThread();
> +	gles2_renderer_destroy(&ec->base);
>  	gbm_device_destroy(ec->gbm);
>  err_sprite:
>  	destroy_sprites(ec);
> diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c
> index 56759fc..1e60d0f 100644
> --- a/src/compositor-wayland.c
> +++ b/src/compositor-wayland.c
> @@ -241,41 +241,6 @@ create_border(struct wayland_compositor *c)
>  	pixman_image_unref(image);
>  }
>  
> -static int
> -wayland_compositor_init_egl(struct wayland_compositor *c)
> -{
> -	EGLint major, minor;
> -	EGLint n;
> -	EGLint config_attribs[] = {
> -		EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
> -		EGL_RED_SIZE, 1,
> -		EGL_GREEN_SIZE, 1,
> -		EGL_BLUE_SIZE, 1,
> -		EGL_ALPHA_SIZE, 1,
> -		EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
> -		EGL_NONE
> -	};
> -
> -	c->base.egl_display = eglGetDisplay(c->parent.wl_display);
> -	if (c->base.egl_display == NULL) {
> -		weston_log("failed to create display\n");
> -		return -1;
> -	}
> -
> -	if (!eglInitialize(c->base.egl_display, &major, &minor)) {
> -		weston_log("failed to initialize display\n");
> -		return -1;
> -	}
> -
> -   	if (!eglChooseConfig(c->base.egl_display, config_attribs,
> -			     &c->base.egl_config, 1, &n) || n == 0) {
> -		weston_log("failed to choose config: %d\n", n);
> -		return -1;
> -	}
> -
> -	return 0;
> -}
> -
>  static void
>  frame_done(void *data, struct wl_callback *callback, uint32_t time)
>  {
> @@ -317,9 +282,9 @@ static void
>  wayland_output_destroy(struct weston_output *output_base)
>  {
>  	struct wayland_output *output = (struct wayland_output *) output_base;
> -	struct weston_compositor *ec = output->base.compositor;
>  
> -	eglDestroySurface(ec->egl_display, output->base.egl_surface);
> +	gles2_renderer_output_unbind(output_base);
> +
>  	wl_egl_window_destroy(output->parent.egl_window);
>  	free(output);
>  
> @@ -373,13 +338,8 @@ wayland_compositor_create_output(struct wayland_compositor *c,
>  		goto cleanup_output;
>  	}
>  
> -	output->base.egl_surface =
> -		eglCreateWindowSurface(c->base.egl_display, c->base.egl_config,
> -				       output->parent.egl_window, NULL);
> -	if (!output->base.egl_surface) {
> -		weston_log("failed to create window surface\n");
> +	if (gles2_renderer_output_state_create_and_bind(&output->base, output->parent.egl_window) < 0)
>  		goto cleanup_window;
> -	}
>  
>  	output->parent.shell_surface =
>  		wl_shell_get_shell_surface(c->parent.shell,
> @@ -831,7 +791,7 @@ wayland_compositor_create(struct wl_display *display,
>  	wl_display_dispatch(c->parent.wl_display);
>  
>  	c->base.wl_display = display;
> -	if (wayland_compositor_init_egl(c) < 0)
> +	if (gles2_renderer_init(&c->base, c->parent.wl_display, 1) < 0)
>  		goto err_display;
>  
>  	c->base.destroy = wayland_destroy;
> @@ -844,11 +804,11 @@ wayland_compositor_create(struct wl_display *display,
>  
>  	/* requires border fields */
>  	if (wayland_compositor_create_output(c, width, height) < 0)
> -		goto err_display;
> +		goto err_gles2;
>  
>  	/* requires wayland_compositor_create_output */
> -	if (gles2_renderer_init(&c->base) < 0)
> -		goto err_display;
> +	if (gles2_renderer_outputs_ready(&c->base) < 0)
> +		goto err_gles2;
>  
>  	/* requires gles2_renderer_init */
>  	create_border(c);
> @@ -860,12 +820,14 @@ wayland_compositor_create(struct wl_display *display,
>  		wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE,
>  				     wayland_compositor_handle_event, c);
>  	if (c->parent.wl_source == NULL)
> -		goto err_display;
> +		goto err_gles2;
>  
>  	wl_event_source_check(c->parent.wl_source);
>  
>  	return &c->base;
>  
> +err_gles2:
> +	gles2_renderer_destroy(&c->base);
>  err_display:
>  	wl_display_disconnect(c->parent.wl_display);
>  err_compositor:
> diff --git a/src/compositor-x11.c b/src/compositor-x11.c
> index e616f45..80c28b0 100644
> --- a/src/compositor-x11.c
> +++ b/src/compositor-x11.c
> @@ -239,53 +239,6 @@ x11_input_destroy(struct x11_compositor *compositor)
>  	weston_seat_release(&compositor->core_seat);
>  }
>  
> -static int
> -x11_compositor_init_egl(struct x11_compositor *c)
> -{
> -	EGLint major, minor;
> -	EGLint n;
> -	EGLint config_attribs[] = {
> -		EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
> -		EGL_RED_SIZE, 1,
> -		EGL_GREEN_SIZE, 1,
> -		EGL_BLUE_SIZE, 1,
> -		EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
> -		EGL_NONE
> -	};
> -
> -	c->base.egl_display = eglGetDisplay(c->dpy);
> -	if (c->base.egl_display == NULL) {
> -		weston_log("failed to create display\n");
> -		return -1;
> -	}
> -
> -	if (!eglInitialize(c->base.egl_display, &major, &minor)) {
> -		weston_log("failed to initialize display\n");
> -		return -1;
> -	}
> -
> -	if (!eglChooseConfig(c->base.egl_display, config_attribs,
> -			     &c->base.egl_config, 1, &n) || n == 0) {
> -		weston_log("failed to choose config: %d\n", n);
> -		return -1;
> -	}
> -
> -	return 0;
> -}
> -
> -static void
> -x11_compositor_fini_egl(struct x11_compositor *compositor)
> -{
> -	gles2_renderer_destroy(&compositor->base);
> -
> -	eglMakeCurrent(compositor->base.egl_display,
> -		       EGL_NO_SURFACE, EGL_NO_SURFACE,
> -		       EGL_NO_CONTEXT);
> -
> -	eglTerminate(compositor->base.egl_display);
> -	eglReleaseThread();
> -}
> -
>  static void
>  x11_output_repaint(struct weston_output *output_base,
>  		   pixman_region32_t *damage)
> @@ -322,8 +275,7 @@ x11_output_destroy(struct weston_output *output_base)
>  	wl_list_remove(&output->base.link);
>  	wl_event_source_remove(output->finish_frame_timer);
>  
> -	eglDestroySurface(compositor->base.egl_display,
> -			  output->base.egl_surface);
> +	gles2_renderer_output_unbind(output_base);
>  
>  	xcb_destroy_window(compositor->conn, output->window);
>  
> @@ -529,13 +481,8 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y,
>  		x11_output_change_state(output, 1,
>  					c->atom.net_wm_state_fullscreen);
>  
> -	output->base.egl_surface = 
> -		eglCreateWindowSurface(c->base.egl_display, c->base.egl_config,
> -				       output->window, NULL);
> -	if (!output->base.egl_surface) {
> -		weston_log("failed to create window surface\n");
> +	if (gles2_renderer_output_state_create_and_bind(&output->base, output->window) < 0)
>  		return NULL;
> -	}
>  
>  	loop = wl_display_get_event_loop(c->base.wl_display);
>  	output->finish_frame_timer =
> @@ -1085,7 +1032,7 @@ x11_destroy(struct weston_compositor *ec)
>  
>  	weston_compositor_shutdown(ec); /* destroys outputs, too */
>  
> -	x11_compositor_fini_egl(compositor);
> +	gles2_renderer_destroy(ec);
>  
>  	XCloseDisplay(compositor->dpy);
>  	free(ec);
> @@ -1133,14 +1080,14 @@ x11_compositor_create(struct wl_display *display,
>  	x11_compositor_get_resources(c);
>  
>  	c->base.wl_display = display;
> -	if (x11_compositor_init_egl(c) < 0)
> +	if (gles2_renderer_init(&c->base, c->dpy, 0) < 0)
>  		goto err_xdisplay;
>  
>  	c->base.destroy = x11_destroy;
>  	c->base.restore = x11_restore;
>  
>  	if (x11_input_create(c, no_input) < 0)
> -		goto err_egl;
> +		goto err_gles2;
>  
>  	width = option_width ? option_width : 1024;
>  	height = option_height ? option_height : 640;
> @@ -1173,8 +1120,8 @@ x11_compositor_create(struct wl_display *display,
>  		x = pixman_region32_extents(&output->base.region)->x2;
>  	}
>  
> -	if (gles2_renderer_init(&c->base) < 0)
> -		goto err_egl;
> +	if (gles2_renderer_outputs_ready(&c->base) < 0)
> +		goto err_x11_input;
>  
>  	c->xcb_source =
>  		wl_event_loop_add_fd(c->base.input_loop,
> @@ -1187,8 +1134,8 @@ x11_compositor_create(struct wl_display *display,
>  
>  err_x11_input:
>  	x11_input_destroy(c);
> -err_egl:
> -	x11_compositor_fini_egl(c);
> +err_gles2:
> +	gles2_renderer_destroy(&c->base);
>  err_xdisplay:
>  	XCloseDisplay(c->dpy);
>  err_free:
> diff --git a/src/compositor.h b/src/compositor.h
> index 3176bfd..59eb4bf 100644
> --- a/src/compositor.h
> +++ b/src/compositor.h
> @@ -154,7 +154,8 @@ enum dpms_enum {
>  struct weston_output {
>  	uint32_t id;
>  
> -	EGLSurface egl_surface;
> +	void *renderer_state;
> +
>  	struct wl_list link;
>  	struct wl_list resource_list;
>  	struct wl_global *global;
> @@ -822,8 +823,26 @@ weston_surface_destroy(struct weston_surface *surface);
>  int
>  weston_output_switch_mode(struct weston_output *output, struct weston_mode *mode);
>  
> +struct gles2_output_state;
> +
> +int
> +gles2_renderer_init(struct weston_compositor *ec, EGLNativeDisplayType display, int alpha);
> +EGLDisplay
> +gles2_renderer_init_without_config(struct weston_compositor *ec, EGLNativeDisplayType display);
> +void
> +gles2_renderer_select_config(struct weston_compositor *ec, EGLConfig config);
>  int
> -gles2_renderer_init(struct weston_compositor *ec);
> +gles2_renderer_outputs_ready(struct weston_compositor *ec);
> +int
> +gles2_renderer_output_state_create_and_bind(struct weston_output *output, EGLNativeWindowType window);
> +struct gles2_output_state *
> +gles2_renderer_output_state_create(struct weston_compositor *ec, EGLNativeWindowType window);
> +void
> +gles2_renderer_output_state_destroy(struct weston_compositor *ec, struct gles2_output_state *state);
> +void
> +gles2_renderer_output_bind(struct weston_output *output, struct gles2_output_state *state);
> +void
> +gles2_renderer_output_unbind(struct weston_output *output);
>  void
>  gles2_renderer_destroy(struct weston_compositor *ec);
>  
> diff --git a/src/gles2-renderer.c b/src/gles2-renderer.c
> index 544cc15..a03a7dd 100644
> --- a/src/gles2-renderer.c
> +++ b/src/gles2-renderer.c
> @@ -30,6 +30,26 @@
>  
>  #include "compositor.h"
>  
> +struct gles2_output_state {
> +	EGLSurface egl_surface;
> +};
> +
> +struct gles2_renderer {
> +	struct weston_renderer base;
> +};
> +
> +static inline struct gles2_output_state *
> +get_output_state(struct weston_output *output)
> +{
> +	return (struct gles2_output_state *)output->renderer_state;
> +}
> +
> +static inline struct gles2_renderer *
> +get_renderer(struct weston_compositor *ec)
> +{
> +	return (struct gles2_renderer *)ec->renderer;
> +}
> +
>  static const char *
>  egl_error_string(EGLint code)
>  {
> @@ -700,6 +720,7 @@ static void
>  gles2_renderer_repaint_output(struct weston_output *output,
>  			      pixman_region32_t *output_damage)
>  {
> +	struct gles2_output_state *output_state = get_output_state(output);
>  	struct weston_compositor *compositor = output->compositor;
>  	EGLBoolean ret;
>  	static int errored;
> @@ -712,8 +733,8 @@ gles2_renderer_repaint_output(struct weston_output *output,
>  
>  	glViewport(0, 0, width, height);
>  
> -	ret = eglMakeCurrent(compositor->egl_display, output->egl_surface,
> -			     output->egl_surface, compositor->egl_context);
> +	ret = eglMakeCurrent(compositor->egl_display, output_state->egl_surface,
> +			     output_state->egl_surface, compositor->egl_context);
>  	if (ret == EGL_FALSE) {
>  		if (errored)
>  			return;
> @@ -749,7 +770,7 @@ gles2_renderer_repaint_output(struct weston_output *output,
>  
>  	wl_signal_emit(&output->frame_signal, output);
>  
> -	ret = eglSwapBuffers(compositor->egl_display, output->egl_surface);
> +	ret = eglSwapBuffers(compositor->egl_display, output_state->egl_surface);
>  	if (ret == EGL_FALSE && !errored) {
>  		errored = 1;
>  		weston_log("Failed in eglSwapBuffers.\n");
> @@ -1157,24 +1178,167 @@ log_egl_config_info(EGLDisplay egldpy, EGLConfig eglconfig)
>  		weston_log_continue(" unknown\n");
>  }
>  
> -struct gles2_renderer {
> -	struct weston_renderer base;
> -};
> +static int
> +create_renderer(struct weston_compositor *ec)
> +{
> +	struct gles2_renderer *renderer = malloc(sizeof *renderer);
> +
> +	if (renderer == NULL)
> +		return -1;
> +
> +	renderer->base.repaint_output = gles2_renderer_repaint_output;
> +	renderer->base.flush_damage = gles2_renderer_flush_damage;
> +	renderer->base.attach = gles2_renderer_attach;
> +	renderer->base.destroy_surface = gles2_renderer_destroy_surface;
> +
> +	ec->renderer = &renderer->base;
> +
> +	return 0;
> +}
> +
> +static int
> +init_display(struct weston_compositor *ec, EGLNativeDisplayType display)
> +{
> +	EGLint major, minor;
> +
> +	if (create_renderer(ec) < 0)
> +		return -1;
> +
> +	ec->egl_display = eglGetDisplay(display);
> +	if (ec->egl_display == NULL) {
> +		weston_log("failed to create display\n");
> +		print_egl_error_state();
> +		return -1;
> +	}
> +
> +	if (!eglInitialize(ec->egl_display, &major, &minor)) {
> +		weston_log("failed to initialize display\n");
> +		print_egl_error_state();
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
> +WL_EXPORT int
> +gles2_renderer_output_state_create_and_bind(struct weston_output *output, EGLNativeWindowType window)
> +{
> +	struct gles2_output_state *state = gles2_renderer_output_state_create(output->compositor, window);
> +
> +	if (!state)
> +		return -1;
> +
> +	gles2_renderer_output_bind(output, state);
> +
> +	return 0;
> +}
> +
> +WL_EXPORT struct gles2_output_state *
> +gles2_renderer_output_state_create(struct weston_compositor *ec, EGLNativeWindowType window)
> +{
> +	struct gles2_output_state *state = calloc(1, sizeof *state);
> +
> +	if (!state)
> +		return NULL;
> +
> +	state->egl_surface =
> +		eglCreateWindowSurface(ec->egl_display,
> +				       ec->egl_config,
> +				       window, NULL);
> +
> +	if (state->egl_surface == EGL_NO_SURFACE) {
> +		weston_log("failed to create egl surface\n");
> +		free(state);
> +		return NULL;
> +	}
> +
> +	return state;
> +}
> +
> +WL_EXPORT void
> +gles2_renderer_output_state_destroy(struct weston_compositor *ec, struct gles2_output_state *state)
> +{
> +	eglDestroySurface(ec->egl_display, state->egl_surface);
> +
> +	free(state);
> +}
> +
> +WL_EXPORT void
> +gles2_renderer_output_bind(struct weston_output *output, struct gles2_output_state *state)
> +{
> +	output->renderer_state = state;
> +}
> +
> +WL_EXPORT void
> +gles2_renderer_output_unbind(struct weston_output *output)
> +{
> +	gles2_renderer_output_state_destroy(output->compositor, get_output_state(output));
> +}
>  
>  WL_EXPORT void
>  gles2_renderer_destroy(struct weston_compositor *ec)
>  {
>  	if (ec->has_bind_display)
>  		ec->unbind_display(ec->egl_display, ec->wl_display);
> +
> +	/* Work around crash in egl_dri2.c's dri2_make_current() - when does this apply? */
> +	eglMakeCurrent(ec->egl_display,
> +		       EGL_NO_SURFACE, EGL_NO_SURFACE,
> +		       EGL_NO_CONTEXT);
> +
> +	eglTerminate(ec->egl_display);
> +	eglReleaseThread();
> +}
> +
> +WL_EXPORT int
> +gles2_renderer_init(struct weston_compositor *ec, EGLNativeDisplayType display, int alpha)
> +{
> +	EGLint n;
> +
> +	const EGLint config_attribs[] = {
> +		EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
> +		EGL_RED_SIZE, 1,
> +		EGL_GREEN_SIZE, 1,
> +		EGL_BLUE_SIZE, 1,
> +		EGL_ALPHA_SIZE, alpha ? 1 : 0,
> +		EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
> +		EGL_NONE
> +	};
> +
> +	if (init_display(ec, display) < 0)
> +		return -1;
> +
> +	if (!eglChooseConfig(ec->egl_display, config_attribs,
> +			     &ec->egl_config, 1, &n) || n != 1) {
> +		weston_log("failed to choose config: %d\n", n);
> +		print_egl_error_state();
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
> +WL_EXPORT EGLDisplay
> +gles2_renderer_init_without_config(struct weston_compositor *ec, EGLNativeDisplayType display)
> +{
> +	if (init_display(ec, display) < 0)
> +		return EGL_NO_DISPLAY;
> +	else
> +		return ec->egl_display;
> +}
> +
> +void
> +gles2_renderer_select_config(struct weston_compositor *ec, EGLConfig config)
> +{
> +	ec->egl_config = config;
>  }
>  
>  WL_EXPORT int
> -gles2_renderer_init(struct weston_compositor *ec)
> +gles2_renderer_outputs_ready(struct weston_compositor *ec)
>  {
> -	struct gles2_renderer *renderer;
>  	const char *extensions;
>  	int has_egl_image_external = 0;
> -	struct weston_output *output;
> +	struct gles2_output_state *output;
>  	EGLBoolean ret;
>  
>  	static const EGLint context_attribs[] = {
> @@ -1182,10 +1346,6 @@ gles2_renderer_init(struct weston_compositor *ec)
>  		EGL_NONE
>  	};
>  
> -	renderer = malloc(sizeof *renderer);
> -	if (renderer == NULL)
> -		return -1;
> -
>  	if (!eglBindAPI(EGL_OPENGL_ES_API)) {
>  		weston_log("failed to bind EGL_OPENGL_ES_API\n");
>  		print_egl_error_state();
> @@ -1202,8 +1362,8 @@ gles2_renderer_init(struct weston_compositor *ec)
>  		return -1;
>  	}
>  
> -	output = container_of(ec->output_list.next,
> -			      struct weston_output, link);
> +	output = get_output_state(container_of(ec->output_list.next,
> +			      struct weston_output, link));
>  	ret = eglMakeCurrent(ec->egl_display, output->egl_surface,
>  			     output->egl_surface, ec->egl_context);
>  	if (ret == EGL_FALSE) {
> @@ -1289,12 +1449,6 @@ gles2_renderer_init(struct weston_compositor *ec)
>  			     vertex_shader, solid_fragment_shader) < 0)
>  		return -1;
>  
> -	renderer->base.repaint_output = gles2_renderer_repaint_output;
> -	renderer->base.flush_damage = gles2_renderer_flush_damage;
> -	renderer->base.attach = gles2_renderer_attach;
> -	renderer->base.destroy_surface = gles2_renderer_destroy_surface;
> -	ec->renderer = &renderer->base;
> -
>  	weston_log("GL ES 2 renderer features:\n");
>  	weston_log_continue(STAMP_SPACE "read-back format: %s\n",
>  			    ec->read_format == GL_BGRA_EXT ? "BGRA" : "RGBA");
> @@ -1303,5 +1457,6 @@ gles2_renderer_init(struct weston_compositor *ec)
>  	weston_log_continue(STAMP_SPACE "EGL Wayland extension: %s\n",
>  			    ec->has_bind_display ? "yes" : "no");
>  
> +
>  	return 0;
>  }
> -- 
> 1.7.12.4
> 
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list