summaryrefslogtreecommitdiff
path: root/firmware/target/arm/gigabeat/meg-fx/lcd-meg-fx.c
diff options
context:
space:
mode:
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.c126
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 297extern 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
403void lcd_set_contrast(int val) { 341void lcd_set_contrast(int val) {
404 (void) val; 342 (void) val;
405 // TODO: 343 // TODO: