1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2015 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/gpu/GrProcessorUnitTest.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include <memory> 11cb93a386Sopenharmony_ci 12cb93a386Sopenharmony_ci#include "include/gpu/GrRecordingContext.h" 13cb93a386Sopenharmony_ci#include "src/gpu/GrFragmentProcessor.h" 14cb93a386Sopenharmony_ci#include "src/gpu/GrRecordingContextPriv.h" 15cb93a386Sopenharmony_ci#include "src/gpu/GrSurfaceProxyView.h" 16cb93a386Sopenharmony_ci 17cb93a386Sopenharmony_ci#if GR_TEST_UTILS 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_ciclass GrGeometryProcessor; 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_ciGrProcessorTestData::GrProcessorTestData(SkRandom* random, GrRecordingContext* context, 22cb93a386Sopenharmony_ci int maxTreeDepth, int numViews, const ViewInfo views[]) 23cb93a386Sopenharmony_ci : GrProcessorTestData(random, context, maxTreeDepth, numViews, views, 24cb93a386Sopenharmony_ci /*inputFP=*/nullptr) {} 25cb93a386Sopenharmony_ci 26cb93a386Sopenharmony_ciGrProcessorTestData::GrProcessorTestData(SkRandom* random, GrRecordingContext* context, 27cb93a386Sopenharmony_ci int maxTreeDepth, int numViews, const ViewInfo views[], 28cb93a386Sopenharmony_ci std::unique_ptr<GrFragmentProcessor> inputFP) 29cb93a386Sopenharmony_ci : fRandom(random) 30cb93a386Sopenharmony_ci , fMaxTreeDepth(maxTreeDepth) 31cb93a386Sopenharmony_ci , fContext(context) 32cb93a386Sopenharmony_ci , fInputFP(std::move(inputFP)) { 33cb93a386Sopenharmony_ci fViews.reset(views, numViews); 34cb93a386Sopenharmony_ci fArena = std::make_unique<SkArenaAlloc>(1000); 35cb93a386Sopenharmony_ci} 36cb93a386Sopenharmony_ci 37cb93a386Sopenharmony_ciGrProcessorTestData::~GrProcessorTestData() {} 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_ciGrProxyProvider* GrProcessorTestData::proxyProvider() { return fContext->priv().proxyProvider(); } 40cb93a386Sopenharmony_ci 41cb93a386Sopenharmony_ciconst GrCaps* GrProcessorTestData::caps() { return fContext->priv().caps(); } 42cb93a386Sopenharmony_ci 43cb93a386Sopenharmony_cistd::unique_ptr<GrFragmentProcessor> GrProcessorTestData::inputFP() { 44cb93a386Sopenharmony_ci if (fCurrentTreeDepth == 0) { 45cb93a386Sopenharmony_ci // At the top level of the tree, provide the input FP from the test data. 46cb93a386Sopenharmony_ci return fInputFP ? fInputFP->clone() : nullptr; 47cb93a386Sopenharmony_ci } else { 48cb93a386Sopenharmony_ci // At deeper levels of recursion, synthesize a random input. 49cb93a386Sopenharmony_ci return GrProcessorUnitTest::MakeChildFP(this); 50cb93a386Sopenharmony_ci } 51cb93a386Sopenharmony_ci} 52cb93a386Sopenharmony_ci 53cb93a386Sopenharmony_ciGrProcessorTestData::ViewInfo GrProcessorTestData::randomView() { 54cb93a386Sopenharmony_ci SkASSERT(!fViews.empty()); 55cb93a386Sopenharmony_ci return fViews[fRandom->nextULessThan(fViews.count())]; 56cb93a386Sopenharmony_ci} 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_ciGrProcessorTestData::ViewInfo GrProcessorTestData::randomAlphaOnlyView() { 59cb93a386Sopenharmony_ci int numAlphaOnly = 0; 60cb93a386Sopenharmony_ci for (const auto& [v, ct, at] : fViews) { 61cb93a386Sopenharmony_ci if (GrColorTypeIsAlphaOnly(ct)) { 62cb93a386Sopenharmony_ci ++numAlphaOnly; 63cb93a386Sopenharmony_ci } 64cb93a386Sopenharmony_ci } 65cb93a386Sopenharmony_ci SkASSERT(numAlphaOnly); 66cb93a386Sopenharmony_ci int idx = fRandom->nextULessThan(numAlphaOnly); 67cb93a386Sopenharmony_ci for (const auto& [v, ct, at] : fViews) { 68cb93a386Sopenharmony_ci if (GrColorTypeIsAlphaOnly(ct) && !idx--) { 69cb93a386Sopenharmony_ci return {v, ct, at}; 70cb93a386Sopenharmony_ci } 71cb93a386Sopenharmony_ci } 72cb93a386Sopenharmony_ci SkUNREACHABLE; 73cb93a386Sopenharmony_ci} 74cb93a386Sopenharmony_ci 75cb93a386Sopenharmony_citemplate <class ProcessorSmartPtr> 76cb93a386Sopenharmony_ciGrProcessorTestFactory<ProcessorSmartPtr>::GrProcessorTestFactory(MakeProc makeProc, 77cb93a386Sopenharmony_ci const char* name) 78cb93a386Sopenharmony_ci : fMakeProc(makeProc), fName(name) { 79cb93a386Sopenharmony_ci GetFactories()->push_back(this); 80cb93a386Sopenharmony_ci} 81cb93a386Sopenharmony_ci 82cb93a386Sopenharmony_citemplate <class ProcessorSmartPtr> 83cb93a386Sopenharmony_ciProcessorSmartPtr GrProcessorTestFactory<ProcessorSmartPtr>::Make(GrProcessorTestData* data) { 84cb93a386Sopenharmony_ci VerifyFactoryCount(); 85cb93a386Sopenharmony_ci if (GetFactories()->count() == 0) { 86cb93a386Sopenharmony_ci return nullptr; 87cb93a386Sopenharmony_ci } 88cb93a386Sopenharmony_ci uint32_t idx = data->fRandom->nextULessThan(GetFactories()->count()); 89cb93a386Sopenharmony_ci return MakeIdx(idx, data); 90cb93a386Sopenharmony_ci} 91cb93a386Sopenharmony_ci 92cb93a386Sopenharmony_citemplate <class ProcessorSmartPtr> 93cb93a386Sopenharmony_ciProcessorSmartPtr GrProcessorTestFactory<ProcessorSmartPtr>::MakeIdx(int idx, 94cb93a386Sopenharmony_ci GrProcessorTestData* data) { 95cb93a386Sopenharmony_ci SkASSERT(idx < GetFactories()->count()); 96cb93a386Sopenharmony_ci GrProcessorTestFactory<ProcessorSmartPtr>* factory = (*GetFactories())[idx]; 97cb93a386Sopenharmony_ci ProcessorSmartPtr processor = factory->fMakeProc(data); 98cb93a386Sopenharmony_ci if (processor == nullptr) { 99cb93a386Sopenharmony_ci SK_ABORT("%s: TestCreate returned null", factory->fName.c_str()); 100cb93a386Sopenharmony_ci } 101cb93a386Sopenharmony_ci return processor; 102cb93a386Sopenharmony_ci} 103cb93a386Sopenharmony_ci 104cb93a386Sopenharmony_citemplate <class ProcessorSmartPtr> 105cb93a386Sopenharmony_ciint GrProcessorTestFactory<ProcessorSmartPtr>::Count() { 106cb93a386Sopenharmony_ci return GetFactories()->count(); 107cb93a386Sopenharmony_ci} 108cb93a386Sopenharmony_ci 109cb93a386Sopenharmony_ciGrXPFactoryTestFactory::GrXPFactoryTestFactory(GetFn* getProc) : fGetProc(getProc) { 110cb93a386Sopenharmony_ci GetFactories()->push_back(this); 111cb93a386Sopenharmony_ci} 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_ciconst GrXPFactory* GrXPFactoryTestFactory::Get(GrProcessorTestData* data) { 114cb93a386Sopenharmony_ci VerifyFactoryCount(); 115cb93a386Sopenharmony_ci if (GetFactories()->count() == 0) { 116cb93a386Sopenharmony_ci return nullptr; 117cb93a386Sopenharmony_ci } 118cb93a386Sopenharmony_ci uint32_t idx = data->fRandom->nextRangeU(0, GetFactories()->count() - 1); 119cb93a386Sopenharmony_ci const GrXPFactory* xpf = (*GetFactories())[idx]->fGetProc(data); 120cb93a386Sopenharmony_ci SkASSERT(xpf); 121cb93a386Sopenharmony_ci return xpf; 122cb93a386Sopenharmony_ci} 123cb93a386Sopenharmony_ci 124cb93a386Sopenharmony_ci/* 125cb93a386Sopenharmony_ci * Originally these were both in the processor unit test header, but then it seemed to cause linker 126cb93a386Sopenharmony_ci * problems on android. 127cb93a386Sopenharmony_ci */ 128cb93a386Sopenharmony_citemplate <> 129cb93a386Sopenharmony_ciSkTArray<GrFragmentProcessorTestFactory*, true>* GrFragmentProcessorTestFactory::GetFactories() { 130cb93a386Sopenharmony_ci static SkTArray<GrFragmentProcessorTestFactory*, true> gFactories; 131cb93a386Sopenharmony_ci return &gFactories; 132cb93a386Sopenharmony_ci} 133cb93a386Sopenharmony_ci 134cb93a386Sopenharmony_citemplate <> 135cb93a386Sopenharmony_ciSkTArray<GrGeometryProcessorTestFactory*, true>* GrGeometryProcessorTestFactory::GetFactories() { 136cb93a386Sopenharmony_ci static SkTArray<GrGeometryProcessorTestFactory*, true> gFactories; 137cb93a386Sopenharmony_ci return &gFactories; 138cb93a386Sopenharmony_ci} 139cb93a386Sopenharmony_ci 140cb93a386Sopenharmony_ciSkTArray<GrXPFactoryTestFactory*, true>* GrXPFactoryTestFactory::GetFactories() { 141cb93a386Sopenharmony_ci static SkTArray<GrXPFactoryTestFactory*, true> gFactories; 142cb93a386Sopenharmony_ci return &gFactories; 143cb93a386Sopenharmony_ci} 144cb93a386Sopenharmony_ci 145cb93a386Sopenharmony_ci/* 146cb93a386Sopenharmony_ci * To ensure we always have successful static initialization, before creating from the factories 147cb93a386Sopenharmony_ci * we verify the count is as expected. If a new factory is added, then these numbers must be 148cb93a386Sopenharmony_ci * manually adjusted. 149cb93a386Sopenharmony_ci */ 150cb93a386Sopenharmony_cistatic constexpr int kFPFactoryCount = 16; 151cb93a386Sopenharmony_cistatic constexpr int kGPFactoryCount = 14; 152cb93a386Sopenharmony_cistatic constexpr int kXPFactoryCount = 4; 153cb93a386Sopenharmony_ci 154cb93a386Sopenharmony_citemplate <> void GrFragmentProcessorTestFactory::VerifyFactoryCount() { 155cb93a386Sopenharmony_ci if (kFPFactoryCount != GetFactories()->count()) { 156cb93a386Sopenharmony_ci SkDebugf("\nExpected %d fragment processor factories, found %d.\n", kFPFactoryCount, 157cb93a386Sopenharmony_ci GetFactories()->count()); 158cb93a386Sopenharmony_ci SK_ABORT("Wrong number of fragment processor factories!"); 159cb93a386Sopenharmony_ci } 160cb93a386Sopenharmony_ci} 161cb93a386Sopenharmony_ci 162cb93a386Sopenharmony_citemplate <> void GrGeometryProcessorTestFactory::VerifyFactoryCount() { 163cb93a386Sopenharmony_ci if (kGPFactoryCount != GetFactories()->count()) { 164cb93a386Sopenharmony_ci SkDebugf("\nExpected %d geometry processor factories, found %d.\n", kGPFactoryCount, 165cb93a386Sopenharmony_ci GetFactories()->count()); 166cb93a386Sopenharmony_ci SK_ABORT("Wrong number of geometry processor factories!"); 167cb93a386Sopenharmony_ci } 168cb93a386Sopenharmony_ci} 169cb93a386Sopenharmony_ci 170cb93a386Sopenharmony_civoid GrXPFactoryTestFactory::VerifyFactoryCount() { 171cb93a386Sopenharmony_ci if (kXPFactoryCount != GetFactories()->count()) { 172cb93a386Sopenharmony_ci SkDebugf("\nExpected %d xp factory factories, found %d.\n", kXPFactoryCount, 173cb93a386Sopenharmony_ci GetFactories()->count()); 174cb93a386Sopenharmony_ci SK_ABORT("Wrong number of xp factory factories!"); 175cb93a386Sopenharmony_ci } 176cb93a386Sopenharmony_ci} 177cb93a386Sopenharmony_ci 178cb93a386Sopenharmony_cistd::unique_ptr<GrFragmentProcessor> GrProcessorUnitTest::MakeChildFP(GrProcessorTestData* data) { 179cb93a386Sopenharmony_ci std::unique_ptr<GrFragmentProcessor> fp; 180cb93a386Sopenharmony_ci 181cb93a386Sopenharmony_ci ++data->fCurrentTreeDepth; 182cb93a386Sopenharmony_ci if (data->fCurrentTreeDepth > data->fMaxTreeDepth) { 183cb93a386Sopenharmony_ci // We've gone too deep, but we can't necessarily return null without risking an assertion. 184cb93a386Sopenharmony_ci // Instead, return a known-simple zero-child FP. This limits the recursion, and the 185cb93a386Sopenharmony_ci // generated FP will be rejected by the numNonNullChildProcessors check below. 186cb93a386Sopenharmony_ci fp = GrFragmentProcessor::MakeColor(SK_PMColor4fTRANSPARENT); 187cb93a386Sopenharmony_ci } else { 188cb93a386Sopenharmony_ci for (;;) { 189cb93a386Sopenharmony_ci fp = GrFragmentProcessorTestFactory::Make(data); 190cb93a386Sopenharmony_ci SkASSERT(fp); 191cb93a386Sopenharmony_ci // If our tree has already reached its max depth, we must reject FPs that have children. 192cb93a386Sopenharmony_ci if (data->fCurrentTreeDepth < data->fMaxTreeDepth || 193cb93a386Sopenharmony_ci fp->numNonNullChildProcessors() == 0) { 194cb93a386Sopenharmony_ci break; 195cb93a386Sopenharmony_ci } 196cb93a386Sopenharmony_ci } 197cb93a386Sopenharmony_ci } 198cb93a386Sopenharmony_ci 199cb93a386Sopenharmony_ci --data->fCurrentTreeDepth; 200cb93a386Sopenharmony_ci return fp; 201cb93a386Sopenharmony_ci} 202cb93a386Sopenharmony_ci 203cb93a386Sopenharmony_cistd::unique_ptr<GrFragmentProcessor> GrProcessorUnitTest::MakeOptionalChildFP( 204cb93a386Sopenharmony_ci GrProcessorTestData* data) { 205cb93a386Sopenharmony_ci return data->fRandom->nextBool() ? MakeChildFP(data) : nullptr; 206cb93a386Sopenharmony_ci} 207cb93a386Sopenharmony_ci 208cb93a386Sopenharmony_citemplate class GrProcessorTestFactory<GrGeometryProcessor*>; 209cb93a386Sopenharmony_citemplate class GrProcessorTestFactory<std::unique_ptr<GrFragmentProcessor>>; 210cb93a386Sopenharmony_ci 211cb93a386Sopenharmony_ci#endif 212