diff options
author | Jens Arnold <amiconn@rockbox.org> | 2005-11-16 01:41:46 +0000 |
---|---|---|
committer | Jens Arnold <amiconn@rockbox.org> | 2005-11-16 01:41:46 +0000 |
commit | 5d8c1529a735254d2cc17e47d294b8835ba575b0 (patch) | |
tree | ac587a676b0c75eacd6ed4a9bcc2b68f98f4d760 /firmware/drivers | |
parent | a7db52ca894f9d80845267f743ae56663b37f605 (diff) | |
download | rockbox-5d8c1529a735254d2cc17e47d294b8835ba575b0.tar.gz rockbox-5d8c1529a735254d2cc17e47d294b8835ba575b0.zip |
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
Diffstat (limited to 'firmware/drivers')
-rw-r--r-- | firmware/drivers/lcd-16bit.c | 180 |
1 files changed, 99 insertions, 81 deletions
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 @@ | |||
34 | 34 | ||
35 | #define SCROLLABLE_LINES 26 | 35 | #define SCROLLABLE_LINES 26 |
36 | 36 | ||
37 | #define RGB_PACK(r,g,b) (htobe16(((r>>3)<<11)|((g>>2)<<5)|(b>>3))) | 37 | #define RGB_PACK(r,g,b) (htobe16(((r)<<11)|((g)<<5)|(b))) |
38 | 38 | ||
39 | /*** globals ***/ | 39 | /*** globals ***/ |
40 | fb_data lcd_framebuffer[LCD_HEIGHT][LCD_WIDTH] __attribute__ ((aligned (4))); | 40 | fb_data lcd_framebuffer[LCD_HEIGHT][LCD_WIDTH] __attribute__ ((aligned (4))); |
@@ -73,7 +73,7 @@ int lcd_default_contrast(void) | |||
73 | void lcd_init(void) | 73 | void lcd_init(void) |
74 | { | 74 | { |
75 | fg_pattern = 0x0000; /* Black */ | 75 | fg_pattern = 0x0000; /* Black */ |
76 | bg_pattern = RGB_PACK(0xb6, 0xc6, 0xe5); /* "Rockbox blue" */ | 76 | bg_pattern = RGB_PACK(0x17, 0x31, 0x1d); /* "Rockbox blue" */ |
77 | 77 | ||
78 | lcd_clear_display(); | 78 | lcd_clear_display(); |
79 | /* Call device specific init */ | 79 | /* Call device specific init */ |
@@ -96,23 +96,22 @@ int lcd_get_drawmode(void) | |||
96 | 96 | ||
97 | void lcd_set_foreground(struct rgb color) | 97 | void lcd_set_foreground(struct rgb color) |
98 | { | 98 | { |
99 | fg_pattern=RGB_PACK(color.red,color.green,color.blue); | 99 | fg_pattern = RGB_PACK(color.red, color.green, color.blue); |
100 | } | 100 | } |
101 | 101 | ||
102 | struct rgb lcd_get_foreground(void) | 102 | struct rgb lcd_get_foreground(void) |
103 | { | 103 | { |
104 | struct rgb colour; | 104 | struct rgb colour; |
105 | 105 | ||
106 | colour.red=((fg_pattern&0xf800)>>11)<<3; | 106 | colour.red = (fg_pattern >> 11) & 0x1f; |
107 | colour.green=((fg_pattern&0x03e0)>>5)<<2; | 107 | colour.green = (fg_pattern >> 5) & 0x3f; |
108 | colour.blue=(fg_pattern&0x1f)<<3; | 108 | colour.blue = fg_pattern & 0x1f; |
109 | |||
110 | return colour; | 109 | return colour; |
111 | } | 110 | } |
112 | 111 | ||
113 | void lcd_set_background(struct rgb color) | 112 | void lcd_set_background(struct rgb color) |
114 | { | 113 | { |
115 | bg_pattern=RGB_PACK(color.red,color.green,color.blue); | 114 | bg_pattern = RGB_PACK(color.red, color.green, color. blue); |
116 | } | 115 | } |
117 | 116 | ||
118 | 117 | ||
@@ -120,9 +119,9 @@ struct rgb lcd_get_background(void) | |||
120 | { | 119 | { |
121 | struct rgb colour; | 120 | struct rgb colour; |
122 | 121 | ||
123 | colour.red=((bg_pattern&0xf800)>>11)<<3; | 122 | colour.red = (bg_pattern >> 11) & 0x1f; |
124 | colour.green=((bg_pattern&0x03e0)>>5)<<2; | 123 | colour.green = (bg_pattern >> 5) & 0x3f; |
125 | colour.blue=(bg_pattern&0x1f)<<3; | 124 | colour.blue = bg_pattern & 0x1f; |
126 | return colour; | 125 | return colour; |
127 | } | 126 | } |
128 | 127 | ||
@@ -174,14 +173,11 @@ static void clearpixel(int x, int y) | |||
174 | 173 | ||
175 | static void flippixel(int x, int y) | 174 | static void flippixel(int x, int y) |
176 | { | 175 | { |
177 | /* What should this do on a color display? */ | 176 | lcd_framebuffer[y][x] = ~lcd_framebuffer[y][x]; |
178 | (void)x; | ||
179 | (void)y; | ||
180 | } | 177 | } |
181 | 178 | ||
182 | static void nopixel(int x, int y) | 179 | static void nopixel(int x, int y) |
183 | { | 180 | { |
184 | /* What should this do on a color display? */ | ||
185 | (void)x; | 181 | (void)x; |
186 | (void)y; | 182 | (void)y; |
187 | } | 183 | } |
@@ -196,13 +192,13 @@ lcd_pixelfunc_type* const lcd_pixelfuncs[8] = { | |||
196 | /* Clear the whole display */ | 192 | /* Clear the whole display */ |
197 | void lcd_clear_display(void) | 193 | void lcd_clear_display(void) |
198 | { | 194 | { |
199 | int i; | 195 | fb_data bits = (drawmode & DRMODE_INVERSEVID) ? fg_pattern : bg_pattern; |
200 | unsigned short bits = (drawmode & DRMODE_INVERSEVID) ? fg_pattern : bg_pattern; | 196 | fb_data *dst = &lcd_framebuffer[0][0]; |
201 | unsigned short* addr = (unsigned short *)lcd_framebuffer; | 197 | fb_data *dst_end = dst + LCD_HEIGHT*LCD_WIDTH; |
202 | 198 | ||
203 | for (i=0;i<LCD_HEIGHT*LCD_WIDTH;i++) { | 199 | do |
204 | *(addr++)=bits; | 200 | *dst++ = bits; |
205 | } | 201 | while (dst < dst_end); |
206 | scrolling_lines = 0; | 202 | scrolling_lines = 0; |
207 | } | 203 | } |
208 | 204 | ||
@@ -361,7 +357,7 @@ void lcd_drawrect(int x, int y, int width, int height) | |||
361 | /* Fill a rectangular area */ | 357 | /* Fill a rectangular area */ |
362 | void lcd_fillrect(int x, int y, int width, int height) | 358 | void lcd_fillrect(int x, int y, int width, int height) |
363 | { | 359 | { |
364 | int nx, ny; | 360 | int xe, ye, xc; |
365 | lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[drawmode]; | 361 | lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[drawmode]; |
366 | 362 | ||
367 | /* nothing to draw? */ | 363 | /* nothing to draw? */ |
@@ -385,13 +381,12 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
385 | if (y + height > LCD_HEIGHT) | 381 | if (y + height > LCD_HEIGHT) |
386 | height = LCD_HEIGHT - y; | 382 | height = LCD_HEIGHT - y; |
387 | 383 | ||
388 | ny = y + height; | 384 | ye = y + height; |
389 | for(;y < ny;y++) | 385 | xe = x + width; |
386 | for(; y < ye; y++) | ||
390 | { | 387 | { |
391 | int xc; | 388 | for(xc = x; xc < xe; xc++) |
392 | nx = x + width; | 389 | pfunc(xc, y); |
393 | for(xc = x;xc < nx;xc++) | ||
394 | pfunc(x, y); | ||
395 | } | 390 | } |
396 | } | 391 | } |
397 | 392 | ||
@@ -404,9 +399,8 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
404 | * byte 1 2nd from left etc. The first row of bytes defines pixel rows | 399 | * byte 1 2nd from left etc. The first row of bytes defines pixel rows |
405 | * 0..7, the second row defines pixel row 8..15 etc. | 400 | * 0..7, the second row defines pixel row 8..15 etc. |
406 | * | 401 | * |
407 | * This is similar to the internal lcd hw format. */ | 402 | * This is the mono bitmap format used on all other targets so far; the |
408 | 403 | * pixel packing doesn't really matter on a 8bit+ target. */ | |
409 | static unsigned char masks[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; | ||
410 | 404 | ||
411 | /* Draw a partial monochrome bitmap */ | 405 | /* Draw a partial monochrome bitmap */ |
412 | void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, | 406 | 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, | |||
415 | void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, | 409 | void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, |
416 | int stride, int x, int y, int width, int height) | 410 | int stride, int x, int y, int width, int height) |
417 | { | 411 | { |
418 | int in_x,in_y; | 412 | int xe, ye, yc; |
419 | int out_x; | 413 | lcd_pixelfunc_type *fgfunc; |
420 | int out_y; | 414 | lcd_pixelfunc_type *bgfunc; |
421 | unsigned char pixel; | ||
422 | fb_data * addr; | ||
423 | 415 | ||
424 | (void)stride; | ||
425 | /* nothing to draw? */ | 416 | /* nothing to draw? */ |
426 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | 417 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) |
427 | || (x + width <= 0) || (y + height <= 0)) | 418 | || (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, | |||
445 | if (y + height > LCD_HEIGHT) | 436 | if (y + height > LCD_HEIGHT) |
446 | height = LCD_HEIGHT - y; | 437 | height = LCD_HEIGHT - y; |
447 | 438 | ||
448 | // src += stride * (src_y >> 3) + src_x; /* move starting point */ | 439 | src += stride * (src_y >> 3) + src_x; /* move starting point */ |
449 | 440 | src_y &= 7; | |
450 | /* Copying from src_x,src_y to (x,y). Size is width,height */ | 441 | |
451 | in_x=src_x; | 442 | xe = x + width; |
452 | for (out_x=x;out_x<(x+width);out_x++) { | 443 | ye = y + height; |
453 | in_y=src_y; | 444 | fgfunc = lcd_pixelfuncs[drawmode]; |
454 | for (out_y=y;out_y<(y+height);out_y++) { | 445 | bgfunc = lcd_pixelfuncs[drawmode ^ DRMODE_INVERSEVID]; |
455 | pixel=(*src)&masks[in_y]; | 446 | |
456 | addr=&lcd_framebuffer[out_y][out_x]; | 447 | for (; x < xe; x++) |
457 | if (pixel > 0) { | 448 | { |
458 | *addr=fg_pattern; | 449 | const unsigned char *src_col = src++; |
459 | } else { | 450 | unsigned char data = *src_col >> src_y; |
460 | *addr=bg_pattern; | 451 | int numbits = 8 - src_y; |
461 | } | 452 | |
462 | in_y++; | 453 | for (yc = y; yc < ye; yc++) |
463 | } | 454 | { |
464 | in_x++; | 455 | if (data & 0x01) |
465 | src++; | 456 | fgfunc(x, yc); |
457 | else | ||
458 | bgfunc(x, yc); | ||
459 | |||
460 | data >>= 1; | ||
461 | if (--numbits == 0) | ||
462 | { | ||
463 | src_col += stride; | ||
464 | data = *src_col; | ||
465 | numbits = 8; | ||
466 | } | ||
467 | } | ||
466 | } | 468 | } |
467 | } | 469 | } |
468 | 470 | ||
@@ -479,33 +481,52 @@ void lcd_bitmap_part(const fb_data *src, int src_x, int src_y, | |||
479 | void lcd_bitmap_part(const fb_data *src, int src_x, int src_y, | 481 | void lcd_bitmap_part(const fb_data *src, int src_x, int src_y, |
480 | int stride, int x, int y, int width, int height) | 482 | int stride, int x, int y, int width, int height) |
481 | { | 483 | { |
482 | (void)src; | 484 | int ye; |
483 | (void)src_x; | 485 | |
484 | (void)src_y; | 486 | /* nothing to draw? */ |
485 | (void)stride; | 487 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) |
486 | (void)x; | 488 | || (x + width <= 0) || (y + height <= 0)) |
487 | (void)y; | 489 | return; |
488 | (void)width; | 490 | |
489 | (void)height; | 491 | /* clipping */ |
492 | if (x < 0) | ||
493 | { | ||
494 | width += x; | ||
495 | src_x -= x; | ||
496 | x = 0; | ||
497 | } | ||
498 | if (y < 0) | ||
499 | { | ||
500 | height += y; | ||
501 | src_y -= y; | ||
502 | y = 0; | ||
503 | } | ||
504 | if (x + width > LCD_WIDTH) | ||
505 | width = LCD_WIDTH - x; | ||
506 | if (y + height > LCD_HEIGHT) | ||
507 | height = LCD_HEIGHT - y; | ||
508 | |||
509 | src += stride * src_y + src_x; /* move starting point */ | ||
510 | ye = y + height; | ||
511 | |||
512 | for (; y < ye; y++) | ||
513 | { | ||
514 | const fb_data *src_row = src; | ||
515 | fb_data *dst = &lcd_framebuffer[y][x]; | ||
516 | fb_data *dst_end = dst + width; | ||
517 | |||
518 | do | ||
519 | *dst++ = *src_row++; | ||
520 | while (dst < dst_end); | ||
521 | |||
522 | src += stride; | ||
523 | } | ||
490 | } | 524 | } |
491 | 525 | ||
492 | /* Draw a full native bitmap */ | 526 | /* Draw a full native bitmap */ |
493 | void lcd_bitmap(const fb_data *src, int x, int y, int width, int height) | 527 | void lcd_bitmap(const fb_data *src, int x, int y, int width, int height) |
494 | { | 528 | { |
495 | fb_data* s=(fb_data *)src; | 529 | lcd_bitmap_part(src, 0, 0, width, x, y, width, height); |
496 | fb_data* d=&lcd_framebuffer[y][x]; | ||
497 | int k=LCD_WIDTH-width; | ||
498 | int i,j; | ||
499 | |||
500 | for (i=0;i<height;i++) { | ||
501 | for (j=0;j<width;j++) { | ||
502 | *(d++)=*(s++); | ||
503 | } | ||
504 | d+=k; | ||
505 | } | ||
506 | |||
507 | //OLD Implementation: lcd_bitmap_part(src, 0, 0, width, x, y, width, height); | ||
508 | |||
509 | } | 530 | } |
510 | 531 | ||
511 | /* put a string at a given pixel position, skipping first ofs pixel columns */ | 532 | /* put a string at a given pixel position, skipping first ofs pixel columns */ |
@@ -571,15 +592,12 @@ void lcd_puts_style(int x, int y, const unsigned char *str, int style) | |||
571 | lcd_putsxy(xpos, ypos, str); | 592 | lcd_putsxy(xpos, ypos, str); |
572 | drawmode = (DRMODE_SOLID|DRMODE_INVERSEVID); | 593 | drawmode = (DRMODE_SOLID|DRMODE_INVERSEVID); |
573 | (void)style; | 594 | (void)style; |
574 | #if 0 | ||
575 | /* TODO: Implement lcd_fillrect */ | ||
576 | lcd_fillrect(xpos + w, ypos, LCD_WIDTH - (xpos + w), h); | 595 | lcd_fillrect(xpos + w, ypos, LCD_WIDTH - (xpos + w), h); |
577 | if (style & STYLE_INVERT) | 596 | if (style & STYLE_INVERT) |
578 | { | 597 | { |
579 | drawmode = DRMODE_COMPLEMENT; | 598 | drawmode = DRMODE_COMPLEMENT; |
580 | lcd_fillrect(xpos, ypos, LCD_WIDTH - xpos, h); | 599 | lcd_fillrect(xpos, ypos, LCD_WIDTH - xpos, h); |
581 | } | 600 | } |
582 | #endif | ||
583 | drawmode = lastmode; | 601 | drawmode = lastmode; |
584 | } | 602 | } |
585 | 603 | ||