blob: f4641bde972270f93929bd80b2e54d9a8a59e5a5 [file] [log] [blame]
David Sodmanbbcb0522014-09-19 10:34:07 -07001/*
2 * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
David Sodman8ef20062015-01-06 09:23:40 -08007#include <fcntl.h>
David Sodmanbbcb0522014-09-19 10:34:07 -07008#include <stdbool.h>
9#include <stddef.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <sys/mman.h>
14#include <unistd.h>
David Sodmanbbcb0522014-09-19 10:34:07 -070015
Dominik Behr797a3832016-01-11 15:53:11 -080016#include "dbus.h"
David Sodmanbbcb0522014-09-19 10:34:07 -070017#include "dbus_interface.h"
David Sodman8ef20062015-01-06 09:23:40 -080018#include "image.h"
David Sodmanf0a925a2015-05-04 11:19:19 -070019#include "input.h"
Dominik Behr44e07e62016-01-13 19:43:57 -080020#include "main.h"
David Sodman8ef20062015-01-06 09:23:40 -080021#include "splash.h"
David Sodmanf0a925a2015-05-04 11:19:19 -070022#include "term.h"
David Sodman8ef20062015-01-06 09:23:40 -080023#include "util.h"
David Sodmanbbcb0522014-09-19 10:34:07 -070024
25#define MAX_SPLASH_IMAGES (30)
David Sodmandd5b23e2015-02-18 21:36:38 -080026#define MAX_SPLASH_WAITTIME (8)
David Sodman8ef20062015-01-06 09:23:40 -080027#define DBUS_WAIT_DELAY (50000)
David Sodmanbbcb0522014-09-19 10:34:07 -070028
29typedef struct {
Stéphane Marchesin00ff1872015-12-14 13:40:09 -080030 image_t* image;
31 uint32_t duration;
David Sodman8ef20062015-01-06 09:23:40 -080032} splash_frame_t;
David Sodmanbbcb0522014-09-19 10:34:07 -070033
34struct _splash_t {
Stéphane Marchesin00ff1872015-12-14 13:40:09 -080035 video_t* video;
36 terminal_t* terminal;
37 int num_images;
38 uint32_t clear;
39 splash_frame_t image_frames[MAX_SPLASH_IMAGES];
40 bool terminated;
41 bool devmode;
Stéphane Marchesin00ff1872015-12-14 13:40:09 -080042 int32_t loop_start;
43 uint32_t loop_duration;
44 uint32_t default_duration;
45 int32_t offset_x;
46 int32_t offset_y;
47 int32_t loop_offset_x;
48 int32_t loop_offset_y;
David Sodmanbbcb0522014-09-19 10:34:07 -070049};
50
David Sodmanbf3f2842014-11-12 08:26:58 -080051
52splash_t* splash_init()
David Sodmanbbcb0522014-09-19 10:34:07 -070053{
54 splash_t* splash;
55
56 splash = (splash_t*)calloc(1, sizeof(splash_t));
Stéphane Marchesinc236e0b2015-12-14 15:29:15 -080057 if (!splash)
David Sodmanbbcb0522014-09-19 10:34:07 -070058 return NULL;
59
David Sodmanbf3f2842014-11-12 08:26:58 -080060 splash->video = video_init();
Yuly Novikov945871e2015-05-23 00:00:41 -040061 if (!splash->video) {
62 free(splash);
63 return NULL;
64 }
65
Stéphane Marchesinf75c8512016-01-07 16:53:21 -080066 splash->terminal = term_create_splash_term(splash->video);
David Sodman8ef20062015-01-06 09:23:40 -080067 splash->loop_start = -1;
68 splash->default_duration = 25;
69 splash->loop_duration = 25;
David Sodmanbbcb0522014-09-19 10:34:07 -070070
71 return splash;
72}
73
74int splash_destroy(splash_t* splash)
75{
David Sodmanf0a925a2015-05-04 11:19:19 -070076 if (splash->terminal) {
77 term_close(splash->terminal);
78 splash->terminal = NULL;
David Sodman8ef20062015-01-06 09:23:40 -080079 }
80 free(splash);
Stéphane Marchesinf75c8512016-01-07 16:53:21 -080081 term_destroy_splash_term();
David Sodmanbbcb0522014-09-19 10:34:07 -070082 return 0;
83}
84
Stéphane Marchesin00ff1872015-12-14 13:40:09 -080085int splash_set_clear(splash_t* splash, uint32_t clear_color)
David Sodmanbbcb0522014-09-19 10:34:07 -070086{
87 splash->clear = clear_color;
88 return 0;
89}
90
David Sodman8ef20062015-01-06 09:23:40 -080091int splash_add_image(splash_t* splash, char* filespec)
David Sodmanbbcb0522014-09-19 10:34:07 -070092{
David Sodman8ef20062015-01-06 09:23:40 -080093 image_t* image;
94 int32_t offset_x, offset_y;
Stéphane Marchesin00ff1872015-12-14 13:40:09 -080095 char* filename;
David Sodman8ef20062015-01-06 09:23:40 -080096 uint32_t duration;
David Sodmanbbcb0522014-09-19 10:34:07 -070097 if (splash->num_images >= MAX_SPLASH_IMAGES)
98 return 1;
99
David Sodman8ef20062015-01-06 09:23:40 -0800100 filename = (char*)malloc(strlen(filespec) + 1);
101 parse_filespec(filespec,
102 filename,
103 &offset_x, &offset_y, &duration,
104 splash->default_duration,
105 splash->offset_x,
106 splash->offset_y);
107
108 image = image_create();
109 image_set_filename(image, filename);
110 image_set_offset(image, offset_x, offset_y);
111 splash->image_frames[splash->num_images].image = image;
112 splash->image_frames[splash->num_images].duration = duration;
David Sodmanbbcb0522014-09-19 10:34:07 -0700113 splash->num_images++;
David Sodman8ef20062015-01-06 09:23:40 -0800114
115 free(filename);
David Sodmanbbcb0522014-09-19 10:34:07 -0700116 return 0;
117}
118
Stéphane Marchesin00ff1872015-12-14 13:40:09 -0800119static void splash_clear_screen(splash_t* splash)
David Sodmanbbcb0522014-09-19 10:34:07 -0700120{
David Sodmanf0a925a2015-05-04 11:19:19 -0700121 term_set_background(splash->terminal, splash->clear);
David Sodmanbbcb0522014-09-19 10:34:07 -0700122}
123
Dominik Behr797a3832016-01-11 15:53:11 -0800124int splash_run(splash_t* splash)
David Sodmanbbcb0522014-09-19 10:34:07 -0700125{
126 int i;
David Sodmanbbcb0522014-09-19 10:34:07 -0700127 int status;
David Sodmanbbcb0522014-09-19 10:34:07 -0700128 int64_t last_show_ms;
129 int64_t now_ms;
130 int64_t sleep_ms;
131 struct timespec sleep_spec;
132 int fd;
133 int num_written;
David Sodman8ef20062015-01-06 09:23:40 -0800134 image_t* image;
135 uint32_t duration;
David Sodmanbbcb0522014-09-19 10:34:07 -0700136
David Sodmanbbcb0522014-09-19 10:34:07 -0700137 /*
138 * First draw the actual splash screen
139 */
David Sodmanf0a925a2015-05-04 11:19:19 -0700140 splash_clear_screen(splash);
141 term_activate(splash->terminal);
142 last_show_ms = -1;
143 for (i = 0; i < splash->num_images; i++) {
144 image = splash->image_frames[i].image;
145 status = image_load_image_from_file(image);
146 if (status != 0) {
147 LOG(WARNING, "image_load_image_from_file failed: %d", status);
148 break;
David Sodman8ef20062015-01-06 09:23:40 -0800149 }
150
David Sodmanf0a925a2015-05-04 11:19:19 -0700151 now_ms = get_monotonic_time_ms();
152 if (last_show_ms > 0) {
153 if (splash->loop_start >= 0 && i >= splash->loop_start)
154 duration = splash->loop_duration;
155 else
156 duration = splash->image_frames[i].duration;
157 sleep_ms = duration - (now_ms - last_show_ms);
158 if (sleep_ms > 0) {
159 sleep_spec.tv_sec = sleep_ms / MS_PER_SEC;
160 sleep_spec.tv_nsec = (sleep_ms % MS_PER_SEC) * NS_PER_MS;
161 nanosleep(&sleep_spec, NULL);
162 }
163 }
164
165 now_ms = get_monotonic_time_ms();
166
167 if (i >= splash->loop_start) {
168 image_set_offset(image,
169 splash->loop_offset_x,
170 splash->loop_offset_y);
171 }
172
173 status = term_show_image(splash->terminal, image);
174 if (status != 0) {
175 LOG(WARNING, "term_show_image failed: %d", status);
176 break;
177 }
Dominik Behr44e07e62016-01-13 19:43:57 -0800178 status = main_process_events(1);
David Sodmanf0a925a2015-05-04 11:19:19 -0700179 if (status != 0) {
180 LOG(WARNING, "input_process failed: %d", status);
181 break;
182 }
183 last_show_ms = now_ms;
184
185 if ((splash->loop_start >= 0) &&
186 (splash->loop_start < splash->num_images)) {
187 if (i == splash->num_images - 1)
188 i = splash->loop_start - 1;
189 }
190
191 image_release(image);
192 }
193
194 for (i = 0; i < splash->num_images; i++) {
195 image_destroy(splash->image_frames[i].image);
196 }
197
Dominik Behr4defb362016-01-13 12:36:14 -0800198 term_set_current_to(NULL);
David Sodmanf0a925a2015-05-04 11:19:19 -0700199
200 /*
201 * Now Chrome can take over
202 */
203 video_release(splash->video);
204 video_unlock(splash->video);
205
Dominik Behr797a3832016-01-11 15:53:11 -0800206 while (!dbus_is_initialized()) {
207 dbus_init();
208 usleep(DBUS_WAIT_DELAY);
David Sodmanf0a925a2015-05-04 11:19:19 -0700209 }
210
211 if (splash->devmode) {
David Sodman5c9afa72015-02-14 09:32:53 -0800212 /*
David Sodmanf0a925a2015-05-04 11:19:19 -0700213 * Now set drm_master_relax so that we can transfer drm_master between
214 * chrome and frecon
David Sodman5c9afa72015-02-14 09:32:53 -0800215 */
David Sodmanf0a925a2015-05-04 11:19:19 -0700216 fd = open("/sys/kernel/debug/dri/drm_master_relax", O_WRONLY);
217 if (fd != -1) {
218 num_written = write(fd, "Y", 1);
219 close(fd);
David Sodmanbbcb0522014-09-19 10:34:07 -0700220
David Sodmanbbcb0522014-09-19 10:34:07 -0700221 /*
David Sodmanf0a925a2015-05-04 11:19:19 -0700222 * If we can't set drm_master relax, then transitions between chrome
223 * and frecon won't work. No point in having frecon hold any resources
David Sodmanbbcb0522014-09-19 10:34:07 -0700224 */
David Sodmanf0a925a2015-05-04 11:19:19 -0700225 if (num_written != 1) {
226 LOG(ERROR, "Unable to set drm_master_relax");
227 splash->devmode = false;
David Sodmanbbcb0522014-09-19 10:34:07 -0700228 }
David Sodmandd5b23e2015-02-18 21:36:38 -0800229 } else {
David Sodmanf0a925a2015-05-04 11:19:19 -0700230 LOG(ERROR, "unable to open drm_master_relax");
David Sodmanbbcb0522014-09-19 10:34:07 -0700231 }
David Sodmanf0a925a2015-05-04 11:19:19 -0700232 } else {
233 /*
234 * Below, we will wait for Chrome to appear above the splash
235 * image. If we are not in dev mode, wait and then exit
236 */
237 sleep(MAX_SPLASH_WAITTIME);
238 exit(EXIT_SUCCESS);
David Sodmanbbcb0522014-09-19 10:34:07 -0700239 }
David Sodman003faed2014-11-03 09:02:10 -0800240
Dominik Behr797a3832016-01-11 15:53:11 -0800241 dbus_take_display_ownership();
David Sodmanf348b0d2015-02-10 08:34:57 -0800242
243 /*
244 * Finally, wait until chrome has drawn on top of the splash. In dev mode,
245 * wait a few seconds for chrome to show up.
246 */
247 sleep(MAX_SPLASH_WAITTIME);
David Sodmanbbcb0522014-09-19 10:34:07 -0700248 return status;
249}
250
David Sodman8ef20062015-01-06 09:23:40 -0800251void splash_set_offset(splash_t* splash, int32_t x, int32_t y)
252{
253 if (splash) {
254 splash->offset_x = x;
255 splash->offset_y = y;
256 }
257}
258
David Sodmanbbcb0522014-09-19 10:34:07 -0700259void splash_set_devmode(splash_t* splash)
260{
David Sodman8ef20062015-01-06 09:23:40 -0800261 if (splash)
262 splash->devmode = true;
263}
264
Stéphane Marchesin00ff1872015-12-14 13:40:09 -0800265int splash_num_images(splash_t* splash)
David Sodman8ef20062015-01-06 09:23:40 -0800266{
267 if (splash)
268 return splash->num_images;
269
270 return 0;
271}
272
273void splash_set_default_duration(splash_t* splash, uint32_t duration)
274{
275 if (splash)
276 splash->default_duration = duration;
277}
278
279void splash_set_loop_start(splash_t* splash, int32_t loop_start)
280{
281 if (splash)
282 splash->loop_start = loop_start;
283}
284
285void splash_set_loop_duration(splash_t* splash, uint32_t duration)
286{
287 if (splash)
288 splash->loop_duration = duration;
289}
290
291void splash_set_loop_offset(splash_t* splash, int32_t x, int32_t y)
292{
293 if (splash) {
294 splash->loop_offset_x = x;
295 splash->loop_offset_y = y;
296 }
David Sodmanbbcb0522014-09-19 10:34:07 -0700297}
David Sodmanf0a925a2015-05-04 11:19:19 -0700298
299void splash_present_term_file(splash_t* splash)
300{
301 fprintf(stdout, "%s\n", term_get_ptsname(splash->terminal));
302}
Dominik Behr32a7c892015-10-09 15:47:53 -0700303
304int splash_is_hires(splash_t* splash)
305{
306 if (splash && splash->video)
307 return video_getwidth(splash->video) > 1920;
308 return 0;
309}