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 25 void 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 119 bool GrGpuGL::programUnitTest(int maxStages) { 120 121 GrTextureDesc dummyDesc; 122 dummyDesc.fFlags = kRenderTarget_GrTextureFlagBit; 123 dummyDesc.fConfig = kSkia8888_GrPixelConfig; 124 dummyDesc.fWidth = 34; 125 dummyDesc.fHeight = 18; 126 SkAutoTUnref<GrTexture> dummyTexture1(this->createTexture(dummyDesc, NULL, 0)); 127 dummyDesc.fFlags = kNone_GrTextureFlags; 128 dummyDesc.fConfig = kAlpha_8_GrPixelConfig; 129 dummyDesc.fWidth = 16; 130 dummyDesc.fHeight = 22; 131 SkAutoTUnref<GrTexture> dummyTexture2(this->createTexture(dummyDesc, NULL, 0)); 132 133 static const int NUM_TESTS = 512; 134 135 SkMWCRandom random; 136 for (int t = 0; t < NUM_TESTS; ++t) { 137 138 #if 0 139 GrPrintf("\nTest Program %d\n-------------\n", t); 140 static const int stop = -1; 141 if (t == stop) { 142 int breakpointhere = 9; 143 } 144 #endif 145 146 GrGLProgramDesc pdesc; 147 148 int currAttribIndex = 1; // we need to always leave room for position 149 int attribIndices[2]; 150 GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()}; 151 152 int numStages = random.nextULessThan(maxStages + 1); 153 int numColorStages = random.nextULessThan(numStages + 1); 154 int numCoverageStages = numStages - numColorStages; 155 156 SkAutoSTMalloc<8, const GrEffectStage*> stages(numStages); 157 158 for (int s = 0; s < numStages; ++s) { 159 SkAutoTUnref<const GrEffectRef> effect(GrEffectTestFactory::CreateStage( 160 &random, 161 this->getContext(), 162 *this->caps(), 163 dummyTextures)); 164 int numAttribs = (*effect)->numVertexAttribs(); 165 166 // If adding this effect would exceed the max attrib count then generate a 167 // new random effect. 168 if (currAttribIndex + numAttribs > GrDrawState::kMaxVertexAttribCnt) { 169 --s; 170 continue; 171 } 172 for (int i = 0; i < numAttribs; ++i) { 173 attribIndices[i] = currAttribIndex++; 174 } 175 GrEffectStage* stage = SkNEW_ARGS(GrEffectStage, 176 (effect.get(), attribIndices[0], attribIndices[1])); 177 stages[s] = stage; 178 } 179 const GrTexture* dstTexture = random.nextBool() ? dummyTextures[0] : dummyTextures[1]; 180 pdesc.setRandom(&random, 181 this, 182 dummyTextures[0]->asRenderTarget(), 183 dstTexture, 184 stages.get(), 185 numColorStages, 186 numCoverageStages, 187 currAttribIndex); 188 189 SkAutoTUnref<GrGLProgram> program(GrGLProgram::Create(this->glContext(), 190 pdesc, 191 stages, 192 stages + numColorStages)); 193 for (int s = 0; s < numStages; ++s) { 194 SkDELETE(stages[s]); 195 } 196 if (NULL == program.get()) { 197 return false; 198 } 199 } 200 return true; 201 } 202 203 static void GLProgramsTest(skiatest::Reporter* reporter, GrContextFactory* factory) { 204 for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) { 205 GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(type)); 206 if (NULL != context) { 207 GrGpuGL* gpu = static_cast<GrGpuGL*>(context->getGpu()); 208 int maxStages = 6; 209 #if SK_ANGLE 210 // Some long shaders run out of temporary registers in the D3D compiler on ANGLE. 211 if (type == GrContextFactory::kANGLE_GLContextType) { 212 maxStages = 3; 213 } 214 #endif 215 REPORTER_ASSERT(reporter, gpu->programUnitTest(maxStages)); 216 } 217 } 218 } 219 220 #include "TestClassDef.h" 221 DEFINE_GPUTESTCLASS("GLPrograms", GLProgramsTestClass, GLProgramsTest) 222 223 // This is evil evil evil. The linker may throw away whole translation units as dead code if it 224 // thinks none of the functions are called. It will do this even if there are static initializers 225 // in the unit that could pass pointers to functions from the unit out to other translation units! 226 // We force some of the effects that would otherwise be discarded to link here. 227 228 #include "SkLightingImageFilter.h" 229 #include "SkMagnifierImageFilter.h" 230 #include "SkColorMatrixFilter.h" 231 232 void forceLinking(); 233 234 void forceLinking() { 235 SkLightingImageFilter::CreateDistantLitDiffuse(SkPoint3(0,0,0), 0, 0, 0); 236 SkMagnifierImageFilter mag(SkRect::MakeWH(SK_Scalar1, SK_Scalar1), SK_Scalar1); 237 GrConfigConversionEffect::Create(NULL, 238 false, 239 GrConfigConversionEffect::kNone_PMConversion, 240 SkMatrix::I()); 241 SkScalar matrix[20]; 242 SkColorMatrixFilter cmf(matrix); 243 } 244 245 #endif 246