Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 // This is a GPU-backend specific test. It relies on static intializers to work | 9 // This is a GPU-backend specific test. It relies on static intializers to work |
| 10 | 10 |
| 11 #include "SkTypes.h" | 11 #include "SkTypes.h" |
| 12 | 12 |
| 13 #if SK_SUPPORT_GPU && SK_ALLOW_STATIC_GLOBAL_INITIALIZERS | 13 #if SK_SUPPORT_GPU && SK_ALLOW_STATIC_GLOBAL_INITIALIZERS |
| 14 | 14 |
| 15 #include "GrBackendProcessorFactory.h" | 15 #include "GrBackendProcessorFactory.h" |
| 16 #include "GrContextFactory.h" | 16 #include "GrContextFactory.h" |
| 17 #include "GrOptDrawState.h" | 17 #include "GrOptDrawState.h" |
| 18 #include "effects/GrConfigConversionEffect.h" | 18 #include "effects/GrConfigConversionEffect.h" |
| 19 #include "gl/GrGLPathRendering.h" | 19 #include "gl/GrGLPathRendering.h" |
| 20 #include "gl/GrGpuGL.h" | 20 #include "gl/GrGpuGL.h" |
| 21 #include "SkChecksum.h" | 21 #include "SkChecksum.h" |
| 22 #include "SkRandom.h" | 22 #include "SkRandom.h" |
| 23 #include "Test.h" | 23 #include "Test.h" |
| 24 | 24 |
| 25 static void get_stage_stats(const GrFragmentStage stage, bool* readsDst, | 25 static const int kRenderTargetHeight = 1; |
| 26 bool* readsFragPosition, bool* requiresVertexShader) { | 26 static const int kRenderTargetWidth = 1; |
| 27 if (stage.getFragmentProcessor()->willReadDstColor()) { | 27 |
| 28 *readsDst = true; | 28 static GrRenderTarget* random_render_target(GrGpuGL* gpu, |
| 29 const GrCacheID& cacheId, | |
|
egdaniel
2014/10/06 14:19:02
move param up and onto same line
| |
| 30 SkRandom* random) { | |
| 31 // setup render target | |
| 32 GrTextureParams params; | |
| 33 GrTextureDesc texDesc; | |
| 34 texDesc.fWidth = kRenderTargetWidth; | |
| 35 texDesc.fHeight = kRenderTargetHeight; | |
| 36 texDesc.fFlags = kRenderTarget_GrTextureFlagBit; | |
| 37 texDesc.fConfig = kRGBA_8888_GrPixelConfig; | |
| 38 texDesc.fOrigin = random->nextBool() == true ? kTopLeft_GrSurfaceOrigin : | |
| 39 kBottomLeft_GrSurfaceOrigin; | |
| 40 | |
| 41 GrTexture* texture = gpu->getContext()->findAndRefTexture(texDesc, cacheId, ¶ms); | |
| 42 if (NULL == texture) { | |
| 43 texture = gpu->getContext()->createTexture(¶ms, texDesc, cacheId, 0, 0); | |
| 44 if (NULL == texture) { | |
| 45 SkDEBUGFAIL("Could not allocate render target"); | |
|
bsalomon
2014/10/06 14:29:04
Maybe just SkDebugf? Hopefully this ripples up and
| |
| 46 return NULL; | |
| 47 } | |
| 29 } | 48 } |
| 30 if (stage.getProcessor()->willReadFragmentPosition()) { | 49 return texture->asRenderTarget(); |
| 31 *readsFragPosition = true; | |
| 32 } | |
| 33 } | |
| 34 | |
| 35 bool GrGLProgramDesc::setRandom(SkRandom* random, | |
| 36 GrGpuGL* gpu, | |
| 37 const GrRenderTarget* dstRenderTarget, | |
| 38 const GrTexture* dstCopyTexture, | |
| 39 const GrGeometryStage* geometryProcessor, | |
| 40 const GrFragmentStage* stages[], | |
| 41 int numColorStages, | |
| 42 int numCoverageStages, | |
| 43 int currAttribIndex, | |
| 44 GrGpu::DrawType drawType) { | |
| 45 bool isPathRendering = GrGpu::IsPathRenderingDrawType(drawType); | |
| 46 bool useLocalCoords = !isPathRendering && | |
| 47 random->nextBool() && | |
| 48 currAttribIndex < GrDrawState::kMaxVertexAttribCnt; | |
| 49 | |
| 50 int numStages = numColorStages + numCoverageStages; | |
| 51 fKey.reset(); | |
| 52 | |
| 53 GR_STATIC_ASSERT(0 == kEffectKeyOffsetsAndLengthOffset % sizeof(uint32_t)); | |
| 54 | |
| 55 // Make room for everything up to and including the array of offsets to effe ct keys. | |
| 56 fKey.push_back_n(kEffectKeyOffsetsAndLengthOffset + 2 * sizeof(uint16_t) * ( numStages + | |
| 57 (geometryProcessor ? 1 : 0))); | |
| 58 | |
| 59 bool dstRead = false; | |
| 60 bool fragPos = false; | |
| 61 bool vertexShader = SkToBool(geometryProcessor); | |
| 62 int offset = 0; | |
| 63 if (geometryProcessor) { | |
| 64 const GrGeometryStage* stage = geometryProcessor; | |
| 65 uint16_t* offsetAndSize = reinterpret_cast<uint16_t*>(fKey.begin() + | |
| 66 kEffectKeyOffsetsA ndLengthOffset + | |
| 67 offset * 2 * sizeo f(uint16_t)); | |
| 68 uint32_t effectKeyOffset = fKey.count(); | |
| 69 if (effectKeyOffset > SK_MaxU16) { | |
| 70 fKey.reset(); | |
| 71 return false; | |
| 72 } | |
| 73 GrProcessorKeyBuilder b(&fKey); | |
| 74 uint16_t effectKeySize; | |
| 75 if (!GetProcessorKey(*stage, gpu->glCaps(), useLocalCoords, &b, &effectK eySize)) { | |
| 76 fKey.reset(); | |
| 77 return false; | |
| 78 } | |
| 79 vertexShader = true; | |
| 80 fragPos = stage->getProcessor()->willReadFragmentPosition(); | |
| 81 offsetAndSize[0] = effectKeyOffset; | |
| 82 offsetAndSize[1] = effectKeySize; | |
| 83 offset++; | |
| 84 } | |
| 85 | |
| 86 for (int s = 0; s < numStages; ++s, ++offset) { | |
| 87 const GrFragmentStage* stage = stages[s]; | |
| 88 uint16_t* offsetAndSize = reinterpret_cast<uint16_t*>(fKey.begin() + | |
| 89 kEffectKeyOffsetsA ndLengthOffset + | |
| 90 offset * 2 * sizeo f(uint16_t)); | |
| 91 uint32_t effectKeyOffset = fKey.count(); | |
| 92 if (effectKeyOffset > SK_MaxU16) { | |
| 93 fKey.reset(); | |
| 94 return false; | |
| 95 } | |
| 96 GrProcessorKeyBuilder b(&fKey); | |
| 97 uint16_t effectKeySize; | |
| 98 if (!GetProcessorKey(*stages[s], gpu->glCaps(), useLocalCoords, &b, &eff ectKeySize)) { | |
| 99 fKey.reset(); | |
| 100 return false; | |
| 101 } | |
| 102 get_stage_stats(*stage, &dstRead, &fragPos, &vertexShader); | |
| 103 offsetAndSize[0] = effectKeyOffset; | |
| 104 offsetAndSize[1] = effectKeySize; | |
| 105 } | |
| 106 | |
| 107 KeyHeader* header = this->header(); | |
| 108 memset(header, 0, kHeaderSize); | |
| 109 header->fEmitsPointSize = random->nextBool(); | |
| 110 | |
| 111 header->fPositionAttributeIndex = 0; | |
| 112 | |
| 113 // if the effects have used up all off the available attributes, | |
| 114 // don't try to use color or coverage attributes as input | |
| 115 do { | |
| 116 header->fColorInput = static_cast<GrGLProgramDesc::ColorInput>( | |
| 117 random->nextULessThan(kColorInputCnt)); | |
| 118 } while ((GrDrawState::kMaxVertexAttribCnt <= currAttribIndex || isPathRende ring) && | |
| 119 kAttribute_ColorInput == header->fColorInput); | |
| 120 header->fColorAttributeIndex = (header->fColorInput == kAttribute_ColorInput ) ? | |
| 121 currAttribIndex++ : | |
| 122 -1; | |
| 123 | |
| 124 do { | |
| 125 header->fCoverageInput = static_cast<GrGLProgramDesc::ColorInput>( | |
| 126 random->nextULessThan(kColorInputCnt)); | |
| 127 } while ((GrDrawState::kMaxVertexAttribCnt <= currAttribIndex || isPathRende ring) && | |
| 128 kAttribute_ColorInput == header->fCoverageInput); | |
| 129 header->fCoverageAttributeIndex = (header->fCoverageInput == kAttribute_Colo rInput) ? | |
| 130 currAttribIndex++ : | |
| 131 -1; | |
| 132 bool useGS = random->nextBool(); | |
| 133 #if GR_GL_EXPERIMENTAL_GS | |
| 134 header->fExperimentalGS = gpu->caps()->geometryShaderSupport() && useGS; | |
| 135 #else | |
| 136 (void) useGS; | |
| 137 #endif | |
| 138 | |
| 139 header->fLocalCoordAttributeIndex = useLocalCoords ? currAttribIndex++ : -1; | |
| 140 | |
| 141 header->fColorEffectCnt = numColorStages; | |
| 142 header->fCoverageEffectCnt = numCoverageStages; | |
| 143 | |
| 144 if (dstRead) { | |
| 145 header->fDstReadKey = SkToU8(GrGLFragmentShaderBuilder::KeyForDstRead(ds tCopyTexture, | |
| 146 gpu->glCap s())); | |
| 147 } else { | |
| 148 header->fDstReadKey = 0; | |
| 149 } | |
| 150 if (fragPos) { | |
| 151 header->fFragPosKey = SkToU8(GrGLFragmentShaderBuilder::KeyForFragmentPo sition(dstRenderTarget, | |
| 152 g pu->glCaps())); | |
| 153 } else { | |
| 154 header->fFragPosKey = 0; | |
| 155 } | |
| 156 | |
| 157 header->fUseFragShaderOnly = isPathRendering && gpu->glPathRendering()->text uringMode() == | |
| 158 GrGLPathRendering::FixedFunc tion_TexturingMode; | |
| 159 header->fHasGeometryProcessor = vertexShader; | |
| 160 | |
| 161 GrOptDrawState::PrimaryOutputType primaryOutput; | |
| 162 GrOptDrawState::SecondaryOutputType secondaryOutput; | |
| 163 if (!dstRead) { | |
| 164 primaryOutput = GrOptDrawState::kModulate_PrimaryOutputType; | |
| 165 } else { | |
| 166 primaryOutput = static_cast<GrOptDrawState::PrimaryOutputType>( | |
| 167 random->nextULessThan(GrOptDrawState::kPrimaryOutputTypeCnt)); | |
| 168 } | |
| 169 | |
| 170 if (GrOptDrawState::kCombineWithDst_PrimaryOutputType == primaryOutput || | |
| 171 !gpu->caps()->dualSourceBlendingSupport()) { | |
| 172 secondaryOutput = GrOptDrawState::kNone_SecondaryOutputType; | |
| 173 } else { | |
| 174 secondaryOutput = static_cast<GrOptDrawState::SecondaryOutputType>( | |
| 175 random->nextULessThan(GrOptDrawState::kSecondaryOutputTypeCnt)); | |
| 176 } | |
| 177 | |
| 178 header->fPrimaryOutputType = primaryOutput; | |
| 179 header->fSecondaryOutputType = secondaryOutput; | |
| 180 | |
| 181 this->finalize(); | |
| 182 return true; | |
| 183 } | 50 } |
| 184 | 51 |
| 185 // TODO clean this up, we have to do this to test geometry processors but there has got to be | 52 // TODO clean this up, we have to do this to test geometry processors but there has got to be |
| 186 // a better way. In the mean time, we actually fill out these generic vertex at tribs below with | 53 // a better way. In the mean time, we actually fill out these generic vertex at tribs below with |
| 187 // the correct vertex attribs from the GP. We have to ensure, however, we don't try to add more | 54 // the correct vertex attribs from the GP. We have to ensure, however, we don't try to add more |
| 188 // than two attributes. | 55 // than two attributes. In addition, we 'pad' the below array with GPs up to 6 entries. |
|
egdaniel
2014/10/06 14:19:02
add into comment that the 6 comes from 4 ff va's a
| |
| 189 GrVertexAttrib genericVertexAttribs[] = { | 56 GrVertexAttrib genericVertexAttribs[] = { |
|
egdaniel
2014/10/06 14:19:02
kGenericVertexAttribs
| |
| 190 { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, | 57 { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, |
| 191 { kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding } , | 58 { kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding } , |
| 59 { kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding } , | |
| 60 { kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding } , | |
| 61 { kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding } , | |
| 192 { kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding } | 62 { kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding } |
| 193 }; | 63 }; |
| 194 | 64 |
| 195 /* | 65 /* |
| 196 * convert sl type to vertexattrib type, not a complete implementation, only use for debugging | 66 * convert sl type to vertexattrib type, not a complete implementation, only use for debugging |
| 197 */ | 67 */ |
| 198 GrVertexAttribType convert_sltype_to_attribtype(GrSLType type) { | 68 static GrVertexAttribType convert_sltype_to_attribtype(GrSLType type) { |
| 199 switch (type) { | 69 switch (type) { |
| 200 case kFloat_GrSLType: | 70 case kFloat_GrSLType: |
| 201 return kFloat_GrVertexAttribType; | 71 return kFloat_GrVertexAttribType; |
| 202 case kVec2f_GrSLType: | 72 case kVec2f_GrSLType: |
| 203 return kVec2f_GrVertexAttribType; | 73 return kVec2f_GrVertexAttribType; |
| 204 case kVec3f_GrSLType: | 74 case kVec3f_GrSLType: |
| 205 return kVec3f_GrVertexAttribType; | 75 return kVec3f_GrVertexAttribType; |
| 206 case kVec4f_GrSLType: | 76 case kVec4f_GrSLType: |
| 207 return kVec4f_GrVertexAttribType; | 77 return kVec4f_GrVertexAttribType; |
| 208 default: | 78 default: |
| 209 SkFAIL("Type isn't convertible"); | 79 SkFAIL("Type isn't convertible"); |
| 210 return kFloat_GrVertexAttribType; | 80 return kFloat_GrVertexAttribType; |
| 211 } | 81 } |
| 212 } | 82 } |
| 213 // TODO end test hack | 83 // TODO end test hack |
|
egdaniel
2014/10/06 14:19:02
What is this TODO for?
| |
| 214 | 84 |
| 85 static void setup_random_ff_attribute(GrVertexAttribBinding binding, GrVertexAtt ribType type, | |
| 86 SkRandom* random, int* attribIndex, int* r unningStride) { | |
| 87 if (random->nextBool()) { | |
| 88 genericVertexAttribs[*attribIndex].fType = type; | |
| 89 genericVertexAttribs[*attribIndex].fOffset = *runningStride; | |
| 90 genericVertexAttribs[*attribIndex].fBinding = binding; | |
| 91 *runningStride += GrVertexAttribTypeSize(genericVertexAttribs[(*attribIn dex)++].fType); | |
| 92 } | |
| 93 } | |
| 94 | |
| 95 static void set_random_gp(GrGpuGL* gpu, SkRandom* random, GrTexture* dummyTextur es[]) { | |
| 96 GrProgramElementRef<const GrGeometryProcessor> gp( | |
| 97 GrProcessorTestFactory<GrGeometryProcessor>::CreateStage(random, | |
| 98 gpu->getCon text(), | |
| 99 *gpu->caps( ), | |
| 100 dummyTextur es)); | |
| 101 SkASSERT(gp); | |
| 102 | |
| 103 // we have to set dummy vertex attributes, first we setup the fixed function attributes | |
| 104 // always leave the position attribute untouched in the array | |
| 105 int attribIndex = 1; | |
| 106 int runningStride = GrVertexAttribTypeSize(genericVertexAttribs[0].fType); | |
| 107 | |
| 108 // local coords | |
| 109 setup_random_ff_attribute(kLocalCoord_GrVertexAttribBinding, kVec2f_GrVertex AttribType, | |
| 110 random, &attribIndex, &runningStride); | |
| 111 | |
| 112 // color | |
| 113 setup_random_ff_attribute(kColor_GrVertexAttribBinding, kVec4f_GrVertexAttri bType, | |
| 114 random, &attribIndex, &runningStride); | |
| 115 | |
| 116 // coverage | |
| 117 setup_random_ff_attribute(kCoverage_GrVertexAttribBinding, kVec4f_GrVertexAt tribType, | |
| 118 random, &attribIndex, &runningStride); | |
| 119 | |
| 120 // Update the geometry processor attributes | |
| 121 const GrGeometryProcessor::VertexAttribArray& v = gp->getVertexAttribs(); | |
| 122 int numGPAttribs = v.count(); | |
| 123 SkASSERT(numGPAttribs <= GrGeometryProcessor::kMaxVertexAttribs && | |
| 124 GrGeometryProcessor::kMaxVertexAttribs == 2); | |
| 125 for (int i = 0; i < numGPAttribs; i++) { | |
| 126 genericVertexAttribs[i + attribIndex].fType = | |
| 127 convert_sltype_to_attribtype(v[i].getType()); | |
| 128 genericVertexAttribs[i + attribIndex].fOffset = runningStride; | |
| 129 genericVertexAttribs[i + attribIndex].fBinding = kGeometryProcessor_GrVe rtexAttribBinding; | |
| 130 runningStride += GrVertexAttribTypeSize(genericVertexAttribs[i + attribI ndex].fType); | |
| 131 } | |
| 132 | |
| 133 // update the vertex attributes with the ds | |
| 134 GrDrawState* ds = gpu->drawState(); | |
| 135 ds->setVertexAttribs<genericVertexAttribs>(attribIndex + numGPAttribs, runni ngStride); | |
| 136 ds->setGeometryProcessor(gp); | |
| 137 } | |
| 138 | |
| 139 void set_random_color_coverage_stages(GrGpuGL* gpu, | |
|
egdaniel
2014/10/06 14:19:02
put some of these params on same line
bsalomon
2014/10/06 14:29:04
static?
bsalomon
2014/10/06 14:29:04
we definitely have mixed styles. In a lot of place
| |
| 140 int maxStages, | |
| 141 bool usePathRendering, | |
| 142 SkRandom* random, | |
| 143 GrTexture* dummyTextures[]) { | |
| 144 int numProcs = random->nextULessThan(maxStages + 1); | |
| 145 int numColorProcs = random->nextULessThan(numProcs + 1); | |
| 146 | |
| 147 int currTextureCoordSet = 0; | |
| 148 for (int s = 0; s < numProcs;) { | |
| 149 GrProgramElementRef<GrFragmentProcessor> fp( | |
| 150 GrProcessorTestFactory<GrFragmentProcessor>::CreateStage(random, | |
| 151 gpu->ge tContext(), | |
| 152 *gpu->c aps(), | |
| 153 dummyTe xtures)); | |
| 154 SkASSERT(fp); | |
| 155 | |
| 156 // don't add dst color reads to coverage stage | |
| 157 if (s >= numColorProcs && fp->willReadDstColor()) { | |
| 158 continue; | |
| 159 } | |
| 160 | |
| 161 // If adding this effect would exceed the max texture coord set count th en generate a | |
| 162 // new random effect. | |
| 163 if (usePathRendering && gpu->glPathRendering()->texturingMode() == | |
| 164 GrGLPathRendering::FixedFunction_TexturingMode) {; | |
| 165 int numTransforms = fp->numTransforms(); | |
| 166 if (currTextureCoordSet + numTransforms > | |
| 167 gpu->glCaps().maxFixedFunctionTextureCoords()) { | |
| 168 continue; | |
| 169 } | |
| 170 currTextureCoordSet += numTransforms; | |
| 171 } | |
| 172 | |
| 173 // finally add the stage to the correct pipeline in the drawstate | |
| 174 GrDrawState* ds = gpu->drawState(); | |
| 175 if (s < numColorProcs) { | |
| 176 ds->addColorProcessor(fp); | |
| 177 } else { | |
| 178 ds->addCoverageProcessor(fp); | |
| 179 } | |
| 180 ++s; | |
| 181 } | |
| 182 } | |
| 183 | |
| 184 // There are only a few cases of random colors which interest us | |
| 185 enum ColorMode { | |
| 186 kAllOnes_ColorMode, | |
| 187 kAllZeros_ColorMode, | |
| 188 kAlphaOne_ColorMode, | |
| 189 kRandom_ColorMode, | |
| 190 kLast_ColorMode = kRandom_ColorMode | |
| 191 }; | |
| 192 | |
| 193 static void set_random_color(GrGpuGL* gpu, SkRandom* random) { | |
| 194 ColorMode colorMode = ColorMode(random->nextULessThan(kLast_ColorMode + 1)); | |
| 195 GrColor color; | |
| 196 switch (colorMode) { | |
| 197 case kAllOnes_ColorMode: | |
| 198 color = GrColorPackRGBA(0xFF, 0xFF, 0xFF, 0xFF); | |
| 199 break; | |
| 200 case kAllZeros_ColorMode: | |
| 201 color = GrColorPackRGBA(0, 0, 0, 0); | |
| 202 break; | |
| 203 case kAlphaOne_ColorMode: | |
| 204 color = GrColorPackRGBA(random->nextULessThan(256), | |
| 205 random->nextULessThan(256), | |
| 206 random->nextULessThan(256), | |
| 207 0xFF); | |
| 208 break; | |
| 209 case kRandom_ColorMode: | |
| 210 uint8_t alpha = random->nextULessThan(256); | |
| 211 color = GrColorPackRGBA(random->nextRangeU(0, alpha), | |
| 212 random->nextRangeU(0, alpha), | |
| 213 random->nextRangeU(0, alpha), | |
| 214 alpha); | |
| 215 break; | |
| 216 } | |
| 217 GrColorIsPMAssert(color); | |
| 218 gpu->drawState()->setColor(color); | |
| 219 } | |
| 220 | |
| 221 // There are only a few cases of random coverages which interest us | |
| 222 enum CoverageMode { | |
| 223 kZero_CoverageMode, | |
| 224 kFF_CoverageMode, | |
| 225 kRandom_CoverageMode, | |
| 226 kLast_CoverageMode = kRandom_CoverageMode | |
| 227 }; | |
| 228 | |
| 229 static void set_random_coverage(GrGpuGL* gpu, SkRandom* random) { | |
| 230 CoverageMode coverageMode = CoverageMode(random->nextULessThan(kLast_Coverag eMode + 1)); | |
| 231 uint8_t coverage; | |
| 232 switch (coverageMode) { | |
| 233 case kZero_CoverageMode: | |
| 234 coverage = 0; | |
| 235 break; | |
| 236 case kFF_CoverageMode: | |
| 237 coverage = 0xFF; | |
| 238 break; | |
| 239 case kRandom_CoverageMode: | |
| 240 coverage = uint8_t(random->nextU()); | |
| 241 break; | |
| 242 } | |
| 243 gpu->drawState()->setCoverage(coverage); | |
| 244 } | |
| 245 | |
| 246 // there is only one hint right now, but we have to make sure more hints aren't added without | |
| 247 // testing them | |
| 248 static void set_random_hints(GrGpuGL* gpu, SkRandom* random) { | |
| 249 GR_STATIC_ASSERT(GrDrawState::kLast_Hint == GrDrawState::kVertexColorsAreOpa que_Hint); | |
| 250 | |
| 251 gpu->drawState()->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, random-> nextBool()); | |
|
bsalomon
2014/10/06 14:29:04
Maybe just go ahead with
if (int i = 1, i <= kLa
| |
| 252 } | |
| 253 | |
| 254 #define SET_RANDOM_BIT(flag) \ | |
| 255 (random->nextBool() << pow++) & (flag) | |
| 256 | |
| 257 // similar to the above, we have to prevent random state bits from being added w ithout testing | |
| 258 static void set_random_state(GrGpuGL* gpu, SkRandom* random) { | |
| 259 GR_STATIC_ASSERT(GrDrawState::kLastPublicStateBit == GrDrawState::kCoverageD rawing_StateBit); | |
|
bsalomon
2014/10/06 14:29:04
loop?
| |
| 260 | |
| 261 uint32_t state = 0; | |
| 262 uint32_t pow = 0; | |
| 263 state |= SET_RANDOM_BIT(GrDrawState::kDither_StateBit); | |
| 264 state |= SET_RANDOM_BIT(GrDrawState::kHWAntialias_StateBit); | |
| 265 state |= SET_RANDOM_BIT(GrDrawState::kClip_StateBit); | |
| 266 state |= SET_RANDOM_BIT(GrDrawState::kNoColorWrites_StateBit); | |
| 267 state |= SET_RANDOM_BIT(GrDrawState::kCoverageDrawing_StateBit); | |
| 268 gpu->drawState()->enableState(state); | |
| 269 } | |
| 270 | |
| 271 // this function will randomly pick non-self referencing blend modes | |
| 272 static void set_random_blend_func(GrGpuGL* gpu, SkRandom* random) { | |
| 273 GrBlendCoeff src; | |
| 274 do { | |
| 275 src = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPub licGrBlendCoeff)); | |
| 276 } while (GrBlendCoeffRefsSrc(src)); | |
| 277 | |
| 278 GrBlendCoeff dst; | |
| 279 do { | |
| 280 dst = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPub licGrBlendCoeff)); | |
| 281 } while (GrBlendCoeffRefsDst(dst)); | |
| 282 | |
| 283 gpu->drawState()->setBlendFunc(src, dst); | |
| 284 } | |
| 285 | |
| 286 // right now, the only thing we seem to care about in drawState's stencil is 'do esWrite()' | |
| 287 static void set_random_stencil(GrGpuGL* gpu, SkRandom* random) { | |
| 288 GR_STATIC_CONST_SAME_STENCIL(kDoesWriteStencil, | |
| 289 kReplace_StencilOp, | |
| 290 kReplace_StencilOp, | |
| 291 kAlways_StencilFunc, | |
| 292 0xffff, | |
| 293 0xffff, | |
| 294 0xffff); | |
| 295 GR_STATIC_CONST_SAME_STENCIL(kDoesNotWriteStencil, | |
| 296 kKeep_StencilOp, | |
| 297 kKeep_StencilOp, | |
| 298 kNever_StencilFunc, | |
| 299 0xffff, | |
| 300 0xffff, | |
| 301 0xffff); | |
| 302 | |
| 303 if (random->nextBool()) { | |
| 304 gpu->drawState()->setStencil(kDoesWriteStencil); | |
| 305 } else { | |
| 306 gpu->drawState()->setStencil(kDoesNotWriteStencil); | |
| 307 } | |
| 308 } | |
| 215 | 309 |
| 216 bool GrGpuGL::programUnitTest(int maxStages) { | 310 bool GrGpuGL::programUnitTest(int maxStages) { |
| 217 | 311 // setup dummy textures |
| 218 GrTextureDesc dummyDesc; | 312 GrTextureDesc dummyDesc; |
| 219 dummyDesc.fFlags = kRenderTarget_GrTextureFlagBit; | 313 dummyDesc.fFlags = kRenderTarget_GrTextureFlagBit; |
| 220 dummyDesc.fConfig = kSkia8888_GrPixelConfig; | 314 dummyDesc.fConfig = kSkia8888_GrPixelConfig; |
| 221 dummyDesc.fWidth = 34; | 315 dummyDesc.fWidth = 34; |
| 222 dummyDesc.fHeight = 18; | 316 dummyDesc.fHeight = 18; |
| 223 SkAutoTUnref<GrTexture> dummyTexture1(this->createTexture(dummyDesc, NULL, 0 )); | 317 SkAutoTUnref<GrTexture> dummyTexture1(this->createTexture(dummyDesc, NULL, 0 )); |
| 224 dummyDesc.fFlags = kNone_GrTextureFlags; | 318 dummyDesc.fFlags = kNone_GrTextureFlags; |
| 225 dummyDesc.fConfig = kAlpha_8_GrPixelConfig; | 319 dummyDesc.fConfig = kAlpha_8_GrPixelConfig; |
| 226 dummyDesc.fWidth = 16; | 320 dummyDesc.fWidth = 16; |
| 227 dummyDesc.fHeight = 22; | 321 dummyDesc.fHeight = 22; |
| 228 SkAutoTUnref<GrTexture> dummyTexture2(this->createTexture(dummyDesc, NULL, 0 )); | 322 SkAutoTUnref<GrTexture> dummyTexture2(this->createTexture(dummyDesc, NULL, 0 )); |
| 229 | 323 |
| 230 if (!dummyTexture1 || ! dummyTexture2) { | 324 if (!dummyTexture1 || ! dummyTexture2) { |
| 231 return false; | 325 return false; |
| 232 } | 326 } |
| 233 | 327 |
| 234 static const int NUM_TESTS = 512; | 328 GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()}; |
| 329 | |
| 330 // Setup texture cache id key | |
| 331 const GrCacheID::Domain glProgramsDomain = GrCacheID::GenerateDomain(); | |
| 332 GrCacheID::Key key; | |
| 333 memset(&key, 0, sizeof(key)); | |
| 334 key.fData32[0] = kRenderTargetWidth; | |
| 335 key.fData32[1] = kRenderTargetHeight; | |
| 336 GrCacheID glProgramsCacheID(glProgramsDomain, key); | |
| 337 | |
| 338 // setup clip | |
| 339 SkRect screen = | |
| 340 SkRect::MakeWH(SkIntToScalar(kRenderTargetWidth), SkIntToScalar(kRen derTargetHeight)); | |
| 341 | |
| 342 SkClipStack stack; | |
| 343 stack.clipDevRect(screen, SkRegion::kReplace_Op, false); | |
| 344 | |
| 345 // wrap the SkClipStack in a GrClipData | |
| 346 GrClipData clipData; | |
| 347 clipData.fClipStack = &stack; | |
| 348 this->setClip(&clipData); | |
| 235 | 349 |
| 236 SkRandom random; | 350 SkRandom random; |
| 351 static const int NUM_TESTS = 512; | |
| 237 for (int t = 0; t < NUM_TESTS; ++t) { | 352 for (int t = 0; t < NUM_TESTS; ++t) { |
| 353 // setup random render target | |
| 354 GrTGpuResourceRef<GrRenderTarget> rt( | |
| 355 SkRef(random_render_target(this, | |
| 356 glProgramsCacheID, | |
| 357 &random)), | |
| 358 GrIORef::kWrite_IOType); | |
| 359 GrDrawState* ds = this->drawState(); | |
| 360 ds->setRenderTarget(rt.get()); | |
| 238 | 361 |
| 239 #if 0 | 362 // if path rendering we have to setup a couple of things like the draw t ype |
| 240 GrPrintf("\nTest Program %d\n-------------\n", t); | |
| 241 static const int stop = -1; | |
| 242 if (t == stop) { | |
| 243 int breakpointhere = 9; | |
| 244 } | |
| 245 #endif | |
| 246 | |
| 247 GrGLProgramDesc pdesc; | |
| 248 | |
| 249 int currAttribIndex = 1; // we need to always leave room for position | |
| 250 int currTextureCoordSet = 0; | |
| 251 GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()}; | |
| 252 | |
| 253 int numStages = random.nextULessThan(maxStages + 1); | |
| 254 int numColorStages = random.nextULessThan(numStages + 1); | |
| 255 int numCoverageStages = numStages - numColorStages; | |
| 256 | |
| 257 SkAutoSTMalloc<8, const GrFragmentStage*> stages(numStages); | |
| 258 | |
| 259 bool usePathRendering = this->glCaps().pathRenderingSupport() && random. nextBool(); | 363 bool usePathRendering = this->glCaps().pathRenderingSupport() && random. nextBool(); |
| 260 | 364 |
| 261 GrGpu::DrawType drawType = usePathRendering ? GrGpu::kDrawPath_DrawType : | 365 GrGpu::DrawType drawType = usePathRendering ? GrGpu::kDrawPath_DrawType : |
| 262 GrGpu::kDrawPoints_DrawTyp e; | 366 GrGpu::kDrawPoints_DrawTyp e; |
| 263 | 367 |
| 264 SkAutoTDelete<GrGeometryStage> geometryProcessor; | 368 // twiddle drawstate knobs randomly |
| 265 bool hasGeometryProcessor = usePathRendering ? false : random.nextBool() ; | 369 bool hasGeometryProcessor = usePathRendering ? false : random.nextBool() ; |
| 266 if (hasGeometryProcessor) { | 370 if (hasGeometryProcessor) { |
| 267 while (true) { | 371 set_random_gp(this, &random, dummyTextures); |
| 268 SkAutoTUnref<const GrGeometryProcessor> effect( | 372 } |
| 269 GrProcessorTestFactory<GrGeometryProcessor>::CreateStage (&random, this->getContext(), *this->caps(), | 373 set_random_color_coverage_stages(this, maxStages, usePathRendering, &ran dom, dummyTextures); |
| 270 dummyTextures)); | 374 set_random_color(this, &random); |
| 271 SkASSERT(effect); | 375 set_random_coverage(this, &random); |
| 272 // Only geometryProcessor can use vertex shader | 376 set_random_hints(this, &random); |
| 273 GrGeometryStage* stage = SkNEW_ARGS(GrGeometryStage, (effect.get ())); | 377 set_random_state(this, &random); |
| 274 geometryProcessor.reset(stage); | 378 set_random_blend_func(this, &random); |
| 379 set_random_stencil(this, &random); | |
| 275 | 380 |
| 276 // we have to set dummy vertex attribs | 381 // create optimized draw state, setup readDst texture if required, and b uild a descriptor |
| 277 const GrGeometryProcessor::VertexAttribArray& v = effect->getVer texAttribs(); | 382 // and program |
| 278 int numVertexAttribs = v.count(); | 383 SkAutoTUnref<GrOptDrawState> ods(ds->createOptState(*this->caps())); |
| 384 const GrGeometryStage* geometryProcessor = NULL; | |
| 385 SkSTArray<8, const GrFragmentStage*, true> colorStages; | |
| 386 SkSTArray<8, const GrFragmentStage*, true> coverageStages; | |
| 387 GrGLProgramDesc desc; | |
| 388 GrDeviceCoordTexture dstCopy; | |
| 279 | 389 |
| 280 SkASSERT(GrGeometryProcessor::kMaxVertexAttribs == 2 && | 390 if (!this->setupDstReadIfNecessary(&dstCopy, NULL)) { |
| 281 GrGeometryProcessor::kMaxVertexAttribs >= numVertexAttr ibs); | 391 SkDEBUGFAIL("Couldn't setup dst read texture"); |
| 282 size_t runningStride = GrVertexAttribTypeSize(genericVertexAttri bs[0].fType); | |
| 283 for (int i = 0; i < numVertexAttribs; i++) { | |
| 284 genericVertexAttribs[i + 1].fOffset = runningStride; | |
| 285 genericVertexAttribs[i + 1].fType = | |
| 286 convert_sltype_to_attribtype(v[i].getType()); | |
| 287 runningStride += GrVertexAttribTypeSize(genericVertexAttribs [i + 1].fType); | |
| 288 } | |
| 289 | |
| 290 // update the vertex attributes with the ds | |
| 291 GrDrawState* ds = this->drawState(); | |
| 292 ds->setVertexAttribs<genericVertexAttribs>(numVertexAttribs + 1, runningStride); | |
| 293 currAttribIndex = numVertexAttribs + 1; | |
| 294 break; | |
| 295 } | |
| 296 } | |
| 297 for (int s = 0; s < numStages;) { | |
| 298 SkAutoTUnref<const GrFragmentProcessor> effect( | |
| 299 GrProcessorTestFactory<GrFragmentProcessor>::CreateStage( | |
| 300 &ran dom, | |
| 301 this ->getContext(), | |
| 302 *thi s->caps(), | |
| 303 dumm yTextures)); | |
| 304 SkASSERT(effect); | |
| 305 | |
| 306 // If adding this effect would exceed the max texture coord set coun t then generate a | |
| 307 // new random effect. | |
| 308 if (usePathRendering && this->glPathRendering()->texturingMode() == | |
| 309 GrGLPathRendering::FixedFunction_TexturingMo de) {; | |
| 310 int numTransforms = effect->numTransforms(); | |
| 311 if (currTextureCoordSet + numTransforms > this->glCaps().maxFixe dFunctionTextureCoords()) { | |
| 312 continue; | |
| 313 } | |
| 314 currTextureCoordSet += numTransforms; | |
| 315 } | |
| 316 GrFragmentStage* stage = SkNEW_ARGS(GrFragmentStage, (effect.get())) ; | |
| 317 | |
| 318 stages[s] = stage; | |
| 319 ++s; | |
| 320 } | |
| 321 const GrTexture* dstTexture = random.nextBool() ? dummyTextures[0] : dum myTextures[1]; | |
| 322 if (!pdesc.setRandom(&random, | |
| 323 this, | |
| 324 dummyTextures[0]->asRenderTarget(), | |
| 325 dstTexture, | |
| 326 geometryProcessor.get(), | |
| 327 stages.get(), | |
| 328 numColorStages, | |
| 329 numCoverageStages, | |
| 330 currAttribIndex, | |
| 331 drawType)) { | |
| 332 return false; | 392 return false; |
| 333 } | 393 } |
| 334 | 394 if (!GrGLProgramDesc::Build(*ods, |
| 335 SkAutoTUnref<GrGLProgram> program(GrGLProgram::Create(this, | 395 drawType, |
| 336 pdesc, | 396 ods->getSrcBlendCoeff(), |
| 337 geometryProcessor. get(), | 397 ods->getDstBlendCoeff(), |
| 338 stages, | 398 this, |
| 339 stages + numColorS tages)); | 399 dstCopy.texture() ? &dstCopy : NULL, |
| 340 for (int s = 0; s < numStages; ++s) { | 400 &geometryProcessor, |
| 341 SkDELETE(stages[s]); | 401 &colorStages, |
| 402 &coverageStages, | |
| 403 &desc)) { | |
| 404 SkDEBUGFAIL("Failed to generate GL program descriptor"); | |
| 405 return false; | |
| 342 } | 406 } |
| 407 SkAutoTUnref<GrGLProgram> program(SkSafeRef(GrGLProgram::Create(this, | |
| 408 desc, | |
| 409 geometry Processor, | |
| 410 colorSta ges.begin(), | |
| 411 coverage Stages.begin()))); | |
| 343 if (NULL == program.get()) { | 412 if (NULL == program.get()) { |
| 413 SkDEBUGFAIL("Failed to create program!"); | |
| 344 return false; | 414 return false; |
| 345 } | 415 } |
| 346 | 416 |
| 347 // We have to reset the drawstate because we might have added a gp | 417 // We have to reset the drawstate because we might have added a gp |
| 348 this->drawState()->reset(); | 418 ds->reset(); |
| 349 } | 419 } |
| 350 return true; | 420 return true; |
| 351 } | 421 } |
| 352 | 422 |
| 353 DEF_GPUTEST(GLPrograms, reporter, factory) { | 423 DEF_GPUTEST(GLPrograms, reporter, factory) { |
| 354 for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) { | 424 for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) { |
| 355 GrContext* context = factory->get(static_cast<GrContextFactory::GLContex tType>(type)); | 425 GrContext* context = factory->get(static_cast<GrContextFactory::GLContex tType>(type)); |
| 356 if (context) { | 426 if (context) { |
| 357 GrGpuGL* gpu = static_cast<GrGpuGL*>(context->getGpu()); | 427 GrGpuGL* gpu = static_cast<GrGpuGL*>(context->getGpu()); |
| 358 int maxStages = 6; | 428 int maxStages = 6; |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 386 SkRect::MakeWH(SK_Scalar1, SK_Scalar1), SK_Scalar1)); | 456 SkRect::MakeWH(SK_Scalar1, SK_Scalar1), SK_Scalar1)); |
| 387 GrConfigConversionEffect::Create(NULL, | 457 GrConfigConversionEffect::Create(NULL, |
| 388 false, | 458 false, |
| 389 GrConfigConversionEffect::kNone_PMConversio n, | 459 GrConfigConversionEffect::kNone_PMConversio n, |
| 390 SkMatrix::I()); | 460 SkMatrix::I()); |
| 391 SkScalar matrix[20]; | 461 SkScalar matrix[20]; |
| 392 SkAutoTUnref<SkColorMatrixFilter> cmf(SkColorMatrixFilter::Create(matrix)); | 462 SkAutoTUnref<SkColorMatrixFilter> cmf(SkColorMatrixFilter::Create(matrix)); |
| 393 } | 463 } |
| 394 | 464 |
| 395 #endif | 465 #endif |
| OLD | NEW |