From 249ee1f985b4bad78db2d5cfdd14ce38edb2c23a Mon Sep 17 00:00:00 2001 From: Mike Klein Date: Tue, 1 Aug 2017 14:51:44 -0400 Subject: clamp to 0 in repeat and mirror image tilers If we were doing this math with real numbers or even just doubles, these clamps wouldn't be necessary. But we're favoring speed over accuracy here when we emulate fmod() and some of those inaccuracies end up with values outside the [0,tile) range, negative! To keep the spirit of fast over 100% accurate, I've just added a safety clamp to 0. The case in the unit test now returns 0 where it should really return something like 7 or 8, but at least we won't try to read _way_ outside the image buffer. BUG=chromium:749260 Change-Id: Ifc5cfe69798beccbb2a16547510158576e06eb3a Reviewed-on: https://skia-review.googlesource.com/29580 Reviewed-by: Florin Malita Commit-Queue: Mike Klein --- tests/SkRasterPipelineTest.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'tests/SkRasterPipelineTest.cpp') diff --git a/tests/SkRasterPipelineTest.cpp b/tests/SkRasterPipelineTest.cpp index bab3d5b63b..33e8b4fe15 100644 --- a/tests/SkRasterPipelineTest.cpp +++ b/tests/SkRasterPipelineTest.cpp @@ -262,3 +262,31 @@ DEF_TEST(SkRasterPipeline_2d, r) { REPORTER_ASSERT(r, ((rgba[2] >> 8) & 0xff) == 128); REPORTER_ASSERT(r, ((rgba[3] >> 8) & 0xff) == 128); } + +DEF_TEST(SkRasterPipeline_repeat_tiling, r) { + // Repeat tiling works roughly like + // v' = v - floor(v / limit) * limit + // + // If v = 19133558.0f and limit = 9.0f, that's + // + // v' = 19133558.0f - floor(19133558.0f / 9.0f) * 9.0f + // + // The problem comes with that division term. In infinite precision, + // that'd be 2125950 + 8/9, but the nearest float is 2125951.0f. + // + // Then 2125951.0f * 9.0f = 19133559.0f, which is greater than v, + // so v' becomes negative. :'( + + // Here's a regression test to make sure this doesn't happen. + float in [4] = {19133558.0f,0,0,0}; + float out[4 * SkJumper_kMaxStride]; + SkJumper_TileCtx tile = { 9.0f, 1/9.0f }; + + SkRasterPipeline_<256> p; + p.append(SkRasterPipeline::uniform_color, in); + p.append(SkRasterPipeline::repeat_x, &tile); + p.append(SkRasterPipeline::store_rgba, out); + p.run(0,0,1,1); + + REPORTER_ASSERT(r, 0.0f <= out[0] && out[0] < 9.0f); +} -- cgit v1.2.3