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 "../private/SkTArray.h"
12 #include "GrTestUtils.h"
13 #include "SkTypes.h"
14 
15 class SkMatrix;
16 class GrCaps;
17 class GrContext;
18 class GrRenderTarget;
19 struct GrProcessorTestData;
20 
21 namespace GrProcessorUnitTest {
22 
23 // Used to access the dummy textures in TestCreate procs.
24 enum {
25     kSkiaPMTextureIdx = 0,
26     kAlphaTextureIdx = 1,
27 };
28 
29 /** This allows parent FPs to implement a test create with known leaf children in order to avoid
30 creating an unbounded FP tree which may overflow various shader limits. */
31 const GrFragmentProcessor* CreateChildFP(GrProcessorTestData*);
32 
33 }
34 
35 /*
36  * GrProcessorTestData is an argument struct to TestCreate functions
37  * fTextures are valid textures that can optionally be used to construct
38  * GrTextureAccesses. The first texture has config kSkia8888_GrPixelConfig and the second has
39  * kAlpha_8_GrPixelConfig. TestCreate functions are also free to create additional textures using
40  * the GrContext.
41  */
42 struct GrProcessorTestData {
GrProcessorTestDataGrProcessorTestData43     GrProcessorTestData(SkRandom* random,
44                         GrContext* context,
45                         const GrCaps* caps,
46                         const GrRenderTarget* rt,
47                         GrTexture* textures[2])
48         : fRandom(random)
49         , fContext(context)
50         , fCaps(caps)
51         , fRenderTarget(rt) {
52         fTextures[0] = textures[0];
53         fTextures[1] = textures[1];
54     }
55     SkRandom* fRandom;
56     GrContext* fContext;
57     const GrCaps* fCaps;
58     const GrRenderTarget* fRenderTarget;
59     GrTexture* fTextures[2];
60 };
61 
62 #if SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
63 
64 class GrProcessor;
65 class GrTexture;
66 
67 template <class Processor> class GrProcessorTestFactory : SkNoncopyable {
68 public:
69     typedef const Processor* (*CreateProc)(GrProcessorTestData*);
70 
GrProcessorTestFactory(CreateProc createProc)71     GrProcessorTestFactory(CreateProc createProc) {
72         fCreateProc = createProc;
73         GetFactories()->push_back(this);
74     }
75 
76     /** Pick a random factory function and create a processor.  */
Create(GrProcessorTestData * data)77     static const Processor* Create(GrProcessorTestData* data) {
78         VerifyFactoryCount();
79         SkASSERT(GetFactories()->count());
80         uint32_t idx = data->fRandom->nextRangeU(0, GetFactories()->count() - 1);
81         return CreateIdx(idx, data);
82     }
83 
84     /** Number of registered factory functions */
Count()85     static int Count() { return GetFactories()->count(); }
86 
87     /** Use factory function at Index idx to create a processor. */
CreateIdx(int idx,GrProcessorTestData * data)88     static const Processor* CreateIdx(int idx, GrProcessorTestData* data) {
89         GrProcessorTestFactory<Processor>* factory = (*GetFactories())[idx];
90         return factory->fCreateProc(data);
91     }
92 
93     /*
94      * A test function which verifies the count of factories.
95      */
96     static void VerifyFactoryCount();
97 
98 private:
99     CreateProc fCreateProc;
100 
101     static SkTArray<GrProcessorTestFactory<Processor>*, true>* GetFactories();
102 };
103 
104 /** GrProcessor subclasses should insert this macro in their declaration to be included in the
105  *  program generation unit test.
106  */
107 #define GR_DECLARE_GEOMETRY_PROCESSOR_TEST                                                         \
108     static GrProcessorTestFactory<GrGeometryProcessor> gTestFactory SK_UNUSED;                     \
109     static const GrGeometryProcessor* TestCreate(GrProcessorTestData*)
110 
111 #define GR_DECLARE_FRAGMENT_PROCESSOR_TEST                                                         \
112     static GrProcessorTestFactory<GrFragmentProcessor> gTestFactory SK_UNUSED;                     \
113     static const GrFragmentProcessor* TestCreate(GrProcessorTestData*)
114 
115 #define GR_DECLARE_XP_FACTORY_TEST                                                                 \
116     static GrProcessorTestFactory<GrXPFactory> gTestFactory SK_UNUSED;                             \
117     static const GrXPFactory* TestCreate(GrProcessorTestData*)
118 
119 /** GrProcessor subclasses should insert this macro in their implementation file. They must then
120  *  also implement this static function:
121  *      GrProcessor* TestCreate(GrProcessorTestData*);
122  */
123 #define GR_DEFINE_FRAGMENT_PROCESSOR_TEST(Effect)                                                  \
124     GrProcessorTestFactory<GrFragmentProcessor> Effect :: gTestFactory(Effect :: TestCreate)
125 
126 #define GR_DEFINE_XP_FACTORY_TEST(Factory)                                                         \
127     GrProcessorTestFactory<GrXPFactory> Factory :: gTestFactory(Factory :: TestCreate)
128 
129 #define GR_DEFINE_GEOMETRY_PROCESSOR_TEST(Effect)                                                  \
130     GrProcessorTestFactory<GrGeometryProcessor> Effect :: gTestFactory(Effect :: TestCreate)
131 
132 #else // !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
133 
134 // The unit test relies on static initializers. Just declare the TestCreate function so that
135 // its definitions will compile.
136 #define GR_DECLARE_FRAGMENT_PROCESSOR_TEST                                                         \
137     static const GrFragmentProcessor* TestCreate(GrProcessorTestData*)
138 #define GR_DEFINE_FRAGMENT_PROCESSOR_TEST(X)
139 
140 // The unit test relies on static initializers. Just declare the TestCreate function so that
141 // its definitions will compile.
142 #define GR_DECLARE_XP_FACTORY_TEST                                                                 \
143     static const GrXPFactory* TestCreate(GrProcessorTestData*)
144 #define GR_DEFINE_XP_FACTORY_TEST(X)
145 
146 // The unit test relies on static initializers. Just declare the TestCreate function so that
147 // its definitions will compile.
148 #define GR_DECLARE_GEOMETRY_PROCESSOR_TEST                                                         \
149     static const GrGeometryProcessor* TestCreate(GrProcessorTestData*)
150 #define GR_DEFINE_GEOMETRY_PROCESSOR_TEST(X)
151 
152 #endif // !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
153 #endif
154