1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 2.0 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Functional rasterization tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "es2fRasterizationTests.hpp"
25 #include "glsRasterizationTestUtil.hpp"
26 #include "tcuSurface.hpp"
27 #include "tcuRenderTarget.hpp"
28 #include "tcuVectorUtil.hpp"
29 #include "tcuStringTemplate.hpp"
30 #include "tcuResultCollector.hpp"
31 #include "gluShaderProgram.hpp"
32 #include "gluRenderContext.hpp"
33 #include "gluPixelTransfer.hpp"
34 #include "gluStrUtil.hpp"
35 #include "deStringUtil.hpp"
36 #include "deRandom.hpp"
37 #include "glwFunctions.hpp"
38 #include "glwEnums.hpp"
39
40 #include <vector>
41
42 namespace deqp
43 {
44 namespace gles2
45 {
46 namespace Functional
47 {
48 namespace
49 {
50
51 using namespace gls::RasterizationTestUtil;
52
53 static const char* const s_shaderVertexTemplate = "attribute highp vec4 a_position;\n"
54 "attribute highp vec4 a_color;\n"
55 "varying highp vec4 v_color;\n"
56 "uniform highp float u_pointSize;\n"
57 "void main ()\n"
58 "{\n"
59 " gl_Position = a_position;\n"
60 " gl_PointSize = u_pointSize;\n"
61 " v_color = a_color;\n"
62 "}\n";
63 static const char* const s_shaderFragmentTemplate = "varying mediump vec4 v_color;\n"
64 "void main ()\n"
65 "{\n"
66 " gl_FragColor = v_color;\n"
67 "}\n";
68 enum InterpolationCaseFlags
69 {
70 INTERPOLATIONFLAGS_NONE = 0,
71 INTERPOLATIONFLAGS_PROJECTED = (1 << 1),
72 };
73
74 enum PrimitiveWideness
75 {
76 PRIMITIVEWIDENESS_NARROW = 0,
77 PRIMITIVEWIDENESS_WIDE,
78
79 PRIMITIVEWIDENESS_LAST
80 };
81
82 class BaseRenderingCase : public TestCase
83 {
84 public:
85 BaseRenderingCase (Context& context, const char* name, const char* desc, int renderSize = 256);
86 ~BaseRenderingCase (void);
87 virtual void init (void);
88 void deinit (void);
89
90 protected:
91 void drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, glw::GLenum primitiveType);
92 void drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, const std::vector<tcu::Vec4>& coloDrata, glw::GLenum primitiveType);
93
94 const int m_renderSize;
95 int m_numSamples;
96 int m_subpixelBits;
97 float m_pointSize;
98 float m_lineWidth;
99
100 private:
101 glu::ShaderProgram* m_shader;
102 };
103
BaseRenderingCase(Context & context,const char * name,const char * desc,int renderSize)104 BaseRenderingCase::BaseRenderingCase (Context& context, const char* name, const char* desc, int renderSize)
105 : TestCase (context, name, desc)
106 , m_renderSize (renderSize)
107 , m_numSamples (-1)
108 , m_subpixelBits (-1)
109 , m_pointSize (1.0f)
110 , m_lineWidth (1.0f)
111 , m_shader (DE_NULL)
112 {
113 }
114
~BaseRenderingCase(void)115 BaseRenderingCase::~BaseRenderingCase (void)
116 {
117 deinit();
118 }
119
init(void)120 void BaseRenderingCase::init (void)
121 {
122 const int width = m_context.getRenderTarget().getWidth();
123 const int height = m_context.getRenderTarget().getHeight();
124
125 // Requirements
126
127 if (width < m_renderSize || height < m_renderSize)
128 throw tcu::NotSupportedError(std::string("Render target size must be at least ") + de::toString(m_renderSize) + "x" + de::toString(m_renderSize));
129
130 if (m_lineWidth != 1.0f)
131 {
132 float range[2] = { 0.0f, 0.0f };
133 m_context.getRenderContext().getFunctions().getFloatv(GL_ALIASED_LINE_WIDTH_RANGE, range);
134
135 if (m_lineWidth < range[0] || m_lineWidth > range[1])
136 throw tcu::NotSupportedError(std::string("Support for line width ") + de::toString(m_lineWidth) + " is required.");
137
138 m_testCtx.getLog() << tcu::TestLog::Message << "ALIASED_LINE_WIDTH_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
139 }
140
141 if (m_pointSize != 1.0f)
142 {
143 float range[2] = { 0.0f, 0.0f };
144 m_context.getRenderContext().getFunctions().getFloatv(GL_ALIASED_POINT_SIZE_RANGE, range);
145
146 if (m_pointSize < range[0] || m_pointSize > range[1])
147 throw tcu::NotSupportedError(std::string("Support for point size ") + de::toString(m_pointSize) + " is required.");
148
149 m_testCtx.getLog() << tcu::TestLog::Message << "ALIASED_POINT_SIZE_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
150 }
151
152 // Query info
153
154 m_numSamples = m_context.getRenderTarget().getNumSamples();
155 m_context.getRenderContext().getFunctions().getIntegerv(GL_SUBPIXEL_BITS, &m_subpixelBits);
156
157 m_testCtx.getLog() << tcu::TestLog::Message << "Sample count = " << m_numSamples << tcu::TestLog::EndMessage;
158 m_testCtx.getLog() << tcu::TestLog::Message << "SUBPIXEL_BITS = " << m_subpixelBits << tcu::TestLog::EndMessage;
159
160 // Gen shader
161
162 {
163 tcu::StringTemplate vertexSource (s_shaderVertexTemplate);
164 tcu::StringTemplate fragmentSource (s_shaderFragmentTemplate);
165 std::map<std::string, std::string> params;
166
167 m_shader = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(vertexSource.specialize(params)) << glu::FragmentSource(fragmentSource.specialize(params)));
168 if (!m_shader->isOk())
169 throw tcu::TestError("could not create shader");
170 }
171 }
172
deinit(void)173 void BaseRenderingCase::deinit (void)
174 {
175 if (m_shader)
176 {
177 delete m_shader;
178 m_shader = DE_NULL;
179 }
180 }
181
drawPrimitives(tcu::Surface & result,const std::vector<tcu::Vec4> & vertexData,glw::GLenum primitiveType)182 void BaseRenderingCase::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, glw::GLenum primitiveType)
183 {
184 // default to color white
185 const std::vector<tcu::Vec4> colorData(vertexData.size(), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
186
187 drawPrimitives(result, vertexData, colorData, primitiveType);
188 }
189
drawPrimitives(tcu::Surface & result,const std::vector<tcu::Vec4> & vertexData,const std::vector<tcu::Vec4> & colorData,glw::GLenum primitiveType)190 void BaseRenderingCase::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, const std::vector<tcu::Vec4>& colorData, glw::GLenum primitiveType)
191 {
192 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
193 const glw::GLint positionLoc = gl.getAttribLocation(m_shader->getProgram(), "a_position");
194 const glw::GLint colorLoc = gl.getAttribLocation(m_shader->getProgram(), "a_color");
195 const glw::GLint pointSizeLoc = gl.getUniformLocation(m_shader->getProgram(), "u_pointSize");
196
197 gl.clearColor (0, 0, 0, 1);
198 gl.clear (GL_COLOR_BUFFER_BIT);
199 gl.viewport (0, 0, m_renderSize, m_renderSize);
200 gl.useProgram (m_shader->getProgram());
201 gl.enableVertexAttribArray (positionLoc);
202 gl.vertexAttribPointer (positionLoc, 4, GL_FLOAT, GL_FALSE, 0, &vertexData[0]);
203 gl.enableVertexAttribArray (colorLoc);
204 gl.vertexAttribPointer (colorLoc, 4, GL_FLOAT, GL_FALSE, 0, &colorData[0]);
205 gl.uniform1f (pointSizeLoc, m_pointSize);
206 gl.lineWidth (m_lineWidth);
207 gl.drawArrays (primitiveType, 0, (glw::GLsizei)vertexData.size());
208 gl.disableVertexAttribArray (colorLoc);
209 gl.disableVertexAttribArray (positionLoc);
210 gl.useProgram (0);
211 gl.finish ();
212 GLU_EXPECT_NO_ERROR (gl.getError(), "draw primitives");
213
214 glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
215 }
216
217 class BaseTriangleCase : public BaseRenderingCase
218 {
219 public:
220 BaseTriangleCase (Context& context, const char* name, const char* desc, glw::GLenum primitiveDrawType);
221 ~BaseTriangleCase (void);
222 IterateResult iterate (void);
223
224 private:
225 virtual void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles) = DE_NULL;
226
227 int m_iteration;
228 const int m_iterationCount;
229 const glw::GLenum m_primitiveDrawType;
230 bool m_allIterationsPassed;
231 };
232
BaseTriangleCase(Context & context,const char * name,const char * desc,glw::GLenum primitiveDrawType)233 BaseTriangleCase::BaseTriangleCase (Context& context, const char* name, const char* desc, glw::GLenum primitiveDrawType)
234 : BaseRenderingCase (context, name, desc)
235 , m_iteration (0)
236 , m_iterationCount (3)
237 , m_primitiveDrawType (primitiveDrawType)
238 , m_allIterationsPassed (true)
239 {
240 }
241
~BaseTriangleCase(void)242 BaseTriangleCase::~BaseTriangleCase (void)
243 {
244 }
245
iterate(void)246 BaseTriangleCase::IterateResult BaseTriangleCase::iterate (void)
247 {
248 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
249 const tcu::ScopedLogSection section (m_testCtx.getLog(), iterationDescription, iterationDescription);
250 tcu::Surface resultImage (m_renderSize, m_renderSize);
251 std::vector<tcu::Vec4> drawBuffer;
252 std::vector<TriangleSceneSpec::SceneTriangle> triangles;
253
254 generateTriangles(m_iteration, drawBuffer, triangles);
255
256 // draw image
257 drawPrimitives(resultImage, drawBuffer, m_primitiveDrawType);
258
259 // compare
260 {
261 bool compareOk;
262 RasterizationArguments args;
263 TriangleSceneSpec scene;
264
265 args.numSamples = m_numSamples;
266 args.subpixelBits = m_subpixelBits;
267 args.redBits = m_context.getRenderTarget().getPixelFormat().redBits;
268 args.greenBits = m_context.getRenderTarget().getPixelFormat().greenBits;
269 args.blueBits = m_context.getRenderTarget().getPixelFormat().blueBits;
270
271 scene.triangles.swap(triangles);
272
273 compareOk = verifyTriangleGroupRasterization(resultImage, scene, args, m_testCtx.getLog());
274
275 if (!compareOk)
276 m_allIterationsPassed = false;
277 }
278
279 // result
280 if (++m_iteration == m_iterationCount)
281 {
282 if (m_allIterationsPassed)
283 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
284 else
285 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rasterization");
286
287 return STOP;
288 }
289 else
290 return CONTINUE;
291 }
292
293 class BaseLineCase : public BaseRenderingCase
294 {
295 public:
296 BaseLineCase (Context& context, const char* name, const char* desc, glw::GLenum primitiveDrawType, PrimitiveWideness wideness);
297 ~BaseLineCase (void);
298 IterateResult iterate (void);
299
300 private:
301 virtual void generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines) = DE_NULL;
302
303 int m_iteration;
304 const int m_iterationCount;
305 const glw::GLenum m_primitiveDrawType;
306 const PrimitiveWideness m_primitiveWideness;
307 bool m_allIterationsPassed;
308 bool m_multisampleRelaxationRequired;
309
310 static const float s_wideSize;
311 };
312
313 const float BaseLineCase::s_wideSize = 5.0f;
314
BaseLineCase(Context & context,const char * name,const char * desc,glw::GLenum primitiveDrawType,PrimitiveWideness wideness)315 BaseLineCase::BaseLineCase (Context& context, const char* name, const char* desc, glw::GLenum primitiveDrawType, PrimitiveWideness wideness)
316 : BaseRenderingCase (context, name, desc)
317 , m_iteration (0)
318 , m_iterationCount (3)
319 , m_primitiveDrawType (primitiveDrawType)
320 , m_primitiveWideness (wideness)
321 , m_allIterationsPassed (true)
322 , m_multisampleRelaxationRequired (false)
323 {
324 DE_ASSERT(m_primitiveWideness < PRIMITIVEWIDENESS_LAST);
325 m_lineWidth = (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE) ? (s_wideSize) : (1.0f);
326 }
327
~BaseLineCase(void)328 BaseLineCase::~BaseLineCase (void)
329 {
330 }
331
iterate(void)332 BaseLineCase::IterateResult BaseLineCase::iterate (void)
333 {
334 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
335 const tcu::ScopedLogSection section (m_testCtx.getLog(), iterationDescription, iterationDescription);
336 tcu::Surface resultImage (m_renderSize, m_renderSize);
337 std::vector<tcu::Vec4> drawBuffer;
338 std::vector<LineSceneSpec::SceneLine> lines;
339
340 // last iteration, max out size
341 if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE &&
342 m_iteration+1 == m_iterationCount)
343 {
344 float range[2] = { 0.0f, 0.0f };
345 m_context.getRenderContext().getFunctions().getFloatv(GL_ALIASED_LINE_WIDTH_RANGE, range);
346
347 m_lineWidth = range[1];
348 }
349
350 // gen data
351 generateLines(m_iteration, drawBuffer, lines);
352
353 // draw image
354 drawPrimitives(resultImage, drawBuffer, m_primitiveDrawType);
355
356 // compare
357 {
358 bool compareOk;
359 RasterizationArguments args;
360 LineSceneSpec scene;
361
362 args.numSamples = m_numSamples;
363 args.subpixelBits = m_subpixelBits;
364 args.redBits = m_context.getRenderTarget().getPixelFormat().redBits;
365 args.greenBits = m_context.getRenderTarget().getPixelFormat().greenBits;
366 args.blueBits = m_context.getRenderTarget().getPixelFormat().blueBits;
367
368 scene.lines.swap(lines);
369 scene.lineWidth = m_lineWidth;
370
371 compareOk = verifyLineGroupRasterization(resultImage, scene, args, m_testCtx.getLog());
372
373 // multisampled wide lines might not be supported
374 if (scene.lineWidth != 1.0f && m_numSamples > 1 && !compareOk)
375 {
376 m_multisampleRelaxationRequired = true;
377 compareOk = true;
378 }
379
380 if (!compareOk)
381 m_allIterationsPassed = false;
382 }
383
384 // result
385 if (++m_iteration == m_iterationCount)
386 {
387 if (m_allIterationsPassed && m_multisampleRelaxationRequired)
388 m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Rasterization of multisampled wide lines failed");
389 else if (m_allIterationsPassed)
390 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
391 else
392 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rasterization");
393
394 return STOP;
395 }
396 else
397 return CONTINUE;
398 }
399
400 class PointCase : public BaseRenderingCase
401 {
402 public:
403 PointCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness);
404 ~PointCase (void);
405 IterateResult iterate (void);
406
407 private:
408 void generatePoints (int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints);
409
410 int m_iteration;
411 const int m_iterationCount;
412 const PrimitiveWideness m_primitiveWideness;
413 bool m_allIterationsPassed;
414
415 static const float s_wideSize;
416 };
417
418 const float PointCase::s_wideSize = 10.0f;
419
PointCase(Context & context,const char * name,const char * desc,PrimitiveWideness wideness)420 PointCase::PointCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness)
421 : BaseRenderingCase (context, name, desc)
422 , m_iteration (0)
423 , m_iterationCount (3)
424 , m_primitiveWideness (wideness)
425 , m_allIterationsPassed (true)
426 {
427 m_pointSize = (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE) ? (s_wideSize) : (1.0f);
428 }
429
~PointCase(void)430 PointCase::~PointCase (void)
431 {
432 }
433
iterate(void)434 PointCase::IterateResult PointCase::iterate (void)
435 {
436 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
437 const tcu::ScopedLogSection section (m_testCtx.getLog(), iterationDescription, iterationDescription);
438 tcu::Surface resultImage (m_renderSize, m_renderSize);
439 std::vector<tcu::Vec4> drawBuffer;
440 std::vector<PointSceneSpec::ScenePoint> points;
441
442 // last iteration, max out size
443 if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE &&
444 m_iteration+1 == m_iterationCount)
445 {
446 float range[2] = { 0.0f, 0.0f };
447 m_context.getRenderContext().getFunctions().getFloatv(GL_ALIASED_POINT_SIZE_RANGE, range);
448
449 m_pointSize = range[1];
450 }
451
452 // gen data
453 generatePoints(m_iteration, drawBuffer, points);
454
455 // draw image
456 drawPrimitives(resultImage, drawBuffer, GL_POINTS);
457
458 // compare
459 {
460 bool compareOk;
461 RasterizationArguments args;
462 PointSceneSpec scene;
463
464 args.numSamples = m_numSamples;
465 args.subpixelBits = m_subpixelBits;
466 args.redBits = m_context.getRenderTarget().getPixelFormat().redBits;
467 args.greenBits = m_context.getRenderTarget().getPixelFormat().greenBits;
468 args.blueBits = m_context.getRenderTarget().getPixelFormat().blueBits;
469
470 scene.points.swap(points);
471
472 compareOk = verifyPointGroupRasterization(resultImage, scene, args, m_testCtx.getLog());
473
474 if (!compareOk)
475 m_allIterationsPassed = false;
476 }
477
478 // result
479 if (++m_iteration == m_iterationCount)
480 {
481 if (m_allIterationsPassed)
482 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
483 else
484 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rasterization");
485
486 return STOP;
487 }
488 else
489 return CONTINUE;
490 }
491
generatePoints(int iteration,std::vector<tcu::Vec4> & outData,std::vector<PointSceneSpec::ScenePoint> & outPoints)492 void PointCase::generatePoints (int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints)
493 {
494 outData.resize(6);
495
496 switch (iteration)
497 {
498 case 0:
499 // \note: these values are chosen arbitrarily
500 outData[0] = tcu::Vec4( 0.2f, 0.8f, 0.0f, 1.0f);
501 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f);
502 outData[2] = tcu::Vec4( 0.5f, 0.3f, 0.0f, 1.0f);
503 outData[3] = tcu::Vec4(-0.5f, 0.2f, 0.0f, 1.0f);
504 outData[4] = tcu::Vec4(-0.2f, -0.4f, 0.0f, 1.0f);
505 outData[5] = tcu::Vec4(-0.4f, 0.2f, 0.0f, 1.0f);
506 break;
507
508 case 1:
509 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
510 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f);
511 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f);
512 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
513 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f);
514 outData[5] = tcu::Vec4( 0.4f, 1.2f, 0.0f, 1.0f);
515 break;
516
517 case 2:
518 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
519 outData[1] = tcu::Vec4( 0.3f, -0.9f, 0.0f, 1.0f);
520 outData[2] = tcu::Vec4( -0.4f, -0.1f, 0.0f, 1.0f);
521 outData[3] = tcu::Vec4(-0.11f, 0.2f, 0.0f, 1.0f);
522 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f);
523 outData[5] = tcu::Vec4( -0.4f, 0.4f, 0.0f, 1.0f);
524 break;
525 }
526
527 outPoints.resize(outData.size());
528 for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
529 {
530 outPoints[pointNdx].position = outData[pointNdx];
531 outPoints[pointNdx].pointSize = m_pointSize;
532 }
533
534 // log
535 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering " << outPoints.size() << " point(s): (point size = " << m_pointSize << ")" << tcu::TestLog::EndMessage;
536 for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
537 m_testCtx.getLog() << tcu::TestLog::Message << "Point " << (pointNdx+1) << ":\t" << outPoints[pointNdx].position << tcu::TestLog::EndMessage;
538 }
539
540 class TrianglesCase : public BaseTriangleCase
541 {
542 public:
543 TrianglesCase (Context& context, const char* name, const char* desc);
544 ~TrianglesCase (void);
545
546 void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
547 };
548
TrianglesCase(Context & context,const char * name,const char * desc)549 TrianglesCase::TrianglesCase (Context& context, const char* name, const char* desc)
550 : BaseTriangleCase(context, name, desc, GL_TRIANGLES)
551 {
552 }
553
~TrianglesCase(void)554 TrianglesCase::~TrianglesCase (void)
555 {
556
557 }
558
generateTriangles(int iteration,std::vector<tcu::Vec4> & outData,std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles)559 void TrianglesCase::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
560 {
561 outData.resize(6);
562
563 switch (iteration)
564 {
565 case 0:
566 // \note: these values are chosen arbitrarily
567 outData[0] = tcu::Vec4( 0.2f, 0.8f, 0.0f, 1.0f);
568 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f);
569 outData[2] = tcu::Vec4( 0.5f, 0.3f, 0.0f, 1.0f);
570 outData[3] = tcu::Vec4(-0.5f, 0.2f, 0.0f, 1.0f);
571 outData[4] = tcu::Vec4(-1.5f, -0.4f, 0.0f, 1.0f);
572 outData[5] = tcu::Vec4(-0.4f, 0.2f, 0.0f, 1.0f);
573 break;
574
575 case 1:
576 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
577 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f);
578 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f);
579 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
580 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f);
581 outData[5] = tcu::Vec4( 0.4f, 1.2f, 0.0f, 1.0f);
582 break;
583
584 case 2:
585 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
586 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f);
587 outData[2] = tcu::Vec4( -1.1f, -0.1f, 0.0f, 1.0f);
588 outData[3] = tcu::Vec4(-0.11f, 0.2f, 0.0f, 1.0f);
589 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f);
590 outData[5] = tcu::Vec4( -0.4f, 0.4f, 0.0f, 1.0f);
591 break;
592 }
593
594 outTriangles.resize(2);
595 outTriangles[0].positions[0] = outData[0]; outTriangles[0].sharedEdge[0] = false;
596 outTriangles[0].positions[1] = outData[1]; outTriangles[0].sharedEdge[1] = false;
597 outTriangles[0].positions[2] = outData[2]; outTriangles[0].sharedEdge[2] = false;
598
599 outTriangles[1].positions[0] = outData[3]; outTriangles[1].sharedEdge[0] = false;
600 outTriangles[1].positions[1] = outData[4]; outTriangles[1].sharedEdge[1] = false;
601 outTriangles[1].positions[2] = outData[5]; outTriangles[1].sharedEdge[2] = false;
602
603 // log
604 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering " << outTriangles.size() << " triangle(s):" << tcu::TestLog::EndMessage;
605 for (int triangleNdx = 0; triangleNdx < (int)outTriangles.size(); ++triangleNdx)
606 {
607 m_testCtx.getLog()
608 << tcu::TestLog::Message
609 << "Triangle " << (triangleNdx+1) << ":"
610 << "\n\t" << outTriangles[triangleNdx].positions[0]
611 << "\n\t" << outTriangles[triangleNdx].positions[1]
612 << "\n\t" << outTriangles[triangleNdx].positions[2]
613 << tcu::TestLog::EndMessage;
614 }
615 }
616
617 class TriangleStripCase : public BaseTriangleCase
618 {
619 public:
620 TriangleStripCase (Context& context, const char* name, const char* desc);
621
622 void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
623 };
624
TriangleStripCase(Context & context,const char * name,const char * desc)625 TriangleStripCase::TriangleStripCase (Context& context, const char* name, const char* desc)
626 : BaseTriangleCase(context, name, desc, GL_TRIANGLE_STRIP)
627 {
628 }
629
generateTriangles(int iteration,std::vector<tcu::Vec4> & outData,std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles)630 void TriangleStripCase::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
631 {
632 outData.resize(5);
633
634 switch (iteration)
635 {
636 case 0:
637 // \note: these values are chosen arbitrarily
638 outData[0] = tcu::Vec4(-0.504f, 0.8f, 0.0f, 1.0f);
639 outData[1] = tcu::Vec4(-0.2f, -0.2f, 0.0f, 1.0f);
640 outData[2] = tcu::Vec4(-0.2f, 0.199f, 0.0f, 1.0f);
641 outData[3] = tcu::Vec4( 0.5f, 0.201f, 0.0f, 1.0f);
642 outData[4] = tcu::Vec4( 1.5f, 0.4f, 0.0f, 1.0f);
643 break;
644
645 case 1:
646 outData[0] = tcu::Vec4(-0.499f, 0.129f, 0.0f, 1.0f);
647 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f);
648 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f);
649 outData[3] = tcu::Vec4( 0.11f, -0.31f, 0.0f, 1.0f);
650 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f);
651 break;
652
653 case 2:
654 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
655 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f);
656 outData[2] = tcu::Vec4(-0.87f, -0.1f, 0.0f, 1.0f);
657 outData[3] = tcu::Vec4(-0.11f, 0.19f, 0.0f, 1.0f);
658 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f);
659 break;
660 }
661
662 outTriangles.resize(3);
663 outTriangles[0].positions[0] = outData[0]; outTriangles[0].sharedEdge[0] = false;
664 outTriangles[0].positions[1] = outData[1]; outTriangles[0].sharedEdge[1] = true;
665 outTriangles[0].positions[2] = outData[2]; outTriangles[0].sharedEdge[2] = false;
666
667 outTriangles[1].positions[0] = outData[2]; outTriangles[1].sharedEdge[0] = true;
668 outTriangles[1].positions[1] = outData[1]; outTriangles[1].sharedEdge[1] = false;
669 outTriangles[1].positions[2] = outData[3]; outTriangles[1].sharedEdge[2] = true;
670
671 outTriangles[2].positions[0] = outData[2]; outTriangles[2].sharedEdge[0] = true;
672 outTriangles[2].positions[1] = outData[3]; outTriangles[2].sharedEdge[1] = false;
673 outTriangles[2].positions[2] = outData[4]; outTriangles[2].sharedEdge[2] = false;
674
675 // log
676 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering triangle strip, " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
677 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
678 {
679 m_testCtx.getLog()
680 << tcu::TestLog::Message
681 << "\t" << outData[vtxNdx]
682 << tcu::TestLog::EndMessage;
683 }
684 }
685
686 class TriangleFanCase : public BaseTriangleCase
687 {
688 public:
689 TriangleFanCase (Context& context, const char* name, const char* desc);
690
691 void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
692 };
693
TriangleFanCase(Context & context,const char * name,const char * desc)694 TriangleFanCase::TriangleFanCase (Context& context, const char* name, const char* desc)
695 : BaseTriangleCase(context, name, desc, GL_TRIANGLE_FAN)
696 {
697 }
698
generateTriangles(int iteration,std::vector<tcu::Vec4> & outData,std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles)699 void TriangleFanCase::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
700 {
701 outData.resize(5);
702
703 switch (iteration)
704 {
705 case 0:
706 // \note: these values are chosen arbitrarily
707 outData[0] = tcu::Vec4( 0.01f, 0.0f, 0.0f, 1.0f);
708 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f);
709 outData[2] = tcu::Vec4( 0.46f, 0.3f, 0.0f, 1.0f);
710 outData[3] = tcu::Vec4(-0.5f, 0.2f, 0.0f, 1.0f);
711 outData[4] = tcu::Vec4(-1.5f, -0.4f, 0.0f, 1.0f);
712 break;
713
714 case 1:
715 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
716 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f);
717 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f);
718 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
719 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f);
720 break;
721
722 case 2:
723 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
724 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f);
725 outData[2] = tcu::Vec4( 0.7f, -0.1f, 0.0f, 1.0f);
726 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
727 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f);
728 break;
729 }
730
731 outTriangles.resize(3);
732 outTriangles[0].positions[0] = outData[0]; outTriangles[0].sharedEdge[0] = false;
733 outTriangles[0].positions[1] = outData[1]; outTriangles[0].sharedEdge[1] = false;
734 outTriangles[0].positions[2] = outData[2]; outTriangles[0].sharedEdge[2] = true;
735
736 outTriangles[1].positions[0] = outData[0]; outTriangles[1].sharedEdge[0] = true;
737 outTriangles[1].positions[1] = outData[2]; outTriangles[1].sharedEdge[1] = false;
738 outTriangles[1].positions[2] = outData[3]; outTriangles[1].sharedEdge[2] = true;
739
740 outTriangles[2].positions[0] = outData[0]; outTriangles[2].sharedEdge[0] = true;
741 outTriangles[2].positions[1] = outData[3]; outTriangles[2].sharedEdge[1] = false;
742 outTriangles[2].positions[2] = outData[4]; outTriangles[2].sharedEdge[2] = false;
743
744 // log
745 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering triangle fan, " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
746 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
747 {
748 m_testCtx.getLog()
749 << tcu::TestLog::Message
750 << "\t" << outData[vtxNdx]
751 << tcu::TestLog::EndMessage;
752 }
753 }
754
755 class LinesCase : public BaseLineCase
756 {
757 public:
758 LinesCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness);
759
760 void generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
761 };
762
LinesCase(Context & context,const char * name,const char * desc,PrimitiveWideness wideness)763 LinesCase::LinesCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness)
764 : BaseLineCase(context, name, desc, GL_LINES, wideness)
765 {
766 }
767
generateLines(int iteration,std::vector<tcu::Vec4> & outData,std::vector<LineSceneSpec::SceneLine> & outLines)768 void LinesCase::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
769 {
770 outData.resize(6);
771
772 switch (iteration)
773 {
774 case 0:
775 // \note: these values are chosen arbitrarily
776 outData[0] = tcu::Vec4( 0.01f, 0.0f, 0.0f, 1.0f);
777 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f);
778 outData[2] = tcu::Vec4( 0.46f, 0.3f, 0.0f, 1.0f);
779 outData[3] = tcu::Vec4(-0.3f, 0.2f, 0.0f, 1.0f);
780 outData[4] = tcu::Vec4(-1.5f, -0.4f, 0.0f, 1.0f);
781 outData[5] = tcu::Vec4( 0.1f, 0.5f, 0.0f, 1.0f);
782 break;
783
784 case 1:
785 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
786 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f);
787 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f);
788 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
789 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f);
790 outData[5] = tcu::Vec4( 0.18f, -0.2f, 0.0f, 1.0f);
791 break;
792
793 case 2:
794 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
795 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f);
796 outData[2] = tcu::Vec4( 0.7f, -0.1f, 0.0f, 1.0f);
797 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
798 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f);
799 outData[5] = tcu::Vec4( 0.8f, -0.7f, 0.0f, 1.0f);
800 break;
801 }
802
803 outLines.resize(3);
804 outLines[0].positions[0] = outData[0];
805 outLines[0].positions[1] = outData[1];
806 outLines[1].positions[0] = outData[2];
807 outLines[1].positions[1] = outData[3];
808 outLines[2].positions[0] = outData[4];
809 outLines[2].positions[1] = outData[5];
810
811 // log
812 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering " << outLines.size() << " lines(s): (width = " << m_lineWidth << ")" << tcu::TestLog::EndMessage;
813 for (int lineNdx = 0; lineNdx < (int)outLines.size(); ++lineNdx)
814 {
815 m_testCtx.getLog()
816 << tcu::TestLog::Message
817 << "Line " << (lineNdx+1) << ":"
818 << "\n\t" << outLines[lineNdx].positions[0]
819 << "\n\t" << outLines[lineNdx].positions[1]
820 << tcu::TestLog::EndMessage;
821 }
822 }
823
824 class LineStripCase : public BaseLineCase
825 {
826 public:
827 LineStripCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness);
828
829 void generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
830 };
831
LineStripCase(Context & context,const char * name,const char * desc,PrimitiveWideness wideness)832 LineStripCase::LineStripCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness)
833 : BaseLineCase(context, name, desc, GL_LINE_STRIP, wideness)
834 {
835 }
836
generateLines(int iteration,std::vector<tcu::Vec4> & outData,std::vector<LineSceneSpec::SceneLine> & outLines)837 void LineStripCase::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
838 {
839 outData.resize(4);
840
841 switch (iteration)
842 {
843 case 0:
844 // \note: these values are chosen arbitrarily
845 outData[0] = tcu::Vec4( 0.01f, 0.0f, 0.0f, 1.0f);
846 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f);
847 outData[2] = tcu::Vec4( 0.46f, 0.3f, 0.0f, 1.0f);
848 outData[3] = tcu::Vec4(-0.5f, 0.2f, 0.0f, 1.0f);
849 break;
850
851 case 1:
852 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
853 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f);
854 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f);
855 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
856 break;
857
858 case 2:
859 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
860 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f);
861 outData[2] = tcu::Vec4( 0.7f, -0.1f, 0.0f, 1.0f);
862 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
863 break;
864 }
865
866 outLines.resize(3);
867 outLines[0].positions[0] = outData[0];
868 outLines[0].positions[1] = outData[1];
869 outLines[1].positions[0] = outData[1];
870 outLines[1].positions[1] = outData[2];
871 outLines[2].positions[0] = outData[2];
872 outLines[2].positions[1] = outData[3];
873
874 // log
875 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering line strip, width = " << m_lineWidth << ", " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
876 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
877 {
878 m_testCtx.getLog()
879 << tcu::TestLog::Message
880 << "\t" << outData[vtxNdx]
881 << tcu::TestLog::EndMessage;
882 }
883 }
884
885 class LineLoopCase : public BaseLineCase
886 {
887 public:
888 LineLoopCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness);
889
890 void generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
891 };
892
LineLoopCase(Context & context,const char * name,const char * desc,PrimitiveWideness wideness)893 LineLoopCase::LineLoopCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness)
894 : BaseLineCase(context, name, desc, GL_LINE_LOOP, wideness)
895 {
896 }
897
generateLines(int iteration,std::vector<tcu::Vec4> & outData,std::vector<LineSceneSpec::SceneLine> & outLines)898 void LineLoopCase::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
899 {
900 outData.resize(4);
901
902 switch (iteration)
903 {
904 case 0:
905 // \note: these values are chosen arbitrarily
906 outData[0] = tcu::Vec4( 0.01f, 0.0f, 0.0f, 1.0f);
907 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f);
908 outData[2] = tcu::Vec4( 0.46f, 0.3f, 0.0f, 1.0f);
909 outData[3] = tcu::Vec4(-0.5f, 0.2f, 0.0f, 1.0f);
910 break;
911
912 case 1:
913 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
914 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f);
915 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f);
916 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
917 break;
918
919 case 2:
920 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
921 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f);
922 outData[2] = tcu::Vec4( 0.7f, -0.1f, 0.0f, 1.0f);
923 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
924 break;
925 }
926
927 outLines.resize(4);
928 outLines[0].positions[0] = outData[0];
929 outLines[0].positions[1] = outData[1];
930 outLines[1].positions[0] = outData[1];
931 outLines[1].positions[1] = outData[2];
932 outLines[2].positions[0] = outData[2];
933 outLines[2].positions[1] = outData[3];
934 outLines[3].positions[0] = outData[3];
935 outLines[3].positions[1] = outData[0];
936
937 // log
938 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering line loop, width = " << m_lineWidth << ", " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
939 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
940 {
941 m_testCtx.getLog()
942 << tcu::TestLog::Message
943 << "\t" << outData[vtxNdx]
944 << tcu::TestLog::EndMessage;
945 }
946 }
947
948 class FillRuleCase : public BaseRenderingCase
949 {
950 public:
951 enum FillRuleCaseType
952 {
953 FILLRULECASE_BASIC = 0,
954 FILLRULECASE_REVERSED,
955 FILLRULECASE_CLIPPED_FULL,
956 FILLRULECASE_CLIPPED_PARTIAL,
957 FILLRULECASE_PROJECTED,
958
959 FILLRULECASE_LAST
960 };
961
962 FillRuleCase (Context& ctx, const char* name, const char* desc, FillRuleCaseType type);
963 ~FillRuleCase (void);
964 IterateResult iterate (void);
965
966 private:
967 int getRenderSize (FillRuleCase::FillRuleCaseType type) const;
968 int getNumIterations (FillRuleCase::FillRuleCaseType type) const;
969 void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData) const;
970
971 const FillRuleCaseType m_caseType;
972 int m_iteration;
973 const int m_iterationCount;
974 bool m_allIterationsPassed;
975
976 };
977
FillRuleCase(Context & ctx,const char * name,const char * desc,FillRuleCaseType type)978 FillRuleCase::FillRuleCase (Context& ctx, const char* name, const char* desc, FillRuleCaseType type)
979 : BaseRenderingCase (ctx, name, desc, getRenderSize(type))
980 , m_caseType (type)
981 , m_iteration (0)
982 , m_iterationCount (getNumIterations(type))
983 , m_allIterationsPassed (true)
984 {
985 DE_ASSERT(type < FILLRULECASE_LAST);
986 }
987
~FillRuleCase(void)988 FillRuleCase::~FillRuleCase (void)
989 {
990 deinit();
991 }
992
iterate(void)993 FillRuleCase::IterateResult FillRuleCase::iterate (void)
994 {
995 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
996 const tcu::ScopedLogSection section (m_testCtx.getLog(), iterationDescription, iterationDescription);
997 const int thresholdRed = 1 << (8 - m_context.getRenderTarget().getPixelFormat().redBits);
998 const int thresholdGreen = 1 << (8 - m_context.getRenderTarget().getPixelFormat().greenBits);
999 const int thresholdBlue = 1 << (8 - m_context.getRenderTarget().getPixelFormat().blueBits);
1000 tcu::Surface resultImage (m_renderSize, m_renderSize);
1001 std::vector<tcu::Vec4> drawBuffer;
1002 bool imageShown = false;
1003
1004 generateTriangles(m_iteration, drawBuffer);
1005
1006 // draw image
1007 {
1008 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1009 const std::vector<tcu::Vec4> colorBuffer (drawBuffer.size(), tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f));
1010
1011 m_testCtx.getLog() << tcu::TestLog::Message << "Drawing gray triangles with shared edges.\nEnabling additive blending to detect overlapping fragments." << tcu::TestLog::EndMessage;
1012
1013 gl.enable(GL_BLEND);
1014 gl.blendEquation(GL_FUNC_ADD);
1015 gl.blendFunc(GL_ONE, GL_ONE);
1016 drawPrimitives(resultImage, drawBuffer, colorBuffer, GL_TRIANGLES);
1017 }
1018
1019 // verify no overdraw
1020 {
1021 const tcu::RGBA triangleColor = tcu::RGBA(127, 127, 127, 255);
1022 bool overdraw = false;
1023
1024 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying result." << tcu::TestLog::EndMessage;
1025
1026 for (int y = 0; y < resultImage.getHeight(); ++y)
1027 for (int x = 0; x < resultImage.getWidth(); ++x)
1028 {
1029 const tcu::RGBA color = resultImage.getPixel(x, y);
1030
1031 // color values are greater than triangle color? Allow lower values for multisampled edges and background.
1032 if ((color.getRed() - triangleColor.getRed()) > thresholdRed ||
1033 (color.getGreen() - triangleColor.getGreen()) > thresholdGreen ||
1034 (color.getBlue() - triangleColor.getBlue()) > thresholdBlue)
1035 overdraw = true;
1036 }
1037
1038 // results
1039 if (!overdraw)
1040 m_testCtx.getLog() << tcu::TestLog::Message << "No overlapping fragments detected." << tcu::TestLog::EndMessage;
1041 else
1042 {
1043 m_testCtx.getLog() << tcu::TestLog::Message << "Overlapping fragments detected, image is not valid." << tcu::TestLog::EndMessage;
1044 m_testCtx.getLog() << tcu::TestLog::ImageSet("Result of rendering", "Result of rendering")
1045 << tcu::TestLog::Image("Result", "Result", resultImage)
1046 << tcu::TestLog::EndImageSet;
1047
1048 imageShown = true;
1049 m_allIterationsPassed = false;
1050 }
1051 }
1052
1053 // verify no missing fragments in the full viewport case
1054 if (m_caseType == FILLRULECASE_CLIPPED_FULL)
1055 {
1056 bool missingFragments = false;
1057
1058 m_testCtx.getLog() << tcu::TestLog::Message << "Searching missing fragments." << tcu::TestLog::EndMessage;
1059
1060 for (int y = 0; y < resultImage.getHeight(); ++y)
1061 for (int x = 0; x < resultImage.getWidth(); ++x)
1062 {
1063 const tcu::RGBA color = resultImage.getPixel(x, y);
1064
1065 // black? (background)
1066 if (color.getRed() <= thresholdRed ||
1067 color.getGreen() <= thresholdGreen ||
1068 color.getBlue() <= thresholdBlue)
1069 missingFragments = true;
1070 }
1071
1072 // results
1073 if (!missingFragments)
1074 m_testCtx.getLog() << tcu::TestLog::Message << "No missing fragments detected." << tcu::TestLog::EndMessage;
1075 else
1076 {
1077 m_testCtx.getLog() << tcu::TestLog::Message << "Missing fragments detected, image is not valid." << tcu::TestLog::EndMessage;
1078
1079 if (!imageShown)
1080 {
1081 m_testCtx.getLog() << tcu::TestLog::ImageSet("Result of rendering", "Result of rendering")
1082 << tcu::TestLog::Image("Result", "Result", resultImage)
1083 << tcu::TestLog::EndImageSet;
1084 }
1085
1086 m_allIterationsPassed = false;
1087 }
1088 }
1089
1090 // result
1091 if (++m_iteration == m_iterationCount)
1092 {
1093 if (m_allIterationsPassed)
1094 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1095 else
1096 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Found invalid pixels");
1097
1098 return STOP;
1099 }
1100 else
1101 return CONTINUE;
1102 }
1103
getRenderSize(FillRuleCase::FillRuleCaseType type) const1104 int FillRuleCase::getRenderSize (FillRuleCase::FillRuleCaseType type) const
1105 {
1106 if (type == FILLRULECASE_CLIPPED_FULL || type == FILLRULECASE_CLIPPED_PARTIAL)
1107 return 64;
1108 else
1109 return 256;
1110 }
1111
getNumIterations(FillRuleCase::FillRuleCaseType type) const1112 int FillRuleCase::getNumIterations (FillRuleCase::FillRuleCaseType type) const
1113 {
1114 if (type == FILLRULECASE_CLIPPED_FULL || type == FILLRULECASE_CLIPPED_PARTIAL)
1115 return 15;
1116 else
1117 return 2;
1118 }
1119
generateTriangles(int iteration,std::vector<tcu::Vec4> & outData) const1120 void FillRuleCase::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData) const
1121 {
1122 switch (m_caseType)
1123 {
1124 case FILLRULECASE_BASIC:
1125 case FILLRULECASE_REVERSED:
1126 case FILLRULECASE_PROJECTED:
1127 {
1128 const int numRows = 4;
1129 const int numColumns = 4;
1130 const float quadSide = 0.15f;
1131 de::Random rnd (0xabcd);
1132
1133 outData.resize(6 * numRows * numColumns);
1134
1135 for (int col = 0; col < numColumns; ++col)
1136 for (int row = 0; row < numRows; ++row)
1137 {
1138 const tcu::Vec2 center = tcu::Vec2((row + 0.5f) / numRows * 2.0f - 1.0f, (col + 0.5f) / numColumns * 2.0f - 1.0f);
1139 const float rotation = (iteration * numColumns * numRows + col * numRows + row) / (float)(m_iterationCount * numColumns * numRows) * DE_PI / 2.0f;
1140 const tcu::Vec2 sideH = quadSide * tcu::Vec2(deFloatCos(rotation), deFloatSin(rotation));
1141 const tcu::Vec2 sideV = tcu::Vec2(sideH.y(), -sideH.x());
1142 const tcu::Vec2 quad[4] =
1143 {
1144 center + sideH + sideV,
1145 center + sideH - sideV,
1146 center - sideH - sideV,
1147 center - sideH + sideV,
1148 };
1149
1150 if (m_caseType == FILLRULECASE_BASIC)
1151 {
1152 outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1153 outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
1154 outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1155 outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1156 outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1157 outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
1158 }
1159 else if (m_caseType == FILLRULECASE_REVERSED)
1160 {
1161 outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1162 outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
1163 outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1164 outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1165 outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1166 outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
1167 }
1168 else if (m_caseType == FILLRULECASE_PROJECTED)
1169 {
1170 const float w0 = rnd.getFloat(0.1f, 4.0f);
1171 const float w1 = rnd.getFloat(0.1f, 4.0f);
1172 const float w2 = rnd.getFloat(0.1f, 4.0f);
1173 const float w3 = rnd.getFloat(0.1f, 4.0f);
1174
1175 outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x() * w0, quad[0].y() * w0, 0.0f, w0);
1176 outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x() * w1, quad[1].y() * w1, 0.0f, w1);
1177 outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x() * w2, quad[2].y() * w2, 0.0f, w2);
1178 outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[2].x() * w2, quad[2].y() * w2, 0.0f, w2);
1179 outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[0].x() * w0, quad[0].y() * w0, 0.0f, w0);
1180 outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x() * w3, quad[3].y() * w3, 0.0f, w3);
1181 }
1182 else
1183 DE_ASSERT(DE_FALSE);
1184 }
1185
1186 break;
1187 }
1188
1189 case FILLRULECASE_CLIPPED_PARTIAL:
1190 case FILLRULECASE_CLIPPED_FULL:
1191 {
1192 const float quadSide = (m_caseType == FILLRULECASE_CLIPPED_PARTIAL) ? (1.0f) : (2.0f);
1193 const tcu::Vec2 center = (m_caseType == FILLRULECASE_CLIPPED_PARTIAL) ? (tcu::Vec2(0.5f, 0.5f)) : (tcu::Vec2(0.0f, 0.0f));
1194 const float rotation = (iteration) / (float)(m_iterationCount - 1) * DE_PI / 2.0f;
1195 const tcu::Vec2 sideH = quadSide * tcu::Vec2(deFloatCos(rotation), deFloatSin(rotation));
1196 const tcu::Vec2 sideV = tcu::Vec2(sideH.y(), -sideH.x());
1197 const tcu::Vec2 quad[4] =
1198 {
1199 center + sideH + sideV,
1200 center + sideH - sideV,
1201 center - sideH - sideV,
1202 center - sideH + sideV,
1203 };
1204
1205 outData.resize(6);
1206 outData[0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1207 outData[1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
1208 outData[2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1209 outData[3] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1210 outData[4] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1211 outData[5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
1212 break;
1213 }
1214
1215 default:
1216 DE_ASSERT(DE_FALSE);
1217 }
1218 }
1219
1220 class CullingTest : public BaseRenderingCase
1221 {
1222 public:
1223 CullingTest (Context& ctx, const char* name, const char* desc, glw::GLenum cullMode, glw::GLenum primitive, glw::GLenum faceOrder);
1224 ~CullingTest (void);
1225 IterateResult iterate (void);
1226
1227 private:
1228 void generateVertices (std::vector<tcu::Vec4>& outData) const;
1229 void extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const;
1230 bool triangleOrder (const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) const;
1231
1232 const glw::GLenum m_cullMode;
1233 const glw::GLenum m_primitive;
1234 const glw::GLenum m_faceOrder;
1235 };
1236
CullingTest(Context & ctx,const char * name,const char * desc,glw::GLenum cullMode,glw::GLenum primitive,glw::GLenum faceOrder)1237 CullingTest::CullingTest (Context& ctx, const char* name, const char* desc, glw::GLenum cullMode, glw::GLenum primitive, glw::GLenum faceOrder)
1238 : BaseRenderingCase (ctx, name, desc)
1239 , m_cullMode (cullMode)
1240 , m_primitive (primitive)
1241 , m_faceOrder (faceOrder)
1242 {
1243 }
1244
~CullingTest(void)1245 CullingTest::~CullingTest (void)
1246 {
1247 }
1248
iterate(void)1249 CullingTest::IterateResult CullingTest::iterate (void)
1250 {
1251 tcu::Surface resultImage(m_renderSize, m_renderSize);
1252 std::vector<tcu::Vec4> drawBuffer;
1253 std::vector<TriangleSceneSpec::SceneTriangle> triangles;
1254
1255 // generate scene
1256 generateVertices(drawBuffer);
1257 extractTriangles(triangles, drawBuffer);
1258
1259 // draw image
1260 {
1261 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1262
1263 gl.enable(GL_CULL_FACE);
1264 gl.cullFace(m_cullMode);
1265 gl.frontFace(m_faceOrder);
1266
1267 m_testCtx.getLog() << tcu::TestLog::Message << "Setting front face to " << glu::getWindingName(m_faceOrder) << tcu::TestLog::EndMessage;
1268 m_testCtx.getLog() << tcu::TestLog::Message << "Setting cull face to " << glu::getFaceName(m_cullMode) << tcu::TestLog::EndMessage;
1269 m_testCtx.getLog() << tcu::TestLog::Message << "Drawing test pattern (" << glu::getPrimitiveTypeName(m_primitive) << ")" << tcu::TestLog::EndMessage;
1270
1271 drawPrimitives(resultImage, drawBuffer, m_primitive);
1272 }
1273
1274 // compare
1275 {
1276 RasterizationArguments args;
1277 TriangleSceneSpec scene;
1278
1279 args.numSamples = m_numSamples;
1280 args.subpixelBits = m_subpixelBits;
1281 args.redBits = m_context.getRenderTarget().getPixelFormat().redBits;
1282 args.greenBits = m_context.getRenderTarget().getPixelFormat().greenBits;
1283 args.blueBits = m_context.getRenderTarget().getPixelFormat().blueBits;
1284
1285 scene.triangles.swap(triangles);
1286
1287 if (verifyTriangleGroupRasterization(resultImage, scene, args, m_testCtx.getLog(), VERIFICATIONMODE_WEAK))
1288 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1289 else
1290 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rendering");
1291 }
1292
1293 return STOP;
1294 }
1295
generateVertices(std::vector<tcu::Vec4> & outData) const1296 void CullingTest::generateVertices (std::vector<tcu::Vec4>& outData) const
1297 {
1298 de::Random rnd(543210);
1299
1300 outData.resize(6);
1301 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
1302 {
1303 outData[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
1304 outData[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
1305 outData[vtxNdx].z() = 0.0f;
1306 outData[vtxNdx].w() = 1.0f;
1307 }
1308 }
1309
extractTriangles(std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles,const std::vector<tcu::Vec4> & vertices) const1310 void CullingTest::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const
1311 {
1312 const bool cullDirection = (m_cullMode == GL_FRONT) ^ (m_faceOrder == GL_CCW);
1313
1314 // No triangles
1315 if (m_cullMode == GL_FRONT_AND_BACK)
1316 return;
1317
1318 switch (m_primitive)
1319 {
1320 case GL_TRIANGLES:
1321 {
1322 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
1323 {
1324 const tcu::Vec4& v0 = vertices[vtxNdx + 0];
1325 const tcu::Vec4& v1 = vertices[vtxNdx + 1];
1326 const tcu::Vec4& v2 = vertices[vtxNdx + 2];
1327
1328 if (triangleOrder(v0, v1, v2) != cullDirection)
1329 {
1330 TriangleSceneSpec::SceneTriangle tri;
1331 tri.positions[0] = v0; tri.sharedEdge[0] = false;
1332 tri.positions[1] = v1; tri.sharedEdge[1] = false;
1333 tri.positions[2] = v2; tri.sharedEdge[2] = false;
1334
1335 outTriangles.push_back(tri);
1336 }
1337 }
1338 break;
1339 }
1340
1341 case GL_TRIANGLE_STRIP:
1342 {
1343 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
1344 {
1345 const tcu::Vec4& v0 = vertices[vtxNdx + 0];
1346 const tcu::Vec4& v1 = vertices[vtxNdx + 1];
1347 const tcu::Vec4& v2 = vertices[vtxNdx + 2];
1348
1349 if (triangleOrder(v0, v1, v2) != (cullDirection ^ (vtxNdx % 2 != 0)))
1350 {
1351 TriangleSceneSpec::SceneTriangle tri;
1352 tri.positions[0] = v0; tri.sharedEdge[0] = false;
1353 tri.positions[1] = v1; tri.sharedEdge[1] = false;
1354 tri.positions[2] = v2; tri.sharedEdge[2] = false;
1355
1356 outTriangles.push_back(tri);
1357 }
1358 }
1359 break;
1360 }
1361
1362 case GL_TRIANGLE_FAN:
1363 {
1364 for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
1365 {
1366 const tcu::Vec4& v0 = vertices[0];
1367 const tcu::Vec4& v1 = vertices[vtxNdx + 0];
1368 const tcu::Vec4& v2 = vertices[vtxNdx + 1];
1369
1370 if (triangleOrder(v0, v1, v2) != cullDirection)
1371 {
1372 TriangleSceneSpec::SceneTriangle tri;
1373 tri.positions[0] = v0; tri.sharedEdge[0] = false;
1374 tri.positions[1] = v1; tri.sharedEdge[1] = false;
1375 tri.positions[2] = v2; tri.sharedEdge[2] = false;
1376
1377 outTriangles.push_back(tri);
1378 }
1379 }
1380 break;
1381 }
1382
1383 default:
1384 DE_ASSERT(false);
1385 }
1386 }
1387
triangleOrder(const tcu::Vec4 & v0,const tcu::Vec4 & v1,const tcu::Vec4 & v2) const1388 bool CullingTest::triangleOrder (const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) const
1389 {
1390 const tcu::Vec2 s0 = v0.swizzle(0, 1) / v0.w();
1391 const tcu::Vec2 s1 = v1.swizzle(0, 1) / v1.w();
1392 const tcu::Vec2 s2 = v2.swizzle(0, 1) / v2.w();
1393
1394 // cross
1395 return ((s1.x() - s0.x()) * (s2.y() - s0.y()) - (s2.x() - s0.x()) * (s1.y() - s0.y())) < 0;
1396 }
1397
1398 class TriangleInterpolationTest : public BaseRenderingCase
1399 {
1400 public:
1401 TriangleInterpolationTest (Context& ctx, const char* name, const char* desc, glw::GLenum primitive, int flags);
1402 ~TriangleInterpolationTest (void);
1403 IterateResult iterate (void);
1404
1405 private:
1406 void generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const;
1407 void extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
1408
1409 const glw::GLenum m_primitive;
1410 const bool m_projective;
1411 const int m_iterationCount;
1412
1413 int m_iteration;
1414 bool m_allIterationsPassed;
1415 };
1416
TriangleInterpolationTest(Context & ctx,const char * name,const char * desc,glw::GLenum primitive,int flags)1417 TriangleInterpolationTest::TriangleInterpolationTest (Context& ctx, const char* name, const char* desc, glw::GLenum primitive, int flags)
1418 : BaseRenderingCase (ctx, name, desc)
1419 , m_primitive (primitive)
1420 , m_projective ((flags & INTERPOLATIONFLAGS_PROJECTED) != 0)
1421 , m_iterationCount (3)
1422 , m_iteration (0)
1423 , m_allIterationsPassed (true)
1424 {
1425 }
1426
~TriangleInterpolationTest(void)1427 TriangleInterpolationTest::~TriangleInterpolationTest (void)
1428 {
1429 deinit();
1430 }
1431
iterate(void)1432 TriangleInterpolationTest::IterateResult TriangleInterpolationTest::iterate (void)
1433 {
1434 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
1435 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription);
1436 tcu::Surface resultImage (m_renderSize, m_renderSize);
1437 std::vector<tcu::Vec4> drawBuffer;
1438 std::vector<tcu::Vec4> colorBuffer;
1439 std::vector<TriangleSceneSpec::SceneTriangle> triangles;
1440
1441 // generate scene
1442 generateVertices(m_iteration, drawBuffer, colorBuffer);
1443 extractTriangles(triangles, drawBuffer, colorBuffer);
1444
1445 // log
1446 {
1447 m_testCtx.getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage;
1448 for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx)
1449 m_testCtx.getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage;
1450 }
1451
1452 // draw image
1453 drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitive);
1454
1455 // compare
1456 {
1457 RasterizationArguments args;
1458 TriangleSceneSpec scene;
1459
1460 args.numSamples = m_numSamples;
1461 args.subpixelBits = m_subpixelBits;
1462 args.redBits = m_context.getRenderTarget().getPixelFormat().redBits;
1463 args.greenBits = m_context.getRenderTarget().getPixelFormat().greenBits;
1464 args.blueBits = m_context.getRenderTarget().getPixelFormat().blueBits;
1465
1466 scene.triangles.swap(triangles);
1467
1468 if (!verifyTriangleGroupInterpolation(resultImage, scene, args, m_testCtx.getLog()))
1469 m_allIterationsPassed = false;
1470 }
1471
1472 // result
1473 if (++m_iteration == m_iterationCount)
1474 {
1475 if (m_allIterationsPassed)
1476 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1477 else
1478 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Found invalid pixel values");
1479
1480 return STOP;
1481 }
1482 else
1483 return CONTINUE;
1484 }
1485
generateVertices(int iteration,std::vector<tcu::Vec4> & outVertices,std::vector<tcu::Vec4> & outColors) const1486 void TriangleInterpolationTest::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const
1487 {
1488 // use only red, green and blue
1489 const tcu::Vec4 colors[] =
1490 {
1491 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
1492 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
1493 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
1494 };
1495
1496 de::Random rnd(123 + iteration * 1000 + (int)m_primitive);
1497
1498 outVertices.resize(6);
1499 outColors.resize(6);
1500
1501 for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx)
1502 {
1503 outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
1504 outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
1505 outVertices[vtxNdx].z() = 0.0f;
1506
1507 if (!m_projective)
1508 outVertices[vtxNdx].w() = 1.0f;
1509 else
1510 {
1511 const float w = rnd.getFloat(0.2f, 4.0f);
1512
1513 outVertices[vtxNdx].x() *= w;
1514 outVertices[vtxNdx].y() *= w;
1515 outVertices[vtxNdx].z() *= w;
1516 outVertices[vtxNdx].w() = w;
1517 }
1518
1519 outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)];
1520 }
1521 }
1522
extractTriangles(std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles,const std::vector<tcu::Vec4> & vertices,const std::vector<tcu::Vec4> & colors) const1523 void TriangleInterpolationTest::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
1524 {
1525 switch (m_primitive)
1526 {
1527 case GL_TRIANGLES:
1528 {
1529 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
1530 {
1531 TriangleSceneSpec::SceneTriangle tri;
1532 tri.positions[0] = vertices[vtxNdx + 0];
1533 tri.positions[1] = vertices[vtxNdx + 1];
1534 tri.positions[2] = vertices[vtxNdx + 2];
1535 tri.sharedEdge[0] = false;
1536 tri.sharedEdge[1] = false;
1537 tri.sharedEdge[2] = false;
1538
1539 tri.colors[0] = colors[vtxNdx + 0];
1540 tri.colors[1] = colors[vtxNdx + 1];
1541 tri.colors[2] = colors[vtxNdx + 2];
1542
1543 outTriangles.push_back(tri);
1544 }
1545 break;
1546 }
1547
1548 case GL_TRIANGLE_STRIP:
1549 {
1550 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
1551 {
1552 TriangleSceneSpec::SceneTriangle tri;
1553 tri.positions[0] = vertices[vtxNdx + 0];
1554 tri.positions[1] = vertices[vtxNdx + 1];
1555 tri.positions[2] = vertices[vtxNdx + 2];
1556 tri.sharedEdge[0] = false;
1557 tri.sharedEdge[1] = false;
1558 tri.sharedEdge[2] = false;
1559
1560 tri.colors[0] = colors[vtxNdx + 0];
1561 tri.colors[1] = colors[vtxNdx + 1];
1562 tri.colors[2] = colors[vtxNdx + 2];
1563
1564 outTriangles.push_back(tri);
1565 }
1566 break;
1567 }
1568
1569 case GL_TRIANGLE_FAN:
1570 {
1571 for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
1572 {
1573 TriangleSceneSpec::SceneTriangle tri;
1574 tri.positions[0] = vertices[0];
1575 tri.positions[1] = vertices[vtxNdx + 0];
1576 tri.positions[2] = vertices[vtxNdx + 1];
1577 tri.sharedEdge[0] = false;
1578 tri.sharedEdge[1] = false;
1579 tri.sharedEdge[2] = false;
1580
1581 tri.colors[0] = colors[0];
1582 tri.colors[1] = colors[vtxNdx + 0];
1583 tri.colors[2] = colors[vtxNdx + 1];
1584
1585 outTriangles.push_back(tri);
1586 }
1587 break;
1588 }
1589
1590 default:
1591 DE_ASSERT(false);
1592 }
1593 }
1594
1595 class LineInterpolationTest : public BaseRenderingCase
1596 {
1597 public:
1598 LineInterpolationTest (Context& ctx, const char* name, const char* desc, glw::GLenum primitive, int flags, float lineWidth);
1599 ~LineInterpolationTest (void);
1600 IterateResult iterate (void);
1601
1602 private:
1603 void generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const;
1604 void extractLines (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
1605
1606 const glw::GLenum m_primitive;
1607 const bool m_projective;
1608 const int m_iterationCount;
1609
1610 int m_iteration;
1611 tcu::ResultCollector m_result;
1612 };
1613
LineInterpolationTest(Context & ctx,const char * name,const char * desc,glw::GLenum primitive,int flags,float lineWidth)1614 LineInterpolationTest::LineInterpolationTest (Context& ctx, const char* name, const char* desc, glw::GLenum primitive, int flags, float lineWidth)
1615 : BaseRenderingCase (ctx, name, desc)
1616 , m_primitive (primitive)
1617 , m_projective ((flags & INTERPOLATIONFLAGS_PROJECTED) != 0)
1618 , m_iterationCount (3)
1619 , m_iteration (0)
1620 {
1621 m_lineWidth = lineWidth;
1622 }
1623
~LineInterpolationTest(void)1624 LineInterpolationTest::~LineInterpolationTest (void)
1625 {
1626 deinit();
1627 }
1628
iterate(void)1629 LineInterpolationTest::IterateResult LineInterpolationTest::iterate (void)
1630 {
1631 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
1632 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription);
1633 tcu::Surface resultImage (m_renderSize, m_renderSize);
1634 std::vector<tcu::Vec4> drawBuffer;
1635 std::vector<tcu::Vec4> colorBuffer;
1636 std::vector<LineSceneSpec::SceneLine> lines;
1637
1638 // generate scene
1639 generateVertices(m_iteration, drawBuffer, colorBuffer);
1640 extractLines(lines, drawBuffer, colorBuffer);
1641
1642 // log
1643 {
1644 m_testCtx.getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage;
1645 for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx)
1646 m_testCtx.getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage;
1647 }
1648
1649 // draw image
1650 drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitive);
1651
1652 // compare
1653 {
1654 RasterizationArguments args;
1655 LineSceneSpec scene;
1656 LineInterpolationMethod iterationResult;
1657
1658 args.numSamples = m_numSamples;
1659 args.subpixelBits = m_subpixelBits;
1660 args.redBits = m_context.getRenderTarget().getPixelFormat().redBits;
1661 args.greenBits = m_context.getRenderTarget().getPixelFormat().greenBits;
1662 args.blueBits = m_context.getRenderTarget().getPixelFormat().blueBits;
1663
1664 scene.lines.swap(lines);
1665 scene.lineWidth = m_lineWidth;
1666
1667 iterationResult = verifyLineGroupInterpolation(resultImage, scene, args, m_testCtx.getLog());
1668 switch (iterationResult)
1669 {
1670 case LINEINTERPOLATION_STRICTLY_CORRECT:
1671 // line interpolation matches the specification
1672 m_result.addResult(QP_TEST_RESULT_PASS, "Pass");
1673 break;
1674
1675 case LINEINTERPOLATION_PROJECTED:
1676 // line interpolation weights are otherwise correct, but they are projected onto major axis
1677 m_testCtx.getLog() << tcu::TestLog::Message
1678 << "Interpolation was calculated using coordinates projected onto major axis. "
1679 "This method does not produce the same values as the non-projecting method defined in the specification."
1680 << tcu::TestLog::EndMessage;
1681 m_result.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Interpolation was calculated using projected coordinateds");
1682 break;
1683
1684 case LINEINTERPOLATION_INCORRECT:
1685 if (scene.lineWidth != 1.0f && m_numSamples > 1)
1686 {
1687 // multisampled wide lines might not be supported
1688 m_result.addResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Interpolation of multisampled wide lines failed");
1689 }
1690 else
1691 {
1692 // line interpolation is incorrect
1693 m_result.addResult(QP_TEST_RESULT_FAIL, "Found invalid pixel values");
1694 }
1695 break;
1696
1697 default:
1698 DE_ASSERT(false);
1699 break;
1700 }
1701 }
1702
1703 // result
1704 if (++m_iteration == m_iterationCount)
1705 {
1706 m_result.setTestContextResult(m_testCtx);
1707 return STOP;
1708 }
1709 else
1710 return CONTINUE;
1711 }
1712
generateVertices(int iteration,std::vector<tcu::Vec4> & outVertices,std::vector<tcu::Vec4> & outColors) const1713 void LineInterpolationTest::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const
1714 {
1715 // use only red, green and blue
1716 const tcu::Vec4 colors[] =
1717 {
1718 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
1719 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
1720 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
1721 };
1722
1723 de::Random rnd(123 + iteration * 1000 + (int)m_primitive);
1724
1725 outVertices.resize(6);
1726 outColors.resize(6);
1727
1728 for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx)
1729 {
1730 outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
1731 outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
1732 outVertices[vtxNdx].z() = 0.0f;
1733
1734 if (!m_projective)
1735 outVertices[vtxNdx].w() = 1.0f;
1736 else
1737 {
1738 const float w = rnd.getFloat(0.2f, 4.0f);
1739
1740 outVertices[vtxNdx].x() *= w;
1741 outVertices[vtxNdx].y() *= w;
1742 outVertices[vtxNdx].z() *= w;
1743 outVertices[vtxNdx].w() = w;
1744 }
1745
1746 outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)];
1747 }
1748 }
1749
extractLines(std::vector<LineSceneSpec::SceneLine> & outLines,const std::vector<tcu::Vec4> & vertices,const std::vector<tcu::Vec4> & colors) const1750 void LineInterpolationTest::extractLines (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
1751 {
1752 switch (m_primitive)
1753 {
1754 case GL_LINES:
1755 {
1756 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; vtxNdx += 2)
1757 {
1758 LineSceneSpec::SceneLine line;
1759 line.positions[0] = vertices[vtxNdx + 0];
1760 line.positions[1] = vertices[vtxNdx + 1];
1761
1762 line.colors[0] = colors[vtxNdx + 0];
1763 line.colors[1] = colors[vtxNdx + 1];
1764
1765 outLines.push_back(line);
1766 }
1767 break;
1768 }
1769
1770 case GL_LINE_STRIP:
1771 {
1772 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
1773 {
1774 LineSceneSpec::SceneLine line;
1775 line.positions[0] = vertices[vtxNdx + 0];
1776 line.positions[1] = vertices[vtxNdx + 1];
1777
1778 line.colors[0] = colors[vtxNdx + 0];
1779 line.colors[1] = colors[vtxNdx + 1];
1780
1781 outLines.push_back(line);
1782 }
1783 break;
1784 }
1785
1786 case GL_LINE_LOOP:
1787 {
1788 for (int vtxNdx = 0; vtxNdx < (int)vertices.size(); ++vtxNdx)
1789 {
1790 LineSceneSpec::SceneLine line;
1791 line.positions[0] = vertices[(vtxNdx + 0) % (int)vertices.size()];
1792 line.positions[1] = vertices[(vtxNdx + 1) % (int)vertices.size()];
1793
1794 line.colors[0] = colors[(vtxNdx + 0) % (int)vertices.size()];
1795 line.colors[1] = colors[(vtxNdx + 1) % (int)vertices.size()];
1796
1797 outLines.push_back(line);
1798 }
1799 break;
1800 }
1801
1802 default:
1803 DE_ASSERT(false);
1804 }
1805 }
1806
1807 } // anonymous
1808
RasterizationTests(Context & context)1809 RasterizationTests::RasterizationTests (Context& context)
1810 : TestCaseGroup(context, "rasterization", "Rasterization Tests")
1811 {
1812 }
1813
~RasterizationTests(void)1814 RasterizationTests::~RasterizationTests (void)
1815 {
1816 }
1817
init(void)1818 void RasterizationTests::init (void)
1819 {
1820 // .primitives
1821 {
1822 tcu::TestCaseGroup* const primitives = new tcu::TestCaseGroup(m_testCtx, "primitives", "Primitive rasterization");
1823
1824 addChild(primitives);
1825
1826 primitives->addChild(new TrianglesCase (m_context, "triangles", "Render primitives as GL_TRIANGLES, verify rasterization result"));
1827 primitives->addChild(new TriangleStripCase (m_context, "triangle_strip", "Render primitives as GL_TRIANGLE_STRIP, verify rasterization result"));
1828 primitives->addChild(new TriangleFanCase (m_context, "triangle_fan", "Render primitives as GL_TRIANGLE_FAN, verify rasterization result"));
1829 primitives->addChild(new LinesCase (m_context, "lines", "Render primitives as GL_LINES, verify rasterization result", PRIMITIVEWIDENESS_NARROW));
1830 primitives->addChild(new LineStripCase (m_context, "line_strip", "Render primitives as GL_LINE_STRIP, verify rasterization result", PRIMITIVEWIDENESS_NARROW));
1831 primitives->addChild(new LineLoopCase (m_context, "line_loop", "Render primitives as GL_LINE_LOOP, verify rasterization result", PRIMITIVEWIDENESS_NARROW));
1832 primitives->addChild(new LinesCase (m_context, "lines_wide", "Render primitives as GL_LINES with wide lines, verify rasterization result", PRIMITIVEWIDENESS_WIDE));
1833 primitives->addChild(new LineStripCase (m_context, "line_strip_wide", "Render primitives as GL_LINE_STRIP with wide lines, verify rasterization result", PRIMITIVEWIDENESS_WIDE));
1834 primitives->addChild(new LineLoopCase (m_context, "line_loop_wide", "Render primitives as GL_LINE_LOOP with wide lines, verify rasterization result", PRIMITIVEWIDENESS_WIDE));
1835 primitives->addChild(new PointCase (m_context, "points", "Render primitives as GL_POINTS, verify rasterization result", PRIMITIVEWIDENESS_WIDE));
1836 }
1837
1838 // .fill_rules
1839 {
1840 tcu::TestCaseGroup* const fillRules = new tcu::TestCaseGroup(m_testCtx, "fill_rules", "Primitive fill rules");
1841
1842 addChild(fillRules);
1843
1844 fillRules->addChild(new FillRuleCase(m_context, "basic_quad", "Verify fill rules", FillRuleCase::FILLRULECASE_BASIC));
1845 fillRules->addChild(new FillRuleCase(m_context, "basic_quad_reverse", "Verify fill rules", FillRuleCase::FILLRULECASE_REVERSED));
1846 fillRules->addChild(new FillRuleCase(m_context, "clipped_full", "Verify fill rules", FillRuleCase::FILLRULECASE_CLIPPED_FULL));
1847 fillRules->addChild(new FillRuleCase(m_context, "clipped_partly", "Verify fill rules", FillRuleCase::FILLRULECASE_CLIPPED_PARTIAL));
1848 fillRules->addChild(new FillRuleCase(m_context, "projected", "Verify fill rules", FillRuleCase::FILLRULECASE_PROJECTED));
1849 }
1850
1851 // .culling
1852 {
1853 static const struct CullMode
1854 {
1855 glw::GLenum mode;
1856 const char* prefix;
1857 } cullModes[] =
1858 {
1859 { GL_FRONT, "front_" },
1860 { GL_BACK, "back_" },
1861 { GL_FRONT_AND_BACK, "both_" },
1862 };
1863 static const struct PrimitiveType
1864 {
1865 glw::GLenum type;
1866 const char* name;
1867 } primitiveTypes[] =
1868 {
1869 { GL_TRIANGLES, "triangles" },
1870 { GL_TRIANGLE_STRIP, "triangle_strip" },
1871 { GL_TRIANGLE_FAN, "triangle_fan" },
1872 };
1873 static const struct FrontFaceOrder
1874 {
1875 glw::GLenum mode;
1876 const char* postfix;
1877 } frontOrders[] =
1878 {
1879 { GL_CCW, "" },
1880 { GL_CW, "_reverse" },
1881 };
1882
1883 tcu::TestCaseGroup* const culling = new tcu::TestCaseGroup(m_testCtx, "culling", "Culling");
1884
1885 addChild(culling);
1886
1887 for (int cullModeNdx = 0; cullModeNdx < DE_LENGTH_OF_ARRAY(cullModes); ++cullModeNdx)
1888 for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); ++primitiveNdx)
1889 for (int frontOrderNdx = 0; frontOrderNdx < DE_LENGTH_OF_ARRAY(frontOrders); ++frontOrderNdx)
1890 {
1891 const std::string name = std::string(cullModes[cullModeNdx].prefix) + primitiveTypes[primitiveNdx].name + frontOrders[frontOrderNdx].postfix;
1892
1893 culling->addChild(new CullingTest(m_context, name.c_str(), "Test primitive culling.", cullModes[cullModeNdx].mode, primitiveTypes[primitiveNdx].type, frontOrders[frontOrderNdx].mode));
1894 }
1895 }
1896
1897 // .interpolation
1898 {
1899 tcu::TestCaseGroup* const interpolation = new tcu::TestCaseGroup(m_testCtx, "interpolation", "Test interpolation");
1900
1901 addChild(interpolation);
1902
1903 // .basic
1904 {
1905 tcu::TestCaseGroup* const basic = new tcu::TestCaseGroup(m_testCtx, "basic", "Non-projective interpolation");
1906
1907 interpolation->addChild(basic);
1908
1909 basic->addChild(new TriangleInterpolationTest (m_context, "triangles", "Verify triangle interpolation", GL_TRIANGLES, INTERPOLATIONFLAGS_NONE));
1910 basic->addChild(new TriangleInterpolationTest (m_context, "triangle_strip", "Verify triangle strip interpolation", GL_TRIANGLE_STRIP, INTERPOLATIONFLAGS_NONE));
1911 basic->addChild(new TriangleInterpolationTest (m_context, "triangle_fan", "Verify triangle fan interpolation", GL_TRIANGLE_FAN, INTERPOLATIONFLAGS_NONE));
1912 basic->addChild(new LineInterpolationTest (m_context, "lines", "Verify line interpolation", GL_LINES, INTERPOLATIONFLAGS_NONE, 1.0f));
1913 basic->addChild(new LineInterpolationTest (m_context, "line_strip", "Verify line strip interpolation", GL_LINE_STRIP, INTERPOLATIONFLAGS_NONE, 1.0f));
1914 basic->addChild(new LineInterpolationTest (m_context, "line_loop", "Verify line loop interpolation", GL_LINE_LOOP, INTERPOLATIONFLAGS_NONE, 1.0f));
1915 basic->addChild(new LineInterpolationTest (m_context, "lines_wide", "Verify wide line interpolation", GL_LINES, INTERPOLATIONFLAGS_NONE, 5.0f));
1916 basic->addChild(new LineInterpolationTest (m_context, "line_strip_wide", "Verify wide line strip interpolation", GL_LINE_STRIP, INTERPOLATIONFLAGS_NONE, 5.0f));
1917 basic->addChild(new LineInterpolationTest (m_context, "line_loop_wide", "Verify wide line loop interpolation", GL_LINE_LOOP, INTERPOLATIONFLAGS_NONE, 5.0f));
1918 }
1919
1920 // .projected
1921 {
1922 tcu::TestCaseGroup* const projected = new tcu::TestCaseGroup(m_testCtx, "projected", "Projective interpolation");
1923
1924 interpolation->addChild(projected);
1925
1926 projected->addChild(new TriangleInterpolationTest (m_context, "triangles", "Verify triangle interpolation", GL_TRIANGLES, INTERPOLATIONFLAGS_PROJECTED));
1927 projected->addChild(new TriangleInterpolationTest (m_context, "triangle_strip", "Verify triangle strip interpolation", GL_TRIANGLE_STRIP, INTERPOLATIONFLAGS_PROJECTED));
1928 projected->addChild(new TriangleInterpolationTest (m_context, "triangle_fan", "Verify triangle fan interpolation", GL_TRIANGLE_FAN, INTERPOLATIONFLAGS_PROJECTED));
1929 projected->addChild(new LineInterpolationTest (m_context, "lines", "Verify line interpolation", GL_LINES, INTERPOLATIONFLAGS_PROJECTED, 1.0f));
1930 projected->addChild(new LineInterpolationTest (m_context, "line_strip", "Verify line strip interpolation", GL_LINE_STRIP, INTERPOLATIONFLAGS_PROJECTED, 1.0f));
1931 projected->addChild(new LineInterpolationTest (m_context, "line_loop", "Verify line loop interpolation", GL_LINE_LOOP, INTERPOLATIONFLAGS_PROJECTED, 1.0f));
1932 projected->addChild(new LineInterpolationTest (m_context, "lines_wide", "Verify wide line interpolation", GL_LINES, INTERPOLATIONFLAGS_PROJECTED, 5.0f));
1933 projected->addChild(new LineInterpolationTest (m_context, "line_strip_wide", "Verify wide line strip interpolation", GL_LINE_STRIP, INTERPOLATIONFLAGS_PROJECTED, 5.0f));
1934 projected->addChild(new LineInterpolationTest (m_context, "line_loop_wide", "Verify wide line loop interpolation", GL_LINE_LOOP, INTERPOLATIONFLAGS_PROJECTED, 5.0f));
1935 }
1936 }
1937 }
1938
1939 } // Functional
1940 } // gles2
1941 } // deqp
1942