| Index: tests/GLProgramsTest.cpp
|
| diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp
|
| index df932f359f74270d0188231bd6f01296429348e7..0ce6933afb7c8a20077072097b473b09e82f7d8c 100644
|
| --- a/tests/GLProgramsTest.cpp
|
| +++ b/tests/GLProgramsTest.cpp
|
| @@ -1,369 +1,369 @@
|
| -
|
| -/*
|
| - * Copyright 2011 Google Inc.
|
| - *
|
| - * Use of this source code is governed by a BSD-style license that can be
|
| - * found in the LICENSE file.
|
| - */
|
| -
|
| -// This is a GPU-backend specific test. It relies on static intializers to work
|
| -
|
| -#include "SkTypes.h"
|
| -
|
| -#if SK_SUPPORT_GPU && SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
|
| -
|
| -#include "GrAutoLocaleSetter.h"
|
| -#include "GrContextFactory.h"
|
| -#include "GrInvariantOutput.h"
|
| -#include "GrPipeline.h"
|
| -#include "GrTest.h"
|
| -#include "GrXferProcessor.h"
|
| -#include "SkChecksum.h"
|
| -#include "SkRandom.h"
|
| -#include "Test.h"
|
| -#include "effects/GrConfigConversionEffect.h"
|
| -#include "effects/GrPorterDuffXferProcessor.h"
|
| -#include "gl/GrGLGpu.h"
|
| -#include "gl/GrGLPathRendering.h"
|
| -#include "gl/builders/GrGLProgramBuilder.h"
|
| -
|
| -/*
|
| - * A dummy processor which just tries to insert a massive key and verify that it can retrieve the
|
| - * whole thing correctly
|
| - */
|
| -static const uint32_t kMaxKeySize = 1024;
|
| -
|
| -class GLBigKeyProcessor : public GrGLFragmentProcessor {
|
| -public:
|
| - GLBigKeyProcessor(const GrProcessor&) {}
|
| -
|
| - virtual void emitCode(GrGLFPBuilder* builder,
|
| - const GrFragmentProcessor& fp,
|
| - const char* outputColor,
|
| - const char* inputColor,
|
| - const TransformedCoordsArray&,
|
| - const TextureSamplerArray&) {}
|
| -
|
| - static void GenKey(const GrProcessor& processor, const GrGLCaps&, GrProcessorKeyBuilder* b) {
|
| - for (uint32_t i = 0; i < kMaxKeySize; i++) {
|
| - b->add32(i);
|
| - }
|
| - }
|
| -
|
| -private:
|
| - typedef GrGLFragmentProcessor INHERITED;
|
| -};
|
| -
|
| -class BigKeyProcessor : public GrFragmentProcessor {
|
| -public:
|
| - static GrFragmentProcessor* Create() {
|
| - GR_CREATE_STATIC_PROCESSOR(gBigKeyProcessor, BigKeyProcessor, ())
|
| - return SkRef(gBigKeyProcessor);
|
| - }
|
| -
|
| - const char* name() const override { return "Big Ole Key"; }
|
| -
|
| - virtual void getGLProcessorKey(const GrGLCaps& caps,
|
| - GrProcessorKeyBuilder* b) const override {
|
| - GLBigKeyProcessor::GenKey(*this, caps, b);
|
| - }
|
| -
|
| - GrGLFragmentProcessor* createGLInstance() const override {
|
| - return SkNEW_ARGS(GLBigKeyProcessor, (*this));
|
| - }
|
| -
|
| -private:
|
| - BigKeyProcessor() {
|
| - this->initClassID<BigKeyProcessor>();
|
| - }
|
| - bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
|
| - void onComputeInvariantOutput(GrInvariantOutput* inout) const override { }
|
| -
|
| - GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
|
| -
|
| - typedef GrFragmentProcessor INHERITED;
|
| -};
|
| -
|
| -GR_DEFINE_FRAGMENT_PROCESSOR_TEST(BigKeyProcessor);
|
| -
|
| -GrFragmentProcessor* BigKeyProcessor::TestCreate(SkRandom*,
|
| - GrContext*,
|
| - const GrDrawTargetCaps&,
|
| - GrTexture*[]) {
|
| - return BigKeyProcessor::Create();
|
| -}
|
| -
|
| -/*
|
| - * Begin test code
|
| - */
|
| -static const int kRenderTargetHeight = 1;
|
| -static const int kRenderTargetWidth = 1;
|
| -
|
| -static GrRenderTarget* random_render_target(GrContext* context, SkRandom* random) {
|
| - // setup render target
|
| - GrTextureParams params;
|
| - GrSurfaceDesc texDesc;
|
| - texDesc.fWidth = kRenderTargetWidth;
|
| - texDesc.fHeight = kRenderTargetHeight;
|
| - texDesc.fFlags = kRenderTarget_GrSurfaceFlag;
|
| - texDesc.fConfig = kRGBA_8888_GrPixelConfig;
|
| - texDesc.fOrigin = random->nextBool() == true ? kTopLeft_GrSurfaceOrigin :
|
| - kBottomLeft_GrSurfaceOrigin;
|
| - GrUniqueKey key;
|
| - static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
|
| - GrUniqueKey::Builder builder(&key, kDomain, 1);
|
| - builder[0] = texDesc.fOrigin;
|
| - builder.finish();
|
| -
|
| - GrTexture* texture = context->findAndRefCachedTexture(key);
|
| - if (!texture) {
|
| - texture = context->createTexture(texDesc, true);
|
| - if (texture) {
|
| - context->addResourceToCache(key, texture);
|
| - }
|
| - }
|
| - return texture ? texture->asRenderTarget() : NULL;
|
| -}
|
| -
|
| -static void set_random_xpf(GrContext* context, const GrDrawTargetCaps& caps,
|
| - GrPipelineBuilder* pipelineBuilder, SkRandom* random,
|
| - GrTexture* dummyTextures[]) {
|
| - SkAutoTUnref<const GrXPFactory> xpf(
|
| - GrProcessorTestFactory<GrXPFactory>::CreateStage(random, context, caps, dummyTextures));
|
| - SkASSERT(xpf);
|
| - pipelineBuilder->setXPFactory(xpf.get());
|
| -}
|
| -
|
| -static const GrGeometryProcessor* get_random_gp(GrContext* context,
|
| - const GrDrawTargetCaps& caps,
|
| - SkRandom* random,
|
| - GrTexture* dummyTextures[]) {
|
| - return GrProcessorTestFactory<GrGeometryProcessor>::CreateStage(random,
|
| - context,
|
| - caps,
|
| - dummyTextures);
|
| -}
|
| -
|
| -static void set_random_color_coverage_stages(GrGLGpu* gpu,
|
| - GrPipelineBuilder* pipelineBuilder,
|
| - int maxStages,
|
| - bool usePathRendering,
|
| - SkRandom* random,
|
| - GrTexture* dummyTextures[]) {
|
| - int numProcs = random->nextULessThan(maxStages + 1);
|
| - int numColorProcs = random->nextULessThan(numProcs + 1);
|
| -
|
| - for (int s = 0; s < numProcs;) {
|
| - SkAutoTUnref<const GrFragmentProcessor> fp(
|
| - GrProcessorTestFactory<GrFragmentProcessor>::CreateStage(random,
|
| - gpu->getContext(),
|
| - *gpu->caps(),
|
| - dummyTextures));
|
| - SkASSERT(fp);
|
| -
|
| - // finally add the stage to the correct pipeline in the drawstate
|
| - if (s < numColorProcs) {
|
| - pipelineBuilder->addColorProcessor(fp);
|
| - } else {
|
| - pipelineBuilder->addCoverageProcessor(fp);
|
| - }
|
| - ++s;
|
| - }
|
| -}
|
| -
|
| -static void set_random_state(GrPipelineBuilder* pipelineBuilder, SkRandom* random) {
|
| - int state = 0;
|
| - for (int i = 1; i <= GrPipelineBuilder::kLast_Flag; i <<= 1) {
|
| - state |= random->nextBool() * i;
|
| - }
|
| - pipelineBuilder->enableState(state);
|
| -}
|
| -
|
| -// right now, the only thing we seem to care about in drawState's stencil is 'doesWrite()'
|
| -static void set_random_stencil(GrPipelineBuilder* pipelineBuilder, SkRandom* random) {
|
| - GR_STATIC_CONST_SAME_STENCIL(kDoesWriteStencil,
|
| - kReplace_StencilOp,
|
| - kReplace_StencilOp,
|
| - kAlways_StencilFunc,
|
| - 0xffff,
|
| - 0xffff,
|
| - 0xffff);
|
| - GR_STATIC_CONST_SAME_STENCIL(kDoesNotWriteStencil,
|
| - kKeep_StencilOp,
|
| - kKeep_StencilOp,
|
| - kNever_StencilFunc,
|
| - 0xffff,
|
| - 0xffff,
|
| - 0xffff);
|
| -
|
| - if (random->nextBool()) {
|
| - pipelineBuilder->setStencil(kDoesWriteStencil);
|
| - } else {
|
| - pipelineBuilder->setStencil(kDoesNotWriteStencil);
|
| - }
|
| -}
|
| -
|
| -bool GrDrawTarget::programUnitTest(int maxStages) {
|
| - GrGLGpu* gpu = static_cast<GrGLGpu*>(fContext->getGpu());
|
| - // setup dummy textures
|
| - GrSurfaceDesc dummyDesc;
|
| - dummyDesc.fFlags = kRenderTarget_GrSurfaceFlag;
|
| - dummyDesc.fConfig = kSkia8888_GrPixelConfig;
|
| - dummyDesc.fWidth = 34;
|
| - dummyDesc.fHeight = 18;
|
| - SkAutoTUnref<GrTexture> dummyTexture1(gpu->createTexture(dummyDesc, false, NULL, 0));
|
| - dummyDesc.fFlags = kNone_GrSurfaceFlags;
|
| - dummyDesc.fConfig = kAlpha_8_GrPixelConfig;
|
| - dummyDesc.fWidth = 16;
|
| - dummyDesc.fHeight = 22;
|
| - SkAutoTUnref<GrTexture> dummyTexture2(gpu->createTexture(dummyDesc, false, NULL, 0));
|
| -
|
| - if (!dummyTexture1 || ! dummyTexture2) {
|
| - SkDebugf("Could not allocate dummy textures");
|
| - return false;
|
| - }
|
| -
|
| - GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()};
|
| -
|
| - // dummy scissor state
|
| - GrScissorState scissor;
|
| -
|
| - // setup clip
|
| - SkRect screen = SkRect::MakeWH(SkIntToScalar(kRenderTargetWidth),
|
| - SkIntToScalar(kRenderTargetHeight));
|
| -
|
| - SkClipStack stack;
|
| - stack.clipDevRect(screen, SkRegion::kReplace_Op, false);
|
| -
|
| - // wrap the SkClipStack in a GrClip
|
| - GrClip clip;
|
| - clip.setClipStack(&stack);
|
| -
|
| - SkRandom random;
|
| - static const int NUM_TESTS = 512;
|
| - for (int t = 0; t < NUM_TESTS;) {
|
| - // setup random render target(can fail)
|
| - SkAutoTUnref<GrRenderTarget> rt(random_render_target(fContext, &random));
|
| - if (!rt.get()) {
|
| - SkDebugf("Could not allocate render target");
|
| - return false;
|
| - }
|
| -
|
| - GrPipelineBuilder pipelineBuilder;
|
| - pipelineBuilder.setRenderTarget(rt.get());
|
| - pipelineBuilder.setClip(clip);
|
| -
|
| - // if path rendering we have to setup a couple of things like the draw type
|
| - bool usePathRendering = gpu->glCaps().pathRenderingSupport() && random.nextBool();
|
| -
|
| - // twiddle drawstate knobs randomly
|
| - bool hasGeometryProcessor = !usePathRendering;
|
| - SkAutoTUnref<const GrGeometryProcessor> gp;
|
| - SkAutoTUnref<const GrPathProcessor> pathProc;
|
| - if (hasGeometryProcessor) {
|
| - gp.reset(get_random_gp(fContext, gpu->glCaps(), &random, dummyTextures));
|
| - } else {
|
| - pathProc.reset(GrPathProcessor::Create(GrColor_WHITE));
|
| - }
|
| - set_random_color_coverage_stages(gpu,
|
| - &pipelineBuilder,
|
| - maxStages - hasGeometryProcessor,
|
| - usePathRendering,
|
| - &random,
|
| - dummyTextures);
|
| -
|
| - // creates a random xfer processor factory on the draw state
|
| - set_random_xpf(fContext, gpu->glCaps(), &pipelineBuilder, &random, dummyTextures);
|
| -
|
| - set_random_state(&pipelineBuilder, &random);
|
| - set_random_stencil(&pipelineBuilder, &random);
|
| -
|
| - GrDeviceCoordTexture dstCopy;
|
| -
|
| - const GrPrimitiveProcessor* primProc;
|
| - if (hasGeometryProcessor) {
|
| - primProc = gp.get();
|
| - } else {
|
| - primProc = pathProc.get();
|
| - }
|
| -
|
| - const GrProcOptInfo& colorPOI = pipelineBuilder.colorProcInfo(primProc);
|
| - const GrProcOptInfo& coveragePOI = pipelineBuilder.coverageProcInfo(primProc);
|
| -
|
| - if (!this->setupDstReadIfNecessary(pipelineBuilder, colorPOI, coveragePOI, &dstCopy,
|
| - NULL)) {
|
| - SkDebugf("Couldn't setup dst read texture");
|
| - return false;
|
| - }
|
| -
|
| - // create optimized draw state, setup readDst texture if required, and build a descriptor
|
| - // and program. ODS creation can fail, so we have to check
|
| - GrPipeline pipeline(pipelineBuilder, colorPOI, coveragePOI,
|
| - *gpu->caps(), scissor, &dstCopy);
|
| - if (pipeline.mustSkip()) {
|
| - continue;
|
| - }
|
| - GrBatchTracker bt;
|
| - primProc->initBatchTracker(&bt, pipeline.getInitBatchTracker());
|
| -
|
| - GrProgramDesc desc;
|
| - gpu->buildProgramDesc(&desc, *primProc, pipeline, bt);
|
| -
|
| - GrGpu::DrawArgs args(primProc, &pipeline, &desc, &bt);
|
| - SkAutoTUnref<GrGLProgram> program(GrGLProgramBuilder::CreateProgram(args, gpu));
|
| -
|
| - if (NULL == program.get()) {
|
| - SkDebugf("Failed to create program!");
|
| - return false;
|
| - }
|
| -
|
| - // because occasionally optimized drawstate creation will fail for valid reasons, we only
|
| - // want to increment on success
|
| - ++t;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -DEF_GPUTEST(GLPrograms, reporter, factory) {
|
| - // Set a locale that would cause shader compilation to fail because of , as decimal separator.
|
| - // skbug 3330
|
| -#ifdef SK_BUILD_FOR_WIN
|
| - GrAutoLocaleSetter als("sv-SE");
|
| -#else
|
| - GrAutoLocaleSetter als("sv_SE.UTF-8");
|
| -#endif
|
| -
|
| - for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
|
| - GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(type));
|
| - if (context) {
|
| - GrGLGpu* gpu = static_cast<GrGLGpu*>(context->getGpu());
|
| -
|
| - /*
|
| - * For the time being, we only support the test with desktop GL or for android on
|
| - * ARM platforms
|
| - * TODO When we run ES 3.00 GLSL in more places, test again
|
| - */
|
| - int maxStages;
|
| - if (kGL_GrGLStandard == gpu->glStandard() ||
|
| - kARM_GrGLVendor == gpu->ctxInfo().vendor()) {
|
| - maxStages = 6;
|
| - } else if (kTegra3_GrGLRenderer == gpu->ctxInfo().renderer() ||
|
| - kOther_GrGLRenderer == gpu->ctxInfo().renderer()) {
|
| - maxStages = 1;
|
| - } else {
|
| - return;
|
| - }
|
| -#if SK_ANGLE
|
| - // Some long shaders run out of temporary registers in the D3D compiler on ANGLE.
|
| - if (type == GrContextFactory::kANGLE_GLContextType) {
|
| - maxStages = 2;
|
| - }
|
| -#endif
|
| - GrTestTarget target;
|
| - context->getTestTarget(&target);
|
| - REPORTER_ASSERT(reporter, target.target()->programUnitTest(maxStages));
|
| - }
|
| - }
|
| -}
|
| -
|
| -#endif
|
| +
|
| +/*
|
| + * Copyright 2011 Google Inc.
|
| + *
|
| + * Use of this source code is governed by a BSD-style license that can be
|
| + * found in the LICENSE file.
|
| + */
|
| +
|
| +// This is a GPU-backend specific test. It relies on static intializers to work
|
| +
|
| +#include "SkTypes.h"
|
| +
|
| +#if SK_SUPPORT_GPU && SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
|
| +
|
| +#include "GrAutoLocaleSetter.h"
|
| +#include "GrContextFactory.h"
|
| +#include "GrInvariantOutput.h"
|
| +#include "GrPipeline.h"
|
| +#include "GrTest.h"
|
| +#include "GrXferProcessor.h"
|
| +#include "SkChecksum.h"
|
| +#include "SkRandom.h"
|
| +#include "Test.h"
|
| +#include "effects/GrConfigConversionEffect.h"
|
| +#include "effects/GrPorterDuffXferProcessor.h"
|
| +#include "gl/GrGLGpu.h"
|
| +#include "gl/GrGLPathRendering.h"
|
| +#include "gl/builders/GrGLProgramBuilder.h"
|
| +
|
| +/*
|
| + * A dummy processor which just tries to insert a massive key and verify that it can retrieve the
|
| + * whole thing correctly
|
| + */
|
| +static const uint32_t kMaxKeySize = 1024;
|
| +
|
| +class GLBigKeyProcessor : public GrGLFragmentProcessor {
|
| +public:
|
| + GLBigKeyProcessor(const GrProcessor&) {}
|
| +
|
| + virtual void emitCode(GrGLFPBuilder* builder,
|
| + const GrFragmentProcessor& fp,
|
| + const char* outputColor,
|
| + const char* inputColor,
|
| + const TransformedCoordsArray&,
|
| + const TextureSamplerArray&) {}
|
| +
|
| + static void GenKey(const GrProcessor& processor, const GrGLSLCaps&, GrProcessorKeyBuilder* b) {
|
| + for (uint32_t i = 0; i < kMaxKeySize; i++) {
|
| + b->add32(i);
|
| + }
|
| + }
|
| +
|
| +private:
|
| + typedef GrGLFragmentProcessor INHERITED;
|
| +};
|
| +
|
| +class BigKeyProcessor : public GrFragmentProcessor {
|
| +public:
|
| + static GrFragmentProcessor* Create() {
|
| + GR_CREATE_STATIC_PROCESSOR(gBigKeyProcessor, BigKeyProcessor, ())
|
| + return SkRef(gBigKeyProcessor);
|
| + }
|
| +
|
| + const char* name() const override { return "Big Ole Key"; }
|
| +
|
| + virtual void getGLProcessorKey(const GrGLSLCaps& caps,
|
| + GrProcessorKeyBuilder* b) const override {
|
| + GLBigKeyProcessor::GenKey(*this, caps, b);
|
| + }
|
| +
|
| + GrGLFragmentProcessor* createGLInstance() const override {
|
| + return SkNEW_ARGS(GLBigKeyProcessor, (*this));
|
| + }
|
| +
|
| +private:
|
| + BigKeyProcessor() {
|
| + this->initClassID<BigKeyProcessor>();
|
| + }
|
| + bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
|
| + void onComputeInvariantOutput(GrInvariantOutput* inout) const override { }
|
| +
|
| + GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
|
| +
|
| + typedef GrFragmentProcessor INHERITED;
|
| +};
|
| +
|
| +GR_DEFINE_FRAGMENT_PROCESSOR_TEST(BigKeyProcessor);
|
| +
|
| +GrFragmentProcessor* BigKeyProcessor::TestCreate(SkRandom*,
|
| + GrContext*,
|
| + const GrDrawTargetCaps&,
|
| + GrTexture*[]) {
|
| + return BigKeyProcessor::Create();
|
| +}
|
| +
|
| +/*
|
| + * Begin test code
|
| + */
|
| +static const int kRenderTargetHeight = 1;
|
| +static const int kRenderTargetWidth = 1;
|
| +
|
| +static GrRenderTarget* random_render_target(GrContext* context, SkRandom* random) {
|
| + // setup render target
|
| + GrTextureParams params;
|
| + GrSurfaceDesc texDesc;
|
| + texDesc.fWidth = kRenderTargetWidth;
|
| + texDesc.fHeight = kRenderTargetHeight;
|
| + texDesc.fFlags = kRenderTarget_GrSurfaceFlag;
|
| + texDesc.fConfig = kRGBA_8888_GrPixelConfig;
|
| + texDesc.fOrigin = random->nextBool() == true ? kTopLeft_GrSurfaceOrigin :
|
| + kBottomLeft_GrSurfaceOrigin;
|
| + GrUniqueKey key;
|
| + static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
|
| + GrUniqueKey::Builder builder(&key, kDomain, 1);
|
| + builder[0] = texDesc.fOrigin;
|
| + builder.finish();
|
| +
|
| + GrTexture* texture = context->findAndRefCachedTexture(key);
|
| + if (!texture) {
|
| + texture = context->createTexture(texDesc, true);
|
| + if (texture) {
|
| + context->addResourceToCache(key, texture);
|
| + }
|
| + }
|
| + return texture ? texture->asRenderTarget() : NULL;
|
| +}
|
| +
|
| +static void set_random_xpf(GrContext* context, const GrDrawTargetCaps& caps,
|
| + GrPipelineBuilder* pipelineBuilder, SkRandom* random,
|
| + GrTexture* dummyTextures[]) {
|
| + SkAutoTUnref<const GrXPFactory> xpf(
|
| + GrProcessorTestFactory<GrXPFactory>::CreateStage(random, context, caps, dummyTextures));
|
| + SkASSERT(xpf);
|
| + pipelineBuilder->setXPFactory(xpf.get());
|
| +}
|
| +
|
| +static const GrGeometryProcessor* get_random_gp(GrContext* context,
|
| + const GrDrawTargetCaps& caps,
|
| + SkRandom* random,
|
| + GrTexture* dummyTextures[]) {
|
| + return GrProcessorTestFactory<GrGeometryProcessor>::CreateStage(random,
|
| + context,
|
| + caps,
|
| + dummyTextures);
|
| +}
|
| +
|
| +static void set_random_color_coverage_stages(GrGLGpu* gpu,
|
| + GrPipelineBuilder* pipelineBuilder,
|
| + int maxStages,
|
| + bool usePathRendering,
|
| + SkRandom* random,
|
| + GrTexture* dummyTextures[]) {
|
| + int numProcs = random->nextULessThan(maxStages + 1);
|
| + int numColorProcs = random->nextULessThan(numProcs + 1);
|
| +
|
| + for (int s = 0; s < numProcs;) {
|
| + SkAutoTUnref<const GrFragmentProcessor> fp(
|
| + GrProcessorTestFactory<GrFragmentProcessor>::CreateStage(random,
|
| + gpu->getContext(),
|
| + *gpu->caps(),
|
| + dummyTextures));
|
| + SkASSERT(fp);
|
| +
|
| + // finally add the stage to the correct pipeline in the drawstate
|
| + if (s < numColorProcs) {
|
| + pipelineBuilder->addColorProcessor(fp);
|
| + } else {
|
| + pipelineBuilder->addCoverageProcessor(fp);
|
| + }
|
| + ++s;
|
| + }
|
| +}
|
| +
|
| +static void set_random_state(GrPipelineBuilder* pipelineBuilder, SkRandom* random) {
|
| + int state = 0;
|
| + for (int i = 1; i <= GrPipelineBuilder::kLast_Flag; i <<= 1) {
|
| + state |= random->nextBool() * i;
|
| + }
|
| + pipelineBuilder->enableState(state);
|
| +}
|
| +
|
| +// right now, the only thing we seem to care about in drawState's stencil is 'doesWrite()'
|
| +static void set_random_stencil(GrPipelineBuilder* pipelineBuilder, SkRandom* random) {
|
| + GR_STATIC_CONST_SAME_STENCIL(kDoesWriteStencil,
|
| + kReplace_StencilOp,
|
| + kReplace_StencilOp,
|
| + kAlways_StencilFunc,
|
| + 0xffff,
|
| + 0xffff,
|
| + 0xffff);
|
| + GR_STATIC_CONST_SAME_STENCIL(kDoesNotWriteStencil,
|
| + kKeep_StencilOp,
|
| + kKeep_StencilOp,
|
| + kNever_StencilFunc,
|
| + 0xffff,
|
| + 0xffff,
|
| + 0xffff);
|
| +
|
| + if (random->nextBool()) {
|
| + pipelineBuilder->setStencil(kDoesWriteStencil);
|
| + } else {
|
| + pipelineBuilder->setStencil(kDoesNotWriteStencil);
|
| + }
|
| +}
|
| +
|
| +bool GrDrawTarget::programUnitTest(int maxStages) {
|
| + GrGLGpu* gpu = static_cast<GrGLGpu*>(fContext->getGpu());
|
| + // setup dummy textures
|
| + GrSurfaceDesc dummyDesc;
|
| + dummyDesc.fFlags = kRenderTarget_GrSurfaceFlag;
|
| + dummyDesc.fConfig = kSkia8888_GrPixelConfig;
|
| + dummyDesc.fWidth = 34;
|
| + dummyDesc.fHeight = 18;
|
| + SkAutoTUnref<GrTexture> dummyTexture1(gpu->createTexture(dummyDesc, false, NULL, 0));
|
| + dummyDesc.fFlags = kNone_GrSurfaceFlags;
|
| + dummyDesc.fConfig = kAlpha_8_GrPixelConfig;
|
| + dummyDesc.fWidth = 16;
|
| + dummyDesc.fHeight = 22;
|
| + SkAutoTUnref<GrTexture> dummyTexture2(gpu->createTexture(dummyDesc, false, NULL, 0));
|
| +
|
| + if (!dummyTexture1 || ! dummyTexture2) {
|
| + SkDebugf("Could not allocate dummy textures");
|
| + return false;
|
| + }
|
| +
|
| + GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()};
|
| +
|
| + // dummy scissor state
|
| + GrScissorState scissor;
|
| +
|
| + // setup clip
|
| + SkRect screen = SkRect::MakeWH(SkIntToScalar(kRenderTargetWidth),
|
| + SkIntToScalar(kRenderTargetHeight));
|
| +
|
| + SkClipStack stack;
|
| + stack.clipDevRect(screen, SkRegion::kReplace_Op, false);
|
| +
|
| + // wrap the SkClipStack in a GrClip
|
| + GrClip clip;
|
| + clip.setClipStack(&stack);
|
| +
|
| + SkRandom random;
|
| + static const int NUM_TESTS = 512;
|
| + for (int t = 0; t < NUM_TESTS;) {
|
| + // setup random render target(can fail)
|
| + SkAutoTUnref<GrRenderTarget> rt(random_render_target(fContext, &random));
|
| + if (!rt.get()) {
|
| + SkDebugf("Could not allocate render target");
|
| + return false;
|
| + }
|
| +
|
| + GrPipelineBuilder pipelineBuilder;
|
| + pipelineBuilder.setRenderTarget(rt.get());
|
| + pipelineBuilder.setClip(clip);
|
| +
|
| + // if path rendering we have to setup a couple of things like the draw type
|
| + bool usePathRendering = gpu->glCaps().pathRenderingSupport() && random.nextBool();
|
| +
|
| + // twiddle drawstate knobs randomly
|
| + bool hasGeometryProcessor = !usePathRendering;
|
| + SkAutoTUnref<const GrGeometryProcessor> gp;
|
| + SkAutoTUnref<const GrPathProcessor> pathProc;
|
| + if (hasGeometryProcessor) {
|
| + gp.reset(get_random_gp(fContext, gpu->glCaps(), &random, dummyTextures));
|
| + } else {
|
| + pathProc.reset(GrPathProcessor::Create(GrColor_WHITE));
|
| + }
|
| + set_random_color_coverage_stages(gpu,
|
| + &pipelineBuilder,
|
| + maxStages - hasGeometryProcessor,
|
| + usePathRendering,
|
| + &random,
|
| + dummyTextures);
|
| +
|
| + // creates a random xfer processor factory on the draw state
|
| + set_random_xpf(fContext, gpu->glCaps(), &pipelineBuilder, &random, dummyTextures);
|
| +
|
| + set_random_state(&pipelineBuilder, &random);
|
| + set_random_stencil(&pipelineBuilder, &random);
|
| +
|
| + GrDeviceCoordTexture dstCopy;
|
| +
|
| + const GrPrimitiveProcessor* primProc;
|
| + if (hasGeometryProcessor) {
|
| + primProc = gp.get();
|
| + } else {
|
| + primProc = pathProc.get();
|
| + }
|
| +
|
| + const GrProcOptInfo& colorPOI = pipelineBuilder.colorProcInfo(primProc);
|
| + const GrProcOptInfo& coveragePOI = pipelineBuilder.coverageProcInfo(primProc);
|
| +
|
| + if (!this->setupDstReadIfNecessary(pipelineBuilder, colorPOI, coveragePOI, &dstCopy,
|
| + NULL)) {
|
| + SkDebugf("Couldn't setup dst read texture");
|
| + return false;
|
| + }
|
| +
|
| + // create optimized draw state, setup readDst texture if required, and build a descriptor
|
| + // and program. ODS creation can fail, so we have to check
|
| + GrPipeline pipeline(pipelineBuilder, colorPOI, coveragePOI,
|
| + *gpu->caps(), scissor, &dstCopy);
|
| + if (pipeline.mustSkip()) {
|
| + continue;
|
| + }
|
| + GrBatchTracker bt;
|
| + primProc->initBatchTracker(&bt, pipeline.getInitBatchTracker());
|
| +
|
| + GrProgramDesc desc;
|
| + gpu->buildProgramDesc(&desc, *primProc, pipeline, bt);
|
| +
|
| + GrGpu::DrawArgs args(primProc, &pipeline, &desc, &bt);
|
| + SkAutoTUnref<GrGLProgram> program(GrGLProgramBuilder::CreateProgram(args, gpu));
|
| +
|
| + if (NULL == program.get()) {
|
| + SkDebugf("Failed to create program!");
|
| + return false;
|
| + }
|
| +
|
| + // because occasionally optimized drawstate creation will fail for valid reasons, we only
|
| + // want to increment on success
|
| + ++t;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +DEF_GPUTEST(GLPrograms, reporter, factory) {
|
| + // Set a locale that would cause shader compilation to fail because of , as decimal separator.
|
| + // skbug 3330
|
| +#ifdef SK_BUILD_FOR_WIN
|
| + GrAutoLocaleSetter als("sv-SE");
|
| +#else
|
| + GrAutoLocaleSetter als("sv_SE.UTF-8");
|
| +#endif
|
| +
|
| + for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
|
| + GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(type));
|
| + if (context) {
|
| + GrGLGpu* gpu = static_cast<GrGLGpu*>(context->getGpu());
|
| +
|
| + /*
|
| + * For the time being, we only support the test with desktop GL or for android on
|
| + * ARM platforms
|
| + * TODO When we run ES 3.00 GLSL in more places, test again
|
| + */
|
| + int maxStages;
|
| + if (kGL_GrGLStandard == gpu->glStandard() ||
|
| + kARM_GrGLVendor == gpu->ctxInfo().vendor()) {
|
| + maxStages = 6;
|
| + } else if (kTegra3_GrGLRenderer == gpu->ctxInfo().renderer() ||
|
| + kOther_GrGLRenderer == gpu->ctxInfo().renderer()) {
|
| + maxStages = 1;
|
| + } else {
|
| + return;
|
| + }
|
| +#if SK_ANGLE
|
| + // Some long shaders run out of temporary registers in the D3D compiler on ANGLE.
|
| + if (type == GrContextFactory::kANGLE_GLContextType) {
|
| + maxStages = 2;
|
| + }
|
| +#endif
|
| + GrTestTarget target;
|
| + context->getTestTarget(&target);
|
| + REPORTER_ASSERT(reporter, target.target()->programUnitTest(maxStages));
|
| + }
|
| + }
|
| +}
|
| +
|
| +#endif
|
|
|