Add blend optimization helpers and use to convert rect draws to clears.
Committed: http://code.google.com/p/skia/source/detail?r=10537
R=robertphillips@google.com, jvanverth@google.com, reed@google.com
Author: bsalomon@google.com
Review URL: https://chromiumcodereview.appspot.com/21877006
git-svn-id: http://skia.googlecode.com/svn/trunk@10562 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 20c633d..20320e8 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -681,9 +681,8 @@
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 @@
#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,48 @@
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.
+ 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 +800,12 @@
}
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;