9da1ecc53c0a798fdb9762c1b7376bdc7c088e2d
[platform/framework/web/crosswalk.git] / src / third_party / skia / tests / GLProgramsTest.cpp
1
2 /*
3  * Copyright 2011 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8
9 // This is a GPU-backend specific test. It relies on static intializers to work
10
11 #include "SkTypes.h"
12
13 #if SK_SUPPORT_GPU && SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
14
15 #include "GrBackendEffectFactory.h"
16 #include "GrContextFactory.h"
17 #include "GrDrawEffect.h"
18 #include "effects/GrConfigConversionEffect.h"
19 #include "gl/GrGpuGL.h"
20
21 #include "SkChecksum.h"
22 #include "SkRandom.h"
23 #include "Test.h"
24
25 bool GrGLProgramDesc::setRandom(SkRandom* random,
26                                 const GrGpuGL* gpu,
27                                 const GrRenderTarget* dstRenderTarget,
28                                 const GrTexture* dstCopyTexture,
29                                 const GrEffectStage* stages[],
30                                 int numColorStages,
31                                 int numCoverageStages,
32                                 int currAttribIndex) {
33     bool useLocalCoords = random->nextBool() && currAttribIndex < GrDrawState::kMaxVertexAttribCnt;
34
35     int numStages = numColorStages + numCoverageStages;
36     fKey.reset();
37
38     GR_STATIC_ASSERT(0 == kEffectKeyOffsetsAndLengthOffset % sizeof(uint32_t));
39
40     // Make room for everything up to and including the array of offsets to effect keys.
41     fKey.push_back_n(kEffectKeyOffsetsAndLengthOffset + 2 * sizeof(uint16_t) * numStages);
42
43     bool dstRead = false;
44     bool fragPos = false;
45     bool vertexCode = false;
46     for (int s = 0; s < numStages; ++s) {
47         uint16_t* offsetAndSize = reinterpret_cast<uint16_t*>(fKey.begin() +
48                                                               kEffectKeyOffsetsAndLengthOffset +
49                                                               s * 2 * sizeof(uint16_t));
50         uint32_t effectKeyOffset = fKey.count();
51         if (effectKeyOffset > SK_MaxU16) {
52             fKey.reset();
53             return false;
54         }
55         GrDrawEffect drawEffect(*stages[s], useLocalCoords);
56         GrEffectKeyBuilder b(&fKey);
57         uint16_t effectKeySize;
58         if (!GetEffectKeyAndUpdateStats(*stages[s], gpu->glCaps(), useLocalCoords, &b,
59                                         &effectKeySize, &dstRead, &fragPos, &vertexCode)) {
60             fKey.reset();
61             return false;
62         }
63         offsetAndSize[0] = effectKeyOffset;
64         offsetAndSize[1] = effectKeySize;
65     }
66
67     KeyHeader* header = this->header();
68     memset(header, 0, kHeaderSize);
69     header->fEmitsPointSize = random->nextBool();
70
71     header->fPositionAttributeIndex = 0;
72
73     // if the effects have used up all off the available attributes,
74     // don't try to use color or coverage attributes as input
75     do {
76         uint32_t colorRand = random->nextULessThan(2);
77         header->fColorInput = (0 == colorRand) ? GrGLProgramDesc::kAttribute_ColorInput :
78                                                  GrGLProgramDesc::kUniform_ColorInput;
79     } while (GrDrawState::kMaxVertexAttribCnt <= currAttribIndex &&
80              kAttribute_ColorInput == header->fColorInput);
81
82     header->fColorAttributeIndex = (header->fColorInput == kAttribute_ColorInput) ?
83                                         currAttribIndex++ :
84                                         -1;
85
86     do {
87         header->fCoverageInput = static_cast<GrGLProgramDesc::ColorInput>(
88                                      random->nextULessThan(kColorInputCnt));
89     } while (GrDrawState::kMaxVertexAttribCnt <= currAttribIndex  &&
90              kAttribute_ColorInput == header->fCoverageInput);
91     header->fCoverageAttributeIndex = (header->fCoverageInput == kAttribute_ColorInput) ?
92                                         currAttribIndex++ :
93                                         -1;
94
95 #if GR_GL_EXPERIMENTAL_GS
96     header->fExperimentalGS = gpu->caps()->geometryShaderSupport() && random->nextBool();
97 #endif
98
99     header->fLocalCoordAttributeIndex = useLocalCoords ? currAttribIndex++ : -1;
100
101     header->fColorEffectCnt = numColorStages;
102     header->fCoverageEffectCnt = numCoverageStages;
103
104     if (dstRead) {
105         header->fDstReadKey = SkToU8(GrGLShaderBuilder::KeyForDstRead(dstCopyTexture,
106                                                                       gpu->glCaps()));
107     } else {
108         header->fDstReadKey = 0;
109     }
110     if (fragPos) {
111         header->fFragPosKey = SkToU8(GrGLShaderBuilder::KeyForFragmentPosition(dstRenderTarget,
112                                                                                gpu->glCaps()));
113     } else {
114         header->fFragPosKey = 0;
115     }
116
117     header->fHasVertexCode = vertexCode ||
118                              useLocalCoords ||
119                              kAttribute_ColorInput == header->fColorInput ||
120                              kAttribute_ColorInput == header->fCoverageInput;
121
122     CoverageOutput coverageOutput;
123     bool illegalCoverageOutput;
124     do {
125         coverageOutput = static_cast<CoverageOutput>(random->nextULessThan(kCoverageOutputCnt));
126         illegalCoverageOutput = (!gpu->caps()->dualSourceBlendingSupport() &&
127                                  CoverageOutputUsesSecondaryOutput(coverageOutput)) ||
128                                 (!dstRead && kCombineWithDst_CoverageOutput == coverageOutput);
129     } while (illegalCoverageOutput);
130
131     header->fCoverageOutput = coverageOutput;
132
133     this->finalize();
134     return true;
135 }
136
137 bool GrGpuGL::programUnitTest(int maxStages) {
138
139     GrTextureDesc dummyDesc;
140     dummyDesc.fFlags = kRenderTarget_GrTextureFlagBit;
141     dummyDesc.fConfig = kSkia8888_GrPixelConfig;
142     dummyDesc.fWidth = 34;
143     dummyDesc.fHeight = 18;
144     SkAutoTUnref<GrTexture> dummyTexture1(this->createTexture(dummyDesc, NULL, 0));
145     dummyDesc.fFlags = kNone_GrTextureFlags;
146     dummyDesc.fConfig = kAlpha_8_GrPixelConfig;
147     dummyDesc.fWidth = 16;
148     dummyDesc.fHeight = 22;
149     SkAutoTUnref<GrTexture> dummyTexture2(this->createTexture(dummyDesc, NULL, 0));
150
151     if (!dummyTexture1 || ! dummyTexture2) {
152         return false;
153     }
154
155     static const int NUM_TESTS = 512;
156
157     SkRandom random;
158     for (int t = 0; t < NUM_TESTS; ++t) {
159
160 #if 0
161         GrPrintf("\nTest Program %d\n-------------\n", t);
162         static const int stop = -1;
163         if (t == stop) {
164             int breakpointhere = 9;
165         }
166 #endif
167
168         GrGLProgramDesc pdesc;
169
170         int currAttribIndex = 1;  // we need to always leave room for position
171         int currTextureCoordSet = 0;
172         int attribIndices[2] = { 0, 0 };
173         GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()};
174
175         int numStages = random.nextULessThan(maxStages + 1);
176         int numColorStages = random.nextULessThan(numStages + 1);
177         int numCoverageStages = numStages - numColorStages;
178
179         SkAutoSTMalloc<8, const GrEffectStage*> stages(numStages);
180
181         bool useFixedFunctionTexturing = this->shouldUseFixedFunctionTexturing();
182
183         for (int s = 0; s < numStages;) {
184             SkAutoTUnref<const GrEffect> effect(GrEffectTestFactory::CreateStage(
185                                                                             &random,
186                                                                             this->getContext(),
187                                                                             *this->caps(),
188                                                                             dummyTextures));
189             SkASSERT(effect);
190             int numAttribs = effect->numVertexAttribs();
191
192             // If adding this effect would exceed the max attrib count then generate a
193             // new random effect.
194             if (currAttribIndex + numAttribs > GrDrawState::kMaxVertexAttribCnt) {
195                 continue;
196             }
197
198
199             // If adding this effect would exceed the max texture coord set count then generate a
200             // new random effect.
201             if (useFixedFunctionTexturing && !effect->hasVertexCode()) {
202                 int numTransforms = effect->numTransforms();
203                 if (currTextureCoordSet + numTransforms > this->glCaps().maxFixedFunctionTextureCoords()) {
204                     continue;
205                 }
206                 currTextureCoordSet += numTransforms;
207             }
208
209             useFixedFunctionTexturing = useFixedFunctionTexturing && !effect->hasVertexCode();
210
211             for (int i = 0; i < numAttribs; ++i) {
212                 attribIndices[i] = currAttribIndex++;
213             }
214             GrEffectStage* stage = SkNEW_ARGS(GrEffectStage,
215                                               (effect.get(), attribIndices[0], attribIndices[1]));
216             stages[s] = stage;
217             ++s;
218         }
219         const GrTexture* dstTexture = random.nextBool() ? dummyTextures[0] : dummyTextures[1];
220         if (!pdesc.setRandom(&random,
221                              this,
222                              dummyTextures[0]->asRenderTarget(),
223                              dstTexture,
224                              stages.get(),
225                              numColorStages,
226                              numCoverageStages,
227                              currAttribIndex)) {
228             return false;
229         }
230
231         SkAutoTUnref<GrGLProgram> program(GrGLProgram::Create(this,
232                                                               pdesc,
233                                                               stages,
234                                                               stages + numColorStages));
235         for (int s = 0; s < numStages; ++s) {
236             SkDELETE(stages[s]);
237         }
238         if (NULL == program.get()) {
239             return false;
240         }
241     }
242     return true;
243 }
244
245 DEF_GPUTEST(GLPrograms, reporter, factory) {
246     for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
247         GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(type));
248         if (NULL != context) {
249             GrGpuGL* gpu = static_cast<GrGpuGL*>(context->getGpu());
250             int maxStages = 6;
251 #if SK_ANGLE
252             // Some long shaders run out of temporary registers in the D3D compiler on ANGLE.
253             if (type == GrContextFactory::kANGLE_GLContextType) {
254                 maxStages = 3;
255             }
256 #endif
257             REPORTER_ASSERT(reporter, gpu->programUnitTest(maxStages));
258         }
259     }
260 }
261
262 // This is evil evil evil. The linker may throw away whole translation units as dead code if it
263 // thinks none of the functions are called. It will do this even if there are static initializers
264 // in the unit that could pass pointers to functions from the unit out to other translation units!
265 // We force some of the effects that would otherwise be discarded to link here.
266
267 #include "SkAlphaThresholdFilter.h"
268 #include "SkColorMatrixFilter.h"
269 #include "SkLightingImageFilter.h"
270 #include "SkMagnifierImageFilter.h"
271
272 void forceLinking();
273
274 void forceLinking() {
275     SkLightingImageFilter::CreateDistantLitDiffuse(SkPoint3(0,0,0), 0, 0, 0);
276     SkAlphaThresholdFilter::Create(SkRegion(), .5f, .5f);
277     SkAutoTUnref<SkMagnifierImageFilter> mag(SkMagnifierImageFilter::Create(
278         SkRect::MakeWH(SK_Scalar1, SK_Scalar1), SK_Scalar1));
279     GrConfigConversionEffect::Create(NULL,
280                                      false,
281                                      GrConfigConversionEffect::kNone_PMConversion,
282                                      SkMatrix::I());
283     SkScalar matrix[20];
284     SkAutoTUnref<SkColorMatrixFilter> cmf(SkColorMatrixFilter::Create(matrix));
285 }
286
287 #endif