1/*
2 * Copyright 2012 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#ifndef GrProcessorUnitTest_DEFINED
9#define GrProcessorUnitTest_DEFINED
10
11#include "include/core/SkTypes.h"
12
13#if GR_TEST_UTILS
14
15#include "include/private/SkTArray.h"
16#include "src/core/SkArenaAlloc.h"
17#include "src/gpu/GrTestUtils.h"
18#include "src/gpu/GrTextureProxy.h"
19
20#include <tuple>
21
22class SkMatrix;
23class GrCaps;
24class GrContext;
25class GrProxyProvider;
26class GrRenderTargetContext;
27class GrProcessorTestData;
28class GrTexture;
29class GrXPFactory;
30class GrGeometryProcessor;
31
32namespace GrProcessorUnitTest {
33
34// Used to access the dummy textures in TestCreate procs.
35enum {
36 kSkiaPMTextureIdx = 0,
37 kAlphaTextureIdx = 1,
38};
39
40/** This allows parent FPs to implement a test create with known leaf children in order to avoid
41creating an unbounded FP tree which may overflow various shader limits. */
42std::unique_ptr<GrFragmentProcessor> MakeChildFP(GrProcessorTestData*);
43
44}
45
46/*
47 * GrProcessorTestData is an argument struct to TestCreate functions
48 * fTextures are valid textures that can optionally be used to construct
49 * TextureSampler. The first texture has a RGBA8 format and the second has Alpha8 format for the
50 * specific backend API. TestCreate functions are also free to create additional textures using
51 * the GrContext.
52 */
53class GrProcessorTestData {
54public:
55 using ViewInfo = std::tuple<GrSurfaceProxyView, GrColorType, SkAlphaType>;
56 GrProcessorTestData(SkRandom* random, GrContext* context, int numProxies, const ViewInfo[]);
57
58 GrContext* context() { return fContext; }
59 GrResourceProvider* resourceProvider();
60 GrProxyProvider* proxyProvider();
61 const GrCaps* caps();
62 SkArenaAlloc* allocator() { return fArena.get(); }
63
64 ViewInfo randomView();
65 ViewInfo randomAlphaOnlyView();
66
67 SkRandom* fRandom;
68
69private:
70 GrContext* fContext;
71 SkTArray<ViewInfo> fViews;
72 std::unique_ptr<SkArenaAlloc> fArena;
73};
74
75class GrProcessor;
76class GrTexture;
77
78template <class ProcessorSmartPtr>
79class GrProcessorTestFactory : private SkNoncopyable {
80public:
81 using MakeProc = ProcessorSmartPtr (*)(GrProcessorTestData*);
82
83 GrProcessorTestFactory(MakeProc makeProc) {
84 fMakeProc = makeProc;
85 GetFactories()->push_back(this);
86 }
87
88 /** Pick a random factory function and create a processor. */
89 static ProcessorSmartPtr Make(GrProcessorTestData* data) {
90 VerifyFactoryCount();
91 if (GetFactories()->count() == 0) {
92 return nullptr;
93 }
94 uint32_t idx = data->fRandom->nextRangeU(0, GetFactories()->count() - 1);
95 return MakeIdx(idx, data);
96 }
97
98 /** Number of registered factory functions */
99 static int Count() { return GetFactories()->count(); }
100
101 /** Use factory function at Index idx to create a processor. */
102 static ProcessorSmartPtr MakeIdx(int idx, GrProcessorTestData* data) {
103 SkASSERT(idx < GetFactories()->count());
104 GrProcessorTestFactory<ProcessorSmartPtr>* factory = (*GetFactories())[idx];
105 ProcessorSmartPtr processor = factory->fMakeProc(data);
106 SkASSERT(processor);
107 return processor;
108 }
109
110private:
111 /**
112 * A test function which verifies the count of factories.
113 */
114 static void VerifyFactoryCount();
115
116 MakeProc fMakeProc;
117
118 static SkTArray<GrProcessorTestFactory<ProcessorSmartPtr>*, true>* GetFactories();
119};
120
121using GrFragmentProcessorTestFactory = GrProcessorTestFactory<std::unique_ptr<GrFragmentProcessor>>;
122using GrGeometryProcessorTestFactory = GrProcessorTestFactory<GrGeometryProcessor*>;
123
124class GrXPFactoryTestFactory : private SkNoncopyable {
125public:
126 using GetFn = const GrXPFactory*(GrProcessorTestData*);
127
128 GrXPFactoryTestFactory(GetFn* getProc) : fGetProc(getProc) { GetFactories()->push_back(this); }
129
130 static const GrXPFactory* Get(GrProcessorTestData* data) {
131 VerifyFactoryCount();
132 if (GetFactories()->count() == 0) {
133 return nullptr;
134 }
135 uint32_t idx = data->fRandom->nextRangeU(0, GetFactories()->count() - 1);
136 const GrXPFactory* xpf = (*GetFactories())[idx]->fGetProc(data);
137 SkASSERT(xpf);
138 return xpf;
139 }
140
141private:
142 static void VerifyFactoryCount();
143
144 GetFn* fGetProc;
145 static SkTArray<GrXPFactoryTestFactory*, true>* GetFactories();
146};
147
148#if SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
149
150/** GrProcessor subclasses should insert this macro in their declaration to be included in the
151 * program generation unit test.
152 */
153#define GR_DECLARE_GEOMETRY_PROCESSOR_TEST \
154 static GrGeometryProcessorTestFactory gTestFactory SK_UNUSED; \
155 static GrGeometryProcessor* TestCreate(GrProcessorTestData*);
156
157#define GR_DECLARE_FRAGMENT_PROCESSOR_TEST \
158 static GrFragmentProcessorTestFactory gTestFactory SK_UNUSED; \
159 static std::unique_ptr<GrFragmentProcessor> TestCreate(GrProcessorTestData*);
160
161#define GR_DECLARE_XP_FACTORY_TEST \
162 static GrXPFactoryTestFactory gTestFactory SK_UNUSED; \
163 static const GrXPFactory* TestGet(GrProcessorTestData*);
164
165/** GrProcessor subclasses should insert this macro in their implementation file. They must then
166 * also implement this static function:
167 * GrProcessor* TestCreate(GrProcessorTestData*);
168 */
169#define GR_DEFINE_FRAGMENT_PROCESSOR_TEST(Effect) \
170 GrFragmentProcessorTestFactory Effect::gTestFactory(Effect::TestCreate)
171
172#define GR_DEFINE_GEOMETRY_PROCESSOR_TEST(Effect) \
173 GrGeometryProcessorTestFactory Effect::gTestFactory(Effect::TestCreate)
174
175#define GR_DEFINE_XP_FACTORY_TEST(Factory) \
176 GrXPFactoryTestFactory Factory::gTestFactory(Factory::TestGet)
177
178#else // !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
179
180// The unit test relies on static initializers. Just declare the TestCreate function so that
181// its definitions will compile.
182#define GR_DECLARE_FRAGMENT_PROCESSOR_TEST \
183 static std::unique_ptr<GrFragmentProcessor> TestCreate(GrProcessorTestData*);
184#define GR_DEFINE_FRAGMENT_PROCESSOR_TEST(X)
185
186// The unit test relies on static initializers. Just declare the TestCreate function so that
187// its definitions will compile.
188#define GR_DECLARE_GEOMETRY_PROCESSOR_TEST \
189 static GrGeometryProcessor* TestCreate(GrProcessorTestData*);
190#define GR_DEFINE_GEOMETRY_PROCESSOR_TEST(X)
191
192// The unit test relies on static initializers. Just declare the TestGet function so that
193// its definitions will compile.
194#define GR_DECLARE_XP_FACTORY_TEST \
195 const GrXPFactory* TestGet(GrProcessorTestData*);
196#define GR_DEFINE_XP_FACTORY_TEST(X)
197
198#endif // !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
199#else // GR_TEST_UTILS
200 #define GR_DECLARE_GEOMETRY_PROCESSOR_TEST
201 #define GR_DECLARE_FRAGMENT_PROCESSOR_TEST
202 #define GR_DECLARE_XP_FACTORY_TEST
203 #define GR_DEFINE_FRAGMENT_PROCESSOR_TEST(...)
204 #define GR_DEFINE_GEOMETRY_PROCESSOR_TEST(...)
205 #define GR_DEFINE_XP_FACTORY_TEST(...)
206 #define GR_DECLARE_FRAGMENT_PROCESSOR_TEST
207 #define GR_DEFINE_FRAGMENT_PROCESSOR_TEST(...)
208 #define GR_DECLARE_GEOMETRY_PROCESSOR_TEST
209 #define GR_DEFINE_GEOMETRY_PROCESSOR_TEST(...)
210 #define GR_DECLARE_XP_FACTORY_TEST
211 #define GR_DEFINE_XP_FACTORY_TEST(...)
212#endif // GR_TEST_UTILS
213#endif // GrProcessorUnitTest_DEFINED
214