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