#define GrEffectStage_DEFINED
#include "GrBackendEffectFactory.h"
+#include "GrCoordTransform.h"
#include "GrEffect.h"
#include "GrProgramElementRef.h"
#include "SkMatrix.h"
}
}
+ bool isPerspectiveCoordTransform(int matrixIndex, bool useExplicitLocalCoords) const {
+ const GrCoordTransform& coordTransform = this->getEffect()->coordTransform(matrixIndex);
+ SkMatrix::TypeMask type0 = coordTransform.getMatrix().getType();
+ SkMatrix::TypeMask type1 = SkMatrix::kIdentity_Mask;
+ if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
+ type1 = useExplicitLocalCoords ?
+ SkMatrix::kIdentity_Mask : this->getCoordChangeMatrix().getType();
+ }
+
+ int combinedTypes = type0 | type1;
+ if (SkMatrix::kPerspective_Mask & combinedTypes) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
const GrEffect* getEffect() const { return fEffect.get(); }
void convertToPendingExec() { fEffect.convertToPendingExec(); }
, fPrecision(kDefault_Precision) {
}
+ GrShaderVar(const SkString& name, GrSLType type, int arrayCount = kNonArray,
+ Precision precision = kDefault_Precision)
+ : fType(type)
+ , fTypeModifier(kNone_TypeModifier)
+ , fName(name)
+ , fCount(arrayCount)
+ , fPrecision(precision) {
+ SkASSERT(kVoid_GrSLType != type);
+ }
+
GrShaderVar(const char* name, GrSLType type, int arrayCount = kNonArray,
Precision precision = kDefault_Precision)
: fType(type)
if (backgroundTex) {
dstColor = "bgColor";
fsBuilder->codeAppendf("\t\tvec4 %s = ", dstColor);
- fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type());
+ fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].getType());
fsBuilder->codeAppendf(";\n");
} else {
dstColor = fsBuilder->dstColor();
const char* dstColor;
if (backgroundTex) {
fsBuilder->codeAppend("\t\tvec4 bgColor = ");
- fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type());
+ fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].getType());
fsBuilder->codeAppendf(";\n");
dstColor = "bgColor";
} else {
GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
fsBuilder->codeAppendf("\t\tvec4 %s = ", dColor);
- fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type());
+ fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].getType());
fsBuilder->codeAppend(";\n");
// Unpremultiply the displacement
"bool %s = (%s.x < 0.0) || (%s.y < 0.0) || (%s.x > 1.0) || (%s.y > 1.0);\t\t",
outOfBounds, cCoords, cCoords, cCoords, cCoords);
fsBuilder->codeAppendf("%s = %s ? vec4(0.0) : ", outputColor, outOfBounds);
- fsBuilder->appendTextureLookup(samplers[1], cCoords, coords[1].type());
+ fsBuilder->appendTextureLookup(samplers[1], cCoords, coords[1].getType());
fsBuilder->codeAppend(";\n");
}
builder->getUniformVariable(fParamUni).appendArrayAccess(2, &p2);
// We interpolate the linear component in coords[1].
- SkASSERT(coords[0].type() == coords[1].type());
+ SkASSERT(coords[0].getType() == coords[1].getType());
const char* coords2D;
SkString bVar;
GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
- if (kVec3f_GrSLType == coords[0].type()) {
+ if (kVec3f_GrSLType == coords[0].getType()) {
fsBuilder->codeAppendf("\tvec3 interpolants = vec3(%s.xy / %s.z, %s.x / %s.z);\n",
coords[0].c_str(), coords[0].c_str(), coords[1].c_str(),
coords[1].c_str());
GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
// We interpolate the linear component in coords[1].
- SkASSERT(coords[0].type() == coords[1].type());
+ SkASSERT(coords[0].getType() == coords[1].getType());
const char* coords2D;
SkString bVar;
- if (kVec3f_GrSLType == coords[0].type()) {
+ if (kVec3f_GrSLType == coords[0].getType()) {
fsBuilder->codeAppendf("\tvec3 interpolants = vec3(%s.xy, %s.x) / %s.z;\n",
coords[0].c_str(), coords[1].c_str(), coords[0].c_str());
coords2D = "interpolants.xy";
fsBuilder->codeAppendf("%s;", tmpDecl.c_str());
fsBuilder->codeAppendf("%s = ", tmpVar.c_str());
- fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type());
+ fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].getType());
fsBuilder->codeAppend(";");
if (GrConfigConversionEffect::kNone_PMConversion == fPMConversion) {
fsBuilder->appendTextureLookupAndModulate(inputColor,
samplers[0],
coords[0].c_str(),
- coords[0].type());
+ coords[0].getType());
fsBuilder->codeAppend(";\n");
}
kMat44f_GrSLType, "YUVMatrix",
&yuvMatrix);
fsBuilder->codeAppendf("\t%s = vec4(\n\t\t", outputColor);
- fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type());
+ fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].getType());
fsBuilder->codeAppend(".r,\n\t\t");
- fsBuilder->appendTextureLookup(samplers[1], coords[0].c_str(), coords[0].type());
+ fsBuilder->appendTextureLookup(samplers[1], coords[0].c_str(), coords[0].getType());
fsBuilder->codeAppend(".r,\n\t\t");
- fsBuilder->appendTextureLookup(samplers[2], coords[0].c_str(), coords[0].type());
+ fsBuilder->appendTextureLookup(samplers[2], coords[0].c_str(), coords[0].getType());
fsBuilder->codeAppendf(".r,\n\t\t1.0) * %s;\n", yuvMatrix);
}
class GrGLGeometryProcessor;
class GrGLEffect {
-
public:
- typedef GrGLProgramEffects::TransformedCoordsArray TransformedCoordsArray;
- typedef GrGLProgramEffects::TextureSampler TextureSampler;
- typedef GrGLProgramEffects::TextureSamplerArray TextureSamplerArray;
+ typedef GrGLProgramDataManager::UniformHandle UniformHandle;
+
+ /**
+ * Passed to GrGLEffects so they can add transformed coordinates to their shader code.
+ */
+ typedef GrShaderVar TransformedCoords;
+ typedef SkTArray<GrShaderVar> TransformedCoordsArray;
+
+ /**
+ * Passed to GrGLEffects so they can add texture reads to their shader code.
+ */
+ class TextureSampler {
+ public:
+ TextureSampler(UniformHandle uniform, const GrTextureAccess& access)
+ : fSamplerUniform(uniform)
+ , fConfigComponentMask(GrPixelConfigComponentMask(access.getTexture()->config())) {
+ SkASSERT(0 != fConfigComponentMask);
+ memcpy(fSwizzle, access.getSwizzle(), 5);
+ }
+
+ // bitfield of GrColorComponentFlags present in the texture's config.
+ uint32_t configComponentMask() const { return fConfigComponentMask; }
+ // this is .abcd
+ const char* swizzle() const { return fSwizzle; }
+
+ private:
+ UniformHandle fSamplerUniform;
+ uint32_t fConfigComponentMask;
+ char fSwizzle[5];
+
+ friend class GrGLShaderBuilder;
+ };
+
+ typedef SkTArray<TextureSampler> TextureSamplerArray;
GrGLEffect(const GrBackendEffectFactory& factory)
: fFactory(factory)
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
+
#include "GrGLProgram.h"
#include "builders/GrGLFragmentOnlyProgramBuilder.h"
if (fGeometryProcessor.get()) {
SkASSERT(geometryProcessor);
- fGeometryProcessor->setData(fGpu, drawType,fProgramDataManager, geometryProcessor);
+ fGeometryProcessor->setData(fGpu, drawType, fProgramDataManager, &geometryProcessor);
}
- fColorEffects->setData(fGpu, drawType,fProgramDataManager, colorStages);
- fCoverageEffects->setData(fGpu, drawType,fProgramDataManager, coverageStages);
+ fColorEffects->setData(fGpu, drawType, fProgramDataManager, colorStages);
+ fCoverageEffects->setData(fGpu, drawType, fProgramDataManager, coverageStages);
// PathTexGen state applies to the the fixed function vertex shader. For
// custom shaders, it's ignored, so we don't need to change the texgen
#include "SkChecksum.h"
+/**
+ * The key for an individual coord transform is made up of a matrix type and a bit that
+ * indicates the source of the input coords.
+ */
+enum {
+ kMatrixTypeKeyBits = 1,
+ kMatrixTypeKeyMask = (1 << kMatrixTypeKeyBits) - 1,
+ kPositionCoords_Flag = (1 << kMatrixTypeKeyBits),
+ kTransformKeyBits = kMatrixTypeKeyBits + 1,
+};
+
+/**
+ * We specialize the vertex code for each of these matrix types.
+ */
+enum MatrixType {
+ kNoPersp_MatrixType = 0,
+ kGeneral_MatrixType = 1,
+};
+
+/**
+ * Do we need to either map r,g,b->a or a->r. configComponentMask indicates which channels are
+ * present in the texture's config. swizzleComponentMask indicates the channels present in the
+ * shader swizzle.
+ */
+static bool swizzle_requires_alpha_remapping(const GrGLCaps& caps,
+ uint32_t configComponentMask,
+ uint32_t swizzleComponentMask) {
+ if (caps.textureSwizzleSupport()) {
+ // Any remapping is handled using texture swizzling not shader modifications.
+ return false;
+ }
+ // check if the texture is alpha-only
+ if (kA_GrColorComponentFlag == configComponentMask) {
+ if (caps.textureRedSupport() && (kA_GrColorComponentFlag & swizzleComponentMask)) {
+ // we must map the swizzle 'a's to 'r'.
+ return true;
+ }
+ if (kRGB_GrColorComponentFlags & swizzleComponentMask) {
+ // The 'r', 'g', and/or 'b's must be mapped to 'a' according to our semantics that
+ // alpha-only textures smear alpha across all four channels when read.
+ return true;
+ }
+ }
+ return false;
+}
+
+static uint32_t gen_attrib_key(const GrEffect* effect) {
+ uint32_t key = 0;
+
+ const GrEffect::VertexAttribArray& vars = effect->getVertexAttribs();
+ int numAttributes = vars.count();
+ SkASSERT(numAttributes <= 2);
+ for (int a = 0; a < numAttributes; ++a) {
+ uint32_t value = 1 << a;
+ key |= value;
+ }
+ return key;
+}
+
+static uint32_t gen_transform_key(const GrEffectStage& effectStage,
+ bool useExplicitLocalCoords) {
+ uint32_t totalKey = 0;
+ int numTransforms = effectStage.getEffect()->numTransforms();
+ for (int t = 0; t < numTransforms; ++t) {
+ uint32_t key = 0;
+ if (effectStage.isPerspectiveCoordTransform(t, useExplicitLocalCoords)) {
+ key |= kGeneral_MatrixType;
+ } else {
+ key |= kNoPersp_MatrixType;
+ }
+
+ const GrCoordTransform& coordTransform = effectStage.getEffect()->coordTransform(t);
+ if (kLocal_GrCoordSet != coordTransform.sourceCoords() && useExplicitLocalCoords) {
+ key |= kPositionCoords_Flag;
+ }
+ key <<= kTransformKeyBits * t;
+ SkASSERT(0 == (totalKey & key)); // keys for each transform ought not to overlap
+ totalKey |= key;
+ }
+ return totalKey;
+}
+
+static uint32_t gen_texture_key(const GrEffect* effect, const GrGLCaps& caps) {
+ uint32_t key = 0;
+ int numTextures = effect->numTextures();
+ for (int t = 0; t < numTextures; ++t) {
+ const GrTextureAccess& access = effect->textureAccess(t);
+ uint32_t configComponentMask = GrPixelConfigComponentMask(access.getTexture()->config());
+ if (swizzle_requires_alpha_remapping(caps, configComponentMask, access.swizzleMask())) {
+ key |= 1 << t;
+ }
+ }
+ return key;
+}
+
+/**
+ * A function which emits a meta key into the key builder. This is required because shader code may
+ * be dependent on properties of the effect that the effect itself doesn't use
+ * in its key (e.g. the pixel format of textures used). So we create a meta-key for
+ * every effect using this function. It is also responsible for inserting the effect's class ID
+ * which must be different for every GrEffect subclass. It can fail if an effect uses too many
+ * textures, attributes, etc for the space allotted in the meta-key.
+ */
+
+static bool gen_effect_meta_key(const GrEffectStage& effectStage,
+ bool useExplicitLocalCoords,
+ const GrGLCaps& caps,
+ GrEffectKeyBuilder* b) {
+
+ uint32_t textureKey = gen_texture_key(effectStage.getEffect(), caps);
+ uint32_t transformKey = gen_transform_key(effectStage,useExplicitLocalCoords);
+ uint32_t attribKey = gen_attrib_key(effectStage.getEffect());
+ uint32_t classID = effectStage.getEffect()->getFactory().effectClassID();
+
+ // Currently we allow 16 bits for each of the above portions of the meta-key. Fail if they
+ // don't fit.
+ static const uint32_t kMetaKeyInvalidMask = ~((uint32_t) SK_MaxU16);
+ if ((textureKey | transformKey | attribKey | classID) & kMetaKeyInvalidMask) {
+ return false;
+ }
+
+ uint32_t* key = b->add32n(2);
+ key[0] = (textureKey << 16 | transformKey);
+ key[1] = (classID << 16 | attribKey);
+ return true;
+}
+
bool GrGLProgramDesc::GetEffectKey(const GrEffectStage& stage, const GrGLCaps& caps,
bool useExplicitLocalCoords, GrEffectKeyBuilder* b,
uint16_t* effectKeySize) {
return false;
}
*effectKeySize = SkToU16(size);
- if (!GrGLProgramEffects::GenEffectMetaKey(stage,
- useExplicitLocalCoords,
- caps,
- b)) {
+ if (!gen_effect_meta_key(stage, useExplicitLocalCoords, caps, b)) {
return false;
}
return true;
#include "gl/GrGLGeometryProcessor.h"
#include "gl/GrGpuGL.h"
-typedef GrGLProgramEffects::TransformedCoords TransformedCoords;
-typedef GrGLProgramEffects::TransformedCoordsArray TransformedCoordsArray;
-typedef GrGLProgramEffects::TextureSampler TextureSampler;
-typedef GrGLProgramEffects::TextureSamplerArray TextureSamplerArray;
-
-/**
- * We specialize the vertex code for each of these matrix types.
- */
-enum MatrixType {
- kNoPersp_MatrixType = 0,
- kGeneral_MatrixType = 1,
-};
-
-/**
- * The key for an individual coord transform is made up of a matrix type and a bit that
- * indicates the source of the input coords.
- */
-enum {
- kMatrixTypeKeyBits = 1,
- kMatrixTypeKeyMask = (1 << kMatrixTypeKeyBits) - 1,
- kPositionCoords_Flag = (1 << kMatrixTypeKeyBits),
- kTransformKeyBits = kMatrixTypeKeyBits + 1,
-};
+typedef GrGLEffect::TransformedCoords TransformedCoords;
+typedef GrGLEffect::TransformedCoordsArray TransformedCoordsArray;
+typedef GrGLEffect::TextureSampler TextureSampler;
+typedef GrGLEffect::TextureSamplerArray TextureSamplerArray;
namespace {
-
-/**
- * Do we need to either map r,g,b->a or a->r. configComponentMask indicates which channels are
- * present in the texture's config. swizzleComponentMask indicates the channels present in the
- * shader swizzle.
- */
-inline bool swizzle_requires_alpha_remapping(const GrGLCaps& caps,
- uint32_t configComponentMask,
- uint32_t swizzleComponentMask) {
- if (caps.textureSwizzleSupport()) {
- // Any remapping is handled using texture swizzling not shader modifications.
- return false;
- }
- // check if the texture is alpha-only
- if (kA_GrColorComponentFlag == configComponentMask) {
- if (caps.textureRedSupport() && (kA_GrColorComponentFlag & swizzleComponentMask)) {
- // we must map the swizzle 'a's to 'r'.
- return true;
- }
- if (kRGB_GrColorComponentFlags & swizzleComponentMask) {
- // The 'r', 'g', and/or 'b's must be mapped to 'a' according to our semantics that
- // alpha-only textures smear alpha across all four channels when read.
- return true;
- }
- }
- return false;
-}
-
-/**
- * Retrieves the matrix type from transformKey for the transform at transformIdx.
- */
-MatrixType get_matrix_type(uint32_t transformKey, int transformIdx) {
- return static_cast<MatrixType>(
- (transformKey >> (kTransformKeyBits * transformIdx)) & kMatrixTypeKeyMask);
-}
-
-/**
- * Retrieves the source coords from transformKey for the transform at transformIdx. It may not be
- * the same coordinate set as the original GrCoordTransform if the position and local coords are
- * identical for this program.
- */
-GrCoordSet get_source_coords(uint32_t transformKey, int transformIdx) {
- return (transformKey >> (kTransformKeyBits * transformIdx)) & kPositionCoords_Flag ?
- kPosition_GrCoordSet :
- kLocal_GrCoordSet;
-}
-
/**
* Retrieves the final matrix that a transform needs to apply to its source coords.
*/
////////////////////////////////////////////////////////////////////////////////
-bool GrGLProgramEffects::GenEffectMetaKey(const GrEffectStage& effectStage,
- bool useExplicitLocalCoords,
- const GrGLCaps& caps,
- GrEffectKeyBuilder* b) {
-
- uint32_t textureKey = GrGLProgramEffects::GenTextureKey(effectStage.getEffect(), caps);
- uint32_t transformKey = GrGLProgramEffects::GenTransformKey(effectStage,useExplicitLocalCoords);
- uint32_t attribKey = GrGLProgramEffects::GenAttribKey(effectStage.getEffect());
- uint32_t classID = effectStage.getEffect()->getFactory().effectClassID();
-
- // Currently we allow 16 bits for each of the above portions of the meta-key. Fail if they
- // don't fit.
- static const uint32_t kMetaKeyInvalidMask = ~((uint32_t) SK_MaxU16);
- if ((textureKey | transformKey | attribKey | classID) & kMetaKeyInvalidMask) {
- return false;
- }
-
- uint32_t* key = b->add32n(2);
- key[0] = (textureKey << 16 | transformKey);
- key[1] = (classID << 16 | attribKey);
- return true;
-}
-
-uint32_t GrGLProgramEffects::GenAttribKey(const GrEffect* effect) {
- uint32_t key = 0;
-
- const GrEffect::VertexAttribArray& vars = effect->getVertexAttribs();
- int numAttributes = vars.count();
- SkASSERT(numAttributes <= 2);
- for (int a = 0; a < numAttributes; ++a) {
- uint32_t value = 1 << a;
- key |= value;
- }
- return key;
-}
-
-uint32_t GrGLProgramEffects::GenTransformKey(const GrEffectStage& effectStage,
- bool useExplicitLocalCoords) {
- uint32_t totalKey = 0;
- int numTransforms = effectStage.getEffect()->numTransforms();
- for (int t = 0; t < numTransforms; ++t) {
- uint32_t key = 0;
- const GrCoordTransform& coordTransform = effectStage.getEffect()->coordTransform(t);
- SkMatrix::TypeMask type0 = coordTransform.getMatrix().getType();
- SkMatrix::TypeMask type1 = SkMatrix::kIdentity_Mask;
- if (kLocal_GrCoordSet == coordTransform.sourceCoords() && !useExplicitLocalCoords) {
- type1 = effectStage.getCoordChangeMatrix().getType();
- } else if (kPosition_GrCoordSet == coordTransform.sourceCoords() && useExplicitLocalCoords) {
- // We only make the key indicate that device coords are referenced when the local coords
- // are not actually determined by positions. Otherwise the local coords var and position
- // var are identical.
- key |= kPositionCoords_Flag;
- }
-
- int combinedTypes = type0 | type1;
-
- if (SkMatrix::kPerspective_Mask & combinedTypes) {
- key |= kGeneral_MatrixType;
- } else {
- key |= kNoPersp_MatrixType;
- }
- key <<= kTransformKeyBits * t;
- SkASSERT(0 == (totalKey & key)); // keys for each transform ought not to overlap
- totalKey |= key;
- }
- return totalKey;
-}
-
-uint32_t GrGLProgramEffects::GenTextureKey(const GrEffect* effect, const GrGLCaps& caps) {
- uint32_t key = 0;
- int numTextures = effect->numTextures();
- for (int t = 0; t < numTextures; ++t) {
- const GrTextureAccess& access = effect->textureAccess(t);
- uint32_t configComponentMask = GrPixelConfigComponentMask(access.getTexture()->config());
- if (swizzle_requires_alpha_remapping(caps, configComponentMask, access.swizzleMask())) {
- key |= 1 << t;
- }
- }
- return key;
-}
-
GrGLProgramEffects::~GrGLProgramEffects() {
int numEffects = fGLEffects.count();
for (int e = 0; e < numEffects; ++e) {
}
}
-void GrGLProgramEffects::emitSamplers(GrGLProgramBuilder* builder,
- const GrEffect& effect,
- TextureSamplerArray* outSamplers) {
- SkTArray<Sampler, true>& samplers = fSamplers.push_back();
- int numTextures = effect.numTextures();
- samplers.push_back_n(numTextures);
- SkString name;
- for (int t = 0; t < numTextures; ++t) {
- name.printf("Sampler%d", t);
- samplers[t].fUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
- kSampler2D_GrSLType,
- name.c_str());
- SkNEW_APPEND_TO_TARRAY(outSamplers, TextureSampler,
- (samplers[t].fUniform, effect.textureAccess(t)));
- }
-}
-
void GrGLProgramEffects::initSamplers(const GrGLProgramDataManager& programResourceManager, int* texUnitIdx) {
int numEffects = fGLEffects.count();
SkASSERT(numEffects == fSamplers.count());
////////////////////////////////////////////////////////////////////////////////
-void GrGLVertexProgramEffects::emitEffect(GrGLFullProgramBuilder* builder,
- const GrEffectStage& stage,
- const GrEffectKey& key,
- const char* outColor,
- const char* inColor,
- int stageIndex) {
- const GrEffect& effect = *stage.getEffect();
- SkSTArray<2, TransformedCoords> coords(effect.numTransforms());
- SkSTArray<4, TextureSampler> samplers(effect.numTextures());
-
- GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
- GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
- vsBuilder->emitAttributes(stage);
- this->emitTransforms(builder, stage, &coords);
- this->emitSamplers(builder, effect, &samplers);
-
- GrGLEffect* glEffect = effect.getFactory().createGLInstance(effect);
- fGLEffects.push_back(glEffect);
-
- // Enclose custom code in a block to avoid namespace conflicts
- SkString openBrace;
- openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
- fsBuilder->codeAppend(openBrace.c_str());
- vsBuilder->codeAppend(openBrace.c_str());
-
- if (glEffect->isVertexEffect()) {
- GrGLGeometryProcessor* vertexEffect = static_cast<GrGLGeometryProcessor*>(glEffect);
- vertexEffect->emitCode(builder, effect, key, outColor, inColor, coords, samplers);
- } else {
- glEffect->emitCode(builder, effect, key, outColor, inColor, coords, samplers);
- }
-
- vsBuilder->codeAppend("\t}\n");
- fsBuilder->codeAppend("\t}\n");
-}
-
-void GrGLVertexProgramEffects::emitTransforms(GrGLFullProgramBuilder* builder,
- const GrEffectStage& effectStage,
- TransformedCoordsArray* outCoords) {
- SkTArray<Transform, true>& transforms = fTransforms.push_back();
- uint32_t totalKey = GenTransformKey(effectStage, fHasExplicitLocalCoords);
- int numTransforms = effectStage.getEffect()->numTransforms();
- transforms.push_back_n(numTransforms);
-
- SkTArray<PathTransform, true>* pathTransforms = NULL;
- const GrGLCaps* glCaps = builder->ctxInfo().caps();
- if (glCaps->pathRenderingSupport() &&
- builder->gpu()->glPathRendering()->texturingMode() ==
- GrGLPathRendering::SeparableShaders_TexturingMode) {
- pathTransforms = &fPathTransforms.push_back();
- pathTransforms->push_back_n(numTransforms);
- }
-
- for (int t = 0; t < numTransforms; t++) {
- GrSLType varyingType = kVoid_GrSLType;
- const char* uniName;
- switch (get_matrix_type(totalKey, t)) {
- case kNoPersp_MatrixType:
- uniName = "StageMatrix";
- varyingType = kVec2f_GrSLType;
- break;
- case kGeneral_MatrixType:
- uniName = "StageMatrix";
- varyingType = kVec3f_GrSLType;
- break;
- default:
- SkFAIL("Unexpected key.");
- }
- SkString suffixedUniName;
- if (0 != t) {
- suffixedUniName.append(uniName);
- suffixedUniName.appendf("_%i", t);
- uniName = suffixedUniName.c_str();
- }
- transforms[t].fHandle = builder->addUniform(GrGLProgramBuilder::kVertex_Visibility,
- kMat33f_GrSLType,
- uniName,
- &uniName);
-
- const char* varyingName = "MatrixCoord";
- SkString suffixedVaryingName;
- if (0 != t) {
- suffixedVaryingName.append(varyingName);
- suffixedVaryingName.appendf("_%i", t);
- varyingName = suffixedVaryingName.c_str();
- }
- const char* vsVaryingName;
- const char* fsVaryingName;
- GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
- if (pathTransforms) {
- (*pathTransforms)[t].fHandle =
- builder->addSeparableVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
- (*pathTransforms)[t].fType = varyingType;
- } else {
- builder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
- }
-
- const GrGLShaderVar& coords = kPosition_GrCoordSet == get_source_coords(totalKey, t) ?
- vsBuilder->positionAttribute() :
- vsBuilder->localCoordsAttribute();
- // varying = matrix * coords (logically)
- SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
- if (kVec2f_GrSLType == varyingType) {
- vsBuilder->codeAppendf("\t%s = (%s * vec3(%s, 1)).xy;\n",
- vsVaryingName, uniName, coords.c_str());
- } else {
- vsBuilder->codeAppendf("\t%s = %s * vec3(%s, 1);\n",
- vsVaryingName, uniName, coords.c_str());
- }
- SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords,
- (SkString(fsVaryingName), varyingType));
- }
-}
-
void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
GrGpu::DrawType drawType,
const GrGLProgramDataManager& programDataManager,
}
}
-void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
- GrGpu::DrawType drawType,
- const GrGLProgramDataManager& programDataManager,
- const GrEffectStage* effectStage) {
- SkASSERT(1 == fTransforms.count());
- SkASSERT(1 == fSamplers.count());
- SkASSERT(1 == fGLEffects.count());
- const GrEffect& effect = *effectStage->getEffect();
- fGLEffects[0]->setData(programDataManager, effect);
- if (GrGpu::IsPathRenderingDrawType(drawType)) {
- this->setPathTransformData(gpu, programDataManager, *effectStage, 0);
- } else {
- this->setTransformData(gpu, programDataManager, *effectStage, 0);
- }
-
- this->bindTextures(gpu, effect, 0);
-}
-
void GrGLVertexProgramEffects::setTransformData(GrGpuGL* gpu,
const GrGLProgramDataManager& pdman,
const GrEffectStage& effectStage,
}
}
-GrGLVertexProgramEffectsBuilder::GrGLVertexProgramEffectsBuilder(GrGLFullProgramBuilder* builder,
- int reserveCount)
- : fBuilder(builder)
- , fProgramEffects(SkNEW_ARGS(GrGLVertexProgramEffects,
- (reserveCount,
- fBuilder->getVertexShaderBuilder()->hasExplicitLocalCoords()))) {
-}
-void GrGLVertexProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
- const GrEffectKey& key,
- const char* outColor,
- const char* inColor,
- int stageIndex) {
- SkASSERT(fProgramEffects.get());
- fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex);
-}
-
////////////////////////////////////////////////////////////////////////////////
-void GrGLPathTexGenProgramEffects::emitEffect(GrGLFragmentOnlyProgramBuilder* builder,
- const GrEffectStage& stage,
- const GrEffectKey& key,
- const char* outColor,
- const char* inColor,
- int stageIndex) {
- const GrEffect& effect = *stage.getEffect();
- SkSTArray<2, TransformedCoords> coords(effect.numTransforms());
- SkSTArray<4, TextureSampler> samplers(effect.numTextures());
-
- SkASSERT(0 == effect.getVertexAttribs().count());
- this->setupPathTexGen(builder, stage, &coords);
- this->emitSamplers(builder, effect, &samplers);
-
- GrGLEffect* glEffect = effect.getFactory().createGLInstance(effect);
- fGLEffects.push_back(glEffect);
-
- GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
- // Enclose custom code in a block to avoid namespace conflicts
- SkString openBrace;
- openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
- fsBuilder->codeAppend(openBrace.c_str());
-
- SkASSERT(!glEffect->isVertexEffect());
- glEffect->emitCode(builder, effect, key, outColor, inColor, coords, samplers);
-
- fsBuilder->codeAppend("\t}\n");
-}
-
-void GrGLPathTexGenProgramEffects::setupPathTexGen(GrGLFragmentOnlyProgramBuilder* builder,
- const GrEffectStage& effectStage,
- TransformedCoordsArray* outCoords) {
- int numTransforms = effectStage.getEffect()->numTransforms();
- uint32_t totalKey = GenTransformKey(effectStage, false);
- int texCoordIndex = builder->addTexCoordSets(numTransforms);
- SkNEW_APPEND_TO_TARRAY(&fTransforms, Transforms, (totalKey, texCoordIndex));
- SkString name;
- for (int t = 0; t < numTransforms; ++t) {
- GrSLType type = kGeneral_MatrixType == get_matrix_type(totalKey, t) ?
- kVec3f_GrSLType :
- kVec2f_GrSLType;
- name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++);
- SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords, (name, type));
- }
-}
-
void GrGLPathTexGenProgramEffects::setData(GrGpuGL* gpu,
GrGpu::DrawType,
const GrGLProgramDataManager& pdman,
void GrGLPathTexGenProgramEffects::setPathTexGenState(GrGpuGL* gpu,
const GrEffectStage& effectStage,
int effectIdx) {
- uint32_t totalKey = fTransforms[effectIdx].fTransformKey;
int texCoordIndex = fTransforms[effectIdx].fTexCoordIndex;
int numTransforms = effectStage.getEffect()->numTransforms();
for (int t = 0; t < numTransforms; ++t) {
- switch (get_matrix_type(totalKey, t)) {
- case kNoPersp_MatrixType: {
- const SkMatrix& transform = get_transform_matrix(effectStage, false, t);
- gpu->glPathRendering()->enablePathTexGen(
- texCoordIndex++,
- GrGLPathRendering::kST_PathTexGenComponents,
- transform);
- break;
- }
- case kGeneral_MatrixType: {
- const SkMatrix& transform = get_transform_matrix(effectStage, false, t);
- gpu->glPathRendering()->enablePathTexGen(
- texCoordIndex++,
- GrGLPathRendering::kSTR_PathTexGenComponents,
- transform);
- break;
- }
- default:
- SkFAIL("Unexpected matrixs type.");
+ const SkMatrix& transform = get_transform_matrix(effectStage, false, t);
+ GrGLPathRendering::PathTexGenComponents components =
+ GrGLPathRendering::kST_PathTexGenComponents;
+ if (effectStage.isPerspectiveCoordTransform(t, false)) {
+ components = GrGLPathRendering::kSTR_PathTexGenComponents;
}
+ gpu->glPathRendering()->enablePathTexGen(texCoordIndex++, components, transform);
}
}
-
-GrGLPathTexGenProgramEffectsBuilder::GrGLPathTexGenProgramEffectsBuilder(
- GrGLFragmentOnlyProgramBuilder* builder,
- int reserveCount)
- : fBuilder(builder)
- , fProgramEffects(SkNEW_ARGS(GrGLPathTexGenProgramEffects, (reserveCount))) {
-}
-void GrGLPathTexGenProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
- const GrEffectKey& key,
- const char* outColor,
- const char* inColor,
- int stageIndex) {
- SkASSERT(fProgramEffects.get());
- fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex);
-}
-
typedef GrGLProgramDataManager::UniformHandle UniformHandle;
typedef GrGLProgramDataManager::VaryingHandle VaryingHandle;
- /**
- * This class emits some of the code inserted into the shaders for an effect. The code it
- * creates may be dependent on properties of the effect that the effect itself doesn't use
- * in its key (e.g. the pixel format of textures used). So this class inserts a meta-key for
- * every effect using this function. It is also responsible for inserting the effect's class ID
- * which must be different for every GrEffect subclass. It can fail if an effect uses too many
- * textures, attributes, etc for the space allotted in the meta-key.
- */
- static bool GenEffectMetaKey(const GrEffectStage&,
- bool,
- const GrGLCaps&,
- GrEffectKeyBuilder*);
-
virtual ~GrGLProgramEffects();
/**
const GrGLProgramDataManager&,
const GrEffectStage* effectStages[]) = 0;
- virtual void setData(GrGpuGL*,
- GrGpu::DrawType,
- const GrGLProgramDataManager&,
- const GrEffectStage* effectStages) { SkFAIL("DO NOT USE"); }
-
- void addEffect(GrGLEffect* effect) { fGLEffects.push_back(effect); }
-
- /**
- * Passed to GrGLEffects so they can add transformed coordinates to their shader code.
- */
- class TransformedCoords {
- public:
- TransformedCoords(const SkString& name, GrSLType type)
- : fName(name), fType(type) {
- }
-
- const char* c_str() const { return fName.c_str(); }
- GrSLType type() const { return fType; }
- const SkString& getName() const { return fName; }
-
- private:
- SkString fName;
- GrSLType fType;
- };
-
- typedef SkTArray<TransformedCoords> TransformedCoordsArray;
-
- /**
- * Passed to GrGLEffects so they can add texture reads to their shader code.
- */
- class TextureSampler {
- public:
- TextureSampler(UniformHandle uniform, const GrTextureAccess& access)
- : fSamplerUniform(uniform)
- , fConfigComponentMask(GrPixelConfigComponentMask(access.getTexture()->config())) {
- SkASSERT(0 != fConfigComponentMask);
- memcpy(fSwizzle, access.getSwizzle(), 5);
- }
-
- UniformHandle samplerUniform() const { return fSamplerUniform; }
- // bitfield of GrColorComponentFlags present in the texture's config.
- uint32_t configComponentMask() const { return fConfigComponentMask; }
- const char* swizzle() const { return fSwizzle; }
-
- private:
- UniformHandle fSamplerUniform;
- uint32_t fConfigComponentMask;
- char fSwizzle[5];
- };
-
- typedef SkTArray<TextureSampler> TextureSamplerArray;
-
protected:
-
- /**
- * Helpers for GenEffectMetaKey.
- */
- static uint32_t GenAttribKey(const GrEffect*);
- static uint32_t GenTransformKey(const GrEffectStage&, bool useExplicitLocalCoords);
- static uint32_t GenTextureKey(const GrEffect*, const GrGLCaps&);
-
GrGLProgramEffects(int reserveCount)
: fGLEffects(reserveCount)
, fSamplers(reserveCount) {
}
/**
- * Helper for emitEffect() in a subclasses. Emits uniforms for an effect's texture accesses and
- * appends the necessary data to the TextureSamplerArray* object so effects can add texture
- * lookups to their code. This method is only meant to be called during the construction phase.
- */
- void emitSamplers(GrGLProgramBuilder*, const GrEffect&, TextureSamplerArray*);
-
- /**
* Helper for setData(). Binds all the textures for an effect.
*/
void bindTextures(GrGpuGL*, const GrEffect&, int effectIdx);
int fTextureUnit;
};
+ /*
+ * Helpers for shader builders to build up program effects objects alongside shader code
+ */
+ void addEffect(GrGLEffect* effect) { fGLEffects.push_back(effect); }
+ SkTArray<Sampler, true>& addSamplers() { return fSamplers.push_back(); }
+
SkTArray<GrGLEffect*> fGLEffects;
SkTArray<SkSTArray<4, Sampler, true> > fSamplers;
private:
- typedef SkRefCnt INHERITED;
-};
+ friend class GrGLProgramBuilder;
+ friend class GrGLFullProgramBuilder;
+ friend class GrGLFragmentOnlyShaderBuilder;
-/**
- * This is an abstract base class for constructing different types of GrGLProgramEffects objects.
- */
-class GrGLProgramEffectsBuilder {
-public:
- virtual ~GrGLProgramEffectsBuilder() { }
- /**
- * Emits the effect's shader code, and stores the necessary uniforms internally.
- */
- virtual void emitEffect(const GrEffectStage&,
- const GrEffectKey&,
- const char* outColor,
- const char* inColor,
- int stageIndex) = 0;
+ typedef SkRefCnt INHERITED;
};
////////////////////////////////////////////////////////////////////////////////
const GrGLProgramDataManager&,
const GrEffectStage* effectStages[]) SK_OVERRIDE;
- virtual void setData(GrGpuGL*,
- GrGpu::DrawType,
- const GrGLProgramDataManager&,
- const GrEffectStage* effectStages) SK_OVERRIDE;
-
private:
- friend class GrGLFullProgramBuilder;
-
GrGLVertexProgramEffects(int reserveCount, bool explicitLocalCoords)
: INHERITED(reserveCount)
, fTransforms(reserveCount)
, fHasExplicitLocalCoords(explicitLocalCoords) {
}
- /**
- * This method is meant to only be called during the construction phase.
- */
- void emitEffect(GrGLFullProgramBuilder*,
- const GrEffectStage&,
- const GrEffectKey&,
- const char* outColor,
- const char* inColor,
- int stageIndex);
-
- /**
- * Helper for emitEffect(). Emits any attributes an effect may have.
- */
- void emitAttributes(GrGLFullProgramBuilder*, const GrEffectStage&);
-
- /**
- * Helper for emitEffect(). Emits code to implement an effect's coord transforms in the VS.
- * Varyings are added as an outputs of the VS and inputs to the FS. The varyings may be either a
- * vec2f or vec3f depending upon whether perspective interpolation is required or not. The names
- * of the varyings in the VS and FS as well their types are appended to the
- * TransformedCoordsArray* object, which is in turn passed to the effect's emitCode() function.
- */
- void emitTransforms(GrGLFullProgramBuilder*,
- const GrEffectStage&,
- TransformedCoordsArray*);
-
- /**
- * Helper for setData(). Sets all the transform matrices for an effect.
- */
- void setTransformData(GrGpuGL* gpu, const GrGLProgramDataManager&, const GrEffectStage&,
- int effectIdx);
- void setPathTransformData(GrGpuGL* gpu, const GrGLProgramDataManager&, const GrEffectStage&,
- int effectIdx);
struct Transform {
Transform() { fCurrentValue = SkMatrix::InvalidMatrix(); }
GrSLType fType;
};
+ /*
+ * These functions are used by the builders to build up program effects along side the shader
+ * code itself
+ */
+ SkSTArray<2, Transform, true>& addTransforms() { return fTransforms.push_back(); }
+ SkTArray<PathTransform, true>& addPathTransforms() { return fPathTransforms.push_back(); }
+
+ /**
+ * Helper for setData(). Sets all the transform matrices for an effect.
+ */
+ void setTransformData(GrGpuGL* gpu, const GrGLProgramDataManager&, const GrEffectStage&,
+ int effectIdx);
+ void setPathTransformData(GrGpuGL* gpu, const GrGLProgramDataManager&, const GrEffectStage&,
+ int effectIdx);
+
SkTArray<SkSTArray<2, Transform, true> > fTransforms;
SkTArray<SkTArray<PathTransform, true> > fPathTransforms;
bool fHasExplicitLocalCoords;
- friend class GrGLVertexProgramEffectsBuilder;
+ friend class GrGLFullProgramBuilder;
typedef GrGLProgramEffects INHERITED;
};
-/**
- * This class is used to construct a GrGLVertexProgramEffects* object.
- */
-class GrGLVertexProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
-public:
- GrGLVertexProgramEffectsBuilder(GrGLFullProgramBuilder*, int reserveCount);
- virtual ~GrGLVertexProgramEffectsBuilder() { }
- virtual void emitEffect(const GrEffectStage&,
- const GrEffectKey&,
- const char* outColor,
- const char* inColor,
- int stageIndex) SK_OVERRIDE;
- /**
- * Finalizes the building process and returns the effect array. After this call, the builder
- * becomes invalid.
- */
- GrGLProgramEffects* finish() { return fProgramEffects.detach(); }
-private:
- GrGLFullProgramBuilder* fBuilder;
- SkAutoTDelete<GrGLVertexProgramEffects> fProgramEffects;
- typedef GrGLProgramEffectsBuilder INHERITED;
-};
-
////////////////////////////////////////////////////////////////////////////////
/**
const GrEffectStage* effectStages[]) SK_OVERRIDE;
private:
- friend class GrGLFragmentOnlyProgramBuilder;
-
GrGLPathTexGenProgramEffects(int reserveCount)
: INHERITED(reserveCount)
, fTransforms(reserveCount) {
}
/**
- * This method is meant to only be called during the construction phase.
- */
- void emitEffect(GrGLFragmentOnlyProgramBuilder*,
- const GrEffectStage&,
- const GrEffectKey&,
- const char* outColor,
- const char* inColor,
- int stageIndex);
-
- /**
- * Helper for emitEffect(). Allocates texture units from the builder for each transform in an
- * effect. The transforms all use adjacent texture units. They either use two or three of the
- * coordinates at a given texture unit, depending on if they need perspective interpolation.
- * The expressions to access the transformed coords (i.e. 'vec2(gl_TexCoord[0])') as well as the
- * types are appended to the TransformedCoordsArray* object, which is in turn passed to the
- * effect's emitCode() function.
- */
- void setupPathTexGen(GrGLFragmentOnlyProgramBuilder*,
- const GrEffectStage&,
- TransformedCoordsArray*);
-
- /**
* Helper for setData(). Sets the PathTexGen state for each transform in an effect.
*/
void setPathTexGenState(GrGpuGL*, const GrEffectStage&, int effectIdx);
struct Transforms {
- Transforms(uint32_t transformKey, int texCoordIndex)
- : fTransformKey(transformKey), fTexCoordIndex(texCoordIndex) {}
- uint32_t fTransformKey;
- int fTexCoordIndex;
+ Transforms(int texCoordIndex)
+ : fTexCoordIndex(texCoordIndex) {}
+ int fTexCoordIndex;
};
+ /*
+ * Helper for fragment only shader builder to build up the program effects alongside the shader
+ */
+ void addTransforms(int coordIndex) {
+ fTransforms.push_back(Transforms(coordIndex));
+ }
+
SkTArray<Transforms> fTransforms;
- friend class GrGLPathTexGenProgramEffectsBuilder;
- typedef GrGLProgramEffects INHERITED;
-};
+ friend class GrGLFragmentOnlyProgramBuilder;
-/**
- * This class is used to construct a GrGLPathTexGenProgramEffects* object.
- */
-class GrGLPathTexGenProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
-public:
- GrGLPathTexGenProgramEffectsBuilder(GrGLFragmentOnlyProgramBuilder*, int reserveCount);
- virtual ~GrGLPathTexGenProgramEffectsBuilder() { }
- virtual void emitEffect(const GrEffectStage&,
- const GrEffectKey&,
- const char* outColor,
- const char* inColor,
- int stageIndex) SK_OVERRIDE;
- /**
- * Finalizes the building process and returns the effect array. After this call, the builder
- * becomes invalid.
- */
- GrGLProgramEffects* finish() { return fProgramEffects.detach(); }
-private:
- GrGLFragmentOnlyProgramBuilder* fBuilder;
- SkAutoTDelete<GrGLPathTexGenProgramEffects> fProgramEffects;
- typedef GrGLProgramEffectsBuilder INHERITED;
+ typedef GrGLProgramEffects INHERITED;
};
-
#endif
return firstFreeCoordSet;
}
-GrGLProgramEffects* GrGLFragmentOnlyProgramBuilder::createAndEmitEffects(
+void
+GrGLFragmentOnlyProgramBuilder::createAndEmitEffects(const GrEffectStage* geometryProcessor,
+ const GrEffectStage* colorStages[],
+ const GrEffectStage* coverageStages[],
+ GrGLSLExpr4* inputColor,
+ GrGLSLExpr4* inputCoverage) {
+ ///////////////////////////////////////////////////////////////////////////
+ // emit the per-effect code for both color and coverage effects
+
+ EffectKeyProvider colorKeyProvider(&this->desc(), EffectKeyProvider::kColor_EffectType);
+ fColorEffects.reset(this->onCreateAndEmitEffects(colorStages,
+ this->desc().numColorEffects(),
+ colorKeyProvider,
+ inputColor));
+
+ EffectKeyProvider coverageKeyProvider(&this->desc(), EffectKeyProvider::kCoverage_EffectType);
+ fCoverageEffects.reset(this->onCreateAndEmitEffects(coverageStages,
+ this->desc().numCoverageEffects(),
+ coverageKeyProvider,
+ inputCoverage));
+}
+
+GrGLProgramEffects* GrGLFragmentOnlyProgramBuilder::onCreateAndEmitEffects(
const GrEffectStage* effectStages[], int effectCnt,
const GrGLProgramDesc::EffectKeyProvider& keyProvider, GrGLSLExpr4* inOutFSColor) {
- GrGLPathTexGenProgramEffectsBuilder pathTexGenEffectsBuilder(this,
- effectCnt);
- this->INHERITED::createAndEmitEffects(&pathTexGenEffectsBuilder,
- effectStages,
+ fProgramEffects.reset(SkNEW_ARGS(GrGLPathTexGenProgramEffects, (effectCnt)));
+ this->INHERITED::createAndEmitEffects(effectStages,
effectCnt,
keyProvider,
inOutFSColor);
- return pathTexGenEffectsBuilder.finish();
+ return fProgramEffects.detach();
+}
+
+void GrGLFragmentOnlyProgramBuilder::emitEffect(const GrEffectStage& stage,
+ const GrEffectKey& key,
+ const char* outColor,
+ const char* inColor,
+ int stageIndex) {
+ SkASSERT(fProgramEffects.get());
+ const GrEffect& effect = *stage.getEffect();
+ SkASSERT(0 == effect.getVertexAttribs().count());
+
+ SkSTArray<2, GrGLEffect::TransformedCoords> coords(effect.numTransforms());
+ SkSTArray<4, GrGLEffect::TextureSampler> samplers(effect.numTextures());
+
+ this->setupPathTexGen(stage, &coords);
+ this->emitSamplers(effect, &samplers);
+
+ GrGLEffect* glEffect = effect.getFactory().createGLInstance(effect);
+ SkASSERT(!glEffect->isVertexEffect());
+ fProgramEffects->addEffect(glEffect);
+
+ GrGLFragmentShaderBuilder* fsBuilder = this->getFragmentShaderBuilder();
+ // Enclose custom code in a block to avoid namespace conflicts
+ SkString openBrace;
+ openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
+ fsBuilder->codeAppend(openBrace.c_str());
+
+ glEffect->emitCode(this, effect, key, outColor, inColor, coords, samplers);
+
+ fsBuilder->codeAppend("\t}\n");
+}
+
+void GrGLFragmentOnlyProgramBuilder::setupPathTexGen(const GrEffectStage& effectStage,
+ GrGLEffect::TransformedCoordsArray* outCoords) {
+ int numTransforms = effectStage.getEffect()->numTransforms();
+ int texCoordIndex = this->addTexCoordSets(numTransforms);
+
+ fProgramEffects->addTransforms(texCoordIndex);
+
+ SkString name;
+ for (int t = 0; t < numTransforms; ++t) {
+ GrSLType type =
+ effectStage.isPerspectiveCoordTransform(t, false) ?
+ kVec3f_GrSLType :
+ kVec2f_GrSLType;
+
+ name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++);
+ SkNEW_APPEND_TO_TARRAY(outCoords, GrGLEffect::TransformedCoords, (name, type));
+ }
}
int addTexCoordSets(int count);
private:
- virtual void emitCodeBeforeEffects(GrGLSLExpr4* color,
- GrGLSLExpr4* coverage) SK_OVERRIDE {}
-
- virtual void emitGeometryProcessor(const GrEffectStage* geometryProcessor,
- GrGLSLExpr4* coverage) SK_OVERRIDE {
- SkASSERT(NULL == geometryProcessor);
- }
-
- virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
- int effectCnt,
- const GrGLProgramDesc::EffectKeyProvider&,
- GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;
-
- virtual void emitCodeAfterEffects() SK_OVERRIDE {}
+ virtual void createAndEmitEffects(const GrEffectStage* geometryProcessor,
+ const GrEffectStage* colorStages[],
+ const GrEffectStage* coverageStages[],
+ GrGLSLExpr4* inputColor,
+ GrGLSLExpr4* inputCoverage) SK_OVERRIDE;
+
+ GrGLProgramEffects* onCreateAndEmitEffects(const GrEffectStage* effectStages[],
+ int effectCnt,
+ const GrGLProgramDesc::EffectKeyProvider&,
+ GrGLSLExpr4* inOutFSColor);
+
+ virtual void emitEffect(const GrEffectStage& stage,
+ const GrEffectKey& key,
+ const char* outColor,
+ const char* inColor,
+ int stageIndex) SK_OVERRIDE;
+
+ /**
+ * Helper for emitEffect(). Allocates texture units from the builder for each transform in an
+ * effect. The transforms all use adjacent texture units. They either use two or three of the
+ * coordinates at a given texture unit, depending on if they need perspective interpolation.
+ * The expressions to access the transformed coords (i.e. 'vec2(gl_TexCoord[0])') as well as the
+ * types are appended to the TransformedCoordsArray* object, which is in turn passed to the
+ * effect's emitCode() function.
+ */
+ void setupPathTexGen(const GrEffectStage&, GrGLEffect::TransformedCoordsArray*);
+
+ virtual GrGLProgramEffects* getProgramEffects() SK_OVERRIDE { return fProgramEffects.get(); }
+
+ typedef GrGLProgramDesc::EffectKeyProvider EffectKeyProvider;
+
+ SkAutoTDelete<GrGLPathTexGenProgramEffects> fProgramEffects;
typedef GrGLProgramBuilder INHERITED;
};
}
SkString GrGLFragmentShaderBuilder::ensureFSCoords2D(const TransformedCoordsArray& coords, int index) {
- if (kVec3f_GrSLType != coords[index].type()) {
- SkASSERT(kVec2f_GrSLType == coords[index].type());
+ if (kVec3f_GrSLType != coords[index].getType()) {
+ SkASSERT(kVec2f_GrSLType == coords[index].getType());
return coords[index].getName();
}
*/
#include "GrGLFullProgramBuilder.h"
+#include "../GrGLGeometryProcessor.h"
#include "../GrGpuGL.h"
GrGLFullProgramBuilder::GrGLFullProgramBuilder(GrGpuGL* gpu,
, fVS(this) {
}
-void GrGLFullProgramBuilder::emitCodeBeforeEffects(GrGLSLExpr4* color,
- GrGLSLExpr4* coverage) {
- fVS.emitCodeBeforeEffects(color, coverage);
-}
+void
+GrGLFullProgramBuilder::createAndEmitEffects(const GrEffectStage* geometryProcessor,
+ const GrEffectStage* colorStages[],
+ const GrEffectStage* coverageStages[],
+ GrGLSLExpr4* inputColor,
+ GrGLSLExpr4* inputCoverage) {
+ fVS.emitCodeBeforeEffects(inputColor, inputCoverage);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // emit the per-effect code for both color and coverage effects
+
+ bool useLocalCoords = this->getVertexShaderBuilder()->hasExplicitLocalCoords();
+ EffectKeyProvider colorKeyProvider(&this->desc(), EffectKeyProvider::kColor_EffectType);
+ fColorEffects.reset(this->onCreateAndEmitEffects(colorStages,
+ this->desc().numColorEffects(),
+ colorKeyProvider,
+ inputColor));
-void GrGLFullProgramBuilder::emitGeometryProcessor(const GrEffectStage* geometryProcessor,
- GrGLSLExpr4* coverage) {
if (geometryProcessor) {
- GrGLProgramDesc::EffectKeyProvider geometryProcessorKeyProvider(
- &this->desc(), GrGLProgramDesc::EffectKeyProvider::kGeometryProcessor_EffectType);
- fGeometryProcessor.reset(this->createAndEmitEffect(
- geometryProcessor,
- geometryProcessorKeyProvider,
- coverage));
+ GrGLSLExpr4 gpInputCoverage = *inputCoverage;
+ GrGLSLExpr4 gpOutputCoverage;
+ EffectKeyProvider gpKeyProvider(&this->desc(),
+ EffectKeyProvider::kGeometryProcessor_EffectType);
+ fProgramEffects.reset(SkNEW_ARGS(GrGLVertexProgramEffects, (1, useLocalCoords)));
+ this->INHERITED::emitEffect(*geometryProcessor, 0, gpKeyProvider, &gpInputCoverage,
+ &gpOutputCoverage);
+ fGeometryProcessor.reset(fProgramEffects.detach());
+ *inputCoverage = gpOutputCoverage;
}
-}
-void GrGLFullProgramBuilder::emitCodeAfterEffects() {
- fVS.emitCodeAfterEffects();
+ EffectKeyProvider coverageKeyProvider(&this->desc(), EffectKeyProvider::kCoverage_EffectType);
+ fCoverageEffects.reset(this->onCreateAndEmitEffects(coverageStages,
+ this->desc().numCoverageEffects(),
+ coverageKeyProvider,
+ inputCoverage));
+
+ fVS.emitCodeAfterEffects();
}
void GrGLFullProgramBuilder::addVarying(GrSLType type,
return VaryingHandle::CreateFromSeparableVaryingIndex(fSeparableVaryingInfos.count() - 1);
}
-
-GrGLProgramEffects* GrGLFullProgramBuilder::createAndEmitEffects(
+GrGLProgramEffects* GrGLFullProgramBuilder::onCreateAndEmitEffects(
const GrEffectStage* effectStages[],
int effectCnt,
const GrGLProgramDesc::EffectKeyProvider& keyProvider,
GrGLSLExpr4* inOutFSColor) {
-
- GrGLVertexProgramEffectsBuilder programEffectsBuilder(this, effectCnt);
- this->INHERITED::createAndEmitEffects(&programEffectsBuilder,
- effectStages,
+ fProgramEffects.reset(SkNEW_ARGS(GrGLVertexProgramEffects,
+ (effectCnt,
+ this->getVertexShaderBuilder()->hasExplicitLocalCoords())));
+ this->INHERITED::createAndEmitEffects(effectStages,
effectCnt,
keyProvider,
inOutFSColor);
- return programEffectsBuilder.finish();
+ return fProgramEffects.detach();
}
-void GrGLFullProgramBuilder::createAndEmitEffect(GrGLProgramEffectsBuilder* programEffectsBuilder,
- const GrEffectStage* effectStages,
- const GrGLProgramDesc::EffectKeyProvider& keyProvider,
- GrGLSLExpr4* fsInOutColor) {
- GrGLSLExpr4 inColor = *fsInOutColor;
- GrGLSLExpr4 outColor;
-
- SkASSERT(effectStages && effectStages->getEffect());
- const GrEffectStage& stage = *effectStages;
+void GrGLFullProgramBuilder::emitEffect(const GrEffectStage& stage,
+ const GrEffectKey& key,
+ const char* outColor,
+ const char* inColor,
+ int stageIndex) {
+ SkASSERT(fProgramEffects.get());
+ const GrEffect& effect = *stage.getEffect();
+ SkSTArray<2, GrGLEffect::TransformedCoords> coords(effect.numTransforms());
+ SkSTArray<4, GrGLEffect::TextureSampler> samplers(effect.numTextures());
+
+ fVS.emitAttributes(stage);
+ this->emitTransforms(stage, &coords);
+ this->emitSamplers(effect, &samplers);
+
+ GrGLEffect* glEffect = effect.getFactory().createGLInstance(effect);
+ fProgramEffects->addEffect(glEffect);
+
+ // Enclose custom code in a block to avoid namespace conflicts
+ SkString openBrace;
+ openBrace.printf("{ // Stage %d: %s\n", stageIndex, glEffect->name());
+ fFS.codeAppend(openBrace.c_str());
+ fVS.codeAppend(openBrace.c_str());
+
+ if (glEffect->isVertexEffect()) {
+ GrGLGeometryProcessor* vertexEffect = static_cast<GrGLGeometryProcessor*>(glEffect);
+ vertexEffect->emitCode(this, effect, key, outColor, inColor, coords, samplers);
+ } else {
+ glEffect->emitCode(this, effect, key, outColor, inColor, coords, samplers);
+ }
- // Using scope to force ASR destructor to be triggered
- {
- CodeStage::AutoStageRestore csar(&fCodeStage, &stage);
+ fVS.codeAppend("\t}\n");
+ fFS.codeAppend("\t}\n");
+}
- if (inColor.isZeros()) {
- SkString inColorName;
+void GrGLFullProgramBuilder::emitTransforms(const GrEffectStage& effectStage,
+ GrGLEffect::TransformedCoordsArray* outCoords) {
+ SkTArray<GrGLVertexProgramEffects::Transform, true>& transforms =
+ fProgramEffects->addTransforms();
+ const GrEffect* effect = effectStage.getEffect();
+ int numTransforms = effect->numTransforms();
+ transforms.push_back_n(numTransforms);
+
+ SkTArray<GrGLVertexProgramEffects::PathTransform, true>* pathTransforms = NULL;
+ const GrGLCaps* glCaps = this->ctxInfo().caps();
+ if (glCaps->pathRenderingSupport() &&
+ this->gpu()->glPathRendering()->texturingMode() ==
+ GrGLPathRendering::SeparableShaders_TexturingMode) {
+ pathTransforms = &fProgramEffects->addPathTransforms();
+ pathTransforms->push_back_n(numTransforms);
+ }
- // Effects have no way to communicate zeros, they treat an empty string as ones.
- this->nameVariable(&inColorName, '\0', "input");
- fFS.codeAppendf("vec4 %s = %s;", inColorName.c_str(), inColor.c_str());
- inColor = inColorName;
+ for (int t = 0; t < numTransforms; t++) {
+ const char* uniName = "StageMatrix";
+ GrSLType varyingType =
+ effectStage.isPerspectiveCoordTransform(t, fVS.hasExplicitLocalCoords()) ?
+ kVec3f_GrSLType :
+ kVec2f_GrSLType;
+
+ SkString suffixedUniName;
+ if (0 != t) {
+ suffixedUniName.append(uniName);
+ suffixedUniName.appendf("_%i", t);
+ uniName = suffixedUniName.c_str();
+ }
+ transforms[t].fHandle = this->addUniform(GrGLProgramBuilder::kVertex_Visibility,
+ kMat33f_GrSLType,
+ uniName,
+ &uniName);
+
+ const char* varyingName = "MatrixCoord";
+ SkString suffixedVaryingName;
+ if (0 != t) {
+ suffixedVaryingName.append(varyingName);
+ suffixedVaryingName.appendf("_%i", t);
+ varyingName = suffixedVaryingName.c_str();
+ }
+ const char* vsVaryingName;
+ const char* fsVaryingName;
+ if (pathTransforms) {
+ (*pathTransforms)[t].fHandle =
+ this->addSeparableVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
+ (*pathTransforms)[t].fType = varyingType;
+ } else {
+ this->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
}
- // create var to hold stage result
- SkString outColorName;
- this->nameVariable(&outColorName, '\0', "output");
- fFS.codeAppendf("vec4 %s;", outColorName.c_str());
- outColor = outColorName;
-
-
- programEffectsBuilder->emitEffect(stage,
- keyProvider.get(0),
- outColor.c_str(),
- inColor.isOnes() ? NULL : inColor.c_str(),
- fCodeStage.stageIndex());
+ const GrGLShaderVar& coords =
+ kPosition_GrCoordSet == effect->coordTransform(t).sourceCoords() ?
+ fVS.positionAttribute() :
+ fVS.localCoordsAttribute();
+ // varying = matrix * coords (logically)
+ SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
+ if (kVec2f_GrSLType == varyingType) {
+ fVS.codeAppendf("%s = (%s * vec3(%s, 1)).xy;",
+ vsVaryingName, uniName, coords.c_str());
+ } else {
+ fVS.codeAppendf("%s = %s * vec3(%s, 1);",
+ vsVaryingName, uniName, coords.c_str());
+ }
+ SkNEW_APPEND_TO_TARRAY(outCoords, GrGLEffect::TransformedCoords,
+ (SkString(fsVaryingName), varyingType));
}
-
- *fsInOutColor = outColor;
-}
-
-GrGLProgramEffects* GrGLFullProgramBuilder::createAndEmitEffect(
- const GrEffectStage* geometryProcessor,
- const GrGLProgramDesc::EffectKeyProvider& keyProvider,
- GrGLSLExpr4* inOutFSColor) {
-
- GrGLVertexProgramEffectsBuilder programEffectsBuilder(this, 1);
- this->createAndEmitEffect(&programEffectsBuilder, geometryProcessor, keyProvider, inOutFSColor);
- return programEffectsBuilder.finish();
}
bool GrGLFullProgramBuilder::compileAndAttachShaders(GrGLuint programId,
#include "GrGLProgramBuilder.h"
+class GrGLVertexProgramEffects;
+
class GrGLFullProgramBuilder : public GrGLProgramBuilder {
public:
GrGLFullProgramBuilder(GrGpuGL*, const GrGLProgramDesc&);
GrGLVertexShaderBuilder* getVertexShaderBuilder() { return &fVS; }
private:
- virtual void emitCodeBeforeEffects(GrGLSLExpr4* color,
- GrGLSLExpr4* coverage) SK_OVERRIDE;
-
- virtual void emitGeometryProcessor(const GrEffectStage* geometryProcessor,
- GrGLSLExpr4* coverage) SK_OVERRIDE;
-
- virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
- int effectCnt,
- const GrGLProgramDesc::EffectKeyProvider&,
- GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;
-
- /*
- * These functions are temporary and will eventually operate not on effects but on
- * geometry processors
+ virtual void createAndEmitEffects(const GrEffectStage* geometryProcessor,
+ const GrEffectStage* colorStages[],
+ const GrEffectStage* coverageStages[],
+ GrGLSLExpr4* inputColor,
+ GrGLSLExpr4* inputCoverage) SK_OVERRIDE;
+
+ GrGLProgramEffects* onCreateAndEmitEffects(const GrEffectStage* effectStages[],
+ int effectCnt,
+ const GrGLProgramDesc::EffectKeyProvider&,
+ GrGLSLExpr4* inOutFSColor);
+
+ virtual void emitEffect(const GrEffectStage& stage,
+ const GrEffectKey& key,
+ const char* outColor,
+ const char* inColor,
+ int stageIndex) SK_OVERRIDE;
+
+ /**
+ * Helper for emitEffect(). Emits code to implement an effect's coord transforms in the VS.
+ * Varyings are added as an outputs of the VS and inputs to the FS. The varyings may be either a
+ * vec2f or vec3f depending upon whether perspective interpolation is required or not. The names
+ * of the varyings in the VS and FS as well their types are appended to the
+ * TransformedCoordsArray* object, which is in turn passed to the effect's emitCode() function.
*/
- void createAndEmitEffect(GrGLProgramEffectsBuilder*,
- const GrEffectStage* effectStage,
- const GrGLProgramDesc::EffectKeyProvider&,
- GrGLSLExpr4* inOutFSColor);
-
- GrGLProgramEffects* createAndEmitEffect(const GrEffectStage* geometryProcessor,
- const GrGLProgramDesc::EffectKeyProvider&,
- GrGLSLExpr4* inOutFSColor);
-
- virtual void emitCodeAfterEffects() SK_OVERRIDE;
+ void emitTransforms(const GrEffectStage& effectStage,
+ GrGLEffect::TransformedCoordsArray* outCoords);
virtual bool compileAndAttachShaders(GrGLuint programId,
SkTDArray<GrGLuint>* shaderIds) const SK_OVERRIDE;
virtual void bindProgramLocations(GrGLuint programId) SK_OVERRIDE;
+ virtual GrGLProgramEffects* getProgramEffects() SK_OVERRIDE { return fProgramEffects.get(); }
+
+ typedef GrGLProgramDesc::EffectKeyProvider EffectKeyProvider;
+
GrGLGeometryShaderBuilder fGS;
GrGLVertexShaderBuilder fVS;
+ SkAutoTDelete<GrGLVertexProgramEffects> fProgramEffects;
typedef GrGLProgramBuilder INHERITED;
};
inputCoverage = GrGLSLExpr4(1);
}
- this->emitCodeBeforeEffects(&inputColor, &inputCoverage);
-
- ///////////////////////////////////////////////////////////////////////////
- // emit the per-effect code for both color and coverage effects
-
- GrGLProgramDesc::EffectKeyProvider colorKeyProvider(
- &this->desc(), GrGLProgramDesc::EffectKeyProvider::kColor_EffectType);
- fColorEffects.reset(this->createAndEmitEffects(colorStages,
- this->desc().numColorEffects(),
- colorKeyProvider,
- &inputColor));
-
- this->emitGeometryProcessor(geometryProcessor, &inputCoverage);
-
- GrGLProgramDesc::EffectKeyProvider coverageKeyProvider(
- &this->desc(), GrGLProgramDesc::EffectKeyProvider::kCoverage_EffectType);
- fCoverageEffects.reset(this->createAndEmitEffects(coverageStages,
- this->desc().numCoverageEffects(),
- coverageKeyProvider,
- &inputCoverage));
-
- this->emitCodeAfterEffects();
+ // Subclasses drive effect emitting
+ this->createAndEmitEffects(geometryProcessor, colorStages, coverageStages, &inputColor,
+ &inputCoverage);
fFS.emitCodeAfterEffects(inputColor, inputCoverage);
}
}
-void GrGLProgramBuilder::createAndEmitEffects(GrGLProgramEffectsBuilder* programEffectsBuilder,
- const GrEffectStage* effectStages[],
+void GrGLProgramBuilder::createAndEmitEffects(const GrEffectStage* effectStages[],
int effectCnt,
const GrGLProgramDesc::EffectKeyProvider& keyProvider,
GrGLSLExpr4* fsInOutColor) {
GrGLSLExpr4 outColor;
for (int e = 0; e < effectCnt; ++e) {
- SkASSERT(effectStages[e] && effectStages[e]->getEffect());
- const GrEffectStage& stage = *effectStages[e];
-
- CodeStage::AutoStageRestore csar(&fCodeStage, &stage);
-
- if (inColor.isZeros()) {
- SkString inColorName;
+ // calls into the subclass to emit the actual effect into the program effect object
+ this->emitEffect(*effectStages[e], e, keyProvider, &inColor, &outColor);
+ effectEmitted = true;
+ }
- // Effects have no way to communicate zeros, they treat an empty string as ones.
- this->nameVariable(&inColorName, '\0', "input");
- fFS.codeAppendf("\tvec4 %s = %s;\n", inColorName.c_str(), inColor.c_str());
- inColor = inColorName;
- }
+ if (effectEmitted) {
+ *fsInOutColor = outColor;
+ }
+}
- // create var to hold stage result
- SkString outColorName;
- this->nameVariable(&outColorName, '\0', "output");
- fFS.codeAppendf("\tvec4 %s;\n", outColorName.c_str());
- outColor = outColorName;
+void GrGLProgramBuilder::emitEffect(const GrEffectStage& effectStage,
+ int effectIndex,
+ const GrGLProgramDesc::EffectKeyProvider& keyProvider,
+ GrGLSLExpr4* inColor,
+ GrGLSLExpr4* outColor) {
+ SkASSERT(effectStage.getEffect());
+ CodeStage::AutoStageRestore csar(&fCodeStage, &effectStage);
+
+ if (inColor->isZeros()) {
+ SkString inColorName;
+
+ // Effects have no way to communicate zeros, they treat an empty string as ones.
+ this->nameVariable(&inColorName, '\0', "input");
+ fFS.codeAppendf("\tvec4 %s = %s;\n", inColorName.c_str(), inColor->c_str());
+ *inColor = inColorName;
+ }
+ // create var to hold stage result
+ SkString outColorName;
+ this->nameVariable(&outColorName, '\0', "output");
+ fFS.codeAppendf("\tvec4 %s;\n", outColorName.c_str());
+ *outColor = outColorName;
- programEffectsBuilder->emitEffect(stage,
- keyProvider.get(e),
- outColor.c_str(),
- inColor.isOnes() ? NULL : inColor.c_str(),
- fCodeStage.stageIndex());
+ this->emitEffect(effectStage, keyProvider.get(effectIndex), outColor->c_str(),
+ inColor->isOnes() ? NULL : inColor->c_str(), fCodeStage.stageIndex());
- inColor = outColor;
- effectEmitted = true;
- }
+ *inColor = *outColor;
+}
- if (effectEmitted) {
- *fsInOutColor = outColor;
+void GrGLProgramBuilder::emitSamplers(const GrEffect& effect,
+ GrGLEffect::TextureSamplerArray* outSamplers) {
+ SkTArray<GrGLProgramEffects::Sampler, true>& samplers =
+ this->getProgramEffects()->addSamplers();
+ int numTextures = effect.numTextures();
+ samplers.push_back_n(numTextures);
+ SkString name;
+ for (int t = 0; t < numTextures; ++t) {
+ name.printf("Sampler%d", t);
+ samplers[t].fUniform = this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+ kSampler2D_GrSLType,
+ name.c_str());
+ SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLEffect::TextureSampler,
+ (samplers[t].fUniform, effect.textureAccess(t)));
}
}
const GrGLProgramDesc& desc() const { return fDesc; }
// Helper for emitEffects().
- void createAndEmitEffects(GrGLProgramEffectsBuilder*,
- const GrEffectStage* effectStages[],
+ void createAndEmitEffects(const GrEffectStage* effectStages[],
int effectCnt,
const GrGLProgramDesc::EffectKeyProvider&,
GrGLSLExpr4* inOutFSColor);
+ /*
+ * A helper function called to emit the geometry processor as well as individual coverage
+ * and color stages. this will call into subclasses emit effect
+ */
+ void emitEffect(const GrEffectStage& effectStage,
+ int effectIndex,
+ const GrGLProgramDesc::EffectKeyProvider& keyProvider,
+ GrGLSLExpr4* inColor,
+ GrGLSLExpr4* outColor);
+
+ /**
+ * Helper for emitEffect() in subclasses. Emits uniforms for an effect's texture accesses and
+ * appends the necessary data to the TextureSamplerArray* object so effects can add texture
+ * lookups to their code. This method is only meant to be called during the construction phase.
+ */
+ void emitSamplers(const GrEffect& effect, GrGLEffect::TextureSamplerArray* outSamplers);
+
// Generates a name for a variable. The generated string will be name prefixed by the prefix
// char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
// generating stage code.
void appendDecls(const VarArray&, SkString*) const;
void appendUniformDecls(ShaderVisibility, SkString*) const;
- SkAutoTUnref<GrGLProgramEffects> fGeometryProcessor;
- SkAutoTUnref<GrGLProgramEffects> fColorEffects;
- SkAutoTUnref<GrGLProgramEffects> fCoverageEffects;
- BuiltinUniformHandles fUniformHandles;
- bool fFragOnly;
- int fTexCoordSetCnt;
- GrGLuint fProgramID;
- GrGLFragmentShaderBuilder fFS;
- SeparableVaryingInfoArray fSeparableVaryingInfos;
-
class CodeStage : SkNoncopyable {
public:
CodeStage() : fNextIndex(0), fCurrentIndex(-1), fEffectStage(NULL) {}
int fNextIndex;
int fCurrentIndex;
const GrEffectStage* fEffectStage;
- } fCodeStage;
-
-private:
+ };
- /**
- * The base class will emit the fragment code that precedes the per-effect code and then call
- * this function. The subclass can use it to insert additional fragment code that should
- * execute before the effects' code and/or emit other shaders (e.g. geometry, vertex).
- *
- * The subclass can modify the initial color or coverage
- */
- virtual void emitCodeBeforeEffects(GrGLSLExpr4* color,
- GrGLSLExpr4* coverage) = 0;
+ CodeStage fCodeStage;
+ SkAutoTUnref<GrGLProgramEffects> fGeometryProcessor;
+ SkAutoTUnref<GrGLProgramEffects> fColorEffects;
+ SkAutoTUnref<GrGLProgramEffects> fCoverageEffects;
+ BuiltinUniformHandles fUniformHandles;
+ bool fFragOnly;
+ int fTexCoordSetCnt;
+ GrGLuint fProgramID;
+ GrGLFragmentShaderBuilder fFS;
+ SeparableVaryingInfoArray fSeparableVaryingInfos;
+private:
+ virtual void createAndEmitEffects(const GrEffectStage* geometryProcessor,
+ const GrEffectStage* colorStages[],
+ const GrEffectStage* coverageStages[],
+ GrGLSLExpr4* inputColor,
+ GrGLSLExpr4* inputCoverage) = 0;
/*
- * Full shader builder needs to emit code after the color stages and before the coverage stages
+ * Subclasses override emitEffect below to emit data and code for a specific single effect
*/
- virtual void emitGeometryProcessor(const GrEffectStage* geometryProcessor,
- GrGLSLExpr4* coverage) = 0;
+ virtual void emitEffect(const GrEffectStage&,
+ const GrEffectKey&,
+ const char* outColor,
+ const char* inColor,
+ int stageIndex) = 0;
- /**
- * Adds code for effects and returns a GrGLProgramEffects* object. The caller is responsible for
- * deleting it when finished. effectStages contains the effects to add. The effect key provider
- * is used to communicate the key each effect created in its GenKey function. inOutFSColor
- * specifies the input color to the first stage and is updated to be the output color of the
- * last stage. The handles to texture samplers for effectStage[i] are added to
- * effectSamplerHandles[i].
- */
- virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
- int effectCnt,
- const GrGLProgramDesc::EffectKeyProvider&,
- GrGLSLExpr4* inOutFSColor) = 0;
-
- /**
- * Similar to emitCodeBeforeEffects() but called after per-effect code is emitted.
+ /*
+ * Because we have fragment only builders, and those builders need to implement a subclass
+ * of program effects, we have to have base classes overload the program effects here
*/
- virtual void emitCodeAfterEffects() = 0;
+ virtual GrGLProgramEffects* getProgramEffects() = 0;
/**
* Compiles all the shaders, links them into a program, and writes the program id to the output
GrSLType varyingType) const {
append_texture_lookup(out,
fProgramBuilder->gpu(),
- fProgramBuilder->getUniformCStr(sampler.samplerUniform()),
+ fProgramBuilder->getUniformCStr(sampler.fSamplerUniform),
coordName,
sampler.configComponentMask(),
sampler.swizzle(),
*/
class GrGLShaderBuilder {
public:
- typedef GrGLProgramEffects::TransformedCoordsArray TransformedCoordsArray;
- typedef GrGLProgramEffects::TextureSampler TextureSampler;
+ typedef GrGLEffect::TransformedCoordsArray TransformedCoordsArray;
+ typedef GrGLEffect::TextureSampler TextureSampler;
GrGLShaderBuilder(GrGLProgramBuilder* program);
void addInput(GrGLShaderVar i) { fInputs.push_back(i); }
fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kVertex_Visibility, &vertShaderSrc);
fProgramBuilder->appendDecls(fInputs, &vertShaderSrc);
fProgramBuilder->appendDecls(fOutputs, &vertShaderSrc);
- vertShaderSrc.append("void main() {\n");
+ vertShaderSrc.append("void main() {");
vertShaderSrc.append(fCode);
- vertShaderSrc.append("}\n");
+ vertShaderSrc.append("}");
GrGLuint vertShaderId = GrGLCompileAndAttachShader(glCtx, programId,
GR_GL_VERTEX_SHADER, vertShaderSrc);
if (!vertShaderId) {
// Transform from Skia's device coords to GL's normalized device coords.
this->codeAppendf(
- "\tgl_Position = vec4(dot(pos3.xz, %s.xy), dot(pos3.yz, %s.zw), 0, pos3.z);\n",
+ "gl_Position = vec4(dot(pos3.xz, %s.xy), dot(pos3.yz, %s.zw), 0, pos3.z);",
rtAdjustName, rtAdjustName);
}
const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader();
fPositionVar = &fInputs.push_back();
- fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition");
+ fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "inPosition");
if (-1 != header.fLocalCoordAttributeIndex) {
fLocalCoordsVar = &fInputs.push_back();
fLocalCoordsVar->set(kVec2f_GrSLType,
GrGLShaderVar::kAttribute_TypeModifier,
- "aLocalCoords");
+ "inLocalCoords");
} else {
fLocalCoordsVar = fPositionVar;
}
&viewMName);
// Transform the position into Skia's device coords.
- this->codeAppendf("\tvec3 pos3 = %s * vec3(%s, 1);\n",
+ this->codeAppendf("vec3 pos3 = %s * vec3(%s, 1);",
viewMName, fPositionVar->c_str());
// we output point size in the GS if present
&& !header.fExperimentalGS
#endif
) {
- this->codeAppend("\tgl_PointSize = 1.0;\n");
+ this->codeAppend("gl_PointSize = 1.0;");
}
if (GrGLProgramDesc::kAttribute_ColorInput == header.fColorInput) {
GrShaderVar::kAttribute_TypeModifier));
const char *vsName, *fsName;
fFullProgramBuilder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName);
- this->codeAppendf("\t%s = %s;\n", vsName, color_attribute_name());
+ this->codeAppendf("%s = %s;", vsName, color_attribute_name());
*color = fsName;
}
GrShaderVar::kAttribute_TypeModifier));
const char *vsName, *fsName;
fFullProgramBuilder->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName);
- this->codeAppendf("\t%s = %s;\n", vsName, coverage_attribute_name());
+ this->codeAppendf("%s = %s;", vsName, coverage_attribute_name());
*coverage = fsName;
}
fEffectAttribOffset = fInputs.count();