blob: 16a259207852daa8cb4e8035a132d299d8f993cd [file] [log] [blame]
bsalomon@google.coma8e686e2011-08-16 15:45:58 +00001/*
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
bsalomon@google.comd4726202012-08-03 14:34:46 +00008// This is a GPU-backend specific test. It relies on static intializers to work
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +00009
bsalomon@google.com2a48c3a2012-08-03 14:54:45 +000010#include "SkTypes.h"
11
12#if SK_SUPPORT_GPU && SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
13
bsalomon6f7f2012015-03-16 14:00:52 -070014#include "GrAutoLocaleSetter.h"
joshualitt6c891102015-05-13 08:51:49 -070015#include "GrBatchTest.h"
bsalomon@google.com67b915d2013-02-04 16:13:32 +000016#include "GrContextFactory.h"
robertphillips391395d2016-03-02 09:26:36 -080017#include "GrDrawContextPriv.h"
robertphillipsa13e2022015-11-11 12:01:09 -080018#include "GrDrawingManager.h"
egdaniel605dd0f2014-11-12 08:35:25 -080019#include "GrInvariantOutput.h"
egdaniel8dd688b2015-01-22 10:16:09 -080020#include "GrPipeline.h"
bsalomon4061b122015-05-29 10:26:19 -070021#include "GrResourceProvider.h"
joshualitt2c93efe2014-11-06 12:57:13 -080022#include "GrTest.h"
egdaniel95131432014-12-09 11:15:43 -080023#include "GrXferProcessor.h"
bsalomon@google.com2db3ded2013-05-22 14:34:04 +000024#include "SkChecksum.h"
tfarina@chromium.org223137f2012-11-21 22:38:36 +000025#include "SkRandom.h"
bsalomon@google.comc3841b92012-08-02 18:11:43 +000026#include "Test.h"
joshualitt74417822015-08-07 11:42:16 -070027
bsalomon16b99132015-08-13 14:55:50 -070028#include "batches/GrDrawBatch.h"
joshualitt74417822015-08-07 11:42:16 -070029
joshualitt2c93efe2014-11-06 12:57:13 -080030#include "effects/GrConfigConversionEffect.h"
egdaniel95131432014-12-09 11:15:43 -080031#include "effects/GrPorterDuffXferProcessor.h"
wangyix059dffa2015-09-10 06:57:05 -070032#include "effects/GrXfermodeFragmentProcessor.h"
joshualitt74417822015-08-07 11:42:16 -070033
jvanverth39edf762014-12-22 11:44:19 -080034#include "gl/GrGLGpu.h"
egdaniel64c47282015-11-13 06:54:19 -080035#include "glsl/GrGLSLFragmentProcessor.h"
egdaniel2d721d32015-11-11 13:06:05 -080036#include "glsl/GrGLSLFragmentShaderBuilder.h"
37#include "glsl/GrGLSLProgramBuilder.h"
bsalomon@google.comc3841b92012-08-02 18:11:43 +000038
joshualitt65171342014-10-09 07:25:36 -070039/*
bsalomon98b33eb2014-10-15 11:05:26 -070040 * A dummy processor which just tries to insert a massive key and verify that it can retrieve the
joshualitt65171342014-10-09 07:25:36 -070041 * whole thing correctly
42 */
43static const uint32_t kMaxKeySize = 1024;
44
egdaniel64c47282015-11-13 06:54:19 -080045class GLBigKeyProcessor : public GrGLSLFragmentProcessor {
joshualitt65171342014-10-09 07:25:36 -070046public:
robertphillips9cdb9922016-02-03 12:25:40 -080047 void emitCode(EmitArgs& args) override {
joshualitt6c891102015-05-13 08:51:49 -070048 // pass through
egdaniel4ca2e602015-11-18 08:01:26 -080049 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomonb5b60322015-09-14 12:26:33 -070050 if (args.fInputColor) {
egdaniel4ca2e602015-11-18 08:01:26 -080051 fragBuilder->codeAppendf("%s = %s;\n", args.fOutputColor, args.fInputColor);
bsalomonb5b60322015-09-14 12:26:33 -070052 } else {
egdaniel4ca2e602015-11-18 08:01:26 -080053 fragBuilder->codeAppendf("%s = vec4(1.0);\n", args.fOutputColor);
bsalomonb5b60322015-09-14 12:26:33 -070054 }
joshualitt6c891102015-05-13 08:51:49 -070055 }
joshualitt65171342014-10-09 07:25:36 -070056
jvanverthcfc18862015-04-28 08:48:20 -070057 static void GenKey(const GrProcessor& processor, const GrGLSLCaps&, GrProcessorKeyBuilder* b) {
joshualitt65171342014-10-09 07:25:36 -070058 for (uint32_t i = 0; i < kMaxKeySize; i++) {
59 b->add32(i);
joshualittd9097592014-10-07 08:37:36 -070060 }
joshualittd9097592014-10-07 08:37:36 -070061 }
62
joshualitt65171342014-10-09 07:25:36 -070063private:
egdaniel64c47282015-11-13 06:54:19 -080064 typedef GrGLSLFragmentProcessor INHERITED;
joshualitt65171342014-10-09 07:25:36 -070065};
66
joshualitteb2a6762014-12-04 11:35:33 -080067class BigKeyProcessor : public GrFragmentProcessor {
68public:
bungeman06ca8ec2016-06-09 08:01:03 -070069 static sk_sp<GrFragmentProcessor> Make() {
70 return sk_sp<GrFragmentProcessor>(new BigKeyProcessor);
joshualitteb2a6762014-12-04 11:35:33 -080071 }
72
mtklein36352bf2015-03-25 18:17:31 -070073 const char* name() const override { return "Big Ole Key"; }
joshualitteb2a6762014-12-04 11:35:33 -080074
egdaniel57d3b032015-11-13 11:57:27 -080075 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
robertphillips9cdb9922016-02-03 12:25:40 -080076 return new GLBigKeyProcessor;
joshualitteb2a6762014-12-04 11:35:33 -080077 }
78
79private:
80 BigKeyProcessor() {
81 this->initClassID<BigKeyProcessor>();
82 }
egdaniel57d3b032015-11-13 11:57:27 -080083 virtual void onGetGLSLProcessorKey(const GrGLSLCaps& caps,
84 GrProcessorKeyBuilder* b) const override {
wangyix4b3050b2015-08-04 07:59:37 -070085 GLBigKeyProcessor::GenKey(*this, caps, b);
86 }
mtklein36352bf2015-03-25 18:17:31 -070087 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
88 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { }
joshualitteb2a6762014-12-04 11:35:33 -080089
90 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
91
92 typedef GrFragmentProcessor INHERITED;
93};
94
95GR_DEFINE_FRAGMENT_PROCESSOR_TEST(BigKeyProcessor);
96
bungeman06ca8ec2016-06-09 08:01:03 -070097sk_sp<GrFragmentProcessor> BigKeyProcessor::TestCreate(GrProcessorTestData*) {
98 return BigKeyProcessor::Make();
joshualitteb2a6762014-12-04 11:35:33 -080099}
100
bsalomonb5b60322015-09-14 12:26:33 -0700101//////////////////////////////////////////////////////////////////////////////
102
103class BlockInputFragmentProcessor : public GrFragmentProcessor {
104public:
bungeman06ca8ec2016-06-09 08:01:03 -0700105 static sk_sp<GrFragmentProcessor> Make(sk_sp<GrFragmentProcessor> fp) {
106 return sk_sp<GrFragmentProcessor>(new BlockInputFragmentProcessor(fp));
bsalomonb5b60322015-09-14 12:26:33 -0700107 }
108
109 const char* name() const override { return "Block Input"; }
110
egdaniel57d3b032015-11-13 11:57:27 -0800111 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLFP; }
bsalomonb5b60322015-09-14 12:26:33 -0700112
113private:
egdaniel64c47282015-11-13 06:54:19 -0800114 class GLFP : public GrGLSLFragmentProcessor {
bsalomonb5b60322015-09-14 12:26:33 -0700115 public:
116 void emitCode(EmitArgs& args) override {
bsalomon38ddbad2015-09-24 06:00:00 -0700117 this->emitChild(0, nullptr, args);
bsalomonb5b60322015-09-14 12:26:33 -0700118 }
119
120 private:
egdaniel64c47282015-11-13 06:54:19 -0800121 typedef GrGLSLFragmentProcessor INHERITED;
bsalomonb5b60322015-09-14 12:26:33 -0700122 };
123
bungeman06ca8ec2016-06-09 08:01:03 -0700124 BlockInputFragmentProcessor(sk_sp<GrFragmentProcessor> child) {
bsalomonb5b60322015-09-14 12:26:33 -0700125 this->initClassID<BlockInputFragmentProcessor>();
bungeman06ca8ec2016-06-09 08:01:03 -0700126 this->registerChildProcessor(std::move(child));
bsalomonb5b60322015-09-14 12:26:33 -0700127 }
128
egdaniel57d3b032015-11-13 11:57:27 -0800129 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {}
bsalomonb5b60322015-09-14 12:26:33 -0700130
131 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
132
133 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
134 inout->setToOther(kRGBA_GrColorComponentFlags, GrColor_WHITE,
135 GrInvariantOutput::kWillNot_ReadInput);
136 this->childProcessor(0).computeInvariantOutput(inout);
137 }
138
139 typedef GrFragmentProcessor INHERITED;
140};
141
142//////////////////////////////////////////////////////////////////////////////
143
joshualitt65171342014-10-09 07:25:36 -0700144/*
145 * Begin test code
146 */
147static const int kRenderTargetHeight = 1;
148static const int kRenderTargetWidth = 1;
149
robertphillips82ec6e52016-05-19 14:01:05 -0700150static sk_sp<GrDrawContext> random_draw_context(GrContext* context,
151 SkRandom* random,
152 const GrCaps* caps) {
153 GrSurfaceOrigin origin = random->nextBool() ? kTopLeft_GrSurfaceOrigin
154 : kBottomLeft_GrSurfaceOrigin;
155 int sampleCnt = random->nextBool() ? SkTMin(4, caps->maxSampleCount()) : 0;
joshualitt6c891102015-05-13 08:51:49 -0700156
robertphillips82ec6e52016-05-19 14:01:05 -0700157 sk_sp<GrDrawContext> drawContext(context->newDrawContext(SkBackingFit::kExact,
158 kRenderTargetWidth,
159 kRenderTargetHeight,
160 kRGBA_8888_GrPixelConfig,
161 sampleCnt,
162 origin));
robertphillips82ec6e52016-05-19 14:01:05 -0700163 return drawContext;
bsalomon@google.com91207482013-02-12 21:45:24 +0000164}
165
robertphillips28a838e2016-06-23 14:07:00 -0700166static void set_random_xpf(GrPaint* paint, GrProcessorTestData* d) {
bungeman06ca8ec2016-06-09 08:01:03 -0700167 sk_sp<GrXPFactory> xpf(GrProcessorTestFactory<GrXPFactory>::Make(d));
egdanielc2304142014-12-11 13:15:13 -0800168 SkASSERT(xpf);
robertphillips28a838e2016-06-23 14:07:00 -0700169 paint->setXPFactory(std::move(xpf));
egdanielc2304142014-12-11 13:15:13 -0800170}
171
bungeman06ca8ec2016-06-09 08:01:03 -0700172static sk_sp<GrFragmentProcessor> create_random_proc_tree(GrProcessorTestData* d,
173 int minLevels, int maxLevels) {
wangyix059dffa2015-09-10 06:57:05 -0700174 SkASSERT(1 <= minLevels);
175 SkASSERT(minLevels <= maxLevels);
176
177 // Return a leaf node if maxLevels is 1 or if we randomly chose to terminate.
178 // If returning a leaf node, make sure that it doesn't have children (e.g. another
179 // GrComposeEffect)
180 const float terminateProbability = 0.3f;
181 if (1 == minLevels) {
182 bool terminate = (1 == maxLevels) || (d->fRandom->nextF() < terminateProbability);
183 if (terminate) {
bungeman06ca8ec2016-06-09 08:01:03 -0700184 sk_sp<GrFragmentProcessor> fp;
wangyix059dffa2015-09-10 06:57:05 -0700185 while (true) {
bungeman06ca8ec2016-06-09 08:01:03 -0700186 fp = GrProcessorTestFactory<GrFragmentProcessor>::Make(d);
wangyix059dffa2015-09-10 06:57:05 -0700187 SkASSERT(fp);
188 if (0 == fp->numChildProcessors()) {
189 break;
190 }
wangyix059dffa2015-09-10 06:57:05 -0700191 }
192 return fp;
193 }
194 }
195 // If we didn't terminate, choose either the left or right subtree to fulfill
196 // the minLevels requirement of this tree; the other child can have as few levels as it wants.
197 // Also choose a random xfer mode that's supported by CreateFrom2Procs().
198 if (minLevels > 1) {
199 --minLevels;
200 }
bungeman06ca8ec2016-06-09 08:01:03 -0700201 sk_sp<GrFragmentProcessor> minLevelsChild(create_random_proc_tree(d, minLevels, maxLevels - 1));
202 sk_sp<GrFragmentProcessor> otherChild(create_random_proc_tree(d, 1, maxLevels - 1));
wangyix059dffa2015-09-10 06:57:05 -0700203 SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(d->fRandom->nextRangeU(0,
204 SkXfermode::kLastCoeffMode));
bungeman06ca8ec2016-06-09 08:01:03 -0700205 sk_sp<GrFragmentProcessor> fp;
wangyix059dffa2015-09-10 06:57:05 -0700206 if (d->fRandom->nextF() < 0.5f) {
bungeman06ca8ec2016-06-09 08:01:03 -0700207 fp = GrXfermodeFragmentProcessor::MakeFromTwoProcessors(std::move(minLevelsChild),
208 std::move(otherChild), mode);
wangyix059dffa2015-09-10 06:57:05 -0700209 SkASSERT(fp);
210 } else {
bungeman06ca8ec2016-06-09 08:01:03 -0700211 fp = GrXfermodeFragmentProcessor::MakeFromTwoProcessors(std::move(otherChild),
212 std::move(minLevelsChild), mode);
wangyix059dffa2015-09-10 06:57:05 -0700213 SkASSERT(fp);
214 }
215 return fp;
216}
217
robertphillips28a838e2016-06-23 14:07:00 -0700218static void set_random_color_coverage_stages(GrPaint* paint,
219 GrProcessorTestData* d,
220 int maxStages) {
wangyix059dffa2015-09-10 06:57:05 -0700221 // Randomly choose to either create a linear pipeline of procs or create one proc tree
222 const float procTreeProbability = 0.5f;
223 if (d->fRandom->nextF() < procTreeProbability) {
224 // A full tree with 5 levels (31 nodes) may exceed the max allowed length of the gl
225 // processor key; maxTreeLevels should be a number from 1 to 4 inclusive.
226 const int maxTreeLevels = 4;
bungeman06ca8ec2016-06-09 08:01:03 -0700227 sk_sp<GrFragmentProcessor> fp(create_random_proc_tree(d, 2, maxTreeLevels));
robertphillips28a838e2016-06-23 14:07:00 -0700228 paint->addColorFragmentProcessor(std::move(fp));
wangyix059dffa2015-09-10 06:57:05 -0700229 } else {
230 int numProcs = d->fRandom->nextULessThan(maxStages + 1);
231 int numColorProcs = d->fRandom->nextULessThan(numProcs + 1);
joshualitt65171342014-10-09 07:25:36 -0700232
wangyix059dffa2015-09-10 06:57:05 -0700233 for (int s = 0; s < numProcs;) {
bungeman06ca8ec2016-06-09 08:01:03 -0700234 sk_sp<GrFragmentProcessor> fp(GrProcessorTestFactory<GrFragmentProcessor>::Make(d));
wangyix059dffa2015-09-10 06:57:05 -0700235 SkASSERT(fp);
236
237 // finally add the stage to the correct pipeline in the drawstate
238 if (s < numColorProcs) {
robertphillips28a838e2016-06-23 14:07:00 -0700239 paint->addColorFragmentProcessor(std::move(fp));
wangyix059dffa2015-09-10 06:57:05 -0700240 } else {
robertphillips28a838e2016-06-23 14:07:00 -0700241 paint->addCoverageFragmentProcessor(std::move(fp));
wangyix059dffa2015-09-10 06:57:05 -0700242 }
243 ++s;
joshualitt65171342014-10-09 07:25:36 -0700244 }
joshualitt65171342014-10-09 07:25:36 -0700245 }
246}
247
robertphillips28a838e2016-06-23 14:07:00 -0700248static bool set_random_state(GrPaint* paint, SkRandom* random) {
249 if (random->nextBool()) {
250 paint->setDisableOutputConversionToSRGB(true);
joshualitt65171342014-10-09 07:25:36 -0700251 }
robertphillips28a838e2016-06-23 14:07:00 -0700252 if (random->nextBool()) {
253 paint->setAllowSRGBInputs(true);
joshualitt6c891102015-05-13 08:51:49 -0700254 }
robertphillips28a838e2016-06-23 14:07:00 -0700255 if (random->nextBool()) {
256 paint->setAntiAlias(true);
257 }
258 return random->nextBool();
joshualitt65171342014-10-09 07:25:36 -0700259}
260
joshualitt65171342014-10-09 07:25:36 -0700261// right now, the only thing we seem to care about in drawState's stencil is 'doesWrite()'
robertphillips28a838e2016-06-23 14:07:00 -0700262static const GrUserStencilSettings* get_random_stencil(SkRandom* random) {
cdalton93a379b2016-05-11 13:58:08 -0700263 static constexpr GrUserStencilSettings kDoesWriteStencil(
264 GrUserStencilSettings::StaticInit<
265 0xffff,
266 GrUserStencilTest::kAlways,
267 0xffff,
268 GrUserStencilOp::kReplace,
269 GrUserStencilOp::kReplace,
270 0xffff>()
271 );
272 static constexpr GrUserStencilSettings kDoesNotWriteStencil(
273 GrUserStencilSettings::StaticInit<
274 0xffff,
275 GrUserStencilTest::kNever,
276 0xffff,
277 GrUserStencilOp::kKeep,
278 GrUserStencilOp::kKeep,
279 0xffff>()
280 );
joshualitt65171342014-10-09 07:25:36 -0700281
282 if (random->nextBool()) {
robertphillips28a838e2016-06-23 14:07:00 -0700283 return &kDoesWriteStencil;
joshualitt65171342014-10-09 07:25:36 -0700284 } else {
robertphillips28a838e2016-06-23 14:07:00 -0700285 return &kDoesNotWriteStencil;
joshualitt65171342014-10-09 07:25:36 -0700286 }
287}
joshualitt249af152014-09-15 11:41:13 -0700288
robertphillips0dfa62c2015-11-16 06:23:31 -0800289bool GrDrawingManager::ProgramUnitTest(GrContext* context, int maxStages) {
robertphillipsa13e2022015-11-11 12:01:09 -0800290 GrDrawingManager* drawingManager = context->drawingManager();
291
joshualitt65171342014-10-09 07:25:36 -0700292 // setup dummy textures
bsalomonf2703d82014-10-28 14:33:06 -0700293 GrSurfaceDesc dummyDesc;
bsalomonbea01502015-07-16 10:00:28 -0700294 dummyDesc.fFlags = kRenderTarget_GrSurfaceFlag;
bsalomon@google.comfec0bc32013-02-07 14:43:04 +0000295 dummyDesc.fConfig = kSkia8888_GrPixelConfig;
bsalomon@google.comd4726202012-08-03 14:34:46 +0000296 dummyDesc.fWidth = 34;
297 dummyDesc.fHeight = 18;
bsalomon4061b122015-05-29 10:26:19 -0700298 SkAutoTUnref<GrTexture> dummyTexture1(
bsalomon5ec26ae2016-02-25 08:33:02 -0800299 context->textureProvider()->createTexture(dummyDesc, SkBudgeted::kNo, nullptr, 0));
bsalomonf2703d82014-10-28 14:33:06 -0700300 dummyDesc.fFlags = kNone_GrSurfaceFlags;
bsalomon@google.comd4726202012-08-03 14:34:46 +0000301 dummyDesc.fConfig = kAlpha_8_GrPixelConfig;
302 dummyDesc.fWidth = 16;
303 dummyDesc.fHeight = 22;
bsalomon4061b122015-05-29 10:26:19 -0700304 SkAutoTUnref<GrTexture> dummyTexture2(
bsalomon5ec26ae2016-02-25 08:33:02 -0800305 context->textureProvider()->createTexture(dummyDesc, SkBudgeted::kNo, nullptr, 0));
bsalomon@google.comd4726202012-08-03 14:34:46 +0000306
bsalomone904c092014-07-17 10:50:59 -0700307 if (!dummyTexture1 || ! dummyTexture2) {
joshualitt65171342014-10-09 07:25:36 -0700308 SkDebugf("Could not allocate dummy textures");
bsalomone904c092014-07-17 10:50:59 -0700309 return false;
310 }
311
joshualitt65171342014-10-09 07:25:36 -0700312 GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()};
313
joshualitt54e0c122014-11-19 09:38:51 -0800314 // dummy scissor state
bsalomon3e791242014-12-17 13:43:13 -0800315 GrScissorState scissor;
joshualitt54e0c122014-11-19 09:38:51 -0800316
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000317 SkRandom random;
bsalomonf3261af2016-04-05 10:57:13 -0700318 static const int NUM_TESTS = 1024;
joshualitt6c891102015-05-13 08:51:49 -0700319 for (int t = 0; t < NUM_TESTS; t++) {
joshualitt65171342014-10-09 07:25:36 -0700320 // setup random render target(can fail)
robertphillips82ec6e52016-05-19 14:01:05 -0700321 sk_sp<GrDrawContext> drawContext(random_draw_context(context, &random, context->caps()));
joshualittf5883a62016-01-13 07:47:38 -0800322 if (!drawContext) {
323 SkDebugf("Could not allocate drawContext");
324 return false;
325 }
robertphillips0dfa62c2015-11-16 06:23:31 -0800326
robertphillips28a838e2016-06-23 14:07:00 -0700327 GrPaint grPaint;
robertphillips82ec6e52016-05-19 14:01:05 -0700328
329 SkAutoTUnref<GrDrawBatch> batch(GrRandomDrawBatch(&random, context));
330 SkASSERT(batch);
331
332 GrProcessorTestData ptd(&random, context, context->caps(),
333 drawContext.get(), dummyTextures);
robertphillips28a838e2016-06-23 14:07:00 -0700334 set_random_color_coverage_stages(&grPaint, &ptd, maxStages);
335 set_random_xpf(&grPaint, &ptd);
336 bool snapToCenters = set_random_state(&grPaint, &random);
337 const GrUserStencilSettings* uss = get_random_stencil(&random);
robertphillips82ec6e52016-05-19 14:01:05 -0700338
robertphillips28a838e2016-06-23 14:07:00 -0700339 drawContext->drawContextPriv().testingOnly_drawBatch(grPaint, batch, uss, snapToCenters);
bsalomon@google.comc3841b92012-08-02 18:11:43 +0000340 }
joshualitt6c891102015-05-13 08:51:49 -0700341 // Flush everything, test passes if flush is successful(ie, no asserts are hit, no crashes)
robertphillipsa13e2022015-11-11 12:01:09 -0800342 drawingManager->flush();
bsalomonb5b60322015-09-14 12:26:33 -0700343
344 // Validate that GrFPs work correctly without an input.
robertphillips82ec6e52016-05-19 14:01:05 -0700345 sk_sp<GrDrawContext> drawContext(context->newDrawContext(SkBackingFit::kExact,
346 kRenderTargetWidth,
347 kRenderTargetHeight,
348 kRGBA_8888_GrPixelConfig));
349 if (!drawContext) {
350 SkDebugf("Could not allocate a drawContext");
351 return false;
352 }
353
bsalomonb5b60322015-09-14 12:26:33 -0700354 int fpFactoryCnt = GrProcessorTestFactory<GrFragmentProcessor>::Count();
355 for (int i = 0; i < fpFactoryCnt; ++i) {
356 // Since FP factories internally randomize, call each 10 times.
357 for (int j = 0; j < 10; ++j) {
358 SkAutoTUnref<GrDrawBatch> batch(GrRandomDrawBatch(&random, context));
359 SkASSERT(batch);
robertphillips82ec6e52016-05-19 14:01:05 -0700360 GrProcessorTestData ptd(&random, context, context->caps(),
361 drawContext.get(), dummyTextures);
robertphillips28a838e2016-06-23 14:07:00 -0700362 GrPaint grPaint;
363 grPaint.setXPFactory(GrPorterDuffXPFactory::Make(SkXfermode::kSrc_Mode));
bsalomonb5b60322015-09-14 12:26:33 -0700364
bungeman06ca8ec2016-06-09 08:01:03 -0700365 sk_sp<GrFragmentProcessor> fp(
366 GrProcessorTestFactory<GrFragmentProcessor>::MakeIdx(i, &ptd));
367 sk_sp<GrFragmentProcessor> blockFP(
368 BlockInputFragmentProcessor::Make(std::move(fp)));
robertphillips28a838e2016-06-23 14:07:00 -0700369 grPaint.addColorFragmentProcessor(std::move(blockFP));
bsalomonb5b60322015-09-14 12:26:33 -0700370
robertphillips28a838e2016-06-23 14:07:00 -0700371 drawContext->drawContextPriv().testingOnly_drawBatch(grPaint, batch);
robertphillipsa13e2022015-11-11 12:01:09 -0800372 drawingManager->flush();
bsalomonb5b60322015-09-14 12:26:33 -0700373 }
374 }
375
bsalomon@google.comc3841b92012-08-02 18:11:43 +0000376 return true;
377}
bsalomon@google.coma8e686e2011-08-16 15:45:58 +0000378
kkinnunen3e980c32015-12-23 01:33:00 -0800379static int get_glprograms_max_stages(GrContext* context) {
380 GrGLGpu* gpu = static_cast<GrGLGpu*>(context->getGpu());
381 /*
382 * For the time being, we only support the test with desktop GL or for android on
383 * ARM platforms
384 * TODO When we run ES 3.00 GLSL in more places, test again
385 */
386 if (kGL_GrGLStandard == gpu->glStandard() ||
387 kARM_GrGLVendor == gpu->ctxInfo().vendor()) {
388 return 6;
389 } else if (kTegra3_GrGLRenderer == gpu->ctxInfo().renderer() ||
390 kOther_GrGLRenderer == gpu->ctxInfo().renderer()) {
391 return 1;
392 }
393 return 0;
394}
395
bsalomonf2f1c172016-04-05 12:59:06 -0700396static void test_glprograms_native(skiatest::Reporter* reporter,
397 const sk_gpu_test::ContextInfo& ctxInfo) {
bsalomon8b7451a2016-05-11 06:33:06 -0700398 int maxStages = get_glprograms_max_stages(ctxInfo.grContext());
kkinnunen3e980c32015-12-23 01:33:00 -0800399 if (maxStages == 0) {
400 return;
401 }
bsalomon8b7451a2016-05-11 06:33:06 -0700402 REPORTER_ASSERT(reporter, GrDrawingManager::ProgramUnitTest(ctxInfo.grContext(), maxStages));
kkinnunen3e980c32015-12-23 01:33:00 -0800403}
404
bsalomonf2f1c172016-04-05 12:59:06 -0700405static void test_glprograms_other_contexts(
406 skiatest::Reporter* reporter,
407 const sk_gpu_test::ContextInfo& ctxInfo) {
bsalomon8b7451a2016-05-11 06:33:06 -0700408 int maxStages = get_glprograms_max_stages(ctxInfo.grContext());
kkinnunen3e980c32015-12-23 01:33:00 -0800409#ifdef SK_BUILD_FOR_WIN
410 // Some long shaders run out of temporary registers in the D3D compiler on ANGLE and
411 // command buffer.
412 maxStages = SkTMin(maxStages, 2);
413#endif
414 if (maxStages == 0) {
415 return;
416 }
bsalomon8b7451a2016-05-11 06:33:06 -0700417 REPORTER_ASSERT(reporter, GrDrawingManager::ProgramUnitTest(ctxInfo.grContext(), maxStages));
kkinnunen3e980c32015-12-23 01:33:00 -0800418}
419
bsalomon758586c2016-04-06 14:02:39 -0700420static bool is_native_gl_context_type(sk_gpu_test::GrContextFactory::ContextType type) {
421 return type == sk_gpu_test::GrContextFactory::kNativeGL_ContextType;
422}
423
424static bool is_other_rendering_gl_context_type(sk_gpu_test::GrContextFactory::ContextType type) {
425 return !is_native_gl_context_type(type) &&
426 kOpenGL_GrBackend == sk_gpu_test::GrContextFactory::ContextTypeBackend(type) &&
427 sk_gpu_test::GrContextFactory::IsRenderingContext(type);
428}
429
kkinnunen3e980c32015-12-23 01:33:00 -0800430DEF_GPUTEST(GLPrograms, reporter, /*factory*/) {
bsalomon3318ee72015-03-16 11:56:29 -0700431 // Set a locale that would cause shader compilation to fail because of , as decimal separator.
432 // skbug 3330
433#ifdef SK_BUILD_FOR_WIN
434 GrAutoLocaleSetter als("sv-SE");
435#else
436 GrAutoLocaleSetter als("sv_SE.UTF-8");
437#endif
438
joshualitt6c891102015-05-13 08:51:49 -0700439 // We suppress prints to avoid spew
bsalomon682c2692015-05-22 14:01:46 -0700440 GrContextOptions opts;
joshualitt6c891102015-05-13 08:51:49 -0700441 opts.fSuppressPrints = true;
bsalomon3724e572016-03-30 18:56:19 -0700442 sk_gpu_test::GrContextFactory debugFactory(opts);
bsalomon758586c2016-04-06 14:02:39 -0700443 skiatest::RunWithGPUTestContexts(test_glprograms_native, &is_native_gl_context_type,
kkinnunen3e980c32015-12-23 01:33:00 -0800444 reporter, &debugFactory);
445 skiatest::RunWithGPUTestContexts(test_glprograms_other_contexts,
bsalomon758586c2016-04-06 14:02:39 -0700446 &is_other_rendering_gl_context_type, reporter, &debugFactory);
bsalomon@google.coma8e686e2011-08-16 15:45:58 +0000447}
448
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000449#endif