1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 2.0 Module
3 * -------------------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Functional rasterization tests.
22 *//*--------------------------------------------------------------------*/
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"
51 using namespace gls::RasterizationTestUtil;
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"
59 " gl_Position = a_position;\n"
60 " gl_PointSize = u_pointSize;\n"
61 " v_color = a_color;\n"
63 static const char* const s_shaderFragmentTemplate = "varying mediump vec4 v_color;\n"
66 " gl_FragColor = v_color;\n"
68 enum InterpolationCaseFlags
70 INTERPOLATIONFLAGS_NONE = 0,
71 INTERPOLATIONFLAGS_PROJECTED = (1 << 1),
74 enum PrimitiveWideness
76 PRIMITIVEWIDENESS_NARROW = 0,
77 PRIMITIVEWIDENESS_WIDE,
79 PRIMITIVEWIDENESS_LAST
82 class BaseRenderingCase : public TestCase
85 BaseRenderingCase (Context& context, const char* name, const char* desc, int renderSize = 256);
86 ~BaseRenderingCase (void);
87 virtual void init (void);
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);
94 const int m_renderSize;
101 glu::ShaderProgram* m_shader;
104 BaseRenderingCase::BaseRenderingCase (Context& context, const char* name, const char* desc, int renderSize)
105 : TestCase (context, name, desc)
106 , m_renderSize (renderSize)
108 , m_subpixelBits (-1)
115 BaseRenderingCase::~BaseRenderingCase (void)
120 void BaseRenderingCase::init (void)
122 const int width = m_context.getRenderTarget().getWidth();
123 const int height = m_context.getRenderTarget().getHeight();
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));
130 if (m_lineWidth != 1.0f)
132 float range[2] = { 0.0f, 0.0f };
133 m_context.getRenderContext().getFunctions().getFloatv(GL_ALIASED_LINE_WIDTH_RANGE, range);
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.");
138 m_testCtx.getLog() << tcu::TestLog::Message << "ALIASED_LINE_WIDTH_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
141 if (m_pointSize != 1.0f)
143 float range[2] = { 0.0f, 0.0f };
144 m_context.getRenderContext().getFunctions().getFloatv(GL_ALIASED_POINT_SIZE_RANGE, range);
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.");
149 m_testCtx.getLog() << tcu::TestLog::Message << "ALIASED_POINT_SIZE_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
154 m_numSamples = m_context.getRenderTarget().getNumSamples();
155 m_context.getRenderContext().getFunctions().getIntegerv(GL_SUBPIXEL_BITS, &m_subpixelBits);
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;
163 tcu::StringTemplate vertexSource (s_shaderVertexTemplate);
164 tcu::StringTemplate fragmentSource (s_shaderFragmentTemplate);
165 std::map<std::string, std::string> params;
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");
173 void BaseRenderingCase::deinit (void)
182 void BaseRenderingCase::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, glw::GLenum primitiveType)
184 // default to color white
185 const std::vector<tcu::Vec4> colorData(vertexData.size(), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
187 drawPrimitives(result, vertexData, colorData, primitiveType);
190 void BaseRenderingCase::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, const std::vector<tcu::Vec4>& colorData, glw::GLenum primitiveType)
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");
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);
212 GLU_EXPECT_NO_ERROR (gl.getError(), "draw primitives");
214 glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
217 class BaseTriangleCase : public BaseRenderingCase
220 BaseTriangleCase (Context& context, const char* name, const char* desc, glw::GLenum primitiveDrawType);
221 ~BaseTriangleCase (void);
222 IterateResult iterate (void);
225 virtual void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles) = DE_NULL;
228 const int m_iterationCount;
229 const glw::GLenum m_primitiveDrawType;
230 bool m_allIterationsPassed;
233 BaseTriangleCase::BaseTriangleCase (Context& context, const char* name, const char* desc, glw::GLenum primitiveDrawType)
234 : BaseRenderingCase (context, name, desc)
236 , m_iterationCount (3)
237 , m_primitiveDrawType (primitiveDrawType)
238 , m_allIterationsPassed (true)
242 BaseTriangleCase::~BaseTriangleCase (void)
246 BaseTriangleCase::IterateResult BaseTriangleCase::iterate (void)
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;
254 generateTriangles(m_iteration, drawBuffer, triangles);
257 drawPrimitives(resultImage, drawBuffer, m_primitiveDrawType);
262 RasterizationArguments args;
263 TriangleSceneSpec scene;
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;
271 scene.triangles.swap(triangles);
273 compareOk = verifyTriangleGroupRasterization(resultImage, scene, args, m_testCtx.getLog());
276 m_allIterationsPassed = false;
280 if (++m_iteration == m_iterationCount)
282 if (m_allIterationsPassed)
283 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
285 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rasterization");
293 class BaseLineCase : public BaseRenderingCase
296 BaseLineCase (Context& context, const char* name, const char* desc, glw::GLenum primitiveDrawType, PrimitiveWideness wideness);
297 ~BaseLineCase (void);
298 IterateResult iterate (void);
301 virtual void generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines) = DE_NULL;
304 const int m_iterationCount;
305 const glw::GLenum m_primitiveDrawType;
306 const PrimitiveWideness m_primitiveWideness;
307 bool m_allIterationsPassed;
309 static const float s_wideSize;
312 const float BaseLineCase::s_wideSize = 5.0f;
314 BaseLineCase::BaseLineCase (Context& context, const char* name, const char* desc, glw::GLenum primitiveDrawType, PrimitiveWideness wideness)
315 : BaseRenderingCase (context, name, desc)
317 , m_iterationCount (3)
318 , m_primitiveDrawType (primitiveDrawType)
319 , m_primitiveWideness (wideness)
320 , m_allIterationsPassed (true)
322 DE_ASSERT(m_primitiveWideness < PRIMITIVEWIDENESS_LAST);
323 m_lineWidth = (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE) ? (s_wideSize) : (1.0f);
326 BaseLineCase::~BaseLineCase (void)
330 BaseLineCase::IterateResult BaseLineCase::iterate (void)
332 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
333 const tcu::ScopedLogSection section (m_testCtx.getLog(), iterationDescription, iterationDescription);
334 tcu::Surface resultImage (m_renderSize, m_renderSize);
335 std::vector<tcu::Vec4> drawBuffer;
336 std::vector<LineSceneSpec::SceneLine> lines;
338 // last iteration, max out size
339 if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE &&
340 m_iteration+1 == m_iterationCount)
342 float range[2] = { 0.0f, 0.0f };
343 m_context.getRenderContext().getFunctions().getFloatv(GL_ALIASED_LINE_WIDTH_RANGE, range);
345 m_lineWidth = range[1];
349 generateLines(m_iteration, drawBuffer, lines);
352 drawPrimitives(resultImage, drawBuffer, m_primitiveDrawType);
357 RasterizationArguments args;
360 args.numSamples = m_numSamples;
361 args.subpixelBits = m_subpixelBits;
362 args.redBits = m_context.getRenderTarget().getPixelFormat().redBits;
363 args.greenBits = m_context.getRenderTarget().getPixelFormat().greenBits;
364 args.blueBits = m_context.getRenderTarget().getPixelFormat().blueBits;
366 scene.lines.swap(lines);
367 scene.lineWidth = m_lineWidth;
369 compareOk = verifyLineGroupRasterization(resultImage, scene, args, m_testCtx.getLog());
372 m_allIterationsPassed = false;
376 if (++m_iteration == m_iterationCount)
378 if (m_allIterationsPassed)
379 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
381 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rasterization");
389 class PointCase : public BaseRenderingCase
392 PointCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness);
394 IterateResult iterate (void);
397 void generatePoints (int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints);
400 const int m_iterationCount;
401 const PrimitiveWideness m_primitiveWideness;
402 bool m_allIterationsPassed;
404 static const float s_wideSize;
407 const float PointCase::s_wideSize = 10.0f;
409 PointCase::PointCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness)
410 : BaseRenderingCase (context, name, desc)
412 , m_iterationCount (3)
413 , m_primitiveWideness (wideness)
414 , m_allIterationsPassed (true)
416 m_pointSize = (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE) ? (s_wideSize) : (1.0f);
419 PointCase::~PointCase (void)
423 PointCase::IterateResult PointCase::iterate (void)
425 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
426 const tcu::ScopedLogSection section (m_testCtx.getLog(), iterationDescription, iterationDescription);
427 tcu::Surface resultImage (m_renderSize, m_renderSize);
428 std::vector<tcu::Vec4> drawBuffer;
429 std::vector<PointSceneSpec::ScenePoint> points;
431 // last iteration, max out size
432 if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE &&
433 m_iteration+1 == m_iterationCount)
435 float range[2] = { 0.0f, 0.0f };
436 m_context.getRenderContext().getFunctions().getFloatv(GL_ALIASED_POINT_SIZE_RANGE, range);
438 m_pointSize = range[1];
442 generatePoints(m_iteration, drawBuffer, points);
445 drawPrimitives(resultImage, drawBuffer, GL_POINTS);
450 RasterizationArguments args;
451 PointSceneSpec scene;
453 args.numSamples = m_numSamples;
454 args.subpixelBits = m_subpixelBits;
455 args.redBits = m_context.getRenderTarget().getPixelFormat().redBits;
456 args.greenBits = m_context.getRenderTarget().getPixelFormat().greenBits;
457 args.blueBits = m_context.getRenderTarget().getPixelFormat().blueBits;
459 scene.points.swap(points);
461 compareOk = verifyPointGroupRasterization(resultImage, scene, args, m_testCtx.getLog());
464 m_allIterationsPassed = false;
468 if (++m_iteration == m_iterationCount)
470 if (m_allIterationsPassed)
471 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
473 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rasterization");
481 void PointCase::generatePoints (int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints)
488 // \note: these values are chosen arbitrarily
489 outData[0] = tcu::Vec4( 0.2f, 0.8f, 0.0f, 1.0f);
490 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f);
491 outData[2] = tcu::Vec4( 0.5f, 0.3f, 0.0f, 1.0f);
492 outData[3] = tcu::Vec4(-0.5f, 0.2f, 0.0f, 1.0f);
493 outData[4] = tcu::Vec4(-0.2f, -0.4f, 0.0f, 1.0f);
494 outData[5] = tcu::Vec4(-0.4f, 0.2f, 0.0f, 1.0f);
498 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
499 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f);
500 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f);
501 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
502 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f);
503 outData[5] = tcu::Vec4( 0.4f, 1.2f, 0.0f, 1.0f);
507 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
508 outData[1] = tcu::Vec4( 0.3f, -0.9f, 0.0f, 1.0f);
509 outData[2] = tcu::Vec4( -0.4f, -0.1f, 0.0f, 1.0f);
510 outData[3] = tcu::Vec4(-0.11f, 0.2f, 0.0f, 1.0f);
511 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f);
512 outData[5] = tcu::Vec4( -0.4f, 0.4f, 0.0f, 1.0f);
516 outPoints.resize(outData.size());
517 for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
519 outPoints[pointNdx].position = outData[pointNdx];
520 outPoints[pointNdx].pointSize = m_pointSize;
524 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering " << outPoints.size() << " point(s): (point size = " << m_pointSize << ")" << tcu::TestLog::EndMessage;
525 for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
526 m_testCtx.getLog() << tcu::TestLog::Message << "Point " << (pointNdx+1) << ":\t" << outPoints[pointNdx].position << tcu::TestLog::EndMessage;
529 class TrianglesCase : public BaseTriangleCase
532 TrianglesCase (Context& context, const char* name, const char* desc);
533 ~TrianglesCase (void);
535 void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
538 TrianglesCase::TrianglesCase (Context& context, const char* name, const char* desc)
539 : BaseTriangleCase(context, name, desc, GL_TRIANGLES)
543 TrianglesCase::~TrianglesCase (void)
548 void TrianglesCase::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
555 // \note: these values are chosen arbitrarily
556 outData[0] = tcu::Vec4( 0.2f, 0.8f, 0.0f, 1.0f);
557 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f);
558 outData[2] = tcu::Vec4( 0.5f, 0.3f, 0.0f, 1.0f);
559 outData[3] = tcu::Vec4(-0.5f, 0.2f, 0.0f, 1.0f);
560 outData[4] = tcu::Vec4(-1.5f, -0.4f, 0.0f, 1.0f);
561 outData[5] = tcu::Vec4(-0.4f, 0.2f, 0.0f, 1.0f);
565 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
566 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f);
567 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f);
568 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
569 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f);
570 outData[5] = tcu::Vec4( 0.4f, 1.2f, 0.0f, 1.0f);
574 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
575 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f);
576 outData[2] = tcu::Vec4( -1.1f, -0.1f, 0.0f, 1.0f);
577 outData[3] = tcu::Vec4(-0.11f, 0.2f, 0.0f, 1.0f);
578 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f);
579 outData[5] = tcu::Vec4( -0.4f, 0.4f, 0.0f, 1.0f);
583 outTriangles.resize(2);
584 outTriangles[0].positions[0] = outData[0]; outTriangles[0].sharedEdge[0] = false;
585 outTriangles[0].positions[1] = outData[1]; outTriangles[0].sharedEdge[1] = false;
586 outTriangles[0].positions[2] = outData[2]; outTriangles[0].sharedEdge[2] = false;
588 outTriangles[1].positions[0] = outData[3]; outTriangles[1].sharedEdge[0] = false;
589 outTriangles[1].positions[1] = outData[4]; outTriangles[1].sharedEdge[1] = false;
590 outTriangles[1].positions[2] = outData[5]; outTriangles[1].sharedEdge[2] = false;
593 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering " << outTriangles.size() << " triangle(s):" << tcu::TestLog::EndMessage;
594 for (int triangleNdx = 0; triangleNdx < (int)outTriangles.size(); ++triangleNdx)
597 << tcu::TestLog::Message
598 << "Triangle " << (triangleNdx+1) << ":"
599 << "\n\t" << outTriangles[triangleNdx].positions[0]
600 << "\n\t" << outTriangles[triangleNdx].positions[1]
601 << "\n\t" << outTriangles[triangleNdx].positions[2]
602 << tcu::TestLog::EndMessage;
606 class TriangleStripCase : public BaseTriangleCase
609 TriangleStripCase (Context& context, const char* name, const char* desc);
611 void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
614 TriangleStripCase::TriangleStripCase (Context& context, const char* name, const char* desc)
615 : BaseTriangleCase(context, name, desc, GL_TRIANGLE_STRIP)
619 void TriangleStripCase::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
626 // \note: these values are chosen arbitrarily
627 outData[0] = tcu::Vec4(-0.504f, 0.8f, 0.0f, 1.0f);
628 outData[1] = tcu::Vec4(-0.2f, -0.2f, 0.0f, 1.0f);
629 outData[2] = tcu::Vec4(-0.2f, 0.199f, 0.0f, 1.0f);
630 outData[3] = tcu::Vec4( 0.5f, 0.201f, 0.0f, 1.0f);
631 outData[4] = tcu::Vec4( 1.5f, 0.4f, 0.0f, 1.0f);
635 outData[0] = tcu::Vec4(-0.499f, 0.129f, 0.0f, 1.0f);
636 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f);
637 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f);
638 outData[3] = tcu::Vec4( 0.11f, -0.31f, 0.0f, 1.0f);
639 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f);
643 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
644 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f);
645 outData[2] = tcu::Vec4(-0.87f, -0.1f, 0.0f, 1.0f);
646 outData[3] = tcu::Vec4(-0.11f, 0.19f, 0.0f, 1.0f);
647 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f);
651 outTriangles.resize(3);
652 outTriangles[0].positions[0] = outData[0]; outTriangles[0].sharedEdge[0] = false;
653 outTriangles[0].positions[1] = outData[1]; outTriangles[0].sharedEdge[1] = true;
654 outTriangles[0].positions[2] = outData[2]; outTriangles[0].sharedEdge[2] = false;
656 outTriangles[1].positions[0] = outData[2]; outTriangles[1].sharedEdge[0] = true;
657 outTriangles[1].positions[1] = outData[1]; outTriangles[1].sharedEdge[1] = false;
658 outTriangles[1].positions[2] = outData[3]; outTriangles[1].sharedEdge[2] = true;
660 outTriangles[2].positions[0] = outData[2]; outTriangles[2].sharedEdge[0] = true;
661 outTriangles[2].positions[1] = outData[3]; outTriangles[2].sharedEdge[1] = false;
662 outTriangles[2].positions[2] = outData[4]; outTriangles[2].sharedEdge[2] = false;
665 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering triangle strip, " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
666 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
669 << tcu::TestLog::Message
670 << "\t" << outData[vtxNdx]
671 << tcu::TestLog::EndMessage;
675 class TriangleFanCase : public BaseTriangleCase
678 TriangleFanCase (Context& context, const char* name, const char* desc);
680 void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
683 TriangleFanCase::TriangleFanCase (Context& context, const char* name, const char* desc)
684 : BaseTriangleCase(context, name, desc, GL_TRIANGLE_FAN)
688 void TriangleFanCase::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
695 // \note: these values are chosen arbitrarily
696 outData[0] = tcu::Vec4( 0.01f, 0.0f, 0.0f, 1.0f);
697 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f);
698 outData[2] = tcu::Vec4( 0.46f, 0.3f, 0.0f, 1.0f);
699 outData[3] = tcu::Vec4(-0.5f, 0.2f, 0.0f, 1.0f);
700 outData[4] = tcu::Vec4(-1.5f, -0.4f, 0.0f, 1.0f);
704 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
705 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f);
706 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f);
707 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
708 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f);
712 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
713 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f);
714 outData[2] = tcu::Vec4( 0.7f, -0.1f, 0.0f, 1.0f);
715 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
716 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f);
720 outTriangles.resize(3);
721 outTriangles[0].positions[0] = outData[0]; outTriangles[0].sharedEdge[0] = false;
722 outTriangles[0].positions[1] = outData[1]; outTriangles[0].sharedEdge[1] = false;
723 outTriangles[0].positions[2] = outData[2]; outTriangles[0].sharedEdge[2] = true;
725 outTriangles[1].positions[0] = outData[0]; outTriangles[1].sharedEdge[0] = true;
726 outTriangles[1].positions[1] = outData[2]; outTriangles[1].sharedEdge[1] = false;
727 outTriangles[1].positions[2] = outData[3]; outTriangles[1].sharedEdge[2] = true;
729 outTriangles[2].positions[0] = outData[0]; outTriangles[2].sharedEdge[0] = true;
730 outTriangles[2].positions[1] = outData[3]; outTriangles[2].sharedEdge[1] = false;
731 outTriangles[2].positions[2] = outData[4]; outTriangles[2].sharedEdge[2] = false;
734 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering triangle fan, " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
735 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
738 << tcu::TestLog::Message
739 << "\t" << outData[vtxNdx]
740 << tcu::TestLog::EndMessage;
744 class LinesCase : public BaseLineCase
747 LinesCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness);
749 void generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
752 LinesCase::LinesCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness)
753 : BaseLineCase(context, name, desc, GL_LINES, wideness)
757 void LinesCase::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
764 // \note: these values are chosen arbitrarily
765 outData[0] = tcu::Vec4( 0.01f, 0.0f, 0.0f, 1.0f);
766 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f);
767 outData[2] = tcu::Vec4( 0.46f, 0.3f, 0.0f, 1.0f);
768 outData[3] = tcu::Vec4(-0.3f, 0.2f, 0.0f, 1.0f);
769 outData[4] = tcu::Vec4(-1.5f, -0.4f, 0.0f, 1.0f);
770 outData[5] = tcu::Vec4( 0.1f, 0.5f, 0.0f, 1.0f);
774 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
775 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f);
776 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f);
777 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
778 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f);
779 outData[5] = tcu::Vec4( 0.18f, -0.2f, 0.0f, 1.0f);
783 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
784 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f);
785 outData[2] = tcu::Vec4( 0.7f, -0.1f, 0.0f, 1.0f);
786 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
787 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f);
788 outData[5] = tcu::Vec4( 0.8f, -0.7f, 0.0f, 1.0f);
793 outLines[0].positions[0] = outData[0];
794 outLines[0].positions[1] = outData[1];
795 outLines[1].positions[0] = outData[2];
796 outLines[1].positions[1] = outData[3];
797 outLines[2].positions[0] = outData[4];
798 outLines[2].positions[1] = outData[5];
801 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering " << outLines.size() << " lines(s): (width = " << m_lineWidth << ")" << tcu::TestLog::EndMessage;
802 for (int lineNdx = 0; lineNdx < (int)outLines.size(); ++lineNdx)
805 << tcu::TestLog::Message
806 << "Line " << (lineNdx+1) << ":"
807 << "\n\t" << outLines[lineNdx].positions[0]
808 << "\n\t" << outLines[lineNdx].positions[1]
809 << tcu::TestLog::EndMessage;
813 class LineStripCase : public BaseLineCase
816 LineStripCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness);
818 void generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
821 LineStripCase::LineStripCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness)
822 : BaseLineCase(context, name, desc, GL_LINE_STRIP, wideness)
826 void LineStripCase::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
833 // \note: these values are chosen arbitrarily
834 outData[0] = tcu::Vec4( 0.01f, 0.0f, 0.0f, 1.0f);
835 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f);
836 outData[2] = tcu::Vec4( 0.46f, 0.3f, 0.0f, 1.0f);
837 outData[3] = tcu::Vec4(-0.5f, 0.2f, 0.0f, 1.0f);
841 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
842 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f);
843 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f);
844 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
848 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
849 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f);
850 outData[2] = tcu::Vec4( 0.7f, -0.1f, 0.0f, 1.0f);
851 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
856 outLines[0].positions[0] = outData[0];
857 outLines[0].positions[1] = outData[1];
858 outLines[1].positions[0] = outData[1];
859 outLines[1].positions[1] = outData[2];
860 outLines[2].positions[0] = outData[2];
861 outLines[2].positions[1] = outData[3];
864 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering line strip, width = " << m_lineWidth << ", " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
865 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
868 << tcu::TestLog::Message
869 << "\t" << outData[vtxNdx]
870 << tcu::TestLog::EndMessage;
874 class LineLoopCase : public BaseLineCase
877 LineLoopCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness);
879 void generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
882 LineLoopCase::LineLoopCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness)
883 : BaseLineCase(context, name, desc, GL_LINE_LOOP, wideness)
887 void LineLoopCase::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
894 // \note: these values are chosen arbitrarily
895 outData[0] = tcu::Vec4( 0.01f, 0.0f, 0.0f, 1.0f);
896 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f);
897 outData[2] = tcu::Vec4( 0.46f, 0.3f, 0.0f, 1.0f);
898 outData[3] = tcu::Vec4(-0.5f, 0.2f, 0.0f, 1.0f);
902 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
903 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f);
904 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f);
905 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
909 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
910 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f);
911 outData[2] = tcu::Vec4( 0.7f, -0.1f, 0.0f, 1.0f);
912 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
917 outLines[0].positions[0] = outData[0];
918 outLines[0].positions[1] = outData[1];
919 outLines[1].positions[0] = outData[1];
920 outLines[1].positions[1] = outData[2];
921 outLines[2].positions[0] = outData[2];
922 outLines[2].positions[1] = outData[3];
923 outLines[3].positions[0] = outData[3];
924 outLines[3].positions[1] = outData[0];
927 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering line loop, width = " << m_lineWidth << ", " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
928 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
931 << tcu::TestLog::Message
932 << "\t" << outData[vtxNdx]
933 << tcu::TestLog::EndMessage;
937 class FillRuleCase : public BaseRenderingCase
940 enum FillRuleCaseType
942 FILLRULECASE_BASIC = 0,
943 FILLRULECASE_REVERSED,
944 FILLRULECASE_CLIPPED_FULL,
945 FILLRULECASE_CLIPPED_PARTIAL,
946 FILLRULECASE_PROJECTED,
951 FillRuleCase (Context& ctx, const char* name, const char* desc, FillRuleCaseType type);
952 ~FillRuleCase (void);
953 IterateResult iterate (void);
956 int getRenderSize (FillRuleCase::FillRuleCaseType type) const;
957 int getNumIterations (FillRuleCase::FillRuleCaseType type) const;
958 void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData) const;
960 const FillRuleCaseType m_caseType;
962 const int m_iterationCount;
963 bool m_allIterationsPassed;
967 FillRuleCase::FillRuleCase (Context& ctx, const char* name, const char* desc, FillRuleCaseType type)
968 : BaseRenderingCase (ctx, name, desc, getRenderSize(type))
971 , m_iterationCount (getNumIterations(type))
972 , m_allIterationsPassed (true)
974 DE_ASSERT(type < FILLRULECASE_LAST);
977 FillRuleCase::~FillRuleCase (void)
982 FillRuleCase::IterateResult FillRuleCase::iterate (void)
984 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
985 const tcu::ScopedLogSection section (m_testCtx.getLog(), iterationDescription, iterationDescription);
986 const int thresholdRed = 1 << (8 - m_context.getRenderTarget().getPixelFormat().redBits);
987 const int thresholdGreen = 1 << (8 - m_context.getRenderTarget().getPixelFormat().greenBits);
988 const int thresholdBlue = 1 << (8 - m_context.getRenderTarget().getPixelFormat().blueBits);
989 tcu::Surface resultImage (m_renderSize, m_renderSize);
990 std::vector<tcu::Vec4> drawBuffer;
991 bool imageShown = false;
993 generateTriangles(m_iteration, drawBuffer);
997 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
998 const std::vector<tcu::Vec4> colorBuffer (drawBuffer.size(), tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f));
1000 m_testCtx.getLog() << tcu::TestLog::Message << "Drawing gray triangles with shared edges.\nEnabling additive blending to detect overlapping fragments." << tcu::TestLog::EndMessage;
1002 gl.enable(GL_BLEND);
1003 gl.blendEquation(GL_FUNC_ADD);
1004 gl.blendFunc(GL_ONE, GL_ONE);
1005 drawPrimitives(resultImage, drawBuffer, colorBuffer, GL_TRIANGLES);
1008 // verify no overdraw
1010 const tcu::RGBA triangleColor = tcu::RGBA(127, 127, 127, 255);
1011 bool overdraw = false;
1013 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying result." << tcu::TestLog::EndMessage;
1015 for (int y = 0; y < resultImage.getHeight(); ++y)
1016 for (int x = 0; x < resultImage.getWidth(); ++x)
1018 const tcu::RGBA color = resultImage.getPixel(x, y);
1020 // color values are greater than triangle color? Allow lower values for multisampled edges and background.
1021 if ((color.getRed() - triangleColor.getRed()) > thresholdRed ||
1022 (color.getGreen() - triangleColor.getGreen()) > thresholdGreen ||
1023 (color.getBlue() - triangleColor.getBlue()) > thresholdBlue)
1029 m_testCtx.getLog() << tcu::TestLog::Message << "No overlapping fragments detected." << tcu::TestLog::EndMessage;
1032 m_testCtx.getLog() << tcu::TestLog::Message << "Overlapping fragments detected, image is not valid." << tcu::TestLog::EndMessage;
1033 m_testCtx.getLog() << tcu::TestLog::ImageSet("Result of rendering", "Result of rendering")
1034 << tcu::TestLog::Image("Result", "Result", resultImage)
1035 << tcu::TestLog::EndImageSet;
1038 m_allIterationsPassed = false;
1042 // verify no missing fragments in the full viewport case
1043 if (m_caseType == FILLRULECASE_CLIPPED_FULL)
1045 bool missingFragments = false;
1047 m_testCtx.getLog() << tcu::TestLog::Message << "Searching missing fragments." << tcu::TestLog::EndMessage;
1049 for (int y = 0; y < resultImage.getHeight(); ++y)
1050 for (int x = 0; x < resultImage.getWidth(); ++x)
1052 const tcu::RGBA color = resultImage.getPixel(x, y);
1054 // black? (background)
1055 if (color.getRed() <= thresholdRed ||
1056 color.getGreen() <= thresholdGreen ||
1057 color.getBlue() <= thresholdBlue)
1058 missingFragments = true;
1062 if (!missingFragments)
1063 m_testCtx.getLog() << tcu::TestLog::Message << "No missing fragments detected." << tcu::TestLog::EndMessage;
1066 m_testCtx.getLog() << tcu::TestLog::Message << "Missing fragments detected, image is not valid." << tcu::TestLog::EndMessage;
1070 m_testCtx.getLog() << tcu::TestLog::ImageSet("Result of rendering", "Result of rendering")
1071 << tcu::TestLog::Image("Result", "Result", resultImage)
1072 << tcu::TestLog::EndImageSet;
1075 m_allIterationsPassed = false;
1080 if (++m_iteration == m_iterationCount)
1082 if (m_allIterationsPassed)
1083 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1085 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Found invalid pixels");
1093 int FillRuleCase::getRenderSize (FillRuleCase::FillRuleCaseType type) const
1095 if (type == FILLRULECASE_CLIPPED_FULL || type == FILLRULECASE_CLIPPED_PARTIAL)
1101 int FillRuleCase::getNumIterations (FillRuleCase::FillRuleCaseType type) const
1103 if (type == FILLRULECASE_CLIPPED_FULL || type == FILLRULECASE_CLIPPED_PARTIAL)
1109 void FillRuleCase::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData) const
1113 case FILLRULECASE_BASIC:
1114 case FILLRULECASE_REVERSED:
1115 case FILLRULECASE_PROJECTED:
1117 const int numRows = 4;
1118 const int numColumns = 4;
1119 const float quadSide = 0.15f;
1120 de::Random rnd (0xabcd);
1122 outData.resize(6 * numRows * numColumns);
1124 for (int col = 0; col < numColumns; ++col)
1125 for (int row = 0; row < numRows; ++row)
1127 const tcu::Vec2 center = tcu::Vec2((row + 0.5f) / numRows * 2.0f - 1.0f, (col + 0.5f) / numColumns * 2.0f - 1.0f);
1128 const float rotation = (iteration * numColumns * numRows + col * numRows + row) / (float)(m_iterationCount * numColumns * numRows) * DE_PI / 2.0f;
1129 const tcu::Vec2 sideH = quadSide * tcu::Vec2(deFloatCos(rotation), deFloatSin(rotation));
1130 const tcu::Vec2 sideV = tcu::Vec2(sideH.y(), -sideH.x());
1131 const tcu::Vec2 quad[4] =
1133 center + sideH + sideV,
1134 center + sideH - sideV,
1135 center - sideH - sideV,
1136 center - sideH + sideV,
1139 if (m_caseType == FILLRULECASE_BASIC)
1141 outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1142 outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
1143 outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1144 outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1145 outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1146 outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
1148 else if (m_caseType == FILLRULECASE_REVERSED)
1150 outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1151 outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
1152 outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1153 outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1154 outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1155 outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
1157 else if (m_caseType == FILLRULECASE_PROJECTED)
1159 const float w0 = rnd.getFloat(0.1f, 4.0f);
1160 const float w1 = rnd.getFloat(0.1f, 4.0f);
1161 const float w2 = rnd.getFloat(0.1f, 4.0f);
1162 const float w3 = rnd.getFloat(0.1f, 4.0f);
1164 outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x() * w0, quad[0].y() * w0, 0.0f, w0);
1165 outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x() * w1, quad[1].y() * w1, 0.0f, w1);
1166 outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x() * w2, quad[2].y() * w2, 0.0f, w2);
1167 outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[2].x() * w2, quad[2].y() * w2, 0.0f, w2);
1168 outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[0].x() * w0, quad[0].y() * w0, 0.0f, w0);
1169 outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x() * w3, quad[3].y() * w3, 0.0f, w3);
1172 DE_ASSERT(DE_FALSE);
1178 case FILLRULECASE_CLIPPED_PARTIAL:
1179 case FILLRULECASE_CLIPPED_FULL:
1181 const float quadSide = (m_caseType == FILLRULECASE_CLIPPED_PARTIAL) ? (1.0f) : (2.0f);
1182 const tcu::Vec2 center = (m_caseType == FILLRULECASE_CLIPPED_PARTIAL) ? (tcu::Vec2(0.5f, 0.5f)) : (tcu::Vec2(0.0f, 0.0f));
1183 const float rotation = (iteration) / (float)(m_iterationCount - 1) * DE_PI / 2.0f;
1184 const tcu::Vec2 sideH = quadSide * tcu::Vec2(deFloatCos(rotation), deFloatSin(rotation));
1185 const tcu::Vec2 sideV = tcu::Vec2(sideH.y(), -sideH.x());
1186 const tcu::Vec2 quad[4] =
1188 center + sideH + sideV,
1189 center + sideH - sideV,
1190 center - sideH - sideV,
1191 center - sideH + sideV,
1195 outData[0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1196 outData[1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
1197 outData[2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1198 outData[3] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1199 outData[4] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1200 outData[5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
1205 DE_ASSERT(DE_FALSE);
1209 class CullingTest : public BaseRenderingCase
1212 CullingTest (Context& ctx, const char* name, const char* desc, glw::GLenum cullMode, glw::GLenum primitive, glw::GLenum faceOrder);
1213 ~CullingTest (void);
1214 IterateResult iterate (void);
1217 void generateVertices (std::vector<tcu::Vec4>& outData) const;
1218 void extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const;
1219 bool triangleOrder (const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) const;
1221 const glw::GLenum m_cullMode;
1222 const glw::GLenum m_primitive;
1223 const glw::GLenum m_faceOrder;
1226 CullingTest::CullingTest (Context& ctx, const char* name, const char* desc, glw::GLenum cullMode, glw::GLenum primitive, glw::GLenum faceOrder)
1227 : BaseRenderingCase (ctx, name, desc)
1228 , m_cullMode (cullMode)
1229 , m_primitive (primitive)
1230 , m_faceOrder (faceOrder)
1234 CullingTest::~CullingTest (void)
1238 CullingTest::IterateResult CullingTest::iterate (void)
1240 tcu::Surface resultImage(m_renderSize, m_renderSize);
1241 std::vector<tcu::Vec4> drawBuffer;
1242 std::vector<TriangleSceneSpec::SceneTriangle> triangles;
1245 generateVertices(drawBuffer);
1246 extractTriangles(triangles, drawBuffer);
1250 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1252 gl.enable(GL_CULL_FACE);
1253 gl.cullFace(m_cullMode);
1254 gl.frontFace(m_faceOrder);
1256 m_testCtx.getLog() << tcu::TestLog::Message << "Setting front face to " << glu::getWindingName(m_faceOrder) << tcu::TestLog::EndMessage;
1257 m_testCtx.getLog() << tcu::TestLog::Message << "Setting cull face to " << glu::getFaceName(m_cullMode) << tcu::TestLog::EndMessage;
1258 m_testCtx.getLog() << tcu::TestLog::Message << "Drawing test pattern (" << glu::getPrimitiveTypeName(m_primitive) << ")" << tcu::TestLog::EndMessage;
1260 drawPrimitives(resultImage, drawBuffer, m_primitive);
1265 RasterizationArguments args;
1266 TriangleSceneSpec scene;
1268 args.numSamples = m_numSamples;
1269 args.subpixelBits = m_subpixelBits;
1270 args.redBits = m_context.getRenderTarget().getPixelFormat().redBits;
1271 args.greenBits = m_context.getRenderTarget().getPixelFormat().greenBits;
1272 args.blueBits = m_context.getRenderTarget().getPixelFormat().blueBits;
1274 scene.triangles.swap(triangles);
1276 if (verifyTriangleGroupRasterization(resultImage, scene, args, m_testCtx.getLog(), VERIFICATIONMODE_WEAK))
1277 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1279 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rendering");
1285 void CullingTest::generateVertices (std::vector<tcu::Vec4>& outData) const
1287 de::Random rnd(543210);
1290 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
1292 outData[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
1293 outData[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
1294 outData[vtxNdx].z() = 0.0f;
1295 outData[vtxNdx].w() = 1.0f;
1299 void CullingTest::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const
1301 const bool cullDirection = (m_cullMode == GL_FRONT) ^ (m_faceOrder == GL_CCW);
1304 if (m_cullMode == GL_FRONT_AND_BACK)
1307 switch (m_primitive)
1311 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
1313 const tcu::Vec4& v0 = vertices[vtxNdx + 0];
1314 const tcu::Vec4& v1 = vertices[vtxNdx + 1];
1315 const tcu::Vec4& v2 = vertices[vtxNdx + 2];
1317 if (triangleOrder(v0, v1, v2) != cullDirection)
1319 TriangleSceneSpec::SceneTriangle tri;
1320 tri.positions[0] = v0; tri.sharedEdge[0] = false;
1321 tri.positions[1] = v1; tri.sharedEdge[1] = false;
1322 tri.positions[2] = v2; tri.sharedEdge[2] = false;
1324 outTriangles.push_back(tri);
1330 case GL_TRIANGLE_STRIP:
1332 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
1334 const tcu::Vec4& v0 = vertices[vtxNdx + 0];
1335 const tcu::Vec4& v1 = vertices[vtxNdx + 1];
1336 const tcu::Vec4& v2 = vertices[vtxNdx + 2];
1338 if (triangleOrder(v0, v1, v2) != (cullDirection ^ (vtxNdx % 2 != 0)))
1340 TriangleSceneSpec::SceneTriangle tri;
1341 tri.positions[0] = v0; tri.sharedEdge[0] = false;
1342 tri.positions[1] = v1; tri.sharedEdge[1] = false;
1343 tri.positions[2] = v2; tri.sharedEdge[2] = false;
1345 outTriangles.push_back(tri);
1351 case GL_TRIANGLE_FAN:
1353 for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
1355 const tcu::Vec4& v0 = vertices[0];
1356 const tcu::Vec4& v1 = vertices[vtxNdx + 0];
1357 const tcu::Vec4& v2 = vertices[vtxNdx + 1];
1359 if (triangleOrder(v0, v1, v2) != cullDirection)
1361 TriangleSceneSpec::SceneTriangle tri;
1362 tri.positions[0] = v0; tri.sharedEdge[0] = false;
1363 tri.positions[1] = v1; tri.sharedEdge[1] = false;
1364 tri.positions[2] = v2; tri.sharedEdge[2] = false;
1366 outTriangles.push_back(tri);
1377 bool CullingTest::triangleOrder (const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) const
1379 const tcu::Vec2 s0 = v0.swizzle(0, 1) / v0.w();
1380 const tcu::Vec2 s1 = v1.swizzle(0, 1) / v1.w();
1381 const tcu::Vec2 s2 = v2.swizzle(0, 1) / v2.w();
1384 return ((s1.x() - s0.x()) * (s2.y() - s0.y()) - (s2.x() - s0.x()) * (s1.y() - s0.y())) < 0;
1387 class TriangleInterpolationTest : public BaseRenderingCase
1390 TriangleInterpolationTest (Context& ctx, const char* name, const char* desc, glw::GLenum primitive, int flags);
1391 ~TriangleInterpolationTest (void);
1392 IterateResult iterate (void);
1395 void generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const;
1396 void extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
1398 const glw::GLenum m_primitive;
1399 const bool m_projective;
1400 const int m_iterationCount;
1403 bool m_allIterationsPassed;
1406 TriangleInterpolationTest::TriangleInterpolationTest (Context& ctx, const char* name, const char* desc, glw::GLenum primitive, int flags)
1407 : BaseRenderingCase (ctx, name, desc)
1408 , m_primitive (primitive)
1409 , m_projective ((flags & INTERPOLATIONFLAGS_PROJECTED) != 0)
1410 , m_iterationCount (3)
1412 , m_allIterationsPassed (true)
1416 TriangleInterpolationTest::~TriangleInterpolationTest (void)
1421 TriangleInterpolationTest::IterateResult TriangleInterpolationTest::iterate (void)
1423 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
1424 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription);
1425 tcu::Surface resultImage (m_renderSize, m_renderSize);
1426 std::vector<tcu::Vec4> drawBuffer;
1427 std::vector<tcu::Vec4> colorBuffer;
1428 std::vector<TriangleSceneSpec::SceneTriangle> triangles;
1431 generateVertices(m_iteration, drawBuffer, colorBuffer);
1432 extractTriangles(triangles, drawBuffer, colorBuffer);
1436 m_testCtx.getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage;
1437 for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx)
1438 m_testCtx.getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage;
1442 drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitive);
1446 RasterizationArguments args;
1447 TriangleSceneSpec scene;
1449 args.numSamples = m_numSamples;
1450 args.subpixelBits = m_subpixelBits;
1451 args.redBits = m_context.getRenderTarget().getPixelFormat().redBits;
1452 args.greenBits = m_context.getRenderTarget().getPixelFormat().greenBits;
1453 args.blueBits = m_context.getRenderTarget().getPixelFormat().blueBits;
1455 scene.triangles.swap(triangles);
1457 if (!verifyTriangleGroupInterpolation(resultImage, scene, args, m_testCtx.getLog()))
1458 m_allIterationsPassed = false;
1462 if (++m_iteration == m_iterationCount)
1464 if (m_allIterationsPassed)
1465 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1467 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Found invalid pixel values");
1475 void TriangleInterpolationTest::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const
1477 // use only red, green and blue
1478 const tcu::Vec4 colors[] =
1480 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
1481 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
1482 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
1485 de::Random rnd(123 + iteration * 1000 + (int)m_primitive);
1487 outVertices.resize(6);
1488 outColors.resize(6);
1490 for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx)
1492 outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
1493 outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
1494 outVertices[vtxNdx].z() = 0.0f;
1497 outVertices[vtxNdx].w() = 1.0f;
1500 const float w = rnd.getFloat(0.2f, 4.0f);
1502 outVertices[vtxNdx].x() *= w;
1503 outVertices[vtxNdx].y() *= w;
1504 outVertices[vtxNdx].z() *= w;
1505 outVertices[vtxNdx].w() = w;
1508 outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)];
1512 void TriangleInterpolationTest::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
1514 switch (m_primitive)
1518 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
1520 TriangleSceneSpec::SceneTriangle tri;
1521 tri.positions[0] = vertices[vtxNdx + 0];
1522 tri.positions[1] = vertices[vtxNdx + 1];
1523 tri.positions[2] = vertices[vtxNdx + 2];
1524 tri.sharedEdge[0] = false;
1525 tri.sharedEdge[1] = false;
1526 tri.sharedEdge[2] = false;
1528 tri.colors[0] = colors[vtxNdx + 0];
1529 tri.colors[1] = colors[vtxNdx + 1];
1530 tri.colors[2] = colors[vtxNdx + 2];
1532 outTriangles.push_back(tri);
1537 case GL_TRIANGLE_STRIP:
1539 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
1541 TriangleSceneSpec::SceneTriangle tri;
1542 tri.positions[0] = vertices[vtxNdx + 0];
1543 tri.positions[1] = vertices[vtxNdx + 1];
1544 tri.positions[2] = vertices[vtxNdx + 2];
1545 tri.sharedEdge[0] = false;
1546 tri.sharedEdge[1] = false;
1547 tri.sharedEdge[2] = false;
1549 tri.colors[0] = colors[vtxNdx + 0];
1550 tri.colors[1] = colors[vtxNdx + 1];
1551 tri.colors[2] = colors[vtxNdx + 2];
1553 outTriangles.push_back(tri);
1558 case GL_TRIANGLE_FAN:
1560 for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
1562 TriangleSceneSpec::SceneTriangle tri;
1563 tri.positions[0] = vertices[0];
1564 tri.positions[1] = vertices[vtxNdx + 0];
1565 tri.positions[2] = vertices[vtxNdx + 1];
1566 tri.sharedEdge[0] = false;
1567 tri.sharedEdge[1] = false;
1568 tri.sharedEdge[2] = false;
1570 tri.colors[0] = colors[0];
1571 tri.colors[1] = colors[vtxNdx + 0];
1572 tri.colors[2] = colors[vtxNdx + 1];
1574 outTriangles.push_back(tri);
1584 class LineInterpolationTest : public BaseRenderingCase
1587 LineInterpolationTest (Context& ctx, const char* name, const char* desc, glw::GLenum primitive, int flags, float lineWidth);
1588 ~LineInterpolationTest (void);
1589 IterateResult iterate (void);
1592 void generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const;
1593 void extractLines (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
1595 const glw::GLenum m_primitive;
1596 const bool m_projective;
1597 const int m_iterationCount;
1600 tcu::ResultCollector m_result;
1603 LineInterpolationTest::LineInterpolationTest (Context& ctx, const char* name, const char* desc, glw::GLenum primitive, int flags, float lineWidth)
1604 : BaseRenderingCase (ctx, name, desc)
1605 , m_primitive (primitive)
1606 , m_projective ((flags & INTERPOLATIONFLAGS_PROJECTED) != 0)
1607 , m_iterationCount (3)
1610 m_lineWidth = lineWidth;
1613 LineInterpolationTest::~LineInterpolationTest (void)
1618 LineInterpolationTest::IterateResult LineInterpolationTest::iterate (void)
1620 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
1621 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription);
1622 tcu::Surface resultImage (m_renderSize, m_renderSize);
1623 std::vector<tcu::Vec4> drawBuffer;
1624 std::vector<tcu::Vec4> colorBuffer;
1625 std::vector<LineSceneSpec::SceneLine> lines;
1628 generateVertices(m_iteration, drawBuffer, colorBuffer);
1629 extractLines(lines, drawBuffer, colorBuffer);
1633 m_testCtx.getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage;
1634 for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx)
1635 m_testCtx.getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage;
1639 drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitive);
1643 RasterizationArguments args;
1644 LineSceneSpec scene;
1645 LineInterpolationMethod iterationResult;
1647 args.numSamples = m_numSamples;
1648 args.subpixelBits = m_subpixelBits;
1649 args.redBits = m_context.getRenderTarget().getPixelFormat().redBits;
1650 args.greenBits = m_context.getRenderTarget().getPixelFormat().greenBits;
1651 args.blueBits = m_context.getRenderTarget().getPixelFormat().blueBits;
1653 scene.lines.swap(lines);
1654 scene.lineWidth = m_lineWidth;
1656 iterationResult = verifyLineGroupInterpolation(resultImage, scene, args, m_testCtx.getLog());
1657 switch (iterationResult)
1659 case LINEINTERPOLATION_STRICTLY_CORRECT:
1660 // line interpolation matches the specification
1661 m_result.addResult(QP_TEST_RESULT_PASS, "Pass");
1664 case LINEINTERPOLATION_PROJECTED:
1665 // line interpolation weights are otherwise correct, but they are projected onto major axis
1666 m_testCtx.getLog() << tcu::TestLog::Message
1667 << "Interpolation was calculated using coordinates projected onto major axis. "
1668 "This method does not produce the same values as the non-projecting method defined in the specification."
1669 << tcu::TestLog::EndMessage;
1670 m_result.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Interpolation was calculated using projected coordinateds");
1673 case LINEINTERPOLATION_INCORRECT:
1674 // line interpolation is incorrect
1675 m_result.addResult(QP_TEST_RESULT_FAIL, "Found invalid pixel values");
1685 if (++m_iteration == m_iterationCount)
1687 m_result.setTestContextResult(m_testCtx);
1694 void LineInterpolationTest::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const
1696 // use only red, green and blue
1697 const tcu::Vec4 colors[] =
1699 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
1700 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
1701 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
1704 de::Random rnd(123 + iteration * 1000 + (int)m_primitive);
1706 outVertices.resize(6);
1707 outColors.resize(6);
1709 for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx)
1711 outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
1712 outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
1713 outVertices[vtxNdx].z() = 0.0f;
1716 outVertices[vtxNdx].w() = 1.0f;
1719 const float w = rnd.getFloat(0.2f, 4.0f);
1721 outVertices[vtxNdx].x() *= w;
1722 outVertices[vtxNdx].y() *= w;
1723 outVertices[vtxNdx].z() *= w;
1724 outVertices[vtxNdx].w() = w;
1727 outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)];
1731 void LineInterpolationTest::extractLines (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
1733 switch (m_primitive)
1737 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; vtxNdx += 2)
1739 LineSceneSpec::SceneLine line;
1740 line.positions[0] = vertices[vtxNdx + 0];
1741 line.positions[1] = vertices[vtxNdx + 1];
1743 line.colors[0] = colors[vtxNdx + 0];
1744 line.colors[1] = colors[vtxNdx + 1];
1746 outLines.push_back(line);
1753 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
1755 LineSceneSpec::SceneLine line;
1756 line.positions[0] = vertices[vtxNdx + 0];
1757 line.positions[1] = vertices[vtxNdx + 1];
1759 line.colors[0] = colors[vtxNdx + 0];
1760 line.colors[1] = colors[vtxNdx + 1];
1762 outLines.push_back(line);
1769 for (int vtxNdx = 0; vtxNdx < (int)vertices.size(); ++vtxNdx)
1771 LineSceneSpec::SceneLine line;
1772 line.positions[0] = vertices[(vtxNdx + 0) % (int)vertices.size()];
1773 line.positions[1] = vertices[(vtxNdx + 1) % (int)vertices.size()];
1775 line.colors[0] = colors[(vtxNdx + 0) % (int)vertices.size()];
1776 line.colors[1] = colors[(vtxNdx + 1) % (int)vertices.size()];
1778 outLines.push_back(line);
1790 RasterizationTests::RasterizationTests (Context& context)
1791 : TestCaseGroup(context, "rasterization", "Rasterization Tests")
1795 RasterizationTests::~RasterizationTests (void)
1799 void RasterizationTests::init (void)
1803 tcu::TestCaseGroup* const primitives = new tcu::TestCaseGroup(m_testCtx, "primitives", "Primitive rasterization");
1805 addChild(primitives);
1807 primitives->addChild(new TrianglesCase (m_context, "triangles", "Render primitives as GL_TRIANGLES, verify rasterization result"));
1808 primitives->addChild(new TriangleStripCase (m_context, "triangle_strip", "Render primitives as GL_TRIANGLE_STRIP, verify rasterization result"));
1809 primitives->addChild(new TriangleFanCase (m_context, "triangle_fan", "Render primitives as GL_TRIANGLE_FAN, verify rasterization result"));
1810 primitives->addChild(new LinesCase (m_context, "lines", "Render primitives as GL_LINES, verify rasterization result", PRIMITIVEWIDENESS_NARROW));
1811 primitives->addChild(new LineStripCase (m_context, "line_strip", "Render primitives as GL_LINE_STRIP, verify rasterization result", PRIMITIVEWIDENESS_NARROW));
1812 primitives->addChild(new LineLoopCase (m_context, "line_loop", "Render primitives as GL_LINE_LOOP, verify rasterization result", PRIMITIVEWIDENESS_NARROW));
1813 primitives->addChild(new LinesCase (m_context, "lines_wide", "Render primitives as GL_LINES with wide lines, verify rasterization result", PRIMITIVEWIDENESS_WIDE));
1814 primitives->addChild(new LineStripCase (m_context, "line_strip_wide", "Render primitives as GL_LINE_STRIP with wide lines, verify rasterization result", PRIMITIVEWIDENESS_WIDE));
1815 primitives->addChild(new LineLoopCase (m_context, "line_loop_wide", "Render primitives as GL_LINE_LOOP with wide lines, verify rasterization result", PRIMITIVEWIDENESS_WIDE));
1816 primitives->addChild(new PointCase (m_context, "points", "Render primitives as GL_POINTS, verify rasterization result", PRIMITIVEWIDENESS_WIDE));
1821 tcu::TestCaseGroup* const fillRules = new tcu::TestCaseGroup(m_testCtx, "fill_rules", "Primitive fill rules");
1823 addChild(fillRules);
1825 fillRules->addChild(new FillRuleCase(m_context, "basic_quad", "Verify fill rules", FillRuleCase::FILLRULECASE_BASIC));
1826 fillRules->addChild(new FillRuleCase(m_context, "basic_quad_reverse", "Verify fill rules", FillRuleCase::FILLRULECASE_REVERSED));
1827 fillRules->addChild(new FillRuleCase(m_context, "clipped_full", "Verify fill rules", FillRuleCase::FILLRULECASE_CLIPPED_FULL));
1828 fillRules->addChild(new FillRuleCase(m_context, "clipped_partly", "Verify fill rules", FillRuleCase::FILLRULECASE_CLIPPED_PARTIAL));
1829 fillRules->addChild(new FillRuleCase(m_context, "projected", "Verify fill rules", FillRuleCase::FILLRULECASE_PROJECTED));
1834 static const struct CullMode
1840 { GL_FRONT, "front_" },
1841 { GL_BACK, "back_" },
1842 { GL_FRONT_AND_BACK, "both_" },
1844 static const struct PrimitiveType
1848 } primitiveTypes[] =
1850 { GL_TRIANGLES, "triangles" },
1851 { GL_TRIANGLE_STRIP, "triangle_strip" },
1852 { GL_TRIANGLE_FAN, "triangle_fan" },
1854 static const struct FrontFaceOrder
1857 const char* postfix;
1861 { GL_CW, "_reverse" },
1864 tcu::TestCaseGroup* const culling = new tcu::TestCaseGroup(m_testCtx, "culling", "Culling");
1868 for (int cullModeNdx = 0; cullModeNdx < DE_LENGTH_OF_ARRAY(cullModes); ++cullModeNdx)
1869 for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); ++primitiveNdx)
1870 for (int frontOrderNdx = 0; frontOrderNdx < DE_LENGTH_OF_ARRAY(frontOrders); ++frontOrderNdx)
1872 const std::string name = std::string(cullModes[cullModeNdx].prefix) + primitiveTypes[primitiveNdx].name + frontOrders[frontOrderNdx].postfix;
1874 culling->addChild(new CullingTest(m_context, name.c_str(), "Test primitive culling.", cullModes[cullModeNdx].mode, primitiveTypes[primitiveNdx].type, frontOrders[frontOrderNdx].mode));
1880 tcu::TestCaseGroup* const interpolation = new tcu::TestCaseGroup(m_testCtx, "interpolation", "Test interpolation");
1882 addChild(interpolation);
1886 tcu::TestCaseGroup* const basic = new tcu::TestCaseGroup(m_testCtx, "basic", "Non-projective interpolation");
1888 interpolation->addChild(basic);
1890 basic->addChild(new TriangleInterpolationTest (m_context, "triangles", "Verify triangle interpolation", GL_TRIANGLES, INTERPOLATIONFLAGS_NONE));
1891 basic->addChild(new TriangleInterpolationTest (m_context, "triangle_strip", "Verify triangle strip interpolation", GL_TRIANGLE_STRIP, INTERPOLATIONFLAGS_NONE));
1892 basic->addChild(new TriangleInterpolationTest (m_context, "triangle_fan", "Verify triangle fan interpolation", GL_TRIANGLE_FAN, INTERPOLATIONFLAGS_NONE));
1893 basic->addChild(new LineInterpolationTest (m_context, "lines", "Verify line interpolation", GL_LINES, INTERPOLATIONFLAGS_NONE, 1.0f));
1894 basic->addChild(new LineInterpolationTest (m_context, "line_strip", "Verify line strip interpolation", GL_LINE_STRIP, INTERPOLATIONFLAGS_NONE, 1.0f));
1895 basic->addChild(new LineInterpolationTest (m_context, "line_loop", "Verify line loop interpolation", GL_LINE_LOOP, INTERPOLATIONFLAGS_NONE, 1.0f));
1896 basic->addChild(new LineInterpolationTest (m_context, "lines_wide", "Verify wide line interpolation", GL_LINES, INTERPOLATIONFLAGS_NONE, 5.0f));
1897 basic->addChild(new LineInterpolationTest (m_context, "line_strip_wide", "Verify wide line strip interpolation", GL_LINE_STRIP, INTERPOLATIONFLAGS_NONE, 5.0f));
1898 basic->addChild(new LineInterpolationTest (m_context, "line_loop_wide", "Verify wide line loop interpolation", GL_LINE_LOOP, INTERPOLATIONFLAGS_NONE, 5.0f));
1903 tcu::TestCaseGroup* const projected = new tcu::TestCaseGroup(m_testCtx, "projected", "Projective interpolation");
1905 interpolation->addChild(projected);
1907 projected->addChild(new TriangleInterpolationTest (m_context, "triangles", "Verify triangle interpolation", GL_TRIANGLES, INTERPOLATIONFLAGS_PROJECTED));
1908 projected->addChild(new TriangleInterpolationTest (m_context, "triangle_strip", "Verify triangle strip interpolation", GL_TRIANGLE_STRIP, INTERPOLATIONFLAGS_PROJECTED));
1909 projected->addChild(new TriangleInterpolationTest (m_context, "triangle_fan", "Verify triangle fan interpolation", GL_TRIANGLE_FAN, INTERPOLATIONFLAGS_PROJECTED));
1910 projected->addChild(new LineInterpolationTest (m_context, "lines", "Verify line interpolation", GL_LINES, INTERPOLATIONFLAGS_PROJECTED, 1.0f));
1911 projected->addChild(new LineInterpolationTest (m_context, "line_strip", "Verify line strip interpolation", GL_LINE_STRIP, INTERPOLATIONFLAGS_PROJECTED, 1.0f));
1912 projected->addChild(new LineInterpolationTest (m_context, "line_loop", "Verify line loop interpolation", GL_LINE_LOOP, INTERPOLATIONFLAGS_PROJECTED, 1.0f));
1913 projected->addChild(new LineInterpolationTest (m_context, "lines_wide", "Verify wide line interpolation", GL_LINES, INTERPOLATIONFLAGS_PROJECTED, 5.0f));
1914 projected->addChild(new LineInterpolationTest (m_context, "line_strip_wide", "Verify wide line strip interpolation", GL_LINE_STRIP, INTERPOLATIONFLAGS_PROJECTED, 5.0f));
1915 projected->addChild(new LineInterpolationTest (m_context, "line_loop_wide", "Verify wide line loop interpolation", GL_LINE_LOOP, INTERPOLATIONFLAGS_PROJECTED, 5.0f));