Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(139)

Unified Diff: src/core/SkScan_AAAPath.cpp

Issue 2430343003: Use Analytic AA in SkAAClip (Closed)
Patch Set: Nit fixes Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/core/SkScan.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/core/SkScan_AAAPath.cpp
diff --git a/src/core/SkScan_AAAPath.cpp b/src/core/SkScan_AAAPath.cpp
index 147c24c3feafd5013e85a547354e2e463a023a29..76348785280dba71606151148c74be41b8cb3fe1 100644
--- a/src/core/SkScan_AAAPath.cpp
+++ b/src/core/SkScan_AAAPath.cpp
@@ -273,6 +273,19 @@ public:
int getWidth() override;
+ // This should only be called when forceRLE = true which implies that SkAAClip
+ // is calling us.
+ // SkAAClip requires that we blit in scan-line order so we have to flush
+ // for each row in order. Without this, we may have the first row unflushed,
+ // then blit the 2nd and the 3rd row with full alpha (so we won't flush the first row);
+ // finally when we blit the fourth row, we trigger the first row to flush, and this
+ // would cause SkAAClip to crash.
+ inline void flush_if_y_changed(SkFixed y, SkFixed nextY) {
+ if (SkFixedFloorToInt(y) != SkFixedFloorToInt(nextY)) {
+ this->flush();
+ }
+ }
+
private:
SkBlitter* fRealBlitter;
@@ -721,10 +734,6 @@ static inline void blit_trapezoid_row(AdditiveBlitter* blitter, int y,
SkFixed joinLeft = SkFixedCeilToFixed(ll);
SkFixed joinRite = SkFixedFloorToFixed(ur);
if (joinLeft <= joinRite) { // There's a rect from joinLeft to joinRite that we can blit
- if (joinLeft < joinRite) {
- blit_full_alpha(blitter, y, joinLeft >> 16, (joinRite - joinLeft) >> 16, fullAlpha,
- maskRow, isUsingMask);
- }
if (ul < joinLeft) {
int len = SkFixedCeilToInt(joinLeft - ul);
if (len == 1) {
@@ -741,6 +750,13 @@ static inline void blit_trapezoid_row(AdditiveBlitter* blitter, int y,
fullAlpha, maskRow, isUsingMask);
}
}
+ // SkAAClip requires that we blit from left to right.
+ // Hence we must blit [ul, joinLeft] before blitting [joinLeft, joinRite]
+ if (joinLeft < joinRite) {
+ blit_full_alpha(blitter, y, SkFixedFloorToInt(joinLeft),
+ SkFixedFloorToInt(joinRite - joinLeft),
+ fullAlpha, maskRow, isUsingMask);
+ }
if (lr > joinRite) {
int len = SkFixedCeilToInt(lr - joinRite);
if (len == 1) {
@@ -880,7 +896,7 @@ static inline bool isSmoothEnough(SkAnalyticEdge* leftE, SkAnalyticEdge* riteE,
static inline void aaa_walk_convex_edges(SkAnalyticEdge* prevHead, AdditiveBlitter* blitter,
int start_y, int stop_y, SkFixed leftBound, SkFixed riteBound,
- bool isUsingMask) {
+ bool isUsingMask, bool forceRLE) {
validate_sort((SkAnalyticEdge*)prevHead->fNext);
SkAnalyticEdge* leftE = (SkAnalyticEdge*) prevHead->fNext;
@@ -961,24 +977,27 @@ static inline void aaa_walk_convex_edges(SkAnalyticEdge* prevHead, AdditiveBlitt
}
if (fullRite >= fullLeft) {
- // Blit all full-height rows from fullTop to fullBot
- if (fullBot > fullTop) {
- blitter->getRealBlitter()->blitAntiRect(fullLeft - 1, fullTop,
- fullRite - fullLeft, fullBot - fullTop,
- f2a(partialLeft), f2a(partialRite));
- }
-
if (partialTop > 0) { // blit first partial row
if (partialLeft > 0) {
blitter->blitAntiH(fullLeft - 1, fullTop - 1,
f2a(SkFixedMul_lowprec(partialTop, partialLeft)));
}
+ blitter->blitAntiH(fullLeft, fullTop - 1, fullRite - fullLeft,
+ f2a(partialTop));
if (partialRite > 0) {
blitter->blitAntiH(fullRite, fullTop - 1,
f2a(SkFixedMul_lowprec(partialTop, partialRite)));
}
- blitter->blitAntiH(fullLeft, fullTop - 1, fullRite - fullLeft,
- f2a(partialTop));
+ if (forceRLE) {
+ ((RunBasedAdditiveBlitter*)blitter)->flush_if_y_changed(y, y + partialTop);
+ }
+ }
+
+ // Blit all full-height rows from fullTop to fullBot
+ if (fullBot > fullTop) {
+ blitter->getRealBlitter()->blitAntiRect(fullLeft - 1, fullTop,
+ fullRite - fullLeft, fullBot - fullTop,
+ f2a(partialLeft), f2a(partialRite));
}
if (partialBot > 0) { // blit last partial row
@@ -986,25 +1005,28 @@ static inline void aaa_walk_convex_edges(SkAnalyticEdge* prevHead, AdditiveBlitt
blitter->blitAntiH(fullLeft - 1, fullBot,
f2a(SkFixedMul_lowprec(partialBot, partialLeft)));
}
+ blitter->blitAntiH(fullLeft, fullBot, fullRite - fullLeft, f2a(partialBot));
if (partialRite > 0) {
blitter->blitAntiH(fullRite, fullBot,
f2a(SkFixedMul_lowprec(partialBot, partialRite)));
}
- blitter->blitAntiH(fullLeft, fullBot, fullRite - fullLeft, f2a(partialBot));
}
} else { // left and rite are within the same pixel
if (partialTop > 0) {
blitter->getRealBlitter()->blitV(fullLeft - 1, fullTop - 1, 1,
f2a(SkFixedMul_lowprec(partialTop, rite - left)));
- }
- if (partialBot > 0) {
- blitter->getRealBlitter()->blitV(fullLeft - 1, fullBot, 1,
- f2a(SkFixedMul_lowprec(partialBot, rite - left)));
+ if (forceRLE) {
+ ((RunBasedAdditiveBlitter*)blitter)->flush_if_y_changed(y, y + partialTop);
+ }
}
if (fullBot >= fullTop) {
blitter->getRealBlitter()->blitV(fullLeft - 1, fullTop, fullBot - fullTop,
f2a(rite - left));
}
+ if (partialBot > 0) {
+ blitter->getRealBlitter()->blitV(fullLeft - 1, fullBot, 1,
+ f2a(SkFixedMul_lowprec(partialBot, rite - left)));
+ }
}
y = local_bot_fixed;
@@ -1048,6 +1070,9 @@ static inline void aaa_walk_convex_edges(SkAnalyticEdge* prevHead, AdditiveBlitt
blit_trapezoid_row(blitter, y >> 16, left & kSnapMask, rite & kSnapMask,
nextLeft & kSnapMask, nextRite & kSnapMask, leftE->fDY, riteE->fDY,
getPartialAlpha(0xFF, dY), maskRow, isUsingMask);
+ if (forceRLE) {
+ ((RunBasedAdditiveBlitter*)blitter)->flush_if_y_changed(y, nextY);
+ }
left = nextLeft; rite = nextRite; y = nextY;
}
@@ -1060,6 +1085,9 @@ static inline void aaa_walk_convex_edges(SkAnalyticEdge* prevHead, AdditiveBlitt
blit_trapezoid_row(blitter, y >> 16, left & kSnapMask, rite & kSnapMask,
nextLeft & kSnapMask, nextRite & kSnapMask,
leftE->fDY, riteE->fDY, 0xFF, maskRow, isUsingMask);
+ if (forceRLE) {
+ ((RunBasedAdditiveBlitter*)blitter)->flush_if_y_changed(y, nextY);
+ }
left = nextLeft; rite = nextRite; y = nextY;
}
}
@@ -1072,11 +1100,15 @@ static inline void aaa_walk_convex_edges(SkAnalyticEdge* prevHead, AdditiveBlitt
SkASSERT(dY <= SK_Fixed1);
// Smooth jumping to integer y may make the last nextLeft/nextRite out of bound.
// Take them back into the bound here.
- SkFixed nextLeft = SkTMax(left + SkFixedMul_lowprec(dLeft, dY), leftBound);
- SkFixed nextRite = SkTMin(rite + SkFixedMul_lowprec(dRite, dY), riteBound);
+ // Note that we substract kSnapHalf later so we have to add them to leftBound/riteBound
+ SkFixed nextLeft = SkTMax(left + SkFixedMul_lowprec(dLeft, dY), leftBound + kSnapHalf);
+ SkFixed nextRite = SkTMin(rite + SkFixedMul_lowprec(dRite, dY), riteBound + kSnapHalf);
blit_trapezoid_row(blitter, y >> 16, left & kSnapMask, rite & kSnapMask,
nextLeft & kSnapMask, nextRite & kSnapMask, leftE->fDY, riteE->fDY,
getPartialAlpha(0xFF, dY), maskRow, isUsingMask);
+ if (forceRLE) {
+ ((RunBasedAdditiveBlitter*)blitter)->flush_if_y_changed(y, local_bot_fixed);
+ }
left = nextLeft; rite = nextRite; y = local_bot_fixed;
left -= kSnapHalf; rite -= kSnapHalf;
}
@@ -1094,7 +1126,8 @@ END_WALK:
}
void SkScan::aaa_fill_path(const SkPath& path, const SkIRect* clipRect, AdditiveBlitter* blitter,
- int start_y, int stop_y, const SkRegion& clipRgn, bool isUsingMask) {
+ int start_y, int stop_y, const SkRegion& clipRgn, bool isUsingMask,
+ bool forceRLE) { // forceRLE implies that SkAAClip is calling us
SkASSERT(blitter);
if (path.isInverseFillType() || !path.isConvex()) {
@@ -1170,7 +1203,8 @@ void SkScan::aaa_fill_path(const SkPath& path, const SkIRect* clipRect, Additive
if (!path.isInverseFillType() && path.isConvex()) {
SkASSERT(count >= 2); // convex walker does not handle missing right edges
aaa_walk_convex_edges(&headEdge, blitter, start_y, stop_y,
- rect.fLeft << 16, rect.fRight << 16, isUsingMask);
+ rect.fLeft << 16, rect.fRight << 16, isUsingMask,
+ forceRLE);
} else {
SkFAIL("Concave AAA is not yet implemented!");
}
@@ -1178,7 +1212,8 @@ void SkScan::aaa_fill_path(const SkPath& path, const SkIRect* clipRect, Additive
///////////////////////////////////////////////////////////////////////////////
-void SkScan::AAAFillPath(const SkPath& path, const SkRegion& origClip, SkBlitter* blitter) {
+void SkScan::AAAFillPath(const SkPath& path, const SkRegion& origClip, SkBlitter* blitter,
+ bool forceRLE) {
if (origClip.isEmpty()) {
return;
}
@@ -1244,12 +1279,14 @@ void SkScan::AAAFillPath(const SkPath& path, const SkRegion& origClip, SkBlitter
SkASSERT(SkIntToScalar(ir.fTop) <= path.getBounds().fTop);
- if (MaskAdditiveBlitter::canHandleRect(ir) && !isInverse) {
+ if (MaskAdditiveBlitter::canHandleRect(ir) && !isInverse && !forceRLE) {
MaskAdditiveBlitter additiveBlitter(blitter, ir, *clipRgn, isInverse);
- aaa_fill_path(path, clipRect, &additiveBlitter, ir.fTop, ir.fBottom, *clipRgn, true);
+ aaa_fill_path(path, clipRect, &additiveBlitter, ir.fTop, ir.fBottom, *clipRgn, true,
+ forceRLE);
} else {
RunBasedAdditiveBlitter additiveBlitter(blitter, ir, *clipRgn, isInverse);
- aaa_fill_path(path, clipRect, &additiveBlitter, ir.fTop, ir.fBottom, *clipRgn, false);
+ aaa_fill_path(path, clipRect, &additiveBlitter, ir.fTop, ir.fBottom, *clipRgn, false,
+ forceRLE);
}
if (isInverse) {
« no previous file with comments | « src/core/SkScan.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698