diff options
Diffstat (limited to 'firmware/target/arm/gigabeat/meg-fx/lcd-meg-fx.c')
-rw-r--r-- | firmware/target/arm/gigabeat/meg-fx/lcd-meg-fx.c | 126 |
1 files changed, 32 insertions, 94 deletions
diff --git a/firmware/target/arm/gigabeat/meg-fx/lcd-meg-fx.c b/firmware/target/arm/gigabeat/meg-fx/lcd-meg-fx.c index 2d2f32069a..1bb68f9686 100644 --- a/firmware/target/arm/gigabeat/meg-fx/lcd-meg-fx.c +++ b/firmware/target/arm/gigabeat/meg-fx/lcd-meg-fx.c | |||
@@ -293,22 +293,12 @@ void lcd_bitmap_transparent_part(const fb_data *src, int src_x, int src_y, | |||
293 | : : "r" (src), "r" (dst), "r" (width), "r" (dst_end), "r" (stride), "r" (transcolor) : "r0", "r1" ); | 293 | : : "r" (src), "r" (dst), "r" (width), "r" (dst_end), "r" (stride), "r" (transcolor) : "r0", "r1" ); |
294 | } | 294 | } |
295 | 295 | ||
296 | #define CSUB_X 2 | 296 | /* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */ |
297 | #define CSUB_Y 2 | 297 | extern void lcd_write_yuv420_lines(fb_data *dst, |
298 | 298 | unsigned char chroma_buf[LCD_HEIGHT/2*3], | |
299 | #define RFULL (31*257) | 299 | unsigned char const * const src[3], |
300 | #define GFULL (63*257) | 300 | int width, |
301 | #define BFULL (31*257) | 301 | int stride); |
302 | #define RYFAC 9277 /* 31 * 257 * 1.0 * (255/219) */ | ||
303 | #define GYFAC 18853 /* 63 * 257 * 1.0 * (255/219) */ | ||
304 | #define BYFAC 9277 /* 31 * 257 * 1.0 * (255/219) */ | ||
305 | #define RVFAC 12716 /* 31 * 257 * 1.402 * (255/224) */ | ||
306 | #define GVFAC (-13163) /* 63 * 257 * -0.714136 * (255/224) */ | ||
307 | #define GUFAC (-6343) /* 63 * 257 * -0.344136 * (255/224) */ | ||
308 | #define BUFAC 16071 /* 31 * 257 * 1.772 * (255/224) */ | ||
309 | |||
310 | #define ROUNDOFFS (127*257) | ||
311 | |||
312 | /* Performance function to blit a YUV bitmap directly to the LCD */ | 302 | /* Performance function to blit a YUV bitmap directly to the LCD */ |
313 | /* For the Gigabeat - show it rotated */ | 303 | /* For the Gigabeat - show it rotated */ |
314 | /* So the LCD_WIDTH is now the height */ | 304 | /* So the LCD_WIDTH is now the height */ |
@@ -316,90 +306,38 @@ void lcd_yuv_blit(unsigned char * const src[3], | |||
316 | int src_x, int src_y, int stride, | 306 | int src_x, int src_y, int stride, |
317 | int x, int y, int width, int height) | 307 | int x, int y, int width, int height) |
318 | { | 308 | { |
319 | width = (width + 1) & ~1; | 309 | /* Caches for chroma data so it only need be recaculated every other |
320 | fb_data *dst = (fb_data*)FRAME + x * LCD_WIDTH + (LCD_WIDTH - y) - 1; | 310 | line */ |
321 | fb_data *dst_last = dst - (height - 1); | 311 | unsigned char chroma_buf[LCD_HEIGHT/2*3]; /* 480 bytes */ |
312 | unsigned char const * yuv_src[3]; | ||
313 | off_t z; | ||
322 | 314 | ||
323 | for (;;) | 315 | if (!lcd_on) |
324 | { | 316 | return; |
325 | fb_data *dst_row = dst; | ||
326 | int count = width; | ||
327 | const unsigned char *ysrc = src[0] + stride * src_y + src_x; | ||
328 | int y, u, v; | ||
329 | int red, green, blue; | ||
330 | unsigned rbits, gbits, bbits; | ||
331 | |||
332 | /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ | ||
333 | const unsigned char *usrc = src[1] + (stride/CSUB_X) * (src_y/CSUB_Y) | ||
334 | + (src_x/CSUB_X); | ||
335 | const unsigned char *vsrc = src[2] + (stride/CSUB_X) * (src_y/CSUB_Y) | ||
336 | + (src_x/CSUB_X); | ||
337 | int xphase = src_x % CSUB_X; | ||
338 | int rc, gc, bc; | ||
339 | |||
340 | u = *usrc++ - 128; | ||
341 | v = *vsrc++ - 128; | ||
342 | rc = RVFAC * v + ROUNDOFFS; | ||
343 | gc = GVFAC * v + GUFAC * u + ROUNDOFFS; | ||
344 | bc = BUFAC * u + ROUNDOFFS; | ||
345 | |||
346 | do | ||
347 | { | ||
348 | y = *ysrc++ - 16; | ||
349 | red = RYFAC * y + rc; | ||
350 | green = GYFAC * y + gc; | ||
351 | blue = BYFAC * y + bc; | ||
352 | |||
353 | if ((unsigned)red > (RFULL*255+ROUNDOFFS)) | ||
354 | { | ||
355 | if (red < 0) | ||
356 | red = 0; | ||
357 | else | ||
358 | red = (RFULL*255+ROUNDOFFS); | ||
359 | } | ||
360 | if ((unsigned)green > (GFULL*255+ROUNDOFFS)) | ||
361 | { | ||
362 | if (green < 0) | ||
363 | green = 0; | ||
364 | else | ||
365 | green = (GFULL*255+ROUNDOFFS); | ||
366 | } | ||
367 | if ((unsigned)blue > (BFULL*255+ROUNDOFFS)) | ||
368 | { | ||
369 | if (blue < 0) | ||
370 | blue = 0; | ||
371 | else | ||
372 | blue = (BFULL*255+ROUNDOFFS); | ||
373 | } | ||
374 | rbits = ((unsigned)red) >> 16 ; | ||
375 | gbits = ((unsigned)green) >> 16 ; | ||
376 | bbits = ((unsigned)blue) >> 16 ; | ||
377 | |||
378 | *dst_row = (rbits << 11) | (gbits << 5) | bbits; | ||
379 | |||
380 | /* next pixel - since rotated, add WIDTH */ | ||
381 | dst_row += LCD_WIDTH; | ||
382 | |||
383 | if (++xphase >= CSUB_X) | ||
384 | { | ||
385 | u = *usrc++ - 128; | ||
386 | v = *vsrc++ - 128; | ||
387 | rc = RVFAC * v + ROUNDOFFS; | ||
388 | gc = GVFAC * v + GUFAC * u + ROUNDOFFS; | ||
389 | bc = BUFAC * u + ROUNDOFFS; | ||
390 | xphase = 0; | ||
391 | } | ||
392 | } | ||
393 | while (--count); | ||
394 | 317 | ||
395 | if (dst == dst_last) break; | 318 | /* Sorry, but width and height must be >= 2 or else */ |
319 | width &= ~1; | ||
320 | height >>= 1; | ||
396 | 321 | ||
397 | dst--; | 322 | fb_data *dst = (fb_data*)FRAME + x * LCD_WIDTH + (LCD_WIDTH - y) - 1; |
398 | src_y++; | 323 | |
324 | z = stride*src_y; | ||
325 | yuv_src[0] = src[0] + z + src_x; | ||
326 | yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1); | ||
327 | yuv_src[2] = src[2] + (yuv_src[1] - src[1]); | ||
328 | |||
329 | do | ||
330 | { | ||
331 | lcd_write_yuv420_lines(dst, chroma_buf, yuv_src, width, | ||
332 | stride); | ||
333 | yuv_src[0] += stride << 1; /* Skip down two luma lines */ | ||
334 | yuv_src[1] += stride >> 1; /* Skip down one chroma line */ | ||
335 | yuv_src[2] += stride >> 1; | ||
336 | dst -= 2; | ||
399 | } | 337 | } |
338 | while (--height > 0); | ||
400 | } | 339 | } |
401 | 340 | ||
402 | |||
403 | void lcd_set_contrast(int val) { | 341 | void lcd_set_contrast(int val) { |
404 | (void) val; | 342 | (void) val; |
405 | // TODO: | 343 | // TODO: |