'<(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',
#include "GrDrawTarget.h"
#include "GrClipMaskManager.h"
#include "GrPathRendering.h"
+#include "GrProgramDesc.h"
#include "SkPath.h"
class GrContext;
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) {
#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();
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;
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()) {
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;
}
drawState.fCachedOptState = SkNEW_ARGS(GrOptDrawState, (drawState, blendFlags, srcCoeff,
- dstCoeff, caps));
+ dstCoeff, gpu, dstCopy, drawType));
drawState.fCachedCapsID = caps.getUniqueID();
} else {
#ifdef SK_DEBUG
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();
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) {
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 |
}
}
-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;
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;
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 {
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.
}
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
fp->computeInvariantOutput(&inout);
if (!inout.fWillUseInputColor) {
*firstCoverageStageIdx = i;
- fInputCoverageIsUsed = false;
+ descInfo->fInputCoverageIsUsed = false;
}
}
#endif
}
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();
}
}
}
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 ||
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;
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;
}
#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;
/**
* 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;
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];
- }
-
/// @}
///////////////////////////////////////////////////////////////////////////
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.
*/
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
* 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
* 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;
// 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;
};
--- /dev/null
+/*
+ * 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<const uint32_t*>(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<uint32_t, kLengthOffset>(); }
+
+ // 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<uint32_t, kChecksumOffset>(); }
+
+ 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<KeyHeader, kHeaderOffset>(); }
+
+ /** 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<const uint16_t*>(
+ 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<const uint32_t*>(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<typename T, size_t OFFSET> T* atOffset() {
+ return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(fKey.begin()) + OFFSET);
+ }
+
+ template<typename T, size_t OFFSET> const T* atOffset() const {
+ return reinterpret_cast<const T*>(reinterpret_cast<intptr_t>(fKey.begin()) + OFFSET);
+ }
+
+ void finalize() {
+ int keyLength = fKey.count();
+ SkASSERT(0 == (keyLength % 4));
+ *(this->atOffset<uint32_t, GrProgramDesc::kLengthOffset>()) = SkToU32(keyLength);
+
+ uint32_t* checksum = this->atOffset<uint32_t, GrProgramDesc::kChecksumOffset>();
+ *checksum = 0;
+ *checksum = SkChecksum::Compute(reinterpret_cast<uint32_t*>(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<kPreAllocSize, uint8_t, true> fKey;
+
+ friend class GrGLProgramDescBuilder;
+};
+
+#endif
///////////////////////////////////////////////////////////////////////////////////////////////////
GrGLProgram::GrGLProgram(GrGpuGL* gpu,
- const GrGLProgramDesc& desc,
+ const GrProgramDesc& desc,
const BuiltinUniformHandles& builtinUniforms,
GrGLuint programID,
const UniformInfoArray& uniforms,
}
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];
fColor = color;
}
break;
- case GrGLProgramDesc::kAllOnes_ColorInput:
+ case GrProgramDesc::kAllOnes_ColorInput:
// Handled by shader creation
break;
default:
}
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];
fCoverage = coverage;
}
break;
- case GrGLProgramDesc::kAllOnes_ColorInput:
+ case GrProgramDesc::kAllOnes_ColorInput:
// Handled by shader creation
break;
default:
/////////////////////////////////////////////////////////////////////////////////////////
GrGLNvprProgramBase::GrGLNvprProgramBase(GrGpuGL* gpu,
- const GrGLProgramDesc& desc,
+ const GrProgramDesc& desc,
const BuiltinUniformHandles& builtinUniforms,
GrGLuint programID,
const UniformInfoArray& uniforms,
/////////////////////////////////////////////////////////////////////////////////////////
GrGLNvprProgram::GrGLNvprProgram(GrGpuGL* gpu,
- const GrGLProgramDesc& desc,
+ const GrProgramDesc& desc,
const BuiltinUniformHandles& builtinUniforms,
GrGLuint programID,
const UniformInfoArray& uniforms,
//////////////////////////////////////////////////////////////////////////////////////
GrGLLegacyNvprProgram::GrGLLegacyNvprProgram(GrGpuGL* gpu,
- const GrGLProgramDesc& desc,
+ const GrProgramDesc& desc,
const BuiltinUniformHandles& builtinUniforms,
GrGLuint programID,
const UniformInfoArray& uniforms,
*/
void abandon();
- const GrGLProgramDesc& getDesc() { return fDesc; }
+ const GrProgramDesc& getDesc() { return fDesc; }
/**
* Gets the GL program ID for this program.
typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
GrGLProgram(GrGpuGL*,
- const GrGLProgramDesc&,
+ const GrProgramDesc&,
const BuiltinUniformHandles&,
GrGLuint programID,
const UniformInfoArray&,
SkAutoTDelete<GrGLInstalledGeoProc> fGeometryProcessor;
SkAutoTUnref<GrGLInstalledFragProcs> fFragmentProcessors;
- GrGLProgramDesc fDesc;
+ GrProgramDesc fDesc;
GrGpuGL* fGpu;
GrGLProgramDataManager fProgramDataManager;
class GrGLNvprProgramBase : public GrGLProgram {
protected:
GrGLNvprProgramBase(GrGpuGL*,
- const GrGLProgramDesc&,
+ const GrProgramDesc&,
const BuiltinUniformHandles&,
GrGLuint programID,
const UniformInfoArray&,
typedef GrGLNvprProgramBuilder::SeparableVaryingInfo SeparableVaryingInfo;
typedef GrGLNvprProgramBuilder::SeparableVaryingInfoArray SeparableVaryingInfoArray;
GrGLNvprProgram(GrGpuGL*,
- const GrGLProgramDesc&,
+ const GrProgramDesc&,
const BuiltinUniformHandles&,
GrGLuint programID,
const UniformInfoArray&,
private:
GrGLLegacyNvprProgram(GrGpuGL* gpu,
- const GrGLProgramDesc& desc,
+ const GrProgramDesc& desc,
const BuiltinUniformHandles&,
GrGLuint programID,
const UniformInfoArray&,
* 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
template <class ProcessorKeyBuilder>
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;
}
uint16_t* offsetAndSize =
- reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
+ reinterpret_cast<uint16_t*>(desc->fKey.begin() + kProcessorKeyOffsetsAndLengthOffset +
*offsetAndSizeIndex * 2 * sizeof(uint16_t));
offsetAndSize[0] = SkToU16(processorOffset);
offsetAndSize[1] = processorKeySize;
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;
// --------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<GLKeyHeader, kHeaderOffset>();
// make sure any padding in the header is zeroed.
memset(header, 0, kHeaderSize);
}
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) {
header->fDstReadKey = 0;
}
- if (optState.readsFragPosition()) {
+ if (descInfo.fReadsFragPosition) {
header->fFragPosKey =
GrGLFragmentShaderBuilder::KeyForFragmentPosition(optState.getRenderTarget(),
gpu->glCaps());
}
// 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++;
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<uint32_t, kLengthOffset>() = SkToU32(keyLength);
-
- uint32_t* checksum = this->atOffset<uint32_t, kChecksumOffset>();
- *checksum = 0;
- *checksum = SkChecksum::Compute(reinterpret_cast<uint32_t*>(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;
-}
#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<const uint32_t*>(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<uint32_t, kLengthOffset>(); }
-
- // 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<uint32_t, kChecksumOffset>(); }
-
- /**
- * 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.
// 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<typename T, size_t OFFSET> T* atOffset() {
- return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(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<typename T, size_t OFFSET> const T* atOffset() const {
- return reinterpret_cast<const T*>(reinterpret_cast<intptr_t>(fKey.begin()) + OFFSET);
+ static const GLKeyHeader& GetHeader(const GrProgramDesc& desc) {
+ return *desc.atOffset<GLKeyHeader, kHeaderOffset>();
}
- KeyHeader* header() { return this->atOffset<KeyHeader, kHeaderOffset>(); }
-
- // a helper class to handle getting an individual processor's key
+private:
template <class ProcessorKeyBuilder>
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<KeyHeader, kHeaderOffset>(); }
-
- /** 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<const uint16_t*>(
- 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<const uint32_t*>(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<kPreAllocSize, uint8_t, true> 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
GL_CALL(PopGroupMarker());
}
}
+
///////////////////////////////////////////////////////////////////////////////
GrGLAttribArrayState* GrGpuGL::HWGeometryState::bindArrayAndBuffersToDraw(
#include "GrGLVertexArray.h"
#include "GrGLVertexBuffer.h"
#include "GrGpu.h"
+#include "GrOptDrawState.h"
#include "SkTypes.h"
#ifdef SK_DEVELOPER
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;
~ProgramCache();
void abandon();
- GrGLProgram* getProgram(const GrOptDrawState&,
- const GrGLProgramDesc&,
- DrawType);
+ GrGLProgram* getProgram(const GrOptDrawState&, DrawType);
private:
enum {
// 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];
};
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);
}
};
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
#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;
}
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
}
const ScissorState& scissorState,
const GrDeviceCoordTexture* dstCopy) {
SkAutoTUnref<GrOptDrawState> optState(GrOptDrawState::Create(this->getDrawState(),
- *this->caps(),
+ this,
+ dstCopy,
type));
if (!optState) {
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;
void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) {
SkAutoTUnref<GrOptDrawState> 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
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");
+ }
+}
}
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) {
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;
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;
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;
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());
#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) {
class GrGLLegacyNvprProgramBuilder : public GrGLProgramBuilder {
public:
- GrGLLegacyNvprProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&);
+ GrGLLegacyNvprProgramBuilder(GrGpuGL*, const GrOptDrawState&);
virtual GrGLProgram* createProgram(GrGLuint programID);
#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) {
}
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
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<GrGLProgramBuilder> builder(CreateProgramBuilder(desc,
- optState,
+ SkAutoTDelete<GrGLProgramBuilder> 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
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);
}
}
}
// write the secondary color output if necessary
- if (GrOptDrawState::kNone_SecondaryOutputType != header.fSecondaryOutputType) {
+ if (GrProgramDesc::kNone_SecondaryOutputType != header.fSecondaryOutputType) {
pb->fFS.enableSecondaryOutput(inputColor, inputCoverage);
}
}
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) {
}
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,
"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,
"Coverage",
&name);
*inputCoverage = GrGLSLExpr4(name);
- } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) {
+ } else if (GrProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) {
*inputCoverage = GrGLSLExpr4(1);
}
}
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<GrGeometryProcessor>(gp, 0, keyProvider, *inputCoverage, &output);
*inputCoverage = output;
}
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);
template <class Proc>
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
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)) {
* 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,
};
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
template <class Proc>
void emitAndInstallProc(const Proc&,
int index,
- const ProcKeyProvider,
+ const ProcKeyProvider&,
const GrGLSLExpr4& input,
GrGLSLExpr4* output);
SkAutoTUnref<GrGLInstalledFragProcs> fFragmentProcessors;
const GrOptDrawState& fOptState;
- const GrGLProgramDesc& fDesc;
+ const GrProgramDesc& fDesc;
GrGpuGL* fGpu;
UniformInfoArray fUniforms;
#ifndef GrGLShaderBuilder_DEFINED
#define GrGLShaderBuilder_DEFINED
+#include "gl/GrGLProcessor.h"
#include "gl/GrGLProgramDesc.h"
#include "gl/GrGLProgramDataManager.h"
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,
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<GrOptDrawState> 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<GrGLProgram> program(
- GrGLProgramBuilder::CreateProgram(*ods, desc, drawType, this));
+ SkAutoTUnref<GrGLProgram> program(GrGLProgramBuilder::CreateProgram(*ods, drawType, this));
if (NULL == program.get()) {
SkDebugf("Failed to create program!");
return false;