blob: ce79d0e4948e29ca0f3a0331fc90c5cd27673dd2 [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"
bsalomon@google.com67b915d2013-02-04 16:13:32 +000015#include "GrContextFactory.h"
csmartdaltonbde96c62016-08-31 12:54:46 -070016#include "GrContextPriv.h"
Brian Salomon5ec9def2016-12-20 15:34:05 -050017#include "GrDrawOpTest.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"
Brian Salomon5ec9def2016-12-20 15:34:05 -050021#include "GrRenderTargetContextPriv.h"
bsalomon4061b122015-05-29 10:26:19 -070022#include "GrResourceProvider.h"
joshualitt2c93efe2014-11-06 12:57:13 -080023#include "GrTest.h"
egdaniel95131432014-12-09 11:15:43 -080024#include "GrXferProcessor.h"
bsalomon@google.com2db3ded2013-05-22 14:34:04 +000025#include "SkChecksum.h"
tfarina@chromium.org223137f2012-11-21 22:38:36 +000026#include "SkRandom.h"
bsalomon@google.comc3841b92012-08-02 18:11:43 +000027#include "Test.h"
joshualitt74417822015-08-07 11:42:16 -070028
Brian Salomon89527432016-12-16 09:52:16 -050029#include "ops/GrDrawOp.h"
joshualitt74417822015-08-07 11:42:16 -070030
joshualitt2c93efe2014-11-06 12:57:13 -080031#include "effects/GrConfigConversionEffect.h"
egdaniel95131432014-12-09 11:15:43 -080032#include "effects/GrPorterDuffXferProcessor.h"
wangyix059dffa2015-09-10 06:57:05 -070033#include "effects/GrXfermodeFragmentProcessor.h"
joshualitt74417822015-08-07 11:42:16 -070034
jvanverth39edf762014-12-22 11:44:19 -080035#include "gl/GrGLGpu.h"
egdaniel64c47282015-11-13 06:54:19 -080036#include "glsl/GrGLSLFragmentProcessor.h"
egdaniel2d721d32015-11-11 13:06:05 -080037#include "glsl/GrGLSLFragmentShaderBuilder.h"
38#include "glsl/GrGLSLProgramBuilder.h"
bsalomon@google.comc3841b92012-08-02 18:11:43 +000039
joshualitt65171342014-10-09 07:25:36 -070040/*
bsalomon98b33eb2014-10-15 11:05:26 -070041 * A dummy processor which just tries to insert a massive key and verify that it can retrieve the
joshualitt65171342014-10-09 07:25:36 -070042 * whole thing correctly
43 */
44static const uint32_t kMaxKeySize = 1024;
45
egdaniel64c47282015-11-13 06:54:19 -080046class GLBigKeyProcessor : public GrGLSLFragmentProcessor {
joshualitt65171342014-10-09 07:25:36 -070047public:
robertphillips9cdb9922016-02-03 12:25:40 -080048 void emitCode(EmitArgs& args) override {
joshualitt6c891102015-05-13 08:51:49 -070049 // pass through
egdaniel4ca2e602015-11-18 08:01:26 -080050 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomonb5b60322015-09-14 12:26:33 -070051 if (args.fInputColor) {
egdaniel4ca2e602015-11-18 08:01:26 -080052 fragBuilder->codeAppendf("%s = %s;\n", args.fOutputColor, args.fInputColor);
bsalomonb5b60322015-09-14 12:26:33 -070053 } else {
egdaniel4ca2e602015-11-18 08:01:26 -080054 fragBuilder->codeAppendf("%s = vec4(1.0);\n", args.fOutputColor);
bsalomonb5b60322015-09-14 12:26:33 -070055 }
joshualitt6c891102015-05-13 08:51:49 -070056 }
joshualitt65171342014-10-09 07:25:36 -070057
Brian Salomon94efbf52016-11-29 13:43:05 -050058 static void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder* b) {
joshualitt65171342014-10-09 07:25:36 -070059 for (uint32_t i = 0; i < kMaxKeySize; i++) {
60 b->add32(i);
joshualittd9097592014-10-07 08:37:36 -070061 }
joshualittd9097592014-10-07 08:37:36 -070062 }
63
joshualitt65171342014-10-09 07:25:36 -070064private:
egdaniel64c47282015-11-13 06:54:19 -080065 typedef GrGLSLFragmentProcessor INHERITED;
joshualitt65171342014-10-09 07:25:36 -070066};
67
joshualitteb2a6762014-12-04 11:35:33 -080068class BigKeyProcessor : public GrFragmentProcessor {
69public:
bungeman06ca8ec2016-06-09 08:01:03 -070070 static sk_sp<GrFragmentProcessor> Make() {
71 return sk_sp<GrFragmentProcessor>(new BigKeyProcessor);
joshualitteb2a6762014-12-04 11:35:33 -080072 }
73
mtklein36352bf2015-03-25 18:17:31 -070074 const char* name() const override { return "Big Ole Key"; }
joshualitteb2a6762014-12-04 11:35:33 -080075
egdaniel57d3b032015-11-13 11:57:27 -080076 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
robertphillips9cdb9922016-02-03 12:25:40 -080077 return new GLBigKeyProcessor;
joshualitteb2a6762014-12-04 11:35:33 -080078 }
79
80private:
81 BigKeyProcessor() {
82 this->initClassID<BigKeyProcessor>();
83 }
Brian Salomon94efbf52016-11-29 13:43:05 -050084 virtual void onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -080085 GrProcessorKeyBuilder* b) const override {
wangyix4b3050b2015-08-04 07:59:37 -070086 GLBigKeyProcessor::GenKey(*this, caps, b);
87 }
mtklein36352bf2015-03-25 18:17:31 -070088 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
89 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { }
joshualitteb2a6762014-12-04 11:35:33 -080090
91 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
92
93 typedef GrFragmentProcessor INHERITED;
94};
95
96GR_DEFINE_FRAGMENT_PROCESSOR_TEST(BigKeyProcessor);
97
bungeman06ca8ec2016-06-09 08:01:03 -070098sk_sp<GrFragmentProcessor> BigKeyProcessor::TestCreate(GrProcessorTestData*) {
99 return BigKeyProcessor::Make();
joshualitteb2a6762014-12-04 11:35:33 -0800100}
101
bsalomonb5b60322015-09-14 12:26:33 -0700102//////////////////////////////////////////////////////////////////////////////
103
104class BlockInputFragmentProcessor : public GrFragmentProcessor {
105public:
bungeman06ca8ec2016-06-09 08:01:03 -0700106 static sk_sp<GrFragmentProcessor> Make(sk_sp<GrFragmentProcessor> fp) {
107 return sk_sp<GrFragmentProcessor>(new BlockInputFragmentProcessor(fp));
bsalomonb5b60322015-09-14 12:26:33 -0700108 }
109
110 const char* name() const override { return "Block Input"; }
111
egdaniel57d3b032015-11-13 11:57:27 -0800112 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLFP; }
bsalomonb5b60322015-09-14 12:26:33 -0700113
114private:
egdaniel64c47282015-11-13 06:54:19 -0800115 class GLFP : public GrGLSLFragmentProcessor {
bsalomonb5b60322015-09-14 12:26:33 -0700116 public:
117 void emitCode(EmitArgs& args) override {
bsalomon38ddbad2015-09-24 06:00:00 -0700118 this->emitChild(0, nullptr, args);
bsalomonb5b60322015-09-14 12:26:33 -0700119 }
120
121 private:
egdaniel64c47282015-11-13 06:54:19 -0800122 typedef GrGLSLFragmentProcessor INHERITED;
bsalomonb5b60322015-09-14 12:26:33 -0700123 };
124
bungeman06ca8ec2016-06-09 08:01:03 -0700125 BlockInputFragmentProcessor(sk_sp<GrFragmentProcessor> child) {
bsalomonb5b60322015-09-14 12:26:33 -0700126 this->initClassID<BlockInputFragmentProcessor>();
bungeman06ca8ec2016-06-09 08:01:03 -0700127 this->registerChildProcessor(std::move(child));
bsalomonb5b60322015-09-14 12:26:33 -0700128 }
129
Brian Salomon94efbf52016-11-29 13:43:05 -0500130 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {}
bsalomonb5b60322015-09-14 12:26:33 -0700131
132 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
133
134 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
135 inout->setToOther(kRGBA_GrColorComponentFlags, GrColor_WHITE,
136 GrInvariantOutput::kWillNot_ReadInput);
137 this->childProcessor(0).computeInvariantOutput(inout);
138 }
139
140 typedef GrFragmentProcessor INHERITED;
141};
142
143//////////////////////////////////////////////////////////////////////////////
144
joshualitt65171342014-10-09 07:25:36 -0700145/*
146 * Begin test code
147 */
148static const int kRenderTargetHeight = 1;
149static const int kRenderTargetWidth = 1;
150
Brian Osman11052242016-10-27 14:47:55 -0400151static sk_sp<GrRenderTargetContext> random_render_target_context(GrContext* context,
152 SkRandom* random,
153 const GrCaps* caps) {
robertphillips82ec6e52016-05-19 14:01:05 -0700154 GrSurfaceOrigin origin = random->nextBool() ? kTopLeft_GrSurfaceOrigin
155 : kBottomLeft_GrSurfaceOrigin;
156 int sampleCnt = random->nextBool() ? SkTMin(4, caps->maxSampleCount()) : 0;
joshualitt6c891102015-05-13 08:51:49 -0700157
Brian Osman11052242016-10-27 14:47:55 -0400158 sk_sp<GrRenderTargetContext> renderTargetContext(context->makeRenderTargetContext(
159 SkBackingFit::kExact,
160 kRenderTargetWidth,
161 kRenderTargetHeight,
162 kRGBA_8888_GrPixelConfig,
163 nullptr,
164 sampleCnt,
165 origin));
166 return renderTargetContext;
bsalomon@google.com91207482013-02-12 21:45:24 +0000167}
168
robertphillips28a838e2016-06-23 14:07:00 -0700169static void set_random_xpf(GrPaint* paint, GrProcessorTestData* d) {
Brian Salomona1633922017-01-09 11:46:10 -0500170 paint->setXPFactory(GrXPFactoryTestFactory::Get(d));
egdanielc2304142014-12-11 13:15:13 -0800171}
172
bungeman06ca8ec2016-06-09 08:01:03 -0700173static sk_sp<GrFragmentProcessor> create_random_proc_tree(GrProcessorTestData* d,
174 int minLevels, int maxLevels) {
wangyix059dffa2015-09-10 06:57:05 -0700175 SkASSERT(1 <= minLevels);
176 SkASSERT(minLevels <= maxLevels);
177
178 // Return a leaf node if maxLevels is 1 or if we randomly chose to terminate.
179 // If returning a leaf node, make sure that it doesn't have children (e.g. another
180 // GrComposeEffect)
181 const float terminateProbability = 0.3f;
182 if (1 == minLevels) {
183 bool terminate = (1 == maxLevels) || (d->fRandom->nextF() < terminateProbability);
184 if (terminate) {
bungeman06ca8ec2016-06-09 08:01:03 -0700185 sk_sp<GrFragmentProcessor> fp;
wangyix059dffa2015-09-10 06:57:05 -0700186 while (true) {
bungeman06ca8ec2016-06-09 08:01:03 -0700187 fp = GrProcessorTestFactory<GrFragmentProcessor>::Make(d);
wangyix059dffa2015-09-10 06:57:05 -0700188 SkASSERT(fp);
189 if (0 == fp->numChildProcessors()) {
190 break;
191 }
wangyix059dffa2015-09-10 06:57:05 -0700192 }
193 return fp;
194 }
195 }
196 // If we didn't terminate, choose either the left or right subtree to fulfill
197 // the minLevels requirement of this tree; the other child can have as few levels as it wants.
198 // Also choose a random xfer mode that's supported by CreateFrom2Procs().
199 if (minLevels > 1) {
200 --minLevels;
201 }
bungeman06ca8ec2016-06-09 08:01:03 -0700202 sk_sp<GrFragmentProcessor> minLevelsChild(create_random_proc_tree(d, minLevels, maxLevels - 1));
203 sk_sp<GrFragmentProcessor> otherChild(create_random_proc_tree(d, 1, maxLevels - 1));
Mike Reed7d954ad2016-10-28 15:42:34 -0400204 SkBlendMode mode = static_cast<SkBlendMode>(d->fRandom->nextRangeU(0,
205 (int)SkBlendMode::kLastCoeffMode));
bungeman06ca8ec2016-06-09 08:01:03 -0700206 sk_sp<GrFragmentProcessor> fp;
wangyix059dffa2015-09-10 06:57:05 -0700207 if (d->fRandom->nextF() < 0.5f) {
bungeman06ca8ec2016-06-09 08:01:03 -0700208 fp = GrXfermodeFragmentProcessor::MakeFromTwoProcessors(std::move(minLevelsChild),
209 std::move(otherChild), mode);
wangyix059dffa2015-09-10 06:57:05 -0700210 SkASSERT(fp);
211 } else {
bungeman06ca8ec2016-06-09 08:01:03 -0700212 fp = GrXfermodeFragmentProcessor::MakeFromTwoProcessors(std::move(otherChild),
213 std::move(minLevelsChild), mode);
wangyix059dffa2015-09-10 06:57:05 -0700214 SkASSERT(fp);
215 }
216 return fp;
217}
218
robertphillips28a838e2016-06-23 14:07:00 -0700219static void set_random_color_coverage_stages(GrPaint* paint,
220 GrProcessorTestData* d,
221 int maxStages) {
wangyix059dffa2015-09-10 06:57:05 -0700222 // Randomly choose to either create a linear pipeline of procs or create one proc tree
223 const float procTreeProbability = 0.5f;
224 if (d->fRandom->nextF() < procTreeProbability) {
225 // A full tree with 5 levels (31 nodes) may exceed the max allowed length of the gl
226 // processor key; maxTreeLevels should be a number from 1 to 4 inclusive.
227 const int maxTreeLevels = 4;
bungeman06ca8ec2016-06-09 08:01:03 -0700228 sk_sp<GrFragmentProcessor> fp(create_random_proc_tree(d, 2, maxTreeLevels));
robertphillips28a838e2016-06-23 14:07:00 -0700229 paint->addColorFragmentProcessor(std::move(fp));
wangyix059dffa2015-09-10 06:57:05 -0700230 } else {
231 int numProcs = d->fRandom->nextULessThan(maxStages + 1);
232 int numColorProcs = d->fRandom->nextULessThan(numProcs + 1);
joshualitt65171342014-10-09 07:25:36 -0700233
wangyix059dffa2015-09-10 06:57:05 -0700234 for (int s = 0; s < numProcs;) {
bungeman06ca8ec2016-06-09 08:01:03 -0700235 sk_sp<GrFragmentProcessor> fp(GrProcessorTestFactory<GrFragmentProcessor>::Make(d));
wangyix059dffa2015-09-10 06:57:05 -0700236 SkASSERT(fp);
237
238 // finally add the stage to the correct pipeline in the drawstate
239 if (s < numColorProcs) {
robertphillips28a838e2016-06-23 14:07:00 -0700240 paint->addColorFragmentProcessor(std::move(fp));
wangyix059dffa2015-09-10 06:57:05 -0700241 } else {
robertphillips28a838e2016-06-23 14:07:00 -0700242 paint->addCoverageFragmentProcessor(std::move(fp));
wangyix059dffa2015-09-10 06:57:05 -0700243 }
244 ++s;
joshualitt65171342014-10-09 07:25:36 -0700245 }
joshualitt65171342014-10-09 07:25:36 -0700246 }
247}
248
robertphillips28a838e2016-06-23 14:07:00 -0700249static bool set_random_state(GrPaint* paint, SkRandom* random) {
250 if (random->nextBool()) {
251 paint->setDisableOutputConversionToSRGB(true);
joshualitt65171342014-10-09 07:25:36 -0700252 }
robertphillips28a838e2016-06-23 14:07:00 -0700253 if (random->nextBool()) {
254 paint->setAllowSRGBInputs(true);
joshualitt6c891102015-05-13 08:51:49 -0700255 }
robertphillips28a838e2016-06-23 14:07:00 -0700256 return random->nextBool();
joshualitt65171342014-10-09 07:25:36 -0700257}
258
joshualitt65171342014-10-09 07:25:36 -0700259// right now, the only thing we seem to care about in drawState's stencil is 'doesWrite()'
robertphillips28a838e2016-06-23 14:07:00 -0700260static const GrUserStencilSettings* get_random_stencil(SkRandom* random) {
cdalton93a379b2016-05-11 13:58:08 -0700261 static constexpr GrUserStencilSettings kDoesWriteStencil(
262 GrUserStencilSettings::StaticInit<
263 0xffff,
264 GrUserStencilTest::kAlways,
265 0xffff,
266 GrUserStencilOp::kReplace,
267 GrUserStencilOp::kReplace,
268 0xffff>()
269 );
270 static constexpr GrUserStencilSettings kDoesNotWriteStencil(
271 GrUserStencilSettings::StaticInit<
272 0xffff,
273 GrUserStencilTest::kNever,
274 0xffff,
275 GrUserStencilOp::kKeep,
276 GrUserStencilOp::kKeep,
277 0xffff>()
278 );
joshualitt65171342014-10-09 07:25:36 -0700279
280 if (random->nextBool()) {
robertphillips28a838e2016-06-23 14:07:00 -0700281 return &kDoesWriteStencil;
joshualitt65171342014-10-09 07:25:36 -0700282 } else {
robertphillips28a838e2016-06-23 14:07:00 -0700283 return &kDoesNotWriteStencil;
joshualitt65171342014-10-09 07:25:36 -0700284 }
285}
joshualitt249af152014-09-15 11:41:13 -0700286
robertphillips0dfa62c2015-11-16 06:23:31 -0800287bool GrDrawingManager::ProgramUnitTest(GrContext* context, int maxStages) {
csmartdaltonbde96c62016-08-31 12:54:46 -0700288 GrDrawingManager* drawingManager = context->contextPriv().drawingManager();
robertphillipsa13e2022015-11-11 12:01:09 -0800289
joshualitt65171342014-10-09 07:25:36 -0700290 // setup dummy textures
bsalomonf2703d82014-10-28 14:33:06 -0700291 GrSurfaceDesc dummyDesc;
bsalomonbea01502015-07-16 10:00:28 -0700292 dummyDesc.fFlags = kRenderTarget_GrSurfaceFlag;
Brian Osman777b5632016-10-14 09:16:21 -0400293 dummyDesc.fConfig = kRGBA_8888_GrPixelConfig;
bsalomon@google.comd4726202012-08-03 14:34:46 +0000294 dummyDesc.fWidth = 34;
295 dummyDesc.fHeight = 18;
Hal Canary342b7ac2016-11-04 11:49:42 -0400296 sk_sp<GrTexture> dummyTexture1(
bsalomon5ec26ae2016-02-25 08:33:02 -0800297 context->textureProvider()->createTexture(dummyDesc, SkBudgeted::kNo, nullptr, 0));
bsalomonf2703d82014-10-28 14:33:06 -0700298 dummyDesc.fFlags = kNone_GrSurfaceFlags;
bsalomon@google.comd4726202012-08-03 14:34:46 +0000299 dummyDesc.fConfig = kAlpha_8_GrPixelConfig;
300 dummyDesc.fWidth = 16;
301 dummyDesc.fHeight = 22;
Hal Canary342b7ac2016-11-04 11:49:42 -0400302 sk_sp<GrTexture> dummyTexture2(
bsalomon5ec26ae2016-02-25 08:33:02 -0800303 context->textureProvider()->createTexture(dummyDesc, SkBudgeted::kNo, nullptr, 0));
bsalomon@google.comd4726202012-08-03 14:34:46 +0000304
bsalomone904c092014-07-17 10:50:59 -0700305 if (!dummyTexture1 || ! dummyTexture2) {
joshualitt65171342014-10-09 07:25:36 -0700306 SkDebugf("Could not allocate dummy textures");
bsalomone904c092014-07-17 10:50:59 -0700307 return false;
308 }
309
joshualitt65171342014-10-09 07:25:36 -0700310 GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()};
311
joshualitt54e0c122014-11-19 09:38:51 -0800312 // dummy scissor state
bsalomon3e791242014-12-17 13:43:13 -0800313 GrScissorState scissor;
joshualitt54e0c122014-11-19 09:38:51 -0800314
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000315 SkRandom random;
bsalomonf3261af2016-04-05 10:57:13 -0700316 static const int NUM_TESTS = 1024;
joshualitt6c891102015-05-13 08:51:49 -0700317 for (int t = 0; t < NUM_TESTS; t++) {
joshualitt65171342014-10-09 07:25:36 -0700318 // setup random render target(can fail)
Brian Osman11052242016-10-27 14:47:55 -0400319 sk_sp<GrRenderTargetContext> renderTargetContext(random_render_target_context(
320 context, &random, context->caps()));
321 if (!renderTargetContext) {
322 SkDebugf("Could not allocate renderTargetContext");
joshualittf5883a62016-01-13 07:47:38 -0800323 return false;
324 }
robertphillips0dfa62c2015-11-16 06:23:31 -0800325
robertphillips28a838e2016-06-23 14:07:00 -0700326 GrPaint grPaint;
robertphillips82ec6e52016-05-19 14:01:05 -0700327
Brian Salomonf8334782017-01-03 09:42:58 -0500328 std::unique_ptr<GrDrawOp> op(GrRandomDrawOp(&random, context));
Brian Salomon1951f3d2016-12-09 16:07:12 -0500329 SkASSERT(op);
robertphillips82ec6e52016-05-19 14:01:05 -0700330
331 GrProcessorTestData ptd(&random, context, context->caps(),
Brian Osman11052242016-10-27 14:47:55 -0400332 renderTargetContext.get(), dummyTextures);
robertphillips28a838e2016-06-23 14:07:00 -0700333 set_random_color_coverage_stages(&grPaint, &ptd, maxStages);
334 set_random_xpf(&grPaint, &ptd);
335 bool snapToCenters = set_random_state(&grPaint, &random);
336 const GrUserStencilSettings* uss = get_random_stencil(&random);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500337 // We don't use kHW because we will hit an assertion if the render target is not
338 // multisampled
339 static constexpr GrAAType kAATypes[] = {GrAAType::kNone, GrAAType::kCoverage};
340 GrAAType aaType = kAATypes[random.nextULessThan(SK_ARRAY_COUNT(kAATypes))];
robertphillips82ec6e52016-05-19 14:01:05 -0700341
Brian Salomon82f44312017-01-11 13:42:54 -0500342 renderTargetContext->priv().testingOnly_addDrawOp(std::move(grPaint), aaType, std::move(op),
343 uss, snapToCenters);
bsalomon@google.comc3841b92012-08-02 18:11:43 +0000344 }
joshualitt6c891102015-05-13 08:51:49 -0700345 // Flush everything, test passes if flush is successful(ie, no asserts are hit, no crashes)
robertphillipsa13e2022015-11-11 12:01:09 -0800346 drawingManager->flush();
bsalomonb5b60322015-09-14 12:26:33 -0700347
348 // Validate that GrFPs work correctly without an input.
Brian Osman11052242016-10-27 14:47:55 -0400349 sk_sp<GrRenderTargetContext> renderTargetContext(context->makeRenderTargetContext(
350 SkBackingFit::kExact,
351 kRenderTargetWidth,
352 kRenderTargetHeight,
353 kRGBA_8888_GrPixelConfig,
354 nullptr));
355 if (!renderTargetContext) {
356 SkDebugf("Could not allocate a renderTargetContext");
robertphillips82ec6e52016-05-19 14:01:05 -0700357 return false;
358 }
359
bsalomonb5b60322015-09-14 12:26:33 -0700360 int fpFactoryCnt = GrProcessorTestFactory<GrFragmentProcessor>::Count();
361 for (int i = 0; i < fpFactoryCnt; ++i) {
362 // Since FP factories internally randomize, call each 10 times.
363 for (int j = 0; j < 10; ++j) {
Brian Salomonf8334782017-01-03 09:42:58 -0500364 std::unique_ptr<GrDrawOp> op(GrRandomDrawOp(&random, context));
Brian Salomon1951f3d2016-12-09 16:07:12 -0500365 SkASSERT(op);
robertphillips82ec6e52016-05-19 14:01:05 -0700366 GrProcessorTestData ptd(&random, context, context->caps(),
Brian Osman11052242016-10-27 14:47:55 -0400367 renderTargetContext.get(), dummyTextures);
robertphillips28a838e2016-06-23 14:07:00 -0700368 GrPaint grPaint;
Brian Salomona1633922017-01-09 11:46:10 -0500369 grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
bsalomonb5b60322015-09-14 12:26:33 -0700370
bungeman06ca8ec2016-06-09 08:01:03 -0700371 sk_sp<GrFragmentProcessor> fp(
372 GrProcessorTestFactory<GrFragmentProcessor>::MakeIdx(i, &ptd));
373 sk_sp<GrFragmentProcessor> blockFP(
374 BlockInputFragmentProcessor::Make(std::move(fp)));
robertphillips28a838e2016-06-23 14:07:00 -0700375 grPaint.addColorFragmentProcessor(std::move(blockFP));
bsalomonb5b60322015-09-14 12:26:33 -0700376
Brian Salomon82f44312017-01-11 13:42:54 -0500377 renderTargetContext->priv().testingOnly_addDrawOp(std::move(grPaint), GrAAType::kNone,
Brian Salomon1951f3d2016-12-09 16:07:12 -0500378 std::move(op));
robertphillipsa13e2022015-11-11 12:01:09 -0800379 drawingManager->flush();
bsalomonb5b60322015-09-14 12:26:33 -0700380 }
381 }
382
bsalomon@google.comc3841b92012-08-02 18:11:43 +0000383 return true;
384}
bsalomon@google.coma8e686e2011-08-16 15:45:58 +0000385
kkinnunen3e980c32015-12-23 01:33:00 -0800386static int get_glprograms_max_stages(GrContext* context) {
387 GrGLGpu* gpu = static_cast<GrGLGpu*>(context->getGpu());
388 /*
389 * For the time being, we only support the test with desktop GL or for android on
390 * ARM platforms
391 * TODO When we run ES 3.00 GLSL in more places, test again
392 */
393 if (kGL_GrGLStandard == gpu->glStandard() ||
394 kARM_GrGLVendor == gpu->ctxInfo().vendor()) {
395 return 6;
396 } else if (kTegra3_GrGLRenderer == gpu->ctxInfo().renderer() ||
397 kOther_GrGLRenderer == gpu->ctxInfo().renderer()) {
398 return 1;
399 }
400 return 0;
401}
402
bsalomonf2f1c172016-04-05 12:59:06 -0700403static void test_glprograms_native(skiatest::Reporter* reporter,
404 const sk_gpu_test::ContextInfo& ctxInfo) {
bsalomon8b7451a2016-05-11 06:33:06 -0700405 int maxStages = get_glprograms_max_stages(ctxInfo.grContext());
kkinnunen3e980c32015-12-23 01:33:00 -0800406 if (maxStages == 0) {
407 return;
408 }
bsalomon8b7451a2016-05-11 06:33:06 -0700409 REPORTER_ASSERT(reporter, GrDrawingManager::ProgramUnitTest(ctxInfo.grContext(), maxStages));
kkinnunen3e980c32015-12-23 01:33:00 -0800410}
411
bsalomonf2f1c172016-04-05 12:59:06 -0700412static void test_glprograms_other_contexts(
413 skiatest::Reporter* reporter,
414 const sk_gpu_test::ContextInfo& ctxInfo) {
bsalomon8b7451a2016-05-11 06:33:06 -0700415 int maxStages = get_glprograms_max_stages(ctxInfo.grContext());
kkinnunen3e980c32015-12-23 01:33:00 -0800416#ifdef SK_BUILD_FOR_WIN
417 // Some long shaders run out of temporary registers in the D3D compiler on ANGLE and
418 // command buffer.
419 maxStages = SkTMin(maxStages, 2);
420#endif
421 if (maxStages == 0) {
422 return;
423 }
bsalomon8b7451a2016-05-11 06:33:06 -0700424 REPORTER_ASSERT(reporter, GrDrawingManager::ProgramUnitTest(ctxInfo.grContext(), maxStages));
kkinnunen3e980c32015-12-23 01:33:00 -0800425}
426
bsalomon758586c2016-04-06 14:02:39 -0700427static bool is_native_gl_context_type(sk_gpu_test::GrContextFactory::ContextType type) {
428 return type == sk_gpu_test::GrContextFactory::kNativeGL_ContextType;
429}
430
431static bool is_other_rendering_gl_context_type(sk_gpu_test::GrContextFactory::ContextType type) {
432 return !is_native_gl_context_type(type) &&
433 kOpenGL_GrBackend == sk_gpu_test::GrContextFactory::ContextTypeBackend(type) &&
434 sk_gpu_test::GrContextFactory::IsRenderingContext(type);
435}
436
kkinnunen3e980c32015-12-23 01:33:00 -0800437DEF_GPUTEST(GLPrograms, reporter, /*factory*/) {
bsalomon3318ee72015-03-16 11:56:29 -0700438 // Set a locale that would cause shader compilation to fail because of , as decimal separator.
439 // skbug 3330
440#ifdef SK_BUILD_FOR_WIN
441 GrAutoLocaleSetter als("sv-SE");
442#else
443 GrAutoLocaleSetter als("sv_SE.UTF-8");
444#endif
445
joshualitt6c891102015-05-13 08:51:49 -0700446 // We suppress prints to avoid spew
bsalomon682c2692015-05-22 14:01:46 -0700447 GrContextOptions opts;
joshualitt6c891102015-05-13 08:51:49 -0700448 opts.fSuppressPrints = true;
bsalomon3724e572016-03-30 18:56:19 -0700449 sk_gpu_test::GrContextFactory debugFactory(opts);
bsalomon758586c2016-04-06 14:02:39 -0700450 skiatest::RunWithGPUTestContexts(test_glprograms_native, &is_native_gl_context_type,
kkinnunen3e980c32015-12-23 01:33:00 -0800451 reporter, &debugFactory);
452 skiatest::RunWithGPUTestContexts(test_glprograms_other_contexts,
bsalomon758586c2016-04-06 14:02:39 -0700453 &is_other_rendering_gl_context_type, reporter, &debugFactory);
bsalomon@google.coma8e686e2011-08-16 15:45:58 +0000454}
455
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000456#endif