/**************************************************************************
* F U N C T I O N I M P L E M E N T A T I O N S *
**************************************************************************/
#ifdef SUPPORT_LOAD_BMP
static void _initKernelEnv(mm_segment_t *oldfs)
{
*oldfs = get_fs();
set_fs(KERNEL_DS);
}
static void _deinitKernelEnv(mm_segment_t *oldfs)
{
set_fs(*oldfs);
}
static struct file *_openFile(char *path, int flag, int mode)
{
struct file *fp;
fp = filp_open(path, flag, 0);
if (fp)
return fp;
else
return NULL;
}
static int _writeFile(struct file *fp, char *buf, int readlen)
{
if (fp->f_op && fp->f_op->read)
return fp->f_op->write(fp, buf, readlen, &fp->f_pos);
else
return -1;
}
static int _readFile(struct file *fp, char *buf, int readlen)
{
if (fp->f_op && fp->f_op->read)
return fp->f_op->read(fp, buf, readlen, &fp->f_pos);
else
return -1;
}
static int _closeFile(struct file *fp)
{
filp_close(fp, NULL);
return 0;
}
static void _Draw_Bmpfile(char *filename, unsigned int *fb_ptr, int device_id, int start_x, int start_y)
{
unsigned char *tmpbuf = NULL;
struct file *fp = NULL;
mm_segment_t oldfs;
BMP_HEADER bmp = {0};
_initKernelEnv(&oldfs);
fp = _openFile(filename, O_RDONLY, 0);
if (!IS_ERR(fp))
{
int line_pitch = 0, bpp = 0;
int x, y, line_index;
if ((fp == NULL) || (fp && (_readFile(fp, (char *)&bmp.identifier, sizeof(BMP_HEADER) - sizeof(unsigned short)) <= 0)))
{
ERRF("read file:%s error\n", filename);
goto Failed;
}
DEBUG("Image info: size %dx%d, bpp %d, compression %d, offset %d, filesize %d\n", bmp.width, bmp.height, bmp.bpp, bmp.compression, bmp.data_offset, bmp.file_size);
if (!(bmp.bpp == 24 || bmp.bpp == 32))
{
ERRF("only support 24 / 32 bit bitmap\n");
goto Failed;
}
if (bmp.bpp == 24)
line_pitch = DISP_ALIGN(bmp.width, 2);
else
line_pitch = bmp.width;
if ((bmp.width + start_x) > gFB_INFO[device_id]->var.xres)
{
ERRF("bmp_width + start_x >= device width, %d + %d >= %d\n", bmp.width, start_x, gFB_INFO[device_id]->var.xres);
goto Failed;
}
if ((bmp.height + start_y) > gFB_INFO[device_id]->var.yres)
{
ERRF("bmp_height + start_y >= device height, %d + %d >= %d\n", bmp.height, start_y, gFB_INFO[device_id]->var.yres);
goto Failed;
}
bpp = bmp.bpp >> 3;
tmpbuf = chunk_malloc(DRAM_B, line_pitch * bmp.height * bpp);
if (IS_ERR(tmpbuf))
{
ERRF("chunk_malloc error\n");
goto Failed;
}
fp->f_op->llseek(fp, bmp.data_offset, 0);
if (_readFile(fp, tmpbuf, line_pitch * bmp.height * bpp) <= 0)
{
ERRF("read file:%s error\n", filename);
goto Failed;
}
fb_ptr += start_y * gFB_INFO[device_id]->var.xres + start_x;
for (y = bmp.height-1; y >= 0; y--)
{
for (x = 0; x < bmp.width; x++)
{
line_index = (line_pitch * y + x) * bpp;
#if 0
DEBUG("B:%x G:%x R:%x A:%x",
tmpbuf[line_index],
tmpbuf[line_index + 1],
tmpbuf[line_index + 2],
(bmp.bpp==24)?0xff:tmpbuf[line_index + 3]);
#endif
fb_ptr[x] = MAKE_ARGB(
(bmp.bpp == 24)?0xff:tmpbuf[line_index + 3],
tmpbuf[line_index + 2],
tmpbuf[line_index + 1],
tmpbuf[line_index]);
}
fb_ptr += gFB_INFO[device_id]->var.xres;
}
}
else
{
ERRF("Can't open %s\n", filename);
goto Failed;
}
Failed:
if ((!IS_ERR(fp)) && (fp != NULL))
_closeFile(fp);
if (!IS_ERR(tmpbuf) && tmpbuf != NULL)
chunk_free(tmpbuf);
_deinitKernelEnv(&oldfs);
return ;
}
#endif