herb | feec878 | 2016-02-17 10:00:07 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2016 Google Inc. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license that can be |
| 5 | * found in the LICENSE file. |
| 6 | */ |
reed | dd9ffea | 2016-02-18 12:39:14 -0800 | [diff] [blame] | 7 | |
herb | c60fee0 | 2016-03-07 09:17:47 -0800 | [diff] [blame] | 8 | #include <algorithm> |
| 9 | #include <array> |
| 10 | #include <tuple> |
| 11 | #include <vector> |
herb | feec878 | 2016-02-17 10:00:07 -0800 | [diff] [blame] | 12 | #include "SkLinearBitmapPipeline.h" |
herb | feec878 | 2016-02-17 10:00:07 -0800 | [diff] [blame] | 13 | #include "SkColor.h" |
herb | c60fee0 | 2016-03-07 09:17:47 -0800 | [diff] [blame] | 14 | #include "SkNx.h" |
| 15 | #include "SkPoint.h" |
reed | dd9ffea | 2016-02-18 12:39:14 -0800 | [diff] [blame] | 16 | #include "SkPM4f.h" |
herb | feec878 | 2016-02-17 10:00:07 -0800 | [diff] [blame] | 17 | #include "Test.h" |
herb | c60fee0 | 2016-03-07 09:17:47 -0800 | [diff] [blame] | 18 | #include "SkLinearBitmapPipeline_tile.h" |
herb | feec878 | 2016-02-17 10:00:07 -0800 | [diff] [blame] | 19 | |
herb | feec878 | 2016-02-17 10:00:07 -0800 | [diff] [blame] | 20 | |
herb | 6eff52a | 2016-03-23 09:00:33 -0700 | [diff] [blame] | 21 | DEF_TEST(LBPBilerpEdge, reporter) { |
| 22 | |
| 23 | } |
| 24 | |
herb | c60fee0 | 2016-03-07 09:17:47 -0800 | [diff] [blame] | 25 | static SkString dump(SkScalar cut, Span prefix, Span remainder) { |
| 26 | SkPoint prefixStart; SkScalar prefixLen; int prefixCount; |
| 27 | std::tie(prefixStart, prefixLen, prefixCount) = prefix; |
| 28 | SkPoint remainderStart; SkScalar remainderLen; int remainderCount; |
| 29 | std::tie(remainderStart, remainderLen, remainderCount) = remainder; |
| 30 | return SkStringPrintf("cut: %f prefix: (%f, %f), %f, %d - remainder: (%f, %f), %f, %d", |
| 31 | cut, |
| 32 | prefixStart.fX, prefixStart.fY, prefixLen, prefixCount, |
| 33 | remainderStart.fX, remainderStart.fY, remainderLen, remainderCount); |
| 34 | } |
| 35 | |
| 36 | static void check_span_result( |
| 37 | skiatest::Reporter* reporter, |
| 38 | Span span, SkScalar dx, SkScalar cut, SkPoint start, SkScalar len, int count) { |
| 39 | SkPoint originalStart; SkScalar originalLen; int originalCount; |
| 40 | std::tie(originalStart, originalLen, originalCount) = span; |
| 41 | |
| 42 | Span prefix = span.breakAt(cut, dx); |
| 43 | |
| 44 | SkPoint prefixStart; SkScalar prefixLen; int prefixCount; |
| 45 | std::tie(prefixStart, prefixLen, prefixCount) = prefix; |
| 46 | |
| 47 | REPORTER_ASSERT_MESSAGE(reporter, prefixStart == start, dump(cut, prefix, span)); |
| 48 | REPORTER_ASSERT_MESSAGE(reporter, prefixLen == len, dump(cut, prefix, span)); |
| 49 | REPORTER_ASSERT_MESSAGE(reporter, prefixCount == count, dump(cut, prefix, span)); |
| 50 | SkPoint expectedRemainderStart; |
| 51 | SkScalar expectedRemainderLen; |
| 52 | int expectedRemainderCount; |
| 53 | if (prefix.isEmpty()) { |
| 54 | expectedRemainderStart = originalStart; |
| 55 | expectedRemainderLen = originalLen; |
| 56 | expectedRemainderCount = originalCount; |
| 57 | } else { |
| 58 | expectedRemainderStart = SkPoint::Make(originalStart.fX + prefixLen + dx, originalStart.fY); |
| 59 | expectedRemainderLen = originalLen - prefixLen - dx; |
| 60 | expectedRemainderCount = originalCount - prefixCount; |
| 61 | } |
| 62 | |
| 63 | if (!span.isEmpty()) { |
| 64 | SkPoint remainderStart; |
| 65 | SkScalar remainderLen; |
| 66 | int remainderCount; |
| 67 | std::tie(remainderStart, remainderLen, remainderCount) = span; |
| 68 | // Remainder span |
| 69 | REPORTER_ASSERT_MESSAGE(reporter, expectedRemainderStart == remainderStart, |
| 70 | dump(cut, prefix, span)); |
| 71 | REPORTER_ASSERT_MESSAGE(reporter, |
| 72 | expectedRemainderLen == remainderLen, |
| 73 | dump(cut, prefix, span)); |
| 74 | REPORTER_ASSERT_MESSAGE(reporter, |
| 75 | expectedRemainderCount == remainderCount, |
| 76 | dump(cut, prefix, span)); |
| 77 | } |
| 78 | } |
| 79 | |
| 80 | DEF_TEST(LBPSpanOps, reporter) { |
| 81 | { |
| 82 | SkScalar dx = 1.0f; |
| 83 | SkPoint start = SkPoint::Make(-5, -5); |
| 84 | Span span{start, 9.0f, 10}; |
| 85 | check_span_result(reporter, span, dx, 0.0f, start, 4.0f, 5); |
| 86 | check_span_result(reporter, span, dx, -6.0f, SkPoint::Make(0, 0), 0.0f, 0); |
| 87 | check_span_result(reporter, span, dx, -5.0f, SkPoint::Make(0, 0), 0.0f, 0); |
| 88 | check_span_result(reporter, span, dx, -4.0f, SkPoint::Make(-5, -5), 0.0f, 1); |
| 89 | check_span_result(reporter, span, dx, 4.0f, SkPoint::Make(-5, -5), 8.0f, 9); |
| 90 | check_span_result(reporter, span, dx, 5.0f, SkPoint::Make(-5, -5), 9.0f, 10); |
| 91 | check_span_result(reporter, span, dx, 6.0f, SkPoint::Make(-5, -5), 9.0f, 10); |
| 92 | } |
| 93 | { |
| 94 | SkScalar dx = -1.0f; |
| 95 | SkPoint start = SkPoint::Make(5, 5); |
| 96 | Span span{start, -9.0f, 10}; |
| 97 | check_span_result(reporter, span, dx, 0.0f, start, -5.0f, 6); |
| 98 | check_span_result(reporter, span, dx, -6.0f, SkPoint::Make(5, 5), -9.0f, 10); |
| 99 | check_span_result(reporter, span, dx, -5.0f, SkPoint::Make(5, 5), -9.0f, 10); |
| 100 | check_span_result(reporter, span, dx, -4.0f, SkPoint::Make(5, 5), -9.0f, 10); |
| 101 | check_span_result(reporter, span, dx, 4.0f, SkPoint::Make(5, 5), -1.0f, 2); |
| 102 | check_span_result(reporter, span, dx, 5.0f, SkPoint::Make(5, 5), 0.0f, 1); |
| 103 | check_span_result(reporter, span, dx, 6.0f, SkPoint::Make(0, 0), 0.0f, 0); |
| 104 | } |
| 105 | } |
| 106 | |
herb | 6eff52a | 2016-03-23 09:00:33 -0700 | [diff] [blame] | 107 | DEF_TEST(LBPBilerpSpanOps, reporter) { |
| 108 | |
| 109 | } |
| 110 | |
| 111 | template <typename XTiler, typename YTiler> |
| 112 | static bool compare_tiler_case( |
| 113 | XTiler& xTiler, YTiler& yTiler, Span span, skiatest::Reporter* reporter) { |
herb | c60fee0 | 2016-03-07 09:17:47 -0800 | [diff] [blame] | 114 | Span originalSpan = span; |
| 115 | std::vector<SkPoint> listPoints; |
| 116 | std::vector<SkPoint> spanPoints; |
| 117 | struct Sink { |
mtklein | e5fb9c8 | 2016-07-07 08:12:09 -0700 | [diff] [blame] | 118 | void SK_VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) { |
herb | c60fee0 | 2016-03-07 09:17:47 -0800 | [diff] [blame] | 119 | SkASSERT(0 < n && n < 4); |
| 120 | if (n >= 1) storePoint({xs[0], ys[0]}); |
| 121 | if (n >= 2) storePoint({xs[1], ys[1]}); |
| 122 | if (n >= 3) storePoint({xs[2], ys[2]}); |
| 123 | } |
| 124 | |
mtklein | e5fb9c8 | 2016-07-07 08:12:09 -0700 | [diff] [blame] | 125 | void SK_VECTORCALL pointList4(Sk4s xs, Sk4s ys) { |
herb | c60fee0 | 2016-03-07 09:17:47 -0800 | [diff] [blame] | 126 | storePoint({xs[0], ys[0]}); |
| 127 | storePoint({xs[1], ys[1]}); |
| 128 | storePoint({xs[2], ys[2]}); |
| 129 | storePoint({xs[3], ys[3]}); |
| 130 | } |
| 131 | |
| 132 | void pointSpan(Span span) { |
| 133 | span_fallback(span, this); |
| 134 | } |
| 135 | |
| 136 | void storePoint(SkPoint pt) { |
| 137 | fPoints->push_back({SkScalarFloorToScalar(X(pt)), SkScalarFloorToScalar(Y(pt))}); |
| 138 | } |
| 139 | |
| 140 | std::vector<SkPoint>* fPoints; |
| 141 | }; |
| 142 | |
| 143 | Sink listSink = {&listPoints}; |
| 144 | Sink spanSink = {&spanPoints}; |
| 145 | |
| 146 | SkPoint start; SkScalar length; int count; |
| 147 | std::tie(start, length, count) = span; |
| 148 | |
| 149 | SkScalar dx = length / (count - 1); |
| 150 | Sk4f xs = Sk4f{X(start)} + Sk4f{0.0f, dx, 2 * dx, 3 * dx}; |
| 151 | Sk4f ys = Sk4f{Y(start)}; |
| 152 | while (count >= 4) { |
| 153 | Sk4f txs = xs; |
| 154 | Sk4f tys = ys; |
herb | 6eff52a | 2016-03-23 09:00:33 -0700 | [diff] [blame] | 155 | xTiler.tileXPoints(&txs); |
| 156 | yTiler.tileYPoints(&tys); |
herb | c60fee0 | 2016-03-07 09:17:47 -0800 | [diff] [blame] | 157 | listSink.pointList4(txs, tys); |
| 158 | xs = xs + 4.0f * dx; |
| 159 | count -= 4; |
| 160 | } |
| 161 | if (count > 0) { |
herb | 6eff52a | 2016-03-23 09:00:33 -0700 | [diff] [blame] | 162 | xTiler.tileXPoints(&xs); |
| 163 | yTiler.tileYPoints(&ys); |
herb | c60fee0 | 2016-03-07 09:17:47 -0800 | [diff] [blame] | 164 | listSink.pointListFew(count, xs, ys); |
| 165 | } |
| 166 | |
herb | 6eff52a | 2016-03-23 09:00:33 -0700 | [diff] [blame] | 167 | std::tie(start, length, count) = originalSpan; |
| 168 | SkScalar x = X(start); |
| 169 | SkScalar y = yTiler.tileY(Y(start)); |
| 170 | Span yAdjustedSpan{{x, y}, length, count}; |
| 171 | |
| 172 | bool handledSpan = xTiler.maybeProcessSpan(yAdjustedSpan, &spanSink); |
herb | c60fee0 | 2016-03-07 09:17:47 -0800 | [diff] [blame] | 173 | if (handledSpan) { |
| 174 | auto firstNotTheSame = std::mismatch( |
| 175 | listPoints.begin(), listPoints.end(), spanPoints.begin()); |
| 176 | if (firstNotTheSame.first != listSink.fPoints->end()) { |
| 177 | auto element = std::distance(listPoints.begin(), firstNotTheSame.first); |
| 178 | SkASSERT(element >= 0); |
| 179 | std::tie(start, length, count) = originalSpan; |
| 180 | ERRORF(reporter, "Span: {%f, %f}, %f, %d", start.fX, start.fY, length, count); |
| 181 | ERRORF(reporter, "Size points: %d, size span: %d", |
| 182 | listPoints.size(), spanPoints.size()); |
| 183 | if ((unsigned)element >= spanPoints.size()) { |
| 184 | ERRORF(reporter, "Size points: %d, size span: %d", |
| 185 | listPoints.size(), spanPoints.size()); |
| 186 | // Mismatch off the end |
| 187 | ERRORF(reporter, |
| 188 | "The mismatch is at position %d and has value %f, %f - it is off the end " |
| 189 | "of the other.", |
| 190 | element, X(*firstNotTheSame.first), Y(*firstNotTheSame.first)); |
| 191 | } else { |
| 192 | ERRORF(reporter, |
| 193 | "Mismatch at %d - points: %f, %f - span: %f, %f", |
| 194 | element, listPoints[element].fX, listPoints[element].fY, |
| 195 | spanPoints[element].fX, spanPoints[element].fY); |
| 196 | } |
| 197 | SkFAIL("aha"); |
herb | feec878 | 2016-02-17 10:00:07 -0800 | [diff] [blame] | 198 | } |
| 199 | } |
herb | c60fee0 | 2016-03-07 09:17:47 -0800 | [diff] [blame] | 200 | return true; |
herb | feec878 | 2016-02-17 10:00:07 -0800 | [diff] [blame] | 201 | } |
| 202 | |
herb | 6eff52a | 2016-03-23 09:00:33 -0700 | [diff] [blame] | 203 | template <typename XTiler, typename YTiler> |
herb | c60fee0 | 2016-03-07 09:17:47 -0800 | [diff] [blame] | 204 | static bool compare_tiler_spans(int width, int height, skiatest::Reporter* reporter) { |
herb | 6eff52a | 2016-03-23 09:00:33 -0700 | [diff] [blame] | 205 | XTiler xTiler{width}; |
| 206 | YTiler yTiler{height}; |
herb | c60fee0 | 2016-03-07 09:17:47 -0800 | [diff] [blame] | 207 | INFOF(reporter, "w: %d, h: %d \n", width, height); |
| 208 | std::array<int, 8> interestingX {{-5, -1, 0, 1, width - 1, width, width + 1, width + 5}}; |
| 209 | std::array<int, 8> interestingY {{-5, -1, 0, 1, height - 1, height, height + 1, height + 5}}; |
| 210 | std::array<int, 6> interestingCount {{1, 2, 3, 4, 5, 10}}; |
| 211 | std::array<SkScalar, 7> interestingScale {{0.0f, 1.0f, 0.5f, 2.1f, -2.1f, -1.0f, -0.5f}}; |
| 212 | for (auto scale : interestingScale) { |
| 213 | for (auto startX : interestingX) { |
| 214 | for (auto count : interestingCount) { |
| 215 | for (auto y : interestingY) { |
| 216 | Span span{ |
| 217 | SkPoint::Make((SkScalar)startX, (SkScalar)y), (count-1.0f) * scale, count}; |
herb | 6eff52a | 2016-03-23 09:00:33 -0700 | [diff] [blame] | 218 | if (!compare_tiler_case(xTiler, yTiler, span, reporter)) { |
herb | c60fee0 | 2016-03-07 09:17:47 -0800 | [diff] [blame] | 219 | return false; |
| 220 | } |
| 221 | } |
| 222 | } |
| 223 | } |
| 224 | } |
| 225 | return true; |
| 226 | } |
| 227 | |
herb | 6eff52a | 2016-03-23 09:00:33 -0700 | [diff] [blame] | 228 | template <typename XTiler, typename YTiler> |
herb | c60fee0 | 2016-03-07 09:17:47 -0800 | [diff] [blame] | 229 | static void test_tiler(skiatest::Reporter* reporter) { |
| 230 | std::array<int, 6> interestingSize {{1, 2, 3, 4, 5, 10}}; |
| 231 | for (auto width : interestingSize) { |
| 232 | for (auto height : interestingSize) { |
herb | 6eff52a | 2016-03-23 09:00:33 -0700 | [diff] [blame] | 233 | if (!compare_tiler_spans<XTiler, YTiler>(width, height, reporter)) { return; } |
herb | c60fee0 | 2016-03-07 09:17:47 -0800 | [diff] [blame] | 234 | } |
| 235 | } |
| 236 | } |
herb | 6eff52a | 2016-03-23 09:00:33 -0700 | [diff] [blame] | 237 | /* |
herb | c60fee0 | 2016-03-07 09:17:47 -0800 | [diff] [blame] | 238 | DEF_TEST(LBPStrategyClampTile, reporter) { |
| 239 | #if 0 |
| 240 | ClampStrategy tiler{SkSize::Make(1, 1)}; |
| 241 | Span span{SkPoint::Make(0, -5), 1.0f, 2}; |
| 242 | compare_tiler_case<ClampStrategy>(tiler, span, reporter); |
| 243 | #else |
herb | 6eff52a | 2016-03-23 09:00:33 -0700 | [diff] [blame] | 244 | test_tiler<XClampStrategy, YClampStrategy>(reporter); |
herb | c60fee0 | 2016-03-07 09:17:47 -0800 | [diff] [blame] | 245 | #endif |
| 246 | } |
| 247 | |
| 248 | DEF_TEST(LBPStrategyRepeatTile, reporter) { |
| 249 | #if 0 |
| 250 | RepeatStrategy tiler{SkSize::Make(3, 1)}; |
| 251 | Span span{SkPoint::Make(-5, -5), 20 * 2.1f, 100}; |
| 252 | compare_tiler_case<RepeatStrategy>(tiler, span, reporter); |
| 253 | #else |
herb | 6eff52a | 2016-03-23 09:00:33 -0700 | [diff] [blame] | 254 | test_tiler<XRepeatStrategy, YRepeatStrategy>(reporter); |
herb | c60fee0 | 2016-03-07 09:17:47 -0800 | [diff] [blame] | 255 | #endif |
| 256 | } |
herb | 6eff52a | 2016-03-23 09:00:33 -0700 | [diff] [blame] | 257 | */ |