compositor-x11: Rename the output make to "weston-X11"
[platform/upstream/weston.git] / clients / nested.c
1 /*
2  * Copyright © 2013 Intel Corporation
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that copyright
7  * notice and this permission notice appear in supporting documentation, and
8  * that the name of the copyright holders not be used in advertising or
9  * publicity pertaining to distribution of the software without specific,
10  * written prior permission.  The copyright holders make no representations
11  * about the suitability of this software for any purpose.  It is provided "as
12  * is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20  * OF THIS SOFTWARE.
21  */
22
23 #include "config.h"
24
25 #include <stdint.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <cairo.h>
30 #include <math.h>
31 #include <assert.h>
32 #include <pixman.h>
33 #include <sys/epoll.h>
34 #include <sys/socket.h>
35 #include <unistd.h>
36
37 #include <EGL/egl.h>
38 #include <EGL/eglext.h>
39 #include <GLES2/gl2.h>
40 #include <GLES2/gl2ext.h>
41
42 #include <cairo-gl.h>
43
44 #include <wayland-client.h>
45 #define WL_HIDE_DEPRECATED
46 #include <wayland-server.h>
47
48 #include "window.h"
49
50 #define MIN(x,y) (((x) < (y)) ? (x) : (y))
51
52 #ifndef EGL_WL_create_wayland_buffer_from_image
53 #define EGL_WL_create_wayland_buffer_from_image 1
54
55 #ifdef EGL_EGLEXT_PROTOTYPES
56 EGLAPI struct wl_buffer * EGLAPIENTRY eglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImageKHR image);
57 #endif
58 typedef struct wl_buffer * (EGLAPIENTRYP PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWL) (EGLDisplay dpy, EGLImageKHR image);
59
60 #endif
61
62 static int option_blit;
63
64 struct nested {
65         struct display *display;
66         struct window *window;
67         struct widget *widget;
68         struct wl_display *child_display;
69         struct task child_task;
70
71         EGLDisplay egl_display;
72         struct program *texture_program;
73
74         struct wl_list surface_list;
75
76         const struct nested_renderer *renderer;
77 };
78
79 struct nested_region {
80         struct wl_resource *resource;
81         pixman_region32_t region;
82 };
83
84 struct nested_buffer_reference {
85         struct nested_buffer *buffer;
86         struct wl_listener destroy_listener;
87 };
88
89 struct nested_buffer {
90         struct wl_resource *resource;
91         struct wl_signal destroy_signal;
92         struct wl_listener destroy_listener;
93         uint32_t busy_count;
94
95         /* A buffer in the parent compositor representing the same
96          * data. This is created on-demand when the subsurface
97          * renderer is used */
98         struct wl_buffer *parent_buffer;
99         /* This reference is used to mark when the parent buffer has
100          * been attached to the subsurface. It will be unrefenced when
101          * we receive a buffer release event. That way we won't inform
102          * the client that the buffer is free until the parent
103          * compositor is also finished with it */
104         struct nested_buffer_reference parent_ref;
105 };
106
107 struct nested_surface {
108         struct wl_resource *resource;
109         struct nested *nested;
110         EGLImageKHR *image;
111         struct wl_list link;
112
113         struct wl_list frame_callback_list;
114
115         struct {
116                 /* wl_surface.attach */
117                 int newly_attached;
118                 struct nested_buffer *buffer;
119                 struct wl_listener buffer_destroy_listener;
120
121                 /* wl_surface.frame */
122                 struct wl_list frame_callback_list;
123
124                 /* wl_surface.damage */
125                 pixman_region32_t damage;
126         } pending;
127
128         void *renderer_data;
129 };
130
131 /* Data used for the blit renderer */
132 struct nested_blit_surface {
133         struct nested_buffer_reference buffer_ref;
134         GLuint texture;
135         cairo_surface_t *cairo_surface;
136 };
137
138 /* Data used for the subsurface renderer */
139 struct nested_ss_surface {
140         struct widget *widget;
141         struct wl_surface *surface;
142         struct wl_subsurface *subsurface;
143         struct wl_callback *frame_callback;
144 };
145
146 struct nested_frame_callback {
147         struct wl_resource *resource;
148         struct wl_list link;
149 };
150
151 struct nested_renderer {
152         void (* surface_init)(struct nested_surface *surface);
153         void (* surface_fini)(struct nested_surface *surface);
154         void (* render_clients)(struct nested *nested, cairo_t *cr);
155         void (* surface_attach)(struct nested_surface *surface,
156                                 struct nested_buffer *buffer);
157 };
158
159 static const struct weston_option nested_options[] = {
160         { WESTON_OPTION_BOOLEAN, "blit", 'b', &option_blit },
161 };
162
163 static const struct nested_renderer nested_blit_renderer;
164 static const struct nested_renderer nested_ss_renderer;
165
166 static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d;
167 static PFNEGLCREATEIMAGEKHRPROC create_image;
168 static PFNEGLDESTROYIMAGEKHRPROC destroy_image;
169 static PFNEGLBINDWAYLANDDISPLAYWL bind_display;
170 static PFNEGLUNBINDWAYLANDDISPLAYWL unbind_display;
171 static PFNEGLQUERYWAYLANDBUFFERWL query_buffer;
172 static PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWL create_wayland_buffer_from_image;
173
174 static void
175 nested_buffer_destroy_handler(struct wl_listener *listener, void *data)
176 {
177         struct nested_buffer *buffer =
178                 container_of(listener, struct nested_buffer, destroy_listener);
179
180         wl_signal_emit(&buffer->destroy_signal, buffer);
181
182         if (buffer->parent_buffer)
183                 wl_buffer_destroy(buffer->parent_buffer);
184
185         free(buffer);
186 }
187
188 static struct nested_buffer *
189 nested_buffer_from_resource(struct wl_resource *resource)
190 {
191         struct nested_buffer *buffer;
192         struct wl_listener *listener;
193
194         listener =
195                 wl_resource_get_destroy_listener(resource,
196                                                  nested_buffer_destroy_handler);
197
198         if (listener)
199                 return container_of(listener, struct nested_buffer,
200                                     destroy_listener);
201
202         buffer = zalloc(sizeof *buffer);
203         if (buffer == NULL)
204                 return NULL;
205
206         buffer->resource = resource;
207         wl_signal_init(&buffer->destroy_signal);
208         buffer->destroy_listener.notify = nested_buffer_destroy_handler;
209         wl_resource_add_destroy_listener(resource, &buffer->destroy_listener);
210
211         return buffer;
212 }
213
214 static void
215 nested_buffer_reference_handle_destroy(struct wl_listener *listener,
216                                        void *data)
217 {
218         struct nested_buffer_reference *ref =
219                 container_of(listener, struct nested_buffer_reference,
220                              destroy_listener);
221
222         assert((struct nested_buffer *)data == ref->buffer);
223         ref->buffer = NULL;
224 }
225
226 static void
227 nested_buffer_reference(struct nested_buffer_reference *ref,
228                         struct nested_buffer *buffer)
229 {
230         if (buffer == ref->buffer)
231                 return;
232
233         if (ref->buffer) {
234                 ref->buffer->busy_count--;
235                 if (ref->buffer->busy_count == 0) {
236                         assert(wl_resource_get_client(ref->buffer->resource));
237                         wl_resource_queue_event(ref->buffer->resource,
238                                                 WL_BUFFER_RELEASE);
239                 }
240                 wl_list_remove(&ref->destroy_listener.link);
241         }
242
243         if (buffer) {
244                 buffer->busy_count++;
245                 wl_signal_add(&buffer->destroy_signal,
246                               &ref->destroy_listener);
247
248                 ref->destroy_listener.notify =
249                         nested_buffer_reference_handle_destroy;
250         }
251
252         ref->buffer = buffer;
253 }
254
255 static void
256 flush_surface_frame_callback_list(struct nested_surface *surface,
257                                   uint32_t time)
258 {
259         struct nested_frame_callback *nc, *next;
260
261         wl_list_for_each_safe(nc, next, &surface->frame_callback_list, link) {
262                 wl_callback_send_done(nc->resource, time);
263                 wl_resource_destroy(nc->resource);
264         }
265         wl_list_init(&surface->frame_callback_list);
266
267         /* FIXME: toytoolkit need a pre-block handler where we can
268          * call this. */
269         wl_display_flush_clients(surface->nested->child_display);
270 }
271
272 static void
273 redraw_handler(struct widget *widget, void *data)
274 {
275         struct nested *nested = data;
276         cairo_surface_t *surface;
277         cairo_t *cr;
278         struct rectangle allocation;
279
280         widget_get_allocation(nested->widget, &allocation);
281
282         surface = window_get_surface(nested->window);
283
284         cr = cairo_create(surface);
285         cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
286         cairo_rectangle(cr,
287                         allocation.x,
288                         allocation.y,
289                         allocation.width,
290                         allocation.height);
291         cairo_set_source_rgba(cr, 0, 0, 0, 0.8);
292         cairo_fill(cr);
293
294         nested->renderer->render_clients(nested, cr);
295
296         cairo_destroy(cr);
297
298         cairo_surface_destroy(surface);
299 }
300
301 static void
302 keyboard_focus_handler(struct window *window,
303                        struct input *device, void *data)
304 {
305         struct nested *nested = data;
306
307         window_schedule_redraw(nested->window);
308 }
309
310 static void
311 handle_child_data(struct task *task, uint32_t events)
312 {
313         struct nested *nested = container_of(task, struct nested, child_task);
314         struct wl_event_loop *loop;
315
316         loop = wl_display_get_event_loop(nested->child_display);
317
318         wl_event_loop_dispatch(loop, -1);
319         wl_display_flush_clients(nested->child_display);
320 }
321
322 struct nested_client {
323         struct wl_client *client;
324         pid_t pid;
325 };
326
327 static struct nested_client *
328 launch_client(struct nested *nested, const char *path)
329 {
330         int sv[2];
331         pid_t pid;
332         struct nested_client *client;
333
334         client = malloc(sizeof *client);
335         if (client == NULL)
336                 return NULL;
337
338         if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sv) < 0) {
339                 fprintf(stderr, "launch_client: "
340                         "socketpair failed while launching '%s': %m\n",
341                         path);
342                 free(client);
343                 return NULL;
344         }
345
346         pid = fork();
347         if (pid == -1) {
348                 close(sv[0]);
349                 close(sv[1]);
350                 free(client);
351                 fprintf(stderr, "launch_client: "
352                         "fork failed while launching '%s': %m\n", path);
353                 return NULL;
354         }
355
356         if (pid == 0) {
357                 int clientfd;
358                 char s[32];
359
360                 /* SOCK_CLOEXEC closes both ends, so we dup the fd to
361                  * get a non-CLOEXEC fd to pass through exec. */
362                 clientfd = dup(sv[1]);
363                 if (clientfd == -1) {
364                         fprintf(stderr, "compositor: dup failed: %m\n");
365                         exit(-1);
366                 }
367
368                 snprintf(s, sizeof s, "%d", clientfd);
369                 setenv("WAYLAND_SOCKET", s, 1);
370
371                 execl(path, path, NULL);
372
373                 fprintf(stderr, "compositor: executing '%s' failed: %m\n",
374                         path);
375                 exit(-1);
376         }
377
378         close(sv[1]);
379
380         client->client = wl_client_create(nested->child_display, sv[0]);
381         if (!client->client) {
382                 close(sv[0]);
383                 free(client);
384                 fprintf(stderr, "launch_client: "
385                         "wl_client_create failed while launching '%s'.\n",
386                         path);
387                 return NULL;
388         }
389
390         client->pid = pid;
391
392         return client;
393 }
394
395 static void
396 destroy_surface(struct wl_resource *resource)
397 {
398         struct nested_surface *surface = wl_resource_get_user_data(resource);
399         struct nested *nested = surface->nested;
400         struct nested_frame_callback *cb, *next;
401
402         wl_list_for_each_safe(cb, next,
403                               &surface->frame_callback_list, link)
404                 wl_resource_destroy(cb->resource);
405
406         wl_list_for_each_safe(cb, next,
407                               &surface->pending.frame_callback_list, link)
408                 wl_resource_destroy(cb->resource);
409
410         pixman_region32_fini(&surface->pending.damage);
411
412         nested->renderer->surface_fini(surface);
413
414         wl_list_remove(&surface->link);
415
416         free(surface);
417 }
418
419 static void
420 surface_destroy(struct wl_client *client, struct wl_resource *resource)
421 {
422         wl_resource_destroy(resource);
423 }
424
425 static void
426 surface_attach(struct wl_client *client,
427                struct wl_resource *resource,
428                struct wl_resource *buffer_resource, int32_t sx, int32_t sy)
429 {
430         struct nested_surface *surface = wl_resource_get_user_data(resource);
431         struct nested *nested = surface->nested;
432         struct nested_buffer *buffer = NULL;
433
434         if (buffer_resource) {
435                 int format;
436
437                 if (!query_buffer(nested->egl_display, (void *) buffer_resource,
438                                   EGL_TEXTURE_FORMAT, &format)) {
439                         wl_resource_post_error(buffer_resource,
440                                                WL_DISPLAY_ERROR_INVALID_OBJECT,
441                                                "attaching non-egl wl_buffer");
442                         return;
443                 }
444
445                 switch (format) {
446                 case EGL_TEXTURE_RGB:
447                 case EGL_TEXTURE_RGBA:
448                         break;
449                 default:
450                         wl_resource_post_error(buffer_resource,
451                                                WL_DISPLAY_ERROR_INVALID_OBJECT,
452                                                "invalid format");
453                         return;
454                 }
455
456                 buffer = nested_buffer_from_resource(buffer_resource);
457                 if (buffer == NULL) {
458                         wl_client_post_no_memory(client);
459                         return;
460                 }
461         }
462
463         if (surface->pending.buffer)
464                 wl_list_remove(&surface->pending.buffer_destroy_listener.link);
465
466         surface->pending.buffer = buffer;
467         surface->pending.newly_attached = 1;
468         if (buffer) {
469                 wl_signal_add(&buffer->destroy_signal,
470                               &surface->pending.buffer_destroy_listener);
471         }
472 }
473
474 static void
475 nested_surface_attach(struct nested_surface *surface,
476                       struct nested_buffer *buffer)
477 {
478         struct nested *nested = surface->nested;
479
480         if (surface->image != EGL_NO_IMAGE_KHR)
481                 destroy_image(nested->egl_display, surface->image);
482
483         surface->image = create_image(nested->egl_display, NULL,
484                                       EGL_WAYLAND_BUFFER_WL, buffer->resource,
485                                       NULL);
486         if (surface->image == EGL_NO_IMAGE_KHR) {
487                 fprintf(stderr, "failed to create img\n");
488                 return;
489         }
490
491         nested->renderer->surface_attach(surface, buffer);
492 }
493
494 static void
495 surface_damage(struct wl_client *client,
496                struct wl_resource *resource,
497                int32_t x, int32_t y, int32_t width, int32_t height)
498 {
499         struct nested_surface *surface = wl_resource_get_user_data(resource);
500
501         pixman_region32_union_rect(&surface->pending.damage,
502                                    &surface->pending.damage,
503                                    x, y, width, height);
504 }
505
506 static void
507 destroy_frame_callback(struct wl_resource *resource)
508 {
509         struct nested_frame_callback *callback = wl_resource_get_user_data(resource);
510
511         wl_list_remove(&callback->link);
512         free(callback);
513 }
514
515 static void
516 surface_frame(struct wl_client *client,
517               struct wl_resource *resource, uint32_t id)
518 {
519         struct nested_frame_callback *callback;
520         struct nested_surface *surface = wl_resource_get_user_data(resource);
521
522         callback = malloc(sizeof *callback);
523         if (callback == NULL) {
524                 wl_resource_post_no_memory(resource);
525                 return;
526         }
527
528         callback->resource = wl_resource_create(client,
529                                                 &wl_callback_interface, 1, id);
530         wl_resource_set_implementation(callback->resource, NULL, callback,
531                                        destroy_frame_callback);
532
533         wl_list_insert(surface->pending.frame_callback_list.prev,
534                        &callback->link);
535 }
536
537 static void
538 surface_set_opaque_region(struct wl_client *client,
539                           struct wl_resource *resource,
540                           struct wl_resource *region_resource)
541 {
542         fprintf(stderr, "surface_set_opaque_region\n");
543 }
544
545 static void
546 surface_set_input_region(struct wl_client *client,
547                          struct wl_resource *resource,
548                          struct wl_resource *region_resource)
549 {
550         fprintf(stderr, "surface_set_input_region\n");
551 }
552
553 static void
554 surface_commit(struct wl_client *client, struct wl_resource *resource)
555 {
556         struct nested_surface *surface = wl_resource_get_user_data(resource);
557         struct nested *nested = surface->nested;
558
559         /* wl_surface.attach */
560         if (surface->pending.newly_attached)
561                 nested_surface_attach(surface, surface->pending.buffer);
562
563         if (surface->pending.buffer) {
564                 wl_list_remove(&surface->pending.buffer_destroy_listener.link);
565                 surface->pending.buffer = NULL;
566         }
567         surface->pending.newly_attached = 0;
568
569         /* wl_surface.damage */
570         pixman_region32_clear(&surface->pending.damage);
571
572         /* wl_surface.frame */
573         wl_list_insert_list(&surface->frame_callback_list,
574                             &surface->pending.frame_callback_list);
575         wl_list_init(&surface->pending.frame_callback_list);
576
577         /* FIXME: For the subsurface renderer we don't need to
578          * actually redraw the window. However we do want to cause a
579          * commit because the subsurface is synchronized. Ideally we
580          * would just queue the commit */
581         window_schedule_redraw(nested->window);
582 }
583
584 static void
585 surface_set_buffer_transform(struct wl_client *client,
586                              struct wl_resource *resource, int transform)
587 {
588         fprintf(stderr, "surface_set_buffer_transform\n");
589 }
590
591 static const struct wl_surface_interface surface_interface = {
592         surface_destroy,
593         surface_attach,
594         surface_damage,
595         surface_frame,
596         surface_set_opaque_region,
597         surface_set_input_region,
598         surface_commit,
599         surface_set_buffer_transform
600 };
601
602 static void
603 surface_handle_pending_buffer_destroy(struct wl_listener *listener, void *data)
604 {
605         struct nested_surface *surface =
606                 container_of(listener, struct nested_surface,
607                              pending.buffer_destroy_listener);
608
609         surface->pending.buffer = NULL;
610 }
611
612 static void
613 compositor_create_surface(struct wl_client *client,
614                           struct wl_resource *resource, uint32_t id)
615 {
616         struct nested *nested = wl_resource_get_user_data(resource);
617         struct nested_surface *surface;
618         
619         surface = zalloc(sizeof *surface);
620         if (surface == NULL) {
621                 wl_resource_post_no_memory(resource);
622                 return;
623         }
624
625         surface->nested = nested;
626
627         wl_list_init(&surface->frame_callback_list);
628
629         wl_list_init(&surface->pending.frame_callback_list);
630         surface->pending.buffer_destroy_listener.notify =
631                 surface_handle_pending_buffer_destroy;
632         pixman_region32_init(&surface->pending.damage);
633
634         display_acquire_window_surface(nested->display,
635                                        nested->window, NULL);
636
637         nested->renderer->surface_init(surface);
638
639         display_release_window_surface(nested->display, nested->window);
640
641         surface->resource =
642                 wl_resource_create(client, &wl_surface_interface, 1, id);
643
644         wl_resource_set_implementation(surface->resource,
645                                        &surface_interface, surface,
646                                        destroy_surface);
647
648         wl_list_insert(nested->surface_list.prev, &surface->link);
649 }
650
651 static void
652 destroy_region(struct wl_resource *resource)
653 {
654         struct nested_region *region = wl_resource_get_user_data(resource);
655
656         pixman_region32_fini(&region->region);
657         free(region);
658 }
659
660 static void
661 region_destroy(struct wl_client *client, struct wl_resource *resource)
662 {
663         wl_resource_destroy(resource);
664 }
665
666 static void
667 region_add(struct wl_client *client, struct wl_resource *resource,
668            int32_t x, int32_t y, int32_t width, int32_t height)
669 {
670         struct nested_region *region = wl_resource_get_user_data(resource);
671
672         pixman_region32_union_rect(&region->region, &region->region,
673                                    x, y, width, height);
674 }
675
676 static void
677 region_subtract(struct wl_client *client, struct wl_resource *resource,
678                 int32_t x, int32_t y, int32_t width, int32_t height)
679 {
680         struct nested_region *region = wl_resource_get_user_data(resource);
681         pixman_region32_t rect;
682
683         pixman_region32_init_rect(&rect, x, y, width, height);
684         pixman_region32_subtract(&region->region, &region->region, &rect);
685         pixman_region32_fini(&rect);
686 }
687
688 static const struct wl_region_interface region_interface = {
689         region_destroy,
690         region_add,
691         region_subtract
692 };
693
694 static void
695 compositor_create_region(struct wl_client *client,
696                          struct wl_resource *resource, uint32_t id)
697 {
698         struct nested_region *region;
699
700         region = malloc(sizeof *region);
701         if (region == NULL) {
702                 wl_resource_post_no_memory(resource);
703                 return;
704         }
705
706         pixman_region32_init(&region->region);
707
708         region->resource =
709                 wl_resource_create(client, &wl_region_interface, 1, id);
710         wl_resource_set_implementation(region->resource, &region_interface,
711                                        region, destroy_region);
712 }
713
714 static const struct wl_compositor_interface compositor_interface = {
715         compositor_create_surface,
716         compositor_create_region
717 };
718
719 static void
720 compositor_bind(struct wl_client *client,
721                 void *data, uint32_t version, uint32_t id)
722 {
723         struct nested *nested = data;
724         struct wl_resource *resource;
725
726         resource = wl_resource_create(client, &wl_compositor_interface,
727                                       MIN(version, 3), id);
728         wl_resource_set_implementation(resource, &compositor_interface,
729                                        nested, NULL);
730 }
731
732 static int
733 nested_init_compositor(struct nested *nested)
734 {
735         const char *extensions;
736         struct wl_event_loop *loop;
737         int use_ss_renderer = 0;
738         int fd, ret;
739
740         wl_list_init(&nested->surface_list);
741         nested->child_display = wl_display_create();
742         loop = wl_display_get_event_loop(nested->child_display);
743         fd = wl_event_loop_get_fd(loop);
744         nested->child_task.run = handle_child_data;
745         display_watch_fd(nested->display, fd,
746                          EPOLLIN, &nested->child_task);
747
748         if (!wl_global_create(nested->child_display,
749                               &wl_compositor_interface, 1,
750                               nested, compositor_bind))
751                 return -1;
752
753         wl_display_init_shm(nested->child_display);
754
755         nested->egl_display = display_get_egl_display(nested->display);
756         extensions = eglQueryString(nested->egl_display, EGL_EXTENSIONS);
757         if (strstr(extensions, "EGL_WL_bind_wayland_display") == NULL) {
758                 fprintf(stderr, "no EGL_WL_bind_wayland_display extension\n");
759                 return -1;
760         }
761
762         bind_display = (void *) eglGetProcAddress("eglBindWaylandDisplayWL");
763         unbind_display = (void *) eglGetProcAddress("eglUnbindWaylandDisplayWL");
764         create_image = (void *) eglGetProcAddress("eglCreateImageKHR");
765         destroy_image = (void *) eglGetProcAddress("eglDestroyImageKHR");
766         query_buffer = (void *) eglGetProcAddress("eglQueryWaylandBufferWL");
767         image_target_texture_2d =
768                 (void *) eglGetProcAddress("glEGLImageTargetTexture2DOES");
769
770         ret = bind_display(nested->egl_display, nested->child_display);
771         if (!ret) {
772                 fprintf(stderr, "failed to bind wl_display\n");
773                 return -1;
774         }
775
776         if (display_has_subcompositor(nested->display)) {
777                 const char *func = "eglCreateWaylandBufferFromImageWL";
778                 const char *ext = "EGL_WL_create_wayland_buffer_from_image";
779
780                 if (strstr(extensions, ext)) {
781                         create_wayland_buffer_from_image =
782                                 (void *) eglGetProcAddress(func);
783                         use_ss_renderer = 1;
784                 }
785         }
786
787         if (option_blit)
788                 use_ss_renderer = 0;
789
790         if (use_ss_renderer) {
791                 printf("Using subsurfaces to render client surfaces\n");
792                 nested->renderer = &nested_ss_renderer;
793         } else {
794                 printf("Using local compositing with blits to "
795                        "render client surfaces\n");
796                 nested->renderer = &nested_blit_renderer;
797         }
798
799         return 0;
800 }
801
802 static struct nested *
803 nested_create(struct display *display)
804 {
805         struct nested *nested;
806
807         nested = zalloc(sizeof *nested);
808         if (nested == NULL)
809                 return nested;
810
811         nested->window = window_create(display);
812         nested->widget = window_frame_create(nested->window, nested);
813         window_set_title(nested->window, "Wayland Nested");
814         nested->display = display;
815
816         window_set_user_data(nested->window, nested);
817         widget_set_redraw_handler(nested->widget, redraw_handler);
818         window_set_keyboard_focus_handler(nested->window,
819                                           keyboard_focus_handler);
820
821         nested_init_compositor(nested);
822
823         widget_schedule_resize(nested->widget, 400, 400);
824
825         return nested;
826 }
827
828 static void
829 nested_destroy(struct nested *nested)
830 {
831         widget_destroy(nested->widget);
832         window_destroy(nested->window);
833         free(nested);
834 }
835
836 /*** blit renderer ***/
837
838 static void
839 blit_surface_init(struct nested_surface *surface)
840 {
841         struct nested_blit_surface *blit_surface =
842                 xzalloc(sizeof *blit_surface);
843
844         glGenTextures(1, &blit_surface->texture);
845         glBindTexture(GL_TEXTURE_2D, blit_surface->texture);
846         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
847         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
848         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
849         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
850
851         surface->renderer_data = blit_surface;
852 }
853
854 static void
855 blit_surface_fini(struct nested_surface *surface)
856 {
857         struct nested_blit_surface *blit_surface = surface->renderer_data;
858
859         nested_buffer_reference(&blit_surface->buffer_ref, NULL);
860
861         glDeleteTextures(1, &blit_surface->texture);
862
863         free(blit_surface);
864 }
865
866 static void
867 blit_frame_callback(void *data, struct wl_callback *callback, uint32_t time)
868 {
869         struct nested *nested = data;
870         struct nested_surface *surface;
871
872         wl_list_for_each(surface, &nested->surface_list, link)
873                 flush_surface_frame_callback_list(surface, time);
874
875         if (callback)
876                 wl_callback_destroy(callback);
877 }
878
879 static const struct wl_callback_listener blit_frame_listener = {
880         blit_frame_callback
881 };
882
883 static void
884 blit_render_clients(struct nested *nested,
885                     cairo_t *cr)
886 {
887         struct nested_surface *s;
888         struct rectangle allocation;
889         struct wl_callback *callback;
890
891         widget_get_allocation(nested->widget, &allocation);
892
893         wl_list_for_each(s, &nested->surface_list, link) {
894                 struct nested_blit_surface *blit_surface = s->renderer_data;
895
896                 display_acquire_window_surface(nested->display,
897                                                nested->window, NULL);
898
899                 glBindTexture(GL_TEXTURE_2D, blit_surface->texture);
900                 image_target_texture_2d(GL_TEXTURE_2D, s->image);
901
902                 display_release_window_surface(nested->display,
903                                                nested->window);
904
905                 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
906                 cairo_set_source_surface(cr, blit_surface->cairo_surface,
907                                          allocation.x + 10,
908                                          allocation.y + 10);
909                 cairo_rectangle(cr, allocation.x + 10,
910                                 allocation.y + 10,
911                                 allocation.width - 10,
912                                 allocation.height - 10);
913
914                 cairo_fill(cr);
915         }
916
917         callback = wl_surface_frame(window_get_wl_surface(nested->window));
918         wl_callback_add_listener(callback, &blit_frame_listener, nested);
919 }
920
921 static void
922 blit_surface_attach(struct nested_surface *surface,
923                     struct nested_buffer *buffer)
924 {
925         struct nested *nested = surface->nested;
926         struct nested_blit_surface *blit_surface = surface->renderer_data;
927         EGLint width, height;
928         cairo_device_t *device;
929
930         nested_buffer_reference(&blit_surface->buffer_ref, buffer);
931
932         if (blit_surface->cairo_surface)
933                 cairo_surface_destroy(blit_surface->cairo_surface);
934
935         query_buffer(nested->egl_display, (void *) buffer->resource,
936                      EGL_WIDTH, &width);
937         query_buffer(nested->egl_display, (void *) buffer->resource,
938                      EGL_HEIGHT, &height);
939
940         device = display_get_cairo_device(nested->display);
941         blit_surface->cairo_surface =
942                 cairo_gl_surface_create_for_texture(device,
943                                                     CAIRO_CONTENT_COLOR_ALPHA,
944                                                     blit_surface->texture,
945                                                     width, height);
946 }
947
948 static const struct nested_renderer
949 nested_blit_renderer = {
950         .surface_init = blit_surface_init,
951         .surface_fini = blit_surface_fini,
952         .render_clients = blit_render_clients,
953         .surface_attach = blit_surface_attach
954 };
955
956 /*** subsurface renderer ***/
957
958 static void
959 ss_surface_init(struct nested_surface *surface)
960 {
961         struct nested *nested = surface->nested;
962         struct wl_compositor *compositor =
963                 display_get_compositor(nested->display);
964         struct nested_ss_surface *ss_surface =
965                 xzalloc(sizeof *ss_surface);
966         struct rectangle allocation;
967         struct wl_region *region;
968
969         ss_surface->widget =
970                 window_add_subsurface(nested->window,
971                                       nested,
972                                       SUBSURFACE_SYNCHRONIZED);
973
974         widget_set_use_cairo(ss_surface->widget, 0);
975
976         ss_surface->surface = widget_get_wl_surface(ss_surface->widget);
977         ss_surface->subsurface = widget_get_wl_subsurface(ss_surface->widget);
978
979         /* The toy toolkit gets confused about the pointer position
980          * when it gets motion events for a subsurface so we'll just
981          * disable input on it */
982         region = wl_compositor_create_region(compositor);
983         wl_surface_set_input_region(ss_surface->surface, region);
984         wl_region_destroy(region);
985
986         widget_get_allocation(nested->widget, &allocation);
987         wl_subsurface_set_position(ss_surface->subsurface,
988                                    allocation.x + 10,
989                                    allocation.y + 10);
990
991         surface->renderer_data = ss_surface;
992 }
993
994 static void
995 ss_surface_fini(struct nested_surface *surface)
996 {
997         struct nested_ss_surface *ss_surface = surface->renderer_data;
998
999         widget_destroy(ss_surface->widget);
1000
1001         if (ss_surface->frame_callback)
1002                 wl_callback_destroy(ss_surface->frame_callback);
1003
1004         free(ss_surface);
1005 }
1006
1007 static void
1008 ss_render_clients(struct nested *nested,
1009                   cairo_t *cr)
1010 {
1011         /* The clients are composited by the parent compositor so we
1012          * don't need to do anything here */
1013 }
1014
1015 static void
1016 ss_buffer_release(void *data, struct wl_buffer *wl_buffer)
1017 {
1018         struct nested_buffer *buffer = data;
1019
1020         nested_buffer_reference(&buffer->parent_ref, NULL);
1021 }
1022
1023 static struct wl_buffer_listener ss_buffer_listener = {
1024    ss_buffer_release
1025 };
1026
1027 static void
1028 ss_frame_callback(void *data, struct wl_callback *callback, uint32_t time)
1029 {
1030         struct nested_surface *surface = data;
1031         struct nested_ss_surface *ss_surface = surface->renderer_data;
1032
1033         flush_surface_frame_callback_list(surface, time);
1034
1035         if (callback)
1036                 wl_callback_destroy(callback);
1037
1038         ss_surface->frame_callback = NULL;
1039 }
1040
1041 static const struct wl_callback_listener ss_frame_listener = {
1042         ss_frame_callback
1043 };
1044
1045 static void
1046 ss_surface_attach(struct nested_surface *surface,
1047                   struct nested_buffer *buffer)
1048 {
1049         struct nested *nested = surface->nested;
1050         struct nested_ss_surface *ss_surface = surface->renderer_data;
1051         struct wl_buffer *parent_buffer;
1052         const pixman_box32_t *rects;
1053         int n_rects, i;
1054
1055         if (buffer) {
1056                 /* Create a representation of the buffer in the parent
1057                  * compositor if we haven't already */
1058                 if (buffer->parent_buffer == NULL) {
1059                         EGLDisplay *edpy = nested->egl_display;
1060                         EGLImageKHR image = surface->image;
1061
1062                         buffer->parent_buffer =
1063                                 create_wayland_buffer_from_image(edpy, image);
1064
1065                         wl_buffer_add_listener(buffer->parent_buffer,
1066                                                &ss_buffer_listener,
1067                                                buffer);
1068                 }
1069
1070                 parent_buffer = buffer->parent_buffer;
1071
1072                 /* We'll take a reference to the buffer while the parent
1073                  * compositor is using it so that we won't report the release
1074                  * event until the parent has also finished with it */
1075                 nested_buffer_reference(&buffer->parent_ref, buffer);
1076         } else {
1077                 parent_buffer = NULL;
1078         }
1079
1080         wl_surface_attach(ss_surface->surface, parent_buffer, 0, 0);
1081
1082         rects = pixman_region32_rectangles(&surface->pending.damage, &n_rects);
1083
1084         for (i = 0; i < n_rects; i++) {
1085                 const pixman_box32_t *rect = rects + i;
1086                 wl_surface_damage(ss_surface->surface,
1087                                   rect->x1,
1088                                   rect->y1,
1089                                   rect->x2 - rect->x1,
1090                                   rect->y2 - rect->y1);
1091         }
1092
1093         if (ss_surface->frame_callback)
1094                 wl_callback_destroy(ss_surface->frame_callback);
1095
1096         ss_surface->frame_callback = wl_surface_frame(ss_surface->surface);
1097         wl_callback_add_listener(ss_surface->frame_callback,
1098                                  &ss_frame_listener,
1099                                  surface);
1100
1101         wl_surface_commit(ss_surface->surface);
1102 }
1103
1104 static const struct nested_renderer
1105 nested_ss_renderer = {
1106         .surface_init = ss_surface_init,
1107         .surface_fini = ss_surface_fini,
1108         .render_clients = ss_render_clients,
1109         .surface_attach = ss_surface_attach
1110 };
1111
1112 int
1113 main(int argc, char *argv[])
1114 {
1115         struct display *display;
1116         struct nested *nested;
1117
1118         if (parse_options(nested_options,
1119                           ARRAY_LENGTH(nested_options), &argc, argv) > 1) {
1120                 printf("Usage: %s [OPTIONS]\n  --blit or -b\n", argv[0]);
1121                 exit(1);
1122         }
1123
1124         display = display_create(&argc, argv);
1125         if (display == NULL) {
1126                 fprintf(stderr, "failed to create display: %m\n");
1127                 return -1;
1128         }
1129
1130         nested = nested_create(display);
1131
1132         launch_client(nested, "weston-nested-client");
1133
1134         display_run(display);
1135
1136         nested_destroy(nested);
1137         display_destroy(display);
1138
1139         return 0;
1140 }