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