From 79f8faeea2692d2948c0f634e956d1e7fc8333e0 Mon Sep 17 00:00:00 2001 From: joshualitt Date: Tue, 28 Oct 2014 17:59:26 -0700 Subject: [PATCH] OptState owns program descriptor BUG=skia: Review URL: https://codereview.chromium.org/674543004 --- gyp/gpu.gypi | 1 + src/gpu/GrGpu.h | 7 + src/gpu/GrOptDrawState.cpp | 129 +++++----- src/gpu/GrOptDrawState.h | 117 ++------- src/gpu/GrProgramDesc.h | 269 +++++++++++++++++++++ src/gpu/gl/GrGLProgram.cpp | 24 +- src/gpu/gl/GrGLProgram.h | 12 +- src/gpu/gl/GrGLProgramDesc.cpp | 88 +++---- src/gpu/gl/GrGLProgramDesc.h | 216 ++++------------- src/gpu/gl/GrGpuGL.cpp | 1 + src/gpu/gl/GrGpuGL.h | 13 +- src/gpu/gl/GrGpuGL_program.cpp | 53 ++-- src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp | 14 +- src/gpu/gl/builders/GrGLFragmentShaderBuilder.h | 2 +- src/gpu/gl/builders/GrGLGeometryShaderBuilder.cpp | 2 +- .../gl/builders/GrGLLegacyNvprProgramBuilder.cpp | 7 +- src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.h | 2 +- src/gpu/gl/builders/GrGLNvprProgramBuilder.cpp | 5 +- src/gpu/gl/builders/GrGLNvprProgramBuilder.h | 2 +- src/gpu/gl/builders/GrGLProgramBuilder.cpp | 56 ++--- src/gpu/gl/builders/GrGLProgramBuilder.h | 20 +- src/gpu/gl/builders/GrGLShaderBuilder.h | 1 + src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp | 2 +- tests/GLProgramsTest.cpp | 28 +-- 24 files changed, 562 insertions(+), 509 deletions(-) create mode 100644 src/gpu/GrProgramDesc.h diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi index 033d51c..9db1d7f 100644 --- a/gyp/gpu.gypi +++ b/gyp/gpu.gypi @@ -114,6 +114,7 @@ '<(skia_src_path)/gpu/GrPathRendering.h', '<(skia_src_path)/gpu/GrPathUtils.cpp', '<(skia_src_path)/gpu/GrPathUtils.h', + '<(skia_src_path)/gpu/GrProgramDesc.h', '<(skia_src_path)/gpu/GrProgramElement.cpp', '<(skia_src_path)/gpu/GrProcessor.cpp', '<(skia_src_path)/gpu/GrGpuResourceRef.cpp', diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h index 9478530..6814ae9 100644 --- a/src/gpu/GrGpu.h +++ b/src/gpu/GrGpu.h @@ -11,6 +11,7 @@ #include "GrDrawTarget.h" #include "GrClipMaskManager.h" #include "GrPathRendering.h" +#include "GrProgramDesc.h" #include "SkPath.h" class GrContext; @@ -324,6 +325,12 @@ public: GrContext::GPUStats* gpuStats() { return &fGPUStats; } + virtual void buildProgramDesc(const GrOptDrawState&, + const GrProgramDesc::DescInfo&, + GrGpu::DrawType, + const GrDeviceCoordTexture* dstCopy, + GrProgramDesc*) = 0; + protected: DrawType PrimTypeToDrawType(GrPrimitiveType type) { switch (type) { diff --git a/src/gpu/GrOptDrawState.cpp b/src/gpu/GrOptDrawState.cpp index 77a9fc8..529e9ed 100644 --- a/src/gpu/GrOptDrawState.cpp +++ b/src/gpu/GrOptDrawState.cpp @@ -9,12 +9,15 @@ #include "GrDrawState.h" #include "GrDrawTargetCaps.h" +#include "gl/GrGpuGL.h" GrOptDrawState::GrOptDrawState(const GrDrawState& drawState, BlendOptFlags blendOptFlags, GrBlendCoeff optSrcCoeff, GrBlendCoeff optDstCoeff, - const GrDrawTargetCaps& caps) { + GrGpu* gpu, + const GrDeviceCoordTexture* dstCopy, + GrGpu::DrawType drawType) { fRenderTarget.set(SkSafeRef(drawState.getRenderTarget()), kWrite_GrIOType); fColor = drawState.getColor(); fCoverage = drawState.getCoverage(); @@ -29,13 +32,14 @@ GrOptDrawState::GrOptDrawState(const GrDrawState& drawState, fBlendOptFlags = blendOptFlags; fSrcBlend = optSrcCoeff; fDstBlend = optDstCoeff; + GrProgramDesc::DescInfo descInfo; - memcpy(fFixedFunctionVertexAttribIndices, + memcpy(descInfo.fFixedFunctionVertexAttribIndices, drawState.getFixedFunctionVertexAttribIndices(), - sizeof(fFixedFunctionVertexAttribIndices)); + sizeof(descInfo.fFixedFunctionVertexAttribIndices)); - fInputColorIsUsed = true; - fInputCoverageIsUsed = true; + descInfo.fInputColorIsUsed = true; + descInfo.fInputCoverageIsUsed = true; int firstColorStageIdx = 0; int firstCoverageStageIdx = 0; @@ -43,16 +47,18 @@ GrOptDrawState::GrOptDrawState(const GrDrawState& drawState, uint8_t fixedFunctionVAToRemove = 0; - this->computeEffectiveColorStages(drawState, &firstColorStageIdx, &fixedFunctionVAToRemove); - this->computeEffectiveCoverageStages(drawState, &firstCoverageStageIdx); - this->adjustFromBlendOpts(drawState, &firstColorStageIdx, &firstCoverageStageIdx, + this->computeEffectiveColorStages(drawState, &descInfo, &firstColorStageIdx, + &fixedFunctionVAToRemove); + this->computeEffectiveCoverageStages(drawState, &descInfo, &firstCoverageStageIdx); + this->adjustFromBlendOpts(drawState, &descInfo, &firstColorStageIdx, &firstCoverageStageIdx, &fixedFunctionVAToRemove); // Should not be setting any more FFVA to be removed at this point if (0 != fixedFunctionVAToRemove) { - this->removeFixedFunctionVertexAttribs(fixedFunctionVAToRemove); + this->removeFixedFunctionVertexAttribs(fixedFunctionVAToRemove, &descInfo); } - this->getStageStats(drawState, firstColorStageIdx, firstCoverageStageIdx); - this->setOutputStateInfo(drawState, caps, firstCoverageStageIdx, &separateCoverageFromColor); + this->getStageStats(drawState, firstColorStageIdx, firstCoverageStageIdx, &descInfo); + this->setOutputStateInfo(drawState, *gpu->caps(), firstCoverageStageIdx, &descInfo, + &separateCoverageFromColor); // Copy GeometryProcesssor from DS or ODS if (drawState.hasGeometryProcessor()) { @@ -79,10 +85,16 @@ GrOptDrawState::GrOptDrawState(const GrDrawState& drawState, fNumColorStages = fFragmentStages.count(); } } + + // now create a key + gpu->buildProgramDesc(*this, descInfo, drawType, dstCopy, &fDesc); }; -GrOptDrawState* GrOptDrawState::Create(const GrDrawState& drawState, const GrDrawTargetCaps& caps, +GrOptDrawState* GrOptDrawState::Create(const GrDrawState& drawState, + GrGpu* gpu, + const GrDeviceCoordTexture* dstCopy, GrGpu::DrawType drawType) { + const GrDrawTargetCaps& caps = *gpu->caps(); if (NULL == drawState.fCachedOptState || caps.getUniqueID() != drawState.fCachedCapsID) { GrBlendCoeff srcCoeff; GrBlendCoeff dstCoeff; @@ -100,7 +112,7 @@ GrOptDrawState* GrOptDrawState::Create(const GrDrawState& drawState, const GrDra } drawState.fCachedOptState = SkNEW_ARGS(GrOptDrawState, (drawState, blendFlags, srcCoeff, - dstCoeff, caps)); + dstCoeff, gpu, dstCopy, drawType)); drawState.fCachedCapsID = caps.getUniqueID(); } else { #ifdef SK_DEBUG @@ -109,8 +121,8 @@ GrOptDrawState* GrOptDrawState::Create(const GrDrawState& drawState, const GrDra BlendOptFlags blendFlags = (BlendOptFlags) drawState.getBlendOpts(false, &srcCoeff, &dstCoeff); - SkASSERT(GrOptDrawState(drawState, blendFlags, srcCoeff, dstCoeff, caps) == - *drawState.fCachedOptState); + SkASSERT(GrOptDrawState(drawState, blendFlags, srcCoeff, dstCoeff, gpu, dstCopy, + drawType) == *drawState.fCachedOptState); #endif } drawState.fCachedOptState->ref(); @@ -120,45 +132,47 @@ GrOptDrawState* GrOptDrawState::Create(const GrDrawState& drawState, const GrDra void GrOptDrawState::setOutputStateInfo(const GrDrawState& ds, const GrDrawTargetCaps& caps, int firstCoverageStageIdx, + GrProgramDesc::DescInfo* descInfo, bool* separateCoverageFromColor) { // Set this default and then possibly change our mind if there is coverage. - fPrimaryOutputType = kModulate_PrimaryOutputType; - fSecondaryOutputType = kNone_SecondaryOutputType; + descInfo->fPrimaryOutputType = GrProgramDesc::kModulate_PrimaryOutputType; + descInfo->fSecondaryOutputType = GrProgramDesc::kNone_SecondaryOutputType; // If we do have coverage determine whether it matters. *separateCoverageFromColor = this->hasGeometryProcessor(); if (!this->isCoverageDrawing() && (ds.numCoverageStages() - firstCoverageStageIdx > 0 || ds.hasGeometryProcessor() || - this->hasCoverageVertexAttribute())) { + descInfo->hasCoverageVertexAttribute())) { if (caps.dualSourceBlendingSupport()) { if (kZero_GrBlendCoeff == fDstBlend) { // write the coverage value to second color - fSecondaryOutputType = kCoverage_SecondaryOutputType; + descInfo->fSecondaryOutputType = GrProgramDesc::kCoverage_SecondaryOutputType; *separateCoverageFromColor = true; fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff; } else if (kSA_GrBlendCoeff == fDstBlend) { // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered. - fSecondaryOutputType = kCoverageISA_SecondaryOutputType; + descInfo->fSecondaryOutputType = GrProgramDesc::kCoverageISA_SecondaryOutputType; *separateCoverageFromColor = true; fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff; } else if (kSC_GrBlendCoeff == fDstBlend) { // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered. - fSecondaryOutputType = kCoverageISC_SecondaryOutputType; + descInfo->fSecondaryOutputType = GrProgramDesc::kCoverageISC_SecondaryOutputType; *separateCoverageFromColor = true; fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff; } - } else if (fReadsDst && + } else if (descInfo->fReadsDst && kOne_GrBlendCoeff == fSrcBlend && kZero_GrBlendCoeff == fDstBlend) { - fPrimaryOutputType = kCombineWithDst_PrimaryOutputType; + descInfo->fPrimaryOutputType = GrProgramDesc::kCombineWithDst_PrimaryOutputType; *separateCoverageFromColor = true; } } } void GrOptDrawState::adjustFromBlendOpts(const GrDrawState& ds, + GrProgramDesc::DescInfo* descInfo, int* firstColorStageIdx, int* firstCoverageStageIdx, uint8_t* fixedFunctionVAToRemove) { @@ -171,15 +185,15 @@ void GrOptDrawState::adjustFromBlendOpts(const GrDrawState& ds, break; case kEmitCoverage_BlendOptFlag: fColor = 0xffffffff; - fInputColorIsUsed = true; + descInfo->fInputColorIsUsed = true; *firstColorStageIdx = ds.numColorStages(); *fixedFunctionVAToRemove |= 0x1 << kColor_GrVertexAttribBinding; break; case kEmitTransBlack_BlendOptFlag: fColor = 0; fCoverage = 0xff; - fInputColorIsUsed = true; - fInputCoverageIsUsed = true; + descInfo->fInputColorIsUsed = true; + descInfo->fInputCoverageIsUsed = true; *firstColorStageIdx = ds.numColorStages(); *firstCoverageStageIdx = ds.numCoverageStages(); *fixedFunctionVAToRemove |= (0x1 << kColor_GrVertexAttribBinding | @@ -190,12 +204,13 @@ void GrOptDrawState::adjustFromBlendOpts(const GrDrawState& ds, } } -void GrOptDrawState::removeFixedFunctionVertexAttribs(uint8_t removeVAFlag) { +void GrOptDrawState::removeFixedFunctionVertexAttribs(uint8_t removeVAFlag, + GrProgramDesc::DescInfo* descInfo) { int numToRemove = 0; uint8_t maskCheck = 0x1; // Count the number of vertex attributes that we will actually remove for (int i = 0; i < kGrFixedFunctionVertexAttribBindingCnt; ++i) { - if ((maskCheck & removeVAFlag) && -1 != fFixedFunctionVertexAttribIndices[i]) { + if ((maskCheck & removeVAFlag) && -1 != descInfo->fFixedFunctionVertexAttribIndices[i]) { ++numToRemove; } maskCheck <<= 1; @@ -211,11 +226,11 @@ void GrOptDrawState::removeFixedFunctionVertexAttribs(uint8_t removeVAFlag) { if (currAttrib.fBinding < kGrFixedFunctionVertexAttribBindingCnt) { uint8_t maskCheck = 0x1 << currAttrib.fBinding; if (maskCheck & removeVAFlag) { - SkASSERT(-1 != fFixedFunctionVertexAttribIndices[currAttrib.fBinding]); - fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = -1; + SkASSERT(-1 != descInfo->fFixedFunctionVertexAttribIndices[currAttrib.fBinding]); + descInfo->fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = -1; continue; } - fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = newIdx; + descInfo->fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = newIdx; } memcpy(dst, src, sizeof(GrVertexAttrib)); ++newIdx; @@ -225,12 +240,14 @@ void GrOptDrawState::removeFixedFunctionVertexAttribs(uint8_t removeVAFlag) { fVAPtr = fOptVA.get(); } -void GrOptDrawState::computeEffectiveColorStages(const GrDrawState& ds, int* firstColorStageIdx, +void GrOptDrawState::computeEffectiveColorStages(const GrDrawState& ds, + GrProgramDesc::DescInfo* descInfo, + int* firstColorStageIdx, uint8_t* fixedFunctionVAToRemove) { // Set up color and flags for ConstantColorComponent checks GrProcessor::InvariantOutput inout; inout.fIsSingleComponent = false; - if (!this->hasColorVertexAttribute()) { + if (!descInfo->hasColorVertexAttribute()) { inout.fColor = ds.getColor(); inout.fValidFlags = kRGBA_GrColorComponentFlags; } else { @@ -249,12 +266,12 @@ void GrOptDrawState::computeEffectiveColorStages(const GrDrawState& ds, int* fir fp->computeInvariantOutput(&inout); if (!inout.fWillUseInputColor) { *firstColorStageIdx = i; - fInputColorIsUsed = false; + descInfo->fInputColorIsUsed = false; } if (kRGBA_GrColorComponentFlags == inout.fValidFlags) { *firstColorStageIdx = i + 1; fColor = inout.fColor; - fInputColorIsUsed = true; + descInfo->fInputColorIsUsed = true; *fixedFunctionVAToRemove |= 0x1 << kColor_GrVertexAttribBinding; // Since we are clearing all previous color stages we are in a state where we have found // zero stages that don't multiply the inputColor. @@ -264,6 +281,7 @@ void GrOptDrawState::computeEffectiveColorStages(const GrDrawState& ds, int* fir } void GrOptDrawState::computeEffectiveCoverageStages(const GrDrawState& ds, + GrProgramDesc::DescInfo* descInfo, int* firstCoverageStageIdx) { // We do not try to optimize out constantColor coverage effects here. It is extremely rare // to have a coverage effect that returns a constant value for all four channels. Thus we @@ -278,7 +296,7 @@ void GrOptDrawState::computeEffectiveCoverageStages(const GrDrawState& ds, fp->computeInvariantOutput(&inout); if (!inout.fWillUseInputColor) { *firstCoverageStageIdx = i; - fInputCoverageIsUsed = false; + descInfo->fInputCoverageIsUsed = false; } } #endif @@ -294,26 +312,26 @@ static void get_stage_stats(const GrFragmentStage& stage, bool* readsDst, bool* } void GrOptDrawState::getStageStats(const GrDrawState& ds, int firstColorStageIdx, - int firstCoverageStageIdx) { + int firstCoverageStageIdx, GrProgramDesc::DescInfo* descInfo) { // We will need a local coord attrib if there is one currently set on the optState and we are // actually generating some effect code - fRequiresLocalCoordAttrib = this->hasLocalCoordAttribute() && + descInfo->fRequiresLocalCoordAttrib = descInfo->hasLocalCoordAttribute() && ds.numTotalStages() - firstColorStageIdx - firstCoverageStageIdx > 0; - fReadsDst = false; - fReadsFragPosition = false; + descInfo->fReadsDst = false; + descInfo->fReadsFragPosition = false; for (int s = firstColorStageIdx; s < ds.numColorStages(); ++s) { const GrFragmentStage& stage = ds.getColorStage(s); - get_stage_stats(stage, &fReadsDst, &fReadsFragPosition); + get_stage_stats(stage, &descInfo->fReadsDst, &descInfo->fReadsFragPosition); } for (int s = firstCoverageStageIdx; s < ds.numCoverageStages(); ++s) { const GrFragmentStage& stage = ds.getCoverageStage(s); - get_stage_stats(stage, &fReadsDst, &fReadsFragPosition); + get_stage_stats(stage, &descInfo->fReadsDst, &descInfo->fReadsFragPosition); } if (ds.hasGeometryProcessor()) { const GrGeometryProcessor& gp = *ds.getGeometryProcessor(); - fReadsFragPosition = fReadsFragPosition || gp.willReadFragmentPosition(); + descInfo->fReadsFragPosition = descInfo->fReadsFragPosition || gp.willReadFragmentPosition(); } } @@ -324,14 +342,15 @@ bool GrOptDrawState::operator== (const GrOptDrawState& that) const { } bool GrOptDrawState::isEqual(const GrOptDrawState& that) const { - bool usingVertexColors = this->hasColorVertexAttribute(); + if (this->fDesc != that.fDesc) { + return false; + } + bool usingVertexColors = that.fDesc.header().fColorAttributeIndex != -1; if (!usingVertexColors && this->fColor != that.fColor) { return false; } if (this->getRenderTarget() != that.getRenderTarget() || - this->fFragmentStages.count() != that.fFragmentStages.count() || - this->fNumColorStages != that.fNumColorStages || !this->fViewMatrix.cheapEqualTo(that.fViewMatrix) || this->fSrcBlend != that.fSrcBlend || this->fDstBlend != that.fDstBlend || @@ -341,23 +360,15 @@ bool GrOptDrawState::isEqual(const GrOptDrawState& that) const { this->fVAStride != that.fVAStride || memcmp(this->fVAPtr, that.fVAPtr, this->fVACount * sizeof(GrVertexAttrib)) || this->fStencilSettings != that.fStencilSettings || - this->fDrawFace != that.fDrawFace || - this->fInputColorIsUsed != that.fInputColorIsUsed || - this->fInputCoverageIsUsed != that.fInputCoverageIsUsed || - this->fReadsDst != that.fReadsDst || - this->fReadsFragPosition != that.fReadsFragPosition || - this->fRequiresLocalCoordAttrib != that.fRequiresLocalCoordAttrib || - this->fPrimaryOutputType != that.fPrimaryOutputType || - this->fSecondaryOutputType != that.fSecondaryOutputType) { + this->fDrawFace != that.fDrawFace) { return false; } - bool usingVertexCoverage = this->hasCoverageVertexAttribute(); + bool usingVertexCoverage = this->fDesc.header().fCoverageAttributeIndex != -1; if (!usingVertexCoverage && this->fCoverage != that.fCoverage) { return false; } - bool explicitLocalCoords = this->hasLocalCoordAttribute(); if (this->hasGeometryProcessor()) { if (!that.hasGeometryProcessor()) { return false; @@ -368,17 +379,13 @@ bool GrOptDrawState::isEqual(const GrOptDrawState& that) const { return false; } + bool explicitLocalCoords = this->fDesc.header().fLocalCoordAttributeIndex != -1; for (int i = 0; i < this->numFragmentStages(); i++) { if (!GrFragmentStage::AreCompatible(this->getFragmentStage(i), that.getFragmentStage(i), explicitLocalCoords)) { return false; } } - - SkASSERT(0 == memcmp(this->fFixedFunctionVertexAttribIndices, - that.fFixedFunctionVertexAttribIndices, - sizeof(this->fFixedFunctionVertexAttribIndices))); - return true; } diff --git a/src/gpu/GrOptDrawState.h b/src/gpu/GrOptDrawState.h index f47913a..f495b89 100644 --- a/src/gpu/GrOptDrawState.h +++ b/src/gpu/GrOptDrawState.h @@ -11,11 +11,13 @@ #include "GrColor.h" #include "GrGpu.h" #include "GrProcessorStage.h" +#include "GrProgramDesc.h" #include "GrStencil.h" #include "GrTypesPriv.h" #include "SkMatrix.h" #include "SkRefCnt.h" +class GrDeviceCoordTexture; class GrDrawState; /** @@ -30,8 +32,8 @@ public: * GrOptDrawState. In all cases the GrOptDrawState is reffed and ownership is given to the * caller. */ - static GrOptDrawState* Create(const GrDrawState& drawState, const GrDrawTargetCaps& caps, - GrGpu::DrawType drawType); + static GrOptDrawState* Create(const GrDrawState& drawState, GrGpu*, + const GrDeviceCoordTexture* dstCopy, GrGpu::DrawType drawType); bool operator== (const GrOptDrawState& that) const; @@ -48,35 +50,6 @@ public: size_t getVertexStride() const { return fVAStride; } - /** - * Getters for index into getVertexAttribs() for particular bindings. -1 is returned if the - * binding does not appear in the current attribs. These bindings should appear only once in - * the attrib array. - */ - - int positionAttributeIndex() const { - return fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]; - } - int localCoordAttributeIndex() const { - return fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding]; - } - int colorVertexAttributeIndex() const { - return fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding]; - } - int coverageVertexAttributeIndex() const { - return fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding]; - } - - bool hasLocalCoordAttribute() const { - return -1 != fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding]; - } - bool hasColorVertexAttribute() const { - return -1 != fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding]; - } - bool hasCoverageVertexAttribute() const { - return -1 != fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding]; - } - /// @} /////////////////////////////////////////////////////////////////////////// @@ -299,48 +272,10 @@ public: kB_CombinedState, }; - bool inputColorIsUsed() const { return fInputColorIsUsed; } - bool inputCoverageIsUsed() const { return fInputCoverageIsUsed; } - - bool readsDst() const { return fReadsDst; } - bool readsFragPosition() const { return fReadsFragPosition; } - bool requiresLocalCoordAttrib() const { return fRequiresLocalCoordAttrib; } - - /////////////////////////////////////////////////////////////////////////// - /// @name Stage Output Types - //// - - enum PrimaryOutputType { - // Modulate color and coverage, write result as the color output. - kModulate_PrimaryOutputType, - // Combines the coverage, dst, and color as coverage * color + (1 - coverage) * dst. This - // can only be set if fDstReadKey is non-zero. - kCombineWithDst_PrimaryOutputType, - - kPrimaryOutputTypeCnt, - }; - - enum SecondaryOutputType { - // There is no secondary output - kNone_SecondaryOutputType, - // Writes coverage as the secondary output. Only set if dual source blending is supported - // and primary output is kModulate. - kCoverage_SecondaryOutputType, - // Writes coverage * (1 - colorA) as the secondary output. Only set if dual source blending - // is supported and primary output is kModulate. - kCoverageISA_SecondaryOutputType, - // Writes coverage * (1 - colorRGBA) as the secondary output. Only set if dual source - // blending is supported and primary output is kModulate. - kCoverageISC_SecondaryOutputType, - - kSecondaryOutputTypeCnt, - }; - - PrimaryOutputType getPrimaryOutputType() const { return fPrimaryOutputType; } - SecondaryOutputType getSecondaryOutputType() const { return fSecondaryOutputType; } - /// @} + const GrProgramDesc& programDesc() const { return fDesc; } + private: /** * Optimizations for blending / coverage to that can be applied based on the current state. @@ -376,7 +311,7 @@ private: */ GrOptDrawState(const GrDrawState& drawState, BlendOptFlags blendOptFlags, GrBlendCoeff optSrcCoeff, GrBlendCoeff optDstCoeff, - const GrDrawTargetCaps& caps); + GrGpu*, const GrDeviceCoordTexture* dstCopy, GrGpu::DrawType); /** * Loops through all the color stage effects to check if the stage will ignore color input or @@ -384,35 +319,38 @@ private: * stages. In the constant color case, we can ignore all previous stages and * the current one and set the state color to the constant color. */ - void computeEffectiveColorStages(const GrDrawState& ds, int* firstColorStageIdx, - uint8_t* fixFunctionVAToRemove); + void computeEffectiveColorStages(const GrDrawState& ds, GrProgramDesc::DescInfo*, + int* firstColorStageIdx, uint8_t* fixFunctionVAToRemove); /** * Loops through all the coverage stage effects to check if the stage will ignore color input. * If a coverage stage will ignore input, then we can ignore all coverage stages before it. We * loop to determine the first effective coverage stage. */ - void computeEffectiveCoverageStages(const GrDrawState& ds, int* firstCoverageStageIdx); + void computeEffectiveCoverageStages(const GrDrawState& ds, GrProgramDesc::DescInfo* descInfo, + int* firstCoverageStageIdx); /** * This function takes in a flag and removes the corresponding fixed function vertex attributes. * The flags are in the same order as GrVertexAttribBinding array. If bit i of removeVAFlags is * set, then vertex attributes with binding (GrVertexAttribute)i will be removed. */ - void removeFixedFunctionVertexAttribs(uint8_t removeVAFlags); + void removeFixedFunctionVertexAttribs(uint8_t removeVAFlags, GrProgramDesc::DescInfo*); /** * Alter the OptDrawState (adjusting stages, vertex attribs, flags, etc.) based on the * BlendOptFlags. */ - void adjustFromBlendOpts(const GrDrawState& ds, int* firstColorStageIdx, - int* firstCoverageStageIdx, uint8_t* fixedFunctionVAToRemove); + void adjustFromBlendOpts(const GrDrawState& ds, GrProgramDesc::DescInfo*, + int* firstColorStageIdx, int* firstCoverageStageIdx, + uint8_t* fixedFunctionVAToRemove); /** * Loop over the effect stages to determine various info like what data they will read and what * shaders they require. */ - void getStageStats(const GrDrawState& ds, int firstColorStageIdx, int firstCoverageStageIdx); + void getStageStats(const GrDrawState& ds, int firstColorStageIdx, int firstCoverageStageIdx, + GrProgramDesc::DescInfo*); /** * Calculates the primary and secondary output types of the shader. For certain output types @@ -420,7 +358,8 @@ private: * blend coeffs will represent those used by backend API. */ void setOutputStateInfo(const GrDrawState& ds, const GrDrawTargetCaps&, - int firstCoverageStageIdx, bool* separateCoverageFromColor); + int firstCoverageStageIdx, GrProgramDesc::DescInfo*, + bool* separateCoverageFromColor); bool isEqual(const GrOptDrawState& that) const; @@ -448,27 +387,11 @@ private: // This function is equivalent to the offset into fFragmentStages where coverage stages begin. int fNumColorStages; - // This is simply a different representation of info in fVertexAttribs and thus does - // not need to be compared in op==. - int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt]; - - // These flags are needed to protect the code from creating an unused uniform color/coverage - // which will cause shader compiler errors. - bool fInputColorIsUsed; - bool fInputCoverageIsUsed; - - // These flags give aggregated info on the effect stages that are used when building programs. - bool fReadsDst; - bool fReadsFragPosition; - bool fRequiresLocalCoordAttrib; - SkAutoSTArray<4, GrVertexAttrib> fOptVA; BlendOptFlags fBlendOptFlags; - // Fragment shader color outputs - PrimaryOutputType fPrimaryOutputType : 8; - SecondaryOutputType fSecondaryOutputType : 8; + GrProgramDesc fDesc; typedef SkRefCnt INHERITED; }; diff --git a/src/gpu/GrProgramDesc.h b/src/gpu/GrProgramDesc.h new file mode 100644 index 0000000..cc8a38a --- /dev/null +++ b/src/gpu/GrProgramDesc.h @@ -0,0 +1,269 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrProgramDesc_DEFINED +#define GrProgramDesc_DEFINED + +#include "GrBackendProcessorFactory.h" +#include "GrColor.h" +#include "GrTypesPriv.h" +#include "SkChecksum.h" + +class GrGpuGL; + +/** This class describes a program to generate. It also serves as a program cache key. Very little + of this is GL-specific. The GL-specific parts could be factored out into a subclass. */ +class GrProgramDesc { +public: + // Creates an uninitialized key that must be populated by GrGpu::buildProgramDesc() + GrProgramDesc() {} + + // Returns this as a uint32_t array to be used as a key in the program cache. + const uint32_t* asKey() const { + return reinterpret_cast(fKey.begin()); + } + + // Gets the number of bytes in asKey(). It will be a 4-byte aligned value. When comparing two + // keys the size of either key can be used with memcmp() since the lengths themselves begin the + // keys and thus the memcmp will exit early if the keys are of different lengths. + uint32_t keyLength() const { return *this->atOffset(); } + + // Gets the a checksum of the key. Can be used as a hash value for a fast lookup in a cache. + uint32_t getChecksum() const { return *this->atOffset(); } + + GrProgramDesc& operator= (const GrProgramDesc& other) { + size_t keyLength = other.keyLength(); + fKey.reset(keyLength); + memcpy(fKey.begin(), other.fKey.begin(), keyLength); + return *this; + } + + bool operator== (const GrProgramDesc& other) const { + // The length is masked as a hint to the compiler that the address will be 4 byte aligned. + return 0 == memcmp(this->asKey(), other.asKey(), this->keyLength() & ~0x3); + } + + bool operator!= (const GrProgramDesc& other) const { + return !(*this == other); + } + + static bool Less(const GrProgramDesc& a, const GrProgramDesc& b) { + return memcmp(a.asKey(), b.asKey(), a.keyLength() & ~0x3) < 0; + } + + + /////////////////////////////////////////////////////////////////////////// + /// @name Stage Output Types + //// + + enum PrimaryOutputType { + // Modulate color and coverage, write result as the color output. + kModulate_PrimaryOutputType, + // Combines the coverage, dst, and color as coverage * color + (1 - coverage) * dst. This + // can only be set if fDstReadKey is non-zero. + kCombineWithDst_PrimaryOutputType, + + kPrimaryOutputTypeCnt, + }; + + enum SecondaryOutputType { + // There is no secondary output + kNone_SecondaryOutputType, + // Writes coverage as the secondary output. Only set if dual source blending is supported + // and primary output is kModulate. + kCoverage_SecondaryOutputType, + // Writes coverage * (1 - colorA) as the secondary output. Only set if dual source blending + // is supported and primary output is kModulate. + kCoverageISA_SecondaryOutputType, + // Writes coverage * (1 - colorRGBA) as the secondary output. Only set if dual source + // blending is supported and primary output is kModulate. + kCoverageISC_SecondaryOutputType, + + kSecondaryOutputTypeCnt, + }; + + // Specifies where the initial color comes from before the stages are applied. + enum ColorInput { + kAllOnes_ColorInput, + kAttribute_ColorInput, + kUniform_ColorInput, + + kColorInputCnt + }; + + struct KeyHeader { + uint8_t fDstReadKey; // set by GrGLShaderBuilder if there + // are effects that must read the dst. + // Otherwise, 0. + uint8_t fFragPosKey; // set by GrGLShaderBuilder if there are + // effects that read the fragment position. + // Otherwise, 0. + + SkBool8 fEmitsPointSize; + + ColorInput fColorInput : 8; + ColorInput fCoverageInput : 8; + + PrimaryOutputType fPrimaryOutputType : 8; + SecondaryOutputType fSecondaryOutputType : 8; + + int8_t fPositionAttributeIndex; + int8_t fLocalCoordAttributeIndex; + int8_t fColorAttributeIndex; + int8_t fCoverageAttributeIndex; + + SkBool8 fHasGeometryProcessor; + int8_t fColorEffectCnt; + int8_t fCoverageEffectCnt; + }; + + + bool hasGeometryProcessor() const { + return SkToBool(this->header().fHasGeometryProcessor); + } + + int numColorEffects() const { + return this->header().fColorEffectCnt; + } + + int numCoverageEffects() const { + return this->header().fCoverageEffectCnt; + } + + int numTotalEffects() const { return this->numColorEffects() + this->numCoverageEffects(); } + + // This should really only be used internally, base classes should return their own headers + const KeyHeader& header() const { return *this->atOffset(); } + + /** Used to provide effects' keys to their emitCode() function. */ + class ProcKeyProvider { + public: + enum ProcessorType { + kGeometry_ProcessorType, + kFragment_ProcessorType, + }; + + ProcKeyProvider(const GrProgramDesc* desc, ProcessorType type, int effectOffset) + : fDesc(desc), fBaseIndex(0), fEffectOffset(effectOffset) { + switch (type) { + case kGeometry_ProcessorType: + // there can be only one + fBaseIndex = 0; + break; + case kFragment_ProcessorType: + fBaseIndex = desc->hasGeometryProcessor() ? 1 : 0; + break; + } + } + + GrProcessorKey get(int index) const { + const uint16_t* offsetsAndLengths = reinterpret_cast( + fDesc->fKey.begin() + fEffectOffset); + // We store two uint16_ts per effect, one for the offset to the effect's key and one for + // its length. Here we just need the offset. + uint16_t offset = offsetsAndLengths[2 * (fBaseIndex + index) + 0]; + uint16_t length = offsetsAndLengths[2 * (fBaseIndex + index) + 1]; + // Currently effects must add to the key in units of uint32_t. + SkASSERT(0 == (length % sizeof(uint32_t))); + return GrProcessorKey(reinterpret_cast(fDesc->fKey.begin() + offset), + length / sizeof(uint32_t)); + } + private: + const GrProgramDesc* fDesc; + int fBaseIndex; + int fEffectOffset; + }; + + // A struct to communicate descriptor information to the program descriptor builder + struct DescInfo { + int positionAttributeIndex() const { + return fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]; + } + int localCoordAttributeIndex() const { + return fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding]; + } + int colorVertexAttributeIndex() const { + return fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding]; + } + int coverageVertexAttributeIndex() const { + return fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding]; + } + bool hasLocalCoordAttribute() const { + return -1 != fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding]; + } + bool hasColorVertexAttribute() const { + return -1 != fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding]; + } + bool hasCoverageVertexAttribute() const { + return -1 != fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding]; + } + + int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt]; + + // These flags are needed to protect the code from creating an unused uniform color/coverage + // which will cause shader compiler errors. + bool fInputColorIsUsed; + bool fInputCoverageIsUsed; + + // These flags give aggregated info on the processor stages that are used when building + // programs. + bool fReadsDst; + bool fReadsFragPosition; + bool fRequiresLocalCoordAttrib; + + // Fragment shader color outputs + GrProgramDesc::PrimaryOutputType fPrimaryOutputType : 8; + GrProgramDesc::SecondaryOutputType fSecondaryOutputType : 8; + }; + +private: + template T* atOffset() { + return reinterpret_cast(reinterpret_cast(fKey.begin()) + OFFSET); + } + + template const T* atOffset() const { + return reinterpret_cast(reinterpret_cast(fKey.begin()) + OFFSET); + } + + void finalize() { + int keyLength = fKey.count(); + SkASSERT(0 == (keyLength % 4)); + *(this->atOffset()) = SkToU32(keyLength); + + uint32_t* checksum = this->atOffset(); + *checksum = 0; + *checksum = SkChecksum::Compute(reinterpret_cast(fKey.begin()), keyLength); + } + + // The key, stored in fKey, is composed of four parts: + // 1. uint32_t for total key length. + // 2. uint32_t for a checksum. + // 3. Header struct defined above. Also room for extensions to the header + // 4. A Backend specific payload. Room is preallocated for this + enum KeyOffsets { + // Part 1. + kLengthOffset = 0, + // Part 2. + kChecksumOffset = kLengthOffset + sizeof(uint32_t), + // Part 3. + kHeaderOffset = kChecksumOffset + sizeof(uint32_t), + kHeaderSize = SkAlign4(2 * sizeof(KeyHeader)), + }; + + enum { + kMaxPreallocProcessors = 8, + kIntsPerProcessor = 4, // This is an overestimate of the average effect key size. + kPreAllocSize = kHeaderOffset + kHeaderSize + + kMaxPreallocProcessors * sizeof(uint32_t) * kIntsPerProcessor, + }; + + SkSTArray fKey; + + friend class GrGLProgramDescBuilder; +}; + +#endif diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index bfa5f3c..f152173 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -56,7 +56,7 @@ static SkMatrix get_transform_matrix(const GrFragmentStage& processorStage, /////////////////////////////////////////////////////////////////////////////////////////////////// GrGLProgram::GrGLProgram(GrGpuGL* gpu, - const GrGLProgramDesc& desc, + const GrProgramDesc& desc, const BuiltinUniformHandles& builtinUniforms, GrGLuint programID, const UniformInfoArray& uniforms, @@ -201,12 +201,12 @@ void GrGLProgram::didSetData(GrGpu::DrawType drawType) { } void GrGLProgram::setColor(const GrOptDrawState& optState, GrColor color) { - const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader(); + const GrProgramDesc::KeyHeader& header = fDesc.header(); switch (header.fColorInput) { - case GrGLProgramDesc::kAttribute_ColorInput: + case GrProgramDesc::kAttribute_ColorInput: // Attribute case is handled in GrGpuGL::setupGeometry break; - case GrGLProgramDesc::kUniform_ColorInput: + case GrProgramDesc::kUniform_ColorInput: if (fColor != color && fBuiltinUniformHandles.fColorUni.isValid()) { // OpenGL ES doesn't support unsigned byte varieties of glUniform GrGLfloat c[4]; @@ -215,7 +215,7 @@ void GrGLProgram::setColor(const GrOptDrawState& optState, GrColor color) { fColor = color; } break; - case GrGLProgramDesc::kAllOnes_ColorInput: + case GrProgramDesc::kAllOnes_ColorInput: // Handled by shader creation break; default: @@ -224,12 +224,12 @@ void GrGLProgram::setColor(const GrOptDrawState& optState, GrColor color) { } void GrGLProgram::setCoverage(const GrOptDrawState& optState, GrColor coverage) { - const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader(); + const GrProgramDesc::KeyHeader& header = fDesc.header(); switch (header.fCoverageInput) { - case GrGLProgramDesc::kAttribute_ColorInput: + case GrProgramDesc::kAttribute_ColorInput: // Attribute case is handled in GrGpuGL::setupGeometry break; - case GrGLProgramDesc::kUniform_ColorInput: + case GrProgramDesc::kUniform_ColorInput: if (fCoverage != coverage) { // OpenGL ES doesn't support unsigned byte varieties of glUniform GrGLfloat c[4]; @@ -238,7 +238,7 @@ void GrGLProgram::setCoverage(const GrOptDrawState& optState, GrColor coverage) fCoverage = coverage; } break; - case GrGLProgramDesc::kAllOnes_ColorInput: + case GrProgramDesc::kAllOnes_ColorInput: // Handled by shader creation break; default: @@ -286,7 +286,7 @@ void GrGLProgram::onSetMatrixAndRenderTargetHeight(GrGpu::DrawType drawType, ///////////////////////////////////////////////////////////////////////////////////////// GrGLNvprProgramBase::GrGLNvprProgramBase(GrGpuGL* gpu, - const GrGLProgramDesc& desc, + const GrProgramDesc& desc, const BuiltinUniformHandles& builtinUniforms, GrGLuint programID, const UniformInfoArray& uniforms, @@ -306,7 +306,7 @@ void GrGLNvprProgramBase::onSetMatrixAndRenderTargetHeight(GrGpu::DrawType drawT ///////////////////////////////////////////////////////////////////////////////////////// GrGLNvprProgram::GrGLNvprProgram(GrGpuGL* gpu, - const GrGLProgramDesc& desc, + const GrProgramDesc& desc, const BuiltinUniformHandles& builtinUniforms, GrGLuint programID, const UniformInfoArray& uniforms, @@ -355,7 +355,7 @@ void GrGLNvprProgram::setTransformData(const GrFragmentStage& proc, GrGLInstalle ////////////////////////////////////////////////////////////////////////////////////// GrGLLegacyNvprProgram::GrGLLegacyNvprProgram(GrGpuGL* gpu, - const GrGLProgramDesc& desc, + const GrProgramDesc& desc, const BuiltinUniformHandles& builtinUniforms, GrGLuint programID, const UniformInfoArray& uniforms, diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h index ca75e20..d7a7cf8 100644 --- a/src/gpu/gl/GrGLProgram.h +++ b/src/gpu/gl/GrGLProgram.h @@ -47,7 +47,7 @@ public: */ void abandon(); - const GrGLProgramDesc& getDesc() { return fDesc; } + const GrProgramDesc& getDesc() { return fDesc; } /** * Gets the GL program ID for this program. @@ -138,7 +138,7 @@ protected: typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray; GrGLProgram(GrGpuGL*, - const GrGLProgramDesc&, + const GrProgramDesc&, const BuiltinUniformHandles&, GrGLuint programID, const UniformInfoArray&, @@ -184,7 +184,7 @@ protected: SkAutoTDelete fGeometryProcessor; SkAutoTUnref fFragmentProcessors; - GrGLProgramDesc fDesc; + GrProgramDesc fDesc; GrGpuGL* fGpu; GrGLProgramDataManager fProgramDataManager; @@ -203,7 +203,7 @@ protected: class GrGLNvprProgramBase : public GrGLProgram { protected: GrGLNvprProgramBase(GrGpuGL*, - const GrGLProgramDesc&, + const GrProgramDesc&, const BuiltinUniformHandles&, GrGLuint programID, const UniformInfoArray&, @@ -221,7 +221,7 @@ private: typedef GrGLNvprProgramBuilder::SeparableVaryingInfo SeparableVaryingInfo; typedef GrGLNvprProgramBuilder::SeparableVaryingInfoArray SeparableVaryingInfoArray; GrGLNvprProgram(GrGpuGL*, - const GrGLProgramDesc&, + const GrProgramDesc&, const BuiltinUniformHandles&, GrGLuint programID, const UniformInfoArray&, @@ -249,7 +249,7 @@ public: private: GrGLLegacyNvprProgram(GrGpuGL* gpu, - const GrGLProgramDesc& desc, + const GrProgramDesc& desc, const BuiltinUniformHandles&, GrGLuint programID, const UniformInfoArray&, diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp index 4a274c6..4a182b3 100644 --- a/src/gpu/gl/GrGLProgramDesc.cpp +++ b/src/gpu/gl/GrGLProgramDesc.cpp @@ -4,15 +4,15 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ - -#include "gl/builders/GrGLFragmentShaderBuilder.h" #include "GrGLProgramDesc.h" + +#include "GrGLProcessor.h" #include "GrBackendProcessorFactory.h" #include "GrProcessor.h" #include "GrGpuGL.h" #include "GrOptDrawState.h" - #include "SkChecksum.h" +#include "gl/builders/GrGLFragmentShaderBuilder.h" /** * The key for an individual coord transform is made up of a matrix type and a bit that @@ -176,10 +176,10 @@ struct FragmentProcessorKeyBuilder { template bool -GrGLProgramDesc::BuildStagedProcessorKey(const typename ProcessorKeyBuilder::StagedProcessor& stage, +GrGLProgramDescBuilder::BuildStagedProcessorKey(const typename ProcessorKeyBuilder::StagedProcessor& stage, const GrGLCaps& caps, bool requiresLocalCoordAttrib, - GrGLProgramDesc* desc, + GrProgramDesc* desc, int* offsetAndSizeIndex) { GrProcessorKeyBuilder b(&desc->fKey); uint16_t processorKeySize; @@ -192,7 +192,7 @@ GrGLProgramDesc::BuildStagedProcessorKey(const typename ProcessorKeyBuilder::Sta } uint16_t* offsetAndSize = - reinterpret_cast(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset + + reinterpret_cast(desc->fKey.begin() + kProcessorKeyOffsetsAndLengthOffset + *offsetAndSizeIndex * 2 * sizeof(uint16_t)); offsetAndSize[0] = SkToU16(processorOffset); offsetAndSize[1] = processorKeySize; @@ -200,27 +200,28 @@ GrGLProgramDesc::BuildStagedProcessorKey(const typename ProcessorKeyBuilder::Sta return true; } -bool GrGLProgramDesc::Build(const GrOptDrawState& optState, +bool GrGLProgramDescBuilder::Build(const GrOptDrawState& optState, + const GrProgramDesc::DescInfo& descInfo, GrGpu::DrawType drawType, GrGpuGL* gpu, const GrDeviceCoordTexture* dstCopy, - GrGLProgramDesc* desc) { - bool inputColorIsUsed = optState.inputColorIsUsed(); - bool inputCoverageIsUsed = optState.inputCoverageIsUsed(); + GrProgramDesc* desc) { + bool inputColorIsUsed = descInfo.fInputColorIsUsed; + bool inputCoverageIsUsed = descInfo.fInputCoverageIsUsed; // The descriptor is used as a cache key. Thus when a field of the // descriptor will not affect program generation (because of the attribute // bindings in use or other descriptor field settings) it should be set // to a canonical value to avoid duplicate programs with different keys. - bool requiresLocalCoordAttrib = optState.requiresLocalCoordAttrib(); + bool requiresLocalCoordAttrib = descInfo.fRequiresLocalCoordAttrib; int numStages = optState.numTotalStages(); - GR_STATIC_ASSERT(0 == kEffectKeyOffsetsAndLengthOffset % sizeof(uint32_t)); + GR_STATIC_ASSERT(0 == kProcessorKeyOffsetsAndLengthOffset % sizeof(uint32_t)); // Make room for everything up to and including the array of offsets to effect keys. desc->fKey.reset(); - desc->fKey.push_back_n(kEffectKeyOffsetsAndLengthOffset + 2 * sizeof(uint16_t) * numStages); + desc->fKey.push_back_n(kProcessorKeyOffsetsAndLengthOffset + 2 * sizeof(uint16_t) * numStages); int offsetAndSizeIndex = 0; @@ -248,7 +249,7 @@ bool GrGLProgramDesc::Build(const GrOptDrawState& optState, // --------DO NOT MOVE HEADER ABOVE THIS LINE-------------------------------------------------- // Because header is a pointer into the dynamic array, we can't push any new data into the key // below here. - KeyHeader* header = desc->header(); + GLKeyHeader* header = desc->atOffset(); // make sure any padding in the header is zeroed. memset(header, 0, kHeaderSize); @@ -266,33 +267,33 @@ bool GrGLProgramDesc::Build(const GrOptDrawState& optState, } bool hasUniformColor = inputColorIsUsed && - (isPathRendering || !optState.hasColorVertexAttribute()); + (isPathRendering || !descInfo.hasColorVertexAttribute()); bool hasUniformCoverage = inputCoverageIsUsed && - (isPathRendering || !optState.hasCoverageVertexAttribute()); + (isPathRendering || !descInfo.hasCoverageVertexAttribute()); if (!inputColorIsUsed) { - header->fColorInput = kAllOnes_ColorInput; + header->fColorInput = GrProgramDesc::kAllOnes_ColorInput; } else if (hasUniformColor) { - header->fColorInput = kUniform_ColorInput; + header->fColorInput = GrProgramDesc::kUniform_ColorInput; } else { - header->fColorInput = kAttribute_ColorInput; + header->fColorInput = GrProgramDesc::kAttribute_ColorInput; SkASSERT(!header->fUseNvpr); } - bool covIsSolidWhite = !optState.hasCoverageVertexAttribute() && + bool covIsSolidWhite = !descInfo.hasCoverageVertexAttribute() && 0xffffffff == optState.getCoverageColor(); if (covIsSolidWhite || !inputCoverageIsUsed) { - header->fCoverageInput = kAllOnes_ColorInput; + header->fCoverageInput = GrProgramDesc::kAllOnes_ColorInput; } else if (hasUniformCoverage) { - header->fCoverageInput = kUniform_ColorInput; + header->fCoverageInput = GrProgramDesc::kUniform_ColorInput; } else { - header->fCoverageInput = kAttribute_ColorInput; + header->fCoverageInput = GrProgramDesc::kAttribute_ColorInput; SkASSERT(!header->fUseNvpr); } - if (optState.readsDst()) { + if (descInfo.fReadsDst) { SkASSERT(dstCopy || gpu->caps()->dstReadInShaderSupport()); const GrTexture* dstCopyTexture = NULL; if (dstCopy) { @@ -305,7 +306,7 @@ bool GrGLProgramDesc::Build(const GrOptDrawState& optState, header->fDstReadKey = 0; } - if (optState.readsFragPosition()) { + if (descInfo.fReadsFragPosition) { header->fFragPosKey = GrGLFragmentShaderBuilder::KeyForFragmentPosition(optState.getRenderTarget(), gpu->glCaps()); @@ -314,14 +315,14 @@ bool GrGLProgramDesc::Build(const GrOptDrawState& optState, } // Record attribute indices - header->fPositionAttributeIndex = optState.positionAttributeIndex(); - header->fLocalCoordAttributeIndex = optState.localCoordAttributeIndex(); + header->fPositionAttributeIndex = descInfo.positionAttributeIndex(); + header->fLocalCoordAttributeIndex = descInfo.localCoordAttributeIndex(); // For constant color and coverage we need an attribute with an index beyond those already set int availableAttributeIndex = optState.getVertexAttribCount(); - if (optState.hasColorVertexAttribute()) { - header->fColorAttributeIndex = optState.colorVertexAttributeIndex(); - } else if (GrGLProgramDesc::kAttribute_ColorInput == header->fColorInput) { + if (descInfo.hasColorVertexAttribute()) { + header->fColorAttributeIndex = descInfo.colorVertexAttributeIndex(); + } else if (GrProgramDesc::kAttribute_ColorInput == header->fColorInput) { SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt); header->fColorAttributeIndex = availableAttributeIndex; availableAttributeIndex++; @@ -329,37 +330,20 @@ bool GrGLProgramDesc::Build(const GrOptDrawState& optState, header->fColorAttributeIndex = -1; } - if (optState.hasCoverageVertexAttribute()) { - header->fCoverageAttributeIndex = optState.coverageVertexAttributeIndex(); - } else if (GrGLProgramDesc::kAttribute_ColorInput == header->fCoverageInput) { + if (descInfo.hasCoverageVertexAttribute()) { + header->fCoverageAttributeIndex = descInfo.coverageVertexAttributeIndex(); + } else if (GrProgramDesc::kAttribute_ColorInput == header->fCoverageInput) { SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt); header->fCoverageAttributeIndex = availableAttributeIndex; } else { header->fCoverageAttributeIndex = -1; } - header->fPrimaryOutputType = optState.getPrimaryOutputType(); - header->fSecondaryOutputType = optState.getSecondaryOutputType(); + header->fPrimaryOutputType = descInfo.fPrimaryOutputType; + header->fSecondaryOutputType = descInfo.fSecondaryOutputType; header->fColorEffectCnt = optState.numColorStages(); header->fCoverageEffectCnt = optState.numCoverageStages(); desc->finalize(); return true; } - -void GrGLProgramDesc::finalize() { - int keyLength = fKey.count(); - SkASSERT(0 == (keyLength % 4)); - *this->atOffset() = SkToU32(keyLength); - - uint32_t* checksum = this->atOffset(); - *checksum = 0; - *checksum = SkChecksum::Compute(reinterpret_cast(fKey.begin()), keyLength); -} - -GrGLProgramDesc& GrGLProgramDesc::operator= (const GrGLProgramDesc& other) { - size_t keyLength = other.keyLength(); - fKey.reset(keyLength); - memcpy(fKey.begin(), other.fKey.begin(), keyLength); - return *this; -} diff --git a/src/gpu/gl/GrGLProgramDesc.h b/src/gpu/gl/GrGLProgramDesc.h index d97bdfd..8bfd506 100644 --- a/src/gpu/gl/GrGLProgramDesc.h +++ b/src/gpu/gl/GrGLProgramDesc.h @@ -8,112 +8,24 @@ #ifndef GrGLProgramDesc_DEFINED #define GrGLProgramDesc_DEFINED -#include "GrGLProcessor.h" -#include "GrDrawState.h" +#include "GrColor.h" +#include "GrProgramDesc.h" #include "GrGpu.h" -#include "GrOptDrawState.h" +#include "GrTypesPriv.h" class GrGpuGL; -/** This class describes a program to generate. It also serves as a program cache key. Very little - of this is GL-specific. The GL-specific parts could be factored out into a subclass. */ -class GrGLProgramDesc { +/** + * This class can be used to build a GrProgramDesc. It also provides helpers for accessing + * GL specific info in the header. + */ +class GrGLProgramDescBuilder { public: - GrGLProgramDesc() {} - GrGLProgramDesc(const GrGLProgramDesc& desc) { *this = desc; } - - // Returns this as a uint32_t array to be used as a key in the program cache. - const uint32_t* asKey() const { - return reinterpret_cast(fKey.begin()); - } - - // Gets the number of bytes in asKey(). It will be a 4-byte aligned value. When comparing two - // keys the size of either key can be used with memcmp() since the lengths themselves begin the - // keys and thus the memcmp will exit early if the keys are of different lengths. - uint32_t keyLength() const { return *this->atOffset(); } - - // Gets the a checksum of the key. Can be used as a hash value for a fast lookup in a cache. - uint32_t getChecksum() const { return *this->atOffset(); } - - /** - * Builds a program descriptor from a GrOptDrawState. Whether the primitive type is points, and - * the caps of the GrGpuGL are also inputs. It also outputs the color and coverage stages - * referenced by the generated descriptor. Coverage stages from the drawState may be treated as - * color stages in the output. - */ - static bool Build(const GrOptDrawState&, - GrGpu::DrawType, - GrGpuGL*, - const GrDeviceCoordTexture*, - GrGLProgramDesc*); - - bool hasGeometryProcessor() const { - return SkToBool(this->getHeader().fHasGeometryProcessor); - } - - int numColorEffects() const { - return this->getHeader().fColorEffectCnt; - } - - int numCoverageEffects() const { - return this->getHeader().fCoverageEffectCnt; - } - - int numTotalEffects() const { return this->numColorEffects() + this->numCoverageEffects(); } - - GrGLProgramDesc& operator= (const GrGLProgramDesc& other); - - bool operator== (const GrGLProgramDesc& other) const { - // The length is masked as a hint to the compiler that the address will be 4 byte aligned. - return 0 == memcmp(this->asKey(), other.asKey(), this->keyLength() & ~0x3); - } - - bool operator!= (const GrGLProgramDesc& other) const { - return !(*this == other); - } - - static bool Less(const GrGLProgramDesc& a, const GrGLProgramDesc& b) { - return memcmp(a.asKey(), b.asKey(), a.keyLength() & ~0x3) < 0; - } - -private: - // Specifies where the initial color comes from before the stages are applied. - enum ColorInput { - kAllOnes_ColorInput, - kAttribute_ColorInput, - kUniform_ColorInput, - - kColorInputCnt + struct GLKeyHeader : public GrProgramDesc::KeyHeader { + SkBool8 fUseNvpr; }; - struct KeyHeader { - uint8_t fDstReadKey; // set by GrGLShaderBuilder if there - // are effects that must read the dst. - // Otherwise, 0. - uint8_t fFragPosKey; // set by GrGLShaderBuilder if there are - // effects that read the fragment position. - // Otherwise, 0. - - SkBool8 fUseNvpr; - SkBool8 fEmitsPointSize; - - ColorInput fColorInput : 8; - ColorInput fCoverageInput : 8; - - GrOptDrawState::PrimaryOutputType fPrimaryOutputType : 8; - GrOptDrawState::SecondaryOutputType fSecondaryOutputType : 8; - - int8_t fPositionAttributeIndex; - int8_t fLocalCoordAttributeIndex; - int8_t fColorAttributeIndex; - int8_t fCoverageAttributeIndex; - - SkBool8 fHasGeometryProcessor; - int8_t fColorEffectCnt; - int8_t fCoverageEffectCnt; - }; - - // The key, stored in fKey, is composed of five parts: + // The key, stored in fKey, is composed of five parts(first 2 are defined in the key itself): // 1. uint32_t for total key length. // 2. uint32_t for a checksum. // 3. Header struct defined above. @@ -121,95 +33,49 @@ private: // offset and size. // 5. per-effect keys. Each effect's key is a variable length array of uint32_t. enum { - // Part 1. - kLengthOffset = 0, - // Part 2. - kChecksumOffset = kLengthOffset + sizeof(uint32_t), // Part 3. - kHeaderOffset = kChecksumOffset + sizeof(uint32_t), - kHeaderSize = SkAlign4(sizeof(KeyHeader)), + kHeaderOffset = GrProgramDesc::kHeaderOffset, + kHeaderSize = SkAlign4(sizeof(GLKeyHeader)), // Part 4. // This is the offset in the overall key to the array of per-effect offset,length pairs. - kEffectKeyOffsetsAndLengthOffset = kHeaderOffset + kHeaderSize, + kProcessorKeyOffsetsAndLengthOffset = kHeaderOffset + kHeaderSize, }; - template T* atOffset() { - return reinterpret_cast(reinterpret_cast(fKey.begin()) + OFFSET); - } + /** + * Builds a GL specific program descriptor + * + * @param GrOptDrawState The optimized drawstate. The descriptor will represent a program + * which this optstate can use to draw with. The optstate contains + * general draw information, as well as the specific color, geometry, + * and coverage stages which will be used to generate the GL Program for + * this optstate. + * @param DescInfo A descriptor info struct, generated by the optstate, which contains a number + * of important facts about the program the built descriptor will represent + * @param DrawType + * @param GrGpuGL A GL Gpu, the caps and Gpu object are used to output processor specific + * parts of the descriptor. + * @param GrDeviceCoordTexture A dstCopy texture, which may be null if frame buffer fetch is + * supported + * @param GrProgramDesc The built and finalized descriptor + **/ + static bool Build(const GrOptDrawState&, + const GrProgramDesc::DescInfo&, + GrGpu::DrawType, + GrGpuGL*, + const GrDeviceCoordTexture*, + GrProgramDesc*); - template const T* atOffset() const { - return reinterpret_cast(reinterpret_cast(fKey.begin()) + OFFSET); + static const GLKeyHeader& GetHeader(const GrProgramDesc& desc) { + return *desc.atOffset(); } - KeyHeader* header() { return this->atOffset(); } - - // a helper class to handle getting an individual processor's key +private: template static bool BuildStagedProcessorKey(const typename ProcessorKeyBuilder::StagedProcessor& stage, const GrGLCaps& caps, bool requiresLocalCoordAttrib, - GrGLProgramDesc* desc, + GrProgramDesc* desc, int* offsetAndSizeIndex); - void finalize(); - - const KeyHeader& getHeader() const { return *this->atOffset(); } - - /** Used to provide effects' keys to their emitCode() function. */ - class ProcKeyProvider { - public: - enum ProcessorType { - kGeometry_ProcessorType, - kFragment_ProcessorType, - }; - - ProcKeyProvider(const GrGLProgramDesc* desc, ProcessorType type) - : fDesc(desc), fBaseIndex(0) { - switch (type) { - case kGeometry_ProcessorType: - // there can be only one - fBaseIndex = 0; - break; - case kFragment_ProcessorType: - fBaseIndex = desc->hasGeometryProcessor() ? 1 : 0; - break; - } - } - - GrProcessorKey get(int index) const { - const uint16_t* offsetsAndLengths = reinterpret_cast( - fDesc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset); - // We store two uint16_ts per effect, one for the offset to the effect's key and one for - // its length. Here we just need the offset. - uint16_t offset = offsetsAndLengths[2 * (fBaseIndex + index) + 0]; - uint16_t length = offsetsAndLengths[2 * (fBaseIndex + index) + 1]; - // Currently effects must add to the key in units of uint32_t. - SkASSERT(0 == (length % sizeof(uint32_t))); - return GrProcessorKey(reinterpret_cast(fDesc->fKey.begin() + offset), - length / sizeof(uint32_t)); - } - private: - const GrGLProgramDesc* fDesc; - int fBaseIndex; - }; - - enum { - kMaxPreallocEffects = 8, - kIntsPerEffect = 4, // This is an overestimate of the average effect key size. - kPreAllocSize = kEffectKeyOffsetsAndLengthOffset + - kMaxPreallocEffects * sizeof(uint32_t) * kIntsPerEffect, - }; - - SkSTArray fKey; - - // GrGLProgram and GrGLShaderBuilder read the private fields to generate code. TODO: Split out - // part of GrGLShaderBuilder that is used by effects so that this header doesn't need to be - // visible to GrGLProcessors. Then make public accessors as necessary and remove friends. - friend class GrGLProgram; - friend class GrGLProgramBuilder; - friend class GrGLLegacyNvprProgramBuilder; - friend class GrGLVertexBuilder; - friend class GrGLFragmentShaderBuilder; - friend class GrGLGeometryBuilder; }; #endif diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp index b9cb2da..88e7be0 100644 --- a/src/gpu/gl/GrGpuGL.cpp +++ b/src/gpu/gl/GrGpuGL.cpp @@ -2583,6 +2583,7 @@ void GrGpuGL::didRemoveGpuTraceMarker() { GL_CALL(PopGroupMarker()); } } + /////////////////////////////////////////////////////////////////////////////// GrGLAttribArrayState* GrGpuGL::HWGeometryState::bindArrayAndBuffersToDraw( diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h index 808f97a..46d9700 100644 --- a/src/gpu/gl/GrGpuGL.h +++ b/src/gpu/gl/GrGpuGL.h @@ -19,6 +19,7 @@ #include "GrGLVertexArray.h" #include "GrGLVertexBuffer.h" #include "GrGpu.h" +#include "GrOptDrawState.h" #include "SkTypes.h" #ifdef SK_DEVELOPER @@ -105,6 +106,12 @@ protected: const SkIRect& srcRect, const SkIPoint& dstPoint) SK_OVERRIDE; + virtual void buildProgramDesc(const GrOptDrawState&, + const GrProgramDesc::DescInfo&, + GrGpu::DrawType, + const GrDeviceCoordTexture* dstCopy, + GrProgramDesc*) SK_OVERRIDE; + private: // GrGpu overrides virtual void onResetContext(uint32_t resetBits) SK_OVERRIDE; @@ -181,9 +188,7 @@ private: ~ProgramCache(); void abandon(); - GrGLProgram* getProgram(const GrOptDrawState&, - const GrGLProgramDesc&, - DrawType); + GrGLProgram* getProgram(const GrOptDrawState&, DrawType); private: enum { @@ -199,7 +204,7 @@ private: // binary search for entry matching desc. returns index into fEntries that matches desc or ~ // of the index of where it should be inserted. - int search(const GrGLProgramDesc& desc) const; + int search(const GrProgramDesc& desc) const; // sorted array of all the entries Entry* fEntries[kMaxEntries]; diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp index a1259c9..23de7a8 100644 --- a/src/gpu/gl/GrGpuGL_program.cpp +++ b/src/gpu/gl/GrGpuGL_program.cpp @@ -31,14 +31,14 @@ struct GrGpuGL::ProgramCache::Entry { }; struct GrGpuGL::ProgramCache::ProgDescLess { - bool operator() (const GrGLProgramDesc& desc, const Entry* entry) { + bool operator() (const GrProgramDesc& desc, const Entry* entry) { SkASSERT(entry->fProgram.get()); - return GrGLProgramDesc::Less(desc, entry->fProgram->getDesc()); + return GrProgramDesc::Less(desc, entry->fProgram->getDesc()); } - bool operator() (const Entry* entry, const GrGLProgramDesc& desc) { + bool operator() (const Entry* entry, const GrProgramDesc& desc) { SkASSERT(entry->fProgram.get()); - return GrGLProgramDesc::Less(entry->fProgram->getDesc(), desc); + return GrProgramDesc::Less(entry->fProgram->getDesc(), desc); } }; @@ -86,35 +86,33 @@ void GrGpuGL::ProgramCache::abandon() { fCount = 0; } -int GrGpuGL::ProgramCache::search(const GrGLProgramDesc& desc) const { +int GrGpuGL::ProgramCache::search(const GrProgramDesc& desc) const { ProgDescLess less; return SkTSearch(fEntries, fCount, desc, sizeof(Entry*), less); } -GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrOptDrawState& optState, - const GrGLProgramDesc& desc, - DrawType type) { +GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrOptDrawState& optState, DrawType type) { #ifdef PROGRAM_CACHE_STATS ++fTotalRequests; #endif Entry* entry = NULL; - uint32_t hashIdx = desc.getChecksum(); + uint32_t hashIdx = optState.programDesc().getChecksum(); hashIdx ^= hashIdx >> 16; if (kHashBits <= 8) { hashIdx ^= hashIdx >> 8; } hashIdx &=((1 << kHashBits) - 1); Entry* hashedEntry = fHashTable[hashIdx]; - if (hashedEntry && hashedEntry->fProgram->getDesc() == desc) { + if (hashedEntry && hashedEntry->fProgram->getDesc() == optState.programDesc()) { SkASSERT(hashedEntry->fProgram); entry = hashedEntry; } int entryIdx; if (NULL == entry) { - entryIdx = this->search(desc); + entryIdx = this->search(optState.programDesc()); if (entryIdx >= 0) { entry = fEntries[entryIdx]; #ifdef PROGRAM_CACHE_STATS @@ -128,7 +126,7 @@ GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrOptDrawState& optState, #ifdef PROGRAM_CACHE_STATS ++fCacheMisses; #endif - GrGLProgram* program = GrGLProgramBuilder::CreateProgram(optState, desc, type, fGpu); + GrGLProgram* program = GrGLProgramBuilder::CreateProgram(optState, type, fGpu); if (NULL == program) { return NULL; } @@ -178,10 +176,10 @@ GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrOptDrawState& optState, SkASSERT(fEntries[0]->fProgram.get()); for (int i = 0; i < fCount - 1; ++i) { SkASSERT(fEntries[i + 1]->fProgram.get()); - const GrGLProgramDesc& a = fEntries[i]->fProgram->getDesc(); - const GrGLProgramDesc& b = fEntries[i + 1]->fProgram->getDesc(); - SkASSERT(GrGLProgramDesc::Less(a, b)); - SkASSERT(!GrGLProgramDesc::Less(b, a)); + const GrProgramDesc& a = fEntries[i]->fProgram->getDesc(); + const GrProgramDesc& b = fEntries[i + 1]->fProgram->getDesc(); + SkASSERT(GrProgramDesc::Less(a, b)); + SkASSERT(!GrProgramDesc::Less(b, a)); } #endif } @@ -207,7 +205,8 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const ScissorState& scissorState, const GrDeviceCoordTexture* dstCopy) { SkAutoTUnref optState(GrOptDrawState::Create(this->getDrawState(), - *this->caps(), + this, + dstCopy, type)); if (!optState) { @@ -234,13 +233,7 @@ bool GrGpuGL::flushGraphicsState(DrawType type, return false; } - GrGLProgramDesc desc; - if (!GrGLProgramDesc::Build(*optState.get(), type, this, dstCopy, &desc)) { - SkDEBUGFAIL("Failed to generate GL program descriptor"); - return false; - } - - fCurrentProgram.reset(fProgramCache->getProgram(*optState.get(), desc, type)); + fCurrentProgram.reset(fProgramCache->getProgram(*optState.get(), type)); if (NULL == fCurrentProgram.get()) { SkDEBUGFAIL("Failed to create program!"); return false; @@ -279,7 +272,7 @@ bool GrGpuGL::flushGraphicsState(DrawType type, void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) { SkAutoTUnref optState( - GrOptDrawState::Create(this->getDrawState(), *this->caps(), + GrOptDrawState::Create(this->getDrawState(), this, info.getDstCopy(), PrimTypeToDrawType(info.primitiveType()))); // If the optState would is NULL it should have been caught in flushGraphicsState before getting @@ -361,3 +354,13 @@ void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) { attribState->disableUnusedArrays(this, usedAttribArraysMask); } } + +void GrGpuGL::buildProgramDesc(const GrOptDrawState& optState, + const GrProgramDesc::DescInfo& descInfo, + GrGpu::DrawType drawType, + const GrDeviceCoordTexture* dstCopy, + GrProgramDesc* desc) { + if (!GrGLProgramDescBuilder::Build(optState, descInfo, drawType, this, dstCopy, desc)) { + SkDEBUGFAIL("Failed to generate GL program descriptor"); + } +} diff --git a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp index ff3989b..6aeba7a 100644 --- a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp +++ b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp @@ -69,12 +69,12 @@ GrGLFragmentShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst, con } GrGLFragmentShaderBuilder::GrGLFragmentShaderBuilder(GrGLProgramBuilder* program, - const GrGLProgramDesc& desc) + uint8_t fragPosKey) : INHERITED(program) , fHasCustomColorOutput(false) , fHasSecondaryOutput(false) , fSetupFragPosition(false) - , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey) + , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == fragPosKey) , fCustomColorOutputIndex(-1) , fHasReadDstColor(false) , fHasReadFragmentPosition(false) { @@ -262,13 +262,13 @@ void GrGLFragmentShaderBuilder::enableSecondaryOutput(const GrGLSLExpr4& inputCo const char* secondaryOutputName = this->getSecondaryColorOutputName(); GrGLSLExpr4 coeff(1); switch (fProgramBuilder->header().fSecondaryOutputType) { - case GrOptDrawState::kCoverage_SecondaryOutputType: + case GrProgramDesc::kCoverage_SecondaryOutputType: break; - case GrOptDrawState::kCoverageISA_SecondaryOutputType: + case GrProgramDesc::kCoverageISA_SecondaryOutputType: // Get (1-A) into coeff coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inputColor.a()); break; - case GrOptDrawState::kCoverageISC_SecondaryOutputType: + case GrProgramDesc::kCoverageISC_SecondaryOutputType: // Get (1-RGBA) into coeff coeff = GrGLSLExpr4(1) - inputColor; break; @@ -283,9 +283,9 @@ void GrGLFragmentShaderBuilder::combineColorAndCoverage(const GrGLSLExpr4& input const GrGLSLExpr4& inputCoverage) { GrGLSLExpr4 fragColor = inputColor * inputCoverage; switch (fProgramBuilder->header().fPrimaryOutputType) { - case GrOptDrawState::kModulate_PrimaryOutputType: + case GrProgramDesc::kModulate_PrimaryOutputType: break; - case GrOptDrawState::kCombineWithDst_PrimaryOutputType: + case GrProgramDesc::kCombineWithDst_PrimaryOutputType: { // Tack on "+(1-coverage)dst onto the frag color. GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inputCoverage; diff --git a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.h b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.h index b5f83d4..226be51 100644 --- a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.h +++ b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.h @@ -84,7 +84,7 @@ public: the key is 0. */ static FragPosKey KeyForFragmentPosition(const GrRenderTarget* dst, const GrGLCaps&); - GrGLFragmentShaderBuilder(GrGLProgramBuilder* program, const GrGLProgramDesc& desc); + GrGLFragmentShaderBuilder(GrGLProgramBuilder* program, uint8_t fragPosKey); // true public interface, defined explicitly in the abstract interfaces above virtual bool enableFeature(GLSLFeature) SK_OVERRIDE; diff --git a/src/gpu/gl/builders/GrGLGeometryShaderBuilder.cpp b/src/gpu/gl/builders/GrGLGeometryShaderBuilder.cpp index af95f56..f35c9ba 100644 --- a/src/gpu/gl/builders/GrGLGeometryShaderBuilder.cpp +++ b/src/gpu/gl/builders/GrGLGeometryShaderBuilder.cpp @@ -48,7 +48,7 @@ bool GrGLGeometryBuilder::compileAndAttachShaders(GrGLuint programId, geomShaderSrc.append("void main() {\n"); geomShaderSrc.append("\tfor (int i = 0; i < 3; ++i) {\n" "\t\tgl_Position = gl_in[i].gl_Position;\n"); - if (fProgramBuilder->desc().getHeader().fEmitsPointSize) { + if (fProgramBuilder->desc().header().fEmitsPointSize) { geomShaderSrc.append("\t\tgl_PointSize = 1.0;\n"); } SkASSERT(fInputs.count() == fOutputs.count()); diff --git a/src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.cpp b/src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.cpp index 1c1cb42..c0c4fbb 100644 --- a/src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.cpp +++ b/src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.cpp @@ -9,12 +9,9 @@ #include "../GrGpuGL.h" GrGLLegacyNvprProgramBuilder::GrGLLegacyNvprProgramBuilder(GrGpuGL* gpu, - const GrOptDrawState& optState, - const GrGLProgramDesc& desc) - : INHERITED(gpu, optState, desc) + const GrOptDrawState& optState) + : INHERITED(gpu, optState) , fTexCoordSetCnt(0) { - SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fColorInput); - SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fCoverageInput); } int GrGLLegacyNvprProgramBuilder::addTexCoordSets(int count) { diff --git a/src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.h b/src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.h index dabec08..cd2cfb7 100644 --- a/src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.h +++ b/src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.h @@ -12,7 +12,7 @@ class GrGLLegacyNvprProgramBuilder : public GrGLProgramBuilder { public: - GrGLLegacyNvprProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&); + GrGLLegacyNvprProgramBuilder(GrGpuGL*, const GrOptDrawState&); virtual GrGLProgram* createProgram(GrGLuint programID); diff --git a/src/gpu/gl/builders/GrGLNvprProgramBuilder.cpp b/src/gpu/gl/builders/GrGLNvprProgramBuilder.cpp index 3d991a2..5488252 100644 --- a/src/gpu/gl/builders/GrGLNvprProgramBuilder.cpp +++ b/src/gpu/gl/builders/GrGLNvprProgramBuilder.cpp @@ -12,9 +12,8 @@ #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X) GrGLNvprProgramBuilder::GrGLNvprProgramBuilder(GrGpuGL* gpu, - const GrOptDrawState& optState, - const GrGLProgramDesc& desc) - : INHERITED(gpu, optState, desc) + const GrOptDrawState& optState) + : INHERITED(gpu, optState) , fSeparableVaryingInfos(kVarsPerBlock) { } diff --git a/src/gpu/gl/builders/GrGLNvprProgramBuilder.h b/src/gpu/gl/builders/GrGLNvprProgramBuilder.h index 008aff7..e9f6b3b 100644 --- a/src/gpu/gl/builders/GrGLNvprProgramBuilder.h +++ b/src/gpu/gl/builders/GrGLNvprProgramBuilder.h @@ -12,7 +12,7 @@ class GrGLNvprProgramBuilder : public GrGLProgramBuilder { public: - GrGLNvprProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&); + GrGLNvprProgramBuilder(GrGpuGL*, const GrOptDrawState&); /* * The separable varying info must be passed to GrGLProgram so this must diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp index 65a7cda..6df086c 100644 --- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp +++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp @@ -29,19 +29,17 @@ static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar: const int GrGLProgramBuilder::kVarsPerBlock = 8; GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState, - const GrGLProgramDesc& desc, GrGpu::DrawType drawType, GrGpuGL* gpu) { // create a builder. This will be handed off to effects so they can use it to add // uniforms, varyings, textures, etc - SkAutoTDelete builder(CreateProgramBuilder(desc, - optState, + SkAutoTDelete builder(CreateProgramBuilder(optState, drawType, optState.hasGeometryProcessor(), gpu)); GrGLProgramBuilder* pb = builder.get(); - const GrGLProgramDesc::KeyHeader& header = pb->header(); + const GrGLProgramDescBuilder::GLKeyHeader& header = GrGLProgramDescBuilder::GetHeader(pb->desc()); // emit code to read the dst copy texture, if necessary if (GrGLFragmentShaderBuilder::kNoDstRead_DstReadKey != header.fDstReadKey @@ -64,10 +62,10 @@ GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState, if (header.fEmitsPointSize) { pb->fVS.codeAppend("gl_PointSize = 1.0;"); } - if (GrGLProgramDesc::kAttribute_ColorInput == header.fColorInput) { + if (GrProgramDesc::kAttribute_ColorInput == header.fColorInput) { pb->fVS.setupBuiltinVertexAttribute("Color", &inputColor); } - if (GrGLProgramDesc::kAttribute_ColorInput == header.fCoverageInput) { + if (GrProgramDesc::kAttribute_ColorInput == header.fCoverageInput) { pb->fVS.setupBuiltinVertexAttribute("Coverage", &inputCoverage); } } @@ -79,7 +77,7 @@ GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState, } // write the secondary color output if necessary - if (GrOptDrawState::kNone_SecondaryOutputType != header.fSecondaryOutputType) { + if (GrProgramDesc::kNone_SecondaryOutputType != header.fSecondaryOutputType) { pb->fFS.enableSecondaryOutput(inputColor, inputCoverage); } @@ -89,38 +87,38 @@ GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState, } GrGLProgramBuilder* -GrGLProgramBuilder::CreateProgramBuilder(const GrGLProgramDesc& desc, - const GrOptDrawState& optState, +GrGLProgramBuilder::CreateProgramBuilder(const GrOptDrawState& optState, GrGpu::DrawType drawType, bool hasGeometryProcessor, GrGpuGL* gpu) { - if (desc.getHeader().fUseNvpr) { + const GrProgramDesc& desc = optState.programDesc(); + if (GrGLProgramDescBuilder::GetHeader(desc).fUseNvpr) { SkASSERT(gpu->glCaps().pathRenderingSupport()); + SkASSERT(GrProgramDesc::kAttribute_ColorInput != desc.header().fColorInput); + SkASSERT(GrProgramDesc::kAttribute_ColorInput != desc.header().fCoverageInput); SkASSERT(!hasGeometryProcessor); if (gpu->glPathRendering()->texturingMode() == GrGLPathRendering::FixedFunction_TexturingMode) { - return SkNEW_ARGS(GrGLLegacyNvprProgramBuilder, (gpu, optState, desc)); + return SkNEW_ARGS(GrGLLegacyNvprProgramBuilder, (gpu, optState)); } else { - return SkNEW_ARGS(GrGLNvprProgramBuilder, (gpu, optState, desc)); + return SkNEW_ARGS(GrGLNvprProgramBuilder, (gpu, optState)); } } else { - return SkNEW_ARGS(GrGLProgramBuilder, (gpu, optState, desc)); + return SkNEW_ARGS(GrGLProgramBuilder, (gpu, optState)); } } ///////////////////////////////////////////////////////////////////////////// -GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu, - const GrOptDrawState& optState, - const GrGLProgramDesc& desc) +GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu, const GrOptDrawState& optState) : fVS(this) , fGS(this) - , fFS(this, desc) + , fFS(this, optState.programDesc().header().fFragPosKey) , fOutOfStage(true) , fStageIndex(-1) , fGeometryProcessor(NULL) , fOptState(optState) - , fDesc(desc) + , fDesc(optState.programDesc()) , fGpu(gpu) , fUniforms(kVarsPerBlock) { } @@ -202,8 +200,8 @@ const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const { void GrGLProgramBuilder::setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage) { - const GrGLProgramDesc::KeyHeader& header = this->header(); - if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) { + const GrProgramDesc::KeyHeader& header = this->header(); + if (GrProgramDesc::kUniform_ColorInput == header.fColorInput) { const char* name; fUniformHandles.fColorUni = this->addUniform(GrGLProgramBuilder::kFragment_Visibility, @@ -211,10 +209,10 @@ void GrGLProgramBuilder::setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* input "Color", &name); *inputColor = GrGLSLExpr4(name); - } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fColorInput) { + } else if (GrProgramDesc::kAllOnes_ColorInput == header.fColorInput) { *inputColor = GrGLSLExpr4(1); } - if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) { + if (GrProgramDesc::kUniform_ColorInput == header.fCoverageInput) { const char* name; fUniformHandles.fCoverageUni = this->addUniform(GrGLProgramBuilder::kFragment_Visibility, @@ -222,7 +220,7 @@ void GrGLProgramBuilder::setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* input "Coverage", &name); *inputCoverage = GrGLSLExpr4(name); - } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) { + } else if (GrProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) { *inputCoverage = GrGLSLExpr4(1); } } @@ -236,7 +234,9 @@ void GrGLProgramBuilder::emitAndInstallProcs(const GrOptDrawState& optState, if (optState.hasGeometryProcessor()) { const GrGeometryProcessor& gp = *optState.getGeometryProcessor(); fVS.emitAttributes(gp); - ProcKeyProvider keyProvider(&fDesc, ProcKeyProvider::kGeometry_ProcessorType); + ProcKeyProvider keyProvider(&fDesc, + ProcKeyProvider::kGeometry_ProcessorType, + GrGLProgramDescBuilder::kProcessorKeyOffsetsAndLengthOffset); GrGLSLExpr4 output; this->emitAndInstallProc(gp, 0, keyProvider, *inputCoverage, &output); *inputCoverage = output; @@ -245,7 +245,9 @@ void GrGLProgramBuilder::emitAndInstallProcs(const GrOptDrawState& optState, } void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut) { - ProcKeyProvider keyProvider(&fDesc, ProcKeyProvider::kFragment_ProcessorType); + ProcKeyProvider keyProvider(&fDesc, + ProcKeyProvider::kFragment_ProcessorType, + GrGLProgramDescBuilder::kProcessorKeyOffsetsAndLengthOffset); for (int e = procOffset; e < numProcs; ++e) { GrGLSLExpr4 output; const GrFragmentStage& stage = fOptState.getFragmentStage(e); @@ -259,7 +261,7 @@ void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset, int numProcs, G template void GrGLProgramBuilder::emitAndInstallProc(const Proc& proc, int index, - const ProcKeyProvider keyProvider, + const ProcKeyProvider& keyProvider, const GrGLSLExpr4& input, GrGLSLExpr4* output) { // Program builders have a bit of state we need to clear with each effect @@ -419,7 +421,7 @@ GrGLProgram* GrGLProgramBuilder::finalize() { this->cleanupProgram(programID, shadersToDelete); return NULL; } - if (!(this->header().fUseNvpr && + if (!(GrGLProgramDescBuilder::GetHeader(fDesc).fUseNvpr && fGpu->glPathRendering()->texturingMode() == GrGLPathRendering::FixedFunction_TexturingMode)) { if (!fVS.compileAndAttachShaders(programID, &shadersToDelete)) { diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.h b/src/gpu/gl/builders/GrGLProgramBuilder.h index 9d8e7e0..0abdf0a 100644 --- a/src/gpu/gl/builders/GrGLProgramBuilder.h +++ b/src/gpu/gl/builders/GrGLProgramBuilder.h @@ -169,10 +169,7 @@ public: * to be used. * @return true if generation was successful. */ - static GrGLProgram* CreateProgram(const GrOptDrawState&, - const GrGLProgramDesc&, - GrGpu::DrawType, - GrGpuGL* gpu); + static GrGLProgram* CreateProgram(const GrOptDrawState&, GrGpu::DrawType, GrGpuGL*); virtual UniformHandle addUniform(uint32_t visibility, GrSLType type, @@ -224,21 +221,20 @@ public: }; protected: - typedef GrGLProgramDesc::ProcKeyProvider ProcKeyProvider; + typedef GrProgramDesc::ProcKeyProvider ProcKeyProvider; typedef GrGLProgramDataManager::UniformInfo UniformInfo; typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray; - static GrGLProgramBuilder* CreateProgramBuilder(const GrGLProgramDesc&, - const GrOptDrawState&, + static GrGLProgramBuilder* CreateProgramBuilder(const GrOptDrawState&, GrGpu::DrawType, bool hasGeometryProcessor, GrGpuGL*); - GrGLProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&); + GrGLProgramBuilder(GrGpuGL*, const GrOptDrawState&); const GrOptDrawState& optState() const { return fOptState; } - const GrGLProgramDesc& desc() const { return fDesc; } - const GrGLProgramDesc::KeyHeader& header() const { return fDesc.getHeader(); } + const GrProgramDesc& desc() const { return fDesc; } + const GrProgramDesc::KeyHeader& header() const { return fDesc.header(); } // Generates a name for a variable. The generated string will be name prefixed by the prefix // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're @@ -252,7 +248,7 @@ protected: template void emitAndInstallProc(const Proc&, int index, - const ProcKeyProvider, + const ProcKeyProvider&, const GrGLSLExpr4& input, GrGLSLExpr4* output); @@ -332,7 +328,7 @@ protected: SkAutoTUnref fFragmentProcessors; const GrOptDrawState& fOptState; - const GrGLProgramDesc& fDesc; + const GrProgramDesc& fDesc; GrGpuGL* fGpu; UniformInfoArray fUniforms; diff --git a/src/gpu/gl/builders/GrGLShaderBuilder.h b/src/gpu/gl/builders/GrGLShaderBuilder.h index cf7ae9b..8b7b9f9 100644 --- a/src/gpu/gl/builders/GrGLShaderBuilder.h +++ b/src/gpu/gl/builders/GrGLShaderBuilder.h @@ -8,6 +8,7 @@ #ifndef GrGLShaderBuilder_DEFINED #define GrGLShaderBuilder_DEFINED +#include "gl/GrGLProcessor.h" #include "gl/GrGLProgramDesc.h" #include "gl/GrGLProgramDataManager.h" diff --git a/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp b/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp index 1fa9467..5a65f71 100644 --- a/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp +++ b/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp @@ -93,7 +93,7 @@ void GrGLVertexBuilder::transformSkiaToGLCoords() { void GrGLVertexBuilder::bindVertexAttributes(GrGLuint programID) { // Bind the attrib locations to same values for all shaders - const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->header(); + const GrProgramDesc::KeyHeader& header = fProgramBuilder->header(); SkASSERT(-1 != header.fPositionAttributeIndex); GL_CALL(BindAttribLocation(programID, header.fPositionAttributeIndex, diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp index 24d6203..c9e840e 100644 --- a/tests/GLProgramsTest.cpp +++ b/tests/GLProgramsTest.cpp @@ -447,32 +447,24 @@ bool GrGpuGL::programUnitTest(int maxStages) { set_random_blend_func(this, &random); set_random_stencil(this, &random); + GrDeviceCoordTexture dstCopy; + + if (!this->setupDstReadIfNecessary(&dstCopy, NULL)) { + SkDebugf("Couldn't setup dst read texture"); + return false; + } + // create optimized draw state, setup readDst texture if required, and build a descriptor // and program. ODS creation can fail, so we have to check SkAutoTUnref ods(GrOptDrawState::Create(this->getDrawState(), - *this->caps(), + this, + &dstCopy, drawType)); if (!ods.get()) { ds->reset(); continue; } - GrGLProgramDesc desc; - GrDeviceCoordTexture dstCopy; - - if (!this->setupDstReadIfNecessary(&dstCopy, NULL)) { - SkDebugf("Couldn't setup dst read texture"); - return false; - } - if (!GrGLProgramDesc::Build(*ods, - drawType, - this, - dstCopy.texture() ? &dstCopy : NULL, - &desc)) { - SkDebugf("Failed to generate GL program descriptor"); - return false; - } - SkAutoTUnref program( - GrGLProgramBuilder::CreateProgram(*ods, desc, drawType, this)); + SkAutoTUnref program(GrGLProgramBuilder::CreateProgram(*ods, drawType, this)); if (NULL == program.get()) { SkDebugf("Failed to create program!"); return false; -- 2.7.4