blob: beb517b3f7aca5cc7c45dd86eaab1e2aef530093 [file] [log] [blame]
mtklein281b33f2016-07-12 15:01:26 -07001/*
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 "Test.h"
9#include "SkRasterPipeline.h"
10
11// load needs two variants, one to load 4 values...
12static void SK_VECTORCALL load(SkRasterPipeline::Stage* st, size_t x,
13 Sk4f v0, Sk4f v1, Sk4f v2, Sk4f v3,
14 Sk4f v4, Sk4f v5, Sk4f v6, Sk4f v7) {
15 auto ptr = st->ctx<const float*>();
16 v0 = Sk4f{ptr[x+0]};
17 v1 = Sk4f{ptr[x+1]};
18 v2 = Sk4f{ptr[x+2]};
19 v3 = Sk4f{ptr[x+3]};
20
21 st->next(x, v0,v1,v2,v3, v4,v5,v6,v7);
22}
23
24// ...and one to load a single value.
25static void SK_VECTORCALL load_tail(SkRasterPipeline::Stage* st, size_t x,
26 Sk4f v0, Sk4f v1, Sk4f v2, Sk4f v3,
27 Sk4f v4, Sk4f v5, Sk4f v6, Sk4f v7) {
28 auto ptr = st->ctx<const float*>();
29 v0 = Sk4f{ptr[x]};
30
31 st->next(x, v0,v1,v2,v3, v4,v5,v6,v7);
32}
33
34// square doesn't really care how many of its inputs are active, nor does it need a context.
35static void SK_VECTORCALL square(SkRasterPipeline::Stage* st, size_t x,
36 Sk4f v0, Sk4f v1, Sk4f v2, Sk4f v3,
37 Sk4f v4, Sk4f v5, Sk4f v6, Sk4f v7) {
38 v0 *= v0;
39 v1 *= v1;
40 v2 *= v2;
41 v3 *= v3;
42 st->next(x, v0,v1,v2,v3, v4,v5,v6,v7);
43}
44
45// Like load, store has a _tail variant. It ends the pipeline by returning.
46static void SK_VECTORCALL store(SkRasterPipeline::Stage* st, size_t x,
47 Sk4f v0, Sk4f v1, Sk4f v2, Sk4f v3,
48 Sk4f v4, Sk4f v5, Sk4f v6, Sk4f v7) {
49 auto ptr = st->ctx<float*>();
50 ptr[x+0] = v0[0];
51 ptr[x+1] = v1[0];
52 ptr[x+2] = v2[0];
53 ptr[x+3] = v3[0];
54}
55
56static void SK_VECTORCALL store_tail(SkRasterPipeline::Stage* st, size_t x,
57 Sk4f v0, Sk4f v1, Sk4f v2, Sk4f v3,
58 Sk4f v4, Sk4f v5, Sk4f v6, Sk4f v7) {
59 auto ptr = st->ctx<float*>();
60 ptr[x+0] = v0[0];
61}
62
63DEF_TEST(SkRasterPipeline, r) {
64 // We'll build up and run a simple pipeline that exercises the salient
65 // mechanics of SkRasterPipeline:
66 // - context pointers
67 // - stages sensitive to the number of pixels
68 // - stages insensitive to the number of pixels
69 //
70 // This pipeline loads up some values, squares them, then writes them back to memory.
71
72 const float src_vals[] = { 1,2,3,4,5 };
73 float dst_vals[] = { 0,0,0,0,0 };
74
75 SkRasterPipeline p;
76 p.append(load, load_tail, src_vals);
77 p.append(square);
78 p.append(store, store_tail, dst_vals);
79
80 p.run(5);
81
82 REPORTER_ASSERT(r, dst_vals[0] == 1);
83 REPORTER_ASSERT(r, dst_vals[1] == 4);
84 REPORTER_ASSERT(r, dst_vals[2] == 9);
85 REPORTER_ASSERT(r, dst_vals[3] == 16);
86 REPORTER_ASSERT(r, dst_vals[4] == 25);
87}
mtklein0abddf72016-07-13 08:22:20 -070088
89DEF_TEST(SkRasterPipeline_empty, r) {
90 // No asserts... just a test that this is safe to run.
91 SkRasterPipeline p;
92 p.run(20);
93}
94
95DEF_TEST(SkRasterPipeline_nonsense, r) {
96 // No asserts... just a test that this is safe to run and terminates.
97 // square() always calls st->next(); this makes sure we've always got something there to call.
98 SkRasterPipeline p;
99 p.append(square);
100 p.run(20);
101}