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