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, | |
| 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 return NULL; | |
| 46 } | |
| 29 } | 47 } |
| 30 if (stage.getProcessor()->willReadFragmentPosition()) { | 48 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 } | 49 } |
| 184 | 50 |
| 185 // TODO clean this up, we have to do this to test geometry processors but there has got to be | 51 // 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 | 52 // 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 | 53 // the correct vertex attribs from the GP. We have to ensure, however, we don't try to add more |
| 188 // than two attributes. | 54 // than two attributes. In addition, we 'pad' the below array with GPs up to 6 entries, 4 fixed |
| 189 GrVertexAttrib genericVertexAttribs[] = { | 55 // function vertex attributes and 2 GP custom attributes. |
| 56 GrVertexAttrib 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 // end test hack |
| 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 kGenericVertexAttribs[*attribIndex].fType = type; | |
| 89 kGenericVertexAttribs[*attribIndex].fOffset = *runningStride; | |
| 90 kGenericVertexAttribs[*attribIndex].fBinding = binding; | |
| 91 *runningStride += GrVertexAttribTypeSize(kGenericVertexAttribs[(*attribI ndex)++].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(kGenericVertexAttribs[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 kGenericVertexAttribs[i + attribIndex].fType = | |
| 127 convert_sltype_to_attribtype(v[i].getType()); | |
| 128 kGenericVertexAttribs[i + attribIndex].fOffset = runningStride; | |
| 129 kGenericVertexAttribs[i + attribIndex].fBinding = kGeometryProcessor_GrV ertexAttribBinding; | |
| 130 runningStride += GrVertexAttribTypeSize(kGenericVertexAttribs[i + attrib Index].fType); | |
| 131 } | |
| 132 | |
| 133 // update the vertex attributes with the ds | |
| 134 GrDrawState* ds = gpu->drawState(); | |
| 135 ds->setVertexAttribs<kGenericVertexAttribs>(attribIndex + numGPAttribs, runn ingStride); | |
| 136 ds->setGeometryProcessor(gp); | |
| 137 } | |
| 138 | |
| 139 static void set_random_color_coverage_stages(GrGpuGL* gpu, | |
| 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 static void set_random_hints(GrGpuGL* gpu, SkRandom* random) { | |
| 247 for (int i = 1; i <= GrDrawState::kLast_Hint; i <<= 1) { | |
| 248 gpu->drawState()->setHint(GrDrawState::Hints(i), random->nextBool()); | |
| 249 } | |
| 250 } | |
| 251 | |
| 252 static void set_random_state(GrGpuGL* gpu, SkRandom* random) { | |
| 253 int state = 0; | |
| 254 for (int i = 1; i <= GrDrawState::kLastPublicStateBit; i <<= 1) { | |
| 255 state |= random->nextBool() * i; | |
| 256 } | |
| 257 gpu->drawState()->enableState(state); | |
| 258 } | |
| 259 | |
| 260 // this function will randomly pick non-self referencing blend modes | |
| 261 static void set_random_blend_func(GrGpuGL* gpu, SkRandom* random) { | |
| 262 GrBlendCoeff src; | |
| 263 do { | |
| 264 src = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPub licGrBlendCoeff)); | |
| 265 } while (GrBlendCoeffRefsSrc(src)); | |
| 266 | |
| 267 GrBlendCoeff dst; | |
| 268 do { | |
| 269 dst = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPub licGrBlendCoeff)); | |
| 270 } while (GrBlendCoeffRefsDst(dst)); | |
| 271 | |
| 272 gpu->drawState()->setBlendFunc(src, dst); | |
| 273 } | |
| 274 | |
| 275 // right now, the only thing we seem to care about in drawState's stencil is 'do esWrite()' | |
| 276 static void set_random_stencil(GrGpuGL* gpu, SkRandom* random) { | |
| 277 GR_STATIC_CONST_SAME_STENCIL(kDoesWriteStencil, | |
| 278 kReplace_StencilOp, | |
| 279 kReplace_StencilOp, | |
| 280 kAlways_StencilFunc, | |
| 281 0xffff, | |
| 282 0xffff, | |
| 283 0xffff); | |
| 284 GR_STATIC_CONST_SAME_STENCIL(kDoesNotWriteStencil, | |
| 285 kKeep_StencilOp, | |
| 286 kKeep_StencilOp, | |
| 287 kNever_StencilFunc, | |
| 288 0xffff, | |
| 289 0xffff, | |
| 290 0xffff); | |
| 291 | |
| 292 if (random->nextBool()) { | |
| 293 gpu->drawState()->setStencil(kDoesWriteStencil); | |
| 294 } else { | |
| 295 gpu->drawState()->setStencil(kDoesNotWriteStencil); | |
| 296 } | |
| 297 } | |
| 215 | 298 |
| 216 bool GrGpuGL::programUnitTest(int maxStages) { | 299 bool GrGpuGL::programUnitTest(int maxStages) { |
| 217 | 300 // setup dummy textures |
| 218 GrTextureDesc dummyDesc; | 301 GrTextureDesc dummyDesc; |
| 219 dummyDesc.fFlags = kRenderTarget_GrTextureFlagBit; | 302 dummyDesc.fFlags = kRenderTarget_GrTextureFlagBit; |
| 220 dummyDesc.fConfig = kSkia8888_GrPixelConfig; | 303 dummyDesc.fConfig = kSkia8888_GrPixelConfig; |
| 221 dummyDesc.fWidth = 34; | 304 dummyDesc.fWidth = 34; |
| 222 dummyDesc.fHeight = 18; | 305 dummyDesc.fHeight = 18; |
| 223 SkAutoTUnref<GrTexture> dummyTexture1(this->createTexture(dummyDesc, NULL, 0 )); | 306 SkAutoTUnref<GrTexture> dummyTexture1(this->createTexture(dummyDesc, NULL, 0 )); |
| 224 dummyDesc.fFlags = kNone_GrTextureFlags; | 307 dummyDesc.fFlags = kNone_GrTextureFlags; |
| 225 dummyDesc.fConfig = kAlpha_8_GrPixelConfig; | 308 dummyDesc.fConfig = kAlpha_8_GrPixelConfig; |
| 226 dummyDesc.fWidth = 16; | 309 dummyDesc.fWidth = 16; |
| 227 dummyDesc.fHeight = 22; | 310 dummyDesc.fHeight = 22; |
| 228 SkAutoTUnref<GrTexture> dummyTexture2(this->createTexture(dummyDesc, NULL, 0 )); | 311 SkAutoTUnref<GrTexture> dummyTexture2(this->createTexture(dummyDesc, NULL, 0 )); |
| 229 | 312 |
| 230 if (!dummyTexture1 || ! dummyTexture2) { | 313 if (!dummyTexture1 || ! dummyTexture2) { |
| 314 SkDebugf("Could not allocate dummy textures"); | |
| 231 return false; | 315 return false; |
| 232 } | 316 } |
| 233 | 317 |
| 234 static const int NUM_TESTS = 512; | 318 GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()}; |
| 319 | |
| 320 // Setup texture cache id key | |
| 321 const GrCacheID::Domain glProgramsDomain = GrCacheID::GenerateDomain(); | |
| 322 GrCacheID::Key key; | |
| 323 memset(&key, 0, sizeof(key)); | |
| 324 key.fData32[0] = kRenderTargetWidth; | |
| 325 key.fData32[1] = kRenderTargetHeight; | |
| 326 GrCacheID glProgramsCacheID(glProgramsDomain, key); | |
| 327 | |
| 328 // setup clip | |
| 329 SkRect screen = | |
| 330 SkRect::MakeWH(SkIntToScalar(kRenderTargetWidth), SkIntToScalar(kRen derTargetHeight)); | |
| 331 | |
| 332 SkClipStack stack; | |
| 333 stack.clipDevRect(screen, SkRegion::kReplace_Op, false); | |
| 334 | |
| 335 // wrap the SkClipStack in a GrClipData | |
| 336 GrClipData clipData; | |
| 337 clipData.fClipStack = &stack; | |
| 338 this->setClip(&clipData); | |
| 235 | 339 |
| 236 SkRandom random; | 340 SkRandom random; |
| 237 for (int t = 0; t < NUM_TESTS; ++t) { | 341 static const int NUM_TESTS = 512; |
| 342 for (int t = 0; t < NUM_TESTS;) { | |
| 343 // setup random render target(can fail) | |
| 344 GrRenderTarget* rtPtr = random_render_target(this, glProgramsCacheID, &r andom); | |
| 345 if (!rtPtr) { | |
| 346 SkDebugf("Could not allocate render target"); | |
| 347 return false; | |
| 348 } | |
| 349 GrTGpuResourceRef<GrRenderTarget> rt(SkRef(rtPtr), GrIORef::kWrite_IOTyp e); | |
| 238 | 350 |
| 239 #if 0 | 351 GrDrawState* ds = this->drawState(); |
| 240 GrPrintf("\nTest Program %d\n-------------\n", t); | 352 ds->setRenderTarget(rt.get()); |
| 241 static const int stop = -1; | |
| 242 if (t == stop) { | |
| 243 int breakpointhere = 9; | |
| 244 } | |
| 245 #endif | |
| 246 | 353 |
| 247 GrGLProgramDesc pdesc; | 354 // if path rendering we have to setup a couple of things like the draw t ype |
| 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(); | 355 bool usePathRendering = this->glCaps().pathRenderingSupport() && random. nextBool(); |
| 260 | 356 |
| 261 GrGpu::DrawType drawType = usePathRendering ? GrGpu::kDrawPath_DrawType : | 357 GrGpu::DrawType drawType = usePathRendering ? GrGpu::kDrawPath_DrawType : |
| 262 GrGpu::kDrawPoints_DrawTyp e; | 358 GrGpu::kDrawPoints_DrawTyp e; |
| 263 | 359 |
| 264 SkAutoTDelete<GrGeometryStage> geometryProcessor; | 360 // twiddle drawstate knobs randomly |
| 265 bool hasGeometryProcessor = usePathRendering ? false : random.nextBool() ; | 361 bool hasGeometryProcessor = usePathRendering ? false : random.nextBool() ; |
| 266 if (hasGeometryProcessor) { | 362 if (hasGeometryProcessor) { |
| 267 while (true) { | 363 set_random_gp(this, &random, dummyTextures); |
| 268 SkAutoTUnref<const GrGeometryProcessor> effect( | 364 } |
| 269 GrProcessorTestFactory<GrGeometryProcessor>::CreateStage (&random, this->getContext(), *this->caps(), | 365 set_random_color_coverage_stages(this, maxStages, usePathRendering, &ran dom, dummyTextures); |
| 270 dummyTextures)); | 366 set_random_color(this, &random); |
| 271 SkASSERT(effect); | 367 set_random_coverage(this, &random); |
| 272 // Only geometryProcessor can use vertex shader | 368 set_random_hints(this, &random); |
| 273 GrGeometryStage* stage = SkNEW_ARGS(GrGeometryStage, (effect.get ())); | 369 set_random_state(this, &random); |
| 274 geometryProcessor.reset(stage); | 370 set_random_blend_func(this, &random); |
| 371 set_random_stencil(this, &random); | |
| 275 | 372 |
| 276 // we have to set dummy vertex attribs | 373 // create optimized draw state, setup readDst texture if required, and b uild a descriptor |
| 277 const GrGeometryProcessor::VertexAttribArray& v = effect->getVer texAttribs(); | 374 // and program. ODS creation can fail, so we have to check |
| 278 int numVertexAttribs = v.count(); | 375 SkAutoTUnref<GrOptDrawState> ods(GrOptDrawState::Create(this->getDrawSta te(), |
| 376 *this->caps(), | |
| 377 drawType)); | |
| 378 if (!ods.get()) { | |
| 379 ds->reset(); | |
| 380 continue; | |
| 381 } | |
| 382 const GrGeometryStage* geometryProcessor = NULL; | |
| 383 SkSTArray<8, const GrFragmentStage*, true> colorStages; | |
| 384 SkSTArray<8, const GrFragmentStage*, true> coverageStages; | |
| 385 GrGLProgramDesc desc; | |
| 386 GrDeviceCoordTexture dstCopy; | |
| 279 | 387 |
| 280 SkASSERT(GrGeometryProcessor::kMaxVertexAttribs == 2 && | 388 if (!this->setupDstReadIfNecessary(&dstCopy, NULL)) { |
| 281 GrGeometryProcessor::kMaxVertexAttribs >= numVertexAttr ibs); | 389 SkDebugf("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; | 390 return false; |
| 333 } | 391 } |
| 334 | 392 if (!GrGLProgramDesc::Build(*ods, |
| 335 SkAutoTUnref<GrOptDrawState> optState(GrOptDrawState::Create(this->getDr awState(), | 393 drawType, |
| 336 *this->caps (), | 394 ods->getSrcBlendCoeff(), |
| 337 drawType)); | 395 ods->getDstBlendCoeff(), |
| 396 this, | |
| 397 dstCopy.texture() ? &dstCopy : NULL, | |
| 398 &geometryProcessor, | |
| 399 &colorStages, | |
| 400 &coverageStages, | |
| 401 &desc)) { | |
| 402 SkDebugf("Failed to generate GL program descriptor"); | |
| 403 return false; | |
| 404 } | |
| 338 SkAutoTUnref<GrGLProgram> program(GrGLProgram::Create(this, | 405 SkAutoTUnref<GrGLProgram> program(GrGLProgram::Create(this, |
| 339 *optState.get(), | 406 » *ods, |
|
joshua.litt
2014/10/07 13:52:41
whoops I'll fix this before committing
| |
| 340 pdesc, | 407 desc, |
| 341 geometryProcessor. get(), | 408 geometryProcessor, |
| 342 stages, | 409 colorStages.begin( ), |
| 343 stages + numColorS tages)); | 410 coverageStages.beg in())); |
| 344 for (int s = 0; s < numStages; ++s) { | |
| 345 SkDELETE(stages[s]); | |
| 346 } | |
| 347 if (NULL == program.get()) { | 411 if (NULL == program.get()) { |
| 412 SkDebugf("Failed to create program!"); | |
| 348 return false; | 413 return false; |
| 349 } | 414 } |
| 350 | 415 |
| 351 // We have to reset the drawstate because we might have added a gp | 416 // We have to reset the drawstate because we might have added a gp |
| 352 this->drawState()->reset(); | 417 ds->reset(); |
| 418 | |
| 419 // because occasionally optimized drawstate creation will fail for valid reasons, we only | |
| 420 // want to increment on success | |
| 421 ++t; | |
| 353 } | 422 } |
| 354 return true; | 423 return true; |
| 355 } | 424 } |
| 356 | 425 |
| 357 DEF_GPUTEST(GLPrograms, reporter, factory) { | 426 DEF_GPUTEST(GLPrograms, reporter, factory) { |
| 358 for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) { | 427 for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) { |
| 359 GrContext* context = factory->get(static_cast<GrContextFactory::GLContex tType>(type)); | 428 GrContext* context = factory->get(static_cast<GrContextFactory::GLContex tType>(type)); |
| 360 if (context) { | 429 if (context) { |
| 361 GrGpuGL* gpu = static_cast<GrGpuGL*>(context->getGpu()); | 430 GrGpuGL* gpu = static_cast<GrGpuGL*>(context->getGpu()); |
| 362 int maxStages = 6; | 431 int maxStages = 6; |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 390 SkRect::MakeWH(SK_Scalar1, SK_Scalar1), SK_Scalar1)); | 459 SkRect::MakeWH(SK_Scalar1, SK_Scalar1), SK_Scalar1)); |
| 391 GrConfigConversionEffect::Create(NULL, | 460 GrConfigConversionEffect::Create(NULL, |
| 392 false, | 461 false, |
| 393 GrConfigConversionEffect::kNone_PMConversio n, | 462 GrConfigConversionEffect::kNone_PMConversio n, |
| 394 SkMatrix::I()); | 463 SkMatrix::I()); |
| 395 SkScalar matrix[20]; | 464 SkScalar matrix[20]; |
| 396 SkAutoTUnref<SkColorMatrixFilter> cmf(SkColorMatrixFilter::Create(matrix)); | 465 SkAutoTUnref<SkColorMatrixFilter> cmf(SkColorMatrixFilter::Create(matrix)); |
| 397 } | 466 } |
| 398 | 467 |
| 399 #endif | 468 #endif |
| OLD | NEW |