forked from len0rd/rockbox
The 16-bit LCD driver is now 16-bit for real
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7880 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
f1bdfbf691
commit
63dc8c14b0
1 changed files with 39 additions and 266 deletions
|
|
@ -34,13 +34,13 @@
|
||||||
|
|
||||||
#define SCROLLABLE_LINES 26
|
#define SCROLLABLE_LINES 26
|
||||||
|
|
||||||
#define RGB_PACK(r,g,b) (swap16(((r>>3)<<11)|((g>>2)<<5)|(b>>3)))
|
#define RGB_PACK(r,g,b) (htobe16(((r>>3)<<11)|((g>>2)<<5)|(b>>3)))
|
||||||
|
|
||||||
/*** globals ***/
|
/*** globals ***/
|
||||||
unsigned char lcd_framebuffer[LCD_HEIGHT][LCD_WIDTH*2] __attribute__ ((aligned (2)));
|
fb_data lcd_framebuffer[LCD_HEIGHT][LCD_WIDTH] __attribute__ ((aligned (2)));
|
||||||
|
|
||||||
static unsigned fg_pattern = 0x0000; /* Black */
|
static unsigned fg_pattern = 0x0000; /* Black */
|
||||||
static unsigned bg_pattern = 0xbc2d; /* "Rockbox blue" */
|
static unsigned bg_pattern = RGB_PACK(0xb6, 0xc6, 0xe5); /* "Rockbox blue" */
|
||||||
static int drawmode = DRMODE_SOLID;
|
static int drawmode = DRMODE_SOLID;
|
||||||
static int xmargin = 0;
|
static int xmargin = 0;
|
||||||
static int ymargin = 0;
|
static int ymargin = 0;
|
||||||
|
|
@ -155,14 +155,12 @@ int lcd_getstringsize(const unsigned char *str, int *w, int *h)
|
||||||
|
|
||||||
static void setpixel(int x, int y)
|
static void setpixel(int x, int y)
|
||||||
{
|
{
|
||||||
unsigned short *data = (unsigned short*)&lcd_framebuffer[y][x*2];
|
lcd_framebuffer[y][x] = fg_pattern;
|
||||||
*data = fg_pattern;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clearpixel(int x, int y)
|
static void clearpixel(int x, int y)
|
||||||
{
|
{
|
||||||
unsigned short *data = (unsigned short*)&lcd_framebuffer[y][x*2];
|
lcd_framebuffer[y][x] = bg_pattern;
|
||||||
*data = bg_pattern;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void flippixel(int x, int y)
|
static void flippixel(int x, int y)
|
||||||
|
|
@ -184,82 +182,6 @@ lcd_pixelfunc_type* const lcd_pixelfuncs[8] = {
|
||||||
nopixel, clearpixel, nopixel, clearpixel
|
nopixel, clearpixel, nopixel, clearpixel
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 'mask' and 'bits' contain 2 bits per pixel */
|
|
||||||
static void flipblock(unsigned char *address, unsigned mask, unsigned bits)
|
|
||||||
ICODE_ATTR;
|
|
||||||
static void flipblock(unsigned char *address, unsigned mask, unsigned bits)
|
|
||||||
{
|
|
||||||
*address ^= bits & mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bgblock(unsigned char *address, unsigned mask, unsigned bits)
|
|
||||||
ICODE_ATTR;
|
|
||||||
static void bgblock(unsigned char *address, unsigned mask, unsigned bits)
|
|
||||||
{
|
|
||||||
(void)bits;
|
|
||||||
if (mask > 0) {
|
|
||||||
*address = bg_pattern;
|
|
||||||
} else {
|
|
||||||
*address = fg_pattern;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fgblock(unsigned char *address, unsigned mask, unsigned bits)
|
|
||||||
ICODE_ATTR;
|
|
||||||
static void fgblock(unsigned char *address, unsigned mask, unsigned bits)
|
|
||||||
{
|
|
||||||
(void)bits;
|
|
||||||
if (mask > 0) {
|
|
||||||
*address = fg_pattern;
|
|
||||||
} else {
|
|
||||||
*address = bg_pattern;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void solidblock(unsigned char *address, unsigned mask, unsigned bits)
|
|
||||||
ICODE_ATTR;
|
|
||||||
static void solidblock(unsigned char *address, unsigned mask, unsigned bits)
|
|
||||||
{
|
|
||||||
*address = (*address & ~mask) | (bits & mask & fg_pattern)
|
|
||||||
| (~bits & mask & bg_pattern);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void flipinvblock(unsigned char *address, unsigned mask, unsigned bits)
|
|
||||||
ICODE_ATTR;
|
|
||||||
static void flipinvblock(unsigned char *address, unsigned mask, unsigned bits)
|
|
||||||
{
|
|
||||||
*address ^= ~bits & mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bginvblock(unsigned char *address, unsigned mask, unsigned bits)
|
|
||||||
ICODE_ATTR;
|
|
||||||
static void bginvblock(unsigned char *address, unsigned mask, unsigned bits)
|
|
||||||
{
|
|
||||||
mask &= bits;
|
|
||||||
*address = (*address & ~mask) | (bg_pattern & mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fginvblock(unsigned char *address, unsigned mask, unsigned bits)
|
|
||||||
ICODE_ATTR;
|
|
||||||
static void fginvblock(unsigned char *address, unsigned mask, unsigned bits)
|
|
||||||
{
|
|
||||||
mask &= ~bits;
|
|
||||||
*address = (*address & ~mask) | (fg_pattern & mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void solidinvblock(unsigned char *address, unsigned mask, unsigned bits)
|
|
||||||
ICODE_ATTR;
|
|
||||||
static void solidinvblock(unsigned char *address, unsigned mask, unsigned bits)
|
|
||||||
{
|
|
||||||
*address = (*address & ~mask) | (~bits & mask & fg_pattern)
|
|
||||||
| (bits & mask & bg_pattern);
|
|
||||||
}
|
|
||||||
|
|
||||||
lcd_blockfunc_type* const lcd_blockfuncs[8] = {
|
|
||||||
flipblock, bgblock, fgblock, solidblock,
|
|
||||||
flipinvblock, bginvblock, fginvblock, solidinvblock
|
|
||||||
};
|
|
||||||
|
|
||||||
/*** drawing functions ***/
|
/*** drawing functions ***/
|
||||||
|
|
||||||
/* Clear the whole display */
|
/* Clear the whole display */
|
||||||
|
|
@ -267,7 +189,7 @@ void lcd_clear_display(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
unsigned short bits = (drawmode & DRMODE_INVERSEVID) ? fg_pattern : bg_pattern;
|
unsigned short bits = (drawmode & DRMODE_INVERSEVID) ? fg_pattern : bg_pattern;
|
||||||
unsigned short* addr = (unsigned short*)lcd_framebuffer;
|
unsigned short* addr = (unsigned short *)lcd_framebuffer;
|
||||||
|
|
||||||
for (i=0;i<LCD_HEIGHT*LCD_WIDTH;i++) {
|
for (i=0;i<LCD_HEIGHT*LCD_WIDTH;i++) {
|
||||||
*(addr++)=bits;
|
*(addr++)=bits;
|
||||||
|
|
@ -357,9 +279,7 @@ void lcd_drawline(int x1, int y1, int x2, int y2)
|
||||||
void lcd_hline(int x1, int x2, int y)
|
void lcd_hline(int x1, int x2, int y)
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
unsigned char *dst, *dst_end;
|
lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[drawmode];
|
||||||
unsigned mask;
|
|
||||||
lcd_blockfunc_type *bfunc;
|
|
||||||
|
|
||||||
/* direction flip */
|
/* direction flip */
|
||||||
if (x2 < x1)
|
if (x2 < x1)
|
||||||
|
|
@ -379,30 +299,23 @@ void lcd_hline(int x1, int x2, int y)
|
||||||
if (x2 >= LCD_WIDTH)
|
if (x2 >= LCD_WIDTH)
|
||||||
x2 = LCD_WIDTH-1;
|
x2 = LCD_WIDTH-1;
|
||||||
|
|
||||||
bfunc = lcd_blockfuncs[drawmode];
|
|
||||||
dst = &lcd_framebuffer[y>>2][x1];
|
|
||||||
mask = 3 << (2 * (y & 3));
|
|
||||||
|
|
||||||
dst_end = dst + x2 - x1;
|
|
||||||
do
|
do
|
||||||
bfunc(dst++, mask, 0xFFu);
|
pfunc(x1++, y);
|
||||||
while (dst <= dst_end);
|
while (x1 <= x2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Draw a vertical line (optimised) */
|
/* Draw a vertical line (optimised) */
|
||||||
void lcd_vline(int x, int y1, int y2)
|
void lcd_vline(int x, int y1, int y2)
|
||||||
{
|
{
|
||||||
int ny;
|
int y;
|
||||||
unsigned char *dst;
|
lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[drawmode];
|
||||||
unsigned mask, mask_bottom;
|
|
||||||
lcd_blockfunc_type *bfunc;
|
|
||||||
|
|
||||||
/* direction flip */
|
/* direction flip */
|
||||||
if (y2 < y1)
|
if (y2 < y1)
|
||||||
{
|
{
|
||||||
ny = y1;
|
y = y1;
|
||||||
y1 = y2;
|
y1 = y2;
|
||||||
y2 = ny;
|
y2 = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* nothing to draw? */
|
/* nothing to draw? */
|
||||||
|
|
@ -415,20 +328,10 @@ void lcd_vline(int x, int y1, int y2)
|
||||||
if (y2 >= LCD_HEIGHT)
|
if (y2 >= LCD_HEIGHT)
|
||||||
y2 = LCD_HEIGHT-1;
|
y2 = LCD_HEIGHT-1;
|
||||||
|
|
||||||
bfunc = lcd_blockfuncs[drawmode];
|
|
||||||
dst = &lcd_framebuffer[y1>>2][x];
|
|
||||||
ny = y2 - (y1 & ~3);
|
|
||||||
mask = 0xFFu << (2 * (y1 & 3));
|
|
||||||
mask_bottom = 0xFFu >> (2 * (~ny & 3));
|
|
||||||
|
|
||||||
for (; ny >= 4; ny -= 4)
|
do
|
||||||
{
|
pfunc(x, y1++);
|
||||||
bfunc(dst, mask, 0xFFu);
|
while (y1 <= y2);
|
||||||
dst += LCD_WIDTH;
|
|
||||||
mask = 0xFFu;
|
|
||||||
}
|
|
||||||
mask &= mask_bottom;
|
|
||||||
bfunc(dst, mask, 0xFFu);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Draw a rectangular box */
|
/* Draw a rectangular box */
|
||||||
|
|
@ -449,12 +352,8 @@ void lcd_drawrect(int x, int y, int width, int height)
|
||||||
/* Fill a rectangular area */
|
/* Fill a rectangular area */
|
||||||
void lcd_fillrect(int x, int y, int width, int height)
|
void lcd_fillrect(int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
int ny;
|
int nx, ny;
|
||||||
unsigned char *dst, *dst_end;
|
lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[drawmode];
|
||||||
unsigned mask, mask_bottom;
|
|
||||||
unsigned bits = fg_pattern;
|
|
||||||
lcd_blockfunc_type *bfunc;
|
|
||||||
bool fillopt;
|
|
||||||
|
|
||||||
/* nothing to draw? */
|
/* nothing to draw? */
|
||||||
if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
|
if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
|
||||||
|
|
@ -477,43 +376,13 @@ void lcd_fillrect(int x, int y, int width, int height)
|
||||||
if (y + height > LCD_HEIGHT)
|
if (y + height > LCD_HEIGHT)
|
||||||
height = LCD_HEIGHT - y;
|
height = LCD_HEIGHT - y;
|
||||||
|
|
||||||
fillopt = (drawmode & DRMODE_INVERSEVID) ?
|
ny = y + height;
|
||||||
(drawmode & DRMODE_BG) : (drawmode & DRMODE_FG);
|
for(;y < ny;y++)
|
||||||
if (fillopt &&(drawmode & DRMODE_INVERSEVID))
|
|
||||||
bits = bg_pattern;
|
|
||||||
bfunc = lcd_blockfuncs[drawmode];
|
|
||||||
dst = &lcd_framebuffer[y>>2][x];
|
|
||||||
ny = height - 1 + (y & 3);
|
|
||||||
mask = 0xFFu << (2 * (y & 3));
|
|
||||||
mask_bottom = 0xFFu >> (2 * (~ny & 3));
|
|
||||||
|
|
||||||
for (; ny >= 4; ny -= 4)
|
|
||||||
{
|
{
|
||||||
if (fillopt && (mask == 0xFFu))
|
int xc;
|
||||||
memset(dst, bits, width);
|
nx = x + width;
|
||||||
else
|
for(xc = x;xc < nx;xc++)
|
||||||
{
|
pfunc(x, y);
|
||||||
unsigned char *dst_row = dst;
|
|
||||||
|
|
||||||
dst_end = dst_row + width;
|
|
||||||
do
|
|
||||||
bfunc(dst_row++, mask, 0xFFu);
|
|
||||||
while (dst_row < dst_end);
|
|
||||||
}
|
|
||||||
|
|
||||||
dst += LCD_WIDTH;
|
|
||||||
mask = 0xFFu;
|
|
||||||
}
|
|
||||||
mask &= mask_bottom;
|
|
||||||
|
|
||||||
if (fillopt && (mask == 0xFFu))
|
|
||||||
memset(dst, bits, width);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dst_end = dst + width;
|
|
||||||
do
|
|
||||||
bfunc(dst++, mask, 0xFFu);
|
|
||||||
while (dst < dst_end);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -541,7 +410,7 @@ void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y,
|
||||||
int out_x;
|
int out_x;
|
||||||
int out_y;
|
int out_y;
|
||||||
unsigned char pixel;
|
unsigned char pixel;
|
||||||
unsigned short* addr;
|
fb_data * addr;
|
||||||
|
|
||||||
(void)stride;
|
(void)stride;
|
||||||
/* nothing to draw? */
|
/* nothing to draw? */
|
||||||
|
|
@ -575,7 +444,7 @@ void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y,
|
||||||
in_y=src_y;
|
in_y=src_y;
|
||||||
for (out_y=y;out_y<(y+height);out_y++) {
|
for (out_y=y;out_y<(y+height);out_y++) {
|
||||||
pixel=(*src)&masks[in_y];
|
pixel=(*src)&masks[in_y];
|
||||||
addr=(unsigned short*)&lcd_framebuffer[out_y][out_x*2];
|
addr=&lcd_framebuffer[out_y][out_x];
|
||||||
if (pixel > 0) {
|
if (pixel > 0) {
|
||||||
*addr=fg_pattern;
|
*addr=fg_pattern;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -595,123 +464,27 @@ void lcd_mono_bitmap(const unsigned char *src, int x, int y, int width, int heig
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Draw a partial native bitmap */
|
/* Draw a partial native bitmap */
|
||||||
void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y,
|
void lcd_bitmap_part(const fb_data *src, int src_x, int src_y,
|
||||||
int stride, int x, int y, int width, int height)
|
int stride, int x, int y, int width, int height)
|
||||||
ICODE_ATTR;
|
ICODE_ATTR;
|
||||||
void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y,
|
void lcd_bitmap_part(const fb_data *src, int src_x, int src_y,
|
||||||
int stride, int x, int y, int width, int height)
|
int stride, int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
int shift, ny;
|
(void)src;
|
||||||
unsigned char *dst, *dst_end;
|
(void)src_x;
|
||||||
unsigned mask, mask_bottom;
|
(void)src_y;
|
||||||
lcd_blockfunc_type *bfunc;
|
(void)stride;
|
||||||
|
(void)x;
|
||||||
/* nothing to draw? */
|
(void)y;
|
||||||
if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
|
(void)width;
|
||||||
|| (x + width <= 0) || (y + height <= 0))
|
(void)height;
|
||||||
return;
|
|
||||||
|
|
||||||
/* clipping */
|
|
||||||
if (x < 0)
|
|
||||||
{
|
|
||||||
width += x;
|
|
||||||
src_x -= x;
|
|
||||||
x = 0;
|
|
||||||
}
|
|
||||||
if (y < 0)
|
|
||||||
{
|
|
||||||
height += y;
|
|
||||||
src_y -= y;
|
|
||||||
y = 0;
|
|
||||||
}
|
|
||||||
if (x + width > LCD_WIDTH)
|
|
||||||
width = LCD_WIDTH - x;
|
|
||||||
if (y + height > LCD_HEIGHT)
|
|
||||||
height = LCD_HEIGHT - y;
|
|
||||||
|
|
||||||
src += stride * (src_y >> 2) + src_x; /* move starting point */
|
|
||||||
src_y &= 3;
|
|
||||||
y -= src_y;
|
|
||||||
dst = &lcd_framebuffer[y>>2][x];
|
|
||||||
shift = y & 3;
|
|
||||||
ny = height - 1 + shift + src_y;
|
|
||||||
|
|
||||||
bfunc = lcd_blockfuncs[drawmode];
|
|
||||||
mask = 0xFFu << (2 * (shift + src_y));
|
|
||||||
mask_bottom = 0xFFu >> (2 * (~ny & 3));
|
|
||||||
|
|
||||||
if (shift == 0)
|
|
||||||
{
|
|
||||||
for (; ny >= 4; ny -= 4)
|
|
||||||
{
|
|
||||||
if (mask == 0xFFu)
|
|
||||||
memcpy(dst, src, width);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const unsigned char *src_row = src;
|
|
||||||
unsigned char *dst_row = dst;
|
|
||||||
|
|
||||||
dst_end = dst_row + width;
|
|
||||||
do
|
|
||||||
bfunc(dst_row++, mask, *src_row++);
|
|
||||||
while (dst_row < dst_end);
|
|
||||||
}
|
|
||||||
|
|
||||||
src += stride;
|
|
||||||
dst += LCD_WIDTH;
|
|
||||||
mask = 0xFFu;
|
|
||||||
}
|
|
||||||
mask &= mask_bottom;
|
|
||||||
|
|
||||||
if (mask == 0xFFu)
|
|
||||||
memcpy(dst, src, width);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dst_end = dst + width;
|
|
||||||
do
|
|
||||||
bfunc(dst++, mask, *src++);
|
|
||||||
while (dst < dst_end);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
shift *= 2;
|
|
||||||
dst_end = dst + width;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
const unsigned char *src_col = src++;
|
|
||||||
unsigned char *dst_col = dst++;
|
|
||||||
unsigned mask_col = mask;
|
|
||||||
unsigned data = 0;
|
|
||||||
|
|
||||||
for (y = ny; y >= 4; y -= 4)
|
|
||||||
{
|
|
||||||
data |= *src_col << shift;
|
|
||||||
|
|
||||||
if (mask_col & 0xFFu)
|
|
||||||
{
|
|
||||||
bfunc(dst_col, mask_col, data);
|
|
||||||
mask_col = 0xFFu;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
mask_col >>= 8;
|
|
||||||
|
|
||||||
src_col += stride;
|
|
||||||
dst_col += LCD_WIDTH;
|
|
||||||
data >>= 8;
|
|
||||||
}
|
|
||||||
data |= *src_col << shift;
|
|
||||||
bfunc(dst_col, mask_col & mask_bottom, data);
|
|
||||||
}
|
|
||||||
while (dst < dst_end);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Draw a full native bitmap */
|
/* Draw a full native bitmap */
|
||||||
void lcd_bitmap(const unsigned char *src, int x, int y, int width, int height)
|
void lcd_bitmap(const fb_data *src, int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
unsigned short* s=(unsigned short*)src;
|
fb_data* s=(fb_data *)src;
|
||||||
unsigned short* d=(unsigned short*)&lcd_framebuffer[y][x*2];
|
fb_data* d=&lcd_framebuffer[y][x];
|
||||||
int k=LCD_WIDTH-width;
|
int k=LCD_WIDTH-width;
|
||||||
int i,j;
|
int i,j;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue