diff options
author | Thom Johansen <thomj@rockbox.org> | 2007-10-16 19:47:15 +0000 |
---|---|---|
committer | Thom Johansen <thomj@rockbox.org> | 2007-10-16 19:47:15 +0000 |
commit | b5f779b2efbefae67c876727b297575e03d5c8a2 (patch) | |
tree | 5473f8d869c11812af6d2d24b3ac56909ca99bb1 /firmware | |
parent | 3688e94083cb4b94728faa9cc242492a354d8394 (diff) | |
download | rockbox-b5f779b2efbefae67c876727b297575e03d5c8a2.tar.gz rockbox-b5f779b2efbefae67c876727b297575e03d5c8a2.zip |
Parts of FS #7951 by Andree Buschmann. Faster YUV BLIT (means faster mpegplayer) for Ipods Nano and Video while we're waiting for the assembler ones.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15147 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/target/arm/ipod/lcd-color_nano.c | 160 | ||||
-rw-r--r-- | firmware/target/arm/ipod/video/lcd-video.c | 54 |
2 files changed, 94 insertions, 120 deletions
diff --git a/firmware/target/arm/ipod/lcd-color_nano.c b/firmware/target/arm/ipod/lcd-color_nano.c index f3a5819d6b..3471372d33 100644 --- a/firmware/target/arm/ipod/lcd-color_nano.c +++ b/firmware/target/arm/ipod/lcd-color_nano.c | |||
@@ -134,16 +134,33 @@ void lcd_blit(const fb_data* data, int x, int by, int width, | |||
134 | #define CSUB_X 2 | 134 | #define CSUB_X 2 |
135 | #define CSUB_Y 2 | 135 | #define CSUB_Y 2 |
136 | 136 | ||
137 | #define RYFAC (31*257) | 137 | /* YUV- > RGB565 conversion |
138 | #define GYFAC (31*257) | 138 | * |R| |1.000000 -0.000001 1.402000| |Y'| |
139 | #define BYFAC (31*257) | 139 | * |G| = |1.000000 -0.334136 -0.714136| |Pb| |
140 | #define RVFAC 11170 /* 31 * 257 * 1.402 */ | 140 | * |B| |1.000000 1.772000 0.000000| |Pr| |
141 | #define GVFAC (-5690) /* 31 * 257 * -0.714136 */ | 141 | * Scaled, normalized, rounded and tweaked to yield RGB 565: |
142 | #define GUFAC (-2742) /* 31 * 257 * -0.344136 */ | 142 | * |R| |74 0 101| |Y' - 16| >> 9 |
143 | #define BUFAC 14118 /* 31 * 257 * 1.772 */ | 143 | * |G| = |74 -24 -51| |Cb - 128| >> 8 |
144 | 144 | * |B| |74 128 0| |Cr - 128| >> 9 | |
145 | #define ROUNDOFFS (127*257) | 145 | */ |
146 | #define ROUNDOFFSG (63*257) | 146 | |
147 | #define RGBYFAC 74 /* 1.0 */ | ||
148 | #define RVFAC 101 /* 1.402 */ | ||
149 | #define GVFAC (-51) /* -0.714136 */ | ||
150 | #define GUFAC (-24) /* -0.334136 */ | ||
151 | #define BUFAC 128 /* 1.772 */ | ||
152 | |||
153 | /* ROUNDOFFS contain constant for correct round-offs as well as | ||
154 | constant parts of the conversion matrix (e.g. (Y'-16)*RGBYFAC | ||
155 | -> constant part = -16*RGBYFAC). Through extraction of these | ||
156 | constant parts we save at leat 4 substractions in the conversion | ||
157 | loop */ | ||
158 | #define ROUNDOFFSR (256 - 16*RGBYFAC - 128*RVFAC) | ||
159 | #define ROUNDOFFSG (128 - 16*RGBYFAC - 128*GVFAC - 128*GUFAC) | ||
160 | #define ROUNDOFFSB (256 - 16*RGBYFAC - 128*BUFAC) | ||
161 | |||
162 | #define MAX_5BIT 0x1f | ||
163 | #define MAX_6BIT 0x3f | ||
147 | 164 | ||
148 | /* Performance function to blit a YUV bitmap directly to the LCD */ | 165 | /* Performance function to blit a YUV bitmap directly to the LCD */ |
149 | void lcd_yuv_blit(unsigned char * const src[3], | 166 | void lcd_yuv_blit(unsigned char * const src[3], |
@@ -225,10 +242,9 @@ void lcd_yuv_blit(unsigned char * const src[3], | |||
225 | const unsigned char *vsrc = src[2] + uvoffset; | 242 | const unsigned char *vsrc = src[2] + uvoffset; |
226 | const unsigned char *row_end = ysrc + width; | 243 | const unsigned char *row_end = ysrc + width; |
227 | 244 | ||
228 | int y, u, v; | 245 | int yp, up, vp; |
229 | int red1, green1, blue1; | 246 | int red1, green1, blue1; |
230 | int red2, green2, blue2; | 247 | int red2, green2, blue2; |
231 | unsigned rbits, gbits, bbits; | ||
232 | 248 | ||
233 | int rc, gc, bc; | 249 | int rc, gc, bc; |
234 | int pixels_to_write; | 250 | int pixels_to_write; |
@@ -257,94 +273,52 @@ void lcd_yuv_blit(unsigned char * const src[3], | |||
257 | 273 | ||
258 | do | 274 | do |
259 | { | 275 | { |
260 | u = *usrc++ - 128; | 276 | up = *usrc++; |
261 | v = *vsrc++ - 128; | 277 | vp = *vsrc++; |
262 | rc = RVFAC * v + ROUNDOFFS; | 278 | rc = RVFAC * vp + ROUNDOFFSR; |
263 | gc = GVFAC * v + GUFAC * u + ROUNDOFFSG; | 279 | gc = GVFAC * vp + GUFAC * up + ROUNDOFFSG; |
264 | bc = BUFAC * u + ROUNDOFFS; | 280 | bc = BUFAC * up + ROUNDOFFSB; |
265 | 281 | ||
266 | /* Pixel 1 */ | 282 | /* Pixel 1 -> RGB565 */ |
267 | y = *ysrc++; | 283 | yp = *ysrc++ * RGBYFAC; |
268 | 284 | red1 = (yp + rc) >> 9; | |
269 | red1 = RYFAC * y + rc; | 285 | green1 = (yp + gc) >> 8; |
270 | green1 = GYFAC * y + gc; | 286 | blue1 = (yp + bc) >> 9; |
271 | blue1 = BYFAC * y + bc; | 287 | |
272 | 288 | /* Pixel 2 -> RGB565 */ | |
273 | /* Pixel 2 */ | 289 | yp = *ysrc++ * RGBYFAC; |
274 | y = *ysrc++; | 290 | red2 = (yp + rc) >> 9; |
275 | red2 = RYFAC * y + rc; | 291 | green2 = (yp + gc) >> 8; |
276 | green2 = GYFAC * y + gc; | 292 | blue2 = (yp + bc) >> 9; |
277 | blue2 = BYFAC * y + bc; | ||
278 | 293 | ||
279 | /* Since out of bounds errors are relatively rare, we check two | 294 | /* Since out of bounds errors are relatively rare, we check two |
280 | pixels at once to see if any components are out of bounds, and | 295 | pixels at once to see if any components are out of bounds, and |
281 | then fix whichever is broken. This works due to high values and | 296 | then fix whichever is broken. This works due to high values and |
282 | negative values both becoming larger than the cutoff when | 297 | negative values both being !=0 when bitmasking them. |
283 | casted to unsigned. And ORing them together checks all of them | 298 | We first check for red and blue components (5bit range). */ |
284 | simultaneously. */ | 299 | if ((red1 | blue1 | red2 | blue2) & ~MAX_5BIT) |
285 | if (((unsigned)(red1 | green1 | blue1 | | 300 | { |
286 | red2 | green2 | blue2)) > (RYFAC*255+ROUNDOFFS)) { | 301 | if (red1 & ~MAX_5BIT) |
287 | if (((unsigned)(red1 | green1 | blue1)) > | 302 | red1 = (red1 >> 31) ? 0 : MAX_5BIT; |
288 | (RYFAC*255+ROUNDOFFS)) { | 303 | if (blue1 & ~MAX_5BIT) |
289 | if ((unsigned)red1 > (RYFAC*255+ROUNDOFFS)) | 304 | blue1 = (blue1 >> 31) ? 0 : MAX_5BIT; |
290 | { | 305 | if (red2 & ~MAX_5BIT) |
291 | if (red1 < 0) | 306 | red2 = (red2 >> 31) ? 0 : MAX_5BIT; |
292 | red1 = 0; | 307 | if (blue2 & ~MAX_5BIT) |
293 | else | 308 | blue2 = (blue2 >> 31) ? 0 : MAX_5BIT; |
294 | red1 = (RYFAC*255+ROUNDOFFS); | 309 | } |
295 | } | 310 | /* We second check for green component (6bit range) */ |
296 | if ((unsigned)green1 > (GYFAC*255+ROUNDOFFSG)) | 311 | if ((green1 | green2) & ~MAX_6BIT) |
297 | { | 312 | { |
298 | if (green1 < 0) | 313 | if (green1 & ~MAX_6BIT) |
299 | green1 = 0; | 314 | green1 = (green1 >> 31) ? 0 : MAX_6BIT; |
300 | else | 315 | if (green2 & ~MAX_6BIT) |
301 | green1 = (GYFAC*255+ROUNDOFFSG); | 316 | green2 = (green2 >> 31) ? 0 : MAX_6BIT; |
302 | } | ||
303 | if ((unsigned)blue1 > (BYFAC*255+ROUNDOFFS)) | ||
304 | { | ||
305 | if (blue1 < 0) | ||
306 | blue1 = 0; | ||
307 | else | ||
308 | blue1 = (BYFAC*255+ROUNDOFFS); | ||
309 | } | ||
310 | } | ||
311 | |||
312 | if (((unsigned)(red2 | green2 | blue2)) > | ||
313 | (RYFAC*255+ROUNDOFFS)) { | ||
314 | if ((unsigned)red2 > (RYFAC*255+ROUNDOFFS)) | ||
315 | { | ||
316 | if (red2 < 0) | ||
317 | red2 = 0; | ||
318 | else | ||
319 | red2 = (RYFAC*255+ROUNDOFFS); | ||
320 | } | ||
321 | if ((unsigned)green2 > (GYFAC*255+ROUNDOFFSG)) | ||
322 | { | ||
323 | if (green2 < 0) | ||
324 | green2 = 0; | ||
325 | else | ||
326 | green2 = (GYFAC*255+ROUNDOFFSG); | ||
327 | } | ||
328 | if ((unsigned)blue2 > (BYFAC*255+ROUNDOFFS)) | ||
329 | { | ||
330 | if (blue2 < 0) | ||
331 | blue2 = 0; | ||
332 | else | ||
333 | blue2 = (BYFAC*255+ROUNDOFFS); | ||
334 | } | ||
335 | } | ||
336 | } | 317 | } |
337 | |||
338 | rbits = red1 >> 16 ; | ||
339 | gbits = green1 >> 15 ; | ||
340 | bbits = blue1 >> 16 ; | ||
341 | 318 | ||
342 | pixel1 = swap16((rbits << 11) | (gbits << 5) | bbits); | 319 | pixel1 = swap16((red1 << 11) | (green1 << 5) | blue1); |
343 | 320 | ||
344 | rbits = red2 >> 16 ; | 321 | pixel2 = swap16((red2 << 11) | (green2 << 5) | blue2); |
345 | gbits = green2 >> 15 ; | ||
346 | bbits = blue2 >> 16 ; | ||
347 | pixel2 = swap16((rbits << 11) | (gbits << 5) | bbits); | ||
348 | 322 | ||
349 | while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_TXOK)); | 323 | while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_TXOK)); |
350 | 324 | ||
diff --git a/firmware/target/arm/ipod/video/lcd-video.c b/firmware/target/arm/ipod/video/lcd-video.c index 27f31c3511..7ec453760e 100644 --- a/firmware/target/arm/ipod/video/lcd-video.c +++ b/firmware/target/arm/ipod/video/lcd-video.c | |||
@@ -135,14 +135,16 @@ void lcd_update_rect(int x, int y, int width, int height) | |||
135 | } | 135 | } |
136 | } | 136 | } |
137 | 137 | ||
138 | if (finishup_needed) { | 138 | if (finishup_needed) |
139 | unsigned int data; | 139 | { |
140 | /* Bottom-half of original lcd_bcm_finishup() function */ | 140 | /* Bottom-half of original lcd_bcm_finishup() function */ |
141 | do { | 141 | unsigned int data = lcd_bcm_read32(0x1F8); |
142 | /* This function takes about 14ms to execute - so we yield() */ | 142 | while (data == 0xFFFA0005 || data == 0xFFFF) |
143 | { | ||
144 | /* This loop can wait for up to 14ms - so we yield() */ | ||
143 | yield(); | 145 | yield(); |
144 | data = lcd_bcm_read32(0x1F8); | 146 | data = lcd_bcm_read32(0x1F8); |
145 | } while (data == 0xFFFA0005 || data == 0xFFFF); | 147 | } |
146 | } | 148 | } |
147 | 149 | ||
148 | lcd_bcm_read32(0x1FC); | 150 | lcd_bcm_read32(0x1FC); |
@@ -236,15 +238,19 @@ void lcd_update(void) | |||
236 | /* Performance function to blit a YUV bitmap directly to the LCD */ | 238 | /* Performance function to blit a YUV bitmap directly to the LCD */ |
237 | void lcd_yuv_blit(unsigned char * const src[3], | 239 | void lcd_yuv_blit(unsigned char * const src[3], |
238 | int src_x, int src_y, int stride, | 240 | int src_x, int src_y, int stride, |
241 | int x, int y, int width, int height) ICODE_ATTR; | ||
242 | void lcd_yuv_blit(unsigned char * const src[3], | ||
243 | int src_x, int src_y, int stride, | ||
239 | int x, int y, int width, int height) | 244 | int x, int y, int width, int height) |
240 | { | 245 | { |
241 | width = (width + 1) & ~1; | 246 | width = (width + 1) & ~1; |
242 | 247 | ||
243 | if (finishup_needed) { | 248 | if (finishup_needed) |
244 | unsigned int data; | 249 | { |
245 | /* Bottom-half of original lcd_bcm_finishup() function */ | 250 | /* Bottom-half of original lcd_bcm_finishup() function */ |
246 | data = lcd_bcm_read32(0x1F8); | 251 | unsigned int data = lcd_bcm_read32(0x1F8); |
247 | while (data == 0xFFFA0005 || data == 0xFFFF) { | 252 | while (data == 0xFFFA0005 || data == 0xFFFF) |
253 | { | ||
248 | /* This loop can wait for up to 14ms - so we yield() */ | 254 | /* This loop can wait for up to 14ms - so we yield() */ |
249 | yield(); | 255 | yield(); |
250 | data = lcd_bcm_read32(0x1F8); | 256 | data = lcd_bcm_read32(0x1F8); |
@@ -321,28 +327,22 @@ void lcd_yuv_blit(unsigned char * const src[3], | |||
321 | We first check for red and blue components (5bit range). */ | 327 | We first check for red and blue components (5bit range). */ |
322 | if ((red1 | blue1 | red2 | blue2) & ~MAX_5BIT) | 328 | if ((red1 | blue1 | red2 | blue2) & ~MAX_5BIT) |
323 | { | 329 | { |
324 | if ((red1 | blue1) & ~MAX_5BIT) | 330 | if (red1 & ~MAX_5BIT) |
325 | { | 331 | red1 = (red1 >> 31) ? 0 : MAX_5BIT; |
326 | if (red1 & ~MAX_5BIT) | 332 | if (blue1 & ~MAX_5BIT) |
327 | red1 = (red1 >> 31) ? 0 : MAX_5BIT; | 333 | blue1 = (blue1 >> 31) ? 0 : MAX_5BIT; |
328 | if (blue1 & ~MAX_5BIT) | 334 | if (red2 & ~MAX_5BIT) |
329 | blue1 = (blue1 >> 31) ? 0 : MAX_5BIT; | 335 | red2 = (red2 >> 31) ? 0 : MAX_5BIT; |
330 | } | 336 | if (blue2 & ~MAX_5BIT) |
331 | if ((red2 | blue2) & ~MAX_5BIT) | 337 | blue2 = (blue2 >> 31) ? 0 : MAX_5BIT; |
332 | { | ||
333 | if (red2 & ~MAX_5BIT) | ||
334 | red2 = (red2 >> 31) ? 0 : MAX_5BIT; | ||
335 | if (blue2 & ~MAX_5BIT) | ||
336 | blue2 = (blue2 >> 31) ? 0 : MAX_5BIT; | ||
337 | } | ||
338 | } | 338 | } |
339 | /* We second check for green component (6bit range) */ | 339 | /* We second check for green component (6bit range) */ |
340 | if ((green1 | green2) & ~MAX_6BIT) | 340 | if ((green1 | green2) & ~MAX_6BIT) |
341 | { | 341 | { |
342 | if (green1 & ~MAX_6BIT) | 342 | if (green1 & ~MAX_6BIT) |
343 | green1 = (green1 >> 31) ? 0 : MAX_6BIT; | 343 | green1 = (green1 >> 31) ? 0 : MAX_6BIT; |
344 | if (green2 & ~MAX_6BIT) | 344 | if (green2 & ~MAX_6BIT) |
345 | green2 = (green2 >> 31) ? 0 : MAX_6BIT; | 345 | green2 = (green2 >> 31) ? 0 : MAX_6BIT; |
346 | } | 346 | } |
347 | 347 | ||
348 | /* pixel1 */ | 348 | /* pixel1 */ |