diff options
author | Brian Osman <brianosman@google.com> | 2017-02-06 16:48:57 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-02-06 22:34:19 +0000 |
commit | a950a86d225b7912e9878ecaa47da71acc88a66d (patch) | |
tree | 0f29715e522c225c8e24e4262a101b008e05ec70 /gm/bitmaptiled.cpp | |
parent | 92eba8a5efc0860d4e95ba7f25052474a0bfca0c (diff) |
Fix rounding error with tiled bitmap draws
We were snapping the top-left of the destination rectangle to integers,
but using the original (fractional) size. This led to us losing rows or
columns of pixels at the first tile boundary.
Also added a GM that demonstrates the bug (now renders correctly).
BUG=skia:
Change-Id: I50629dab9dd90fedad2c7e3393a1b1d1c7a8d45e
Reviewed-on: https://skia-review.googlesource.com/8102
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
Diffstat (limited to 'gm/bitmaptiled.cpp')
-rw-r--r-- | gm/bitmaptiled.cpp | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/gm/bitmaptiled.cpp b/gm/bitmaptiled.cpp new file mode 100644 index 0000000000..7cb716c00d --- /dev/null +++ b/gm/bitmaptiled.cpp @@ -0,0 +1,75 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "gm.h" + +#if SK_SUPPORT_GPU +#include "GrContext.h" + +// This test exercises Ganesh's drawing of tiled bitmaps. In particular, that the offsets and the +// extents of the tiles don't causes gaps between tiles. +static void draw_tile_bitmap_with_fractional_offset(SkCanvas* canvas, bool vertical) { + GrContext* context = canvas->getGrContext(); + if (!context) { + skiagm::GM::DrawGpuOnlyMessage(canvas); + return; + } + + // This should match kBmpSmallTileSize in SkGpuDevice.cpp. Note that our canvas size is tuned + // to this constant as well. + const int kTileSize = 1 << 10; + + // We're going to draw a section of the bitmap that intersects 3 tiles (3x1 or 1x3). + // We need that to be < 50% of the total image, so our image is 7 tiles (7x1 or 1x7). + const int kBitmapLongEdge = 7 * kTileSize; + const int kBitmapShortEdge = 1 * kTileSize; + + // To trigger tiling, we also need the image to be more than 50% of the cache, so we ensure the + // cache is sized to make that true. + const int kBitmapArea = kBitmapLongEdge * kBitmapShortEdge; + const size_t kBitmapBytes = kBitmapArea * sizeof(SkPMColor); + + int oldMaxResources; + size_t oldMaxResourceBytes; + context->getResourceCacheLimits(&oldMaxResources, &oldMaxResourceBytes); + + const size_t newMaxResourceBytes = kBitmapBytes + (kBitmapBytes / 2); + context->setResourceCacheLimits(oldMaxResources, newMaxResourceBytes); + + // Construct our bitmap as either very wide or very tall + SkBitmap bmp; + bmp.allocN32Pixels(vertical ? kBitmapShortEdge : kBitmapLongEdge, + vertical ? kBitmapLongEdge : kBitmapShortEdge, true); + bmp.eraseColor(SK_ColorWHITE); + + // Draw ten strips with varying fractional offset to catch any rasterization issues with tiling + for (int i = 0; i < 10; ++i) { + float offset = i * 0.1f; + if (vertical) { + canvas->drawBitmapRect(bmp, SkRect::MakeXYWH(0.0f, (kTileSize - 50) + offset, + 32.0f, 1124.0f), + SkRect::MakeXYWH(37.0f * i, 0.0f, 32.0f, 1124.0f), nullptr); + } else { + canvas->drawBitmapRect(bmp, SkRect::MakeXYWH((kTileSize - 50) + offset, 0.0f, + 1124.0f, 32.0f), + SkRect::MakeXYWH(0.0f, 37.0f * i, 1124.0f, 32.0f), nullptr); + } + } + + // Restore the cache + context->setResourceCacheLimits(oldMaxResources, oldMaxResourceBytes); +} + +DEF_SIMPLE_GM_BG(bitmaptiled_fractional_horizontal, canvas, 1124, 365, SK_ColorBLACK) { + draw_tile_bitmap_with_fractional_offset(canvas, false); +} + +DEF_SIMPLE_GM_BG(bitmaptiled_fractional_vertical, canvas, 1124, 365, SK_ColorBLACK) { + draw_tile_bitmap_with_fractional_offset(canvas, true); +} + +#endif |