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