aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-01-18 16:38:40 +0000
committerGravatar robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-01-18 16:38:40 +0000
commit8b8bf4d12ecf8fb340a1362c91a8a57395dd31a3 (patch)
treece457e2cde808ff0867d0b9a9ae0ce44bfedd3b0
parent98d97fc0bb40005549503c756db86ff572f159f3 (diff)
Added shaderproc for 1xN repeatX/repeatY BitmapProcShader
-rw-r--r--src/core/SkBitmapProcState.cpp126
-rw-r--r--src/core/SkBitmapProcState_filter.h44
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);
+}