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