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 "SkRandom.h"
12#include "SkTArray.h"
13#include "SkTypes.h"
14
15class SkMatrix;
16class GrDrawTargetCaps;
17
18namespace GrProcessorUnitTest {
19// Used to access the dummy textures in TestCreate procs.
20enum {
21    kSkiaPMTextureIdx = 0,
22    kAlphaTextureIdx = 1,
23};
24
25/**
26 * A helper for use in GrProcessor::TestCreate functions.
27 */
28const SkMatrix& TestMatrix(SkRandom*);
29
30}
31
32#if SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
33
34class GrContext;
35class GrProcessor;
36class GrTexture;
37
38template <class Processor>
39class GrProcessorTestFactory : SkNoncopyable {
40public:
41
42    typedef Processor* (*CreateProc)(SkRandom*,
43                                    GrContext*,
44                                    const GrDrawTargetCaps& caps,
45                                    GrTexture* dummyTextures[]);
46
47    GrProcessorTestFactory(CreateProc createProc) {
48        fCreateProc = createProc;
49        GetFactories()->push_back(this);
50    }
51
52    static Processor* CreateStage(SkRandom* random,
53                                 GrContext* context,
54                                 const GrDrawTargetCaps& caps,
55                                 GrTexture* dummyTextures[]) {
56        uint32_t idx = random->nextRangeU(0, GetFactories()->count() - 1);
57        GrProcessorTestFactory<Processor>* factory = (*GetFactories())[idx];
58        return factory->fCreateProc(random, context, caps, dummyTextures);
59    }
60
61private:
62    CreateProc fCreateProc;
63
64    #if SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
65    static SkTArray<GrProcessorTestFactory<Processor>*, true>* GetFactories() {
66        static SkTArray<GrProcessorTestFactory<Processor>*, true> gFactories;
67        return &gFactories;
68    }
69    #endif
70};
71
72/** GrProcessor subclasses should insert this macro in their declaration to be included in the
73 *  program generation unit test.
74 */
75
76#define GR_DECLARE_GEOMETRY_PROCESSOR_TEST                                                         \
77    static GrProcessorTestFactory<GrGeometryProcessor> gTestFactory;                               \
78    static GrGeometryProcessor* TestCreate(SkRandom*,                                              \
79                                GrContext*,                                                        \
80                                const GrDrawTargetCaps&,                                           \
81                                GrTexture* dummyTextures[2])
82
83#define GR_DECLARE_FRAGMENT_PROCESSOR_TEST                                                         \
84    static GrProcessorTestFactory<GrFragmentProcessor> gTestFactory;                               \
85    static GrFragmentProcessor* TestCreate(SkRandom*,                                              \
86                                GrContext*,                                                        \
87                                const GrDrawTargetCaps&,                                           \
88                                GrTexture* dummyTextures[2])
89
90/** GrProcessor subclasses should insert this macro in their implementation file. They must then
91 *  also implement this static function:
92 *      GrProcessor* TestCreate(SkRandom*,
93 *                           GrContext*,
94 *                           const GrDrawTargetCaps&,
95 *                           GrTexture* dummyTextures[2]);
96 * dummyTextures[] are valid textures that can optionally be used to construct GrTextureAccesses.
97 * The first texture has config kSkia8888_GrPixelConfig and the second has
98 * kAlpha_8_GrPixelConfig. TestCreate functions are also free to create additional textures using
99 * the GrContext.
100 */
101#define GR_DEFINE_FRAGMENT_PROCESSOR_TEST(Effect)                                                  \
102    GrProcessorTestFactory<GrFragmentProcessor> Effect :: gTestFactory(Effect :: TestCreate)
103
104#define GR_DEFINE_GEOMETRY_PROCESSOR_TEST(Effect)                                                  \
105    GrProcessorTestFactory<GrGeometryProcessor> Effect :: gTestFactory(Effect :: TestCreate)
106
107#else // !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
108
109// The unit test relies on static initializers. Just declare the TestCreate function so that
110// its definitions will compile.
111#define GR_DECLARE_FRAGMENT_PROCESSOR_TEST                                                         \
112    static GrFragmentProcessor* TestCreate(SkRandom*,                                              \
113                                GrContext*,                                                        \
114                                const GrDrawTargetCaps&,                                           \
115                                GrTexture* dummyTextures[2])
116#define GR_DEFINE_FRAGMENT_PROCESSOR_TEST(X)
117
118// The unit test relies on static initializers. Just declare the TestCreate function so that
119// its definitions will compile.
120#define GR_DECLARE_GEOMETRY_PROCESSOR_TEST                                                         \
121    static GrGeometryProcessor* TestCreate(SkRandom*,                                              \
122                                GrContext*,                                                        \
123                                const GrDrawTargetCaps&,                                           \
124                                GrTexture* dummyTextures[2])
125#define GR_DEFINE_GEOMETRY_PROCESSOR_TEST(X)
126
127#endif // !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
128#endif
129