blob: 89d1adb19a31662c8d62b9cef1599b0d9de78feb [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
David Sodmanbbcb0522014-09-19 10:34:07 -070016#include "dbus_interface.h"
David Sodman8ef20062015-01-06 09:23:40 -080017#include "image.h"
18#include "splash.h"
19#include "util.h"
David Sodmanbbcb0522014-09-19 10:34:07 -070020
21#define MAX_SPLASH_IMAGES (30)
David Sodmandd5b23e2015-02-18 21:36:38 -080022#define MAX_SPLASH_WAITTIME (8)
David Sodman8ef20062015-01-06 09:23:40 -080023#define DBUS_WAIT_DELAY (50000)
David Sodmanbbcb0522014-09-19 10:34:07 -070024
25typedef struct {
David Sodman8ef20062015-01-06 09:23:40 -080026 image_t *image;
27 uint32_t duration;
28} splash_frame_t;
David Sodmanbbcb0522014-09-19 10:34:07 -070029
30struct _splash_t {
31 video_t *video;
32 int num_images;
David Sodman8ef20062015-01-06 09:23:40 -080033 splash_frame_t image_frames[MAX_SPLASH_IMAGES];
David Sodmanbbcb0522014-09-19 10:34:07 -070034 uint32_t clear;
35 bool terminated;
36 bool devmode;
37 dbus_t *dbus;
David Sodman8ef20062015-01-06 09:23:40 -080038 int32_t loop_start;
39 uint32_t loop_duration;
40 uint32_t default_duration;
41 int32_t offset_x;
42 int32_t offset_y;
43 int32_t loop_offset_x;
44 int32_t loop_offset_y;
David Sodmanbbcb0522014-09-19 10:34:07 -070045};
46
David Sodmanbf3f2842014-11-12 08:26:58 -080047
48splash_t* splash_init()
David Sodmanbbcb0522014-09-19 10:34:07 -070049{
50 splash_t* splash;
David Sodman73e82272014-11-17 10:11:47 -080051 FILE *cookie_fp;
David Sodmanbbcb0522014-09-19 10:34:07 -070052
53 splash = (splash_t*)calloc(1, sizeof(splash_t));
54 if (splash == NULL)
55 return NULL;
56
David Sodmanbf3f2842014-11-12 08:26:58 -080057 splash->video = video_init();
David Sodman8ef20062015-01-06 09:23:40 -080058 splash->loop_start = -1;
59 splash->default_duration = 25;
60 splash->loop_duration = 25;
David Sodmanbbcb0522014-09-19 10:34:07 -070061
David Sodman73e82272014-11-17 10:11:47 -080062 cookie_fp = fopen("/tmp/display_info.bin", "wb");
63 if (cookie_fp) {
64 fwrite(&splash->video->internal_panel, sizeof(char), 1, cookie_fp);
65 fwrite(splash->video->edid, EDID_SIZE, 1, cookie_fp);
66 fclose(cookie_fp);
67 }
68
David Sodmanbbcb0522014-09-19 10:34:07 -070069 return splash;
70}
71
72int splash_destroy(splash_t* splash)
73{
David Sodman8ef20062015-01-06 09:23:40 -080074 if (splash->video) {
75 video_close(splash->video);
76 splash->video = NULL;
77 }
78 free(splash);
David Sodmanbbcb0522014-09-19 10:34:07 -070079 return 0;
80}
81
82int splash_set_clear(splash_t *splash, int32_t clear_color)
83{
84 splash->clear = clear_color;
85 return 0;
86}
87
David Sodman8ef20062015-01-06 09:23:40 -080088int splash_add_image(splash_t* splash, char* filespec)
David Sodmanbbcb0522014-09-19 10:34:07 -070089{
David Sodman8ef20062015-01-06 09:23:40 -080090 image_t* image;
91 int32_t offset_x, offset_y;
92 char *filename;
93 uint32_t duration;
David Sodmanbbcb0522014-09-19 10:34:07 -070094 if (splash->num_images >= MAX_SPLASH_IMAGES)
95 return 1;
96
David Sodman8ef20062015-01-06 09:23:40 -080097 filename = (char*)malloc(strlen(filespec) + 1);
98 parse_filespec(filespec,
99 filename,
100 &offset_x, &offset_y, &duration,
101 splash->default_duration,
102 splash->offset_x,
103 splash->offset_y);
104
105 image = image_create();
106 image_set_filename(image, filename);
107 image_set_offset(image, offset_x, offset_y);
108 splash->image_frames[splash->num_images].image = image;
109 splash->image_frames[splash->num_images].duration = duration;
David Sodmanbbcb0522014-09-19 10:34:07 -0700110 splash->num_images++;
David Sodman8ef20062015-01-06 09:23:40 -0800111
112 free(filename);
David Sodmanbbcb0522014-09-19 10:34:07 -0700113 return 0;
114}
115
David Sodmanbbcb0522014-09-19 10:34:07 -0700116static void splash_clear_screen(splash_t *splash, uint32_t *video_buffer)
117{
118 int i,j;
119 buffer_properties_t *bp;
120
121 video_setmode(splash->video);
122
123 bp = video_get_buffer_properties(splash->video);
124
125 for (j = 0; j < bp->height; j++) {
126 for (i = 0; i < bp->width; i++) {
127 (video_buffer + bp->pitch/4 * j)[i] = splash->clear;
128 }
129 }
130}
131
132int splash_run(splash_t* splash, dbus_t** dbus)
133{
134 int i;
135 uint32_t* video_buffer;
136 int status;
David Sodmanbbcb0522014-09-19 10:34:07 -0700137 int64_t last_show_ms;
138 int64_t now_ms;
139 int64_t sleep_ms;
140 struct timespec sleep_spec;
141 int fd;
142 int num_written;
David Sodman8ef20062015-01-06 09:23:40 -0800143 image_t* image;
144 uint32_t duration;
David Sodmanbbcb0522014-09-19 10:34:07 -0700145
146 status = 0;
147
148 /*
149 * First draw the actual splash screen
150 */
151 video_buffer = video_lock(splash->video);
152 if (video_buffer != NULL) {
153 splash_clear_screen(splash, video_buffer);
154 last_show_ms = -1;
155 for (i = 0; i < splash->num_images; i++) {
David Sodman8ef20062015-01-06 09:23:40 -0800156 image = splash->image_frames[i].image;
157 status = image_load_image_from_file(image);
David Sodmanbbcb0522014-09-19 10:34:07 -0700158 if (status != 0) {
David Sodman8ef20062015-01-06 09:23:40 -0800159 LOG(WARNING, "image_load_image_from_file failed: %d", status);
David Sodmanbbcb0522014-09-19 10:34:07 -0700160 break;
161 }
162
163 now_ms = get_monotonic_time_ms();
164 if (last_show_ms > 0) {
David Sodman8ef20062015-01-06 09:23:40 -0800165 if (splash->loop_start >= 0 && i >= splash->loop_start)
166 duration = splash->loop_duration;
167 else
168 duration = splash->image_frames[i].duration;
169 sleep_ms = duration - (now_ms - last_show_ms);
David Sodmanbbcb0522014-09-19 10:34:07 -0700170 if (sleep_ms > 0) {
171 sleep_spec.tv_sec = sleep_ms / MS_PER_SEC;
172 sleep_spec.tv_nsec = (sleep_ms % MS_PER_SEC) * NS_PER_MS;
173 nanosleep(&sleep_spec, NULL);
174 }
175 }
176
177 now_ms = get_monotonic_time_ms();
178
David Sodman8ef20062015-01-06 09:23:40 -0800179 if (i >= splash->loop_start) {
180 image_set_offset(image,
181 splash->loop_offset_x,
182 splash->loop_offset_y);
183 }
184
185 status = image_show(image, splash->video);
David Sodmanbbcb0522014-09-19 10:34:07 -0700186 if (status != 0) {
David Sodman8ef20062015-01-06 09:23:40 -0800187 LOG(WARNING, "image_show failed: %d", status);
David Sodmanbbcb0522014-09-19 10:34:07 -0700188 break;
189 }
190 last_show_ms = now_ms;
David Sodman8ef20062015-01-06 09:23:40 -0800191
192 if ((splash->loop_start >= 0) &&
193 (splash->loop_start < splash->num_images)) {
194 if (i == splash->num_images - 1)
195 i = splash->loop_start - 1;
196 }
197
198 image_release(image);
David Sodmanbbcb0522014-09-19 10:34:07 -0700199 }
200 video_unlock(splash->video);
201
David Sodman8ef20062015-01-06 09:23:40 -0800202 for (i = 0; i < splash->num_images; i++) {
203 image_destroy(splash->image_frames[i].image);
204 }
205
David Sodman5c9afa72015-02-14 09:32:53 -0800206 /*
207 * Now Chrome can take over
208 */
209 video_release(splash->video);
Daniel Nicoara13616512015-03-19 17:52:43 -0400210 sync_lock(false);
David Sodman8ef20062015-01-06 09:23:40 -0800211 video_unlock(splash->video);
David Sodman5c9afa72015-02-14 09:32:53 -0800212
David Sodman8ef20062015-01-06 09:23:40 -0800213 if (dbus != NULL) {
214 do {
215 *dbus = dbus_init();
216 usleep(DBUS_WAIT_DELAY);
217 } while (*dbus == NULL);
218 splash_set_dbus(splash, *dbus);
219 }
David Sodmanbbcb0522014-09-19 10:34:07 -0700220
David Sodmanbf3f2842014-11-12 08:26:58 -0800221 if (splash->devmode) {
David Sodmanbbcb0522014-09-19 10:34:07 -0700222 /*
David Sodmanbf3f2842014-11-12 08:26:58 -0800223 * Now set drm_master_relax so that we can transfer drm_master between
224 * chrome and frecon
David Sodmanbbcb0522014-09-19 10:34:07 -0700225 */
David Sodmanbf3f2842014-11-12 08:26:58 -0800226 fd = open("/sys/kernel/debug/dri/drm_master_relax", O_WRONLY);
227 if (fd != -1) {
228 num_written = write(fd, "Y", 1);
229 close(fd);
230
231 /*
232 * If we can't set drm_master relax, then transitions between chrome
233 * and frecon won't work. No point in having frecon hold any resources
234 */
235 if (num_written != 1) {
236 LOG(ERROR, "Unable to set drm_master_relax");
237 splash->devmode = false;
238 }
239 } else {
240 LOG(ERROR, "unable to open drm_master_relax");
David Sodmanbbcb0522014-09-19 10:34:07 -0700241 }
David Sodmandd5b23e2015-02-18 21:36:38 -0800242 } else {
243 /*
244 * Below, we will wait for Chrome to appear above the splash
245 * image. If we are not in dev mode, wait and then exit
246 */
247 sleep(MAX_SPLASH_WAITTIME);
248 exit(EXIT_SUCCESS);
David Sodmanbbcb0522014-09-19 10:34:07 -0700249 }
250 }
David Sodman003faed2014-11-03 09:02:10 -0800251
David Sodman8ef20062015-01-06 09:23:40 -0800252 if (splash->dbus) {
253 (void)dbus_method_call0(splash->dbus,
254 kLibCrosServiceName,
255 kLibCrosServicePath,
256 kLibCrosServiceInterface,
257 kTakeDisplayOwnership);
258 }
David Sodmanf348b0d2015-02-10 08:34:57 -0800259
260 /*
261 * Finally, wait until chrome has drawn on top of the splash. In dev mode,
262 * wait a few seconds for chrome to show up.
263 */
264 sleep(MAX_SPLASH_WAITTIME);
David Sodmanbbcb0522014-09-19 10:34:07 -0700265 return status;
266}
267
David Sodman8ef20062015-01-06 09:23:40 -0800268void splash_set_offset(splash_t* splash, int32_t x, int32_t y)
269{
270 if (splash) {
271 splash->offset_x = x;
272 splash->offset_y = y;
273 }
274}
275
David Sodmanbbcb0522014-09-19 10:34:07 -0700276void splash_set_dbus(splash_t* splash, dbus_t* dbus)
277{
David Sodman8ef20062015-01-06 09:23:40 -0800278 if (splash)
279 splash->dbus = dbus;
David Sodmanbbcb0522014-09-19 10:34:07 -0700280}
281
282void splash_set_devmode(splash_t* splash)
283{
David Sodman8ef20062015-01-06 09:23:40 -0800284 if (splash)
285 splash->devmode = true;
286}
287
288int splash_num_images(splash_t *splash)
289{
290 if (splash)
291 return splash->num_images;
292
293 return 0;
294}
295
296void splash_set_default_duration(splash_t* splash, uint32_t duration)
297{
298 if (splash)
299 splash->default_duration = duration;
300}
301
302void splash_set_loop_start(splash_t* splash, int32_t loop_start)
303{
304 if (splash)
305 splash->loop_start = loop_start;
306}
307
308void splash_set_loop_duration(splash_t* splash, uint32_t duration)
309{
310 if (splash)
311 splash->loop_duration = duration;
312}
313
314void splash_set_loop_offset(splash_t* splash, int32_t x, int32_t y)
315{
316 if (splash) {
317 splash->loop_offset_x = x;
318 splash->loop_offset_y = y;
319 }
David Sodmanbbcb0522014-09-19 10:34:07 -0700320}