#include <common.h>
#include <malloc.h>
#include <lcd.h>
DECLARE_GLOBAL_DATA_PTR;
extern unsigned char rle_default_logo_addr[];
extern int lcd_line_length;
static inline unsigned int color16_to_32(unsigned short color) {
unsigned int r, g, b;
r = color >> 11;
r = (r << 3) | 0x7;
g = (color >> 5) & 0x003F;
g = (g << 2) | 0x3;
b = color & 0x001F;
b = (b << 3) | 0x7;
return r << 16 | g << 8 | b;
}
static inline void fb_set_bpp16(unsigned short *dst, unsigned short color, unsigned int count) {
while (count--) {
*dst++ = color;
}
}
static inline void fb_set_bpp32(unsigned int *dst, unsigned int color, unsigned int count) {
while (count--) {
*dst++ = color;
}
}
/**
* create_fb_from_rle: 通过rle数组所表示的图片和显存每像素所需要的位数创建一片显存,并返回显存的宽度和高度
* @rle: rle数组的起始地址
* @rle_width: 返回显存宽度
* @rle_height: 返回显存高度
* @bpp: 显存每像素所需要的位数
* @return: 返回显存的地址
*/
void *create_fb_from_rle(unsigned short *rle, unsigned int *rle_width, unsigned int *rle_height, int bpp)
{
int is_32_bpp = (bpp == 32 || bpp == 24 || bpp == 18);
unsigned short width, height;
unsigned short count;
unsigned short value;
unsigned int i, j;
unsigned short *dst, *mem;
width = rle[0];
height = rle[1];
rle += 4;
mem = malloc(height * ((width * 2) << is_32_bpp));
if (!mem) {
printf ("%s: failed to allocate memory for rle\n", __func__);
return NULL;
}
dst = mem;
for (i = 0; i < height; ++i) {
for (j = 0; j < width;) {
count = *rle++;
value = *rle++;
if (is_32_bpp)
fb_set_bpp32((unsigned int *)dst, color16_to_32(value), count);
else
fb_set_bpp16(dst, value, count);
dst += (count << is_32_bpp);
j += count;
}
}
*rle_width = width;
*rle_height = height;
return mem;
}
/**
* write_mem: 把base1地址内存中宽width和高height的内容拷贝到base0地址内存中
* @base0: 源内存起始地址
* @base1: 目标内存起始地址
* @width: 源内存内容的宽度
* @height: 源内存内容的高度
* @pixels_line0: 源内存行大小
* @pixels_line1: 目标内存行大小
* @size: 位大小
*/
void write_mem(void *base0, void *base1, int width, int height,
int pixels_line0, int pixels_line1, int size) {
int i;
width = max(width, 0);
height = max(height, 0);
for (i = 0; i < height; ++i) {
memcpy(base0, base1, width * size);
base0 += pixels_line0 * size;
base1 += pixels_line1 * size;
}
}
/**
* write_fb: 把每像素所需的位数相同的源显存src拷贝到目标显存dst的(x,y)位置,注意每像素所需的位数是相同的
* @dst: 目标显存起始地址
* @dst_xres: 目标显存宽度
* @dst_yres: 目标显存高度
* @dst_pixels_line_length: 目标显存行大小
* @src: 源显存起始地址
* @src_xres: 源显存宽度
* @src_yres: 源显存高度
* @src_pixels_line_length: 源显存行大小
* @x: x坐标
* @y: y坐标
* @bpp: 每像素所需的位数
*/
void write_fb(void *dst, int dst_xres, int dst_yres, int dst_pixels_line_length,
void *src, int src_xres, int src_yres, int src_pixels_line_length,
int x, int y, int bpp) {
int x0, y0, x1, y1, x_off, y_off;
int x_len, y_len;
int size = 0;
int is_32_bpp = (bpp == 32 || bpp == 24 || bpp == 18);
if(is_32_bpp)
size = 4;
else
size = 2;
x0 = max(0, x);
y0 = max(0, y);
x_off = x0 - x;
y_off = y0 - y;
if (x >= dst_xres || y >= dst_yres)
return;
x1 = x + src_xres;
y1 = y + src_yres;
if (x1 <= 0 || y1 <= 0)
return;
x_len = x > 0 ? src_xres : x1;
y_len = y > 0 ? src_yres : y1;
if (x1 > dst_xres)
x_len -= (x1 - dst_xres);
if (y1 > dst_yres)
y_len -= (y1 - dst_yres);
write_mem(dst + (y0 * dst_pixels_line_length + x0) * size,
src + (y_off * src_pixels_line_length + x_off) * size,
x_len, y_len,
dst_pixels_line_length, src_pixels_line_length, size);
}
/**
* show_rle_picture: 将rle存储格式的图片以宽为dst_xres高为dst_yres显示在目标显存dst的(x,y)位置
* @src_picture_addr: 源图片rle数组起始地址
* @dst: 目标显存起始地址
* @dst_xres: 目标显存的宽度
* @dst_yres: 目标显存的高度
* @dst_pixels_line_length: 目标显存行大小
* @x: x坐标
* @y: y坐标
* @bpp: 目标显存每像素所需的位数
*/
int show_rle_picture(unsigned short *src_picture_addr, unsigned int *dst,
int dst_xres, int dst_yres, int dst_pixels_line_length,
int x, int y, int bpp) {
unsigned int width, height;
unsigned int *mem = NULL;
mem = create_fb_from_rle(src_picture_addr, &width, &height, bpp);
if (!mem)
return -1;
write_fb(dst, dst_xres, dst_yres, dst_pixels_line_length,
mem, width, height, width,
x, y, bpp);
free(mem);
lcd_sync();
return 0;
}
/**
* show_rle_picture_in_middle: 将rle存储格式的图片以宽为dst_xres高为dst_yres居中显示在目标显存dst上
* @src_picture_addr: 源图片rle数组起始地址
* @dst: 目标显存起始地址
* @dst_xres: 目标显存的宽度
* @dst_yres: 目标显存的高度
* @dst_pixels_line_length: 目标显存行大小
* @bpp: 目标显存每像素所需的位数
*/
int show_rle_picture_in_middle(unsigned short *src_picture_addr, unsigned int *dst,
int dst_xres, int dst_yres,
int dst_pixels_line_length, int bpp) {
int x, y;
unsigned int width, height;
unsigned int *mem = NULL;
mem = create_fb_from_rle(src_picture_addr, &width, &height, bpp);
if (!mem)
return -1;
x = (int)(panel_info.vl_col - width) / 2;
y = (int)(panel_info.vl_row - height) / 2;
write_fb(dst, dst_xres, dst_yres, dst_pixels_line_length,
mem, width, height, width,
x, y, bpp);
free(mem);
lcd_sync();
return 0;
}
/**
* show_rle_picture_in_fb_middle: 居中显示rle存储格式的图片在屏幕上
* @src_picture_addr: 源图片rle数组起始地址
*/
int show_rle_picture_in_fb_middle(unsigned short *src_picture_addr)
{
int ret;
int pixels_line_length = lcd_get_pixels_line_length();
int bpp = NBITS(panel_info.vl_bpix);
ret = show_rle_picture_in_middle(src_picture_addr, gd->fb_base,
panel_info.vl_col, panel_info.vl_row,
pixels_line_length, bpp);
return ret;
}
/*test to show the lcd_logo*/
static int
do_lcd_logo_test(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
unsigned int width, height;
unsigned int *mem = NULL;
int x = 0, y = 0;
if (!((argc == 1) || (argc == 3)))
return CMD_RET_USAGE;
if (argc == 3 ) {
x = simple_strtol(argv[1], NULL, 10);
y = simple_strtol(argv[2], NULL, 10);
}
printf("mem:%p\n", rle_default_logo_addr);
mem = create_fb_from_rle((unsigned int short *)rle_default_logo_addr, &width, &height, 32);
printf("mem:%p width:%d height:%d %d %d \n", mem, width, height, x, y);
if (!mem)
return CMD_RET_SUCCESS;
write_fb(gd->fb_base, panel_info.vl_col, panel_info.vl_row, panel_info.vl_col,
mem, width, height, width,
x, y, 32);
free(mem);
lcd_sync();
return CMD_RET_SUCCESS;
}
U_BOOT_CMD(lcd_logo_test, 3, 0, do_lcd_logo_test,
"test lcd_logo",
"lcd_logo_test [x, y]");
show_rle_picture
最新推荐文章于 2022-10-14 17:26:03 发布