Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(105)

Unified Diff: src/core/SkBitmapProcState.cpp

Issue 18978014: Working plumb of image scaling: (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Rework plumb to have filter quality as an enum, avoid allocating new purgable bitmap Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/core/SkBitmapProcState.cpp
diff --git a/src/core/SkBitmapProcState.cpp b/src/core/SkBitmapProcState.cpp
index a2c7f990c2d9b19fe5ee238de9eae68757a62c3b..d769aa7db05d514971435fb6fa9b36a3316ec66e 100644
--- a/src/core/SkBitmapProcState.cpp
+++ b/src/core/SkBitmapProcState.cpp
@@ -90,6 +90,10 @@ static bool valid_for_filtering(unsigned dimension) {
return (dimension & ~0x3FFF) == 0;
}
+void SkBitmapProcState::endContext() {
+ SkDELETE(fBitmapFilter);
+}
+
bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
if (fOrigBitmap.width() == 0 || fOrigBitmap.height() == 0) {
return false;
@@ -109,8 +113,58 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
}
fBitmap = &fOrigBitmap;
- if (fOrigBitmap.hasMipMap()) {
- int shift = fOrigBitmap.extractMipLevel(&fMipBitmap,
+
+ // Check to see if the transformation matrix is scaling up, and if
+ // the matrix is simple, and if the paint has high quality scaling
+ // turned on. If so, do the bitmap scale here and remove the scaling component from the matrix.
+
+ uint32_t hqUpsampleMask = SkPaint::kFilterBitmap_Flag
+ | SkPaint::kHighQualityFilterBitmap_Flag
+ ;
+ if (inv.getType() == (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask) &&
+ (inv.getScaleX() < 1 || inv.getScaleY() < 1) &&
+ ((paint.getFlags() & hqUpsampleMask) == hqUpsampleMask) &&
+ fOrigBitmap.config() == SkBitmap::kARGB_8888_Config) {
+
+ // All the criteria are met; let's make a new bitmap.
+ fScaledBitmap.setConfig(SkBitmap::kARGB_8888_Config, fOrigBitmap.width() / inv.getScaleX(), fOrigBitmap.height() / inv.getScaleY());
reed1 2013/07/11 15:43:42 nit: line-wrap
reed1 2013/07/11 15:49:08 grrrr, this is tricky, since we have one predicate
humper 2013/07/11 16:03:03 Done.
+ fScaledBitmap.allocPixels();
+ fOrigBitmap.scale(&fScaledBitmap);
+ fBitmap = &fScaledBitmap;
+
+ // Now get rid of the scale factor from the matrix
+
+ if (m != &fUnitInvMatrix) {
+ fUnitInvMatrix = *m;
+ m = &fUnitInvMatrix;
+ }
+
+ // set the inv matrix type to translate-only; this should have
+ // the side-effect of disabling bitmap filtering also.
+
+ fUnitInvMatrix.setTranslate( 1/m->getScaleX() * m->getTranslateX(), 1/m->getScaleY() * m->getTranslateY() );
reed1 2013/07/11 15:43:42 nit: line-wrap
humper 2013/07/11 16:03:03 Done.
+ } else if (!fBitmap->hasMipMap()) {
+ // Check to see if the transformation matrix is scaling *down*.
+ // If so, automatically build mipmaps
+
+ SkPoint v1, v2;
+
+ // guess if the matrix is scaling down by seeing what it does to two unit vectors.
+
+ v1.fX = inv.getScaleX();
+ v1.fY = inv.getSkewY();
+
+ v2.fX = inv.getSkewX();
+ v2.fY = inv.getScaleY();
+
+ if (v1.fX * v1.fX + v1.fY * v1.fY > 1 ||
+ v2.fX * v2.fX + v2.fY * v2.fY > 1) {
+ fBitmap->buildMipMap();
+ }
+ }
+
+ if (fBitmap->hasMipMap()) {
+ int shift = fBitmap->extractMipLevel(&fMipBitmap,
SkScalarToFixed(m->getScaleX()),
SkScalarToFixed(m->getSkewY()));
@@ -156,20 +210,42 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
fInvKyFractionalInt = SkScalarToFractionalInt(m->getSkewY());
fAlphaScale = SkAlpha255To256(paint.getAlpha());
+
+ fShaderProc32 = NULL;
+ fShaderProc16 = NULL;
+ fSampleProc32 = NULL;
+ fSampleProc16 = NULL;
// pick-up filtering from the paint, but only if the matrix is
// more complex than identity/translate (i.e. no need to pay the cost
// of filtering if we're not scaled etc.).
// note: we explicitly check inv, since m might be scaled due to unitinv
// trickery, but we don't want to see that for this test
- fDoFilter = paint.isFilterBitmap() &&
- (fInvType > SkMatrix::kTranslate_Mask &&
- valid_for_filtering(fBitmap->width() | fBitmap->height()));
-
- fShaderProc32 = NULL;
- fShaderProc16 = NULL;
- fSampleProc32 = NULL;
- fSampleProc16 = NULL;
+
+ fFilterQuality = kNone_BitmapFilter;
+
+ if (paint.isFilterBitmap()) {
+ if ((paint.getFlags() & hqUpsampleMask) == hqUpsampleMask) {
+ // The paint wants high quality sampling, so let's try to do it.
+ fFilterQuality = kHQ_BitmapFilter;
+ fShaderProc32 = this->chooseBitmapFilterProc();
+ }
+
+ if (!fShaderProc32) {
+ // if no shader proc is set, either the caller didn't ask
+ // for high quality filtering (so we didn't try at all),
+ // or our attempt to install an HQ sampler failed.
+ // Attempt to use bilerp in either case.
+
+ // Only install bilerp if the matrix is "interesting" and
+ // the image has a suitable size.
+
+ if (fInvType > SkMatrix::kTranslate_Mask &&
reed1 2013/07/11 15:43:42 Shouldn't we perform this (not scaled enough to ju
reed1 2013/07/11 15:49:08 Ah, I see that you are *re*calling this logic afte
humper 2013/07/11 16:03:03 the valid_for_filtering function actually checks t
+ valid_for_filtering(fBitmap->width() | fBitmap->height())) {
+ fFilterQuality = kBilerp_BitmapFilter;
+ }
+ }
+ }
fMatrixProc = this->chooseMatrixProc(trivial_matrix);
if (NULL == fMatrixProc) {
@@ -185,7 +261,7 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
index |= 2;
}
- if (fDoFilter) {
+ if (fFilterQuality != kNone_BitmapFilter) {
index |= 4;
}
// bits 3,4,5 encoding the source bitmap format
@@ -302,10 +378,6 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
fShaderProc32 = this->chooseShaderProc32();
}
- if (NULL == fShaderProc32) {
- fShaderProc32 = this->chooseBitmapFilterProc(paint);
- }
-
// see if our platform has any accelerated overrides
this->platformProcs();
@@ -319,7 +391,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(!s.fDoFilter);
+ SkASSERT(s.fFilterQuality == kNone_BitmapFilter);
const int maxX = s.fBitmap->width() - 1;
const int maxY = s.fBitmap->height() - 1;
@@ -393,7 +465,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(!s.fDoFilter);
+ SkASSERT(s.fFilterQuality == kNone_BitmapFilter);
reed1 2013/07/11 15:43:42 nit: skia likes to place the literal on the left (
const int stopX = s.fBitmap->width();
const int stopY = s.fBitmap->height();
@@ -439,7 +511,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.fDoFilter) {
+ if (s.fFilterQuality != SkBitmapProcState::kNone_BitmapFilter) {
SkBitmapProcState::MatrixProc mproc = s.getMatrixProc();
uint32_t xy[2];
@@ -520,7 +592,7 @@ static void S32_D32_constX_shaderproc(const SkBitmapProcState& s,
const SkPMColor* row0 = s.fBitmap->getAddr32(0, iY0);
SkPMColor color;
- if (s.fDoFilter) {
+ if (s.fFilterQuality != SkBitmapProcState::kNone_BitmapFilter) {
const SkPMColor* row1 = s.fBitmap->getAddr32(0, iY1);
if (s.fAlphaScale < 256) {
@@ -576,7 +648,9 @@ SkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() {
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()) {
+ if (fFilterQuality == kNone_BitmapFilter &&
+ fInvType <= SkMatrix::kTranslate_Mask &&
+ !this->setupForTranslate()) {
return DoNothing_shaderproc;
}
return S32_D32_constX_shaderproc;
@@ -588,7 +662,7 @@ SkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() {
if (fInvType > SkMatrix::kTranslate_Mask) {
return NULL;
}
- if (fDoFilter) {
+ if (fFilterQuality != kNone_BitmapFilter) {
return NULL;
}
@@ -684,9 +758,9 @@ void SkBitmapProcState::DebugMatrixProc(const SkBitmapProcState& state,
// scale -vs- affine
// filter -vs- nofilter
if (state.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
- proc = state.fDoFilter ? check_scale_filter : check_scale_nofilter;
+ proc = state.fFilterQuality != kNone_BitmapFilter ? check_scale_filter : check_scale_nofilter;
} else {
- proc = state.fDoFilter ? check_affine_filter : check_affine_nofilter;
+ proc = state.fFilterQuality != kNone_BitmapFilter ? check_affine_filter : check_affine_nofilter;
}
proc(bitmapXY, count, state.fBitmap->width(), state.fBitmap->height());
}
@@ -721,7 +795,7 @@ int SkBitmapProcState::maxCountForBufferSize(size_t bufferSize) const {
size >>= 2;
}
- if (fDoFilter) {
+ if (fFilterQuality != kNone_BitmapFilter) {
size >>= 1;
}

Powered by Google App Engine
This is Rietveld 408576698