Index: tests/SkLinearBitmapPipelineTest.cpp |
diff --git a/tests/SkLinearBitmapPipelineTest.cpp b/tests/SkLinearBitmapPipelineTest.cpp |
index 04f2e2783e8e053ac75713a3d68ccc5481511843..e715b62d89567892043759897124c2538deedfc2 100644 |
--- a/tests/SkLinearBitmapPipelineTest.cpp |
+++ b/tests/SkLinearBitmapPipelineTest.cpp |
@@ -5,54 +5,237 @@ |
* found in the LICENSE file. |
*/ |
+#include <algorithm> |
+#include <array> |
+#include <tuple> |
+#include <vector> |
#include "SkLinearBitmapPipeline.h" |
#include "SkColor.h" |
+#include "SkNx.h" |
+#include "SkPoint.h" |
#include "SkPM4f.h" |
#include "Test.h" |
+#include "SkLinearBitmapPipeline_tile.h" |
-using Pixel = float[4]; |
-DEF_TEST(SkBitmapFP, reporter) { |
- int width = 10; |
- int height = 10; |
- uint32_t* bitmap = new uint32_t[width * height]; |
- for (int y = 0; y < height; y++) { |
- for (int x = 0; x < width; x++) { |
- bitmap[y * width + x] = (y << 8) + x + (128<<24); |
- } |
+static SkString dump(SkScalar cut, Span prefix, Span remainder) { |
+ SkPoint prefixStart; SkScalar prefixLen; int prefixCount; |
+ std::tie(prefixStart, prefixLen, prefixCount) = prefix; |
+ SkPoint remainderStart; SkScalar remainderLen; int remainderCount; |
+ std::tie(remainderStart, remainderLen, remainderCount) = remainder; |
+ return SkStringPrintf("cut: %f prefix: (%f, %f), %f, %d - remainder: (%f, %f), %f, %d", |
+ cut, |
+ prefixStart.fX, prefixStart.fY, prefixLen, prefixCount, |
+ remainderStart.fX, remainderStart.fY, remainderLen, remainderCount); |
+} |
+ |
+static void check_span_result( |
+ skiatest::Reporter* reporter, |
+ Span span, SkScalar dx, SkScalar cut, SkPoint start, SkScalar len, int count) { |
+ SkPoint originalStart; SkScalar originalLen; int originalCount; |
+ std::tie(originalStart, originalLen, originalCount) = span; |
+ |
+ Span prefix = span.breakAt(cut, dx); |
+ |
+ SkPoint prefixStart; SkScalar prefixLen; int prefixCount; |
+ std::tie(prefixStart, prefixLen, prefixCount) = prefix; |
+ |
+ REPORTER_ASSERT_MESSAGE(reporter, prefixStart == start, dump(cut, prefix, span)); |
+ REPORTER_ASSERT_MESSAGE(reporter, prefixLen == len, dump(cut, prefix, span)); |
+ REPORTER_ASSERT_MESSAGE(reporter, prefixCount == count, dump(cut, prefix, span)); |
+ SkPoint expectedRemainderStart; |
+ SkScalar expectedRemainderLen; |
+ int expectedRemainderCount; |
+ if (prefix.isEmpty()) { |
+ expectedRemainderStart = originalStart; |
+ expectedRemainderLen = originalLen; |
+ expectedRemainderCount = originalCount; |
+ } else { |
+ expectedRemainderStart = SkPoint::Make(originalStart.fX + prefixLen + dx, originalStart.fY); |
+ expectedRemainderLen = originalLen - prefixLen - dx; |
+ expectedRemainderCount = originalCount - prefixCount; |
} |
- SkPM4f* FPbuffer = new SkPM4f[width * height]; |
+ if (!span.isEmpty()) { |
+ SkPoint remainderStart; |
+ SkScalar remainderLen; |
+ int remainderCount; |
+ std::tie(remainderStart, remainderLen, remainderCount) = span; |
+ // Remainder span |
+ REPORTER_ASSERT_MESSAGE(reporter, expectedRemainderStart == remainderStart, |
+ dump(cut, prefix, span)); |
+ REPORTER_ASSERT_MESSAGE(reporter, |
+ expectedRemainderLen == remainderLen, |
+ dump(cut, prefix, span)); |
+ REPORTER_ASSERT_MESSAGE(reporter, |
+ expectedRemainderCount == remainderCount, |
+ dump(cut, prefix, span)); |
+ } |
+} |
- SkMatrix m = SkMatrix::I(); |
- //m.setRotate(30.0f, 1.0f, 1.0f); |
- SkMatrix invert; |
- bool trash = m.invert(&invert); |
- sk_ignore_unused_variable(trash); |
+DEF_TEST(LBPSpanOps, reporter) { |
+ { |
+ SkScalar dx = 1.0f; |
+ SkPoint start = SkPoint::Make(-5, -5); |
+ Span span{start, 9.0f, 10}; |
+ check_span_result(reporter, span, dx, 0.0f, start, 4.0f, 5); |
+ check_span_result(reporter, span, dx, -6.0f, SkPoint::Make(0, 0), 0.0f, 0); |
+ check_span_result(reporter, span, dx, -5.0f, SkPoint::Make(0, 0), 0.0f, 0); |
+ check_span_result(reporter, span, dx, -4.0f, SkPoint::Make(-5, -5), 0.0f, 1); |
+ check_span_result(reporter, span, dx, 4.0f, SkPoint::Make(-5, -5), 8.0f, 9); |
+ check_span_result(reporter, span, dx, 5.0f, SkPoint::Make(-5, -5), 9.0f, 10); |
+ check_span_result(reporter, span, dx, 6.0f, SkPoint::Make(-5, -5), 9.0f, 10); |
+ } |
+ { |
+ SkScalar dx = -1.0f; |
+ SkPoint start = SkPoint::Make(5, 5); |
+ Span span{start, -9.0f, 10}; |
+ check_span_result(reporter, span, dx, 0.0f, start, -5.0f, 6); |
+ check_span_result(reporter, span, dx, -6.0f, SkPoint::Make(5, 5), -9.0f, 10); |
+ check_span_result(reporter, span, dx, -5.0f, SkPoint::Make(5, 5), -9.0f, 10); |
+ check_span_result(reporter, span, dx, -4.0f, SkPoint::Make(5, 5), -9.0f, 10); |
+ check_span_result(reporter, span, dx, 4.0f, SkPoint::Make(5, 5), -1.0f, 2); |
+ check_span_result(reporter, span, dx, 5.0f, SkPoint::Make(5, 5), 0.0f, 1); |
+ check_span_result(reporter, span, dx, 6.0f, SkPoint::Make(0, 0), 0.0f, 0); |
+ } |
+} |
- const SkImageInfo info = |
- SkImageInfo::MakeN32Premul(width, height, kLinear_SkColorProfileType); |
+template <typename Tiler> |
+static bool compare_tiler_case(Tiler& tiler, Span span, skiatest::Reporter* reporter) { |
+ Span originalSpan = span; |
+ std::vector<SkPoint> listPoints; |
+ std::vector<SkPoint> spanPoints; |
+ struct Sink { |
+ void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) { |
+ SkASSERT(0 < n && n < 4); |
+ if (n >= 1) storePoint({xs[0], ys[0]}); |
+ if (n >= 2) storePoint({xs[1], ys[1]}); |
+ if (n >= 3) storePoint({xs[2], ys[2]}); |
+ } |
- SkPixmap srcPixmap{info, bitmap, static_cast<size_t>(4 * width)}; |
+ void VECTORCALL pointList4(Sk4s xs, Sk4s ys) { |
+ storePoint({xs[0], ys[0]}); |
+ storePoint({xs[1], ys[1]}); |
+ storePoint({xs[2], ys[2]}); |
+ storePoint({xs[3], ys[3]}); |
+ } |
- SkLinearBitmapPipeline pipeline{invert, kNone_SkFilterQuality, SkShader::kClamp_TileMode, |
- SkShader::kClamp_TileMode, srcPixmap}; |
+ void pointSpan(Span span) { |
+ span_fallback(span, this); |
+ } |
- int count = 10; |
+ void storePoint(SkPoint pt) { |
+ fPoints->push_back({SkScalarFloorToScalar(X(pt)), SkScalarFloorToScalar(Y(pt))}); |
+ } |
- pipeline.shadeSpan4f(3, 6, FPbuffer, count); |
-#if 0 |
- Pixel* pixelBuffer = (Pixel*)FPbuffer; |
- for (int i = 0; i < count; i++) { |
- printf("i: %d - (%g, %g, %g, %g)\n", i, |
- pixelBuffer[i][0] * 255.0f, |
- pixelBuffer[i][1] * 255.0f, |
- pixelBuffer[i][2] * 255.0f, |
- pixelBuffer[i][3] * 255.0f); |
+ std::vector<SkPoint>* fPoints; |
+ }; |
+ |
+ Sink listSink = {&listPoints}; |
+ Sink spanSink = {&spanPoints}; |
+ |
+ SkPoint start; SkScalar length; int count; |
+ std::tie(start, length, count) = span; |
+ |
+ SkScalar dx = length / (count - 1); |
+ Sk4f xs = Sk4f{X(start)} + Sk4f{0.0f, dx, 2 * dx, 3 * dx}; |
+ Sk4f ys = Sk4f{Y(start)}; |
+ while (count >= 4) { |
+ Sk4f txs = xs; |
+ Sk4f tys = ys; |
+ tiler.processPoints(&txs, &tys); |
+ listSink.pointList4(txs, tys); |
+ xs = xs + 4.0f * dx; |
+ count -= 4; |
} |
+ if (count > 0) { |
+ tiler.processPoints(&xs, &ys); |
+ listSink.pointListFew(count, xs, ys); |
+ } |
+ |
+ bool handledSpan = tiler.maybeProcessSpan(span, &spanSink); |
+ if (handledSpan) { |
+ auto firstNotTheSame = std::mismatch( |
+ listPoints.begin(), listPoints.end(), spanPoints.begin()); |
+ if (firstNotTheSame.first != listSink.fPoints->end()) { |
+ auto element = std::distance(listPoints.begin(), firstNotTheSame.first); |
+ SkASSERT(element >= 0); |
+ std::tie(start, length, count) = originalSpan; |
+ ERRORF(reporter, "Span: {%f, %f}, %f, %d", start.fX, start.fY, length, count); |
+ ERRORF(reporter, "Size points: %d, size span: %d", |
+ listPoints.size(), spanPoints.size()); |
+ if ((unsigned)element >= spanPoints.size()) { |
+ ERRORF(reporter, "Size points: %d, size span: %d", |
+ listPoints.size(), spanPoints.size()); |
+ // Mismatch off the end |
+ ERRORF(reporter, |
+ "The mismatch is at position %d and has value %f, %f - it is off the end " |
+ "of the other.", |
+ element, X(*firstNotTheSame.first), Y(*firstNotTheSame.first)); |
+ } else { |
+ ERRORF(reporter, |
+ "Mismatch at %d - points: %f, %f - span: %f, %f", |
+ element, listPoints[element].fX, listPoints[element].fY, |
+ spanPoints[element].fX, spanPoints[element].fY); |
+ } |
+ SkFAIL("aha"); |
+ } |
+ } |
+ return true; |
+} |
+ |
+template <typename Tiler> |
+static bool compare_tiler_spans(int width, int height, skiatest::Reporter* reporter) { |
+ Tiler tiler{SkSize::Make((SkScalar)width, (SkScalar)height)}; |
+ INFOF(reporter, "w: %d, h: %d \n", width, height); |
+ std::array<int, 8> interestingX {{-5, -1, 0, 1, width - 1, width, width + 1, width + 5}}; |
+ std::array<int, 8> interestingY {{-5, -1, 0, 1, height - 1, height, height + 1, height + 5}}; |
+ std::array<int, 6> interestingCount {{1, 2, 3, 4, 5, 10}}; |
+ std::array<SkScalar, 7> interestingScale {{0.0f, 1.0f, 0.5f, 2.1f, -2.1f, -1.0f, -0.5f}}; |
+ for (auto scale : interestingScale) { |
+ for (auto startX : interestingX) { |
+ for (auto count : interestingCount) { |
+ for (auto y : interestingY) { |
+ Span span{ |
+ SkPoint::Make((SkScalar)startX, (SkScalar)y), (count-1.0f) * scale, count}; |
+ if (!compare_tiler_case(tiler, span, reporter)) { |
+ return false; |
+ } |
+ } |
+ } |
+ } |
+ } |
+ return true; |
+} |
+ |
+template <typename Tiler> |
+static void test_tiler(skiatest::Reporter* reporter) { |
+ std::array<int, 6> interestingSize {{1, 2, 3, 4, 5, 10}}; |
+ for (auto width : interestingSize) { |
+ for (auto height : interestingSize) { |
+ if (!compare_tiler_spans<Tiler>(width, height, reporter)) { return; } |
+ } |
+ } |
+} |
+ |
+DEF_TEST(LBPStrategyClampTile, reporter) { |
+#if 0 |
+ ClampStrategy tiler{SkSize::Make(1, 1)}; |
+ Span span{SkPoint::Make(0, -5), 1.0f, 2}; |
+ compare_tiler_case<ClampStrategy>(tiler, span, reporter); |
+#else |
+ test_tiler<ClampStrategy>(reporter); |
#endif |
+} |
- delete [] bitmap; |
- delete [] FPbuffer; |
+DEF_TEST(LBPStrategyRepeatTile, reporter) { |
+#if 0 |
+ RepeatStrategy tiler{SkSize::Make(3, 1)}; |
+ Span span{SkPoint::Make(-5, -5), 20 * 2.1f, 100}; |
+ compare_tiler_case<RepeatStrategy>(tiler, span, reporter); |
+#else |
+ test_tiler<RepeatStrategy>(reporter); |
+#endif |
} |
+ |