blob: fad04aa9f57690f93ee926f1ee5fdfe1319b745a [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
Benjamin Franzkeeefc36c2011-03-11 16:39:20 +0100160static int
161wayland_output_prepare_render(struct wlsc_output *output_base)
162{
163 struct wayland_output *output = (struct wayland_output *) output_base;
164 struct wlsc_compositor *ec = output->base.compositor;
165
166 if (!eglMakeCurrent(ec->display, output->egl_surface,
167 output->egl_surface, ec->context)) {
168 fprintf(stderr, "failed to make current\n");
169 return -1;
170 }
171
172 return 0;
173}
174
Kristian Høgsberg33418202011-08-16 23:01:28 -0400175static void
176frame_done(void *data, struct wl_callback *wl_callback, uint32_t time)
177{
178 struct wlsc_output *output = data;
179
180 wlsc_output_finish_frame(output, time);
181}
182
183static const struct wl_callback_listener frame_listener = {
184 frame_done
185};
186
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100187static int
188wayland_output_present(struct wlsc_output *output_base)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100189{
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100190 struct wayland_output *output = (struct wayland_output *) output_base;
191 struct wayland_compositor *c =
192 (struct wayland_compositor *) output->base.compositor;
Kristian Høgsberg33418202011-08-16 23:01:28 -0400193 struct wl_callback *callback;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100194
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100195 if (wayland_output_prepare_render(&output->base))
196 return -1;
Benjamin Franzkeeefc36c2011-03-11 16:39:20 +0100197
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100198 eglSwapBuffers(c->base.display, output->egl_surface);
Kristian Høgsberg33418202011-08-16 23:01:28 -0400199 callback = wl_surface_frame(output->parent.surface);
200 wl_callback_add_listener(callback, &frame_listener, output);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100201
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100202 return 0;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100203}
204
205static int
Benjamin Franzke66aa2352011-04-20 17:06:13 +0200206wayland_output_prepare_scanout_surface(struct wlsc_output *output_base,
207 struct wlsc_surface *es)
Benjamin Franzke1178a3c2011-04-10 16:49:52 +0200208{
Benjamin Franzke66aa2352011-04-20 17:06:13 +0200209 return -1;
Benjamin Franzke1178a3c2011-04-10 16:49:52 +0200210}
211
212static int
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200213wayland_output_set_cursor(struct wlsc_output *output_base,
Kristian Høgsberge4c40a42011-05-06 14:04:21 -0400214 struct wlsc_input_device *input)
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200215{
216 return -1;
217}
218
Matt Roper361d2ad2011-08-29 13:52:23 -0700219static void
220wayland_output_destroy(struct wlsc_output *output_base)
221{
222 struct wayland_output *output = (struct wayland_output *) output_base;
223 struct wlsc_compositor *ec = output->base.compositor;
224
225 eglDestroySurface(ec->display, output->egl_surface);
226 wl_egl_window_destroy(output->parent.egl_window);
227 free(output);
228
229 return;
230}
231
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200232static int
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100233wayland_compositor_create_output(struct wayland_compositor *c,
234 int width, int height)
235{
236 struct wayland_output *output;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100237
238 output = malloc(sizeof *output);
239 if (output == NULL)
240 return -1;
241 memset(output, 0, sizeof *output);
242
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400243 output->mode.flags =
244 WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
245 output->mode.width = width;
246 output->mode.height = height;
247 output->mode.refresh = 60;
248 wl_list_init(&output->base.mode_list);
249 wl_list_insert(&output->base.mode_list, &output->mode.link);
250
251 output->base.current = &output->mode;
Benjamin Franzkebe014562011-02-18 17:04:24 +0100252 wlsc_output_init(&output->base, &c->base, 0, 0, width, height,
253 WL_OUTPUT_FLIPPED);
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400254
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100255 output->parent.surface =
256 wl_compositor_create_surface(c->parent.compositor);
257 wl_surface_set_user_data(output->parent.surface, output);
258
Benjamin Franzkebe014562011-02-18 17:04:24 +0100259 output->parent.egl_window =
Kristian Høgsberg91342c62011-04-14 14:44:58 -0400260 wl_egl_window_create(output->parent.surface,
Kristian Høgsberg7c476672011-06-18 06:22:05 -0400261 width, height, c->parent.visual);
Benjamin Franzkebe014562011-02-18 17:04:24 +0100262 if (!output->parent.egl_window) {
263 fprintf(stderr, "failure to create wl_egl_window\n");
264 goto cleanup_output;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100265 }
266
Benjamin Franzkebe014562011-02-18 17:04:24 +0100267 output->egl_surface =
268 eglCreateWindowSurface(c->base.display, c->base.config,
269 output->parent.egl_window, NULL);
270 if (!output->egl_surface) {
271 fprintf(stderr, "failed to create window surface\n");
272 goto cleanup_window;
273 }
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100274
Benjamin Franzkebe014562011-02-18 17:04:24 +0100275 if (!eglMakeCurrent(c->base.display, output->egl_surface,
276 output->egl_surface, c->base.context)) {
277 fprintf(stderr, "failed to make surface current\n");
278 goto cleanup_surface;
279 return -1;
280 }
281
Kristian Høgsberg7c476672011-06-18 06:22:05 -0400282 wl_shell_set_toplevel(c->parent.shell, output->parent.surface);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100283
284 glClearColor(0, 0, 0, 0.5);
285
Benjamin Franzkeeefc36c2011-03-11 16:39:20 +0100286 output->base.prepare_render = wayland_output_prepare_render;
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100287 output->base.present = wayland_output_present;
Benjamin Franzke66aa2352011-04-20 17:06:13 +0200288 output->base.prepare_scanout_surface =
289 wayland_output_prepare_scanout_surface;
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200290 output->base.set_hardware_cursor = wayland_output_set_cursor;
Matt Roper361d2ad2011-08-29 13:52:23 -0700291 output->base.destroy = wayland_output_destroy;
Benjamin Franzkeeefc36c2011-03-11 16:39:20 +0100292
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100293 wl_list_insert(c->base.output_list.prev, &output->base.link);
294
295 return 0;
Benjamin Franzkebe014562011-02-18 17:04:24 +0100296
297cleanup_surface:
298 eglDestroySurface(c->base.display, output->egl_surface);
299cleanup_window:
300 wl_egl_window_destroy(output->parent.egl_window);
301cleanup_output:
302 /* FIXME: cleanup wlsc_output */
303 free(output);
304
305 return -1;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100306}
307
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100308/* Events received from the wayland-server this compositor is client of: */
309
310/* parent output interface */
311static void
312display_handle_geometry(void *data,
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400313 struct wl_output *wl_output,
314 int x,
315 int y,
316 int physical_width,
317 int physical_height,
318 int subpixel,
319 const char *make,
320 const char *model)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100321{
322 struct wayland_compositor *c = data;
323
Kristian Høgsbergf8fc08f2010-12-01 20:10:10 -0500324 c->parent.screen_allocation.x = x;
325 c->parent.screen_allocation.y = y;
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400326}
327
328static void
329display_handle_mode(void *data,
330 struct wl_output *wl_output,
331 uint32_t flags,
332 int width,
333 int height,
334 int refresh)
335{
336 struct wayland_compositor *c = data;
337
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100338 c->parent.screen_allocation.width = width;
339 c->parent.screen_allocation.height = height;
340}
341
342static const struct wl_output_listener output_listener = {
343 display_handle_geometry,
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400344 display_handle_mode
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100345};
346
347/* parent shell interface */
348static void
349handle_configure(void *data, struct wl_shell *shell,
350 uint32_t time, uint32_t edges,
Kristian Høgsbergcbe6f042010-12-17 09:54:45 -0500351 struct wl_surface *surface, int32_t width, int32_t height)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100352{
353#if 0
354 struct output *output = wl_surface_get_user_data(surface);
355
356 /* FIXME: add resize? */
357#endif
358}
359
360static const struct wl_shell_listener shell_listener = {
361 handle_configure,
362};
363
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100364/* parent input interface */
365static void
366input_handle_motion(void *data, struct wl_input_device *input_device,
367 uint32_t time,
368 int32_t x, int32_t y, int32_t sx, int32_t sy)
369{
370 struct wayland_input *input = data;
371 struct wayland_compositor *c = input->compositor;
372
373 notify_motion(c->base.input_device, time, sx, sy);
374}
375
376static void
377input_handle_button(void *data,
378 struct wl_input_device *input_device,
379 uint32_t time, uint32_t button, uint32_t state)
380{
381 struct wayland_input *input = data;
382 struct wayland_compositor *c = input->compositor;
383
384 notify_button(c->base.input_device, time, button, state);
385}
386
387static void
388input_handle_key(void *data, struct wl_input_device *input_device,
389 uint32_t time, uint32_t key, uint32_t state)
390{
391 struct wayland_input *input = data;
392 struct wayland_compositor *c = input->compositor;
393
394 notify_key(c->base.input_device, time, key, state);
395}
396
397static void
398input_handle_pointer_focus(void *data,
399 struct wl_input_device *input_device,
400 uint32_t time, struct wl_surface *surface,
401 int32_t x, int32_t y, int32_t sx, int32_t sy)
402{
403 struct wayland_input *input = data;
Kristian Høgsbergaf82bea2011-01-27 20:18:17 -0500404 struct wayland_output *output;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100405 struct wayland_compositor *c = input->compositor;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100406
407 if (surface) {
Kristian Høgsberg93331ff2011-01-26 20:35:07 -0500408 output = wl_surface_get_user_data(surface);
409 notify_pointer_focus(c->base.input_device,
410 time, &output->base, sx, sy);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100411 } else {
Kristian Høgsberg93331ff2011-01-26 20:35:07 -0500412 notify_pointer_focus(c->base.input_device, time, NULL, 0, 0);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100413 }
414}
415
416static void
417input_handle_keyboard_focus(void *data,
418 struct wl_input_device *input_device,
419 uint32_t time,
420 struct wl_surface *surface,
421 struct wl_array *keys)
422{
Kristian Høgsbergaf82bea2011-01-27 20:18:17 -0500423 struct wayland_input *input = data;
424 struct wayland_compositor *c = input->compositor;
425 struct wayland_output *output;
426
427 if (surface) {
428 output = wl_surface_get_user_data(surface);
429 notify_keyboard_focus(c->base.input_device,
430 time, &output->base, keys);
431 } else {
432 notify_keyboard_focus(c->base.input_device, time, NULL, NULL);
433 }
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100434}
435
436static const struct wl_input_device_listener input_device_listener = {
437 input_handle_motion,
438 input_handle_button,
439 input_handle_key,
440 input_handle_pointer_focus,
441 input_handle_keyboard_focus,
442};
443
444static void
445display_add_input(struct wayland_compositor *c, uint32_t id)
446{
447 struct wayland_input *input;
448
449 input = malloc(sizeof *input);
450 if (input == NULL)
451 return;
452
453 memset(input, 0, sizeof *input);
454
455 input->compositor = c;
Kristian Høgsberg91342c62011-04-14 14:44:58 -0400456 input->input_device = wl_input_device_create(c->parent.display, id, 1);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100457 wl_list_insert(c->input_list.prev, &input->link);
458
459 wl_input_device_add_listener(input->input_device,
460 &input_device_listener, input);
461 wl_input_device_set_user_data(input->input_device, input);
462}
463
464static void
Kristian Høgsberg7c476672011-06-18 06:22:05 -0400465compositor_handle_visual(void *data,
466 struct wl_compositor *compositor,
467 uint32_t id, uint32_t token)
468{
469 struct wayland_compositor *c = data;
470
471 switch (token) {
472 case WL_COMPOSITOR_VISUAL_ARGB32:
473 c->parent.visual = wl_visual_create(c->parent.display, id, 1);
474 break;
475 }
476}
477
478static const struct wl_compositor_listener compositor_listener = {
479 compositor_handle_visual,
480};
481
482static void
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100483display_handle_global(struct wl_display *display, uint32_t id,
484 const char *interface, uint32_t version, void *data)
485{
486 struct wayland_compositor *c = data;
487
Benjamin Franzke080ab6c2011-04-30 10:41:27 +0200488 if (strcmp(interface, "wl_compositor") == 0) {
Kristian Høgsberg91342c62011-04-14 14:44:58 -0400489 c->parent.compositor = wl_compositor_create(display, id, 1);
Kristian Høgsberg7c476672011-06-18 06:22:05 -0400490 wl_compositor_add_listener(c->parent.compositor,
491 &compositor_listener, c);
Benjamin Franzke080ab6c2011-04-30 10:41:27 +0200492 } else if (strcmp(interface, "wl_output") == 0) {
Kristian Høgsberg91342c62011-04-14 14:44:58 -0400493 c->parent.output = wl_output_create(display, id, 1);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100494 wl_output_add_listener(c->parent.output, &output_listener, c);
Benjamin Franzke080ab6c2011-04-30 10:41:27 +0200495 } else if (strcmp(interface, "wl_input_device") == 0) {
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100496 display_add_input(c, id);
Benjamin Franzke080ab6c2011-04-30 10:41:27 +0200497 } else if (strcmp(interface, "wl_shell") == 0) {
Kristian Høgsberg91342c62011-04-14 14:44:58 -0400498 c->parent.shell = wl_shell_create(display, id, 1);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100499 wl_shell_add_listener(c->parent.shell, &shell_listener, c);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100500 }
501}
502
503static int
504update_event_mask(uint32_t mask, void *data)
505{
506 struct wayland_compositor *c = data;
507
508 c->parent.event_mask = mask;
509 if (c->parent.wl_source)
510 wl_event_source_fd_update(c->parent.wl_source, mask);
511
512 return 0;
513}
514
Kristian Høgsberg95d843d2011-04-22 13:01:26 -0400515static int
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100516wayland_compositor_handle_event(int fd, uint32_t mask, void *data)
517{
518 struct wayland_compositor *c = data;
519
520 if (mask & WL_EVENT_READABLE)
521 wl_display_iterate(c->parent.display, WL_DISPLAY_READABLE);
522 if (mask & WL_EVENT_WRITEABLE)
523 wl_display_iterate(c->parent.display, WL_DISPLAY_WRITABLE);
Kristian Høgsberg95d843d2011-04-22 13:01:26 -0400524
525 return 1;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100526}
527
Kristian Høgsbergcaa64422010-12-01 16:52:15 -0500528static void
529wayland_destroy(struct wlsc_compositor *ec)
530{
Matt Roper361d2ad2011-08-29 13:52:23 -0700531 wlsc_compositor_shutdown(ec);
532
Kristian Høgsbergcaa64422010-12-01 16:52:15 -0500533 free(ec);
534}
535
Kristian Høgsberg6c709a32011-05-06 14:52:41 -0400536static struct wlsc_compositor *
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100537wayland_compositor_create(struct wl_display *display, int width, int height)
538{
539 struct wayland_compositor *c;
540 struct wl_event_loop *loop;
541 int fd;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100542
543 c = malloc(sizeof *c);
544 if (c == NULL)
545 return NULL;
546
547 memset(c, 0, sizeof *c);
548
Kristian Høgsberg2bb3ebe2010-12-01 15:36:20 -0500549 c->parent.display = wl_display_connect(NULL);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100550
551 if (c->parent.display == NULL) {
552 fprintf(stderr, "failed to create display: %m\n");
553 return NULL;
554 }
555
556 wl_list_init(&c->input_list);
557 wl_display_add_global_listener(c->parent.display,
558 display_handle_global, c);
559
560 wl_display_iterate(c->parent.display, WL_DISPLAY_READABLE);
561
562 c->base.wl_display = display;
563 if (wayland_compositor_init_egl(c) < 0)
564 return NULL;
565
Benjamin Franzkeecfb2b92011-01-15 12:34:48 +0100566 c->base.destroy = wayland_destroy;
Benjamin Franzkeecfb2b92011-01-15 12:34:48 +0100567
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100568 /* Can't init base class until we have a current egl context */
569 if (wlsc_compositor_init(&c->base, display) < 0)
570 return NULL;
571
572 if (wayland_compositor_create_output(c, width, height) < 0)
573 return NULL;
574
575 if (wayland_input_create(c) < 0)
576 return NULL;
577
578 loop = wl_display_get_event_loop(c->base.wl_display);
579
580 fd = wl_display_get_fd(c->parent.display, update_event_mask, c);
581 c->parent.wl_source =
582 wl_event_loop_add_fd(loop, fd, c->parent.event_mask,
583 wayland_compositor_handle_event, c);
584 if (c->parent.wl_source == NULL)
585 return NULL;
586
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100587 return &c->base;
588}
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400589
590struct wlsc_compositor *
Kristian Høgsberg6c709a32011-05-06 14:52:41 -0400591backend_init(struct wl_display *display, char *options);
592
593WL_EXPORT struct wlsc_compositor *
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400594backend_init(struct wl_display *display, char *options)
595{
596 int width = 1024, height = 640, i;
597 char *p, *value;
598
599 static char * const tokens[] = { "width", "height", NULL };
600
601 p = options;
602 while (i = getsubopt(&p, tokens, &value), i != -1) {
603 switch (i) {
604 case 0:
605 width = strtol(value, NULL, 0);
606 break;
607 case 1:
608 height = strtol(value, NULL, 0);
609 break;
610 }
611 }
612
613 return wayland_compositor_create(display, width, height);
614}