aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests/SkBlend_optsTest.cpp
blob: 9142f9d7a1b96c1a0c44e9675cc960ded43b2449 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <string>
#include <tuple>
#include <vector>
#include "Resources.h"
#include "SkCpu.h"
#include "SkImage.h"
#include "SkImage_Base.h"
#include "SkOpts.h"
#include "SkNx.h"
#include "Test.h"
#include "../include/core/SkImageInfo.h"

typedef void (*Blender)(uint32_t* dst, const uint32_t* const srcStart, int ndst, const int nsrc);

namespace sk_default {
extern void brute_force_srcover_srgb_srgb(
    uint32_t* dst, const uint32_t* const srcStart, int ndst, const int nsrc);
}

namespace sk_default {
extern void trivial_srcover_srgb_srgb(
    uint32_t* dst, const uint32_t* const srcStart, int ndst, const int nsrc);

extern void best_non_simd_srcover_srgb_srgb(
    uint32_t* dst, const uint32_t* const srcStart, int ndst, const int nsrc);

extern void srcover_srgb_srgb(
    uint32_t* dst, const uint32_t* const srcStart, int ndst, const int nsrc);
}

#if defined(SK_CPU_X86) && !defined(SK_BUILD_NO_OPTS)
namespace sk_sse41 {
extern void srcover_srgb_srgb(
    uint32_t* dst, const uint32_t* const srcStart, int ndst, const int nsrc);
}
#endif

static SkString missmatch_message(std::string resourceName, std::string name, int x, int y,
                                  uint32_t src, uint32_t good, uint32_t bad) {
    return SkStringPrintf(
        "%s - %s missmatch at %d, %d src: %08x good: %08x bad: %08x",
        resourceName.c_str(), name.c_str(), x, y, src, good, bad);
}

using Spec = std::tuple<Blender, std::string>;

static void test_blender(
    Spec spec,
    std::string resourceName,
    skiatest::Reporter* reporter)
{
    Blender blender;
    std::string name;
    std::tie(blender, name) = spec;

    std::string fileName = resourceName + ".png";
    sk_sp<SkImage> image = GetResourceAsImage(fileName.c_str());
    if (image == nullptr) {
        ERRORF(reporter, "image is NULL");
        return;
    }
    SkBitmap bm;
    if (!as_IB(image)->getROPixels(&bm)) {
        ERRORF(reporter, "Could not read resource");
        return;
    }

    SkPixmap pixmap;
    bm.peekPixels(&pixmap);
    SkASSERTF(pixmap.colorType() == kN32_SkColorType, "colorType: %d", pixmap.colorType());
    SkASSERT(pixmap.alphaType() != kUnpremul_SkAlphaType);
    const uint32_t* src = pixmap.addr32();
    const int width = pixmap.rowBytesAsPixels();
    SkASSERT(width > 0);
    SkASSERT(width < 4000);
    SkAutoTArray<uint32_t> correctDst(width);
    SkAutoTArray<uint32_t> testDst(width);

    for (int y = 0; y < pixmap.height(); y++) {
        memset(correctDst.get(), 0, width * sizeof(uint32_t));
        memset(testDst.get(), 0, width * sizeof(uint32_t));
        sk_default::brute_force_srcover_srgb_srgb(correctDst.get(), src, width, width);
        blender(testDst.get(), src, width, width);
        for (int x = 0; x < width; x++) {
            REPORTER_ASSERT_MESSAGE(
                reporter, correctDst[x] == testDst[x],
                missmatch_message(resourceName, name, x, y, src[x], correctDst[x], testDst[x]));
            if (correctDst[x] != testDst[x]) break;
        }
        src += width;
    }
}

DEF_TEST(SkBlend_optsCheck, reporter) {
    std::vector<Spec> specs = {
        Spec{sk_default::trivial_srcover_srgb_srgb,       "trivial"},
        Spec{sk_default::best_non_simd_srcover_srgb_srgb, "best_non_simd"},
        Spec{sk_default::srcover_srgb_srgb,               "default"},
    };
    #if defined(SK_CPU_X86) && !defined(SK_BUILD_NO_OPTS)
    if (SkCpu::Supports(SkCpu::SSE41)) {
        specs.push_back(Spec{sk_sse41::srcover_srgb_srgb, "sse41", });
    }
    #endif

    std::vector<std::string> testResources = {
        "yellow_rose", "baby_tux", "plane", "mandrill_512", "iconstrip"
    };

    for (auto& spec : specs) {
        for (auto& resourceName : testResources) {
            test_blender(spec, resourceName, reporter);
        }
    }
}



DEF_TEST(SkBlend_optsSqrtCheck, reporter) {
    for (int c = 0; c < 256; c++) {
        Sk4f i{(float)c};
        Sk4f ii = i * i;
        Sk4f s = ii.sqrt() + 0.5f;
        Sk4f sf = s.floor();
        REPORTER_ASSERT_MESSAGE(
            reporter, i[0] == sf[0], SkStringPrintf("i: %f, s: %f", i[0], sf[0]));
    }
}