• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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