diff options
| -rw-r--r-- | README | 5 | ||||
| -rw-r--r-- | common/lcd.c | 144 | 
2 files changed, 149 insertions, 0 deletions
| @@ -1469,6 +1469,11 @@ CBFS (Coreboot Filesystem) support  		Normally display is black on white background; define  		CONFIG_SYS_WHITE_ON_BLACK to get it inverted. +		CONFIG_LCD_BMP_RLE8 + +		Support drawing of RLE8-compressed bitmaps on the LCD. + +  - Splash Screen Support: CONFIG_SPLASH_SCREEN  		If this option is set, the environment is checked for diff --git a/common/lcd.c b/common/lcd.c index 7c6cb096f..4c83a8bf0 100644 --- a/common/lcd.c +++ b/common/lcd.c @@ -642,6 +642,138 @@ static void splash_align_axis(int *axis, unsigned long panel_size,  }  #endif + +#ifdef CONFIG_LCD_BMP_RLE8 + +#define BMP_RLE8_ESCAPE		0 +#define BMP_RLE8_EOL		0 +#define BMP_RLE8_EOBMP		1 +#define BMP_RLE8_DELTA		2 + +static void draw_unencoded_bitmap(ushort **fbp, uchar *bmap, ushort *cmap, +				  int cnt) +{ +	while (cnt > 0) { +		*(*fbp)++ = cmap[*bmap++]; +		cnt--; +	} +} + +static void draw_encoded_bitmap(ushort **fbp, ushort c, int cnt) +{ +	ushort *fb = *fbp; +	int cnt_8copy = cnt >> 3; + +	cnt -= cnt_8copy << 3; +	while (cnt_8copy > 0) { +		*fb++ = c; +		*fb++ = c; +		*fb++ = c; +		*fb++ = c; +		*fb++ = c; +		*fb++ = c; +		*fb++ = c; +		*fb++ = c; +		cnt_8copy--; +	} +	while (cnt > 0) { +		*fb++ = c; +		cnt--; +	} +	(*fbp) = fb; +} + +/* + * Do not call this function directly, must be called from + * lcd_display_bitmap. + */ +static void lcd_display_rle8_bitmap(bmp_image_t *bmp, ushort *cmap, uchar *fb, +				    int x_off, int y_off) +{ +	uchar *bmap; +	ulong width, height; +	ulong cnt, runlen; +	int x, y; +	int decode = 1; + +	width = le32_to_cpu(bmp->header.width); +	height = le32_to_cpu(bmp->header.height); +	bmap = (uchar *)bmp + le32_to_cpu(bmp->header.data_offset); + +	x = 0; +	y = height - 1; + +	while (decode) { +		if (bmap[0] == BMP_RLE8_ESCAPE) { +			switch (bmap[1]) { +			case BMP_RLE8_EOL: +				/* end of line */ +				bmap += 2; +				x = 0; +				y--; +				/* 16bpix, 2-byte per pixel, width should *2 */ +				fb -= (width * 2 + lcd_line_length); +				break; +			case BMP_RLE8_EOBMP: +				/* end of bitmap */ +				decode = 0; +				break; +			case BMP_RLE8_DELTA: +				/* delta run */ +				x += bmap[2]; +				y -= bmap[3]; +				/* 16bpix, 2-byte per pixel, x should *2 */ +				fb = (uchar *) (lcd_base + (y + y_off - 1) +					* lcd_line_length + (x + x_off) * 2); +				bmap += 4; +				break; +			default: +				/* unencoded run */ +				runlen = bmap[1]; +				bmap += 2; +				if (y < height) { +					if (x < width) { +						if (x + runlen > width) +							cnt = width - x; +						else +							cnt = runlen; +						draw_unencoded_bitmap( +							(ushort **)&fb, +							bmap, cmap, cnt); +					} +					x += runlen; +				} +				bmap += runlen; +				if (runlen & 1) +					bmap++; +			} +		} else { +			/* encoded run */ +			if (y < height) { +				runlen = bmap[0]; +				if (x < width) { +					/* aggregate the same code */ +					while (bmap[0] == 0xff && +					       bmap[2] != BMP_RLE8_ESCAPE && +					       bmap[1] == bmap[3]) { +						runlen += bmap[2]; +						bmap += 2; +					} +					if (x + runlen > width) +						cnt = width - x; +					else +						cnt = runlen; +					draw_encoded_bitmap((ushort **)&fb, +						cmap[bmap[1]], cnt); +				} +				x += runlen; +			} +			bmap += 2; +		} +	} +} +#endif +  #if defined(CONFIG_MPC823) || defined(CONFIG_MCC200)  #define FB_PUT_BYTE(fb, from) *(fb)++ = (255 - *(from)++)  #else @@ -781,6 +913,18 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y)  	switch (bmp_bpix) {  	case 1: /* pass through */  	case 8: +#ifdef CONFIG_LCD_BMP_RLE8 +		if (le32_to_cpu(bmp->header.compression) == BMP_BI_RLE8) { +			if (bpix != 16) { +				/* TODO implement render code for bpix != 16 */ +				printf("Error: only support 16 bpix"); +				return 1; +			} +			lcd_display_rle8_bitmap(bmp, cmap_base, fb, x, y); +			break; +		} +#endif +  		if (bpix != 16)  			byte_width = width;  		else |