GLProgramsTest.cpp revision 2c84aa35988c661b3e5513c8ba9b3959832ff288
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 "SkChecksum.h" 22#include "SkRandom.h" 23#include "Test.h" 24 25void GrGLProgramDesc::setRandom(SkMWCRandom* random, 26 const GrGpuGL* gpu, 27 const GrRenderTarget* dstRenderTarget, 28 const GrTexture* dstCopyTexture, 29 const GrEffectStage* stages[], 30 int numColorStages, 31 int numCoverageStages, 32 int currAttribIndex) { 33 int numEffects = numColorStages + numCoverageStages; 34 size_t keyLength = KeyLength(numEffects); 35 fKey.reset(keyLength); 36 *this->atOffset<uint32_t, kLengthOffset>() = static_cast<uint32_t>(keyLength); 37 memset(this->header(), 0, kHeaderSize); 38 39 KeyHeader* header = this->header(); 40 header->fEmitsPointSize = random->nextBool(); 41 42 header->fPositionAttributeIndex = 0; 43 44 // if the effects have used up all off the available attributes, 45 // don't try to use color or coverage attributes as input 46 do { 47 header->fColorInput = random->nextULessThan(kColorInputCnt); 48 } while (GrDrawState::kMaxVertexAttribCnt <= currAttribIndex && 49 kAttribute_ColorInput == header->fColorInput); 50 header->fColorAttributeIndex = (header->fColorInput == kAttribute_ColorInput) ? 51 currAttribIndex++ : 52 -1; 53 54 do { 55 header->fCoverageInput = random->nextULessThan(kColorInputCnt); 56 } while (GrDrawState::kMaxVertexAttribCnt <= currAttribIndex && 57 kAttribute_ColorInput == header->fCoverageInput); 58 header->fCoverageAttributeIndex = (header->fCoverageInput == kAttribute_ColorInput) ? 59 currAttribIndex++ : 60 -1; 61 62 header->fColorFilterXfermode = random->nextULessThan(SkXfermode::kLastCoeffMode + 1); 63 64#if GR_GL_EXPERIMENTAL_GS 65 header->fExperimentalGS = gpu->caps()->geometryShaderSupport() && random->nextBool(); 66#endif 67 68 header->fDiscardIfZeroCoverage = random->nextBool(); 69 70 bool useLocalCoords = random->nextBool() && currAttribIndex < GrDrawState::kMaxVertexAttribCnt; 71 header->fLocalCoordAttributeIndex = useLocalCoords ? currAttribIndex++ : -1; 72 73 header->fColorEffectCnt = numColorStages; 74 header->fCoverageEffectCnt = numCoverageStages; 75 76 bool dstRead = false; 77 bool fragPos = false; 78 int numStages = numColorStages + numCoverageStages; 79 for (int s = 0; s < numStages; ++s) { 80 const GrBackendEffectFactory& factory = (*stages[s]->getEffect())->getFactory(); 81 GrDrawEffect drawEffect(*stages[s], useLocalCoords); 82 this->effectKeys()[s] = factory.glEffectKey(drawEffect, gpu->glCaps()); 83 if ((*stages[s]->getEffect())->willReadDstColor()) { 84 dstRead = true; 85 } 86 if ((*stages[s]->getEffect())->willReadFragmentPosition()) { 87 fragPos = true; 88 } 89 } 90 91 if (dstRead) { 92 header->fDstReadKey = GrGLShaderBuilder::KeyForDstRead(dstCopyTexture, gpu->glCaps()); 93 } else { 94 header->fDstReadKey = 0; 95 } 96 if (fragPos) { 97 header->fFragPosKey = GrGLShaderBuilder::KeyForFragmentPosition(dstRenderTarget, 98 gpu->glCaps()); 99 } else { 100 header->fFragPosKey = 0; 101 } 102 103 CoverageOutput coverageOutput; 104 bool illegalCoverageOutput; 105 do { 106 coverageOutput = static_cast<CoverageOutput>(random->nextULessThan(kCoverageOutputCnt)); 107 illegalCoverageOutput = (!gpu->caps()->dualSourceBlendingSupport() && 108 CoverageOutputUsesSecondaryOutput(coverageOutput)) || 109 (!dstRead && kCombineWithDst_CoverageOutput == coverageOutput); 110 } while (illegalCoverageOutput); 111 112 header->fCoverageOutput = coverageOutput; 113 114 *this->checksum() = 0; 115 *this->checksum() = SkChecksum::Compute(reinterpret_cast<uint32_t*>(fKey.get()), keyLength); 116 fInitialized = true; 117} 118 119bool GrGpuGL::programUnitTest(int maxStages) { 120 121 maxStages = GrMin(maxStages, (int)GrDrawState::kNumStages); 122 123 GrTextureDesc dummyDesc; 124 dummyDesc.fFlags = kRenderTarget_GrTextureFlagBit; 125 dummyDesc.fConfig = kSkia8888_GrPixelConfig; 126 dummyDesc.fWidth = 34; 127 dummyDesc.fHeight = 18; 128 SkAutoTUnref<GrTexture> dummyTexture1(this->createTexture(dummyDesc, NULL, 0)); 129 dummyDesc.fFlags = kNone_GrTextureFlags; 130 dummyDesc.fConfig = kAlpha_8_GrPixelConfig; 131 dummyDesc.fWidth = 16; 132 dummyDesc.fHeight = 22; 133 SkAutoTUnref<GrTexture> dummyTexture2(this->createTexture(dummyDesc, NULL, 0)); 134 135 static const int NUM_TESTS = 512; 136 137 SkMWCRandom random; 138 for (int t = 0; t < NUM_TESTS; ++t) { 139 140#if 0 141 GrPrintf("\nTest Program %d\n-------------\n", t); 142 static const int stop = -1; 143 if (t == stop) { 144 int breakpointhere = 9; 145 } 146#endif 147 148 GrGLProgramDesc pdesc; 149 150 int currAttribIndex = 1; // we need to always leave room for position 151 int attribIndices[2]; 152 GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()}; 153 154 int numStages = random.nextULessThan(maxStages + 1); 155 int numColorStages = random.nextULessThan(numStages + 1); 156 int numCoverageStages = numStages - numColorStages; 157 158 SkAutoSTMalloc<8, const GrEffectStage*> stages(numStages); 159 160 for (int s = 0; s < numStages; ++s) { 161 SkAutoTUnref<const GrEffectRef> effect(GrEffectTestFactory::CreateStage( 162 &random, 163 this->getContext(), 164 *this->caps(), 165 dummyTextures)); 166 int numAttribs = (*effect)->numVertexAttribs(); 167 168 // If adding this effect would exceed the max attrib count then generate a 169 // new random effect. 170 if (currAttribIndex + numAttribs > GrDrawState::kMaxVertexAttribCnt) { 171 --s; 172 continue; 173 } 174 for (int i = 0; i < numAttribs; ++i) { 175 attribIndices[i] = currAttribIndex++; 176 } 177 GrEffectStage* stage = SkNEW(GrEffectStage); 178 stage->setEffect(effect.get(), attribIndices[0], attribIndices[1]); 179 stages[s] = stage; 180 } 181 const GrTexture* dstTexture = random.nextBool() ? dummyTextures[0] : dummyTextures[1]; 182 pdesc.setRandom(&random, 183 this, 184 dummyTextures[0]->asRenderTarget(), 185 dstTexture, 186 stages.get(), 187 numColorStages, 188 numCoverageStages, 189 currAttribIndex); 190 191 SkAutoTUnref<GrGLProgram> program(GrGLProgram::Create(this->glContext(), 192 pdesc, 193 stages, 194 stages + numColorStages)); 195 for (int s = 0; s < numStages; ++s) { 196 SkDELETE(stages[s]); 197 } 198 if (NULL == program.get()) { 199 return false; 200 } 201 } 202 return true; 203} 204 205static void GLProgramsTest(skiatest::Reporter* reporter, GrContextFactory* factory) { 206 for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) { 207 GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(type)); 208 if (NULL != context) { 209 GrGpuGL* gpu = static_cast<GrGpuGL*>(context->getGpu()); 210 int maxStages = GrDrawState::kNumStages; 211#if SK_ANGLE 212 // Some long shaders run out of temporary registers in the D3D compiler on ANGLE. 213 if (type == GrContextFactory::kANGLE_GLContextType) { 214 maxStages = 3; 215 } 216#endif 217 REPORTER_ASSERT(reporter, gpu->programUnitTest(maxStages)); 218 } 219 } 220} 221 222#include "TestClassDef.h" 223DEFINE_GPUTESTCLASS("GLPrograms", GLProgramsTestClass, GLProgramsTest) 224 225// This is evil evil evil. The linker may throw away whole translation units as dead code if it 226// thinks none of the functions are called. It will do this even if there are static initializers 227// in the unit that could pass pointers to functions from the unit out to other translation units! 228// We force some of the effects that would otherwise be discarded to link here. 229 230#include "SkLightingImageFilter.h" 231#include "SkMagnifierImageFilter.h" 232#include "SkColorMatrixFilter.h" 233 234void forceLinking(); 235 236void forceLinking() { 237 SkLightingImageFilter::CreateDistantLitDiffuse(SkPoint3(0,0,0), 0, 0, 0); 238 SkMagnifierImageFilter mag(SkRect::MakeWH(SK_Scalar1, SK_Scalar1), SK_Scalar1); 239 GrConfigConversionEffect::Create(NULL, 240 false, 241 GrConfigConversionEffect::kNone_PMConversion, 242 SkMatrix::I()); 243 SkScalar matrix[20]; 244 SkColorMatrixFilter cmf(matrix); 245} 246 247#endif 248