GLProgramsTest.cpp revision b8b705b1b983a2ee3a254bed4dd03f926101e4e7
1
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9// This is a GPU-backend specific test. It relies on static intializers to work
10
11#include "SkTypes.h"
12
13#if SK_SUPPORT_GPU && SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
14
15#include "gl/GrGpuGL.h"
16#include "GrBackendEffectFactory.h"
17#include "GrContextFactory.h"
18#include "effects/GrConfigConversionEffect.h"
19
20#include "SkRandom.h"
21#include "Test.h"
22
23void GrGLProgram::Desc::setRandom(SkMWCRandom* random,
24                                  const GrGpuGL* gpu,
25                                  const GrEffectStage stages[GrDrawState::kNumStages]) {
26    fAttribBindings = 0;
27    fEmitsPointSize = random->nextBool();
28    fColorInput = random->nextULessThan(kColorInputCnt);
29    fCoverageInput = random->nextULessThan(kColorInputCnt);
30
31    fColorFilterXfermode = random->nextULessThan(SkXfermode::kCoeffModesCnt);
32
33    fFirstCoverageStage = random->nextULessThan(GrDrawState::kNumStages);
34
35    fAttribBindings |= random->nextBool() ? GrDrawState::kCoverage_AttribBindingsBit : 0;
36
37#if GR_GL_EXPERIMENTAL_GS
38    fExperimentalGS = gpu->getCaps().geometryShaderSupport() && random->nextBool();
39#endif
40
41    bool edgeAA = random->nextBool();
42    if (edgeAA) {
43        fAttribBindings |= GrDrawState::kEdge_AttribBindingsBit;
44        if (gpu->getCaps().shaderDerivativeSupport()) {
45            fVertexEdgeType = (GrDrawState::VertexEdgeType)
46                              random->nextULessThan(GrDrawState::kVertexEdgeTypeCnt);
47            fDiscardIfOutsideEdge = random->nextBool();
48        } else {
49            fVertexEdgeType = GrDrawState::kHairLine_EdgeType;
50            fDiscardIfOutsideEdge = false;
51        }
52    }
53
54    if (gpu->getCaps().dualSourceBlendingSupport()) {
55        fDualSrcOutput = random->nextULessThan(kDualSrcOutputCnt);
56    } else {
57        fDualSrcOutput = kNone_DualSrcOutput;
58    }
59
60    bool useOnce = false;
61    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
62        if (NULL != stages[s].getEffect()) {
63            const GrBackendEffectFactory& factory = (*stages[s].getEffect())->getFactory();
64            fEffectKeys[s] = factory.glEffectKey(stages[s], gpu->glCaps());
65            // use separate tex coords?
66            if (!useOnce && random->nextBool()) {
67                fAttribBindings |= GrDrawState::ExplicitTexCoordAttribBindingsBit(s);
68                useOnce = true;
69            }
70        }
71    }
72
73    int attributeIndex = 0;
74    fPositionAttributeIndex = attributeIndex;
75    ++attributeIndex;
76    if (fColorInput || (fAttribBindings & GrDrawState::kColor_AttribBindingsBit)) {
77        fColorAttributeIndex = attributeIndex;
78        ++attributeIndex;
79    }
80    if (fCoverageInput || (fAttribBindings & GrDrawState::kCoverage_AttribBindingsBit)) {
81        fCoverageAttributeIndex = attributeIndex;
82        ++attributeIndex;
83    }
84    if (fAttribBindings & GrDrawState::kEdge_AttribBindingsBit) {
85        fEdgeAttributeIndex = attributeIndex;
86        ++attributeIndex;
87    }
88    if (GrDrawState::AttributesBindExplicitTexCoords(fAttribBindings)) {
89        fTexCoordAttributeIndex = attributeIndex;
90        ++attributeIndex;
91    }
92}
93
94bool GrGpuGL::programUnitTest(int maxStages) {
95
96    maxStages = GrMin(maxStages, (int)GrDrawState::kNumStages);
97
98    GrTextureDesc dummyDesc;
99    dummyDesc.fConfig = kSkia8888_GrPixelConfig;
100    dummyDesc.fWidth = 34;
101    dummyDesc.fHeight = 18;
102    SkAutoTUnref<GrTexture> dummyTexture1(this->createTexture(dummyDesc, NULL, 0));
103    dummyDesc.fConfig = kAlpha_8_GrPixelConfig;
104    dummyDesc.fWidth = 16;
105    dummyDesc.fHeight = 22;
106    SkAutoTUnref<GrTexture> dummyTexture2(this->createTexture(dummyDesc, NULL, 0));
107
108    static const int NUM_TESTS = 512;
109
110    SkMWCRandom random;
111    for (int t = 0; t < NUM_TESTS; ++t) {
112
113#if 0
114        GrPrintf("\nTest Program %d\n-------------\n", t);
115        static const int stop = -1;
116        if (t == stop) {
117            int breakpointhere = 9;
118        }
119#endif
120
121        GrGLProgram::Desc pdesc;
122        GrEffectStage stages[GrDrawState::kNumStages];
123
124        for (int s = 0; s < maxStages; ++s) {
125            // enable the stage?
126            if (random.nextBool()) {
127                GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()};
128                SkAutoTUnref<const GrEffectRef> effect(GrEffectTestFactory::CreateStage(
129                                                                                &random,
130                                                                                this->getContext(),
131                                                                                dummyTextures));
132                stages[s].setEffect(effect.get());
133            }
134        }
135        pdesc.setRandom(&random, this, stages);
136
137        const GrEffectStage* stagePtrs[GrDrawState::kNumStages];
138        for (int s = 0; s < GrDrawState::kNumStages; ++s) {
139            stagePtrs[s] = &stages[s];
140        }
141        SkAutoTUnref<GrGLProgram> program(GrGLProgram::Create(this->glContextInfo(),
142                                                              pdesc,
143                                                              stagePtrs));
144        if (NULL == program.get()) {
145            return false;
146        }
147    }
148    return true;
149}
150
151static void GLProgramsTest(skiatest::Reporter* reporter, GrContextFactory* factory) {
152    for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
153        GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(type));
154        if (NULL != context) {
155            GrGpuGL* gpu = static_cast<GrGpuGL*>(context->getGpu());
156            int maxStages = GrDrawState::kNumStages;
157#if SK_ANGLE
158            // Some long shaders run out of temporary registers in the D3D compiler on ANGLE.
159            if (type == GrContextFactory::kANGLE_GLContextType) {
160                maxStages = 3;
161            }
162#endif
163            REPORTER_ASSERT(reporter, gpu->programUnitTest(maxStages));
164        }
165    }
166}
167
168#include "TestClassDef.h"
169DEFINE_GPUTESTCLASS("GLPrograms", GLProgramsTestClass, GLProgramsTest)
170
171// This is evil evil evil. The linker may throw away whole translation units as dead code if it
172// thinks none of the functions are called. It will do this even if there are static initializers
173// in the unit that could pass pointers to functions from the unit out to other translation units!
174// We force some of the effects that would otherwise be discarded to link here.
175
176#include "SkLightingImageFilter.h"
177#include "SkMagnifierImageFilter.h"
178#include "SkColorMatrixFilter.h"
179
180void forceLinking();
181
182void forceLinking() {
183    SkLightingImageFilter::CreateDistantLitDiffuse(SkPoint3(0,0,0), 0, 0, 0);
184    SkMagnifierImageFilter mag(SkRect::MakeWH(SK_Scalar1, SK_Scalar1), SK_Scalar1);
185    GrConfigConversionEffect::Create(NULL,
186                                     false,
187                                     GrConfigConversionEffect::kNone_PMConversion,
188                                     SkMatrix::I());
189    SkScalar matrix[20];
190    SkColorMatrixFilter cmf(matrix);
191}
192
193#endif
194