blob: bf7ddd18e25e3db91d898b09cf37f02f3b2d9c89 [file] [log] [blame]
bsalomon506c8022015-09-14 13:16:26 -07001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/gpu/GrProcessorUnitTest.h"
bsalomon506c8022015-09-14 13:16:26 -07009
John Stilesfbd050b2020-08-03 13:21:46 -040010#include <memory>
11
Robert Phillips4e105e22020-07-16 09:18:50 -040012#include "include/gpu/GrRecordingContext.h"
Brian Salomon766098d2019-12-18 10:41:58 -050013#include "src/gpu/GrFragmentProcessor.h"
Robert Phillips4e105e22020-07-16 09:18:50 -040014#include "src/gpu/GrRecordingContextPriv.h"
Robert Phillipscc44feb2021-07-06 12:21:37 -040015#include "src/gpu/GrSurfaceProxyView.h"
Brian Salomon766098d2019-12-18 10:41:58 -050016
Hal Canary6f6961e2017-01-31 13:50:44 -050017#if GR_TEST_UTILS
18
John Stileseac4ad72020-07-17 15:46:20 -040019class GrGeometryProcessor;
20
John Stiles6609cb62020-07-17 14:52:12 -040021GrProcessorTestData::GrProcessorTestData(SkRandom* random, GrRecordingContext* context,
John Stiles87d0a2f2020-08-10 13:12:41 -040022 int maxTreeDepth, int numViews, const ViewInfo views[])
23 : GrProcessorTestData(random, context, maxTreeDepth, numViews, views,
24 /*inputFP=*/nullptr) {}
John Stiles278b4a62020-07-17 16:44:49 -040025
26GrProcessorTestData::GrProcessorTestData(SkRandom* random, GrRecordingContext* context,
John Stiles87d0a2f2020-08-10 13:12:41 -040027 int maxTreeDepth, int numViews, const ViewInfo views[],
John Stiles6609cb62020-07-17 14:52:12 -040028 std::unique_ptr<GrFragmentProcessor> inputFP)
John Stiles87d0a2f2020-08-10 13:12:41 -040029 : fRandom(random)
30 , fMaxTreeDepth(maxTreeDepth)
31 , fContext(context)
32 , fInputFP(std::move(inputFP)) {
Greg Daniel026a60c2020-02-12 10:53:51 -050033 fViews.reset(views, numViews);
John Stilesfbd050b2020-08-03 13:21:46 -040034 fArena = std::make_unique<SkArenaAlloc>(1000);
Brian Salomon766098d2019-12-18 10:41:58 -050035}
36
John Stilese911ce52020-07-17 13:32:27 -040037GrProcessorTestData::~GrProcessorTestData() {}
Brian Salomon766098d2019-12-18 10:41:58 -050038
39GrProxyProvider* GrProcessorTestData::proxyProvider() { return fContext->priv().proxyProvider(); }
40
41const GrCaps* GrProcessorTestData::caps() { return fContext->priv().caps(); }
42
John Stiles87d0a2f2020-08-10 13:12:41 -040043std::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}
John Stiles6609cb62020-07-17 14:52:12 -040052
Greg Daniel026a60c2020-02-12 10:53:51 -050053GrProcessorTestData::ViewInfo GrProcessorTestData::randomView() {
54 SkASSERT(!fViews.empty());
55 return fViews[fRandom->nextULessThan(fViews.count())];
Brian Salomon766098d2019-12-18 10:41:58 -050056}
57
Greg Daniel026a60c2020-02-12 10:53:51 -050058GrProcessorTestData::ViewInfo GrProcessorTestData::randomAlphaOnlyView() {
Brian Salomon766098d2019-12-18 10:41:58 -050059 int numAlphaOnly = 0;
Greg Daniel026a60c2020-02-12 10:53:51 -050060 for (const auto& [v, ct, at] : fViews) {
Brian Salomon766098d2019-12-18 10:41:58 -050061 if (GrColorTypeIsAlphaOnly(ct)) {
62 ++numAlphaOnly;
63 }
64 }
65 SkASSERT(numAlphaOnly);
66 int idx = fRandom->nextULessThan(numAlphaOnly);
Greg Daniel026a60c2020-02-12 10:53:51 -050067 for (const auto& [v, ct, at] : fViews) {
Brian Salomon766098d2019-12-18 10:41:58 -050068 if (GrColorTypeIsAlphaOnly(ct) && !idx--) {
Greg Daniel026a60c2020-02-12 10:53:51 -050069 return {v, ct, at};
Brian Salomon766098d2019-12-18 10:41:58 -050070 }
71 }
72 SkUNREACHABLE;
73}
74
John Stileseac4ad72020-07-17 15:46:20 -040075template <class ProcessorSmartPtr>
John Stiles7c7a7e52020-07-24 17:03:04 -040076GrProcessorTestFactory<ProcessorSmartPtr>::GrProcessorTestFactory(MakeProc makeProc,
77 const char* name)
78 : fMakeProc(makeProc), fName(name) {
John Stileseac4ad72020-07-17 15:46:20 -040079 GetFactories()->push_back(this);
80}
81
82template <class ProcessorSmartPtr>
83ProcessorSmartPtr 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
92template <class ProcessorSmartPtr>
93ProcessorSmartPtr 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);
John Stiles7c7a7e52020-07-24 17:03:04 -040098 if (processor == nullptr) {
99 SK_ABORT("%s: TestCreate returned null", factory->fName.c_str());
100 }
John Stileseac4ad72020-07-17 15:46:20 -0400101 return processor;
102}
103
104template <class ProcessorSmartPtr>
105int GrProcessorTestFactory<ProcessorSmartPtr>::Count() {
106 return GetFactories()->count();
107}
108
109GrXPFactoryTestFactory::GrXPFactoryTestFactory(GetFn* getProc) : fGetProc(getProc) {
110 GetFactories()->push_back(this);
111}
112
113const 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}
Brian Salomon766098d2019-12-18 10:41:58 -0500123
124/*
125 * Originally these were both in the processor unit test header, but then it seemed to cause linker
126 * problems on android.
127 */
128template <>
129SkTArray<GrFragmentProcessorTestFactory*, true>* GrFragmentProcessorTestFactory::GetFactories() {
130 static SkTArray<GrFragmentProcessorTestFactory*, true> gFactories;
131 return &gFactories;
132}
133
134template <>
135SkTArray<GrGeometryProcessorTestFactory*, true>* GrGeometryProcessorTestFactory::GetFactories() {
136 static SkTArray<GrGeometryProcessorTestFactory*, true> gFactories;
137 return &gFactories;
138}
139
140SkTArray<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 */
Brian Osmane9ab3912021-07-02 10:17:45 -0400150static constexpr int kFPFactoryCount = 17;
John Stileseac4ad72020-07-17 15:46:20 -0400151static constexpr int kGPFactoryCount = 14;
152static constexpr int kXPFactoryCount = 4;
Brian Salomon766098d2019-12-18 10:41:58 -0500153
154template <> 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
162template <> 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
170void 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
Brian Salomonaff329b2017-08-11 09:40:37 -0400178std::unique_ptr<GrFragmentProcessor> GrProcessorUnitTest::MakeChildFP(GrProcessorTestData* data) {
Brian Salomonaff329b2017-08-11 09:40:37 -0400179 std::unique_ptr<GrFragmentProcessor> fp;
John Stiles87d0a2f2020-08-10 13:12:41 -0400180
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.
Brian Salomon354147a2021-04-14 11:15:05 -0400186 fp = GrFragmentProcessor::MakeColor(SK_PMColor4fTRANSPARENT);
John Stiles87d0a2f2020-08-10 13:12:41 -0400187 } 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;
bungeman06ca8ec2016-06-09 08:01:03 -0700200 return fp;
bsalomon506c8022015-09-14 13:16:26 -0700201}
John Stileseac4ad72020-07-17 15:46:20 -0400202
John Stiles87d0a2f2020-08-10 13:12:41 -0400203std::unique_ptr<GrFragmentProcessor> GrProcessorUnitTest::MakeOptionalChildFP(
204 GrProcessorTestData* data) {
205 return data->fRandom->nextBool() ? MakeChildFP(data) : nullptr;
206}
207
John Stileseac4ad72020-07-17 15:46:20 -0400208template class GrProcessorTestFactory<GrGeometryProcessor*>;
209template class GrProcessorTestFactory<std::unique_ptr<GrFragmentProcessor>>;
210
Hal Canary6f6961e2017-01-31 13:50:44 -0500211#endif