OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkRasterPipeline.h" | 8 #include "SkRasterPipeline.h" |
9 | 9 |
10 SkRasterPipeline::SkRasterPipeline() {} | 10 SkRasterPipeline::SkRasterPipeline() {} |
11 | 11 |
12 void SkRasterPipeline::append(SkRasterPipeline::Fn body, const void* body_ctx, | 12 void SkRasterPipeline::append(SkRasterPipeline::Fn body_fn, const void* body_ctx
, |
13 SkRasterPipeline::Fn tail, const void* tail_ctx) { | 13 SkRasterPipeline::Fn tail_fn, const void* tail_ctx
) { |
14 // We can't add more stages after being rewired to run(). | 14 // Each stage holds its own context and the next function to call. |
15 SkASSERT(!fReadyToRun); | 15 // So the pipeline itself has to hold onto the first function that starts th
e pipeline. |
| 16 (fBody.empty() ? fBodyStart : fBody.back().fNext) = body_fn; |
| 17 (fTail.empty() ? fTailStart : fTail.back().fNext) = tail_fn; |
16 | 18 |
17 // For now, just stash the stage's function in its own fNext slot. | 19 // Each last stage starts with its next function set to JustReturn as a safe
ty net. |
18 // We'll rewire our stages before running the pipeline so fNext makes sense. | 20 // It'll be overwritten by the next call to append(). |
19 fBody.push_back({ body, const_cast<void*>(body_ctx) }); | 21 fBody.push_back({ &JustReturn, const_cast<void*>(body_ctx) }); |
20 fTail.push_back({ tail, const_cast<void*>(tail_ctx) }); | 22 fTail.push_back({ &JustReturn, const_cast<void*>(tail_ctx) }); |
21 } | 23 } |
22 | 24 |
23 void SkRasterPipeline::run(size_t n) { | 25 void SkRasterPipeline::run(size_t n) { |
24 if (fBody.empty() || fTail.empty()) { | |
25 return; | |
26 } | |
27 | |
28 if (!fReadyToRun) { | |
29 auto rewire = [](Stages* stages) { | |
30 SkASSERT(!stages->empty()); | |
31 | |
32 // Rotate the fNext pointers so they point to the next function to | |
33 // call, not function we're currently calling as set by append(). | |
34 auto start = stages->front().fNext; | |
35 for (int i = 0; i < stages->count() - 1; i++) { | |
36 (*stages)[i].fNext = (*stages)[i+1].fNext; | |
37 } | |
38 stages->back().fNext = start; // This is a pretty handy place to st
ash this. | |
39 }; | |
40 rewire(&fBody); | |
41 rewire(&fTail); | |
42 fReadyToRun = true; | |
43 } | |
44 | |
45 // It's fastest to start uninitialized if the compilers all let us. If not,
next fastest is 0. | 26 // It's fastest to start uninitialized if the compilers all let us. If not,
next fastest is 0. |
46 Sk4f v; | 27 Sk4f v; |
47 | 28 |
48 auto start_body = fBody.back().fNext, // See rewire(). | |
49 start_tail = fTail.back().fNext; | |
50 | |
51 auto body = fBody.begin(), | |
52 tail = fTail.begin(); | |
53 | |
54 size_t x = 0; | 29 size_t x = 0; |
55 while (n >= 4) { | 30 while (n >= 4) { |
56 start_body(body, x, v,v,v,v, v,v,v,v); | 31 fBodyStart(fBody.begin(), x, v,v,v,v, v,v,v,v); |
57 x += 4; | 32 x += 4; |
58 n -= 4; | 33 n -= 4; |
59 } | 34 } |
60 while (n > 0) { | 35 while (n > 0) { |
61 start_tail(tail, x, v,v,v,v, v,v,v,v); | 36 fTailStart(fTail.begin(), x, v,v,v,v, v,v,v,v); |
62 x += 1; | 37 x += 1; |
63 n -= 1; | 38 n -= 1; |
64 } | 39 } |
65 } | 40 } |
| 41 |
| 42 void SK_VECTORCALL SkRasterPipeline::JustReturn(Stage*, size_t, Sk4f,Sk4f,Sk4f,S
k4f, |
| 43 Sk4f,Sk4f,Sk4f,S
k4f) {} |
OLD | NEW |