OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 // This is a GPU-backend specific test. It relies on static intializers to work | 9 // This is a GPU-backend specific test. It relies on static intializers to work |
10 | 10 |
11 #include "SkTypes.h" | 11 #include "SkTypes.h" |
12 | 12 |
13 #if SK_SUPPORT_GPU && SK_ALLOW_STATIC_GLOBAL_INITIALIZERS | 13 #if SK_SUPPORT_GPU && SK_ALLOW_STATIC_GLOBAL_INITIALIZERS |
14 | 14 |
15 #include "GrAutoLocaleSetter.h" | 15 #include "GrAutoLocaleSetter.h" |
| 16 #include "GrBatch.h" |
| 17 #include "GrBatchTest.h" |
16 #include "GrContextFactory.h" | 18 #include "GrContextFactory.h" |
17 #include "GrInvariantOutput.h" | 19 #include "GrInvariantOutput.h" |
18 #include "GrPipeline.h" | 20 #include "GrPipeline.h" |
19 #include "GrTest.h" | 21 #include "GrTest.h" |
20 #include "GrXferProcessor.h" | 22 #include "GrXferProcessor.h" |
21 #include "SkChecksum.h" | 23 #include "SkChecksum.h" |
22 #include "SkRandom.h" | 24 #include "SkRandom.h" |
23 #include "Test.h" | 25 #include "Test.h" |
24 #include "effects/GrConfigConversionEffect.h" | 26 #include "effects/GrConfigConversionEffect.h" |
25 #include "effects/GrPorterDuffXferProcessor.h" | 27 #include "effects/GrPorterDuffXferProcessor.h" |
26 #include "gl/GrGLGpu.h" | 28 #include "gl/GrGLGpu.h" |
27 #include "gl/GrGLPathRendering.h" | 29 #include "gl/GrGLPathRendering.h" |
28 #include "gl/builders/GrGLProgramBuilder.h" | 30 #include "gl/builders/GrGLProgramBuilder.h" |
29 | 31 |
30 /* | 32 /* |
31 * A dummy processor which just tries to insert a massive key and verify that it
can retrieve the | 33 * A dummy processor which just tries to insert a massive key and verify that it
can retrieve the |
32 * whole thing correctly | 34 * whole thing correctly |
33 */ | 35 */ |
34 static const uint32_t kMaxKeySize = 1024; | 36 static const uint32_t kMaxKeySize = 1024; |
35 | 37 |
36 class GLBigKeyProcessor : public GrGLFragmentProcessor { | 38 class GLBigKeyProcessor : public GrGLFragmentProcessor { |
37 public: | 39 public: |
38 GLBigKeyProcessor(const GrProcessor&) {} | 40 GLBigKeyProcessor(const GrProcessor&) {} |
39 | 41 |
40 virtual void emitCode(GrGLFPBuilder* builder, | 42 virtual void emitCode(GrGLFPBuilder* builder, |
41 const GrFragmentProcessor& fp, | 43 const GrFragmentProcessor& fp, |
42 const char* outputColor, | 44 const char* outputColor, |
43 const char* inputColor, | 45 const char* inputColor, |
44 const TransformedCoordsArray&, | 46 const TransformedCoordsArray&, |
45 const TextureSamplerArray&) {} | 47 const TextureSamplerArray&) { |
| 48 // pass through |
| 49 GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); |
| 50 fsBuilder->codeAppendf("%s = %s;\n", outputColor, inputColor); |
| 51 } |
46 | 52 |
47 static void GenKey(const GrProcessor& processor, const GrGLSLCaps&, GrProces
sorKeyBuilder* b) { | 53 static void GenKey(const GrProcessor& processor, const GrGLSLCaps&, GrProces
sorKeyBuilder* b) { |
48 for (uint32_t i = 0; i < kMaxKeySize; i++) { | 54 for (uint32_t i = 0; i < kMaxKeySize; i++) { |
49 b->add32(i); | 55 b->add32(i); |
50 } | 56 } |
51 } | 57 } |
52 | 58 |
53 private: | 59 private: |
54 typedef GrGLFragmentProcessor INHERITED; | 60 typedef GrGLFragmentProcessor INHERITED; |
55 }; | 61 }; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 static GrRenderTarget* random_render_target(GrContext* context, SkRandom* random
) { | 108 static GrRenderTarget* random_render_target(GrContext* context, SkRandom* random
) { |
103 // setup render target | 109 // setup render target |
104 GrTextureParams params; | 110 GrTextureParams params; |
105 GrSurfaceDesc texDesc; | 111 GrSurfaceDesc texDesc; |
106 texDesc.fWidth = kRenderTargetWidth; | 112 texDesc.fWidth = kRenderTargetWidth; |
107 texDesc.fHeight = kRenderTargetHeight; | 113 texDesc.fHeight = kRenderTargetHeight; |
108 texDesc.fFlags = kRenderTarget_GrSurfaceFlag; | 114 texDesc.fFlags = kRenderTarget_GrSurfaceFlag; |
109 texDesc.fConfig = kRGBA_8888_GrPixelConfig; | 115 texDesc.fConfig = kRGBA_8888_GrPixelConfig; |
110 texDesc.fOrigin = random->nextBool() == true ? kTopLeft_GrSurfaceOrigin : | 116 texDesc.fOrigin = random->nextBool() == true ? kTopLeft_GrSurfaceOrigin : |
111 kBottomLeft_GrSurfaceOrigin; | 117 kBottomLeft_GrSurfaceOrigin; |
| 118 texDesc.fSampleCnt = random->nextBool() == true ? 4 : 0; |
| 119 |
112 GrUniqueKey key; | 120 GrUniqueKey key; |
113 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); | 121 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); |
114 GrUniqueKey::Builder builder(&key, kDomain, 1); | 122 GrUniqueKey::Builder builder(&key, kDomain, 2); |
115 builder[0] = texDesc.fOrigin; | 123 builder[0] = texDesc.fOrigin; |
| 124 builder[1] = texDesc.fSampleCnt; |
116 builder.finish(); | 125 builder.finish(); |
117 | 126 |
118 GrTexture* texture = context->textureProvider()->findAndRefTextureByUniqueKe
y(key); | 127 GrTexture* texture = context->textureProvider()->findAndRefTextureByUniqueKe
y(key); |
119 if (!texture) { | 128 if (!texture) { |
120 texture = context->textureProvider()->createTexture(texDesc, true); | 129 texture = context->textureProvider()->createTexture(texDesc, true); |
121 if (texture) { | 130 if (texture) { |
122 context->textureProvider()->assignUniqueKeyToTexture(key, texture); | 131 context->textureProvider()->assignUniqueKeyToTexture(key, texture); |
123 } | 132 } |
124 } | 133 } |
125 return texture ? texture->asRenderTarget() : NULL; | 134 return texture ? texture->asRenderTarget() : NULL; |
126 } | 135 } |
127 | 136 |
128 static void set_random_xpf(GrContext* context, const GrDrawTargetCaps& caps, | 137 static void set_random_xpf(GrContext* context, const GrDrawTargetCaps& caps, |
129 GrPipelineBuilder* pipelineBuilder, SkRandom* random, | 138 GrPipelineBuilder* pipelineBuilder, SkRandom* random, |
130 GrTexture* dummyTextures[]) { | 139 GrTexture* dummyTextures[]) { |
131 SkAutoTUnref<const GrXPFactory> xpf( | 140 SkAutoTUnref<const GrXPFactory> xpf( |
132 GrProcessorTestFactory<GrXPFactory>::CreateStage(random, context, caps,
dummyTextures)); | 141 GrProcessorTestFactory<GrXPFactory>::CreateStage(random, context, caps,
dummyTextures)); |
133 SkASSERT(xpf); | 142 SkASSERT(xpf); |
134 pipelineBuilder->setXPFactory(xpf.get()); | 143 pipelineBuilder->setXPFactory(xpf.get()); |
135 } | 144 } |
136 | 145 |
137 static const GrGeometryProcessor* get_random_gp(GrContext* context, | |
138 const GrDrawTargetCaps& caps, | |
139 SkRandom* random, | |
140 GrTexture* dummyTextures[]) { | |
141 return GrProcessorTestFactory<GrGeometryProcessor>::CreateStage(random, | |
142 context, | |
143 caps, | |
144 dummyTexture
s); | |
145 } | |
146 | |
147 static void set_random_color_coverage_stages(GrGLGpu* gpu, | 146 static void set_random_color_coverage_stages(GrGLGpu* gpu, |
148 GrPipelineBuilder* pipelineBuilder, | 147 GrPipelineBuilder* pipelineBuilder, |
149 int maxStages, | 148 int maxStages, |
150 bool usePathRendering, | |
151 SkRandom* random, | 149 SkRandom* random, |
152 GrTexture* dummyTextures[]) { | 150 GrTexture* dummyTextures[]) { |
153 int numProcs = random->nextULessThan(maxStages + 1); | 151 int numProcs = random->nextULessThan(maxStages + 1); |
154 int numColorProcs = random->nextULessThan(numProcs + 1); | 152 int numColorProcs = random->nextULessThan(numProcs + 1); |
155 | 153 |
156 for (int s = 0; s < numProcs;) { | 154 for (int s = 0; s < numProcs;) { |
157 SkAutoTUnref<const GrFragmentProcessor> fp( | 155 SkAutoTUnref<const GrFragmentProcessor> fp( |
158 GrProcessorTestFactory<GrFragmentProcessor>::CreateStage(random, | 156 GrProcessorTestFactory<GrFragmentProcessor>::CreateStage(random, |
159 gpu->ge
tContext(), | 157 gpu->ge
tContext(), |
160 *gpu->c
aps(), | 158 *gpu->c
aps(), |
161 dummyTe
xtures)); | 159 dummyTe
xtures)); |
162 SkASSERT(fp); | 160 SkASSERT(fp); |
163 | 161 |
164 // finally add the stage to the correct pipeline in the drawstate | 162 // finally add the stage to the correct pipeline in the drawstate |
165 if (s < numColorProcs) { | 163 if (s < numColorProcs) { |
166 pipelineBuilder->addColorProcessor(fp); | 164 pipelineBuilder->addColorProcessor(fp); |
167 } else { | 165 } else { |
168 pipelineBuilder->addCoverageProcessor(fp); | 166 pipelineBuilder->addCoverageProcessor(fp); |
169 } | 167 } |
170 ++s; | 168 ++s; |
171 } | 169 } |
172 } | 170 } |
173 | 171 |
174 static void set_random_state(GrPipelineBuilder* pipelineBuilder, SkRandom* rando
m) { | 172 static void set_random_state(GrPipelineBuilder* pipelineBuilder, SkRandom* rando
m) { |
175 int state = 0; | 173 int state = 0; |
176 for (int i = 1; i <= GrPipelineBuilder::kLast_Flag; i <<= 1) { | 174 for (int i = 1; i <= GrPipelineBuilder::kLast_Flag; i <<= 1) { |
177 state |= random->nextBool() * i; | 175 state |= random->nextBool() * i; |
178 } | 176 } |
| 177 |
| 178 // If we don't have an MSAA rendertarget then we have to disable useHWAA |
| 179 if ((state | GrPipelineBuilder::kHWAntialias_Flag) && |
| 180 !pipelineBuilder->getRenderTarget()->isMultisampled()) { |
| 181 state &= ~GrPipelineBuilder::kHWAntialias_Flag; |
| 182 } |
179 pipelineBuilder->enableState(state); | 183 pipelineBuilder->enableState(state); |
180 } | 184 } |
181 | 185 |
182 // right now, the only thing we seem to care about in drawState's stencil is 'do
esWrite()' | 186 // right now, the only thing we seem to care about in drawState's stencil is 'do
esWrite()' |
183 static void set_random_stencil(GrPipelineBuilder* pipelineBuilder, SkRandom* ran
dom) { | 187 static void set_random_stencil(GrPipelineBuilder* pipelineBuilder, SkRandom* ran
dom) { |
184 GR_STATIC_CONST_SAME_STENCIL(kDoesWriteStencil, | 188 GR_STATIC_CONST_SAME_STENCIL(kDoesWriteStencil, |
185 kReplace_StencilOp, | 189 kReplace_StencilOp, |
186 kReplace_StencilOp, | 190 kReplace_StencilOp, |
187 kAlways_StencilFunc, | 191 kAlways_StencilFunc, |
188 0xffff, | 192 0xffff, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 if (!dummyTexture1 || ! dummyTexture2) { | 225 if (!dummyTexture1 || ! dummyTexture2) { |
222 SkDebugf("Could not allocate dummy textures"); | 226 SkDebugf("Could not allocate dummy textures"); |
223 return false; | 227 return false; |
224 } | 228 } |
225 | 229 |
226 GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()}; | 230 GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()}; |
227 | 231 |
228 // dummy scissor state | 232 // dummy scissor state |
229 GrScissorState scissor; | 233 GrScissorState scissor; |
230 | 234 |
231 // setup clip | 235 // wide open clip |
232 SkRect screen = SkRect::MakeWH(SkIntToScalar(kRenderTargetWidth), | |
233 SkIntToScalar(kRenderTargetHeight)); | |
234 | |
235 SkClipStack stack; | |
236 stack.clipDevRect(screen, SkRegion::kReplace_Op, false); | |
237 | |
238 // wrap the SkClipStack in a GrClip | |
239 GrClip clip; | 236 GrClip clip; |
240 clip.setClipStack(&stack); | |
241 | 237 |
242 SkRandom random; | 238 SkRandom random; |
243 static const int NUM_TESTS = 512; | 239 static const int NUM_TESTS = 2048; |
244 for (int t = 0; t < NUM_TESTS;) { | 240 for (int t = 0; t < NUM_TESTS; t++) { |
245 // setup random render target(can fail) | 241 // setup random render target(can fail) |
246 SkAutoTUnref<GrRenderTarget> rt(random_render_target(fContext, &random))
; | 242 SkAutoTUnref<GrRenderTarget> rt(random_render_target(fContext, &random))
; |
247 if (!rt.get()) { | 243 if (!rt.get()) { |
248 SkDebugf("Could not allocate render target"); | 244 SkDebugf("Could not allocate render target"); |
249 return false; | 245 return false; |
250 } | 246 } |
251 | 247 |
252 GrPipelineBuilder pipelineBuilder; | 248 GrPipelineBuilder pipelineBuilder; |
253 pipelineBuilder.setRenderTarget(rt.get()); | 249 pipelineBuilder.setRenderTarget(rt.get()); |
254 pipelineBuilder.setClip(clip); | 250 pipelineBuilder.setClip(clip); |
255 | 251 |
256 // if path rendering we have to setup a couple of things like the draw t
ype | 252 SkAutoTUnref<GrBatch> batch(GrRandomBatch(&random, fContext)); |
257 bool usePathRendering = gpu->glCaps().shaderCaps()->pathRenderingSupport
() && | 253 SkASSERT(batch); |
258 random.nextBool(); | |
259 | 254 |
260 // twiddle drawstate knobs randomly | |
261 bool hasGeometryProcessor = !usePathRendering; | |
262 SkAutoTUnref<const GrGeometryProcessor> gp; | |
263 SkAutoTUnref<const GrPathProcessor> pathProc; | |
264 if (hasGeometryProcessor) { | |
265 gp.reset(get_random_gp(fContext, gpu->glCaps(), &random, dummyTextur
es)); | |
266 } else { | |
267 pathProc.reset(GrPathProcessor::Create(GrColor_WHITE)); | |
268 } | |
269 set_random_color_coverage_stages(gpu, | 255 set_random_color_coverage_stages(gpu, |
270 &pipelineBuilder, | 256 &pipelineBuilder, |
271 maxStages - hasGeometryProcessor, | 257 maxStages, |
272 usePathRendering, | |
273 &random, | 258 &random, |
274 dummyTextures); | 259 dummyTextures); |
275 | 260 |
276 // creates a random xfer processor factory on the draw state | 261 // creates a random xfer processor factory on the draw state |
277 set_random_xpf(fContext, gpu->glCaps(), &pipelineBuilder, &random, dummy
Textures); | 262 set_random_xpf(fContext, gpu->glCaps(), &pipelineBuilder, &random, dummy
Textures); |
278 | 263 |
279 set_random_state(&pipelineBuilder, &random); | 264 set_random_state(&pipelineBuilder, &random); |
280 set_random_stencil(&pipelineBuilder, &random); | 265 set_random_stencil(&pipelineBuilder, &random); |
281 | 266 |
282 GrDeviceCoordTexture dstCopy; | 267 this->drawBatch(&pipelineBuilder, batch); |
| 268 } |
283 | 269 |
284 const GrPrimitiveProcessor* primProc; | 270 // Flush everything, test passes if flush is successful(ie, no asserts are h
it, no crashes) |
285 if (hasGeometryProcessor) { | 271 this->flush(); |
286 primProc = gp.get(); | |
287 } else { | |
288 primProc = pathProc.get(); | |
289 } | |
290 | |
291 const GrProcOptInfo& colorPOI = pipelineBuilder.colorProcInfo(primProc); | |
292 const GrProcOptInfo& coveragePOI = pipelineBuilder.coverageProcInfo(prim
Proc); | |
293 | |
294 if (!this->setupDstReadIfNecessary(pipelineBuilder, colorPOI, coveragePO
I, &dstCopy, | |
295 NULL)) { | |
296 SkDebugf("Couldn't setup dst read texture"); | |
297 return false; | |
298 } | |
299 | |
300 // create optimized draw state, setup readDst texture if required, and b
uild a descriptor | |
301 // and program. ODS creation can fail, so we have to check | |
302 GrPipeline pipeline(pipelineBuilder, colorPOI, coveragePOI, | |
303 *gpu->caps(), scissor, &dstCopy); | |
304 if (pipeline.mustSkip()) { | |
305 continue; | |
306 } | |
307 | |
308 GrXferBarrierType barrierType; | |
309 if (pipeline.getXferProcessor()->willNeedXferBarrier(rt, *gpu->caps(), &
barrierType)) { | |
310 gpu->xferBarrier(barrierType); | |
311 } | |
312 | |
313 GrBatchTracker bt; | |
314 primProc->initBatchTracker(&bt, pipeline.getInitBatchTracker()); | |
315 | |
316 GrProgramDesc desc; | |
317 gpu->buildProgramDesc(&desc, *primProc, pipeline, bt); | |
318 | |
319 GrGpu::DrawArgs args(primProc, &pipeline, &desc, &bt); | |
320 SkAutoTUnref<GrGLProgram> program(GrGLProgramBuilder::CreateProgram(args
, gpu)); | |
321 | |
322 if (NULL == program.get()) { | |
323 SkDebugf("Failed to create program!"); | |
324 return false; | |
325 } | |
326 | |
327 // because occasionally optimized drawstate creation will fail for valid
reasons, we only | |
328 // want to increment on success | |
329 ++t; | |
330 } | |
331 return true; | 272 return true; |
332 } | 273 } |
333 | 274 |
334 DEF_GPUTEST(GLPrograms, reporter, factory) { | 275 DEF_GPUTEST(GLPrograms, reporter, factory) { |
335 // Set a locale that would cause shader compilation to fail because of , as
decimal separator. | 276 // Set a locale that would cause shader compilation to fail because of , as
decimal separator. |
336 // skbug 3330 | 277 // skbug 3330 |
337 #ifdef SK_BUILD_FOR_WIN | 278 #ifdef SK_BUILD_FOR_WIN |
338 GrAutoLocaleSetter als("sv-SE"); | 279 GrAutoLocaleSetter als("sv-SE"); |
339 #else | 280 #else |
340 GrAutoLocaleSetter als("sv_SE.UTF-8"); | 281 GrAutoLocaleSetter als("sv_SE.UTF-8"); |
341 #endif | 282 #endif |
342 | 283 |
| 284 // We suppress prints to avoid spew |
| 285 GrContext::Options opts; |
| 286 opts.fSuppressPrints = true; |
| 287 GrContextFactory debugFactory(opts); |
343 for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) { | 288 for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) { |
344 GrContext* context = factory->get(static_cast<GrContextFactory::GLContex
tType>(type)); | 289 GrContext* context = debugFactory.get(static_cast<GrContextFactory::GLCo
ntextType>(type)); |
345 if (context) { | 290 if (context) { |
346 GrGLGpu* gpu = static_cast<GrGLGpu*>(context->getGpu()); | 291 GrGLGpu* gpu = static_cast<GrGLGpu*>(context->getGpu()); |
347 | 292 |
348 /* | 293 /* |
349 * For the time being, we only support the test with desktop GL or f
or android on | 294 * For the time being, we only support the test with desktop GL or f
or android on |
350 * ARM platforms | 295 * ARM platforms |
351 * TODO When we run ES 3.00 GLSL in more places, test again | 296 * TODO When we run ES 3.00 GLSL in more places, test again |
352 */ | 297 */ |
353 int maxStages; | 298 int maxStages; |
354 if (kGL_GrGLStandard == gpu->glStandard() || | 299 if (kGL_GrGLStandard == gpu->glStandard() || |
(...skipping 12 matching lines...) Expand all Loading... |
367 } | 312 } |
368 #endif | 313 #endif |
369 GrTestTarget target; | 314 GrTestTarget target; |
370 context->getTestTarget(&target); | 315 context->getTestTarget(&target); |
371 REPORTER_ASSERT(reporter, target.target()->programUnitTest(maxStages
)); | 316 REPORTER_ASSERT(reporter, target.target()->programUnitTest(maxStages
)); |
372 } | 317 } |
373 } | 318 } |
374 } | 319 } |
375 | 320 |
376 #endif | 321 #endif |
OLD | NEW |