diff options
author | Jens Arnold <amiconn@rockbox.org> | 2005-06-29 01:39:50 +0000 |
---|---|---|
committer | Jens Arnold <amiconn@rockbox.org> | 2005-06-29 01:39:50 +0000 |
commit | 576908d36a58d51ee880791418a32cef25b49aba (patch) | |
tree | da2e34886085ca15de28d1b7226064be2906232b /firmware/drivers/lcd-h100-remote.c | |
parent | 7e11acbce9b9a63c28ded055d02301175391e027 (diff) | |
download | rockbox-576908d36a58d51ee880791418a32cef25b49aba.tar.gz rockbox-576908d36a58d51ee880791418a32cef25b49aba.zip |
Third part of graphics api rework. Some small but effective optimisations. Ported remote lcd driver to new api. Preparations for including the low-level functions in the plugin api.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6907 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers/lcd-h100-remote.c')
-rw-r--r-- | firmware/drivers/lcd-h100-remote.c | 632 |
1 files changed, 368 insertions, 264 deletions
diff --git a/firmware/drivers/lcd-h100-remote.c b/firmware/drivers/lcd-h100-remote.c index 90bb12e7c3..fe1c82dd3d 100644 --- a/firmware/drivers/lcd-h100-remote.c +++ b/firmware/drivers/lcd-h100-remote.c | |||
@@ -72,9 +72,10 @@ unsigned char lcd_remote_framebuffer[LCD_REMOTE_HEIGHT/8][LCD_REMOTE_WIDTH] | |||
72 | #endif | 72 | #endif |
73 | ; | 73 | ; |
74 | 74 | ||
75 | static int curfont = FONT_SYSFIXED; | 75 | static int drawmode = DRMODE_SOLID; |
76 | static int xmargin = 0; | 76 | static int xmargin = 0; |
77 | static int ymargin = 0; | 77 | static int ymargin = 0; |
78 | static int curfont = FONT_SYSFIXED; | ||
78 | #ifndef SIMULATOR | 79 | #ifndef SIMULATOR |
79 | static int xoffset; /* needed for flip */ | 80 | static int xoffset; /* needed for flip */ |
80 | 81 | ||
@@ -90,12 +91,6 @@ static int cached_contrast = 32; | |||
90 | static int cached_roll = 0; | 91 | static int cached_roll = 0; |
91 | #endif | 92 | #endif |
92 | 93 | ||
93 | /* All zeros and ones bitmaps for area filling */ | ||
94 | static const unsigned char zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
95 | static const unsigned char ones[8] = { | ||
96 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff | ||
97 | }; | ||
98 | |||
99 | /* scrolling */ | 94 | /* scrolling */ |
100 | static volatile int scrolling_lines=0; /* Bitpattern of which lines are scrolling */ | 95 | static volatile int scrolling_lines=0; /* Bitpattern of which lines are scrolling */ |
101 | #ifndef SIMULATOR | 96 | #ifndef SIMULATOR |
@@ -397,10 +392,10 @@ void lcd_remote_update(void) | |||
397 | return; | 392 | return; |
398 | 393 | ||
399 | /* Copy display bitmap to hardware */ | 394 | /* Copy display bitmap to hardware */ |
400 | for (y = 0; y < LCD_REMOTE_HEIGHT / 8; y++) | 395 | for (y = 0; y < LCD_REMOTE_HEIGHT/8; y++) |
401 | { | 396 | { |
402 | lcd_remote_write_command(LCD_REMOTE_CNTL_SET_PAGE_ADDRESS | y); | 397 | lcd_remote_write_command(LCD_REMOTE_CNTL_SET_PAGE_ADDRESS | y); |
403 | lcd_remote_write_command(LCD_REMOTE_CNTL_HIGHCOL | ((xoffset>>4) & 0xf)); | 398 | lcd_remote_write_command(LCD_REMOTE_CNTL_HIGHCOL | ((xoffset >> 4) & 0xf)); |
404 | lcd_remote_write_command(LCD_REMOTE_CNTL_LOWCOL | (xoffset & 0xf)); | 399 | lcd_remote_write_command(LCD_REMOTE_CNTL_LOWCOL | (xoffset & 0xf)); |
405 | lcd_remote_write_data(lcd_remote_framebuffer[y], LCD_REMOTE_WIDTH); | 400 | lcd_remote_write_data(lcd_remote_framebuffer[y], LCD_REMOTE_WIDTH); |
406 | } | 401 | } |
@@ -408,39 +403,49 @@ void lcd_remote_update(void) | |||
408 | 403 | ||
409 | /* Update a fraction of the display. */ | 404 | /* Update a fraction of the display. */ |
410 | void lcd_remote_update_rect(int, int, int, int) __attribute__ ((section (".icode"))); | 405 | void lcd_remote_update_rect(int, int, int, int) __attribute__ ((section (".icode"))); |
411 | void lcd_remote_update_rect(int x_start, int y, int width, int height) | 406 | void lcd_remote_update_rect(int x, int y, int width, int height) |
412 | { | 407 | { |
413 | int ymax; | 408 | int ymax; |
414 | 409 | ||
415 | if (!remote_initialized) | 410 | if (!remote_initialized) |
416 | return; | 411 | return; |
417 | 412 | ||
418 | /* The Y coordinates have to work on even 8 pixel rows */ | 413 | /* The Y coordinates have to work on even 8 pixel rows */ |
419 | ymax = (y + height-1)/8; | 414 | ymax = (y + height-1) >> 3; |
420 | y /= 8; | 415 | y >>= 3; |
421 | 416 | ||
422 | if(x_start + width > LCD_REMOTE_WIDTH) | 417 | if(x + width > LCD_REMOTE_WIDTH) |
423 | width = LCD_REMOTE_WIDTH - x_start; | 418 | width = LCD_REMOTE_WIDTH - x; |
424 | if (width <= 0) | 419 | if (width <= 0) |
425 | return; /* nothing left to do, 0 is harmful to lcd_write_data() */ | 420 | return; /* nothing left to do, 0 is harmful to lcd_write_data() */ |
426 | if(ymax >= LCD_REMOTE_HEIGHT/8) | 421 | if(ymax >= LCD_REMOTE_HEIGHT/8) |
427 | ymax = LCD_REMOTE_HEIGHT/8-1; | 422 | ymax = LCD_REMOTE_HEIGHT/8-1; |
423 | |||
424 | x += xoffset; | ||
428 | 425 | ||
429 | /* Copy specified rectange bitmap to hardware */ | 426 | /* Copy specified rectange bitmap to hardware */ |
430 | for (; y <= ymax; y++) | 427 | for (; y <= ymax; y++) |
431 | { | 428 | { |
432 | lcd_remote_write_command(LCD_REMOTE_CNTL_SET_PAGE_ADDRESS | y); | 429 | lcd_remote_write_command(LCD_REMOTE_CNTL_SET_PAGE_ADDRESS | y); |
433 | lcd_remote_write_command(LCD_REMOTE_CNTL_HIGHCOL | 430 | lcd_remote_write_command(LCD_REMOTE_CNTL_HIGHCOL | ((x >> 4) & 0xf)); |
434 | | (((x_start+xoffset)>>4) & 0xf)); | 431 | lcd_remote_write_command(LCD_REMOTE_CNTL_LOWCOL | (x & 0xf)); |
435 | lcd_remote_write_command(LCD_REMOTE_CNTL_LOWCOL | 432 | lcd_remote_write_data(&lcd_remote_framebuffer[y][x], width); |
436 | | ((x_start+xoffset) & 0xf)); | ||
437 | lcd_remote_write_data(&lcd_remote_framebuffer[y][x_start], width); | ||
438 | } | 433 | } |
439 | } | 434 | } |
440 | #endif /* !SIMULATOR */ | 435 | #endif /* !SIMULATOR */ |
441 | 436 | ||
442 | /*** parameter handling ***/ | 437 | /*** parameter handling ***/ |
443 | 438 | ||
439 | void lcd_remote_set_drawmode(int mode) | ||
440 | { | ||
441 | drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); | ||
442 | } | ||
443 | |||
444 | int lcd_remote_get_drawmode(void) | ||
445 | { | ||
446 | return drawmode; | ||
447 | } | ||
448 | |||
444 | void lcd_remote_setmargins(int x, int y) | 449 | void lcd_remote_setmargins(int x, int y) |
445 | { | 450 | { |
446 | xmargin = x; | 451 | xmargin = x; |
@@ -468,102 +473,99 @@ int lcd_remote_getstringsize(const unsigned char *str, int *w, int *h) | |||
468 | return font_getstringsize(str, w, h, curfont); | 473 | return font_getstringsize(str, w, h, curfont); |
469 | } | 474 | } |
470 | 475 | ||
471 | /*** drawing functions ***/ | 476 | /*** low-level drawing functions ***/ |
472 | 477 | ||
473 | void lcd_remote_clear_display(void) | 478 | static void setpixel(int x, int y) |
474 | { | 479 | { |
475 | memset(lcd_remote_framebuffer, 0, sizeof lcd_remote_framebuffer); | 480 | REMOTE_DRAW_PIXEL(x, y); |
476 | } | 481 | } |
477 | 482 | ||
478 | /* Set a single pixel */ | 483 | static void clearpixel(int x, int y) |
479 | void lcd_remote_drawpixel(int x, int y) | ||
480 | { | 484 | { |
481 | REMOTE_DRAW_PIXEL(x,y); | 485 | REMOTE_CLEAR_PIXEL(x, y); |
482 | } | 486 | } |
483 | 487 | ||
484 | /* Clear a single pixel */ | 488 | static void flippixel(int x, int y) |
485 | void lcd_remote_clearpixel(int x, int y) | ||
486 | { | 489 | { |
487 | REMOTE_CLEAR_PIXEL(x,y); | 490 | REMOTE_INVERT_PIXEL(x, y); |
488 | } | 491 | } |
489 | 492 | ||
490 | /* Invert a single pixel */ | 493 | static void nopixel(int x, int y) |
491 | void lcd_remote_invertpixel(int x, int y) | ||
492 | { | 494 | { |
493 | REMOTE_INVERT_PIXEL(x,y); | 495 | (void)x; |
496 | (void)y; | ||
494 | } | 497 | } |
495 | 498 | ||
496 | void lcd_remote_drawline(int x1, int y1, int x2, int y2) | 499 | lcd_pixelfunc_type* lcd_remote_pixelfuncs[8] = { |
500 | flippixel, nopixel, setpixel, setpixel, | ||
501 | nopixel, clearpixel, nopixel, clearpixel | ||
502 | }; | ||
503 | |||
504 | static void flipblock(unsigned char *address, unsigned mask, unsigned bits) | ||
497 | { | 505 | { |
498 | int numpixels; | 506 | *address ^= (bits & mask); |
499 | int i; | 507 | } |
500 | int deltax, deltay; | ||
501 | int d, dinc1, dinc2; | ||
502 | int x, xinc1, xinc2; | ||
503 | int y, yinc1, yinc2; | ||
504 | 508 | ||
505 | deltax = abs(x2 - x1); | 509 | static void bgblock(unsigned char *address, unsigned mask, unsigned bits) |
506 | deltay = abs(y2 - y1); | 510 | { |
511 | *address &= (bits | ~mask); | ||
512 | } | ||
507 | 513 | ||
508 | if(deltax >= deltay) | 514 | static void fgblock(unsigned char *address, unsigned mask, unsigned bits) |
509 | { | 515 | { |
510 | numpixels = deltax; | 516 | *address |= (bits & mask); |
511 | d = 2 * deltay - deltax; | 517 | } |
512 | dinc1 = deltay * 2; | ||
513 | dinc2 = (deltay - deltax) * 2; | ||
514 | xinc1 = 1; | ||
515 | xinc2 = 1; | ||
516 | yinc1 = 0; | ||
517 | yinc2 = 1; | ||
518 | } | ||
519 | else | ||
520 | { | ||
521 | numpixels = deltay; | ||
522 | d = 2 * deltax - deltay; | ||
523 | dinc1 = deltax * 2; | ||
524 | dinc2 = (deltax - deltay) * 2; | ||
525 | xinc1 = 0; | ||
526 | xinc2 = 1; | ||
527 | yinc1 = 1; | ||
528 | yinc2 = 1; | ||
529 | } | ||
530 | numpixels++; /* include endpoints */ | ||
531 | 518 | ||
532 | if(x1 > x2) | 519 | static void solidblock(unsigned char *address, unsigned mask, unsigned bits) |
533 | { | 520 | { |
534 | xinc1 = -xinc1; | 521 | *address = (*address & ~mask) | (bits & mask); |
535 | xinc2 = -xinc2; | 522 | } |
536 | } | ||
537 | 523 | ||
538 | if(y1 > y2) | 524 | static void flipinvblock(unsigned char *address, unsigned mask, unsigned bits) |
539 | { | 525 | { |
540 | yinc1 = -yinc1; | 526 | *address ^= (~bits & mask); |
541 | yinc2 = -yinc2; | 527 | } |
542 | } | ||
543 | 528 | ||
544 | x = x1; | 529 | static void bginvblock(unsigned char *address, unsigned mask, unsigned bits) |
545 | y = y1; | 530 | { |
531 | *address &= ~(bits & mask); | ||
532 | } | ||
546 | 533 | ||
547 | for(i=0; i<numpixels; i++) | 534 | static void fginvblock(unsigned char *address, unsigned mask, unsigned bits) |
548 | { | 535 | { |
549 | REMOTE_DRAW_PIXEL(x,y); | 536 | *address |= (~bits & mask); |
537 | } | ||
550 | 538 | ||
551 | if(d < 0) | 539 | static void solidinvblock(unsigned char *address, unsigned mask, unsigned bits) |
552 | { | 540 | { |
553 | d += dinc1; | 541 | *address = (*address & ~mask) | (~bits & mask); |
554 | x += xinc1; | ||
555 | y += yinc1; | ||
556 | } | ||
557 | else | ||
558 | { | ||
559 | d += dinc2; | ||
560 | x += xinc2; | ||
561 | y += yinc2; | ||
562 | } | ||
563 | } | ||
564 | } | 542 | } |
565 | 543 | ||
566 | void lcd_remote_clearline(int x1, int y1, int x2, int y2) | 544 | lcd_blockfunc_type* lcd_remote_blockfuncs[8] = { |
545 | flipblock, bgblock, fgblock, solidblock, | ||
546 | flipinvblock, bginvblock, fginvblock, solidinvblock | ||
547 | }; | ||
548 | |||
549 | /*** drawing functions ***/ | ||
550 | |||
551 | /* Clear the whole display */ | ||
552 | void lcd_remote_clear_display(void) | ||
553 | { | ||
554 | unsigned bits = (drawmode & DRMODE_INVERSEVID) ? 0xFFu : 0; | ||
555 | |||
556 | memset(lcd_remote_framebuffer, bits, sizeof lcd_remote_framebuffer); | ||
557 | scrolling_lines = 0; | ||
558 | } | ||
559 | |||
560 | /* Set a single pixel */ | ||
561 | void lcd_remote_drawpixel(int x, int y) | ||
562 | { | ||
563 | if (((unsigned)x < LCD_REMOTE_WIDTH) || ((unsigned)y < LCD_REMOTE_HEIGHT)) | ||
564 | lcd_remote_pixelfuncs[drawmode](x, y); | ||
565 | } | ||
566 | |||
567 | /* Draw a line */ | ||
568 | void lcd_remote_drawline(int x1, int y1, int x2, int y2) | ||
567 | { | 569 | { |
568 | int numpixels; | 570 | int numpixels; |
569 | int i; | 571 | int i; |
@@ -571,20 +573,21 @@ void lcd_remote_clearline(int x1, int y1, int x2, int y2) | |||
571 | int d, dinc1, dinc2; | 573 | int d, dinc1, dinc2; |
572 | int x, xinc1, xinc2; | 574 | int x, xinc1, xinc2; |
573 | int y, yinc1, yinc2; | 575 | int y, yinc1, yinc2; |
576 | lcd_pixelfunc_type *pfunc = lcd_remote_pixelfuncs[drawmode]; | ||
574 | 577 | ||
575 | deltax = abs(x2 - x1); | 578 | deltax = abs(x2 - x1); |
576 | deltay = abs(y2 - y1); | 579 | deltay = abs(y2 - y1); |
580 | xinc2 = 1; | ||
581 | yinc2 = 1; | ||
577 | 582 | ||
578 | if(deltax >= deltay) | 583 | if (deltax >= deltay) |
579 | { | 584 | { |
580 | numpixels = deltax; | 585 | numpixels = deltax; |
581 | d = 2 * deltay - deltax; | 586 | d = 2 * deltay - deltax; |
582 | dinc1 = deltay * 2; | 587 | dinc1 = deltay * 2; |
583 | dinc2 = (deltay - deltax) * 2; | 588 | dinc2 = (deltay - deltax) * 2; |
584 | xinc1 = 1; | 589 | xinc1 = 1; |
585 | xinc2 = 1; | ||
586 | yinc1 = 0; | 590 | yinc1 = 0; |
587 | yinc2 = 1; | ||
588 | } | 591 | } |
589 | else | 592 | else |
590 | { | 593 | { |
@@ -593,19 +596,17 @@ void lcd_remote_clearline(int x1, int y1, int x2, int y2) | |||
593 | dinc1 = deltax * 2; | 596 | dinc1 = deltax * 2; |
594 | dinc2 = (deltax - deltay) * 2; | 597 | dinc2 = (deltax - deltay) * 2; |
595 | xinc1 = 0; | 598 | xinc1 = 0; |
596 | xinc2 = 1; | ||
597 | yinc1 = 1; | 599 | yinc1 = 1; |
598 | yinc2 = 1; | ||
599 | } | 600 | } |
600 | numpixels++; /* include endpoints */ | 601 | numpixels++; /* include endpoints */ |
601 | 602 | ||
602 | if(x1 > x2) | 603 | if (x1 > x2) |
603 | { | 604 | { |
604 | xinc1 = -xinc1; | 605 | xinc1 = -xinc1; |
605 | xinc2 = -xinc2; | 606 | xinc2 = -xinc2; |
606 | } | 607 | } |
607 | 608 | ||
608 | if(y1 > y2) | 609 | if (y1 > y2) |
609 | { | 610 | { |
610 | yinc1 = -yinc1; | 611 | yinc1 = -yinc1; |
611 | yinc2 = -yinc2; | 612 | yinc2 = -yinc2; |
@@ -614,11 +615,12 @@ void lcd_remote_clearline(int x1, int y1, int x2, int y2) | |||
614 | x = x1; | 615 | x = x1; |
615 | y = y1; | 616 | y = y1; |
616 | 617 | ||
617 | for(i=0; i<numpixels; i++) | 618 | for (i = 0; i < numpixels; i++) |
618 | { | 619 | { |
619 | REMOTE_CLEAR_PIXEL(x,y); | 620 | if (((unsigned)x < LCD_REMOTE_WIDTH) && ((unsigned)y < LCD_REMOTE_HEIGHT)) |
621 | pfunc(x, y); | ||
620 | 622 | ||
621 | if(d < 0) | 623 | if (d < 0) |
622 | { | 624 | { |
623 | d += dinc1; | 625 | d += dinc1; |
624 | x += xinc1; | 626 | x += xinc1; |
@@ -633,185 +635,292 @@ void lcd_remote_clearline(int x1, int y1, int x2, int y2) | |||
633 | } | 635 | } |
634 | } | 636 | } |
635 | 637 | ||
636 | void lcd_remote_drawrect(int x, int y, int nx, int ny) | 638 | /* Draw a horizontal line (optimised) */ |
639 | void lcd_remote_hline(int x1, int x2, int y) | ||
637 | { | 640 | { |
638 | int i; | 641 | int x; |
642 | unsigned char *dst; | ||
643 | unsigned mask; | ||
644 | lcd_blockfunc_type *bfunc; | ||
639 | 645 | ||
640 | if (x > LCD_REMOTE_WIDTH) | 646 | /* direction flip */ |
647 | if (x2 < x1) | ||
641 | { | 648 | { |
642 | return; | 649 | x = x1; |
650 | x1 = x2; | ||
651 | x2 = x; | ||
643 | } | 652 | } |
644 | 653 | ||
645 | if (y > LCD_REMOTE_HEIGHT) | 654 | /* nothing to draw? */ |
646 | { | 655 | if (((unsigned)y >= LCD_REMOTE_HEIGHT) || (x1 >= LCD_REMOTE_WIDTH) |
647 | return; | 656 | || (x2 < 0)) |
648 | } | 657 | return; |
649 | |||
650 | if (x + nx > LCD_REMOTE_WIDTH) | ||
651 | { | ||
652 | nx = LCD_REMOTE_WIDTH - x; | ||
653 | } | ||
654 | 658 | ||
655 | if (y + ny > LCD_REMOTE_HEIGHT) | 659 | /* clipping */ |
656 | { | 660 | if (x1 < 0) |
657 | ny = LCD_REMOTE_HEIGHT - y; | 661 | x1 = 0; |
658 | } | 662 | if (x2 >= LCD_REMOTE_WIDTH) |
663 | x2 = LCD_REMOTE_WIDTH-1; | ||
664 | |||
665 | bfunc = lcd_remote_blockfuncs[drawmode]; | ||
666 | dst = &lcd_remote_framebuffer[y>>3][x1]; | ||
667 | mask = 1 << (y & 7); | ||
659 | 668 | ||
660 | /* vertical lines */ | 669 | for (x = x1; x <= x2; x++) |
661 | for (i = 0; i < ny; i++) | 670 | bfunc(dst++, mask, 0xFFu); |
671 | } | ||
672 | |||
673 | /* Draw a vertical line (optimised) */ | ||
674 | void lcd_remote_vline(int x, int y1, int y2) | ||
675 | { | ||
676 | int ny; | ||
677 | unsigned char *dst; | ||
678 | unsigned mask, mask_bottom; | ||
679 | lcd_blockfunc_type *bfunc; | ||
680 | |||
681 | /* direction flip */ | ||
682 | if (y2 < y1) | ||
662 | { | 683 | { |
663 | REMOTE_DRAW_PIXEL(x, (y + i)); | 684 | ny = y1; |
664 | REMOTE_DRAW_PIXEL((x + nx - 1), (y + i)); | 685 | y1 = y2; |
686 | y2 = ny; | ||
665 | } | 687 | } |
666 | 688 | ||
667 | /* horizontal lines */ | 689 | /* nothing to draw? */ |
668 | for (i = 0; i < nx; i++) | 690 | if (((unsigned)x >= LCD_REMOTE_WIDTH) || (y1 >= LCD_REMOTE_HEIGHT) |
691 | || (y2 < 0)) | ||
692 | return; | ||
693 | |||
694 | /* clipping */ | ||
695 | if (y1 < 0) | ||
696 | y1 = 0; | ||
697 | if (y2 >= LCD_REMOTE_HEIGHT) | ||
698 | y2 = LCD_REMOTE_HEIGHT-1; | ||
699 | |||
700 | bfunc = lcd_remote_blockfuncs[drawmode]; | ||
701 | dst = &lcd_remote_framebuffer[y1>>3][x]; | ||
702 | ny = y2 - (y1 & ~7); | ||
703 | mask = 0xFFu << (y1 & 7); | ||
704 | mask_bottom = 0xFFu >> (7 - (ny & 7)); | ||
705 | |||
706 | for (; ny >= 8; ny -= 8) | ||
669 | { | 707 | { |
670 | REMOTE_DRAW_PIXEL((x + i),y); | 708 | bfunc(dst, mask, 0xFFu); |
671 | REMOTE_DRAW_PIXEL((x + i),(y + ny - 1)); | 709 | dst += LCD_REMOTE_WIDTH; |
710 | mask = 0xFFu; | ||
672 | } | 711 | } |
712 | mask_bottom &= mask; | ||
713 | bfunc(dst, mask_bottom, 0xFFu); | ||
673 | } | 714 | } |
674 | 715 | ||
675 | /* Clear a rectangular area at (x, y), size (nx, ny) */ | 716 | /* Draw a rectangular box */ |
676 | void lcd_remote_clearrect(int x, int y, int nx, int ny) | 717 | void lcd_remote_drawrect(int x, int y, int width, int height) |
677 | { | 718 | { |
678 | int i; | 719 | if ((width <= 0) || (height <= 0)) |
679 | for (i = 0; i < nx; i++) | 720 | return; |
680 | lcd_remote_bitmap(zeros, x+i, y, 1, ny, true); | ||
681 | } | ||
682 | 721 | ||
683 | /* Fill a rectangular area at (x, y), size (nx, ny) */ | 722 | int x2 = x + width - 1; |
684 | void lcd_remote_fillrect(int x, int y, int nx, int ny) | 723 | int y2 = y + height - 1; |
685 | { | 724 | |
686 | int i; | 725 | lcd_remote_vline(x, y, y2); |
687 | for (i = 0; i < nx; i++) | 726 | lcd_remote_vline(x2, y, y2); |
688 | lcd_remote_bitmap(ones, x+i, y, 1, ny, true); | 727 | lcd_remote_hline(x, x2, y); |
728 | lcd_remote_hline(x, x2, y2); | ||
689 | } | 729 | } |
690 | 730 | ||
691 | /* Invert a rectangular area at (x, y), size (nx, ny) */ | 731 | /* Fill a rectangular area */ |
692 | void lcd_remote_invertrect(int x, int y, int nx, int ny) | 732 | void lcd_remote_fillrect(int x, int y, int width, int height) |
693 | { | 733 | { |
694 | int i, j; | 734 | int ny, i; |
695 | 735 | unsigned char *dst; | |
696 | if (x > LCD_REMOTE_WIDTH) | 736 | unsigned mask, mask_bottom; |
697 | return; | 737 | unsigned bits = 0xFFu; |
698 | if (y > LCD_REMOTE_HEIGHT) | 738 | lcd_blockfunc_type *bfunc; |
739 | bool fillopt; | ||
740 | |||
741 | /* nothing to draw? */ | ||
742 | if ((width <= 0) || (height <= 0) || (x >= LCD_REMOTE_WIDTH) | ||
743 | || (y >= LCD_REMOTE_HEIGHT) || (x + width <= 0) || (y + height <= 0)) | ||
699 | return; | 744 | return; |
700 | 745 | ||
701 | if (x + nx > LCD_REMOTE_WIDTH) | 746 | /* clipping */ |
702 | nx = LCD_REMOTE_WIDTH - x; | 747 | if (x < 0) |
703 | if (y + ny > LCD_REMOTE_HEIGHT) | 748 | { |
704 | ny = LCD_REMOTE_HEIGHT - y; | 749 | width += x; |
750 | x = 0; | ||
751 | } | ||
752 | if (y < 0) | ||
753 | { | ||
754 | height += y; | ||
755 | y = 0; | ||
756 | } | ||
757 | if (x + width > LCD_REMOTE_WIDTH) | ||
758 | width = LCD_REMOTE_WIDTH - x; | ||
759 | if (y + height > LCD_REMOTE_HEIGHT) | ||
760 | height = LCD_REMOTE_HEIGHT - y; | ||
761 | |||
762 | fillopt = (drawmode & DRMODE_INVERSEVID) ? | ||
763 | (drawmode & DRMODE_BG) : (drawmode & DRMODE_FG); | ||
764 | if (fillopt &&(drawmode & DRMODE_INVERSEVID)) | ||
765 | bits = 0; | ||
766 | bfunc = lcd_remote_blockfuncs[drawmode]; | ||
767 | dst = &lcd_remote_framebuffer[y>>3][x]; | ||
768 | ny = height - 1 + (y & 7); | ||
769 | mask = 0xFFu << (y & 7); | ||
770 | mask_bottom = 0xFFu >> (7 - (ny & 7)); | ||
771 | |||
772 | for (; ny >= 8; ny -= 8) | ||
773 | { | ||
774 | if (fillopt && (mask == 0xFFu)) | ||
775 | memset(dst, bits, width); | ||
776 | else | ||
777 | { | ||
778 | unsigned char *dst_row = dst; | ||
705 | 779 | ||
706 | for (i = 0; i < nx; i++) | 780 | for (i = width; i > 0; i--) |
707 | for (j = 0; j < ny; j++) | 781 | bfunc(dst_row++, mask, 0xFFu); |
708 | REMOTE_INVERT_PIXEL((x + i), (y + j)); | 782 | } |
709 | } | ||
710 | 783 | ||
711 | void lcd_remote_bitmap(const unsigned char *src, int x, int y, int nx, int ny, | 784 | dst += LCD_REMOTE_WIDTH; |
712 | bool clear) __attribute__ ((section (".icode"))); | 785 | mask = 0xFFu; |
713 | void lcd_remote_bitmap(const unsigned char *src, int x, int y, int nx, int ny, | 786 | } |
714 | bool clear) | 787 | mask_bottom &= mask; |
715 | { | 788 | |
716 | const unsigned char *src_col; | 789 | if (fillopt && (mask_bottom == 0xFFu)) |
717 | unsigned char *dst, *dst_col; | 790 | memset(dst, bits, width); |
718 | unsigned int data, mask1, mask2, mask3, mask4; | 791 | else |
719 | int stride, shift; | ||
720 | |||
721 | if (((unsigned) x >= LCD_REMOTE_WIDTH) || ((unsigned) y >= LCD_REMOTE_HEIGHT)) | ||
722 | { | 792 | { |
723 | return; | 793 | for (i = width; i > 0; i--) |
794 | bfunc(dst++, mask_bottom, 0xFFu); | ||
724 | } | 795 | } |
725 | 796 | } | |
726 | stride = nx; /* otherwise right-clipping will destroy the image */ | ||
727 | 797 | ||
728 | if (((unsigned) (x + nx)) >= LCD_REMOTE_WIDTH) | 798 | /* About Rockbox' internal bitmap format: |
799 | * | ||
800 | * A bitmap contains one bit for every pixel that defines if that pixel is | ||
801 | * black (1) or white (0). Bits within a byte are arranged vertically, LSB | ||
802 | * at top. | ||
803 | * The bytes are stored in row-major order, with byte 0 being top left, | ||
804 | * byte 1 2nd from left etc. The first row of bytes defines pixel rows | ||
805 | * 0..7, the second row defines pixel row 8..15 etc. | ||
806 | * | ||
807 | * This is the same as the internal lcd hw format. */ | ||
808 | |||
809 | /* Draw a partial bitmap */ | ||
810 | void lcd_remote_bitmap_part(const unsigned char *src, int src_x, int src_y, | ||
811 | int stride, int x, int y, int width, int height) | ||
812 | __attribute__ ((section(".icode"))); | ||
813 | void lcd_remote_bitmap_part(const unsigned char *src, int src_x, int src_y, | ||
814 | int stride, int x, int y, int width, int height) | ||
815 | { | ||
816 | int shift, ny, i; | ||
817 | unsigned char *dst; | ||
818 | unsigned mask, mask_bottom; | ||
819 | lcd_blockfunc_type *bfunc; | ||
820 | |||
821 | /* nothing to draw? */ | ||
822 | if ((width <= 0) || (height <= 0) || (x >= LCD_REMOTE_WIDTH) | ||
823 | || (y >= LCD_REMOTE_HEIGHT) || (x + width <= 0) || (y + height <= 0)) | ||
824 | return; | ||
825 | |||
826 | /* clipping */ | ||
827 | if (x < 0) | ||
729 | { | 828 | { |
730 | nx = LCD_REMOTE_WIDTH - x; | 829 | width += x; |
830 | src_x -= x; | ||
831 | x = 0; | ||
731 | } | 832 | } |
732 | 833 | if (y < 0) | |
733 | if (((unsigned) (y + ny)) >= LCD_REMOTE_HEIGHT) | ||
734 | { | 834 | { |
735 | ny = LCD_REMOTE_HEIGHT - y; | 835 | height += y; |
836 | src_y -= y; | ||
837 | y = 0; | ||
736 | } | 838 | } |
737 | 839 | if (x + width > LCD_REMOTE_WIDTH) | |
738 | dst = &lcd_remote_framebuffer[y >> 3][x]; | 840 | width = LCD_REMOTE_WIDTH - x; |
739 | shift = y & 7; | 841 | if (y + height > LCD_REMOTE_HEIGHT) |
842 | height = LCD_REMOTE_HEIGHT - y; | ||
843 | |||
844 | src += stride * (src_y >> 3) + src_x; /* move starting point */ | ||
845 | src_y &= 7; | ||
846 | y -= src_y; | ||
847 | dst = &lcd_remote_framebuffer[y>>3][x]; | ||
848 | shift = y & 7; | ||
849 | ny = height - 1 + shift + src_y; | ||
850 | |||
851 | bfunc = lcd_remote_blockfuncs[drawmode]; | ||
852 | mask = 0xFFu << (shift + src_y); | ||
853 | mask_bottom = 0xFFu >> (7 - (ny & 7)); | ||
740 | 854 | ||
741 | if (!shift && clear) /* shortcut for byte aligned match with clear */ | 855 | if (shift == 0) |
742 | { | 856 | { |
743 | while (ny >= 8) /* all full rows */ | 857 | bool copyopt = (drawmode == DRMODE_SOLID); |
858 | |||
859 | for (; ny >= 8; ny -= 8) | ||
744 | { | 860 | { |
745 | memcpy(dst, src, nx); | 861 | if (copyopt && (mask == 0xFFu)) |
862 | memcpy(dst, src, width); | ||
863 | else | ||
864 | { | ||
865 | const unsigned char *src_row = src; | ||
866 | unsigned char *dst_row = dst; | ||
867 | |||
868 | for (i = width; i > 0; i--) | ||
869 | bfunc(dst_row++, mask, *src_row++); | ||
870 | } | ||
871 | |||
746 | src += stride; | 872 | src += stride; |
747 | dst += LCD_REMOTE_WIDTH; | 873 | dst += LCD_REMOTE_WIDTH; |
748 | ny -= 8; | 874 | mask = 0xFFu; |
749 | } | ||
750 | if (ny == 0) /* nothing left to do? */ | ||
751 | { | ||
752 | return; | ||
753 | } | 875 | } |
754 | /* last partial row to do by default routine */ | 876 | mask_bottom &= mask; |
755 | } | ||
756 | |||
757 | ny += shift; | ||
758 | 877 | ||
759 | /* Calculate bit masks */ | 878 | if (copyopt && (mask_bottom == 0xFFu)) |
760 | mask4 = ~(0xfe << ((ny-1) & 7)); /* data mask for last partial row */ | 879 | memcpy(dst, src, width); |
761 | 880 | else | |
762 | if (clear) | ||
763 | { | ||
764 | mask1 = ~(0xff << shift); /* clearing of first partial row */ | ||
765 | mask2 = 0; /* clearing of intermediate (full) rows */ | ||
766 | mask3 = ~mask4; /* clearing of last partial row */ | ||
767 | if (ny <= 8) | ||
768 | { | 881 | { |
769 | mask3 |= mask1; | 882 | for (i = width; i > 0; i--) |
883 | bfunc(dst++, mask_bottom, *src++); | ||
770 | } | 884 | } |
771 | } | 885 | } |
772 | else | 886 | else |
773 | { | 887 | { |
774 | mask1 = mask2 = mask3 = 0xff; | 888 | for (x = 0; x < width; x++) |
775 | } | ||
776 | |||
777 | /* Loop for each column */ | ||
778 | for (x = 0; x < nx; x++) | ||
779 | { | ||
780 | src_col = src++; | ||
781 | dst_col = dst++; | ||
782 | data = 0; | ||
783 | y = 0; | ||
784 | |||
785 | if (ny > 8) | ||
786 | { | 889 | { |
787 | /* First partial row */ | 890 | const unsigned char *src_col = src++; |
788 | data = *src_col << shift; | 891 | unsigned char *dst_col = dst++; |
789 | *dst_col = (*dst_col & mask1) | data; | 892 | unsigned mask_col = mask; |
790 | src_col += stride; | 893 | unsigned data = 0; |
791 | dst_col += LCD_REMOTE_WIDTH; | 894 | |
792 | data >>= 8; | 895 | for (y = ny; y >= 8; y -= 8) |
793 | |||
794 | /* Intermediate rows */ | ||
795 | for (y = 8; y < ny-8; y += 8) | ||
796 | { | 896 | { |
797 | data |= *src_col << shift; | 897 | data |= *src_col << shift; |
798 | *dst_col = (*dst_col & mask2) | data; | 898 | |
899 | if (mask_col & 0xFFu) | ||
900 | { | ||
901 | bfunc(dst_col, mask_col, data); | ||
902 | mask_col = 0xFFu; | ||
903 | } | ||
904 | else | ||
905 | mask_col >>= 8; | ||
906 | |||
799 | src_col += stride; | 907 | src_col += stride; |
800 | dst_col += LCD_REMOTE_WIDTH; | 908 | dst_col += LCD_REMOTE_WIDTH; |
801 | data >>= 8; | 909 | data >>= 8; |
802 | } | 910 | } |
803 | } | ||
804 | |||
805 | /* Last partial row */ | ||
806 | if (y + shift < ny) | ||
807 | { | ||
808 | data |= *src_col << shift; | 911 | data |= *src_col << shift; |
912 | bfunc(dst_col, mask_col & mask_bottom, data); | ||
809 | } | 913 | } |
810 | |||
811 | *dst_col = (*dst_col & mask3) | (data & mask4); | ||
812 | } | 914 | } |
813 | } | 915 | } |
814 | 916 | ||
917 | /* Draw a full bitmap */ | ||
918 | void lcd_remote_bitmap(const unsigned char *src, int x, int y, int width, | ||
919 | int height) | ||
920 | { | ||
921 | lcd_remote_bitmap_part(src, 0, 0, width, x, y, width, height); | ||
922 | } | ||
923 | |||
815 | /* put a string at a given pixel position, skipping first ofs pixel columns */ | 924 | /* put a string at a given pixel position, skipping first ofs pixel columns */ |
816 | static void lcd_remote_putsxyofs(int x, int y, int ofs, const unsigned char *str) | 925 | static void lcd_remote_putsxyofs(int x, int y, int ofs, const unsigned char *str) |
817 | { | 926 | { |
@@ -820,7 +929,8 @@ static void lcd_remote_putsxyofs(int x, int y, int ofs, const unsigned char *str | |||
820 | 929 | ||
821 | while ((ch = *str++) != '\0' && x < LCD_REMOTE_WIDTH) | 930 | while ((ch = *str++) != '\0' && x < LCD_REMOTE_WIDTH) |
822 | { | 931 | { |
823 | int gwidth, width; | 932 | int width; |
933 | const unsigned char *bits; | ||
824 | 934 | ||
825 | /* check input range */ | 935 | /* check input range */ |
826 | if (ch < pf->firstchar || ch >= pf->firstchar+pf->size) | 936 | if (ch < pf->firstchar || ch >= pf->firstchar+pf->size) |
@@ -828,40 +938,21 @@ static void lcd_remote_putsxyofs(int x, int y, int ofs, const unsigned char *str | |||
828 | ch -= pf->firstchar; | 938 | ch -= pf->firstchar; |
829 | 939 | ||
830 | /* get proportional width and glyph bits */ | 940 | /* get proportional width and glyph bits */ |
831 | gwidth = pf->width ? pf->width[ch] : pf->maxwidth; | 941 | width = pf->width ? pf->width[ch] : pf->maxwidth; |
832 | width = MIN (gwidth, LCD_REMOTE_WIDTH - x); | ||
833 | 942 | ||
834 | if (ofs != 0) | 943 | if (ofs > width) |
835 | { | 944 | { |
836 | if (ofs > width) | 945 | ofs -= width; |
837 | { | 946 | continue; |
838 | ofs -= width; | ||
839 | continue; | ||
840 | } | ||
841 | width -= ofs; | ||
842 | } | 947 | } |
843 | 948 | ||
844 | if (width > 0) | 949 | bits = pf->bits + (pf->offset ? |
845 | { | 950 | pf->offset[ch] : ((pf->height + 7) / 8 * pf->maxwidth * ch)); |
846 | unsigned int i; | ||
847 | const unsigned char* bits = pf->bits + | ||
848 | (pf->offset ? pf->offset[ch] | ||
849 | : ((pf->height + 7) / 8 * pf->maxwidth * ch)); | ||
850 | 951 | ||
851 | if (ofs != 0) | 952 | lcd_remote_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, |
852 | { | 953 | pf->height); |
853 | for (i = 0; i < pf->height; i += 8) | 954 | |
854 | { | 955 | x += width - ofs; |
855 | lcd_remote_bitmap (bits + ofs, x, y + i, width, | ||
856 | MIN(8, pf->height - i), true); | ||
857 | bits += gwidth; | ||
858 | } | ||
859 | } | ||
860 | else | ||
861 | lcd_remote_bitmap ((unsigned char*) bits, x, y, gwidth, | ||
862 | pf->height, true); | ||
863 | x += width; | ||
864 | } | ||
865 | ofs = 0; | 956 | ofs = 0; |
866 | } | 957 | } |
867 | } | 958 | } |
@@ -883,9 +974,10 @@ void lcd_remote_puts(int x, int y, const unsigned char *str) | |||
883 | void lcd_remote_puts_style(int x, int y, const unsigned char *str, int style) | 974 | void lcd_remote_puts_style(int x, int y, const unsigned char *str, int style) |
884 | { | 975 | { |
885 | int xpos,ypos,w,h; | 976 | int xpos,ypos,w,h; |
977 | int lastmode = lcd_remote_get_drawmode(); | ||
886 | 978 | ||
887 | /* make sure scrolling is turned off on the line we are updating */ | 979 | /* make sure scrolling is turned off on the line we are updating */ |
888 | //scrolling_lines &= ~(1 << y); | 980 | scrolling_lines &= ~(1 << y); |
889 | 981 | ||
890 | if(!str || !str[0]) | 982 | if(!str || !str[0]) |
891 | return; | 983 | return; |
@@ -894,10 +986,14 @@ void lcd_remote_puts_style(int x, int y, const unsigned char *str, int style) | |||
894 | xpos = xmargin + x*w / strlen(str); | 986 | xpos = xmargin + x*w / strlen(str); |
895 | ypos = ymargin + y*h; | 987 | ypos = ymargin + y*h; |
896 | lcd_remote_putsxy(xpos, ypos, str); | 988 | lcd_remote_putsxy(xpos, ypos, str); |
897 | lcd_remote_clearrect(xpos + w, ypos, LCD_REMOTE_WIDTH - (xpos + w), h); | 989 | lcd_remote_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); |
990 | lcd_remote_fillrect(xpos + w, ypos, LCD_REMOTE_WIDTH - (xpos + w), h); | ||
898 | if (style & STYLE_INVERT) | 991 | if (style & STYLE_INVERT) |
899 | lcd_remote_invertrect(xpos, ypos, LCD_REMOTE_WIDTH - xpos, h); | 992 | { |
900 | 993 | lcd_remote_set_drawmode(DRMODE_COMPLEMENT); | |
994 | lcd_remote_fillrect(xpos, ypos, LCD_REMOTE_WIDTH - xpos, h); | ||
995 | } | ||
996 | lcd_remote_set_drawmode(lastmode); | ||
901 | } | 997 | } |
902 | 998 | ||
903 | /*** scrolling ***/ | 999 | /*** scrolling ***/ |
@@ -1008,6 +1104,7 @@ static void scroll_thread(void) | |||
1008 | struct scrollinfo* s; | 1104 | struct scrollinfo* s; |
1009 | int index; | 1105 | int index; |
1010 | int xpos, ypos; | 1106 | int xpos, ypos; |
1107 | int lastmode; | ||
1011 | 1108 | ||
1012 | /* initialize scroll struct array */ | 1109 | /* initialize scroll struct array */ |
1013 | scrolling_lines = 0; | 1110 | scrolling_lines = 0; |
@@ -1061,10 +1158,17 @@ static void scroll_thread(void) | |||
1061 | s->offset %= s->width; | 1158 | s->offset %= s->width; |
1062 | } | 1159 | } |
1063 | 1160 | ||
1064 | lcd_remote_clearrect(xpos, ypos, LCD_REMOTE_WIDTH - xpos, pf->height); | 1161 | lastmode = lcd_remote_get_drawmode(); |
1162 | lcd_remote_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); | ||
1163 | lcd_remote_fillrect(xpos, ypos, LCD_REMOTE_WIDTH - xpos, pf->height); | ||
1164 | lcd_remote_set_drawmode(DRMODE_SOLID); | ||
1065 | lcd_remote_putsxyofs(xpos, ypos, s->offset, s->line); | 1165 | lcd_remote_putsxyofs(xpos, ypos, s->offset, s->line); |
1066 | if (s->invert) | 1166 | if (s->invert) |
1067 | lcd_remote_invertrect(xpos, ypos, LCD_REMOTE_WIDTH - xpos, pf->height); | 1167 | { |
1168 | lcd_remote_set_drawmode(DRMODE_COMPLEMENT); | ||
1169 | lcd_remote_fillrect(xpos, ypos, LCD_REMOTE_WIDTH - xpos, pf->height); | ||
1170 | } | ||
1171 | lcd_remote_set_drawmode(lastmode); | ||
1068 | lcd_remote_update_rect(xpos, ypos, LCD_REMOTE_WIDTH - xpos, pf->height); | 1172 | lcd_remote_update_rect(xpos, ypos, LCD_REMOTE_WIDTH - xpos, pf->height); |
1069 | } | 1173 | } |
1070 | 1174 | ||