aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/utils/SkTextureCompressor_Blitter.h
diff options
context:
space:
mode:
authorGravatar krajcevski <krajcevski@google.com>2014-08-08 08:41:21 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-08-08 08:41:21 -0700
commitdff491ba3eab17d5ae631e8c46f83a82390213b8 (patch)
treeb66587c77aa2fcc83629305d2d58453715099521 /src/utils/SkTextureCompressor_Blitter.h
parentec989ba3b5945594986d691069dd217abded34b1 (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/utils/SkTextureCompressor_Blitter.h')
-rw-r--r--src/utils/SkTextureCompressor_Blitter.h84
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