OptState owns program descriptor

BUG=skia:

Review URL: https://codereview.chromium.org/674543004
This commit is contained in:
joshualitt 2014-10-28 17:59:26 -07:00 committed by Commit bot
parent 7a56931784
commit 79f8faeea2
24 changed files with 564 additions and 511 deletions

View File

@ -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',

View File

@ -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) {

View File

@ -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;
}

View File

@ -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;
};

269
src/gpu/GrProgramDesc.h Normal file
View File

@ -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<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

View File

@ -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,

View File

@ -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<GrGLInstalledGeoProc> fGeometryProcessor;
SkAutoTUnref<GrGLInstalledFragProcs> 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&,

View File

@ -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 <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;
@ -192,7 +192,7 @@ GrGLProgramDesc::BuildStagedProcessorKey(const typename ProcessorKeyBuilder::Sta
}
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;
@ -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<GLKeyHeader, kHeaderOffset>();
// 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<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;
}

View File

@ -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<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.
@ -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<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*);
static const GLKeyHeader& GetHeader(const GrProgramDesc& desc) {
return *desc.atOffset<GLKeyHeader, kHeaderOffset>();
}
template<typename T, size_t OFFSET> const T* atOffset() const {
return reinterpret_cast<const T*>(reinterpret_cast<intptr_t>(fKey.begin()) + OFFSET);
}
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

View File

@ -2583,6 +2583,7 @@ void GrGpuGL::didRemoveGpuTraceMarker() {
GL_CALL(PopGroupMarker());
}
}
///////////////////////////////////////////////////////////////////////////////
GrGLAttribArrayState* GrGpuGL::HWGeometryState::bindArrayAndBuffersToDraw(

View File

@ -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];

View File

@ -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<GrOptDrawState> 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<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
@ -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");
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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());

View File

@ -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) {

View File

@ -12,7 +12,7 @@
class GrGLLegacyNvprProgramBuilder : public GrGLProgramBuilder {
public:
GrGLLegacyNvprProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&);
GrGLLegacyNvprProgramBuilder(GrGpuGL*, const GrOptDrawState&);
virtual GrGLProgram* createProgram(GrGLuint programID);

View File

@ -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) {
}

View File

@ -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

View File

@ -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<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
@ -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<GrGeometryProcessor>(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 <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
@ -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)) {

View File

@ -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 <class Proc>
void emitAndInstallProc(const Proc&,
int index,
const ProcKeyProvider,
const ProcKeyProvider&,
const GrGLSLExpr4& input,
GrGLSLExpr4* output);
@ -332,7 +328,7 @@ protected:
SkAutoTUnref<GrGLInstalledFragProcs> fFragmentProcessors;
const GrOptDrawState& fOptState;
const GrGLProgramDesc& fDesc;
const GrProgramDesc& fDesc;
GrGpuGL* fGpu;
UniformInfoArray fUniforms;

View File

@ -8,6 +8,7 @@
#ifndef GrGLShaderBuilder_DEFINED
#define GrGLShaderBuilder_DEFINED
#include "gl/GrGLProcessor.h"
#include "gl/GrGLProgramDesc.h"
#include "gl/GrGLProgramDataManager.h"

View File

@ -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,

View File

@ -447,32 +447,24 @@ bool GrGpuGL::programUnitTest(int maxStages) {
set_random_blend_func(this, &random);
set_random_stencil(this, &random);
// 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(),
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;
// 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,
&dstCopy,
drawType));
if (!ods.get()) {
ds->reset();
continue;
}
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;