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