aboutsummaryrefslogtreecommitdiffhomepage
path: root/gm/bitmaptiled.cpp
diff options
context:
space:
mode:
authorGravatar Brian Osman <brianosman@google.com>2017-02-06 16:48:57 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-02-06 22:34:19 +0000
commita950a86d225b7912e9878ecaa47da71acc88a66d (patch)
tree0f29715e522c225c8e24e4262a101b008e05ec70 /gm/bitmaptiled.cpp
parent92eba8a5efc0860d4e95ba7f25052474a0bfca0c (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.cpp75
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