1
0
Fork 0
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:
Linus Nielsen Feltzing 2005-11-14 20:48:34 +00:00
parent f1bdfbf691
commit 63dc8c14b0

View file

@ -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 */
@ -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;