From d0c1a06cb98dd4a009dfa79e37ba6ca23a8c180b Mon Sep 17 00:00:00 2001 From: "tomhudson@google.com" Date: Thu, 12 Jul 2012 17:23:52 +0000 Subject: [PATCH] Introduces new SingleTextureEffect base class for GrCustomStage objects. This class tracks the texture that the object uses. A future commit will get rid of the GrTexture pointer currenty stored in the GrDrawState, allowing us to have CustomStages *without* textures. Requires gyp change on next roll. http://codereview.appspot.com/6306097/ git-svn-id: http://skia.googlecode.com/svn/trunk@4576 2bbb7eff-a529-9590-31e7-b0007b416f81 --- gyp/gpu.gyp | 2 + include/core/SkImageFilter.h | 3 +- include/gpu/GrCustomStage.h | 19 +++++-- src/core/SkPaint.cpp | 2 +- src/effects/SkLightingImageFilter.cpp | 63 +++++++++++++---------- src/gpu/GrContext.cpp | 4 +- src/gpu/GrCustomStage.cpp | 21 ++++++++ src/gpu/SkGpuDevice.cpp | 29 ++++++----- src/gpu/effects/Gr1DKernelEffect.h | 12 +++-- src/gpu/effects/GrConvolutionEffect.cpp | 15 +++--- src/gpu/effects/GrConvolutionEffect.h | 3 +- src/gpu/effects/GrGradientEffects.cpp | 32 +++++++----- src/gpu/effects/GrGradientEffects.h | 35 ++++++------- src/gpu/effects/GrMorphologyEffect.cpp | 12 +++-- src/gpu/effects/GrMorphologyEffect.h | 2 +- src/gpu/effects/GrSingleTextureEffect.cpp | 29 +++++++++++ src/gpu/effects/GrSingleTextureEffect.h | 28 ++++++++++ src/gpu/gl/GrGLProgramStage.cpp | 1 - src/gpu/gl/GrGLProgramStage.h | 1 - src/gpu/gl/GrGpuGL.cpp | 15 ++++++ src/gpu/gl/GrGpuGL.h | 1 + src/gpu/gl/GrGpuGL_program.cpp | 2 +- src/gpu/gl/GrGpuGL_unittest.cpp | 27 +++++----- 23 files changed, 243 insertions(+), 115 deletions(-) create mode 100644 src/gpu/effects/GrSingleTextureEffect.cpp create mode 100644 src/gpu/effects/GrSingleTextureEffect.h diff --git a/gyp/gpu.gyp b/gyp/gpu.gyp index cabd331488..4a708d8e38 100644 --- a/gyp/gpu.gyp +++ b/gyp/gpu.gyp @@ -293,6 +293,8 @@ '../src/gpu/effects/GrGradientEffects.h', '../src/gpu/effects/GrMorphologyEffect.cpp', '../src/gpu/effects/GrMorphologyEffect.h', + '../src/gpu/effects/GrSingleTextureEffect.cpp', + '../src/gpu/effects/GrSingleTextureEffect.h', '../src/gpu/gl/GrGLCaps.cpp', '../src/gpu/gl/GrGLCaps.h', diff --git a/include/core/SkImageFilter.h b/include/core/SkImageFilter.h index b7bf8bcfef..0915b90714 100644 --- a/include/core/SkImageFilter.h +++ b/include/core/SkImageFilter.h @@ -15,6 +15,7 @@ class SkDevice; class SkMatrix; struct SkPoint; class GrCustomStage; +class GrTexture; /** * Experimental. @@ -86,7 +87,7 @@ public: * in it. The caller assumes ownership of the stage, and it is up to the * caller to unref it. */ - virtual bool asNewCustomStage(GrCustomStage** stage) const; + virtual bool asNewCustomStage(GrCustomStage** stage, GrTexture*) const; /** * Experimental. diff --git a/include/gpu/GrCustomStage.h b/include/gpu/GrCustomStage.h index fd01c9a767..9f5efd33fb 100644 --- a/include/gpu/GrCustomStage.h +++ b/include/gpu/GrCustomStage.h @@ -13,11 +13,17 @@ #include "GrProgramStageFactory.h" class GrContext; +class GrTexture; /** Provides custom vertex shader, fragment shader, uniform data for a particular stage of the Ganesh shading pipeline. Subclasses must have a function that produces a human-readable name: static const char* Name(); + GrCustomStage objects *must* be immutable: after being constructed, + their fields may not change. (Immutability isn't actually required + until they've been used in a draw call, but supporting that would require + setters and getters that could fail, copy-on-write, or deep copying of these + objects when they're stored by a GrGLProgramStage.) */ class GrCustomStage : public GrRefCnt { @@ -60,15 +66,22 @@ public: To test for equivalence (that they will generate the same shader code, but may have different uniforms), check equality of the stageKey produced by the GrProgramStageFactory: - a.getFactory().glStageKey(a) == b.getFactory().glStageKey(b). */ - virtual bool isEqual(const GrCustomStage&) const = 0; + a.getFactory().glStageKey(a) == b.getFactory().glStageKey(b). + + The default implementation of this function returns true iff + the two stages have the same return value for numTextures() and + for texture() over all valid indicse. + */ + virtual bool isEqual(const GrCustomStage&) const; /** Human-meaningful string to identify this effect; may be embedded in generated shader code. */ const char* name() const { return this->getFactory().name(); } -private: + virtual unsigned int numTextures() const; + virtual GrTexture* texture(unsigned int index) const; +private: typedef GrRefCnt INHERITED; }; diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp index ea2d1f636e..19abb4b085 100644 --- a/src/core/SkPaint.cpp +++ b/src/core/SkPaint.cpp @@ -2214,7 +2214,7 @@ bool SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, return true; } -bool SkImageFilter::asNewCustomStage(GrCustomStage**) const { +bool SkImageFilter::asNewCustomStage(GrCustomStage**, GrTexture*) const { return false; } diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp index acfc73b789..8d1e8e7714 100644 --- a/src/effects/SkLightingImageFilter.cpp +++ b/src/effects/SkLightingImageFilter.cpp @@ -9,6 +9,7 @@ #include "SkBitmap.h" #include "SkColorPriv.h" #include "GrProgramStageFactory.h" +#include "effects/GrSingleTextureEffect.h" #include "gl/GrGLProgramStage.h" #include "gl/GrGLSL.h" #include "gl/GrGLTexture.h" @@ -251,7 +252,7 @@ public: SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar kd); SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDiffuseLightingImageFilter) - virtual bool asNewCustomStage(GrCustomStage** stage) const SK_OVERRIDE; + virtual bool asNewCustomStage(GrCustomStage** stage, GrTexture*) const SK_OVERRIDE; SkScalar kd() const { return fKD; } protected: @@ -271,7 +272,7 @@ public: SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess); SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSpecularLightingImageFilter) - virtual bool asNewCustomStage(GrCustomStage** stage) const SK_OVERRIDE; + virtual bool asNewCustomStage(GrCustomStage** stage, GrTexture*) const SK_OVERRIDE; SkScalar ks() const { return fKS; } SkScalar shininess() const { return fShininess; } @@ -288,9 +289,9 @@ private: }; -class GrLightingEffect : public GrCustomStage { +class GrLightingEffect : public GrSingleTextureEffect { public: - GrLightingEffect(const SkLight* light, SkScalar surfaceScale); + GrLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale); virtual ~GrLightingEffect(); virtual bool isEqual(const GrCustomStage&) const SK_OVERRIDE; @@ -298,14 +299,17 @@ public: const SkLight* light() const { return fLight; } SkScalar surfaceScale() const { return fSurfaceScale; } private: - typedef GrCustomStage INHERITED; + typedef GrSingleTextureEffect INHERITED; const SkLight* fLight; SkScalar fSurfaceScale; }; class GrDiffuseLightingEffect : public GrLightingEffect { public: - GrDiffuseLightingEffect(const SkLight* light, SkScalar surfaceScale, SkScalar kd); + GrDiffuseLightingEffect(GrTexture* texture, + const SkLight* light, + SkScalar surfaceScale, + SkScalar kd); static const char* Name() { return "DiffuseLighting"; } @@ -321,7 +325,11 @@ private: class GrSpecularLightingEffect : public GrLightingEffect { public: - GrSpecularLightingEffect(const SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess); + GrSpecularLightingEffect(GrTexture* texture, + const SkLight* light, + SkScalar surfaceScale, + SkScalar ks, + SkScalar shininess); static const char* Name() { return "SpecularLighting"; } @@ -775,10 +783,11 @@ bool SkDiffuseLightingImageFilter::onFilterImage(Proxy*, return true; } -bool SkDiffuseLightingImageFilter::asNewCustomStage(GrCustomStage** stage) const { +bool SkDiffuseLightingImageFilter::asNewCustomStage(GrCustomStage** stage, + GrTexture* texture) const { if (stage) { SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255)); - *stage = new GrDiffuseLightingEffect(light(), scale, kd()); + *stage = new GrDiffuseLightingEffect(texture, light(), scale, kd()); } return true; } @@ -838,10 +847,11 @@ bool SkSpecularLightingImageFilter::onFilterImage(Proxy*, return true; } -bool SkSpecularLightingImageFilter::asNewCustomStage(GrCustomStage** stage) const { +bool SkSpecularLightingImageFilter::asNewCustomStage(GrCustomStage** stage, + GrTexture* texture) const { if (stage) { SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255)); - *stage = new GrSpecularLightingEffect(light(), scale, ks(), shininess()); + *stage = new GrSpecularLightingEffect(texture, light(), scale, ks(), shininess()); } return true; } @@ -869,7 +879,6 @@ public: virtual void initUniforms(const GrGLInterface*, int programID) SK_OVERRIDE; virtual void setData(const GrGLInterface*, - const GrGLTexture&, const GrCustomStage&, int stageNum) SK_OVERRIDE; @@ -894,7 +903,6 @@ public: virtual void emitLightFunc(SkString* funcs) SK_OVERRIDE; virtual void initUniforms(const GrGLInterface*, int programID) SK_OVERRIDE; virtual void setData(const GrGLInterface*, - const GrGLTexture&, const GrCustomStage&, int stageNum) SK_OVERRIDE; @@ -916,7 +924,6 @@ public: virtual void emitLightFunc(SkString* funcs) SK_OVERRIDE; virtual void initUniforms(const GrGLInterface*, int programID) SK_OVERRIDE; virtual void setData(const GrGLInterface*, - const GrGLTexture&, const GrCustomStage&, int stageNum) SK_OVERRIDE; @@ -931,8 +938,9 @@ private: /////////////////////////////////////////////////////////////////////////////// -GrLightingEffect::GrLightingEffect(const SkLight* light, SkScalar surfaceScale) - : fLight(light) +GrLightingEffect::GrLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale) + : GrSingleTextureEffect(texture) + , fLight(light) , fSurfaceScale(surfaceScale) { fLight->ref(); } @@ -944,14 +952,15 @@ GrLightingEffect::~GrLightingEffect() { bool GrLightingEffect::isEqual(const GrCustomStage& sBase) const { const GrLightingEffect& s = static_cast(sBase); - return fLight->isEqual(*s.fLight) && + return INHERITED::isEqual(sBase) && + fLight->isEqual(*s.fLight) && fSurfaceScale == s.fSurfaceScale; } /////////////////////////////////////////////////////////////////////////////// -GrDiffuseLightingEffect::GrDiffuseLightingEffect(const SkLight* light, SkScalar surfaceScale, SkScalar kd) - : INHERITED(light, surfaceScale), fKD(kd) { +GrDiffuseLightingEffect::GrDiffuseLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale, SkScalar kd) + : INHERITED(texture, light, surfaceScale), fKD(kd) { } const GrProgramStageFactory& GrDiffuseLightingEffect::getFactory() const { @@ -1056,11 +1065,11 @@ GrGLProgramStage::StageKey GrGLLightingEffect::GenKey( } void GrGLLightingEffect::setData(const GrGLInterface* gl, - const GrGLTexture& texture, const GrCustomStage& data, int stageNum) { const GrLightingEffect& effect = static_cast(data); + GrTexture& texture = *data.texture(0); GR_GL_CALL(gl, Uniform2f(fImageIncrementLocation, 1.0f / texture.width(), 1.0f / texture.height())); GR_GL_CALL(gl, Uniform1f(fSurfaceScaleLocation, effect.surfaceScale())); fLight->setData(gl, effect.light()); @@ -1100,10 +1109,9 @@ void GrGLDiffuseLightingEffect::emitLightFunc(SkString* funcs) { } void GrGLDiffuseLightingEffect::setData(const GrGLInterface* gl, - const GrGLTexture& texture, const GrCustomStage& data, int stageNum) { - INHERITED::setData(gl, texture, data, stageNum); + INHERITED::setData(gl, data, stageNum); const GrDiffuseLightingEffect& effect = static_cast(data); GR_GL_CALL(gl, Uniform1f(fKDLocation, effect.kd())); @@ -1111,8 +1119,8 @@ void GrGLDiffuseLightingEffect::setData(const GrGLInterface* gl, /////////////////////////////////////////////////////////////////////////////// -GrSpecularLightingEffect::GrSpecularLightingEffect(const SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess) - : INHERITED(light, surfaceScale), +GrSpecularLightingEffect::GrSpecularLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess) + : INHERITED(texture, light, surfaceScale), fKS(ks), fShininess(shininess) { } @@ -1170,10 +1178,9 @@ void GrGLSpecularLightingEffect::emitLightFunc(SkString* funcs) { } void GrGLSpecularLightingEffect::setData(const GrGLInterface* gl, - const GrGLTexture& texture, - const GrCustomStage& data, - int stageNum) { - INHERITED::setData(gl, texture, data, stageNum); + const GrCustomStage& data, + int stageNum) { + INHERITED::setData(gl, data, stageNum); const GrSpecularLightingEffect& effect = static_cast(data); GR_GL_CALL(gl, Uniform1f(fKSLocation, effect.ks())); diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 149359f83e..95e0ecac63 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -244,7 +244,7 @@ void apply_morphology(GrGpu* gpu, sampleM.setIDiv(texture->width(), texture->height()); drawState->sampler(0)->reset(sampleM); SkAutoTUnref morph( - SkNEW_ARGS(GrMorphologyEffect, (direction, radius, morphType))); + SkNEW_ARGS(GrMorphologyEffect, (texture, direction, radius, morphType))); drawState->sampler(0)->setCustomStage(morph); drawState->setTexture(0, texture); gpu->drawSimpleRect(rect, NULL, 1 << 0); @@ -264,7 +264,7 @@ void convolve_gaussian(GrGpu* gpu, sampleM.setIDiv(texture->width(), texture->height()); drawState->sampler(0)->reset(sampleM); SkAutoTUnref conv(SkNEW_ARGS(GrConvolutionEffect, - (direction, radius))); + (texture, direction, radius))); conv->setGaussianKernel(sigma); drawState->sampler(0)->setCustomStage(conv); drawState->setTexture(0, texture); diff --git a/src/gpu/GrCustomStage.cpp b/src/gpu/GrCustomStage.cpp index c0ec330339..66b78a6635 100644 --- a/src/gpu/GrCustomStage.cpp +++ b/src/gpu/GrCustomStage.cpp @@ -14,6 +14,7 @@ int32_t GrProgramStageFactory::fCurrStageClassID = GrProgramStageFactory::kIllegalStageClassID; GrCustomStage::GrCustomStage() { + } GrCustomStage::~GrCustomStage() { @@ -24,3 +25,23 @@ bool GrCustomStage::isOpaque(bool inputTextureIsOpaque) const { return false; } +bool GrCustomStage::isEqual(const GrCustomStage& s) const { + if (this->numTextures() != s.numTextures()) { + return false; + } + for (unsigned int i = 0; i < this->numTextures(); ++i) { + if (this->texture(i) != s.texture(i)) { + return false; + } + } + return true; +} + +unsigned int GrCustomStage::numTextures() const { + return 0; +} + +GrTexture* GrCustomStage::texture(unsigned int index) const { + return NULL; +} + diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index 2a2bbcdc37..11543136a6 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -536,26 +536,36 @@ inline bool skPaint2GrPaintShader(SkGpuDevice* dev, } return false; } + GrSamplerState* sampler = grPaint->textureSampler(kShaderTextureIdx); + GrTexture* texture = act->set(dev, bitmap, sampler); + if (NULL == texture) { + SkDebugf("Couldn't convert bitmap to texture.\n"); + return false; + } + grPaint->setTexture(kShaderTextureIdx, texture); + switch (bmptype) { case SkShader::kRadial_BitmapType: - sampler->setCustomStage(SkNEW(GrRadialGradient))->unref(); + sampler->setCustomStage(SkNEW_ARGS(GrRadialGradient, (texture)))->unref(); sampler->setFilter(GrSamplerState::kBilinear_Filter); break; case SkShader::kSweep_BitmapType: - sampler->setCustomStage(SkNEW(GrSweepGradient))->unref(); + sampler->setCustomStage(SkNEW_ARGS(GrSweepGradient, (texture)))->unref(); sampler->setFilter(GrSamplerState::kBilinear_Filter); break; case SkShader::kTwoPointRadial_BitmapType: sampler->setCustomStage(SkNEW_ARGS(GrRadial2Gradient, - (twoPointParams[0], + (texture, + twoPointParams[0], twoPointParams[1], twoPointParams[2] < 0)))->unref(); sampler->setFilter(GrSamplerState::kBilinear_Filter); break; case SkShader::kTwoPointConical_BitmapType: sampler->setCustomStage(SkNEW_ARGS(GrConical2Gradient, - (twoPointParams[0], + (texture, + twoPointParams[0], twoPointParams[1], twoPointParams[2])))->unref(); sampler->setFilter(GrSamplerState::kBilinear_Filter); @@ -571,13 +581,6 @@ inline bool skPaint2GrPaintShader(SkGpuDevice* dev, sampler->setWrapX(sk_tile_mode_to_grwrap(tileModes[0])); sampler->setWrapY(sk_tile_mode_to_grwrap(tileModes[1])); - GrTexture* texture = act->set(dev, bitmap, sampler); - if (NULL == texture) { - SkDebugf("Couldn't convert bitmap to texture.\n"); - return false; - } - grPaint->setTexture(kShaderTextureIdx, texture); - // 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 SkMatrix localM; @@ -1474,7 +1477,7 @@ static GrTexture* filter_texture(GrContext* context, GrTexture* texture, desc.fConfig = kRGBA_8888_PM_GrPixelConfig; GrCustomStage* stage; - if (filter->asNewCustomStage(&stage)) { + if (filter->asNewCustomStage(&stage, texture)) { GrAutoScratchTexture dst(context, desc); apply_custom_stage(context, texture, dst.texture(), rect, stage); texture = dst.detach(); @@ -1607,7 +1610,7 @@ bool SkGpuDevice::canHandleImageFilter(SkImageFilter* filter) { SkSize size; SkISize radius; - if (!filter->asNewCustomStage(NULL) && + if (!filter->asNewCustomStage(NULL, NULL) && !filter->asABlur(&size) && !filter->asADilate(&radius) && !filter->asAnErode(&radius)) { diff --git a/src/gpu/effects/Gr1DKernelEffect.h b/src/gpu/effects/Gr1DKernelEffect.h index b6e116fa96..9ef765268c 100644 --- a/src/gpu/effects/Gr1DKernelEffect.h +++ b/src/gpu/effects/Gr1DKernelEffect.h @@ -8,7 +8,7 @@ #ifndef Gr1DKernelEffect_DEFINED #define Gr1DKernelEffect_DEFINED -#include "GrCustomStage.h" +#include "GrSingleTextureEffect.h" /** * Base class for 1D kernel effects. The kernel operates either in X or Y and @@ -18,7 +18,7 @@ * read. Since the center pixel is also read, the total width is one larger than * two times the radius. */ -class Gr1DKernelEffect : public GrCustomStage { +class Gr1DKernelEffect : public GrSingleTextureEffect { public: enum Direction { @@ -26,9 +26,11 @@ public: kY_Direction, }; - Gr1DKernelEffect(Direction direction, + Gr1DKernelEffect(GrTexture* texture, + Direction direction, int radius) - : fDirection(direction) + : GrSingleTextureEffect(texture) + , fDirection(direction) , fRadius(radius) {} virtual ~Gr1DKernelEffect() {}; @@ -44,7 +46,7 @@ private: Direction fDirection; int fRadius; - typedef GrCustomStage INHERITED; + typedef GrSingleTextureEffect INHERITED; }; #endif diff --git a/src/gpu/effects/GrConvolutionEffect.cpp b/src/gpu/effects/GrConvolutionEffect.cpp index 42dc2b49f1..4970d6270d 100644 --- a/src/gpu/effects/GrConvolutionEffect.cpp +++ b/src/gpu/effects/GrConvolutionEffect.cpp @@ -28,7 +28,6 @@ public: virtual void initUniforms(const GrGLInterface*, int programID) SK_OVERRIDE; virtual void setData(const GrGLInterface*, - const GrGLTexture&, const GrCustomStage&, int stageNum) SK_OVERRIDE; @@ -118,11 +117,11 @@ void GrGLConvolutionEffect::initUniforms(const GrGLInterface* gl, } void GrGLConvolutionEffect::setData(const GrGLInterface* gl, - const GrGLTexture& texture, const GrCustomStage& data, int stageNum) { const GrConvolutionEffect& conv = static_cast(data); + GrTexture& texture = *data.texture(0); // the code we generated was for a specific kernel radius GrAssert(conv.radius() == fRadius); float imageIncrement[2] = { 0 }; @@ -148,10 +147,11 @@ GrGLProgramStage::StageKey GrGLConvolutionEffect::GenKey( /////////////////////////////////////////////////////////////////////////////// -GrConvolutionEffect::GrConvolutionEffect(Direction direction, +GrConvolutionEffect::GrConvolutionEffect(GrTexture* texture, + Direction direction, int radius, const float* kernel) - : Gr1DKernelEffect(direction, radius) { + : Gr1DKernelEffect(texture, direction, radius) { GrAssert(radius <= kMaxKernelRadius); int width = this->width(); if (NULL != kernel) { @@ -171,9 +171,10 @@ const GrProgramStageFactory& GrConvolutionEffect::getFactory() const { bool GrConvolutionEffect::isEqual(const GrCustomStage& sBase) const { const GrConvolutionEffect& s = static_cast(sBase); - return (this->radius() == s.radius() && - this->direction() == s.direction() && - 0 == memcmp(fKernel, s.fKernel, this->width() * sizeof(float))); + return (INHERITED::isEqual(sBase) && + this->radius() == s.radius() && + this->direction() == s.direction() && + 0 == memcmp(fKernel, s.fKernel, this->width() * sizeof(float))); } void GrConvolutionEffect::setGaussianKernel(float sigma) { diff --git a/src/gpu/effects/GrConvolutionEffect.h b/src/gpu/effects/GrConvolutionEffect.h index fd6883b430..58cad83b53 100644 --- a/src/gpu/effects/GrConvolutionEffect.h +++ b/src/gpu/effects/GrConvolutionEffect.h @@ -21,7 +21,8 @@ class GrConvolutionEffect : public Gr1DKernelEffect { public: - GrConvolutionEffect(Direction, int halfWidth, const float* kernel = NULL); + GrConvolutionEffect(GrTexture*, Direction, + int halfWidth, const float* kernel = NULL); virtual ~GrConvolutionEffect(); void setKernel(const float* kernel) { diff --git a/src/gpu/effects/GrGradientEffects.cpp b/src/gpu/effects/GrGradientEffects.cpp index 604595692d..d4719b3a24 100644 --- a/src/gpu/effects/GrGradientEffects.cpp +++ b/src/gpu/effects/GrGradientEffects.cpp @@ -49,7 +49,8 @@ void GrGLRadialGradient::emitFS(GrGLShaderBuilder* state, ///////////////////////////////////////////////////////////////////// -GrRadialGradient::GrRadialGradient() { +GrRadialGradient::GrRadialGradient(GrTexture* texture) + : GrSingleTextureEffect(texture) { } @@ -63,7 +64,7 @@ const GrProgramStageFactory& GrRadialGradient::getFactory() const { } bool GrRadialGradient::isEqual(const GrCustomStage& sBase) const { - return true; + return INHERITED::isEqual(sBase); } ///////////////////////////////////////////////////////////////////// @@ -86,7 +87,6 @@ public: const char* samplerName) SK_OVERRIDE; virtual void initUniforms(const GrGLInterface*, int programID) SK_OVERRIDE; virtual void setData(const GrGLInterface*, - const GrGLTexture&, const GrCustomStage&, int stageNum) SK_OVERRIDE; @@ -257,7 +257,6 @@ void GrGLRadial2Gradient::initUniforms(const GrGLInterface* gl, int programID) { } void GrGLRadial2Gradient::setData(const GrGLInterface* gl, - const GrGLTexture& texture, const GrCustomStage& baseData, int stageNum) { const GrRadial2Gradient& data = @@ -296,10 +295,12 @@ void GrGLRadial2Gradient::setData(const GrGLInterface* gl, ///////////////////////////////////////////////////////////////////// -GrRadial2Gradient::GrRadial2Gradient(GrScalar center, +GrRadial2Gradient::GrRadial2Gradient(GrTexture* texture, + GrScalar center, GrScalar radius, bool posRoot) - : fCenterX1 (center) + : GrSingleTextureEffect(texture) + , fCenterX1 (center) , fRadius0 (radius) , fPosRoot (posRoot) { @@ -316,7 +317,8 @@ const GrProgramStageFactory& GrRadial2Gradient::getFactory() const { bool GrRadial2Gradient::isEqual(const GrCustomStage& sBase) const { const GrRadial2Gradient& s = static_cast(sBase); - return (this->fCenterX1 == s.fCenterX1 && + return (INHERITED::isEqual(sBase) && + this->fCenterX1 == s.fCenterX1 && this->fRadius0 == s.fRadius0 && this->fPosRoot == s.fPosRoot); } @@ -341,7 +343,6 @@ public: const char* samplerName) SK_OVERRIDE; virtual void initUniforms(const GrGLInterface*, int programID) SK_OVERRIDE; virtual void setData(const GrGLInterface*, - const GrGLTexture&, const GrCustomStage&, int stageNum) SK_OVERRIDE; @@ -571,7 +572,6 @@ void GrGLConical2Gradient::initUniforms(const GrGLInterface* gl, int programID) } void GrGLConical2Gradient::setData(const GrGLInterface* gl, - const GrGLTexture& texture, const GrCustomStage& baseData, int stageNum) { const GrConical2Gradient& data = @@ -612,10 +612,12 @@ void GrGLConical2Gradient::setData(const GrGLInterface* gl, ///////////////////////////////////////////////////////////////////// -GrConical2Gradient::GrConical2Gradient(GrScalar center, +GrConical2Gradient::GrConical2Gradient(GrTexture* texture, + GrScalar center, GrScalar radius, GrScalar diffRadius) - : fCenterX1 (center) + : GrSingleTextureEffect (texture) + , fCenterX1 (center) , fRadius0 (radius) , fDiffRadius (diffRadius) { @@ -632,7 +634,8 @@ const GrProgramStageFactory& GrConical2Gradient::getFactory() const { bool GrConical2Gradient::isEqual(const GrCustomStage& sBase) const { const GrConical2Gradient& s = static_cast(sBase); - return (this->fCenterX1 == s.fCenterX1 && + return (INHERITED::isEqual(sBase) && + this->fCenterX1 == s.fCenterX1 && this->fRadius0 == s.fRadius0 && this->fDiffRadius == s.fDiffRadius); } @@ -677,7 +680,8 @@ void GrGLSweepGradient::emitFS(GrGLShaderBuilder* state, ///////////////////////////////////////////////////////////////////// -GrSweepGradient::GrSweepGradient() { +GrSweepGradient::GrSweepGradient(GrTexture* texture) + : GrSingleTextureEffect(texture) { } @@ -690,6 +694,6 @@ const GrProgramStageFactory& GrSweepGradient::getFactory() const { } bool GrSweepGradient::isEqual(const GrCustomStage& sBase) const { - return true; + return INHERITED::isEqual(sBase); } diff --git a/src/gpu/effects/GrGradientEffects.h b/src/gpu/effects/GrGradientEffects.h index cf6827f251..37e4642eab 100644 --- a/src/gpu/effects/GrGradientEffects.h +++ b/src/gpu/effects/GrGradientEffects.h @@ -8,7 +8,7 @@ #ifndef GrGradientEffects_DEFINED #define GrGradientEffects_DEFINED -#include "GrCustomStage.h" +#include "GrSingleTextureEffect.h" #include "GrTypes.h" #include "GrScalar.h" @@ -37,11 +37,11 @@ class GrGLRadialGradient; -class GrRadialGradient : public GrCustomStage { +class GrRadialGradient : public GrSingleTextureEffect { public: - GrRadialGradient(); + GrRadialGradient(GrTexture* texture); virtual ~GrRadialGradient(); static const char* Name() { return "Radial Gradient"; } @@ -52,24 +52,23 @@ public: private: - typedef GrCustomStage INHERITED; + typedef GrSingleTextureEffect INHERITED; }; class GrGLRadial2Gradient; -class GrRadial2Gradient : public GrCustomStage { +class GrRadial2Gradient : public GrSingleTextureEffect { public: - GrRadial2Gradient(GrScalar center, GrScalar radius, bool posRoot); + GrRadial2Gradient(GrTexture* texture, GrScalar center, GrScalar radius, bool posRoot); virtual ~GrRadial2Gradient(); static const char* Name() { return "Two-Point Radial Gradient"; } virtual const GrProgramStageFactory& getFactory() const SK_OVERRIDE; virtual bool isEqual(const GrCustomStage&) const SK_OVERRIDE; - // The radial gradient parameters can collapse to a linear (instead - // of quadratic) equation. + // The radial gradient parameters can collapse to a linear (instead of quadratic) equation. bool isDegenerate() const { return GR_Scalar1 == fCenterX1; } GrScalar center() const { return fCenterX1; } GrScalar radius() const { return fRadius0; } @@ -89,26 +88,24 @@ private: // @} - typedef GrCustomStage INHERITED; + typedef GrSingleTextureEffect INHERITED; }; class GrGLConical2Gradient; -class GrConical2Gradient : public GrCustomStage { +class GrConical2Gradient : public GrSingleTextureEffect { public: - GrConical2Gradient(GrScalar center, GrScalar radius, GrScalar diffRadius); + GrConical2Gradient(GrTexture* texture, GrScalar center, GrScalar radius, GrScalar diffRadius); virtual ~GrConical2Gradient(); static const char* Name() { return "Two-Point Conical Gradient"; } virtual const GrProgramStageFactory& getFactory() const SK_OVERRIDE; virtual bool isEqual(const GrCustomStage&) const SK_OVERRIDE; - // The radial gradient parameters can collapse to a linear (instead - // of quadratic) equation. - bool isDegenerate() const { return SkScalarAbs(fDiffRadius) == - SkScalarAbs(fCenterX1); } + // The radial gradient parameters can collapse to a linear (instead of quadratic) equation. + bool isDegenerate() const { return SkScalarAbs(fDiffRadius) == SkScalarAbs(fCenterX1); } GrScalar center() const { return fCenterX1; } GrScalar diffRadius() const { return fDiffRadius; } GrScalar radius() const { return fRadius0; } @@ -127,16 +124,16 @@ private: // @} - typedef GrCustomStage INHERITED; + typedef GrSingleTextureEffect INHERITED; }; class GrGLSweepGradient; -class GrSweepGradient : public GrCustomStage { +class GrSweepGradient : public GrSingleTextureEffect { public: - GrSweepGradient(); + GrSweepGradient(GrTexture* texture); virtual ~GrSweepGradient(); static const char* Name() { return "Sweep Gradient"; } @@ -147,7 +144,7 @@ public: protected: - typedef GrCustomStage INHERITED; + typedef GrSingleTextureEffect INHERITED; }; #endif diff --git a/src/gpu/effects/GrMorphologyEffect.cpp b/src/gpu/effects/GrMorphologyEffect.cpp index 43e870285f..3ea2cbd125 100644 --- a/src/gpu/effects/GrMorphologyEffect.cpp +++ b/src/gpu/effects/GrMorphologyEffect.cpp @@ -31,7 +31,6 @@ public: virtual void initUniforms(const GrGLInterface*, int programID) SK_OVERRIDE; virtual void setData(const GrGLInterface*, - const GrGLTexture&, const GrCustomStage&, int stageNum) SK_OVERRIDE; @@ -124,11 +123,12 @@ GrGLProgramStage::StageKey GrGLMorphologyEffect::GenKey( } void GrGLMorphologyEffect ::setData(const GrGLInterface* gl, - const GrGLTexture& texture, const GrCustomStage& data, int stageNum) { const Gr1DKernelEffect& kern = static_cast(data); + GrGLTexture& texture = + *static_cast(data.texture(0)); // the code we generated was for a specific kernel radius GrAssert(kern.radius() == fRadius); float imageIncrement[2] = { 0 }; @@ -147,10 +147,11 @@ void GrGLMorphologyEffect ::setData(const GrGLInterface* gl, /////////////////////////////////////////////////////////////////////////////// -GrMorphologyEffect::GrMorphologyEffect(Direction direction, +GrMorphologyEffect::GrMorphologyEffect(GrTexture* texture, + Direction direction, int radius, MorphologyType type) - : Gr1DKernelEffect(direction, radius) + : Gr1DKernelEffect(texture, direction, radius) , fType(type) { } @@ -164,7 +165,8 @@ const GrProgramStageFactory& GrMorphologyEffect::getFactory() const { bool GrMorphologyEffect::isEqual(const GrCustomStage& sBase) const { const GrMorphologyEffect& s = static_cast(sBase); - return (this->radius() == s.radius() && + return (INHERITED::isEqual(sBase) && + this->radius() == s.radius() && this->direction() == s.direction() && this->type() == s.type()); } diff --git a/src/gpu/effects/GrMorphologyEffect.h b/src/gpu/effects/GrMorphologyEffect.h index c784460819..c8bd2d51db 100644 --- a/src/gpu/effects/GrMorphologyEffect.h +++ b/src/gpu/effects/GrMorphologyEffect.h @@ -25,7 +25,7 @@ public: typedef GrContext::MorphologyType MorphologyType; - GrMorphologyEffect(Direction, int radius, MorphologyType); + GrMorphologyEffect(GrTexture*, Direction, int radius, MorphologyType); virtual ~GrMorphologyEffect(); MorphologyType type() const { return fType; } diff --git a/src/gpu/effects/GrSingleTextureEffect.cpp b/src/gpu/effects/GrSingleTextureEffect.cpp new file mode 100644 index 0000000000..a373ebe4e1 --- /dev/null +++ b/src/gpu/effects/GrSingleTextureEffect.cpp @@ -0,0 +1,29 @@ +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "effects/GrSingleTextureEffect.h" +#include "GrTexture.h" + +GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture) + : fTexture (texture) { + SkSafeRef(fTexture); +} + +GrSingleTextureEffect::~GrSingleTextureEffect() { + SkSafeUnref(fTexture); +} + +unsigned int GrSingleTextureEffect::numTextures() const { + return 1; +} + +GrTexture* GrSingleTextureEffect::texture(unsigned int index) const { + GrAssert(0 == index); + return fTexture; +} + + diff --git a/src/gpu/effects/GrSingleTextureEffect.h b/src/gpu/effects/GrSingleTextureEffect.h new file mode 100644 index 0000000000..9a6bd1cae3 --- /dev/null +++ b/src/gpu/effects/GrSingleTextureEffect.h @@ -0,0 +1,28 @@ +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrSingleTextureEffect_DEFINED +#define GrSingleTextureEffect_DEFINED + +#include "GrCustomStage.h" + +class GrSingleTextureEffect : public GrCustomStage { + +public: + GrSingleTextureEffect(GrTexture* texture); + virtual ~GrSingleTextureEffect(); + + virtual unsigned int numTextures() const SK_OVERRIDE; + virtual GrTexture* texture(unsigned int index) const SK_OVERRIDE; + +private: + GrTexture* fTexture; + + typedef GrCustomStage INHERITED; +}; + +#endif diff --git a/src/gpu/gl/GrGLProgramStage.cpp b/src/gpu/gl/GrGLProgramStage.cpp index 487b46865f..b5e4f4068c 100644 --- a/src/gpu/gl/GrGLProgramStage.cpp +++ b/src/gpu/gl/GrGLProgramStage.cpp @@ -26,7 +26,6 @@ void GrGLProgramStage::initUniforms(const GrGLInterface*, int progID) { } void GrGLProgramStage::setData(const GrGLInterface*, - const GrGLTexture&, const GrCustomStage&, int stageNum) { } diff --git a/src/gpu/gl/GrGLProgramStage.h b/src/gpu/gl/GrGLProgramStage.h index fe3ed4b9b7..9cf2c1aa97 100644 --- a/src/gpu/gl/GrGLProgramStage.h +++ b/src/gpu/gl/GrGLProgramStage.h @@ -82,7 +82,6 @@ public: a stage and uploads any uniform variables required by the shaders created in emit*(). */ virtual void setData(const GrGLInterface* gl, - const GrGLTexture& texture, const GrCustomStage& stage, int stageNum); diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp index 7ebe9d7f06..edabb9c108 100644 --- a/src/gpu/gl/GrGpuGL.cpp +++ b/src/gpu/gl/GrGpuGL.cpp @@ -2140,6 +2140,21 @@ void GrGpuGL::flushBoundTextureAndParams(int stage) { GrGLTexture* nextTexture = static_cast(drawState->getTexture(stage)); + // HACK - if we're using a new SingleTextureEffect, override + // the old texture pointer + const GrSamplerState& sampler = drawState->getSampler(stage); + GrCustomStage* customStage = sampler.getCustomStage(); + if (customStage && customStage->numTextures()) { + nextTexture = + static_cast(customStage->texture(0)); + } + + flushBoundTextureAndParams(stage, nextTexture); +} + +void GrGpuGL::flushBoundTextureAndParams(int stage, GrGLTexture* nextTexture) { + GrDrawState* drawState = this->drawState(); + // true for now, but maybe not with GrEffect. GrAssert(NULL != nextTexture); // if we created a rt/tex and rendered to it without using a diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h index 2d6aa68120..0871a57b7e 100644 --- a/src/gpu/gl/GrGpuGL.h +++ b/src/gpu/gl/GrGpuGL.h @@ -213,6 +213,7 @@ private: // call to flushScissor must occur after all textures have been flushed via // this function. void flushBoundTextureAndParams(int stage); + void flushBoundTextureAndParams(int stage, GrGLTexture* nextTexture); // sets the texture matrix and domain for the currently bound program void flushTextureMatrixAndDomain(int stage); diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp index 3a3d6386f0..a7187d548c 100644 --- a/src/gpu/gl/GrGpuGL_program.cpp +++ b/src/gpu/gl/GrGpuGL_program.cpp @@ -479,7 +479,7 @@ bool GrGpuGL::flushGraphicsState(DrawType type) { static_cast( this->getDrawState().getTexture(s)); fProgramData->fCustomStage[s]->setData( - this->glInterface(), *texture, + this->glInterface(), *sampler.getCustomStage(), s); } } diff --git a/src/gpu/gl/GrGpuGL_unittest.cpp b/src/gpu/gl/GrGpuGL_unittest.cpp index 044d4777d9..004013a55a 100644 --- a/src/gpu/gl/GrGpuGL_unittest.cpp +++ b/src/gpu/gl/GrGpuGL_unittest.cpp @@ -77,7 +77,8 @@ GrCustomStage* create_random_effect(StageDesc* stageDesc, stageDesc->fOptFlags |= StageDesc::kNoPerspective_OptFlagBit; stageDesc->fInConfigFlags &= ~kMulByAlphaMask; return SkNEW_ARGS(GrConvolutionEffect, - (gKernelDirections[direction], + (NULL, + gKernelDirections[direction], kernelRadius, kernel)); } @@ -88,7 +89,8 @@ GrCustomStage* create_random_effect(StageDesc* stageDesc, stageDesc->fOptFlags |= StageDesc::kNoPerspective_OptFlagBit; stageDesc->fInConfigFlags &= ~kMulByAlphaMask; return SkNEW_ARGS(GrMorphologyEffect, - (gKernelDirections[direction], + (NULL, + gKernelDirections[direction], kernelRadius, GrContext::kErode_MorphologyType)); } @@ -99,12 +101,13 @@ GrCustomStage* create_random_effect(StageDesc* stageDesc, stageDesc->fOptFlags |= StageDesc::kNoPerspective_OptFlagBit; stageDesc->fInConfigFlags &= ~kMulByAlphaMask; return SkNEW_ARGS(GrMorphologyEffect, - (gKernelDirections[direction], + (NULL, + gKernelDirections[direction], kernelRadius, GrContext::kDilate_MorphologyType)); } case kRadialGradient_EffectType: { - return SkNEW(GrRadialGradient); + return SkNEW_ARGS(GrRadialGradient, (NULL)); } case kRadial2Gradient_EffectType: { float center; @@ -113,10 +116,10 @@ GrCustomStage* create_random_effect(StageDesc* stageDesc, } while (GR_Scalar1 == center); float radius = random->nextF(); bool root = random_bool(random); - return SkNEW_ARGS(GrRadial2Gradient, (center, radius, root)); + return SkNEW_ARGS(GrRadial2Gradient, (NULL, center, radius, root)); } case kSweepGradient_EffectType: { - return SkNEW(GrSweepGradient); + return SkNEW_ARGS(GrSweepGradient, (NULL)); } case kDiffuseDistant_EffectType: { SkPoint3 direction = random_point3(random); @@ -127,7 +130,7 @@ GrCustomStage* create_random_effect(StageDesc* stageDesc, SkAutoTUnref filter(SkLightingImageFilter::CreateDistantLitDiffuse(direction, lightColor, surfaceScale, kd)); // does not work with perspective or mul-by-alpha-mask GrCustomStage* stage; - bool ok = filter->asNewCustomStage(&stage); + bool ok = filter->asNewCustomStage(&stage, NULL); SkASSERT(ok); return stage; } @@ -139,7 +142,7 @@ GrCustomStage* create_random_effect(StageDesc* stageDesc, SkAutoTUnref filter(SkLightingImageFilter::CreatePointLitDiffuse(location, lightColor, surfaceScale, kd)); // does not work with perspective or mul-by-alpha-mask GrCustomStage* stage; - bool ok = filter->asNewCustomStage(&stage); + bool ok = filter->asNewCustomStage(&stage, NULL); SkASSERT(ok); return stage; } @@ -156,7 +159,7 @@ GrCustomStage* create_random_effect(StageDesc* stageDesc, location, target, specularExponent, cutoffAngle, lightColor, surfaceScale, ks, shininess)); // does not work with perspective or mul-by-alpha-mask GrCustomStage* stage; - bool ok = filter->asNewCustomStage(&stage); + bool ok = filter->asNewCustomStage(&stage, NULL); SkASSERT(ok); return stage; } @@ -170,7 +173,7 @@ GrCustomStage* create_random_effect(StageDesc* stageDesc, SkAutoTUnref filter(SkLightingImageFilter::CreateDistantLitSpecular(direction, lightColor, surfaceScale, ks, shininess)); // does not work with perspective or mul-by-alpha-mask GrCustomStage* stage; - bool ok = filter->asNewCustomStage(&stage); + bool ok = filter->asNewCustomStage(&stage, NULL); SkASSERT(ok); return stage; } @@ -183,7 +186,7 @@ GrCustomStage* create_random_effect(StageDesc* stageDesc, SkAutoTUnref filter(SkLightingImageFilter::CreatePointLitSpecular(location, lightColor, surfaceScale, ks, shininess)); // does not work with perspective or mul-by-alpha-mask GrCustomStage* stage; - bool ok = filter->asNewCustomStage(&stage); + bool ok = filter->asNewCustomStage(&stage, NULL); SkASSERT(ok); return stage; } @@ -200,7 +203,7 @@ GrCustomStage* create_random_effect(StageDesc* stageDesc, location, target, specularExponent, cutoffAngle, lightColor, surfaceScale, ks, shininess)); // does not work with perspective or mul-by-alpha-mask GrCustomStage* stage; - bool ok = filter->asNewCustomStage(&stage); + bool ok = filter->asNewCustomStage(&stage, NULL); SkASSERT(ok); return stage; }