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@3887 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
tomhudson@google.com 2012-05-10 12:13:36 +00:00
parent 96a162eb71
commit d8f856c32b
38 changed files with 480 additions and 209 deletions

View File

@ -164,6 +164,7 @@
'../include/config', '../include/config',
'../include/gpu', '../include/gpu',
'../src/core', # SkRasterClip.h '../src/core', # SkRasterClip.h
'../src/gpu'
], ],
'dependencies': [ 'dependencies': [
'libtess.gyp:libtess', 'libtess.gyp:libtess',
@ -248,6 +249,8 @@
'../src/gpu/GrPathUtils.cpp', '../src/gpu/GrPathUtils.cpp',
'../src/gpu/GrPathUtils.h', '../src/gpu/GrPathUtils.h',
'../src/gpu/GrPlotMgr.h', '../src/gpu/GrPlotMgr.h',
'../src/gpu/GrProgramStageFactory.cpp',
'../src/gpu/GrProgramStageFactory.h',
'../src/gpu/GrRandom.h', '../src/gpu/GrRandom.h',
'../src/gpu/GrRectanizer.cpp', '../src/gpu/GrRectanizer.cpp',
'../src/gpu/GrRectanizer.h', '../src/gpu/GrRectanizer.h',
@ -276,6 +279,9 @@
'../src/gpu/GrVertexBuffer.h', '../src/gpu/GrVertexBuffer.h',
'../src/gpu/gr_unittests.cpp', '../src/gpu/gr_unittests.cpp',
'../src/gpu/effects/GrConvolutionEffect.cpp',
'../src/gpu/effects/GrConvolutionEffect.h',
'../src/gpu/gl/GrGLCaps.cpp', '../src/gpu/gl/GrGLCaps.cpp',
'../src/gpu/gl/GrGLCaps.h', '../src/gpu/gl/GrGLCaps.h',
'../src/gpu/gl/GrGLContextInfo.cpp', '../src/gpu/gl/GrGLContextInfo.cpp',

View File

@ -11,7 +11,7 @@
#include "GrRefCnt.h" #include "GrRefCnt.h"
class GrContext; class GrContext;
class GrGLProgramStageFactory; class GrProgramStageFactory;
/** Provides custom vertex shader, fragment shader, uniform data for a /** Provides custom vertex shader, fragment shader, uniform data for a
particular stage of the Ganesh shading pipeline. particular stage of the Ganesh shading pipeline.
@ -23,6 +23,10 @@ public:
GrCustomStage(); GrCustomStage();
virtual ~GrCustomStage(); virtual ~GrCustomStage();
/** Human-meaningful string to identify this effect; may be embedded
in generated shader code. */
virtual const char* name() const = 0;
/** If given an input texture that is/is not opaque, is this /** If given an input texture that is/is not opaque, is this
stage guaranteed to produce an opaque output? */ stage guaranteed to produce an opaque output? */
virtual bool isOpaque(bool inputTextureIsOpaque) const; virtual bool isOpaque(bool inputTextureIsOpaque) const;
@ -30,14 +34,20 @@ public:
/** This pointer, besides creating back-end-specific helper /** This pointer, besides creating back-end-specific helper
objects, is used for run-time-type-identification. Every objects, is used for run-time-type-identification. Every
subclass must return a consistent unique value for it. */ subclass must return a consistent unique value for it. */
virtual GrGLProgramStageFactory* getGLFactory() const = 0; virtual GrProgramStageFactory* getFactory() const = 0;
/** Returns true if the other custom stage will generate /** Returns true if the other custom stage will generate
a compatible/equivalent shader. Must only be called if equal output.
the two are already known to be of the same type (i.e. Must only be called if the two are already known to be of the
they return the same value from getGLFactory()). */ same type (i.e. they return the same value from getFactory()).
virtual bool isEquivalent(const GrCustomStage *) const = 0; For equivalence (that they will generate the same
shader, but perhaps have different uniforms), check equality
of the stageKey produced by the GrProgramStageFactory. */
virtual bool isEqual(const GrCustomStage *) const = 0;
private:
typedef GrRefCnt INHERITED;
}; };
#endif #endif

View File

@ -133,9 +133,9 @@ public:
return !memcmp(this, &s, bitwiseRegion) && return !memcmp(this, &s, bitwiseRegion) &&
((fCustomStage == s.fCustomStage) || ((fCustomStage == s.fCustomStage) ||
(fCustomStage && s.fCustomStage && (fCustomStage && s.fCustomStage &&
(fCustomStage->getGLFactory() == (fCustomStage->getFactory() ==
s.fCustomStage->getGLFactory()) && s.fCustomStage->getFactory()) &&
fCustomStage->isEquivalent(s.fCustomStage))); fCustomStage->isEqual(s.fCustomStage)));
} }
bool operator !=(const GrSamplerState& s) const { return !(*this == s); } bool operator !=(const GrSamplerState& s) const { return !(*this == s); }
@ -289,10 +289,6 @@ private:
uint8_t fKernelWidth; uint8_t fKernelWidth;
float fKernel[MAX_KERNEL_WIDTH]; float fKernel[MAX_KERNEL_WIDTH];
/// BUG! Ganesh only works correctly so long as fCustomStage is
/// NULL; we need to have a complex ID system here so that we can
/// have an equality-like comparison to determine whether two
/// fCustomStages are equal.
GrCustomStage* fCustomStage; GrCustomStage* fCustomStage;
}; };

View File

@ -11,6 +11,7 @@
#include "GrBufferAllocPool.h" #include "GrBufferAllocPool.h"
#include "GrClipIterator.h" #include "GrClipIterator.h"
#include "effects/GrConvolutionEffect.h"
#include "GrGpu.h" #include "GrGpu.h"
#include "GrIndexBuffer.h" #include "GrIndexBuffer.h"
#include "GrInOrderDrawBuffer.h" #include "GrInOrderDrawBuffer.h"
@ -296,8 +297,8 @@ void convolve(GrGpu* gpu,
drawState->sampler(0)->reset(GrSamplerState::kClamp_WrapMode, drawState->sampler(0)->reset(GrSamplerState::kClamp_WrapMode,
GrSamplerState::kConvolution_Filter, GrSamplerState::kConvolution_Filter,
sampleM); sampleM);
drawState->sampler(0)->setConvolutionParams(kernelWidth, kernel); drawState->sampler(0)->setCustomStage(
drawState->sampler(0)->setFilterDirection(direction); new GrConvolutionEffect(direction, kernelWidth, kernel));
drawState->setTexture(0, texture); drawState->setTexture(0, texture);
gpu->drawSimpleRect(rect, NULL, 1 << 0); gpu->drawSimpleRect(rect, NULL, 1 << 0);
} }

View File

@ -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;
}

View File

@ -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

View File

@ -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)));
}

View File

@ -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

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2012 Google Inc. * Copyright 2012 Google Inc.
* *

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2012 Google Inc. * Copyright 2012 Google Inc.
* *

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2012 Google Inc. * Copyright 2012 Google Inc.
* *

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2011 Google Inc. * Copyright 2011 Google Inc.
* *

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2011 Google Inc. * Copyright 2011 Google Inc.
* *
@ -8,7 +7,7 @@
#include "gl/GrGLInterface.h" #include "gl/GrGLInterface.h"
#include "../GrTDArray.h" #include "GrTDArray.h"
#include "GrGLDefines.h" #include "GrGLDefines.h"
GrGLvoid GR_GL_FUNCTION_TYPE nullGLActiveTexture(GrGLenum texture) {} GrGLvoid GR_GL_FUNCTION_TYPE nullGLActiveTexture(GrGLenum texture) {}

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2011 Google Inc. * Copyright 2011 Google Inc.
* *

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2011 Google Inc. * Copyright 2011 Google Inc.
* *

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2011 Google Inc. * Copyright 2011 Google Inc.
* *

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2011 Google Inc. * Copyright 2011 Google Inc.
* *

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2011 Google Inc. * Copyright 2011 Google Inc.
* *

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2011 Google Inc. * Copyright 2011 Google Inc.
* *
@ -11,7 +10,7 @@
#ifndef GrGLIndexBuffer_DEFINED #ifndef GrGLIndexBuffer_DEFINED
#define GrGLIndexBuffer_DEFINED #define GrGLIndexBuffer_DEFINED
#include "../GrIndexBuffer.h" #include "GrIndexBuffer.h"
#include "gl/GrGLInterface.h" #include "gl/GrGLInterface.h"
class GrGpuGL; class GrGpuGL;

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2011 Google Inc. * Copyright 2011 Google Inc.
* *

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2011 Google Inc. * Copyright 2011 Google Inc.
* *
@ -6,13 +5,13 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#include "GrGLProgram.h" #include "GrGLProgram.h"
#include "../GrAllocator.h" #include "GrAllocator.h"
#include "GrCustomStage.h" #include "GrCustomStage.h"
#include "GrGLProgramStage.h" #include "GrGLProgramStage.h"
#include "GrGLShaderVar.h" #include "GrGLShaderVar.h"
#include "GrProgramStageFactory.h"
#include "SkTrace.h" #include "SkTrace.h"
#include "SkXfermode.h" #include "SkXfermode.h"
@ -647,7 +646,6 @@ GrGLProgram::CachedData::~CachedData() {
bool GrGLProgram::genProgram(const GrGLContextInfo& gl, bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
GrCustomStage** customStages, GrCustomStage** customStages,
GrGLProgram::CachedData* programData) const { GrGLProgram::CachedData* programData) const {
ShaderCodeSegments segments; ShaderCodeSegments segments;
const uint32_t& layout = fProgramDesc.fVertexLayout; const uint32_t& layout = fProgramDesc.fVertexLayout;
@ -757,19 +755,13 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
} }
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Convert generic effect representation to GL-specific backend so they // We need to convert generic effect representations to GL-specific
// can be accesseed in genStageCode() and in subsequent uses of // backends so they can be accesseed in genStageCode() and in subsequent,
// programData. // 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) { 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;
} }
}
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// compute the final color // compute the final color
@ -798,6 +790,12 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
inCoords = texCoordAttrs[tcIdx].c_str(); inCoords = texCoordAttrs[tcIdx].c_str();
} }
if (NULL != customStages[s]) {
GrProgramStageFactory* factory =
customStages[s]->getFactory();
programData->fCustomStage[s] =
factory->createGLInstance(customStages[s]);
}
this->genStageCode(gl, this->genStageCode(gl,
s, s,
fProgramDesc.fStages[s], fProgramDesc.fStages[s],
@ -918,6 +916,12 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
inCoords = texCoordAttrs[tcIdx].c_str(); 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, this->genStageCode(gl, s,
fProgramDesc.fStages[s], fProgramDesc.fStages[s],
inCoverage.size() ? inCoverage.c_str() : NULL, 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, void genMorphologyVS(int stageNum,
const StageDesc& desc, const StageDesc& desc,
ShaderCodeSegments* segments, ShaderCodeSegments* segments,
@ -1775,7 +1709,7 @@ void GrGLProgram::genStageCode(const GrGLContextInfo& gl,
/// Vertex Shader Stuff /// Vertex Shader Stuff
if (NULL != customStage) { if (NULL != customStage) {
customStage->setupVSUnis(segments->fVSUnis, stageNum); customStage->setupVSUnis(&segments->fVSUnis, stageNum);
} }
// decide whether we need a matrix to transform texture coords // decide whether we need a matrix to transform texture coords
@ -1852,10 +1786,7 @@ void GrGLProgram::genStageCode(const GrGLContextInfo& gl,
GrGLShaderVar* kernel = NULL; GrGLShaderVar* kernel = NULL;
const char* imageIncrementName = NULL; const char* imageIncrementName = NULL;
if (StageDesc::kConvolution_FetchMode == desc.fFetchMode) { if (StageDesc::kDilate_FetchMode == desc.fFetchMode ||
genConvolutionVS(stageNum, desc, segments, locations,
&kernel, &imageIncrementName, varyingVSName);
} else if (StageDesc::kDilate_FetchMode == desc.fFetchMode ||
StageDesc::kErode_FetchMode == desc.fFetchMode) { StageDesc::kErode_FetchMode == desc.fFetchMode) {
genMorphologyVS(stageNum, desc, segments, locations, genMorphologyVS(stageNum, desc, segments, locations,
&imageIncrementName, varyingVSName); &imageIncrementName, varyingVSName);
@ -1864,15 +1795,16 @@ void GrGLProgram::genStageCode(const GrGLContextInfo& gl,
if (NULL != customStage) { if (NULL != customStage) {
GrStringBuilder vertexShader; GrStringBuilder vertexShader;
customStage->emitVS(&vertexShader, varyingVSName); 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.append(vertexShader);
segments->fVSCode.appendf("}\n"); segments->fVSCode.appendf("\t}\n");
} }
/// Fragment Shader Stuff /// Fragment Shader Stuff
if (NULL != customStage) { if (NULL != customStage) {
customStage->setupFSUnis(segments->fFSUnis, stageNum); customStage->setupFSUnis(&segments->fFSUnis, stageNum);
} }
GrStringBuilder fsCoordName; GrStringBuilder fsCoordName;
@ -1985,9 +1917,6 @@ void GrGLProgram::genStageCode(const GrGLContextInfo& gl,
break; break;
case StageDesc::kConvolution_FetchMode: case StageDesc::kConvolution_FetchMode:
GrAssert(!(desc.fInConfigFlags & kMulByAlphaMask)); GrAssert(!(desc.fInConfigFlags & kMulByAlphaMask));
genConvolutionFS(stageNum, desc, segments,
samplerName, kernel, swizzle, imageIncrementName, fsOutColor,
sampleCoords, texFunc, modulate);
break; break;
case StageDesc::kDilate_FetchMode: case StageDesc::kDilate_FetchMode:
case StageDesc::kErode_FetchMode: case StageDesc::kErode_FetchMode:
@ -2040,15 +1969,16 @@ void GrGLProgram::genStageCode(const GrGLContextInfo& gl,
GrStringBuilder fragmentShader; GrStringBuilder fragmentShader;
fsCoordName = customStage->emitTextureSetup( fsCoordName = customStage->emitTextureSetup(
&fragmentShader, varyingFSName, &fragmentShader, sampleCoords.c_str(),
stageNum, coordDims, varyingDims); stageNum, coordDims, varyingDims);
customStage->emitFS(&fragmentShader, fsOutColor, fsInColor, customStage->emitFS(&fragmentShader, fsOutColor, fsInColor,
samplerName, fsCoordName.c_str()); samplerName, fsCoordName.c_str());
// Enclose custom code in a block to avoid namespace conflicts // 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.append(fragmentShader);
segments->fFSCode.appendf("}\n"); segments->fFSCode.appendf("\t}\n");
} }
} }

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2011 Google Inc. * Copyright 2011 Google Inc.
* *
@ -10,11 +9,11 @@
#ifndef GrGLProgram_DEFINED #ifndef GrGLProgram_DEFINED
#define GrGLProgram_DEFINED #define GrGLProgram_DEFINED
#include "../GrDrawState.h" #include "GrDrawState.h"
#include "GrGLContextInfo.h" #include "GrGLContextInfo.h"
#include "GrGLSL.h" #include "GrGLSL.h"
#include "../GrStringBuilder.h" #include "GrStringBuilder.h"
#include "../GrGpu.h" #include "GrGpu.h"
#include "SkXfermode.h" #include "SkXfermode.h"
@ -108,6 +107,7 @@ public:
kCustomTextureDomain_OptFlagBit = 1 << 2, kCustomTextureDomain_OptFlagBit = 1 << 2,
kIsEnabled_OptFlagBit = 1 << 7 kIsEnabled_OptFlagBit = 1 << 7
}; };
// Convolution is obsolete; left in for testing only
enum FetchMode { enum FetchMode {
kSingle_FetchMode, kSingle_FetchMode,
k2x2_FetchMode, k2x2_FetchMode,
@ -320,6 +320,9 @@ public:
void copyAndTakeOwnership(CachedData& other) { void copyAndTakeOwnership(CachedData& other) {
memcpy(this, &other, sizeof(*this)); memcpy(this, &other, sizeof(*this));
for (int i = 0; i < GrDrawState::kNumStages; ++i) {
other.fCustomStage[i] = NULL;
}
} }
public: public:

View File

@ -13,19 +13,11 @@ GrGLProgramStage::~GrGLProgramStage() {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
GrGLProgramStageFactory::~GrGLProgramStageFactory(void) { void GrGLProgramStage::setupVSUnis(VarArray* vsUnis, int stage) {
} }
uint16_t GrGLProgramStageFactory::stageKey(const GrCustomStage*) { void GrGLProgramStage::setupFSUnis(VarArray* fsUnis, int stage) {
return 0;
}
void GrGLProgramStage::setupVSUnis(VarArray& vsUnis, 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*) {
} }

View File

@ -8,13 +8,14 @@
#ifndef GrGLCustomStage_DEFINED #ifndef GrGLCustomStage_DEFINED
#define GrGLCustomStage_DEFINED #define GrGLCustomStage_DEFINED
#include "../GrAllocator.h" #include "GrAllocator.h"
#include "GrGLShaderVar.h" #include "GrGLShaderVar.h"
#include "GrGLSL.h" #include "GrGLSL.h"
#include "../GrStringBuilder.h" #include "GrStringBuilder.h"
class GrCustomStage; class GrCustomStage;
struct GrGLInterface; struct GrGLInterface;
class GrGLTexture;
/** @file /** @file
This file contains specializations for OpenGL of the shader stages This file contains specializations for OpenGL of the shader stages
@ -39,17 +40,19 @@ public:
virtual ~GrGLProgramStage(); virtual ~GrGLProgramStage();
virtual const char* name() const = 0;
/** Creates any uniform variables the vertex shader requires /** Creates any uniform variables the vertex shader requires
and appends them to vsUnis; and appends them to vsUnis;
must guarantee they are unique (typically done by must guarantee they are unique (typically done by
appending the stage number). */ 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 /** Creates any uniform variables the fragment shader requires
and appends them to fsUnis; and appends them to fsUnis;
must guarantee they are unique (typically done by must guarantee they are unique (typically done by
appending the stage number). */ 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; /** Given an empty GrStringBuilder and the names of variables;
must write shader code into that GrStringBuilder. must write shader code into that GrStringBuilder.
@ -86,7 +89,8 @@ public:
are to be read. are to be read.
TODO: since we don't have a factory, we can't assert to enforce TODO: since we don't have a factory, we can't assert to enforce
this. Shouldn't we? */ this. Shouldn't we? */
virtual void setData(const GrGLInterface*, GrCustomStage*); virtual void setData(const GrGLInterface*, GrCustomStage*,
const GrGLTexture*);
// TODO: needs a better name // TODO: needs a better name
enum SamplerMode { enum SamplerMode {
@ -95,7 +99,7 @@ public:
kExplicitDivide_SamplerMode // must do an explicit divide 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 /** Returns the *effective* coord name after any perspective divide
or other transform. */ 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 #endif

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2011 Google Inc. * Copyright 2011 Google Inc.
* *
@ -6,7 +5,6 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#include "GrGLRenderTarget.h" #include "GrGLRenderTarget.h"
#include "GrGpuGL.h" #include "GrGpuGL.h"

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2011 Google Inc. * Copyright 2011 Google Inc.
* *

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2011 Google Inc. * Copyright 2011 Google Inc.
* *
@ -11,7 +10,7 @@
#include "GrGLContextInfo.h" #include "GrGLContextInfo.h"
#include "GrGLSL.h" #include "GrGLSL.h"
#include "../GrStringBuilder.h" #include "GrStringBuilder.h"
#define USE_UNIFORM_FLOAT_ARRAYS true #define USE_UNIFORM_FLOAT_ARRAYS true

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2011 Google Inc. * Copyright 2011 Google Inc.
* *

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2011 Google Inc. * Copyright 2011 Google Inc.
* *
@ -11,7 +10,7 @@
#define GrGLStencilBuffer_DEFINED #define GrGLStencilBuffer_DEFINED
#include "gl/GrGLInterface.h" #include "gl/GrGLInterface.h"
#include "../GrStencilBuffer.h" #include "GrStencilBuffer.h"
class GrGLStencilBuffer : public GrStencilBuffer { class GrGLStencilBuffer : public GrStencilBuffer {
public: public:

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2011 Google Inc. * Copyright 2011 Google Inc.
* *

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2011 Google Inc. * Copyright 2011 Google Inc.
* *
@ -10,7 +9,7 @@
#ifndef GrGLTexture_DEFINED #ifndef GrGLTexture_DEFINED
#define GrGLTexture_DEFINED #define GrGLTexture_DEFINED
#include "../GrGpu.h" #include "GrGpu.h"
#include "GrGLRenderTarget.h" #include "GrGLRenderTarget.h"
/** /**

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2011 Google Inc. * Copyright 2011 Google Inc.
* *

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2011 Google Inc. * Copyright 2011 Google Inc.
* *

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2011 Google Inc. * Copyright 2011 Google Inc.
* *
@ -11,7 +10,7 @@
#ifndef GrGLVertexBuffer_DEFINED #ifndef GrGLVertexBuffer_DEFINED
#define GrGLVertexBuffer_DEFINED #define GrGLVertexBuffer_DEFINED
#include "../GrVertexBuffer.h" #include "GrVertexBuffer.h"
#include "gl/GrGLInterface.h" #include "gl/GrGLInterface.h"
class GrGpuGL; class GrGpuGL;

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2011 Google Inc. * Copyright 2011 Google Inc.
* *

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2011 Google Inc. * Copyright 2011 Google Inc.
* *
@ -11,8 +10,8 @@
#ifndef GrGpuGL_DEFINED #ifndef GrGpuGL_DEFINED
#define GrGpuGL_DEFINED #define GrGpuGL_DEFINED
#include "../GrDrawState.h" #include "GrDrawState.h"
#include "../GrGpu.h" #include "GrGpu.h"
#include "GrGLContextInfo.h" #include "GrGLContextInfo.h"
#include "GrGLIndexBuffer.h" #include "GrGLIndexBuffer.h"
#include "GrGLIRect.h" #include "GrGLIRect.h"

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2011 Google Inc. * Copyright 2011 Google Inc.
* *
@ -7,16 +6,18 @@
*/ */
#include "../GrBinHashKey.h" #include "GrBinHashKey.h"
#include "effects/GrConvolutionEffect.h"
#include "GrCustomStage.h" #include "GrCustomStage.h"
#include "GrGLProgram.h" #include "GrGLProgram.h"
#include "GrGLProgramStage.h" #include "GrGLProgramStage.h"
#include "GrGLSL.h" #include "GrGLSL.h"
#include "GrGpuGLShaders.h" #include "GrGpuGLShaders.h"
#include "../GrGpuVertex.h" #include "GrGpuVertex.h"
#include "GrNoncopyable.h" #include "GrNoncopyable.h"
#include "../GrStringBuilder.h" #include "GrProgramStageFactory.h"
#include "../GrRandom.h" #include "GrRandom.h"
#include "GrStringBuilder.h"
#define SKIP_CACHE_CHECK true #define SKIP_CACHE_CHECK true
#define GR_UINT32_MAX static_cast<uint32_t>(-1) #define GR_UINT32_MAX static_cast<uint32_t>(-1)
@ -263,6 +264,10 @@ bool GrGpuGLShaders::programUnitTest() {
pdesc.fVertexLayout |= kTextFormat_VertexLayoutBit; pdesc.fVertexLayout |= kTextFormat_VertexLayoutBit;
} }
StageDesc& stage = pdesc.fStages[s]; StageDesc& stage = pdesc.fStages[s];
stage.fCustomStageKey = 0;
customStages[s] = NULL;
stage.fOptFlags = STAGE_OPTS[random_int(&random, GR_ARRAY_COUNT(STAGE_OPTS))]; 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.fInConfigFlags = IN_CONFIG_FLAGS[random_int(&random, GR_ARRAY_COUNT(IN_CONFIG_FLAGS))];
stage.fCoordMapping = random_int(&random, StageDesc::kCoordMappingCnt); stage.fCoordMapping = random_int(&random, StageDesc::kCoordMappingCnt);
@ -294,8 +299,19 @@ bool GrGpuGLShaders::programUnitTest() {
break; break;
} }
stage.fCustomStageKey = 0; // TODO: is there a more elegant way to express this?
customStages[s] = NULL; 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; CachedData cachedData;
if (!program.genProgram(this->glContextInfo(), customStages, if (!program.genProgram(this->glContextInfo(), customStages,
@ -829,8 +845,11 @@ bool GrGpuGLShaders::flushGraphicsState(GrPrimitiveType type) {
if (NULL != fProgramData->fCustomStage[s]) { if (NULL != fProgramData->fCustomStage[s]) {
const GrSamplerState& sampler = const GrSamplerState& sampler =
this->getDrawState().getSampler(s); this->getDrawState().getSampler(s);
const GrGLTexture* texture =
static_cast<const GrGLTexture*>(
this->getDrawState().getTexture(s));
fProgramData->fCustomStage[s]->setData( 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) { GrGLProgram* program, int index) {
GrCustomStage* customStage = sampler.getCustomStage(); GrCustomStage* customStage = sampler.getCustomStage();
if (customStage) { if (customStage) {
GrGLProgramStageFactory* factory = customStage->getGLFactory(); GrProgramStageFactory* factory = customStage->getFactory();
stage->fCustomStageKey = factory->stageKey(customStage); stage->fCustomStageKey = factory->stageKey(customStage);
customStages[index] = customStage; customStages[index] = customStage;
} else { } else {
@ -1215,8 +1234,7 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type,
} }
} }
if (sampler.getFilter() == GrSamplerState::kConvolution_Filter || if (sampler.getFilter() == GrSamplerState::kDilate_Filter ||
sampler.getFilter() == GrSamplerState::kDilate_Filter ||
sampler.getFilter() == GrSamplerState::kErode_Filter) { sampler.getFilter() == GrSamplerState::kErode_Filter) {
stage.fKernelWidth = sampler.getKernelWidth(); stage.fKernelWidth = sampler.getKernelWidth();
} else { } else {

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2011 Google Inc. * Copyright 2011 Google Inc.
* *