diff options
author | tomhudson@google.com <tomhudson@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-12-01 21:09:00 +0000 |
---|---|---|
committer | tomhudson@google.com <tomhudson@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-12-01 21:09:00 +0000 |
commit | f974a5d7826688c9d87cc36a56c697ea5fae12de (patch) | |
tree | 42859d8a4fbe39095526ef62a48cd5c92fb1d729 /src/core | |
parent | 05fffdcc912cb9678e03d39529577e2a29b9209e (diff) |
New function SkBlitter::blitAntiRect(); specifically accelerated for
supersampled antialiased clips.
git-svn-id: http://skia.googlecode.com/svn/trunk@2783 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/SkAAClip.cpp | 38 | ||||
-rw-r--r-- | src/core/SkBlitter.cpp | 20 | ||||
-rw-r--r-- | src/core/SkScan_AntiPath.cpp | 58 |
3 files changed, 62 insertions, 54 deletions
diff --git a/src/core/SkAAClip.cpp b/src/core/SkAAClip.cpp index cb49178e35..fd5d8979bd 100644 --- a/src/core/SkAAClip.cpp +++ b/src/core/SkAAClip.cpp @@ -930,7 +930,36 @@ public: SkASSERT(fBounds.contains(x + width - 1, y + height - 1)); this->addRun(x, y, 0xFF, width); - // we assum the rect must be all we'll see for these scanlines + // we assume the rect must be all we'll see for these scanlines + // so we ensure our row goes all the way to our right + this->flushRowH(fCurrRow); + + y -= fBounds.fTop; + SkASSERT(y == fCurrRow->fY); + fCurrRow->fY = y + height - 1; + } + + void addAntiRectRun(int x, int y, int width, int height, + SkAlpha leftAlpha, SkAlpha rightAlpha) { + SkASSERT(fBounds.contains(x + width - 1, y + height - 1)); + SkASSERT(width >= 0); + + // Conceptually we're always adding 3 runs, but we should + // merge or omit them if possible. + if (leftAlpha == 0xFF) { + width++; + } else if (leftAlpha > 0) { + this->addRun(x++, y, leftAlpha, 1); + } + if (rightAlpha == 0xFF) { + width++; + } + this->addRun(x, y, 0xFF, width); + if (rightAlpha > 0 && rightAlpha < 255) { + this->addRun(x + width, y, rightAlpha, 1); + } + + // we assume the rect must be all we'll see for these scanlines // so we ensure our row goes all the way to our right this->flushRowH(fCurrRow); @@ -1113,6 +1142,7 @@ public: } } + // Must evaluate clips in scan-line order, so can't allow blitV() virtual void blitV(int x, int y, int height, SkAlpha alpha) SK_OVERRIDE { unexpected(); } @@ -1121,6 +1151,12 @@ public: fBuilder->addRectRun(x, y, width, height); } + virtual void blitAntiRect(int x, int y, int width, int height, + SkAlpha leftAlpha, SkAlpha rightAlpha) SK_OVERRIDE { + this->recordMinY(y); + fBuilder->addAntiRectRun(x, y, width, height, leftAlpha, rightAlpha); + } + virtual void blitMask(const SkMask&, const SkIRect& clip) SK_OVERRIDE { unexpected(); } diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp index 307d51b340..17cba4776d 100644 --- a/src/core/SkBlitter.cpp +++ b/src/core/SkBlitter.cpp @@ -52,6 +52,16 @@ void SkBlitter::blitRect(int x, int y, int width, int height) { } } +/// Default implementation doesn't check for any easy optimizations +/// such as alpha == 0 or 255; also uses blitV(), which some subclasses +/// may not support. +void SkBlitter::blitAntiRect(int x, int y, int width, int height, + SkAlpha leftAlpha, SkAlpha rightAlpha) { + this->blitV(x, y, height, leftAlpha); + this->blitRect(x + 1, y, width, height); + this->blitV(x + width - 1, y, height, rightAlpha); +} + ////////////////////////////////////////////////////////////////////////////// static inline void bits_to_runs(SkBlitter* blitter, int x, int y, @@ -118,7 +128,8 @@ void SkBlitter::blitMask(const SkMask& mask, const SkIRect& clip) { int rite_mask = 0xFF << (8 - (rite_edge & 7)); int full_runs = (rite_edge >> 3) - ((left_edge + 7) >> 3); - // check for empty right mask, so we don't read off the end (or go slower than we need to) + // check for empty right mask, so we don't read off the end + // (or go slower than we need to) if (rite_mask == 0) { SkASSERT(full_runs >= 0); full_runs -= 1; @@ -128,8 +139,8 @@ void SkBlitter::blitMask(const SkMask& mask, const SkIRect& clip) { full_runs -= 1; } - // back up manually so we can keep in sync with our byte-aligned src - // have cx reflect our actual starting x-coord + // Back up manually so we can keep in sync with our byte-aligned + // src; have cx reflect our actual starting x-coord. cx -= left_edge & 7; if (full_runs < 0) { @@ -141,7 +152,8 @@ void SkBlitter::blitMask(const SkMask& mask, const SkIRect& clip) { } } else { while (--height >= 0) { - bits_to_runs(this, cx, cy, bits, left_mask, full_runs + 2, rite_mask); + bits_to_runs(this, cx, cy, bits, left_mask, full_runs + 2, + rite_mask); bits += mask_rowBytes; cy += 1; } diff --git a/src/core/SkScan_AntiPath.cpp b/src/core/SkScan_AntiPath.cpp index bf9866ec97..36005c173a 100644 --- a/src/core/SkScan_AntiPath.cpp +++ b/src/core/SkScan_AntiPath.cpp @@ -219,42 +219,7 @@ void SuperBlitter::blitH(int x, int y, int width) { #endif } -static void set_left_rite_runs(SkAlphaRuns& runs, int ileft, U8CPU leftA, - int n, U8CPU riteA) { - SkASSERT(leftA <= 0xFF); - SkASSERT(riteA <= 0xFF); - - int16_t* run = runs.fRuns; - uint8_t* aa = runs.fAlpha; - - if (ileft > 0) { - run[0] = ileft; - aa[0] = 0; - run += ileft; - aa += ileft; - } - - SkASSERT(leftA < 0xFF); - if (leftA > 0) { - *run++ = 1; - *aa++ = leftA; - } - - if (n > 0) { - run[0] = n; - aa[0] = 0xFF; - run += n; - aa += n; - } - - SkASSERT(riteA < 0xFF); - if (riteA > 0) { - *run++ = 1; - *aa++ = riteA; - } - run[0] = 0; -} - +// All parameters are in supersampled space. void SuperBlitter::blitRect(int x, int y, int width, int height) { SkASSERT(width > 0); SkASSERT(height > 0); @@ -275,6 +240,7 @@ void SuperBlitter::blitRect(int x, int y, int width, int height) { int stop_y = (y + height) >> SHIFT; int count = stop_y - start_y; if (count > 0) { + y += count << SHIFT; height -= count << SHIFT; @@ -318,19 +284,9 @@ void SuperBlitter::blitRect(int x, int y, int width, int height) { const int coverageR = coverage_to_alpha(xrite) << SHIFT; SkASSERT(n + (coverageR != 0) <= fWidth); - for (int i = start_y; i < stop_y; ++i) { - // note: we should only need to call set_left_rite once, but - // our clipping blitters sometimes modify runs/alpha in-place, - // so for now we reset fRuns each time :( - // - // TODO: - // - don't modify in-place, or at least tell us when you're going to - // - pass height down to blitAntiH (blitAntiHV) so that aaclip and - // other can take advantage of the vertical-repeat explicitly - // - set_left_rite_runs(fRuns, ileft, coverageL, n, coverageR); - fRealBlitter->blitAntiH(fLeft, i, fRuns.fAlpha, fRuns.fRuns); - } + fRealBlitter->blitAntiRect(ileft + fLeft, start_y, n, count, + coverageL > 0 ? coverageL : 255, + coverageR > 0 ? coverageR : 255); // preamble for our next call to blitH() fCurrIY = stop_y - 1; @@ -360,6 +316,10 @@ public: virtual void blitH(int x, int y, int width) SK_OVERRIDE; + // TODO: blitAntiRect() if we ever have performance problems - + // but the gains aren't expected to be nearly as large as for + // SuperBlitter. + static bool CanHandleRect(const SkIRect& bounds) { #ifdef FORCE_RLE return false; |