Home | History | Annotate | Line # | Download | only in splash
splash.c revision 1.7.2.1
      1 /* $NetBSD: splash.c,v 1.7.2.1 2010/04/30 14:43:50 uebayasi Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2006 Jared D. McNeill <jmcneill (at) invisible.ca>
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *        This product includes software developed by the NetBSD
     18  *        Foundation, Inc. and its contributors.
     19  * 4. Neither the name of The NetBSD Foundation nor the names of its
     20  *    contributors may be used to endorse or promote products derived
     21  *    from this software without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     24  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     25  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     26  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     27  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     33  * POSSIBILITY OF SUCH DAMAGE.
     34  */
     35 
     36 #include <sys/cdefs.h>
     37 __KERNEL_RCSID(0, "$NetBSD: splash.c,v 1.7.2.1 2010/04/30 14:43:50 uebayasi Exp $");
     38 
     39 #include "opt_splash.h"
     40 
     41 /* XXX */
     42 #define	NSPLASH8 1
     43 #define	NSPLASH16 1
     44 #define	NSPLASH32 1
     45 
     46 #include <sys/param.h>
     47 #include <sys/device.h>
     48 #include <sys/systm.h>
     49 #include <sys/types.h>
     50 #include <sys/kernel.h>
     51 #include <sys/kthread.h>
     52 
     53 #include <dev/splash/splash.h>
     54 
     55 #if !defined(SPLASHSCREEN) && defined(SPLASHSCREEN_PROGRESS)
     56 #error "options SPLASHSCREEN_PROGRESS requires SPLASHSCREEN"
     57 #endif
     58 
     59 #ifdef __HAVE_CPU_COUNTER
     60 #include <sys/cpu.h>
     61 #include <machine/cpu_counter.h>
     62 #endif
     63 
     64 #ifndef SPLASHSCREEN_IMAGE
     65 #define SPLASHSCREEN_IMAGE "dev/splash/images/netbsd.h"
     66 #endif
     67 
     68 #ifdef SPLASHSCREEN
     69 #include SPLASHSCREEN_IMAGE
     70 
     71 #ifdef SPLASHSCREEN_PROGRESS
     72 struct splash_progress *splash_progress_state;
     73 #ifdef __HAVE_CPU_COUNTER
     74 static uint64_t splash_last_update;
     75 #endif
     76 #endif
     77 
     78 #if NSPLASH8 > 0
     79 static void	splash_render8(struct splash_info *, const char *, int,
     80 			       int, int, int, int);
     81 #endif
     82 #if NSPLASH16 > 0
     83 static void	splash_render16(struct splash_info *, const char *, int,
     84 				int, int, int, int);
     85 #endif
     86 #if NSPLASH32 > 0
     87 static void	splash_render32(struct splash_info *, const char *, int,
     88 				int, int, int, int);
     89 #endif
     90 
     91 void
     92 splash_render(struct splash_info *si, int flg)
     93 {
     94 	int xoff, yoff;
     95 
     96 	/* XXX */
     97 	if (flg & SPLASH_F_CENTER) {
     98 		xoff = (si->si_width - _splash_width) / 2;
     99 		yoff = (si->si_height - _splash_height) / 2;
    100 	} else
    101 		xoff = yoff = 0;
    102 
    103 	switch (si->si_depth) {
    104 #if NSPLASH8 > 0
    105 	case 8:
    106 		splash_render8(si, _splash_header_data, xoff, yoff,
    107 		    _splash_width, _splash_height, flg);
    108 		break;
    109 #endif
    110 #if NSPLASH16 > 0
    111 	case 16:
    112 		splash_render16(si, _splash_header_data, xoff, yoff,
    113 		    _splash_width, _splash_height, flg);
    114 		break;
    115 #endif
    116 #if NSPLASH32 > 0
    117 	case 32:
    118 		splash_render32(si, _splash_header_data, xoff, yoff,
    119 		    _splash_width, _splash_height, flg);
    120 		break;
    121 #endif
    122 	default:
    123 		aprint_error("WARNING: Splash not supported at %dbpp\n",
    124 		    si->si_depth);
    125 		break;
    126 	}
    127 
    128 	return;
    129 }
    130 
    131 #if NSPLASH8 > 0
    132 static void
    133 splash_render8(struct splash_info *si, const char *data, int xoff, int yoff,
    134 	       int swidth, int sheight, int flg)
    135 {
    136 	const char *p;
    137 	u_char *fb, pix;
    138 	int x, y, i;
    139 	int filled;
    140 
    141 	fb = si->si_bits;
    142 	if (flg & SPLASH_F_FILL)
    143 		filled = 0;
    144 	else
    145 		filled = 1;
    146 
    147 	p = data;
    148 	fb += xoff + (yoff * si->si_width);
    149 	for (y = 0; y < sheight; y++) {
    150 		for (x = 0; x < swidth; x++) {
    151 			pix = *p++;
    152 			pix += SPLASH_CMAP_OFFSET;
    153 			if (filled == 0) {
    154 				for (i = 0; i < (si->si_width * si->si_height);
    155 				     i++)
    156 					si->si_bits[i] = pix;
    157 				filled = 1;
    158 			}
    159 			fb[x] = pix;
    160 		}
    161 		fb += si->si_width;
    162 	}
    163 
    164 	/* If we've just written to the shadow fb, copy it to the display */
    165 	if (si->si_hwbits) {
    166 		if (flg & SPLASH_F_FILL) {
    167 			memcpy(si->si_hwbits, si->si_bits,
    168 			    si->si_width*si->si_height);
    169 		} else {
    170 			u_char *rp, *hrp;
    171 
    172 			rp = si->si_bits + xoff + (yoff * si->si_width);
    173 			hrp = si->si_hwbits + xoff + (yoff * si->si_width);
    174 
    175 			for (y = 0; y < sheight; y++) {
    176 				memcpy(hrp, rp, swidth);
    177 				hrp += si->si_stride;
    178 				rp += si->si_stride;
    179 			}
    180 		}
    181 	}
    182 
    183 	return;
    184 }
    185 #endif /* !NSPLASH8 > 0 */
    186 
    187 #if NSPLASH16 > 0
    188 #define RGBTO16(b, o, x, c)					\
    189 	do {							\
    190 		uint16_t *_ptr = (uint16_t *)(&(b)[(o)]);	\
    191 		*_ptr = (((c)[(x)*3+0] / 8) << 11) |		\
    192 			(((c)[(x)*3+1] / 4) << 5) |		\
    193 			(((c)[(x)*3+2] / 8) << 0);		\
    194 	} while (0)
    195 
    196 static void
    197 splash_render16(struct splash_info *si, const char *data, int xoff, int yoff,
    198 		int swidth, int sheight, int flg)
    199 {
    200 	const char *d;
    201 	u_char *fb, *p;
    202 	u_char pix[3];
    203 	int x, y, i;
    204 	int filled;
    205 
    206 	fb = si->si_bits;
    207 
    208 	if (flg & SPLASH_F_FILL)
    209 		filled = 0;
    210 	else
    211 		filled = 1;
    212 
    213 	d = data;
    214 	fb += xoff * 2 + yoff * si->si_stride;
    215 
    216 	for (y = 0; y < sheight; y++) {
    217 		for (x = 0; x < swidth; x++) {
    218 			_SPLASH_HEADER_PIXEL(d, pix);
    219 			if (filled == 0) {
    220 				p = si->si_bits;
    221 				i = 0;
    222 				while (i < si->si_height*si->si_stride) {
    223 					RGBTO16(p, i, 0, pix);
    224 					i += 2;
    225 				}
    226 				filled = 1;
    227 			}
    228 			RGBTO16(fb, x*2, 0, pix);
    229 		}
    230 		fb += si->si_stride;
    231 	}
    232 
    233 	/* If we've just written to the shadow fb, copy it to the display */
    234 	if (si->si_hwbits) {
    235 		if (flg & SPLASH_F_FILL) {
    236 			memcpy(si->si_hwbits, si->si_bits,
    237 			    si->si_height*si->si_stride);
    238 		} else {
    239 			u_char *rp, *hrp;
    240 
    241 			rp = si->si_bits + (xoff * 2) + (yoff * si->si_stride);
    242 			hrp = si->si_hwbits + (xoff * 2) +
    243 			    (yoff * si->si_stride);
    244 
    245 			for (y = 0; y < sheight; y++) {
    246 				memcpy(hrp, rp, swidth * 2);
    247 				rp += si->si_stride;
    248 				hrp += si->si_stride;
    249 			}
    250 		}
    251 	}
    252 
    253 	return;
    254 }
    255 #undef RGBTO16
    256 #endif /* !NSPLASH16 > 0 */
    257 
    258 #if NSPLASH32 > 0
    259 static void
    260 splash_render32(struct splash_info *si, const char *data, int xoff, int yoff,
    261 		int swidth, int sheight, int flg)
    262 {
    263 	const char *d;
    264 	u_char *fb, *p;
    265 	u_char pix[3];
    266 	int x, y, i;
    267 	int filled;
    268 
    269 	fb = si->si_bits;
    270 
    271 	if (flg & SPLASH_F_FILL)
    272 		filled = 0;
    273 	else
    274 		filled = 1;
    275 
    276 	d = data;
    277 	fb += xoff * 4 + yoff * si->si_stride;
    278 
    279 	for (y = 0; y < sheight; y++) {
    280 		for (x = 0; x < swidth; x++) {
    281 			_SPLASH_HEADER_PIXEL(d, pix);
    282 			if (filled == 0) {
    283 				p = si->si_bits;
    284 				i = 0;
    285 				while (i < si->si_height*si->si_stride) {
    286 					p[i++] = pix[2];
    287 					p[i++] = pix[1];
    288 					p[i++] = pix[0];
    289 					p[i++] = 0;
    290 				}
    291 				filled = 1;
    292 			}
    293 			fb[x*4+0] = pix[2];
    294 			fb[x*4+1] = pix[1];
    295 			fb[x*4+2] = pix[0];
    296 			fb[x*4+3] = 0;
    297 		}
    298 		fb += si->si_stride;
    299 	}
    300 
    301 	/* If we've just written to the shadow fb, copy it to the display */
    302 	if (si->si_hwbits) {
    303 		if (flg & SPLASH_F_FILL) {
    304 			memcpy(si->si_hwbits, si->si_bits,
    305 			    si->si_height*si->si_stride);
    306 		} else {
    307 			u_char *rp, *hrp;
    308 
    309 			rp = si->si_bits + (xoff * 4) + (yoff * si->si_stride);
    310 			hrp = si->si_hwbits + (xoff * 4) +
    311 			    (yoff * si->si_stride);
    312 
    313 			for (y = 0; y < sheight; y++) {
    314 				memcpy(hrp, rp, swidth * 4);
    315 				rp += si->si_stride;
    316 				hrp += si->si_stride;
    317 			}
    318 		}
    319 	}
    320 
    321 	return;
    322 }
    323 #endif /* !NSPLASH32 > 0 */
    324 
    325 #ifdef SPLASHSCREEN_PROGRESS
    326 
    327 static void
    328 splash_progress_render(struct splash_progress *sp)
    329 {
    330 	struct splash_info *si;
    331 	int i;
    332 	int w;
    333 	int spacing;
    334 	int xoff;
    335 	int yoff;
    336 	int flg;
    337 
    338 	si = sp->sp_si;
    339 	flg = 0;
    340 
    341 	/* where should we draw the pulsers? */
    342 	yoff = (si->si_height / 8) * 7;
    343 	w = _pulse_off_width * SPLASH_PROGRESS_NSTATES;
    344 	xoff = (si->si_width / 4) * 3;
    345 	spacing = _pulse_off_width; /* XXX */
    346 
    347 	for (i = 0; i < SPLASH_PROGRESS_NSTATES; i++) {
    348 		const char *d = (sp->sp_state == i ? _pulse_on_header_data :
    349 				 _pulse_off_header_data);
    350 		switch (si->si_depth) {
    351 #if NSPLASH8 > 0
    352 		case 8:
    353 			splash_render8(si, d, (xoff + (i * spacing)),
    354 			    yoff, _pulse_off_width, _pulse_off_height, flg);
    355 			break;
    356 #endif
    357 #if NSPLASH16 > 0
    358 		case 16:
    359 			splash_render16(si, d, (xoff + (i * spacing)),
    360 			    yoff, _pulse_off_width, _pulse_off_height, flg);
    361 			break;
    362 #endif
    363 #if NSPLASH32 > 0
    364 		case 32:
    365 			splash_render32(si, d, (xoff + (i * spacing)),
    366 			    yoff, _pulse_off_width, _pulse_off_height, flg);
    367 			break;
    368 #endif
    369 		default:
    370 			/* do nothing */
    371 			break;
    372 		}
    373 	}
    374 }
    375 
    376 static int
    377 splash_progress_stop(device_t dev)
    378 {
    379 	struct splash_progress *sp;
    380 
    381 	sp = (struct splash_progress *)dev;
    382 	sp->sp_running = 0;
    383 
    384 	return 0;
    385 }
    386 
    387 void
    388 splash_progress_init(struct splash_progress *sp)
    389 {
    390 #ifdef __HAVE_CPU_COUNTER
    391 	if (cpu_hascounter())
    392 		splash_last_update = cpu_counter();
    393 	else
    394 		splash_last_update = 0;
    395 #endif
    396 
    397 	sp->sp_running = 1;
    398 	sp->sp_force = 0;
    399 	splash_progress_state = sp;
    400 	splash_progress_render(sp);
    401 	config_finalize_register((device_t)sp, splash_progress_stop);
    402 
    403 	return;
    404 }
    405 
    406 void
    407 splash_progress_update(struct splash_progress *sp)
    408 {
    409 	if (sp->sp_running == 0 && sp->sp_force == 0)
    410 		return;
    411 
    412 #ifdef __HAVE_CPU_COUNTER
    413 	if (cpu_hascounter()) {
    414 		uint64_t now;
    415 
    416 		if (splash_last_update == 0) {
    417 			splash_last_update = cpu_counter();
    418 		} else {
    419 			now = cpu_counter();
    420 			if (splash_last_update + cpu_frequency(curcpu())/4 >
    421 			    now)
    422 				return;
    423 			splash_last_update = now;
    424 		}
    425 	}
    426 #endif
    427 	sp->sp_state++;
    428 	if (sp->sp_state >= SPLASH_PROGRESS_NSTATES)
    429 		sp->sp_state = 0;
    430 
    431 	splash_progress_render(sp);
    432 }
    433 
    434 #endif /* !SPLASHSCREEN_PROGRESS */
    435 
    436 #endif /* !SPLASHSCREEN */
    437