• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011 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 // This is a GPU-backend specific test. It relies on static intializers to work
9 
10 #include "SkTypes.h"
11 
12 #if SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
13 
14 #include "GrAutoLocaleSetter.h"
15 #include "GrContextFactory.h"
16 #include "GrContextPriv.h"
17 #include "GrDrawOpTest.h"
18 #include "GrDrawingManager.h"
19 #include "GrPipeline.h"
20 #include "GrRenderTargetContextPriv.h"
21 #include "GrXferProcessor.h"
22 #include "SkChecksum.h"
23 #include "SkRandom.h"
24 #include "Test.h"
25 
26 #include "ops/GrDrawOp.h"
27 
28 #include "effects/GrConfigConversionEffect.h"
29 #include "effects/GrPorterDuffXferProcessor.h"
30 #include "effects/GrXfermodeFragmentProcessor.h"
31 
32 #include "gl/GrGLGpu.h"
33 #include "glsl/GrGLSLFragmentProcessor.h"
34 #include "glsl/GrGLSLFragmentShaderBuilder.h"
35 #include "glsl/GrGLSLProgramBuilder.h"
36 
37 /*
38  * A dummy processor which just tries to insert a massive key and verify that it can retrieve the
39  * whole thing correctly
40  */
41 static const uint32_t kMaxKeySize = 1024;
42 
43 class GLBigKeyProcessor : public GrGLSLFragmentProcessor {
44 public:
emitCode(EmitArgs & args)45     void emitCode(EmitArgs& args) override {
46         // pass through
47         GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
48         if (args.fInputColor) {
49             fragBuilder->codeAppendf("%s = %s;\n", args.fOutputColor, args.fInputColor);
50         } else {
51             fragBuilder->codeAppendf("%s = vec4(1.0);\n", args.fOutputColor);
52         }
53     }
54 
GenKey(const GrProcessor &,const GrShaderCaps &,GrProcessorKeyBuilder * b)55     static void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder* b) {
56         for (uint32_t i = 0; i < kMaxKeySize; i++) {
57             b->add32(i);
58         }
59     }
60 
61 private:
62     typedef GrGLSLFragmentProcessor INHERITED;
63 };
64 
65 class BigKeyProcessor : public GrFragmentProcessor {
66 public:
Make()67     static std::unique_ptr<GrFragmentProcessor> Make() {
68         return std::unique_ptr<GrFragmentProcessor>(new BigKeyProcessor);
69     }
70 
name() const71     const char* name() const override { return "Big Ole Key"; }
72 
onCreateGLSLInstance() const73     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
74         return new GLBigKeyProcessor;
75     }
76 
clone() const77     std::unique_ptr<GrFragmentProcessor> clone() const override { return Make(); }
78 
79 private:
BigKeyProcessor()80     BigKeyProcessor() : INHERITED(kBigKeyProcessor_ClassID, kNone_OptimizationFlags) { }
onGetGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const81     virtual void onGetGLSLProcessorKey(const GrShaderCaps& caps,
82                                        GrProcessorKeyBuilder* b) const override {
83         GLBigKeyProcessor::GenKey(*this, caps, b);
84     }
onIsEqual(const GrFragmentProcessor &) const85     bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
86 
87     GR_DECLARE_FRAGMENT_PROCESSOR_TEST
88 
89     typedef GrFragmentProcessor INHERITED;
90 };
91 
92 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(BigKeyProcessor);
93 
94 #if GR_TEST_UTILS
TestCreate(GrProcessorTestData *)95 std::unique_ptr<GrFragmentProcessor> BigKeyProcessor::TestCreate(GrProcessorTestData*) {
96     return BigKeyProcessor::Make();
97 }
98 #endif
99 
100 //////////////////////////////////////////////////////////////////////////////
101 
102 class BlockInputFragmentProcessor : public GrFragmentProcessor {
103 public:
Make(std::unique_ptr<GrFragmentProcessor> fp)104     static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> fp) {
105         return std::unique_ptr<GrFragmentProcessor>(new BlockInputFragmentProcessor(std::move(fp)));
106     }
107 
name() const108     const char* name() const override { return "Block Input"; }
109 
onCreateGLSLInstance() const110     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLFP; }
111 
clone() const112     std::unique_ptr<GrFragmentProcessor> clone() const override {
113         return Make(this->childProcessor(0).clone());
114     }
115 
116 private:
117     class GLFP : public GrGLSLFragmentProcessor {
118     public:
emitCode(EmitArgs & args)119         void emitCode(EmitArgs& args) override {
120             this->emitChild(0, args);
121         }
122 
123     private:
124         typedef GrGLSLFragmentProcessor INHERITED;
125     };
126 
BlockInputFragmentProcessor(std::unique_ptr<GrFragmentProcessor> child)127     BlockInputFragmentProcessor(std::unique_ptr<GrFragmentProcessor> child)
128             : INHERITED(kBlockInputFragmentProcessor_ClassID, kNone_OptimizationFlags) {
129         this->registerChildProcessor(std::move(child));
130     }
131 
onGetGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const132     void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {}
133 
onIsEqual(const GrFragmentProcessor &) const134     bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
135 
136     typedef GrFragmentProcessor INHERITED;
137 };
138 
139 //////////////////////////////////////////////////////////////////////////////
140 
141 /*
142  * Begin test code
143  */
144 static const int kRenderTargetHeight = 1;
145 static const int kRenderTargetWidth = 1;
146 
random_render_target_context(GrContext * context,SkRandom * random,const GrCaps * caps)147 static sk_sp<GrRenderTargetContext> random_render_target_context(GrContext* context,
148                                                                  SkRandom* random,
149                                                                  const GrCaps* caps) {
150     GrSurfaceOrigin origin = random->nextBool() ? kTopLeft_GrSurfaceOrigin
151                                                 : kBottomLeft_GrSurfaceOrigin;
152     int sampleCnt =
153             random->nextBool() ? caps->getRenderTargetSampleCount(2, kRGBA_8888_GrPixelConfig) : 1;
154     // Above could be 0 if msaa isn't supported.
155     sampleCnt = SkTMax(1, sampleCnt);
156 
157     const GrBackendFormat format = caps->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
158 
159     sk_sp<GrRenderTargetContext> renderTargetContext(
160         context->contextPriv().makeDeferredRenderTargetContext(format,
161                                                                SkBackingFit::kExact,
162                                                                kRenderTargetWidth,
163                                                                kRenderTargetHeight,
164                                                                kRGBA_8888_GrPixelConfig,
165                                                                nullptr,
166                                                                sampleCnt,
167                                                                GrMipMapped::kNo,
168                                                                origin));
169     return renderTargetContext;
170 }
171 
172 #if GR_TEST_UTILS
set_random_xpf(GrPaint * paint,GrProcessorTestData * d)173 static void set_random_xpf(GrPaint* paint, GrProcessorTestData* d) {
174     paint->setXPFactory(GrXPFactoryTestFactory::Get(d));
175 }
176 
create_random_proc_tree(GrProcessorTestData * d,int minLevels,int maxLevels)177 static std::unique_ptr<GrFragmentProcessor> create_random_proc_tree(GrProcessorTestData* d,
178                                                                     int minLevels, int maxLevels) {
179     SkASSERT(1 <= minLevels);
180     SkASSERT(minLevels <= maxLevels);
181 
182     // Return a leaf node if maxLevels is 1 or if we randomly chose to terminate.
183     // If returning a leaf node, make sure that it doesn't have children (e.g. another
184     // GrComposeEffect)
185     const float terminateProbability = 0.3f;
186     if (1 == minLevels) {
187         bool terminate = (1 == maxLevels) || (d->fRandom->nextF() < terminateProbability);
188         if (terminate) {
189             std::unique_ptr<GrFragmentProcessor> fp;
190             while (true) {
191                 fp = GrFragmentProcessorTestFactory::Make(d);
192                 SkASSERT(fp);
193                 if (0 == fp->numChildProcessors()) {
194                     break;
195                 }
196             }
197             return fp;
198         }
199     }
200     // If we didn't terminate, choose either the left or right subtree to fulfill
201     // the minLevels requirement of this tree; the other child can have as few levels as it wants.
202     // Also choose a random xfer mode.
203     if (minLevels > 1) {
204         --minLevels;
205     }
206     auto minLevelsChild = create_random_proc_tree(d, minLevels, maxLevels - 1);
207     std::unique_ptr<GrFragmentProcessor> otherChild(create_random_proc_tree(d, 1, maxLevels - 1));
208     SkBlendMode mode = static_cast<SkBlendMode>(d->fRandom->nextRangeU(0,
209                                                                (int)SkBlendMode::kLastMode));
210     std::unique_ptr<GrFragmentProcessor> fp;
211     if (d->fRandom->nextF() < 0.5f) {
212         fp = GrXfermodeFragmentProcessor::MakeFromTwoProcessors(std::move(minLevelsChild),
213                                                                 std::move(otherChild), mode);
214         SkASSERT(fp);
215     } else {
216         fp = GrXfermodeFragmentProcessor::MakeFromTwoProcessors(std::move(otherChild),
217                                                                 std::move(minLevelsChild), mode);
218         SkASSERT(fp);
219     }
220     return fp;
221 }
222 
set_random_color_coverage_stages(GrPaint * paint,GrProcessorTestData * d,int maxStages,int maxTreeLevels)223 static void set_random_color_coverage_stages(GrPaint* paint,
224                                              GrProcessorTestData* d,
225                                              int maxStages,
226                                              int maxTreeLevels) {
227     // Randomly choose to either create a linear pipeline of procs or create one proc tree
228     const float procTreeProbability = 0.5f;
229     if (d->fRandom->nextF() < procTreeProbability) {
230         std::unique_ptr<GrFragmentProcessor> fp(create_random_proc_tree(d, 2, maxTreeLevels));
231         if (fp) {
232             paint->addColorFragmentProcessor(std::move(fp));
233         }
234     } else {
235         int numProcs = d->fRandom->nextULessThan(maxStages + 1);
236         int numColorProcs = d->fRandom->nextULessThan(numProcs + 1);
237 
238         for (int s = 0; s < numProcs;) {
239             std::unique_ptr<GrFragmentProcessor> fp(GrFragmentProcessorTestFactory::Make(d));
240             SkASSERT(fp);
241 
242             // finally add the stage to the correct pipeline in the drawstate
243             if (s < numColorProcs) {
244                 paint->addColorFragmentProcessor(std::move(fp));
245             } else {
246                 paint->addCoverageFragmentProcessor(std::move(fp));
247             }
248             ++s;
249         }
250     }
251 }
252 
253 #endif
254 
255 #if !GR_TEST_UTILS
ProgramUnitTest(GrContext *,int)256 bool GrDrawingManager::ProgramUnitTest(GrContext*, int) { return true; }
257 #else
ProgramUnitTest(GrContext * context,int maxStages,int maxLevels)258 bool GrDrawingManager::ProgramUnitTest(GrContext* context, int maxStages, int maxLevels) {
259     GrDrawingManager* drawingManager = context->contextPriv().drawingManager();
260     GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
261 
262     sk_sp<GrTextureProxy> proxies[2];
263 
264     // setup dummy textures
265     {
266         GrSurfaceDesc dummyDesc;
267         dummyDesc.fFlags = kRenderTarget_GrSurfaceFlag;
268         dummyDesc.fWidth = 34;
269         dummyDesc.fHeight = 18;
270         dummyDesc.fConfig = kRGBA_8888_GrPixelConfig;
271         const GrBackendFormat format =
272             context->contextPriv().caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
273         proxies[0] = proxyProvider->createProxy(format, dummyDesc, kBottomLeft_GrSurfaceOrigin,
274                                                 GrMipMapped::kYes, SkBackingFit::kExact,
275                                                 SkBudgeted::kNo, GrInternalSurfaceFlags::kNone);
276     }
277     {
278         GrSurfaceDesc dummyDesc;
279         dummyDesc.fFlags = kNone_GrSurfaceFlags;
280         dummyDesc.fWidth = 16;
281         dummyDesc.fHeight = 22;
282         dummyDesc.fConfig = kAlpha_8_GrPixelConfig;
283         const GrBackendFormat format =
284             context->contextPriv().caps()->getBackendFormatFromColorType(kAlpha_8_SkColorType);
285         proxies[1] = proxyProvider->createProxy(format, dummyDesc, kTopLeft_GrSurfaceOrigin,
286                                                 GrMipMapped::kYes, SkBackingFit::kExact,
287                                                 SkBudgeted::kNo, GrInternalSurfaceFlags::kNone);
288     }
289 
290     if (!proxies[0] || !proxies[1]) {
291         SkDebugf("Could not allocate dummy textures");
292         return false;
293     }
294 
295     // dummy scissor state
296     GrScissorState scissor;
297 
298     SkRandom random;
299     static const int NUM_TESTS = 1024;
300     for (int t = 0; t < NUM_TESTS; t++) {
301         // setup random render target(can fail)
302         sk_sp<GrRenderTargetContext> renderTargetContext(
303                 random_render_target_context(context, &random, context->contextPriv().caps()));
304         if (!renderTargetContext) {
305             SkDebugf("Could not allocate renderTargetContext");
306             return false;
307         }
308 
309         GrPaint paint;
310         GrProcessorTestData ptd(&random, context, renderTargetContext.get(), proxies);
311         set_random_color_coverage_stages(&paint, &ptd, maxStages, maxLevels);
312         set_random_xpf(&paint, &ptd);
313         GrDrawRandomOp(&random, renderTargetContext.get(), std::move(paint));
314     }
315     // Flush everything, test passes if flush is successful(ie, no asserts are hit, no crashes)
316     drawingManager->flush(nullptr);
317 
318     const GrBackendFormat format =
319             context->contextPriv().caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
320     // Validate that GrFPs work correctly without an input.
321     sk_sp<GrRenderTargetContext> renderTargetContext(
322                  context->contextPriv().makeDeferredRenderTargetContext(format,
323                                                                         SkBackingFit::kExact,
324                                                                         kRenderTargetWidth,
325                                                                         kRenderTargetHeight,
326                                                                         kRGBA_8888_GrPixelConfig,
327                                                                         nullptr));
328     if (!renderTargetContext) {
329         SkDebugf("Could not allocate a renderTargetContext");
330         return false;
331     }
332 
333     int fpFactoryCnt = GrFragmentProcessorTestFactory::Count();
334     for (int i = 0; i < fpFactoryCnt; ++i) {
335         // Since FP factories internally randomize, call each 10 times.
336         for (int j = 0; j < 10; ++j) {
337             GrProcessorTestData ptd(&random, context, renderTargetContext.get(), proxies);
338 
339             GrPaint paint;
340             paint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
341             auto fp = GrFragmentProcessorTestFactory::MakeIdx(i, &ptd);
342             auto blockFP = BlockInputFragmentProcessor::Make(std::move(fp));
343             paint.addColorFragmentProcessor(std::move(blockFP));
344             GrDrawRandomOp(&random, renderTargetContext.get(), std::move(paint));
345             drawingManager->flush(nullptr);
346         }
347     }
348 
349     return true;
350 }
351 #endif
352 
get_glprograms_max_stages(const sk_gpu_test::ContextInfo & ctxInfo)353 static int get_glprograms_max_stages(const sk_gpu_test::ContextInfo& ctxInfo) {
354     GrContext* context = ctxInfo.grContext();
355     GrGLGpu* gpu = static_cast<GrGLGpu*>(context->contextPriv().getGpu());
356     int maxStages = 6;
357     if (kGLES_GrGLStandard == gpu->glStandard()) {
358     // We've had issues with driver crashes and HW limits being exceeded with many effects on
359     // Android devices. We have passes on ARM devices with the default number of stages.
360     // TODO When we run ES 3.00 GLSL in more places, test again
361 #ifdef SK_BUILD_FOR_ANDROID
362         if (kARM_GrGLVendor != gpu->ctxInfo().vendor()) {
363             maxStages = 1;
364         }
365 #endif
366     // On iOS we can exceed the maximum number of varyings. http://skbug.com/6627.
367 #ifdef SK_BUILD_FOR_IOS
368         maxStages = 3;
369 #endif
370     }
371     if (ctxInfo.type() == sk_gpu_test::GrContextFactory::kANGLE_D3D9_ES2_ContextType ||
372         ctxInfo.type() == sk_gpu_test::GrContextFactory::kANGLE_D3D11_ES2_ContextType) {
373         // On Angle D3D we will hit a limit of out variables if we use too many stages.
374         maxStages = 3;
375     }
376     return maxStages;
377 }
378 
get_glprograms_max_levels(const sk_gpu_test::ContextInfo & ctxInfo)379 static int get_glprograms_max_levels(const sk_gpu_test::ContextInfo& ctxInfo) {
380     // A full tree with 5 levels (31 nodes) may cause a program that exceeds shader limits
381     // (e.g. uniform or varying limits); maxTreeLevels should be a number from 1 to 4 inclusive.
382     int maxTreeLevels = 4;
383     // On iOS we can exceed the maximum number of varyings. http://skbug.com/6627.
384 #ifdef SK_BUILD_FOR_IOS
385     maxTreeLevels = 2;
386 #endif
387     if (ctxInfo.type() == sk_gpu_test::GrContextFactory::kANGLE_D3D9_ES2_ContextType ||
388         ctxInfo.type() == sk_gpu_test::GrContextFactory::kANGLE_D3D11_ES2_ContextType) {
389         // On Angle D3D we will hit a limit of out variables if we use too many stages.
390         maxTreeLevels = 2;
391     }
392     return maxTreeLevels;
393 }
394 
test_glprograms(skiatest::Reporter * reporter,const sk_gpu_test::ContextInfo & ctxInfo)395 static void test_glprograms(skiatest::Reporter* reporter, const sk_gpu_test::ContextInfo& ctxInfo) {
396     int maxStages = get_glprograms_max_stages(ctxInfo);
397     if (maxStages == 0) {
398         return;
399     }
400     int maxLevels = get_glprograms_max_levels(ctxInfo);
401     if (maxLevels == 0) {
402         return;
403     }
404 
405     REPORTER_ASSERT(reporter, GrDrawingManager::ProgramUnitTest(ctxInfo.grContext(), maxStages,
406                                                                 maxLevels));
407 }
408 
DEF_GPUTEST(GLPrograms,reporter,options)409 DEF_GPUTEST(GLPrograms, reporter, options) {
410     // Set a locale that would cause shader compilation to fail because of , as decimal separator.
411     // skbug 3330
412 #ifdef SK_BUILD_FOR_WIN
413     GrAutoLocaleSetter als("sv-SE");
414 #else
415     GrAutoLocaleSetter als("sv_SE.UTF-8");
416 #endif
417 
418     // We suppress prints to avoid spew
419     GrContextOptions opts = options;
420     opts.fSuppressPrints = true;
421     sk_gpu_test::GrContextFactory debugFactory(opts);
422     skiatest::RunWithGPUTestContexts(test_glprograms, &skiatest::IsRenderingGLContextType, reporter,
423                                      opts);
424 }
425 
426 #endif
427