blob: 4f0b025a856f9bdcf11f6a4022f662ae220d6d88 [file] [log] [blame]
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001/*
Kristian Høgsberg96aa7da2011-09-15 15:43:14 -04002 * Copyright © 2010-2011 Benjamin Franzke
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01003 *
Kristian Høgsberg96aa7da2011-09-15 15:43:14 -04004 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010013 *
Kristian Høgsberg96aa7da2011-09-15 15:43:14 -040014 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010021 */
22
23#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
26
27#include <stddef.h>
28#define _GNU_SOURCE
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <fcntl.h>
33#include <unistd.h>
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010034
Benjamin Franzkebe014562011-02-18 17:04:24 +010035#include <wayland-client.h>
36#include <wayland-egl.h>
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010037
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010038#include <GLES2/gl2.h>
39#include <GLES2/gl2ext.h>
40#include <EGL/egl.h>
41#include <EGL/eglext.h>
42
43#include "compositor.h"
44
45struct wayland_compositor {
46 struct wlsc_compositor base;
47
48 struct {
49 struct wl_display *display;
50 struct wl_compositor *compositor;
51 struct wl_shell *shell;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010052 struct wl_output *output;
53
54 struct {
55 int32_t x, y, width, height;
56 } screen_allocation;
57
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010058 struct wl_event_source *wl_source;
59 uint32_t event_mask;
60 } parent;
61
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010062 struct wl_list input_list;
63};
64
65struct wayland_output {
66 struct wlsc_output base;
67
68 struct {
69 struct wl_surface *surface;
Benjamin Franzkebe014562011-02-18 17:04:24 +010070 struct wl_egl_window *egl_window;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010071 } parent;
Benjamin Franzkebe014562011-02-18 17:04:24 +010072 EGLSurface egl_surface;
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -040073 struct wlsc_mode mode;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010074};
75
76struct wayland_input {
77 struct wayland_compositor *compositor;
78 struct wl_input_device *input_device;
79 struct wl_list link;
80};
81
82static int
83wayland_input_create(struct wayland_compositor *c)
84{
85 struct wlsc_input_device *input;
86
87 input = malloc(sizeof *input);
88 if (input == NULL)
89 return -1;
90
91 memset(input, 0, sizeof *input);
92 wlsc_input_device_init(input, &c->base);
93
Kristian Høgsberg9c3e8d72010-12-08 09:48:52 -050094 c->base.input_device = &input->input_device;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010095
96 return 0;
97}
98
99static int
100wayland_compositor_init_egl(struct wayland_compositor *c)
101{
102 EGLint major, minor;
Benjamin Franzkebe014562011-02-18 17:04:24 +0100103 EGLint n;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100104 const char *extensions;
Benjamin Franzkebe014562011-02-18 17:04:24 +0100105 EGLint config_attribs[] = {
106 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
107 EGL_RED_SIZE, 1,
108 EGL_GREEN_SIZE, 1,
109 EGL_BLUE_SIZE, 1,
Kristian Høgsbergf389cac2011-08-31 16:21:38 -0400110 EGL_ALPHA_SIZE, 0,
Benjamin Franzkebe014562011-02-18 17:04:24 +0100111 EGL_DEPTH_SIZE, 1,
Kristian Høgsbergd28ab362011-03-02 11:36:30 -0500112 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
Benjamin Franzkebe014562011-02-18 17:04:24 +0100113 EGL_NONE
114 };
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100115 static const EGLint context_attribs[] = {
116 EGL_CONTEXT_CLIENT_VERSION, 2,
117 EGL_NONE
118 };
119
Kristian Høgsberg91342c62011-04-14 14:44:58 -0400120 c->base.display = eglGetDisplay(c->parent.display);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100121 if (c->base.display == NULL) {
122 fprintf(stderr, "failed to create display\n");
123 return -1;
124 }
125
126 if (!eglInitialize(c->base.display, &major, &minor)) {
127 fprintf(stderr, "failed to initialize display\n");
128 return -1;
129 }
130
131 extensions = eglQueryString(c->base.display, EGL_EXTENSIONS);
132 if (!strstr(extensions, "EGL_KHR_surfaceless_opengl")) {
133 fprintf(stderr, "EGL_KHR_surfaceless_opengl not available\n");
134 return -1;
135 }
136
137 if (!eglBindAPI(EGL_OPENGL_ES_API)) {
138 fprintf(stderr, "failed to bind EGL_OPENGL_ES_API\n");
139 return -1;
140 }
Benjamin Franzkebe014562011-02-18 17:04:24 +0100141 if (!eglChooseConfig(c->base.display, config_attribs,
142 &c->base.config, 1, &n) || n == 0) {
143 fprintf(stderr, "failed to choose config: %d\n", n);
144 return -1;
145 }
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100146
Benjamin Franzkebe014562011-02-18 17:04:24 +0100147 c->base.context = eglCreateContext(c->base.display, c->base.config,
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100148 EGL_NO_CONTEXT, context_attribs);
149 if (c->base.context == NULL) {
150 fprintf(stderr, "failed to create context\n");
151 return -1;
152 }
153
154 if (!eglMakeCurrent(c->base.display, EGL_NO_SURFACE,
155 EGL_NO_SURFACE, c->base.context)) {
156 fprintf(stderr, "failed to make context current\n");
157 return -1;
158 }
159
160 return 0;
161}
162
Benjamin Franzkeeefc36c2011-03-11 16:39:20 +0100163static int
164wayland_output_prepare_render(struct wlsc_output *output_base)
165{
166 struct wayland_output *output = (struct wayland_output *) output_base;
167 struct wlsc_compositor *ec = output->base.compositor;
168
169 if (!eglMakeCurrent(ec->display, output->egl_surface,
170 output->egl_surface, ec->context)) {
171 fprintf(stderr, "failed to make current\n");
172 return -1;
173 }
174
175 return 0;
176}
177
Kristian Høgsberg33418202011-08-16 23:01:28 -0400178static void
179frame_done(void *data, struct wl_callback *wl_callback, uint32_t time)
180{
181 struct wlsc_output *output = data;
182
183 wlsc_output_finish_frame(output, time);
184}
185
186static const struct wl_callback_listener frame_listener = {
187 frame_done
188};
189
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100190static int
191wayland_output_present(struct wlsc_output *output_base)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100192{
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100193 struct wayland_output *output = (struct wayland_output *) output_base;
194 struct wayland_compositor *c =
195 (struct wayland_compositor *) output->base.compositor;
Kristian Høgsberg33418202011-08-16 23:01:28 -0400196 struct wl_callback *callback;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100197
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100198 if (wayland_output_prepare_render(&output->base))
199 return -1;
Benjamin Franzkeeefc36c2011-03-11 16:39:20 +0100200
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100201 eglSwapBuffers(c->base.display, output->egl_surface);
Kristian Høgsberg33418202011-08-16 23:01:28 -0400202 callback = wl_surface_frame(output->parent.surface);
203 wl_callback_add_listener(callback, &frame_listener, output);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100204
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100205 return 0;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100206}
207
208static int
Benjamin Franzke66aa2352011-04-20 17:06:13 +0200209wayland_output_prepare_scanout_surface(struct wlsc_output *output_base,
210 struct wlsc_surface *es)
Benjamin Franzke1178a3c2011-04-10 16:49:52 +0200211{
Benjamin Franzke66aa2352011-04-20 17:06:13 +0200212 return -1;
Benjamin Franzke1178a3c2011-04-10 16:49:52 +0200213}
214
215static int
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200216wayland_output_set_cursor(struct wlsc_output *output_base,
Kristian Høgsberge4c40a42011-05-06 14:04:21 -0400217 struct wlsc_input_device *input)
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200218{
219 return -1;
220}
221
Matt Roper361d2ad2011-08-29 13:52:23 -0700222static void
223wayland_output_destroy(struct wlsc_output *output_base)
224{
225 struct wayland_output *output = (struct wayland_output *) output_base;
226 struct wlsc_compositor *ec = output->base.compositor;
227
228 eglDestroySurface(ec->display, output->egl_surface);
229 wl_egl_window_destroy(output->parent.egl_window);
230 free(output);
231
232 return;
233}
234
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200235static int
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100236wayland_compositor_create_output(struct wayland_compositor *c,
237 int width, int height)
238{
239 struct wayland_output *output;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100240
241 output = malloc(sizeof *output);
242 if (output == NULL)
243 return -1;
244 memset(output, 0, sizeof *output);
245
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400246 output->mode.flags =
247 WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
248 output->mode.width = width;
249 output->mode.height = height;
250 output->mode.refresh = 60;
251 wl_list_init(&output->base.mode_list);
252 wl_list_insert(&output->base.mode_list, &output->mode.link);
253
254 output->base.current = &output->mode;
Benjamin Franzkebe014562011-02-18 17:04:24 +0100255 wlsc_output_init(&output->base, &c->base, 0, 0, width, height,
256 WL_OUTPUT_FLIPPED);
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400257
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100258 output->parent.surface =
259 wl_compositor_create_surface(c->parent.compositor);
260 wl_surface_set_user_data(output->parent.surface, output);
261
Benjamin Franzkebe014562011-02-18 17:04:24 +0100262 output->parent.egl_window =
Kristian Høgsbergf389cac2011-08-31 16:21:38 -0400263 wl_egl_window_create(output->parent.surface, width, height);
Benjamin Franzkebe014562011-02-18 17:04:24 +0100264 if (!output->parent.egl_window) {
265 fprintf(stderr, "failure to create wl_egl_window\n");
266 goto cleanup_output;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100267 }
268
Benjamin Franzkebe014562011-02-18 17:04:24 +0100269 output->egl_surface =
270 eglCreateWindowSurface(c->base.display, c->base.config,
271 output->parent.egl_window, NULL);
272 if (!output->egl_surface) {
273 fprintf(stderr, "failed to create window surface\n");
274 goto cleanup_window;
275 }
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100276
Benjamin Franzkebe014562011-02-18 17:04:24 +0100277 if (!eglMakeCurrent(c->base.display, output->egl_surface,
278 output->egl_surface, c->base.context)) {
279 fprintf(stderr, "failed to make surface current\n");
280 goto cleanup_surface;
281 return -1;
282 }
283
Kristian Høgsberg7c476672011-06-18 06:22:05 -0400284 wl_shell_set_toplevel(c->parent.shell, output->parent.surface);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100285
286 glClearColor(0, 0, 0, 0.5);
287
Benjamin Franzkeeefc36c2011-03-11 16:39:20 +0100288 output->base.prepare_render = wayland_output_prepare_render;
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100289 output->base.present = wayland_output_present;
Benjamin Franzke66aa2352011-04-20 17:06:13 +0200290 output->base.prepare_scanout_surface =
291 wayland_output_prepare_scanout_surface;
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200292 output->base.set_hardware_cursor = wayland_output_set_cursor;
Matt Roper361d2ad2011-08-29 13:52:23 -0700293 output->base.destroy = wayland_output_destroy;
Benjamin Franzkeeefc36c2011-03-11 16:39:20 +0100294
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100295 wl_list_insert(c->base.output_list.prev, &output->base.link);
296
297 return 0;
Benjamin Franzkebe014562011-02-18 17:04:24 +0100298
299cleanup_surface:
300 eglDestroySurface(c->base.display, output->egl_surface);
301cleanup_window:
302 wl_egl_window_destroy(output->parent.egl_window);
303cleanup_output:
304 /* FIXME: cleanup wlsc_output */
305 free(output);
306
307 return -1;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100308}
309
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100310/* Events received from the wayland-server this compositor is client of: */
311
312/* parent output interface */
313static void
314display_handle_geometry(void *data,
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400315 struct wl_output *wl_output,
316 int x,
317 int y,
318 int physical_width,
319 int physical_height,
320 int subpixel,
321 const char *make,
322 const char *model)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100323{
324 struct wayland_compositor *c = data;
325
Kristian Høgsbergf8fc08f2010-12-01 20:10:10 -0500326 c->parent.screen_allocation.x = x;
327 c->parent.screen_allocation.y = y;
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400328}
329
330static void
331display_handle_mode(void *data,
332 struct wl_output *wl_output,
333 uint32_t flags,
334 int width,
335 int height,
336 int refresh)
337{
338 struct wayland_compositor *c = data;
339
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100340 c->parent.screen_allocation.width = width;
341 c->parent.screen_allocation.height = height;
342}
343
344static const struct wl_output_listener output_listener = {
345 display_handle_geometry,
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400346 display_handle_mode
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100347};
348
349/* parent shell interface */
350static void
351handle_configure(void *data, struct wl_shell *shell,
352 uint32_t time, uint32_t edges,
Kristian Høgsbergcbe6f042010-12-17 09:54:45 -0500353 struct wl_surface *surface, int32_t width, int32_t height)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100354{
355#if 0
356 struct output *output = wl_surface_get_user_data(surface);
357
358 /* FIXME: add resize? */
359#endif
360}
361
362static const struct wl_shell_listener shell_listener = {
363 handle_configure,
364};
365
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100366/* parent input interface */
367static void
368input_handle_motion(void *data, struct wl_input_device *input_device,
369 uint32_t time,
370 int32_t x, int32_t y, int32_t sx, int32_t sy)
371{
372 struct wayland_input *input = data;
373 struct wayland_compositor *c = input->compositor;
374
375 notify_motion(c->base.input_device, time, sx, sy);
376}
377
378static void
379input_handle_button(void *data,
380 struct wl_input_device *input_device,
381 uint32_t time, uint32_t button, uint32_t state)
382{
383 struct wayland_input *input = data;
384 struct wayland_compositor *c = input->compositor;
385
386 notify_button(c->base.input_device, time, button, state);
387}
388
389static void
390input_handle_key(void *data, struct wl_input_device *input_device,
391 uint32_t time, uint32_t key, uint32_t state)
392{
393 struct wayland_input *input = data;
394 struct wayland_compositor *c = input->compositor;
395
396 notify_key(c->base.input_device, time, key, state);
397}
398
399static void
400input_handle_pointer_focus(void *data,
401 struct wl_input_device *input_device,
402 uint32_t time, struct wl_surface *surface,
403 int32_t x, int32_t y, int32_t sx, int32_t sy)
404{
405 struct wayland_input *input = data;
Kristian Høgsbergaf82bea2011-01-27 20:18:17 -0500406 struct wayland_output *output;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100407 struct wayland_compositor *c = input->compositor;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100408
409 if (surface) {
Kristian Høgsberg93331ff2011-01-26 20:35:07 -0500410 output = wl_surface_get_user_data(surface);
411 notify_pointer_focus(c->base.input_device,
412 time, &output->base, sx, sy);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100413 } else {
Kristian Høgsberg93331ff2011-01-26 20:35:07 -0500414 notify_pointer_focus(c->base.input_device, time, NULL, 0, 0);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100415 }
416}
417
418static void
419input_handle_keyboard_focus(void *data,
420 struct wl_input_device *input_device,
421 uint32_t time,
422 struct wl_surface *surface,
423 struct wl_array *keys)
424{
Kristian Høgsbergaf82bea2011-01-27 20:18:17 -0500425 struct wayland_input *input = data;
426 struct wayland_compositor *c = input->compositor;
427 struct wayland_output *output;
428
429 if (surface) {
430 output = wl_surface_get_user_data(surface);
431 notify_keyboard_focus(c->base.input_device,
432 time, &output->base, keys);
433 } else {
434 notify_keyboard_focus(c->base.input_device, time, NULL, NULL);
435 }
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100436}
437
438static const struct wl_input_device_listener input_device_listener = {
439 input_handle_motion,
440 input_handle_button,
441 input_handle_key,
442 input_handle_pointer_focus,
443 input_handle_keyboard_focus,
444};
445
446static void
447display_add_input(struct wayland_compositor *c, uint32_t id)
448{
449 struct wayland_input *input;
450
451 input = malloc(sizeof *input);
452 if (input == NULL)
453 return;
454
455 memset(input, 0, sizeof *input);
456
457 input->compositor = c;
Kristian Høgsbergf790c792011-08-19 14:41:57 -0400458 input->input_device = wl_display_bind(c->parent.display,
459 id, &wl_input_device_interface);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100460 wl_list_insert(c->input_list.prev, &input->link);
461
462 wl_input_device_add_listener(input->input_device,
463 &input_device_listener, input);
464 wl_input_device_set_user_data(input->input_device, input);
465}
466
467static void
468display_handle_global(struct wl_display *display, uint32_t id,
469 const char *interface, uint32_t version, void *data)
470{
471 struct wayland_compositor *c = data;
472
Benjamin Franzke080ab6c2011-04-30 10:41:27 +0200473 if (strcmp(interface, "wl_compositor") == 0) {
Kristian Høgsbergf790c792011-08-19 14:41:57 -0400474 c->parent.compositor =
475 wl_display_bind(display, id, &wl_compositor_interface);
Benjamin Franzke080ab6c2011-04-30 10:41:27 +0200476 } else if (strcmp(interface, "wl_output") == 0) {
Kristian Høgsbergf790c792011-08-19 14:41:57 -0400477 c->parent.output =
478 wl_display_bind(display, id, &wl_output_interface);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100479 wl_output_add_listener(c->parent.output, &output_listener, c);
Benjamin Franzke080ab6c2011-04-30 10:41:27 +0200480 } else if (strcmp(interface, "wl_input_device") == 0) {
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100481 display_add_input(c, id);
Benjamin Franzke080ab6c2011-04-30 10:41:27 +0200482 } else if (strcmp(interface, "wl_shell") == 0) {
Kristian Høgsbergf790c792011-08-19 14:41:57 -0400483 c->parent.shell =
484 wl_display_bind(display, id, &wl_shell_interface);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100485 wl_shell_add_listener(c->parent.shell, &shell_listener, c);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100486 }
487}
488
489static int
490update_event_mask(uint32_t mask, void *data)
491{
492 struct wayland_compositor *c = data;
493
494 c->parent.event_mask = mask;
495 if (c->parent.wl_source)
496 wl_event_source_fd_update(c->parent.wl_source, mask);
497
498 return 0;
499}
500
Kristian Høgsberg95d843d2011-04-22 13:01:26 -0400501static int
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100502wayland_compositor_handle_event(int fd, uint32_t mask, void *data)
503{
504 struct wayland_compositor *c = data;
505
506 if (mask & WL_EVENT_READABLE)
507 wl_display_iterate(c->parent.display, WL_DISPLAY_READABLE);
508 if (mask & WL_EVENT_WRITEABLE)
509 wl_display_iterate(c->parent.display, WL_DISPLAY_WRITABLE);
Kristian Høgsberg95d843d2011-04-22 13:01:26 -0400510
511 return 1;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100512}
513
Kristian Høgsbergcaa64422010-12-01 16:52:15 -0500514static void
515wayland_destroy(struct wlsc_compositor *ec)
516{
Matt Roper361d2ad2011-08-29 13:52:23 -0700517 wlsc_compositor_shutdown(ec);
518
Kristian Høgsbergcaa64422010-12-01 16:52:15 -0500519 free(ec);
520}
521
Kristian Høgsberg6c709a32011-05-06 14:52:41 -0400522static struct wlsc_compositor *
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100523wayland_compositor_create(struct wl_display *display, int width, int height)
524{
525 struct wayland_compositor *c;
526 struct wl_event_loop *loop;
527 int fd;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100528
529 c = malloc(sizeof *c);
530 if (c == NULL)
531 return NULL;
532
533 memset(c, 0, sizeof *c);
534
Kristian Høgsberg2bb3ebe2010-12-01 15:36:20 -0500535 c->parent.display = wl_display_connect(NULL);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100536
537 if (c->parent.display == NULL) {
538 fprintf(stderr, "failed to create display: %m\n");
539 return NULL;
540 }
541
542 wl_list_init(&c->input_list);
543 wl_display_add_global_listener(c->parent.display,
544 display_handle_global, c);
545
546 wl_display_iterate(c->parent.display, WL_DISPLAY_READABLE);
547
548 c->base.wl_display = display;
549 if (wayland_compositor_init_egl(c) < 0)
550 return NULL;
551
Benjamin Franzkeecfb2b92011-01-15 12:34:48 +0100552 c->base.destroy = wayland_destroy;
Benjamin Franzkeecfb2b92011-01-15 12:34:48 +0100553
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100554 /* Can't init base class until we have a current egl context */
555 if (wlsc_compositor_init(&c->base, display) < 0)
556 return NULL;
557
558 if (wayland_compositor_create_output(c, width, height) < 0)
559 return NULL;
560
561 if (wayland_input_create(c) < 0)
562 return NULL;
563
564 loop = wl_display_get_event_loop(c->base.wl_display);
565
566 fd = wl_display_get_fd(c->parent.display, update_event_mask, c);
567 c->parent.wl_source =
568 wl_event_loop_add_fd(loop, fd, c->parent.event_mask,
569 wayland_compositor_handle_event, c);
570 if (c->parent.wl_source == NULL)
571 return NULL;
572
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100573 return &c->base;
574}
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400575
576struct wlsc_compositor *
Kristian Høgsberg6c709a32011-05-06 14:52:41 -0400577backend_init(struct wl_display *display, char *options);
578
579WL_EXPORT struct wlsc_compositor *
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400580backend_init(struct wl_display *display, char *options)
581{
582 int width = 1024, height = 640, i;
583 char *p, *value;
584
585 static char * const tokens[] = { "width", "height", NULL };
586
587 p = options;
588 while (i = getsubopt(&p, tokens, &value), i != -1) {
589 switch (i) {
590 case 0:
591 width = strtol(value, NULL, 0);
592 break;
593 case 1:
594 height = strtol(value, NULL, 0);
595 break;
596 }
597 }
598
599 return wayland_compositor_create(display, width, height);
600}