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