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