aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrGeometryProcessor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu/GrGeometryProcessor.cpp')
-rw-r--r--src/gpu/GrGeometryProcessor.cpp439
1 files changed, 389 insertions, 50 deletions
diff --git a/src/gpu/GrGeometryProcessor.cpp b/src/gpu/GrGeometryProcessor.cpp
index 6bd6b2b54b..e8ffc7b3a7 100644
--- a/src/gpu/GrGeometryProcessor.cpp
+++ b/src/gpu/GrGeometryProcessor.cpp
@@ -7,8 +7,68 @@
#include "GrGeometryProcessor.h"
-#include "gl/GrGLGeometryProcessor.h"
+#include "GrCoordTransform.h"
#include "GrInvariantOutput.h"
+#include "gl/GrGLGeometryProcessor.h"
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * The key for an individual coord transform is made up of a matrix type, a precision, and a bit
+ * that indicates the source of the input coords.
+ */
+enum {
+ kMatrixTypeKeyBits = 1,
+ kMatrixTypeKeyMask = (1 << kMatrixTypeKeyBits) - 1,
+
+ kPrecisionBits = 2,
+ kPrecisionShift = kMatrixTypeKeyBits,
+
+ kPositionCoords_Flag = (1 << (kPrecisionShift + kPrecisionBits)),
+ kDeviceCoords_Flag = kPositionCoords_Flag + kPositionCoords_Flag,
+
+ kTransformKeyBits = kMatrixTypeKeyBits + kPrecisionBits + 2,
+};
+
+GR_STATIC_ASSERT(kHigh_GrSLPrecision < (1 << kPrecisionBits));
+
+/**
+ * We specialize the vertex code for each of these matrix types.
+ */
+enum MatrixType {
+ kNoPersp_MatrixType = 0,
+ kGeneral_MatrixType = 1,
+};
+
+uint32_t
+GrPrimitiveProcessor::getTransformKey(const SkTArray<const GrCoordTransform*, true>& coords) const {
+ uint32_t totalKey = 0;
+ for (int t = 0; t < coords.count(); ++t) {
+ uint32_t key = 0;
+ const GrCoordTransform* coordTransform = coords[t];
+ if (coordTransform->getMatrix().hasPerspective()) {
+ key |= kGeneral_MatrixType;
+ } else {
+ key |= kNoPersp_MatrixType;
+ }
+
+ if (kLocal_GrCoordSet == coordTransform->sourceCoords() &&
+ !this->hasExplicitLocalCoords()) {
+ key |= kPositionCoords_Flag;
+ } else if (kDevice_GrCoordSet == coordTransform->sourceCoords()) {
+ key |= kDeviceCoords_Flag;
+ }
+
+ GR_STATIC_ASSERT(kGrSLPrecisionCount <= (1 << kPrecisionBits));
+ key |= (coordTransform->precision() << kPrecisionShift);
+
+ key <<= kTransformKeyBits * t;
+
+ SkASSERT(0 == (totalKey & key)); // keys for each transform ought not to overlap
+ totalKey |= key;
+ }
+ return totalKey;
+}
///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -33,11 +93,34 @@ void GrGeometryProcessor::getInvariantOutputCoverage(GrInitInvariantOutput* out)
#include "gl/builders/GrGLProgramBuilder.h"
-void GrGLGeometryProcessor::setupColorPassThrough(GrGLGPBuilder* pb,
- GrGPInput inputType,
- const char* outputName,
- const GrGeometryProcessor::GrAttribute* colorAttr,
- UniformHandle* colorUniform) {
+SkMatrix GrGLPrimitiveProcessor::GetTransformMatrix(const SkMatrix& localMatrix,
+ const GrCoordTransform& coordTransform) {
+ SkMatrix combined;
+ // We only apply the localmatrix to localcoords
+ if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
+ combined.setConcat(coordTransform.getMatrix(), localMatrix);
+ } else {
+ combined = coordTransform.getMatrix();
+ }
+ if (coordTransform.reverseY()) {
+ // combined.postScale(1,-1);
+ // combined.postTranslate(0,1);
+ combined.set(SkMatrix::kMSkewY,
+ combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]);
+ combined.set(SkMatrix::kMScaleY,
+ combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]);
+ combined.set(SkMatrix::kMTransY,
+ combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]);
+ }
+ return combined;
+}
+
+void
+GrGLPrimitiveProcessor::setupColorPassThrough(GrGLGPBuilder* pb,
+ GrGPInput inputType,
+ const char* outputName,
+ const GrGeometryProcessor::GrAttribute* colorAttr,
+ UniformHandle* colorUniform) {
GrGLGPFragmentBuilder* fs = pb->getFragmentShaderBuilder();
if (kUniform_GrGPInput == inputType) {
SkASSERT(colorUniform);
@@ -56,15 +139,15 @@ void GrGLGeometryProcessor::setupColorPassThrough(GrGLGPBuilder* pb,
}
}
-void GrGLGeometryProcessor::addUniformViewMatrix(GrGLGPBuilder* pb) {
+void GrGLPrimitiveProcessor::addUniformViewMatrix(GrGLGPBuilder* pb) {
fViewMatrixUniform = pb->addUniform(GrGLProgramBuilder::kVertex_Visibility,
kMat33f_GrSLType, kDefault_GrSLPrecision,
"uViewM",
&fViewMatrixName);
}
-void GrGLGeometryProcessor::setUniformViewMatrix(const GrGLProgramDataManager& pdman,
- const SkMatrix& viewMatrix) {
+void GrGLPrimitiveProcessor::setUniformViewMatrix(const GrGLProgramDataManager& pdman,
+ const SkMatrix& viewMatrix) {
if (!fViewMatrix.cheapEqualTo(viewMatrix)) {
SkASSERT(fViewMatrixUniform.isValid());
fViewMatrix = viewMatrix;
@@ -77,6 +160,98 @@ void GrGLGeometryProcessor::setUniformViewMatrix(const GrGLProgramDataManager& p
///////////////////////////////////////////////////////////////////////////////////////////////////
+
+void GrGLGeometryProcessor::emitCode(EmitArgs& args) {
+ GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
+ vsBuilder->codeAppendf("vec3 %s;", this->position());
+ this->onEmitCode(args);
+ vsBuilder->transformToNormalizedDeviceSpace(this->position());
+}
+
+void GrGLGeometryProcessor::emitTransforms(GrGLGPBuilder* pb,
+ const char* position,
+ const char* localCoords,
+ const SkMatrix& localMatrix,
+ const TransformsIn& tin,
+ TransformsOut* tout) {
+ GrGLVertexBuilder* vb = pb->getVertexShaderBuilder();
+ tout->push_back_n(tin.count());
+ fInstalledTransforms.push_back_n(tin.count());
+ for (int i = 0; i < tin.count(); i++) {
+ const ProcCoords& coordTransforms = tin[i];
+ fInstalledTransforms[i].push_back_n(coordTransforms.count());
+ for (int t = 0; t < coordTransforms.count(); t++) {
+ SkString strUniName("StageMatrix");
+ strUniName.appendf("_%i_%i", i, t);
+ GrSLType varyingType;
+
+ GrCoordSet coordType = coordTransforms[t]->sourceCoords();
+ uint32_t type = coordTransforms[t]->getMatrix().getType();
+ if (kLocal_GrCoordSet == coordType) {
+ type |= localMatrix.getType();
+ }
+ varyingType = SkToBool(SkMatrix::kPerspective_Mask & type) ? kVec3f_GrSLType :
+ kVec2f_GrSLType;
+ GrSLPrecision precision = coordTransforms[t]->precision();
+
+ const char* uniName;
+ fInstalledTransforms[i][t].fHandle =
+ pb->addUniform(GrGLProgramBuilder::kVertex_Visibility,
+ kMat33f_GrSLType, precision,
+ strUniName.c_str(),
+ &uniName).toShaderBuilderIndex();
+
+ SkString strVaryingName("MatrixCoord");
+ strVaryingName.appendf("_%i_%i", i, t);
+
+ GrGLVertToFrag v(varyingType);
+ pb->addVarying(strVaryingName.c_str(), &v, precision);
+
+ SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
+ SkNEW_APPEND_TO_TARRAY(&(*tout)[i], GrGLProcessor::TransformedCoords,
+ (SkString(v.fsIn()), varyingType));
+
+ // varying = matrix * coords (logically)
+ if (kDevice_GrCoordSet == coordType) {
+ if (kVec2f_GrSLType == varyingType) {
+ vb->codeAppendf("%s = (%s * %s).xy;", v.vsOut(), uniName, position);
+ } else {
+ vb->codeAppendf("%s = %s * %s;", v.vsOut(), uniName, position);
+ }
+ } else {
+ if (kVec2f_GrSLType == varyingType) {
+ vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;", v.vsOut(), uniName, localCoords);
+ } else {
+ vb->codeAppendf("%s = %s * vec3(%s, 1);", v.vsOut(), uniName, localCoords);
+ }
+ }
+ }
+ }
+}
+
+
+void
+GrGLGeometryProcessor::setTransformData(const GrPrimitiveProcessor* primProc,
+ const GrGLProgramDataManager& pdman,
+ int index,
+ const SkTArray<const GrCoordTransform*, true>& transforms) {
+ SkSTArray<2, Transform, true>& procTransforms = fInstalledTransforms[index];
+ int numTransforms = transforms.count();
+ for (int t = 0; t < numTransforms; ++t) {
+ SkASSERT(procTransforms[t].fHandle.isValid());
+ const SkMatrix& transform = GetTransformMatrix(primProc->localMatrix(), *transforms[t]);
+ if (!procTransforms[t].fCurrentValue.cheapEqualTo(transform)) {
+ pdman.setSkMatrix(procTransforms[t].fHandle.convertToUniformHandle(), transform);
+ procTransforms[t].fCurrentValue = transform;
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+#include "gl/GrGLGpu.h"
+#include "gl/GrGLPathRendering.h"
+
struct PathBatchTracker {
GrGPInput fInputColorType;
GrGPInput fInputCoverageType;
@@ -84,58 +259,214 @@ struct PathBatchTracker {
bool fUsesLocalCoords;
};
-class GrGLPathProcessor : public GrGLGeometryProcessor {
+GrGLPathProcessor::GrGLPathProcessor(const GrPathProcessor&, const GrBatchTracker&)
+ : fColor(GrColor_ILLEGAL) {}
+
+void GrGLPathProcessor::emitCode(EmitArgs& args) {
+ GrGLGPBuilder* pb = args.fPB;
+ GrGLGPFragmentBuilder* fs = args.fPB->getFragmentShaderBuilder();
+ const PathBatchTracker& local = args.fBT.cast<PathBatchTracker>();
+
+ // emit transforms
+ this->emitTransforms(args.fPB, args.fTransformsIn, args.fTransformsOut);
+
+ // Setup uniform color
+ if (kUniform_GrGPInput == local.fInputColorType) {
+ const char* stagedLocalVarName;
+ fColorUniform = pb->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+ kVec4f_GrSLType,
+ kDefault_GrSLPrecision,
+ "Color",
+ &stagedLocalVarName);
+ fs->codeAppendf("%s = %s;", args.fOutputColor, stagedLocalVarName);
+ }
+
+ // setup constant solid coverage
+ if (kAllOnes_GrGPInput == local.fInputCoverageType) {
+ fs->codeAppendf("%s = vec4(1);", args.fOutputCoverage);
+ }
+}
+
+void GrGLPathProcessor::GenKey(const GrPathProcessor&,
+ const GrBatchTracker& bt,
+ const GrGLCaps&,
+ GrProcessorKeyBuilder* b) {
+ const PathBatchTracker& local = bt.cast<PathBatchTracker>();
+ b->add32(local.fInputColorType | local.fInputCoverageType << 16);
+}
+
+void GrGLPathProcessor::setData(const GrGLProgramDataManager& pdman,
+ const GrPrimitiveProcessor& primProc,
+ const GrBatchTracker& bt) {
+ const PathBatchTracker& local = bt.cast<PathBatchTracker>();
+ if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
+ GrGLfloat c[4];
+ GrColorToRGBAFloat(local.fColor, c);
+ pdman.set4fv(fColorUniform, 1, c);
+ fColor = local.fColor;
+ }
+}
+
+class GrGLLegacyPathProcessor : public GrGLPathProcessor {
public:
- GrGLPathProcessor(const GrPathProcessor&, const GrBatchTracker&)
- : fColor(GrColor_ILLEGAL) {}
-
- void emitCode(const EmitArgs& args) SK_OVERRIDE {
- GrGLGPBuilder* pb = args.fPB;
- GrGLGPFragmentBuilder* fs = args.fPB->getFragmentShaderBuilder();
- const PathBatchTracker& local = args.fBT.cast<PathBatchTracker>();
-
- // Setup uniform color
- if (kUniform_GrGPInput == local.fInputColorType) {
- const char* stagedLocalVarName;
- fColorUniform = pb->addUniform(GrGLProgramBuilder::kFragment_Visibility,
- kVec4f_GrSLType,
- kDefault_GrSLPrecision,
- "Color",
- &stagedLocalVarName);
- fs->codeAppendf("%s = %s;", args.fOutputColor, stagedLocalVarName);
+ GrGLLegacyPathProcessor(const GrPathProcessor& pathProc, const GrBatchTracker& bt,
+ int maxTexCoords)
+ : INHERITED(pathProc, bt)
+ , fMaxTexCoords(maxTexCoords)
+ , fTexCoordSetCnt(0) {}
+
+ int addTexCoordSets(int count) {
+ int firstFreeCoordSet = fTexCoordSetCnt;
+ fTexCoordSetCnt += count;
+ SkASSERT(fMaxTexCoords >= fTexCoordSetCnt);
+ return firstFreeCoordSet;
+ }
+
+ void emitTransforms(GrGLGPBuilder*, const TransformsIn& tin, TransformsOut* tout) SK_OVERRIDE {
+ tout->push_back_n(tin.count());
+ fInstalledTransforms.push_back_n(tin.count());
+ for (int i = 0; i < tin.count(); i++) {
+ const ProcCoords& coordTransforms = tin[i];
+ int texCoordIndex = this->addTexCoordSets(coordTransforms.count());
+
+ // Use the first uniform location as the texcoord index.
+ fInstalledTransforms[i].push_back_n(1);
+ fInstalledTransforms[i][0].fHandle = ShaderVarHandle(texCoordIndex);
+
+ SkString name;
+ for (int t = 0; t < coordTransforms.count(); ++t) {
+ GrSLType type = coordTransforms[t]->getMatrix().hasPerspective() ? kVec3f_GrSLType :
+ kVec2f_GrSLType;
+
+ name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++);
+ SkNEW_APPEND_TO_TARRAY(&(*tout)[i], GrGLProcessor::TransformedCoords, (name, type));
+ }
+ }
+ }
+
+ void setTransformData(const GrPrimitiveProcessor* primProc,
+ int index,
+ const SkTArray<const GrCoordTransform*, true>& transforms,
+ GrGLPathRendering* glpr,
+ GrGLuint) SK_OVERRIDE {
+ // We've hidden the texcoord index in the first entry of the transforms array for each
+ // effect
+ int texCoordIndex = fInstalledTransforms[index][0].fHandle.handle();
+ for (int t = 0; t < transforms.count(); ++t) {
+ const SkMatrix& transform = GetTransformMatrix(primProc->localMatrix(), *transforms[t]);
+ GrGLPathRendering::PathTexGenComponents components =
+ GrGLPathRendering::kST_PathTexGenComponents;
+ if (transform.hasPerspective()) {
+ components = GrGLPathRendering::kSTR_PathTexGenComponents;
+ }
+ glpr->enablePathTexGen(texCoordIndex++, components, transform);
}
+ }
+
+ void didSetData(GrGLPathRendering* glpr) SK_OVERRIDE {
+ glpr->flushPathTexGenSettings(fTexCoordSetCnt);
+ }
+
+private:
+ int fMaxTexCoords;
+ int fTexCoordSetCnt;
+
+ typedef GrGLPathProcessor INHERITED;
+};
- // setup constant solid coverage
- if (kAllOnes_GrGPInput == local.fInputCoverageType) {
- fs->codeAppendf("%s = vec4(1);", args.fOutputCoverage);
+class GrGLNormalPathProcessor : public GrGLPathProcessor {
+public:
+ GrGLNormalPathProcessor(const GrPathProcessor& pathProc, const GrBatchTracker& bt)
+ : INHERITED(pathProc, bt) {}
+
+ void emitTransforms(GrGLGPBuilder* pb, const TransformsIn& tin,
+ TransformsOut* tout) SK_OVERRIDE {
+ tout->push_back_n(tin.count());
+ fInstalledTransforms.push_back_n(tin.count());
+ for (int i = 0; i < tin.count(); i++) {
+ const ProcCoords& coordTransforms = tin[i];
+ fInstalledTransforms[i].push_back_n(coordTransforms.count());
+ for (int t = 0; t < coordTransforms.count(); t++) {
+ GrSLType varyingType =
+ coordTransforms[t]->getMatrix().hasPerspective() ? kVec3f_GrSLType :
+ kVec2f_GrSLType;
+
+ const char* varyingName = "MatrixCoord";
+ SkString suffixedVaryingName;
+ if (0 != t) {
+ suffixedVaryingName.append(varyingName);
+ suffixedVaryingName.appendf("_%i", t);
+ varyingName = suffixedVaryingName.c_str();
+ }
+ GrGLVertToFrag v(varyingType);
+ pb->addVarying(varyingName, &v);
+ SeparableVaryingInfo& varyingInfo = fSeparableVaryingInfos.push_back();
+ varyingInfo.fVariable = pb->getFragmentShaderBuilder()->fInputs.back();
+ varyingInfo.fLocation = fSeparableVaryingInfos.count() - 1;
+ varyingInfo.fType = varyingType;
+ fInstalledTransforms[i][t].fHandle = ShaderVarHandle(varyingInfo.fLocation);
+ fInstalledTransforms[i][t].fType = varyingType;
+
+ SkNEW_APPEND_TO_TARRAY(&(*tout)[i], GrGLProcessor::TransformedCoords,
+ (SkString(v.fsIn()), varyingType));
+ }
}
}
- static inline void GenKey(const GrPathProcessor&,
- const GrBatchTracker& bt,
- const GrGLCaps&,
- GrProcessorKeyBuilder* b) {
- const PathBatchTracker& local = bt.cast<PathBatchTracker>();
- b->add32(local.fInputColorType | local.fInputCoverageType << 16);
+ void resolveSeparableVaryings(GrGLGpu* gpu, GrGLuint programId) {
+ int count = fSeparableVaryingInfos.count();
+ for (int i = 0; i < count; ++i) {
+ GrGLint location;
+ GR_GL_CALL_RET(gpu->glInterface(),
+ location,
+ GetProgramResourceLocation(programId,
+ GR_GL_FRAGMENT_INPUT,
+ fSeparableVaryingInfos[i].fVariable.c_str()));
+ fSeparableVaryingInfos[i].fLocation = location;
+ }
}
- void setData(const GrGLProgramDataManager& pdman,
- const GrPrimitiveProcessor& primProc,
- const GrBatchTracker& bt) SK_OVERRIDE {
- const PathBatchTracker& local = bt.cast<PathBatchTracker>();
- if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
- GrGLfloat c[4];
- GrColorToRGBAFloat(local.fColor, c);
- pdman.set4fv(fColorUniform, 1, c);
- fColor = local.fColor;
+ void setTransformData(const GrPrimitiveProcessor* primProc,
+ int index,
+ const SkTArray<const GrCoordTransform*, true>& coordTransforms,
+ GrGLPathRendering* glpr,
+ GrGLuint programID) SK_OVERRIDE {
+ SkSTArray<2, Transform, true>& transforms = fInstalledTransforms[index];
+ int numTransforms = transforms.count();
+ for (int t = 0; t < numTransforms; ++t) {
+ SkASSERT(transforms[t].fHandle.isValid());
+ const SkMatrix& transform = GetTransformMatrix(primProc->localMatrix(),
+ *coordTransforms[t]);
+ if (transforms[t].fCurrentValue.cheapEqualTo(transform)) {
+ continue;
+ }
+ transforms[t].fCurrentValue = transform;
+ const SeparableVaryingInfo& fragmentInput =
+ fSeparableVaryingInfos[transforms[t].fHandle.handle()];
+ SkASSERT(transforms[t].fType == kVec2f_GrSLType ||
+ transforms[t].fType == kVec3f_GrSLType);
+ unsigned components = transforms[t].fType == kVec2f_GrSLType ? 2 : 3;
+ glpr->setProgramPathFragmentInputTransform(programID,
+ fragmentInput.fLocation,
+ GR_GL_OBJECT_LINEAR,
+ components,
+ transform);
}
}
private:
- UniformHandle fColorUniform;
- GrColor fColor;
+ struct SeparableVaryingInfo {
+ GrSLType fType;
+ GrGLShaderVar fVariable;
+ GrGLint fLocation;
+ };
- typedef GrGLGeometryProcessor INHERITED;
+
+ typedef SkSTArray<8, SeparableVaryingInfo, true> SeparableVaryingInfoArray;
+
+ SeparableVaryingInfoArray fSeparableVaryingInfos;
+
+ typedef GrGLPathProcessor INHERITED;
};
GrPathProcessor::GrPathProcessor(GrColor color,
@@ -196,6 +527,14 @@ void GrPathProcessor::getGLProcessorKey(const GrBatchTracker& bt,
GrGLPathProcessor::GenKey(*this, bt, caps, b);
}
-GrGLGeometryProcessor* GrPathProcessor::createGLInstance(const GrBatchTracker& bt) const {
- return SkNEW_ARGS(GrGLPathProcessor, (*this, bt));
+GrGLPrimitiveProcessor* GrPathProcessor::createGLInstance(const GrBatchTracker& bt,
+ const GrGLCaps& caps) const {
+ SkASSERT(caps.nvprSupport() != GrGLCaps::kNone_NvprSupport);
+ if (caps.nvprSupport() == GrGLCaps::kLegacy_NvprSupport) {
+ return SkNEW_ARGS(GrGLLegacyPathProcessor, (*this, bt,
+ caps.maxFixedFunctionTextureCoords()));
+ } else {
+ return SkNEW_ARGS(GrGLNormalPathProcessor, (*this, bt));
+ }
}
+