diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2011-01-11 01:21:31 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2011-01-11 01:21:31 +0000 |
commit | 0dd74ca7224d8cb141fd924727bd65be1bda9ec6 (patch) | |
tree | 2988b0745f88ede6d6c06a46e732f5d5f72a9021 /firmware/target/arm/philips/sa9200/lcd-sa9200.c | |
parent | 2e686eca633a329d99daf5a6a45b41ccb9dc5563 (diff) | |
download | rockbox-0dd74ca7224d8cb141fd924727bd65be1bda9ec6.tar.gz rockbox-0dd74ca7224d8cb141fd924727bd65be1bda9ec6.zip |
SA9200: Add YUV blitting, do full-screen updates more efficiently and properly clip partial updates. Plugin struct becomes incompatible for this target but leave version alone since it's still dev-only.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29028 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/philips/sa9200/lcd-sa9200.c')
-rw-r--r-- | firmware/target/arm/philips/sa9200/lcd-sa9200.c | 111 |
1 files changed, 96 insertions, 15 deletions
diff --git a/firmware/target/arm/philips/sa9200/lcd-sa9200.c b/firmware/target/arm/philips/sa9200/lcd-sa9200.c index 51a3cf0f71..47fbfa3843 100644 --- a/firmware/target/arm/philips/sa9200/lcd-sa9200.c +++ b/firmware/target/arm/philips/sa9200/lcd-sa9200.c | |||
@@ -97,9 +97,9 @@ static void lcd_send_data(unsigned data) | |||
97 | static void lcd_send_command(unsigned cmd) | 97 | static void lcd_send_command(unsigned cmd) |
98 | { | 98 | { |
99 | lcd_wait_write(); | 99 | lcd_wait_write(); |
100 | LCD1_CMD = cmd >> 8; | 100 | LCD1_CMD = 0; |
101 | lcd_wait_write(); | 101 | lcd_wait_write(); |
102 | LCD1_CMD = cmd & 0xff; | 102 | LCD1_CMD = cmd; |
103 | } | 103 | } |
104 | 104 | ||
105 | static void lcd_write_reg(unsigned reg, unsigned data) | 105 | static void lcd_write_reg(unsigned reg, unsigned data) |
@@ -401,25 +401,101 @@ void lcd_yuv_set_options(unsigned options) | |||
401 | } | 401 | } |
402 | 402 | ||
403 | /* Performance function to blit a YUV bitmap directly to the LCD */ | 403 | /* Performance function to blit a YUV bitmap directly to the LCD */ |
404 | void lcd_write_yuv420_lines(unsigned char const * const src[3], | ||
405 | int width, | ||
406 | int stride); | ||
407 | void lcd_write_yuv420_lines_odither(unsigned char const * const src[3], | ||
408 | int width, | ||
409 | int stride, | ||
410 | int x_screen, | ||
411 | int y_screen); | ||
404 | void lcd_blit_yuv(unsigned char * const src[3], | 412 | void lcd_blit_yuv(unsigned char * const src[3], |
405 | int src_x, int src_y, int stride, | 413 | int src_x, int src_y, int stride, |
406 | int x, int y, int width, int height) | 414 | int x, int y, int width, int height) |
407 | { | 415 | { |
408 | (void)src; | 416 | const unsigned char *yuv_src[3]; |
409 | (void)src_x; | 417 | const unsigned char *ysrc_max; |
410 | (void)src_y; | 418 | int options; |
411 | (void)stride; | 419 | |
412 | (void)x; | 420 | if (!display_on) |
413 | (void)y; | 421 | return; |
414 | (void)width; | 422 | |
415 | (void)height; | 423 | width &= ~1; |
424 | height &= ~1; | ||
425 | |||
426 | /* calculate the drawing region */ | ||
427 | lcd_write_reg(R_VERT_RAM_ADDR_POS, ((x + width - 1) << 8) | x); | ||
428 | |||
429 | /* convert YUV coordinates to screen coordinates */ | ||
430 | y = LCD_WIDTH - 1 - y; | ||
431 | |||
432 | /* 2px strip: cursor moves left, then down in gram */ | ||
433 | /* BGR=1, MDT1-0=00, I/D1-0=10, AM=0 */ | ||
434 | lcd_write_reg(R_ENTRY_MODE, 0x1020); | ||
435 | |||
436 | yuv_src[0] = src[0] + src_y * stride + src_x; | ||
437 | yuv_src[1] = src[1] + (src_y * stride >> 2) + (src_x >> 1); | ||
438 | yuv_src[2] = src[2] + (yuv_src[1] - src[1]); | ||
439 | ysrc_max = yuv_src[0] + height * stride; | ||
440 | |||
441 | /* cache options setting */ | ||
442 | options = lcd_yuv_options; | ||
443 | |||
444 | do | ||
445 | { | ||
446 | /* max horiz << 8 | start horiz */ | ||
447 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, (y << 8) | (y - 1)); | ||
448 | |||
449 | /* position cursor (set AD0-AD15) */ | ||
450 | lcd_write_reg(R_RAM_ADDR_SET, (x << 8) | y); | ||
451 | |||
452 | /* start drawing */ | ||
453 | lcd_send_command(R_WRITE_DATA_2_GRAM); | ||
454 | |||
455 | if (options & LCD_YUV_DITHER) | ||
456 | { | ||
457 | lcd_write_yuv420_lines_odither(yuv_src, width, stride, | ||
458 | y, x); | ||
459 | } | ||
460 | else | ||
461 | { | ||
462 | lcd_write_yuv420_lines(yuv_src, width, stride); | ||
463 | } | ||
464 | |||
465 | y -= 2; /* move strip by "down" 2 px */ | ||
466 | yuv_src[0] += stride << 1; | ||
467 | yuv_src[1] += stride >> 1; | ||
468 | yuv_src[2] += stride >> 1; | ||
469 | } | ||
470 | while (yuv_src[0] < ysrc_max); | ||
471 | |||
472 | /* back to normal right, then down cursor in gram */ | ||
473 | /* BGR=1, MDT1-0=00, I/D1-0=11, AM=0 */ | ||
474 | lcd_write_reg(R_ENTRY_MODE, 0x1030); | ||
416 | } | 475 | } |
417 | 476 | ||
418 | /* Update the display. | 477 | /* Update the display. |
419 | This must be called after all other LCD functions that change the display. */ | 478 | This must be called after all other LCD functions that change the display. */ |
420 | void lcd_update(void) | 479 | void lcd_update(void) |
421 | { | 480 | { |
422 | lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); | 481 | const fb_data *addr, *end; |
482 | |||
483 | if (!display_on) | ||
484 | return; | ||
485 | |||
486 | addr = &lcd_framebuffer[0][0]; | ||
487 | end = &lcd_framebuffer[LCD_HEIGHT - 1][LCD_WIDTH]; | ||
488 | |||
489 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, (LCD_WIDTH - 1) << 8); | ||
490 | lcd_write_reg(R_VERT_RAM_ADDR_POS, (LCD_HEIGHT - 1) << 8); | ||
491 | lcd_write_reg(R_RAM_ADDR_SET, 0); | ||
492 | lcd_send_command(R_WRITE_DATA_2_GRAM); | ||
493 | |||
494 | do | ||
495 | { | ||
496 | lcd_send_data(*addr++); | ||
497 | } | ||
498 | while (addr < end); | ||
423 | } | 499 | } |
424 | 500 | ||
425 | /* Update a fraction of the display. */ | 501 | /* Update a fraction of the display. */ |
@@ -432,18 +508,23 @@ void lcd_update_rect(int x, int y, int width, int height) | |||
432 | 508 | ||
433 | if (x + width > LCD_WIDTH) | 509 | if (x + width > LCD_WIDTH) |
434 | width = LCD_WIDTH - x; | 510 | width = LCD_WIDTH - x; |
511 | if (x < 0) | ||
512 | width += x, x = 0; | ||
513 | if (width <= 0) | ||
514 | return; /* Nothing left to do. */ | ||
435 | 515 | ||
436 | if (y + height > LCD_HEIGHT) | 516 | if (y + height > LCD_HEIGHT) |
437 | height = LCD_HEIGHT - y; | 517 | height = LCD_HEIGHT - y; |
438 | 518 | if (y < 0) | |
439 | if ((width <= 0) || (height <= 0)) | 519 | height += y, y = 0; |
520 | if (height <= 0) | ||
440 | return; /* Nothing left to do. */ | 521 | return; /* Nothing left to do. */ |
441 | 522 | ||
442 | addr = &lcd_framebuffer[y][x]; | 523 | addr = &lcd_framebuffer[y][x]; |
443 | 524 | ||
444 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, ((x + width - 1) << 8) | x); | 525 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, ((x + width - 1) << 8) | x); |
445 | lcd_write_reg(R_VERT_RAM_ADDR_POS, ((y + height -1) << 8) | y); | 526 | lcd_write_reg(R_VERT_RAM_ADDR_POS, ((y + height - 1) << 8) | y); |
446 | lcd_write_reg(R_RAM_ADDR_SET, ((y & 0xff) << 8) | (x & 0xff)); | 527 | lcd_write_reg(R_RAM_ADDR_SET, (y << 8) | x); |
447 | lcd_send_command(R_WRITE_DATA_2_GRAM); | 528 | lcd_send_command(R_WRITE_DATA_2_GRAM); |
448 | 529 | ||
449 | do { | 530 | do { |