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