diff options
author | krajcevski <krajcevski@google.com> | 2014-08-08 08:41:21 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-08-08 08:41:21 -0700 |
commit | dff491ba3eab17d5ae631e8c46f83a82390213b8 (patch) | |
tree | b66587c77aa2fcc83629305d2d58453715099521 /src | |
parent | ec989ba3b5945594986d691069dd217abded34b1 (diff) |
Implement BlitRect for SkTCompressedAlphaBlitter
R=robertphillips@google.com, reed@google.com
Author: krajcevski@google.com
Review URL: https://codereview.chromium.org/451823002
Diffstat (limited to 'src')
-rw-r--r-- | src/utils/SkTextureCompressor_Blitter.h | 84 |
1 files changed, 72 insertions, 12 deletions
diff --git a/src/utils/SkTextureCompressor_Blitter.h b/src/utils/SkTextureCompressor_Blitter.h index fe465be0a0..4470201b86 100644 --- a/src/utils/SkTextureCompressor_Blitter.h +++ b/src/utils/SkTextureCompressor_Blitter.h @@ -43,7 +43,12 @@ public: // 0x7FFE is one minus the largest positive 16-bit int. We use it for // debugging to make sure that we're properly setting the nextX distance // in flushRuns(). - : kLongestRun(0x7FFE), kZeroAlpha(0) +#ifdef SK_DEBUG + : fBlitMaskCalled(false), +#else + : +#endif + kLongestRun(0x7FFE), kZeroAlpha(0) , fNextRun(0) , fWidth(width) , fHeight(height) @@ -155,17 +160,72 @@ public: SkFAIL("Not implemented!"); } - // Blit a pattern of pixels defined by a rectangle-clipped mask; - // typically used for text. - virtual void blitMask(const SkMask&, const SkIRect& clip) SK_OVERRIDE { - // This function is currently not implemented. It is not explicitly - // required by the contract, but if at some time a code path runs into - // this function (which is entirely possible), it needs to be implemented. - // - // TODO (krajcevski): - // This function will be most easily implemented in the same way as - // blitAntiRect above. - SkFAIL("Not implemented!"); + // Blit a pattern of pixels defined by a rectangle-clipped mask; We make an + // assumption here that if this function gets called, then it will replace all + // of the compressed texture blocks that it touches. Hence, two separate calls + // to blitMask that have clips next to one another will cause artifacts. Most + // of the time, however, this function gets called because constructing the mask + // was faster than constructing the RLE for blitAntiH, and this function will + // only be called once. +#ifdef SK_DEBUG + bool fBlitMaskCalled; +#endif + virtual void blitMask(const SkMask& mask, const SkIRect& clip) SK_OVERRIDE { + + // Assumptions: + SkASSERT(!fBlitMaskCalled && (fBlitMaskCalled = true)); + SkASSERT(SkMask::kA8_Format == mask.fFormat); + SkASSERT(mask.fBounds.contains(clip)); + + // Start from largest block boundary less than the clip boundaries. + const int startI = BlockDim * (clip.left() / BlockDim); + const int startJ = BlockDim * (clip.top() / BlockDim); + + for (int j = startJ; j < clip.bottom(); j += BlockDim) { + + // Get the destination for this block row + uint8_t* dst = this->getBlock(startI, j); + for (int i = startI; i < clip.right(); i += BlockDim) { + + // At this point, the block should intersect the clip. + SkASSERT(SkIRect::IntersectsNoEmptyCheck( + SkIRect::MakeXYWH(i, j, BlockDim, BlockDim), clip)); + + // Do we need to pad it? + if (i < clip.left() || j < clip.top() || + i + BlockDim > clip.right() || j + BlockDim > clip.bottom()) { + + uint8_t block[BlockDim*BlockDim]; + memset(block, 0, sizeof(block)); + + const int startX = SkMax32(i, clip.left()); + const int startY = SkMax32(j, clip.top()); + + const int endX = SkMin32(i + BlockDim, clip.right()); + const int endY = SkMin32(j + BlockDim, clip.bottom()); + + for (int y = startY; y < endY; ++y) { + const int col = startX - i; + const int row = y - j; + const int valsWide = endX - startX; + SkASSERT(valsWide <= BlockDim); + SkASSERT(0 <= col && col < BlockDim); + SkASSERT(0 <= row && row < BlockDim); + memcpy(block + row*BlockDim + col, + mask.getAddr8(startX, j + row), valsWide); + } + + CompressorType::CompressA8Horizontal(dst, block, BlockDim); + } else { + // Otherwise, just compress it. + uint8_t*const src = mask.getAddr8(i, j); + const uint32_t rb = mask.fRowBytes; + CompressorType::CompressA8Horizontal(dst, src, rb); + } + + dst += EncodedBlockSize; + } + } } // If the blitter just sets a single value for each pixel, return the |