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 | |
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
-rw-r--r-- | apps/plugin.c | 4 | ||||
-rw-r--r-- | apps/plugin.h | 6 | ||||
-rw-r--r-- | apps/plugins/mpegplayer/video_out_rockbox.c | 28 | ||||
-rw-r--r-- | firmware/drivers/lcd-h300.c | 141 | ||||
-rw-r--r-- | firmware/export/lcd.h | 3 |
5 files changed, 160 insertions, 22 deletions
diff --git a/apps/plugin.c b/apps/plugin.c index 4474d0d5ee..bbc5d7d15c 100644 --- a/apps/plugin.c +++ b/apps/plugin.c | |||
@@ -463,8 +463,8 @@ static const struct plugin_api rockbox_api = { | |||
463 | lcd_remote_bitmap, | 463 | lcd_remote_bitmap, |
464 | #endif | 464 | #endif |
465 | 465 | ||
466 | #if (CONFIG_LCD == LCD_IPODCOLOR || CONFIG_LCD == LCD_IPODNANO) && \ | 466 | #if (CONFIG_LCD == LCD_IPODCOLOR || CONFIG_LCD == LCD_IPODNANO \ |
467 | !defined(SIMULATOR) | 467 | || CONFIG_LCD == LCD_H300) && !defined(SIMULATOR) |
468 | lcd_yuv_blit, | 468 | lcd_yuv_blit, |
469 | #endif | 469 | #endif |
470 | 470 | ||
diff --git a/apps/plugin.h b/apps/plugin.h index b764d860c3..f43e0ae08b 100644 --- a/apps/plugin.h +++ b/apps/plugin.h | |||
@@ -104,7 +104,7 @@ | |||
104 | #define PLUGIN_MAGIC 0x526F634B /* RocK */ | 104 | #define PLUGIN_MAGIC 0x526F634B /* RocK */ |
105 | 105 | ||
106 | /* increase this every time the api struct changes */ | 106 | /* increase this every time the api struct changes */ |
107 | #define PLUGIN_API_VERSION 27 | 107 | #define PLUGIN_API_VERSION 28 |
108 | 108 | ||
109 | /* update this to latest version if a change to the api struct breaks | 109 | /* update this to latest version if a change to the api struct breaks |
110 | backwards compatibility (and please take the opportunity to sort in any | 110 | backwards compatibility (and please take the opportunity to sort in any |
@@ -539,8 +539,8 @@ struct plugin_api { | |||
539 | void (*lcd_remote_bitmap)(const fb_remote_data *src, int x, int y, int width, | 539 | void (*lcd_remote_bitmap)(const fb_remote_data *src, int x, int y, int width, |
540 | int height); | 540 | int height); |
541 | #endif | 541 | #endif |
542 | #if (CONFIG_LCD == LCD_IPODCOLOR || CONFIG_LCD == LCD_IPODNANO) && \ | 542 | #if (CONFIG_LCD == LCD_IPODCOLOR || CONFIG_LCD == LCD_IPODNANO \ |
543 | !defined(SIMULATOR) | 543 | || CONFIG_LCD == LCD_H300) && !defined(SIMULATOR) |
544 | void (*lcd_yuv_blit)(unsigned char * const src[3], | 544 | void (*lcd_yuv_blit)(unsigned char * const src[3], |
545 | int src_x, int src_y, int stride, | 545 | int src_x, int src_y, int stride, |
546 | int x, int y, int width, int height); | 546 | int x, int y, int width, int height); |
diff --git a/apps/plugins/mpegplayer/video_out_rockbox.c b/apps/plugins/mpegplayer/video_out_rockbox.c index 786d9d0e14..a5fdf5efbb 100644 --- a/apps/plugins/mpegplayer/video_out_rockbox.c +++ b/apps/plugins/mpegplayer/video_out_rockbox.c | |||
@@ -35,12 +35,14 @@ static int starttick; | |||
35 | #define CSUB_X 2 | 35 | #define CSUB_X 2 |
36 | #define CSUB_Y 2 | 36 | #define CSUB_Y 2 |
37 | 37 | ||
38 | static int image_x; | ||
39 | static int image_y; | ||
40 | static int image_width; | 38 | static int image_width; |
41 | static int image_height; | 39 | static int image_height; |
42 | static int image_chroma_x; | 40 | static int image_chroma_x; |
43 | static int image_chroma_y; | 41 | static int image_chroma_y; |
42 | static int output_x; | ||
43 | static int output_y; | ||
44 | static int output_width; | ||
45 | static int output_height; | ||
44 | 46 | ||
45 | #if (LCD_DEPTH == 16) && \ | 47 | #if (LCD_DEPTH == 16) && \ |
46 | ((LCD_PIXELFORMAT == RGB565) || (LCD_PIXELFORMAT == RGB565SWAPPED)) | 48 | ((LCD_PIXELFORMAT == RGB565) || (LCD_PIXELFORMAT == RGB565SWAPPED)) |
@@ -197,16 +199,16 @@ static void rockbox_draw_frame (vo_instance_t * instance, | |||
197 | (void)id; | 199 | (void)id; |
198 | (void)instance; | 200 | (void)instance; |
199 | 201 | ||
200 | #if (CONFIG_LCD == LCD_IPODCOLOR || CONFIG_LCD == LCD_IPODNANO) && \ | 202 | #if (CONFIG_LCD == LCD_IPODCOLOR || CONFIG_LCD == LCD_IPODNANO \ |
201 | !defined(SIMULATOR) | 203 | || CONFIG_LCD == LCD_H300) && !defined(SIMULATOR) |
202 | rb->lcd_yuv_blit(buf, | 204 | rb->lcd_yuv_blit(buf, |
203 | 0,0,image_width, | 205 | 0,0,image_width, |
204 | image_x,image_y,image_width,image_height); | 206 | output_x,output_y,output_width,output_height); |
205 | #elif (LCD_DEPTH == 16) && \ | 207 | #elif (LCD_DEPTH == 16) && \ |
206 | ((LCD_PIXELFORMAT == RGB565) || (LCD_PIXELFORMAT == RGB565SWAPPED)) | 208 | ((LCD_PIXELFORMAT == RGB565) || (LCD_PIXELFORMAT == RGB565SWAPPED)) |
207 | yuv_bitmap_part(buf,0,0,image_width, | 209 | yuv_bitmap_part(buf,0,0,image_width, |
208 | image_x,image_y,image_width,image_height); | 210 | output_x,output_y,output_width,output_height); |
209 | rb->lcd_update_rect(image_x,image_y,image_width,image_height); | 211 | rb->lcd_update_rect(output_x,output_y,output_width,output_height); |
210 | #endif | 212 | #endif |
211 | 213 | ||
212 | if (starttick==0) starttick=*rb->current_tick-1; /* Avoid divby0 */ | 214 | if (starttick==0) starttick=*rb->current_tick-1; /* Avoid divby0 */ |
@@ -265,15 +267,19 @@ static int rockbox_setup (vo_instance_t * instance, unsigned int width, | |||
265 | image_chroma_y=image_height/chroma_height; | 267 | image_chroma_y=image_height/chroma_height; |
266 | 268 | ||
267 | if (image_width >= LCD_WIDTH) { | 269 | if (image_width >= LCD_WIDTH) { |
268 | image_x = 0; | 270 | output_width = LCD_WIDTH; |
271 | output_x = 0; | ||
269 | } else { | 272 | } else { |
270 | image_x = (LCD_WIDTH-image_width)/2; | 273 | output_width = image_width; |
274 | output_x = (LCD_WIDTH-image_width)/2; | ||
271 | } | 275 | } |
272 | 276 | ||
273 | if (image_height >= LCD_HEIGHT) { | 277 | if (image_height >= LCD_HEIGHT) { |
274 | image_y = 0; | 278 | output_height = LCD_HEIGHT; |
279 | output_y = 0; | ||
275 | } else { | 280 | } else { |
276 | image_y = (LCD_HEIGHT-image_height)/2; | 281 | output_height = image_height; |
282 | output_y = (LCD_HEIGHT-image_height)/2; | ||
277 | } | 283 | } |
278 | 284 | ||
279 | return 0; | 285 | return 0; |
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; |
diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h index 32a958af2a..7551a1ab23 100644 --- a/firmware/export/lcd.h +++ b/firmware/export/lcd.h | |||
@@ -71,7 +71,8 @@ extern void lcd_puts_scroll_style(int x, int y, const unsigned char* string, | |||
71 | int style); | 71 | int style); |
72 | extern void lcd_icon(int icon, bool enable); | 72 | extern void lcd_icon(int icon, bool enable); |
73 | 73 | ||
74 | #if CONFIG_LCD == LCD_IPODCOLOR || CONFIG_LCD == LCD_IPODNANO | 74 | #if CONFIG_LCD == LCD_IPODCOLOR || CONFIG_LCD == LCD_IPODNANO \ |
75 | || CONFIG_LCD == LCD_H300 | ||
75 | void lcd_yuv_blit(unsigned char * const src[3], | 76 | void lcd_yuv_blit(unsigned char * const src[3], |
76 | int src_x, int src_y, int stride, | 77 | int src_x, int src_y, int stride, |
77 | int x, int y, int width, int height); | 78 | int x, int y, int width, int height); |