diff options
author | tomhudson@google.com <tomhudson@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-05-10 12:13:36 +0000 |
---|---|---|
committer | tomhudson@google.com <tomhudson@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-05-10 12:13:36 +0000 |
commit | b6b7f6d275d9f518b9d84c265c0e50a801458a23 (patch) | |
tree | 35d05257e676b7fd44e6708286f3d679da96bab0 | |
parent | 87c46428e6d8465f9b18467a66737c17e71d36e0 (diff) | |
download | src-b6b7f6d275d9f518b9d84c265c0e50a801458a23.tar.gz |
Move convolution from code in GrGLProgram to new GrConvolutionEffect
class. This is the first test of the new Ganesh shader pipeline.
Also includes some cleanup of the gpu.gyp file: added src/gpu, allowing
us to remove ../ from many #include directives.
http://codereview.appspot.com/6199053/
git-svn-id: http://skia.googlecode.com/svn/trunk/src@3887 2bbb7eff-a529-9590-31e7-b0007b416f81
35 files changed, 455 insertions, 196 deletions
diff --git a/gpu/GrContext.cpp b/gpu/GrContext.cpp index 58f84404..5d58f1e5 100644 --- a/gpu/GrContext.cpp +++ b/gpu/GrContext.cpp @@ -11,6 +11,7 @@ #include "GrBufferAllocPool.h" #include "GrClipIterator.h" +#include "effects/GrConvolutionEffect.h" #include "GrGpu.h" #include "GrIndexBuffer.h" #include "GrInOrderDrawBuffer.h" @@ -296,8 +297,8 @@ void convolve(GrGpu* gpu, drawState->sampler(0)->reset(GrSamplerState::kClamp_WrapMode, GrSamplerState::kConvolution_Filter, sampleM); - drawState->sampler(0)->setConvolutionParams(kernelWidth, kernel); - drawState->sampler(0)->setFilterDirection(direction); + drawState->sampler(0)->setCustomStage( + new GrConvolutionEffect(direction, kernelWidth, kernel)); drawState->setTexture(0, texture); gpu->drawSimpleRect(rect, NULL, 1 << 0); } diff --git a/gpu/GrProgramStageFactory.cpp b/gpu/GrProgramStageFactory.cpp new file mode 100644 index 00000000..4bacf921 --- /dev/null +++ b/gpu/GrProgramStageFactory.cpp @@ -0,0 +1,17 @@ +/* + * 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 "GrProgramStageFactory.h" + +GrProgramStageFactory::~GrProgramStageFactory(void) { + +} + +uint16_t GrProgramStageFactory::stageKey(const GrCustomStage*) { + return 0; +} + diff --git a/gpu/GrProgramStageFactory.h b/gpu/GrProgramStageFactory.h new file mode 100644 index 00000000..d3580d5e --- /dev/null +++ b/gpu/GrProgramStageFactory.h @@ -0,0 +1,50 @@ +/* + * 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 GrProgramStageFactory_DEFINED +#define GrProgramStageFactory_DEFINED + +#include "GrTypes.h" + +class GrCustomStage; +class GrGLProgramStage; + +/** Given a GrCustomStage of a particular type, creates the corresponding + graphics-backend-specific GrProgramStage. Also tracks equivalence + of shaders generated via stageKey(). + + TODO: most of this class' subclasses are boilerplate and ought to be + templateable? +*/ + +class GrProgramStageFactory { + +public: + + virtual ~GrProgramStageFactory(); + + /** Returns a short unique identifier for this subclass x its + parameters. If the key differs, different shader code must + be generated; if the key matches, shader code can be reused. + 0 == no custom stage. */ + virtual uint16_t stageKey(const GrCustomStage*); + + /** Returns a new instance of the appropriate *GL* implementation class + for the given GrCustomStage; caller is responsible for deleting + the object. */ + virtual GrGLProgramStage* createGLInstance(GrCustomStage*) = 0; + +protected: + + /** Disable default constructor - instances should be singletons + with static factory functions: our test examples are all stateless, + but we suspect that future implementations may want to cache data? */ + GrProgramStageFactory() { } +}; + + +#endif diff --git a/gpu/effects/GrConvolutionEffect.cpp b/gpu/effects/GrConvolutionEffect.cpp new file mode 100644 index 00000000..e4ddd293 --- /dev/null +++ b/gpu/effects/GrConvolutionEffect.cpp @@ -0,0 +1,257 @@ +/* + * 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 "GrConvolutionEffect.h" +#include "gl/GrGLProgramStage.h" +#include "gl/GrGLSL.h" +#include "gl/GrGLTexture.h" +#include "GrProgramStageFactory.h" + +///////////////////////////////////////////////////////////////////// + +class GrGLConvolutionEffect : public GrGLProgramStage { + +public: + + GrGLConvolutionEffect(GrConvolutionEffect* data); + virtual const char* name() const SK_OVERRIDE; + virtual void setupVSUnis(VarArray* vsUnis, int stage) SK_OVERRIDE; + virtual void setupFSUnis(VarArray* fsUnis, int stage) SK_OVERRIDE; + virtual void emitVS(GrStringBuilder* code, + const char* vertexCoords) SK_OVERRIDE; + virtual void emitFS(GrStringBuilder* code, + const char* outputColor, + const char* inputColor, + const char* samplerName, + const char* sampleCoords) SK_OVERRIDE; + virtual void initUniforms(const GrGLInterface*, int programID) SK_OVERRIDE; + + virtual void setData(const GrGLInterface*, GrCustomStage*, + const GrGLTexture*) SK_OVERRIDE; + +protected: + + GrConvolutionEffect* fData; + + GrGLShaderVar* fKernelVar; + GrGLShaderVar* fImageIncrementVar; + + GrGLint fKernelLocation; + GrGLint fImageIncrementLocation; + +private: + + typedef GrGLProgramStage INHERITED; +}; + +GrGLConvolutionEffect::GrGLConvolutionEffect(GrConvolutionEffect* data) + : fData(data) + , fKernelVar(NULL) + , fImageIncrementVar(NULL) + , fKernelLocation(0) + , fImageIncrementLocation(0) +{ + +} + +const char* GrGLConvolutionEffect::name() const SK_OVERRIDE { + return fData->name(); +} + +void GrGLConvolutionEffect::setupVSUnis(VarArray* vsUnis, + int stage) SK_OVERRIDE { + fImageIncrementVar = &vsUnis->push_back(); + fImageIncrementVar->setType(kVec2f_GrSLType); + fImageIncrementVar->setTypeModifier( + GrGLShaderVar::kUniform_TypeModifier); + (*fImageIncrementVar->accessName()) = "uImageIncrement"; + fImageIncrementVar->accessName()->appendS32(stage); + fImageIncrementVar->setEmitPrecision(true); + + fImageIncrementLocation = kUseUniform; +} + +void GrGLConvolutionEffect::setupFSUnis(VarArray* fsUnis, + int stage) SK_OVERRIDE { + fKernelVar = &fsUnis->push_back(); + fKernelVar->setType(kFloat_GrSLType); + fKernelVar->setTypeModifier( + GrGLShaderVar::kUniform_TypeModifier); + fKernelVar->setArrayCount(fData->fKernelWidth); + (*fKernelVar->accessName()) = "uKernel"; + fKernelVar->accessName()->appendS32(stage); + + fKernelLocation = kUseUniform; + + // Image increment is used in both vertex & fragment shaders. + fsUnis->push_back(*fImageIncrementVar).setEmitPrecision(false); +} + +void GrGLConvolutionEffect::emitVS(GrStringBuilder* code, + const char* vertexCoords) SK_OVERRIDE { + float scale = (fData->fKernelWidth - 1) * 0.5f; + code->appendf("\t\t%s -= vec2(%g, %g) * %s;\n", + vertexCoords, scale, scale, + fImageIncrementVar->getName().c_str()); + +} + +void GrGLConvolutionEffect::emitFS(GrStringBuilder* code, + const char* outputColor, + const char* inputColor, + const char* samplerName, + const char* sampleCoords) SK_OVERRIDE { + const char* texFunc = "texture2D"; + bool complexCoord = false; + + GrStringBuilder modulate; + if (NULL != inputColor) { + modulate.printf(" * %s", inputColor); + } + + // Creates the string "kernel[i]" with workarounds for + // possible driver bugs + GrStringBuilder kernelIndex; + fKernelVar->appendArrayAccess("i", &kernelIndex); + + code->appendf("\t\tvec4 sum = vec4(0, 0, 0, 0);\n"); + code->appendf("\t\tvec2 coord = %s;\n", sampleCoords); + code->appendf("\t\tfor (int i = 0; i < %d; i++) {\n", + fData->fKernelWidth); + + code->appendf("\t\t\tsum += "); + this->emitTextureLookup(code, samplerName, "coord"); + code->appendf(" * %s;\n", kernelIndex.c_str()); + + code->appendf("\t\t\tcoord += %s;\n", + fImageIncrementVar->getName().c_str()); + code->appendf("\t\t}\n"); + code->appendf("\t\t%s = sum%s;\n", outputColor, modulate.c_str()); +} + +void GrGLConvolutionEffect::initUniforms(const GrGLInterface* gl, + int programID) SK_OVERRIDE { + GR_GL_CALL_RET(gl, fKernelLocation, + GetUniformLocation(programID, fKernelVar->getName().c_str())); + GR_GL_CALL_RET(gl, fImageIncrementLocation, + GetUniformLocation(programID, + fImageIncrementVar->getName().c_str())); +} + +void GrGLConvolutionEffect::setData(const GrGLInterface* gl, + GrCustomStage* data, + const GrGLTexture* texture) SK_OVERRIDE { + fData = static_cast<GrConvolutionEffect*>(data); + GR_GL_CALL(gl, Uniform1fv(fKernelLocation, + fData->fKernelWidth, + fData->fKernel)); + float imageIncrement[2] = { 0 }; + switch (fData->fDirection) { + case GrSamplerState::kX_FilterDirection: + imageIncrement[0] = 1.0f / texture->width(); + break; + case GrSamplerState::kY_FilterDirection: + imageIncrement[1] = 1.0f / texture->width(); + break; + default: + GrCrash("Unknown filter direction."); + } + GR_GL_CALL(gl, Uniform2fv(fImageIncrementLocation, 1, imageIncrement)); +} + +///////////////////////////////////////////////////////////////////// +// TODO: stageKey() and sEffectId are the only non-boilerplate in +// this class; we ought to be able to templatize? + +class GrConvolutionEffectFactory : public GrProgramStageFactory { + +public: + + virtual ~GrConvolutionEffectFactory(); + + virtual uint16_t stageKey(const GrCustomStage* s) SK_OVERRIDE; + virtual GrGLProgramStage* createGLInstance(GrCustomStage* s) SK_OVERRIDE; + + static GrConvolutionEffectFactory* getInstance(); + +protected: + + GrConvolutionEffectFactory(); + + // TODO: find a more reliable installation than hand-coding + // id values like '1'. + static const int sEffectId = 1; + +private: + + typedef GrProgramStageFactory INHERITED; +}; + +GrConvolutionEffectFactory::~GrConvolutionEffectFactory() { + +} + +uint16_t GrConvolutionEffectFactory::stageKey(const GrCustomStage* s) + SK_OVERRIDE { + const GrConvolutionEffect* c = + static_cast<const GrConvolutionEffect*>(s); + GrAssert(c->width() < 256); + return (sEffectId << 8) | (c->width() & 0xff); +} + +GrGLProgramStage* GrConvolutionEffectFactory::createGLInstance( + GrCustomStage* s) SK_OVERRIDE { + return new GrGLConvolutionEffect(static_cast<GrConvolutionEffect*>(s)); +} + +GrConvolutionEffectFactory* GrConvolutionEffectFactory::getInstance() { + static GrConvolutionEffectFactory* instance = + new GrConvolutionEffectFactory; + return instance; +} + +GrConvolutionEffectFactory::GrConvolutionEffectFactory() { + +} + +///////////////////////////////////////////////////////////////////// + +GrConvolutionEffect::GrConvolutionEffect( + GrSamplerState::FilterDirection direction, + unsigned int kernelWidth, + const float* kernel) + : fDirection (direction) + , fKernelWidth (kernelWidth) { + GrAssert(kernelWidth <= MAX_KERNEL_WIDTH); + for (unsigned int i = 0; i < kernelWidth; i++) { + fKernel[i] = kernel[i]; + } +} + +GrConvolutionEffect::~GrConvolutionEffect() { + +} + +const char* GrConvolutionEffect::name() const { + return "Convolution"; +} + +GrProgramStageFactory* GrConvolutionEffect::getFactory() const { + return GrConvolutionEffectFactory::getInstance(); +} + +bool GrConvolutionEffect::isEqual(const GrCustomStage * sBase) const { + const GrConvolutionEffect* s = + static_cast<const GrConvolutionEffect*>(sBase); + + return (fKernelWidth == s->fKernelWidth && + fDirection == s->fDirection && + 0 == memcmp(fKernel, s->fKernel, fKernelWidth * sizeof(float))); +} + + + diff --git a/gpu/effects/GrConvolutionEffect.h b/gpu/effects/GrConvolutionEffect.h new file mode 100644 index 00000000..e3c3aa9c --- /dev/null +++ b/gpu/effects/GrConvolutionEffect.h @@ -0,0 +1,41 @@ +/* + * 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 GrConvolutionEffect_DEFINED +#define GrConvolutionEffect_DEFINED + +#include "GrCustomStage.h" +#include "GrSamplerState.h" // for MAX_KENEL_WIDTH, FilterDirection + +class GrConvolutionEffect : public GrCustomStage { + +public: + + GrConvolutionEffect(GrSamplerState::FilterDirection direction, + unsigned int kernelWidth, const float* kernel); + virtual ~GrConvolutionEffect(); + + virtual const char* name() const SK_OVERRIDE; + virtual GrProgramStageFactory* getFactory() const SK_OVERRIDE; + virtual bool isEqual(const GrCustomStage *) const SK_OVERRIDE; + + unsigned int width() const { return fKernelWidth; } + +protected: + + GrSamplerState::FilterDirection fDirection; + unsigned int fKernelWidth; + float fKernel[MAX_KERNEL_WIDTH]; + + friend class GrGLConvolutionEffect; + +private: + + typedef GrCustomStage INHERITED; +}; + +#endif diff --git a/gpu/gl/GrGLCaps.cpp b/gpu/gl/GrGLCaps.cpp index 6031c735..e3dcd57f 100644 --- a/gpu/gl/GrGLCaps.cpp +++ b/gpu/gl/GrGLCaps.cpp @@ -1,4 +1,3 @@ - /* * Copyright 2012 Google Inc. * diff --git a/gpu/gl/GrGLCaps.h b/gpu/gl/GrGLCaps.h index eb095765..d159d989 100644 --- a/gpu/gl/GrGLCaps.h +++ b/gpu/gl/GrGLCaps.h @@ -1,4 +1,3 @@ - /* * Copyright 2012 Google Inc. * diff --git a/gpu/gl/GrGLContextInfo.cpp b/gpu/gl/GrGLContextInfo.cpp index 33e19ab0..45368fe2 100644 --- a/gpu/gl/GrGLContextInfo.cpp +++ b/gpu/gl/GrGLContextInfo.cpp @@ -1,4 +1,3 @@ - /* * Copyright 2012 Google Inc. * diff --git a/gpu/gl/GrGLCreateNativeInterface_none.cpp b/gpu/gl/GrGLCreateNativeInterface_none.cpp index 914ed51a..e0c72c53 100644 --- a/gpu/gl/GrGLCreateNativeInterface_none.cpp +++ b/gpu/gl/GrGLCreateNativeInterface_none.cpp @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * diff --git a/gpu/gl/GrGLCreateNullInterface.cpp b/gpu/gl/GrGLCreateNullInterface.cpp index 0a27a066..d790e06d 100644 --- a/gpu/gl/GrGLCreateNullInterface.cpp +++ b/gpu/gl/GrGLCreateNullInterface.cpp @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * @@ -8,7 +7,7 @@ #include "gl/GrGLInterface.h" -#include "../GrTDArray.h" +#include "GrTDArray.h" #include "GrGLDefines.h" GrGLvoid GR_GL_FUNCTION_TYPE nullGLActiveTexture(GrGLenum texture) {} diff --git a/gpu/gl/GrGLDefaultInterface_native.cpp b/gpu/gl/GrGLDefaultInterface_native.cpp index 13988c01..e695f15a 100644 --- a/gpu/gl/GrGLDefaultInterface_native.cpp +++ b/gpu/gl/GrGLDefaultInterface_native.cpp @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * diff --git a/gpu/gl/GrGLDefaultInterface_none.cpp b/gpu/gl/GrGLDefaultInterface_none.cpp index 183c4770..84c7f7c3 100644 --- a/gpu/gl/GrGLDefaultInterface_none.cpp +++ b/gpu/gl/GrGLDefaultInterface_none.cpp @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * diff --git a/gpu/gl/GrGLDefines.h b/gpu/gl/GrGLDefines.h index 0e03b556..d63a1666 100644 --- a/gpu/gl/GrGLDefines.h +++ b/gpu/gl/GrGLDefines.h @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * diff --git a/gpu/gl/GrGLIRect.h b/gpu/gl/GrGLIRect.h index 05bba117..038520d2 100644 --- a/gpu/gl/GrGLIRect.h +++ b/gpu/gl/GrGLIRect.h @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * diff --git a/gpu/gl/GrGLIndexBuffer.cpp b/gpu/gl/GrGLIndexBuffer.cpp index b99bdd40..54689923 100644 --- a/gpu/gl/GrGLIndexBuffer.cpp +++ b/gpu/gl/GrGLIndexBuffer.cpp @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * diff --git a/gpu/gl/GrGLIndexBuffer.h b/gpu/gl/GrGLIndexBuffer.h index 68c165f6..3a08c0e3 100644 --- a/gpu/gl/GrGLIndexBuffer.h +++ b/gpu/gl/GrGLIndexBuffer.h @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * @@ -11,7 +10,7 @@ #ifndef GrGLIndexBuffer_DEFINED #define GrGLIndexBuffer_DEFINED -#include "../GrIndexBuffer.h" +#include "GrIndexBuffer.h" #include "gl/GrGLInterface.h" class GrGpuGL; diff --git a/gpu/gl/GrGLInterface.cpp b/gpu/gl/GrGLInterface.cpp index bbcf9233..a86c143b 100644 --- a/gpu/gl/GrGLInterface.cpp +++ b/gpu/gl/GrGLInterface.cpp @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * diff --git a/gpu/gl/GrGLProgram.cpp b/gpu/gl/GrGLProgram.cpp index 3e1f1d40..88b1456d 100644 --- a/gpu/gl/GrGLProgram.cpp +++ b/gpu/gl/GrGLProgram.cpp @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * @@ -6,13 +5,13 @@ * found in the LICENSE file. */ - #include "GrGLProgram.h" -#include "../GrAllocator.h" +#include "GrAllocator.h" #include "GrCustomStage.h" #include "GrGLProgramStage.h" #include "GrGLShaderVar.h" +#include "GrProgramStageFactory.h" #include "SkTrace.h" #include "SkXfermode.h" @@ -647,7 +646,6 @@ GrGLProgram::CachedData::~CachedData() { bool GrGLProgram::genProgram(const GrGLContextInfo& gl, GrCustomStage** customStages, GrGLProgram::CachedData* programData) const { - ShaderCodeSegments segments; const uint32_t& layout = fProgramDesc.fVertexLayout; @@ -757,18 +755,12 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl, } /////////////////////////////////////////////////////////////////////////// - // Convert generic effect representation to GL-specific backend so they - // can be accesseed in genStageCode() and in subsequent uses of - // programData. + // We need to convert generic effect representations to GL-specific + // backends so they can be accesseed in genStageCode() and in subsequent, + // uses of programData, but it's safest to do so below when we're *sure* + // we need them. for (int s = 0; s < GrDrawState::kNumStages; ++s) { - GrCustomStage* customStage = customStages[s]; - if (NULL != customStage) { - GrGLProgramStageFactory* factory = customStage->getGLFactory(); - programData->fCustomStage[s] = - factory->createGLInstance(customStage); - } else { - programData->fCustomStage[s] = NULL; - } + programData->fCustomStage[s] = NULL; } /////////////////////////////////////////////////////////////////////////// @@ -798,6 +790,12 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl, inCoords = texCoordAttrs[tcIdx].c_str(); } + if (NULL != customStages[s]) { + GrProgramStageFactory* factory = + customStages[s]->getFactory(); + programData->fCustomStage[s] = + factory->createGLInstance(customStages[s]); + } this->genStageCode(gl, s, fProgramDesc.fStages[s], @@ -918,6 +916,12 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl, inCoords = texCoordAttrs[tcIdx].c_str(); } + if (NULL != customStages[s]) { + GrProgramStageFactory* factory = + customStages[s]->getFactory(); + programData->fCustomStage[s] = + factory->createGLInstance(customStages[s]); + } this->genStageCode(gl, s, fProgramDesc.fStages[s], inCoverage.size() ? inCoverage.c_str() : NULL, @@ -1618,76 +1622,6 @@ void gen2x2FS(int stageNum, } -void genConvolutionVS(int stageNum, - const StageDesc& desc, - ShaderCodeSegments* segments, - GrGLProgram::StageUniLocations* locations, - GrGLShaderVar** kernel, - const char** imageIncrementName, - const char* varyingVSName) { - //GrGLShaderVar* kernel = &segments->fFSUnis.push_back(); - *kernel = &segments->fFSUnis.push_back(); - (*kernel)->setType(kFloat_GrSLType); - (*kernel)->setTypeModifier(GrGLShaderVar::kUniform_TypeModifier); - (*kernel)->setArrayCount(desc.fKernelWidth); - GrGLShaderVar* imgInc = &segments->fFSUnis.push_back(); - imgInc->setType(kVec2f_GrSLType); - imgInc->setTypeModifier(GrGLShaderVar::kUniform_TypeModifier); - - convolve_param_names(stageNum, - (*kernel)->accessName(), - imgInc->accessName()); - *imageIncrementName = imgInc->getName().c_str(); - - // need image increment in both VS and FS - segments->fVSUnis.push_back(*imgInc).setEmitPrecision(true); - - locations->fKernelUni = kUseUniform; - locations->fImageIncrementUni = kUseUniform; - float scale = (desc.fKernelWidth - 1) * 0.5f; - segments->fVSCode.appendf("\t%s -= vec2(%g, %g) * %s;\n", - varyingVSName, scale, scale, - *imageIncrementName); -} - -void genConvolutionFS(int stageNum, - const StageDesc& desc, - ShaderCodeSegments* segments, - const char* samplerName, - GrGLShaderVar* kernel, - const char* swizzle, - const char* imageIncrementName, - const char* fsOutColor, - GrStringBuilder& sampleCoords, - GrStringBuilder& texFunc, - GrStringBuilder& modulate) { - GrStringBuilder sumVar("sum"); - sumVar.appendS32(stageNum); - GrStringBuilder coordVar("coord"); - coordVar.appendS32(stageNum); - - GrStringBuilder kernelIndex; - kernel->appendArrayAccess("i", &kernelIndex); - - segments->fFSCode.appendf("\tvec4 %s = vec4(0, 0, 0, 0);\n", - sumVar.c_str()); - segments->fFSCode.appendf("\tvec2 %s = %s;\n", - coordVar.c_str(), - sampleCoords.c_str()); - segments->fFSCode.appendf("\tfor (int i = 0; i < %d; i++) {\n", - desc.fKernelWidth); - segments->fFSCode.appendf("\t\t%s += %s(%s, %s)%s * %s;\n", - sumVar.c_str(), texFunc.c_str(), - samplerName, coordVar.c_str(), swizzle, - kernelIndex.c_str()); - segments->fFSCode.appendf("\t\t%s += %s;\n", - coordVar.c_str(), - imageIncrementName); - segments->fFSCode.append("\t}\n"); - segments->fFSCode.appendf("\t%s = %s%s;\n", fsOutColor, - sumVar.c_str(), modulate.c_str()); -} - void genMorphologyVS(int stageNum, const StageDesc& desc, ShaderCodeSegments* segments, @@ -1775,7 +1709,7 @@ void GrGLProgram::genStageCode(const GrGLContextInfo& gl, /// Vertex Shader Stuff if (NULL != customStage) { - customStage->setupVSUnis(segments->fVSUnis, stageNum); + customStage->setupVSUnis(&segments->fVSUnis, stageNum); } // decide whether we need a matrix to transform texture coords @@ -1852,10 +1786,7 @@ void GrGLProgram::genStageCode(const GrGLContextInfo& gl, GrGLShaderVar* kernel = NULL; const char* imageIncrementName = NULL; - if (StageDesc::kConvolution_FetchMode == desc.fFetchMode) { - genConvolutionVS(stageNum, desc, segments, locations, - &kernel, &imageIncrementName, varyingVSName); - } else if (StageDesc::kDilate_FetchMode == desc.fFetchMode || + if (StageDesc::kDilate_FetchMode == desc.fFetchMode || StageDesc::kErode_FetchMode == desc.fFetchMode) { genMorphologyVS(stageNum, desc, segments, locations, &imageIncrementName, varyingVSName); @@ -1864,15 +1795,16 @@ void GrGLProgram::genStageCode(const GrGLContextInfo& gl, if (NULL != customStage) { GrStringBuilder vertexShader; customStage->emitVS(&vertexShader, varyingVSName); - segments->fVSCode.appendf("{\n"); + segments->fVSCode.appendf("\t{ // stage %d %s\n", + stageNum, customStage->name()); segments->fVSCode.append(vertexShader); - segments->fVSCode.appendf("}\n"); + segments->fVSCode.appendf("\t}\n"); } /// Fragment Shader Stuff if (NULL != customStage) { - customStage->setupFSUnis(segments->fFSUnis, stageNum); + customStage->setupFSUnis(&segments->fFSUnis, stageNum); } GrStringBuilder fsCoordName; @@ -1985,9 +1917,6 @@ void GrGLProgram::genStageCode(const GrGLContextInfo& gl, break; case StageDesc::kConvolution_FetchMode: GrAssert(!(desc.fInConfigFlags & kMulByAlphaMask)); - genConvolutionFS(stageNum, desc, segments, - samplerName, kernel, swizzle, imageIncrementName, fsOutColor, - sampleCoords, texFunc, modulate); break; case StageDesc::kDilate_FetchMode: case StageDesc::kErode_FetchMode: @@ -2040,15 +1969,16 @@ void GrGLProgram::genStageCode(const GrGLContextInfo& gl, GrStringBuilder fragmentShader; fsCoordName = customStage->emitTextureSetup( - &fragmentShader, varyingFSName, + &fragmentShader, sampleCoords.c_str(), stageNum, coordDims, varyingDims); customStage->emitFS(&fragmentShader, fsOutColor, fsInColor, samplerName, fsCoordName.c_str()); // Enclose custom code in a block to avoid namespace conflicts - segments->fFSCode.appendf("{\n"); + segments->fFSCode.appendf("\t{ // stage %d %s \n", + stageNum, customStage->name()); segments->fFSCode.append(fragmentShader); - segments->fFSCode.appendf("}\n"); + segments->fFSCode.appendf("\t}\n"); } } diff --git a/gpu/gl/GrGLProgram.h b/gpu/gl/GrGLProgram.h index 73bfa949..9e2ee7e3 100644 --- a/gpu/gl/GrGLProgram.h +++ b/gpu/gl/GrGLProgram.h @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * @@ -10,11 +9,11 @@ #ifndef GrGLProgram_DEFINED #define GrGLProgram_DEFINED -#include "../GrDrawState.h" +#include "GrDrawState.h" #include "GrGLContextInfo.h" #include "GrGLSL.h" -#include "../GrStringBuilder.h" -#include "../GrGpu.h" +#include "GrStringBuilder.h" +#include "GrGpu.h" #include "SkXfermode.h" @@ -108,6 +107,7 @@ public: kCustomTextureDomain_OptFlagBit = 1 << 2, kIsEnabled_OptFlagBit = 1 << 7 }; + // Convolution is obsolete; left in for testing only enum FetchMode { kSingle_FetchMode, k2x2_FetchMode, @@ -320,6 +320,9 @@ public: void copyAndTakeOwnership(CachedData& other) { memcpy(this, &other, sizeof(*this)); + for (int i = 0; i < GrDrawState::kNumStages; ++i) { + other.fCustomStage[i] = NULL; + } } public: diff --git a/gpu/gl/GrGLProgramStage.cpp b/gpu/gl/GrGLProgramStage.cpp index 302eb07d..66204384 100644 --- a/gpu/gl/GrGLProgramStage.cpp +++ b/gpu/gl/GrGLProgramStage.cpp @@ -13,19 +13,11 @@ GrGLProgramStage::~GrGLProgramStage() { /////////////////////////////////////////////////////////////////////////////// -GrGLProgramStageFactory::~GrGLProgramStageFactory(void) { +void GrGLProgramStage::setupVSUnis(VarArray* vsUnis, int stage) { } -uint16_t GrGLProgramStageFactory::stageKey(const GrCustomStage*) { - return 0; -} - -void GrGLProgramStage::setupVSUnis(VarArray& vsUnis, int stage) { - -} - -void GrGLProgramStage::setupFSUnis(VarArray& fsUnis, int stage) { +void GrGLProgramStage::setupFSUnis(VarArray* fsUnis, int stage) { } @@ -33,7 +25,8 @@ void GrGLProgramStage::initUniforms(const GrGLInterface*, int progID) { } -void GrGLProgramStage::setData(const GrGLInterface*, GrCustomStage*) { +void GrGLProgramStage::setData(const GrGLInterface*, GrCustomStage*, + const GrGLTexture*) { } diff --git a/gpu/gl/GrGLProgramStage.h b/gpu/gl/GrGLProgramStage.h index 210b4c31..340c99fd 100644 --- a/gpu/gl/GrGLProgramStage.h +++ b/gpu/gl/GrGLProgramStage.h @@ -8,13 +8,14 @@ #ifndef GrGLCustomStage_DEFINED #define GrGLCustomStage_DEFINED -#include "../GrAllocator.h" +#include "GrAllocator.h" #include "GrGLShaderVar.h" #include "GrGLSL.h" -#include "../GrStringBuilder.h" +#include "GrStringBuilder.h" class GrCustomStage; struct GrGLInterface; +class GrGLTexture; /** @file This file contains specializations for OpenGL of the shader stages @@ -39,17 +40,19 @@ public: virtual ~GrGLProgramStage(); + virtual const char* name() const = 0; + /** Creates any uniform variables the vertex shader requires and appends them to vsUnis; must guarantee they are unique (typically done by appending the stage number). */ - virtual void setupVSUnis(VarArray& vsUnis, int stage); + virtual void setupVSUnis(VarArray* vsUnis, int stage); /** Creates any uniform variables the fragment shader requires and appends them to fsUnis; must guarantee they are unique (typically done by appending the stage number). */ - virtual void setupFSUnis(VarArray& fsUnis, int stage); + virtual void setupFSUnis(VarArray* fsUnis, int stage); /** Given an empty GrStringBuilder and the names of variables; must write shader code into that GrStringBuilder. @@ -86,7 +89,8 @@ public: are to be read. TODO: since we don't have a factory, we can't assert to enforce this. Shouldn't we? */ - virtual void setData(const GrGLInterface*, GrCustomStage*); + virtual void setData(const GrGLInterface*, GrCustomStage*, + const GrGLTexture*); // TODO: needs a better name enum SamplerMode { @@ -95,7 +99,7 @@ public: kExplicitDivide_SamplerMode // must do an explicit divide }; - void setSamplerMode(SamplerMode shaderMode) { fSamplerMode = shaderMode; } + void setSamplerMode(SamplerMode samplerMode) { fSamplerMode = samplerMode; } /** Returns the *effective* coord name after any perspective divide or other transform. */ @@ -118,33 +122,4 @@ protected: }; - -/// Every GrGLProgramStage subclass needs a GrGLProgramStageFactory subclass -/// to manage its creation. - -class GrGLProgramStageFactory { - -public: - - virtual ~GrGLProgramStageFactory(); - - /** Returns a short unique identifier for this subclass x its - parameters. If the key differs, different shader code must - be generated; if the key matches, shader code can be reused. - 0 == no custom stage. */ - virtual uint16_t stageKey(const GrCustomStage*); - - /** Returns a new instance of the appropriate implementation class - for the given GrCustomStage; caller is responsible for deleting - the object. */ - virtual GrGLProgramStage* createGLInstance(GrCustomStage*) = 0; - -protected: - - /** Disable default constructor - instances should be singletons - with static factory functions: our test examples are all stateless, - but we suspect that future implementations may want to cache data? */ - GrGLProgramStageFactory() { } -}; - #endif diff --git a/gpu/gl/GrGLRenderTarget.cpp b/gpu/gl/GrGLRenderTarget.cpp index c98914a3..cce3def8 100644 --- a/gpu/gl/GrGLRenderTarget.cpp +++ b/gpu/gl/GrGLRenderTarget.cpp @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * @@ -6,7 +5,6 @@ * found in the LICENSE file. */ - #include "GrGLRenderTarget.h" #include "GrGpuGL.h" diff --git a/gpu/gl/GrGLRenderTarget.h b/gpu/gl/GrGLRenderTarget.h index eb817df6..d5f04d41 100644 --- a/gpu/gl/GrGLRenderTarget.h +++ b/gpu/gl/GrGLRenderTarget.h @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * diff --git a/gpu/gl/GrGLShaderVar.h b/gpu/gl/GrGLShaderVar.h index 149214e3..1f9b9906 100644 --- a/gpu/gl/GrGLShaderVar.h +++ b/gpu/gl/GrGLShaderVar.h @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * @@ -11,7 +10,7 @@ #include "GrGLContextInfo.h" #include "GrGLSL.h" -#include "../GrStringBuilder.h" +#include "GrStringBuilder.h" #define USE_UNIFORM_FLOAT_ARRAYS true diff --git a/gpu/gl/GrGLStencilBuffer.cpp b/gpu/gl/GrGLStencilBuffer.cpp index bc0bb364..69c0959a 100644 --- a/gpu/gl/GrGLStencilBuffer.cpp +++ b/gpu/gl/GrGLStencilBuffer.cpp @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * diff --git a/gpu/gl/GrGLStencilBuffer.h b/gpu/gl/GrGLStencilBuffer.h index 908921a4..87bdb4a8 100644 --- a/gpu/gl/GrGLStencilBuffer.h +++ b/gpu/gl/GrGLStencilBuffer.h @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * @@ -11,7 +10,7 @@ #define GrGLStencilBuffer_DEFINED #include "gl/GrGLInterface.h" -#include "../GrStencilBuffer.h" +#include "GrStencilBuffer.h" class GrGLStencilBuffer : public GrStencilBuffer { public: diff --git a/gpu/gl/GrGLTexture.cpp b/gpu/gl/GrGLTexture.cpp index 0a38da3d..3d30610d 100644 --- a/gpu/gl/GrGLTexture.cpp +++ b/gpu/gl/GrGLTexture.cpp @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * diff --git a/gpu/gl/GrGLTexture.h b/gpu/gl/GrGLTexture.h index d13fc446..77e1c327 100644 --- a/gpu/gl/GrGLTexture.h +++ b/gpu/gl/GrGLTexture.h @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * @@ -10,7 +9,7 @@ #ifndef GrGLTexture_DEFINED #define GrGLTexture_DEFINED -#include "../GrGpu.h" +#include "GrGpu.h" #include "GrGLRenderTarget.h" /** diff --git a/gpu/gl/GrGLUtil.cpp b/gpu/gl/GrGLUtil.cpp index c11c8c08..9d854ba5 100644 --- a/gpu/gl/GrGLUtil.cpp +++ b/gpu/gl/GrGLUtil.cpp @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * diff --git a/gpu/gl/GrGLVertexBuffer.cpp b/gpu/gl/GrGLVertexBuffer.cpp index 5c94c363..d932f11b 100644 --- a/gpu/gl/GrGLVertexBuffer.cpp +++ b/gpu/gl/GrGLVertexBuffer.cpp @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * diff --git a/gpu/gl/GrGLVertexBuffer.h b/gpu/gl/GrGLVertexBuffer.h index 5d2ba308..7df759e0 100644 --- a/gpu/gl/GrGLVertexBuffer.h +++ b/gpu/gl/GrGLVertexBuffer.h @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * @@ -11,7 +10,7 @@ #ifndef GrGLVertexBuffer_DEFINED #define GrGLVertexBuffer_DEFINED -#include "../GrVertexBuffer.h" +#include "GrVertexBuffer.h" #include "gl/GrGLInterface.h" class GrGpuGL; diff --git a/gpu/gl/GrGpuGL.cpp b/gpu/gl/GrGpuGL.cpp index 9aa9b318..69e494af 100644 --- a/gpu/gl/GrGpuGL.cpp +++ b/gpu/gl/GrGpuGL.cpp @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * diff --git a/gpu/gl/GrGpuGL.h b/gpu/gl/GrGpuGL.h index 77b300a9..0f16feb8 100644 --- a/gpu/gl/GrGpuGL.h +++ b/gpu/gl/GrGpuGL.h @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * @@ -11,8 +10,8 @@ #ifndef GrGpuGL_DEFINED #define GrGpuGL_DEFINED -#include "../GrDrawState.h" -#include "../GrGpu.h" +#include "GrDrawState.h" +#include "GrGpu.h" #include "GrGLContextInfo.h" #include "GrGLIndexBuffer.h" #include "GrGLIRect.h" diff --git a/gpu/gl/GrGpuGLShaders.cpp b/gpu/gl/GrGpuGLShaders.cpp index f3815647..9b6600bf 100644 --- a/gpu/gl/GrGpuGLShaders.cpp +++ b/gpu/gl/GrGpuGLShaders.cpp @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * @@ -7,16 +6,18 @@ */ -#include "../GrBinHashKey.h" +#include "GrBinHashKey.h" +#include "effects/GrConvolutionEffect.h" #include "GrCustomStage.h" #include "GrGLProgram.h" #include "GrGLProgramStage.h" #include "GrGLSL.h" #include "GrGpuGLShaders.h" -#include "../GrGpuVertex.h" +#include "GrGpuVertex.h" #include "GrNoncopyable.h" -#include "../GrStringBuilder.h" -#include "../GrRandom.h" +#include "GrProgramStageFactory.h" +#include "GrRandom.h" +#include "GrStringBuilder.h" #define SKIP_CACHE_CHECK true #define GR_UINT32_MAX static_cast<uint32_t>(-1) @@ -263,6 +264,10 @@ bool GrGpuGLShaders::programUnitTest() { pdesc.fVertexLayout |= kTextFormat_VertexLayoutBit; } StageDesc& stage = pdesc.fStages[s]; + + stage.fCustomStageKey = 0; + customStages[s] = NULL; + stage.fOptFlags = STAGE_OPTS[random_int(&random, GR_ARRAY_COUNT(STAGE_OPTS))]; stage.fInConfigFlags = IN_CONFIG_FLAGS[random_int(&random, GR_ARRAY_COUNT(IN_CONFIG_FLAGS))]; stage.fCoordMapping = random_int(&random, StageDesc::kCoordMappingCnt); @@ -294,8 +299,19 @@ bool GrGpuGLShaders::programUnitTest() { break; } - stage.fCustomStageKey = 0; - customStages[s] = NULL; + // TODO: is there a more elegant way to express this? + if (stage.fFetchMode == StageDesc::kConvolution_FetchMode) { + int direction = random_int(&random, 2); + float kernel[stage.fKernelWidth]; + for (int i = 0; i < stage.fKernelWidth; i++) { + kernel[i] = random.nextF(); + } + customStages[s] = new GrConvolutionEffect( + (GrSamplerState::FilterDirection)direction, + stage.fKernelWidth, kernel); + stage.fCustomStageKey = + customStages[s]->getFactory()->stageKey(customStages[s]); + } } CachedData cachedData; if (!program.genProgram(this->glContextInfo(), customStages, @@ -829,8 +845,11 @@ bool GrGpuGLShaders::flushGraphicsState(GrPrimitiveType type) { if (NULL != fProgramData->fCustomStage[s]) { const GrSamplerState& sampler = this->getDrawState().getSampler(s); + const GrGLTexture* texture = + static_cast<const GrGLTexture*>( + this->getDrawState().getTexture(s)); fProgramData->fCustomStage[s]->setData( - this->glInterface(), sampler.getCustomStage()); + this->glInterface(), sampler.getCustomStage(), texture); } } } @@ -1002,7 +1021,7 @@ void setup_custom_stage(GrGLProgram::ProgramDesc::StageDesc* stage, GrGLProgram* program, int index) { GrCustomStage* customStage = sampler.getCustomStage(); if (customStage) { - GrGLProgramStageFactory* factory = customStage->getGLFactory(); + GrProgramStageFactory* factory = customStage->getFactory(); stage->fCustomStageKey = factory->stageKey(customStage); customStages[index] = customStage; } else { @@ -1215,8 +1234,7 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type, } } - if (sampler.getFilter() == GrSamplerState::kConvolution_Filter || - sampler.getFilter() == GrSamplerState::kDilate_Filter || + if (sampler.getFilter() == GrSamplerState::kDilate_Filter || sampler.getFilter() == GrSamplerState::kErode_Filter) { stage.fKernelWidth = sampler.getKernelWidth(); } else { diff --git a/gpu/gl/GrGpuGLShaders.h b/gpu/gl/GrGpuGLShaders.h index 2ce95eb2..55fd952b 100644 --- a/gpu/gl/GrGpuGLShaders.h +++ b/gpu/gl/GrGpuGLShaders.h @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * |