diff options
Diffstat (limited to 'firmware/target/arm/sandisk/sansa-e200/lcd-e200.c')
-rw-r--r-- | firmware/target/arm/sandisk/sansa-e200/lcd-e200.c | 138 |
1 files changed, 34 insertions, 104 deletions
diff --git a/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c b/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c index 6b51531056..3e8246b367 100644 --- a/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c +++ b/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c | |||
@@ -329,115 +329,45 @@ void lcd_blit(const fb_data* data, int x, int by, int width, | |||
329 | (void)stride; | 329 | (void)stride; |
330 | } | 330 | } |
331 | 331 | ||
332 | #define CSUB_X 2 | 332 | /* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */ |
333 | #define CSUB_Y 2 | 333 | extern void lcd_write_yuv420_lines(fb_data *dst, |
334 | 334 | unsigned char chroma_buf[LCD_HEIGHT/2*3], | |
335 | #define RYFAC (31*257) | 335 | unsigned char const * const src[3], |
336 | #define GYFAC (63*257) | 336 | int width, |
337 | #define BYFAC (31*257) | 337 | int stride); |
338 | #define RVFAC 11170 /* 31 * 257 * 1.402 */ | 338 | /* Performance function to blit a YUV bitmap directly to the LCD */ |
339 | #define GVFAC (-11563) /* 63 * 257 * -0.714136 */ | 339 | /* For the e200 - show it rotated */ |
340 | #define GUFAC (-5572) /* 63 * 257 * -0.344136 */ | 340 | /* So the LCD_WIDTH is now the height */ |
341 | #define BUFAC 14118 /* 31 * 257 * 1.772 */ | ||
342 | |||
343 | #define ROUNDOFFS (127*257) | ||
344 | |||
345 | /* Performance function to blit a YUV bitmap directly to the LCD | ||
346 | Actually this code is from gigabeat, because this target is also | ||
347 | writing direct to a buffer. */ | ||
348 | void lcd_yuv_blit(unsigned char * const src[3], | 341 | void lcd_yuv_blit(unsigned char * const src[3], |
349 | int src_x, int src_y, int stride, | 342 | int src_x, int src_y, int stride, |
350 | int _x, int _y, int width, int height) | 343 | int x, int y, int width, int height) |
351 | { | 344 | { |
352 | const unsigned char *usrc; | 345 | /* Caches for chroma data so it only need be recaculated every other |
353 | const unsigned char *vsrc; | 346 | line */ |
354 | const unsigned char *ysrc; | 347 | unsigned char chroma_buf[LCD_HEIGHT/2*3]; /* 480 bytes */ |
355 | int xphase; | 348 | unsigned char const * yuv_src[3]; |
356 | int rc, gc, bc; | 349 | off_t z; |
357 | int y, u, v; | 350 | |
358 | int red, green, blue; | 351 | /* Sorry, but width and height must be >= 2 or else */ |
359 | unsigned rbits, gbits, bbits; | 352 | width &= ~1; |
360 | int count; | 353 | height >>= 1; |
361 | fb_data *dst_row; | 354 | |
362 | |||
363 | |||
364 | width = (width + 1) & ~1; | ||
365 | fb_data *dst = (fb_data*)lcd_driver_framebuffer + | 355 | fb_data *dst = (fb_data*)lcd_driver_framebuffer + |
366 | _x * LCD_WIDTH + (LCD_WIDTH - _y) - 1; | 356 | x * LCD_WIDTH + (LCD_WIDTH - y) - 1; |
367 | fb_data *dst_last = dst - (height - 1); | 357 | |
358 | z = stride*src_y; | ||
359 | yuv_src[0] = src[0] + z + src_x; | ||
360 | yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1); | ||
361 | yuv_src[2] = src[2] + (yuv_src[1] - src[1]); | ||
368 | 362 | ||
369 | do | 363 | do |
370 | { | 364 | { |
371 | dst_row = dst; | 365 | lcd_write_yuv420_lines(dst, chroma_buf, yuv_src, width, |
372 | count = width; | 366 | stride); |
373 | ysrc = src[0] + stride * src_y + src_x; | 367 | yuv_src[0] += stride << 1; /* Skip down two luma lines */ |
374 | 368 | yuv_src[1] += stride >> 1; /* Skip down one chroma line */ | |
375 | /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ | 369 | yuv_src[2] += stride >> 1; |
376 | usrc = src[1] + (stride/CSUB_X) * (src_y/CSUB_Y) | 370 | dst -= 2; |
377 | + (src_x/CSUB_X); | 371 | } |
378 | vsrc = src[2] + (stride/CSUB_X) * (src_y/CSUB_Y) | 372 | while (--height > 0); |
379 | + (src_x/CSUB_X); | ||
380 | xphase = src_x % CSUB_X; | ||
381 | |||
382 | u = *usrc++ - 128; | ||
383 | v = *vsrc++ - 128; | ||
384 | rc = RVFAC * v + ROUNDOFFS; | ||
385 | gc = GVFAC * v + GUFAC * u + ROUNDOFFS; | ||
386 | bc = BUFAC * u + ROUNDOFFS; | ||
387 | |||
388 | do | ||
389 | { | ||
390 | y = *ysrc++; | ||
391 | red = RYFAC * y + rc; | ||
392 | green = GYFAC * y + gc; | ||
393 | blue = BYFAC * y + bc; | ||
394 | |||
395 | if ((unsigned)red > (RYFAC*255+ROUNDOFFS)) | ||
396 | { | ||
397 | if (red < 0) | ||
398 | red = 0; | ||
399 | else | ||
400 | red = (RYFAC*255+ROUNDOFFS); | ||
401 | } | ||
402 | if ((unsigned)green > (GYFAC*255+ROUNDOFFS)) | ||
403 | { | ||
404 | if (green < 0) | ||
405 | green = 0; | ||
406 | else | ||
407 | green = (GYFAC*255+ROUNDOFFS); | ||
408 | } | ||
409 | if ((unsigned)blue > (BYFAC*255+ROUNDOFFS)) | ||
410 | { | ||
411 | if (blue < 0) | ||
412 | blue = 0; | ||
413 | else | ||
414 | blue = (BYFAC*255+ROUNDOFFS); | ||
415 | } | ||
416 | rbits = ((unsigned)red) >> 16 ; | ||
417 | gbits = ((unsigned)green) >> 16 ; | ||
418 | bbits = ((unsigned)blue) >> 16 ; | ||
419 | |||
420 | *dst_row = (rbits << 11) | (gbits << 5) | bbits; | ||
421 | |||
422 | /* next pixel - since rotated, add WIDTH */ | ||
423 | dst_row += LCD_WIDTH; | ||
424 | |||
425 | if (++xphase >= CSUB_X) | ||
426 | { | ||
427 | u = *usrc++ - 128; | ||
428 | v = *vsrc++ - 128; | ||
429 | rc = RVFAC * v + ROUNDOFFS; | ||
430 | gc = GVFAC * v + GUFAC * u + ROUNDOFFS; | ||
431 | bc = BUFAC * u + ROUNDOFFS; | ||
432 | xphase = 0; | ||
433 | } | ||
434 | } | ||
435 | while (--count); | ||
436 | |||
437 | if (dst == dst_last) break; | ||
438 | |||
439 | dst--; | ||
440 | src_y++; | ||
441 | } while( 1); | ||
442 | } | 373 | } |
443 | |||