/* * 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 "include/core/SkTypes.h" #if GR_TEST_UTILS #include "include/private/SkTArray.h" #include "src/core/SkArenaAlloc.h" #include "src/gpu/GrTestUtils.h" #include "src/gpu/GrTextureProxy.h" #include class SkMatrix; class GrCaps; class GrProxyProvider; class GrProcessorTestData; class GrTexture; class GrXPFactory; class GrGeometryProcessor; namespace GrProcessorUnitTest { /** 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. * MakeOptionalChildFP is the same as MakeChildFP, but can return null. */ std::unique_ptr MakeChildFP(GrProcessorTestData*); std::unique_ptr MakeOptionalChildFP(GrProcessorTestData*); } // namespace GrProcessorUnitTest /** GrProcessorTestData is an argument struct to TestCreate functions * fTextures are valid textures that can optionally be used to construct * TextureSampler. The first texture has a RGBA8 format and the second has Alpha8 format for the * specific backend API. TestCreate functions are also free to create additional textures using * the GrContext. */ class GrProcessorTestData { public: using ViewInfo = std::tuple; GrProcessorTestData(SkRandom* random, GrRecordingContext* context, int maxTreeDepth, int numViews, const ViewInfo views[]); GrProcessorTestData(SkRandom* random, GrRecordingContext* context, int maxTreeDepth, int numViews, const ViewInfo views[], std::unique_ptr inputFP); GrProcessorTestData(const GrProcessorTestData&) = delete; ~GrProcessorTestData(); GrRecordingContext* context() { return fContext; } GrProxyProvider* proxyProvider(); const GrCaps* caps(); SkArenaAlloc* allocator() { return fArena.get(); } std::unique_ptr inputFP(); ViewInfo randomView(); ViewInfo randomAlphaOnlyView(); SkRandom* fRandom; int fCurrentTreeDepth = 0; int fMaxTreeDepth = 1; private: GrRecordingContext* fContext; SkTArray fViews; std::unique_ptr fArena; std::unique_ptr fInputFP; }; class GrProcessor; class GrTexture; template class GrProcessorTestFactory : private SkNoncopyable { public: using MakeProc = ProcessorSmartPtr (*)(GrProcessorTestData*); GrProcessorTestFactory(MakeProc makeProc, const char* name); /** Pick a random factory function and create a processor. */ static ProcessorSmartPtr Make(GrProcessorTestData* data); /** Use factory function at Index idx to create a processor. */ static ProcessorSmartPtr MakeIdx(int idx, GrProcessorTestData* data); /** Number of registered factory functions */ static int Count(); private: /** A test function which verifies the count of factories. */ static void VerifyFactoryCount(); static SkTArray*, true>* GetFactories(); MakeProc fMakeProc; SkString fName; }; using GrFragmentProcessorTestFactory = GrProcessorTestFactory>; using GrGeometryProcessorTestFactory = GrProcessorTestFactory; class GrXPFactoryTestFactory : private SkNoncopyable { public: using GetFn = const GrXPFactory*(GrProcessorTestData*); GrXPFactoryTestFactory(GetFn* getProc); static const GrXPFactory* Get(GrProcessorTestData* data); private: /** A test function which verifies the count of factories. */ static void VerifyFactoryCount(); static SkTArray* GetFactories(); GetFn* fGetProc; }; #if SK_ALLOW_STATIC_GLOBAL_INITIALIZERS /** 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 GrGeometryProcessor* TestCreate(GrProcessorTestData*); #define GR_DECLARE_FRAGMENT_PROCESSOR_TEST \ static GrFragmentProcessorTestFactory gTestFactory SK_UNUSED; \ static std::unique_ptr 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, #Effect) #define GR_DEFINE_GEOMETRY_PROCESSOR_TEST(Effect) \ GrGeometryProcessorTestFactory Effect::gTestFactory(Effect::TestCreate, #Effect) #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 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 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