Home | History | Annotate | Download | only in tests
      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  */
      7 
      8 #include <algorithm>
      9 #include <array>
     10 #include <tuple>
     11 #include <vector>
     12 #include "SkLinearBitmapPipeline.h"
     13 #include "SkColor.h"
     14 #include "SkNx.h"
     15 #include "SkPoint.h"
     16 #include "SkPM4f.h"
     17 #include "Test.h"
     18 #include "SkLinearBitmapPipeline_tile.h"
     19 
     20 
     21 DEF_TEST(LBPBilerpEdge, reporter) {
     22 
     23 }
     24 
     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 
    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) {
    114     Span originalSpan = span;
    115     std::vector<SkPoint> listPoints;
    116     std::vector<SkPoint> spanPoints;
    117     struct Sink {
    118         void SK_VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) {
    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 
    125         void SK_VECTORCALL pointList4(Sk4s xs, Sk4s ys) {
    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;
    155         xTiler.tileXPoints(&txs);
    156         yTiler.tileYPoints(&tys);
    157         listSink.pointList4(txs, tys);
    158         xs = xs + 4.0f * dx;
    159         count -= 4;
    160     }
    161     if (count > 0) {
    162         xTiler.tileXPoints(&xs);
    163         yTiler.tileYPoints(&ys);
    164         listSink.pointListFew(count, xs, ys);
    165     }
    166 
    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);
    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");
    198         }
    199     }
    200     return true;
    201 }
    202 
    203 template <typename XTiler, typename YTiler>
    204 static bool compare_tiler_spans(int width, int height, skiatest::Reporter* reporter) {
    205     XTiler xTiler{width};
    206     YTiler yTiler{height};
    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};
    218                     if (!compare_tiler_case(xTiler, yTiler, span, reporter)) {
    219                         return false;
    220                     }
    221                 }
    222             }
    223         }
    224     }
    225     return true;
    226 }
    227 
    228 template <typename XTiler, typename YTiler>
    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) {
    233             if (!compare_tiler_spans<XTiler, YTiler>(width, height, reporter)) { return; }
    234         }
    235     }
    236 }
    237 /*
    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
    244     test_tiler<XClampStrategy, YClampStrategy>(reporter);
    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
    254     test_tiler<XRepeatStrategy, YRepeatStrategy>(reporter);
    255 #endif
    256 }
    257 */
    258