diff options
author | Dave Chapman <dave@dchapman.com> | 2006-08-17 08:37:35 +0000 |
---|---|---|
committer | Dave Chapman <dave@dchapman.com> | 2006-08-17 08:37:35 +0000 |
commit | b80266c45617acd5ef8ac5aa51a257222f611f4e (patch) | |
tree | 7a5c7d1491e807983635c744f63996abc69fc091 /firmware | |
parent | 10af966be2a489004b7d254476eb25f4ea9b0ef8 (diff) | |
download | rockbox-b80266c45617acd5ef8ac5aa51a257222f611f4e.tar.gz rockbox-b80266c45617acd5ef8ac5aa51a257222f611f4e.zip |
Optimisations to lcd_yuv_blit by Tom Meyer - speeds up mpegplayer by about 10-15%
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10627 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/drivers/lcd-ipodvideo.c | 160 |
1 files changed, 92 insertions, 68 deletions
diff --git a/firmware/drivers/lcd-ipodvideo.c b/firmware/drivers/lcd-ipodvideo.c index ef0ad4d2f3..237162b664 100644 --- a/firmware/drivers/lcd-ipodvideo.c +++ b/firmware/drivers/lcd-ipodvideo.c | |||
@@ -209,14 +209,15 @@ void lcd_update(void) | |||
209 | #define CSUB_Y 2 | 209 | #define CSUB_Y 2 |
210 | 210 | ||
211 | #define RYFAC (31*257) | 211 | #define RYFAC (31*257) |
212 | #define GYFAC (63*257) | 212 | #define GYFAC (31*257) |
213 | #define BYFAC (31*257) | 213 | #define BYFAC (31*257) |
214 | #define RVFAC 11170 /* 31 * 257 * 1.402 */ | 214 | #define RVFAC 11170 /* 31 * 257 * 1.402 */ |
215 | #define GVFAC (-11563) /* 63 * 257 * -0.714136 */ | 215 | #define GVFAC (-5690) /* 31 * 257 * -0.714136 */ |
216 | #define GUFAC (-5572) /* 63 * 257 * -0.344136 */ | 216 | #define GUFAC (-2742) /* 31 * 257 * -0.344136 */ |
217 | #define BUFAC 14118 /* 31 * 257 * 1.772 */ | 217 | #define BUFAC 14118 /* 31 * 257 * 1.772 */ |
218 | 218 | ||
219 | #define ROUNDOFFS (127*257) | 219 | #define ROUNDOFFS (127*257) |
220 | #define ROUNDOFFSG (63*257) | ||
220 | 221 | ||
221 | /* Performance function to blit a YUV bitmap directly to the LCD */ | 222 | /* Performance function to blit a YUV bitmap directly to the LCD */ |
222 | void lcd_yuv_blit(unsigned char * const src[3], | 223 | void lcd_yuv_blit(unsigned char * const src[3], |
@@ -230,11 +231,12 @@ void lcd_yuv_blit(unsigned char * const src[3], | |||
230 | if (finishup_needed) { | 231 | if (finishup_needed) { |
231 | unsigned int data; | 232 | unsigned int data; |
232 | /* Bottom-half of original lcd_bcm_finishup() function */ | 233 | /* Bottom-half of original lcd_bcm_finishup() function */ |
233 | do { | 234 | data = lcd_bcm_read32(0x1F8); |
234 | /* This function takes about 14ms to execute - so we yield() */ | 235 | while (data == 0xFFFA0005 || data == 0xFFFF) { |
236 | /* This loop can wait for up to 14ms - so we yield() */ | ||
235 | yield(); | 237 | yield(); |
236 | data = lcd_bcm_read32(0x1F8); | 238 | data = lcd_bcm_read32(0x1F8); |
237 | } while (data == 0xFFFA0005 || data == 0xFFFF); | 239 | } |
238 | } | 240 | } |
239 | 241 | ||
240 | lcd_bcm_read32(0x1FC); | 242 | lcd_bcm_read32(0x1FC); |
@@ -261,18 +263,23 @@ void lcd_yuv_blit(unsigned char * const src[3], | |||
261 | 263 | ||
262 | ymax = y + height - 1 ; | 264 | ymax = y + height - 1 ; |
263 | 265 | ||
266 | const int stride_div_csub_x = stride/CSUB_X; | ||
267 | |||
264 | for (; y <= ymax ; y++) | 268 | for (; y <= ymax ; y++) |
265 | { | 269 | { |
266 | /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ | 270 | /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ |
267 | const unsigned char *ysrc = src[0] + stride * src_y + src_x; | 271 | const unsigned char *ysrc = src[0] + stride * src_y + src_x; |
268 | const unsigned char *usrc = src[1] + (stride/CSUB_X) * (src_y/CSUB_Y) | 272 | |
269 | + (src_x/CSUB_X); | 273 | const int uvoffset = stride_div_csub_x * (src_y/CSUB_Y) + |
270 | const unsigned char *vsrc = src[2] + (stride/CSUB_X) * (src_y/CSUB_Y) | 274 | (src_x/CSUB_X); |
271 | + (src_x/CSUB_X); | 275 | |
276 | const unsigned char *usrc = src[1] + uvoffset; | ||
277 | const unsigned char *vsrc = src[2] + uvoffset; | ||
272 | const unsigned char *row_end = ysrc + width; | 278 | const unsigned char *row_end = ysrc + width; |
273 | 279 | ||
274 | int y, u, v; | 280 | int y, u, v; |
275 | int red, green, blue; | 281 | int red1, green1, blue1; |
282 | int red2, green2, blue2; | ||
276 | unsigned rbits, gbits, bbits; | 283 | unsigned rbits, gbits, bbits; |
277 | 284 | ||
278 | int rc, gc, bc; | 285 | int rc, gc, bc; |
@@ -282,73 +289,90 @@ void lcd_yuv_blit(unsigned char * const src[3], | |||
282 | u = *usrc++ - 128; | 289 | u = *usrc++ - 128; |
283 | v = *vsrc++ - 128; | 290 | v = *vsrc++ - 128; |
284 | rc = RVFAC * v + ROUNDOFFS; | 291 | rc = RVFAC * v + ROUNDOFFS; |
285 | gc = GVFAC * v + GUFAC * u + ROUNDOFFS; | 292 | gc = GVFAC * v + GUFAC * u + ROUNDOFFSG; |
286 | bc = BUFAC * u + ROUNDOFFS; | 293 | bc = BUFAC * u + ROUNDOFFS; |
287 | 294 | ||
288 | /* Pixel 1 */ | 295 | /* Pixel 1 */ |
289 | y = *ysrc++; | 296 | y = *ysrc++; |
290 | red = RYFAC * y + rc; | ||
291 | green = GYFAC * y + gc; | ||
292 | blue = BYFAC * y + bc; | ||
293 | |||
294 | if ((unsigned)red > (RYFAC*255+ROUNDOFFS)) | ||
295 | { | ||
296 | if (red < 0) | ||
297 | red = 0; | ||
298 | else | ||
299 | red = (RYFAC*255+ROUNDOFFS); | ||
300 | } | ||
301 | if ((unsigned)green > (GYFAC*255+ROUNDOFFS)) | ||
302 | { | ||
303 | if (green < 0) | ||
304 | green = 0; | ||
305 | else | ||
306 | green = (GYFAC*255+ROUNDOFFS); | ||
307 | } | ||
308 | if ((unsigned)blue > (BYFAC*255+ROUNDOFFS)) | ||
309 | { | ||
310 | if (blue < 0) | ||
311 | blue = 0; | ||
312 | else | ||
313 | blue = (BYFAC*255+ROUNDOFFS); | ||
314 | } | ||
315 | rbits = ((unsigned)red) >> 16 ; | ||
316 | gbits = ((unsigned)green) >> 16 ; | ||
317 | bbits = ((unsigned)blue) >> 16 ; | ||
318 | 297 | ||
319 | outw((rbits << 11) | (gbits << 5) | bbits, 0x30000000); | 298 | red1 = RYFAC * y + rc; |
299 | green1 = GYFAC * y + gc; | ||
300 | blue1 = BYFAC * y + bc; | ||
320 | 301 | ||
321 | /* Pixel 2 */ | 302 | /* Pixel 2 */ |
322 | y = *ysrc++; | 303 | y = *ysrc++; |
323 | red = RYFAC * y + rc; | 304 | red2 = RYFAC * y + rc; |
324 | green = GYFAC * y + gc; | 305 | green2 = GYFAC * y + gc; |
325 | blue = BYFAC * y + bc; | 306 | blue2 = BYFAC * y + bc; |
326 | 307 | ||
327 | if ((unsigned)red > (RYFAC*255+ROUNDOFFS)) | 308 | /* Since out of bounds errors are relatively rare, we check two |
328 | { | 309 | pixels at once to see if any components are out of bounds, and |
329 | if (red < 0) | 310 | then fix whichever is broken. This works due to high values and |
330 | red = 0; | 311 | negative values both becoming larger than the cutoff when |
331 | else | 312 | casted to unsigned. And ORing them together checks all of them |
332 | red = (RYFAC*255+ROUNDOFFS); | 313 | simultaneously. */ |
333 | } | 314 | if (((unsigned)(red1 | green1 | blue1 | |
334 | if ((unsigned)green > (GYFAC*255+ROUNDOFFS)) | 315 | red2 | green2 | blue2)) > (RYFAC*255+ROUNDOFFS)) { |
335 | { | 316 | if (((unsigned)(red1 | green1 | blue1)) > |
336 | if (green < 0) | 317 | (RYFAC*255+ROUNDOFFS)) { |
337 | green = 0; | 318 | if ((unsigned)red1 > (RYFAC*255+ROUNDOFFS)) |
338 | else | 319 | { |
339 | green = (GYFAC*255+ROUNDOFFS); | 320 | if (red1 < 0) |
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 | } | ||
340 | |||
341 | if (((unsigned)(red2 | green2 | blue2)) > | ||
342 | (RYFAC*255+ROUNDOFFS)) { | ||
343 | if ((unsigned)red2 > (RYFAC*255+ROUNDOFFS)) | ||
344 | { | ||
345 | if (red2 < 0) | ||
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 | } | ||
340 | } | 365 | } |
341 | if ((unsigned)blue > (BYFAC*255+ROUNDOFFS)) | 366 | |
342 | { | 367 | rbits = red1 >> 16 ; |
343 | if (blue < 0) | 368 | gbits = green1 >> 15 ; |
344 | blue = 0; | 369 | bbits = blue1 >> 16 ; |
345 | else | 370 | |
346 | blue = (BYFAC*255+ROUNDOFFS); | 371 | outw((rbits << 11) | (gbits << 5) | bbits, 0x30000000); |
347 | } | ||
348 | rbits = ((unsigned)red) >> 16 ; | ||
349 | gbits = ((unsigned)green) >> 16 ; | ||
350 | bbits = ((unsigned)blue) >> 16 ; | ||
351 | 372 | ||
373 | rbits = red2 >> 16 ; | ||
374 | gbits = green2 >> 15 ; | ||
375 | bbits = blue2 >> 16 ; | ||
352 | outw((rbits << 11) | (gbits << 5) | bbits, 0x30000000); | 376 | outw((rbits << 11) | (gbits << 5) | bbits, 0x30000000); |
353 | } | 377 | } |
354 | while (ysrc < row_end); | 378 | while (ysrc < row_end); |