Don't look at current vertex layout when vertex source hasn't been set
authorbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Thu, 29 Mar 2012 19:07:12 +0000 (19:07 +0000)
committerbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Thu, 29 Mar 2012 19:07:12 +0000 (19:07 +0000)
Review URL: http://codereview.appspot.com/5959047

git-svn-id: http://skia.googlecode.com/svn/trunk@3545 2bbb7eff-a529-9590-31e7-b0007b416f81

src/gpu/GrContext.cpp
src/gpu/GrDrawTarget.cpp
src/gpu/GrDrawTarget.h
src/gpu/GrGpu.cpp
src/gpu/GrInOrderDrawBuffer.cpp
src/gpu/gl/GrGpuGLShaders.cpp

index f7ad9f8..64ae1a5 100644 (file)
@@ -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
index 5cce435..ef03a61 100644 (file)
@@ -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,
index 731cae5..8f5be3c 100644 (file)
@@ -117,38 +117,39 @@ public:
     }
 
     /**
-     * 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
      * color alpha value. For other blend modes they must be handled separately.
      * 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,     //<! src has not been specified
@@ -977,7 +978,7 @@ protected:
     }
 
     bool isStageEnabled(int stage) const {
-        return StageWillBeUsed(stage, this->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;
 
index ab16218..6863630 100644 (file)
@@ -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,
index 37cac0f..2bdfb0d 100644 (file)
@@ -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,
index ec2d4e2..b416b5c 100644 (file)
@@ -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;