blob: 287451d100a88afb55ef1d09ab1be4f5b680944b [file] [log] [blame]
Pekka Paalanene8de35c2012-11-07 12:25:14 +02001/*
2 * Copyright © 2008-2011 Kristian Høgsberg
3 * Copyright © 2011 Intel Corporation
Pekka Paalanene31e0532013-05-22 18:03:07 +03004 * Copyright © 2012-2013 Raspberry Pi Foundation
Pekka Paalanene8de35c2012-11-07 12:25:14 +02005 *
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
Daniel Stonec228e232013-05-22 18:03:19 +030025#include "config.h"
Pekka Paalanene8de35c2012-11-07 12:25:14 +020026
27#include <errno.h>
28#include <stdlib.h>
29#include <stdio.h>
30#include <string.h>
31#include <math.h>
Jonas Ådahle0de3c22014-03-12 22:08:42 +010032#include <sys/time.h>
Pekka Paalanene8de35c2012-11-07 12:25:14 +020033#include <sys/types.h>
34#include <fcntl.h>
35#include <unistd.h>
36
Jonas Ådahle0de3c22014-03-12 22:08:42 +010037#include <linux/input.h>
Pekka Paalanene8de35c2012-11-07 12:25:14 +020038#include <libudev.h>
39
Pekka Paalanene8de35c2012-11-07 12:25:14 +020040#ifdef HAVE_BCM_HOST
41# include <bcm_host.h>
42#else
43# include "rpi-bcm-stubs.h"
44#endif
45
46#include "compositor.h"
Pekka Paalanene31e0532013-05-22 18:03:07 +030047#include "rpi-renderer.h"
Kristian Høgsberg3f495872013-09-18 23:00:17 -070048#include "launcher-util.h"
Jonas Ådahle0de3c22014-03-12 22:08:42 +010049#include "udev-input.h"
Pekka Paalanene8de35c2012-11-07 12:25:14 +020050
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +020051#if 0
52#define DBG(...) \
53 weston_log(__VA_ARGS__)
54#else
55#define DBG(...) do {} while (0)
56#endif
57
Pekka Paalanene8de35c2012-11-07 12:25:14 +020058struct rpi_compositor;
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +020059struct rpi_output;
60
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +020061struct rpi_flippipe {
62 int readfd;
63 int writefd;
64 struct wl_event_source *source;
65};
Pekka Paalanene8de35c2012-11-07 12:25:14 +020066
67struct rpi_output {
68 struct rpi_compositor *compositor;
69 struct weston_output base;
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +020070 int single_buffer;
Pekka Paalanene8de35c2012-11-07 12:25:14 +020071
72 struct weston_mode mode;
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +020073 struct rpi_flippipe flippipe;
Pekka Paalanene8de35c2012-11-07 12:25:14 +020074
75 DISPMANX_DISPLAY_HANDLE_T display;
Pekka Paalanene8de35c2012-11-07 12:25:14 +020076};
77
78struct rpi_seat {
79 struct weston_seat base;
80 struct wl_list devices_list;
81
82 struct udev_monitor *udev_monitor;
83 struct wl_event_source *udev_monitor_source;
84 char *seat_id;
85};
86
87struct rpi_compositor {
88 struct weston_compositor base;
89 uint32_t prev_state;
90
91 struct udev *udev;
Jonas Ådahl37d38d92013-12-02 22:05:02 +010092 struct udev_input input;
Kristian Høgsberg61741a22013-09-17 16:02:57 -070093 struct wl_listener session_listener;
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +020094
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +020095 int single_buffer;
Pekka Paalanene8de35c2012-11-07 12:25:14 +020096};
97
98static inline struct rpi_output *
99to_rpi_output(struct weston_output *base)
100{
101 return container_of(base, struct rpi_output, base);
102}
103
104static inline struct rpi_seat *
105to_rpi_seat(struct weston_seat *base)
106{
107 return container_of(base, struct rpi_seat, base);
108}
109
110static inline struct rpi_compositor *
111to_rpi_compositor(struct weston_compositor *base)
112{
113 return container_of(base, struct rpi_compositor, base);
114}
115
Jonas Ådahle5a12252013-04-05 23:07:11 +0200116static uint64_t
117rpi_get_current_time(void)
118{
119 struct timeval tv;
120
121 /* XXX: use CLOCK_MONOTONIC instead? */
122 gettimeofday(&tv, NULL);
123 return (uint64_t)tv.tv_sec * 1000 + tv.tv_usec / 1000;
124}
125
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +0200126static void
127rpi_flippipe_update_complete(DISPMANX_UPDATE_HANDLE_T update, void *data)
128{
129 /* This function runs in a different thread. */
130 struct rpi_flippipe *flippipe = data;
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +0200131 uint64_t time;
132 ssize_t ret;
133
134 /* manufacture flip completion timestamp */
Jonas Ådahle5a12252013-04-05 23:07:11 +0200135 time = rpi_get_current_time();
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +0200136
137 ret = write(flippipe->writefd, &time, sizeof time);
138 if (ret != sizeof time)
139 weston_log("ERROR: %s failed to write, ret %zd, errno %d\n",
140 __func__, ret, errno);
141}
142
143static int
144rpi_dispmanx_update_submit(DISPMANX_UPDATE_HANDLE_T update,
145 struct rpi_output *output)
146{
147 /*
148 * The callback registered here will eventually be called
149 * in a different thread context. Therefore we cannot call
150 * the usual functions from rpi_flippipe_update_complete().
151 * Instead, we have a pipe for passing the message from the
152 * thread, waking up the Weston main event loop, calling
153 * rpi_flippipe_handler(), and then ending up in
154 * rpi_output_update_complete() in the main thread context,
155 * where we can do the frame finishing work.
156 */
157 return vc_dispmanx_update_submit(update, rpi_flippipe_update_complete,
158 &output->flippipe);
159}
160
161static void
162rpi_output_update_complete(struct rpi_output *output, uint64_t time);
163
164static int
165rpi_flippipe_handler(int fd, uint32_t mask, void *data)
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200166{
167 struct rpi_output *output = data;
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +0200168 ssize_t ret;
169 uint64_t time;
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200170
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +0200171 if (mask != WL_EVENT_READABLE)
172 weston_log("ERROR: unexpected mask 0x%x in %s\n",
173 mask, __func__);
174
175 ret = read(fd, &time, sizeof time);
176 if (ret != sizeof time) {
177 weston_log("ERROR: %s failed to read, ret %zd, errno %d\n",
178 __func__, ret, errno);
179 }
180
181 rpi_output_update_complete(output, time);
182
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200183 return 1;
184}
185
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +0200186static int
187rpi_flippipe_init(struct rpi_flippipe *flippipe, struct rpi_output *output)
188{
189 struct wl_event_loop *loop;
190 int fd[2];
191
192 if (pipe2(fd, O_CLOEXEC) == -1)
193 return -1;
194
195 flippipe->readfd = fd[0];
196 flippipe->writefd = fd[1];
197
198 loop = wl_display_get_event_loop(output->compositor->base.wl_display);
199 flippipe->source = wl_event_loop_add_fd(loop, flippipe->readfd,
200 WL_EVENT_READABLE,
201 rpi_flippipe_handler, output);
202
203 if (!flippipe->source) {
204 close(flippipe->readfd);
205 close(flippipe->writefd);
206 return -1;
207 }
208
209 return 0;
210}
211
212static void
213rpi_flippipe_release(struct rpi_flippipe *flippipe)
214{
215 wl_event_source_remove(flippipe->source);
216 close(flippipe->readfd);
217 close(flippipe->writefd);
218}
219
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200220static void
Jonas Ådahle5a12252013-04-05 23:07:11 +0200221rpi_output_start_repaint_loop(struct weston_output *output)
222{
223 uint64_t time;
224
225 time = rpi_get_current_time();
226 weston_output_finish_frame(output, time);
227}
228
David Herrmann1edf44c2013-10-22 17:11:26 +0200229static int
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200230rpi_output_repaint(struct weston_output *base, pixman_region32_t *damage)
231{
232 struct rpi_output *output = to_rpi_output(base);
233 struct rpi_compositor *compositor = output->compositor;
Ander Conselvan de Oliveira0a887722012-11-22 15:57:00 +0200234 struct weston_plane *primary_plane = &compositor->base.primary_plane;
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +0200235 DISPMANX_UPDATE_HANDLE_T update;
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200236
Pekka Paalanene31e0532013-05-22 18:03:07 +0300237 DBG("frame update start\n");
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +0200238
Pekka Paalanene31e0532013-05-22 18:03:07 +0300239 /* Update priority higher than in rpi-renderer's
240 * output destroy function, see rpi_output_destroy().
241 */
242 update = vc_dispmanx_update_start(1);
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +0200243
Pekka Paalanene31e0532013-05-22 18:03:07 +0300244 rpi_renderer_set_update_handle(&output->base, update);
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200245 compositor->base.renderer->repaint_output(&output->base, damage);
246
Ander Conselvan de Oliveira0a887722012-11-22 15:57:00 +0200247 pixman_region32_subtract(&primary_plane->damage,
248 &primary_plane->damage, damage);
249
Pekka Paalanene31e0532013-05-22 18:03:07 +0300250 /* schedule callback to rpi_output_update_complete() */
251 rpi_dispmanx_update_submit(update, output);
252 DBG("frame update submitted\n");
David Herrmann1edf44c2013-10-22 17:11:26 +0200253 return 0;
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +0200254}
255
256static void
257rpi_output_update_complete(struct rpi_output *output, uint64_t time)
258{
Pekka Paalanene31e0532013-05-22 18:03:07 +0300259 DBG("frame update complete(%" PRIu64 ")\n", time);
Pekka Paalanene31e0532013-05-22 18:03:07 +0300260 rpi_renderer_finish_frame(&output->base);
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +0200261 weston_output_finish_frame(&output->base, time);
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200262}
263
264static void
265rpi_output_destroy(struct weston_output *base)
266{
267 struct rpi_output *output = to_rpi_output(base);
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200268
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +0200269 DBG("%s\n", __func__);
270
Pekka Paalanene31e0532013-05-22 18:03:07 +0300271 rpi_renderer_output_destroy(base);
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200272
Pekka Paalanene31e0532013-05-22 18:03:07 +0300273 /* rpi_renderer_output_destroy() will schedule a removal of
274 * all Dispmanx Elements, and wait for the update to complete.
275 * Assuming updates are sequential, the wait should guarantee,
276 * that any pending rpi_flippipe_update_complete() callbacks
277 * have happened already. Therefore we can destroy the flippipe
278 * now.
279 */
280 rpi_flippipe_release(&output->flippipe);
281
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200282 weston_output_destroy(&output->base);
283
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200284 vc_dispmanx_display_close(output->display);
285
286 free(output);
287}
288
Pekka Paalanene31e0532013-05-22 18:03:07 +0300289static const char *transform_names[] = {
290 [WL_OUTPUT_TRANSFORM_NORMAL] = "normal",
291 [WL_OUTPUT_TRANSFORM_90] = "90",
292 [WL_OUTPUT_TRANSFORM_180] = "180",
293 [WL_OUTPUT_TRANSFORM_270] = "270",
294 [WL_OUTPUT_TRANSFORM_FLIPPED] = "flipped",
295 [WL_OUTPUT_TRANSFORM_FLIPPED_90] = "flipped-90",
296 [WL_OUTPUT_TRANSFORM_FLIPPED_180] = "flipped-180",
297 [WL_OUTPUT_TRANSFORM_FLIPPED_270] = "flipped-270",
298};
299
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200300static int
Pekka Paalanene31e0532013-05-22 18:03:07 +0300301str2transform(const char *name)
302{
303 unsigned i;
304
305 for (i = 0; i < ARRAY_LENGTH(transform_names); i++)
306 if (strcmp(name, transform_names[i]) == 0)
307 return i;
308
309 return -1;
310}
311
312static const char *
313transform2str(uint32_t output_transform)
314{
315 if (output_transform >= ARRAY_LENGTH(transform_names))
316 return "<illegal value>";
317
318 return transform_names[output_transform];
319}
320
321static int
322rpi_output_create(struct rpi_compositor *compositor, uint32_t transform)
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200323{
324 struct rpi_output *output;
325 DISPMANX_MODEINFO_T modeinfo;
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200326 int ret;
327 float mm_width, mm_height;
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200328
329 output = calloc(1, sizeof *output);
330 if (!output)
331 return -1;
332
333 output->compositor = compositor;
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +0200334 output->single_buffer = compositor->single_buffer;
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +0200335
336 if (rpi_flippipe_init(&output->flippipe, output) < 0) {
337 weston_log("Creating message pipe failed.\n");
338 goto out_free;
339 }
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200340
341 output->display = vc_dispmanx_display_open(DISPMANX_ID_HDMI);
342 if (!output->display) {
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +0200343 weston_log("Failed to open dispmanx HDMI display.\n");
344 goto out_pipe;
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200345 }
346
347 ret = vc_dispmanx_display_get_info(output->display, &modeinfo);
348 if (ret < 0) {
349 weston_log("Failed to get display mode information.\n");
350 goto out_dmx_close;
351 }
352
Jonas Ådahle5a12252013-04-05 23:07:11 +0200353 output->base.start_repaint_loop = rpi_output_start_repaint_loop;
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200354 output->base.repaint = rpi_output_repaint;
355 output->base.destroy = rpi_output_destroy;
Pekka Paalanene31e0532013-05-22 18:03:07 +0300356 output->base.assign_planes = NULL;
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200357 output->base.set_backlight = NULL;
358 output->base.set_dpms = NULL;
359 output->base.switch_mode = NULL;
360
361 /* XXX: use tvservice to get information from and control the
362 * HDMI and SDTV outputs. See:
363 * /opt/vc/include/interface/vmcs_host/vc_tvservice.h
364 */
365
366 /* only one static mode in list */
367 output->mode.flags =
368 WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
369 output->mode.width = modeinfo.width;
370 output->mode.height = modeinfo.height;
371 output->mode.refresh = 60000;
372 wl_list_init(&output->base.mode_list);
373 wl_list_insert(&output->base.mode_list, &output->mode.link);
374
Hardeningff39efa2013-09-18 23:56:35 +0200375 output->base.current_mode = &output->mode;
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200376 output->base.subpixel = WL_OUTPUT_SUBPIXEL_UNKNOWN;
377 output->base.make = "unknown";
378 output->base.model = "unknown";
379
380 /* guess 96 dpi */
381 mm_width = modeinfo.width * (25.4f / 96.0f);
382 mm_height = modeinfo.height * (25.4f / 96.0f);
383
384 weston_output_init(&output->base, &compositor->base,
385 0, 0, round(mm_width), round(mm_height),
Pekka Paalanene31e0532013-05-22 18:03:07 +0300386 transform, 1);
John Kåre Alsaker94659272012-11-13 19:10:18 +0100387
Pekka Paalanene31e0532013-05-22 18:03:07 +0300388 if (rpi_renderer_output_create(&output->base, output->display) < 0)
John Kåre Alsaker94659272012-11-13 19:10:18 +0100389 goto out_output;
390
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200391 wl_list_insert(compositor->base.output_list.prev, &output->base.link);
392
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200393 weston_log("Raspberry Pi HDMI output %dx%d px\n",
394 output->mode.width, output->mode.height);
395 weston_log_continue(STAMP_SPACE "guessing %d Hz and 96 dpi\n",
396 output->mode.refresh / 1000);
Pekka Paalanene31e0532013-05-22 18:03:07 +0300397 weston_log_continue(STAMP_SPACE "orientation: %s\n",
398 transform2str(output->base.transform));
399
400 if (!strncmp(transform2str(output->base.transform), "flipped", 7))
401 weston_log("warning: flipped output transforms may not work\n");
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200402
403 return 0;
404
John Kåre Alsaker94659272012-11-13 19:10:18 +0100405out_output:
406 weston_output_destroy(&output->base);
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200407
408out_dmx_close:
409 vc_dispmanx_display_close(output->display);
410
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +0200411out_pipe:
412 rpi_flippipe_release(&output->flippipe);
413
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200414out_free:
415 free(output);
416 return -1;
417}
418
419static void
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200420rpi_compositor_destroy(struct weston_compositor *base)
421{
422 struct rpi_compositor *compositor = to_rpi_compositor(base);
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200423
Jonas Ådahl37d38d92013-12-02 22:05:02 +0100424 udev_input_destroy(&compositor->input);
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200425
426 /* destroys outputs, too */
427 weston_compositor_shutdown(&compositor->base);
428
Kristian Høgsberg3f495872013-09-18 23:00:17 -0700429 weston_launcher_destroy(compositor->base.launcher);
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200430
431 bcm_host_deinit();
432 free(compositor);
433}
434
435static void
Kristian Høgsberg61741a22013-09-17 16:02:57 -0700436session_notify(struct wl_listener *listener, void *data)
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200437{
Kristian Høgsberg61741a22013-09-17 16:02:57 -0700438 struct rpi_compositor *compositor = data;
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200439 struct weston_output *output;
440
Kristian Høgsberg61741a22013-09-17 16:02:57 -0700441 if (compositor->base.session_active) {
442 weston_log("activating session\n");
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200443 compositor->base.state = compositor->prev_state;
444 weston_compositor_damage_all(&compositor->base);
Jonas Ådahl0feb32e2014-03-12 22:08:41 +0100445 udev_input_enable(&compositor->input);
Kristian Høgsberg61741a22013-09-17 16:02:57 -0700446 } else {
447 weston_log("deactivating session\n");
Jonas Ådahl37d38d92013-12-02 22:05:02 +0100448 udev_input_disable(&compositor->input);
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200449
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200450 compositor->prev_state = compositor->base.state;
Philipp Brüschweiler57edf7f2013-03-29 13:01:56 +0100451 weston_compositor_offscreen(&compositor->base);
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200452
453 /* If we have a repaint scheduled (either from a
454 * pending pageflip or the idle handler), make sure we
455 * cancel that so we don't try to pageflip when we're
Philipp Brüschweiler57edf7f2013-03-29 13:01:56 +0100456 * vt switched away. The OFFSCREEN state will prevent
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200457 * further attemps at repainting. When we switch
458 * back, we schedule a repaint, which will process
459 * pending frame callbacks. */
460
461 wl_list_for_each(output,
462 &compositor->base.output_list, link) {
463 output->repaint_needed = 0;
464 }
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200465 };
466}
467
468static void
Kristian Høgsberg3f495872013-09-18 23:00:17 -0700469rpi_restore(struct weston_compositor *compositor)
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200470{
Kristian Høgsberg3f495872013-09-18 23:00:17 -0700471 weston_launcher_restore(compositor->launcher);
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200472}
473
474static void
Kristian Høgsberge3148752013-05-06 23:19:49 -0400475switch_vt_binding(struct weston_seat *seat, uint32_t time, uint32_t key, void *data)
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200476{
Kristian Høgsberg3f495872013-09-18 23:00:17 -0700477 struct weston_compositor *compositor = data;
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200478
Kristian Høgsberg3f495872013-09-18 23:00:17 -0700479 weston_launcher_activate_vt(compositor->launcher, key - KEY_F1 + 1);
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200480}
481
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +0200482struct rpi_parameters {
483 int tty;
Pekka Paalanene31e0532013-05-22 18:03:07 +0300484 struct rpi_renderer_parameters renderer;
485 uint32_t output_transform;
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +0200486};
487
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200488static struct weston_compositor *
Kristian Høgsberg4172f662013-02-20 15:27:49 -0500489rpi_compositor_create(struct wl_display *display, int *argc, char *argv[],
Kristian Høgsberg14e438c2013-05-26 21:48:14 -0400490 struct weston_config *config,
491 struct rpi_parameters *param)
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200492{
493 struct rpi_compositor *compositor;
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200494 uint32_t key;
495
496 weston_log("initializing Raspberry Pi backend\n");
497
498 compositor = calloc(1, sizeof *compositor);
499 if (compositor == NULL)
500 return NULL;
501
502 if (weston_compositor_init(&compositor->base, display, argc, argv,
Kristian Høgsberg14e438c2013-05-26 21:48:14 -0400503 config) < 0)
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200504 goto out_free;
505
506 compositor->udev = udev_new();
507 if (compositor->udev == NULL) {
508 weston_log("Failed to initialize udev context.\n");
509 goto out_compositor;
510 }
511
Kristian Høgsberg61741a22013-09-17 16:02:57 -0700512 compositor->session_listener.notify = session_notify;
513 wl_signal_add(&compositor->base.session_signal,
514 &compositor ->session_listener);
Kristian Høgsberg6ff3ff52013-10-02 10:53:33 -0700515 compositor->base.launcher =
David Herrmanncc5b2ed2013-10-22 00:28:09 +0200516 weston_launcher_connect(&compositor->base, param->tty, "seat0");
Kristian Høgsberg3f495872013-09-18 23:00:17 -0700517 if (!compositor->base.launcher) {
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200518 weston_log("Failed to initialize tty.\n");
Pekka Paalanen47733322013-12-04 15:34:48 +0200519 goto out_udev;
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200520 }
521
522 compositor->base.destroy = rpi_compositor_destroy;
523 compositor->base.restore = rpi_restore;
524
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200525 compositor->prev_state = WESTON_COMPOSITOR_ACTIVE;
Pekka Paalanene31e0532013-05-22 18:03:07 +0300526 compositor->single_buffer = param->renderer.single_buffer;
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +0200527
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +0200528 weston_log("Dispmanx planes are %s buffered.\n",
529 compositor->single_buffer ? "single" : "double");
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200530
531 for (key = KEY_F1; key < KEY_F9; key++)
532 weston_compositor_add_key_binding(&compositor->base, key,
533 MODIFIER_CTRL | MODIFIER_ALT,
534 switch_vt_binding, compositor);
535
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +0200536 /*
537 * bcm_host_init() creates threads.
538 * Therefore we must have all signal handlers set and signals blocked
539 * before calling it. Otherwise the signals may end in the bcm
540 * threads and cause the default behaviour there. For instance,
541 * SIGUSR1 used for VT switching caused Weston to terminate there.
542 */
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200543 bcm_host_init();
544
Pekka Paalanene31e0532013-05-22 18:03:07 +0300545 if (rpi_renderer_create(&compositor->base, &param->renderer) < 0)
Emilio Pozuelo Monfortbf539e32014-02-03 16:57:27 +0100546 goto out_launcher;
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200547
Pekka Paalanene31e0532013-05-22 18:03:07 +0300548 if (rpi_output_create(compositor, param->output_transform) < 0)
549 goto out_renderer;
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200550
Emilio Pozuelo Monfortbf539e32014-02-03 16:57:27 +0100551 if (udev_input_init(&compositor->input,
552 &compositor->base,
553 compositor->udev, "seat0") != 0) {
554 weston_log("Failed to initialize udev input.\n");
555 goto out_renderer;
556 }
557
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200558 return &compositor->base;
559
Pekka Paalanene31e0532013-05-22 18:03:07 +0300560out_renderer:
Vasily Khoruzhick52cfd612013-01-08 19:09:01 +0300561 compositor->base.renderer->destroy(&compositor->base);
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200562
Pekka Paalanen47733322013-12-04 15:34:48 +0200563out_launcher:
564 weston_launcher_destroy(compositor->base.launcher);
565
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200566out_udev:
567 udev_unref(compositor->udev);
568
569out_compositor:
570 weston_compositor_shutdown(&compositor->base);
571
572out_free:
573 bcm_host_deinit();
574 free(compositor);
575
576 return NULL;
577}
578
579WL_EXPORT struct weston_compositor *
Kristian Høgsberg4172f662013-02-20 15:27:49 -0500580backend_init(struct wl_display *display, int *argc, char *argv[],
Kristian Høgsberg14e438c2013-05-26 21:48:14 -0400581 struct weston_config *config)
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200582{
Pekka Paalanene31e0532013-05-22 18:03:07 +0300583 const char *transform = "normal";
584 int ret;
585
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +0200586 struct rpi_parameters param = {
587 .tty = 0, /* default to current tty */
Pekka Paalanene31e0532013-05-22 18:03:07 +0300588 .renderer.single_buffer = 0,
589 .output_transform = WL_OUTPUT_TRANSFORM_NORMAL,
Tomeu Vizosoe4f7b922013-12-02 17:18:58 +0100590 .renderer.opaque_regions = 0,
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +0200591 };
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200592
593 const struct weston_option rpi_options[] = {
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +0200594 { WESTON_OPTION_INTEGER, "tty", 0, &param.tty },
Pekka Paalanen7fb46fb2012-11-07 12:25:15 +0200595 { WESTON_OPTION_BOOLEAN, "single-buffer", 0,
Pekka Paalanene31e0532013-05-22 18:03:07 +0300596 &param.renderer.single_buffer },
597 { WESTON_OPTION_STRING, "transform", 0, &transform },
Tomeu Vizosoe4f7b922013-12-02 17:18:58 +0100598 { WESTON_OPTION_BOOLEAN, "opaque-regions", 0,
599 &param.renderer.opaque_regions },
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200600 };
601
602 parse_options(rpi_options, ARRAY_LENGTH(rpi_options), argc, argv);
603
Pekka Paalanene31e0532013-05-22 18:03:07 +0300604 ret = str2transform(transform);
605 if (ret < 0)
606 weston_log("invalid transform \"%s\"\n", transform);
607 else
608 param.output_transform = ret;
609
Kristian Høgsberg14e438c2013-05-26 21:48:14 -0400610 return rpi_compositor_create(display, argc, argv, config, &param);
Pekka Paalanene8de35c2012-11-07 12:25:14 +0200611}