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