Fast path for blurred round rects -- blur a small 9patch rect on the CPU
And nonlinearly stretch the resulting texture across proxy geometry. BUG= Committed: http://code.google.com/p/skia/source/detail?r=14392 Committed: http://code.google.com/p/skia/source/detail?r=14404 R=bsalomon@google.com, reed@google.com Author: humper@google.com Review URL: https://codereview.chromium.org/248613004 git-svn-id: http://skia.googlecode.com/svn/trunk@14420 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
0974a618fe
commit
3d8bf232bd
@ -57,3 +57,6 @@ aaclip
|
|||||||
composeshader
|
composeshader
|
||||||
peekpixels
|
peekpixels
|
||||||
|
|
||||||
|
# humper: https://codereview.chromium.org/248613004/
|
||||||
|
# Changed the test in a few ways, will need rebaselining.
|
||||||
|
simpleblurroundrect
|
||||||
|
@ -106,30 +106,32 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual SkISize onISize() SK_OVERRIDE {
|
virtual SkISize onISize() SK_OVERRIDE {
|
||||||
return SkISize::Make(750, 750);
|
return SkISize::Make(950, 950);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
|
virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
|
||||||
canvas->scale(1.5f, 1.5f);
|
canvas->scale(1.5f, 1.5f);
|
||||||
|
canvas->translate(50,50);
|
||||||
|
|
||||||
const int blurRadii[] = { 1, 3, 6, 10 };
|
const float blurRadii[] = { 1,5,10,20 };
|
||||||
const int cornerRadii[] = { 1, 3, 6, 10 };
|
const int cornerRadii[] = { 1,5,10,20 };
|
||||||
const SkRect r = SkRect::MakeWH(SkIntToScalar(100), SkIntToScalar(100));
|
const SkRect r = SkRect::MakeWH(SkIntToScalar(100), SkIntToScalar(100));
|
||||||
for (size_t i = 0; i < SK_ARRAY_COUNT(blurRadii); ++i) {
|
for (size_t i = 0; i < SK_ARRAY_COUNT(blurRadii); ++i) {
|
||||||
SkAutoCanvasRestore autoRestore(canvas, true);
|
SkAutoCanvasRestore autoRestore(canvas, true);
|
||||||
canvas->translate(0, (r.height() + SkIntToScalar(20)) * i);
|
canvas->translate(0, (r.height() + SkIntToScalar(50)) * i);
|
||||||
for (size_t j = 0; j < SK_ARRAY_COUNT(cornerRadii); ++j) {
|
for (size_t j = 0; j < SK_ARRAY_COUNT(cornerRadii); ++j) {
|
||||||
SkMaskFilter* filter = SkBlurMaskFilter::Create(
|
SkMaskFilter* filter = SkBlurMaskFilter::Create(
|
||||||
kNormal_SkBlurStyle,
|
kNormal_SkBlurStyle,
|
||||||
SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(blurRadii[i])));
|
SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(blurRadii[i])),
|
||||||
|
SkBlurMaskFilter::kHighQuality_BlurFlag);
|
||||||
SkPaint paint;
|
SkPaint paint;
|
||||||
paint.setColor(SK_ColorBLUE);
|
paint.setColor(SK_ColorBLACK);
|
||||||
paint.setMaskFilter(filter)->unref();
|
paint.setMaskFilter(filter)->unref();
|
||||||
|
|
||||||
SkRRect rrect;
|
SkRRect rrect;
|
||||||
rrect.setRectXY(r, SkIntToScalar(cornerRadii[j]), SkIntToScalar(cornerRadii[j]));
|
rrect.setRectXY(r, SkIntToScalar(cornerRadii[j]), SkIntToScalar(cornerRadii[j]));
|
||||||
canvas->drawRRect(rrect, paint);
|
canvas->drawRRect(rrect, paint);
|
||||||
canvas->translate(r.width() + SkIntToScalar(10), 0);
|
canvas->translate(r.width() + SkIntToScalar(50), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -475,14 +475,16 @@ void SkMask_FreeImage(uint8_t* image) {
|
|||||||
SkMask::FreeImage(image);
|
SkMask::FreeImage(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SkBlurMask::BoxBlur(SkMask* dst, const SkMask& src, SkScalar sigma, SkBlurStyle style,
|
bool SkBlurMask::BoxBlur(SkMask* dst, const SkMask& src,
|
||||||
SkBlurQuality quality, SkIPoint* margin) {
|
SkScalar sigma, SkBlurStyle style, SkBlurQuality quality,
|
||||||
|
SkIPoint* margin, bool force_quality) {
|
||||||
|
|
||||||
if (src.fFormat != SkMask::kA8_Format) {
|
if (src.fFormat != SkMask::kA8_Format) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Force high quality off for small radii (performance)
|
// Force high quality off for small radii (performance)
|
||||||
if (sigma <= SkIntToScalar(2)) {
|
if (!force_quality && sigma <= SkIntToScalar(2)) {
|
||||||
quality = kLow_SkBlurQuality;
|
quality = kLow_SkBlurQuality;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,9 +23,16 @@ public:
|
|||||||
SkIPoint *margin = NULL,
|
SkIPoint *margin = NULL,
|
||||||
SkMask::CreateMode createMode =
|
SkMask::CreateMode createMode =
|
||||||
SkMask::kComputeBoundsAndRenderImage_CreateMode);
|
SkMask::kComputeBoundsAndRenderImage_CreateMode);
|
||||||
|
|
||||||
|
// forceQuality will prevent BoxBlur from falling back to the low quality approach when sigma
|
||||||
|
// is very small -- this can be used predict the margin bump ahead of time without completely
|
||||||
|
// replicating the internal logic. This permits not only simpler caching of blurred results,
|
||||||
|
// but also being able to predict precisely at what pixels the blurred profile of e.g. a
|
||||||
|
// rectangle will lie.
|
||||||
|
|
||||||
static bool BoxBlur(SkMask* dst, const SkMask& src,
|
static bool BoxBlur(SkMask* dst, const SkMask& src,
|
||||||
SkScalar sigma, SkBlurStyle style, SkBlurQuality quality,
|
SkScalar sigma, SkBlurStyle style, SkBlurQuality quality,
|
||||||
SkIPoint* margin = NULL);
|
SkIPoint* margin = NULL, bool force_quality=false);
|
||||||
|
|
||||||
// the "ground truth" blur does a gaussian convolution; it's slow
|
// the "ground truth" blur does a gaussian convolution; it's slow
|
||||||
// but useful for comparison purposes.
|
// but useful for comparison purposes.
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "effects/GrSimpleTextureEffect.h"
|
#include "effects/GrSimpleTextureEffect.h"
|
||||||
#include "GrTBackendEffectFactory.h"
|
#include "GrTBackendEffectFactory.h"
|
||||||
#include "SkGrPixelRef.h"
|
#include "SkGrPixelRef.h"
|
||||||
|
#include "SkDraw.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class SkBlurMaskFilterImpl : public SkMaskFilter {
|
class SkBlurMaskFilterImpl : public SkMaskFilter {
|
||||||
@ -251,9 +252,9 @@ static bool rect_exceeds(const SkRect& r, SkScalar v) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SK_IGNORE_FAST_RRECT_BLUR
|
#ifdef SK_IGNORE_FAST_RRECT_BLUR
|
||||||
SK_CONF_DECLARE( bool, c_analyticBlurRRect, "mask.filter.blur.analyticRRect", false, "Use the faster analytic blur approach for ninepatch rects" );
|
SK_CONF_DECLARE( bool, c_analyticBlurRRect, "mask.filter.blur.analyticblurrrect", false, "Use the faster analytic blur approach for ninepatch rects" );
|
||||||
#else
|
#else
|
||||||
SK_CONF_DECLARE( bool, c_analyticBlurRRect, "mask.filter.blur.analyticRRect", true, "Use the faster analytic blur approach for ninepatch round rects" );
|
SK_CONF_DECLARE( bool, c_analyticBlurRRect, "mask.filter.blur.analyticblurrrect", true, "Use the faster analytic blur approach for ninepatch round rects" );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SkMaskFilter::FilterReturn
|
SkMaskFilter::FilterReturn
|
||||||
@ -809,11 +810,285 @@ bool SkBlurMaskFilterImpl::directFilterMaskGPU(GrContext* context,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class GrGLRRectBlurEffect;
|
||||||
|
|
||||||
|
class GrRRectBlurEffect : public GrEffect {
|
||||||
|
public:
|
||||||
|
|
||||||
|
static GrEffectRef* Create(GrContext* context, float sigma, const SkRRect&);
|
||||||
|
|
||||||
|
virtual ~GrRRectBlurEffect() {};
|
||||||
|
static const char* Name() { return "GrRRectBlur"; }
|
||||||
|
|
||||||
|
const SkRRect& getRRect() const { return fRRect; }
|
||||||
|
float getSigma() const { return fSigma; }
|
||||||
|
|
||||||
|
typedef GrGLRRectBlurEffect GLEffect;
|
||||||
|
|
||||||
|
virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
|
||||||
|
|
||||||
|
virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
GrRRectBlurEffect(float sigma, const SkRRect&, GrTexture* profileTexture);
|
||||||
|
|
||||||
|
virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE;
|
||||||
|
|
||||||
|
SkRRect fRRect;
|
||||||
|
float fSigma;
|
||||||
|
GrTextureAccess fNinePatchAccess;
|
||||||
|
|
||||||
|
GR_DECLARE_EFFECT_TEST;
|
||||||
|
|
||||||
|
typedef GrEffect INHERITED;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
GrEffectRef* GrRRectBlurEffect::Create(GrContext* context, float sigma, const SkRRect& rrect) {
|
||||||
|
if (!rrect.isSimpleCircular()) {
|
||||||
|
SkDebugf( "not simple circular\n" );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we can successfully ninepatch this rrect -- the blur sigma has to be
|
||||||
|
// sufficiently small relative to both the size of the corner radius and the
|
||||||
|
// width (and height) of the rrect.
|
||||||
|
|
||||||
|
unsigned int blurRadius = 3*SkScalarCeilToInt(sigma-1/6.0f);
|
||||||
|
unsigned int cornerRadius = SkScalarCeilToInt(rrect.getSimpleRadii().x());
|
||||||
|
if (cornerRadius + blurRadius > rrect.width()/2 ||
|
||||||
|
cornerRadius + blurRadius > rrect.height()/2) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const GrCacheID::Domain gRRectBlurDomain = GrCacheID::GenerateDomain();
|
||||||
|
GrCacheID::Key key;
|
||||||
|
memset(&key, 0, sizeof(key));
|
||||||
|
key.fData32[0] = blurRadius;
|
||||||
|
key.fData32[1] = cornerRadius;
|
||||||
|
GrCacheID blurRRectNinePatchID(gRRectBlurDomain, key);
|
||||||
|
|
||||||
|
GrTextureParams params;
|
||||||
|
params.setFilterMode(GrTextureParams::kBilerp_FilterMode);
|
||||||
|
|
||||||
|
unsigned int smallRectSide = 2*(blurRadius + cornerRadius) + 1;
|
||||||
|
unsigned int texSide = smallRectSide + 2*blurRadius;
|
||||||
|
GrTextureDesc texDesc;
|
||||||
|
texDesc.fWidth = texSide;
|
||||||
|
texDesc.fHeight = texSide;
|
||||||
|
texDesc.fConfig = kAlpha_8_GrPixelConfig;
|
||||||
|
|
||||||
|
GrTexture *blurNinePatchTexture = context->findAndRefTexture(texDesc, blurRRectNinePatchID, ¶ms);
|
||||||
|
|
||||||
|
if (NULL == blurNinePatchTexture) {
|
||||||
|
SkMask mask;
|
||||||
|
|
||||||
|
mask.fBounds = SkIRect::MakeWH(smallRectSide, smallRectSide);
|
||||||
|
mask.fFormat = SkMask::kA8_Format;
|
||||||
|
mask.fRowBytes = mask.fBounds.width();
|
||||||
|
mask.fImage = SkMask::AllocImage(mask.computeTotalImageSize());
|
||||||
|
SkAutoMaskFreeImage amfi(mask.fImage);
|
||||||
|
|
||||||
|
memset(mask.fImage, 0, mask.computeTotalImageSize());
|
||||||
|
|
||||||
|
SkRect smallRect;
|
||||||
|
smallRect.setWH(SkIntToScalar(smallRectSide), SkIntToScalar(smallRectSide));
|
||||||
|
|
||||||
|
SkRRect smallRRect;
|
||||||
|
smallRRect.setRectXY(smallRect, SkIntToScalar(cornerRadius), SkIntToScalar(cornerRadius));
|
||||||
|
|
||||||
|
SkPath path;
|
||||||
|
path.addRRect( smallRRect );
|
||||||
|
|
||||||
|
SkDraw::DrawToMask(path, &mask.fBounds, NULL, NULL, &mask, SkMask::kJustRenderImage_CreateMode, SkPaint::kFill_Style);
|
||||||
|
|
||||||
|
SkMask blurred_mask;
|
||||||
|
SkBlurMask::BoxBlur(&blurred_mask, mask, sigma, kNormal_SkBlurStyle, kHigh_SkBlurQuality, NULL, true );
|
||||||
|
|
||||||
|
blurNinePatchTexture = context->createTexture(¶ms, texDesc, blurRRectNinePatchID, blurred_mask.fImage, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NULL == blurNinePatchTexture) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(GrRRectBlurEffect,
|
||||||
|
(sigma, rrect, blurNinePatchTexture))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GrRRectBlurEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
|
||||||
|
*validFlags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GrBackendEffectFactory& GrRRectBlurEffect::getFactory() const {
|
||||||
|
return GrTBackendEffectFactory<GrRRectBlurEffect>::getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
GrRRectBlurEffect::GrRRectBlurEffect(float sigma, const SkRRect& rrect, GrTexture *ninePatchTexture)
|
||||||
|
: fRRect(rrect),
|
||||||
|
fSigma(sigma),
|
||||||
|
fNinePatchAccess(ninePatchTexture) {
|
||||||
|
this->addTextureAccess(&fNinePatchAccess);
|
||||||
|
this->setWillReadFragmentPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GrRRectBlurEffect::onIsEqual(const GrEffect& other) const {
|
||||||
|
const GrRRectBlurEffect& rrbe = CastEffect<GrRRectBlurEffect>(other);
|
||||||
|
return fRRect.getSimpleRadii().fX == rrbe.fRRect.getSimpleRadii().fX && fSigma == rrbe.fSigma;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GR_DEFINE_EFFECT_TEST(GrRRectBlurEffect);
|
||||||
|
|
||||||
|
GrEffectRef* GrRRectBlurEffect::TestCreate(SkRandom* random,
|
||||||
|
GrContext* context,
|
||||||
|
const GrDrawTargetCaps& caps,
|
||||||
|
GrTexture*[]) {
|
||||||
|
SkScalar w = random->nextRangeScalar(100.f, 1000.f);
|
||||||
|
SkScalar h = random->nextRangeScalar(100.f, 1000.f);
|
||||||
|
SkScalar r = random->nextRangeF(1.f, 9.f);
|
||||||
|
SkScalar sigma = random->nextRangeF(1.f,10.f);
|
||||||
|
SkRRect rrect;
|
||||||
|
rrect.setRectXY(SkRect::MakeWH(w, h), r, r);
|
||||||
|
return GrRRectBlurEffect::Create(context, sigma, rrect);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class GrGLRRectBlurEffect : public GrGLEffect {
|
||||||
|
public:
|
||||||
|
GrGLRRectBlurEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
|
||||||
|
|
||||||
|
virtual void emitCode(GrGLShaderBuilder* builder,
|
||||||
|
const GrDrawEffect& drawEffect,
|
||||||
|
EffectKey key,
|
||||||
|
const char* outputColor,
|
||||||
|
const char* inputColor,
|
||||||
|
const TransformedCoordsArray&,
|
||||||
|
const TextureSamplerArray&) SK_OVERRIDE;
|
||||||
|
|
||||||
|
virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
GrGLUniformManager::UniformHandle fProxyRectUniform;
|
||||||
|
GrGLUniformManager::UniformHandle fCornerRadiusUniform;
|
||||||
|
GrGLUniformManager::UniformHandle fBlurRadiusUniform;
|
||||||
|
typedef GrGLEffect INHERITED;
|
||||||
|
};
|
||||||
|
|
||||||
|
GrGLRRectBlurEffect::GrGLRRectBlurEffect(const GrBackendEffectFactory& factory,
|
||||||
|
const GrDrawEffect& drawEffect)
|
||||||
|
: INHERITED (factory) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void GrGLRRectBlurEffect::emitCode(GrGLShaderBuilder* builder,
|
||||||
|
const GrDrawEffect& drawEffect,
|
||||||
|
EffectKey key,
|
||||||
|
const char* outputColor,
|
||||||
|
const char* inputColor,
|
||||||
|
const TransformedCoordsArray&,
|
||||||
|
const TextureSamplerArray& samplers) {
|
||||||
|
const char *rectName;
|
||||||
|
const char *cornerRadiusName;
|
||||||
|
const char *blurRadiusName;
|
||||||
|
|
||||||
|
// The proxy rect has left, top, right, and bottom edges correspond to
|
||||||
|
// components x, y, z, and w, respectively.
|
||||||
|
|
||||||
|
fProxyRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
|
||||||
|
kVec4f_GrSLType,
|
||||||
|
"proxyRect",
|
||||||
|
&rectName);
|
||||||
|
fCornerRadiusUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
|
||||||
|
kFloat_GrSLType,
|
||||||
|
"cornerRadius",
|
||||||
|
&cornerRadiusName);
|
||||||
|
fBlurRadiusUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
|
||||||
|
kFloat_GrSLType,
|
||||||
|
"blurRadius",
|
||||||
|
&blurRadiusName);
|
||||||
|
const char* fragmentPos = builder->fragmentPosition();
|
||||||
|
|
||||||
|
// warp the fragment position to the appropriate part of the 9patch blur texture
|
||||||
|
|
||||||
|
builder->fsCodeAppendf("\t\tvec2 rectCenter = (%s.xy + %s.zw)/2.0;\n", rectName, rectName);
|
||||||
|
builder->fsCodeAppendf("\t\tvec2 translatedFragPos = %s.xy - %s.xy;\n", fragmentPos, rectName);
|
||||||
|
builder->fsCodeAppendf("\t\tfloat threshold = %s + 2.0*%s;\n", cornerRadiusName, blurRadiusName );
|
||||||
|
builder->fsCodeAppendf("\t\tvec2 middle = %s.zw - %s.xy - 2.0*threshold;\n", rectName, rectName );
|
||||||
|
|
||||||
|
builder->fsCodeAppendf("\t\tif (translatedFragPos.x >= threshold && translatedFragPos.x < (middle.x+threshold)) {\n" );
|
||||||
|
builder->fsCodeAppendf("\t\t\ttranslatedFragPos.x = threshold;\n");
|
||||||
|
builder->fsCodeAppendf("\t\t} else if (translatedFragPos.x >= (middle.x + threshold)) {\n");
|
||||||
|
builder->fsCodeAppendf("\t\t\ttranslatedFragPos.x -= middle.x;\n");
|
||||||
|
builder->fsCodeAppendf("\t\t}\n");
|
||||||
|
|
||||||
|
builder->fsCodeAppendf("\t\tif (translatedFragPos.y > threshold && translatedFragPos.y < (middle.y+threshold)) {\n" );
|
||||||
|
builder->fsCodeAppendf("\t\t\ttranslatedFragPos.y = threshold;\n");
|
||||||
|
builder->fsCodeAppendf("\t\t} else if (translatedFragPos.y >= (middle.y + threshold)) {\n");
|
||||||
|
builder->fsCodeAppendf("\t\t\ttranslatedFragPos.y -= middle.y;\n");
|
||||||
|
builder->fsCodeAppendf("\t\t}\n");
|
||||||
|
|
||||||
|
builder->fsCodeAppendf("\t\tvec2 proxyDims = vec2(2.0*threshold+1.0);\n");
|
||||||
|
builder->fsCodeAppendf("\t\tvec2 texCoord = translatedFragPos / proxyDims;\n");
|
||||||
|
|
||||||
|
builder->fsCodeAppendf("\t%s = ", outputColor);
|
||||||
|
builder->fsAppendTextureLookupAndModulate(inputColor, samplers[0], "texCoord");
|
||||||
|
builder->fsCodeAppend(";\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void GrGLRRectBlurEffect::setData(const GrGLUniformManager& uman,
|
||||||
|
const GrDrawEffect& drawEffect) {
|
||||||
|
const GrRRectBlurEffect& brre = drawEffect.castEffect<GrRRectBlurEffect>();
|
||||||
|
SkRRect rrect = brre.getRRect();
|
||||||
|
|
||||||
|
float blurRadius = 3.f*SkScalarCeilToScalar(brre.getSigma()-1/6.0f);
|
||||||
|
uman.set1f(fBlurRadiusUniform, blurRadius);
|
||||||
|
|
||||||
|
SkRect rect = rrect.getBounds();
|
||||||
|
rect.outset(blurRadius, blurRadius);
|
||||||
|
uman.set4f(fProxyRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
|
||||||
|
|
||||||
|
SkScalar radius = 0;
|
||||||
|
SkASSERT(rrect.isSimpleCircular() || rrect.isRect());
|
||||||
|
radius = rrect.getSimpleRadii().fX;
|
||||||
|
uman.set1f(fCornerRadiusUniform, radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SkBlurMaskFilterImpl::directFilterRRectMaskGPU(GrContext* context,
|
bool SkBlurMaskFilterImpl::directFilterRRectMaskGPU(GrContext* context,
|
||||||
GrPaint* grp,
|
GrPaint* grp,
|
||||||
const SkStrokeRec& strokeRec,
|
const SkStrokeRec& strokeRec,
|
||||||
const SkRRect& rrect) const {
|
const SkRRect& rrect) const {
|
||||||
return false;
|
if (fBlurStyle != kNormal_SkBlurStyle) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strokeRec.isFillStyle()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SkRect proxy_rect = rrect.rect();
|
||||||
|
SkMatrix ctm = context->getMatrix();
|
||||||
|
SkScalar xformedSigma = this->computeXformedSigma(ctm);
|
||||||
|
float extra=3.f*SkScalarCeilToScalar(xformedSigma-1/6.0f);
|
||||||
|
proxy_rect.outset(extra, extra);
|
||||||
|
|
||||||
|
SkAutoTUnref<GrEffectRef> effect(GrRRectBlurEffect::Create(
|
||||||
|
context, xformedSigma, rrect));
|
||||||
|
if (!effect) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
GrContext::AutoMatrix am;
|
||||||
|
if (!am.setIdentity(context, grp)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
grp->addCoverageEffect(effect);
|
||||||
|
|
||||||
|
context->drawRect(*grp, proxy_rect);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRect& srcBounds,
|
bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRect& srcBounds,
|
||||||
|
@ -559,15 +559,6 @@ static void Index8_To_RGB(const uint8_t* in, uint8_t* rgb, int width,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Alpha8_To_RGB(const uint8_t* in, uint8_t* rgb, int width,
|
|
||||||
const SkPMColor* SK_RESTRICT ctable) {
|
|
||||||
const uint8_t* SK_RESTRICT src = (const uint8_t*)in;
|
|
||||||
for (int i = 0; i < width; ++i) {
|
|
||||||
rgb[0] = rgb[1] = rgb[2] = *src++;
|
|
||||||
rgb += 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static ScanlineImporter ChooseImporter(const SkBitmap::Config& config,
|
static ScanlineImporter ChooseImporter(const SkBitmap::Config& config,
|
||||||
bool hasAlpha,
|
bool hasAlpha,
|
||||||
int* bpp) {
|
int* bpp) {
|
||||||
@ -594,9 +585,6 @@ static ScanlineImporter ChooseImporter(const SkBitmap::Config& config,
|
|||||||
case SkBitmap::kIndex8_Config:
|
case SkBitmap::kIndex8_Config:
|
||||||
*bpp = 3;
|
*bpp = 3;
|
||||||
return Index8_To_RGB;
|
return Index8_To_RGB;
|
||||||
case SkBitmap::kA8_Config:
|
|
||||||
*bpp = 3;
|
|
||||||
return Alpha8_To_RGB;
|
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user