blob: df63daf38954429103515eb4814d33bfe0867308 [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
Matt Roper361d2ad2011-08-29 13:52:23 -0700215static void
216wayland_output_destroy(struct wlsc_output *output_base)
217{
218 struct wayland_output *output = (struct wayland_output *) output_base;
219 struct wlsc_compositor *ec = output->base.compositor;
220
221 eglDestroySurface(ec->display, output->egl_surface);
222 wl_egl_window_destroy(output->parent.egl_window);
223 free(output);
224
225 return;
226}
227
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200228static int
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100229wayland_compositor_create_output(struct wayland_compositor *c,
230 int width, int height)
231{
232 struct wayland_output *output;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100233
234 output = malloc(sizeof *output);
235 if (output == NULL)
236 return -1;
237 memset(output, 0, sizeof *output);
238
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400239 output->mode.flags =
240 WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
241 output->mode.width = width;
242 output->mode.height = height;
243 output->mode.refresh = 60;
244 wl_list_init(&output->base.mode_list);
245 wl_list_insert(&output->base.mode_list, &output->mode.link);
246
247 output->base.current = &output->mode;
Benjamin Franzkebe014562011-02-18 17:04:24 +0100248 wlsc_output_init(&output->base, &c->base, 0, 0, width, height,
249 WL_OUTPUT_FLIPPED);
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400250
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100251 output->parent.surface =
252 wl_compositor_create_surface(c->parent.compositor);
253 wl_surface_set_user_data(output->parent.surface, output);
254
Benjamin Franzkebe014562011-02-18 17:04:24 +0100255 output->parent.egl_window =
Kristian Høgsberg91342c62011-04-14 14:44:58 -0400256 wl_egl_window_create(output->parent.surface,
Kristian Høgsberg7c476672011-06-18 06:22:05 -0400257 width, height, c->parent.visual);
Benjamin Franzkebe014562011-02-18 17:04:24 +0100258 if (!output->parent.egl_window) {
259 fprintf(stderr, "failure to create wl_egl_window\n");
260 goto cleanup_output;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100261 }
262
Benjamin Franzkebe014562011-02-18 17:04:24 +0100263 output->egl_surface =
264 eglCreateWindowSurface(c->base.display, c->base.config,
265 output->parent.egl_window, NULL);
266 if (!output->egl_surface) {
267 fprintf(stderr, "failed to create window surface\n");
268 goto cleanup_window;
269 }
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100270
Benjamin Franzkebe014562011-02-18 17:04:24 +0100271 if (!eglMakeCurrent(c->base.display, output->egl_surface,
272 output->egl_surface, c->base.context)) {
273 fprintf(stderr, "failed to make surface current\n");
274 goto cleanup_surface;
275 return -1;
276 }
277
Kristian Høgsberg7c476672011-06-18 06:22:05 -0400278 wl_shell_set_toplevel(c->parent.shell, output->parent.surface);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100279
280 glClearColor(0, 0, 0, 0.5);
281
Benjamin Franzkeeefc36c2011-03-11 16:39:20 +0100282 output->base.prepare_render = wayland_output_prepare_render;
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100283 output->base.present = wayland_output_present;
Benjamin Franzke66aa2352011-04-20 17:06:13 +0200284 output->base.prepare_scanout_surface =
285 wayland_output_prepare_scanout_surface;
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200286 output->base.set_hardware_cursor = wayland_output_set_cursor;
Matt Roper361d2ad2011-08-29 13:52:23 -0700287 output->base.destroy = wayland_output_destroy;
Benjamin Franzkeeefc36c2011-03-11 16:39:20 +0100288
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100289 wl_list_insert(c->base.output_list.prev, &output->base.link);
290
291 return 0;
Benjamin Franzkebe014562011-02-18 17:04:24 +0100292
293cleanup_surface:
294 eglDestroySurface(c->base.display, output->egl_surface);
295cleanup_window:
296 wl_egl_window_destroy(output->parent.egl_window);
297cleanup_output:
298 /* FIXME: cleanup wlsc_output */
299 free(output);
300
301 return -1;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100302}
303
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100304/* Events received from the wayland-server this compositor is client of: */
305
306/* parent output interface */
307static void
308display_handle_geometry(void *data,
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400309 struct wl_output *wl_output,
310 int x,
311 int y,
312 int physical_width,
313 int physical_height,
314 int subpixel,
315 const char *make,
316 const char *model)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100317{
318 struct wayland_compositor *c = data;
319
Kristian Høgsbergf8fc08f2010-12-01 20:10:10 -0500320 c->parent.screen_allocation.x = x;
321 c->parent.screen_allocation.y = y;
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400322}
323
324static void
325display_handle_mode(void *data,
326 struct wl_output *wl_output,
327 uint32_t flags,
328 int width,
329 int height,
330 int refresh)
331{
332 struct wayland_compositor *c = data;
333
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100334 c->parent.screen_allocation.width = width;
335 c->parent.screen_allocation.height = height;
336}
337
338static const struct wl_output_listener output_listener = {
339 display_handle_geometry,
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400340 display_handle_mode
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100341};
342
343/* parent shell interface */
344static void
345handle_configure(void *data, struct wl_shell *shell,
346 uint32_t time, uint32_t edges,
Kristian Høgsbergcbe6f042010-12-17 09:54:45 -0500347 struct wl_surface *surface, int32_t width, int32_t height)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100348{
349#if 0
350 struct output *output = wl_surface_get_user_data(surface);
351
352 /* FIXME: add resize? */
353#endif
354}
355
356static const struct wl_shell_listener shell_listener = {
357 handle_configure,
358};
359
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100360/* parent input interface */
361static void
362input_handle_motion(void *data, struct wl_input_device *input_device,
363 uint32_t time,
364 int32_t x, int32_t y, int32_t sx, int32_t sy)
365{
366 struct wayland_input *input = data;
367 struct wayland_compositor *c = input->compositor;
368
369 notify_motion(c->base.input_device, time, sx, sy);
370}
371
372static void
373input_handle_button(void *data,
374 struct wl_input_device *input_device,
375 uint32_t time, uint32_t button, uint32_t state)
376{
377 struct wayland_input *input = data;
378 struct wayland_compositor *c = input->compositor;
379
380 notify_button(c->base.input_device, time, button, state);
381}
382
383static void
384input_handle_key(void *data, struct wl_input_device *input_device,
385 uint32_t time, uint32_t key, uint32_t state)
386{
387 struct wayland_input *input = data;
388 struct wayland_compositor *c = input->compositor;
389
390 notify_key(c->base.input_device, time, key, state);
391}
392
393static void
394input_handle_pointer_focus(void *data,
395 struct wl_input_device *input_device,
396 uint32_t time, struct wl_surface *surface,
397 int32_t x, int32_t y, int32_t sx, int32_t sy)
398{
399 struct wayland_input *input = data;
Kristian Høgsbergaf82bea2011-01-27 20:18:17 -0500400 struct wayland_output *output;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100401 struct wayland_compositor *c = input->compositor;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100402
403 if (surface) {
Kristian Høgsberg93331ff2011-01-26 20:35:07 -0500404 output = wl_surface_get_user_data(surface);
405 notify_pointer_focus(c->base.input_device,
406 time, &output->base, sx, sy);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100407 } else {
Kristian Høgsberg93331ff2011-01-26 20:35:07 -0500408 notify_pointer_focus(c->base.input_device, time, NULL, 0, 0);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100409 }
410}
411
412static void
413input_handle_keyboard_focus(void *data,
414 struct wl_input_device *input_device,
415 uint32_t time,
416 struct wl_surface *surface,
417 struct wl_array *keys)
418{
Kristian Høgsbergaf82bea2011-01-27 20:18:17 -0500419 struct wayland_input *input = data;
420 struct wayland_compositor *c = input->compositor;
421 struct wayland_output *output;
422
423 if (surface) {
424 output = wl_surface_get_user_data(surface);
425 notify_keyboard_focus(c->base.input_device,
426 time, &output->base, keys);
427 } else {
428 notify_keyboard_focus(c->base.input_device, time, NULL, NULL);
429 }
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100430}
431
432static const struct wl_input_device_listener input_device_listener = {
433 input_handle_motion,
434 input_handle_button,
435 input_handle_key,
436 input_handle_pointer_focus,
437 input_handle_keyboard_focus,
438};
439
440static void
441display_add_input(struct wayland_compositor *c, uint32_t id)
442{
443 struct wayland_input *input;
444
445 input = malloc(sizeof *input);
446 if (input == NULL)
447 return;
448
449 memset(input, 0, sizeof *input);
450
451 input->compositor = c;
Kristian Høgsberg91342c62011-04-14 14:44:58 -0400452 input->input_device = wl_input_device_create(c->parent.display, id, 1);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100453 wl_list_insert(c->input_list.prev, &input->link);
454
455 wl_input_device_add_listener(input->input_device,
456 &input_device_listener, input);
457 wl_input_device_set_user_data(input->input_device, input);
458}
459
460static void
Kristian Høgsberg7c476672011-06-18 06:22:05 -0400461compositor_handle_visual(void *data,
462 struct wl_compositor *compositor,
463 uint32_t id, uint32_t token)
464{
465 struct wayland_compositor *c = data;
466
467 switch (token) {
468 case WL_COMPOSITOR_VISUAL_ARGB32:
469 c->parent.visual = wl_visual_create(c->parent.display, id, 1);
470 break;
471 }
472}
473
474static const struct wl_compositor_listener compositor_listener = {
475 compositor_handle_visual,
476};
477
478static void
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100479display_handle_global(struct wl_display *display, uint32_t id,
480 const char *interface, uint32_t version, void *data)
481{
482 struct wayland_compositor *c = data;
483
Benjamin Franzke080ab6c2011-04-30 10:41:27 +0200484 if (strcmp(interface, "wl_compositor") == 0) {
Kristian Høgsberg91342c62011-04-14 14:44:58 -0400485 c->parent.compositor = wl_compositor_create(display, id, 1);
Kristian Høgsberg7c476672011-06-18 06:22:05 -0400486 wl_compositor_add_listener(c->parent.compositor,
487 &compositor_listener, c);
Benjamin Franzke080ab6c2011-04-30 10:41:27 +0200488 } else if (strcmp(interface, "wl_output") == 0) {
Kristian Høgsberg91342c62011-04-14 14:44:58 -0400489 c->parent.output = wl_output_create(display, id, 1);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100490 wl_output_add_listener(c->parent.output, &output_listener, c);
Benjamin Franzke080ab6c2011-04-30 10:41:27 +0200491 } else if (strcmp(interface, "wl_input_device") == 0) {
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100492 display_add_input(c, id);
Benjamin Franzke080ab6c2011-04-30 10:41:27 +0200493 } else if (strcmp(interface, "wl_shell") == 0) {
Kristian Høgsberg91342c62011-04-14 14:44:58 -0400494 c->parent.shell = wl_shell_create(display, id, 1);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100495 wl_shell_add_listener(c->parent.shell, &shell_listener, c);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100496 }
497}
498
499static int
500update_event_mask(uint32_t mask, void *data)
501{
502 struct wayland_compositor *c = data;
503
504 c->parent.event_mask = mask;
505 if (c->parent.wl_source)
506 wl_event_source_fd_update(c->parent.wl_source, mask);
507
508 return 0;
509}
510
Kristian Høgsberg95d843d2011-04-22 13:01:26 -0400511static int
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100512wayland_compositor_handle_event(int fd, uint32_t mask, void *data)
513{
514 struct wayland_compositor *c = data;
515
516 if (mask & WL_EVENT_READABLE)
517 wl_display_iterate(c->parent.display, WL_DISPLAY_READABLE);
518 if (mask & WL_EVENT_WRITEABLE)
519 wl_display_iterate(c->parent.display, WL_DISPLAY_WRITABLE);
Kristian Høgsberg95d843d2011-04-22 13:01:26 -0400520
521 return 1;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100522}
523
Kristian Høgsbergcaa64422010-12-01 16:52:15 -0500524static void
525wayland_destroy(struct wlsc_compositor *ec)
526{
Matt Roper361d2ad2011-08-29 13:52:23 -0700527 wlsc_compositor_shutdown(ec);
528
Kristian Høgsbergcaa64422010-12-01 16:52:15 -0500529 free(ec);
530}
531
Kristian Høgsberg6c709a32011-05-06 14:52:41 -0400532static struct wlsc_compositor *
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100533wayland_compositor_create(struct wl_display *display, int width, int height)
534{
535 struct wayland_compositor *c;
536 struct wl_event_loop *loop;
537 int fd;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100538
539 c = malloc(sizeof *c);
540 if (c == NULL)
541 return NULL;
542
543 memset(c, 0, sizeof *c);
544
Kristian Høgsberg2bb3ebe2010-12-01 15:36:20 -0500545 c->parent.display = wl_display_connect(NULL);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100546
547 if (c->parent.display == NULL) {
548 fprintf(stderr, "failed to create display: %m\n");
549 return NULL;
550 }
551
552 wl_list_init(&c->input_list);
553 wl_display_add_global_listener(c->parent.display,
554 display_handle_global, c);
555
556 wl_display_iterate(c->parent.display, WL_DISPLAY_READABLE);
557
558 c->base.wl_display = display;
559 if (wayland_compositor_init_egl(c) < 0)
560 return NULL;
561
Benjamin Franzkeecfb2b92011-01-15 12:34:48 +0100562 c->base.destroy = wayland_destroy;
Benjamin Franzkeecfb2b92011-01-15 12:34:48 +0100563
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100564 /* Can't init base class until we have a current egl context */
565 if (wlsc_compositor_init(&c->base, display) < 0)
566 return NULL;
567
568 if (wayland_compositor_create_output(c, width, height) < 0)
569 return NULL;
570
571 if (wayland_input_create(c) < 0)
572 return NULL;
573
574 loop = wl_display_get_event_loop(c->base.wl_display);
575
576 fd = wl_display_get_fd(c->parent.display, update_event_mask, c);
577 c->parent.wl_source =
578 wl_event_loop_add_fd(loop, fd, c->parent.event_mask,
579 wayland_compositor_handle_event, c);
580 if (c->parent.wl_source == NULL)
581 return NULL;
582
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100583 return &c->base;
584}
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400585
586struct wlsc_compositor *
Kristian Høgsberg6c709a32011-05-06 14:52:41 -0400587backend_init(struct wl_display *display, char *options);
588
589WL_EXPORT struct wlsc_compositor *
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400590backend_init(struct wl_display *display, char *options)
591{
592 int width = 1024, height = 640, i;
593 char *p, *value;
594
595 static char * const tokens[] = { "width", "height", NULL };
596
597 p = options;
598 while (i = getsubopt(&p, tokens, &value), i != -1) {
599 switch (i) {
600 case 0:
601 width = strtol(value, NULL, 0);
602 break;
603 case 1:
604 height = strtol(value, NULL, 0);
605 break;
606 }
607 }
608
609 return wayland_compositor_create(display, width, height);
610}