[PATCH weston 3/3] clients: Add a client that renders transformed buffers

Kristian Høgsberg hoegsberg at gmail.com
Tue Nov 27 08:36:48 PST 2012


On Tue, Nov 27, 2012 at 05:03:44PM +0200, Ander Conselvan de Oliveira wrote:
> This new client, called transformed, renders a cross with the top part
> red and the right green, with the same transform as the output the
> surface is in.
> 
> This is based on simple-egl.

I think we need some kind of helper here...  It makes sense to keep
simple-egl and simple-shm as standalone, one-file clients, but we have
too many "simple" clients that are 1000+ lines of code.  It's hard to
maintain and it's hard to write a new one with all that boiler plate.
Can we use toytoolkit for this or should we have some kind of simple
egl client helper?  I've committed this for now, but it is getting to
be a problem.

Kristian


> ---
>  clients/Makefile.am   |    7 +-
>  clients/transformed.c |  787 +++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 793 insertions(+), 1 deletion(-)
>  create mode 100644 clients/transformed.c
> 
> diff --git a/clients/Makefile.am b/clients/Makefile.am
> index a6927d7..86fe535 100644
> --- a/clients/Makefile.am
> +++ b/clients/Makefile.am
> @@ -41,11 +41,16 @@ endif
>  
>  if BUILD_SIMPLE_EGL_CLIENTS
>  simple_egl_clients_programs =			\
> -	simple-egl
> +	simple-egl				\
> +	transformed
>  
>  simple_egl_SOURCES = simple-egl.c
>  simple_egl_CPPFLAGS = $(SIMPLE_EGL_CLIENT_CFLAGS)
>  simple_egl_LDADD = $(SIMPLE_EGL_CLIENT_LIBS) -lm
> +
> +transformed_SOURCES = transformed.c
> +transformed_CPPFLAGS = $(SIMPLE_EGL_CLIENT_CFLAGS)
> +transformed_LDADD = $(SIMPLE_EGL_CLIENT_LIBS) -lm
>  endif
>  
>  if BUILD_CLIENTS
> diff --git a/clients/transformed.c b/clients/transformed.c
> new file mode 100644
> index 0000000..9c019fb
> --- /dev/null
> +++ b/clients/transformed.c
> @@ -0,0 +1,787 @@
> +/*
> + * Copyright © 2011 Benjamin Franzke
> + * Copyright © 2012 Intel Corporation
> + *
> + * Permission to use, copy, modify, distribute, and sell this software and its
> + * documentation for any purpose is hereby granted without fee, provided that
> + * the above copyright notice appear in all copies and that both that copyright
> + * notice and this permission notice appear in supporting documentation, and
> + * that the name of the copyright holders not be used in advertising or
> + * publicity pertaining to distribution of the software without specific,
> + * written prior permission.  The copyright holders make no representations
> + * about the suitability of this software for any purpose.  It is provided "as
> + * is" without express or implied warranty.
> + *
> + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
> + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
> + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
> + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
> + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
> + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
> + * OF THIS SOFTWARE.
> + */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <stdbool.h>
> +#include <math.h>
> +#include <assert.h>
> +#include <signal.h>
> +
> +#include <linux/input.h>
> +
> +#include <wayland-client.h>
> +#include <wayland-egl.h>
> +
> +#include <GLES2/gl2.h>
> +#include <EGL/egl.h>
> +
> +struct window;
> +struct seat;
> +
> +struct display {
> +	struct wl_display *display;
> +	struct wl_registry *registry;
> +	struct wl_compositor *compositor;
> +	struct wl_shell *shell;
> +	struct wl_seat *seat;
> +	struct wl_pointer *pointer;
> +	struct wl_keyboard *keyboard;
> +	struct wl_shm *shm;
> +	struct wl_list output_list;
> +	struct {
> +		EGLDisplay dpy;
> +		EGLContext ctx;
> +		EGLConfig conf;
> +	} egl;
> +	struct window *window;
> +};
> +
> +struct output {
> +	struct wl_output *output;
> +	int transform;
> +	struct wl_list link;
> +};
> +
> +struct geometry {
> +	int width, height;
> +};
> +
> +struct window {
> +	struct display *display;
> +	struct geometry geometry, window_size;
> +	struct {
> +		GLuint fbo;
> +		GLuint color_rbo;
> +
> +		GLuint transform_uniform;
> +
> +		GLuint pos;
> +		GLuint col;
> +	} gl;
> +
> +	struct output *output;
> +	struct wl_egl_window *native;
> +	struct wl_surface *surface;
> +	struct wl_shell_surface *shell_surface;
> +	EGLSurface egl_surface;
> +	struct wl_callback *callback;
> +	int fullscreen, configured;
> +};
> +
> +static const char *vert_shader_text =
> +	"uniform mat4 transform;\n"
> +	"attribute vec4 pos;\n"
> +	"attribute vec4 color;\n"
> +	"varying vec4 v_color;\n"
> +	"void main() {\n"
> +	"  gl_Position = transform * pos;\n"
> +	"  v_color = color;\n"
> +	"}\n";
> +
> +static const char *frag_shader_text =
> +	"precision mediump float;\n"
> +	"varying vec4 v_color;\n"
> +	"void main() {\n"
> +	"  gl_FragColor = v_color;\n"
> +	"}\n";
> +
> +static int running = 1;
> +
> +static void
> +init_egl(struct display *display)
> +{
> +	static const EGLint context_attribs[] = {
> +		EGL_CONTEXT_CLIENT_VERSION, 2,
> +		EGL_NONE
> +	};
> +
> +	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
> +	};
> +
> +	EGLint major, minor, n;
> +	EGLBoolean ret;
> +
> +	display->egl.dpy = eglGetDisplay(display->display);
> +	assert(display->egl.dpy);
> +
> +	ret = eglInitialize(display->egl.dpy, &major, &minor);
> +	assert(ret == EGL_TRUE);
> +	ret = eglBindAPI(EGL_OPENGL_ES_API);
> +	assert(ret == EGL_TRUE);
> +
> +	ret = eglChooseConfig(display->egl.dpy, config_attribs,
> +			      &display->egl.conf, 1, &n);
> +	assert(ret && n == 1);
> +
> +	display->egl.ctx = eglCreateContext(display->egl.dpy,
> +					    display->egl.conf,
> +					    EGL_NO_CONTEXT, context_attribs);
> +	assert(display->egl.ctx);
> +
> +}
> +
> +static void
> +fini_egl(struct display *display)
> +{
> +	/* Required, otherwise segfault in egl_dri2.c: dri2_make_current()
> +	 * on eglReleaseThread(). */
> +	eglMakeCurrent(display->egl.dpy, EGL_NO_SURFACE, EGL_NO_SURFACE,
> +		       EGL_NO_CONTEXT);
> +
> +	eglTerminate(display->egl.dpy);
> +	eglReleaseThread();
> +}
> +
> +static GLuint
> +create_shader(struct window *window, const char *source, GLenum shader_type)
> +{
> +	GLuint shader;
> +	GLint status;
> +
> +	shader = glCreateShader(shader_type);
> +	assert(shader != 0);
> +
> +	glShaderSource(shader, 1, (const char **) &source, NULL);
> +	glCompileShader(shader);
> +
> +	glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
> +	if (!status) {
> +		char log[1000];
> +		GLsizei len;
> +		glGetShaderInfoLog(shader, 1000, &len, log);
> +		fprintf(stderr, "Error: compiling %s: %*s\n",
> +			shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment",
> +			len, log);
> +		exit(1);
> +	}
> +
> +	return shader;
> +}
> +
> +static void
> +init_gl(struct window *window)
> +{
> +	GLuint frag, vert;
> +	GLuint program;
> +	GLint status;
> +
> +	frag = create_shader(window, frag_shader_text, GL_FRAGMENT_SHADER);
> +	vert = create_shader(window, vert_shader_text, GL_VERTEX_SHADER);
> +
> +	program = glCreateProgram();
> +	glAttachShader(program, frag);
> +	glAttachShader(program, vert);
> +	glLinkProgram(program);
> +
> +	glGetProgramiv(program, GL_LINK_STATUS, &status);
> +	if (!status) {
> +		char log[1000];
> +		GLsizei len;
> +		glGetProgramInfoLog(program, 1000, &len, log);
> +		fprintf(stderr, "Error: linking:\n%*s\n", len, log);
> +		exit(1);
> +	}
> +
> +	glUseProgram(program);
> +
> +	window->gl.pos = 0;
> +	window->gl.col = 1;
> +
> +	glBindAttribLocation(program, window->gl.pos, "pos");
> +	glBindAttribLocation(program, window->gl.col, "color");
> +	glLinkProgram(program);
> +
> +	window->gl.transform_uniform =
> +		glGetUniformLocation(program, "transform");
> +}
> +
> +static void
> +handle_ping(void *data, struct wl_shell_surface *shell_surface,
> +	    uint32_t serial)
> +{
> +	wl_shell_surface_pong(shell_surface, serial);
> +}
> +
> +static void
> +handle_configure(void *data, struct wl_shell_surface *shell_surface,
> +		 uint32_t edges, int32_t width, int32_t height)
> +{
> +	struct window *window = data;
> +	int transform = WL_OUTPUT_TRANSFORM_NORMAL;
> +	int32_t tmp;
> +
> +	window->geometry.width = width;
> +	window->geometry.height = height;
> +
> +	if (!window->fullscreen)
> +		window->window_size = window->geometry;
> +
> +	if (window->output)
> +		transform = window->output->transform;
> +
> +	switch (transform) {
> +	case WL_OUTPUT_TRANSFORM_90:
> +	case WL_OUTPUT_TRANSFORM_270:
> +	case WL_OUTPUT_TRANSFORM_FLIPPED_90:
> +	case WL_OUTPUT_TRANSFORM_FLIPPED_270:
> +		tmp = width;
> +		width = height;
> +		height = tmp;
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	if (window->native)
> +		wl_egl_window_resize(window->native, width, height, 0, 0);
> +}
> +
> +static void
> +handle_popup_done(void *data, struct wl_shell_surface *shell_surface)
> +{
> +}
> +
> +static const struct wl_shell_surface_listener shell_surface_listener = {
> +	handle_ping,
> +	handle_configure,
> +	handle_popup_done
> +};
> +
> +static void
> +toggle_fullscreen(struct window *window, int fullscreen);
> +
> +static void
> +surface_enter(void *data, struct wl_surface *wl_surface,
> +	      struct wl_output *wl_output)
> +{
> +	struct window *window = data;
> +	struct output *output = NULL;
> +
> +	wl_list_for_each(output, &window->display->output_list, link) {
> +		if (output->output == wl_output)
> +			break;
> +	}
> +
> +	if (output && output->output == wl_output) {
> +		/* We use the output information only for rendering according
> +		 * to the output transform. Since we can't "please" two
> +		 * different outputs if they have a different transform, just
> +		 * do it according to the last output the surface entered. */
> +		window->output = output;
> +
> +		/* Force a redraw with the new transform */
> +		toggle_fullscreen(window, window->fullscreen);
> +	}
> +}
> +
> +static void
> +surface_leave(void *data, struct wl_surface *wl_surface,
> +	      struct wl_output *wl_output)
> +{
> +	struct window *window = data;
> +	struct output *output = NULL;
> +
> +	wl_list_for_each(output, &window->display->output_list, link) {
> +		if (output->output == wl_output)
> +			break;
> +	}
> +
> +	if (output && output->output == wl_output && output == window->output)
> +		window->output = NULL;
> +}
> +
> +static const struct wl_surface_listener surface_listener = {
> +	surface_enter,
> +	surface_leave
> +};
> +
> +static void
> +redraw(struct window *window);
> +
> +static void
> +configure_callback(void *data, struct wl_callback *callback, uint32_t  time)
> +{
> +	struct window *window = data;
> +
> +	wl_callback_destroy(callback);
> +
> +	redraw(window);
> +}
> +
> +static struct wl_callback_listener configure_callback_listener = {
> +	configure_callback,
> +};
> +
> +static void
> +toggle_fullscreen(struct window *window, int fullscreen)
> +{
> +	struct wl_callback *callback;
> +
> +	window->fullscreen = fullscreen;
> +
> +	if (fullscreen) {
> +		wl_shell_surface_set_fullscreen(window->shell_surface,
> +						WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
> +						0, NULL);
> +	} else {
> +		wl_shell_surface_set_toplevel(window->shell_surface);
> +		handle_configure(window, window->shell_surface, 0,
> +				 window->window_size.width,
> +				 window->window_size.height);
> +	}
> +
> +	callback = wl_display_sync(window->display->display);
> +	wl_callback_add_listener(callback, &configure_callback_listener,
> +				 window);
> +}
> +
> +static void
> +create_surface(struct window *window)
> +{
> +	struct display *display = window->display;
> +	EGLBoolean ret;
> +	
> +	window->surface = wl_compositor_create_surface(display->compositor);
> +	window->shell_surface = wl_shell_get_shell_surface(display->shell,
> +							   window->surface);
> +
> +	wl_surface_add_listener(window->surface, &surface_listener, window);
> +	wl_shell_surface_add_listener(window->shell_surface,
> +				      &shell_surface_listener, window);
> +
> +	window->native =
> +		wl_egl_window_create(window->surface,
> +				     window->window_size.width,
> +				     window->window_size.height);
> +	window->egl_surface =
> +		eglCreateWindowSurface(display->egl.dpy,
> +				       display->egl.conf,
> +				       window->native, NULL);
> +
> +	wl_shell_surface_set_title(window->shell_surface, "simple-egl");
> +
> +	ret = eglMakeCurrent(window->display->egl.dpy, window->egl_surface,
> +			     window->egl_surface, window->display->egl.ctx);
> +	assert(ret == EGL_TRUE);
> +
> +	toggle_fullscreen(window, window->fullscreen);
> +}
> +
> +static void
> +destroy_surface(struct window *window)
> +{
> +	wl_egl_window_destroy(window->native);
> +
> +	wl_shell_surface_destroy(window->shell_surface);
> +	wl_surface_destroy(window->surface);
> +
> +	if (window->callback)
> +		wl_callback_destroy(window->callback);
> +}
> +
> +static void
> +update_transform(struct window *window)
> +{
> +	int transform = WL_OUTPUT_TRANSFORM_NORMAL;
> +	int swap_w_h = 0;
> +	int flip;
> +
> +	GLfloat mat[4][4] = {
> +		{ 1, 0, 0, 0 },
> +		{ 0, 1, 0, 0 },
> +		{ 0, 0, 1, 0 },
> +		{ 0, 0, 0, 1 }
> +	};
> +
> +
> +	if (window->output)
> +		transform = window->output->transform;
> +
> +	switch(transform) {
> +	case WL_OUTPUT_TRANSFORM_FLIPPED:
> +	case WL_OUTPUT_TRANSFORM_FLIPPED_90:
> +	case WL_OUTPUT_TRANSFORM_FLIPPED_180:
> +	case WL_OUTPUT_TRANSFORM_FLIPPED_270:
> +		flip = -1;
> +		break;
> +	default:
> +		flip = 1;
> +		break;
> +	}
> +
> +	switch (transform) {
> +	case WL_OUTPUT_TRANSFORM_NORMAL:
> +	case WL_OUTPUT_TRANSFORM_FLIPPED:
> +		mat[0][0] = flip;
> +		mat[0][1] = 0;
> +		mat[1][0] = 0;
> +		mat[1][1] = 1;
> +		break;
> +	case WL_OUTPUT_TRANSFORM_90:
> +	case WL_OUTPUT_TRANSFORM_FLIPPED_90:
> +		mat[0][0] = 0;
> +		mat[0][1] = -flip;
> +		mat[1][0] = 1;
> +		mat[1][1] = 0;
> +		swap_w_h = 1;
> +		break;
> +	case WL_OUTPUT_TRANSFORM_180:
> +	case WL_OUTPUT_TRANSFORM_FLIPPED_180:
> +		mat[0][0] = -flip;
> +		mat[0][1] = 0;
> +		mat[1][0] = 0;
> +		mat[1][1] = -1;
> +		break;
> +	case WL_OUTPUT_TRANSFORM_270:
> +	case WL_OUTPUT_TRANSFORM_FLIPPED_270:
> +		mat[0][0] = 0;
> +		mat[0][1] = flip;
> +		mat[1][0] = -1;
> +		mat[1][1] = 0;
> +		swap_w_h = 1;
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	if (swap_w_h)
> +		glViewport(0, 0, window->geometry.height,
> +			   window->geometry.width);
> +	else
> +		glViewport(0, 0, window->geometry.width,
> +			   window->geometry.height);
> +
> +	glUniformMatrix4fv(window->gl.transform_uniform, 1, GL_FALSE,
> +			   (GLfloat *) mat);
> +	wl_surface_set_buffer_transform(window->surface, transform);
> +	printf("Rendering buffer with transform == %d\n", transform);
> +}
> +
> +static void
> +redraw(struct window *window)
> +{
> +	static const GLfloat verts[8][2] = {
> +		{  0.0,  0.0 },
> +		{  0.0,  1.0 },
> +		{  0.0,  0.0 },
> +		{  1.0,  0.0 },
> +		{  0.0,  0.0 },
> +		{ -1.0,  0.0 },
> +		{  0.0,  0.0 },
> +		{  0.0, -1.0 }
> +	};
> +	static const GLfloat colors[8][3] = {
> +		{ 1, 0, 0 },
> +		{ 1, 0, 0 },
> +		{ 0, 1, 0 },
> +		{ 0, 1, 0 },
> +		{ 1, 1, 1 },
> +		{ 1, 1, 1 },
> +		{ 1, 1, 1 },
> +		{ 1, 1, 1 }
> +	};
> +	struct wl_region *region;
> +
> +	update_transform(window);
> +
> +	glClearColor(0.0, 0.0, 0.0, 1.0);
> +	glClear(GL_COLOR_BUFFER_BIT);
> +
> +	glVertexAttribPointer(window->gl.pos, 2, GL_FLOAT, GL_FALSE, 0, verts);
> +	glVertexAttribPointer(window->gl.col, 3, GL_FLOAT, GL_FALSE, 0, colors);
> +	glEnableVertexAttribArray(window->gl.pos);
> +	glEnableVertexAttribArray(window->gl.col);
> +
> +	glDrawArrays(GL_LINES, 0, 8);
> +
> +	glDisableVertexAttribArray(window->gl.pos);
> +	glDisableVertexAttribArray(window->gl.col);
> +
> +	region = wl_compositor_create_region(window->display->compositor);
> +	wl_region_add(region, 0, 0,
> +		      window->geometry.width,
> +		      window->geometry.height);
> +	wl_surface_set_opaque_region(window->surface, region);
> +	wl_region_destroy(region);
> +
> +	eglSwapBuffers(window->display->egl.dpy, window->egl_surface);
> +}
> +
> +static void
> +pointer_handle_enter(void *data, struct wl_pointer *pointer,
> +		     uint32_t serial, struct wl_surface *surface,
> +		     wl_fixed_t sx, wl_fixed_t sy)
> +{
> +	wl_pointer_set_cursor(pointer, serial, NULL, 0, 0);
> +}
> +
> +static void
> +pointer_handle_leave(void *data, struct wl_pointer *pointer,
> +		     uint32_t serial, struct wl_surface *surface)
> +{
> +}
> +
> +static void
> +pointer_handle_motion(void *data, struct wl_pointer *pointer,
> +		      uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
> +{
> +}
> +
> +static void
> +pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
> +		      uint32_t serial, uint32_t time, uint32_t button,
> +		      uint32_t state)
> +{
> +}
> +
> +static void
> +pointer_handle_axis(void *data, struct wl_pointer *wl_pointer,
> +		    uint32_t time, uint32_t axis, wl_fixed_t value)
> +{
> +}
> +
> +static const struct wl_pointer_listener pointer_listener = {
> +	pointer_handle_enter,
> +	pointer_handle_leave,
> +	pointer_handle_motion,
> +	pointer_handle_button,
> +	pointer_handle_axis,
> +};
> +
> +static void
> +keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
> +		       uint32_t format, int fd, uint32_t size)
> +{
> +}
> +
> +static void
> +keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
> +		      uint32_t serial, struct wl_surface *surface,
> +		      struct wl_array *keys)
> +{
> +}
> +
> +static void
> +keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
> +		      uint32_t serial, struct wl_surface *surface)
> +{
> +}
> +
> +static void
> +keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
> +		    uint32_t serial, uint32_t time, uint32_t key,
> +		    uint32_t state)
> +{
> +	struct display *d = data;
> +
> +	if (key == KEY_F11 && state)
> +		toggle_fullscreen(d->window, d->window->fullscreen ^ 1);
> +	else if (key == KEY_ESC && state)
> +		running = 0;
> +}
> +
> +static void
> +keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
> +			  uint32_t serial, uint32_t mods_depressed,
> +			  uint32_t mods_latched, uint32_t mods_locked,
> +			  uint32_t group)
> +{
> +}
> +
> +static const struct wl_keyboard_listener keyboard_listener = {
> +	keyboard_handle_keymap,
> +	keyboard_handle_enter,
> +	keyboard_handle_leave,
> +	keyboard_handle_key,
> +	keyboard_handle_modifiers,
> +};
> +
> +static void
> +seat_handle_capabilities(void *data, struct wl_seat *seat,
> +			 enum wl_seat_capability caps)
> +{
> +	struct display *d = data;
> +
> +	if ((caps & WL_SEAT_CAPABILITY_POINTER) && !d->pointer) {
> +		d->pointer = wl_seat_get_pointer(seat);
> +		wl_pointer_add_listener(d->pointer, &pointer_listener, d);
> +	} else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && d->pointer) {
> +		wl_pointer_destroy(d->pointer);
> +		d->pointer = NULL;
> +	}
> +
> +	if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !d->keyboard) {
> +		d->keyboard = wl_seat_get_keyboard(seat);
> +		wl_keyboard_add_listener(d->keyboard, &keyboard_listener, d);
> +	} else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && d->keyboard) {
> +		wl_keyboard_destroy(d->keyboard);
> +		d->keyboard = NULL;
> +	}
> +}
> +
> +static const struct wl_seat_listener seat_listener = {
> +	seat_handle_capabilities,
> +};
> +
> +static void
> +output_handle_geometry(void *data, struct wl_output *wl_output, int x, int y,
> +		       int physical_width, int physical_height, int subpixel,
> +		       const char *make, const char *model, int transform)
> +{
> +	struct output *output = data;
> +
> +	output->transform = transform;
> +}
> +
> +static void
> +output_handle_mode(void *data, struct wl_output *output, uint32_t flags,
> +		   int width, int height, int refresh)
> +{
> +}
> +
> +static const struct wl_output_listener output_listener = {
> +	output_handle_geometry,
> +	output_handle_mode
> +};
> +
> +static void
> +registry_handle_global(void *data, struct wl_registry *registry,
> +		       uint32_t name, const char *interface, uint32_t version)
> +{
> +	struct display *d = data;
> +
> +	if (strcmp(interface, "wl_compositor") == 0) {
> +		d->compositor =
> +			wl_registry_bind(registry, name,
> +					 &wl_compositor_interface, 1);
> +	} else if (strcmp(interface, "wl_shell") == 0) {
> +		d->shell = wl_registry_bind(registry, name,
> +					    &wl_shell_interface, 1);
> +	} else if (strcmp(interface, "wl_seat") == 0) {
> +		d->seat = wl_registry_bind(registry, name,
> +					   &wl_seat_interface, 1);
> +		wl_seat_add_listener(d->seat, &seat_listener, d);
> +	} else if (strcmp(interface, "wl_output") == 0) {
> +		struct output *output = malloc(sizeof *output);
> +
> +		if (!output)
> +			return;
> +
> +		output->output = wl_registry_bind(registry, name,
> +						  &wl_output_interface, 1);
> +		wl_output_add_listener(output->output, &output_listener,
> +				       output);
> +		wl_list_insert(&d->output_list, &output->link);
> +	}
> +}
> +
> +static const struct wl_registry_listener registry_listener = {
> +	registry_handle_global
> +};
> +
> +static void
> +signal_int(int signum)
> +{
> +	running = 0;
> +}
> +
> +static void
> +usage(int error_code)
> +{
> +	fprintf(stderr, "Usage: simple-egl [OPTIONS]\n\n"
> +		"  -f\tRun in fullscreen mode\n"
> +		"  -h\tThis help text\n\n");
> +
> +	exit(error_code);
> +}
> +
> +int
> +main(int argc, char **argv)
> +{
> +	struct sigaction sigint;
> +	struct display display = { 0 };
> +	struct window  window  = { 0 };
> +	int i, ret = 0;
> +
> +	window.display = &display;
> +	display.window = &window;
> +	window.window_size.width  = 500;
> +	window.window_size.height = 250;
> +
> +	wl_list_init(&display.output_list);
> +
> +	for (i = 1; i < argc; i++) {
> +		if (strcmp("-f", argv[i]) == 0)
> +			window.fullscreen = 1;
> +		else if (strcmp("-h", argv[i]) == 0)
> +			usage(EXIT_SUCCESS);
> +		else
> +			usage(EXIT_FAILURE);
> +	}
> +
> +	display.display = wl_display_connect(NULL);
> +	assert(display.display);
> +
> +	display.registry = wl_display_get_registry(display.display);
> +	wl_registry_add_listener(display.registry,
> +				 &registry_listener, &display);
> +
> +	wl_display_dispatch(display.display);
> +
> +	init_egl(&display);
> +	create_surface(&window);
> +	init_gl(&window);
> +
> +	sigint.sa_handler = signal_int;
> +	sigemptyset(&sigint.sa_mask);
> +	sigint.sa_flags = SA_RESETHAND;
> +	sigaction(SIGINT, &sigint, NULL);
> +
> +	while (running && ret != -1)
> +		ret = wl_display_dispatch(display.display);
> +
> +	fprintf(stderr, "simple-egl exiting\n");
> +
> +	destroy_surface(&window);
> +	fini_egl(&display);
> +
> +	if (display.shell)
> +		wl_shell_destroy(display.shell);
> +
> +	if (display.compositor)
> +		wl_compositor_destroy(display.compositor);
> +
> +	wl_display_flush(display.display);
> +	wl_display_disconnect(display.display);
> +
> +	return 0;
> +}
> -- 
> 1.7.10.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