blob: f547c624ae7dd05eb33d8dc4eb1d59e2096a7195 [file] [log] [blame]
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001/*
2 * Copyright © 2010 Benjamin Franzke
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19#ifdef HAVE_CONFIG_H
20#include <config.h>
21#endif
22
23#include <stddef.h>
24#define _GNU_SOURCE
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <fcntl.h>
29#include <unistd.h>
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010030
Benjamin Franzkebe014562011-02-18 17:04:24 +010031#include <wayland-client.h>
32#include <wayland-egl.h>
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010033
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010034#include <GLES2/gl2.h>
35#include <GLES2/gl2ext.h>
36#include <EGL/egl.h>
37#include <EGL/eglext.h>
38
39#include "compositor.h"
40
41struct wayland_compositor {
42 struct wlsc_compositor base;
43
44 struct {
45 struct wl_display *display;
46 struct wl_compositor *compositor;
47 struct wl_shell *shell;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010048 struct wl_output *output;
Kristian Høgsberg7c476672011-06-18 06:22:05 -040049 struct wl_visual *visual;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010050
51 struct {
52 int32_t x, y, width, height;
53 } screen_allocation;
54
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010055 struct wl_event_source *wl_source;
56 uint32_t event_mask;
57 } parent;
58
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010059 struct wl_list input_list;
60};
61
62struct wayland_output {
63 struct wlsc_output base;
64
65 struct {
66 struct wl_surface *surface;
Benjamin Franzkebe014562011-02-18 17:04:24 +010067 struct wl_egl_window *egl_window;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010068 } parent;
Benjamin Franzkebe014562011-02-18 17:04:24 +010069 EGLSurface egl_surface;
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -040070 struct wlsc_mode mode;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010071};
72
73struct wayland_input {
74 struct wayland_compositor *compositor;
75 struct wl_input_device *input_device;
76 struct wl_list link;
77};
78
79static int
80wayland_input_create(struct wayland_compositor *c)
81{
82 struct wlsc_input_device *input;
83
84 input = malloc(sizeof *input);
85 if (input == NULL)
86 return -1;
87
88 memset(input, 0, sizeof *input);
89 wlsc_input_device_init(input, &c->base);
90
Kristian Høgsberg9c3e8d72010-12-08 09:48:52 -050091 c->base.input_device = &input->input_device;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010092
93 return 0;
94}
95
96static int
97wayland_compositor_init_egl(struct wayland_compositor *c)
98{
99 EGLint major, minor;
Benjamin Franzkebe014562011-02-18 17:04:24 +0100100 EGLint n;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100101 const char *extensions;
Benjamin Franzkebe014562011-02-18 17:04:24 +0100102 EGLint config_attribs[] = {
103 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
104 EGL_RED_SIZE, 1,
105 EGL_GREEN_SIZE, 1,
106 EGL_BLUE_SIZE, 1,
107 EGL_DEPTH_SIZE, 1,
Kristian Høgsbergd28ab362011-03-02 11:36:30 -0500108 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
Benjamin Franzkebe014562011-02-18 17:04:24 +0100109 EGL_NONE
110 };
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100111 static const EGLint context_attribs[] = {
112 EGL_CONTEXT_CLIENT_VERSION, 2,
113 EGL_NONE
114 };
115
Egbert Eiche7b8d902011-05-10 20:00:19 +0000116 setenv("EGL_PLATFORM", "wayland", 1);
Kristian Høgsberg91342c62011-04-14 14:44:58 -0400117 c->base.display = eglGetDisplay(c->parent.display);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100118 if (c->base.display == NULL) {
119 fprintf(stderr, "failed to create display\n");
120 return -1;
121 }
122
123 if (!eglInitialize(c->base.display, &major, &minor)) {
124 fprintf(stderr, "failed to initialize display\n");
125 return -1;
126 }
127
128 extensions = eglQueryString(c->base.display, EGL_EXTENSIONS);
129 if (!strstr(extensions, "EGL_KHR_surfaceless_opengl")) {
130 fprintf(stderr, "EGL_KHR_surfaceless_opengl not available\n");
131 return -1;
132 }
133
134 if (!eglBindAPI(EGL_OPENGL_ES_API)) {
135 fprintf(stderr, "failed to bind EGL_OPENGL_ES_API\n");
136 return -1;
137 }
Benjamin Franzkebe014562011-02-18 17:04:24 +0100138 if (!eglChooseConfig(c->base.display, config_attribs,
139 &c->base.config, 1, &n) || n == 0) {
140 fprintf(stderr, "failed to choose config: %d\n", n);
141 return -1;
142 }
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100143
Benjamin Franzkebe014562011-02-18 17:04:24 +0100144 c->base.context = eglCreateContext(c->base.display, c->base.config,
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100145 EGL_NO_CONTEXT, context_attribs);
146 if (c->base.context == NULL) {
147 fprintf(stderr, "failed to create context\n");
148 return -1;
149 }
150
151 if (!eglMakeCurrent(c->base.display, EGL_NO_SURFACE,
152 EGL_NO_SURFACE, c->base.context)) {
153 fprintf(stderr, "failed to make context current\n");
154 return -1;
155 }
156
157 return 0;
158}
159
160static void
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100161frame_callback(struct wl_surface *surface, void *data, uint32_t time)
Kristian Høgsberg3ada7ec2010-12-01 09:42:10 -0500162{
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100163 struct wlsc_output *output = data;
Kristian Høgsberg3ada7ec2010-12-01 09:42:10 -0500164
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100165 wlsc_output_finish_frame(output, time);
Kristian Høgsberg3ada7ec2010-12-01 09:42:10 -0500166}
167
Benjamin Franzkeeefc36c2011-03-11 16:39:20 +0100168static int
169wayland_output_prepare_render(struct wlsc_output *output_base)
170{
171 struct wayland_output *output = (struct wayland_output *) output_base;
172 struct wlsc_compositor *ec = output->base.compositor;
173
174 if (!eglMakeCurrent(ec->display, output->egl_surface,
175 output->egl_surface, ec->context)) {
176 fprintf(stderr, "failed to make current\n");
177 return -1;
178 }
179
180 return 0;
181}
182
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100183static int
184wayland_output_present(struct wlsc_output *output_base)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100185{
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100186 struct wayland_output *output = (struct wayland_output *) output_base;
187 struct wayland_compositor *c =
188 (struct wayland_compositor *) output->base.compositor;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100189
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100190 if (wayland_output_prepare_render(&output->base))
191 return -1;
Benjamin Franzkeeefc36c2011-03-11 16:39:20 +0100192
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100193 eglSwapBuffers(c->base.display, output->egl_surface);
194 wl_display_frame_callback(c->parent.display,
195 output->parent.surface,
196 frame_callback, &output->base);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100197
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100198 return 0;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100199}
200
201static int
Benjamin Franzke66aa2352011-04-20 17:06:13 +0200202wayland_output_prepare_scanout_surface(struct wlsc_output *output_base,
203 struct wlsc_surface *es)
Benjamin Franzke1178a3c2011-04-10 16:49:52 +0200204{
Benjamin Franzke66aa2352011-04-20 17:06:13 +0200205 return -1;
Benjamin Franzke1178a3c2011-04-10 16:49:52 +0200206}
207
208static int
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200209wayland_output_set_cursor(struct wlsc_output *output_base,
Kristian Høgsberge4c40a42011-05-06 14:04:21 -0400210 struct wlsc_input_device *input)
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200211{
212 return -1;
213}
214
215static int
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100216wayland_compositor_create_output(struct wayland_compositor *c,
217 int width, int height)
218{
219 struct wayland_output *output;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100220
221 output = malloc(sizeof *output);
222 if (output == NULL)
223 return -1;
224 memset(output, 0, sizeof *output);
225
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400226 output->mode.flags =
227 WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
228 output->mode.width = width;
229 output->mode.height = height;
230 output->mode.refresh = 60;
231 wl_list_init(&output->base.mode_list);
232 wl_list_insert(&output->base.mode_list, &output->mode.link);
233
234 output->base.current = &output->mode;
Benjamin Franzkebe014562011-02-18 17:04:24 +0100235 wlsc_output_init(&output->base, &c->base, 0, 0, width, height,
236 WL_OUTPUT_FLIPPED);
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400237
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100238 output->parent.surface =
239 wl_compositor_create_surface(c->parent.compositor);
240 wl_surface_set_user_data(output->parent.surface, output);
241
Benjamin Franzkebe014562011-02-18 17:04:24 +0100242 output->parent.egl_window =
Kristian Høgsberg91342c62011-04-14 14:44:58 -0400243 wl_egl_window_create(output->parent.surface,
Kristian Høgsberg7c476672011-06-18 06:22:05 -0400244 width, height, c->parent.visual);
Benjamin Franzkebe014562011-02-18 17:04:24 +0100245 if (!output->parent.egl_window) {
246 fprintf(stderr, "failure to create wl_egl_window\n");
247 goto cleanup_output;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100248 }
249
Benjamin Franzkebe014562011-02-18 17:04:24 +0100250 output->egl_surface =
251 eglCreateWindowSurface(c->base.display, c->base.config,
252 output->parent.egl_window, NULL);
253 if (!output->egl_surface) {
254 fprintf(stderr, "failed to create window surface\n");
255 goto cleanup_window;
256 }
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100257
Benjamin Franzkebe014562011-02-18 17:04:24 +0100258 if (!eglMakeCurrent(c->base.display, output->egl_surface,
259 output->egl_surface, c->base.context)) {
260 fprintf(stderr, "failed to make surface current\n");
261 goto cleanup_surface;
262 return -1;
263 }
264
Kristian Høgsberg7c476672011-06-18 06:22:05 -0400265 wl_shell_set_toplevel(c->parent.shell, output->parent.surface);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100266
267 glClearColor(0, 0, 0, 0.5);
268
Benjamin Franzkeeefc36c2011-03-11 16:39:20 +0100269 output->base.prepare_render = wayland_output_prepare_render;
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100270 output->base.present = wayland_output_present;
Benjamin Franzke66aa2352011-04-20 17:06:13 +0200271 output->base.prepare_scanout_surface =
272 wayland_output_prepare_scanout_surface;
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200273 output->base.set_hardware_cursor = wayland_output_set_cursor;
Benjamin Franzkeeefc36c2011-03-11 16:39:20 +0100274
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100275 wl_list_insert(c->base.output_list.prev, &output->base.link);
276
277 return 0;
Benjamin Franzkebe014562011-02-18 17:04:24 +0100278
279cleanup_surface:
280 eglDestroySurface(c->base.display, output->egl_surface);
281cleanup_window:
282 wl_egl_window_destroy(output->parent.egl_window);
283cleanup_output:
284 /* FIXME: cleanup wlsc_output */
285 free(output);
286
287 return -1;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100288}
289
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100290/* Events received from the wayland-server this compositor is client of: */
291
292/* parent output interface */
293static void
294display_handle_geometry(void *data,
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400295 struct wl_output *wl_output,
296 int x,
297 int y,
298 int physical_width,
299 int physical_height,
300 int subpixel,
301 const char *make,
302 const char *model)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100303{
304 struct wayland_compositor *c = data;
305
Kristian Høgsbergf8fc08f2010-12-01 20:10:10 -0500306 c->parent.screen_allocation.x = x;
307 c->parent.screen_allocation.y = y;
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400308}
309
310static void
311display_handle_mode(void *data,
312 struct wl_output *wl_output,
313 uint32_t flags,
314 int width,
315 int height,
316 int refresh)
317{
318 struct wayland_compositor *c = data;
319
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100320 c->parent.screen_allocation.width = width;
321 c->parent.screen_allocation.height = height;
322}
323
324static const struct wl_output_listener output_listener = {
325 display_handle_geometry,
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400326 display_handle_mode
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100327};
328
329/* parent shell interface */
330static void
331handle_configure(void *data, struct wl_shell *shell,
332 uint32_t time, uint32_t edges,
Kristian Høgsbergcbe6f042010-12-17 09:54:45 -0500333 struct wl_surface *surface, int32_t width, int32_t height)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100334{
335#if 0
336 struct output *output = wl_surface_get_user_data(surface);
337
338 /* FIXME: add resize? */
339#endif
340}
341
342static const struct wl_shell_listener shell_listener = {
343 handle_configure,
344};
345
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100346/* parent input interface */
347static void
348input_handle_motion(void *data, struct wl_input_device *input_device,
349 uint32_t time,
350 int32_t x, int32_t y, int32_t sx, int32_t sy)
351{
352 struct wayland_input *input = data;
353 struct wayland_compositor *c = input->compositor;
354
355 notify_motion(c->base.input_device, time, sx, sy);
356}
357
358static void
359input_handle_button(void *data,
360 struct wl_input_device *input_device,
361 uint32_t time, uint32_t button, uint32_t state)
362{
363 struct wayland_input *input = data;
364 struct wayland_compositor *c = input->compositor;
365
366 notify_button(c->base.input_device, time, button, state);
367}
368
369static void
370input_handle_key(void *data, struct wl_input_device *input_device,
371 uint32_t time, uint32_t key, uint32_t state)
372{
373 struct wayland_input *input = data;
374 struct wayland_compositor *c = input->compositor;
375
376 notify_key(c->base.input_device, time, key, state);
377}
378
379static void
380input_handle_pointer_focus(void *data,
381 struct wl_input_device *input_device,
382 uint32_t time, struct wl_surface *surface,
383 int32_t x, int32_t y, int32_t sx, int32_t sy)
384{
385 struct wayland_input *input = data;
Kristian Høgsbergaf82bea2011-01-27 20:18:17 -0500386 struct wayland_output *output;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100387 struct wayland_compositor *c = input->compositor;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100388
389 if (surface) {
Kristian Høgsberg93331ff2011-01-26 20:35:07 -0500390 output = wl_surface_get_user_data(surface);
391 notify_pointer_focus(c->base.input_device,
392 time, &output->base, sx, sy);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100393 } else {
Kristian Høgsberg93331ff2011-01-26 20:35:07 -0500394 notify_pointer_focus(c->base.input_device, time, NULL, 0, 0);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100395 }
396}
397
398static void
399input_handle_keyboard_focus(void *data,
400 struct wl_input_device *input_device,
401 uint32_t time,
402 struct wl_surface *surface,
403 struct wl_array *keys)
404{
Kristian Høgsbergaf82bea2011-01-27 20:18:17 -0500405 struct wayland_input *input = data;
406 struct wayland_compositor *c = input->compositor;
407 struct wayland_output *output;
408
409 if (surface) {
410 output = wl_surface_get_user_data(surface);
411 notify_keyboard_focus(c->base.input_device,
412 time, &output->base, keys);
413 } else {
414 notify_keyboard_focus(c->base.input_device, time, NULL, NULL);
415 }
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100416}
417
418static const struct wl_input_device_listener input_device_listener = {
419 input_handle_motion,
420 input_handle_button,
421 input_handle_key,
422 input_handle_pointer_focus,
423 input_handle_keyboard_focus,
424};
425
426static void
427display_add_input(struct wayland_compositor *c, uint32_t id)
428{
429 struct wayland_input *input;
430
431 input = malloc(sizeof *input);
432 if (input == NULL)
433 return;
434
435 memset(input, 0, sizeof *input);
436
437 input->compositor = c;
Kristian Høgsberg91342c62011-04-14 14:44:58 -0400438 input->input_device = wl_input_device_create(c->parent.display, id, 1);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100439 wl_list_insert(c->input_list.prev, &input->link);
440
441 wl_input_device_add_listener(input->input_device,
442 &input_device_listener, input);
443 wl_input_device_set_user_data(input->input_device, input);
444}
445
446static void
Kristian Høgsberg7c476672011-06-18 06:22:05 -0400447compositor_handle_visual(void *data,
448 struct wl_compositor *compositor,
449 uint32_t id, uint32_t token)
450{
451 struct wayland_compositor *c = data;
452
453 switch (token) {
454 case WL_COMPOSITOR_VISUAL_ARGB32:
455 c->parent.visual = wl_visual_create(c->parent.display, id, 1);
456 break;
457 }
458}
459
460static const struct wl_compositor_listener compositor_listener = {
461 compositor_handle_visual,
462};
463
464static void
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100465display_handle_global(struct wl_display *display, uint32_t id,
466 const char *interface, uint32_t version, void *data)
467{
468 struct wayland_compositor *c = data;
469
Benjamin Franzke080ab6c2011-04-30 10:41:27 +0200470 if (strcmp(interface, "wl_compositor") == 0) {
Kristian Høgsberg91342c62011-04-14 14:44:58 -0400471 c->parent.compositor = wl_compositor_create(display, id, 1);
Kristian Høgsberg7c476672011-06-18 06:22:05 -0400472 wl_compositor_add_listener(c->parent.compositor,
473 &compositor_listener, c);
Benjamin Franzke080ab6c2011-04-30 10:41:27 +0200474 } else if (strcmp(interface, "wl_output") == 0) {
Kristian Høgsberg91342c62011-04-14 14:44:58 -0400475 c->parent.output = wl_output_create(display, id, 1);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100476 wl_output_add_listener(c->parent.output, &output_listener, c);
Benjamin Franzke080ab6c2011-04-30 10:41:27 +0200477 } else if (strcmp(interface, "wl_input_device") == 0) {
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100478 display_add_input(c, id);
Benjamin Franzke080ab6c2011-04-30 10:41:27 +0200479 } else if (strcmp(interface, "wl_shell") == 0) {
Kristian Høgsberg91342c62011-04-14 14:44:58 -0400480 c->parent.shell = wl_shell_create(display, id, 1);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100481 wl_shell_add_listener(c->parent.shell, &shell_listener, c);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100482 }
483}
484
485static int
486update_event_mask(uint32_t mask, void *data)
487{
488 struct wayland_compositor *c = data;
489
490 c->parent.event_mask = mask;
491 if (c->parent.wl_source)
492 wl_event_source_fd_update(c->parent.wl_source, mask);
493
494 return 0;
495}
496
Kristian Høgsberg95d843d2011-04-22 13:01:26 -0400497static int
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100498wayland_compositor_handle_event(int fd, uint32_t mask, void *data)
499{
500 struct wayland_compositor *c = data;
501
502 if (mask & WL_EVENT_READABLE)
503 wl_display_iterate(c->parent.display, WL_DISPLAY_READABLE);
504 if (mask & WL_EVENT_WRITEABLE)
505 wl_display_iterate(c->parent.display, WL_DISPLAY_WRITABLE);
Kristian Høgsberg95d843d2011-04-22 13:01:26 -0400506
507 return 1;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100508}
509
Kristian Høgsbergcaa64422010-12-01 16:52:15 -0500510static void
511wayland_destroy(struct wlsc_compositor *ec)
512{
513 free(ec);
514}
515
Kristian Høgsberg6c709a32011-05-06 14:52:41 -0400516static struct wlsc_compositor *
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100517wayland_compositor_create(struct wl_display *display, int width, int height)
518{
519 struct wayland_compositor *c;
520 struct wl_event_loop *loop;
521 int fd;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100522
523 c = malloc(sizeof *c);
524 if (c == NULL)
525 return NULL;
526
527 memset(c, 0, sizeof *c);
528
Kristian Høgsberg2bb3ebe2010-12-01 15:36:20 -0500529 c->parent.display = wl_display_connect(NULL);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100530
531 if (c->parent.display == NULL) {
532 fprintf(stderr, "failed to create display: %m\n");
533 return NULL;
534 }
535
536 wl_list_init(&c->input_list);
537 wl_display_add_global_listener(c->parent.display,
538 display_handle_global, c);
539
540 wl_display_iterate(c->parent.display, WL_DISPLAY_READABLE);
541
542 c->base.wl_display = display;
543 if (wayland_compositor_init_egl(c) < 0)
544 return NULL;
545
Benjamin Franzkeecfb2b92011-01-15 12:34:48 +0100546 c->base.destroy = wayland_destroy;
Benjamin Franzkeecfb2b92011-01-15 12:34:48 +0100547
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100548 /* Can't init base class until we have a current egl context */
549 if (wlsc_compositor_init(&c->base, display) < 0)
550 return NULL;
551
552 if (wayland_compositor_create_output(c, width, height) < 0)
553 return NULL;
554
555 if (wayland_input_create(c) < 0)
556 return NULL;
557
558 loop = wl_display_get_event_loop(c->base.wl_display);
559
560 fd = wl_display_get_fd(c->parent.display, update_event_mask, c);
561 c->parent.wl_source =
562 wl_event_loop_add_fd(loop, fd, c->parent.event_mask,
563 wayland_compositor_handle_event, c);
564 if (c->parent.wl_source == NULL)
565 return NULL;
566
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100567 return &c->base;
568}
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400569
570struct wlsc_compositor *
Kristian Høgsberg6c709a32011-05-06 14:52:41 -0400571backend_init(struct wl_display *display, char *options);
572
573WL_EXPORT struct wlsc_compositor *
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400574backend_init(struct wl_display *display, char *options)
575{
576 int width = 1024, height = 640, i;
577 char *p, *value;
578
579 static char * const tokens[] = { "width", "height", NULL };
580
581 p = options;
582 while (i = getsubopt(&p, tokens, &value), i != -1) {
583 switch (i) {
584 case 0:
585 width = strtol(value, NULL, 0);
586 break;
587 case 1:
588 height = strtol(value, NULL, 0);
589 break;
590 }
591 }
592
593 return wayland_compositor_create(display, width, height);
594}