| 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 |