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 |