desktop-shell: Fix black edges on scaled desktop pattern
[profile/ivi/weston-ivi-shell.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 empty_region(pixman_region32_t *region)
555 {
556         pixman_region32_fini(region);
557         pixman_region32_init(region);
558 }
559
560 static void
561 surface_commit(struct wl_client *client, struct wl_resource *resource)
562 {
563         struct nested_surface *surface = wl_resource_get_user_data(resource);
564         struct nested *nested = surface->nested;
565
566         /* wl_surface.attach */
567         if (surface->pending.newly_attached)
568                 nested_surface_attach(surface, surface->pending.buffer);
569
570         if (surface->pending.buffer) {
571                 wl_list_remove(&surface->pending.buffer_destroy_listener.link);
572                 surface->pending.buffer = NULL;
573         }
574         surface->pending.newly_attached = 0;
575
576         /* wl_surface.damage */
577         empty_region(&surface->pending.damage);
578
579         /* wl_surface.frame */
580         wl_list_insert_list(&surface->frame_callback_list,
581                             &surface->pending.frame_callback_list);
582         wl_list_init(&surface->pending.frame_callback_list);
583
584         /* FIXME: For the subsurface renderer we don't need to
585          * actually redraw the window. However we do want to cause a
586          * commit because the subsurface is synchronized. Ideally we
587          * would just queue the commit */
588         window_schedule_redraw(nested->window);
589 }
590
591 static void
592 surface_set_buffer_transform(struct wl_client *client,
593                              struct wl_resource *resource, int transform)
594 {
595         fprintf(stderr, "surface_set_buffer_transform\n");
596 }
597
598 static const struct wl_surface_interface surface_interface = {
599         surface_destroy,
600         surface_attach,
601         surface_damage,
602         surface_frame,
603         surface_set_opaque_region,
604         surface_set_input_region,
605         surface_commit,
606         surface_set_buffer_transform
607 };
608
609 static void
610 surface_handle_pending_buffer_destroy(struct wl_listener *listener, void *data)
611 {
612         struct nested_surface *surface =
613                 container_of(listener, struct nested_surface,
614                              pending.buffer_destroy_listener);
615
616         surface->pending.buffer = NULL;
617 }
618
619 static void
620 compositor_create_surface(struct wl_client *client,
621                           struct wl_resource *resource, uint32_t id)
622 {
623         struct nested *nested = wl_resource_get_user_data(resource);
624         struct nested_surface *surface;
625         
626         surface = zalloc(sizeof *surface);
627         if (surface == NULL) {
628                 wl_resource_post_no_memory(resource);
629                 return;
630         }
631
632         surface->nested = nested;
633
634         wl_list_init(&surface->frame_callback_list);
635
636         wl_list_init(&surface->pending.frame_callback_list);
637         surface->pending.buffer_destroy_listener.notify =
638                 surface_handle_pending_buffer_destroy;
639         pixman_region32_init(&surface->pending.damage);
640
641         display_acquire_window_surface(nested->display,
642                                        nested->window, NULL);
643
644         nested->renderer->surface_init(surface);
645
646         display_release_window_surface(nested->display, nested->window);
647
648         surface->resource =
649                 wl_resource_create(client, &wl_surface_interface, 1, id);
650
651         wl_resource_set_implementation(surface->resource,
652                                        &surface_interface, surface,
653                                        destroy_surface);
654
655         wl_list_insert(nested->surface_list.prev, &surface->link);
656 }
657
658 static void
659 destroy_region(struct wl_resource *resource)
660 {
661         struct nested_region *region = wl_resource_get_user_data(resource);
662
663         pixman_region32_fini(&region->region);
664         free(region);
665 }
666
667 static void
668 region_destroy(struct wl_client *client, struct wl_resource *resource)
669 {
670         wl_resource_destroy(resource);
671 }
672
673 static void
674 region_add(struct wl_client *client, struct wl_resource *resource,
675            int32_t x, int32_t y, int32_t width, int32_t height)
676 {
677         struct nested_region *region = wl_resource_get_user_data(resource);
678
679         pixman_region32_union_rect(&region->region, &region->region,
680                                    x, y, width, height);
681 }
682
683 static void
684 region_subtract(struct wl_client *client, struct wl_resource *resource,
685                 int32_t x, int32_t y, int32_t width, int32_t height)
686 {
687         struct nested_region *region = wl_resource_get_user_data(resource);
688         pixman_region32_t rect;
689
690         pixman_region32_init_rect(&rect, x, y, width, height);
691         pixman_region32_subtract(&region->region, &region->region, &rect);
692         pixman_region32_fini(&rect);
693 }
694
695 static const struct wl_region_interface region_interface = {
696         region_destroy,
697         region_add,
698         region_subtract
699 };
700
701 static void
702 compositor_create_region(struct wl_client *client,
703                          struct wl_resource *resource, uint32_t id)
704 {
705         struct nested_region *region;
706
707         region = malloc(sizeof *region);
708         if (region == NULL) {
709                 wl_resource_post_no_memory(resource);
710                 return;
711         }
712
713         pixman_region32_init(&region->region);
714
715         region->resource =
716                 wl_resource_create(client, &wl_region_interface, 1, id);
717         wl_resource_set_implementation(region->resource, &region_interface,
718                                        region, destroy_region);
719 }
720
721 static const struct wl_compositor_interface compositor_interface = {
722         compositor_create_surface,
723         compositor_create_region
724 };
725
726 static void
727 compositor_bind(struct wl_client *client,
728                 void *data, uint32_t version, uint32_t id)
729 {
730         struct nested *nested = data;
731         struct wl_resource *resource;
732
733         resource = wl_resource_create(client, &wl_compositor_interface,
734                                       MIN(version, 3), id);
735         wl_resource_set_implementation(resource, &compositor_interface,
736                                        nested, NULL);
737 }
738
739 static int
740 nested_init_compositor(struct nested *nested)
741 {
742         const char *extensions;
743         struct wl_event_loop *loop;
744         int use_ss_renderer = 0;
745         int fd, ret;
746
747         wl_list_init(&nested->surface_list);
748         nested->child_display = wl_display_create();
749         loop = wl_display_get_event_loop(nested->child_display);
750         fd = wl_event_loop_get_fd(loop);
751         nested->child_task.run = handle_child_data;
752         display_watch_fd(nested->display, fd,
753                          EPOLLIN, &nested->child_task);
754
755         if (!wl_global_create(nested->child_display,
756                               &wl_compositor_interface, 1,
757                               nested, compositor_bind))
758                 return -1;
759
760         wl_display_init_shm(nested->child_display);
761
762         nested->egl_display = display_get_egl_display(nested->display);
763         extensions = eglQueryString(nested->egl_display, EGL_EXTENSIONS);
764         if (strstr(extensions, "EGL_WL_bind_wayland_display") == NULL) {
765                 fprintf(stderr, "no EGL_WL_bind_wayland_display extension\n");
766                 return -1;
767         }
768
769         bind_display = (void *) eglGetProcAddress("eglBindWaylandDisplayWL");
770         unbind_display = (void *) eglGetProcAddress("eglUnbindWaylandDisplayWL");
771         create_image = (void *) eglGetProcAddress("eglCreateImageKHR");
772         destroy_image = (void *) eglGetProcAddress("eglDestroyImageKHR");
773         query_buffer = (void *) eglGetProcAddress("eglQueryWaylandBufferWL");
774         image_target_texture_2d =
775                 (void *) eglGetProcAddress("glEGLImageTargetTexture2DOES");
776
777         ret = bind_display(nested->egl_display, nested->child_display);
778         if (!ret) {
779                 fprintf(stderr, "failed to bind wl_display\n");
780                 return -1;
781         }
782
783         if (display_has_subcompositor(nested->display)) {
784                 const char *func = "eglCreateWaylandBufferFromImageWL";
785                 const char *ext = "EGL_WL_create_wayland_buffer_from_image";
786
787                 if (strstr(extensions, ext)) {
788                         create_wayland_buffer_from_image =
789                                 (void *) eglGetProcAddress(func);
790                         use_ss_renderer = 1;
791                 }
792         }
793
794         if (option_blit)
795                 use_ss_renderer = 0;
796
797         if (use_ss_renderer) {
798                 printf("Using subsurfaces to render client surfaces\n");
799                 nested->renderer = &nested_ss_renderer;
800         } else {
801                 printf("Using local compositing with blits to "
802                        "render client surfaces\n");
803                 nested->renderer = &nested_blit_renderer;
804         }
805
806         return 0;
807 }
808
809 static struct nested *
810 nested_create(struct display *display)
811 {
812         struct nested *nested;
813
814         nested = zalloc(sizeof *nested);
815         if (nested == NULL)
816                 return nested;
817
818         nested->window = window_create(display);
819         nested->widget = window_frame_create(nested->window, nested);
820         window_set_title(nested->window, "Wayland Nested");
821         nested->display = display;
822
823         window_set_user_data(nested->window, nested);
824         widget_set_redraw_handler(nested->widget, redraw_handler);
825         window_set_keyboard_focus_handler(nested->window,
826                                           keyboard_focus_handler);
827
828         nested_init_compositor(nested);
829
830         widget_schedule_resize(nested->widget, 400, 400);
831
832         return nested;
833 }
834
835 static void
836 nested_destroy(struct nested *nested)
837 {
838         widget_destroy(nested->widget);
839         window_destroy(nested->window);
840         free(nested);
841 }
842
843 /*** blit renderer ***/
844
845 static void
846 blit_surface_init(struct nested_surface *surface)
847 {
848         struct nested_blit_surface *blit_surface =
849                 xzalloc(sizeof *blit_surface);
850
851         glGenTextures(1, &blit_surface->texture);
852         glBindTexture(GL_TEXTURE_2D, blit_surface->texture);
853         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
854         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
855         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
856         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
857
858         surface->renderer_data = blit_surface;
859 }
860
861 static void
862 blit_surface_fini(struct nested_surface *surface)
863 {
864         struct nested_blit_surface *blit_surface = surface->renderer_data;
865
866         nested_buffer_reference(&blit_surface->buffer_ref, NULL);
867
868         glDeleteTextures(1, &blit_surface->texture);
869
870         free(blit_surface);
871 }
872
873 static void
874 blit_frame_callback(void *data, struct wl_callback *callback, uint32_t time)
875 {
876         struct nested *nested = data;
877         struct nested_surface *surface;
878
879         wl_list_for_each(surface, &nested->surface_list, link)
880                 flush_surface_frame_callback_list(surface, time);
881
882         if (callback)
883                 wl_callback_destroy(callback);
884 }
885
886 static const struct wl_callback_listener blit_frame_listener = {
887         blit_frame_callback
888 };
889
890 static void
891 blit_render_clients(struct nested *nested,
892                     cairo_t *cr)
893 {
894         struct nested_surface *s;
895         struct rectangle allocation;
896         struct wl_callback *callback;
897
898         widget_get_allocation(nested->widget, &allocation);
899
900         wl_list_for_each(s, &nested->surface_list, link) {
901                 struct nested_blit_surface *blit_surface = s->renderer_data;
902
903                 display_acquire_window_surface(nested->display,
904                                                nested->window, NULL);
905
906                 glBindTexture(GL_TEXTURE_2D, blit_surface->texture);
907                 image_target_texture_2d(GL_TEXTURE_2D, s->image);
908
909                 display_release_window_surface(nested->display,
910                                                nested->window);
911
912                 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
913                 cairo_set_source_surface(cr, blit_surface->cairo_surface,
914                                          allocation.x + 10,
915                                          allocation.y + 10);
916                 cairo_rectangle(cr, allocation.x + 10,
917                                 allocation.y + 10,
918                                 allocation.width - 10,
919                                 allocation.height - 10);
920
921                 cairo_fill(cr);
922         }
923
924         callback = wl_surface_frame(window_get_wl_surface(nested->window));
925         wl_callback_add_listener(callback, &blit_frame_listener, nested);
926 }
927
928 static void
929 blit_surface_attach(struct nested_surface *surface,
930                     struct nested_buffer *buffer)
931 {
932         struct nested *nested = surface->nested;
933         struct nested_blit_surface *blit_surface = surface->renderer_data;
934         EGLint width, height;
935         cairo_device_t *device;
936
937         nested_buffer_reference(&blit_surface->buffer_ref, buffer);
938
939         if (blit_surface->cairo_surface)
940                 cairo_surface_destroy(blit_surface->cairo_surface);
941
942         query_buffer(nested->egl_display, (void *) buffer->resource,
943                      EGL_WIDTH, &width);
944         query_buffer(nested->egl_display, (void *) buffer->resource,
945                      EGL_HEIGHT, &height);
946
947         device = display_get_cairo_device(nested->display);
948         blit_surface->cairo_surface =
949                 cairo_gl_surface_create_for_texture(device,
950                                                     CAIRO_CONTENT_COLOR_ALPHA,
951                                                     blit_surface->texture,
952                                                     width, height);
953 }
954
955 static const struct nested_renderer
956 nested_blit_renderer = {
957         .surface_init = blit_surface_init,
958         .surface_fini = blit_surface_fini,
959         .render_clients = blit_render_clients,
960         .surface_attach = blit_surface_attach
961 };
962
963 /*** subsurface renderer ***/
964
965 static void
966 ss_surface_init(struct nested_surface *surface)
967 {
968         struct nested *nested = surface->nested;
969         struct wl_compositor *compositor =
970                 display_get_compositor(nested->display);
971         struct nested_ss_surface *ss_surface =
972                 xzalloc(sizeof *ss_surface);
973         struct rectangle allocation;
974         struct wl_region *region;
975
976         ss_surface->widget =
977                 window_add_subsurface(nested->window,
978                                       nested,
979                                       SUBSURFACE_SYNCHRONIZED);
980
981         widget_set_use_cairo(ss_surface->widget, 0);
982
983         ss_surface->surface = widget_get_wl_surface(ss_surface->widget);
984         ss_surface->subsurface = widget_get_wl_subsurface(ss_surface->widget);
985
986         /* The toy toolkit gets confused about the pointer position
987          * when it gets motion events for a subsurface so we'll just
988          * disable input on it */
989         region = wl_compositor_create_region(compositor);
990         wl_surface_set_input_region(ss_surface->surface, region);
991         wl_region_destroy(region);
992
993         widget_get_allocation(nested->widget, &allocation);
994         wl_subsurface_set_position(ss_surface->subsurface,
995                                    allocation.x + 10,
996                                    allocation.y + 10);
997
998         surface->renderer_data = ss_surface;
999 }
1000
1001 static void
1002 ss_surface_fini(struct nested_surface *surface)
1003 {
1004         struct nested_ss_surface *ss_surface = surface->renderer_data;
1005
1006         widget_destroy(ss_surface->widget);
1007
1008         if (ss_surface->frame_callback)
1009                 wl_callback_destroy(ss_surface->frame_callback);
1010
1011         free(ss_surface);
1012 }
1013
1014 static void
1015 ss_render_clients(struct nested *nested,
1016                   cairo_t *cr)
1017 {
1018         /* The clients are composited by the parent compositor so we
1019          * don't need to do anything here */
1020 }
1021
1022 static void
1023 ss_buffer_release(void *data, struct wl_buffer *wl_buffer)
1024 {
1025         struct nested_buffer *buffer = data;
1026
1027         nested_buffer_reference(&buffer->parent_ref, NULL);
1028 }
1029
1030 static struct wl_buffer_listener ss_buffer_listener = {
1031    ss_buffer_release
1032 };
1033
1034 static void
1035 ss_frame_callback(void *data, struct wl_callback *callback, uint32_t time)
1036 {
1037         struct nested_surface *surface = data;
1038         struct nested_ss_surface *ss_surface = surface->renderer_data;
1039
1040         flush_surface_frame_callback_list(surface, time);
1041
1042         if (callback)
1043                 wl_callback_destroy(callback);
1044
1045         ss_surface->frame_callback = NULL;
1046 }
1047
1048 static const struct wl_callback_listener ss_frame_listener = {
1049         ss_frame_callback
1050 };
1051
1052 static void
1053 ss_surface_attach(struct nested_surface *surface,
1054                   struct nested_buffer *buffer)
1055 {
1056         struct nested *nested = surface->nested;
1057         struct nested_ss_surface *ss_surface = surface->renderer_data;
1058         struct wl_buffer *parent_buffer;
1059         const pixman_box32_t *rects;
1060         int n_rects, i;
1061
1062         if (buffer) {
1063                 /* Create a representation of the buffer in the parent
1064                  * compositor if we haven't already */
1065                 if (buffer->parent_buffer == NULL) {
1066                         EGLDisplay *edpy = nested->egl_display;
1067                         EGLImageKHR image = surface->image;
1068
1069                         buffer->parent_buffer =
1070                                 create_wayland_buffer_from_image(edpy, image);
1071
1072                         wl_buffer_add_listener(buffer->parent_buffer,
1073                                                &ss_buffer_listener,
1074                                                buffer);
1075                 }
1076
1077                 parent_buffer = buffer->parent_buffer;
1078
1079                 /* We'll take a reference to the buffer while the parent
1080                  * compositor is using it so that we won't report the release
1081                  * event until the parent has also finished with it */
1082                 nested_buffer_reference(&buffer->parent_ref, buffer);
1083         } else {
1084                 parent_buffer = NULL;
1085         }
1086
1087         wl_surface_attach(ss_surface->surface, parent_buffer, 0, 0);
1088
1089         rects = pixman_region32_rectangles(&surface->pending.damage, &n_rects);
1090
1091         for (i = 0; i < n_rects; i++) {
1092                 const pixman_box32_t *rect = rects + i;
1093                 wl_surface_damage(ss_surface->surface,
1094                                   rect->x1,
1095                                   rect->y1,
1096                                   rect->x2 - rect->x1,
1097                                   rect->y2 - rect->y1);
1098         }
1099
1100         if (ss_surface->frame_callback)
1101                 wl_callback_destroy(ss_surface->frame_callback);
1102
1103         ss_surface->frame_callback = wl_surface_frame(ss_surface->surface);
1104         wl_callback_add_listener(ss_surface->frame_callback,
1105                                  &ss_frame_listener,
1106                                  surface);
1107
1108         wl_surface_commit(ss_surface->surface);
1109 }
1110
1111 static const struct nested_renderer
1112 nested_ss_renderer = {
1113         .surface_init = ss_surface_init,
1114         .surface_fini = ss_surface_fini,
1115         .render_clients = ss_render_clients,
1116         .surface_attach = ss_surface_attach
1117 };
1118
1119 int
1120 main(int argc, char *argv[])
1121 {
1122         struct display *display;
1123         struct nested *nested;
1124
1125         parse_options(nested_options,
1126                       ARRAY_LENGTH(nested_options), &argc, argv);
1127
1128         display = display_create(&argc, argv);
1129         if (display == NULL) {
1130                 fprintf(stderr, "failed to create display: %m\n");
1131                 return -1;
1132         }
1133
1134         nested = nested_create(display);
1135
1136         launch_client(nested, "weston-nested-client");
1137
1138         display_run(display);
1139
1140         nested_destroy(nested);
1141         display_destroy(display);
1142
1143         return 0;
1144 }