[weston PATCH v6 1/7] compositor, shell: add fullscreen implementation shell part

Kristian Hoegsberg hoegsberg at gmail.com
Tue Feb 21 14:33:57 PST 2012


On Fri, Feb 17, 2012 at 03:26:10PM +0800, juan.j.zhao at linux.intel.com wrote:
> From: Juan Zhao <juan.j.zhao at linux.intel.com>
> 
> ---
>  clients/window.c     |    3 +-
>  src/compositor-drm.c |   10 ++++-
>  src/compositor.c     |    5 ++-
>  src/compositor.h     |   11 +++++-
>  src/shell.c          |   97 +++++++++++++++++++++++++++++++++++++++++---------
>  5 files changed, 103 insertions(+), 23 deletions(-)
> 
> diff --git a/clients/window.c b/clients/window.c
> index ae5a791..1e7e89f 100644
> --- a/clients/window.c
> +++ b/clients/window.c
> @@ -786,9 +786,10 @@ window_set_type(struct window *window)
>  	if (!window->shell_surface)
>  		return;
>  
> +#define FRAMERATE 0
>  	switch (window->type) {
>  	case TYPE_FULLSCREEN:
> -		wl_shell_surface_set_fullscreen(window->shell_surface);
> +		wl_shell_surface_set_fullscreen(window->shell_surface, 0, FRAMERATE, 0);

I changed the way this works in master (this part no longer
necessary), but one of these arguments is a pointer and should be
NULL, the other is a enum defined in the protocol
(WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT).

>  		break;
>  	case TYPE_TOPLEVEL:
>  		wl_shell_surface_set_toplevel(window->shell_surface);
> diff --git a/src/compositor-drm.c b/src/compositor-drm.c
> index de6feb4..623799f 100644
> --- a/src/compositor-drm.c
> +++ b/src/compositor-drm.c
> @@ -161,8 +161,14 @@ drm_output_repaint(struct weston_output *output_base)
>  
>  	drm_output_prepare_scanout_surface(output);
>  
> -	wl_list_for_each_reverse(surface, &compositor->base.surface_list, link)
> -		weston_surface_draw(surface, &output->base);
> +	wl_list_for_each_reverse(surface, &compositor->base.surface_list, link){
> +		if(!surface->fs_support.fullscreen_output) {
> +			weston_surface_draw(surface, &output->base);
> +		} else {
> +			glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
> +			weston_surface_draw(surface, &output->base);
> +		}
> +	}

We talked about this in IRC, but instead of doing the glClear() here,
we need to create a solid color black surface and insert below the
fullscreen surface.  It's much more efficient, and lets us keep the
repaint loop simple and free of special cases.  And scanout hardware
could potentially recognize the fullscreen black surface and use a
solid color plane that some hw has instead, similar to how we do the
sprite support.

>  
>  	glFlush();
>  
> diff --git a/src/compositor.c b/src/compositor.c
> index ab90ded..8e2e7e9 100644
> --- a/src/compositor.c
> +++ b/src/compositor.c
> @@ -194,7 +194,8 @@ weston_surface_create(struct weston_compositor *compositor)
>  	surface->image = EGL_NO_IMAGE_KHR;
>  	surface->alpha = 255;
>  
> -	surface->fullscreen_output = NULL;
> +	surface->fs_support.fullscreen_output = NULL;
> +	surface->fs_support.fs_method = WESTON_SURFACE_FULLSCREEN_DEFAULT;
>  	surface->buffer = NULL;
>  	surface->output = NULL;
>  
> @@ -214,7 +215,7 @@ weston_surface_create(struct weston_compositor *compositor)
>  	return surface;
>  }
>  
> -static void
> +WL_EXPORT void
>  weston_surface_set_color(struct weston_surface *surface,
>  		 GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
>  {
> diff --git a/src/compositor.h b/src/compositor.h
> index 966d3f4..82d7d51 100644
> --- a/src/compositor.h
> +++ b/src/compositor.h
> @@ -35,6 +35,11 @@
>  
>  #include "matrix.h"
>  
> +#define WESTON_SURFACE_FULLSCREEN_DEFAULT 0
> +#define WESTON_SURFACE_FULLSCREEN_SCALE 1
> +#define WESTON_SURFACE_FULLSCREEN_DRIVER 2
> +#define WESTON_SURFACE_FULLSCREEN_FILL 3
> +

We already have #defines for these in the generated protocol header.

>  struct weston_transform {
>  	struct weston_matrix matrix;
>  	struct wl_list link;
> @@ -282,6 +287,11 @@ struct weston_surface {
>  
>  		struct weston_transform position; /* matrix from x, y */
>  	} transform;
> +	struct {
> +		uint32_t framerate;
> +		uint32_t fs_method;
> +		struct weston_output *fullscreen_output;
> +	} fs_support;

Let's put all this in struct shell_surface instead.  We don't need it
in weston_surface if we use the solid color surface described above.
Put the struct in shell_surface and just call it 'fullscreen', with
'framerate', 'method' and 'output' fields.

>  	/*
>  	 * Which output to vsync this surface to.
> @@ -290,7 +300,6 @@ struct weston_surface {
>  	 */
>  	struct weston_output *output;
>  
> -	struct weston_output *fullscreen_output;
>  	struct wl_list frame_callback_list;
>  
>  	EGLImageKHR image;
> diff --git a/src/shell.c b/src/shell.c
> index 66c4f01..b77cef3 100644
> --- a/src/shell.c
> +++ b/src/shell.c
> @@ -349,7 +349,7 @@ reset_shell_surface_type(struct shell_surface *surface)
>  		weston_surface_set_position(surface->surface,
>  					    surface->saved_x,
>  					    surface->saved_y);
> -		surface->surface->fullscreen_output = NULL;
> +		surface->surface->fs_support.fullscreen_output = NULL;

This now just becomes surface->fullscreen.output = NULL;

>  		break;
>  	case SHELL_SURFACE_PANEL:
>  	case SHELL_SURFACE_BACKGROUND:
> @@ -417,28 +417,59 @@ get_default_output(struct weston_compositor *compositor)
>  
>  static void
>  shell_surface_set_fullscreen(struct wl_client *client,
> -			     struct wl_resource *resource)
> +			     struct wl_resource *resource,
> +			     uint32_t method,
> +			     uint32_t framerate,
> +			     struct wl_resource *output_resource)
>  
>  {
>  	struct shell_surface *shsurf = resource->data;
>  	struct weston_surface *es = shsurf->surface;
> -	struct weston_output *output;
> +
> +	if (output_resource)
> +		shsurf->output = output_resource->data;
> +	else
> +		shsurf->output = get_default_output(es->compositor);
>  
>  	if (reset_shell_surface_type(shsurf))
>  		return;
>  
> -	/* FIXME: Fullscreen on first output */
> -	/* FIXME: Handle output going away */
> -	output = get_default_output(es->compositor);
> -	es->output = output;
> -
>  	shsurf->saved_x = es->geometry.x;
>  	shsurf->saved_y = es->geometry.y;
>  	weston_surface_set_position(es,
> -		(output->current->width - es->geometry.width) / 2,
> -		(output->current->height - es->geometry.height) / 2);
> -	es->fullscreen_output = output;
> +		(shsurf->output->current->width - es->geometry.width) / 2,
> +		(shsurf->output->current->height - es->geometry.height) / 2);

I changed this when I applied the initial fullscreen support too.  We
don't change the surface position (or anything about the surface) when
we get the set_fullscreen request.  It all happens in map or
configure, when the client posts the new buffer in response to the
configure event we send out.

> +	es->fs_support.fullscreen_output = shsurf->output;
> +	es->fs_support.framerate = framerate;
> +
> +	wl_resource_post_event( &shsurf->resource,
> +				WL_SHELL_SURFACE_CONFIGURE,
> +				weston_compositor_get_time(), 0,
> +				shsurf->output->current->width,
> +				shsurf->output->current->height);
>  	shsurf->type = SHELL_SURFACE_FULLSCREEN;
> +
> +	switch(method){
> +		case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT:

Minor whitespace mismatch here: need space after 'switch' and, 'case'
aligns with 'switch'

> +			es->fs_support.fs_method = WESTON_SURFACE_FULLSCREEN_DEFAULT;
> +			break;
> +		case WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE:
> +			es->fs_support.fs_method = WESTON_SURFACE_FULLSCREEN_SCALE;
> +			break;
> +		case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER:
> +			es->fs_support.fs_method =
> +					WESTON_SURFACE_FULLSCREEN_DRIVER;
> +			break;
> +		case WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL:
> +			es->fs_support.fs_method = WESTON_SURFACE_FULLSCREEN_FILL;
> +			break;

... but can we just do shsurf->fullscreen.method = method; instead.

> +		default :
> +			fprintf(stderr,
> +				"unknown parameter for fullscreen support, \
> +				 fall back to default\n");
> +			es->fs_support.fs_method = WESTON_SURFACE_FULLSCREEN_DEFAULT;
> +			break;
> +	}
>  }

We need to send an error here, something like 

	wl_resource_post_error(&surface->resource,
			       WL_DISPLAY_ERROR_INVALID_METHOD,
			       "invalid fullscreen method");

will do for now, but we do need shell error codes eventually.

>  
>  static void
> @@ -1266,6 +1297,35 @@ center_on_output(struct weston_surface *surface, struct weston_output *output)
>  	weston_surface_set_position(surface, output->x + x, output->y + y);
>  }
>  
> +static int
> +weston_surface_set_fullscreen(struct weston_surface *surface)
> +{
> +	struct weston_output *output = surface->fs_support.fullscreen_output;
> +	center_on_output(surface, output);

Missing a blank line between variable declarations and code.

> +
> +	if(output->current->width == surface->geometry.width &&
> +	   output->current->height == surface->geometry.height)
> +	        return 0;
> +
> +	switch(surface->fs_support.fs_method) {
> +	case WESTON_SURFACE_FULLSCREEN_DEFAULT:
> +		weston_surface_damage(surface);
> +		break;
> +	case WESTON_SURFACE_FULLSCREEN_SCALE:
> +		weston_surface_damage(surface);
> +		break;
> +	case WESTON_SURFACE_FULLSCREEN_DRIVER:
> +		break;
> +	case WESTON_SURFACE_FULLSCREEN_FILL:
> +		weston_surface_damage(surface);
> +		break;
> +	default:
> +		break;
> +	}

We don't need to damage at all, center_on_output calls
weston_surface_set_position, which takes care of it all.  So this
function and the changes below shouldn't be necessary.

> +	return 0;
> +}
> +
>  static void
>  map(struct weston_shell *base,
>      struct weston_surface *surface, int32_t width, int32_t height)
> @@ -1300,12 +1360,12 @@ map(struct weston_shell *base,
>  					    10 + random() % 400);
>  		break;
>  	case SHELL_SURFACE_SCREENSAVER:
> -	case SHELL_SURFACE_FULLSCREEN:
> -		center_on_output(surface, surface->fullscreen_output);
> -		break;
>  	case SHELL_SURFACE_LOCK:
>  		center_on_output(surface, get_default_output(compositor));
>  		break;
> +	case SHELL_SURFACE_FULLSCREEN:
> +		weston_surface_set_fullscreen(surface);
> +		break;

(these changes)

>  	case SHELL_SURFACE_POPUP:
>  		shell_map_popup(shsurf, shsurf->popup.time);
>  		break;
> @@ -1357,6 +1417,8 @@ map(struct weston_shell *base,
>  	if (do_configure) {
>  		weston_surface_assign_output(surface);
>  		weston_compositor_repick(compositor);
> +		if (surface_type == SHELL_SURFACE_FULLSCREEN)
> +			surface->output = shsurf->output;

We shouldn't need this, weston_surface_assign_output picks the right
output.

>  	}
>  
>  	switch (surface_type) {
> @@ -1399,7 +1461,7 @@ configure(struct weston_shell *base, struct weston_surface *surface,
>  		do_configure = !do_configure;
>  		/* fall through */
>  	case SHELL_SURFACE_FULLSCREEN:
> -		center_on_output(surface, surface->fullscreen_output);
> +		weston_surface_set_fullscreen(surface);
>  		break;
>  	default:
>  		break;
> @@ -1410,7 +1472,8 @@ configure(struct weston_shell *base, struct weston_surface *surface,
>  		weston_surface_configure(surface, x, y, width, height);
>  		weston_surface_assign_output(surface);
>  
> -		if (surface_type == SHELL_SURFACE_SCREENSAVER)
> +		if (surface_type == SHELL_SURFACE_SCREENSAVER ||
> +		    surface_type == SHELL_SURFACE_FULLSCREEN)
>  			surface->output = shsurf->output;
>  	}
>  }
> @@ -1518,7 +1581,7 @@ screensaver_set_surface(struct wl_client *client,
>  
>  	surface->type = SHELL_SURFACE_SCREENSAVER;
>  
> -	surface->surface->fullscreen_output = output;
> +	surface->surface->fs_support.fullscreen_output = output;
>  	surface->output = output;
>  	wl_list_insert(shell->screensaver.surfaces.prev, &surface->link);
>  }
> -- 
> 1.7.5.4
> 


More information about the wayland-devel mailing list