diff options
author | Jens Arnold <amiconn@rockbox.org> | 2006-08-08 13:44:43 +0000 |
---|---|---|
committer | Jens Arnold <amiconn@rockbox.org> | 2006-08-08 13:44:43 +0000 |
commit | c5a309afbd60114a4cb8b7f758647f7a6af0a6bd (patch) | |
tree | cb615f1619892e1d059c1767481d3f5f67a47402 /firmware/drivers | |
parent | 905cf06e32197f54cd005851e4060f0e8cbff34c (diff) | |
download | rockbox-c5a309afbd60114a4cb8b7f758647f7a6af0a6bd.tar.gz rockbox-c5a309afbd60114a4cb8b7f758647f7a6af0a6bd.zip |
H300: * Implemented lcd_yuv_blit(). Speeds up video playback by about 7%. No bounds check in lcd_yuv_blit() (by convention), implementations for other targets should be adapted. * Fixed off-by-one bug in lcd_update_rect()
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10484 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers')
-rw-r--r-- | firmware/drivers/lcd-h300.c | 141 |
1 files changed, 136 insertions, 5 deletions
diff --git a/firmware/drivers/lcd-h300.c b/firmware/drivers/lcd-h300.c index 0bdb123d41..c3f5d48f87 100644 --- a/firmware/drivers/lcd-h300.c +++ b/firmware/drivers/lcd-h300.c | |||
@@ -77,18 +77,20 @@ static int xoffset = 0; /* needed for flip */ | |||
77 | #define R_HORIZ_RAM_ADDR_POS 0x44 | 77 | #define R_HORIZ_RAM_ADDR_POS 0x44 |
78 | #define R_VERT_RAM_ADDR_POS 0x45 | 78 | #define R_VERT_RAM_ADDR_POS 0x45 |
79 | 79 | ||
80 | #define LCD_CMD (*(volatile unsigned short *)0xf0000000) | ||
81 | #define LCD_DATA (*(volatile unsigned short *)0xf0000002) | ||
80 | 82 | ||
81 | /* called very frequently - inline! */ | 83 | /* called very frequently - inline! */ |
82 | static inline void lcd_write_reg(int reg, int val) | 84 | static inline void lcd_write_reg(int reg, int val) |
83 | { | 85 | { |
84 | *(volatile unsigned short *)0xf0000000 = reg; | 86 | LCD_CMD = reg; |
85 | *(volatile unsigned short *)0xf0000002 = val; | 87 | LCD_DATA = val; |
86 | } | 88 | } |
87 | 89 | ||
88 | /* called very frequently - inline! */ | 90 | /* called very frequently - inline! */ |
89 | static inline void lcd_begin_write_gram(void) | 91 | static inline void lcd_begin_write_gram(void) |
90 | { | 92 | { |
91 | *(volatile unsigned short *)0xf0000000 = R_WRITE_DATA_2_GRAM; | 93 | LCD_CMD = R_WRITE_DATA_2_GRAM; |
92 | } | 94 | } |
93 | 95 | ||
94 | /*** hardware configuration ***/ | 96 | /*** hardware configuration ***/ |
@@ -299,6 +301,135 @@ void lcd_blit(const fb_data* data, int x, int by, int width, | |||
299 | /*if(display_on)*/ | 301 | /*if(display_on)*/ |
300 | } | 302 | } |
301 | 303 | ||
304 | #define CSUB_X 2 | ||
305 | #define CSUB_Y 2 | ||
306 | |||
307 | #define RYFAC (31*257) | ||
308 | #define GYFAC (63*257) | ||
309 | #define BYFAC (31*257) | ||
310 | #define RVFAC 11170 /* 31 * 257 * 1.402 */ | ||
311 | #define GVFAC (-11563) /* 63 * 257 * -0.714136 */ | ||
312 | #define GUFAC (-5572) /* 63 * 257 * -0.344136 */ | ||
313 | #define BUFAC 14118 /* 31 * 257 * 1.772 */ | ||
314 | |||
315 | #define ROUNDOFFS (127*257) | ||
316 | |||
317 | /* Performance function to blit a YUV bitmap directly to the LCD */ | ||
318 | void lcd_yuv_blit(unsigned char * const src[3], | ||
319 | int src_x, int src_y, int stride, | ||
320 | int x, int y, int width, int height) | ||
321 | { | ||
322 | if (display_on) | ||
323 | { | ||
324 | int ymax; | ||
325 | |||
326 | width = (width + 1) & ~1; | ||
327 | height = (height + 1) & ~1; | ||
328 | ymax = y + height - 1; | ||
329 | |||
330 | /* set update window */ | ||
331 | |||
332 | /* horiz ram addr */ | ||
333 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, (ymax << 8) | y); | ||
334 | |||
335 | /* vert ram addr */ | ||
336 | lcd_write_reg(R_VERT_RAM_ADDR_POS,((x+xoffset+width-1) << 8) | (x+xoffset)); | ||
337 | lcd_write_reg(R_RAM_ADDR_SET, ((x+xoffset) << 8) | y); | ||
338 | lcd_begin_write_gram(); | ||
339 | |||
340 | for (; y <= ymax; y++) | ||
341 | { | ||
342 | /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ | ||
343 | const unsigned char *ysrc = src[0] + stride * src_y + src_x; | ||
344 | const unsigned char *usrc = src[1] + (stride/CSUB_X) * (src_y/CSUB_Y) | ||
345 | + (src_x/CSUB_X); | ||
346 | const unsigned char *vsrc = src[2] + (stride/CSUB_X) * (src_y/CSUB_Y) | ||
347 | + (src_x/CSUB_X); | ||
348 | const unsigned char *row_end = ysrc + width; | ||
349 | |||
350 | int y, u, v; | ||
351 | int rc, gc, bc; | ||
352 | int red, green, blue; | ||
353 | unsigned rbits, gbits, bbits; | ||
354 | |||
355 | do | ||
356 | { | ||
357 | u = *usrc++ - 128; | ||
358 | v = *vsrc++ - 128; | ||
359 | rc = RVFAC * v + ROUNDOFFS; | ||
360 | gc = GVFAC * v + GUFAC * u + ROUNDOFFS; | ||
361 | bc = BUFAC * u + ROUNDOFFS; | ||
362 | |||
363 | y = *ysrc++; | ||
364 | red = RYFAC * y + rc; | ||
365 | green = GYFAC * y + gc; | ||
366 | blue = BYFAC * y + bc; | ||
367 | |||
368 | if ((unsigned)red > (RYFAC*255+ROUNDOFFS)) | ||
369 | { | ||
370 | if (red < 0) | ||
371 | red = 0; | ||
372 | else | ||
373 | red = (RYFAC*255+ROUNDOFFS); | ||
374 | } | ||
375 | if ((unsigned)green > (GYFAC*255+ROUNDOFFS)) | ||
376 | { | ||
377 | if (green < 0) | ||
378 | green = 0; | ||
379 | else | ||
380 | green = (GYFAC*255+ROUNDOFFS); | ||
381 | } | ||
382 | if ((unsigned)blue > (BYFAC*255+ROUNDOFFS)) | ||
383 | { | ||
384 | if (blue < 0) | ||
385 | blue = 0; | ||
386 | else | ||
387 | blue = (BYFAC*255+ROUNDOFFS); | ||
388 | } | ||
389 | rbits = ((unsigned)red) >> 16 ; | ||
390 | gbits = ((unsigned)green) >> 16 ; | ||
391 | bbits = ((unsigned)blue) >> 16 ; | ||
392 | |||
393 | LCD_DATA = (rbits << 11) | (gbits << 5) | bbits; | ||
394 | |||
395 | y = *ysrc++; | ||
396 | red = RYFAC * y + rc; | ||
397 | green = GYFAC * y + gc; | ||
398 | blue = BYFAC * y + bc; | ||
399 | |||
400 | if ((unsigned)red > (RYFAC*255+ROUNDOFFS)) | ||
401 | { | ||
402 | if (red < 0) | ||
403 | red = 0; | ||
404 | else | ||
405 | red = (RYFAC*255+ROUNDOFFS); | ||
406 | } | ||
407 | if ((unsigned)green > (GYFAC*255+ROUNDOFFS)) | ||
408 | { | ||
409 | if (green < 0) | ||
410 | green = 0; | ||
411 | else | ||
412 | green = (GYFAC*255+ROUNDOFFS); | ||
413 | } | ||
414 | if ((unsigned)blue > (BYFAC*255+ROUNDOFFS)) | ||
415 | { | ||
416 | if (blue < 0) | ||
417 | blue = 0; | ||
418 | else | ||
419 | blue = (BYFAC*255+ROUNDOFFS); | ||
420 | } | ||
421 | rbits = ((unsigned)red) >> 16 ; | ||
422 | gbits = ((unsigned)green) >> 16 ; | ||
423 | bbits = ((unsigned)blue) >> 16 ; | ||
424 | |||
425 | LCD_DATA = (rbits << 11) | (gbits << 5) | bbits; | ||
426 | } | ||
427 | while (ysrc < row_end); | ||
428 | |||
429 | src_y++; | ||
430 | } | ||
431 | } | ||
432 | } | ||
302 | 433 | ||
303 | /* Update the display. | 434 | /* Update the display. |
304 | This must be called after all other LCD functions that change the display. */ | 435 | This must be called after all other LCD functions that change the display. */ |
@@ -324,8 +455,8 @@ void lcd_update(void) | |||
324 | void lcd_update_rect(int, int, int, int) ICODE_ATTR; | 455 | void lcd_update_rect(int, int, int, int) ICODE_ATTR; |
325 | void lcd_update_rect(int x, int y, int width, int height) | 456 | void lcd_update_rect(int x, int y, int width, int height) |
326 | { | 457 | { |
327 | if(display_on) { | 458 | if(display_on) { |
328 | int ymax = y + height; | 459 | int ymax = y + height - 1; |
329 | 460 | ||
330 | if(x + width > LCD_WIDTH) | 461 | if(x + width > LCD_WIDTH) |
331 | width = LCD_WIDTH - x; | 462 | width = LCD_WIDTH - x; |