aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-07-22 17:18:18 +0000
committerGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-07-22 17:18:18 +0000
commit9cfc83cc8ac2ee50a7ce889e65a707941f48bdea (patch)
tree879cd1f934857a2f296d5fe9c5dbf190af1f40af /src/core
parent35f02fb9c9f548656e1cb2cc66d3ed20006384f8 (diff)
stop using bitmap-filter flags outside of paint itself, as a step towards really changing them into an enum
BUG= Review URL: https://codereview.chromium.org/19825002 git-svn-id: http://skia.googlecode.com/svn/trunk@10240 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/core')
-rw-r--r--src/core/SkBitmapFilter.cpp2
-rw-r--r--src/core/SkBitmapProcState.cpp152
-rw-r--r--src/core/SkBitmapProcState.h7
-rw-r--r--src/core/SkBitmapProcState_matrixProcs.cpp4
-rw-r--r--src/core/SkBitmapProcState_sample.h8
-rw-r--r--src/core/SkBitmapProcState_shaderproc.h2
6 files changed, 97 insertions, 78 deletions
diff --git a/src/core/SkBitmapFilter.cpp b/src/core/SkBitmapFilter.cpp
index 060400944f..c2f68d4879 100644
--- a/src/core/SkBitmapFilter.cpp
+++ b/src/core/SkBitmapFilter.cpp
@@ -101,7 +101,7 @@ SkBitmapFilter *SkBitmapFilter::Allocate() {
SkBitmapProcState::ShaderProc32
SkBitmapProcState::chooseBitmapFilterProc() {
- if (fFilterQuality != kHQ_BitmapFilter) {
+ if (fFilterLevel != SkPaint::kHigh_FilterLevel) {
return NULL;
}
diff --git a/src/core/SkBitmapProcState.cpp b/src/core/SkBitmapProcState.cpp
index ebb010fd0a..2298398bd5 100644
--- a/src/core/SkBitmapProcState.cpp
+++ b/src/core/SkBitmapProcState.cpp
@@ -91,13 +91,26 @@ static bool valid_for_filtering(unsigned dimension) {
return (dimension & ~0x3FFF) == 0;
}
+static bool effective_matrix_scale_sqrd(const SkMatrix& mat) {
+ SkPoint v1, v2;
+
+ v1.fX = mat.getScaleX();
+ v1.fY = mat.getSkewY();
+
+ v2.fX = mat.getSkewX();
+ v2.fY = mat.getScaleY();
+
+ return SkMaxScalar(v1.lengthSqd(), v2.lengthSqd());
+}
+
// TODO -- we may want to pass the clip into this function so we only scale
// the portion of the image that we're going to need. This will complicate
// the interface to the cache, but might be well worth it.
void SkBitmapProcState::possiblyScaleImage() {
- if (fFilterQuality != kHQ_BitmapFilter) {
+ if (fFilterLevel <= SkPaint::kLow_FilterLevel) {
+ // none or low (bilerp) does not need to look any further
return;
}
@@ -125,7 +138,7 @@ void SkBitmapProcState::possiblyScaleImage() {
// doing high quality scaling. If so, do the bitmap scale here and
// remove the scaling component from the matrix.
- if (fFilterQuality == kHQ_BitmapFilter &&
+ if (SkPaint::kHigh_FilterLevel == fFilterLevel &&
fInvMatrix.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask) &&
fOrigBitmap.config() == SkBitmap::kARGB_8888_Config) {
@@ -148,55 +161,73 @@ void SkBitmapProcState::possiblyScaleImage() {
// no need for any further filtering; we just did it!
- fFilterQuality = kNone_BitmapFilter;
+ fFilterLevel = SkPaint::kNone_FilterLevel;
return;
}
- if (!fOrigBitmap.hasMipMap() && fFilterQuality != kNone_BitmapFilter) {
-
- // STEP 2: MIPMAP DOWNSAMPLE?
-
- // Check to see if the transformation matrix is scaling *down*.
- // If so, automatically build mipmaps.
-
- SkPoint v1, v2;
-
- // conservatively estimate if the matrix is scaling down by seeing
- // what its upper left 2x2 portion does to two unit vectors.
+ /*
+ * If we get here, the caller has requested either Med or High filter-level
+ *
+ * If High, then our special-case for scale-only did not take, and so we
+ * have to make a choice:
+ * 1. fall back on mipmaps + bilerp
+ * 2. fall back on scanline bicubic filter
+ * For now, we compute the "scale" value from the matrix, and have a
+ * threshold to decide when bicubic is better, and when mips are better.
+ * No doubt a fancier decision tree could be used uere.
+ *
+ * If Medium, then we just try to build a mipmap and select a level,
+ * setting the filter-level to kLow to signal that we just need bilerp
+ * to process the selected level.
+ */
- v1.fX = fInvMatrix.getScaleX();
- v1.fY = fInvMatrix.getSkewY();
+ SkScalar scaleSqd = effective_matrix_scale_sqrd(fInvMatrix);
+
+ if (SkPaint::kHigh_FilterLevel == fFilterLevel) {
+ // Set the limit at 0.25 for the CTM... if the CTM is scaling smaller
+ // than this, then the mipmaps quality may be greater (certainly faster)
+ // so we only keep High quality if the scale is greater than this.
+ //
+ // Since we're dealing with the inverse, we compare against its inverse.
+ const SkScalar bicubicLimit = SkFloatToScalar(4.0f);
+ const SkScalar bicubicLimitSqd = bicubicLimit * bicubicLimit;
+ if (scaleSqd < bicubicLimitSqd) { // use bicubic scanline
+ return;
+ }
- v2.fX = fInvMatrix.getSkewX();
- v2.fY = fInvMatrix.getScaleY();
+ // else set the filter-level to Medium, since we're scaling down and
+ // want to reqeust mipmaps
+ fFilterLevel = SkPaint::kMedium_FilterLevel;
+ }
+
+ SkASSERT(SkPaint::kMedium_FilterLevel == fFilterLevel);
- if (v1.fX * v1.fX + v1.fY * v1.fY > 1 ||
- v2.fX * v2.fX + v2.fY * v2.fY > 1) {
+ /**
+ * Medium quality means use a mipmap for down-scaling, and just bilper
+ * for upscaling. Since we're examining the inverse matrix, we look for
+ * a scale > 1 to indicate down scaling by the CTM.
+ */
+ if (scaleSqd > SK_Scalar1) {
+ if (!fOrigBitmap.hasMipMap()) {
fOrigBitmap.buildMipMap();
-
- // Now that we've built the mipmaps and we know we're downsampling,
- // downgrade to bilinear interpolation for the mip level.
-
- fFilterQuality = kBilerp_BitmapFilter;
+ // build may fail, so we need to check again
}
- }
-
- if (fOrigBitmap.hasMipMap()) {
-
- // STEP 3: We've got mipmaps, let's choose the closest level as our render
- // source and adjust the matrix accordingly.
-
- int shift = fOrigBitmap.extractMipLevel(&fScaledBitmap,
- SkScalarToFixed(fInvMatrix.getScaleX()),
- SkScalarToFixed(fInvMatrix.getSkewY()));
-
- if (shift > 0) {
- SkScalar scale = SkFixedToScalar(SK_Fixed1 >> shift);
- fInvMatrix.postScale(scale, scale);
- fBitmap = &fScaledBitmap;
+ if (fOrigBitmap.hasMipMap()) {
+ int shift = fOrigBitmap.extractMipLevel(&fScaledBitmap,
+ SkScalarToFixed(fInvMatrix.getScaleX()),
+ SkScalarToFixed(fInvMatrix.getSkewY()));
+ if (shift > 0) {
+ SkScalar scale = SkFixedToScalar(SK_Fixed1 >> shift);
+ fInvMatrix.postScale(scale, scale);
+ fBitmap = &fScaledBitmap;
+ }
}
}
+
+ // Now that we've built the mipmaps (if applicable), we set the filter-level
+ // bilinear interpolation.
+ fFilterLevel = SkPaint::kLow_FilterLevel;
}
void SkBitmapProcState::endContext() {
@@ -225,14 +256,7 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
// We may downgrade it later if we determine that we either don't need
// or can't provide as high a quality filtering as the user requested.
- fFilterQuality = kNone_BitmapFilter;
- if (paint.isFilterBitmap()) {
- if (paint.getFlags() & SkPaint::kHighQualityFilterBitmap_Flag) {
- fFilterQuality = kHQ_BitmapFilter;
- } else {
- fFilterQuality = kBilerp_BitmapFilter;
- }
- }
+ fFilterLevel = paint.getFilterLevel();
#ifndef SK_IGNORE_IMAGE_PRESCALE
// possiblyScaleImage will look to see if it can rescale the image as a
@@ -284,7 +308,7 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0;
- if (kHQ_BitmapFilter == fFilterQuality) {
+ if (SkPaint::kHigh_FilterLevel == fFilterLevel) {
// If this is still set, that means we wanted HQ sampling
// but couldn't do it as a preprocess. Let's try to install
// the scanline version of the HQ sampler. If that process fails,
@@ -300,17 +324,17 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
fShaderProc32 = this->chooseBitmapFilterProc();
if (!fShaderProc32) {
- fFilterQuality = kBilerp_BitmapFilter;
+ fFilterLevel = SkPaint::kLow_FilterLevel;
}
}
- if (kBilerp_BitmapFilter == fFilterQuality) {
+ if (SkPaint::kLow_FilterLevel == fFilterLevel) {
// Only try bilerp if the matrix is "interesting" and
// the image has a suitable size.
if (fInvType <= SkMatrix::kTranslate_Mask ||
- !valid_for_filtering(fBitmap->width() | fBitmap->height())) {
- fFilterQuality = kNone_BitmapFilter;
+ !valid_for_filtering(fBitmap->width() | fBitmap->height())) {
+ fFilterLevel = SkPaint::kNone_FilterLevel;
}
}
@@ -328,7 +352,7 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
// still set to HQ by the time we get here, then we must have installed
// the shader proc above and can skip all this.
- if (fFilterQuality < kHQ_BitmapFilter) {
+ if (fFilterLevel < SkPaint::kHigh_FilterLevel) {
int index = 0;
if (fAlphaScale < 256) { // note: this distinction is not used for D16
@@ -337,7 +361,7 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
index |= 2;
}
- if (fFilterQuality != kNone_BitmapFilter) {
+ if (fFilterLevel > SkPaint::kNone_FilterLevel) {
index |= 4;
}
// bits 3,4,5 encoding the source bitmap format
@@ -468,7 +492,7 @@ static void Clamp_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s,
SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0);
SkASSERT(s.fInvKy == 0);
SkASSERT(count > 0 && colors != NULL);
- SkASSERT(SkBitmapProcState::kNone_BitmapFilter == s.fFilterQuality);
+ SkASSERT(SkPaint::kNone_FilterLevel == s.fFilterLevel);
const int maxX = s.fBitmap->width() - 1;
const int maxY = s.fBitmap->height() - 1;
@@ -542,7 +566,7 @@ static void Repeat_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s,
SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0);
SkASSERT(s.fInvKy == 0);
SkASSERT(count > 0 && colors != NULL);
- SkASSERT(SkBitmapProcState::kNone_BitmapFilter == s.fFilterQuality);
+ SkASSERT(SkPaint::kNone_FilterLevel == s.fFilterLevel);
const int stopX = s.fBitmap->width();
const int stopY = s.fBitmap->height();
@@ -588,7 +612,7 @@ static void S32_D32_constX_shaderproc(const SkBitmapProcState& s,
int iY1 SK_INIT_TO_AVOID_WARNING;
int iSubY SK_INIT_TO_AVOID_WARNING;
- if (s.fFilterQuality != SkBitmapProcState::kNone_BitmapFilter) {
+ if (SkPaint::kNone_FilterLevel != s.fFilterLevel) {
SkBitmapProcState::MatrixProc mproc = s.getMatrixProc();
uint32_t xy[2];
@@ -669,7 +693,7 @@ static void S32_D32_constX_shaderproc(const SkBitmapProcState& s,
const SkPMColor* row0 = s.fBitmap->getAddr32(0, iY0);
SkPMColor color;
- if (s.fFilterQuality != SkBitmapProcState::kNone_BitmapFilter) {
+ if (SkPaint::kNone_FilterLevel != s.fFilterLevel) {
const SkPMColor* row1 = s.fBitmap->getAddr32(0, iY1);
if (s.fAlphaScale < 256) {
@@ -725,7 +749,7 @@ SkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() {
static const unsigned kMask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
if (1 == fBitmap->width() && 0 == (fInvType & ~kMask)) {
- if (kNone_BitmapFilter == fFilterQuality &&
+ if (SkPaint::kNone_FilterLevel == fFilterLevel &&
fInvType <= SkMatrix::kTranslate_Mask &&
!this->setupForTranslate()) {
return DoNothing_shaderproc;
@@ -739,7 +763,7 @@ SkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() {
if (fInvType > SkMatrix::kTranslate_Mask) {
return NULL;
}
- if (fFilterQuality != kNone_BitmapFilter) {
+ if (SkPaint::kNone_FilterLevel != fFilterLevel) {
return NULL;
}
@@ -835,9 +859,9 @@ void SkBitmapProcState::DebugMatrixProc(const SkBitmapProcState& state,
// scale -vs- affine
// filter -vs- nofilter
if (state.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
- proc = state.fFilterQuality != kNone_BitmapFilter ? check_scale_filter : check_scale_nofilter;
+ proc = state.fFilterLevel != SkPaint::kNone_FilterLevel ? check_scale_filter : check_scale_nofilter;
} else {
- proc = state.fFilterQuality != kNone_BitmapFilter ? check_affine_filter : check_affine_nofilter;
+ proc = state.fFilterLevel != SkPaint::kNone_FilterLevel ? check_affine_filter : check_affine_nofilter;
}
proc(bitmapXY, count, state.fBitmap->width(), state.fBitmap->height());
}
@@ -872,7 +896,7 @@ int SkBitmapProcState::maxCountForBufferSize(size_t bufferSize) const {
size >>= 2;
}
- if (fFilterQuality != kNone_BitmapFilter) {
+ if (fFilterLevel != SkPaint::kNone_FilterLevel) {
size >>= 1;
}
diff --git a/src/core/SkBitmapProcState.h b/src/core/SkBitmapProcState.h
index b4fae045f8..349194f3b4 100644
--- a/src/core/SkBitmapProcState.h
+++ b/src/core/SkBitmapProcState.h
@@ -89,12 +89,7 @@ struct SkBitmapProcState {
uint8_t fInvType; // chooseProcs
uint8_t fTileModeX; // CONSTRUCTOR
uint8_t fTileModeY; // CONSTRUCTOR
-
- enum {
- kNone_BitmapFilter,
- kBilerp_BitmapFilter,
- kHQ_BitmapFilter
- } fFilterQuality; // chooseProcs
+ uint8_t fFilterLevel; // chooseProcs
/** The shader will let us know when we can release some of our resources
* like scaled bitmaps.
diff --git a/src/core/SkBitmapProcState_matrixProcs.cpp b/src/core/SkBitmapProcState_matrixProcs.cpp
index d3cd5504fb..a3d2b08665 100644
--- a/src/core/SkBitmapProcState_matrixProcs.cpp
+++ b/src/core/SkBitmapProcState_matrixProcs.cpp
@@ -472,7 +472,7 @@ SkBitmapProcState::chooseMatrixProc(bool trivial_matrix) {
// test_int_tileprocs();
// check for our special case when there is no scale/affine/perspective
if (trivial_matrix) {
- SkASSERT(kNone_BitmapFilter == fFilterQuality);
+ SkASSERT(SkPaint::kNone_FilterLevel == fFilterLevel);
fIntTileProcY = choose_int_tile_proc(fTileModeY);
switch (fTileModeX) {
case SkShader::kClamp_TileMode:
@@ -485,7 +485,7 @@ SkBitmapProcState::chooseMatrixProc(bool trivial_matrix) {
}
int index = 0;
- if (fFilterQuality != kNone_BitmapFilter) {
+ if (fFilterLevel != SkPaint::kNone_FilterLevel) {
index = 1;
}
if (fInvType & SkMatrix::kPerspective_Mask) {
diff --git a/src/core/SkBitmapProcState_sample.h b/src/core/SkBitmapProcState_sample.h
index ac14b96278..5c5f199f25 100644
--- a/src/core/SkBitmapProcState_sample.h
+++ b/src/core/SkBitmapProcState_sample.h
@@ -42,7 +42,7 @@ void MAKENAME(_nofilter_DXDY)(const SkBitmapProcState& s,
const uint32_t* SK_RESTRICT xy,
int count, DSTTYPE* SK_RESTRICT colors) {
SkASSERT(count > 0 && colors != NULL);
- SkASSERT(SkBitmapProcState::kNone_BitmapFilter == s.fFilterQuality);
+ SkASSERT(SkPaint::kNone_FilterLevel == s.fFilterLevel);
SkDEBUGCODE(CHECKSTATE(s);)
#ifdef PREAMBLE
@@ -85,7 +85,7 @@ void MAKENAME(_nofilter_DX)(const SkBitmapProcState& s,
int count, DSTTYPE* SK_RESTRICT colors) {
SkASSERT(count > 0 && colors != NULL);
SkASSERT(s.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask));
- SkASSERT(SkBitmapProcState::kNone_BitmapFilter == s.fFilterQuality);
+ SkASSERT(SkPaint::kNone_FilterLevel == s.fFilterLevel);
SkDEBUGCODE(CHECKSTATE(s);)
#ifdef PREAMBLE
@@ -139,7 +139,7 @@ void MAKENAME(_filter_DX)(const SkBitmapProcState& s,
const uint32_t* SK_RESTRICT xy,
int count, DSTTYPE* SK_RESTRICT colors) {
SkASSERT(count > 0 && colors != NULL);
- SkASSERT(s.fFilterQuality != SkBitmapProcState::kNone_BitmapFilter);
+ SkASSERT(s.fFilterLevel != SkPaint::kNone_FilterLevel);
SkDEBUGCODE(CHECKSTATE(s);)
#ifdef PREAMBLE
@@ -185,7 +185,7 @@ void MAKENAME(_filter_DXDY)(const SkBitmapProcState& s,
const uint32_t* SK_RESTRICT xy,
int count, DSTTYPE* SK_RESTRICT colors) {
SkASSERT(count > 0 && colors != NULL);
- SkASSERT(s.fFilterQuality != SkBitmapProcState::kNone_BitmapFilter);
+ SkASSERT(s.fFilterLevel != SkPaint::kNone_FilterLevel);
SkDEBUGCODE(CHECKSTATE(s);)
#ifdef PREAMBLE
diff --git a/src/core/SkBitmapProcState_shaderproc.h b/src/core/SkBitmapProcState_shaderproc.h
index d765b8e92d..0014b4a526 100644
--- a/src/core/SkBitmapProcState_shaderproc.h
+++ b/src/core/SkBitmapProcState_shaderproc.h
@@ -21,7 +21,7 @@ void SCALE_FILTER_NAME(const SkBitmapProcState& s, int x, int y,
SkMatrix::kScale_Mask)) == 0);
SkASSERT(s.fInvKy == 0);
SkASSERT(count > 0 && colors != NULL);
- SkASSERT(s.fFilterQuality != SkBitmapProcState::kNone_BitmapFilter);
+ SkASSERT(s.fFilterLevel != SkPaint::kNone_FilterLevel);
SkDEBUGCODE(CHECKSTATE(s);)
const unsigned maxX = s.fBitmap->width() - 1;