diff options
author | 2013-01-18 16:38:40 +0000 | |
---|---|---|
committer | 2013-01-18 16:38:40 +0000 | |
commit | 8b8bf4d12ecf8fb340a1362c91a8a57395dd31a3 (patch) | |
tree | ce457e2cde808ff0867d0b9a9ae0ce44bfedd3b0 | |
parent | 98d97fc0bb40005549503c756db86ff572f159f3 (diff) |
Added shaderproc for 1xN repeatX/repeatY BitmapProcShader
https://codereview.appspot.com/7063054/
git-svn-id: http://skia.googlecode.com/svn/trunk@7273 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r-- | src/core/SkBitmapProcState.cpp | 126 | ||||
-rw-r--r-- | src/core/SkBitmapProcState_filter.h | 44 |
2 files changed, 165 insertions, 5 deletions
diff --git a/src/core/SkBitmapProcState.cpp b/src/core/SkBitmapProcState.cpp index ea09c5d364..79dcc9a1c0 100644 --- a/src/core/SkBitmapProcState.cpp +++ b/src/core/SkBitmapProcState.cpp @@ -91,7 +91,7 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { const SkMatrix* m; bool trivial_matrix = (inv.getType() & ~SkMatrix::kTranslate_Mask) == 0; bool clamp_clamp = SkShader::kClamp_TileMode == fTileModeX && - SkShader::kClamp_TileMode == fTileModeY; + SkShader::kClamp_TileMode == fTileModeY; if (clamp_clamp || trivial_matrix) { m = &inv; @@ -255,7 +255,7 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { S4444_opaque_D32_filter_DX, S4444_alpha_D32_filter_DX, - // A8 treats alpha/opauqe the same (equally efficient) + // A8 treats alpha/opaque the same (equally efficient) SA8_alpha_D32_nofilter_DXDY, SA8_alpha_D32_nofilter_DXDY, SA8_alpha_D32_nofilter_DX, @@ -380,6 +380,14 @@ static inline int sk_int_mod(int x, int n) { return x; } +static inline int sk_int_mirror(int x, int n) { + x = sk_int_mod(x, 2 * n); + if (x >= n) { + x = n + ~(x - n); + } + return x; +} + static void Repeat_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s, int x, int y, SkPMColor* SK_RESTRICT colors, @@ -420,6 +428,103 @@ static void Repeat_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s, } } +static void S32_D32_constX_shaderproc(const SkBitmapProcState& s, + int x, int y, + SkPMColor* SK_RESTRICT colors, + int count) { + SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) == 0); + SkASSERT(s.fInvKy == 0); + SkASSERT(count > 0 && colors != NULL); + SkASSERT(1 == s.fBitmap->width()); + + int iY0, iY1, iSubY; + + if (s.fDoFilter) { + SkBitmapProcState::MatrixProc mproc = s.getMatrixProc(); + uint32_t xy[2]; + + mproc(s, xy, 1, x, y); + + iY0 = xy[0] >> 18; + iY1 = xy[0] & 0x3FFF; + iSubY = (xy[0] >> 14) & 0xF; + } else { + int yTemp; + + if (s.fInvType > SkMatrix::kTranslate_Mask) { + SkPoint pt; + s.fInvProc(*s.fInvMatrix, + SkIntToScalar(x) + SK_ScalarHalf, + SkIntToScalar(y) + SK_ScalarHalf, + &pt); + yTemp = SkScalarFloorToInt(pt.fY); + } else { + yTemp = s.fFilterOneY + y; + } + + const int stopY = s.fBitmap->height(); + switch (s.fTileModeY) { + case SkShader::kClamp_TileMode: + iY0 = SkClampMax(yTemp, stopY-1); + break; + case SkShader::kRepeat_TileMode: + iY0 = sk_int_mod(yTemp, stopY); + break; + case SkShader::kMirror_TileMode: + default: + iY0 = sk_int_mirror(yTemp, stopY); + break; + } + +#ifdef SK_DEBUG + { + SkPoint pt; + s.fInvProc(*s.fInvMatrix, + SkIntToScalar(x) + SK_ScalarHalf, + SkIntToScalar(y) + SK_ScalarHalf, + &pt); + int iY2; + + switch (s.fTileModeY) { + case SkShader::kClamp_TileMode: + iY2 = SkClampMax(SkScalarFloorToInt(pt.fY), stopY-1); + break; + case SkShader::kRepeat_TileMode: + iY2 = sk_int_mod(SkScalarFloorToInt(pt.fY), stopY); + break; + case SkShader::kMirror_TileMode: + default: + iY2 = sk_int_mirror(SkScalarFloorToInt(pt.fY), stopY); + break; + } + + SkASSERT(iY0 == iY2); + } +#endif + } + + const SkPMColor* row0 = s.fBitmap->getAddr32(0, iY0); + SkPMColor color; + + if (s.fDoFilter) { + const SkPMColor* row1 = s.fBitmap->getAddr32(0, iY1); + + if (s.fAlphaScale < 256) { + Filter_32_alpha(iSubY, *row0, *row1, &color, s.fAlphaScale); + } else { + Filter_32_opaque(iSubY, *row0, *row1, &color); + } + } else { + if (s.fAlphaScale < 256) { + color = SkAlphaMulQ(*row0, s.fAlphaScale); + } else { + color = *row0; + } + } + + sk_memset32(colors, color, count); +} + static void DoNothing_shaderproc(const SkBitmapProcState&, int x, int y, SkPMColor* SK_RESTRICT colors, int count) { // if we get called, the matrix is too tricky, so we just draw nothing @@ -449,6 +554,20 @@ bool SkBitmapProcState::setupForTranslate() { } SkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() { + + if (SkBitmap::kARGB_8888_Config != fBitmap->config()) { + return NULL; + } + + static const unsigned kMask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; + + if (1 == fBitmap->width() && 0 == (fInvType & ~kMask)) { + if (!fDoFilter && fInvType <= SkMatrix::kTranslate_Mask && !this->setupForTranslate()) { + return DoNothing_shaderproc; + } + return S32_D32_constX_shaderproc; + } + if (fAlphaScale < 256) { return NULL; } @@ -458,9 +577,6 @@ SkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() { if (fDoFilter) { return NULL; } - if (SkBitmap::kARGB_8888_Config != fBitmap->config()) { - return NULL; - } SkShader::TileMode tx = (SkShader::TileMode)fTileModeX; SkShader::TileMode ty = (SkShader::TileMode)fTileModeY; diff --git a/src/core/SkBitmapProcState_filter.h b/src/core/SkBitmapProcState_filter.h index f7848f7812..12606656dd 100644 --- a/src/core/SkBitmapProcState_filter.h +++ b/src/core/SkBitmapProcState_filter.h @@ -79,3 +79,47 @@ static inline void Filter_32_alpha(unsigned x, unsigned y, *dstColor = ((lo >> 8) & mask) | (hi & ~mask); } +// Two color version, where we filter only along 1 axis +static inline void Filter_32_opaque(unsigned t, + SkPMColor color0, + SkPMColor color1, + SkPMColor* dstColor) { + SkASSERT((unsigned)t <= 0xF); + + static const uint32_t mask = gMask_00FF00FF; //0x00FF00FF; + + int scale = 256 - 16*t; + uint32_t lo = (color0 & mask) * scale; + uint32_t hi = ((color0 >> 8) & mask) * scale; + + scale = 16*t; + lo += (color1 & mask) * scale; + hi += ((color1 >> 8) & mask) * scale; + + *dstColor = ((lo >> 8) & mask) | (hi & ~mask); +} + +// Two color version, where we filter only along 1 axis +static inline void Filter_32_alpha(unsigned t, + SkPMColor color0, + SkPMColor color1, + SkPMColor* dstColor, + unsigned alphaScale) { + SkASSERT((unsigned)t <= 0xF); + SkASSERT(alphaScale <= 256); + + static const uint32_t mask = gMask_00FF00FF; //0x00FF00FF; + + int scale = 256 - 16*t; + uint32_t lo = (color0 & mask) * scale; + uint32_t hi = ((color0 >> 8) & mask) * scale; + + scale = 16*t; + lo += (color1 & mask) * scale; + hi += ((color1 >> 8) & mask) * scale; + + lo = ((lo >> 8) & mask) * alphaScale; + hi = ((hi >> 8) & mask) * alphaScale; + + *dstColor = ((lo >> 8) & mask) | (hi & ~mask); +} |