1 | /* |
2 | * Copyright 2015 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 "src/gpu/GrProcessorUnitTest.h" |
9 | |
10 | #include <memory> |
11 | |
12 | #include "include/gpu/GrRecordingContext.h" |
13 | #include "src/gpu/GrFragmentProcessor.h" |
14 | #include "src/gpu/GrRecordingContextPriv.h" |
15 | #include "src/gpu/effects/generated/GrConstColorProcessor.h" |
16 | |
17 | #if GR_TEST_UTILS |
18 | |
19 | class GrGeometryProcessor; |
20 | |
21 | GrProcessorTestData::GrProcessorTestData(SkRandom* random, GrRecordingContext* context, |
22 | int maxTreeDepth, int numViews, const ViewInfo views[]) |
23 | : GrProcessorTestData(random, context, maxTreeDepth, numViews, views, |
24 | /*inputFP=*/nullptr) {} |
25 | |
26 | GrProcessorTestData::GrProcessorTestData(SkRandom* random, GrRecordingContext* context, |
27 | int maxTreeDepth, int numViews, const ViewInfo views[], |
28 | std::unique_ptr<GrFragmentProcessor> inputFP) |
29 | : fRandom(random) |
30 | , fMaxTreeDepth(maxTreeDepth) |
31 | , fContext(context) |
32 | , fInputFP(std::move(inputFP)) { |
33 | fViews.reset(views, numViews); |
34 | fArena = std::make_unique<SkArenaAlloc>(1000); |
35 | } |
36 | |
37 | GrProcessorTestData::~GrProcessorTestData() {} |
38 | |
39 | GrProxyProvider* GrProcessorTestData::proxyProvider() { return fContext->priv().proxyProvider(); } |
40 | |
41 | const GrCaps* GrProcessorTestData::caps() { return fContext->priv().caps(); } |
42 | |
43 | std::unique_ptr<GrFragmentProcessor> GrProcessorTestData::inputFP() { |
44 | if (fCurrentTreeDepth == 0) { |
45 | // At the top level of the tree, provide the input FP from the test data. |
46 | return fInputFP ? fInputFP->clone() : nullptr; |
47 | } else { |
48 | // At deeper levels of recursion, synthesize a random input. |
49 | return GrProcessorUnitTest::MakeChildFP(this); |
50 | } |
51 | } |
52 | |
53 | GrProcessorTestData::ViewInfo GrProcessorTestData::randomView() { |
54 | SkASSERT(!fViews.empty()); |
55 | return fViews[fRandom->nextULessThan(fViews.count())]; |
56 | } |
57 | |
58 | GrProcessorTestData::ViewInfo GrProcessorTestData::randomAlphaOnlyView() { |
59 | int numAlphaOnly = 0; |
60 | for (const auto& [v, ct, at] : fViews) { |
61 | if (GrColorTypeIsAlphaOnly(ct)) { |
62 | ++numAlphaOnly; |
63 | } |
64 | } |
65 | SkASSERT(numAlphaOnly); |
66 | int idx = fRandom->nextULessThan(numAlphaOnly); |
67 | for (const auto& [v, ct, at] : fViews) { |
68 | if (GrColorTypeIsAlphaOnly(ct) && !idx--) { |
69 | return {v, ct, at}; |
70 | } |
71 | } |
72 | SkUNREACHABLE; |
73 | } |
74 | |
75 | template <class ProcessorSmartPtr> |
76 | GrProcessorTestFactory<ProcessorSmartPtr>::GrProcessorTestFactory(MakeProc makeProc, |
77 | const char* name) |
78 | : fMakeProc(makeProc), fName(name) { |
79 | GetFactories()->push_back(this); |
80 | } |
81 | |
82 | template <class ProcessorSmartPtr> |
83 | ProcessorSmartPtr GrProcessorTestFactory<ProcessorSmartPtr>::Make(GrProcessorTestData* data) { |
84 | VerifyFactoryCount(); |
85 | if (GetFactories()->count() == 0) { |
86 | return nullptr; |
87 | } |
88 | uint32_t idx = data->fRandom->nextULessThan(GetFactories()->count()); |
89 | return MakeIdx(idx, data); |
90 | } |
91 | |
92 | template <class ProcessorSmartPtr> |
93 | ProcessorSmartPtr GrProcessorTestFactory<ProcessorSmartPtr>::MakeIdx(int idx, |
94 | GrProcessorTestData* data) { |
95 | SkASSERT(idx < GetFactories()->count()); |
96 | GrProcessorTestFactory<ProcessorSmartPtr>* factory = (*GetFactories())[idx]; |
97 | ProcessorSmartPtr processor = factory->fMakeProc(data); |
98 | if (processor == nullptr) { |
99 | SK_ABORT("%s: TestCreate returned null" , factory->fName.c_str()); |
100 | } |
101 | return processor; |
102 | } |
103 | |
104 | template <class ProcessorSmartPtr> |
105 | int GrProcessorTestFactory<ProcessorSmartPtr>::Count() { |
106 | return GetFactories()->count(); |
107 | } |
108 | |
109 | GrXPFactoryTestFactory::GrXPFactoryTestFactory(GetFn* getProc) : fGetProc(getProc) { |
110 | GetFactories()->push_back(this); |
111 | } |
112 | |
113 | const GrXPFactory* GrXPFactoryTestFactory::Get(GrProcessorTestData* data) { |
114 | VerifyFactoryCount(); |
115 | if (GetFactories()->count() == 0) { |
116 | return nullptr; |
117 | } |
118 | uint32_t idx = data->fRandom->nextRangeU(0, GetFactories()->count() - 1); |
119 | const GrXPFactory* xpf = (*GetFactories())[idx]->fGetProc(data); |
120 | SkASSERT(xpf); |
121 | return xpf; |
122 | } |
123 | |
124 | /* |
125 | * Originally these were both in the processor unit test header, but then it seemed to cause linker |
126 | * problems on android. |
127 | */ |
128 | template <> |
129 | SkTArray<GrFragmentProcessorTestFactory*, true>* GrFragmentProcessorTestFactory::GetFactories() { |
130 | static SkTArray<GrFragmentProcessorTestFactory*, true> gFactories; |
131 | return &gFactories; |
132 | } |
133 | |
134 | template <> |
135 | SkTArray<GrGeometryProcessorTestFactory*, true>* GrGeometryProcessorTestFactory::GetFactories() { |
136 | static SkTArray<GrGeometryProcessorTestFactory*, true> gFactories; |
137 | return &gFactories; |
138 | } |
139 | |
140 | SkTArray<GrXPFactoryTestFactory*, true>* GrXPFactoryTestFactory::GetFactories() { |
141 | static SkTArray<GrXPFactoryTestFactory*, true> gFactories; |
142 | return &gFactories; |
143 | } |
144 | |
145 | /* |
146 | * To ensure we always have successful static initialization, before creating from the factories |
147 | * we verify the count is as expected. If a new factory is added, then these numbers must be |
148 | * manually adjusted. |
149 | */ |
150 | static constexpr int kFPFactoryCount = 37; |
151 | static constexpr int kGPFactoryCount = 14; |
152 | static constexpr int kXPFactoryCount = 4; |
153 | |
154 | template <> void GrFragmentProcessorTestFactory::VerifyFactoryCount() { |
155 | if (kFPFactoryCount != GetFactories()->count()) { |
156 | SkDebugf("\nExpected %d fragment processor factories, found %d.\n" , kFPFactoryCount, |
157 | GetFactories()->count()); |
158 | SK_ABORT("Wrong number of fragment processor factories!" ); |
159 | } |
160 | } |
161 | |
162 | template <> void GrGeometryProcessorTestFactory::VerifyFactoryCount() { |
163 | if (kGPFactoryCount != GetFactories()->count()) { |
164 | SkDebugf("\nExpected %d geometry processor factories, found %d.\n" , kGPFactoryCount, |
165 | GetFactories()->count()); |
166 | SK_ABORT("Wrong number of geometry processor factories!" ); |
167 | } |
168 | } |
169 | |
170 | void GrXPFactoryTestFactory::VerifyFactoryCount() { |
171 | if (kXPFactoryCount != GetFactories()->count()) { |
172 | SkDebugf("\nExpected %d xp factory factories, found %d.\n" , kXPFactoryCount, |
173 | GetFactories()->count()); |
174 | SK_ABORT("Wrong number of xp factory factories!" ); |
175 | } |
176 | } |
177 | |
178 | std::unique_ptr<GrFragmentProcessor> GrProcessorUnitTest::MakeChildFP(GrProcessorTestData* data) { |
179 | std::unique_ptr<GrFragmentProcessor> fp; |
180 | |
181 | ++data->fCurrentTreeDepth; |
182 | if (data->fCurrentTreeDepth > data->fMaxTreeDepth) { |
183 | // We've gone too deep, but we can't necessarily return null without risking an assertion. |
184 | // Instead, return a known-simple zero-child FP. This limits the recursion, and the |
185 | // generated FP will be rejected by the numNonNullChildProcessors check below. |
186 | fp = GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT); |
187 | } else { |
188 | for (;;) { |
189 | fp = GrFragmentProcessorTestFactory::Make(data); |
190 | SkASSERT(fp); |
191 | // If our tree has already reached its max depth, we must reject FPs that have children. |
192 | if (data->fCurrentTreeDepth < data->fMaxTreeDepth || |
193 | fp->numNonNullChildProcessors() == 0) { |
194 | break; |
195 | } |
196 | } |
197 | } |
198 | |
199 | --data->fCurrentTreeDepth; |
200 | return fp; |
201 | } |
202 | |
203 | std::unique_ptr<GrFragmentProcessor> GrProcessorUnitTest::MakeOptionalChildFP( |
204 | GrProcessorTestData* data) { |
205 | return data->fRandom->nextBool() ? MakeChildFP(data) : nullptr; |
206 | } |
207 | |
208 | template class GrProcessorTestFactory<GrGeometryProcessor*>; |
209 | template class GrProcessorTestFactory<std::unique_ptr<GrFragmentProcessor>>; |
210 | |
211 | #endif |
212 | |