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