diff options
author | Thom Johansen <thomj@rockbox.org> | 2007-09-28 11:25:02 +0000 |
---|---|---|
committer | Thom Johansen <thomj@rockbox.org> | 2007-09-28 11:25:02 +0000 |
commit | d6ad3fbeb51ff49942b1f218fa729498e4f340d4 (patch) | |
tree | 21cfa868529d0afe328cd727a92532e92ef65277 /firmware/target | |
parent | d7cb90722f2cbda4c10c1552248a54633d30820c (diff) | |
download | rockbox-d6ad3fbeb51ff49942b1f218fa729498e4f340d4.tar.gz rockbox-d6ad3fbeb51ff49942b1f218fa729498e4f340d4.zip |
FS #7763 by Andree Buschmann. Speed up video rendering for Ipod Video.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14882 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/arm/ipod/video/lcd-video.c | 206 |
1 files changed, 91 insertions, 115 deletions
diff --git a/firmware/target/arm/ipod/video/lcd-video.c b/firmware/target/arm/ipod/video/lcd-video.c index 237162b664..27f31c3511 100644 --- a/firmware/target/arm/ipod/video/lcd-video.c +++ b/firmware/target/arm/ipod/video/lcd-video.c | |||
@@ -104,7 +104,7 @@ static void lcd_bcm_setup_rect(unsigned cmd, | |||
104 | lcd_bcm_write32(0xE001C, 0); | 104 | lcd_bcm_write32(0xE001C, 0); |
105 | } | 105 | } |
106 | 106 | ||
107 | static unsigned lcd_bcm_read32(unsigned address) { | 107 | static inline unsigned lcd_bcm_read32(unsigned address) { |
108 | while ((inw(0x30020000) & 1) == 0); | 108 | while ((inw(0x30020000) & 1) == 0); |
109 | 109 | ||
110 | /* write out destination address as two 16bit values */ | 110 | /* write out destination address as two 16bit values */ |
@@ -205,27 +205,39 @@ void lcd_update(void) | |||
205 | lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); | 205 | lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); |
206 | } | 206 | } |
207 | 207 | ||
208 | #define CSUB_X 2 | 208 | /* YUV- > RGB565 conversion |
209 | #define CSUB_Y 2 | 209 | * |R| |1.000000 -0.000001 1.402000| |Y'| |
210 | 210 | * |G| = |1.000000 -0.334136 -0.714136| |Pb| | |
211 | #define RYFAC (31*257) | 211 | * |B| |1.000000 1.772000 0.000000| |Pr| |
212 | #define GYFAC (31*257) | 212 | * Scaled, normalized, rounded and tweaked to yield RGB 565: |
213 | #define BYFAC (31*257) | 213 | * |R| |74 0 101| |Y' - 16| >> 9 |
214 | #define RVFAC 11170 /* 31 * 257 * 1.402 */ | 214 | * |G| = |74 -24 -51| |Cb - 128| >> 8 |
215 | #define GVFAC (-5690) /* 31 * 257 * -0.714136 */ | 215 | * |B| |74 128 0| |Cr - 128| >> 9 |
216 | #define GUFAC (-2742) /* 31 * 257 * -0.344136 */ | 216 | */ |
217 | #define BUFAC 14118 /* 31 * 257 * 1.772 */ | 217 | |
218 | 218 | #define RGBYFAC 74 /* 1.0 */ | |
219 | #define ROUNDOFFS (127*257) | 219 | #define RVFAC 101 /* 1.402 */ |
220 | #define ROUNDOFFSG (63*257) | 220 | #define GVFAC (-51) /* -0.714136 */ |
221 | #define GUFAC (-24) /* -0.334136 */ | ||
222 | #define BUFAC 128 /* 1.772 */ | ||
223 | |||
224 | /* ROUNDOFFS contain constant for correct round-offs as well as | ||
225 | constant parts of the conversion matrix (e.g. (Y'-16)*RGBYFAC | ||
226 | -> constant part = -16*RGBYFAC). Through extraction of these | ||
227 | constant parts we save at leat 4 substractions in the conversion | ||
228 | loop */ | ||
229 | #define ROUNDOFFSR (256 - 16*RGBYFAC - 128*RVFAC) | ||
230 | #define ROUNDOFFSG (128 - 16*RGBYFAC - 128*GVFAC - 128*GUFAC) | ||
231 | #define ROUNDOFFSB (256 - 16*RGBYFAC - 128*BUFAC) | ||
232 | |||
233 | #define MAX_5BIT 0x1f | ||
234 | #define MAX_6BIT 0x3f | ||
221 | 235 | ||
222 | /* Performance function to blit a YUV bitmap directly to the LCD */ | 236 | /* Performance function to blit a YUV bitmap directly to the LCD */ |
223 | void lcd_yuv_blit(unsigned char * const src[3], | 237 | void lcd_yuv_blit(unsigned char * const src[3], |
224 | int src_x, int src_y, int stride, | 238 | int src_x, int src_y, int stride, |
225 | int x, int y, int width, int height) | 239 | int x, int y, int width, int height) |
226 | { | 240 | { |
227 | int ymax; | ||
228 | |||
229 | width = (width + 1) & ~1; | 241 | width = (width + 1) & ~1; |
230 | 242 | ||
231 | if (finishup_needed) { | 243 | if (finishup_needed) { |
@@ -261,119 +273,83 @@ void lcd_yuv_blit(unsigned char * const src[3], | |||
261 | /* wait for it to be write ready */ | 273 | /* wait for it to be write ready */ |
262 | while ((inw(0x30030000) & 0x2) == 0); | 274 | while ((inw(0x30030000) & 0x2) == 0); |
263 | 275 | ||
264 | ymax = y + height - 1 ; | 276 | const int ymax = y + height - 1; |
265 | 277 | const int stride_div_sub_x = stride >> 1; | |
266 | const int stride_div_csub_x = stride/CSUB_X; | 278 | unsigned char *ysrc = 0; |
279 | unsigned char *usrc = 0; | ||
280 | unsigned char *vsrc = 0; | ||
281 | unsigned char *row_end = 0; | ||
282 | int uvoffset; | ||
283 | int yp, up, vp, rc, gc, bc; /* temporary variables */ | ||
284 | int red1, green1, blue1; /* contain RGB of 1st pixel */ | ||
285 | int red2, green2, blue2; /* contain RGB of 2nd pixel */ | ||
267 | 286 | ||
268 | for (; y <= ymax ; y++) | 287 | for (; y <= ymax ; y++) |
269 | { | 288 | { |
270 | /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ | 289 | /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ |
271 | const unsigned char *ysrc = src[0] + stride * src_y + src_x; | 290 | uvoffset = stride_div_sub_x*(src_y >> 1) + (src_x >> 1); |
272 | 291 | ysrc = src[0] + stride * src_y + src_x; | |
273 | const int uvoffset = stride_div_csub_x * (src_y/CSUB_Y) + | 292 | usrc = src[1] + uvoffset; |
274 | (src_x/CSUB_X); | 293 | vsrc = src[2] + uvoffset; |
275 | 294 | ||
276 | const unsigned char *usrc = src[1] + uvoffset; | 295 | row_end = ysrc + width; |
277 | const unsigned char *vsrc = src[2] + uvoffset; | ||
278 | const unsigned char *row_end = ysrc + width; | ||
279 | |||
280 | int y, u, v; | ||
281 | int red1, green1, blue1; | ||
282 | int red2, green2, blue2; | ||
283 | unsigned rbits, gbits, bbits; | ||
284 | |||
285 | int rc, gc, bc; | ||
286 | 296 | ||
287 | do | 297 | do |
288 | { | 298 | { |
289 | u = *usrc++ - 128; | 299 | up = *usrc++; |
290 | v = *vsrc++ - 128; | 300 | vp = *vsrc++; |
291 | rc = RVFAC * v + ROUNDOFFS; | 301 | rc = RVFAC * vp + ROUNDOFFSR; |
292 | gc = GVFAC * v + GUFAC * u + ROUNDOFFSG; | 302 | gc = GVFAC * vp + GUFAC * up + ROUNDOFFSG; |
293 | bc = BUFAC * u + ROUNDOFFS; | 303 | bc = BUFAC * up + ROUNDOFFSB; |
294 | 304 | ||
295 | /* Pixel 1 */ | 305 | /* Pixel 1 -> RGB565 */ |
296 | y = *ysrc++; | 306 | yp = *ysrc++ * RGBYFAC; |
297 | 307 | red1 = (yp + rc) >> 9; | |
298 | red1 = RYFAC * y + rc; | 308 | green1 = (yp + gc) >> 8; |
299 | green1 = GYFAC * y + gc; | 309 | blue1 = (yp + bc) >> 9; |
300 | blue1 = BYFAC * y + bc; | 310 | |
301 | 311 | /* Pixel 2 -> RGB565 */ | |
302 | /* Pixel 2 */ | 312 | yp = *ysrc++ * RGBYFAC; |
303 | y = *ysrc++; | 313 | red2 = (yp + rc) >> 9; |
304 | red2 = RYFAC * y + rc; | 314 | green2 = (yp + gc) >> 8; |
305 | green2 = GYFAC * y + gc; | 315 | blue2 = (yp + bc) >> 9; |
306 | blue2 = BYFAC * y + bc; | 316 | |
307 | |||
308 | /* Since out of bounds errors are relatively rare, we check two | 317 | /* Since out of bounds errors are relatively rare, we check two |
309 | pixels at once to see if any components are out of bounds, and | 318 | pixels at once to see if any components are out of bounds, and |
310 | then fix whichever is broken. This works due to high values and | 319 | then fix whichever is broken. This works due to high values and |
311 | negative values both becoming larger than the cutoff when | 320 | negative values both being !=0 when bitmasking them. |
312 | casted to unsigned. And ORing them together checks all of them | 321 | We first check for red and blue components (5bit range). */ |
313 | simultaneously. */ | 322 | if ((red1 | blue1 | red2 | blue2) & ~MAX_5BIT) |
314 | if (((unsigned)(red1 | green1 | blue1 | | 323 | { |
315 | red2 | green2 | blue2)) > (RYFAC*255+ROUNDOFFS)) { | 324 | if ((red1 | blue1) & ~MAX_5BIT) |
316 | if (((unsigned)(red1 | green1 | blue1)) > | 325 | { |
317 | (RYFAC*255+ROUNDOFFS)) { | 326 | if (red1 & ~MAX_5BIT) |
318 | if ((unsigned)red1 > (RYFAC*255+ROUNDOFFS)) | 327 | red1 = (red1 >> 31) ? 0 : MAX_5BIT; |
319 | { | 328 | if (blue1 & ~MAX_5BIT) |
320 | if (red1 < 0) | 329 | blue1 = (blue1 >> 31) ? 0 : MAX_5BIT; |
321 | red1 = 0; | ||
322 | else | ||
323 | red1 = (RYFAC*255+ROUNDOFFS); | ||
324 | } | ||
325 | if ((unsigned)green1 > (GYFAC*255+ROUNDOFFSG)) | ||
326 | { | ||
327 | if (green1 < 0) | ||
328 | green1 = 0; | ||
329 | else | ||
330 | green1 = (GYFAC*255+ROUNDOFFSG); | ||
331 | } | ||
332 | if ((unsigned)blue1 > (BYFAC*255+ROUNDOFFS)) | ||
333 | { | ||
334 | if (blue1 < 0) | ||
335 | blue1 = 0; | ||
336 | else | ||
337 | blue1 = (BYFAC*255+ROUNDOFFS); | ||
338 | } | ||
339 | } | 330 | } |
340 | 331 | if ((red2 | blue2) & ~MAX_5BIT) | |
341 | if (((unsigned)(red2 | green2 | blue2)) > | 332 | { |
342 | (RYFAC*255+ROUNDOFFS)) { | 333 | if (red2 & ~MAX_5BIT) |
343 | if ((unsigned)red2 > (RYFAC*255+ROUNDOFFS)) | 334 | red2 = (red2 >> 31) ? 0 : MAX_5BIT; |
344 | { | 335 | if (blue2 & ~MAX_5BIT) |
345 | if (red2 < 0) | 336 | blue2 = (blue2 >> 31) ? 0 : MAX_5BIT; |
346 | red2 = 0; | ||
347 | else | ||
348 | red2 = (RYFAC*255+ROUNDOFFS); | ||
349 | } | ||
350 | if ((unsigned)green2 > (GYFAC*255+ROUNDOFFSG)) | ||
351 | { | ||
352 | if (green2 < 0) | ||
353 | green2 = 0; | ||
354 | else | ||
355 | green2 = (GYFAC*255+ROUNDOFFSG); | ||
356 | } | ||
357 | if ((unsigned)blue2 > (BYFAC*255+ROUNDOFFS)) | ||
358 | { | ||
359 | if (blue2 < 0) | ||
360 | blue2 = 0; | ||
361 | else | ||
362 | blue2 = (BYFAC*255+ROUNDOFFS); | ||
363 | } | ||
364 | } | 337 | } |
365 | } | 338 | } |
366 | 339 | /* We second check for green component (6bit range) */ | |
367 | rbits = red1 >> 16 ; | 340 | if ((green1 | green2) & ~MAX_6BIT) |
368 | gbits = green1 >> 15 ; | 341 | { |
369 | bbits = blue1 >> 16 ; | 342 | if (green1 & ~MAX_6BIT) |
370 | 343 | green1 = (green1 >> 31) ? 0 : MAX_6BIT; | |
371 | outw((rbits << 11) | (gbits << 5) | bbits, 0x30000000); | 344 | if (green2 & ~MAX_6BIT) |
345 | green2 = (green2 >> 31) ? 0 : MAX_6BIT; | ||
346 | } | ||
347 | |||
348 | /* pixel1 */ | ||
349 | outw((red1 << 11) | (green1 << 5) | blue1, 0x30000000); | ||
372 | 350 | ||
373 | rbits = red2 >> 16 ; | 351 | /* pixel2 */ |
374 | gbits = green2 >> 15 ; | 352 | outw((red2 << 11) | (green2 << 5) | blue2, 0x30000000); |
375 | bbits = blue2 >> 16 ; | ||
376 | outw((rbits << 11) | (gbits << 5) | bbits, 0x30000000); | ||
377 | } | 353 | } |
378 | while (ysrc < row_end); | 354 | while (ysrc < row_end); |
379 | 355 | ||