Initial change to create GeometryProcessor
BUG=skia: R=bsalomon@google.com, robertphillips@google.com, egdaniel@google.com, jvanverth@google.com Author: joshualitt@chromium.org Review URL: https://codereview.chromium.org/509153002
This commit is contained in:
parent
c5ba71d2e5
commit
bd769d0f1c
@ -36,3 +36,6 @@
|
||||
# jvanverth
|
||||
fontcache
|
||||
|
||||
# joshualitt
|
||||
convex_poly_clip
|
||||
bezier_cubic_effects
|
@ -170,7 +170,7 @@ protected:
|
||||
GrDrawState* drawState = tt.target()->drawState();
|
||||
drawState->setVertexAttribs<kAttribs>(2, sizeof(Vertex));
|
||||
|
||||
drawState->addCoverageEffect(effect, 1);
|
||||
drawState->setGeometryProcessor(effect, 1);
|
||||
drawState->setRenderTarget(rt);
|
||||
drawState->setColor(0xff000000);
|
||||
|
||||
@ -325,7 +325,7 @@ protected:
|
||||
GrDrawState* drawState = tt.target()->drawState();
|
||||
drawState->setVertexAttribs<kAttribs>(2, sizeof(Vertex));
|
||||
|
||||
drawState->addCoverageEffect(effect, 1);
|
||||
drawState->setGeometryProcessor(effect, 1);
|
||||
drawState->setRenderTarget(rt);
|
||||
drawState->setColor(0xff000000);
|
||||
|
||||
@ -509,7 +509,7 @@ protected:
|
||||
GrDrawState* drawState = tt.target()->drawState();
|
||||
drawState->setVertexAttribs<kAttribs>(2, sizeof(Vertex));
|
||||
|
||||
drawState->addCoverageEffect(effect, 1);
|
||||
drawState->setGeometryProcessor(effect, 1);
|
||||
drawState->setRenderTarget(rt);
|
||||
drawState->setColor(0xff000000);
|
||||
|
||||
|
@ -678,7 +678,7 @@ bool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath,
|
||||
|
||||
static const int kEdgeAttrIndex = 1;
|
||||
GrEffect* quadEffect = QuadEdgeEffect::Create();
|
||||
drawState->addCoverageEffect(quadEffect, kEdgeAttrIndex)->unref();
|
||||
drawState->setGeometryProcessor(quadEffect, kEdgeAttrIndex)->unref();
|
||||
|
||||
GrDrawTarget::AutoReleaseGeometry arg(target, vCount, iCount);
|
||||
if (!arg.succeeded()) {
|
||||
|
@ -1002,7 +1002,7 @@ bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path,
|
||||
SkASSERT(NULL != hairQuadEffect);
|
||||
GrDrawState::AutoRestoreEffects are(drawState);
|
||||
target->setIndexSourceToBuffer(fQuadsIndexBuffer);
|
||||
drawState->addCoverageEffect(hairQuadEffect, kEdgeAttrIndex)->unref();
|
||||
drawState->setGeometryProcessor(hairQuadEffect, kEdgeAttrIndex)->unref();
|
||||
int quads = 0;
|
||||
while (quads < quadCnt) {
|
||||
int n = SkTMin(quadCnt - quads, kNumQuadsInIdxBuffer);
|
||||
@ -1021,7 +1021,7 @@ bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path,
|
||||
GrEffect* hairConicEffect = GrConicEffect::Create(kHairlineAA_GrEffectEdgeType,
|
||||
*target->caps());
|
||||
SkASSERT(NULL != hairConicEffect);
|
||||
drawState->addCoverageEffect(hairConicEffect, 1, 2)->unref();
|
||||
drawState->setGeometryProcessor(hairConicEffect, 1, 2)->unref();
|
||||
int conics = 0;
|
||||
while (conics < conicCnt) {
|
||||
int n = SkTMin(conicCnt - conics, kNumQuadsInIdxBuffer);
|
||||
|
@ -648,7 +648,7 @@ void GrAARectRenderer::shaderFillAARect(GrGpu* gpu,
|
||||
GrEffect* effect = GrRectEffect::Create();
|
||||
static const int kRectAttrIndex = 1;
|
||||
static const int kWidthIndex = 2;
|
||||
drawState->addCoverageEffect(effect, kRectAttrIndex, kWidthIndex)->unref();
|
||||
drawState->setGeometryProcessor(effect, kRectAttrIndex, kWidthIndex)->unref();
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
verts[i].fCenter = center;
|
||||
@ -697,7 +697,7 @@ void GrAARectRenderer::shaderFillAlignedAARect(GrGpu* gpu,
|
||||
|
||||
GrEffect* effect = GrAlignedRectEffect::Create();
|
||||
static const int kOffsetIndex = 1;
|
||||
drawState->addCoverageEffect(effect, kOffsetIndex)->unref();
|
||||
drawState->setGeometryProcessor(effect, kOffsetIndex)->unref();
|
||||
|
||||
SkRect devRect;
|
||||
combinedMatrix.mapRect(&devRect, rect);
|
||||
|
@ -108,7 +108,7 @@ void GrBitmapTextContext::flushGlyphs() {
|
||||
// This effect could be stored with one of the cache objects (atlas?)
|
||||
int coordsIdx = drawState->hasColorVertexAttribute() ? kGlyphCoordsWithColorAttributeIndex :
|
||||
kGlyphCoordsNoColorAttributeIndex;
|
||||
drawState->addCoverageEffect(fCachedEffect.get(), coordsIdx);
|
||||
drawState->setGeometryProcessor(fCachedEffect.get(), coordsIdx);
|
||||
SkASSERT(NULL != fStrike);
|
||||
switch (fStrike->getMaskFormat()) {
|
||||
// Color bitmap text
|
||||
|
@ -1738,7 +1738,8 @@ GrDrawTarget* GrContext::prepareToDraw(const GrPaint* paint,
|
||||
AutoCheckFlush* acf) {
|
||||
// All users of this draw state should be freeing up all effects when they're done.
|
||||
// Otherwise effects that own resources may keep those resources alive indefinitely.
|
||||
SkASSERT(0 == fDrawState->numColorStages() && 0 == fDrawState->numCoverageStages());
|
||||
SkASSERT(0 == fDrawState->numColorStages() && 0 == fDrawState->numCoverageStages() &&
|
||||
!fDrawState->hasGeometryProcessor());
|
||||
|
||||
if (NULL == fGpu) {
|
||||
return NULL;
|
||||
|
@ -54,6 +54,9 @@ GrDrawState::GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatr
|
||||
SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
|
||||
*this = state;
|
||||
if (!preConcatMatrix.isIdentity()) {
|
||||
if (this->hasGeometryProcessor()) {
|
||||
fGeometryProcessor->localCoordChange(preConcatMatrix);
|
||||
}
|
||||
for (int i = 0; i < this->numColorStages(); ++i) {
|
||||
fColorStages[i].localCoordChange(preConcatMatrix);
|
||||
}
|
||||
@ -79,6 +82,11 @@ GrDrawState& GrDrawState::operator=(const GrDrawState& that) {
|
||||
fStencilSettings = that.fStencilSettings;
|
||||
fCoverage = that.fCoverage;
|
||||
fDrawFace = that.fDrawFace;
|
||||
if (that.hasGeometryProcessor()) {
|
||||
fGeometryProcessor.reset(SkNEW_ARGS(GrEffectStage, (*that.fGeometryProcessor.get())));
|
||||
} else {
|
||||
fGeometryProcessor.reset(NULL);
|
||||
}
|
||||
fColorStages = that.fColorStages;
|
||||
fCoverageStages = that.fCoverageStages;
|
||||
fOptSrcBlend = that.fOptSrcBlend;
|
||||
@ -95,6 +103,7 @@ GrDrawState& GrDrawState::operator=(const GrDrawState& that) {
|
||||
|
||||
void GrDrawState::onReset(const SkMatrix* initialViewMatrix) {
|
||||
SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
|
||||
fGeometryProcessor.reset(NULL);
|
||||
fColorStages.reset();
|
||||
fCoverageStages.reset();
|
||||
|
||||
@ -128,6 +137,9 @@ bool GrDrawState::setIdentityViewMatrix() {
|
||||
// sad trombone sound
|
||||
return false;
|
||||
}
|
||||
if (this->hasGeometryProcessor()) {
|
||||
fGeometryProcessor->localCoordChange(invVM);
|
||||
}
|
||||
for (int s = 0; s < this->numColorStages(); ++s) {
|
||||
fColorStages[s].localCoordChange(invVM);
|
||||
}
|
||||
@ -142,6 +154,7 @@ bool GrDrawState::setIdentityViewMatrix() {
|
||||
void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRenderTarget* rt) {
|
||||
SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
|
||||
|
||||
fGeometryProcessor.reset(NULL);
|
||||
fColorStages.reset();
|
||||
fCoverageStages.reset();
|
||||
|
||||
@ -286,6 +299,8 @@ GrDrawState::AutoVertexAttribRestore::AutoVertexAttribRestore(
|
||||
|
||||
void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
|
||||
if (NULL != fDrawState) {
|
||||
fDrawState->fGeometryProcessor.reset(fGeometryProcessor.detach());
|
||||
|
||||
int m = fDrawState->numColorStages() - fColorEffectCnt;
|
||||
SkASSERT(m >= 0);
|
||||
fDrawState->fColorStages.pop_back_n(m);
|
||||
@ -300,6 +315,11 @@ void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
|
||||
}
|
||||
fDrawState = ds;
|
||||
if (NULL != ds) {
|
||||
if (ds->hasGeometryProcessor()) {
|
||||
fGeometryProcessor.reset(SkNEW_ARGS(GrEffectStage, (*ds->getGeometryProcessor())));
|
||||
} else {
|
||||
fGeometryProcessor.reset(NULL);
|
||||
}
|
||||
fColorEffectCnt = ds->numColorStages();
|
||||
fCoverageEffectCnt = ds->numCoverageStages();
|
||||
SkDEBUGCODE(++ds->fBlockEffectRemovalCnt;)
|
||||
@ -429,6 +449,10 @@ void GrDrawState::AutoViewMatrixRestore::restore() {
|
||||
SkASSERT(fDrawState->numCoverageStages() >= numCoverageStages);
|
||||
|
||||
int i = 0;
|
||||
if (fHasGeometryProcessor) {
|
||||
SkASSERT(fDrawState->hasGeometryProcessor());
|
||||
fDrawState->fGeometryProcessor->restoreCoordChange(fSavedCoordChanges[i++]);
|
||||
}
|
||||
for (int s = 0; s < fNumColorStages; ++s, ++i) {
|
||||
fDrawState->fColorStages[s].restoreCoordChange(fSavedCoordChanges[i]);
|
||||
}
|
||||
@ -471,6 +495,7 @@ bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
|
||||
if (0 == drawState->numTotalStages()) {
|
||||
drawState->fViewMatrix.reset();
|
||||
fDrawState = drawState;
|
||||
fHasGeometryProcessor = false;
|
||||
fNumColorStages = 0;
|
||||
fSavedCoordChanges.reset(0);
|
||||
SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
|
||||
@ -492,6 +517,13 @@ void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& co
|
||||
fSavedCoordChanges.reset(fDrawState->numTotalStages());
|
||||
int i = 0;
|
||||
|
||||
fHasGeometryProcessor = false;
|
||||
if (fDrawState->hasGeometryProcessor()) {
|
||||
fDrawState->fGeometryProcessor->saveCoordChange(&fSavedCoordChanges[i++]);
|
||||
fDrawState->fGeometryProcessor->localCoordChange(coordChangeMatrix);
|
||||
fHasGeometryProcessor = true;
|
||||
}
|
||||
|
||||
fNumColorStages = fDrawState->numColorStages();
|
||||
for (int s = 0; s < fNumColorStages; ++s, ++i) {
|
||||
fDrawState->getColorStage(s).saveCoordChange(&fSavedCoordChanges[i]);
|
||||
@ -543,6 +575,10 @@ bool GrDrawState::srcAlphaWillBeOne() const {
|
||||
}
|
||||
|
||||
// Run through the coverage stages
|
||||
if (this->hasGeometryProcessor()) {
|
||||
const GrEffect* effect = fGeometryProcessor->getEffect();
|
||||
effect->getConstantColorComponents(&coverage, &coverageComponentFlags);
|
||||
}
|
||||
for (int s = 0; s < this->numCoverageStages(); ++s) {
|
||||
const GrEffect* effect = this->getCoverageStage(s).getEffect();
|
||||
effect->getConstantColorComponents(&coverage, &coverageComponentFlags);
|
||||
|
@ -165,6 +165,20 @@ public:
|
||||
|
||||
/// @}
|
||||
|
||||
/**
|
||||
* The geometry processor is the sole element of the skia pipeline which can use the vertex,
|
||||
* geometry, and tesselation shaders. The GP may also compute a coverage in its fragment shader
|
||||
* but is never put in the color processing pipeline.
|
||||
*/
|
||||
|
||||
const GrEffect* setGeometryProcessor(const GrEffect* effect, int attr0 = -1, int attr1 = -1) {
|
||||
SkASSERT(NULL != effect);
|
||||
SkASSERT(!this->hasGeometryProcessor());
|
||||
fGeometryProcessor.reset(new GrEffectStage(effect, attr0, attr1));
|
||||
this->invalidateBlendOptFlags();
|
||||
return effect;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
/// @name Effect Stages
|
||||
/// Each stage hosts a GrEffect. The effect produces an output color or coverage in the fragment
|
||||
@ -242,6 +256,7 @@ public:
|
||||
|
||||
private:
|
||||
GrDrawState* fDrawState;
|
||||
SkAutoTDelete<GrEffectStage> fGeometryProcessor;
|
||||
int fColorEffectCnt;
|
||||
int fCoverageEffectCnt;
|
||||
};
|
||||
@ -364,6 +379,7 @@ public:
|
||||
GrDrawState* fDrawState;
|
||||
SkMatrix fViewMatrix;
|
||||
int fNumColorStages;
|
||||
bool fHasGeometryProcessor;
|
||||
SkAutoSTArray<8, GrEffectStage::SavedCoordChange> fSavedCoordChanges;
|
||||
};
|
||||
|
||||
|
@ -389,6 +389,15 @@ bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
|
||||
|
||||
SkASSERT(NULL != drawState.getRenderTarget());
|
||||
|
||||
if (drawState.hasGeometryProcessor()) {
|
||||
const GrEffect* effect = drawState.getGeometryProcessor()->getEffect();
|
||||
int numTextures = effect->numTextures();
|
||||
for (int t = 0; t < numTextures; ++t) {
|
||||
GrTexture* texture = effect->texture(t);
|
||||
SkASSERT(texture->asRenderTarget() != drawState.getRenderTarget());
|
||||
}
|
||||
}
|
||||
|
||||
for (int s = 0; s < drawState.numColorStages(); ++s) {
|
||||
const GrEffect* effect = drawState.getColorStage(s).getEffect();
|
||||
int numTextures = effect->numTextures();
|
||||
|
@ -553,7 +553,7 @@ void GrOvalRenderer::drawCircle(GrDrawTarget* target,
|
||||
|
||||
GrEffect* effect = CircleEdgeEffect::Create(isStrokeOnly && innerRadius > 0);
|
||||
static const int kCircleEdgeAttrIndex = 1;
|
||||
drawState->addCoverageEffect(effect, kCircleEdgeAttrIndex)->unref();
|
||||
drawState->setGeometryProcessor(effect, kCircleEdgeAttrIndex)->unref();
|
||||
|
||||
// The radii are outset for two reasons. First, it allows the shader to simply perform
|
||||
// clamp(distance-to-center - radius, 0, 1). Second, the outer radius is used to compute the
|
||||
@ -696,7 +696,7 @@ bool GrOvalRenderer::drawEllipse(GrDrawTarget* target,
|
||||
|
||||
static const int kEllipseCenterAttrIndex = 1;
|
||||
static const int kEllipseEdgeAttrIndex = 2;
|
||||
drawState->addCoverageEffect(effect, kEllipseCenterAttrIndex, kEllipseEdgeAttrIndex)->unref();
|
||||
drawState->setGeometryProcessor(effect, kEllipseCenterAttrIndex, kEllipseEdgeAttrIndex)->unref();
|
||||
|
||||
// Compute the reciprocals of the radii here to save time in the shader
|
||||
SkScalar xRadRecip = SkScalarInvert(xRadius);
|
||||
@ -814,8 +814,8 @@ bool GrOvalRenderer::drawDIEllipse(GrDrawTarget* target,
|
||||
|
||||
static const int kEllipseOuterOffsetAttrIndex = 1;
|
||||
static const int kEllipseInnerOffsetAttrIndex = 2;
|
||||
drawState->addCoverageEffect(effect, kEllipseOuterOffsetAttrIndex,
|
||||
kEllipseInnerOffsetAttrIndex)->unref();
|
||||
drawState->setGeometryProcessor(effect, kEllipseOuterOffsetAttrIndex,
|
||||
kEllipseInnerOffsetAttrIndex)->unref();
|
||||
|
||||
// This expands the outer rect so that after CTM we end up with a half-pixel border
|
||||
SkScalar a = vm[SkMatrix::kMScaleX];
|
||||
@ -1063,7 +1063,7 @@ bool GrOvalRenderer::drawRRect(GrDrawTarget* target, GrContext* context, bool us
|
||||
|
||||
GrEffect* effect = CircleEdgeEffect::Create(isStrokeOnly);
|
||||
static const int kCircleEdgeAttrIndex = 1;
|
||||
drawState->addCoverageEffect(effect, kCircleEdgeAttrIndex)->unref();
|
||||
drawState->setGeometryProcessor(effect, kCircleEdgeAttrIndex)->unref();
|
||||
|
||||
// The radii are outset for two reasons. First, it allows the shader to simply perform
|
||||
// clamp(distance-to-center - radius, 0, 1). Second, the outer radius is used to compute the
|
||||
@ -1168,8 +1168,9 @@ bool GrOvalRenderer::drawRRect(GrDrawTarget* target, GrContext* context, bool us
|
||||
GrEffect* effect = EllipseEdgeEffect::Create(isStrokeOnly);
|
||||
static const int kEllipseOffsetAttrIndex = 1;
|
||||
static const int kEllipseRadiiAttrIndex = 2;
|
||||
drawState->addCoverageEffect(effect,
|
||||
kEllipseOffsetAttrIndex, kEllipseRadiiAttrIndex)->unref();
|
||||
drawState->setGeometryProcessor(effect,
|
||||
kEllipseOffsetAttrIndex,
|
||||
kEllipseRadiiAttrIndex)->unref();
|
||||
|
||||
// Compute the reciprocals of the radii here to save time in the shader
|
||||
SkScalar xRadRecip = SkScalarInvert(xRadius);
|
||||
|
@ -38,6 +38,18 @@ bool GrRODrawState::isEqual(const GrRODrawState& that) const {
|
||||
}
|
||||
|
||||
bool explicitLocalCoords = this->hasLocalCoordAttribute();
|
||||
if (this->hasGeometryProcessor()) {
|
||||
if (!that.hasGeometryProcessor()) {
|
||||
return kIncompatible_CombinedState;
|
||||
} else if (!GrEffectStage::AreCompatible(*this->getGeometryProcessor(),
|
||||
*that.getGeometryProcessor(),
|
||||
explicitLocalCoords)) {
|
||||
return kIncompatible_CombinedState;
|
||||
}
|
||||
} else if (that.hasGeometryProcessor()) {
|
||||
return kIncompatible_CombinedState;
|
||||
}
|
||||
|
||||
for (int i = 0; i < this->numColorStages(); i++) {
|
||||
if (!GrEffectStage::AreCompatible(this->getColorStage(i), that.getColorStage(i),
|
||||
explicitLocalCoords)) {
|
||||
@ -66,11 +78,9 @@ bool GrRODrawState::validateVertexAttribs() const {
|
||||
for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
|
||||
slTypes[i] = static_cast<GrSLType>(-1);
|
||||
}
|
||||
int totalStages = this->numTotalStages();
|
||||
for (int s = 0; s < totalStages; ++s) {
|
||||
int covIdx = s - this->numColorStages();
|
||||
const GrEffectStage& stage = covIdx < 0 ? this->getColorStage(s) :
|
||||
this->getCoverageStage(covIdx);
|
||||
|
||||
if (this->hasGeometryProcessor()) {
|
||||
const GrEffectStage& stage = *this->getGeometryProcessor();
|
||||
const GrEffect* effect = stage.getEffect();
|
||||
SkASSERT(NULL != effect);
|
||||
// make sure that any attribute indices have the correct binding type, that the attrib
|
||||
@ -118,6 +128,10 @@ bool GrRODrawState::hasSolidCoverage() const {
|
||||
}
|
||||
|
||||
// Run through the coverage stages and see if the coverage will be all ones at the end.
|
||||
if (this->hasGeometryProcessor()) {
|
||||
const GrEffect* effect = fGeometryProcessor->getEffect();
|
||||
effect->getConstantColorComponents(&coverage, &validComponentFlags);
|
||||
}
|
||||
for (int s = 0; s < this->numCoverageStages(); ++s) {
|
||||
const GrEffect* effect = this->getCoverageStage(s).getEffect();
|
||||
effect->getConstantColorComponents(&coverage, &validComponentFlags);
|
||||
@ -140,6 +154,11 @@ bool GrRODrawState::willEffectReadDstColor() const {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (this->hasGeometryProcessor()) {
|
||||
if (fGeometryProcessor->getEffect()->willReadDstColor()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -121,8 +121,13 @@ public:
|
||||
|
||||
int numColorStages() const { return fColorStages.count(); }
|
||||
int numCoverageStages() const { return fCoverageStages.count(); }
|
||||
int numTotalStages() const { return this->numColorStages() + this->numCoverageStages(); }
|
||||
int numTotalStages() const {
|
||||
return this->numColorStages() + this->numCoverageStages() +
|
||||
(this->hasGeometryProcessor() ? 1 : 0);
|
||||
}
|
||||
|
||||
bool hasGeometryProcessor() const { return NULL != fGeometryProcessor.get(); }
|
||||
const GrEffectStage* getGeometryProcessor() const { return fGeometryProcessor.get(); }
|
||||
const GrEffectStage& getColorStage(int stageIdx) const { return fColorStages[stageIdx]; }
|
||||
const GrEffectStage& getCoverageStage(int stageIdx) const { return fCoverageStages[stageIdx]; }
|
||||
|
||||
@ -358,6 +363,7 @@ protected:
|
||||
GrBlendCoeff fDstBlend;
|
||||
|
||||
typedef SkSTArray<4, GrEffectStage> EffectStageArray;
|
||||
SkAutoTDelete<GrEffectStage> fGeometryProcessor;
|
||||
EffectStageArray fColorStages;
|
||||
EffectStageArray fCoverageStages;
|
||||
|
||||
|
@ -345,7 +345,7 @@ bool GrDashingEffect::DrawDashLine(const SkPoint pts[2], const GrPaint& paint,
|
||||
bool isRoundCap = SkPaint::kRound_Cap == cap;
|
||||
GrDashingEffect::DashCap capType = isRoundCap ? GrDashingEffect::kRound_DashCap :
|
||||
GrDashingEffect::kNonRound_DashCap;
|
||||
drawState->addCoverageEffect(
|
||||
drawState->setGeometryProcessor(
|
||||
GrDashingEffect::Create(edgeType, devInfo, strokeWidth, capType), 1)->unref();
|
||||
}
|
||||
|
||||
|
@ -23,17 +23,19 @@
|
||||
|
||||
GrGLProgram* GrGLProgram::Create(GrGpuGL* gpu,
|
||||
const GrGLProgramDesc& desc,
|
||||
const GrEffectStage* geometryProcessor,
|
||||
const GrEffectStage* colorStages[],
|
||||
const GrEffectStage* coverageStages[]) {
|
||||
SkAutoTDelete<GrGLProgramBuilder> builder;
|
||||
if (!desc.getHeader().fRequiresVertexShader &&
|
||||
gpu->glCaps().pathRenderingSupport() &&
|
||||
gpu->glPathRendering()->texturingMode() == GrGLPathRendering::FixedFunction_TexturingMode) {
|
||||
SkASSERT(NULL == geometryProcessor);
|
||||
builder.reset(SkNEW_ARGS(GrGLFragmentOnlyProgramBuilder, (gpu, desc)));
|
||||
} else {
|
||||
builder.reset(SkNEW_ARGS(GrGLFullProgramBuilder, (gpu, desc)));
|
||||
}
|
||||
if (builder->genProgram(colorStages, coverageStages)) {
|
||||
if (builder->genProgram(geometryProcessor, colorStages, coverageStages)) {
|
||||
SkASSERT(0 != builder->getProgramID());
|
||||
return SkNEW_ARGS(GrGLProgram, (gpu, desc, *builder));
|
||||
}
|
||||
@ -47,6 +49,7 @@ GrGLProgram::GrGLProgram(GrGpuGL* gpu,
|
||||
, fCoverage(GrColor_ILLEGAL)
|
||||
, fDstCopyTexUnit(-1)
|
||||
, fBuiltinUniformHandles(builder.getBuiltinUniformHandles())
|
||||
, fGeometryProcessor(SkSafeRef(builder.getGeometryProcessor()))
|
||||
, fColorEffects(SkRef(builder.getColorEffects()))
|
||||
, fCoverageEffects(SkRef(builder.getCoverageEffects()))
|
||||
, fProgramID(builder.getProgramID())
|
||||
@ -97,6 +100,9 @@ void GrGLProgram::initSamplerUniforms() {
|
||||
fProgramDataManager.setSampler(fBuiltinUniformHandles.fDstCopySamplerUni, texUnitIdx);
|
||||
fDstCopyTexUnit = texUnitIdx++;
|
||||
}
|
||||
if (NULL != fGeometryProcessor.get()) {
|
||||
fGeometryProcessor->initSamplers(fProgramDataManager, &texUnitIdx);
|
||||
}
|
||||
fColorEffects->initSamplers(fProgramDataManager, &texUnitIdx);
|
||||
fCoverageEffects->initSamplers(fProgramDataManager, &texUnitIdx);
|
||||
}
|
||||
@ -105,6 +111,7 @@ void GrGLProgram::initSamplerUniforms() {
|
||||
|
||||
void GrGLProgram::setData(GrGpu::DrawType drawType,
|
||||
GrDrawState::BlendOptFlags blendOpts,
|
||||
const GrEffectStage* geometryProcessor,
|
||||
const GrEffectStage* colorStages[],
|
||||
const GrEffectStage* coverageStages[],
|
||||
const GrDeviceCoordTexture* dstCopy,
|
||||
@ -149,6 +156,10 @@ void GrGLProgram::setData(GrGpu::DrawType drawType,
|
||||
SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid());
|
||||
}
|
||||
|
||||
if (NULL != fGeometryProcessor.get()) {
|
||||
SkASSERT(NULL != geometryProcessor);
|
||||
fGeometryProcessor->setData(fGpu, drawType,fProgramDataManager, geometryProcessor);
|
||||
}
|
||||
fColorEffects->setData(fGpu, drawType,fProgramDataManager, colorStages);
|
||||
fCoverageEffects->setData(fGpu, drawType,fProgramDataManager, coverageStages);
|
||||
|
||||
|
@ -41,6 +41,7 @@ public:
|
||||
|
||||
static GrGLProgram* Create(GrGpuGL* gpu,
|
||||
const GrGLProgramDesc& desc,
|
||||
const GrEffectStage* geometryProcessor,
|
||||
const GrEffectStage* colorStages[],
|
||||
const GrEffectStage* coverageStages[]);
|
||||
|
||||
@ -158,6 +159,7 @@ public:
|
||||
*/
|
||||
void setData(GrGpu::DrawType,
|
||||
GrDrawState::BlendOptFlags,
|
||||
const GrEffectStage* geometryProcessor,
|
||||
const GrEffectStage* colorStages[],
|
||||
const GrEffectStage* coverageStages[],
|
||||
const GrDeviceCoordTexture* dstCopy, // can be NULL
|
||||
@ -191,6 +193,7 @@ private:
|
||||
int fDstCopyTexUnit;
|
||||
|
||||
BuiltinUniformHandles fBuiltinUniformHandles;
|
||||
SkAutoTUnref<GrGLProgramEffects> fGeometryProcessor;
|
||||
SkAutoTUnref<GrGLProgramEffects> fColorEffects;
|
||||
SkAutoTUnref<GrGLProgramEffects> fCoverageEffects;
|
||||
GrGLuint fProgramID;
|
||||
|
@ -53,6 +53,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
|
||||
GrBlendCoeff dstCoeff,
|
||||
const GrGpuGL* gpu,
|
||||
const GrDeviceCoordTexture* dstCopy,
|
||||
const GrEffectStage** geometryProcessor,
|
||||
SkTArray<const GrEffectStage*, true>* colorStages,
|
||||
SkTArray<const GrEffectStage*, true>* coverageStages,
|
||||
GrGLProgramDesc* desc) {
|
||||
@ -69,6 +70,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
|
||||
|
||||
int firstEffectiveColorStage = 0;
|
||||
bool inputColorIsUsed = true;
|
||||
|
||||
if (!skipColor) {
|
||||
firstEffectiveColorStage = drawState.numColorStages();
|
||||
while (firstEffectiveColorStage > 0 && inputColorIsUsed) {
|
||||
@ -107,6 +109,9 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
|
||||
bool requiresVertexShader = !GrGpu::IsPathRenderingDrawType(drawType);
|
||||
|
||||
int numStages = 0;
|
||||
if (drawState.hasGeometryProcessor()) {
|
||||
numStages++;
|
||||
}
|
||||
if (!skipColor) {
|
||||
numStages += drawState.numColorStages() - firstEffectiveColorStage;
|
||||
}
|
||||
@ -120,9 +125,14 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
|
||||
|
||||
int offsetAndSizeIndex = 0;
|
||||
bool effectKeySuccess = true;
|
||||
if (!skipColor) {
|
||||
for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) {
|
||||
uint16_t* offsetAndSize =
|
||||
|
||||
KeyHeader* header = desc->header();
|
||||
// make sure any padding in the header is zeroed.
|
||||
memset(desc->header(), 0, kHeaderSize);
|
||||
|
||||
// We can only have one effect which touches the vertex shader
|
||||
if (drawState.hasGeometryProcessor()) {
|
||||
uint16_t* offsetAndSize =
|
||||
reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
|
||||
offsetAndSizeIndex * 2 * sizeof(uint16_t));
|
||||
|
||||
@ -130,7 +140,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
|
||||
uint16_t effectKeySize;
|
||||
uint32_t effectOffset = desc->fKey.count();
|
||||
effectKeySuccess |= GetEffectKeyAndUpdateStats(
|
||||
drawState.getColorStage(s), gpu->glCaps(),
|
||||
*drawState.getGeometryProcessor(), gpu->glCaps(),
|
||||
requiresLocalCoordAttrib, &b,
|
||||
&effectKeySize, &readsDst,
|
||||
&readFragPosition, &requiresVertexShader);
|
||||
@ -139,6 +149,32 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
|
||||
offsetAndSize[0] = SkToU16(effectOffset);
|
||||
offsetAndSize[1] = effectKeySize;
|
||||
++offsetAndSizeIndex;
|
||||
*geometryProcessor = drawState.getGeometryProcessor();
|
||||
SkASSERT(requiresVertexShader);
|
||||
header->fHasGeometryProcessor = true;
|
||||
}
|
||||
|
||||
if (!skipColor) {
|
||||
for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) {
|
||||
uint16_t* offsetAndSize =
|
||||
reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
|
||||
offsetAndSizeIndex * 2 * sizeof(uint16_t));
|
||||
|
||||
bool effectRequiresVertexShader = false;
|
||||
GrEffectKeyBuilder b(&desc->fKey);
|
||||
uint16_t effectKeySize;
|
||||
uint32_t effectOffset = desc->fKey.count();
|
||||
effectKeySuccess |= GetEffectKeyAndUpdateStats(
|
||||
drawState.getColorStage(s), gpu->glCaps(),
|
||||
requiresLocalCoordAttrib, &b,
|
||||
&effectKeySize, &readsDst,
|
||||
&readFragPosition, &effectRequiresVertexShader);
|
||||
effectKeySuccess |= (effectOffset <= SK_MaxU16);
|
||||
|
||||
offsetAndSize[0] = SkToU16(effectOffset);
|
||||
offsetAndSize[1] = effectKeySize;
|
||||
++offsetAndSizeIndex;
|
||||
SkASSERT(!effectRequiresVertexShader);
|
||||
}
|
||||
}
|
||||
if (!skipCoverage) {
|
||||
@ -147,6 +183,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
|
||||
reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
|
||||
offsetAndSizeIndex * 2 * sizeof(uint16_t));
|
||||
|
||||
bool effectRequiresVertexShader = false;
|
||||
GrEffectKeyBuilder b(&desc->fKey);
|
||||
uint16_t effectKeySize;
|
||||
uint32_t effectOffset = desc->fKey.count();
|
||||
@ -154,12 +191,13 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
|
||||
drawState.getCoverageStage(s), gpu->glCaps(),
|
||||
requiresLocalCoordAttrib, &b,
|
||||
&effectKeySize, &readsDst,
|
||||
&readFragPosition, &requiresVertexShader);
|
||||
&readFragPosition, &effectRequiresVertexShader);
|
||||
effectKeySuccess |= (effectOffset <= SK_MaxU16);
|
||||
|
||||
offsetAndSize[0] = SkToU16(effectOffset);
|
||||
offsetAndSize[1] = effectKeySize;
|
||||
++offsetAndSizeIndex;
|
||||
SkASSERT(!effectRequiresVertexShader);
|
||||
}
|
||||
}
|
||||
if (!effectKeySuccess) {
|
||||
@ -167,10 +205,6 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
|
||||
return false;
|
||||
}
|
||||
|
||||
KeyHeader* header = desc->header();
|
||||
// make sure any padding in the header is zeroed.
|
||||
memset(desc->header(), 0, kHeaderSize);
|
||||
|
||||
// Because header is a pointer into the dynamic array, we can't push any new data into the key
|
||||
// below here.
|
||||
|
||||
@ -259,9 +293,11 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
|
||||
header->fCoverageOutput = kModulate_CoverageOutput;
|
||||
|
||||
// If we do have coverage determine whether it matters.
|
||||
bool separateCoverageFromColor = false;
|
||||
bool separateCoverageFromColor = drawState.hasGeometryProcessor();
|
||||
if (!drawState.isCoverageDrawing() && !skipCoverage &&
|
||||
(drawState.numCoverageStages() > 0 || requiresCoverageAttrib)) {
|
||||
(drawState.numCoverageStages() > 0 ||
|
||||
drawState.hasGeometryProcessor() ||
|
||||
requiresCoverageAttrib)) {
|
||||
|
||||
if (gpu->caps()->dualSourceBlendingSupport() &&
|
||||
!(blendOpts & (GrDrawState::kEmitCoverage_BlendOptFlag |
|
||||
@ -286,6 +322,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
|
||||
separateCoverageFromColor = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!skipColor) {
|
||||
for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) {
|
||||
colorStages->push_back(&drawState.getColorStage(s));
|
||||
|
@ -48,6 +48,7 @@ public:
|
||||
const GrGpuGL* gpu,
|
||||
const GrRenderTarget* dummyDstRenderTarget,
|
||||
const GrTexture* dummyDstCopyTexture,
|
||||
const GrEffectStage* geometryProcessor,
|
||||
const GrEffectStage* stages[],
|
||||
int numColorStages,
|
||||
int numCoverageStages,
|
||||
@ -67,10 +68,15 @@ public:
|
||||
GrBlendCoeff dstCoeff,
|
||||
const GrGpuGL* gpu,
|
||||
const GrDeviceCoordTexture* dstCopy,
|
||||
const GrEffectStage** outGeometryProcessor,
|
||||
SkTArray<const GrEffectStage*, true>* outColorStages,
|
||||
SkTArray<const GrEffectStage*, true>* outCoverageStages,
|
||||
GrGLProgramDesc* outDesc);
|
||||
|
||||
bool hasGeometryProcessor() const {
|
||||
return SkToBool(this->getHeader().fHasGeometryProcessor);
|
||||
}
|
||||
|
||||
int numColorEffects() const {
|
||||
return this->getHeader().fColorEffectCnt;
|
||||
}
|
||||
@ -161,6 +167,7 @@ private:
|
||||
int8_t fColorAttributeIndex;
|
||||
int8_t fCoverageAttributeIndex;
|
||||
|
||||
SkBool8 fHasGeometryProcessor;
|
||||
int8_t fColorEffectCnt;
|
||||
int8_t fCoverageEffectCnt;
|
||||
};
|
||||
@ -213,13 +220,24 @@ private:
|
||||
class EffectKeyProvider {
|
||||
public:
|
||||
enum EffectType {
|
||||
kGeometryProcessor_EffectType,
|
||||
kColor_EffectType,
|
||||
kCoverage_EffectType,
|
||||
};
|
||||
|
||||
EffectKeyProvider(const GrGLProgramDesc* desc, EffectType type) : fDesc(desc) {
|
||||
// Coverage effect key offsets begin immediately after those of the color effects.
|
||||
fBaseIndex = kColor_EffectType == type ? 0 : desc->numColorEffects();
|
||||
switch (type) {
|
||||
case kGeometryProcessor_EffectType:
|
||||
// there can be only one
|
||||
fBaseIndex = 0;
|
||||
break;
|
||||
case kColor_EffectType:
|
||||
fBaseIndex = desc->hasGeometryProcessor() ? 1 : 0;
|
||||
break;
|
||||
case kCoverage_EffectType:
|
||||
fBaseIndex = desc->numColorEffects() + (desc->hasGeometryProcessor() ? 1 : 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GrEffectKey get(int index) const {
|
||||
|
@ -387,6 +387,24 @@ void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
|
||||
GrGpu::DrawType drawType,
|
||||
const GrGLProgramDataManager& programDataManager,
|
||||
const GrEffectStage* effectStage) {
|
||||
SkASSERT(1 == fTransforms.count());
|
||||
SkASSERT(1 == fSamplers.count());
|
||||
SkASSERT(1 == fGLEffects.count());
|
||||
GrDrawEffect drawEffect(*effectStage, fHasExplicitLocalCoords);
|
||||
fGLEffects[0]->setData(programDataManager, drawEffect);
|
||||
if (GrGpu::IsPathRenderingDrawType(drawType)) {
|
||||
this->setPathTransformData(gpu, programDataManager, drawEffect, 0);
|
||||
} else {
|
||||
this->setTransformData(gpu, programDataManager, drawEffect, 0);
|
||||
}
|
||||
|
||||
this->bindTextures(gpu, drawEffect.effect(), 0);
|
||||
}
|
||||
|
||||
void GrGLVertexProgramEffects::setTransformData(GrGpuGL* gpu,
|
||||
const GrGLProgramDataManager& pdman,
|
||||
const GrDrawEffect& drawEffect,
|
||||
|
@ -57,6 +57,11 @@ public:
|
||||
const GrGLProgramDataManager&,
|
||||
const GrEffectStage* effectStages[]) = 0;
|
||||
|
||||
virtual void setData(GrGpuGL*,
|
||||
GrGpu::DrawType,
|
||||
const GrGLProgramDataManager&,
|
||||
const GrEffectStage* effectStages) { SkFAIL("DO NOT USE"); }
|
||||
|
||||
void addEffect(GrGLEffect* effect) { fGLEffects.push_back(effect); }
|
||||
|
||||
/**
|
||||
@ -140,7 +145,6 @@ protected:
|
||||
SkTArray<SkSTArray<4, Sampler, true> > fSamplers;
|
||||
|
||||
private:
|
||||
friend class GrGLFragmentO;
|
||||
typedef SkRefCnt INHERITED;
|
||||
};
|
||||
|
||||
@ -172,6 +176,11 @@ public:
|
||||
const GrGLProgramDataManager&,
|
||||
const GrEffectStage* effectStages[]) SK_OVERRIDE;
|
||||
|
||||
virtual void setData(GrGpuGL*,
|
||||
GrGpu::DrawType,
|
||||
const GrGLProgramDataManager&,
|
||||
const GrEffectStage* effectStages) SK_OVERRIDE;
|
||||
|
||||
private:
|
||||
friend class GrGLFullProgramBuilder;
|
||||
|
||||
|
@ -179,6 +179,7 @@ private:
|
||||
|
||||
void abandon();
|
||||
GrGLProgram* getProgram(const GrGLProgramDesc& desc,
|
||||
const GrEffectStage* geometryProcessor,
|
||||
const GrEffectStage* colorStages[],
|
||||
const GrEffectStage* coverageStages[]);
|
||||
|
||||
|
@ -90,6 +90,7 @@ int GrGpuGL::ProgramCache::search(const GrGLProgramDesc& desc) const {
|
||||
}
|
||||
|
||||
GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrGLProgramDesc& desc,
|
||||
const GrEffectStage* geometryProcessor,
|
||||
const GrEffectStage* colorStages[],
|
||||
const GrEffectStage* coverageStages[]) {
|
||||
#ifdef PROGRAM_CACHE_STATS
|
||||
@ -126,7 +127,8 @@ GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrGLProgramDesc& desc,
|
||||
#ifdef PROGRAM_CACHE_STATS
|
||||
++fCacheMisses;
|
||||
#endif
|
||||
GrGLProgram* program = GrGLProgram::Create(fGpu, desc, colorStages, coverageStages);
|
||||
GrGLProgram* program = GrGLProgram::Create(fGpu, desc, geometryProcessor,
|
||||
colorStages, coverageStages);
|
||||
if (NULL == program) {
|
||||
return NULL;
|
||||
}
|
||||
@ -222,6 +224,7 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
|
||||
return false;
|
||||
}
|
||||
|
||||
const GrEffectStage* geometryProcessor = NULL;
|
||||
SkSTArray<8, const GrEffectStage*, true> colorStages;
|
||||
SkSTArray<8, const GrEffectStage*, true> coverageStages;
|
||||
GrGLProgramDesc desc;
|
||||
@ -232,6 +235,7 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
|
||||
dstCoeff,
|
||||
this,
|
||||
dstCopy,
|
||||
&geometryProcessor,
|
||||
&colorStages,
|
||||
&coverageStages,
|
||||
&desc)) {
|
||||
@ -240,6 +244,7 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
|
||||
}
|
||||
|
||||
fCurrentProgram.reset(fProgramCache->getProgram(desc,
|
||||
geometryProcessor,
|
||||
colorStages.begin(),
|
||||
coverageStages.begin()));
|
||||
if (NULL == fCurrentProgram.get()) {
|
||||
@ -260,6 +265,7 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
|
||||
|
||||
fCurrentProgram->setData(type,
|
||||
blendOpts,
|
||||
geometryProcessor,
|
||||
colorStages.begin(),
|
||||
coverageStages.begin(),
|
||||
dstCopy,
|
||||
|
@ -31,7 +31,8 @@ static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar:
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool GrGLProgramBuilder::genProgram(const GrEffectStage* colorStages[],
|
||||
bool GrGLProgramBuilder::genProgram(const GrEffectStage* geometryProcessor,
|
||||
const GrEffectStage* colorStages[],
|
||||
const GrEffectStage* coverageStages[]) {
|
||||
const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader();
|
||||
|
||||
@ -79,6 +80,8 @@ bool GrGLProgramBuilder::genProgram(const GrEffectStage* colorStages[],
|
||||
colorKeyProvider,
|
||||
&inputColor));
|
||||
|
||||
this->emitGeometryProcessor(geometryProcessor, &inputCoverage);
|
||||
|
||||
GrGLProgramDesc::EffectKeyProvider coverageKeyProvider(
|
||||
&this->desc(), GrGLProgramDesc::EffectKeyProvider::kCoverage_EffectType);
|
||||
fCoverageEffects.reset(this->createAndEmitEffects(coverageStages,
|
||||
@ -334,10 +337,23 @@ GrGLFullProgramBuilder::GrGLFullProgramBuilder(GrGpuGL* gpu,
|
||||
, fVS(this) {
|
||||
}
|
||||
|
||||
void GrGLFullProgramBuilder::emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) {
|
||||
void GrGLFullProgramBuilder::emitCodeBeforeEffects(GrGLSLExpr4* color,
|
||||
GrGLSLExpr4* coverage) {
|
||||
fVS.emitCodeBeforeEffects(color, coverage);
|
||||
}
|
||||
|
||||
void GrGLFullProgramBuilder::emitGeometryProcessor(const GrEffectStage* geometryProcessor,
|
||||
GrGLSLExpr4* coverage) {
|
||||
if (NULL != geometryProcessor) {
|
||||
GrGLProgramDesc::EffectKeyProvider geometryProcessorKeyProvider(
|
||||
&this->desc(), GrGLProgramDesc::EffectKeyProvider::kGeometryProcessor_EffectType);
|
||||
fGeometryProcessor.reset(this->createAndEmitEffect(
|
||||
geometryProcessor,
|
||||
geometryProcessorKeyProvider,
|
||||
coverage));
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLFullProgramBuilder::emitCodeAfterEffects() {
|
||||
fVS.emitCodeAfterEffects();
|
||||
}
|
||||
@ -388,6 +404,56 @@ GrGLProgramEffects* GrGLFullProgramBuilder::createAndEmitEffects(
|
||||
return programEffectsBuilder.finish();
|
||||
}
|
||||
|
||||
void GrGLFullProgramBuilder::createAndEmitEffect(GrGLProgramEffectsBuilder* programEffectsBuilder,
|
||||
const GrEffectStage* effectStages,
|
||||
const GrGLProgramDesc::EffectKeyProvider& keyProvider,
|
||||
GrGLSLExpr4* fsInOutColor) {
|
||||
GrGLSLExpr4 inColor = *fsInOutColor;
|
||||
GrGLSLExpr4 outColor;
|
||||
|
||||
SkASSERT(NULL != effectStages && NULL != effectStages->getEffect());
|
||||
const GrEffectStage& stage = *effectStages;
|
||||
|
||||
// Using scope to force ASR destructor to be triggered
|
||||
{
|
||||
CodeStage::AutoStageRestore csar(&fCodeStage, &stage);
|
||||
|
||||
if (inColor.isZeros()) {
|
||||
SkString inColorName;
|
||||
|
||||
// Effects have no way to communicate zeros, they treat an empty string as ones.
|
||||
this->nameVariable(&inColorName, '\0', "input");
|
||||
fFS.codeAppendf("vec4 %s = %s;", inColorName.c_str(), inColor.c_str());
|
||||
inColor = inColorName;
|
||||
}
|
||||
|
||||
// create var to hold stage result
|
||||
SkString outColorName;
|
||||
this->nameVariable(&outColorName, '\0', "output");
|
||||
fFS.codeAppendf("vec4 %s;", outColorName.c_str());
|
||||
outColor = outColorName;
|
||||
|
||||
|
||||
programEffectsBuilder->emitEffect(stage,
|
||||
keyProvider.get(0),
|
||||
outColor.c_str(),
|
||||
inColor.isOnes() ? NULL : inColor.c_str(),
|
||||
fCodeStage.stageIndex());
|
||||
}
|
||||
|
||||
*fsInOutColor = outColor;
|
||||
}
|
||||
|
||||
GrGLProgramEffects* GrGLFullProgramBuilder::createAndEmitEffect(
|
||||
const GrEffectStage* geometryProcessor,
|
||||
const GrGLProgramDesc::EffectKeyProvider& keyProvider,
|
||||
GrGLSLExpr4* inOutFSColor) {
|
||||
|
||||
GrGLVertexProgramEffectsBuilder programEffectsBuilder(this, 1);
|
||||
this->createAndEmitEffect(&programEffectsBuilder, geometryProcessor, keyProvider, inOutFSColor);
|
||||
return programEffectsBuilder.finish();
|
||||
}
|
||||
|
||||
bool GrGLFullProgramBuilder::compileAndAttachShaders(GrGLuint programId,
|
||||
SkTDArray<GrGLuint>* shaderIds) const {
|
||||
return INHERITED::compileAndAttachShaders(programId, shaderIds)
|
||||
|
@ -84,11 +84,14 @@ public:
|
||||
* to be used.
|
||||
* @return true if generation was successful.
|
||||
*/
|
||||
bool genProgram(const GrEffectStage* inColorStages[],
|
||||
|
||||
bool genProgram(const GrEffectStage* inGeometryProcessor,
|
||||
const GrEffectStage* inColorStages[],
|
||||
const GrEffectStage* inCoverageStages[]);
|
||||
|
||||
// Below are the results of the shader generation.
|
||||
|
||||
GrGLProgramEffects* getGeometryProcessor() const {
|
||||
SkASSERT(fProgramID); return fGeometryProcessor.get();
|
||||
}
|
||||
GrGLProgramEffects* getColorEffects() const { SkASSERT(fProgramID); return fColorEffects.get(); }
|
||||
GrGLProgramEffects* getCoverageEffects() const { SkASSERT(fProgramID); return fCoverageEffects.get(); }
|
||||
const BuiltinUniformHandles& getBuiltinUniformHandles() const {
|
||||
@ -165,6 +168,7 @@ protected:
|
||||
void appendDecls(const VarArray&, SkString*) const;
|
||||
void appendUniformDecls(ShaderVisibility, SkString*) const;
|
||||
|
||||
SkAutoTUnref<GrGLProgramEffects> fGeometryProcessor;
|
||||
SkAutoTUnref<GrGLProgramEffects> fColorEffects;
|
||||
SkAutoTUnref<GrGLProgramEffects> fCoverageEffects;
|
||||
BuiltinUniformHandles fUniformHandles;
|
||||
@ -173,7 +177,7 @@ protected:
|
||||
GrGLuint fProgramID;
|
||||
GrGLFragmentShaderBuilder fFS;
|
||||
SeparableVaryingInfoArray fSeparableVaryingInfos;
|
||||
private:
|
||||
|
||||
class CodeStage : SkNoncopyable {
|
||||
public:
|
||||
CodeStage() : fNextIndex(0), fCurrentIndex(-1), fEffectStage(NULL) {}
|
||||
@ -224,6 +228,7 @@ private:
|
||||
int fCurrentIndex;
|
||||
const GrEffectStage* fEffectStage;
|
||||
} fCodeStage;
|
||||
private:
|
||||
|
||||
/**
|
||||
* The base class will emit the fragment code that precedes the per-effect code and then call
|
||||
@ -232,7 +237,14 @@ private:
|
||||
*
|
||||
* The subclass can modify the initial color or coverage
|
||||
*/
|
||||
virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) = 0;
|
||||
virtual void emitCodeBeforeEffects(GrGLSLExpr4* color,
|
||||
GrGLSLExpr4* coverage) = 0;
|
||||
|
||||
/*
|
||||
* Full shader builder needs to emit code after the color stages and before the coverage stages
|
||||
*/
|
||||
virtual void emitGeometryProcessor(const GrEffectStage* geometryProcessor,
|
||||
GrGLSLExpr4* coverage) = 0;
|
||||
|
||||
/**
|
||||
* Adds code for effects and returns a GrGLProgramEffects* object. The caller is responsible for
|
||||
@ -297,13 +309,30 @@ public:
|
||||
GrGLVertexShaderBuilder* getVertexShaderBuilder() { return &fVS; }
|
||||
|
||||
private:
|
||||
virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) SK_OVERRIDE;
|
||||
virtual void emitCodeBeforeEffects(GrGLSLExpr4* color,
|
||||
GrGLSLExpr4* coverage) SK_OVERRIDE;
|
||||
|
||||
virtual void emitGeometryProcessor(const GrEffectStage* geometryProcessor,
|
||||
GrGLSLExpr4* coverage) SK_OVERRIDE;
|
||||
|
||||
virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
|
||||
int effectCnt,
|
||||
const GrGLProgramDesc::EffectKeyProvider&,
|
||||
GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;
|
||||
|
||||
/*
|
||||
* These functions are temporary and will eventually operate not on effects but on
|
||||
* geometry processors
|
||||
*/
|
||||
void createAndEmitEffect(GrGLProgramEffectsBuilder*,
|
||||
const GrEffectStage* effectStage,
|
||||
const GrGLProgramDesc::EffectKeyProvider&,
|
||||
GrGLSLExpr4* inOutFSColor);
|
||||
|
||||
GrGLProgramEffects* createAndEmitEffect(const GrEffectStage* geometryProcessor,
|
||||
const GrGLProgramDesc::EffectKeyProvider&,
|
||||
GrGLSLExpr4* inOutFSColor);
|
||||
|
||||
virtual void emitCodeAfterEffects() SK_OVERRIDE;
|
||||
|
||||
virtual bool compileAndAttachShaders(GrGLuint programId,
|
||||
@ -326,7 +355,13 @@ public:
|
||||
int addTexCoordSets(int count);
|
||||
|
||||
private:
|
||||
virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) SK_OVERRIDE {}
|
||||
virtual void emitCodeBeforeEffects(GrGLSLExpr4* color,
|
||||
GrGLSLExpr4* coverage) SK_OVERRIDE {}
|
||||
|
||||
virtual void emitGeometryProcessor(const GrEffectStage* geometryProcessor,
|
||||
GrGLSLExpr4* coverage) SK_OVERRIDE {
|
||||
SkASSERT(NULL == geometryProcessor);
|
||||
}
|
||||
|
||||
virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
|
||||
int effectCnt,
|
||||
|
@ -26,6 +26,7 @@ bool GrGLProgramDesc::setRandom(SkRandom* random,
|
||||
const GrGpuGL* gpu,
|
||||
const GrRenderTarget* dstRenderTarget,
|
||||
const GrTexture* dstCopyTexture,
|
||||
const GrEffectStage* geometryProcessor,
|
||||
const GrEffectStage* stages[],
|
||||
int numColorStages,
|
||||
int numCoverageStages,
|
||||
@ -38,24 +39,50 @@ bool GrGLProgramDesc::setRandom(SkRandom* random,
|
||||
GR_STATIC_ASSERT(0 == kEffectKeyOffsetsAndLengthOffset % sizeof(uint32_t));
|
||||
|
||||
// Make room for everything up to and including the array of offsets to effect keys.
|
||||
fKey.push_back_n(kEffectKeyOffsetsAndLengthOffset + 2 * sizeof(uint16_t) * numStages);
|
||||
fKey.push_back_n(kEffectKeyOffsetsAndLengthOffset + 2 * sizeof(uint16_t) * (numStages +
|
||||
(geometryProcessor ? 1 : 0)));
|
||||
|
||||
bool dstRead = false;
|
||||
bool fragPos = false;
|
||||
bool vertexShader = false;
|
||||
for (int s = 0; s < numStages; ++s) {
|
||||
bool vertexShader = (NULL != geometryProcessor);
|
||||
int offset = 0;
|
||||
if (NULL != geometryProcessor) {
|
||||
const GrEffectStage* stage = geometryProcessor;
|
||||
uint16_t* offsetAndSize = reinterpret_cast<uint16_t*>(fKey.begin() +
|
||||
kEffectKeyOffsetsAndLengthOffset +
|
||||
s * 2 * sizeof(uint16_t));
|
||||
offset * 2 * sizeof(uint16_t));
|
||||
uint32_t effectKeyOffset = fKey.count();
|
||||
if (effectKeyOffset > SK_MaxU16) {
|
||||
fKey.reset();
|
||||
return false;
|
||||
}
|
||||
GrDrawEffect drawEffect(*stages[s], useLocalCoords);
|
||||
GrDrawEffect drawEffect(*stage, useLocalCoords);
|
||||
GrEffectKeyBuilder b(&fKey);
|
||||
uint16_t effectKeySize;
|
||||
if (!GetEffectKeyAndUpdateStats(*stages[s], gpu->glCaps(), useLocalCoords, &b,
|
||||
if (!GetEffectKeyAndUpdateStats(*stage, gpu->glCaps(), useLocalCoords, &b,
|
||||
&effectKeySize, &dstRead, &fragPos, &vertexShader)) {
|
||||
fKey.reset();
|
||||
return false;
|
||||
}
|
||||
offsetAndSize[0] = effectKeyOffset;
|
||||
offsetAndSize[1] = effectKeySize;
|
||||
offset++;
|
||||
}
|
||||
|
||||
for (int s = 0; s < numStages; ++s, ++offset) {
|
||||
const GrEffectStage* stage = stages[s];
|
||||
uint16_t* offsetAndSize = reinterpret_cast<uint16_t*>(fKey.begin() +
|
||||
kEffectKeyOffsetsAndLengthOffset +
|
||||
offset * 2 * sizeof(uint16_t));
|
||||
uint32_t effectKeyOffset = fKey.count();
|
||||
if (effectKeyOffset > SK_MaxU16) {
|
||||
fKey.reset();
|
||||
return false;
|
||||
}
|
||||
GrDrawEffect drawEffect(*stage, useLocalCoords);
|
||||
GrEffectKeyBuilder b(&fKey);
|
||||
uint16_t effectKeySize;
|
||||
if (!GetEffectKeyAndUpdateStats(*stage, gpu->glCaps(), useLocalCoords, &b,
|
||||
&effectKeySize, &dstRead, &fragPos, &vertexShader)) {
|
||||
fKey.reset();
|
||||
return false;
|
||||
@ -118,6 +145,7 @@ bool GrGLProgramDesc::setRandom(SkRandom* random,
|
||||
useLocalCoords ||
|
||||
kAttribute_ColorInput == header->fColorInput ||
|
||||
kAttribute_ColorInput == header->fCoverageInput;
|
||||
header->fHasGeometryProcessor = vertexShader;
|
||||
|
||||
CoverageOutput coverageOutput;
|
||||
bool illegalCoverageOutput;
|
||||
@ -179,8 +207,35 @@ bool GrGpuGL::programUnitTest(int maxStages) {
|
||||
SkAutoSTMalloc<8, const GrEffectStage*> stages(numStages);
|
||||
|
||||
bool useFixedFunctionPathRendering = this->glCaps().pathRenderingSupport() &&
|
||||
this->glPathRendering()->texturingMode() == GrGLPathRendering::FixedFunction_TexturingMode;
|
||||
this->glPathRendering()->texturingMode() == GrGLPathRendering::FixedFunction_TexturingMode &&
|
||||
random.nextBool();
|
||||
|
||||
SkAutoTDelete<GrEffectStage> geometryProcessor;
|
||||
bool hasGeometryProcessor = useFixedFunctionPathRendering ? false : random.nextBool();
|
||||
if (hasGeometryProcessor) {
|
||||
while (true) {
|
||||
SkAutoTUnref<const GrEffect> effect(GrEffectTestFactory::CreateStage(
|
||||
&random,
|
||||
this->getContext(),
|
||||
*this->caps(),
|
||||
dummyTextures));
|
||||
SkASSERT(effect);
|
||||
|
||||
// Only geometryProcessor can use vertex shader
|
||||
if (!effect->requiresVertexShader()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int numAttribs = effect->numVertexAttribs();
|
||||
for (int i = 0; i < numAttribs; ++i) {
|
||||
attribIndices[i] = currAttribIndex++;
|
||||
}
|
||||
GrEffectStage* stage = SkNEW_ARGS(GrEffectStage,
|
||||
(effect.get(), attribIndices[0], attribIndices[1]));
|
||||
geometryProcessor.reset(stage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int s = 0; s < numStages;) {
|
||||
SkAutoTUnref<const GrEffect> effect(GrEffectTestFactory::CreateStage(
|
||||
&random,
|
||||
@ -188,32 +243,24 @@ bool GrGpuGL::programUnitTest(int maxStages) {
|
||||
*this->caps(),
|
||||
dummyTextures));
|
||||
SkASSERT(effect);
|
||||
int numAttribs = effect->numVertexAttribs();
|
||||
|
||||
// If adding this effect would exceed the max attrib count then generate a
|
||||
// new random effect.
|
||||
if (currAttribIndex + numAttribs > GrDrawState::kMaxVertexAttribCnt) {
|
||||
// Only geometryProcessor can use vertex shader
|
||||
if (effect->requiresVertexShader()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// If adding this effect would exceed the max texture coord set count then generate a
|
||||
// new random effect.
|
||||
if (useFixedFunctionPathRendering && !effect->requiresVertexShader()) {
|
||||
if (useFixedFunctionPathRendering) {
|
||||
int numTransforms = effect->numTransforms();
|
||||
if (currTextureCoordSet + numTransforms > this->glCaps().maxFixedFunctionTextureCoords()) {
|
||||
continue;
|
||||
}
|
||||
currTextureCoordSet += numTransforms;
|
||||
}
|
||||
|
||||
useFixedFunctionPathRendering = useFixedFunctionPathRendering && !effect->requiresVertexShader();
|
||||
|
||||
for (int i = 0; i < numAttribs; ++i) {
|
||||
attribIndices[i] = currAttribIndex++;
|
||||
}
|
||||
GrEffectStage* stage = SkNEW_ARGS(GrEffectStage,
|
||||
(effect.get(), attribIndices[0], attribIndices[1]));
|
||||
|
||||
stages[s] = stage;
|
||||
++s;
|
||||
}
|
||||
@ -222,6 +269,7 @@ bool GrGpuGL::programUnitTest(int maxStages) {
|
||||
this,
|
||||
dummyTextures[0]->asRenderTarget(),
|
||||
dstTexture,
|
||||
geometryProcessor.get(),
|
||||
stages.get(),
|
||||
numColorStages,
|
||||
numCoverageStages,
|
||||
@ -231,6 +279,7 @@ bool GrGpuGL::programUnitTest(int maxStages) {
|
||||
|
||||
SkAutoTUnref<GrGLProgram> program(GrGLProgram::Create(this,
|
||||
pdesc,
|
||||
geometryProcessor.get(),
|
||||
stages,
|
||||
stages + numColorStages));
|
||||
for (int s = 0; s < numStages; ++s) {
|
||||
|
Loading…
Reference in New Issue
Block a user