// TODO: generalize this function so that when
// a clip gets complex enough it can just be done in SW regardless
// of whether it would invoke the GrSoftwarePathRenderer.
- bool useSW = false;
SkStroke stroke;
stroke.setDoFill(true);
// TODO: Do rects directly to the accumulator using a aa-rect GrEffect that covers the
// entire mask bounds and writes 0 outside the rect.
if (element->isAA()) {
- getContext()->getAARectRenderer()->fillAARect(fGpu, fGpu, element->getRect(), true);
+ getContext()->getAARectRenderer()->fillAARect(fGpu,
+ fGpu,
+ element->getRect(),
+ false);
} else {
fGpu->drawSimpleRect(element->getRect(), NULL);
}
// we populate with a rasterization of the clip.
SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpaceIBounds.height());
+ // We're drawing a coverage mask and want coverage to be run through the blend function.
+ drawState->enableState(GrDrawState::kCoverageDrawing_StateBit);
+
// Set the matrix so that rendered clip elements are transformed to mask space from clip space.
drawState->viewMatrix()->setTranslate(clipToMaskOffset);
* edge-AA computed coverage. (This latter is going away as soon as it can be rewritten as a
* GrEffect).
*
+ * See the documentation of kCoverageDrawing_StateBit for information about disabling the
+ * the color / coverage distinction.
+ *
* Stages 0 through GrPaint::kTotalStages-1 are reserved for stages copied from the client's
* GrPaint. Stages GrPaint::kTotalStages through kNumStages-2 are earmarked for use by
* GrTextContext and GrPathRenderer-derived classes. kNumStages-1 is earmarked for clipping
*/
kDither_StateBit = 0x01,
/**
- * Perform HW anti-aliasing. This means either HW FSAA, if supported
- * by the render target, or smooth-line rendering if a line primitive
- * is drawn and line smoothing is supported by the 3D API.
+ * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
+ * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
+ * the 3D API.
*/
kHWAntialias_StateBit = 0x02,
/**
*/
kNoColorWrites_StateBit = 0x08,
+ /**
+ * Usually coverage is applied after color blending. The color is blended using the coeffs
+ * specified by setBlendFunc(). The blended color is then combined with dst using coeffs
+ * of src_coverage, 1-src_coverage. Sometimes we are explicitly drawing a coverage mask. In
+ * this case there is no distinction between coverage and color and the caller needs direct
+ * control over the blend coeffs. When set, there will be a single blend step controlled by
+ * setBlendFunc() which will use coverage*color as the src color.
+ */
+ kCoverageDrawing_StateBit = 0x10,
+
// Users of the class may add additional bits to the vector
kDummyStateBit,
kLastPublicStateBit = kDummyStateBit-1,
return 0 != (fFlagBits & kNoColorWrites_StateBit);
}
+ bool isCoverageDrawing() const {
+ return 0 != (fFlagBits & kCoverageDrawing_StateBit);
+ }
+
bool isStateFlagEnabled(uint32_t stateBit) const {
return 0 != (stateBit & fFlagBits);
}
* We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D
* By tweaking the source color's alpha we're replacing S with S'=fS. It's
* obvious that that first term will always be ok. The second term can be
- * rearranged as [1-(1-Cd)f]D. By substituing in the various possbilities
+ * rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities
* for Cd we find that only 1, ISA, and ISC produce the correct depth
- * coeffecient in terms of S' and D.
+ * coefficient in terms of S' and D.
*/
GrBlendCoeff dstCoeff = this->getDrawState().getDstBlendCoeff();
return kOne_GrBlendCoeff == dstCoeff ||
kISA_GrBlendCoeff == dstCoeff ||
- kISC_GrBlendCoeff == dstCoeff;
+ kISC_GrBlendCoeff == dstCoeff ||
+ this->getDrawState().isCoverageDrawing();
}
bool GrDrawTarget::srcAlphaWillBeOne(GrVertexLayout layout) const {
if (SkXfermode::kDst_Mode != drawState.getColorFilterMode()) {
return false;
}
+ int stageCnt;
+ // Check whether coverage is treated as color
+ if (drawState.isCoverageDrawing()) {
+ if (0xff != GrColorUnpackA(drawState.getCoverage())) {
+ return false;
+ }
+ stageCnt = GrDrawState::kNumStages;
+ } else {
+ stageCnt = drawState.getFirstCoverageStage();
+ }
// Check if a color stage could create a partial alpha
- for (int s = 0; s < drawState.getFirstCoverageStage(); ++s) {
- if (this->isStageEnabled(s)) {
- const GrEffect* effect = drawState.getStage(s).getEffect();
+ for (int s = 0; s < stageCnt; ++s) {
+ const GrEffect* effect = drawState.getStage(s).getEffect();
+ if (NULL != effect) {
// FIXME: The param indicates whether the texture is opaque or not. However, the effect
// already controls its textures. It really needs to know whether the incoming color
// (from a uni, per-vertex colors, or previous stage) is opaque or not.
}
*dstCoeff = drawState.getDstBlendCoeff();
- // We don't ever expect source coeffecients to reference the source
- GrAssert(kSA_GrBlendCoeff != *srcCoeff &&
- kISA_GrBlendCoeff != *srcCoeff &&
- kSC_GrBlendCoeff != *srcCoeff &&
- kISC_GrBlendCoeff != *srcCoeff);
- // same for dst
- GrAssert(kDA_GrBlendCoeff != *dstCoeff &&
- kIDA_GrBlendCoeff != *dstCoeff &&
- kDC_GrBlendCoeff != *dstCoeff &&
- kIDC_GrBlendCoeff != *dstCoeff);
-
if (drawState.isColorWriteDisabled()) {
*srcCoeff = kZero_GrBlendCoeff;
*dstCoeff = kOne_GrBlendCoeff;
bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
(kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
-
+ bool covIsZero = !drawState.isCoverageDrawing() &&
+ !(layout & kCoverage_VertexLayoutBit) &&
+ 0 == drawState.getCoverage();
// When coeffs are (0,1) there is no reason to draw at all, unless
// stenciling is enabled. Having color writes disabled is effectively
// (0,1). The same applies when coverage is known to be 0.
- if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) ||
- (!(layout & kCoverage_VertexLayoutBit) &&
- 0 == drawState.getCoverage())) {
+ if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
if (drawState.getStencil().doesWrite()) {
return kDisableBlend_BlendOptFlag |
kEmitTransBlack_BlendOptFlag;
// or blend, just write transparent black into the dst.
*srcCoeff = kOne_GrBlendCoeff;
*dstCoeff = kZero_GrBlendCoeff;
- return kDisableBlend_BlendOptFlag |
- kEmitTransBlack_BlendOptFlag;
+ return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
}
}
+ } else if (drawState.isCoverageDrawing()) {
+ // we have coverage but we aren't distinguishing it from alpha by request.
+ return kCoverageAsAlpha_BlendOptFlag;
} else {
// check whether coverage can be safely rolled into alpha
// of if we can skip color computation and just emit coverage
const SkMatrix* matrix,
const GrRect* srcRects[],
const SkMatrix* srcMatrices[]);
+ /**
+ * Helper for drawRect when the caller doesn't need separate src rects or
+ * matrices.
+ */
+ void drawSimpleRect(const GrRect& rect, const SkMatrix* matrix = NULL) {
+ drawRect(rect, matrix, NULL, NULL);
+ }
+ void drawSimpleRect(const GrIRect& irect, const SkMatrix* matrix = NULL) {
+ SkRect rect = SkRect::MakeFromIRect(irect);
+ this->drawRect(rect, matrix, NULL, NULL);
+ }
+
/**
* This call is used to draw multiple instances of some geometry with a
* given number of vertices (V) and indices (I) per-instance. The indices in
int verticesPerInstance,
int indicesPerInstance);
- /**
- * Helper for drawRect when the caller doesn't need separate src rects or
- * matrices.
- */
- void drawSimpleRect(const GrRect& rect,
- const SkMatrix* matrix) {
- drawRect(rect, matrix, NULL, NULL);
- }
-
/**
* Clear the current render target if one isn't passed in. Ignores the
* clip and all other draw state (blend mode, stages, etc). Clears the
};
GR_DECL_BITFIELD_OPS_FRIENDS(BlendOptFlags);
- // Determines what optimizations can be applied based on the blend.
- // The coeffecients may have to be tweaked in order for the optimization
- // to work. srcCoeff and dstCoeff are optional params that receive the
- // tweaked coeffecients.
- // Normally the function looks at the current state to see if coverage
- // is enabled. By setting forceCoverage the caller can speculatively
- // determine the blend optimizations that would be used if there was
- // partial pixel coverage
+ /**
+ * Determines what optimizations can be applied based on the blend. The coefficients may have
+ * to be tweaked in order for the optimization to work. srcCoeff and dstCoeff are optional
+ * params that receive the tweaked coefficients. Normally the function looks at the current
+ * state to see if coverage is enabled. By setting forceCoverage the caller can speculatively
+ * determine the blend optimizations that would be used if there was partial pixel coverage.
+ */
BlendOptFlags getBlendOpts(bool forceCoverage = false,
GrBlendCoeff* srcCoeff = NULL,
GrBlendCoeff* dstCoeff = NULL) const;