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 const int kRenderTargetHeight = 1; | 25 static void get_stage_stats(const GrFragmentStage stage, bool* readsDst, |
26 static const int kRenderTargetWidth = 1; | 26 bool* readsFragPosition, bool* requiresVertexShader)
{ |
| 27 if (stage.getFragmentProcessor()->willReadDstColor()) { |
| 28 *readsDst = true; |
| 29 } |
| 30 if (stage.getProcessor()->willReadFragmentPosition()) { |
| 31 *readsFragPosition = true; |
| 32 } |
| 33 } |
27 | 34 |
28 static GrRenderTarget* random_render_target(GrGpuGL* gpu, | 35 bool GrGLProgramDesc::setRandom(SkRandom* random, |
29 const GrCacheID& cacheId, | 36 GrGpuGL* gpu, |
30 SkRandom* random) { | 37 const GrRenderTarget* dstRenderTarget, |
31 // setup render target | 38 const GrTexture* dstCopyTexture, |
32 GrTextureParams params; | 39 const GrGeometryStage* geometryProcessor, |
33 GrTextureDesc texDesc; | 40 const GrFragmentStage* stages[], |
34 texDesc.fWidth = kRenderTargetWidth; | 41 int numColorStages, |
35 texDesc.fHeight = kRenderTargetHeight; | 42 int numCoverageStages, |
36 texDesc.fFlags = kRenderTarget_GrTextureFlagBit; | 43 int currAttribIndex, |
37 texDesc.fConfig = kRGBA_8888_GrPixelConfig; | 44 GrGpu::DrawType drawType) { |
38 texDesc.fOrigin = random->nextBool() == true ? kTopLeft_GrSurfaceOrigin : | 45 bool isPathRendering = GrGpu::IsPathRenderingDrawType(drawType); |
39 kBottomLeft_GrSurfaceOrigin; | 46 bool useLocalCoords = !isPathRendering && |
| 47 random->nextBool() && |
| 48 currAttribIndex < GrDrawState::kMaxVertexAttribCnt; |
40 | 49 |
41 GrTexture* texture = gpu->getContext()->findAndRefTexture(texDesc, cacheId,
¶ms); | 50 int numStages = numColorStages + numCoverageStages; |
42 if (NULL == texture) { | 51 fKey.reset(); |
43 texture = gpu->getContext()->createTexture(¶ms, texDesc, cacheId, 0,
0); | 52 |
44 if (NULL == texture) { | 53 GR_STATIC_ASSERT(0 == kEffectKeyOffsetsAndLengthOffset % sizeof(uint32_t)); |
45 return NULL; | 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; |
46 } | 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++; |
47 } | 84 } |
48 return texture->asRenderTarget(); | 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; |
49 } | 183 } |
50 | 184 |
51 // TODO clean this up, we have to do this to test geometry processors but there
has got to be | 185 // TODO clean this up, we have to do this to test geometry processors but there
has got to be |
52 // a better way. In the mean time, we actually fill out these generic vertex at
tribs below with | 186 // a better way. In the mean time, we actually fill out these generic vertex at
tribs below with |
53 // the correct vertex attribs from the GP. We have to ensure, however, we don't
try to add more | 187 // the correct vertex attribs from the GP. We have to ensure, however, we don't
try to add more |
54 // than two attributes. In addition, we 'pad' the below array with GPs up to 6
entries, 4 fixed | 188 // than two attributes. |
55 // function vertex attributes and 2 GP custom attributes. | 189 GrVertexAttrib genericVertexAttribs[] = { |
56 GrVertexAttrib kGenericVertexAttribs[] = { | |
57 { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, | 190 { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, |
58 { kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding }
, | 191 { kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding }
, |
59 { kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding }
, | |
60 { kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding }
, | |
61 { kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding }
, | |
62 { kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding } | 192 { kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding } |
63 }; | 193 }; |
64 | 194 |
65 /* | 195 /* |
66 * convert sl type to vertexattrib type, not a complete implementation, only use
for debugging | 196 * convert sl type to vertexattrib type, not a complete implementation, only use
for debugging |
67 */ | 197 */ |
68 static GrVertexAttribType convert_sltype_to_attribtype(GrSLType type) { | 198 GrVertexAttribType convert_sltype_to_attribtype(GrSLType type) { |
69 switch (type) { | 199 switch (type) { |
70 case kFloat_GrSLType: | 200 case kFloat_GrSLType: |
71 return kFloat_GrVertexAttribType; | 201 return kFloat_GrVertexAttribType; |
72 case kVec2f_GrSLType: | 202 case kVec2f_GrSLType: |
73 return kVec2f_GrVertexAttribType; | 203 return kVec2f_GrVertexAttribType; |
74 case kVec3f_GrSLType: | 204 case kVec3f_GrSLType: |
75 return kVec3f_GrVertexAttribType; | 205 return kVec3f_GrVertexAttribType; |
76 case kVec4f_GrSLType: | 206 case kVec4f_GrSLType: |
77 return kVec4f_GrVertexAttribType; | 207 return kVec4f_GrVertexAttribType; |
78 default: | 208 default: |
79 SkFAIL("Type isn't convertible"); | 209 SkFAIL("Type isn't convertible"); |
80 return kFloat_GrVertexAttribType; | 210 return kFloat_GrVertexAttribType; |
81 } | 211 } |
82 } | 212 } |
83 // end test hack | 213 // TODO end test hack |
84 | 214 |
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 | |
126 // we actually can't overflow if kMaxVertexAttribs == 2, but GCC 4.8 wants m
ore proof | |
127 int maxIndex = SK_ARRAY_COUNT(kGenericVertexAttribs); | |
128 for (int i = 0; i < numGPAttribs && i + attribIndex < maxIndex; i++) { | |
129 kGenericVertexAttribs[i + attribIndex].fType = | |
130 convert_sltype_to_attribtype(v[i].getType()); | |
131 kGenericVertexAttribs[i + attribIndex].fOffset = runningStride; | |
132 kGenericVertexAttribs[i + attribIndex].fBinding = kGeometryProcessor_GrV
ertexAttribBinding; | |
133 runningStride += GrVertexAttribTypeSize(kGenericVertexAttribs[i + attrib
Index].fType); | |
134 } | |
135 | |
136 // update the vertex attributes with the ds | |
137 GrDrawState* ds = gpu->drawState(); | |
138 ds->setVertexAttribs<kGenericVertexAttribs>(attribIndex + numGPAttribs, runn
ingStride); | |
139 ds->setGeometryProcessor(gp); | |
140 } | |
141 | |
142 static void set_random_color_coverage_stages(GrGpuGL* gpu, | |
143 int maxStages, | |
144 bool usePathRendering, | |
145 SkRandom* random, | |
146 GrTexture* dummyTextures[]) { | |
147 int numProcs = random->nextULessThan(maxStages + 1); | |
148 int numColorProcs = random->nextULessThan(numProcs + 1); | |
149 | |
150 int currTextureCoordSet = 0; | |
151 for (int s = 0; s < numProcs;) { | |
152 GrProgramElementRef<GrFragmentProcessor> fp( | |
153 GrProcessorTestFactory<GrFragmentProcessor>::CreateStage(random, | |
154 gpu->ge
tContext(), | |
155 *gpu->c
aps(), | |
156 dummyTe
xtures)); | |
157 SkASSERT(fp); | |
158 | |
159 // don't add dst color reads to coverage stage | |
160 if (s >= numColorProcs && fp->willReadDstColor()) { | |
161 continue; | |
162 } | |
163 | |
164 // If adding this effect would exceed the max texture coord set count th
en generate a | |
165 // new random effect. | |
166 if (usePathRendering && gpu->glPathRendering()->texturingMode() == | |
167 GrGLPathRendering::FixedFunction_TexturingMode)
{; | |
168 int numTransforms = fp->numTransforms(); | |
169 if (currTextureCoordSet + numTransforms > | |
170 gpu->glCaps().maxFixedFunctionTextureCoords()) { | |
171 continue; | |
172 } | |
173 currTextureCoordSet += numTransforms; | |
174 } | |
175 | |
176 // finally add the stage to the correct pipeline in the drawstate | |
177 GrDrawState* ds = gpu->drawState(); | |
178 if (s < numColorProcs) { | |
179 ds->addColorProcessor(fp); | |
180 } else { | |
181 ds->addCoverageProcessor(fp); | |
182 } | |
183 ++s; | |
184 } | |
185 } | |
186 | |
187 // There are only a few cases of random colors which interest us | |
188 enum ColorMode { | |
189 kAllOnes_ColorMode, | |
190 kAllZeros_ColorMode, | |
191 kAlphaOne_ColorMode, | |
192 kRandom_ColorMode, | |
193 kLast_ColorMode = kRandom_ColorMode | |
194 }; | |
195 | |
196 static void set_random_color(GrGpuGL* gpu, SkRandom* random) { | |
197 ColorMode colorMode = ColorMode(random->nextULessThan(kLast_ColorMode + 1)); | |
198 GrColor color; | |
199 switch (colorMode) { | |
200 case kAllOnes_ColorMode: | |
201 color = GrColorPackRGBA(0xFF, 0xFF, 0xFF, 0xFF); | |
202 break; | |
203 case kAllZeros_ColorMode: | |
204 color = GrColorPackRGBA(0, 0, 0, 0); | |
205 break; | |
206 case kAlphaOne_ColorMode: | |
207 color = GrColorPackRGBA(random->nextULessThan(256), | |
208 random->nextULessThan(256), | |
209 random->nextULessThan(256), | |
210 0xFF); | |
211 break; | |
212 case kRandom_ColorMode: | |
213 uint8_t alpha = random->nextULessThan(256); | |
214 color = GrColorPackRGBA(random->nextRangeU(0, alpha), | |
215 random->nextRangeU(0, alpha), | |
216 random->nextRangeU(0, alpha), | |
217 alpha); | |
218 break; | |
219 } | |
220 GrColorIsPMAssert(color); | |
221 gpu->drawState()->setColor(color); | |
222 } | |
223 | |
224 // There are only a few cases of random coverages which interest us | |
225 enum CoverageMode { | |
226 kZero_CoverageMode, | |
227 kFF_CoverageMode, | |
228 kRandom_CoverageMode, | |
229 kLast_CoverageMode = kRandom_CoverageMode | |
230 }; | |
231 | |
232 static void set_random_coverage(GrGpuGL* gpu, SkRandom* random) { | |
233 CoverageMode coverageMode = CoverageMode(random->nextULessThan(kLast_Coverag
eMode + 1)); | |
234 uint8_t coverage; | |
235 switch (coverageMode) { | |
236 case kZero_CoverageMode: | |
237 coverage = 0; | |
238 break; | |
239 case kFF_CoverageMode: | |
240 coverage = 0xFF; | |
241 break; | |
242 case kRandom_CoverageMode: | |
243 coverage = uint8_t(random->nextU()); | |
244 break; | |
245 } | |
246 gpu->drawState()->setCoverage(coverage); | |
247 } | |
248 | |
249 static void set_random_hints(GrGpuGL* gpu, SkRandom* random) { | |
250 for (int i = 1; i <= GrDrawState::kLast_Hint; i <<= 1) { | |
251 gpu->drawState()->setHint(GrDrawState::Hints(i), random->nextBool()); | |
252 } | |
253 } | |
254 | |
255 static void set_random_state(GrGpuGL* gpu, SkRandom* random) { | |
256 int state = 0; | |
257 for (int i = 1; i <= GrDrawState::kLastPublicStateBit; i <<= 1) { | |
258 state |= random->nextBool() * i; | |
259 } | |
260 gpu->drawState()->enableState(state); | |
261 } | |
262 | |
263 // this function will randomly pick non-self referencing blend modes | |
264 static void set_random_blend_func(GrGpuGL* gpu, SkRandom* random) { | |
265 GrBlendCoeff src; | |
266 do { | |
267 src = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPub
licGrBlendCoeff)); | |
268 } while (GrBlendCoeffRefsSrc(src)); | |
269 | |
270 GrBlendCoeff dst; | |
271 do { | |
272 dst = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPub
licGrBlendCoeff)); | |
273 } while (GrBlendCoeffRefsDst(dst)); | |
274 | |
275 gpu->drawState()->setBlendFunc(src, dst); | |
276 } | |
277 | |
278 // right now, the only thing we seem to care about in drawState's stencil is 'do
esWrite()' | |
279 static void set_random_stencil(GrGpuGL* gpu, SkRandom* random) { | |
280 GR_STATIC_CONST_SAME_STENCIL(kDoesWriteStencil, | |
281 kReplace_StencilOp, | |
282 kReplace_StencilOp, | |
283 kAlways_StencilFunc, | |
284 0xffff, | |
285 0xffff, | |
286 0xffff); | |
287 GR_STATIC_CONST_SAME_STENCIL(kDoesNotWriteStencil, | |
288 kKeep_StencilOp, | |
289 kKeep_StencilOp, | |
290 kNever_StencilFunc, | |
291 0xffff, | |
292 0xffff, | |
293 0xffff); | |
294 | |
295 if (random->nextBool()) { | |
296 gpu->drawState()->setStencil(kDoesWriteStencil); | |
297 } else { | |
298 gpu->drawState()->setStencil(kDoesNotWriteStencil); | |
299 } | |
300 } | |
301 | 215 |
302 bool GrGpuGL::programUnitTest(int maxStages) { | 216 bool GrGpuGL::programUnitTest(int maxStages) { |
303 // setup dummy textures | 217 |
304 GrTextureDesc dummyDesc; | 218 GrTextureDesc dummyDesc; |
305 dummyDesc.fFlags = kRenderTarget_GrTextureFlagBit; | 219 dummyDesc.fFlags = kRenderTarget_GrTextureFlagBit; |
306 dummyDesc.fConfig = kSkia8888_GrPixelConfig; | 220 dummyDesc.fConfig = kSkia8888_GrPixelConfig; |
307 dummyDesc.fWidth = 34; | 221 dummyDesc.fWidth = 34; |
308 dummyDesc.fHeight = 18; | 222 dummyDesc.fHeight = 18; |
309 SkAutoTUnref<GrTexture> dummyTexture1(this->createTexture(dummyDesc, NULL, 0
)); | 223 SkAutoTUnref<GrTexture> dummyTexture1(this->createTexture(dummyDesc, NULL, 0
)); |
310 dummyDesc.fFlags = kNone_GrTextureFlags; | 224 dummyDesc.fFlags = kNone_GrTextureFlags; |
311 dummyDesc.fConfig = kAlpha_8_GrPixelConfig; | 225 dummyDesc.fConfig = kAlpha_8_GrPixelConfig; |
312 dummyDesc.fWidth = 16; | 226 dummyDesc.fWidth = 16; |
313 dummyDesc.fHeight = 22; | 227 dummyDesc.fHeight = 22; |
314 SkAutoTUnref<GrTexture> dummyTexture2(this->createTexture(dummyDesc, NULL, 0
)); | 228 SkAutoTUnref<GrTexture> dummyTexture2(this->createTexture(dummyDesc, NULL, 0
)); |
315 | 229 |
316 if (!dummyTexture1 || ! dummyTexture2) { | 230 if (!dummyTexture1 || ! dummyTexture2) { |
317 SkDebugf("Could not allocate dummy textures"); | |
318 return false; | 231 return false; |
319 } | 232 } |
320 | 233 |
321 GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()}; | 234 static const int NUM_TESTS = 512; |
322 | |
323 // Setup texture cache id key | |
324 const GrCacheID::Domain glProgramsDomain = GrCacheID::GenerateDomain(); | |
325 GrCacheID::Key key; | |
326 memset(&key, 0, sizeof(key)); | |
327 key.fData32[0] = kRenderTargetWidth; | |
328 key.fData32[1] = kRenderTargetHeight; | |
329 GrCacheID glProgramsCacheID(glProgramsDomain, key); | |
330 | |
331 // setup clip | |
332 SkRect screen = | |
333 SkRect::MakeWH(SkIntToScalar(kRenderTargetWidth), SkIntToScalar(kRen
derTargetHeight)); | |
334 | |
335 SkClipStack stack; | |
336 stack.clipDevRect(screen, SkRegion::kReplace_Op, false); | |
337 | |
338 // wrap the SkClipStack in a GrClipData | |
339 GrClipData clipData; | |
340 clipData.fClipStack = &stack; | |
341 this->setClip(&clipData); | |
342 | 235 |
343 SkRandom random; | 236 SkRandom random; |
344 static const int NUM_TESTS = 512; | 237 for (int t = 0; t < NUM_TESTS; ++t) { |
345 for (int t = 0; t < NUM_TESTS;) { | 238 |
346 // setup random render target(can fail) | 239 #if 0 |
347 GrRenderTarget* rtPtr = random_render_target(this, glProgramsCacheID, &r
andom); | 240 GrPrintf("\nTest Program %d\n-------------\n", t); |
348 if (!rtPtr) { | 241 static const int stop = -1; |
349 SkDebugf("Could not allocate render target"); | 242 if (t == stop) { |
350 return false; | 243 int breakpointhere = 9; |
351 } | 244 } |
352 GrTGpuResourceRef<GrRenderTarget> rt(SkRef(rtPtr), GrIORef::kWrite_IOTyp
e); | 245 #endif |
353 | 246 |
354 GrDrawState* ds = this->drawState(); | 247 GrGLProgramDesc pdesc; |
355 ds->setRenderTarget(rt.get()); | |
356 | 248 |
357 // if path rendering we have to setup a couple of things like the draw t
ype | 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 |
358 bool usePathRendering = this->glCaps().pathRenderingSupport() && random.
nextBool(); | 259 bool usePathRendering = this->glCaps().pathRenderingSupport() && random.
nextBool(); |
359 | 260 |
360 GrGpu::DrawType drawType = usePathRendering ? GrGpu::kDrawPath_DrawType
: | 261 GrGpu::DrawType drawType = usePathRendering ? GrGpu::kDrawPath_DrawType
: |
361 GrGpu::kDrawPoints_DrawTyp
e; | 262 GrGpu::kDrawPoints_DrawTyp
e; |
362 | 263 |
363 // twiddle drawstate knobs randomly | 264 SkAutoTDelete<GrGeometryStage> geometryProcessor; |
364 bool hasGeometryProcessor = usePathRendering ? false : random.nextBool()
; | 265 bool hasGeometryProcessor = usePathRendering ? false : random.nextBool()
; |
365 if (hasGeometryProcessor) { | 266 if (hasGeometryProcessor) { |
366 set_random_gp(this, &random, dummyTextures); | 267 while (true) { |
| 268 SkAutoTUnref<const GrGeometryProcessor> effect( |
| 269 GrProcessorTestFactory<GrGeometryProcessor>::CreateStage
(&random, this->getContext(), *this->caps(), |
| 270 dummyTextures)); |
| 271 SkASSERT(effect); |
| 272 // Only geometryProcessor can use vertex shader |
| 273 GrGeometryStage* stage = SkNEW_ARGS(GrGeometryStage, (effect.get
())); |
| 274 geometryProcessor.reset(stage); |
| 275 |
| 276 // we have to set dummy vertex attribs |
| 277 const GrGeometryProcessor::VertexAttribArray& v = effect->getVer
texAttribs(); |
| 278 int numVertexAttribs = v.count(); |
| 279 |
| 280 SkASSERT(GrGeometryProcessor::kMaxVertexAttribs == 2 && |
| 281 GrGeometryProcessor::kMaxVertexAttribs >= numVertexAttr
ibs); |
| 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 } |
367 } | 296 } |
368 set_random_color_coverage_stages(this, maxStages, usePathRendering, &ran
dom, dummyTextures); | 297 for (int s = 0; s < numStages;) { |
369 set_random_color(this, &random); | 298 SkAutoTUnref<const GrFragmentProcessor> effect( |
370 set_random_coverage(this, &random); | 299 GrProcessorTestFactory<GrFragmentProcessor>::CreateStage( |
371 set_random_hints(this, &random); | 300 &ran
dom, |
372 set_random_state(this, &random); | 301 this
->getContext(), |
373 set_random_blend_func(this, &random); | 302 *thi
s->caps(), |
374 set_random_stencil(this, &random); | 303 dumm
yTextures)); |
| 304 SkASSERT(effect); |
375 | 305 |
376 // create optimized draw state, setup readDst texture if required, and b
uild a descriptor | 306 // If adding this effect would exceed the max texture coord set coun
t then generate a |
377 // and program. ODS creation can fail, so we have to check | 307 // new random effect. |
378 SkAutoTUnref<GrOptDrawState> ods(GrOptDrawState::Create(this->getDrawSta
te(), | 308 if (usePathRendering && this->glPathRendering()->texturingMode() == |
379 *this->caps(), | 309 GrGLPathRendering::FixedFunction_TexturingMo
de) {; |
380 drawType)); | 310 int numTransforms = effect->numTransforms(); |
381 if (!ods.get()) { | 311 if (currTextureCoordSet + numTransforms > this->glCaps().maxFixe
dFunctionTextureCoords()) { |
382 ds->reset(); | 312 continue; |
383 continue; | 313 } |
| 314 currTextureCoordSet += numTransforms; |
| 315 } |
| 316 GrFragmentStage* stage = SkNEW_ARGS(GrFragmentStage, (effect.get()))
; |
| 317 |
| 318 stages[s] = stage; |
| 319 ++s; |
384 } | 320 } |
385 const GrGeometryStage* geometryProcessor = NULL; | 321 const GrTexture* dstTexture = random.nextBool() ? dummyTextures[0] : dum
myTextures[1]; |
386 SkSTArray<8, const GrFragmentStage*, true> colorStages; | 322 if (!pdesc.setRandom(&random, |
387 SkSTArray<8, const GrFragmentStage*, true> coverageStages; | 323 this, |
388 GrGLProgramDesc desc; | 324 dummyTextures[0]->asRenderTarget(), |
389 GrDeviceCoordTexture dstCopy; | 325 dstTexture, |
390 | 326 geometryProcessor.get(), |
391 if (!this->setupDstReadIfNecessary(&dstCopy, NULL)) { | 327 stages.get(), |
392 SkDebugf("Couldn't setup dst read texture"); | 328 numColorStages, |
| 329 numCoverageStages, |
| 330 currAttribIndex, |
| 331 drawType)) { |
393 return false; | 332 return false; |
394 } | 333 } |
395 if (!GrGLProgramDesc::Build(*ods, | 334 |
396 drawType, | 335 SkAutoTUnref<GrOptDrawState> optState(GrOptDrawState::Create(this->getDr
awState(), |
397 ods->getSrcBlendCoeff(), | 336 *this->caps
(), |
398 ods->getDstBlendCoeff(), | 337 drawType)); |
399 this, | 338 SkAutoTUnref<GrGLProgram> program(GrGLProgram::Create(this, |
400 dstCopy.texture() ? &dstCopy : NULL, | 339 *optState.get(), |
401 &geometryProcessor, | 340 pdesc, |
402 &colorStages, | 341 geometryProcessor.
get(), |
403 &coverageStages, | 342 stages, |
404 &desc)) { | 343 stages + numColorS
tages)); |
405 SkDebugf("Failed to generate GL program descriptor"); | 344 for (int s = 0; s < numStages; ++s) { |
406 return false; | 345 SkDELETE(stages[s]); |
407 } | 346 } |
408 SkAutoTUnref<GrGLProgram> program(GrGLProgram::Create(this, | |
409 *ods, | |
410 desc, | |
411 geometryProcessor, | |
412 colorStages.begin(
), | |
413 coverageStages.beg
in())); | |
414 if (NULL == program.get()) { | 347 if (NULL == program.get()) { |
415 SkDebugf("Failed to create program!"); | |
416 return false; | 348 return false; |
417 } | 349 } |
418 | 350 |
419 // We have to reset the drawstate because we might have added a gp | 351 // We have to reset the drawstate because we might have added a gp |
420 ds->reset(); | 352 this->drawState()->reset(); |
421 | |
422 // because occasionally optimized drawstate creation will fail for valid
reasons, we only | |
423 // want to increment on success | |
424 ++t; | |
425 } | 353 } |
426 return true; | 354 return true; |
427 } | 355 } |
428 | 356 |
429 DEF_GPUTEST(GLPrograms, reporter, factory) { | 357 DEF_GPUTEST(GLPrograms, reporter, factory) { |
430 for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) { | 358 for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) { |
431 GrContext* context = factory->get(static_cast<GrContextFactory::GLContex
tType>(type)); | 359 GrContext* context = factory->get(static_cast<GrContextFactory::GLContex
tType>(type)); |
432 if (context) { | 360 if (context) { |
433 GrGpuGL* gpu = static_cast<GrGpuGL*>(context->getGpu()); | 361 GrGpuGL* gpu = static_cast<GrGpuGL*>(context->getGpu()); |
434 int maxStages = 6; | 362 int maxStages = 6; |
(...skipping 27 matching lines...) Expand all Loading... |
462 SkRect::MakeWH(SK_Scalar1, SK_Scalar1), SK_Scalar1)); | 390 SkRect::MakeWH(SK_Scalar1, SK_Scalar1), SK_Scalar1)); |
463 GrConfigConversionEffect::Create(NULL, | 391 GrConfigConversionEffect::Create(NULL, |
464 false, | 392 false, |
465 GrConfigConversionEffect::kNone_PMConversio
n, | 393 GrConfigConversionEffect::kNone_PMConversio
n, |
466 SkMatrix::I()); | 394 SkMatrix::I()); |
467 SkScalar matrix[20]; | 395 SkScalar matrix[20]; |
468 SkAutoTUnref<SkColorMatrixFilter> cmf(SkColorMatrixFilter::Create(matrix)); | 396 SkAutoTUnref<SkColorMatrixFilter> cmf(SkColorMatrixFilter::Create(matrix)); |
469 } | 397 } |
470 | 398 |
471 #endif | 399 #endif |
OLD | NEW |