OptState owns program descriptor
BUG=skia: Review URL: https://codereview.chromium.org/674543004
This commit is contained in:
parent
7a56931784
commit
79f8faeea2
@ -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',
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
269
src/gpu/GrProgramDesc.h
Normal 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
|
@ -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,
|
||||
|
@ -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&,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -2583,6 +2583,7 @@ void GrGpuGL::didRemoveGpuTraceMarker() {
|
||||
GL_CALL(PopGroupMarker());
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GrGLAttribArrayState* GrGpuGL::HWGeometryState::bindArrayAndBuffersToDraw(
|
||||
|
@ -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];
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
@ -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) {
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
class GrGLLegacyNvprProgramBuilder : public GrGLProgramBuilder {
|
||||
public:
|
||||
GrGLLegacyNvprProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&);
|
||||
GrGLLegacyNvprProgramBuilder(GrGpuGL*, const GrOptDrawState&);
|
||||
|
||||
virtual GrGLProgram* createProgram(GrGLuint programID);
|
||||
|
||||
|
@ -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) {
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#ifndef GrGLShaderBuilder_DEFINED
|
||||
#define GrGLShaderBuilder_DEFINED
|
||||
|
||||
#include "gl/GrGLProcessor.h"
|
||||
#include "gl/GrGLProgramDesc.h"
|
||||
#include "gl/GrGLProgramDataManager.h"
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user