summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThom Johansen <thomj@rockbox.org>2007-10-16 19:47:15 +0000
committerThom Johansen <thomj@rockbox.org>2007-10-16 19:47:15 +0000
commitb5f779b2efbefae67c876727b297575e03d5c8a2 (patch)
tree5473f8d869c11812af6d2d24b3ac56909ca99bb1
parent3688e94083cb4b94728faa9cc242492a354d8394 (diff)
downloadrockbox-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
-rw-r--r--firmware/target/arm/ipod/lcd-color_nano.c160
-rw-r--r--firmware/target/arm/ipod/video/lcd-video.c54
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 */
149void lcd_yuv_blit(unsigned char * const src[3], 166void 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 */
237void lcd_yuv_blit(unsigned char * const src[3], 239void 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;
242void 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 */