Working plumb of image scaling:

1) always generate mipmaps if we detect that we are downsampling.
2) pre-scale the image if we detect that we are upsampling
   (currently valid for scale+translate only)
3) A few miscellaneous bug fixes related to image scaling.

Still need SSE/Neon versions of these image scalers.

BUG=
R=bsalomon@google.com, robertphillips@google.com

Review URL: https://codereview.chromium.org/18978014

git-svn-id: http://skia.googlecode.com/svn/trunk@10056 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
humper@google.com 2013-07-12 21:14:33 +00:00
parent 5383a75253
commit d64d8a905a
17 changed files with 718 additions and 414 deletions

201
gm/downsamplebitmap.cpp Normal file
View File

@ -0,0 +1,201 @@
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "gm.h"
#include "SkGradientShader.h"
#include "SkTypeface.h"
#include "SkImageDecoder.h"
#include "SkStream.h"
static void setTypeface(SkPaint* paint, const char name[], SkTypeface::Style style) {
SkSafeUnref(paint->setTypeface(SkTypeface::CreateFromName(name, style)));
}
class DownsampleBitmapGM : public skiagm::GM {
public:
SkBitmap fBM;
SkString fName;
bool fBitmapMade;
DownsampleBitmapGM()
{
this->setBGColor(0xFFDDDDDD);
fBitmapMade = false;
}
void setName(const char name[]) {
fName.set(name);
}
protected:
virtual SkString onShortName() SK_OVERRIDE {
return fName;
}
virtual SkISize onISize() SK_OVERRIDE {
make_bitmap_wrapper();
return SkISize::Make(4 * fBM.width(), fBM.height());
}
void make_bitmap_wrapper() {
if (!fBitmapMade) {
fBitmapMade = true;
make_bitmap();
}
}
virtual void make_bitmap() = 0;
virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
make_bitmap_wrapper();
int curX = 0;
int curWidth;
float curScale = 1;
do {
SkMatrix matrix;
matrix.setScale( curScale, curScale );
SkPaint paint;
paint.setFilterBitmap(true);
paint.setFlags( paint.getFlags() | SkPaint::kHighQualityFilterBitmap_Flag );
canvas->save();
canvas->translate( curX, 0 );
canvas->drawBitmapMatrix( fBM, matrix, &paint );
canvas->restore();
curWidth = (int) (fBM.width() * curScale + 2);
curX += curWidth;
curScale *= 0.75;
} while (curX < 4*fBM.width());
}
private:
typedef skiagm::GM INHERITED;
};
class DownsampleBitmapTextGM: public DownsampleBitmapGM {
public:
DownsampleBitmapTextGM(float textSize)
: fTextSize(textSize)
{
char name[1024];
sprintf(name, "downsamplebitmap_text_%.2fpt", fTextSize);
setName(name);
}
protected:
float fTextSize;
virtual void make_bitmap() SK_OVERRIDE {
fBM.setConfig(SkBitmap::kARGB_8888_Config, int(fTextSize * 8), int(fTextSize * 6));
fBM.allocPixels();
SkCanvas canvas(fBM);
canvas.drawColor(SK_ColorWHITE);
SkPaint paint;
paint.setAntiAlias(true);
paint.setSubpixelText(true);
paint.setTextSize(fTextSize);
setTypeface(&paint, "Times", SkTypeface::kNormal);
canvas.drawText("Hamburgefons", 12, fTextSize/2, 1.2f*fTextSize, paint);
setTypeface(&paint, "Times", SkTypeface::kBold);
canvas.drawText("Hamburgefons", 12, fTextSize/2, 2.4f*fTextSize, paint);
setTypeface(&paint, "Times", SkTypeface::kItalic);
canvas.drawText("Hamburgefons", 12, fTextSize/2, 3.6f*fTextSize, paint);
setTypeface(&paint, "Times", SkTypeface::kBoldItalic);
canvas.drawText("Hamburgefons", 12, fTextSize/2, 4.8f*fTextSize, paint);
}
private:
typedef DownsampleBitmapGM INHERITED;
};
class DownsampleBitmapCheckerboardGM: public DownsampleBitmapGM {
public:
DownsampleBitmapCheckerboardGM(int size, int numChecks)
: fSize(size), fNumChecks(numChecks)
{
char name[1024];
sprintf(name, "downsamplebitmap_checkerboard_%d_%d", fSize, fNumChecks);
setName(name);
}
protected:
int fSize;
int fNumChecks;
virtual void make_bitmap() SK_OVERRIDE {
fBM.setConfig(SkBitmap::kARGB_8888_Config, fSize, fSize);
fBM.allocPixels();
SkAutoLockPixels lock(fBM);
for (int y = 0; y < fSize; ++y) {
for (int x = 0; x < fSize; ++x) {
SkPMColor* s = fBM.getAddr32(x, y);
int cx = (x * fNumChecks) / fSize;
int cy = (y * fNumChecks) / fSize;
if ((cx+cy)%2) {
*s = 0xFFFFFFFF;
} else {
*s = 0xFF000000;
}
}
}
}
private:
typedef DownsampleBitmapGM INHERITED;
};
class DownsampleBitmapImageGM: public DownsampleBitmapGM {
public:
DownsampleBitmapImageGM(const char filename[])
: fFilename(filename)
{
char name[1024];
sprintf(name, "downsamplebitmap_image_%s", filename);
setName(name);
}
protected:
SkString fFilename;
int fSize;
virtual void make_bitmap() SK_OVERRIDE {
SkString path(skiagm::GM::gResourcePath);
path.append("/");
path.append(fFilename);
SkImageDecoder *codec = NULL;
SkFILEStream stream(path.c_str());
if (stream.isValid()) {
codec = SkImageDecoder::Factory(&stream);
}
if (codec) {
stream.rewind();
codec->decode(&stream, &fBM, SkBitmap::kARGB_8888_Config,
SkImageDecoder::kDecodePixels_Mode);
SkDELETE(codec);
} else {
fBM.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
fBM.allocPixels();
*(fBM.getAddr32(0,0)) = 0xFF0000FF; // red == bad
}
fSize = fBM.height();
}
private:
typedef DownsampleBitmapGM INHERITED;
};
//////////////////////////////////////////////////////////////////////////////
DEF_GM( return new DownsampleBitmapTextGM(72); )
DEF_GM( return new DownsampleBitmapCheckerboardGM(512,256); )
DEF_GM( return new DownsampleBitmapImageGM("mandrill_512.png"); )

View File

@ -35,6 +35,7 @@
'../gm/deviceproperties.cpp',
'../gm/distantclip.cpp',
'../gm/displacement.cpp',
'../gm/downsamplebitmap.cpp',
'../gm/drawbitmaprect.cpp',
'../gm/drawlooper.cpp',
'../gm/extractbitmap.cpp',

View File

@ -22,28 +22,28 @@ void highQualityFilter(const SkBitmapProcState& s, int x, int y,
while (count-- > 0) {
SkPoint srcPt;
s.fInvProc(*s.fInvMatrix, SkFloatToScalar(x + 0.5f),
s.fInvProc(s.fInvMatrix, SkFloatToScalar(x + 0.5f),
SkFloatToScalar(y + 0.5f), &srcPt);
srcPt.fX -= SK_ScalarHalf;
srcPt.fY -= SK_ScalarHalf;
SkFixed weight = 0;
SkFixed fr = 0, fg = 0, fb = 0, fa = 0;
SkScalar weight = 0;
SkScalar fr = 0, fg = 0, fb = 0, fa = 0;
int y0 = SkClampMax(sk_float_ceil2int(SkScalarToFloat(srcPt.fY)-s.getBitmapFilter()->width()), maxY);
int y1 = SkClampMax(sk_float_floor2int(SkScalarToFloat(srcPt.fY)+s.getBitmapFilter()->width()), maxY);
int x0 = SkClampMax(sk_float_ceil2int(SkScalarToFloat(srcPt.fX)-s.getBitmapFilter()->width()), maxX);
int x1 = SkClampMax(sk_float_floor2int(SkScalarToFloat(srcPt.fX)+s.getBitmapFilter()->width()), maxX);
int y0 = SkClampMax(SkScalarCeilToInt(srcPt.fY-s.getBitmapFilter()->width()), maxY);
int y1 = SkClampMax(SkScalarFloorToInt(srcPt.fY+s.getBitmapFilter()->width()), maxY);
int x0 = SkClampMax(SkScalarCeilToInt(srcPt.fX-s.getBitmapFilter()->width()), maxX);
int x1 = SkClampMax(SkScalarFloorToInt(srcPt.fX+s.getBitmapFilter()->width()), maxX);
for (int src_y = y0; src_y <= y1; src_y++) {
SkFixed yweight = s.getBitmapFilter()->lookup((srcPt.fY - src_y));
for (int srcY = y0; srcY <= y1; srcY++) {
SkScalar yWeight = s.getBitmapFilter()->lookupScalar((srcPt.fY - srcY));
for (int src_x = x0; src_x <= x1 ; src_x++) {
SkFixed xweight = s.getBitmapFilter()->lookup((srcPt.fX - src_x));
for (int srcX = x0; srcX <= x1 ; srcX++) {
SkScalar xWeight = s.getBitmapFilter()->lookupScalar((srcPt.fX - srcX));
SkFixed combined_weight = SkFixedMul(xweight, yweight);
SkScalar combined_weight = SkScalarMul(xWeight, yWeight);
SkPMColor c = *s.fBitmap->getAddr32(src_x, src_y);
SkPMColor c = *s.fBitmap->getAddr32(srcX, srcY);
fr += combined_weight * SkGetPackedR32(c);
fg += combined_weight * SkGetPackedG32(c);
fb += combined_weight * SkGetPackedB32(c);
@ -52,15 +52,15 @@ void highQualityFilter(const SkBitmapProcState& s, int x, int y,
}
}
fr = SkFixedDiv(fr, weight);
fg = SkFixedDiv(fg, weight);
fb = SkFixedDiv(fb, weight);
fa = SkFixedDiv(fa, weight);
fr = SkScalarDiv(fr, weight);
fg = SkScalarDiv(fg, weight);
fb = SkScalarDiv(fb, weight);
fa = SkScalarDiv(fa, weight);
int a = SkClampMax(SkFixedRoundToInt(fa), 255);
int r = SkClampMax(SkFixedRoundToInt(fr), a);
int g = SkClampMax(SkFixedRoundToInt(fg), a);
int b = SkClampMax(SkFixedRoundToInt(fb), a);
int a = SkClampMax(SkScalarRoundToInt(fa), 255);
int r = SkClampMax(SkScalarRoundToInt(fr), a);
int g = SkClampMax(SkScalarRoundToInt(fg), a);
int b = SkClampMax(SkScalarRoundToInt(fb), a);
*colors++ = SkPackARGB32(a, r, g, b);
@ -75,33 +75,33 @@ void highQualityFilter_ScaleOnly(const SkBitmapProcState &s, int x, int y,
SkPoint srcPt;
s.fInvProc(*s.fInvMatrix, SkFloatToScalar(x + 0.5f),
s.fInvProc(s.fInvMatrix, SkFloatToScalar(x + 0.5f),
SkFloatToScalar(y + 0.5f), &srcPt);
srcPt.fY -= SK_ScalarHalf;
int y0 = SkClampMax(sk_float_ceil2int(SkScalarToFloat(srcPt.fY)-s.getBitmapFilter()->width()), maxY);
int y1 = SkClampMax(sk_float_floor2int(SkScalarToFloat(srcPt.fY)+s.getBitmapFilter()->width()), maxY);
int y0 = SkClampMax(SkScalarCeilToInt(srcPt.fY-s.getBitmapFilter()->width()), maxY);
int y1 = SkClampMax(SkScalarFloorToInt(srcPt.fY+s.getBitmapFilter()->width()), maxY);
while (count-- > 0) {
s.fInvProc(*s.fInvMatrix, SkFloatToScalar(x + 0.5f),
s.fInvProc(s.fInvMatrix, SkFloatToScalar(x + 0.5f),
SkFloatToScalar(y + 0.5f), &srcPt);
srcPt.fX -= SK_ScalarHalf;
srcPt.fY -= SK_ScalarHalf;
SkFixed weight = 0;
SkFixed fr = 0, fg = 0, fb = 0, fa = 0;
SkScalar weight = 0;
SkScalar fr = 0, fg = 0, fb = 0, fa = 0;
int x0 = SkClampMax(sk_float_ceil2int(SkScalarToFloat(srcPt.fX)-s.getBitmapFilter()->width()), maxX);
int x1 = SkClampMax(sk_float_floor2int(SkScalarToFloat(srcPt.fX)+s.getBitmapFilter()->width()), maxX);
int x0 = SkClampMax(SkScalarCeilToInt(srcPt.fX-s.getBitmapFilter()->width()), maxX);
int x1 = SkClampMax(SkScalarFloorToInt(srcPt.fX+s.getBitmapFilter()->width()), maxX);
for (int src_y = y0; src_y <= y1; src_y++) {
SkFixed yweight = s.getBitmapFilter()->lookup((srcPt.fY - src_y));
for (int srcY = y0; srcY <= y1; srcY++) {
SkScalar yWeight = s.getBitmapFilter()->lookupScalar((srcPt.fY - srcY));
for (int src_x = x0; src_x <= x1 ; src_x++) {
SkFixed xweight = s.getBitmapFilter()->lookup((srcPt.fX - src_x));
for (int srcX = x0; srcX <= x1 ; srcX++) {
SkScalar xWeight = s.getBitmapFilter()->lookupScalar((srcPt.fX - srcX));
SkFixed combined_weight = SkFixedMul(xweight, yweight);
SkScalar combined_weight = SkScalarMul(xWeight, yWeight);
SkPMColor c = *s.fBitmap->getAddr32(src_x, src_y);
SkPMColor c = *s.fBitmap->getAddr32(srcX, srcY);
fr += combined_weight * SkGetPackedR32(c);
fg += combined_weight * SkGetPackedG32(c);
fb += combined_weight * SkGetPackedB32(c);
@ -110,15 +110,15 @@ void highQualityFilter_ScaleOnly(const SkBitmapProcState &s, int x, int y,
}
}
fr = SkFixedDiv(fr, weight);
fg = SkFixedDiv(fg, weight);
fb = SkFixedDiv(fb, weight);
fa = SkFixedDiv(fa, weight);
fr = SkScalarDiv(fr, weight);
fg = SkScalarDiv(fg, weight);
fb = SkScalarDiv(fb, weight);
fa = SkScalarDiv(fa, weight);
int a = SkClampMax(SkFixedRoundToInt(fa), 255);
int r = SkClampMax(SkFixedRoundToInt(fr), a);
int g = SkClampMax(SkFixedRoundToInt(fg), a);
int b = SkClampMax(SkFixedRoundToInt(fb), a);
int a = SkClampMax(SkScalarRoundToInt(fa), 255);
int r = SkClampMax(SkScalarRoundToInt(fr), a);
int g = SkClampMax(SkScalarRoundToInt(fg), a);
int b = SkClampMax(SkScalarRoundToInt(fb), a);
*colors++ = SkPackARGB32(a, r, g, b);
@ -147,12 +147,13 @@ static SkBitmapFilter *allocateBitmapFilter() {
}
SkBitmapProcState::ShaderProc32
SkBitmapProcState::chooseBitmapFilterProc(const SkPaint& paint) {
// we need to be requested
uint32_t mask = SkPaint::kFilterBitmap_Flag
| SkPaint::kHighQualityFilterBitmap_Flag
;
if ((paint.getFlags() & mask) != mask) {
SkBitmapProcState::chooseBitmapFilterProc() {
if (fFilterQuality != kHQ_BitmapFilter) {
return NULL;
}
if (fAlphaScale != 256) {
return NULL;
}
@ -166,11 +167,6 @@ SkBitmapProcState::chooseBitmapFilterProc(const SkPaint& paint) {
return NULL;
}
// TODO: support blending inside our procs
if (0xFF != paint.getAlpha()) {
return NULL;
}
if (fInvType & (SkMatrix::kAffine_Mask | SkMatrix::kScale_Mask)) {
fBitmapFilter = allocateBitmapFilter();
}
@ -184,66 +180,66 @@ SkBitmapProcState::chooseBitmapFilterProc(const SkPaint& paint) {
}
}
static void divideByWeights(SkFixed *sums, SkFixed *weights, SkBitmap *dst) {
static void divideByWeights(SkScalar *sums, SkScalar *weights, SkBitmap *dst) {
for (int y = 0 ; y < dst->height() ; y++) {
for (int x = 0 ; x < dst->width() ; x++) {
SkFixed fr = SkFixedDiv(sums[4*(y*dst->width() + x) + 0], weights[y*dst->width() + x]);
SkFixed fg = SkFixedDiv(sums[4*(y*dst->width() + x) + 1], weights[y*dst->width() + x]);
SkFixed fb = SkFixedDiv(sums[4*(y*dst->width() + x) + 2], weights[y*dst->width() + x]);
SkFixed fa = SkFixedDiv(sums[4*(y*dst->width() + x) + 3], weights[y*dst->width() + x]);
int a = SkClampMax(SkFixedRoundToInt(fa), 255);
int r = SkClampMax(SkFixedRoundToInt(fr), a);
int g = SkClampMax(SkFixedRoundToInt(fg), a);
int b = SkClampMax(SkFixedRoundToInt(fb), a);
SkScalar fr = SkScalarDiv(sums[4*(y*dst->width() + x) + 0], weights[y*dst->width() + x]);
SkScalar fg = SkScalarDiv(sums[4*(y*dst->width() + x) + 1], weights[y*dst->width() + x]);
SkScalar fb = SkScalarDiv(sums[4*(y*dst->width() + x) + 2], weights[y*dst->width() + x]);
SkScalar fa = SkScalarDiv(sums[4*(y*dst->width() + x) + 3], weights[y*dst->width() + x]);
int a = SkClampMax(SkScalarRoundToInt(fa), 255);
int r = SkClampMax(SkScalarRoundToInt(fr), a);
int g = SkClampMax(SkScalarRoundToInt(fg), a);
int b = SkClampMax(SkScalarRoundToInt(fb), a);
*dst->getAddr32(x,y) = SkPackARGB32(a, r, g, b);
}
}
}
static void upScaleHoriz(const SkBitmap *src, SkBitmap *dst, float scale, SkBitmapFilter *filter) {
for (int y = 0 ; y < src->height() ; y++) {
static void upScaleHorizTranspose(const SkBitmap *src, SkBitmap *dst, float scale, SkBitmapFilter *filter) {
for (int y = 0 ; y < dst->height() ; y++) {
for (int x = 0 ; x < dst->width() ; x++) {
float sx = (x + 0.5f) / scale - 0.5f;
float sx = (y + 0.5f) / scale - 0.5f;
int x0 = SkClampMax(sk_float_ceil2int(sx-filter->width()), src->width()-1);
int x1 = SkClampMax(sk_float_floor2int(sx+filter->width()), src->width()-1);
SkFixed total_weight = 0;
SkFixed fr = 0, fg = 0, fb = 0, fa = 0;
SkScalar totalWeight = 0;
SkScalar fr = 0, fg = 0, fb = 0, fa = 0;
for (int src_x = x0 ; src_x <= x1 ; src_x++) {
SkFixed weight = filter->lookup(sx - src_x);
SkPMColor c = *src->getAddr32(src_x,y);
fr += weight * SkGetPackedR32(c);
fg += weight * SkGetPackedG32(c);
fb += weight * SkGetPackedB32(c);
fa += weight * SkGetPackedA32(c);
total_weight += weight;
for (int srcX = x0 ; srcX <= x1 ; srcX++) {
SkScalar weight = filter->lookupScalar(sx - srcX);
SkPMColor c = *src->getAddr32(srcX, x);
fr += SkScalarMul(weight,SkGetPackedR32(c));
fg += SkScalarMul(weight,SkGetPackedG32(c));
fb += SkScalarMul(weight,SkGetPackedB32(c));
fa += SkScalarMul(weight,SkGetPackedA32(c));
totalWeight += weight;
}
fr = SkFixedDiv(fr, total_weight);
fg = SkFixedDiv(fg, total_weight);
fb = SkFixedDiv(fb, total_weight);
fa = SkFixedDiv(fa, total_weight);
fr = SkScalarDiv(fr,totalWeight);
fg = SkScalarDiv(fg,totalWeight);
fb = SkScalarDiv(fb,totalWeight);
fa = SkScalarDiv(fa,totalWeight);
int a = SkClampMax(SkFixedRoundToInt(fa), 255);
int r = SkClampMax(SkFixedRoundToInt(fr), a);
int g = SkClampMax(SkFixedRoundToInt(fg), a);
int b = SkClampMax(SkFixedRoundToInt(fb), a);
int a = SkClampMax(SkScalarRoundToInt(fa), 255);
int r = SkClampMax(SkScalarRoundToInt(fr), a);
int g = SkClampMax(SkScalarRoundToInt(fg), a);
int b = SkClampMax(SkScalarRoundToInt(fb), a);
*dst->getAddr32(x,y) = SkPackARGB32(a, r, g, b);
*dst->getAddr32(x,y) = SkPackARGB32(a, r, g, b);
}
}
}
static void downScaleHoriz(const SkBitmap *src, SkBitmap *dst, float scale, SkBitmapFilter *filter) {
SkFixed *sums = SkNEW_ARRAY(SkFixed, dst->width() * dst->height() * 4);
SkFixed *weights = SkNEW_ARRAY(SkFixed, dst->width() * dst->height());
SkScalar *sums = SkNEW_ARRAY(SkScalar, dst->width() * dst->height() * 4);
SkScalar *weights = SkNEW_ARRAY(SkScalar, dst->width() * dst->height());
SkAutoTDeleteArray<SkFixed> ada1(sums);
SkAutoTDeleteArray<SkFixed> ada2(weights);
SkAutoTDeleteArray<SkScalar> ada1(sums);
SkAutoTDeleteArray<SkScalar> ada2(weights);
memset(sums, 0, dst->width() * dst->height() * sizeof(SkFixed) * 4);
memset(weights, 0, dst->width() * dst->height() * sizeof(SkFixed));
memset(sums, 0, dst->width() * dst->height() * sizeof(SkScalar) * 4);
memset(weights, 0, dst->width() * dst->height() * sizeof(SkScalar));
for (int y = 0 ; y < src->height() ; y++) {
for (int x = 0 ; x < src->width() ; x++) {
@ -255,7 +251,7 @@ static void downScaleHoriz(const SkBitmap *src, SkBitmap *dst, float scale, SkBi
SkPMColor c = *src->getAddr32(x,y);
for (int dst_x = x0 ; dst_x <= x1 ; dst_x++) {
SkFixed weight = filter->lookup(dx - dst_x);
SkScalar weight = filter->lookup(dx - dst_x);
sums[4*(y*dst->width() + dst_x) + 0] += weight*SkGetPackedR32(c);
sums[4*(y*dst->width() + dst_x) + 1] += weight*SkGetPackedG32(c);
sums[4*(y*dst->width() + dst_x) + 2] += weight*SkGetPackedB32(c);
@ -268,49 +264,15 @@ static void downScaleHoriz(const SkBitmap *src, SkBitmap *dst, float scale, SkBi
divideByWeights(sums, weights, dst);
}
static void upScaleVert(const SkBitmap *src, SkBitmap *dst, float scale, SkBitmapFilter *filter) {
for (int y = 0 ; y < dst->height() ; y++) {
for (int x = 0 ; x < dst->width() ; x++) {
float sy = (y + 0.5f) / scale - 0.5f;
int y0 = SkClampMax(sk_float_ceil2int(sy-filter->width()), src->height()-1);
int y1 = SkClampMax(sk_float_floor2int(sy+filter->width()), src->height()-1);
SkFixed total_weight = 0;
SkFixed fr = 0, fg = 0, fb = 0, fa = 0;
for (int src_y = y0 ; src_y <= y1 ; src_y++) {
SkFixed weight = filter->lookup(sy - src_y);
SkPMColor c = *src->getAddr32(x,src_y);
fr += weight * SkGetPackedR32(c);
fg += weight * SkGetPackedG32(c);
fb += weight * SkGetPackedB32(c);
fa += weight * SkGetPackedA32(c);
total_weight += weight;
}
fr = SkFixedDiv(fr, total_weight);
fg = SkFixedDiv(fg, total_weight);
fb = SkFixedDiv(fb, total_weight);
fa = SkFixedDiv(fa, total_weight);
int a = SkClampMax(SkFixedRoundToInt(fa), 255);
int r = SkClampMax(SkFixedRoundToInt(fr), a);
int g = SkClampMax(SkFixedRoundToInt(fg), a);
int b = SkClampMax(SkFixedRoundToInt(fb), a);
*dst->getAddr32(x,y) = SkPackARGB32(a, r, g, b);
}
}
}
static void downScaleVert(const SkBitmap *src, SkBitmap *dst, float scale, SkBitmapFilter *filter) {
SkFixed *sums = SkNEW_ARRAY(SkFixed, dst->width() * dst->height() * 4);
SkFixed *weights = SkNEW_ARRAY(SkFixed, dst->width() * dst->height());
SkScalar *sums = SkNEW_ARRAY(SkScalar, dst->width() * dst->height() * 4);
SkScalar *weights = SkNEW_ARRAY(SkScalar, dst->width() * dst->height());
SkAutoTDeleteArray<SkFixed> ada1(sums);
SkAutoTDeleteArray<SkFixed> ada2(weights);
SkAutoTDeleteArray<SkScalar> ada1(sums);
SkAutoTDeleteArray<SkScalar> ada2(weights);
memset(sums, 0, dst->width() * dst->height() * sizeof(SkFixed) * 4);
memset(weights, 0, dst->width() * dst->height() * sizeof(SkFixed));
memset(sums, 0, dst->width() * dst->height() * sizeof(SkScalar) * 4);
memset(weights, 0, dst->width() * dst->height() * sizeof(SkScalar));
for (int y = 0 ; y < src->height() ; y++) {
for (int x = 0 ; x < src->width() ; x++) {
@ -322,7 +284,7 @@ static void downScaleVert(const SkBitmap *src, SkBitmap *dst, float scale, SkBit
SkPMColor c = *src->getAddr32(x,y);
for (int dst_y = y0 ; dst_y <= y1 ; dst_y++) {
SkFixed weight = filter->lookup(dy - dst_y);
SkScalar weight = filter->lookupScalar(dy - dst_y);
sums[4*(dst_y*dst->width() + x) + 0] += weight*SkGetPackedR32(c);
sums[4*(dst_y*dst->width() + x) + 1] += weight*SkGetPackedG32(c);
sums[4*(dst_y*dst->width() + x) + 2] += weight*SkGetPackedB32(c);
@ -337,31 +299,27 @@ static void downScaleVert(const SkBitmap *src, SkBitmap *dst, float scale, SkBit
void SkBitmap::scale(SkBitmap *dst) const {
SkBitmap horiz_temp;
SkBitmap horizTemp;
horiz_temp.setConfig(SkBitmap::kARGB_8888_Config, dst->width(), height());
horiz_temp.allocPixels();
horizTemp.setConfig(SkBitmap::kARGB_8888_Config, height(), dst->width());
horizTemp.allocPixels();
SkBitmapFilter *filter = allocateBitmapFilter();
float horiz_scale = float(dst->width()) / width();
float horizScale = float(dst->width()) / width();
if (horiz_scale == 1) {
this->copyPixelsTo(horiz_temp.getPixels(), getSize());
} else if (horiz_scale > 1) {
upScaleHoriz(this, &horiz_temp, horiz_scale, filter);
} else if (horiz_scale < 1) {
downScaleHoriz(this, &horiz_temp, horiz_scale, filter);
if (horizScale >= 1) {
upScaleHorizTranspose(this, &horizTemp, horizScale, filter);
} else if (horizScale < 1) {
downScaleHoriz(this, &horizTemp, horizScale, filter);
}
float vert_scale = float(dst->height()) / height();
float vertScale = float(dst->height()) / height();
if (vert_scale == 1) {
horiz_temp.copyPixelsTo(dst->getPixels(), dst->getSize());
} else if (vert_scale > 1) {
upScaleVert(&horiz_temp, dst, vert_scale, filter);
} else if (vert_scale < 1) {
downScaleVert(&horiz_temp, dst, vert_scale, filter);
if (vertScale >= 1) {
upScaleHorizTranspose(&horizTemp, dst, vertScale, filter);
} else if (vertScale < 1) {
downScaleVert(&horizTemp, dst, vertScale, filter);
}
SkDELETE(filter);

View File

@ -22,23 +22,26 @@ class SkBitmapFilter {
public:
SkBitmapFilter(float width)
: fWidth(width), fInvWidth(1.f/width) {
precomputed = false;
fPrecomputed = false;
fLookupMultiplier = this->invWidth() * (SKBITMAP_FILTER_TABLE_SIZE-1);
}
SkFixed lookup( float x ) const {
if (!precomputed) {
if (!fPrecomputed) {
precomputeTable();
}
int filter_idx = int(fabsf(x * invWidth() * SKBITMAP_FILTER_TABLE_SIZE));
return fFilterTable[ SkTMin(filter_idx, SKBITMAP_FILTER_TABLE_SIZE-1) ];
int filter_idx = int(sk_float_abs(x * fLookupMultiplier));
SkASSERT(filter_idx < SKBITMAP_FILTER_TABLE_SIZE);
return fFilterTable[ filter_idx ];
}
float lookupFloat( float x ) const {
if (!precomputed) {
SkScalar lookupScalar( float x ) const {
if (!fPrecomputed) {
precomputeTable();
}
int filter_idx = int(fabsf(x * invWidth() * SKBITMAP_FILTER_TABLE_SIZE));
return fFilterTableFloat[ SkTMin(filter_idx, SKBITMAP_FILTER_TABLE_SIZE-1) ];
int filter_idx = int(sk_float_abs(x * fLookupMultiplier));
SkASSERT(filter_idx < SKBITMAP_FILTER_TABLE_SIZE);
return fFilterTableScalar[ filter_idx ];
}
float width() const { return fWidth; }
@ -48,19 +51,21 @@ class SkBitmapFilter {
protected:
float fWidth;
float fInvWidth;
float fLookupMultiplier;
mutable bool precomputed;
mutable bool fPrecomputed;
mutable SkFixed fFilterTable[SKBITMAP_FILTER_TABLE_SIZE];
mutable float fFilterTableFloat[SKBITMAP_FILTER_TABLE_SIZE];
mutable SkScalar fFilterTableScalar[SKBITMAP_FILTER_TABLE_SIZE];
private:
void precomputeTable() const {
precomputed = true;
fPrecomputed = true;
SkFixed *ftp = fFilterTable;
float *ftp_float = fFilterTableFloat;
SkScalar *ftpScalar = fFilterTableScalar;
for (int x = 0; x < SKBITMAP_FILTER_TABLE_SIZE; ++x) {
float fx = ((float)x + .5f) * this->width() / SKBITMAP_FILTER_TABLE_SIZE;
float filter_value = evaluate(fx);
*ftp_float++ = filter_value;
*ftpScalar++ = SkFloatToScalar(filter_value);
*ftp++ = SkFloatToFixed(filter_value);
}
}

View File

@ -142,6 +142,7 @@ bool SkBitmapProcShader::setContext(const SkBitmap& device,
void SkBitmapProcShader::endContext() {
fState.fOrigBitmap.unlockPixels();
fState.endContext();
this->INHERITED::endContext();
}

View File

@ -90,220 +90,346 @@ static bool valid_for_filtering(unsigned dimension) {
return (dimension & ~0x3FFF) == 0;
}
// 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) {
return;
}
// STEP 1: UPSAMPLE?
// Check to see if the transformation matrix is scaling up, and if
// the matrix is simple, and if we're doing high quality scaling.
// If so, do the bitmap scale here and remove the scaling component from the matrix.
if (fInvMatrix.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask) &&
(fInvMatrix.getScaleX() < 1 || fInvMatrix.getScaleY() < 1) &&
fOrigBitmap.config() == SkBitmap::kARGB_8888_Config) {
// All the criteria are met; let's make a new bitmap.
fScaledBitmap.setConfig(SkBitmap::kARGB_8888_Config,
(int)(fOrigBitmap.width() / fInvMatrix.getScaleX()),
(int)(fOrigBitmap.height() / fInvMatrix.getScaleY()));
fScaledBitmap.allocPixels();
fOrigBitmap.scale(&fScaledBitmap);
fBitmap = &fScaledBitmap;
// set the inv matrix type to translate-only;
fInvMatrix.setTranslate( 1/fInvMatrix.getScaleX() * fInvMatrix.getTranslateX(),
1/fInvMatrix.getScaleY() * fInvMatrix.getTranslateY() );
// no need for any further filtering; we just did it!
fFilterQuality = kNone_BitmapFilter;
return;
}
if (!fOrigBitmap.hasMipMap()) {
// STEP 2: 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.
v1.fX = fInvMatrix.getScaleX();
v1.fY = fInvMatrix.getSkewY();
v2.fX = fInvMatrix.getSkewX();
v2.fY = fInvMatrix.getScaleY();
if (v1.fX * v1.fX + v1.fY * v1.fY > 1 ||
v2.fX * v2.fX + v2.fY * v2.fY > 1) {
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;
}
}
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;
}
}
}
void SkBitmapProcState::endContext() {
SkDELETE(fBitmapFilter);
fBitmapFilter = NULL;
fScaledBitmap.reset();
}
bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
if (fOrigBitmap.width() == 0 || fOrigBitmap.height() == 0) {
return false;
}
const SkMatrix* m;
bool trivial_matrix = (inv.getType() & ~SkMatrix::kTranslate_Mask) == 0;
bool clamp_clamp = SkShader::kClamp_TileMode == fTileModeX &&
bool trivialMatrix = (inv.getType() & ~SkMatrix::kTranslate_Mask) == 0;
bool clampClamp = SkShader::kClamp_TileMode == fTileModeX &&
SkShader::kClamp_TileMode == fTileModeY;
if (clamp_clamp || trivial_matrix) {
m = &inv;
} else {
fUnitInvMatrix = inv;
fUnitInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height());
m = &fUnitInvMatrix;
fInvMatrix = inv;
if (!(clampClamp || trivialMatrix)) {
fInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height());
}
fBitmap = &fOrigBitmap;
if (fOrigBitmap.hasMipMap()) {
int shift = fOrigBitmap.extractMipLevel(&fMipBitmap,
SkScalarToFixed(m->getScaleX()),
SkScalarToFixed(m->getSkewY()));
if (shift > 0) {
if (m != &fUnitInvMatrix) {
fUnitInvMatrix = *m;
m = &fUnitInvMatrix;
}
SkScalar scale = SkFixedToScalar(SK_Fixed1 >> shift);
fUnitInvMatrix.postScale(scale, scale);
// now point here instead of fOrigBitmap
fBitmap = &fMipBitmap;
// initialize our filter quality to the one requested by the caller.
// 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;
}
}
// wack our matrix to exactly no-scale, if we're really close to begin with
if (matrix_only_scale_translate(*m)) {
#ifndef SK_IGNORE_IMAGE_PRESCALE
// possiblyScaleImage will look to see if it can rescale the image as a
// preprocess; either by scaling up to the target size, or by selecting
// a nearby mipmap level. If it does, it will adjust the working
// matrix as well as the working bitmap. It may also adjust the filter
// quality to avoid re-filtering an already perfectly scaled image.
this->possiblyScaleImage();
#endif
// Now that all possible changes to the matrix have taken place, check
// to see if we're really close to a no-scale matrix. If so, explicitly
// set it to be so. Subsequent code may inspect this matrix to choose
// a faster path in this case.
// This code will only execute if the matrix has some scale component;
// if it's already pure translate then we won't do this inversion.
if (matrix_only_scale_translate(fInvMatrix)) {
SkMatrix forward;
if (m->invert(&forward)) {
if (clamp_clamp ? just_trans_clamp(forward, *fBitmap)
if (fInvMatrix.invert(&forward)) {
if (clampClamp ? just_trans_clamp(forward, *fBitmap)
: just_trans_general(forward)) {
SkScalar tx = -SkScalarRoundToScalar(forward.getTranslateX());
SkScalar ty = -SkScalarRoundToScalar(forward.getTranslateY());
fUnitInvMatrix.setTranslate(tx, ty);
m = &fUnitInvMatrix;
// now the following code will sniff m, and decide to take the
// fast case (since m is purely translate).
fInvMatrix.setTranslate(tx, ty);
}
}
}
// Below this point, we should never refer to the inv parameter, since we
// may be using a munged version for "our" inverse.
fInvMatrix = m;
fInvProc = m->getMapXYProc();
fInvType = m->getType();
fInvSx = SkScalarToFixed(m->getScaleX());
fInvSxFractionalInt = SkScalarToFractionalInt(m->getScaleX());
fInvKy = SkScalarToFixed(m->getSkewY());
fInvKyFractionalInt = SkScalarToFractionalInt(m->getSkewY());
fInvProc = fInvMatrix.getMapXYProc();
fInvType = fInvMatrix.getType();
fInvSx = SkScalarToFixed(fInvMatrix.getScaleX());
fInvSxFractionalInt = SkScalarToFractionalInt(fInvMatrix.getScaleX());
fInvKy = SkScalarToFixed(fInvMatrix.getSkewY());
fInvKyFractionalInt = SkScalarToFractionalInt(fInvMatrix.getSkewY());
fAlphaScale = SkAlpha255To256(paint.getAlpha());
// 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;
// recompute the triviality of the matrix here because we may have
// changed it!
trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0;
fMatrixProc = this->chooseMatrixProc(trivial_matrix);
if (kHQ_BitmapFilter == fFilterQuality) {
// 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,
// downgrade to bilerp.
// NOTE: Might need to be careful here in the future when we want
// to have the platform proc have a shot at this; it's possible that
// the chooseBitmapFilterProc will fail to install a shader but a
// platform-specific one might succeed, so it might be premature here
// to fall back to bilerp. This needs thought.
SkASSERT(fInvType > SkMatrix::kTranslate_Mask);
fShaderProc32 = this->chooseBitmapFilterProc();
if (!fShaderProc32) {
fFilterQuality = kBilerp_BitmapFilter;
}
}
if (kBilerp_BitmapFilter == fFilterQuality) {
// 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;
}
}
// At this point, we know exactly what kind of sampling the per-scanline
// shader will perform.
fMatrixProc = this->chooseMatrixProc(trivialMatrix);
if (NULL == fMatrixProc) {
return false;
}
///////////////////////////////////////////////////////////////////////
int index = 0;
if (fAlphaScale < 256) { // note: this distinction is not used for D16
index |= 1;
}
if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
index |= 2;
}
if (fDoFilter) {
index |= 4;
}
// bits 3,4,5 encoding the source bitmap format
switch (fBitmap->config()) {
case SkBitmap::kARGB_8888_Config:
index |= 0;
break;
case SkBitmap::kRGB_565_Config:
index |= 8;
break;
case SkBitmap::kIndex8_Config:
index |= 16;
break;
case SkBitmap::kARGB_4444_Config:
index |= 24;
break;
case SkBitmap::kA8_Config:
index |= 32;
fPaintPMColor = SkPreMultiplyColor(paint.getColor());
break;
default:
return false;
}
// No need to do this if we're doing HQ sampling; if filter quality is
// 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 !SK_ARM_NEON_IS_ALWAYS
static const SampleProc32 gSkBitmapProcStateSample32[] = {
S32_opaque_D32_nofilter_DXDY,
S32_alpha_D32_nofilter_DXDY,
S32_opaque_D32_nofilter_DX,
S32_alpha_D32_nofilter_DX,
S32_opaque_D32_filter_DXDY,
S32_alpha_D32_filter_DXDY,
S32_opaque_D32_filter_DX,
S32_alpha_D32_filter_DX,
S16_opaque_D32_nofilter_DXDY,
S16_alpha_D32_nofilter_DXDY,
S16_opaque_D32_nofilter_DX,
S16_alpha_D32_nofilter_DX,
S16_opaque_D32_filter_DXDY,
S16_alpha_D32_filter_DXDY,
S16_opaque_D32_filter_DX,
S16_alpha_D32_filter_DX,
SI8_opaque_D32_nofilter_DXDY,
SI8_alpha_D32_nofilter_DXDY,
SI8_opaque_D32_nofilter_DX,
SI8_alpha_D32_nofilter_DX,
SI8_opaque_D32_filter_DXDY,
SI8_alpha_D32_filter_DXDY,
SI8_opaque_D32_filter_DX,
SI8_alpha_D32_filter_DX,
S4444_opaque_D32_nofilter_DXDY,
S4444_alpha_D32_nofilter_DXDY,
S4444_opaque_D32_nofilter_DX,
S4444_alpha_D32_nofilter_DX,
S4444_opaque_D32_filter_DXDY,
S4444_alpha_D32_filter_DXDY,
S4444_opaque_D32_filter_DX,
S4444_alpha_D32_filter_DX,
// A8 treats alpha/opaque the same (equally efficient)
SA8_alpha_D32_nofilter_DXDY,
SA8_alpha_D32_nofilter_DXDY,
SA8_alpha_D32_nofilter_DX,
SA8_alpha_D32_nofilter_DX,
SA8_alpha_D32_filter_DXDY,
SA8_alpha_D32_filter_DXDY,
SA8_alpha_D32_filter_DX,
SA8_alpha_D32_filter_DX
};
static const SampleProc16 gSkBitmapProcStateSample16[] = {
S32_D16_nofilter_DXDY,
S32_D16_nofilter_DX,
S32_D16_filter_DXDY,
S32_D16_filter_DX,
S16_D16_nofilter_DXDY,
S16_D16_nofilter_DX,
S16_D16_filter_DXDY,
S16_D16_filter_DX,
SI8_D16_nofilter_DXDY,
SI8_D16_nofilter_DX,
SI8_D16_filter_DXDY,
SI8_D16_filter_DX,
// Don't support 4444 -> 565
NULL, NULL, NULL, NULL,
// Don't support A8 -> 565
NULL, NULL, NULL, NULL
};
#endif
fSampleProc32 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample32)[index];
index >>= 1; // shift away any opaque/alpha distinction
fSampleProc16 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample16)[index];
// our special-case shaderprocs
if (SK_ARM_NEON_WRAP(S16_D16_filter_DX) == fSampleProc16) {
if (clamp_clamp) {
fShaderProc16 = SK_ARM_NEON_WRAP(Clamp_S16_D16_filter_DX_shaderproc);
} else if (SkShader::kRepeat_TileMode == fTileModeX &&
SkShader::kRepeat_TileMode == fTileModeY) {
fShaderProc16 = SK_ARM_NEON_WRAP(Repeat_S16_D16_filter_DX_shaderproc);
if (fFilterQuality < kHQ_BitmapFilter) {
int index = 0;
if (fAlphaScale < 256) { // note: this distinction is not used for D16
index |= 1;
}
if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
index |= 2;
}
if (fFilterQuality != kNone_BitmapFilter) {
index |= 4;
}
// bits 3,4,5 encoding the source bitmap format
switch (fBitmap->config()) {
case SkBitmap::kARGB_8888_Config:
index |= 0;
break;
case SkBitmap::kRGB_565_Config:
index |= 8;
break;
case SkBitmap::kIndex8_Config:
index |= 16;
break;
case SkBitmap::kARGB_4444_Config:
index |= 24;
break;
case SkBitmap::kA8_Config:
index |= 32;
fPaintPMColor = SkPreMultiplyColor(paint.getColor());
break;
default:
return false;
}
} else if (SK_ARM_NEON_WRAP(SI8_opaque_D32_filter_DX) == fSampleProc32 && clamp_clamp) {
fShaderProc32 = SK_ARM_NEON_WRAP(Clamp_SI8_opaque_D32_filter_DX_shaderproc);
}
if (NULL == fShaderProc32) {
fShaderProc32 = this->chooseShaderProc32();
}
#if !SK_ARM_NEON_IS_ALWAYS
static const SampleProc32 gSkBitmapProcStateSample32[] = {
S32_opaque_D32_nofilter_DXDY,
S32_alpha_D32_nofilter_DXDY,
S32_opaque_D32_nofilter_DX,
S32_alpha_D32_nofilter_DX,
S32_opaque_D32_filter_DXDY,
S32_alpha_D32_filter_DXDY,
S32_opaque_D32_filter_DX,
S32_alpha_D32_filter_DX,
if (NULL == fShaderProc32) {
fShaderProc32 = this->chooseBitmapFilterProc(paint);
S16_opaque_D32_nofilter_DXDY,
S16_alpha_D32_nofilter_DXDY,
S16_opaque_D32_nofilter_DX,
S16_alpha_D32_nofilter_DX,
S16_opaque_D32_filter_DXDY,
S16_alpha_D32_filter_DXDY,
S16_opaque_D32_filter_DX,
S16_alpha_D32_filter_DX,
SI8_opaque_D32_nofilter_DXDY,
SI8_alpha_D32_nofilter_DXDY,
SI8_opaque_D32_nofilter_DX,
SI8_alpha_D32_nofilter_DX,
SI8_opaque_D32_filter_DXDY,
SI8_alpha_D32_filter_DXDY,
SI8_opaque_D32_filter_DX,
SI8_alpha_D32_filter_DX,
S4444_opaque_D32_nofilter_DXDY,
S4444_alpha_D32_nofilter_DXDY,
S4444_opaque_D32_nofilter_DX,
S4444_alpha_D32_nofilter_DX,
S4444_opaque_D32_filter_DXDY,
S4444_alpha_D32_filter_DXDY,
S4444_opaque_D32_filter_DX,
S4444_alpha_D32_filter_DX,
// A8 treats alpha/opaque the same (equally efficient)
SA8_alpha_D32_nofilter_DXDY,
SA8_alpha_D32_nofilter_DXDY,
SA8_alpha_D32_nofilter_DX,
SA8_alpha_D32_nofilter_DX,
SA8_alpha_D32_filter_DXDY,
SA8_alpha_D32_filter_DXDY,
SA8_alpha_D32_filter_DX,
SA8_alpha_D32_filter_DX
};
static const SampleProc16 gSkBitmapProcStateSample16[] = {
S32_D16_nofilter_DXDY,
S32_D16_nofilter_DX,
S32_D16_filter_DXDY,
S32_D16_filter_DX,
S16_D16_nofilter_DXDY,
S16_D16_nofilter_DX,
S16_D16_filter_DXDY,
S16_D16_filter_DX,
SI8_D16_nofilter_DXDY,
SI8_D16_nofilter_DX,
SI8_D16_filter_DXDY,
SI8_D16_filter_DX,
// Don't support 4444 -> 565
NULL, NULL, NULL, NULL,
// Don't support A8 -> 565
NULL, NULL, NULL, NULL
};
#endif
fSampleProc32 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample32)[index];
index >>= 1; // shift away any opaque/alpha distinction
fSampleProc16 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample16)[index];
// our special-case shaderprocs
if (SK_ARM_NEON_WRAP(S16_D16_filter_DX) == fSampleProc16) {
if (clampClamp) {
fShaderProc16 = SK_ARM_NEON_WRAP(Clamp_S16_D16_filter_DX_shaderproc);
} else if (SkShader::kRepeat_TileMode == fTileModeX &&
SkShader::kRepeat_TileMode == fTileModeY) {
fShaderProc16 = SK_ARM_NEON_WRAP(Repeat_S16_D16_filter_DX_shaderproc);
}
} else if (SK_ARM_NEON_WRAP(SI8_opaque_D32_filter_DX) == fSampleProc32 && clampClamp) {
fShaderProc32 = SK_ARM_NEON_WRAP(Clamp_SI8_opaque_D32_filter_DX_shaderproc);
}
if (NULL == fShaderProc32) {
fShaderProc32 = this->chooseShaderProc32();
}
}
// see if our platform has any accelerated overrides
@ -319,7 +445,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(SkBitmapProcState::kNone_BitmapFilter == s.fFilterQuality);
const int maxX = s.fBitmap->width() - 1;
const int maxY = s.fBitmap->height() - 1;
@ -328,7 +454,7 @@ static void Clamp_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s,
#ifdef SK_DEBUG
{
SkPoint pt;
s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &pt);
int iy2 = SkClampMax(SkScalarFloorToInt(pt.fY), maxY);
int ix2 = SkScalarFloorToInt(pt.fX);
@ -393,7 +519,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(SkBitmapProcState::kNone_BitmapFilter == s.fFilterQuality);
const int stopX = s.fBitmap->width();
const int stopY = s.fBitmap->height();
@ -402,7 +528,7 @@ static void Repeat_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s,
#ifdef SK_DEBUG
{
SkPoint pt;
s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &pt);
int iy2 = sk_int_mod(SkScalarFloorToInt(pt.fY), stopY);
int ix2 = SkScalarFloorToInt(pt.fX);
@ -439,7 +565,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];
@ -453,7 +579,7 @@ static void S32_D32_constX_shaderproc(const SkBitmapProcState& s,
if (s.fInvType > SkMatrix::kTranslate_Mask) {
SkPoint pt;
s.fInvProc(*s.fInvMatrix,
s.fInvProc(s.fInvMatrix,
SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf,
&pt);
@ -488,7 +614,7 @@ static void S32_D32_constX_shaderproc(const SkBitmapProcState& s,
#ifdef SK_DEBUG
{
SkPoint pt;
s.fInvProc(*s.fInvMatrix,
s.fInvProc(s.fInvMatrix,
SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf,
&pt);
@ -520,7 +646,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) {
@ -547,7 +673,7 @@ static void DoNothing_shaderproc(const SkBitmapProcState&, int x, int y,
bool SkBitmapProcState::setupForTranslate() {
SkPoint pt;
fInvProc(*fInvMatrix, SK_ScalarHalf, SK_ScalarHalf, &pt);
fInvProc(fInvMatrix, SK_ScalarHalf, SK_ScalarHalf, &pt);
/*
* if the translate is larger than our ints, we can get random results, or
@ -576,7 +702,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 (kNone_BitmapFilter == fFilterQuality &&
fInvType <= SkMatrix::kTranslate_Mask &&
!this->setupForTranslate()) {
return DoNothing_shaderproc;
}
return S32_D32_constX_shaderproc;
@ -588,7 +716,7 @@ SkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() {
if (fInvType > SkMatrix::kTranslate_Mask) {
return NULL;
}
if (fDoFilter) {
if (fFilterQuality != kNone_BitmapFilter) {
return NULL;
}
@ -684,9 +812,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 +849,7 @@ int SkBitmapProcState::maxCountForBufferSize(size_t bufferSize) const {
size >>= 2;
}
if (fDoFilter) {
if (fFilterQuality != kNone_BitmapFilter) {
size >>= 1;
}

View File

@ -33,7 +33,7 @@
class SkPaint;
struct SkBitmapProcState {
SkBitmapProcState(): fBitmapFilter(NULL) {}
~SkBitmapProcState() {
SkDELETE(fBitmapFilter);
@ -64,8 +64,8 @@ struct SkBitmapProcState {
typedef U16CPU (*FixedTileLowBitsProc)(SkFixed, int); // returns 0..0xF
typedef U16CPU (*IntTileProc)(int value, int count); // returns 0..count-1
const SkBitmap* fBitmap; // chooseProcs - orig or mip
const SkMatrix* fInvMatrix; // chooseProcs
const SkBitmap* fBitmap; // chooseProcs - orig or scaled
SkMatrix fInvMatrix; // chooseProcs
SkMatrix::MapXYProc fInvProc; // chooseProcs
SkFractionalInt fInvSxFractionalInt;
@ -86,7 +86,18 @@ struct SkBitmapProcState {
uint8_t fInvType; // chooseProcs
uint8_t fTileModeX; // CONSTRUCTOR
uint8_t fTileModeY; // CONSTRUCTOR
SkBool8 fDoFilter; // chooseProcs
enum {
kNone_BitmapFilter,
kBilerp_BitmapFilter,
kHQ_BitmapFilter
} fFilterQuality; // chooseProcs
/** The shader will let us know when we can release some of our resources
* like scaled bitmaps.
*/
void endContext();
/** Platforms implement this, and can optionally overwrite only the
following fields:
@ -140,18 +151,18 @@ private:
SampleProc32 fSampleProc32; // chooseProcs
SampleProc16 fSampleProc16; // chooseProcs
SkMatrix fUnitInvMatrix; // chooseProcs
SkBitmap fOrigBitmap; // CONSTRUCTOR
SkBitmap fMipBitmap;
SkBitmap fScaledBitmap; // chooseProcs
MatrixProc chooseMatrixProc(bool trivial_matrix);
bool chooseProcs(const SkMatrix& inv, const SkPaint&);
ShaderProc32 chooseShaderProc32();
void possiblyScaleImage();
void buildFilterCoefficients(SkFixed dst[4], float t) const;
SkBitmapFilter *fBitmapFilter;
ShaderProc32 chooseBitmapFilterProc(const SkPaint &paint);
ShaderProc32 chooseBitmapFilterProc();
// Return false if we failed to setup for fast translate (e.g. overflow)
bool setupForTranslate();

View File

@ -55,7 +55,7 @@ void SCALE_NOFILTER_NAME(const SkBitmapProcState& s,
SkFractionalInt fx;
{
SkPoint pt;
s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &pt);
fx = SkScalarToFractionalInt(pt.fY);
const unsigned maxY = s.fBitmap->height() - 1;
@ -116,7 +116,7 @@ void AFFINE_NOFILTER_NAME(const SkBitmapProcState& s,
PREAMBLE(s);
SkPoint srcPt;
s.fInvProc(*s.fInvMatrix,
s.fInvProc(s.fInvMatrix,
SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
@ -143,7 +143,7 @@ void PERSP_NOFILTER_NAME(const SkBitmapProcState& s,
int maxX = s.fBitmap->width() - 1;
int maxY = s.fBitmap->height() - 1;
SkPerspIter iter(*s.fInvMatrix,
SkPerspIter iter(s.fInvMatrix,
SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, count);
@ -188,7 +188,7 @@ void SCALE_FILTER_NAME(const SkBitmapProcState& s,
{
SkPoint pt;
s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &pt);
const SkFixed fy = SkScalarToFixed(pt.fY) - (s.fFilterOneY >> 1);
const unsigned maxY = s.fBitmap->height() - 1;
@ -222,7 +222,7 @@ void AFFINE_FILTER_NAME(const SkBitmapProcState& s,
PREAMBLE(s);
SkPoint srcPt;
s.fInvProc(*s.fInvMatrix,
s.fInvProc(s.fInvMatrix,
SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
@ -254,7 +254,7 @@ void PERSP_FILTER_NAME(const SkBitmapProcState& s,
SkFixed oneX = s.fFilterOneX;
SkFixed oneY = s.fFilterOneY;
SkPerspIter iter(*s.fInvMatrix,
SkPerspIter iter(s.fInvMatrix,
SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, count);

View File

@ -311,7 +311,7 @@ static void fill_sequential(uint16_t xptr[], int start, int count) {
static int nofilter_trans_preamble(const SkBitmapProcState& s, uint32_t** xy,
int x, int y) {
SkPoint pt;
s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &pt);
**xy = s.fIntTileProcY(SkScalarToFixed(pt.fY) >> 16,
s.fBitmap->height());
@ -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(!fDoFilter);
SkASSERT(kNone_BitmapFilter == fFilterQuality);
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 (fDoFilter) {
if (fFilterQuality != kNone_BitmapFilter) {
index = 1;
}
if (fInvType & SkMatrix::kPerspective_Mask) {

View File

@ -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(s.fDoFilter == false);
SkASSERT(SkBitmapProcState::kNone_BitmapFilter == s.fFilterQuality);
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(s.fDoFilter == false);
SkASSERT(SkBitmapProcState::kNone_BitmapFilter == s.fFilterQuality);
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.fDoFilter);
SkASSERT(s.fFilterQuality != SkBitmapProcState::kNone_BitmapFilter);
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.fDoFilter);
SkASSERT(s.fFilterQuality != SkBitmapProcState::kNone_BitmapFilter);
SkDEBUGCODE(CHECKSTATE(s);)
#ifdef PREAMBLE

View File

@ -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.fDoFilter);
SkASSERT(s.fFilterQuality != SkBitmapProcState::kNone_BitmapFilter);
SkDEBUGCODE(CHECKSTATE(s);)
const unsigned maxX = s.fBitmap->width() - 1;
@ -34,7 +34,7 @@ void SCALE_FILTER_NAME(const SkBitmapProcState& s, int x, int y,
{
SkPoint pt;
s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &pt);
SkFixed fy = SkScalarToFixed(pt.fY) - (s.fFilterOneY >> 1);
const unsigned maxY = s.fBitmap->height() - 1;

View File

@ -55,7 +55,7 @@ void highQualityFilter_SSE2(const SkBitmapProcState& s, int x, int y,
while (count-- > 0) {
SkPoint srcPt;
s.fInvProc(*s.fInvMatrix, SkIntToScalar(x),
s.fInvProc(s.fInvMatrix, SkIntToScalar(x),
SkIntToScalar(y), &srcPt);
srcPt.fX -= SK_ScalarHalf;
srcPt.fY -= SK_ScalarHalf;
@ -72,10 +72,10 @@ void highQualityFilter_SSE2(const SkBitmapProcState& s, int x, int y,
int x1 = SkTMin(maxX, int(floor(sx+s.getBitmapFilter()->width() + 0.5f)));
for (int src_y = y0; src_y <= y1; src_y++) {
float yweight = s.getBitmapFilter()->lookupFloat( (srcPt.fY - src_y) );
float yweight = SkScalarToFloat(s.getBitmapFilter()->lookupScalar(srcPt.fY - src_y));
for (int src_x = x0; src_x <= x1 ; src_x++) {
float xweight = s.getBitmapFilter()->lookupFloat( (srcPt.fX - src_x) );
float xweight = SkScalarToFloat(s.getBitmapFilter()->lookupScalar(srcPt.fX - src_x));
float combined_weight = xweight * yweight;
@ -118,7 +118,7 @@ void highQualityFilter_ScaleOnly_SSE2(const SkBitmapProcState &s, int x, int y,
const int maxY = s.fBitmap->height() - 1;
SkPoint srcPt;
s.fInvProc(*s.fInvMatrix, SkIntToScalar(x),
s.fInvProc(s.fInvMatrix, SkIntToScalar(x),
SkIntToScalar(y), &srcPt);
srcPt.fY -= SK_ScalarHalf;
int sy = SkScalarFloorToInt(srcPt.fY);
@ -139,10 +139,10 @@ void highQualityFilter_ScaleOnly_SSE2(const SkBitmapProcState &s, int x, int y,
int x1 = SkTMin(maxX, int(floor(sx+s.getBitmapFilter()->width() + 0.5f)));
for (int src_y = y0; src_y <= y1; src_y++) {
float yweight = s.getBitmapFilter()->lookupFloat( (srcPt.fY - src_y) );
float yweight = SkScalarToFloat(s.getBitmapFilter()->lookupScalar(srcPt.fY - src_y));
for (int src_x = x0; src_x <= x1 ; src_x++) {
float xweight = s.getBitmapFilter()->lookupFloat( (srcPt.fX - src_x) );
float xweight = SkScalarToFloat(s.getBitmapFilter()->lookupScalar(srcPt.fX - src_x));
float combined_weight = xweight * yweight;
@ -175,7 +175,7 @@ void highQualityFilter_ScaleOnly_SSE2(const SkBitmapProcState &s, int x, int y,
x++;
s.fInvProc(*s.fInvMatrix, SkIntToScalar(x),
s.fInvProc(s.fInvMatrix, SkIntToScalar(x),
SkIntToScalar(y), &srcPt);
}

View File

@ -67,8 +67,8 @@ static void SCALE_NOFILTER_NAME(const SkBitmapProcState& s,
SkFixed fx;
{
SkPoint pt;
s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &pt);
s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &pt);
fx = SkScalarToFixed(pt.fY);
const unsigned maxY = s.fBitmap->height() - 1;
*xy++ = TILEY_PROCF(fx, maxY);
@ -169,7 +169,7 @@ static void AFFINE_NOFILTER_NAME(const SkBitmapProcState& s,
PREAMBLE(s);
SkPoint srcPt;
s.fInvProc(*s.fInvMatrix,
s.fInvProc(s.fInvMatrix,
SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
@ -282,7 +282,7 @@ static void PERSP_NOFILTER_NAME(const SkBitmapProcState& s,
int maxX = s.fBitmap->width() - 1;
int maxY = s.fBitmap->height() - 1;
SkPerspIter iter(*s.fInvMatrix,
SkPerspIter iter(s.fInvMatrix,
SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, count);
@ -492,8 +492,8 @@ static void SCALE_FILTER_NAME(const SkBitmapProcState& s,
{
SkPoint pt;
s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &pt);
s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &pt);
const SkFixed fy = SkScalarToFixed(pt.fY) - (s.fFilterOneY >> 1);
const unsigned maxY = s.fBitmap->height() - 1;
// compute our two Y values up front
@ -596,7 +596,7 @@ static void AFFINE_FILTER_NAME(const SkBitmapProcState& s,
PREAMBLE(s);
SkPoint srcPt;
s.fInvProc(*s.fInvMatrix,
s.fInvProc(s.fInvMatrix,
SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
@ -757,7 +757,7 @@ static void PERSP_FILTER_NAME(const SkBitmapProcState& s,
SkFixed oneX = s.fFilterOneX;
SkFixed oneY = s.fFilterOneY;
SkPerspIter iter(*s.fInvMatrix,
SkPerspIter iter(s.fInvMatrix,
SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, count);

View File

@ -65,8 +65,8 @@ static void SCALE_NOFILTER_NAME(const SkBitmapProcState& s,
SkFixed fx;
{
SkPoint pt;
s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &pt);
s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &pt);
fx = SkScalarToFixed(pt.fY);
const unsigned maxY = s.fBitmap->height() - 1;
*xy++ = TILEY_PROCF(fx, maxY);
@ -167,7 +167,7 @@ static void AFFINE_NOFILTER_NAME(const SkBitmapProcState& s,
PREAMBLE(s);
SkPoint srcPt;
s.fInvProc(*s.fInvMatrix,
s.fInvProc(s.fInvMatrix,
SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
@ -284,7 +284,7 @@ static void PERSP_NOFILTER_NAME(const SkBitmapProcState& s,
int maxX = s.fBitmap->width() - 1;
int maxY = s.fBitmap->height() - 1;
SkPerspIter iter(*s.fInvMatrix,
SkPerspIter iter(s.fInvMatrix,
SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, count);
@ -422,8 +422,8 @@ static void SCALE_FILTER_NAME(const SkBitmapProcState& s,
{
SkPoint pt;
s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &pt);
s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &pt);
const SkFixed fy = SkScalarToFixed(pt.fY) - (s.fFilterOneY >> 1);
const unsigned maxY = s.fBitmap->height() - 1;
// compute our two Y values up front
@ -457,7 +457,7 @@ static void AFFINE_FILTER_NAME(const SkBitmapProcState& s,
PREAMBLE(s);
SkPoint srcPt;
s.fInvProc(*s.fInvMatrix,
s.fInvProc(s.fInvMatrix,
SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
@ -493,7 +493,7 @@ static void PERSP_FILTER_NAME(const SkBitmapProcState& s,
SkPerspIter iter(*s.fInvMatrix,
SkPerspIter iter(s.fInvMatrix,
SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, count);

View File

@ -15,7 +15,7 @@ void S32_opaque_D32_filter_DX_SSE2(const SkBitmapProcState& s,
const uint32_t* xy,
int count, uint32_t* colors) {
SkASSERT(count > 0 && colors != NULL);
SkASSERT(s.fDoFilter);
SkASSERT(s.fFilterQuality != SkBitmapProcState::kNone_BitmapFilter);
SkASSERT(s.fBitmap->config() == SkBitmap::kARGB_8888_Config);
SkASSERT(s.fAlphaScale == 256);
@ -121,7 +121,7 @@ void S32_alpha_D32_filter_DX_SSE2(const SkBitmapProcState& s,
const uint32_t* xy,
int count, uint32_t* colors) {
SkASSERT(count > 0 && colors != NULL);
SkASSERT(s.fDoFilter);
SkASSERT(s.fFilterQuality != SkBitmapProcState::kNone_BitmapFilter);
SkASSERT(s.fBitmap->config() == SkBitmap::kARGB_8888_Config);
SkASSERT(s.fAlphaScale < 256);
@ -255,8 +255,8 @@ void ClampX_ClampY_filter_scale_SSE2(const SkBitmapProcState& s, uint32_t xy[],
SkFixed fx;
SkPoint pt;
s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &pt);
s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &pt);
const SkFixed fy = SkScalarToFixed(pt.fY) - (s.fFilterOneY >> 1);
const unsigned maxY = s.fBitmap->height() - 1;
// compute our two Y values up front
@ -376,8 +376,8 @@ void ClampX_ClampY_nofilter_scale_SSE2(const SkBitmapProcState& s,
const unsigned maxX = s.fBitmap->width() - 1;
SkFixed fx;
SkPoint pt;
s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &pt);
s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &pt);
fx = SkScalarToFixed(pt.fY);
const unsigned maxY = s.fBitmap->height() - 1;
*xy++ = SkClampMax(fx >> 16, maxY);
@ -490,7 +490,7 @@ void ClampX_ClampY_nofilter_scale_SSE2(const SkBitmapProcState& s,
void ClampX_ClampY_filter_affine_SSE2(const SkBitmapProcState& s,
uint32_t xy[], int count, int x, int y) {
SkPoint srcPt;
s.fInvProc(*s.fInvMatrix,
s.fInvProc(s.fInvMatrix,
SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
@ -566,7 +566,7 @@ void ClampX_ClampY_nofilter_affine_SSE2(const SkBitmapProcState& s,
SkMatrix::kAffine_Mask)) == 0);
SkPoint srcPt;
s.fInvProc(*s.fInvMatrix,
s.fInvProc(s.fInvMatrix,
SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
@ -641,7 +641,7 @@ void S32_D16_filter_DX_SSE2(const SkBitmapProcState& s,
const uint32_t* xy,
int count, uint16_t* colors) {
SkASSERT(count > 0 && colors != NULL);
SkASSERT(s.fDoFilter);
SkASSERT(s.fFilterQuality != SkBitmapProcState::kNone_BitmapFilter);
SkASSERT(s.fBitmap->config() == SkBitmap::kARGB_8888_Config);
SkASSERT(s.fBitmap->isOpaque());

View File

@ -385,7 +385,7 @@ void S32_generic_D32_filter_DX_SSSE3(const SkBitmapProcState& s,
const uint32_t* xy,
int count, uint32_t* colors) {
SkASSERT(count > 0 && colors != NULL);
SkASSERT(s.fDoFilter);
SkASSERT(s.fFilterQuality != SkBitmapProcState::kNone_BitmapFilter);
SkASSERT(s.fBitmap->config() == SkBitmap::kARGB_8888_Config);
if (has_alpha) {
SkASSERT(s.fAlphaScale < 256);
@ -576,7 +576,7 @@ void S32_generic_D32_filter_DXDY_SSSE3(const SkBitmapProcState& s,
const uint32_t* xy,
int count, uint32_t* colors) {
SkASSERT(count > 0 && colors != NULL);
SkASSERT(s.fDoFilter);
SkASSERT(s.fFilterQuality != SkBitmapProcState::kNone_BitmapFilter);
SkASSERT(s.fBitmap->config() == SkBitmap::kARGB_8888_Config);
if (has_alpha) {
SkASSERT(s.fAlphaScale < 256);

View File

@ -23,7 +23,7 @@ void SI8_D16_nofilter_DX_arm(const SkBitmapProcState& s,
int count, uint16_t* SK_RESTRICT colors) {
SkASSERT(count > 0 && colors != NULL);
SkASSERT(s.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask));
SkASSERT(s.fDoFilter == false);
SkASSERT(SkBitmapProcState::kNone_BitmapFilter == s.fFilterQuality);
const uint16_t* SK_RESTRICT table = s.fBitmap->getColorTable()->lock16BitCache();
const uint8_t* SK_RESTRICT srcAddr = (const uint8_t*)s.fBitmap->getPixels();
@ -114,7 +114,7 @@ void SI8_opaque_D32_nofilter_DX_arm(const SkBitmapProcState& s,
int count, SkPMColor* SK_RESTRICT colors) {
SkASSERT(count > 0 && colors != NULL);
SkASSERT(s.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask));
SkASSERT(s.fDoFilter == false);
SkASSERT(SkBitmapProcState::kNone_BitmapFilter == s.fFilterQuality);
const SkPMColor* SK_RESTRICT table = s.fBitmap->getColorTable()->lockColors();
const uint8_t* SK_RESTRICT srcAddr = (const uint8_t*)s.fBitmap->getPixels();
@ -190,7 +190,6 @@ void SI8_opaque_D32_nofilter_DX_arm(const SkBitmapProcState& s,
otherwise the shader won't even look at the matrix/sampler
*/
void SkBitmapProcState::platformProcs() {
bool doFilter = fDoFilter;
bool isOpaque = 256 == fAlphaScale;
bool justDx = false;
@ -201,7 +200,7 @@ void SkBitmapProcState::platformProcs() {
switch (fBitmap->config()) {
case SkBitmap::kIndex8_Config:
#if SK_ARM_ARCH >= 6 && !defined(SK_CPU_BENDIAN)
if (justDx && !doFilter) {
if (justDx && kNone_BitmapFilter == fFilterQuality) {
#if 0 /* crashing on android device */
fSampleProc16 = SI8_D16_nofilter_DX_arm;
fShaderProc16 = NULL;