diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index f7ad9f8918..64ae1a5e4c 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -1943,10 +1943,9 @@ void GrContext::setPaint(const GrPaint& paint, GrDrawTarget* target) { drawState->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff); drawState->setColorFilter(paint.fColorFilterColor, paint.fColorFilterXfermode); drawState->setCoverage(paint.fCoverage); - -#if 0 // this code is broken. canApplyCoverage incorrectly looks at the - // the vertex layout when the vertex src hasn't been set yet - if (paint.getActiveMaskStageMask() && !target->canApplyCoverage()) { +#if GR_DEBUG + if ((paint.getActiveMaskStageMask() || 0xff != paint.fCoverage) && + !target->canApplyCoverage()) { GrPrintf("Partial pixel coverage will be incorrectly blended.\n"); } #endif diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp index 5cce435916..ef03a61417 100644 --- a/src/gpu/GrDrawTarget.cpp +++ b/src/gpu/GrDrawTarget.cpp @@ -853,9 +853,7 @@ bool GrDrawTarget::canTweakAlphaForCoverage() const { kISC_BlendCoeff == dstCoeff; } - -bool GrDrawTarget::srcAlphaWillBeOne() const { - const GrVertexLayout& layout = this->getGeomSrc().fVertexLayout; +bool GrDrawTarget::srcAlphaWillBeOne(GrVertexLayout layout) const { const GrDrawState& drawState = this->getDrawState(); // Check if per-vertex or constant color may have partial alpha @@ -882,12 +880,28 @@ bool GrDrawTarget::srcAlphaWillBeOne() const { return true; } +namespace { +GrVertexLayout default_blend_opts_vertex_layout() { + GrVertexLayout layout = 0; + for (int s = 0; s < GrDrawState::kNumStages; ++s) { + layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s); + } + return layout; +} +} + GrDrawTarget::BlendOptFlags GrDrawTarget::getBlendOpts(bool forceCoverage, GrBlendCoeff* srcCoeff, GrBlendCoeff* dstCoeff) const { - const GrVertexLayout& layout = this->getGeomSrc().fVertexLayout; + GrVertexLayout layout; + if (kNone_GeometrySrcType == this->getGeomSrc().fVertexSrc) { + layout = default_blend_opts_vertex_layout(); + } else { + layout = this->getVertexLayout(); + } + const GrDrawState& drawState = this->getDrawState(); GrBlendCoeff bogusSrcCoeff, bogusDstCoeff; @@ -917,7 +931,7 @@ GrDrawTarget::getBlendOpts(bool forceCoverage, *dstCoeff = kOne_BlendCoeff; } - bool srcAIsOne = this->srcAlphaWillBeOne(); + bool srcAIsOne = this->srcAlphaWillBeOne(layout); bool dstCoeffIsOne = kOne_BlendCoeff == *dstCoeff || (kSA_BlendCoeff == *dstCoeff && srcAIsOne); bool dstCoeffIsZero = kZero_BlendCoeff == *dstCoeff || @@ -1022,11 +1036,6 @@ bool GrDrawTarget::canApplyCoverage() const { kNone_BlendOpt != this->getBlendOpts(true); } -bool GrDrawTarget::drawWillReadDst() const { - return SkToBool((kDisableBlend_BlendOptFlag | kSkipDraw_BlendOptFlag) & - this->getBlendOpts()); -} - //////////////////////////////////////////////////////////////////////////////// void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type, diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h index 731cae5d25..8f5be3c500 100644 --- a/src/gpu/GrDrawTarget.h +++ b/src/gpu/GrDrawTarget.h @@ -116,15 +116,6 @@ public: this->drawState()->preConcatSamplerMatrices(stageMask, matrix); } - /** - * Determines if blending will require a read of a dst given the current - * state set on the draw target - * - * @return true if the dst surface will be read at each pixel hit by the - * a draw operation. - */ - bool drawWillReadDst() const; - /** * Color alpha and coverage are two inputs to the drawing pipeline. For some * blend modes it is safe to fold the coverage into constant or per-vertex @@ -132,23 +123,33 @@ public: * Depending on features available in the underlying 3D API this may or may * not be possible. * - * This function looks at the current blend on the draw target and the draw - * target's capabilities to determine whether coverage can be handled - * correctly. + * This function considers the current draw state and the draw target's + * capabilities to determine whether coverage can be handled correctly. The + * following assumptions are made: + * 1. The caller intends to somehow specify coverage. This can be + * specified either by enabling a coverage stage on the GrDrawState or + * via the vertex layout. + * 2. Other than enabling coverage stages, the current configuration of + * the target's GrDrawState is as it will be at draw time. + * 3. If a vertex source has not yet been specified then all stages with + * non-NULL textures will be referenced by the vertex layout. */ bool canApplyCoverage() const; /** * Determines whether incorporating partial pixel coverage into the constant * color specified by setColor or per-vertex colors will give the right - * blending result. + * blending result. If a vertex source has not yet been specified then + * the function assumes that all stages with non-NULL textures will be + * referenced by the vertex layout. */ bool canTweakAlphaForCoverage() const; /** - * Given the current draw state, vertex layout, and hw support, will HW AA - * lines be used (if line primitive type is drawn)? (Note that lines are - * always 1 pixel wide) + * Given the current draw state and hw support, will HW AA lines be used + * (if line primitive type is drawn)? If a vertex source has not yet been + * specified then the function assumes that all stages with non-NULL + * textures will be referenced by the vertex layout. */ bool willUseHWAALines() const; @@ -925,7 +926,7 @@ protected: GrBlendCoeff* dstCoeff = NULL) const; // determine if src alpha is guaranteed to be one for all src pixels - bool srcAlphaWillBeOne() const; + bool srcAlphaWillBeOne(GrVertexLayout vertexLayout) const; enum GeometrySrcType { kNone_GeometrySrcType, //getGeomSrc().fVertexLayout, + return StageWillBeUsed(stage, this->getVertexLayout(), this->getDrawState()); } @@ -1050,10 +1051,18 @@ protected: GrVertexLayout layout, void* vertices); - // accessor for derived classes + // accessors for derived classes const GeometrySrcState& getGeomSrc() const { return fGeoSrcStateStack.back(); } + // it is prefereable to call this rather than getGeomSrc()->fVertexLayout + // because of the assert. + GrVertexLayout getVertexLayout() const { + // the vertex layout is only valid if a vertex source has been + // specified. + GrAssert(this->getGeomSrc().fVertexSrc != kNone_GeometrySrcType); + return this->getGeomSrc().fVertexLayout; + } GrClip fClip; diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp index ab16218a51..68636300fe 100644 --- a/src/gpu/GrGpu.cpp +++ b/src/gpu/GrGpu.cpp @@ -911,7 +911,7 @@ void GrGpu::onSetVertexSourceToArray(const void* vertexArray, int vertexCount) { #if GR_DEBUG bool success = #endif - fVertexPool->appendVertices(this->getGeomSrc().fVertexLayout, + fVertexPool->appendVertices(this->getVertexLayout(), vertexCount, vertexArray, &geomPoolState.fPoolVertexBuffer, diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp index 37cac0fa65..2bdfb0d5f3 100644 --- a/src/gpu/GrInOrderDrawBuffer.cpp +++ b/src/gpu/GrInOrderDrawBuffer.cpp @@ -356,7 +356,7 @@ void GrInOrderDrawBuffer::onDrawIndexed(GrPrimitiveType primitiveType, this->pushState(); } - draw.fVertexLayout = this->getGeomSrc().fVertexLayout; + draw.fVertexLayout = this->getVertexLayout(); switch (this->getGeomSrc().fVertexSrc) { case kBuffer_GeometrySrcType: draw.fVertexBuffer = this->getGeomSrc().fVertexBuffer; @@ -364,7 +364,7 @@ void GrInOrderDrawBuffer::onDrawIndexed(GrPrimitiveType primitiveType, case kReserved_GeometrySrcType: // fallthrough case kArray_GeometrySrcType: { size_t vertexBytes = (vertexCount + startVertex) * - VertexSize(this->getGeomSrc().fVertexLayout); + VertexSize(draw.fVertexLayout); poolState.fUsedPoolVertexBytes = GrMax(poolState.fUsedPoolVertexBytes, vertexBytes); draw.fVertexBuffer = poolState.fPoolVertexBuffer; @@ -423,7 +423,7 @@ void GrInOrderDrawBuffer::onDrawNonIndexed(GrPrimitiveType primitiveType, this->pushState(); } - draw.fVertexLayout = this->getGeomSrc().fVertexLayout; + draw.fVertexLayout = this->getVertexLayout(); switch (this->getGeomSrc().fVertexSrc) { case kBuffer_GeometrySrcType: draw.fVertexBuffer = this->getGeomSrc().fVertexBuffer; @@ -431,7 +431,7 @@ void GrInOrderDrawBuffer::onDrawNonIndexed(GrPrimitiveType primitiveType, case kReserved_GeometrySrcType: // fallthrough case kArray_GeometrySrcType: { size_t vertexBytes = (vertexCount + startVertex) * - VertexSize(this->getGeomSrc().fVertexLayout); + VertexSize(draw.fVertexLayout); poolState.fUsedPoolVertexBytes = GrMax(poolState.fUsedPoolVertexBytes, vertexBytes); draw.fVertexBuffer = poolState.fPoolVertexBuffer; @@ -706,7 +706,7 @@ void GrInOrderDrawBuffer::onSetVertexSourceToArray(const void* vertexArray, #if GR_DEBUG bool success = #endif - fVertexPool.appendVertices(this->getGeomSrc().fVertexLayout, + fVertexPool.appendVertices(this->getVertexLayout(), vertexCount, vertexArray, &poolState.fPoolVertexBuffer, diff --git a/src/gpu/gl/GrGpuGLShaders.cpp b/src/gpu/gl/GrGpuGLShaders.cpp index ec2d4e2fc8..b416b5cdd1 100644 --- a/src/gpu/gl/GrGpuGLShaders.cpp +++ b/src/gpu/gl/GrGpuGLShaders.cpp @@ -661,7 +661,7 @@ void GrGpuGLShaders::flushColor(GrColor color) { const ProgramDesc& desc = fCurrentProgram.getDesc(); const GrDrawState& drawState = this->getDrawState(); - if (this->getGeomSrc().fVertexLayout & kColor_VertexLayoutBit) { + if (this->getVertexLayout() & kColor_VertexLayoutBit) { // color will be specified per-vertex as an attribute // invalidate the const vertex attrib color fHWDrawState.setColor(GrColor_ILLEGAL); @@ -711,7 +711,7 @@ void GrGpuGLShaders::flushCoverage(GrColor coverage) { const GrDrawState& drawState = this->getDrawState(); - if (this->getGeomSrc().fVertexLayout & kCoverage_VertexLayoutBit) { + if (this->getVertexLayout() & kCoverage_VertexLayoutBit) { // coverage will be specified per-vertex as an attribute // invalidate the const vertex attrib coverage fHWDrawState.setCoverage4(GrColor_ILLEGAL); @@ -833,8 +833,10 @@ void GrGpuGLShaders::setupGeometry(int* startVertex, int newTexCoordOffsets[GrDrawState::kMaxTexCoords]; int newEdgeOffset; + GrVertexLayout currLayout = this->getVertexLayout(); + GrGLsizei newStride = VertexSizeAndOffsetsByIdx( - this->getGeomSrc().fVertexLayout, + currLayout, newTexCoordOffsets, &newColorOffset, &newCoverageOffset, @@ -858,7 +860,7 @@ void GrGpuGLShaders::setupGeometry(int* startVertex, GrGLenum scalarType; bool texCoordNorm; - if (this->getGeomSrc().fVertexLayout & kTextFormat_VertexLayoutBit) { + if (currLayout & kTextFormat_VertexLayoutBit) { scalarType = GrGLTextType; texCoordNorm = GR_GL_TEXT_TEXTURE_NORMALIZED; } else { @@ -882,8 +884,7 @@ void GrGpuGLShaders::setupGeometry(int* startVertex, bool posAndTexChange = allOffsetsChange || (((GrGLTextType != GrGLType) || GR_GL_TEXT_TEXTURE_NORMALIZED) && (kTextFormat_VertexLayoutBit & - (fHWGeometryState.fVertexLayout ^ - this->getGeomSrc().fVertexLayout))); + (fHWGeometryState.fVertexLayout ^ currLayout))); if (posAndTexChange) { int idx = GrGLProgram::PositionAttributeIdx(); @@ -955,7 +956,7 @@ void GrGpuGLShaders::setupGeometry(int* startVertex, GL_CALL(DisableVertexAttribArray(GrGLProgram::EdgeAttributeIdx())); } - fHWGeometryState.fVertexLayout = this->getGeomSrc().fVertexLayout; + fHWGeometryState.fVertexLayout = currLayout; fHWGeometryState.fArrayPtrsDirty = false; } @@ -979,7 +980,7 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type, // to a canonical value to avoid duplicate programs with different keys. // Must initialize all fields or cache will have false negatives! - desc.fVertexLayout = this->getGeomSrc().fVertexLayout; + desc.fVertexLayout = this->getVertexLayout(); desc.fEmitsPointSize = kPoints_PrimitiveType == type;