From 2215e0cb51b1783cce07d8b590ca9015d8f4a8b0 Mon Sep 17 00:00:00 2001 From: Eric Culp Date: Sat, 16 Jun 2012 16:51:53 -0400 Subject: GRAPHICS: Add 32bit versions of interpolate* functions --- graphics/colormasks.h | 29 ++++++-- graphics/scaler/intern.h | 170 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 195 insertions(+), 4 deletions(-) diff --git a/graphics/colormasks.h b/graphics/colormasks.h index eebfc13213..4ad31a858a 100644 --- a/graphics/colormasks.h +++ b/graphics/colormasks.h @@ -59,8 +59,8 @@ The meaning of these is masks is the following: To be specific: They pack the masks for two 16 bit pixels at once. The pixels are split into "high" and "low" bits, which are then separately interpolated and finally re-composed. That way, 2x2 pixels or even 4x2 pixels can - be interpolated in one go. - + be interpolated in one go. They are also included in 888 and 8888 to make + the same functions compatible when interpolating 2 32-bit pixels. */ @@ -239,7 +239,18 @@ struct ColorMasks<888> { kGreenMask = ((1 << kGreenBits) - 1) << kGreenShift, kBlueMask = ((1 << kBlueBits) - 1) << kBlueShift, - kRedBlueMask = kRedMask | kBlueMask + kRedBlueMask = kRedMask | kBlueMask, + + kLowBits = (1 << kRedShift) | (1 << kGreenShift) | (1 << kBlueShift), + kLow2Bits = (3 << kRedShift) | (3 << kGreenShift) | (3 << kBlueShift), + kLow3Bits = (7 << kRedShift) | (7 << kGreenShift) | (7 << kBlueShift), + kLow4Bits = (15 << kRedShift) | (15 << kGreenShift) | (15 << kBlueShift), + + kLowBitsMask = kLowBits, + // Prevent mask from including padding byte + kHighBitsMask = (~kLowBits) & (kRedMask | kBlueMask | kGreenMask), + qLowBitsMask = kLow2Bits, + qHighBitsMask = (~kLowBits) & (kRedMask | kBlueMask | kGreenMask) }; }; @@ -263,7 +274,17 @@ struct ColorMasks<8888> { kGreenMask = ((1 << kGreenBits) - 1) << kGreenShift, kBlueMask = ((1 << kBlueBits) - 1) << kBlueShift, - kRedBlueMask = kRedMask | kBlueMask + kRedBlueMask = kRedMask | kBlueMask, + + kLowBits = (1 << kRedShift) | (1 << kGreenShift) | (1 << kBlueShift) | (1 << kAlphaShift), + kLow2Bits = (3 << kRedShift) | (3 << kGreenShift) | (3 << kBlueShift) | (3 << kAlphaShift), + kLow3Bits = (7 << kRedShift) | (7 << kGreenShift) | (7 << kBlueShift) | (7 << kAlphaShift), + kLow4Bits = (15 << kRedShift) | (15 << kGreenShift) | (15 << kBlueShift) | (15 << kAlphaShift), + + kLowBitsMask = kLowBits, + kHighBitsMask = ~kLowBits, + qLowBitsMask = kLow2Bits, + qHighBitsMask = ~kLow2Bits }; }; diff --git a/graphics/scaler/intern.h b/graphics/scaler/intern.h index 213b69b049..8ec7249263 100644 --- a/graphics/scaler/intern.h +++ b/graphics/scaler/intern.h @@ -31,9 +31,15 @@ * Interpolate two 16 bit pixel *pairs* at once with equal weights 1. * In particular, p1 and p2 can contain two pixels each in the upper * and lower halves. + * + * This also works for 32 bit pixels. */ template static inline uint32 interpolate32_1_1(uint32 p1, uint32 p2) { + // Clear the low bit of each channel, + // divide each channel by 2, + // add the two pixels together, + // add 1 to each channel if the lowbits would have added to 2 return (((p1 & ColorMask::kHighBitsMask) >> 1) + ((p2 & ColorMask::kHighBitsMask) >> 1) + (p1 & p2 & ColorMask::kLowBitsMask)); @@ -43,16 +49,180 @@ static inline uint32 interpolate32_1_1(uint32 p1, uint32 p2) { * Interpolate two 16 bit pixel *pairs* at once with weights 3 resp. 1. * In particular, p1 and p2 can contain two pixels/each in the upper * and lower halves. + * + * This also works for 32 bit pixels. */ template static inline uint32 interpolate32_3_1(uint32 p1, uint32 p2) { + // Clear the 2 lowest bits of each channel, + // divide each channel by 4, multiply p1 by 3 + // add the two pixels together, uint32 x = ((p1 & ColorMask::qhighBits) >> 2) * 3 + ((p2 & ColorMask::qhighBits) >> 2); + // Get 2 lowest bits of each channel, + // multiply p1 by 3, add them together, then divide by 4 uint32 y = ((p1 & ColorMask::qlowBits) * 3 + (p2 & ColorMask::qlowBits)) >> 2; + // Use only the low bits of the second result to add to the first result y &= ColorMask::qlowBits; return x + y; } +/** + * Interpolate two 32 bit pixels with weights 5 and 3 and 1, i.e., (5*p1+3*p2)/8. + * @see interpolate_32_3_1 for similar method + */ +template +static inline uint32 interpolate32_5_3(uint32 p1, uint32 p2) { + uint32 x = ((p1 & ~ColorMask::kLow3Bits) >> 3) * 5 + ((p2 & ~ColorMask::kLow3Bits) >> 3) * 3; + uint32 y = ((p1 & ColorMask::kLow3Bits) * 5 + (p2 & ColorMask::kLow3Bits) * 3) >> 3; + + y &= ColorMask::kLow3Bits; + return x + y; +} + +/** + * Interpolate two 32 bit pixels with weights 7 and 1, i.e., (7*p1+p2)/8. + * + * @see interpolate32_3_1 for similar method + */ +template +static inline uint32 interpolate32_7_1(uint32 p1, uint32 p2) { + uint32 x = ((p1 & ~ColorMask::kLow3Bits) >> 3) * 7 + ((p2 & ~ColorMask::kLow3Bits) >> 3); + uint32 y = ((p1 & ColorMask::kLow3Bits) * 7 + (p2 & ColorMask::kLow3Bits)) >> 3; + + y &= ColorMask::kLow3Bits; + return x + y; +} + +/** + * Interpolate three 32 bit pixels with weights 2, 1, and 1, i.e., (2*p1+p2+p3)/4. + * + * @see interpolate32_3_1 for similar method + */ +template +static inline uint32 interpolate32_2_1_1(uint32 p1, uint32 p2, uint32 p3) { + uint32 x = ((p1 & ColorMask::qHighBitsMask) >> 1) + + ((p2 & ColorMask::qHighBitsMask) >> 2) + + ((p3 & ColorMask::qHighBitsMask) >> 2); + uint32 y = ((p1 & ColorMask::qLowBitsMask) << 1) + + (p2 & ColorMask::qLowBitsMask) + + (p2 & ColorMask::qLowBitsMask); + y >>= 2; + y &= ColorMask::qLowBits; + return x + y; +} + +/** + * Interpolate three 32 bit pixels with weights 5, 2, and 1, i.e., (5*p1+2*p2+p3)/8. + * + * @see interpolate32_3_1 for similar method + */ +template +static inline uint32 interpolate32_5_2_1(uint32 p1, uint32 p2, uint32 p3) { + uint32 x = ((p1 & ~ColorMask::kLow3Bits) >> 3) * 5 + + ((p2 & ~ColorMask::kLow3Bits) >> 3) * 2 + + ((p3 & ~ColorMask::kLow3Bits) >> 3); + uint32 y = (p1 & ColorMask::kLow3Bits) * 5 + + (p2 & ColorMask::kLow3Bits) * 2 + + (p2 & ColorMask::kLow3Bits); + y >>= 3; + y &= ColorMask::kLow3Bits; + return x + y; +} + +/** + * Interpolate three 32 bit pixels with weights 6, 1, and 1, i.e., (6*p1+p2+p3)/8. + * + * @see interpolate32_3_1 for similar method + */ +template +static inline uint32 interpolate32_6_1_1(uint32 p1, uint32 p2, uint32 p3) { + uint32 x = ((p1 & ~ColorMask::kLow3Bits) >> 3) * 6 + + ((p2 & ~ColorMask::kLow3Bits) >> 3) + + ((p3 & ~ColorMask::kLow3Bits) >> 3); + uint32 y = (p1 & ColorMask::kLow3Bits) * 6 + + (p2 & ColorMask::kLow3Bits) + + (p2 & ColorMask::kLow3Bits); + y >>= 3; + y &= ColorMask::kLow3Bits; + return x + y; +} + +/** + * Interpolate three 32 bit pixels with weights 2, 3, and 3, i.e., (2*p1+3*(p2+p3))/8. + * + * @see interpolate32_3_1 for similar method + */ +template +static inline uint32 interpolate32_2_3_3(uint32 p1, uint32 p2, uint32 p3) { + uint32 x = ((p1 & ~ColorMask::kLow3Bits) >> 2) + + (((p2 & ~ColorMask::kLow3Bits) >> 3) + + ((p3 & ~ColorMask::kLow3Bits) >> 3)) * 3; + uint32 y = (p1 & ColorMask::kLow3Bits) * 2 + + ((p2 & ColorMask::kLow3Bits) + + (p2 & ColorMask::kLow3Bits)) * 3; + y >>= 3; + y &= ColorMask::kLow3Bits; + return x + y; +} + +/** + * Interpolate three 32 bit pixels with weights 2, 7, and 7, i.e., (2*p1+7*(p2+p3))/16. + * + * @see interpolate32_3_1 for similar method + */ +template +static inline uint32 interpolate32_2_7_7(uint32 p1, uint32 p2, uint32 p3) { + uint32 x = ((p1 & ~ColorMask::kLow4Bits) >> 3) + + (((p2 & ~ColorMask::kLow4Bits) >> 4) + + ((p3 & ~ColorMask::kLow4Bits) >> 4)) * 7; + uint32 y = (p1 & ColorMask::kLow4Bits) * 2 + + ((p2 & ColorMask::kLow4Bits) + + (p2 & ColorMask::kLow4Bits)) * 7; + y >>= 4; + y &= ColorMask::kLow4Bits; + return x + y; +} + +/** + * Interpolate three 32 bit pixels with weights 14, 1, and 1, i.e., (14*p1+p2+p3)/16. + * + * @see interpolate32_3_1 for similar method + */ +template +static inline uint32 interpolate32_14_1_1(uint32 p1, uint32 p2, uint32 p3) { + uint32 x = ((p1 & ~ColorMask::kLow4Bits) >> 4) * 14 + + ((p2 & ~ColorMask::kLow4Bits) >> 4) + + ((p3 & ~ColorMask::kLow4Bits) >> 4); + uint32 y = (p1 & ColorMask::kLow4Bits) * 14; + + (p2 & ColorMask::kLow4Bits) + + (p2 & ColorMask::kLow4Bits); + y >>= 4; + y &= ColorMask::kLow4Bits; + return x + y; +} + +/** + * Interpolate four 32 bit pixels with weights 1, 1, 1, and 1, i.e., (p1+p2+p3+p4)/4. + * + * @see interpolate32_3_1 for similar method + */ +template +static inline uint32 interpolate32_1_1_1_1(uint32 p1, uint32 p2, uint32 p3, uint32 p4) { + uint32 x = ((p1 & ~ColorMask::kLow2Bits) >> 2) + + ((p2 & ~ColorMask::kLow2Bits) >> 2) + + ((p3 & ~ColorMask::kLow2Bits) >> 2) + + ((p4 & ~ColorMask::kLow2Bits) >> 2); + uint32 y = (p1 & ColorMask::kLow2Bits) + + (p2 & ColorMask::kLow2Bits) + + (p3 & ColorMask::kLow2Bits) + + (p4 & ColorMask::kLow2Bits); + y >>= 2; + y &= ColorMask::kLow2Bits; + return x + y; +} + + /** * Interpolate two 16 bit pixels with weights 1 and 1, i.e., (p1+p2)/2. * See for details on how this works. -- cgit v1.2.3