diff options
author | joshualitt <joshualitt@chromium.org> | 2015-02-12 14:20:52 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-02-12 14:20:52 -0800 |
commit | 8072caa80384292858d31ae34b7e19768875866b (patch) | |
tree | 540934943305cb0aa1e73bfa836e260cab8b45b0 | |
parent | b0fb935bd544b0c6f68c692c7e1ee40876184a1a (diff) |
A simple change to move a bunch of stuff out of Gr*Geometry.h
BUG=skia:
Review URL: https://codereview.chromium.org/920863002
-rw-r--r-- | gyp/gpu.gypi | 9 | ||||
-rw-r--r-- | src/gpu/GrDrawTarget.h | 2 | ||||
-rw-r--r-- | src/gpu/GrGeometryProcessor.cpp | 542 | ||||
-rw-r--r-- | src/gpu/GrGeometryProcessor.h | 264 | ||||
-rw-r--r-- | src/gpu/GrPathProcessor.cpp | 73 | ||||
-rw-r--r-- | src/gpu/GrPathProcessor.h | 65 | ||||
-rw-r--r-- | src/gpu/GrPipelineBuilder.h | 1 | ||||
-rw-r--r-- | src/gpu/GrPrimitiveProcessor.cpp | 67 | ||||
-rw-r--r-- | src/gpu/GrPrimitiveProcessor.h | 230 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGeometryProcessor.cpp | 129 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGeometryProcessor.h | 156 | ||||
-rw-r--r-- | src/gpu/gl/GrGLPathProcessor.cpp | 183 | ||||
-rw-r--r-- | src/gpu/gl/GrGLPathProcessor.h | 113 | ||||
-rw-r--r-- | src/gpu/gl/GrGLPrimitiveProcessor.cpp | 75 | ||||
-rw-r--r-- | src/gpu/gl/GrGLPrimitiveProcessor.h | 130 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.cpp | 4 | ||||
-rw-r--r-- | src/gpu/gl/builders/GrGLProgramBuilder.cpp | 7 | ||||
-rw-r--r-- | src/gpu/gl/builders/GrGLProgramBuilder.h | 2 |
18 files changed, 1087 insertions, 965 deletions
diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi index 9c250f0e9b..f06477fa8e 100644 --- a/gyp/gpu.gypi +++ b/gyp/gpu.gypi @@ -111,6 +111,8 @@ '<(skia_src_path)/gpu/GrPaint.cpp', '<(skia_src_path)/gpu/GrPath.cpp', '<(skia_src_path)/gpu/GrPath.h', + '<(skia_src_path)/gpu/GrPathProcessor.cpp', + '<(skia_src_path)/gpu/GrPathProcessor.h', '<(skia_src_path)/gpu/GrPathRange.cpp', '<(skia_src_path)/gpu/GrPathRange.h', '<(skia_src_path)/gpu/GrPathRendererChain.cpp', @@ -126,6 +128,8 @@ '<(skia_src_path)/gpu/GrPipeline.h', '<(skia_src_path)/gpu/GrPipelineBuilder.cpp', '<(skia_src_path)/gpu/GrPipelineBuilder.h', + '<(skia_src_path)/gpu/GrPrimitiveProcessor.cpp', + '<(skia_src_path)/gpu/GrPrimitiveProcessor.h', '<(skia_src_path)/gpu/GrProgramDesc.h', '<(skia_src_path)/gpu/GrProgramElement.cpp', '<(skia_src_path)/gpu/GrProcessor.cpp', @@ -231,6 +235,7 @@ '<(skia_src_path)/gpu/gl/GrGLCreateNativeInterface_none.cpp', '<(skia_src_path)/gpu/gl/GrGLDefaultInterface_none.cpp', '<(skia_src_path)/gpu/gl/GrGLDefines.h', + '<(skia_src_path)/gpu/gl/GrGLGeometryProcessor.cpp', '<(skia_src_path)/gpu/gl/GrGLGeometryProcessor.h', '<(skia_src_path)/gpu/gl/GrGLGpu.cpp', '<(skia_src_path)/gpu/gl/GrGLGpu.h', @@ -246,10 +251,14 @@ '<(skia_src_path)/gpu/gl/GrGLNoOpInterface.h', '<(skia_src_path)/gpu/gl/GrGLPath.cpp', '<(skia_src_path)/gpu/gl/GrGLPath.h', + '<(skia_src_path)/gpu/gl/GrGLPathProcessor.cpp', + '<(skia_src_path)/gpu/gl/GrGLPathProcessor.h', '<(skia_src_path)/gpu/gl/GrGLPathRange.cpp', '<(skia_src_path)/gpu/gl/GrGLPathRange.h', '<(skia_src_path)/gpu/gl/GrGLPathRendering.cpp', '<(skia_src_path)/gpu/gl/GrGLPathRendering.h', + '<(skia_src_path)/gpu/gl/GrGLPrimitiveProcessor.cpp', + '<(skia_src_path)/gpu/gl/GrGLPrimitiveProcessor.h', '<(skia_src_path)/gpu/gl/GrGLProcessor.h', '<(skia_src_path)/gpu/gl/GrGLProgram.cpp', '<(skia_src_path)/gpu/gl/GrGLProgram.h', diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h index 1b6651716c..65407e653b 100644 --- a/src/gpu/GrDrawTarget.h +++ b/src/gpu/GrDrawTarget.h @@ -11,6 +11,8 @@ #include "GrClipData.h" #include "GrClipMaskManager.h" #include "GrContext.h" +#include "GrPathProcessor.h" +#include "GrPrimitiveProcessor.h" #include "GrIndexBuffer.h" #include "GrPathRendering.h" #include "GrPipelineBuilder.h" diff --git a/src/gpu/GrGeometryProcessor.cpp b/src/gpu/GrGeometryProcessor.cpp index c707efc6a2..23989cfe92 100644 --- a/src/gpu/GrGeometryProcessor.cpp +++ b/src/gpu/GrGeometryProcessor.cpp @@ -7,70 +7,7 @@ #include "GrGeometryProcessor.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; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// void GrGeometryProcessor::getInvariantOutputColor(GrInitInvariantOutput* out) const { if (fHasVertexColor) { @@ -89,483 +26,4 @@ void GrGeometryProcessor::getInvariantOutputCoverage(GrInitInvariantOutput* out) this->onGetInvariantOutputCoverage(out); } -/////////////////////////////////////////////////////////////////////////////////////////////////// - -#include "gl/builders/GrGLProgramBuilder.h" - -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::Attribute* colorAttr, - UniformHandle* colorUniform) { - GrGLGPFragmentBuilder* fs = pb->getFragmentShaderBuilder(); - if (kUniform_GrGPInput == inputType) { - SkASSERT(colorUniform); - const char* stagedLocalVarName; - *colorUniform = pb->addUniform(GrGLProgramBuilder::kFragment_Visibility, - kVec4f_GrSLType, - kDefault_GrSLPrecision, - "Color", - &stagedLocalVarName); - fs->codeAppendf("%s = %s;", outputName, stagedLocalVarName); - } else if (kAttribute_GrGPInput == inputType) { - SkASSERT(colorAttr); - pb->addPassThroughAttribute(colorAttr, outputName); - } else if (kAllOnes_GrGPInput == inputType) { - fs->codeAppendf("%s = vec4(1);", outputName); - } -} - -void GrGLPrimitiveProcessor::addUniformViewMatrix(GrGLGPBuilder* pb) { - fViewMatrixUniform = pb->addUniform(GrGLProgramBuilder::kVertex_Visibility, - kMat33f_GrSLType, kDefault_GrSLPrecision, - "uViewM", - &fViewMatrixName); -} - -void GrGLPrimitiveProcessor::setUniformViewMatrix(const GrGLProgramDataManager& pdman, - const SkMatrix& viewMatrix) { - if (!fViewMatrix.cheapEqualTo(viewMatrix)) { - SkASSERT(fViewMatrixUniform.isValid()); - fViewMatrix = viewMatrix; - - GrGLfloat viewMatrix[3 * 3]; - GrGLGetMatrix<3>(viewMatrix, fViewMatrix); - pdman.setMatrix3f(fViewMatrixUniform, viewMatrix); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// - - -void GrGLGeometryProcessor::emitCode(EmitArgs& args) { - GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); - GrGPArgs gpArgs; - this->onEmitCode(args, &gpArgs); - vsBuilder->transformToNormalizedDeviceSpace(gpArgs.fPositionVar); -} - -void GrGLGeometryProcessor::emitTransforms(GrGLGPBuilder* pb, - const GrShaderVar& posVar, - 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) { - if (kVec2f_GrSLType == posVar.getType()) { - vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;", - v.vsOut(), uniName, posVar.c_str()); - } else { - // The brackets here are just to scope the temp variable - vb->codeAppendf("{ vec3 temp = %s * %s;", uniName, posVar.c_str()); - vb->codeAppendf("%s = vec2(temp.x/temp.z, temp.y/temp.z); }", v.vsOut()); - } - } else { - if (kVec2f_GrSLType == posVar.getType()) { - vb->codeAppendf("%s = %s * vec3(%s, 1);", - v.vsOut(), uniName, posVar.c_str()); - } else { - vb->codeAppendf("%s = %s * %s;", v.vsOut(), uniName, posVar.c_str()); - } - } - } 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; - } - } -} - -void GrGLGeometryProcessor::SetupPosition(GrGLVertexBuilder* vsBuilder, - GrGPArgs* gpArgs, - const char* posName, - const SkMatrix& mat, - const char* matName) { - if (mat.isIdentity()) { - gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2"); - - vsBuilder->codeAppendf("vec2 %s = %s;", gpArgs->fPositionVar.c_str(), posName); - } else if (!mat.hasPerspective()) { - gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2"); - - vsBuilder->codeAppendf("vec2 %s = vec2(%s * vec3(%s, 1));", - gpArgs->fPositionVar.c_str(), matName, posName); - } else { - gpArgs->fPositionVar.set(kVec3f_GrSLType, "pos3"); - - vsBuilder->codeAppendf("vec3 %s = %s * vec3(%s, 1);", - gpArgs->fPositionVar.c_str(), matName, posName); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -#include "gl/GrGLGpu.h" -#include "gl/GrGLPathRendering.h" - -struct PathBatchTracker { - GrGPInput fInputColorType; - GrGPInput fInputCoverageType; - GrColor fColor; - bool fUsesLocalCoords; -}; - -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: - GrGLLegacyPathProcessor(const GrPathProcessor& pathProc, const GrBatchTracker& bt, - int maxTexCoords) - : INHERITED(pathProc, bt) - , fTexCoordSetCnt(0) { - SkDEBUGCODE(fMaxTexCoords = maxTexCoords;) - } - - 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: - SkDEBUGCODE(int fMaxTexCoords;) - int fTexCoordSetCnt; - - typedef GrGLPathProcessor INHERITED; -}; - -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; - - - SkString strVaryingName("MatrixCoord"); - strVaryingName.appendf("_%i_%i", i, t); - GrGLVertToFrag v(varyingType); - pb->addVarying(strVaryingName.c_str(), &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)); - } - } - } - - 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 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: - struct SeparableVaryingInfo { - GrSLType fType; - GrGLShaderVar fVariable; - GrGLint fLocation; - }; - - - typedef SkSTArray<8, SeparableVaryingInfo, true> SeparableVaryingInfoArray; - - SeparableVaryingInfoArray fSeparableVaryingInfos; - - typedef GrGLPathProcessor INHERITED; -}; - -GrPathProcessor::GrPathProcessor(GrColor color, - const SkMatrix& viewMatrix, - const SkMatrix& localMatrix) - : INHERITED(viewMatrix, localMatrix, true) - , fColor(color) { - this->initClassID<GrPathProcessor>(); -} - -void GrPathProcessor::getInvariantOutputColor(GrInitInvariantOutput* out) const { - out->setKnownFourComponents(fColor); -} - -void GrPathProcessor::getInvariantOutputCoverage(GrInitInvariantOutput* out) const { - out->setKnownSingleComponent(0xff); -} - -void GrPathProcessor::initBatchTracker(GrBatchTracker* bt, const GrPipelineInfo& init) const { - PathBatchTracker* local = bt->cast<PathBatchTracker>(); - if (init.fColorIgnored) { - local->fInputColorType = kIgnored_GrGPInput; - local->fColor = GrColor_ILLEGAL; - } else { - local->fInputColorType = kUniform_GrGPInput; - local->fColor = GrColor_ILLEGAL == init.fOverrideColor ? this->color() : - init.fOverrideColor; - } - - local->fInputCoverageType = init.fCoverageIgnored ? kIgnored_GrGPInput : kAllOnes_GrGPInput; - local->fUsesLocalCoords = init.fUsesLocalCoords; -} - -bool GrPathProcessor::canMakeEqual(const GrBatchTracker& m, - const GrPrimitiveProcessor& that, - const GrBatchTracker& t) const { - if (this->classID() != that.classID() || !this->hasSameTextureAccesses(that)) { - return false; - } - - if (!this->viewMatrix().cheapEqualTo(that.viewMatrix())) { - return false; - } - - const PathBatchTracker& mine = m.cast<PathBatchTracker>(); - const PathBatchTracker& theirs = t.cast<PathBatchTracker>(); - return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords, - that, theirs.fUsesLocalCoords) && - CanCombineOutput(mine.fInputColorType, mine.fColor, - theirs.fInputColorType, theirs.fColor) && - CanCombineOutput(mine.fInputCoverageType, 0xff, - theirs.fInputCoverageType, 0xff); -} - -void GrPathProcessor::getGLProcessorKey(const GrBatchTracker& bt, - const GrGLCaps& caps, - GrProcessorKeyBuilder* b) const { - GrGLPathProcessor::GenKey(*this, bt, caps, b); -} - -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)); - } -} diff --git a/src/gpu/GrGeometryProcessor.h b/src/gpu/GrGeometryProcessor.h index a7fea765ab..7f8d041af8 100644 --- a/src/gpu/GrGeometryProcessor.h +++ b/src/gpu/GrGeometryProcessor.h @@ -8,224 +8,7 @@ #ifndef GrGeometryProcessor_DEFINED #define GrGeometryProcessor_DEFINED -#include "GrColor.h" -#include "GrProcessor.h" -#include "GrShaderVar.h" - -/* - * The GrPrimitiveProcessor represents some kind of geometric primitive. This includes the shape - * of the primitive and the inherent color of the primitive. The GrPrimitiveProcessor is - * responsible for providing a color and coverage input into the Ganesh rendering pipeline. Through - * optimization, Ganesh may decide a different color, no color, and / or no coverage are required - * from the GrPrimitiveProcessor, so the GrPrimitiveProcessor must be able to support this - * functionality. We also use the GrPrimitiveProcessor to make batching decisions. - * - * There are two feedback loops between the GrFragmentProcessors, the GrXferProcessor, and the - * GrPrimitiveProcessor. These loops run on the CPU and compute any invariant components which - * might be useful for correctness / optimization decisions. The GrPrimitiveProcessor seeds these - * loops, one with initial color and one with initial coverage, in its - * onComputeInvariantColor / Coverage calls. These seed values are processed by the subsequent - * stages of the rendering pipeline and the output is then fed back into the GrPrimitiveProcessor in - * the initBatchTracker call, where the GrPrimitiveProcessor can then initialize the GrBatchTracker - * struct with the appropriate values. - * - * We are evolving this system to move towards generating geometric meshes and their associated - * vertex data after we have batched and reordered draws. This system, known as 'deferred geometry' - * will allow the GrPrimitiveProcessor much greater control over how data is transmitted to shaders. - * - * In a deferred geometry world, the GrPrimitiveProcessor can always 'batch' To do this, each - * primitive type is associated with one GrPrimitiveProcessor, who has complete control of how - * it draws. Each primitive draw will bundle all required data to perform the draw, and these - * bundles of data will be owned by an instance of the associated GrPrimitiveProcessor. Bundles - * can be updated alongside the GrBatchTracker struct itself, ultimately allowing the - * GrPrimitiveProcessor complete control of how it gets data into the fragment shader as long as - * it emits the appropriate color, or none at all, as directed. - */ - -/* - * A struct for tracking batching decisions. While this lives on GrOptState, it is managed - * entirely by the derived classes of the GP. - * // TODO this was an early attempt at handling out of order batching. It should be - * used carefully as it is being replaced by GrBatch - */ -class GrBatchTracker { -public: - template <typename T> const T& cast() const { - SkASSERT(sizeof(T) <= kMaxSize); - return *reinterpret_cast<const T*>(fData.get()); - } - - template <typename T> T* cast() { - SkASSERT(sizeof(T) <= kMaxSize); - return reinterpret_cast<T*>(fData.get()); - } - - static const size_t kMaxSize = 32; - -private: - SkAlignedSStorage<kMaxSize> fData; -}; - -class GrIndexBufferAllocPool; -class GrGLCaps; -class GrGLPrimitiveProcessor; -class GrVertexBufferAllocPool; - -struct GrInitInvariantOutput; - -/* - * This struct allows the GrPipeline to communicate information about the pipeline. Most of this - * is overrides, but some of it is general information. Logically it should live in GrPipeline.h, - * but this is problematic due to circular dependencies. - */ -struct GrPipelineInfo { - bool fColorIgnored; - bool fCoverageIgnored; - GrColor fOverrideColor; - bool fUsesLocalCoords; -}; - -/* - * This enum is shared by GrPrimitiveProcessors and GrGLPrimitiveProcessors to coordinate shaders - * with vertex attributes / uniforms. - */ -enum GrGPInput { - kAllOnes_GrGPInput, - kAttribute_GrGPInput, - kUniform_GrGPInput, - kIgnored_GrGPInput, -}; - -/* - * GrPrimitiveProcessor defines an interface which all subclasses must implement. All - * GrPrimitiveProcessors must proivide seed color and coverage for the Ganesh color / coverage - * pipelines, and they must provide some notion of equality - */ -class GrPrimitiveProcessor : public GrProcessor { -public: - // TODO let the PrimProc itself set this in its setData call, this should really live on the - // bundle of primitive data - const SkMatrix& viewMatrix() const { return fViewMatrix; } - const SkMatrix& localMatrix() const { return fLocalMatrix; } - - virtual void initBatchTracker(GrBatchTracker*, const GrPipelineInfo&) const = 0; - - virtual bool canMakeEqual(const GrBatchTracker& mine, - const GrPrimitiveProcessor& that, - const GrBatchTracker& theirs) const = 0; - - virtual void getInvariantOutputColor(GrInitInvariantOutput* out) const = 0; - virtual void getInvariantOutputCoverage(GrInitInvariantOutput* out) const = 0; - - // Only the GrGeometryProcessor subclass actually has a geo shader or vertex attributes, but - // we put these calls on the base class to prevent having to cast - virtual bool willUseGeoShader() const = 0; - - /* - * This is a safeguard to prevent GrPrimitiveProcessor's from going beyond platform specific - * attribute limits. This number can almost certainly be raised if required. - */ - static const int kMaxVertexAttribs = 6; - - struct Attribute { - Attribute() - : fName(NULL) - , fType(kFloat_GrVertexAttribType) - , fOffset(0) {} - Attribute(const char* name, GrVertexAttribType type) - : fName(name) - , fType(type) - , fOffset(SkAlign4(GrVertexAttribTypeSize(type))) {} - const char* fName; - GrVertexAttribType fType; - size_t fOffset; - }; - - int numAttribs() const { return fNumAttribs; } - const Attribute& getAttrib(int index) const { - SkASSERT(index < fNumAttribs); - return fAttribs[index]; - } - - // Returns the vertex stride of the GP. A common use case is to request geometry from a - // drawtarget based off of the stride, and to populate this memory using an implicit array of - // structs. In this case, it is best to assert the vertexstride == sizeof(VertexStruct). - size_t getVertexStride() const { return fVertexStride; } - - /** - * Gets a transformKey from an array of coord transforms - */ - uint32_t getTransformKey(const SkTArray<const GrCoordTransform*, true>&) const; - - /** - * Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this geometry - * processor's GL backend implementation. - */ - virtual void getGLProcessorKey(const GrBatchTracker& bt, - const GrGLCaps& caps, - GrProcessorKeyBuilder* b) const = 0; - - - /** Returns a new instance of the appropriate *GL* implementation class - for the given GrProcessor; caller is responsible for deleting - the object. */ - virtual GrGLPrimitiveProcessor* createGLInstance(const GrBatchTracker& bt, - const GrGLCaps& caps) const = 0; - - bool isPathRendering() const { return fIsPathRendering; } - -protected: - GrPrimitiveProcessor(const SkMatrix& viewMatrix, const SkMatrix& localMatrix, - bool isPathRendering) - : fNumAttribs(0) - , fVertexStride(0) - , fViewMatrix(viewMatrix) - , fLocalMatrix(localMatrix) - , fIsPathRendering(isPathRendering) {} - - /* - * CanCombineOutput will return true if two draws are 'batchable' from a color perspective. - * TODO remove this when GPs can upgrade to attribute color - */ - static bool CanCombineOutput(GrGPInput left, GrColor lColor, GrGPInput right, GrColor rColor) { - if (left != right) { - return false; - } - - if (kUniform_GrGPInput == left && lColor != rColor) { - return false; - } - - return true; - } - - static bool CanCombineLocalMatrices(const GrPrimitiveProcessor& left, - bool leftUsesLocalCoords, - const GrPrimitiveProcessor& right, - bool rightUsesLocalCoords) { - if (leftUsesLocalCoords != rightUsesLocalCoords) { - return false; - } - - if (leftUsesLocalCoords && !left.localMatrix().cheapEqualTo(right.localMatrix())) { - return false; - } - return true; - } - - Attribute fAttribs[kMaxVertexAttribs]; - int fNumAttribs; - size_t fVertexStride; - -private: - virtual bool hasExplicitLocalCoords() const = 0; - - const SkMatrix fViewMatrix; - SkMatrix fLocalMatrix; - bool fIsPathRendering; - - typedef GrProcessor INHERITED; -}; +#include "GrPrimitiveProcessor.h" /** * A GrGeometryProcessor is a flexible method for rendering a primitive. The GrGeometryProcessor @@ -370,49 +153,4 @@ private: typedef GrPrimitiveProcessor INHERITED; }; -/* - * The path equivalent of the GP. For now this just manages color. In the long term we plan on - * extending this class to handle all nvpr uniform / varying / program work. - */ -class GrPathProcessor : public GrPrimitiveProcessor { -public: - static GrPathProcessor* Create(GrColor color, - const SkMatrix& viewMatrix = SkMatrix::I(), - const SkMatrix& localMatrix = SkMatrix::I()) { - return SkNEW_ARGS(GrPathProcessor, (color, viewMatrix, localMatrix)); - } - - void initBatchTracker(GrBatchTracker*, const GrPipelineInfo&) const SK_OVERRIDE; - - bool canMakeEqual(const GrBatchTracker& mine, - const GrPrimitiveProcessor& that, - const GrBatchTracker& theirs) const SK_OVERRIDE; - - const char* name() const SK_OVERRIDE { return "PathProcessor"; } - - GrColor color() const { return fColor; } - - void getInvariantOutputColor(GrInitInvariantOutput* out) const SK_OVERRIDE; - void getInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE; - - bool willUseGeoShader() const SK_OVERRIDE { return false; } - - virtual void getGLProcessorKey(const GrBatchTracker& bt, - const GrGLCaps& caps, - GrProcessorKeyBuilder* b) const SK_OVERRIDE; - - virtual GrGLPrimitiveProcessor* createGLInstance(const GrBatchTracker& bt, - const GrGLCaps& caps) const SK_OVERRIDE; - -protected: - GrPathProcessor(GrColor color, const SkMatrix& viewMatrix, const SkMatrix& localMatrix); - -private: - bool hasExplicitLocalCoords() const SK_OVERRIDE { return false; } - - GrColor fColor; - - typedef GrPrimitiveProcessor INHERITED; -}; - #endif diff --git a/src/gpu/GrPathProcessor.cpp b/src/gpu/GrPathProcessor.cpp new file mode 100644 index 0000000000..f6c164016e --- /dev/null +++ b/src/gpu/GrPathProcessor.cpp @@ -0,0 +1,73 @@ +#include "GrPathProcessor.h" + +#include "gl/GrGLPathProcessor.h" +#include "gl/GrGLGpu.h" + +GrPathProcessor::GrPathProcessor(GrColor color, + const SkMatrix& viewMatrix, + const SkMatrix& localMatrix) + : INHERITED(viewMatrix, localMatrix, true) + , fColor(color) { + this->initClassID<GrPathProcessor>(); +} + +void GrPathProcessor::getInvariantOutputColor(GrInitInvariantOutput* out) const { + out->setKnownFourComponents(fColor); +} + +void GrPathProcessor::getInvariantOutputCoverage(GrInitInvariantOutput* out) const { + out->setKnownSingleComponent(0xff); +} + +void GrPathProcessor::initBatchTracker(GrBatchTracker* bt, const GrPipelineInfo& init) const { + PathBatchTracker* local = bt->cast<PathBatchTracker>(); + if (init.fColorIgnored) { + local->fInputColorType = kIgnored_GrGPInput; + local->fColor = GrColor_ILLEGAL; + } else { + local->fInputColorType = kUniform_GrGPInput; + local->fColor = GrColor_ILLEGAL == init.fOverrideColor ? this->color() : + init.fOverrideColor; + } + + local->fInputCoverageType = init.fCoverageIgnored ? kIgnored_GrGPInput : kAllOnes_GrGPInput; + local->fUsesLocalCoords = init.fUsesLocalCoords; +} + +bool GrPathProcessor::canMakeEqual(const GrBatchTracker& m, + const GrPrimitiveProcessor& that, + const GrBatchTracker& t) const { + if (this->classID() != that.classID() || !this->hasSameTextureAccesses(that)) { + return false; + } + + if (!this->viewMatrix().cheapEqualTo(that.viewMatrix())) { + return false; + } + + const PathBatchTracker& mine = m.cast<PathBatchTracker>(); + const PathBatchTracker& theirs = t.cast<PathBatchTracker>(); + return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords, + that, theirs.fUsesLocalCoords) && + CanCombineOutput(mine.fInputColorType, mine.fColor, + theirs.fInputColorType, theirs.fColor) && + CanCombineOutput(mine.fInputCoverageType, 0xff, + theirs.fInputCoverageType, 0xff); +} + +void GrPathProcessor::getGLProcessorKey(const GrBatchTracker& bt, + const GrGLCaps& caps, + GrProcessorKeyBuilder* b) const { + GrGLPathProcessor::GenKey(*this, bt, caps, b); +} + +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)); + } +} diff --git a/src/gpu/GrPathProcessor.h b/src/gpu/GrPathProcessor.h new file mode 100644 index 0000000000..03d3907459 --- /dev/null +++ b/src/gpu/GrPathProcessor.h @@ -0,0 +1,65 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrPathProcessor_DEFINED +#define GrPathProcessor_DEFINED + +#include "GrPrimitiveProcessor.h" + +struct PathBatchTracker { + GrGPInput fInputColorType; + GrGPInput fInputCoverageType; + GrColor fColor; + bool fUsesLocalCoords; +}; + +/* + * The path equivalent of the GP. For now this just manages color. In the long term we plan on + * extending this class to handle all nvpr uniform / varying / program work. + */ +class GrPathProcessor : public GrPrimitiveProcessor { +public: + static GrPathProcessor* Create(GrColor color, + const SkMatrix& viewMatrix = SkMatrix::I(), + const SkMatrix& localMatrix = SkMatrix::I()) { + return SkNEW_ARGS(GrPathProcessor, (color, viewMatrix, localMatrix)); + } + + void initBatchTracker(GrBatchTracker*, const GrPipelineInfo&) const SK_OVERRIDE; + + bool canMakeEqual(const GrBatchTracker& mine, + const GrPrimitiveProcessor& that, + const GrBatchTracker& theirs) const SK_OVERRIDE; + + const char* name() const SK_OVERRIDE { return "PathProcessor"; } + + GrColor color() const { return fColor; } + + void getInvariantOutputColor(GrInitInvariantOutput* out) const SK_OVERRIDE; + void getInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE; + + bool willUseGeoShader() const SK_OVERRIDE { return false; } + + virtual void getGLProcessorKey(const GrBatchTracker& bt, + const GrGLCaps& caps, + GrProcessorKeyBuilder* b) const SK_OVERRIDE; + + virtual GrGLPrimitiveProcessor* createGLInstance(const GrBatchTracker& bt, + const GrGLCaps& caps) const SK_OVERRIDE; + +protected: + GrPathProcessor(GrColor color, const SkMatrix& viewMatrix, const SkMatrix& localMatrix); + +private: + bool hasExplicitLocalCoords() const SK_OVERRIDE { return false; } + + GrColor fColor; + + typedef GrPrimitiveProcessor INHERITED; +}; + +#endif diff --git a/src/gpu/GrPipelineBuilder.h b/src/gpu/GrPipelineBuilder.h index 5743c39dc5..c6adf870b3 100644 --- a/src/gpu/GrPipelineBuilder.h +++ b/src/gpu/GrPipelineBuilder.h @@ -11,7 +11,6 @@ #include "GrBatch.h" #include "GrBlend.h" #include "GrDrawTargetCaps.h" -#include "GrGeometryProcessor.h" #include "GrGpuResourceRef.h" #include "GrFragmentStage.h" #include "GrProcOptInfo.h" diff --git a/src/gpu/GrPrimitiveProcessor.cpp b/src/gpu/GrPrimitiveProcessor.cpp new file mode 100644 index 0000000000..673656821b --- /dev/null +++ b/src/gpu/GrPrimitiveProcessor.cpp @@ -0,0 +1,67 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrPrimitiveProcessor.h" + +#include "GrCoordTransform.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; +} diff --git a/src/gpu/GrPrimitiveProcessor.h b/src/gpu/GrPrimitiveProcessor.h new file mode 100644 index 0000000000..a088d38b61 --- /dev/null +++ b/src/gpu/GrPrimitiveProcessor.h @@ -0,0 +1,230 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrPrimitiveProcessor_DEFINED +#define GrPrimitiveProcessor_DEFINED + +#include "GrColor.h" +#include "GrProcessor.h" +#include "GrShaderVar.h" + +/* + * The GrPrimitiveProcessor represents some kind of geometric primitive. This includes the shape + * of the primitive and the inherent color of the primitive. The GrPrimitiveProcessor is + * responsible for providing a color and coverage input into the Ganesh rendering pipeline. Through + * optimization, Ganesh may decide a different color, no color, and / or no coverage are required + * from the GrPrimitiveProcessor, so the GrPrimitiveProcessor must be able to support this + * functionality. We also use the GrPrimitiveProcessor to make batching decisions. + * + * There are two feedback loops between the GrFragmentProcessors, the GrXferProcessor, and the + * GrPrimitiveProcessor. These loops run on the CPU and compute any invariant components which + * might be useful for correctness / optimization decisions. The GrPrimitiveProcessor seeds these + * loops, one with initial color and one with initial coverage, in its + * onComputeInvariantColor / Coverage calls. These seed values are processed by the subsequent + * stages of the rendering pipeline and the output is then fed back into the GrPrimitiveProcessor in + * the initBatchTracker call, where the GrPrimitiveProcessor can then initialize the GrBatchTracker + * struct with the appropriate values. + * + * We are evolving this system to move towards generating geometric meshes and their associated + * vertex data after we have batched and reordered draws. This system, known as 'deferred geometry' + * will allow the GrPrimitiveProcessor much greater control over how data is transmitted to shaders. + * + * In a deferred geometry world, the GrPrimitiveProcessor can always 'batch' To do this, each + * primitive type is associated with one GrPrimitiveProcessor, who has complete control of how + * it draws. Each primitive draw will bundle all required data to perform the draw, and these + * bundles of data will be owned by an instance of the associated GrPrimitiveProcessor. Bundles + * can be updated alongside the GrBatchTracker struct itself, ultimately allowing the + * GrPrimitiveProcessor complete control of how it gets data into the fragment shader as long as + * it emits the appropriate color, or none at all, as directed. + */ + +/* + * A struct for tracking batching decisions. While this lives on GrOptState, it is managed + * entirely by the derived classes of the GP. + * // TODO this was an early attempt at handling out of order batching. It should be + * used carefully as it is being replaced by GrBatch + */ +class GrBatchTracker { +public: + template <typename T> const T& cast() const { + SkASSERT(sizeof(T) <= kMaxSize); + return *reinterpret_cast<const T*>(fData.get()); + } + + template <typename T> T* cast() { + SkASSERT(sizeof(T) <= kMaxSize); + return reinterpret_cast<T*>(fData.get()); + } + + static const size_t kMaxSize = 32; + +private: + SkAlignedSStorage<kMaxSize> fData; +}; + +class GrIndexBufferAllocPool; +class GrGLCaps; +class GrGLPrimitiveProcessor; +class GrVertexBufferAllocPool; + +struct GrInitInvariantOutput; + +/* + * This struct allows the GrPipeline to communicate information about the pipeline. Most of this + * is overrides, but some of it is general information. Logically it should live in GrPipeline.h, + * but this is problematic due to circular dependencies. + */ +struct GrPipelineInfo { + bool fColorIgnored; + bool fCoverageIgnored; + GrColor fOverrideColor; + bool fUsesLocalCoords; +}; + +/* + * This enum is shared by GrPrimitiveProcessors and GrGLPrimitiveProcessors to coordinate shaders + * with vertex attributes / uniforms. + */ +enum GrGPInput { + kAllOnes_GrGPInput, + kAttribute_GrGPInput, + kUniform_GrGPInput, + kIgnored_GrGPInput, +}; + +/* + * GrPrimitiveProcessor defines an interface which all subclasses must implement. All + * GrPrimitiveProcessors must proivide seed color and coverage for the Ganesh color / coverage + * pipelines, and they must provide some notion of equality + */ +class GrPrimitiveProcessor : public GrProcessor { +public: + // TODO let the PrimProc itself set this in its setData call, this should really live on the + // bundle of primitive data + const SkMatrix& viewMatrix() const { return fViewMatrix; } + const SkMatrix& localMatrix() const { return fLocalMatrix; } + + virtual void initBatchTracker(GrBatchTracker*, const GrPipelineInfo&) const = 0; + + virtual bool canMakeEqual(const GrBatchTracker& mine, + const GrPrimitiveProcessor& that, + const GrBatchTracker& theirs) const = 0; + + virtual void getInvariantOutputColor(GrInitInvariantOutput* out) const = 0; + virtual void getInvariantOutputCoverage(GrInitInvariantOutput* out) const = 0; + + // Only the GrGeometryProcessor subclass actually has a geo shader or vertex attributes, but + // we put these calls on the base class to prevent having to cast + virtual bool willUseGeoShader() const = 0; + + /* + * This is a safeguard to prevent GrPrimitiveProcessor's from going beyond platform specific + * attribute limits. This number can almost certainly be raised if required. + */ + static const int kMaxVertexAttribs = 6; + + struct Attribute { + Attribute() + : fName(NULL) + , fType(kFloat_GrVertexAttribType) + , fOffset(0) {} + Attribute(const char* name, GrVertexAttribType type) + : fName(name) + , fType(type) + , fOffset(SkAlign4(GrVertexAttribTypeSize(type))) {} + const char* fName; + GrVertexAttribType fType; + size_t fOffset; + }; + + int numAttribs() const { return fNumAttribs; } + const Attribute& getAttrib(int index) const { + SkASSERT(index < fNumAttribs); + return fAttribs[index]; + } + + // Returns the vertex stride of the GP. A common use case is to request geometry from a + // drawtarget based off of the stride, and to populate this memory using an implicit array of + // structs. In this case, it is best to assert the vertexstride == sizeof(VertexStruct). + size_t getVertexStride() const { return fVertexStride; } + + /** + * Gets a transformKey from an array of coord transforms + */ + uint32_t getTransformKey(const SkTArray<const GrCoordTransform*, true>&) const; + + /** + * Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this geometry + * processor's GL backend implementation. + */ + virtual void getGLProcessorKey(const GrBatchTracker& bt, + const GrGLCaps& caps, + GrProcessorKeyBuilder* b) const = 0; + + + /** Returns a new instance of the appropriate *GL* implementation class + for the given GrProcessor; caller is responsible for deleting + the object. */ + virtual GrGLPrimitiveProcessor* createGLInstance(const GrBatchTracker& bt, + const GrGLCaps& caps) const = 0; + + bool isPathRendering() const { return fIsPathRendering; } + +protected: + GrPrimitiveProcessor(const SkMatrix& viewMatrix, const SkMatrix& localMatrix, + bool isPathRendering) + : fNumAttribs(0) + , fVertexStride(0) + , fViewMatrix(viewMatrix) + , fLocalMatrix(localMatrix) + , fIsPathRendering(isPathRendering) {} + + /* + * CanCombineOutput will return true if two draws are 'batchable' from a color perspective. + * TODO remove this when GPs can upgrade to attribute color + */ + static bool CanCombineOutput(GrGPInput left, GrColor lColor, GrGPInput right, GrColor rColor) { + if (left != right) { + return false; + } + + if (kUniform_GrGPInput == left && lColor != rColor) { + return false; + } + + return true; + } + + static bool CanCombineLocalMatrices(const GrPrimitiveProcessor& left, + bool leftUsesLocalCoords, + const GrPrimitiveProcessor& right, + bool rightUsesLocalCoords) { + if (leftUsesLocalCoords != rightUsesLocalCoords) { + return false; + } + + if (leftUsesLocalCoords && !left.localMatrix().cheapEqualTo(right.localMatrix())) { + return false; + } + return true; + } + + Attribute fAttribs[kMaxVertexAttribs]; + int fNumAttribs; + size_t fVertexStride; + +private: + virtual bool hasExplicitLocalCoords() const = 0; + + const SkMatrix fViewMatrix; + SkMatrix fLocalMatrix; + bool fIsPathRendering; + + typedef GrProcessor INHERITED; +}; + +#endif diff --git a/src/gpu/gl/GrGLGeometryProcessor.cpp b/src/gpu/gl/GrGLGeometryProcessor.cpp new file mode 100644 index 0000000000..a8d020a166 --- /dev/null +++ b/src/gpu/gl/GrGLGeometryProcessor.cpp @@ -0,0 +1,129 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrGLGeometryProcessor.h" + +#include "builders/GrGLProgramBuilder.h" + +void GrGLGeometryProcessor::emitCode(EmitArgs& args) { + GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); + GrGPArgs gpArgs; + this->onEmitCode(args, &gpArgs); + vsBuilder->transformToNormalizedDeviceSpace(gpArgs.fPositionVar); +} + +void GrGLGeometryProcessor::emitTransforms(GrGLGPBuilder* pb, + const GrShaderVar& posVar, + 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) { + if (kVec2f_GrSLType == posVar.getType()) { + vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;", + v.vsOut(), uniName, posVar.c_str()); + } else { + // The brackets here are just to scope the temp variable + vb->codeAppendf("{ vec3 temp = %s * %s;", uniName, posVar.c_str()); + vb->codeAppendf("%s = vec2(temp.x/temp.z, temp.y/temp.z); }", v.vsOut()); + } + } else { + if (kVec2f_GrSLType == posVar.getType()) { + vb->codeAppendf("%s = %s * vec3(%s, 1);", + v.vsOut(), uniName, posVar.c_str()); + } else { + vb->codeAppendf("%s = %s * %s;", v.vsOut(), uniName, posVar.c_str()); + } + } + } 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; + } + } +} + +void GrGLGeometryProcessor::SetupPosition(GrGLVertexBuilder* vsBuilder, + GrGPArgs* gpArgs, + const char* posName, + const SkMatrix& mat, + const char* matName) { + if (mat.isIdentity()) { + gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2"); + + vsBuilder->codeAppendf("vec2 %s = %s;", gpArgs->fPositionVar.c_str(), posName); + } else if (!mat.hasPerspective()) { + gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2"); + + vsBuilder->codeAppendf("vec2 %s = vec2(%s * vec3(%s, 1));", + gpArgs->fPositionVar.c_str(), matName, posName); + } else { + gpArgs->fPositionVar.set(kVec3f_GrSLType, "pos3"); + + vsBuilder->codeAppendf("vec3 %s = %s * vec3(%s, 1);", + gpArgs->fPositionVar.c_str(), matName, posName); + } +} diff --git a/src/gpu/gl/GrGLGeometryProcessor.h b/src/gpu/gl/GrGLGeometryProcessor.h index da6c347314..e8b16afe33 100644 --- a/src/gpu/gl/GrGLGeometryProcessor.h +++ b/src/gpu/gl/GrGLGeometryProcessor.h @@ -8,126 +8,10 @@ #ifndef GrGLGeometryProcessor_DEFINED #define GrGLGeometryProcessor_DEFINED -#include "GrGLProcessor.h" +#include "GrGLPrimitiveProcessor.h" -class GrBatchTracker; -class GrFragmentProcessor; -class GrGLGPBuilder; - -class GrGLPrimitiveProcessor { -public: - GrGLPrimitiveProcessor() : fViewMatrixName(NULL) { fViewMatrix = SkMatrix::InvalidMatrix(); } - virtual ~GrGLPrimitiveProcessor() {} - - typedef GrGLProgramDataManager::UniformHandle UniformHandle; - typedef GrGLProcessor::TextureSamplerArray TextureSamplerArray; - - typedef SkSTArray<2, const GrCoordTransform*, true> ProcCoords; - typedef SkSTArray<8, ProcCoords> TransformsIn; - typedef SkSTArray<8, GrGLProcessor::TransformedCoordsArray> TransformsOut; - - struct EmitArgs { - EmitArgs(GrGLGPBuilder* pb, - const GrPrimitiveProcessor& gp, - const GrBatchTracker& bt, - const char* outputColor, - const char* outputCoverage, - const TextureSamplerArray& samplers, - const TransformsIn& transformsIn, - TransformsOut* transformsOut) - : fPB(pb) - , fGP(gp) - , fBT(bt) - , fOutputColor(outputColor) - , fOutputCoverage(outputCoverage) - , fSamplers(samplers) - , fTransformsIn(transformsIn) - , fTransformsOut(transformsOut) {} - GrGLGPBuilder* fPB; - const GrPrimitiveProcessor& fGP; - const GrBatchTracker& fBT; - const char* fOutputColor; - const char* fOutputCoverage; - const TextureSamplerArray& fSamplers; - const TransformsIn& fTransformsIn; - TransformsOut* fTransformsOut; - }; - - /** - * This is similar to emitCode() in the base class, except it takes a full shader builder. - * This allows the effect subclass to emit vertex code. - */ - virtual void emitCode(EmitArgs&) = 0; - - - /** A GrGLPrimitiveProcessor instance can be reused with any GrGLPrimitiveProcessor that - produces the same stage key; this function reads data from a GrGLPrimitiveProcessor and - uploads any uniform variables required by the shaders created in emitCode(). The - GrPrimitiveProcessor parameter is guaranteed to be of the same type that created this - GrGLPrimitiveProcessor and to have an identical processor key as the one that created this - GrGLPrimitiveProcessor. */ - virtual void setData(const GrGLProgramDataManager&, - const GrPrimitiveProcessor&, - const GrBatchTracker&) = 0; - - static SkMatrix GetTransformMatrix(const SkMatrix& localMatrix, const GrCoordTransform&); - -protected: - /** a helper which can setup vertex, constant, or uniform color depending on inputType. - * This function will only do the minimum required to emit the correct shader code. If - * inputType == attribute, then colorAttr must not be NULL. Likewise, if inputType == Uniform - * then colorUniform must not be NULL. - */ - void setupColorPassThrough(GrGLGPBuilder* pb, - GrGPInput inputType, - const char* inputName, - const GrGeometryProcessor::Attribute* colorAttr, - UniformHandle* colorUniform); - - const char* uViewM() const { return fViewMatrixName; } - - /** a helper function to setup the uniform handle for the uniform view matrix */ - void addUniformViewMatrix(GrGLGPBuilder*); - - - /** a helper function to upload a uniform viewmatrix. - * TODO we can remove this function when we have deferred geometry in place - */ - void setUniformViewMatrix(const GrGLProgramDataManager&, - const SkMatrix& viewMatrix); - - class ShaderVarHandle { - public: - bool isValid() const { return fHandle > -1; } - ShaderVarHandle() : fHandle(-1) {} - ShaderVarHandle(int value) : fHandle(value) { SkASSERT(this->isValid()); } - int handle() const { SkASSERT(this->isValid()); return fHandle; } - UniformHandle convertToUniformHandle() { - SkASSERT(this->isValid()); - return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fHandle); - } - - private: - int fHandle; - }; - - struct Transform { - Transform() : fType(kVoid_GrSLType) { fCurrentValue = SkMatrix::InvalidMatrix(); } - ShaderVarHandle fHandle; - SkMatrix fCurrentValue; - GrSLType fType; - }; - - SkSTArray<8, SkSTArray<2, Transform, true> > fInstalledTransforms; - -private: - UniformHandle fViewMatrixUniform; - SkMatrix fViewMatrix; - const char* fViewMatrixName; -}; - -class GrGLPathRendering; class GrGLVertexBuilder; + /** * If a GL effect needs a GrGLFullShaderBuilder* object to emit vertex code, then it must inherit * from this class. Since paths don't have vertices, this class is only meant to be used internally @@ -189,40 +73,4 @@ private: typedef GrGLPrimitiveProcessor INHERITED; }; -class GrGLGpu; - -class GrGLPathProcessor : public GrGLPrimitiveProcessor { -public: - GrGLPathProcessor(const GrPathProcessor&, const GrBatchTracker&); - - static void GenKey(const GrPathProcessor&, - const GrBatchTracker& bt, - const GrGLCaps&, - GrProcessorKeyBuilder* b); - - void emitCode(EmitArgs&) SK_OVERRIDE; - - virtual void emitTransforms(GrGLGPBuilder*, const TransformsIn&, TransformsOut*) = 0; - - virtual void resolveSeparableVaryings(GrGLGpu* gpu, GrGLuint programId) {} - - void setData(const GrGLProgramDataManager&, - const GrPrimitiveProcessor&, - const GrBatchTracker&) SK_OVERRIDE; - - virtual void setTransformData(const GrPrimitiveProcessor&, - int index, - const SkTArray<const GrCoordTransform*, true>& transforms, - GrGLPathRendering*, - GrGLuint programID) = 0; - - virtual void didSetData(GrGLPathRendering*) {} - -private: - UniformHandle fColorUniform; - GrColor fColor; - - typedef GrGLPrimitiveProcessor INHERITED; -}; - #endif diff --git a/src/gpu/gl/GrGLPathProcessor.cpp b/src/gpu/gl/GrGLPathProcessor.cpp new file mode 100644 index 0000000000..3f3e5d9be7 --- /dev/null +++ b/src/gpu/gl/GrGLPathProcessor.cpp @@ -0,0 +1,183 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrGLPathProcessor.h" + +#include "GrPathProcessor.h" +#include "GrGLGpu.h" +#include "GrGLPathRendering.h" + +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; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +void GrGLLegacyPathProcessor::emitTransforms(GrGLGPBuilder*, const TransformsIn& tin, + TransformsOut* tout) { + 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 GrGLLegacyPathProcessor::setTransformData( + const GrPrimitiveProcessor& primProc, + int index, + const SkTArray<const GrCoordTransform*, true>& transforms, + GrGLPathRendering* glpr, + GrGLuint) { + // 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 GrGLLegacyPathProcessor::didSetData(GrGLPathRendering* glpr) { + glpr->flushPathTexGenSettings(fTexCoordSetCnt); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +void GrGLNormalPathProcessor::emitTransforms(GrGLGPBuilder* pb, const TransformsIn& tin, + TransformsOut* tout) { + 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; + + + SkString strVaryingName("MatrixCoord"); + strVaryingName.appendf("_%i_%i", i, t); + GrGLVertToFrag v(varyingType); + pb->addVarying(strVaryingName.c_str(), &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)); + } + } +} + +void GrGLNormalPathProcessor::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 GrGLNormalPathProcessor::setTransformData( + const GrPrimitiveProcessor& primProc, + int index, + const SkTArray<const GrCoordTransform*, true>& coordTransforms, + GrGLPathRendering* glpr, + GrGLuint programID) { + 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); + } +} diff --git a/src/gpu/gl/GrGLPathProcessor.h b/src/gpu/gl/GrGLPathProcessor.h new file mode 100644 index 0000000000..368f1f9fcd --- /dev/null +++ b/src/gpu/gl/GrGLPathProcessor.h @@ -0,0 +1,113 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrGLPathProcessor_DEFINED +#define GrGLPathProcessor_DEFINED + +#include "GrGLPrimitiveProcessor.h" + +class GrPathProcessor; +class GrGLPathRendering; +class GrGLGpu; + +class GrGLPathProcessor : public GrGLPrimitiveProcessor { +public: + GrGLPathProcessor(const GrPathProcessor&, const GrBatchTracker&); + + static void GenKey(const GrPathProcessor&, + const GrBatchTracker& bt, + const GrGLCaps&, + GrProcessorKeyBuilder* b); + + void emitCode(EmitArgs&) SK_OVERRIDE; + + virtual void emitTransforms(GrGLGPBuilder*, const TransformsIn&, TransformsOut*) = 0; + + virtual void resolveSeparableVaryings(GrGLGpu* gpu, GrGLuint programId) {} + + void setData(const GrGLProgramDataManager&, + const GrPrimitiveProcessor&, + const GrBatchTracker&) SK_OVERRIDE; + + virtual void setTransformData(const GrPrimitiveProcessor&, + int index, + const SkTArray<const GrCoordTransform*, true>& transforms, + GrGLPathRendering*, + GrGLuint programID) = 0; + + virtual void didSetData(GrGLPathRendering*) {} + +private: + UniformHandle fColorUniform; + GrColor fColor; + + typedef GrGLPrimitiveProcessor INHERITED; +}; + +class GrGLLegacyPathProcessor : public GrGLPathProcessor { +public: + GrGLLegacyPathProcessor(const GrPathProcessor& pathProc, const GrBatchTracker& bt, + int maxTexCoords) + : INHERITED(pathProc, bt) + , fTexCoordSetCnt(0) { + SkDEBUGCODE(fMaxTexCoords = maxTexCoords;) + } + + int addTexCoordSets(int count) { + int firstFreeCoordSet = fTexCoordSetCnt; + fTexCoordSetCnt += count; + SkASSERT(fMaxTexCoords >= fTexCoordSetCnt); + return firstFreeCoordSet; + } + + void emitTransforms(GrGLGPBuilder*, const TransformsIn& tin, TransformsOut* tout) SK_OVERRIDE; + + void setTransformData(const GrPrimitiveProcessor& primProc, + int index, + const SkTArray<const GrCoordTransform*, true>& transforms, + GrGLPathRendering* glpr, + GrGLuint) SK_OVERRIDE; + + void didSetData(GrGLPathRendering* glpr) SK_OVERRIDE; + +private: + SkDEBUGCODE(int fMaxTexCoords;) + int fTexCoordSetCnt; + + typedef GrGLPathProcessor INHERITED; +}; + +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; + + void resolveSeparableVaryings(GrGLGpu* gpu, GrGLuint programId); + + void setTransformData(const GrPrimitiveProcessor& primProc, + int index, + const SkTArray<const GrCoordTransform*, true>& coordTransforms, + GrGLPathRendering* glpr, + GrGLuint programID) SK_OVERRIDE; + +private: + struct SeparableVaryingInfo { + GrSLType fType; + GrGLShaderVar fVariable; + GrGLint fLocation; + }; + + typedef SkSTArray<8, SeparableVaryingInfo, true> SeparableVaryingInfoArray; + + SeparableVaryingInfoArray fSeparableVaryingInfos; + + typedef GrGLPathProcessor INHERITED; +}; + +#endif diff --git a/src/gpu/gl/GrGLPrimitiveProcessor.cpp b/src/gpu/gl/GrGLPrimitiveProcessor.cpp new file mode 100644 index 0000000000..335dc4fe5f --- /dev/null +++ b/src/gpu/gl/GrGLPrimitiveProcessor.cpp @@ -0,0 +1,75 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrGLPrimitiveProcessor.h" + +#include "builders/GrGLProgramBuilder.h" + +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::Attribute* colorAttr, + UniformHandle* colorUniform) { + GrGLGPFragmentBuilder* fs = pb->getFragmentShaderBuilder(); + if (kUniform_GrGPInput == inputType) { + SkASSERT(colorUniform); + const char* stagedLocalVarName; + *colorUniform = pb->addUniform(GrGLProgramBuilder::kFragment_Visibility, + kVec4f_GrSLType, + kDefault_GrSLPrecision, + "Color", + &stagedLocalVarName); + fs->codeAppendf("%s = %s;", outputName, stagedLocalVarName); + } else if (kAttribute_GrGPInput == inputType) { + SkASSERT(colorAttr); + pb->addPassThroughAttribute(colorAttr, outputName); + } else if (kAllOnes_GrGPInput == inputType) { + fs->codeAppendf("%s = vec4(1);", outputName); + } +} + +void GrGLPrimitiveProcessor::addUniformViewMatrix(GrGLGPBuilder* pb) { + fViewMatrixUniform = pb->addUniform(GrGLProgramBuilder::kVertex_Visibility, + kMat33f_GrSLType, kDefault_GrSLPrecision, + "uViewM", + &fViewMatrixName); +} + +void GrGLPrimitiveProcessor::setUniformViewMatrix(const GrGLProgramDataManager& pdman, + const SkMatrix& viewMatrix) { + if (!fViewMatrix.cheapEqualTo(viewMatrix)) { + SkASSERT(fViewMatrixUniform.isValid()); + fViewMatrix = viewMatrix; + + GrGLfloat viewMatrix[3 * 3]; + GrGLGetMatrix<3>(viewMatrix, fViewMatrix); + pdman.setMatrix3f(fViewMatrixUniform, viewMatrix); + } +} diff --git a/src/gpu/gl/GrGLPrimitiveProcessor.h b/src/gpu/gl/GrGLPrimitiveProcessor.h new file mode 100644 index 0000000000..30b1c178cd --- /dev/null +++ b/src/gpu/gl/GrGLPrimitiveProcessor.h @@ -0,0 +1,130 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrGLPrimitiveProcessor_DEFINED +#define GrGLPrimitiveProcessor_DEFINED + +#include "GrPrimitiveProcessor.h" +#include "GrGLProcessor.h" + +class GrBatchTracker; +class GrPrimitiveProcessor; +class GrGLGPBuilder; + +class GrGLPrimitiveProcessor { +public: + GrGLPrimitiveProcessor() : fViewMatrixName(NULL) { fViewMatrix = SkMatrix::InvalidMatrix(); } + virtual ~GrGLPrimitiveProcessor() {} + + typedef GrGLProgramDataManager::UniformHandle UniformHandle; + typedef GrGLProcessor::TextureSamplerArray TextureSamplerArray; + + typedef SkSTArray<2, const GrCoordTransform*, true> ProcCoords; + typedef SkSTArray<8, ProcCoords> TransformsIn; + typedef SkSTArray<8, GrGLProcessor::TransformedCoordsArray> TransformsOut; + + struct EmitArgs { + EmitArgs(GrGLGPBuilder* pb, + const GrPrimitiveProcessor& gp, + const GrBatchTracker& bt, + const char* outputColor, + const char* outputCoverage, + const TextureSamplerArray& samplers, + const TransformsIn& transformsIn, + TransformsOut* transformsOut) + : fPB(pb) + , fGP(gp) + , fBT(bt) + , fOutputColor(outputColor) + , fOutputCoverage(outputCoverage) + , fSamplers(samplers) + , fTransformsIn(transformsIn) + , fTransformsOut(transformsOut) {} + GrGLGPBuilder* fPB; + const GrPrimitiveProcessor& fGP; + const GrBatchTracker& fBT; + const char* fOutputColor; + const char* fOutputCoverage; + const TextureSamplerArray& fSamplers; + const TransformsIn& fTransformsIn; + TransformsOut* fTransformsOut; + }; + + /** + * This is similar to emitCode() in the base class, except it takes a full shader builder. + * This allows the effect subclass to emit vertex code. + */ + virtual void emitCode(EmitArgs&) = 0; + + + /** A GrGLPrimitiveProcessor instance can be reused with any GrGLPrimitiveProcessor that + produces the same stage key; this function reads data from a GrGLPrimitiveProcessor and + uploads any uniform variables required by the shaders created in emitCode(). The + GrPrimitiveProcessor parameter is guaranteed to be of the same type that created this + GrGLPrimitiveProcessor and to have an identical processor key as the one that created this + GrGLPrimitiveProcessor. */ + virtual void setData(const GrGLProgramDataManager&, + const GrPrimitiveProcessor&, + const GrBatchTracker&) = 0; + + static SkMatrix GetTransformMatrix(const SkMatrix& localMatrix, const GrCoordTransform&); + +protected: + /** a helper which can setup vertex, constant, or uniform color depending on inputType. + * This function will only do the minimum required to emit the correct shader code. If + * inputType == attribute, then colorAttr must not be NULL. Likewise, if inputType == Uniform + * then colorUniform must not be NULL. + */ + void setupColorPassThrough(GrGLGPBuilder* pb, + GrGPInput inputType, + const char* inputName, + const GrPrimitiveProcessor::Attribute* colorAttr, + UniformHandle* colorUniform); + + const char* uViewM() const { return fViewMatrixName; } + + /** a helper function to setup the uniform handle for the uniform view matrix */ + void addUniformViewMatrix(GrGLGPBuilder*); + + + /** a helper function to upload a uniform viewmatrix. + * TODO we can remove this function when we have deferred geometry in place + */ + void setUniformViewMatrix(const GrGLProgramDataManager&, + const SkMatrix& viewMatrix); + + class ShaderVarHandle { + public: + bool isValid() const { return fHandle > -1; } + ShaderVarHandle() : fHandle(-1) {} + ShaderVarHandle(int value) : fHandle(value) { SkASSERT(this->isValid()); } + int handle() const { SkASSERT(this->isValid()); return fHandle; } + UniformHandle convertToUniformHandle() { + SkASSERT(this->isValid()); + return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fHandle); + } + + private: + int fHandle; + }; + + struct Transform { + Transform() : fType(kVoid_GrSLType) { fCurrentValue = SkMatrix::InvalidMatrix(); } + ShaderVarHandle fHandle; + SkMatrix fCurrentValue; + GrSLType fType; + }; + + SkSTArray<8, SkSTArray<2, Transform, true> > fInstalledTransforms; + +private: + UniformHandle fViewMatrixUniform; + SkMatrix fViewMatrix; + const char* fViewMatrixName; +}; + +#endif diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index eebcf6b2f3..2f6b784b40 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -11,12 +11,12 @@ #include "GrProcessor.h" #include "GrCoordTransform.h" #include "GrGLGeometryProcessor.h" -#include "GrGLProcessor.h" -#include "GrGLXferProcessor.h" #include "GrGLGpu.h" +#include "GrGLPathProcessor.h" #include "GrGLPathRendering.h" #include "GrGLShaderVar.h" #include "GrGLSL.h" +#include "GrGLXferProcessor.h" #include "GrPipeline.h" #include "GrXferProcessor.h" #include "SkXfermode.h" diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp index bb278be395..5a623033fb 100644 --- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp +++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp @@ -6,11 +6,14 @@ */ #include "GrGLProgramBuilder.h" + +#include "gl/GrGLGeometryProcessor.h" +#include "gl/GrGLGpu.h" +#include "gl/GrGLPathProcessor.h" #include "gl/GrGLProgram.h" #include "gl/GrGLSLPrettyPrint.h" #include "gl/GrGLUniformHandle.h" -#include "../GrGLXferProcessor.h" -#include "../GrGLGpu.h" +#include "gl/GrGLXferProcessor.h" #include "GrCoordTransform.h" #include "GrGLProgramBuilder.h" #include "GrTexture.h" diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.h b/src/gpu/gl/builders/GrGLProgramBuilder.h index a9288cc9b0..37908f9971 100644 --- a/src/gpu/gl/builders/GrGLProgramBuilder.h +++ b/src/gpu/gl/builders/GrGLProgramBuilder.h @@ -13,7 +13,7 @@ #include "GrGLVertexShaderBuilder.h" #include "../GrGLProgramDataManager.h" #include "../GrGLUniformHandle.h" -#include "../GrGLGeometryProcessor.h" +#include "../GrGLPrimitiveProcessor.h" #include "../GrGLXferProcessor.h" #include "../../GrPendingFragmentStage.h" #include "../../GrPipeline.h" |