/* * Copyright 2012 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef GrProcessorUnitTest_DEFINED #define GrProcessorUnitTest_DEFINED #include "SkTypes.h" #if GR_TEST_UTILS #include "../private/GrTextureProxy.h" #include "../private/SkTArray.h" #include "GrTestUtils.h" class SkMatrix; class GrCaps; class GrContext; class GrProxyProvider; class GrRenderTargetContext; struct GrProcessorTestData; class GrTexture; class GrXPFactory; class GrGeometryProcessor; namespace GrProcessorUnitTest { // Used to access the dummy textures in TestCreate procs. enum { kSkiaPMTextureIdx = 0, kAlphaTextureIdx = 1, }; /** This allows parent FPs to implement a test create with known leaf children in order to avoid creating an unbounded FP tree which may overflow various shader limits. */ std::unique_ptr<GrFragmentProcessor> MakeChildFP(GrProcessorTestData*); } /* * GrProcessorTestData is an argument struct to TestCreate functions * fTextures are valid textures that can optionally be used to construct * TextureSampler. The first texture has config kSkia8888_GrPixelConfig and the second has * kAlpha_8_GrPixelConfig. TestCreate functions are also free to create additional textures using * the GrContext. */ struct GrProcessorTestData { GrProcessorTestData(SkRandom* random, GrContext* context, const GrRenderTargetContext* renderTargetContext, sk_sp<GrTextureProxy> proxies[2]) : fRandom(random) , fRenderTargetContext(renderTargetContext) , fContext(context) { SkASSERT(proxies[0] && proxies[1]); fProxies[0] = proxies[0]; fProxies[1] = proxies[1]; } SkRandom* fRandom; const GrRenderTargetContext* fRenderTargetContext; GrContext* context() { return fContext; } GrResourceProvider* resourceProvider(); GrProxyProvider* proxyProvider(); const GrCaps* caps(); sk_sp<GrTextureProxy> textureProxy(int index) { return fProxies[index]; } private: GrContext* fContext; sk_sp<GrTextureProxy> fProxies[2]; }; #if SK_ALLOW_STATIC_GLOBAL_INITIALIZERS class GrProcessor; class GrTexture; template <class ProcessorSmartPtr> class GrProcessorTestFactory : private SkNoncopyable { public: using Processor = typename ProcessorSmartPtr::element_type; using MakeProc = ProcessorSmartPtr (*)(GrProcessorTestData*); GrProcessorTestFactory(MakeProc makeProc) { fMakeProc = makeProc; GetFactories()->push_back(this); } /** Pick a random factory function and create a processor. */ static ProcessorSmartPtr Make(GrProcessorTestData* data) { VerifyFactoryCount(); SkASSERT(GetFactories()->count()); uint32_t idx = data->fRandom->nextRangeU(0, GetFactories()->count() - 1); return MakeIdx(idx, data); } /** Number of registered factory functions */ static int Count() { return GetFactories()->count(); } /** Use factory function at Index idx to create a processor. */ static ProcessorSmartPtr MakeIdx(int idx, GrProcessorTestData* data) { GrProcessorTestFactory<ProcessorSmartPtr>* factory = (*GetFactories())[idx]; ProcessorSmartPtr processor = factory->fMakeProc(data); SkASSERT(processor); return processor; } private: /** * A test function which verifies the count of factories. */ static void VerifyFactoryCount(); MakeProc fMakeProc; static SkTArray<GrProcessorTestFactory<ProcessorSmartPtr>*, true>* GetFactories(); }; using GrFragmentProcessorTestFactory = GrProcessorTestFactory<std::unique_ptr<GrFragmentProcessor>>; using GrGeometryProcessorTestFactory = GrProcessorTestFactory<sk_sp<GrGeometryProcessor>>; class GrXPFactoryTestFactory : private SkNoncopyable { public: using GetFn = const GrXPFactory*(GrProcessorTestData*); GrXPFactoryTestFactory(GetFn* getProc) : fGetProc(getProc) { GetFactories()->push_back(this); } static const GrXPFactory* Get(GrProcessorTestData* data) { VerifyFactoryCount(); SkASSERT(GetFactories()->count()); uint32_t idx = data->fRandom->nextRangeU(0, GetFactories()->count() - 1); const GrXPFactory* xpf = (*GetFactories())[idx]->fGetProc(data); SkASSERT(xpf); return xpf; } private: static void VerifyFactoryCount(); GetFn* fGetProc; static SkTArray<GrXPFactoryTestFactory*, true>* GetFactories(); }; /** GrProcessor subclasses should insert this macro in their declaration to be included in the * program generation unit test. */ #define GR_DECLARE_GEOMETRY_PROCESSOR_TEST \ static GrGeometryProcessorTestFactory gTestFactory SK_UNUSED; \ static sk_sp<GrGeometryProcessor> TestCreate(GrProcessorTestData*); #define GR_DECLARE_FRAGMENT_PROCESSOR_TEST \ static GrFragmentProcessorTestFactory gTestFactory SK_UNUSED; \ static std::unique_ptr<GrFragmentProcessor> TestCreate(GrProcessorTestData*); #define GR_DECLARE_XP_FACTORY_TEST \ static GrXPFactoryTestFactory gTestFactory SK_UNUSED; \ static const GrXPFactory* TestGet(GrProcessorTestData*); /** GrProcessor subclasses should insert this macro in their implementation file. They must then * also implement this static function: * GrProcessor* TestCreate(GrProcessorTestData*); */ #define GR_DEFINE_FRAGMENT_PROCESSOR_TEST(Effect) \ GrFragmentProcessorTestFactory Effect::gTestFactory(Effect::TestCreate) #define GR_DEFINE_GEOMETRY_PROCESSOR_TEST(Effect) \ GrGeometryProcessorTestFactory Effect::gTestFactory(Effect::TestCreate) #define GR_DEFINE_XP_FACTORY_TEST(Factory) \ GrXPFactoryTestFactory Factory::gTestFactory(Factory::TestGet) #else // !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS // The unit test relies on static initializers. Just declare the TestCreate function so that // its definitions will compile. #define GR_DECLARE_FRAGMENT_PROCESSOR_TEST \ static std::unique_ptr<GrFragmentProcessor> TestCreate(GrProcessorTestData*); #define GR_DEFINE_FRAGMENT_PROCESSOR_TEST(X) // The unit test relies on static initializers. Just declare the TestCreate function so that // its definitions will compile. #define GR_DECLARE_GEOMETRY_PROCESSOR_TEST \ static sk_sp<GrGeometryProcessor> TestCreate(GrProcessorTestData*); #define GR_DEFINE_GEOMETRY_PROCESSOR_TEST(X) // The unit test relies on static initializers. Just declare the TestGet function so that // its definitions will compile. #define GR_DECLARE_XP_FACTORY_TEST \ const GrXPFactory* TestGet(GrProcessorTestData*); #define GR_DEFINE_XP_FACTORY_TEST(X) #endif // !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS #else // GR_TEST_UTILS #define GR_DECLARE_GEOMETRY_PROCESSOR_TEST #define GR_DECLARE_FRAGMENT_PROCESSOR_TEST #define GR_DECLARE_XP_FACTORY_TEST #define GR_DEFINE_FRAGMENT_PROCESSOR_TEST(...) #define GR_DEFINE_GEOMETRY_PROCESSOR_TEST(...) #define GR_DEFINE_XP_FACTORY_TEST(...) #define GR_DECLARE_FRAGMENT_PROCESSOR_TEST #define GR_DEFINE_FRAGMENT_PROCESSOR_TEST(...) #define GR_DECLARE_GEOMETRY_PROCESSOR_TEST #define GR_DEFINE_GEOMETRY_PROCESSOR_TEST(...) #define GR_DECLARE_XP_FACTORY_TEST #define GR_DEFINE_XP_FACTORY_TEST(...) #endif // GR_TEST_UTILS #endif // GrProcessorUnitTest_DEFINED