diff options
Diffstat (limited to 'apps/plugins')
-rw-r--r-- | apps/plugins/pictureflow.c | 71 |
1 files changed, 63 insertions, 8 deletions
diff --git a/apps/plugins/pictureflow.c b/apps/plugins/pictureflow.c index 665ef9576f..025d1e6be2 100644 --- a/apps/plugins/pictureflow.c +++ b/apps/plugins/pictureflow.c | |||
@@ -337,17 +337,73 @@ static inline PFreal fmul(PFreal a, PFreal b) | |||
337 | return (a*b) >> PFREAL_SHIFT; | 337 | return (a*b) >> PFREAL_SHIFT; |
338 | } | 338 | } |
339 | 339 | ||
340 | /* There are some precision issues when not using (long long) which in turn | 340 | /* ARMv5+ have a clz instruction. So do most modern desktop processors, and the |
341 | takes very long to compute... I guess the best solution would be to optimize | 341 | * simulator doesn't need to be as concerned about savings for inlining a calls |
342 | the computations so it only requires a single long */ | 342 | * to a clz function. |
343 | static inline PFreal fdiv(PFreal num, PFreal den) | 343 | */ |
344 | #if defined(SIMULATOR) || (defined(CPU_ARM) && (ARM_ARCH > 4)) | ||
345 | static inline int clz(uint32_t v) | ||
344 | { | 346 | { |
345 | long long p = (long long) (num) << (PFREAL_SHIFT * 2); | 347 | return __builtin_clz(v); |
346 | long long q = p / (long long) den; | 348 | } |
347 | long long r = q >> PFREAL_SHIFT; | ||
348 | 349 | ||
350 | /* Otherwise, use our clz, which can be inlined */ | ||
351 | #else | ||
352 | /* This clz is based on the log2(n) implementation at | ||
353 | * http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog | ||
354 | */ | ||
355 | static inline int clz(uint32_t v) | ||
356 | { | ||
357 | uint32_t r = 31; | ||
358 | if (v > 0x8000) | ||
359 | { | ||
360 | v >>= 16; | ||
361 | r -= 16; | ||
362 | } | ||
363 | if (v & 0xff00) | ||
364 | { | ||
365 | v >>= 8; | ||
366 | r -= 8; | ||
367 | } | ||
368 | if (v & 0xf0) | ||
369 | { | ||
370 | v >>= 4; | ||
371 | r -= 4; | ||
372 | } | ||
373 | if (v & 0xc) | ||
374 | { | ||
375 | v >>= 2; | ||
376 | r -= 2; | ||
377 | } | ||
378 | if (v & 2) | ||
379 | r -= 1; | ||
349 | return r; | 380 | return r; |
350 | } | 381 | } |
382 | #endif | ||
383 | |||
384 | /* Return the maximum possible left shift for a signed int32, without | ||
385 | * overflow | ||
386 | */ | ||
387 | static inline int allowed_shift(int32_t val) | ||
388 | { | ||
389 | uint32_t uval = val ^ (val >> 31); | ||
390 | if (!uval) | ||
391 | return 31; | ||
392 | else | ||
393 | return clz(uval) - 1; | ||
394 | } | ||
395 | |||
396 | /* Calculate num/den, with the result shifted left by PFREAL_SHIFT, by shifting | ||
397 | * num and den before dividing. | ||
398 | */ | ||
399 | static inline PFreal fdiv(PFreal num, PFreal den) | ||
400 | { | ||
401 | int shift = allowed_shift(num); | ||
402 | shift = MIN(PFREAL_SHIFT, shift); | ||
403 | num <<= shift; | ||
404 | den >>= PFREAL_SHIFT - shift; | ||
405 | return num / den; | ||
406 | } | ||
351 | 407 | ||
352 | #define fmin(a,b) (((a) < (b)) ? (a) : (b)) | 408 | #define fmin(a,b) (((a) < (b)) ? (a) : (b)) |
353 | #define fmax(a,b) (((a) > (b)) ? (a) : (b)) | 409 | #define fmax(a,b) (((a) > (b)) ? (a) : (b)) |
@@ -579,7 +635,6 @@ int create_track_index(const int slide_index) | |||
579 | return (track_count > 0) ? 0 : -1; | 635 | return (track_count > 0) ? 0 : -1; |
580 | } | 636 | } |
581 | 637 | ||
582 | |||
583 | /** | 638 | /** |
584 | Determine filename of the album art for the given slide_index and | 639 | Determine filename of the album art for the given slide_index and |
585 | store the result in buf. | 640 | store the result in buf. |