aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-08-14 21:56:37 +0000
committerGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-08-14 21:56:37 +0000
commit24ab3b0ce50b3428f063849b6160e468f047487c (patch)
treeb66480c5461ddfa1fdd6a8ccc6745697159d77ce
parent2865c4457040fde9a7617484b53c2e2db623c3e3 (diff)
Add blend optimization helpers and use to convert rect draws to clears.
R=robertphillips@google.com, jvanverth@google.com Author: bsalomon@google.com Review URL: https://chromiumcodereview.appspot.com/22558003 git-svn-id: http://skia.googlecode.com/svn/trunk@10723 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r--gyp/gpu.gypi2
-rw-r--r--include/core/SkMatrix.h12
-rw-r--r--include/core/SkRect.h5
-rw-r--r--include/gpu/GrPaint.h21
-rw-r--r--include/gpu/GrSurface.h7
-rw-r--r--src/gpu/GrBlend.cpp154
-rw-r--r--src/gpu/GrBlend.h45
-rw-r--r--src/gpu/GrContext.cpp93
-rw-r--r--src/gpu/GrDrawState.h25
-rw-r--r--src/gpu/GrPaint.cpp94
10 files changed, 398 insertions, 60 deletions
diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi
index fff79220ff..c71abbf273 100644
--- a/gyp/gpu.gypi
+++ b/gyp/gpu.gypi
@@ -55,6 +55,8 @@
'<(skia_src_path)/gpu/GrAtlas.cpp',
'<(skia_src_path)/gpu/GrAtlas.h',
'<(skia_src_path)/gpu/GrBinHashKey.h',
+ '<(skia_src_path)/gpu/GrBlend.cpp',
+ '<(skia_src_path)/gpu/GrBlend.h',
'<(skia_src_path)/gpu/GrBufferAllocPool.cpp',
'<(skia_src_path)/gpu/GrBufferAllocPool.h',
'<(skia_src_path)/gpu/GrCacheID.cpp',
diff --git a/include/core/SkMatrix.h b/include/core/SkMatrix.h
index f148e390b5..71e6b9737b 100644
--- a/include/core/SkMatrix.h
+++ b/include/core/SkMatrix.h
@@ -470,6 +470,18 @@ public:
return this->mapRect(rect, *rect);
}
+ /** Apply this matrix to the src rectangle, and write the four transformed
+ points into dst. The points written to dst will be the original top-left, top-right,
+ bottom-right, and bottom-left points transformed by the matrix.
+ @param dst Where the transformed quad is written.
+ @param rect The original rectangle to be transformed.
+ */
+ void mapRectToQuad(SkPoint dst[4], const SkRect& rect) const {
+ // This could potentially be faster if we only transformed each x and y of the rect once.
+ rect.toQuad(dst);
+ this->mapPoints(dst, 4);
+ }
+
/** Return the mean radius of a circle after it has been mapped by
this matrix. NOTE: in perspective this value assumes the circle
has its center at the origin.
diff --git a/include/core/SkRect.h b/include/core/SkRect.h
index 9f3b59a38f..d0eaac40e4 100644
--- a/include/core/SkRect.h
+++ b/include/core/SkRect.h
@@ -466,8 +466,9 @@ struct SK_API SkRect {
return !SkScalarsEqual((SkScalar*)&a, (SkScalar*)&b, 4);
}
- /** return the 4 points that enclose the rectangle
- */
+ /** return the 4 points that enclose the rectangle (top-left, top-right, bottom-right,
+ bottom-left). TODO: Consider adding param to control whether quad is CW or CCW.
+ */
void toQuad(SkPoint quad[4]) const;
/** Set this rectangle to the empty rectangle (0,0,0,0)
diff --git a/include/gpu/GrPaint.h b/include/gpu/GrPaint.h
index 9e326f0495..59343e70ec 100644
--- a/include/gpu/GrPaint.h
+++ b/include/gpu/GrPaint.h
@@ -174,7 +174,28 @@ public:
this->resetColorFilter();
}
+ /**
+ * Determines whether the drawing with this paint is opaque with respect to both color blending
+ * and fractional coverage. It does not consider whether AA has been enabled on the paint or
+ * not. Depending upon whether multisampling or coverage-based AA is in use, AA may make the
+ * result only apply to the interior of primitives.
+ *
+ */
+ bool isOpaque() const;
+
+ /**
+ * Returns true if isOpaque would return true and the paint represents a solid constant color
+ * draw. If the result is true, constantColor will be updated to contain the constant color.
+ */
+ bool isOpaqueAndConstantColor(GrColor* constantColor) const;
+
private:
+
+ /**
+ * Helper for isOpaque and isOpaqueAndConstantColor.
+ */
+ bool getOpaqueAndKnownColor(GrColor* solidColor, uint32_t* solidColorKnownComponents) const;
+
/**
* Called when the source coord system from which geometry is rendered changes. It ensures that
* the local coordinates seen by effects remains unchanged. oldToNew gives the transformation
diff --git a/include/gpu/GrSurface.h b/include/gpu/GrSurface.h
index 52a56659ab..eeb63ad21b 100644
--- a/include/gpu/GrSurface.h
+++ b/include/gpu/GrSurface.h
@@ -11,6 +11,7 @@
#include "GrTypes.h"
#include "GrResource.h"
+#include "SkRect.h"
class GrTexture;
class GrRenderTarget;
@@ -33,6 +34,12 @@ public:
*/
int height() const { return fDesc.fHeight; }
+ /**
+ * Helper that gets the width and height of the surface as a bounding rectangle.
+ */
+ void getBoundsRect(SkRect* rect) const { rect->setWH(SkIntToScalar(this->width()),
+ SkIntToScalar(this->height())); }
+
GrSurfaceOrigin origin() const {
GrAssert(kTopLeft_GrSurfaceOrigin == fDesc.fOrigin || kBottomLeft_GrSurfaceOrigin == fDesc.fOrigin);
return fDesc.fOrigin;
diff --git a/src/gpu/GrBlend.cpp b/src/gpu/GrBlend.cpp
new file mode 100644
index 0000000000..c0621a9b3f
--- /dev/null
+++ b/src/gpu/GrBlend.cpp
@@ -0,0 +1,154 @@
+
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrBlend.h"
+
+static inline GrBlendCoeff swap_coeff_src_dst(GrBlendCoeff coeff) {
+ switch (coeff) {
+ case kDC_GrBlendCoeff:
+ return kSC_GrBlendCoeff;
+ case kIDC_GrBlendCoeff:
+ return kISC_GrBlendCoeff;
+ case kDA_GrBlendCoeff:
+ return kSA_GrBlendCoeff;
+ case kIDA_GrBlendCoeff:
+ return kISA_GrBlendCoeff;
+ case kSC_GrBlendCoeff:
+ return kDC_GrBlendCoeff;
+ case kISC_GrBlendCoeff:
+ return kIDC_GrBlendCoeff;
+ case kSA_GrBlendCoeff:
+ return kDA_GrBlendCoeff;
+ case kISA_GrBlendCoeff:
+ return kIDA_GrBlendCoeff;
+ default:
+ return coeff;
+ }
+}
+
+static inline unsigned saturated_add(unsigned a, unsigned b) {
+ SkASSERT(a <= 255);
+ SkASSERT(b <= 255);
+ unsigned sum = a + b;
+ if (sum > 255) {
+ sum = 255;
+ }
+ return sum;
+}
+
+static GrColor add_colors(GrColor src, GrColor dst) {
+ unsigned r = saturated_add(GrColorUnpackR(src), GrColorUnpackR(dst));
+ unsigned g = saturated_add(GrColorUnpackG(src), GrColorUnpackG(dst));
+ unsigned b = saturated_add(GrColorUnpackB(src), GrColorUnpackB(dst));
+ unsigned a = saturated_add(GrColorUnpackA(src), GrColorUnpackA(dst));
+ return GrColorPackRGBA(r, g, b, a);
+}
+
+static inline bool valid_color(uint32_t compFlags) {
+ return (kRGBA_GrColorComponentFlags & compFlags) == kRGBA_GrColorComponentFlags;
+}
+
+static GrColor simplify_blend_term(GrBlendCoeff* srcCoeff,
+ GrColor srcColor, uint32_t srcCompFlags,
+ GrColor dstColor, uint32_t dstCompFlags,
+ GrColor constantColor) {
+
+ GrAssert(!GrBlendCoeffRefsSrc(*srcCoeff));
+ GrAssert(NULL != srcCoeff);
+
+ // Check whether srcCoeff can be reduced to kOne or kZero based on known color inputs.
+ // We could pick out the coeff r,g,b,a values here and use them to compute the blend term color,
+ // if possible, below but that is not implemented now.
+ switch (*srcCoeff) {
+ case kIDC_GrBlendCoeff:
+ dstColor = ~dstColor; // fallthrough
+ case kDC_GrBlendCoeff:
+ if (valid_color(dstCompFlags)) {
+ if (0xffffffff == dstColor) {
+ *srcCoeff = kOne_GrBlendCoeff;
+ } else if (0 == dstColor) {
+ *srcCoeff = kZero_GrBlendCoeff;
+ }
+ }
+ break;
+
+ case kIDA_GrBlendCoeff:
+ dstColor = ~dstColor; // fallthrough
+ case kDA_GrBlendCoeff:
+ if (kA_GrColorComponentFlag & dstCompFlags) {
+ if (0xff == GrColorUnpackA(dstColor)) {
+ *srcCoeff = kOne_GrBlendCoeff;
+ } else if (0 == GrColorUnpackA(dstColor)) {
+ *srcCoeff = kZero_GrBlendCoeff;
+ }
+ }
+ break;
+
+ case kIConstC_GrBlendCoeff:
+ constantColor = ~constantColor; // fallthrough
+ case kConstC_GrBlendCoeff:
+ if (0xffffffff == constantColor) {
+ *srcCoeff = kOne_GrBlendCoeff;
+ } else if (0 == constantColor) {
+ *srcCoeff = kZero_GrBlendCoeff;
+ }
+ break;
+
+ case kIConstA_GrBlendCoeff:
+ constantColor = ~constantColor; // fallthrough
+ case kConstA_GrBlendCoeff:
+ if (0xff == GrColorUnpackA(constantColor)) {
+ *srcCoeff = kOne_GrBlendCoeff;
+ } else if (0 == GrColorUnpackA(constantColor)) {
+ *srcCoeff = kZero_GrBlendCoeff;
+ }
+ break;
+
+ default:
+ break;
+ }
+ // We may have invalidated these above and shouldn't read them again.
+ GR_DEBUGCODE(dstColor = constantColor = GrColor_ILLEGAL;)
+
+ if (kZero_GrBlendCoeff == *srcCoeff || (valid_color(srcCompFlags) && 0 == srcColor)) {
+ *srcCoeff = kZero_GrBlendCoeff;
+ return 0;
+ }
+
+ if (kOne_GrBlendCoeff == *srcCoeff && valid_color(srcCompFlags)) {
+ return srcColor;
+ } else {
+ return GrColor_ILLEGAL;
+ }
+}
+
+GrColor GrSimplifyBlend(GrBlendCoeff* srcCoeff,
+ GrBlendCoeff* dstCoeff,
+ GrColor srcColor, uint32_t srcCompFlags,
+ GrColor dstColor, uint32_t dstCompFlags,
+ GrColor constantColor) {
+ GrColor srcTermColor = simplify_blend_term(srcCoeff,
+ srcColor, srcCompFlags,
+ dstColor, dstCompFlags,
+ constantColor);
+
+ // We call the same function to simplify the dst blend coeff. We trick it out by swapping the
+ // src and dst.
+ GrBlendCoeff spoofedCoeff = swap_coeff_src_dst(*dstCoeff);
+ GrColor dstTermColor = simplify_blend_term(&spoofedCoeff,
+ dstColor, dstCompFlags,
+ srcColor, srcCompFlags,
+ constantColor);
+ *dstCoeff = swap_coeff_src_dst(spoofedCoeff);
+
+ if (GrColor_ILLEGAL != srcTermColor && GrColor_ILLEGAL != dstTermColor) {
+ return add_colors(srcTermColor, dstTermColor);
+ } else {
+ return GrColor_ILLEGAL;
+ }
+}
diff --git a/src/gpu/GrBlend.h b/src/gpu/GrBlend.h
new file mode 100644
index 0000000000..e70d945777
--- /dev/null
+++ b/src/gpu/GrBlend.h
@@ -0,0 +1,45 @@
+
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrTypes.h"
+#include "GrColor.h"
+
+#ifndef GrBlend_DEFINED
+#define GrBlend_DEFINED
+
+static inline bool GrBlendCoeffRefsSrc(GrBlendCoeff coeff) {
+ switch (coeff) {
+ case kSC_GrBlendCoeff:
+ case kISC_GrBlendCoeff:
+ case kSA_GrBlendCoeff:
+ case kISA_GrBlendCoeff:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static inline bool GrBlendCoeffRefsDst(GrBlendCoeff coeff) {
+ switch (coeff) {
+ case kDC_GrBlendCoeff:
+ case kIDC_GrBlendCoeff:
+ case kDA_GrBlendCoeff:
+ case kIDA_GrBlendCoeff:
+ return true;
+ default:
+ return false;
+ }
+}
+
+GrColor GrSimplifyBlend(GrBlendCoeff* srcCoeff,
+ GrBlendCoeff* dstCoeff,
+ GrColor srcColor, uint32_t srcCompFlags,
+ GrColor dstColor, uint32_t dstCompFlags,
+ GrColor constantColor);
+
+#endif
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 20c633dc67..4d5551e494 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -681,9 +681,8 @@ static bool isIRect(const SkRect& r) {
static bool apply_aa_to_rect(GrDrawTarget* target,
const SkRect& rect,
SkScalar strokeWidth,
- const SkMatrix* matrix,
- SkMatrix* combinedMatrix,
- SkRect* devRect,
+ const SkMatrix& combinedMatrix,
+ SkRect* devBoundRect,
bool* useVertexCoverage) {
// we use a simple coverage ramp to do aa on axis-aligned rects
// we check if the rect will be axis-aligned, and the rect won't land on
@@ -716,52 +715,32 @@ static bool apply_aa_to_rect(GrDrawTarget* target,
#if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT)
if (strokeWidth >= 0) {
#endif
- if (!drawState.getViewMatrix().preservesAxisAlignment()) {
+ if (!combinedMatrix.preservesAxisAlignment()) {
return false;
}
- if (NULL != matrix && !matrix->preservesAxisAlignment()) {
- return false;
- }
#if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT)
} else {
- if (!drawState.getViewMatrix().preservesAxisAlignment() &&
- !drawState.getViewMatrix().preservesRightAngles()) {
- return false;
- }
-
- if (NULL != matrix && !matrix->preservesRightAngles()) {
+ if (!combinedMatrix.preservesRightAngles()) {
return false;
}
}
#endif
- *combinedMatrix = drawState.getViewMatrix();
- if (NULL != matrix) {
- combinedMatrix->preConcat(*matrix);
-
-#if GR_DEBUG
-#if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT)
- if (strokeWidth >= 0) {
-#endif
- GrAssert(combinedMatrix->preservesAxisAlignment());
-#if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT)
- } else {
- GrAssert(combinedMatrix->preservesRightAngles());
- }
-#endif
-#endif
- }
-
- combinedMatrix->mapRect(devRect, rect);
+ combinedMatrix.mapRect(devBoundRect, rect);
if (strokeWidth < 0) {
- return !isIRect(*devRect);
+ return !isIRect(*devBoundRect);
} else {
return true;
}
}
+static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
+ return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
+ point.fY >= rect.fTop && point.fY <= rect.fBottom;
+}
+
void GrContext::drawRect(const GrPaint& paint,
const SkRect& rect,
SkScalar width,
@@ -771,13 +750,51 @@ void GrContext::drawRect(const GrPaint& paint,
AutoRestoreEffects are;
GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are);
- SkRect devRect;
- SkMatrix combinedMatrix;
+ SkMatrix combinedMatrix = target->drawState()->getViewMatrix();
+ if (NULL != matrix) {
+ combinedMatrix.preConcat(*matrix);
+ }
+
+ // Check if this is a full RT draw and can be replaced with a clear. We don't bother checking
+ // cases where the RT is fully inside a stroke.
+ if (width < 0) {
+ SkRect rtRect;
+ target->getDrawState().getRenderTarget()->getBoundsRect(&rtRect);
+ SkRect clipSpaceRTRect = rtRect;
+ bool checkClip = false;
+ if (NULL != this->getClip()) {
+ checkClip = true;
+ clipSpaceRTRect.offset(SkIntToScalar(this->getClip()->fOrigin.fX),
+ SkIntToScalar(this->getClip()->fOrigin.fY));
+ }
+ // Does the clip contain the entire RT?
+ if (!checkClip || target->getClip()->fClipStack->quickContains(clipSpaceRTRect)) {
+ SkMatrix invM;
+ if (!combinedMatrix.invert(&invM)) {
+ return;
+ }
+ // Does the rect bound the RT?
+ SkPoint srcSpaceRTQuad[4];
+ invM.mapRectToQuad(srcSpaceRTQuad, rtRect);
+ if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) &&
+ rect_contains_inclusive(rect, srcSpaceRTQuad[1]) &&
+ rect_contains_inclusive(rect, srcSpaceRTQuad[2]) &&
+ rect_contains_inclusive(rect, srcSpaceRTQuad[3])) {
+ // Will it blend?
+ GrColor clearColor;
+ if (paint.isOpaqueAndConstantColor(&clearColor)) {
+ target->clear(NULL, clearColor);
+ return;
+ }
+ }
+ }
+ }
+
+ SkRect devBoundRect;
bool useVertexCoverage;
bool needAA = paint.isAntiAlias() &&
!target->getDrawState().getRenderTarget()->isMultisampled();
- bool doAA = needAA && apply_aa_to_rect(target, rect, width, matrix,
- &combinedMatrix, &devRect,
+ bool doAA = needAA && apply_aa_to_rect(target, rect, width, combinedMatrix, &devBoundRect,
&useVertexCoverage);
if (doAA) {
GrDrawState::AutoViewMatrixRestore avmr;
@@ -786,12 +803,12 @@ void GrContext::drawRect(const GrPaint& paint,
}
if (width >= 0) {
fAARectRenderer->strokeAARect(this->getGpu(), target,
- rect, combinedMatrix, devRect,
+ rect, combinedMatrix, devBoundRect,
width, useVertexCoverage);
} else {
// filled AA rect
fAARectRenderer->fillAARect(this->getGpu(), target,
- rect, combinedMatrix, devRect,
+ rect, combinedMatrix, devBoundRect,
useVertexCoverage);
}
return;
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index c006e6c5dd..785be77f58 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -9,6 +9,7 @@
#define GrDrawState_DEFINED
#include "GrBackendEffectFactory.h"
+#include "GrBlend.h"
#include "GrColor.h"
#include "GrEffectStage.h"
#include "GrPaint.h"
@@ -469,27 +470,11 @@ public:
fCommon.fSrcBlend = srcCoeff;
fCommon.fDstBlend = dstCoeff;
#if GR_DEBUG
- switch (dstCoeff) {
- case kDC_GrBlendCoeff:
- case kIDC_GrBlendCoeff:
- case kDA_GrBlendCoeff:
- case kIDA_GrBlendCoeff:
- GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
- "coverage stages.\n");
- break;
- default:
- break;
+ if (GrBlendCoeffRefsDst(dstCoeff)) {
+ GrPrintf("Unexpected dst blend coeff. Won't work correctly with coverage stages.\n");
}
- switch (srcCoeff) {
- case kSC_GrBlendCoeff:
- case kISC_GrBlendCoeff:
- case kSA_GrBlendCoeff:
- case kISA_GrBlendCoeff:
- GrPrintf("Unexpected src blend coeff. Won't work correctly with"
- "coverage stages.\n");
- break;
- default:
- break;
+ if (GrBlendCoeffRefsSrc(srcCoeff)) {
+ GrPrintf("Unexpected src blend coeff. Won't work correctly with coverage stages.\n");
}
#endif
}
diff --git a/src/gpu/GrPaint.cpp b/src/gpu/GrPaint.cpp
index d67f2e8707..898a32ff70 100644
--- a/src/gpu/GrPaint.cpp
+++ b/src/gpu/GrPaint.cpp
@@ -8,6 +8,7 @@
#include "GrPaint.h"
+#include "GrBlend.h"
#include "effects/GrSimpleTextureEffect.h"
void GrPaint::addColorTextureEffect(GrTexture* texture, const SkMatrix& matrix) {
@@ -33,3 +34,96 @@ void GrPaint::addCoverageTextureEffect(GrTexture* texture,
GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix, params);
this->addCoverageEffect(effect)->unref();
}
+
+bool GrPaint::isOpaque() const {
+ return this->getOpaqueAndKnownColor(NULL, NULL);
+}
+
+bool GrPaint::isOpaqueAndConstantColor(GrColor* color) const {
+ GrColor tempColor;
+ uint32_t colorComps;
+ if (this->getOpaqueAndKnownColor(&tempColor, &colorComps)) {
+ if (kRGBA_GrColorComponentFlags == colorComps) {
+ *color = tempColor;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool GrPaint::getOpaqueAndKnownColor(GrColor* solidColor,
+ uint32_t* solidColorKnownComponents) const {
+
+ // TODO: Share this implementation with GrDrawState
+
+ // Since fColorFilterXfermode is going away soon, we aren't attempting to handle anything but
+ // the default setting.
+ if (SkXfermode::kDst_Mode != fColorFilterXfermode) {
+ return false;
+ }
+
+ GrColor coverage = GrColorPackRGBA(fCoverage, fCoverage, fCoverage, fCoverage);
+ uint32_t coverageComps = kRGBA_GrColorComponentFlags;
+ int count = fCoverageStages.count();
+ for (int i = 0; i < count; ++i) {
+ (*fCoverageStages[i].getEffect())->getConstantColorComponents(&coverage, &coverageComps);
+ }
+ if (kRGBA_GrColorComponentFlags != coverageComps || 0xffffffff != coverage) {
+ return false;
+ }
+
+ GrColor color = fColor;
+ uint32_t colorComps = kRGBA_GrColorComponentFlags;
+ count = fColorStages.count();
+ for (int i = 0; i < count; ++i) {
+ (*fColorStages[i].getEffect())->getConstantColorComponents(&color, &colorComps);
+ }
+
+ GrAssert((NULL == solidColor) == (NULL == solidColorKnownComponents));
+
+ GrBlendCoeff srcCoeff = fSrcBlendCoeff;
+ GrBlendCoeff dstCoeff = fDstBlendCoeff;
+ GrSimplifyBlend(&srcCoeff, &dstCoeff, color, colorComps, 0, 0, 0);
+
+ bool opaque = kZero_GrBlendCoeff == dstCoeff && !GrBlendCoeffRefsDst(srcCoeff);
+ if (NULL != solidColor) {
+ if (opaque) {
+ switch (srcCoeff) {
+ case kZero_GrBlendCoeff:
+ *solidColor = 0;
+ *solidColorKnownComponents = kRGBA_GrColorComponentFlags;
+ break;
+
+ case kOne_GrBlendCoeff:
+ *solidColor = color;
+ *solidColorKnownComponents = colorComps;
+ break;
+
+ // The src coeff should never refer to the src and if it refers to dst then opaque
+ // should have been false.
+ case kSC_GrBlendCoeff:
+ case kISC_GrBlendCoeff:
+ case kDC_GrBlendCoeff:
+ case kIDC_GrBlendCoeff:
+ case kSA_GrBlendCoeff:
+ case kISA_GrBlendCoeff:
+ case kDA_GrBlendCoeff:
+ case kIDA_GrBlendCoeff:
+ default:
+ GrCrash("srcCoeff should not refer to src or dst.");
+ break;
+
+ // TODO: update this once GrPaint actually has a const color.
+ case kConstC_GrBlendCoeff:
+ case kIConstC_GrBlendCoeff:
+ case kConstA_GrBlendCoeff:
+ case kIConstA_GrBlendCoeff:
+ *solidColorKnownComponents = 0;
+ break;
+ }
+ } else {
+ solidColorKnownComponents = 0;
+ }
+ }
+ return opaque;
+}