diff --git a/include/gpu/GrSamplerState.h b/include/gpu/GrSamplerState.h index e8182f978..385dba7bd 100644 --- a/include/gpu/GrSamplerState.h +++ b/include/gpu/GrSamplerState.h @@ -17,69 +17,6 @@ #include "SkShader.h" -class GrTextureParams { -public: - GrTextureParams() { - this->reset(); - } - - GrTextureParams(const GrTextureParams& params) { - *this = params; - } - - GrTextureParams& operator =(const GrTextureParams& params) { - fTileModes[0] = params.fTileModes[0]; - fTileModes[1] = params.fTileModes[1]; - fBilerp = params.fBilerp; - return *this; - } - - void reset() { - this->reset(SkShader::kClamp_TileMode, false); - } - - void reset(SkShader::TileMode tileXAndY, bool filter) { - fTileModes[0] = fTileModes[1] = tileXAndY; - fBilerp = filter; - } - void reset(SkShader::TileMode tileModes[2], bool filter) { - fTileModes[0] = tileModes[0]; - fTileModes[1] = tileModes[1]; - fBilerp = filter; - } - - void setClampNoFilter() { - fTileModes[0] = fTileModes[1] = SkShader::kClamp_TileMode; - fBilerp = false; - } - - void setClamp() { - fTileModes[0] = fTileModes[1] = SkShader::kClamp_TileMode; - } - - void setBilerp(bool bilerp) { fBilerp = bilerp; } - - void setTileModeX(const SkShader::TileMode tm) { fTileModes[0] = tm; } - void setTileModeY(const SkShader::TileMode tm) { fTileModes[1] = tm; } - void setTileModeXAndY(const SkShader::TileMode tm) { fTileModes[0] = fTileModes[1] = tm; } - - SkShader::TileMode getTileModeX() const { return fTileModes[0]; } - - SkShader::TileMode getTileModeY() const { return fTileModes[1]; } - - bool isTiled() const { - return SkShader::kClamp_TileMode != fTileModes[0] || - SkShader::kClamp_TileMode != fTileModes[1]; - } - - bool isBilerp() const { return fBilerp; } - -private: - - SkShader::TileMode fTileModes[2]; - bool fBilerp; -}; - class GrSamplerState { public: static const bool kBilerpDefault = false; @@ -118,19 +55,13 @@ public: bool operator !=(const GrSamplerState& s) const { return !(*this == s); } GrSamplerState& operator =(const GrSamplerState& s) { - // memcpy() breaks refcounting - fTextureParams = s.fTextureParams; fMatrix = s.fMatrix; - GrSafeAssign(fCustomStage, s.fCustomStage); - return *this; } const GrMatrix& getMatrix() const { return fMatrix; } - GrTextureParams* textureParams() { return &fTextureParams; } - const GrTextureParams& getTextureParams() const { return fTextureParams; } /** * Access the sampler's matrix. See SampleMode for explanation of * relationship between the matrix and sample mode. @@ -149,21 +80,14 @@ public: */ void preConcatMatrix(const GrMatrix& matrix) { fMatrix.preConcat(matrix); } - void reset(SkShader::TileMode tileXAndY, - bool filter, - const GrMatrix& matrix) { - fTextureParams.reset(tileXAndY, filter); + void reset(const GrMatrix& matrix) { fMatrix = matrix; GrSafeSetNull(fCustomStage); } - void reset(SkShader::TileMode wrapXAndY, bool filter) { - this->reset(wrapXAndY, filter, GrMatrix::I()); - } - void reset(const GrMatrix& matrix) { - this->reset(kTileModeDefault, kBilerpDefault, matrix); - } + void reset() { - this->reset(kTileModeDefault, kBilerpDefault, GrMatrix::I()); + fMatrix.reset(); + GrSafeSetNull(fCustomStage); } GrCustomStage* setCustomStage(GrCustomStage* stage) { @@ -173,7 +97,6 @@ public: const GrCustomStage* getCustomStage() const { return fCustomStage; } private: - GrTextureParams fTextureParams; GrMatrix fMatrix; GrCustomStage* fCustomStage; diff --git a/include/gpu/GrTextureAccess.h b/include/gpu/GrTextureAccess.h index e4e373294..7f47b6e79 100644 --- a/include/gpu/GrTextureAccess.h +++ b/include/gpu/GrTextureAccess.h @@ -10,9 +10,96 @@ #include "GrNoncopyable.h" #include "SkRefCnt.h" +#include "SkShader.h" class GrTexture; +/** + * Represents the filtering and tile modes used to access a texture. It is mostly used with + * GrTextureAccess (defined below). Also, some of the texture cache methods require knowledge about + * filtering and tiling to perform a cache lookup. If it wasn't for this latter usage this would + * be folded into GrTextureAccess. + */ +class GrTextureParams { +public: + GrTextureParams() { + this->reset(); + } + + GrTextureParams(SkShader::TileMode tileXAndY, bool bilerp) { + this->reset(tileXAndY, bilerp); + } + + GrTextureParams(SkShader::TileMode tileModes[2], bool bilerp) { + this->reset(tileModes, bilerp); + } + + GrTextureParams(const GrTextureParams& params) { + *this = params; + } + + GrTextureParams& operator= (const GrTextureParams& params) { + fTileModes[0] = params.fTileModes[0]; + fTileModes[1] = params.fTileModes[1]; + fBilerp = params.fBilerp; + return *this; + } + + void reset() { + this->reset(SkShader::kClamp_TileMode, false); + } + + void reset(SkShader::TileMode tileXAndY, bool bilerp) { + fTileModes[0] = fTileModes[1] = tileXAndY; + fBilerp = bilerp; + } + + void reset(SkShader::TileMode tileModes[2], bool bilerp) { + fTileModes[0] = tileModes[0]; + fTileModes[1] = tileModes[1]; + fBilerp = bilerp; + } + + void setClampNoFilter() { + fTileModes[0] = fTileModes[1] = SkShader::kClamp_TileMode; + fBilerp = false; + } + + void setClamp() { + fTileModes[0] = fTileModes[1] = SkShader::kClamp_TileMode; + } + + void setBilerp(bool bilerp) { fBilerp = bilerp; } + + void setTileModeX(const SkShader::TileMode tm) { fTileModes[0] = tm; } + void setTileModeY(const SkShader::TileMode tm) { fTileModes[1] = tm; } + void setTileModeXAndY(const SkShader::TileMode tm) { fTileModes[0] = fTileModes[1] = tm; } + + SkShader::TileMode getTileModeX() const { return fTileModes[0]; } + + SkShader::TileMode getTileModeY() const { return fTileModes[1]; } + + bool isTiled() const { + return SkShader::kClamp_TileMode != fTileModes[0] || + SkShader::kClamp_TileMode != fTileModes[1]; + } + + bool isBilerp() const { return fBilerp; } + + bool operator== (const GrTextureParams& other) const { + return fTileModes[0] == other.fTileModes[0] && + fTileModes[1] == other.fTileModes[1] && + fBilerp == other.fBilerp; + } + + bool operator!= (const GrTextureParams& other) const { return !(*this == other); } + +private: + + SkShader::TileMode fTileModes[2]; + bool fBilerp; +}; + /** A class representing the swizzle access pattern for a texture. Note that if the texture is * an alpha-only texture then the alpha channel is substituted for other components. Any mangling * to handle the r,g,b->a conversions for alpha textures is automatically included in the stage @@ -27,19 +114,45 @@ public: */ GrTextureAccess(); + /** + * Uses the default swizzle, "rgba". + */ + GrTextureAccess(GrTexture*, const GrTextureParams&); + explicit GrTextureAccess(GrTexture*, + bool bilerp = false, + SkShader::TileMode tileXAndY = SkShader::kClamp_TileMode); + /** * swizzle must be a string between one and four (inclusive) characters containing only 'r', * 'g', 'b', and/or 'a'. */ - GrTextureAccess(GrTexture*, const char* swizzle); + GrTextureAccess(GrTexture*, const char* swizzle, const GrTextureParams&); + GrTextureAccess(GrTexture*, + const char* swizzle, + bool bilerp = false, + SkShader::TileMode tileXAndY = SkShader::kClamp_TileMode); - /** - * Uses the default swizzle, "rgba". - */ - GrTextureAccess(GrTexture*); + void reset(GrTexture*, const GrTextureParams&); + void reset(GrTexture*, + bool bilerp = false, + SkShader::TileMode tileXAndY = SkShader::kClamp_TileMode); + void reset(GrTexture*, const char* swizzle, const GrTextureParams&); + void reset(GrTexture*, + const char* swizzle, + bool bilerp = false, + SkShader::TileMode tileXAndY = SkShader::kClamp_TileMode); - void reset(GrTexture*, const char* swizzle); - void reset(GrTexture*); + bool operator== (const GrTextureAccess& other) const { +#if GR_DEBUG + // below assumes all chars in fSwizzle are initialized even if string is < 4 chars long. + GrAssert(memcmp(fSwizzle, other.fSwizzle, sizeof(fSwizzle)) == + strcmp(fSwizzle, other.fSwizzle)); +#endif + return fParams == other.fParams && + memcmp(fSwizzle, other.fSwizzle, sizeof(fSwizzle)); + } + + bool operator!= (const GrTextureAccess& other) const { return !(*this == other); } GrTexture* getTexture() const { return fTexture.get(); } @@ -60,10 +173,17 @@ public: /** Returns a mask indicating which components are referenced in the swizzle. */ uint32_t swizzleMask() const { return fSwizzleMask; } + const GrTextureParams& getParams() const { return fParams; } + private: + void setSwizzle(const char*); + + GrTextureParams fParams; SkAutoTUnref fTexture; uint32_t fSwizzleMask; char fSwizzle[5]; + + typedef GrNoncopyable INHERITED; }; #endif diff --git a/include/gpu/SkGpuDevice.h b/include/gpu/SkGpuDevice.h index 49eea2657..04c4e0fec 100644 --- a/include/gpu/SkGpuDevice.h +++ b/include/gpu/SkGpuDevice.h @@ -156,8 +156,12 @@ private: const GrTextureParams& sampler, const SkIRect* srcRectPtr, int* tileSize) const; - void internalDrawBitmap(const SkDraw&, const SkBitmap&, - const SkIRect&, const SkMatrix&, GrPaint* grPaint); + void internalDrawBitmap(const SkDraw&, + const SkBitmap&, + const SkIRect&, + const SkMatrix&, + const GrTextureParams& params, + GrPaint* grPaint); /** * Returns non-initialized instance. diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp index f0dac4d18..9a965ff81 100644 --- a/src/effects/gradients/SkGradientShader.cpp +++ b/src/effects/gradients/SkGradientShader.cpp @@ -718,7 +718,7 @@ void GrGLGradientStage::emitColorLookup(GrGLShaderBuilder* builder, GrGradientEffect::GrGradientEffect(GrContext* ctx, const SkGradientShaderBase& shader, - GrSamplerState* sampler) + SkShader::TileMode tileMode) : fUseTexture (true) { // TODO: check for simple cases where we don't need a texture: //GradientInfo info; @@ -737,14 +737,19 @@ GrGradientEffect::GrGradientEffect(GrContext* ctx, fAtlas = GrTextureStripAtlas::GetAtlas(desc); GrAssert(NULL != fAtlas); + // We always filter the gradient table. Each table is one row of a texture, so always y-clamp. + GrTextureParams params; + params.setBilerp(true); + params.setTileModeX(tileMode); + fRow = fAtlas->lockRow(bitmap); if (-1 != fRow) { fYCoord = fAtlas->getYOffset(fRow) + GR_ScalarHalf * fAtlas->getVerticalScaleFactor(); - fTextureAccess.reset(fAtlas->getTexture()); + fTextureAccess.reset(fAtlas->getTexture(), params); } else { - GrTexture* texture = GrLockCachedBitmapTexture(ctx, bitmap, sampler->textureParams()); - fTextureAccess.reset(texture); + GrTexture* texture = GrLockCachedBitmapTexture(ctx, bitmap, ¶ms); + fTextureAccess.reset(texture, params); fYCoord = GR_ScalarHalf; // Unlock immediately, this is not great, but we don't have a way of diff --git a/src/effects/gradients/SkGradientShaderPriv.h b/src/effects/gradients/SkGradientShaderPriv.h index 0e7c2fc27..bdea9008e 100644 --- a/src/effects/gradients/SkGradientShaderPriv.h +++ b/src/effects/gradients/SkGradientShaderPriv.h @@ -226,8 +226,9 @@ class GrProgramStageFactory; class GrGradientEffect : public GrCustomStage { public: - GrGradientEffect(GrContext* ctx, const SkGradientShaderBase& shader, - GrSamplerState* sampler); + GrGradientEffect(GrContext* ctx, + const SkGradientShaderBase& shader, + SkShader::TileMode tileMode); virtual ~GrGradientEffect(); diff --git a/src/effects/gradients/SkLinearGradient.cpp b/src/effects/gradients/SkLinearGradient.cpp index bcebc2683..4b673f669 100644 --- a/src/effects/gradients/SkLinearGradient.cpp +++ b/src/effects/gradients/SkLinearGradient.cpp @@ -503,9 +503,8 @@ private: class GrLinearGradient : public GrGradientEffect { public: - GrLinearGradient(GrContext* ctx, const SkLinearGradient& shader, - GrSamplerState* sampler) - : INHERITED(ctx, shader, sampler) { } + GrLinearGradient(GrContext* ctx, const SkLinearGradient& shader, SkShader::TileMode tm) + : INHERITED(ctx, shader, tm) { } virtual ~GrLinearGradient() { } static const char* Name() { return "Linear Gradient"; } @@ -562,10 +561,7 @@ GrCustomStage* SkLinearGradient::asNewCustomStage(GrContext* context, GrSamplerState* sampler) const { SkASSERT(NULL != context && NULL != sampler); sampler->matrix()->preConcat(fPtsToUnit); - sampler->textureParams()->setTileModeX(fTileMode); - sampler->textureParams()->setTileModeY(kClamp_TileMode); - sampler->textureParams()->setBilerp(true); - return SkNEW_ARGS(GrLinearGradient, (context, *this, sampler)); + return SkNEW_ARGS(GrLinearGradient, (context, *this, fTileMode)); } #else diff --git a/src/effects/gradients/SkRadialGradient.cpp b/src/effects/gradients/SkRadialGradient.cpp index 799e548d9..512eafb2b 100644 --- a/src/effects/gradients/SkRadialGradient.cpp +++ b/src/effects/gradients/SkRadialGradient.cpp @@ -500,10 +500,8 @@ private: class GrRadialGradient : public GrGradientEffect { public: - GrRadialGradient(GrContext* ctx, - const SkRadialGradient& shader, - GrSamplerState* sampler) - : INHERITED(ctx, shader, sampler) { + GrRadialGradient(GrContext* ctx, const SkRadialGradient& shader, SkShader::TileMode tm) + : INHERITED(ctx, shader, tm) { } virtual ~GrRadialGradient() { } @@ -562,10 +560,7 @@ GrCustomStage* SkRadialGradient::asNewCustomStage(GrContext* context, GrSamplerState* sampler) const { SkASSERT(NULL != context && NULL != sampler); sampler->matrix()->preConcat(fPtsToUnit); - sampler->textureParams()->setTileModeX(fTileMode); - sampler->textureParams()->setTileModeY(kClamp_TileMode); - sampler->textureParams()->setBilerp(true); - return SkNEW_ARGS(GrRadialGradient, (context, *this, sampler)); + return SkNEW_ARGS(GrRadialGradient, (context, *this, fTileMode)); } #else diff --git a/src/effects/gradients/SkSweepGradient.cpp b/src/effects/gradients/SkSweepGradient.cpp index 843d1aaf2..f18b08ea9 100644 --- a/src/effects/gradients/SkSweepGradient.cpp +++ b/src/effects/gradients/SkSweepGradient.cpp @@ -410,9 +410,8 @@ class GrSweepGradient : public GrGradientEffect { public: GrSweepGradient(GrContext* ctx, - const SkSweepGradient& shader, - GrSamplerState* sampler) - : INHERITED(ctx, shader, sampler) { } + const SkSweepGradient& shader) + : INHERITED(ctx, shader, SkShader::kClamp_TileMode) { } virtual ~GrSweepGradient() { } static const char* Name() { return "Sweep Gradient"; } @@ -467,10 +466,7 @@ void GrGLSweepGradient::emitFS(GrGLShaderBuilder* builder, GrCustomStage* SkSweepGradient::asNewCustomStage(GrContext* context, GrSamplerState* sampler) const { sampler->matrix()->preConcat(fPtsToUnit); - sampler->textureParams()->setTileModeX(fTileMode); - sampler->textureParams()->setTileModeY(kClamp_TileMode); - sampler->textureParams()->setBilerp(true); - return SkNEW_ARGS(GrSweepGradient, (context, *this, sampler)); + return SkNEW_ARGS(GrSweepGradient, (context, *this)); } #else diff --git a/src/effects/gradients/SkTwoPointConicalGradient.cpp b/src/effects/gradients/SkTwoPointConicalGradient.cpp index 3466d2cbe..31e3b37c1 100644 --- a/src/effects/gradients/SkTwoPointConicalGradient.cpp +++ b/src/effects/gradients/SkTwoPointConicalGradient.cpp @@ -370,9 +370,10 @@ private: class GrConical2Gradient : public GrGradientEffect { public: - GrConical2Gradient(GrContext* ctx, const SkTwoPointConicalGradient& shader, - GrSamplerState* sampler) - : INHERITED(ctx, shader, sampler) + GrConical2Gradient(GrContext* ctx, + const SkTwoPointConicalGradient& shader, + SkShader::TileMode tm) + : INHERITED(ctx, shader, tm) , fCenterX1(shader.getCenterX1()) , fRadius0(shader.getStartRadius()) , fDiffRadius(shader.getDiffRadius()) { } @@ -685,10 +686,7 @@ GrCustomStage* SkTwoPointConicalGradient::asNewCustomStage( sampler->matrix()->reset(); } sampler->matrix()->preTranslate(-fCenter1.fX, -fCenter1.fY); - sampler->textureParams()->setTileModeX(fTileMode); - sampler->textureParams()->setTileModeY(kClamp_TileMode); - sampler->textureParams()->setBilerp(true); - return SkNEW_ARGS(GrConical2Gradient, (context, *this, sampler)); + return SkNEW_ARGS(GrConical2Gradient, (context, *this, fTileMode)); } #else diff --git a/src/effects/gradients/SkTwoPointRadialGradient.cpp b/src/effects/gradients/SkTwoPointRadialGradient.cpp index 9362dedca..97f335d97 100644 --- a/src/effects/gradients/SkTwoPointRadialGradient.cpp +++ b/src/effects/gradients/SkTwoPointRadialGradient.cpp @@ -405,9 +405,8 @@ private: class GrRadial2Gradient : public GrGradientEffect { public: - GrRadial2Gradient(GrContext* ctx, const SkTwoPointRadialGradient& shader, - GrSamplerState* sampler) - : INHERITED(ctx, shader, sampler) + GrRadial2Gradient(GrContext* ctx, const SkTwoPointRadialGradient& shader, SkShader::TileMode tm) + : INHERITED(ctx, shader, tm) , fCenterX1(shader.getCenterX1()) , fRadius0(shader.getStartRadius()) , fPosRoot(shader.getDiffRadius() < 0) { } @@ -660,10 +659,7 @@ GrCustomStage* SkTwoPointRadialGradient::asNewCustomStage( sampler->matrix()->reset(); } sampler->matrix()->preConcat(fPtsToUnit); - sampler->textureParams()->setTileModeX(fTileMode); - sampler->textureParams()->setTileModeY(kClamp_TileMode); - sampler->textureParams()->setBilerp(true); - return SkNEW_ARGS(GrRadial2Gradient, (context, *this, sampler)); + return SkNEW_ARGS(GrRadial2Gradient, (context, *this, fTileMode)); } #else diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 9e2e01416..05ca68771 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -309,9 +309,9 @@ GrTexture* GrContext::createResizedTexture(const GrTextureDesc& desc, // if filtering is not desired then we want to ensure all // texels in the resampled image are copies of texels from // the original. - drawState->sampler(0)->reset(SkShader::kClamp_TileMode, - needsFiltering); - drawState->createTextureEffect(0, clampedTexture); + drawState->sampler(0)->reset(); + GrTextureParams params(SkShader::kClamp_TileMode, needsFiltering); + drawState->createTextureEffect(0, clampedTexture, params); static const GrVertexLayout layout = GrDrawTarget::StageTexCoordVertexLayoutBit(0,0); @@ -1864,7 +1864,6 @@ GrTexture* GrContext::gaussianBlur(GrTexture* srcTexture, GrPaint paint; paint.reset(); - paint.textureSampler(0)->textureParams()->setBilerp(true); for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) { paint.textureSampler(0)->matrix()->setIDiv(srcTexture->width(), @@ -1874,7 +1873,7 @@ GrTexture* GrContext::gaussianBlur(GrTexture* srcTexture, scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f, i < scaleFactorY ? 0.5f : 1.0f); paint.textureSampler(0)->setCustomStage(SkNEW_ARGS(GrSingleTextureEffect, - (srcTexture)))->unref(); + (srcTexture, true)))->unref(); this->drawRectToRect(paint, dstRect, srcRect); srcRect = dstRect; srcTexture = dstTexture; @@ -1928,12 +1927,11 @@ GrTexture* GrContext::gaussianBlur(GrTexture* srcTexture, 1, srcIRect.height()); this->clear(&clearRect, 0x0); // FIXME: This should be mitchell, not bilinear. - paint.textureSampler(0)->textureParams()->setBilerp(true); paint.textureSampler(0)->matrix()->setIDiv(srcTexture->width(), srcTexture->height()); this->setRenderTarget(dstTexture->asRenderTarget()); paint.textureSampler(0)->setCustomStage(SkNEW_ARGS(GrSingleTextureEffect, - (srcTexture)))->unref(); + (srcTexture, true)))->unref(); SkRect dstRect(srcRect); scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY); this->drawRectToRect(paint, dstRect, srcRect); diff --git a/src/gpu/GrCustomStage.cpp b/src/gpu/GrCustomStage.cpp index 3f79af828..b9ad4eabc 100644 --- a/src/gpu/GrCustomStage.cpp +++ b/src/gpu/GrCustomStage.cpp @@ -55,7 +55,7 @@ bool GrCustomStage::isEqual(const GrCustomStage& s) const { return false; } for (int i = 0; i < this->numTextures(); ++i) { - if (this->texture(i) != s.texture(i)) { + if (this->textureAccess(i) != s.textureAccess(i)) { return false; } } diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h index 8be76b36a..648c83ea7 100644 --- a/src/gpu/GrDrawState.h +++ b/src/gpu/GrDrawState.h @@ -181,6 +181,12 @@ public: this->sampler(stage)->setCustomStage( SkNEW_ARGS(GrSingleTextureEffect, (texture)))->unref(); } + void createTextureEffect(int stage, GrTexture* texture, const GrTextureParams& params) { + GrAssert(!this->getSampler(stage).getCustomStage()); + this->sampler(stage)->setCustomStage( + SkNEW_ARGS(GrSingleTextureEffect, (texture, params)))->unref(); + } + bool stagesDisabled() { for (int i = 0; i < kNumStages; ++i) { diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp index edd92db08..109fc6bc9 100644 --- a/src/gpu/GrTextContext.cpp +++ b/src/gpu/GrTextContext.cpp @@ -19,6 +19,7 @@ #include "SkPath.h" enum { + kGlyphMaskStage = GrPaint::kTotalStages, }; @@ -29,12 +30,12 @@ void GrTextContext::flushGlyphs() { GrDrawState* drawState = fDrawTarget->drawState(); if (fCurrVertex > 0) { // setup our sampler state for our text texture/atlas - drawState->sampler(kGlyphMaskStage)->reset(SkShader::kRepeat_TileMode, - !fExtMatrix.isIdentity()); + drawState->sampler(kGlyphMaskStage)->reset(); GrAssert(GrIsALIGN4(fCurrVertex)); GrAssert(fCurrTexture); - drawState->createTextureEffect(kGlyphMaskStage, fCurrTexture); + GrTextureParams params(SkShader::kRepeat_TileMode, !fExtMatrix.isIdentity()); + drawState->createTextureEffect(kGlyphMaskStage, fCurrTexture, params); if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) { if (kOne_GrBlendCoeff != fPaint.fSrcBlendCoeff || diff --git a/src/gpu/GrTextureAccess.cpp b/src/gpu/GrTextureAccess.cpp index c3c803806..1156ec215 100644 --- a/src/gpu/GrTextureAccess.cpp +++ b/src/gpu/GrTextureAccess.cpp @@ -16,25 +16,76 @@ GrTextureAccess::GrTextureAccess() { #endif } -GrTextureAccess::GrTextureAccess(GrTexture* texture, const char* swizzle) { - this->reset(texture, swizzle); +GrTextureAccess::GrTextureAccess(GrTexture* texture, const GrTextureParams& params) { + this->reset(texture, params); } -GrTextureAccess::GrTextureAccess(GrTexture* texture) { - this->reset(texture); +GrTextureAccess::GrTextureAccess(GrTexture* texture, + bool bilerp, + SkShader::TileMode tileXAndY) { + this->reset(texture, bilerp, tileXAndY); } -void GrTextureAccess::reset(GrTexture* texture, const char* swizzle) { +GrTextureAccess::GrTextureAccess(GrTexture* texture, + const char* swizzle, + const GrTextureParams& params) { + this->reset(texture, swizzle, params); +} + +GrTextureAccess::GrTextureAccess(GrTexture* texture, + const char* swizzle, + bool bilerp, + SkShader::TileMode tileXAndY) { + this->reset(texture, swizzle, bilerp, tileXAndY); +} + +void GrTextureAccess::reset(GrTexture* texture, + const char* swizzle, + const GrTextureParams& params) { GrAssert(NULL != texture); GrAssert(strlen(swizzle) >= 1 && strlen(swizzle) <= 4); - texture->ref(); - fTexture.reset(texture); + fParams = params; + fTexture.reset(SkRef(texture)); + this->setSwizzle(swizzle); +} +void GrTextureAccess::reset(GrTexture* texture, + const char* swizzle, + bool bilerp, + SkShader::TileMode tileXAndY) { + GrAssert(NULL != texture); + GrAssert(strlen(swizzle) >= 1 && strlen(swizzle) <= 4); + + fParams.reset(tileXAndY, bilerp); + fTexture.reset(SkRef(texture)); + this->setSwizzle(swizzle); +} + +void GrTextureAccess::reset(GrTexture* texture, + const GrTextureParams& params) { + GrAssert(NULL != texture); + fTexture.reset(SkRef(texture)); + fParams = params; + memcpy(fSwizzle, "rgba", 5); + fSwizzleMask = (kRGB_SwizzleMask | kA_SwizzleFlag); +} + +void GrTextureAccess::reset(GrTexture* texture, + bool bilerp, + SkShader::TileMode tileXAndY) { + GrAssert(NULL != texture); + fTexture.reset(SkRef(texture)); + fParams.reset(tileXAndY, bilerp); + memcpy(fSwizzle, "rgba", 5); + fSwizzleMask = (kRGB_SwizzleMask | kA_SwizzleFlag); +} + +void GrTextureAccess::setSwizzle(const char* swizzle) { fSwizzleMask = 0; - fSwizzle[4] = '\0'; + memset(fSwizzle, '\0', 5); int i = 0; - do { + for (int i = 0; i < 4 && '\0' != swizzle[i]; ++i) { fSwizzle[i] = swizzle[i]; switch (swizzle[i]) { case 'r': @@ -49,19 +100,9 @@ void GrTextureAccess::reset(GrTexture* texture, const char* swizzle) { case 'a': fSwizzleMask |= kA_SwizzleFlag; break; - case '\0': - break; default: GrCrash("Unexpected swizzle string character."); break; } - } while ('\0' != swizzle[i] && ++i < 4); -} - -void GrTextureAccess::reset(GrTexture* texture) { - GrAssert(NULL != texture); - texture->ref(); - fTexture.reset(texture); - memcpy(fSwizzle, "rgba", 5); - fSwizzleMask = (kRGB_SwizzleMask | kA_SwizzleFlag); + } } diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index fa0f60e68..e7fd8c420 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -545,6 +545,7 @@ inline bool skPaint2GrPaintNoShader(SkGpuDevice* dev, SkScalar matrix[20]; SkBitmap colorTransformTable; grPaint->resetColorFilter(); + // TODO: SkColorFilter::asCustomStage() if (colorFilter != NULL && colorFilter->asColorMode(&color, &filterMode)) { grPaint->fColorMatrixEnabled = false; if (!constantColor) { @@ -558,13 +559,12 @@ inline bool skPaint2GrPaintNoShader(SkGpuDevice* dev, grPaint->fColorMatrixEnabled = true; memcpy(grPaint->fColorMatrix, matrix, sizeof(matrix)); grPaint->fColorFilterXfermode = SkXfermode::kDst_Mode; - } else if (colorFilter != NULL && colorFilter->asComponentTable( - &colorTransformTable)) { + } else if (colorFilter != NULL && colorFilter->asComponentTable(&colorTransformTable)) { grPaint->resetColorFilter(); + // pass NULL because the color table effect doesn't use tiling or filtering. + GrTexture* texture = act->set(dev, colorTransformTable, NULL); GrSamplerState* colorSampler = grPaint->textureSampler(kColorFilterTextureIdx); - GrTexture* texture = act->set(dev, colorTransformTable, colorSampler->textureParams()); - colorSampler->reset(); colorSampler->setCustomStage(SkNEW_ARGS(GrColorTableEffect, (texture)))->unref(); } @@ -638,15 +638,16 @@ inline bool skPaint2GrPaintShader(SkGpuDevice* dev, } // Must set wrap and filter on the sampler before requesting a texture. - sampler->textureParams()->reset(tileModes, skPaint.isFilterBitmap()); - GrTexture* texture = textures[kShaderTextureIdx].set(dev, bitmap, sampler->textureParams()); + GrTextureParams params(tileModes, skPaint.isFilterBitmap()); + GrTexture* texture = textures[kShaderTextureIdx].set(dev, bitmap, ¶ms); if (NULL == texture) { SkDebugf("Couldn't convert bitmap to texture.\n"); return false; } - sampler->setCustomStage(SkNEW_ARGS(GrSingleTextureEffect, (texture)))->unref(); + sampler->reset(); + sampler->setCustomStage(SkNEW_ARGS(GrSingleTextureEffect, (texture, params)))->unref(); // since our texture coords will be in local space, we wack the texture // matrix to map them back into 0...1 before we load it @@ -923,7 +924,6 @@ bool drawWithGPUMaskFilter(GrContext* context, const SkPath& path, if (!isNormalBlur) { GrPaint paint; paint.reset(); - paint.textureSampler(0)->textureParams()->setClampNoFilter(); paint.textureSampler(0)->matrix()->setIDiv(pathTexture->width(), pathTexture->height()); // Blend pathTexture over blurTexture. @@ -1269,7 +1269,7 @@ void SkGpuDevice::drawBitmap(const SkDraw& draw, srcRect.set(0,0, srcRect.width(), srcRect.height()); } SkPaint paintWithTexture(paint); - paintWithTexture.setShader(SkShader::CreateBitmapShader( *bitmapPtr, + paintWithTexture.setShader(SkShader::CreateBitmapShader(*bitmapPtr, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode))->unref(); SkRect ScalarRect; ScalarRect.set(srcRect); @@ -1292,13 +1292,13 @@ void SkGpuDevice::drawBitmap(const SkDraw& draw, if (!skPaint2GrPaintNoShader(this, paint, true, false, &colorLutTexture, &grPaint)) { return; } - GrTextureParams* params = grPaint.textureSampler(kBitmapTextureIdx)->textureParams(); - params->setBilerp(paint.isFilterBitmap()); + GrTextureParams params; + params.setBilerp(paint.isFilterBitmap()); int tileSize; - if (!this->shouldTileBitmap(bitmap, *params, srcRectPtr, &tileSize)) { + if (!this->shouldTileBitmap(bitmap, params, srcRectPtr, &tileSize)) { // take the simple case - this->internalDrawBitmap(draw, bitmap, srcRect, m, &grPaint); + this->internalDrawBitmap(draw, bitmap, srcRect, m, params, &grPaint); return; } @@ -1348,7 +1348,7 @@ void SkGpuDevice::drawBitmap(const SkDraw& draw, int dy = tileR.fTop - DY + SkMax32(0, srcR.fTop); tmpM.preTranslate(SkIntToScalar(dx), SkIntToScalar(dy)); } - this->internalDrawBitmap(draw, tmpB, srcR, tmpM, &grPaint); + this->internalDrawBitmap(draw, tmpB, srcR, tmpM, params, &grPaint); } } } @@ -1408,6 +1408,7 @@ void SkGpuDevice::internalDrawBitmap(const SkDraw& draw, const SkBitmap& bitmap, const SkIRect& srcRect, const SkMatrix& m, + const GrTextureParams& params, GrPaint* grPaint) { SkASSERT(bitmap.width() <= fContext->getMaxTextureSize() && bitmap.height() <= fContext->getMaxTextureSize()); @@ -1420,18 +1421,14 @@ void SkGpuDevice::internalDrawBitmap(const SkDraw& draw, GrSamplerState* sampler = grPaint->textureSampler(kBitmapTextureIdx); - sampler->textureParams()->setClamp(); sampler->matrix()->reset(); GrTexture* texture; - SkAutoCachedTexture act(this, bitmap, sampler->textureParams(), &texture); + SkAutoCachedTexture act(this, bitmap, ¶ms, &texture); if (NULL == texture) { return; } - grPaint->textureSampler(kBitmapTextureIdx)->setCustomStage(SkNEW_ARGS - (GrSingleTextureEffect, (texture)))->unref(); - GrRect dstRect = SkRect::MakeWH(GrIntToScalar(srcRect.width()), GrIntToScalar(srcRect.height())); GrRect paintRect; @@ -1443,7 +1440,7 @@ void SkGpuDevice::internalDrawBitmap(const SkDraw& draw, SkFloatToScalar(srcRect.fBottom * hInv)); bool needsTextureDomain = false; - if (sampler->textureParams()->isBilerp()) { + if (params.isBilerp()) { // Need texture domain if drawing a sub rect. needsTextureDomain = srcRect.width() < bitmap.width() || srcRect.height() < bitmap.height(); if (m.rectStaysRect() && draw.fMatrix->rectStaysRect()) { @@ -1455,8 +1452,8 @@ void SkGpuDevice::internalDrawBitmap(const SkDraw& draw, srcToDeviceMatrix.mapRect(&transformedRect, floatSrcRect); if (hasAlignedSamples(floatSrcRect, transformedRect)) { - // Samples are texel-aligned, so filtering is futile - sampler->textureParams()->setBilerp(false); + // We could also turn off filtering here (but we already did a cache lookup with + // params). needsTextureDomain = false; } else { needsTextureDomain = needsTextureDomain && @@ -1466,7 +1463,7 @@ void SkGpuDevice::internalDrawBitmap(const SkDraw& draw, } GrRect textureDomain = GrRect::MakeEmpty(); - + SkAutoTUnref stage; if (needsTextureDomain) { // Use a constrained texture domain to avoid color bleeding GrScalar left, top, right, bottom; @@ -1485,11 +1482,11 @@ void SkGpuDevice::internalDrawBitmap(const SkDraw& draw, top = bottom = GrScalarHalf(paintRect.top() + paintRect.bottom()); } textureDomain.setLTRB(left, top, right, bottom); - sampler->setCustomStage(SkNEW_ARGS(GrTextureDomainEffect, - (texture, - textureDomain)))->unref(); + stage.reset(SkNEW_ARGS(GrTextureDomainEffect, (texture, textureDomain, params))); + } else { + stage.reset(SkNEW_ARGS(GrSingleTextureEffect, (texture, params))); } - + grPaint->textureSampler(kBitmapTextureIdx)->setCustomStage(stage); fContext->drawRectToRect(*grPaint, dstRect, paintRect, &m); } @@ -1509,7 +1506,6 @@ void apply_custom_stage(GrContext* context, sampleM.setIDiv(srcTexture->width(), srcTexture->height()); GrPaint paint; paint.reset(); - paint.textureSampler(0)->textureParams()->setBilerp(true); paint.textureSampler(0)->reset(sampleM); paint.textureSampler(0)->setCustomStage(stage); context->drawRect(paint, rect); @@ -1563,7 +1559,8 @@ void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap, GrTexture* texture; sampler->reset(); - SkAutoCachedTexture act(this, bitmap, sampler->textureParams(), &texture); + // draw sprite uses the default texture params + SkAutoCachedTexture act(this, bitmap, NULL, &texture); grPaint.textureSampler(kBitmapTextureIdx)->setCustomStage(SkNEW_ARGS (GrSingleTextureEffect, (texture)))->unref(); @@ -1668,7 +1665,9 @@ bool SkGpuDevice::filterImage(SkImageFilter* filter, const SkBitmap& src, GrSamplerState* sampler = paint.textureSampler(kBitmapTextureIdx); GrTexture* texture; - SkAutoCachedTexture act(this, src, sampler->textureParams(), &texture); + // We assume here that the filter will not attempt to tile the src. Otherwise, this cache lookup + // must be pushed upstack. + SkAutoCachedTexture act(this, src, NULL, &texture); result->setConfig(src.config(), src.width(), src.height()); GrRect rect = GrRect::MakeWH(SkIntToScalar(src.width()), diff --git a/src/gpu/effects/GrSingleTextureEffect.cpp b/src/gpu/effects/GrSingleTextureEffect.cpp index b2e920538..e96eb47c0 100644 --- a/src/gpu/effects/GrSingleTextureEffect.cpp +++ b/src/gpu/effects/GrSingleTextureEffect.cpp @@ -41,6 +41,14 @@ GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture) : fTextureAccess(texture) { } +GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture, bool bilerp) + : fTextureAccess(texture, bilerp) { +} + +GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture, const GrTextureParams& params) + : fTextureAccess(texture, params) { +} + GrSingleTextureEffect::~GrSingleTextureEffect() { } diff --git a/src/gpu/effects/GrSingleTextureEffect.h b/src/gpu/effects/GrSingleTextureEffect.h index 209019623..4d0a40f33 100644 --- a/src/gpu/effects/GrSingleTextureEffect.h +++ b/src/gpu/effects/GrSingleTextureEffect.h @@ -18,7 +18,14 @@ class GrGLSingleTextureEffect; class GrSingleTextureEffect : public GrCustomStage { public: + /** Uses default texture params (unfiltered, clamp) */ GrSingleTextureEffect(GrTexture* texture); + + /** Uses default tile mode (clamp) */ + GrSingleTextureEffect(GrTexture* texture, bool bilerp); + + GrSingleTextureEffect(GrTexture* texture, const GrTextureParams&); + virtual ~GrSingleTextureEffect(); virtual int numTextures() const SK_OVERRIDE; diff --git a/src/gpu/effects/GrTextureDomainEffect.cpp b/src/gpu/effects/GrTextureDomainEffect.cpp index 279e48137..c00f40f08 100644 --- a/src/gpu/effects/GrTextureDomainEffect.cpp +++ b/src/gpu/effects/GrTextureDomainEffect.cpp @@ -91,11 +91,18 @@ void GrGLTextureDomainEffect::setData(const GrGLUniformManager& uman, /////////////////////////////////////////////////////////////////////////////// -GrTextureDomainEffect::GrTextureDomainEffect(GrTexture* texture, GrRect domain) +GrTextureDomainEffect::GrTextureDomainEffect(GrTexture* texture, const GrRect& domain) : GrSingleTextureEffect(texture) , fTextureDomain(domain) { } +GrTextureDomainEffect::GrTextureDomainEffect(GrTexture* texture, + const GrRect& domain, + const GrTextureParams& params) + : GrSingleTextureEffect(texture, params) + , fTextureDomain(domain) { +} + GrTextureDomainEffect::~GrTextureDomainEffect() { } diff --git a/src/gpu/effects/GrTextureDomainEffect.h b/src/gpu/effects/GrTextureDomainEffect.h index 559398eca..872d57de2 100644 --- a/src/gpu/effects/GrTextureDomainEffect.h +++ b/src/gpu/effects/GrTextureDomainEffect.h @@ -20,8 +20,11 @@ class GrGLTextureDomainEffect; class GrTextureDomainEffect : public GrSingleTextureEffect { public: + /** Uses default texture params (no filter, clamp) */ + GrTextureDomainEffect(GrTexture*, const GrRect& domain); + + GrTextureDomainEffect(GrTexture*, const GrRect& domain, const GrTextureParams& params); - GrTextureDomainEffect(GrTexture*, GrRect domain); virtual ~GrTextureDomainEffect(); static const char* Name() { return "TextureDomain"; } diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp index 1cca043ee..d9988c42e 100644 --- a/src/gpu/gl/GrGpuGL.cpp +++ b/src/gpu/gl/GrGpuGL.cpp @@ -2024,9 +2024,7 @@ void GrGpuGL::flushBoundTextureAndParams(int stage) { const GrCustomStage* customStage = drawState->sampler(stage)->getCustomStage(); GrGLTexture* nextTexture = static_cast(customStage->texture(0)); if (NULL != nextTexture) { - // Currently we always use the texture params from the GrSamplerState. Soon custom stages - // will provide their own params. - const GrTextureParams& texParams = drawState->getSampler(stage).getTextureParams(); + const GrTextureParams& texParams = customStage->textureAccess(0).getParams(); this->flushBoundTextureAndParams(stage, texParams, nextTexture); } }