input: Rename weston_device_repick() to weston_seat_repick()
[platform/upstream/weston.git] / src / compositor-rpi.c
1 /*
2  * Copyright © 2008-2011 Kristian Høgsberg
3  * Copyright © 2011 Intel Corporation
4  * Copyright © 2012 Raspberry Pi Foundation
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and
7  * its documentation for any purpose is hereby granted without fee, provided
8  * that the above copyright notice appear in all copies and that both that
9  * copyright notice and this permission notice appear in supporting
10  * documentation, and that the name of the copyright holders not be used in
11  * advertising or publicity pertaining to distribution of the software
12  * without specific, written prior permission.  The copyright holders make
13  * no representations about the suitability of this software for any
14  * purpose.  It is provided "as is" without express or implied warranty.
15  *
16  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
17  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
18  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
20  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
21  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
22  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23  */
24
25 #define _GNU_SOURCE
26
27 #include <errno.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <math.h>
32 #include <sys/types.h>
33 #include <fcntl.h>
34 #include <unistd.h>
35
36 #include <libudev.h>
37
38 #include "config.h"
39
40 #ifdef HAVE_BCM_HOST
41 #  include <bcm_host.h>
42 #else
43 #  include "rpi-bcm-stubs.h"
44 #endif
45
46 #include "compositor.h"
47 #include "gl-renderer.h"
48 #include "evdev.h"
49
50 /*
51  * Dispmanx API offers alpha-blended overlays for hardware compositing.
52  * The final composite consists of dispmanx elements, and their contents:
53  * the dispmanx resource assigned to the element. The elements may be
54  * scanned out directly, or composited to a temporary surface, depending on
55  * how the firmware decides to handle the scene. Updates to multiple elements
56  * may be queued in a single dispmanx update object, resulting in atomic and
57  * vblank synchronized display updates.
58  *
59  * To avoid tearing and display artifacts, the current dispmanx resource in a
60  * dispmanx element must not be touched. Therefore each element must be
61  * double-buffered, using two resources, the front and the back. The update
62  * sequence is:
63  * 0. the front resource is already in-use, the back resource is unused
64  * 1. write data into the back resource
65  * 2. submit an element update, back becomes in-use
66  * 3. swap back and front pointers (both are in-use now)
67  * 4. wait for update_submit completion, the new back resource becomes unused
68  *
69  * A resource may be destroyed only, when the update removing the element has
70  * completed. Otherwise you risk showing an incomplete composition.
71  *
72  * The dispmanx element used as the native window for EGL does not need
73  * manually allocated resources, EGL does double-buffering internally.
74  * Unfortunately it also means, that we cannot alternate between two
75  * buffers like the DRM backend does, since we have no control over what
76  * resources EGL uses. We are forced to use EGL_BUFFER_PRESERVED as the
77  * EGL_SWAP_BEHAVIOR to avoid repainting the whole output every frame.
78  *
79  * We also cannot bundle eglSwapBuffers into our own display update, which
80  * means that Weston's primary plane updates and the overlay updates may
81  * happen unsynchronized.
82  */
83
84 #ifndef ELEMENT_CHANGE_LAYER
85 /* copied from interface/vmcs_host/vc_vchi_dispmanx.h of userland.git */
86 #define ELEMENT_CHANGE_LAYER          (1<<0)
87 #define ELEMENT_CHANGE_OPACITY        (1<<1)
88 #define ELEMENT_CHANGE_DEST_RECT      (1<<2)
89 #define ELEMENT_CHANGE_SRC_RECT       (1<<3)
90 #define ELEMENT_CHANGE_MASK_RESOURCE  (1<<4)
91 #define ELEMENT_CHANGE_TRANSFORM      (1<<5)
92 #endif
93
94 /* Enabling this debugging incurs a significant performance hit */
95 #if 0
96 #define DBG(...) \
97         weston_log(__VA_ARGS__)
98 #else
99 #define DBG(...) do {} while (0)
100 #endif
101
102 /* If we had a fully featured vc_dispmanx_resource_write_data()... */
103 /*#define HAVE_RESOURCE_WRITE_DATA_RECT 1*/
104
105 struct rpi_compositor;
106 struct rpi_output;
107
108 struct rpi_resource {
109         DISPMANX_RESOURCE_HANDLE_T handle;
110         int width;
111         int height; /* height of the image (valid pixel data) */
112         int stride; /* bytes */
113         int buffer_height; /* height of the buffer */
114         VC_IMAGE_TYPE_T ifmt;
115 };
116
117 struct rpi_element {
118         struct wl_list link;
119         struct weston_plane plane;
120         struct rpi_output *output;
121
122         DISPMANX_ELEMENT_HANDLE_T handle;
123         int layer;
124         int need_swap;
125         int single_buffer;
126
127         struct rpi_resource resources[2];
128         struct rpi_resource *front;
129         struct rpi_resource *back;
130         pixman_region32_t prev_damage;
131
132         struct weston_surface *surface;
133         struct wl_listener surface_destroy_listener;
134 };
135
136 struct rpi_flippipe {
137         int readfd;
138         int writefd;
139         struct wl_event_source *source;
140 };
141
142 struct rpi_output {
143         struct rpi_compositor *compositor;
144         struct weston_output base;
145         int single_buffer;
146
147         struct weston_mode mode;
148         struct rpi_flippipe flippipe;
149
150         DISPMANX_DISPLAY_HANDLE_T display;
151         EGL_DISPMANX_WINDOW_T egl_window;
152         DISPMANX_ELEMENT_HANDLE_T egl_element;
153
154         struct wl_list element_list; /* struct rpi_element */
155         struct wl_list old_element_list; /* struct rpi_element */
156 };
157
158 struct rpi_seat {
159         struct weston_seat base;
160         struct wl_list devices_list;
161
162         struct udev_monitor *udev_monitor;
163         struct wl_event_source *udev_monitor_source;
164         char *seat_id;
165 };
166
167 struct rpi_compositor {
168         struct weston_compositor base;
169         uint32_t prev_state;
170
171         struct udev *udev;
172         struct tty *tty;
173
174         int max_planes; /* per output, really */
175         int single_buffer;
176 };
177
178 static inline struct rpi_output *
179 to_rpi_output(struct weston_output *base)
180 {
181         return container_of(base, struct rpi_output, base);
182 }
183
184 static inline struct rpi_seat *
185 to_rpi_seat(struct weston_seat *base)
186 {
187         return container_of(base, struct rpi_seat, base);
188 }
189
190 static inline struct rpi_compositor *
191 to_rpi_compositor(struct weston_compositor *base)
192 {
193         return container_of(base, struct rpi_compositor, base);
194 }
195
196 static inline int
197 int_max(int a, int b)
198 {
199         return a > b ? a : b;
200 }
201
202 static void
203 rpi_resource_init(struct rpi_resource *resource)
204 {
205         resource->handle = DISPMANX_NO_HANDLE;
206 }
207
208 static void
209 rpi_resource_release(struct rpi_resource *resource)
210 {
211         if (resource->handle == DISPMANX_NO_HANDLE)
212                 return;
213
214         vc_dispmanx_resource_delete(resource->handle);
215         DBG("resource %p release\n", resource);
216         resource->handle = DISPMANX_NO_HANDLE;
217 }
218
219 static int
220 rpi_resource_realloc(struct rpi_resource *resource, VC_IMAGE_TYPE_T ifmt,
221                      int width, int height, int stride, int buffer_height)
222 {
223         uint32_t dummy;
224
225         if (resource->handle != DISPMANX_NO_HANDLE &&
226             resource->width == width &&
227             resource->height == height &&
228             resource->stride == stride &&
229             resource->buffer_height == buffer_height &&
230             resource->ifmt == ifmt)
231                 return 0;
232
233         rpi_resource_release(resource);
234
235         /* NOTE: if stride is not a multiple of 16 pixels in bytes,
236          * the vc_image_* functions may break. Dispmanx elements
237          * should be fine, though. Buffer_height probably has similar
238          * constraints, too.
239          */
240         resource->handle =
241                 vc_dispmanx_resource_create(ifmt,
242                                             width | (stride << 16),
243                                             height | (buffer_height << 16),
244                                             &dummy);
245         if (resource->handle == DISPMANX_NO_HANDLE)
246                 return -1;
247
248         resource->width = width;
249         resource->height = height;
250         resource->stride = stride;
251         resource->buffer_height = buffer_height;
252         resource->ifmt = ifmt;
253         DBG("resource %p alloc\n", resource);
254         return 0;
255 }
256
257 static VC_IMAGE_TYPE_T
258 shm_buffer_get_vc_format(struct wl_buffer *buffer)
259 {
260         switch (wl_shm_buffer_get_format(buffer)) {
261         case WL_SHM_FORMAT_XRGB8888:
262                 return VC_IMAGE_XRGB8888;
263         case WL_SHM_FORMAT_ARGB8888:
264                 return VC_IMAGE_ARGB8888;
265         default:
266                 /* invalid format */
267                 return VC_IMAGE_MIN;
268         }
269 }
270
271 static int
272 rpi_resource_update(struct rpi_resource *resource, struct wl_buffer *buffer,
273                     pixman_region32_t *region)
274 {
275         pixman_region32_t write_region;
276         pixman_box32_t *r;
277         VC_RECT_T rect;
278         VC_IMAGE_TYPE_T ifmt;
279         uint32_t *pixels;
280         int width;
281         int height;
282         int stride;
283         int ret;
284 #ifdef HAVE_RESOURCE_WRITE_DATA_RECT
285         int n;
286 #endif
287
288         if (!buffer)
289                 return -1;
290
291         ifmt = shm_buffer_get_vc_format(buffer);
292         width = wl_shm_buffer_get_width(buffer);
293         height = wl_shm_buffer_get_height(buffer);
294         stride = wl_shm_buffer_get_stride(buffer);
295         pixels = wl_shm_buffer_get_data(buffer);
296
297         if (rpi_resource_realloc(resource, ifmt, width, height,
298                                  stride, height) < 0)
299                 return -1;
300
301         pixman_region32_init(&write_region);
302         pixman_region32_intersect_rect(&write_region, region,
303                                        0, 0, width, height);
304
305 #ifdef HAVE_RESOURCE_WRITE_DATA_RECT
306         /* XXX: Can this do a format conversion, so that scanout does not have to? */
307         r = pixman_region32_rectangles(&write_region, &n);
308         while (n--) {
309                 vc_dispmanx_rect_set(&rect, r[n].x1, r[n].y1,
310                                      r[n].x2 - r[n].x1, r[n].y2 - r[n].y1);
311
312                 ret = vc_dispmanx_resource_write_data_rect(resource->handle,
313                                                            ifmt, stride,
314                                                            pixels, &rect,
315                                                            rect.x, rect.y);
316                 DBG("%s: %p %ux%u@%u,%u, ret %d\n", __func__, resource,
317                     rect.width, rect.height, rect.x, rect.y, ret);
318                 if (ret)
319                         break;
320         }
321 #else
322         /* vc_dispmanx_resource_write_data() ignores ifmt,
323          * rect.x, rect.width, and uses stride only for computing
324          * the size of the transfer as rect.height * stride.
325          * Therefore we can only write rows starting at x=0.
326          * To be able to write more than one scanline at a time,
327          * the resource must have been created with the same stride
328          * as used here, and we must write full scanlines.
329          */
330
331         r = pixman_region32_extents(&write_region);
332         vc_dispmanx_rect_set(&rect, 0, r->y1, width, r->y2 - r->y1);
333         ret = vc_dispmanx_resource_write_data(resource->handle, ifmt,
334                                                stride, pixels, &rect);
335         DBG("%s: %p %ux%u@%u,%u, ret %d\n", __func__, resource,
336             width, r->y2 - r->y1, 0, r->y1, ret);
337 #endif
338
339         pixman_region32_fini(&write_region);
340
341         return ret ? -1 : 0;
342 }
343
344 static void
345 rpi_element_handle_surface_destroy(struct wl_listener *listener, void *data)
346 {
347         struct rpi_element *element =
348                 container_of(listener, struct rpi_element,
349                              surface_destroy_listener);
350
351         element->surface = NULL;
352 }
353
354 static struct rpi_element *
355 rpi_element_create(struct rpi_output *output, struct weston_surface *surface)
356 {
357         struct rpi_element *element;
358
359         element = calloc(1, sizeof *element);
360         if (!element)
361                 return NULL;
362
363         element->output = output;
364         element->single_buffer = output->single_buffer;
365         element->handle = DISPMANX_NO_HANDLE;
366         rpi_resource_init(&element->resources[0]);
367         rpi_resource_init(&element->resources[1]);
368         element->front = &element->resources[0];
369
370         if (element->single_buffer) {
371                 element->back = element->front;
372         } else {
373                 element->back = &element->resources[1];
374         }
375
376         pixman_region32_init(&element->prev_damage);
377
378         weston_plane_init(&element->plane, floor(surface->geometry.x),
379                           floor(surface->geometry.y));
380
381         element->surface = surface;
382         element->surface_destroy_listener.notify =
383                 rpi_element_handle_surface_destroy;
384         wl_signal_add(&surface->surface.resource.destroy_signal,
385                       &element->surface_destroy_listener);
386
387         wl_list_insert(output->element_list.prev, &element->link);
388
389         return element;
390 }
391
392 static void
393 rpi_element_destroy(struct rpi_element *element)
394 {
395         struct weston_surface *surface = element->surface;
396
397         if (surface) {
398                 if (surface->plane == &element->plane) {
399                         /* If a surface, that was on a plane, gets hidden,
400                          * it will not appear in the repaint surface list,
401                          * is never considered in rpi_output_assign_planes(),
402                          * and hence can stay assigned to this element's plane.
403                          * We need to reassign it here.
404                          */
405                         DBG("surface %p (%dx%d@%.1f,%.1f) to primary plane*\n",
406                             surface,
407                             surface->geometry.width, surface->geometry.height,
408                             surface->geometry.x, surface->geometry.y);
409                         weston_surface_move_to_plane(surface,
410                                 &surface->compositor->primary_plane);
411                 }
412                 wl_list_remove(&element->surface_destroy_listener.link);
413         }
414
415         wl_list_remove(&element->link);
416         weston_plane_release(&element->plane);
417
418         if (element->handle != DISPMANX_NO_HANDLE)
419                 weston_log("ERROR rpi: destroying on-screen element\n");
420
421         pixman_region32_fini(&element->prev_damage);
422         rpi_resource_release(&element->resources[0]);
423         rpi_resource_release(&element->resources[1]);
424         DBG("element %p destroyed (%u)\n", element, element->handle);
425
426         free(element);
427 }
428
429 static void
430 rpi_element_reuse(struct rpi_element *element)
431 {
432         wl_list_remove(&element->link);
433         wl_list_insert(element->output->element_list.prev, &element->link);
434 }
435
436 static void
437 rpi_element_schedule_destroy(struct rpi_element *element)
438 {
439         wl_list_remove(&element->link);
440         wl_list_insert(element->output->old_element_list.prev,
441                        &element->link);
442 }
443
444 static int
445 rpi_element_damage(struct rpi_element *element, struct wl_buffer *buffer,
446                    pixman_region32_t *damage)
447 {
448         pixman_region32_t upload;
449         int ret;
450
451         if (!pixman_region32_not_empty(damage))
452                 return 0;
453
454         DBG("element %p update resource %p\n", element, element->back);
455
456         if (element->single_buffer) {
457                 ret = rpi_resource_update(element->back, buffer, damage);
458         } else {
459                 pixman_region32_init(&upload);
460                 pixman_region32_union(&upload, &element->prev_damage, damage);
461                 ret = rpi_resource_update(element->back, buffer, &upload);
462                 pixman_region32_fini(&upload);
463         }
464
465         pixman_region32_copy(&element->prev_damage, damage);
466         element->need_swap = 1;
467
468         return ret;
469 }
470
471 static void
472 rpi_element_compute_rects(struct rpi_element *element,
473                           VC_RECT_T *src_rect, VC_RECT_T *dst_rect)
474 {
475         struct weston_output *output = &element->output->base;
476         int src_x, src_y;
477         int dst_x, dst_y;
478         int width, height;
479
480         /* assume element->plane.{x,y} == element->surface->geometry.{x,y} */
481         src_x = 0;
482         src_y = 0;
483         width = element->surface->geometry.width;
484         height = element->surface->geometry.height;
485
486         dst_x = element->plane.x - output->x;
487         dst_y = element->plane.y - output->y;
488
489         if (dst_x < 0) {
490                 width += dst_x;
491                 src_x -= dst_x;
492                 dst_x = 0;
493         }
494
495         if (dst_y < 0) {
496                 height += dst_y;
497                 src_y -= dst_y;
498                 dst_y = 0;
499         }
500
501         width = int_max(width, 0);
502         height = int_max(height, 0);
503
504         /* src_rect is in 16.16, dst_rect is in 32.0 unsigned fixed point */
505         vc_dispmanx_rect_set(src_rect, src_x << 16, src_y << 16,
506                              width << 16, height << 16);
507         vc_dispmanx_rect_set(dst_rect, dst_x, dst_y, width, height);
508 }
509
510 static void
511 rpi_element_dmx_add(struct rpi_element *element,
512                     DISPMANX_UPDATE_HANDLE_T update, int layer)
513 {
514         VC_DISPMANX_ALPHA_T alphasetup = {
515                 DISPMANX_FLAGS_ALPHA_FROM_SOURCE | DISPMANX_FLAGS_ALPHA_PREMULT,
516                 255, /* opacity 0-255 */
517                 0 /* mask resource handle */
518         };
519         VC_RECT_T dst_rect;
520         VC_RECT_T src_rect;
521
522         rpi_element_compute_rects(element, &src_rect, &dst_rect);
523
524         element->handle = vc_dispmanx_element_add(
525                 update,
526                 element->output->display,
527                 layer,
528                 &dst_rect,
529                 element->back->handle,
530                 &src_rect,
531                 DISPMANX_PROTECTION_NONE,
532                 &alphasetup,
533                 NULL /* clamp */,
534                 DISPMANX_NO_ROTATE);
535         DBG("element %p add %u\n", element, element->handle);
536 }
537
538 static void
539 rpi_element_dmx_swap(struct rpi_element *element,
540                      DISPMANX_UPDATE_HANDLE_T update)
541 {
542         VC_RECT_T rect;
543         pixman_box32_t *r;
544
545         /* XXX: skip, iff resource was not reallocated, and single-buffering */
546         vc_dispmanx_element_change_source(update, element->handle,
547                                           element->back->handle);
548
549         /* This is current damage now, after rpi_assign_plane() */
550         r = pixman_region32_extents(&element->prev_damage);
551
552         vc_dispmanx_rect_set(&rect, r->x1, r->y1,
553                              r->x2 - r->x1, r->y2 - r->y1);
554         vc_dispmanx_element_modified(update, element->handle, &rect);
555         DBG("element %p swap\n", element);
556 }
557
558 static void
559 rpi_element_dmx_move(struct rpi_element *element,
560                      DISPMANX_UPDATE_HANDLE_T update, int layer)
561 {
562         VC_RECT_T dst_rect;
563         VC_RECT_T src_rect;
564
565         /* XXX: return early, if all attributes stay the same */
566
567         rpi_element_compute_rects(element, &src_rect, &dst_rect);
568
569         vc_dispmanx_element_change_attributes(
570                 update,
571                 element->handle,
572                 ELEMENT_CHANGE_LAYER |
573                         ELEMENT_CHANGE_DEST_RECT |
574                         ELEMENT_CHANGE_SRC_RECT,
575                 layer,
576                 255,
577                 &dst_rect,
578                 &src_rect,
579                 DISPMANX_NO_HANDLE,
580                 VC_IMAGE_ROT0);
581         DBG("element %p move\n", element);
582 }
583
584 static int
585 rpi_element_update(struct rpi_element *element,
586                    DISPMANX_UPDATE_HANDLE_T update, int layer)
587 {
588         struct rpi_resource *tmp;
589
590         if (element->handle == DISPMANX_NO_HANDLE) {
591                 /* need_swap is already true, see rpi_assign_plane() */
592
593                 rpi_element_dmx_add(element, update, layer);
594                 if (element->handle == DISPMANX_NO_HANDLE)
595                         weston_log("ERROR rpi: element_add() failed.\n");
596         } else {
597                 if (element->need_swap)
598                         rpi_element_dmx_swap(element, update);
599                 rpi_element_dmx_move(element, update, layer);
600         }
601         element->layer = layer;
602
603         if (element->need_swap) {
604                 tmp = element->front;
605                 element->front = element->back;
606                 element->back = tmp;
607                 element->need_swap = 0;
608                 DBG("new back %p, new front %p\n",
609                     element->back, element->front);
610         }
611
612         return 0;
613 }
614
615 static uint64_t
616 rpi_get_current_time(void)
617 {
618         struct timeval tv;
619
620         /* XXX: use CLOCK_MONOTONIC instead? */
621         gettimeofday(&tv, NULL);
622         return (uint64_t)tv.tv_sec * 1000 + tv.tv_usec / 1000;
623 }
624
625 static void
626 rpi_flippipe_update_complete(DISPMANX_UPDATE_HANDLE_T update, void *data)
627 {
628         /* This function runs in a different thread. */
629         struct rpi_flippipe *flippipe = data;
630         uint64_t time;
631         ssize_t ret;
632
633         /* manufacture flip completion timestamp */
634         time = rpi_get_current_time();
635
636         ret = write(flippipe->writefd, &time, sizeof time);
637         if (ret != sizeof time)
638                 weston_log("ERROR: %s failed to write, ret %zd, errno %d\n",
639                            __func__, ret, errno);
640 }
641
642 static int
643 rpi_dispmanx_update_submit(DISPMANX_UPDATE_HANDLE_T update,
644                            struct rpi_output *output)
645 {
646         /*
647          * The callback registered here will eventually be called
648          * in a different thread context. Therefore we cannot call
649          * the usual functions from rpi_flippipe_update_complete().
650          * Instead, we have a pipe for passing the message from the
651          * thread, waking up the Weston main event loop, calling
652          * rpi_flippipe_handler(), and then ending up in
653          * rpi_output_update_complete() in the main thread context,
654          * where we can do the frame finishing work.
655          */
656         return vc_dispmanx_update_submit(update, rpi_flippipe_update_complete,
657                                          &output->flippipe);
658 }
659
660 static void
661 rpi_output_update_complete(struct rpi_output *output, uint64_t time);
662
663 static int
664 rpi_flippipe_handler(int fd, uint32_t mask, void *data)
665 {
666         struct rpi_output *output = data;
667         ssize_t ret;
668         uint64_t time;
669
670         if (mask != WL_EVENT_READABLE)
671                 weston_log("ERROR: unexpected mask 0x%x in %s\n",
672                            mask, __func__);
673
674         ret = read(fd, &time, sizeof time);
675         if (ret != sizeof time) {
676                 weston_log("ERROR: %s failed to read, ret %zd, errno %d\n",
677                            __func__, ret, errno);
678         }
679
680         rpi_output_update_complete(output, time);
681
682         return 1;
683 }
684
685 static int
686 rpi_flippipe_init(struct rpi_flippipe *flippipe, struct rpi_output *output)
687 {
688         struct wl_event_loop *loop;
689         int fd[2];
690
691         if (pipe2(fd, O_CLOEXEC) == -1)
692                 return -1;
693
694         flippipe->readfd = fd[0];
695         flippipe->writefd = fd[1];
696
697         loop = wl_display_get_event_loop(output->compositor->base.wl_display);
698         flippipe->source = wl_event_loop_add_fd(loop, flippipe->readfd,
699                                                 WL_EVENT_READABLE,
700                                                 rpi_flippipe_handler, output);
701
702         if (!flippipe->source) {
703                 close(flippipe->readfd);
704                 close(flippipe->writefd);
705                 return -1;
706         }
707
708         return 0;
709 }
710
711 static void
712 rpi_flippipe_release(struct rpi_flippipe *flippipe)
713 {
714         wl_event_source_remove(flippipe->source);
715         close(flippipe->readfd);
716         close(flippipe->writefd);
717 }
718
719 static struct rpi_element *
720 find_rpi_element_from_surface(struct weston_surface *surface)
721 {
722         struct wl_listener *listener;
723         struct rpi_element *element;
724
725         listener = wl_signal_get(&surface->surface.resource.destroy_signal,
726                                  rpi_element_handle_surface_destroy);
727         if (!listener)
728                 return NULL;
729
730         element = container_of(listener, struct rpi_element,
731                                surface_destroy_listener);
732
733         if (element->surface != surface)
734                 weston_log("ERROR rpi: sanity check failure in %s.\n",
735                            __func__);
736
737         return element;
738 }
739
740 static struct rpi_element *
741 rpi_assign_plane(struct weston_surface *surface, struct rpi_output *output)
742 {
743         struct rpi_element *element;
744
745         /* dispmanx elements cannot transform */
746         if (surface->transform.enabled) {
747                 /* XXX: inspect the transformation matrix, we might still
748                  * be able to put it into an element; scaling, additional
749                  * translation (window titlebar context menus?)
750                  */
751                 DBG("surface %p rejected: transform\n", surface);
752                 return NULL;
753         }
754
755         /* only shm surfaces supported */
756         if (surface->buffer_ref.buffer &&
757             !wl_buffer_is_shm(surface->buffer_ref.buffer)) {
758                 DBG("surface %p rejected: not shm\n", surface);
759                 return NULL;
760         }
761
762         if (surface->buffer_transform != WL_OUTPUT_TRANSFORM_NORMAL) {
763                 DBG("surface %p rejected: unsupported buffer transform\n",
764                     surface);
765                 return NULL;
766         }
767
768         /* check if this surface previously belonged to an element */
769         element = find_rpi_element_from_surface(surface);
770
771         if (element) {
772                 rpi_element_reuse(element);
773                 element->plane.x = floor(surface->geometry.x);
774                 element->plane.y = floor(surface->geometry.y);
775                 DBG("surface %p reuse element %p\n", surface, element);
776         } else {
777                 if (!surface->buffer_ref.buffer) {
778                         DBG("surface %p rejected: no buffer\n", surface);
779                         return NULL;
780                 }
781
782                 element = rpi_element_create(output, surface);
783                 DBG("element %p created\n", element);
784         }
785
786         if (!element) {
787                 DBG("surface %p rejected: no element\n", surface);
788                 return NULL;
789         }
790
791         return element;
792 }
793
794 static void
795 rpi_output_assign_planes(struct weston_output *base)
796 {
797         struct rpi_output *output = to_rpi_output(base);
798         struct rpi_compositor *compositor = output->compositor;
799         struct weston_surface *surface;
800         pixman_region32_t overlap;
801         pixman_region32_t surface_overlap;
802         struct rpi_element *element;
803         int n = 0;
804
805         /* Construct the list of rpi_elements to be used into
806          * output->element_list, which is empty right now.
807          * Re-used elements are moved from old_element_list to
808          * element_list. */
809
810         DBG("%s\n", __func__);
811
812         pixman_region32_init(&overlap);
813         wl_list_for_each(surface, &compositor->base.surface_list, link) {
814                 /* always, since all buffers are shm on rpi */
815                 surface->keep_buffer = 1;
816
817                 pixman_region32_init(&surface_overlap);
818                 pixman_region32_intersect(&surface_overlap, &overlap,
819                                           &surface->transform.boundingbox);
820
821                 element = NULL;
822                 if (!pixman_region32_not_empty(&surface_overlap) &&
823                     n < compositor->max_planes)
824                         element = rpi_assign_plane(surface, output);
825
826                 if (element) {
827                         weston_surface_move_to_plane(surface, &element->plane);
828                         DBG("surface %p (%dx%d@%.1f,%.1f) to element %p\n",
829                             surface,
830                             surface->geometry.width, surface->geometry.height,
831                             surface->geometry.x, surface->geometry.y, element);
832
833                         /* weston_surface_move_to_plane() does full-surface
834                          * damage, if the plane is new, so no need to force
835                          * initial resource update.
836                          */
837                         if (rpi_element_damage(element,
838                                                surface->buffer_ref.buffer,
839                                                &surface->damage) < 0) {
840                                 rpi_element_schedule_destroy(element);
841                                 DBG("surface %p rejected: resource update failed\n",
842                                     surface);
843                                 element = NULL;
844                         } else {
845                                 n++;
846                         }
847                 }
848
849                 if (!element) {
850                         weston_surface_move_to_plane(surface,
851                                         &compositor->base.primary_plane);
852                         DBG("surface %p (%dx%d@%.1f,%.1f) to primary plane\n",
853                             surface,
854                             surface->geometry.width, surface->geometry.height,
855                             surface->geometry.x, surface->geometry.y);
856                         pixman_region32_union(&overlap, &overlap,
857                                               &surface->transform.boundingbox);
858                 }
859
860                 pixman_region32_fini(&surface_overlap);
861         }
862         pixman_region32_fini(&overlap);
863 }
864
865 static void
866 rpi_remove_elements(struct wl_list *element_list,
867                     DISPMANX_UPDATE_HANDLE_T update)
868 {
869         struct rpi_element *element;
870
871         wl_list_for_each(element, element_list, link) {
872                 if (element->handle == DISPMANX_NO_HANDLE)
873                         continue;
874
875                 vc_dispmanx_element_remove(update, element->handle);
876                 DBG("element %p remove %u\n", element, element->handle);
877                 element->handle = DISPMANX_NO_HANDLE;
878         }
879 }
880
881 static void
882 rpi_output_destroy_old_elements(struct rpi_output *output)
883 {
884         struct rpi_element *element, *tmp;
885
886         wl_list_for_each_safe(element, tmp, &output->old_element_list, link) {
887                 if (element->handle != DISPMANX_NO_HANDLE)
888                         continue;
889
890                 rpi_element_destroy(element);
891         }
892 }
893
894 static void
895 rpi_output_start_repaint_loop(struct weston_output *output)
896 {
897         uint64_t time;
898
899         time = rpi_get_current_time();
900         weston_output_finish_frame(output, time);
901 }
902
903 static void
904 rpi_output_repaint(struct weston_output *base, pixman_region32_t *damage)
905 {
906         struct rpi_output *output = to_rpi_output(base);
907         struct rpi_compositor *compositor = output->compositor;
908         struct weston_plane *primary_plane = &compositor->base.primary_plane;
909         struct rpi_element *element;
910         DISPMANX_UPDATE_HANDLE_T update;
911         int layer = 10000;
912
913         DBG("%s\n", __func__);
914
915         update = vc_dispmanx_update_start(0);
916
917         /* update all live elements */
918         wl_list_for_each(element, &output->element_list, link) {
919                 if (rpi_element_update(element, update, layer--) < 0)
920                         weston_log("ERROR rpi: element update failed.\n");
921         }
922
923         /* remove all unused elements */
924         rpi_remove_elements(&output->old_element_list, update);
925
926         /* schedule callback to rpi_output_update_complete() */
927         rpi_dispmanx_update_submit(update, output);
928
929         /* XXX: if there is anything to composite in GL,
930          * framerate seems to suffer */
931         /* XXX: optimise the renderer for the case of nothing to render */
932         /* XXX: if nothing to render, remove the element...
933          * but how, is destroying the EGLSurface a bad performance hit?
934          */
935         compositor->base.renderer->repaint_output(&output->base, damage);
936
937         pixman_region32_subtract(&primary_plane->damage,
938                                  &primary_plane->damage, damage);
939
940         /* Move the list of elements into the old_element_list. */
941         wl_list_insert_list(&output->old_element_list, &output->element_list);
942         wl_list_init(&output->element_list);
943 }
944
945 static void
946 rpi_output_update_complete(struct rpi_output *output, uint64_t time)
947 {
948         rpi_output_destroy_old_elements(output);
949         weston_output_finish_frame(&output->base, time);
950 }
951
952 static void
953 rpi_output_destroy(struct weston_output *base)
954 {
955         struct rpi_output *output = to_rpi_output(base);
956         DISPMANX_UPDATE_HANDLE_T update;
957         struct rpi_element *element, *tmp;
958
959         DBG("%s\n", __func__);
960
961         rpi_flippipe_release(&output->flippipe);
962
963         update = vc_dispmanx_update_start(0);
964         rpi_remove_elements(&output->element_list, update);
965         rpi_remove_elements(&output->old_element_list, update);
966         vc_dispmanx_element_remove(update, output->egl_element);
967         vc_dispmanx_update_submit_sync(update);
968
969         gl_renderer_output_destroy(base);
970
971         wl_list_for_each_safe(element, tmp, &output->element_list, link)
972                 rpi_element_destroy(element);
973
974         wl_list_for_each_safe(element, tmp, &output->old_element_list, link)
975                 rpi_element_destroy(element);
976
977         wl_list_remove(&output->base.link);
978         weston_output_destroy(&output->base);
979
980         vc_dispmanx_display_close(output->display);
981
982         free(output);
983 }
984
985 static int
986 rpi_output_create(struct rpi_compositor *compositor)
987 {
988         struct rpi_output *output;
989         DISPMANX_MODEINFO_T modeinfo;
990         DISPMANX_UPDATE_HANDLE_T update;
991         VC_RECT_T dst_rect;
992         VC_RECT_T src_rect;
993         int ret;
994         float mm_width, mm_height;
995         VC_DISPMANX_ALPHA_T alphasetup = {
996                 DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS,
997                 255, /* opacity 0-255 */
998                 0 /* mask resource handle */
999         };
1000
1001         output = calloc(1, sizeof *output);
1002         if (!output)
1003                 return -1;
1004
1005         output->compositor = compositor;
1006         output->single_buffer = compositor->single_buffer;
1007         wl_list_init(&output->element_list);
1008         wl_list_init(&output->old_element_list);
1009
1010         if (rpi_flippipe_init(&output->flippipe, output) < 0) {
1011                 weston_log("Creating message pipe failed.\n");
1012                 goto out_free;
1013         }
1014
1015         output->display = vc_dispmanx_display_open(DISPMANX_ID_HDMI);
1016         if (!output->display) {
1017                 weston_log("Failed to open dispmanx HDMI display.\n");
1018                 goto out_pipe;
1019         }
1020
1021         ret = vc_dispmanx_display_get_info(output->display, &modeinfo);
1022         if (ret < 0) {
1023                 weston_log("Failed to get display mode information.\n");
1024                 goto out_dmx_close;
1025         }
1026
1027         vc_dispmanx_rect_set(&dst_rect, 0, 0, modeinfo.width, modeinfo.height);
1028         vc_dispmanx_rect_set(&src_rect, 0, 0,
1029                              modeinfo.width << 16, modeinfo.height << 16);
1030
1031         update = vc_dispmanx_update_start(0);
1032         output->egl_element = vc_dispmanx_element_add(update,
1033                                                       output->display,
1034                                                       0 /* layer */,
1035                                                       &dst_rect,
1036                                                       0 /* src resource */,
1037                                                       &src_rect,
1038                                                       DISPMANX_PROTECTION_NONE,
1039                                                       &alphasetup,
1040                                                       NULL /* clamp */,
1041                                                       DISPMANX_NO_ROTATE);
1042         vc_dispmanx_update_submit_sync(update);
1043
1044         output->egl_window.element = output->egl_element;
1045         output->egl_window.width = modeinfo.width;
1046         output->egl_window.height = modeinfo.height;
1047
1048         output->base.start_repaint_loop = rpi_output_start_repaint_loop;
1049         output->base.repaint = rpi_output_repaint;
1050         output->base.destroy = rpi_output_destroy;
1051         if (compositor->max_planes > 0)
1052                 output->base.assign_planes = rpi_output_assign_planes;
1053         output->base.set_backlight = NULL;
1054         output->base.set_dpms = NULL;
1055         output->base.switch_mode = NULL;
1056
1057         /* XXX: use tvservice to get information from and control the
1058          * HDMI and SDTV outputs. See:
1059          * /opt/vc/include/interface/vmcs_host/vc_tvservice.h
1060          */
1061
1062         /* only one static mode in list */
1063         output->mode.flags =
1064                 WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
1065         output->mode.width = modeinfo.width;
1066         output->mode.height = modeinfo.height;
1067         output->mode.refresh = 60000;
1068         wl_list_init(&output->base.mode_list);
1069         wl_list_insert(&output->base.mode_list, &output->mode.link);
1070
1071         output->base.current = &output->mode;
1072         output->base.origin = &output->mode;
1073         output->base.subpixel = WL_OUTPUT_SUBPIXEL_UNKNOWN;
1074         output->base.make = "unknown";
1075         output->base.model = "unknown";
1076
1077         /* guess 96 dpi */
1078         mm_width  = modeinfo.width * (25.4f / 96.0f);
1079         mm_height = modeinfo.height * (25.4f / 96.0f);
1080
1081         weston_output_init(&output->base, &compositor->base,
1082                            0, 0, round(mm_width), round(mm_height),
1083                            WL_OUTPUT_TRANSFORM_NORMAL);
1084
1085         if (gl_renderer_output_create(&output->base,
1086                         (EGLNativeWindowType)&output->egl_window) < 0)
1087                 goto out_output;
1088
1089         if (!eglSurfaceAttrib(gl_renderer_display(&compositor->base),
1090                               gl_renderer_output_surface(&output->base),
1091                               EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED)) {
1092                 weston_log("Failed to set swap behaviour to preserved.\n");
1093                 gl_renderer_print_egl_error_state();
1094                 goto out_gl;
1095         }
1096
1097         wl_list_insert(compositor->base.output_list.prev, &output->base.link);
1098
1099         weston_log("Raspberry Pi HDMI output %dx%d px\n",
1100                    output->mode.width, output->mode.height);
1101         weston_log_continue(STAMP_SPACE "guessing %d Hz and 96 dpi\n",
1102                             output->mode.refresh / 1000);
1103
1104         return 0;
1105
1106 out_gl:
1107         gl_renderer_output_destroy(&output->base);
1108 out_output:
1109         weston_output_destroy(&output->base);
1110         update = vc_dispmanx_update_start(0);
1111         vc_dispmanx_element_remove(update, output->egl_element);
1112         vc_dispmanx_update_submit_sync(update);
1113
1114 out_dmx_close:
1115         vc_dispmanx_display_close(output->display);
1116
1117 out_pipe:
1118         rpi_flippipe_release(&output->flippipe);
1119
1120 out_free:
1121         free(output);
1122         return -1;
1123 }
1124
1125 static void
1126 rpi_led_update(struct weston_seat *seat_base, enum weston_led leds)
1127 {
1128         struct rpi_seat *seat = to_rpi_seat(seat_base);
1129         struct evdev_device *device;
1130
1131         wl_list_for_each(device, &seat->devices_list, link)
1132                 evdev_led_update(device, leds);
1133 }
1134
1135 static const char default_seat[] = "seat0";
1136
1137 static void
1138 device_added(struct udev_device *udev_device, struct rpi_seat *master)
1139 {
1140         struct evdev_device *device;
1141         const char *devnode;
1142         const char *device_seat;
1143         int fd;
1144
1145         device_seat = udev_device_get_property_value(udev_device, "ID_SEAT");
1146         if (!device_seat)
1147                 device_seat = default_seat;
1148
1149         if (strcmp(device_seat, master->seat_id))
1150                 return;
1151
1152         devnode = udev_device_get_devnode(udev_device);
1153
1154         /* Use non-blocking mode so that we can loop on read on
1155          * evdev_device_data() until all events on the fd are
1156          * read.  mtdev_get() also expects this. */
1157         fd = open(devnode, O_RDWR | O_NONBLOCK | O_CLOEXEC);
1158         if (fd < 0) {
1159                 weston_log("opening input device '%s' failed.\n", devnode);
1160                 return;
1161         }
1162
1163         device = evdev_device_create(&master->base, devnode, fd);
1164         if (!device) {
1165                 close(fd);
1166                 weston_log("not using input device '%s'.\n", devnode);
1167                 return;
1168         }
1169
1170         wl_list_insert(master->devices_list.prev, &device->link);
1171 }
1172
1173 static void
1174 evdev_add_devices(struct udev *udev, struct weston_seat *seat_base)
1175 {
1176         struct rpi_seat *seat = to_rpi_seat(seat_base);
1177         struct udev_enumerate *e;
1178         struct udev_list_entry *entry;
1179         struct udev_device *device;
1180         const char *path, *sysname;
1181
1182         e = udev_enumerate_new(udev);
1183         udev_enumerate_add_match_subsystem(e, "input");
1184         udev_enumerate_scan_devices(e);
1185         udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
1186                 path = udev_list_entry_get_name(entry);
1187                 device = udev_device_new_from_syspath(udev, path);
1188
1189                 sysname = udev_device_get_sysname(device);
1190                 if (strncmp("event", sysname, 5) != 0) {
1191                         udev_device_unref(device);
1192                         continue;
1193                 }
1194
1195                 device_added(device, seat);
1196
1197                 udev_device_unref(device);
1198         }
1199         udev_enumerate_unref(e);
1200
1201         evdev_notify_keyboard_focus(&seat->base, &seat->devices_list);
1202
1203         if (wl_list_empty(&seat->devices_list)) {
1204                 weston_log(
1205                         "warning: no input devices on entering Weston. "
1206                         "Possible causes:\n"
1207                         "\t- no permissions to read /dev/input/event*\n"
1208                         "\t- seats misconfigured "
1209                         "(Weston backend option 'seat', "
1210                         "udev device property ID_SEAT)\n");
1211         }
1212 }
1213
1214 static int
1215 evdev_udev_handler(int fd, uint32_t mask, void *data)
1216 {
1217         struct rpi_seat *seat = data;
1218         struct udev_device *udev_device;
1219         struct evdev_device *device, *next;
1220         const char *action;
1221         const char *devnode;
1222
1223         udev_device = udev_monitor_receive_device(seat->udev_monitor);
1224         if (!udev_device)
1225                 return 1;
1226
1227         action = udev_device_get_action(udev_device);
1228         if (!action)
1229                 goto out;
1230
1231         if (strncmp("event", udev_device_get_sysname(udev_device), 5) != 0)
1232                 goto out;
1233
1234         if (!strcmp(action, "add")) {
1235                 device_added(udev_device, seat);
1236         }
1237         else if (!strcmp(action, "remove")) {
1238                 devnode = udev_device_get_devnode(udev_device);
1239                 wl_list_for_each_safe(device, next, &seat->devices_list, link)
1240                         if (!strcmp(device->devnode, devnode)) {
1241                                 weston_log("input device %s, %s removed\n",
1242                                            device->devname, device->devnode);
1243                                 evdev_device_destroy(device);
1244                                 break;
1245                         }
1246         }
1247
1248 out:
1249         udev_device_unref(udev_device);
1250
1251         return 0;
1252 }
1253
1254 static int
1255 evdev_enable_udev_monitor(struct udev *udev, struct weston_seat *seat_base)
1256 {
1257         struct rpi_seat *master = to_rpi_seat(seat_base);
1258         struct wl_event_loop *loop;
1259         struct weston_compositor *c = master->base.compositor;
1260         int fd;
1261
1262         master->udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
1263         if (!master->udev_monitor) {
1264                 weston_log("udev: failed to create the udev monitor\n");
1265                 return 0;
1266         }
1267
1268         udev_monitor_filter_add_match_subsystem_devtype(master->udev_monitor,
1269                         "input", NULL);
1270
1271         if (udev_monitor_enable_receiving(master->udev_monitor)) {
1272                 weston_log("udev: failed to bind the udev monitor\n");
1273                 udev_monitor_unref(master->udev_monitor);
1274                 return 0;
1275         }
1276
1277         loop = wl_display_get_event_loop(c->wl_display);
1278         fd = udev_monitor_get_fd(master->udev_monitor);
1279         master->udev_monitor_source =
1280                 wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE,
1281                                      evdev_udev_handler, master);
1282         if (!master->udev_monitor_source) {
1283                 udev_monitor_unref(master->udev_monitor);
1284                 return 0;
1285         }
1286
1287         return 1;
1288 }
1289
1290 static void
1291 evdev_disable_udev_monitor(struct weston_seat *seat_base)
1292 {
1293         struct rpi_seat *seat = to_rpi_seat(seat_base);
1294
1295         if (!seat->udev_monitor)
1296                 return;
1297
1298         udev_monitor_unref(seat->udev_monitor);
1299         seat->udev_monitor = NULL;
1300         wl_event_source_remove(seat->udev_monitor_source);
1301         seat->udev_monitor_source = NULL;
1302 }
1303
1304 static void
1305 evdev_input_create(struct weston_compositor *c, struct udev *udev,
1306                    const char *seat_id)
1307 {
1308         struct rpi_seat *seat;
1309
1310         seat = malloc(sizeof *seat);
1311         if (seat == NULL)
1312                 return;
1313
1314         memset(seat, 0, sizeof *seat);
1315         weston_seat_init(&seat->base, c);
1316         seat->base.led_update = rpi_led_update;
1317
1318         wl_list_init(&seat->devices_list);
1319         seat->seat_id = strdup(seat_id);
1320         if (!evdev_enable_udev_monitor(udev, &seat->base)) {
1321                 free(seat->seat_id);
1322                 free(seat);
1323                 return;
1324         }
1325
1326         evdev_add_devices(udev, &seat->base);
1327 }
1328
1329 static void
1330 evdev_remove_devices(struct weston_seat *seat_base)
1331 {
1332         struct rpi_seat *seat = to_rpi_seat(seat_base);
1333         struct evdev_device *device, *next;
1334
1335         wl_list_for_each_safe(device, next, &seat->devices_list, link)
1336                 evdev_device_destroy(device);
1337
1338         if (seat->base.seat.keyboard)
1339                 notify_keyboard_focus_out(&seat->base);
1340 }
1341
1342 static void
1343 evdev_input_destroy(struct weston_seat *seat_base)
1344 {
1345         struct rpi_seat *seat = to_rpi_seat(seat_base);
1346
1347         evdev_remove_devices(seat_base);
1348         evdev_disable_udev_monitor(&seat->base);
1349
1350         weston_seat_release(seat_base);
1351         free(seat->seat_id);
1352         free(seat);
1353 }
1354
1355 static void
1356 rpi_compositor_destroy(struct weston_compositor *base)
1357 {
1358         struct rpi_compositor *compositor = to_rpi_compositor(base);
1359         struct weston_seat *seat, *next;
1360
1361         wl_list_for_each_safe(seat, next, &compositor->base.seat_list, link)
1362                 evdev_input_destroy(seat);
1363
1364         /* destroys outputs, too */
1365         weston_compositor_shutdown(&compositor->base);
1366
1367         compositor->base.renderer->destroy(&compositor->base);
1368         tty_destroy(compositor->tty);
1369
1370         bcm_host_deinit();
1371         free(compositor);
1372 }
1373
1374 static void
1375 vt_func(struct weston_compositor *base, int event)
1376 {
1377         struct rpi_compositor *compositor = to_rpi_compositor(base);
1378         struct weston_seat *seat;
1379         struct weston_output *output;
1380
1381         switch (event) {
1382         case TTY_ENTER_VT:
1383                 weston_log("entering VT\n");
1384                 compositor->base.focus = 1;
1385                 compositor->base.state = compositor->prev_state;
1386                 weston_compositor_damage_all(&compositor->base);
1387                 wl_list_for_each(seat, &compositor->base.seat_list, link) {
1388                         evdev_add_devices(compositor->udev, seat);
1389                         evdev_enable_udev_monitor(compositor->udev, seat);
1390                 }
1391                 break;
1392         case TTY_LEAVE_VT:
1393                 weston_log("leaving VT\n");
1394                 wl_list_for_each(seat, &compositor->base.seat_list, link) {
1395                         evdev_disable_udev_monitor(seat);
1396                         evdev_remove_devices(seat);
1397                 }
1398
1399                 compositor->base.focus = 0;
1400                 compositor->prev_state = compositor->base.state;
1401                 weston_compositor_offscreen(&compositor->base);
1402
1403                 /* If we have a repaint scheduled (either from a
1404                  * pending pageflip or the idle handler), make sure we
1405                  * cancel that so we don't try to pageflip when we're
1406                  * vt switched away.  The OFFSCREEN state will prevent
1407                  * further attemps at repainting.  When we switch
1408                  * back, we schedule a repaint, which will process
1409                  * pending frame callbacks. */
1410
1411                 wl_list_for_each(output,
1412                                  &compositor->base.output_list, link) {
1413                         output->repaint_needed = 0;
1414                 }
1415
1416                 break;
1417         };
1418 }
1419
1420 static void
1421 rpi_restore(struct weston_compositor *base)
1422 {
1423         struct rpi_compositor *compositor = to_rpi_compositor(base);
1424
1425         tty_reset(compositor->tty);
1426 }
1427
1428 static void
1429 switch_vt_binding(struct wl_seat *seat, uint32_t time, uint32_t key, void *data)
1430 {
1431         struct rpi_compositor *ec = data;
1432
1433         tty_activate_vt(ec->tty, key - KEY_F1 + 1);
1434 }
1435
1436 struct rpi_parameters {
1437         int tty;
1438         int max_planes;
1439         int single_buffer;
1440 };
1441
1442 static struct weston_compositor *
1443 rpi_compositor_create(struct wl_display *display, int *argc, char *argv[],
1444                       const char *config_file, struct rpi_parameters *param)
1445 {
1446         struct rpi_compositor *compositor;
1447         const char *seat = default_seat;
1448         uint32_t key;
1449         static const EGLint config_attrs[] = {
1450                 EGL_SURFACE_TYPE, EGL_WINDOW_BIT |
1451                                   EGL_SWAP_BEHAVIOR_PRESERVED_BIT,
1452                 EGL_RED_SIZE, 1,
1453                 EGL_GREEN_SIZE, 1,
1454                 EGL_BLUE_SIZE, 1,
1455                 EGL_ALPHA_SIZE, 0,
1456                 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
1457                 EGL_NONE
1458         };
1459
1460         weston_log("initializing Raspberry Pi backend\n");
1461
1462         compositor = calloc(1, sizeof *compositor);
1463         if (compositor == NULL)
1464                 return NULL;
1465
1466         if (weston_compositor_init(&compositor->base, display, argc, argv,
1467                                    config_file) < 0)
1468                 goto out_free;
1469
1470         compositor->udev = udev_new();
1471         if (compositor->udev == NULL) {
1472                 weston_log("Failed to initialize udev context.\n");
1473                 goto out_compositor;
1474         }
1475
1476         compositor->tty = tty_create(&compositor->base, vt_func, param->tty);
1477         if (!compositor->tty) {
1478                 weston_log("Failed to initialize tty.\n");
1479                 goto out_udev;
1480         }
1481
1482         compositor->base.destroy = rpi_compositor_destroy;
1483         compositor->base.restore = rpi_restore;
1484
1485         compositor->base.focus = 1;
1486         compositor->prev_state = WESTON_COMPOSITOR_ACTIVE;
1487         compositor->max_planes = int_max(param->max_planes, 0);
1488         compositor->single_buffer = param->single_buffer;
1489
1490         weston_log("Maximum number of additional Dispmanx planes: %d\n",
1491                    compositor->max_planes);
1492         weston_log("Dispmanx planes are %s buffered.\n",
1493                    compositor->single_buffer ? "single" : "double");
1494
1495         for (key = KEY_F1; key < KEY_F9; key++)
1496                 weston_compositor_add_key_binding(&compositor->base, key,
1497                                                   MODIFIER_CTRL | MODIFIER_ALT,
1498                                                   switch_vt_binding, compositor);
1499
1500         /*
1501          * bcm_host_init() creates threads.
1502          * Therefore we must have all signal handlers set and signals blocked
1503          * before calling it. Otherwise the signals may end in the bcm
1504          * threads and cause the default behaviour there. For instance,
1505          * SIGUSR1 used for VT switching caused Weston to terminate there.
1506          */
1507         bcm_host_init();
1508
1509         if (gl_renderer_create(&compositor->base, EGL_DEFAULT_DISPLAY,
1510                 config_attrs, NULL) < 0)
1511                 goto out_tty;
1512
1513         if (rpi_output_create(compositor) < 0)
1514                 goto out_gl;
1515
1516         evdev_input_create(&compositor->base, compositor->udev, seat);
1517
1518         return &compositor->base;
1519
1520 out_gl:
1521         compositor->base.renderer->destroy(&compositor->base);
1522
1523 out_tty:
1524         tty_destroy(compositor->tty);
1525
1526 out_udev:
1527         udev_unref(compositor->udev);
1528
1529 out_compositor:
1530         weston_compositor_shutdown(&compositor->base);
1531
1532 out_free:
1533         bcm_host_deinit();
1534         free(compositor);
1535
1536         return NULL;
1537 }
1538
1539 /*
1540  * If you have a recent enough firmware in Raspberry Pi, that
1541  * supports falling back to off-line hardware compositing, and
1542  * you have enabled it with dispmanx_offline=1 in /boot/config.txt,
1543  * then VideoCore should be able to handle almost 100 Dispmanx
1544  * elements. Therefore use 80 as the default limit.
1545  *
1546  * If you don't have off-line compositing support, this would be
1547  * better as something like 10. Failing on-line compositing may
1548  * show up as visible glitches, HDMI blanking, or invisible surfaces.
1549  *
1550  * When the max-planes number is reached, rpi-backend will start
1551  * to fall back to GLESv2 compositing.
1552  */
1553 #define DEFAULT_MAX_PLANES 80
1554
1555 WL_EXPORT struct weston_compositor *
1556 backend_init(struct wl_display *display, int *argc, char *argv[],
1557              const char *config_file)
1558 {
1559         struct rpi_parameters param = {
1560                 .tty = 0, /* default to current tty */
1561                 .max_planes = DEFAULT_MAX_PLANES,
1562                 .single_buffer = 0,
1563         };
1564
1565         const struct weston_option rpi_options[] = {
1566                 { WESTON_OPTION_INTEGER, "tty", 0, &param.tty },
1567                 { WESTON_OPTION_INTEGER, "max-planes", 0, &param.max_planes },
1568                 { WESTON_OPTION_BOOLEAN, "single-buffer", 0,
1569                   &param.single_buffer },
1570         };
1571
1572         parse_options(rpi_options, ARRAY_LENGTH(rpi_options), argc, argv);
1573
1574         return rpi_compositor_create(display, argc, argv, config_file, &param);
1575 }