From 5d8c1529a735254d2cc17e47d294b8835ba575b0 Mon Sep 17 00:00:00 2001 From: Jens Arnold Date: Wed, 16 Nov 2005 01:41:46 +0000 Subject: 16bit LCD driver: * The colour get/set functions now use the native ranges for red/green/blue as intended. * Fixed lcd_fillrect(). * Properly working lcd_mono_bitmap_part(). * Implemented lcd_bitmap_part(). * Some optimisations. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7900 a1c6a512-1295-4272-9138-f99709370657 --- firmware/drivers/lcd-16bit.c | 180 ++++++++++++++++++++++++------------------- 1 file changed, 99 insertions(+), 81 deletions(-) (limited to 'firmware/drivers') diff --git a/firmware/drivers/lcd-16bit.c b/firmware/drivers/lcd-16bit.c index 9f698bbacd..185f572182 100644 --- a/firmware/drivers/lcd-16bit.c +++ b/firmware/drivers/lcd-16bit.c @@ -34,7 +34,7 @@ #define SCROLLABLE_LINES 26 -#define RGB_PACK(r,g,b) (htobe16(((r>>3)<<11)|((g>>2)<<5)|(b>>3))) +#define RGB_PACK(r,g,b) (htobe16(((r)<<11)|((g)<<5)|(b))) /*** globals ***/ fb_data lcd_framebuffer[LCD_HEIGHT][LCD_WIDTH] __attribute__ ((aligned (4))); @@ -73,7 +73,7 @@ int lcd_default_contrast(void) void lcd_init(void) { fg_pattern = 0x0000; /* Black */ - bg_pattern = RGB_PACK(0xb6, 0xc6, 0xe5); /* "Rockbox blue" */ + bg_pattern = RGB_PACK(0x17, 0x31, 0x1d); /* "Rockbox blue" */ lcd_clear_display(); /* Call device specific init */ @@ -96,23 +96,22 @@ int lcd_get_drawmode(void) void lcd_set_foreground(struct rgb color) { - fg_pattern=RGB_PACK(color.red,color.green,color.blue); + fg_pattern = RGB_PACK(color.red, color.green, color.blue); } struct rgb lcd_get_foreground(void) { struct rgb colour; - colour.red=((fg_pattern&0xf800)>>11)<<3; - colour.green=((fg_pattern&0x03e0)>>5)<<2; - colour.blue=(fg_pattern&0x1f)<<3; - + colour.red = (fg_pattern >> 11) & 0x1f; + colour.green = (fg_pattern >> 5) & 0x3f; + colour.blue = fg_pattern & 0x1f; return colour; } void lcd_set_background(struct rgb color) { - bg_pattern=RGB_PACK(color.red,color.green,color.blue); + bg_pattern = RGB_PACK(color.red, color.green, color. blue); } @@ -120,9 +119,9 @@ struct rgb lcd_get_background(void) { struct rgb colour; - colour.red=((bg_pattern&0xf800)>>11)<<3; - colour.green=((bg_pattern&0x03e0)>>5)<<2; - colour.blue=(bg_pattern&0x1f)<<3; + colour.red = (bg_pattern >> 11) & 0x1f; + colour.green = (bg_pattern >> 5) & 0x3f; + colour.blue = bg_pattern & 0x1f; return colour; } @@ -174,14 +173,11 @@ static void clearpixel(int x, int y) static void flippixel(int x, int y) { - /* What should this do on a color display? */ - (void)x; - (void)y; + lcd_framebuffer[y][x] = ~lcd_framebuffer[y][x]; } static void nopixel(int x, int y) { - /* What should this do on a color display? */ (void)x; (void)y; } @@ -196,13 +192,13 @@ lcd_pixelfunc_type* const lcd_pixelfuncs[8] = { /* Clear the whole display */ void lcd_clear_display(void) { - int i; - unsigned short bits = (drawmode & DRMODE_INVERSEVID) ? fg_pattern : bg_pattern; - unsigned short* addr = (unsigned short *)lcd_framebuffer; - - for (i=0;i LCD_HEIGHT) height = LCD_HEIGHT - y; - ny = y + height; - for(;y < ny;y++) + ye = y + height; + xe = x + width; + for(; y < ye; y++) { - int xc; - nx = x + width; - for(xc = x;xc < nx;xc++) - pfunc(x, y); + for(xc = x; xc < xe; xc++) + pfunc(xc, y); } } @@ -404,9 +399,8 @@ void lcd_fillrect(int x, int y, int width, int height) * byte 1 2nd from left etc. The first row of bytes defines pixel rows * 0..7, the second row defines pixel row 8..15 etc. * - * This is similar to the internal lcd hw format. */ - -static unsigned char masks[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; + * This is the mono bitmap format used on all other targets so far; the + * pixel packing doesn't really matter on a 8bit+ target. */ /* Draw a partial monochrome bitmap */ void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, @@ -415,13 +409,10 @@ void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, int stride, int x, int y, int width, int height) { - int in_x,in_y; - int out_x; - int out_y; - unsigned char pixel; - fb_data * addr; + int xe, ye, yc; + lcd_pixelfunc_type *fgfunc; + lcd_pixelfunc_type *bgfunc; - (void)stride; /* nothing to draw? */ if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) || (x + width <= 0) || (y + height <= 0)) @@ -445,24 +436,35 @@ void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, if (y + height > LCD_HEIGHT) height = LCD_HEIGHT - y; -// src += stride * (src_y >> 3) + src_x; /* move starting point */ - - /* Copying from src_x,src_y to (x,y). Size is width,height */ - in_x=src_x; - for (out_x=x;out_x<(x+width);out_x++) { - in_y=src_y; - for (out_y=y;out_y<(y+height);out_y++) { - pixel=(*src)&masks[in_y]; - addr=&lcd_framebuffer[out_y][out_x]; - if (pixel > 0) { - *addr=fg_pattern; - } else { - *addr=bg_pattern; - } - in_y++; - } - in_x++; - src++; + src += stride * (src_y >> 3) + src_x; /* move starting point */ + src_y &= 7; + + xe = x + width; + ye = y + height; + fgfunc = lcd_pixelfuncs[drawmode]; + bgfunc = lcd_pixelfuncs[drawmode ^ DRMODE_INVERSEVID]; + + for (; x < xe; x++) + { + const unsigned char *src_col = src++; + unsigned char data = *src_col >> src_y; + int numbits = 8 - src_y; + + for (yc = y; yc < ye; yc++) + { + if (data & 0x01) + fgfunc(x, yc); + else + bgfunc(x, yc); + + data >>= 1; + if (--numbits == 0) + { + src_col += stride; + data = *src_col; + numbits = 8; + } + } } } @@ -479,33 +481,52 @@ void lcd_bitmap_part(const fb_data *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) { - (void)src; - (void)src_x; - (void)src_y; - (void)stride; - (void)x; - (void)y; - (void)width; - (void)height; + int ye; + + /* nothing to draw? */ + if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) + || (x + width <= 0) || (y + height <= 0)) + 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 + src_x; /* move starting point */ + ye = y + height; + + for (; y < ye; y++) + { + const fb_data *src_row = src; + fb_data *dst = &lcd_framebuffer[y][x]; + fb_data *dst_end = dst + width; + + do + *dst++ = *src_row++; + while (dst < dst_end); + + src += stride; + } } /* Draw a full native bitmap */ void lcd_bitmap(const fb_data *src, int x, int y, int width, int height) { - fb_data* s=(fb_data *)src; - fb_data* d=&lcd_framebuffer[y][x]; - int k=LCD_WIDTH-width; - int i,j; - - for (i=0;i