1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.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 "es3fRasterizationTests.hpp"
25 #include "tcuRasterizationVerifier.hpp"
26 #include "tcuSurface.hpp"
27 #include "tcuRenderTarget.hpp"
28 #include "tcuVectorUtil.hpp"
29 #include "tcuStringTemplate.hpp"
30 #include "tcuTextureUtil.hpp"
31 #include "tcuResultCollector.hpp"
32 #include "gluShaderProgram.hpp"
33 #include "gluRenderContext.hpp"
34 #include "gluPixelTransfer.hpp"
35 #include "gluStrUtil.hpp"
36 #include "gluTextureUtil.hpp"
37 #include "deStringUtil.hpp"
38 #include "deRandom.hpp"
39 #include "glwFunctions.hpp"
40 #include "glwEnums.hpp"
41
42 #include <vector>
43
44 namespace deqp
45 {
46 namespace gles3
47 {
48 namespace Functional
49 {
50 namespace
51 {
52
53 using tcu::RasterizationArguments;
54 using tcu::TriangleSceneSpec;
55 using tcu::PointSceneSpec;
56 using tcu::LineSceneSpec;
57 using tcu::LineInterpolationMethod;
58
59 static const char* const s_shaderVertexTemplate = "#version 300 es\n"
60 "in highp vec4 a_position;\n"
61 "in highp vec4 a_color;\n"
62 "${INTERPOLATION}out highp vec4 v_color;\n"
63 "uniform highp float u_pointSize;\n"
64 "void main ()\n"
65 "{\n"
66 " gl_Position = a_position;\n"
67 " gl_PointSize = u_pointSize;\n"
68 " v_color = a_color;\n"
69 "}\n";
70 static const char* const s_shaderFragmentTemplate = "#version 300 es\n"
71 "layout(location = 0) out highp vec4 fragColor;\n"
72 "${INTERPOLATION}in highp vec4 v_color;\n"
73 "void main ()\n"
74 "{\n"
75 " fragColor = v_color;\n"
76 "}\n";
77 enum InterpolationCaseFlags
78 {
79 INTERPOLATIONFLAGS_NONE = 0,
80 INTERPOLATIONFLAGS_PROJECTED = (1 << 1),
81 INTERPOLATIONFLAGS_FLATSHADE = (1 << 2),
82 };
83
84 enum PrimitiveWideness
85 {
86 PRIMITIVEWIDENESS_NARROW = 0,
87 PRIMITIVEWIDENESS_WIDE,
88
89 PRIMITIVEWIDENESS_LAST
90 };
91
getInternalFormatPixelFormat(glw::GLenum internalFormat)92 static tcu::PixelFormat getInternalFormatPixelFormat (glw::GLenum internalFormat)
93 {
94 const tcu::IVec4 bitDepth = tcu::getTextureFormatBitDepth(glu::mapGLInternalFormat(internalFormat));
95 return tcu::PixelFormat(bitDepth.x(), bitDepth.y(), bitDepth.z(), bitDepth.w());
96 }
97
98 class BaseRenderingCase : public TestCase
99 {
100 public:
101 enum RenderTarget
102 {
103 RENDERTARGET_DEFAULT = 0,
104 RENDERTARGET_TEXTURE_2D,
105 RENDERTARGET_RBO_SINGLESAMPLE,
106 RENDERTARGET_RBO_MULTISAMPLE,
107
108 RENDERTARGET_LAST
109 };
110
111 enum
112 {
113 DEFAULT_RENDER_SIZE = 256,
114 SAMPLE_COUNT_MAX = -2,
115 };
116
117 BaseRenderingCase (Context& context, const char* name, const char* desc, RenderTarget target, int numSamples, int renderSize);
118 ~BaseRenderingCase (void);
119 virtual void init (void);
120 void deinit (void);
121
122 protected:
123 void drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, glw::GLenum primitiveType);
124 void drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, const std::vector<tcu::Vec4>& coloDrata, glw::GLenum primitiveType);
125
126 virtual float getLineWidth (void) const;
127 virtual float getPointSize (void) const;
128 const tcu::PixelFormat& getPixelFormat (void) const;
129
130 const int m_renderSize;
131 int m_numSamples;
132 int m_subpixelBits;
133 bool m_flatshade;
134 const int m_numRequestedSamples;
135
136 private:
137 const RenderTarget m_renderTarget;
138 const glw::GLenum m_fboInternalFormat;
139 const tcu::PixelFormat m_pixelFormat;
140 glu::ShaderProgram* m_shader;
141 glw::GLuint m_fbo;
142 glw::GLuint m_texture;
143 glw::GLuint m_rbo;
144 glw::GLuint m_blitDstFbo;
145 glw::GLuint m_blitDstRbo;
146 };
147
BaseRenderingCase(Context & context,const char * name,const char * desc,RenderTarget target,int numSamples,int renderSize)148 BaseRenderingCase::BaseRenderingCase (Context& context, const char* name, const char* desc, RenderTarget target, int numSamples, int renderSize)
149 : TestCase (context, name, desc)
150 , m_renderSize (renderSize)
151 , m_numSamples (-1)
152 , m_subpixelBits (-1)
153 , m_flatshade (false)
154 , m_numRequestedSamples (numSamples)
155 , m_renderTarget (target)
156 , m_fboInternalFormat (GL_RGBA8)
157 , m_pixelFormat ((m_renderTarget == RENDERTARGET_DEFAULT) ? (m_context.getRenderTarget().getPixelFormat()) : (getInternalFormatPixelFormat(m_fboInternalFormat)))
158 , m_shader (DE_NULL)
159 , m_fbo (0)
160 , m_texture (0)
161 , m_rbo (0)
162 , m_blitDstFbo (0)
163 , m_blitDstRbo (0)
164 {
165 DE_ASSERT(m_renderTarget < RENDERTARGET_LAST);
166 DE_ASSERT((m_numRequestedSamples == -1) == (m_renderTarget != RENDERTARGET_RBO_MULTISAMPLE));
167 }
168
~BaseRenderingCase(void)169 BaseRenderingCase::~BaseRenderingCase (void)
170 {
171 deinit();
172 }
173
init(void)174 void BaseRenderingCase::init (void)
175 {
176 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
177 const int width = m_context.getRenderTarget().getWidth();
178 const int height = m_context.getRenderTarget().getHeight();
179 int msaaTargetSamples = -1;
180
181 // Requirements
182
183 if (m_renderTarget == RENDERTARGET_DEFAULT && (width < m_renderSize || height < m_renderSize))
184 throw tcu::NotSupportedError(std::string("Render target size must be at least ") + de::toString(m_renderSize) + "x" + de::toString(m_renderSize));
185
186 if (m_renderTarget == RENDERTARGET_RBO_MULTISAMPLE)
187 {
188 glw::GLint maxSampleCount = 0;
189 gl.getInternalformativ(GL_RENDERBUFFER, m_fboInternalFormat, GL_SAMPLES, 1, &maxSampleCount);
190
191 if (m_numRequestedSamples == SAMPLE_COUNT_MAX)
192 msaaTargetSamples = maxSampleCount;
193 else if (maxSampleCount >= m_numRequestedSamples)
194 msaaTargetSamples = m_numRequestedSamples;
195 else
196 throw tcu::NotSupportedError("Test requires " + de::toString(m_numRequestedSamples) + "x msaa rbo");
197 }
198
199 // Gen shader
200
201 {
202 tcu::StringTemplate vertexSource (s_shaderVertexTemplate);
203 tcu::StringTemplate fragmentSource (s_shaderFragmentTemplate);
204 std::map<std::string, std::string> params;
205
206 params["INTERPOLATION"] = (m_flatshade) ? ("flat ") : ("");
207
208 m_shader = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(vertexSource.specialize(params)) << glu::FragmentSource(fragmentSource.specialize(params)));
209 if (!m_shader->isOk())
210 throw tcu::TestError("could not create shader");
211 }
212
213 // Fbo
214 if (m_renderTarget != RENDERTARGET_DEFAULT)
215 {
216 glw::GLenum error;
217
218 gl.genFramebuffers(1, &m_fbo);
219 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
220
221 switch (m_renderTarget)
222 {
223 case RENDERTARGET_TEXTURE_2D:
224 {
225 gl.genTextures(1, &m_texture);
226 gl.bindTexture(GL_TEXTURE_2D, m_texture);
227 gl.texStorage2D(GL_TEXTURE_2D, 1, m_fboInternalFormat, m_renderSize, m_renderSize);
228
229 error = gl.getError();
230 if (error == GL_OUT_OF_MEMORY)
231 throw tcu::NotSupportedError("could not create target texture, got out of memory");
232 else if (error != GL_NO_ERROR)
233 throw tcu::TestError("got " + de::toString(glu::getErrorStr(error)));
234
235 gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0);
236 break;
237 }
238
239 case RENDERTARGET_RBO_SINGLESAMPLE:
240 case RENDERTARGET_RBO_MULTISAMPLE:
241 {
242 gl.genRenderbuffers(1, &m_rbo);
243 gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo);
244
245 if (m_renderTarget == RENDERTARGET_RBO_SINGLESAMPLE)
246 gl.renderbufferStorage(GL_RENDERBUFFER, m_fboInternalFormat, m_renderSize, m_renderSize);
247 else if (m_renderTarget == RENDERTARGET_RBO_MULTISAMPLE)
248 gl.renderbufferStorageMultisample(GL_RENDERBUFFER, msaaTargetSamples, m_fboInternalFormat, m_renderSize, m_renderSize);
249 else
250 DE_ASSERT(false);
251
252 error = gl.getError();
253 if (error == GL_OUT_OF_MEMORY)
254 throw tcu::NotSupportedError("could not create target texture, got out of memory");
255 else if (error != GL_NO_ERROR)
256 throw tcu::TestError("got " + de::toString(glu::getErrorStr(error)));
257
258 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo);
259 break;
260 }
261
262 default:
263 DE_ASSERT(false);
264 }
265 }
266
267 // Resolve (blitFramebuffer) target fbo for MSAA targets
268 if (m_renderTarget == RENDERTARGET_RBO_MULTISAMPLE)
269 {
270 glw::GLenum error;
271
272 gl.genFramebuffers(1, &m_blitDstFbo);
273 gl.bindFramebuffer(GL_FRAMEBUFFER, m_blitDstFbo);
274
275 gl.genRenderbuffers(1, &m_blitDstRbo);
276 gl.bindRenderbuffer(GL_RENDERBUFFER, m_blitDstRbo);
277 gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, m_renderSize, m_renderSize);
278
279 error = gl.getError();
280 if (error == GL_OUT_OF_MEMORY)
281 throw tcu::NotSupportedError("could not create blit target, got out of memory");
282 else if (error != GL_NO_ERROR)
283 throw tcu::TestError("got " + de::toString(glu::getErrorStr(error)));
284
285 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_blitDstRbo);
286
287 // restore state
288 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
289 }
290
291 // Query info
292
293 if (m_renderTarget == RENDERTARGET_DEFAULT)
294 m_numSamples = m_context.getRenderTarget().getNumSamples();
295 else if (m_renderTarget == RENDERTARGET_RBO_MULTISAMPLE)
296 {
297 m_numSamples = -1;
298 gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo);
299 gl.getRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &m_numSamples);
300
301 GLU_EXPECT_NO_ERROR(gl.getError(), "get RENDERBUFFER_SAMPLES");
302 }
303 else
304 m_numSamples = 0;
305
306 gl.getIntegerv(GL_SUBPIXEL_BITS, &m_subpixelBits);
307
308 m_testCtx.getLog() << tcu::TestLog::Message << "Sample count = " << m_numSamples << tcu::TestLog::EndMessage;
309 m_testCtx.getLog() << tcu::TestLog::Message << "SUBPIXEL_BITS = " << m_subpixelBits << tcu::TestLog::EndMessage;
310 }
311
deinit(void)312 void BaseRenderingCase::deinit (void)
313 {
314 if (m_shader)
315 {
316 delete m_shader;
317 m_shader = DE_NULL;
318 }
319
320 if (m_fbo)
321 {
322 m_context.getRenderContext().getFunctions().deleteFramebuffers(1, &m_fbo);
323 m_fbo = 0;
324 }
325
326 if (m_rbo)
327 {
328 m_context.getRenderContext().getFunctions().deleteRenderbuffers(1, &m_rbo);
329 m_rbo = 0;
330 }
331
332 if (m_texture)
333 {
334 m_context.getRenderContext().getFunctions().deleteTextures(1, &m_texture);
335 m_texture = 0;
336 }
337
338 if (m_blitDstFbo)
339 {
340 m_context.getRenderContext().getFunctions().deleteFramebuffers(1, &m_blitDstFbo);
341 m_blitDstFbo = 0;
342 }
343
344 if (m_blitDstRbo)
345 {
346 m_context.getRenderContext().getFunctions().deleteRenderbuffers(1, &m_blitDstRbo);
347 m_blitDstRbo = 0;
348 }
349 }
350
drawPrimitives(tcu::Surface & result,const std::vector<tcu::Vec4> & vertexData,glw::GLenum primitiveType)351 void BaseRenderingCase::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, glw::GLenum primitiveType)
352 {
353 // default to color white
354 const std::vector<tcu::Vec4> colorData(vertexData.size(), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
355
356 drawPrimitives(result, vertexData, colorData, primitiveType);
357 }
358
drawPrimitives(tcu::Surface & result,const std::vector<tcu::Vec4> & vertexData,const std::vector<tcu::Vec4> & colorData,glw::GLenum primitiveType)359 void BaseRenderingCase::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, const std::vector<tcu::Vec4>& colorData, glw::GLenum primitiveType)
360 {
361 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
362 const glw::GLint positionLoc = gl.getAttribLocation(m_shader->getProgram(), "a_position");
363 const glw::GLint colorLoc = gl.getAttribLocation(m_shader->getProgram(), "a_color");
364 const glw::GLint pointSizeLoc = gl.getUniformLocation(m_shader->getProgram(), "u_pointSize");
365
366 gl.clearColor (0, 0, 0, 1);
367 gl.clear (GL_COLOR_BUFFER_BIT);
368 gl.viewport (0, 0, m_renderSize, m_renderSize);
369 gl.useProgram (m_shader->getProgram());
370 gl.enableVertexAttribArray (positionLoc);
371 gl.vertexAttribPointer (positionLoc, 4, GL_FLOAT, GL_FALSE, 0, &vertexData[0]);
372 gl.enableVertexAttribArray (colorLoc);
373 gl.vertexAttribPointer (colorLoc, 4, GL_FLOAT, GL_FALSE, 0, &colorData[0]);
374 gl.uniform1f (pointSizeLoc, getPointSize());
375 gl.lineWidth (getLineWidth());
376 gl.drawArrays (primitiveType, 0, (glw::GLsizei)vertexData.size());
377 gl.disableVertexAttribArray (colorLoc);
378 gl.disableVertexAttribArray (positionLoc);
379 gl.useProgram (0);
380 gl.finish ();
381 GLU_EXPECT_NO_ERROR (gl.getError(), "draw primitives");
382
383 // read pixels
384 if (m_renderTarget == RENDERTARGET_RBO_MULTISAMPLE)
385 {
386 // resolve msaa
387 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo);
388 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_blitDstFbo);
389
390 gl.blitFramebuffer(0, 0, m_renderSize, m_renderSize, 0, 0, m_renderSize, m_renderSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
391 GLU_EXPECT_NO_ERROR(gl.getError(), "blit");
392
393 // read resolved
394 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_blitDstFbo);
395
396 glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
397 GLU_EXPECT_NO_ERROR(gl.getError(), "read pixels");
398
399 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
400 }
401 else
402 {
403 glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
404 GLU_EXPECT_NO_ERROR (gl.getError(), "read pixels");
405 }
406 }
407
getLineWidth(void) const408 float BaseRenderingCase::getLineWidth (void) const
409 {
410 return 1.0f;
411 }
412
getPointSize(void) const413 float BaseRenderingCase::getPointSize (void) const
414 {
415 return 1.0f;
416 }
417
getPixelFormat(void) const418 const tcu::PixelFormat& BaseRenderingCase::getPixelFormat (void) const
419 {
420 return m_pixelFormat;
421 }
422
423 class BaseTriangleCase : public BaseRenderingCase
424 {
425 public:
426 BaseTriangleCase (Context& context, const char* name, const char* desc, glw::GLenum primitiveDrawType, BaseRenderingCase::RenderTarget renderTarget, int numSamples);
427 ~BaseTriangleCase (void);
428 IterateResult iterate (void);
429
430 private:
431 virtual void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles) = DE_NULL;
432
433 int m_iteration;
434 const int m_iterationCount;
435 const glw::GLenum m_primitiveDrawType;
436 bool m_allIterationsPassed;
437 };
438
BaseTriangleCase(Context & context,const char * name,const char * desc,glw::GLenum primitiveDrawType,BaseRenderingCase::RenderTarget renderTarget,int numSamples)439 BaseTriangleCase::BaseTriangleCase (Context& context, const char* name, const char* desc, glw::GLenum primitiveDrawType, BaseRenderingCase::RenderTarget renderTarget, int numSamples)
440 : BaseRenderingCase (context, name, desc, renderTarget, numSamples, DEFAULT_RENDER_SIZE)
441 , m_iteration (0)
442 , m_iterationCount (3)
443 , m_primitiveDrawType (primitiveDrawType)
444 , m_allIterationsPassed (true)
445 {
446 }
447
~BaseTriangleCase(void)448 BaseTriangleCase::~BaseTriangleCase (void)
449 {
450 }
451
iterate(void)452 BaseTriangleCase::IterateResult BaseTriangleCase::iterate (void)
453 {
454 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
455 const tcu::ScopedLogSection section (m_testCtx.getLog(), iterationDescription, iterationDescription);
456 tcu::Surface resultImage (m_renderSize, m_renderSize);
457 std::vector<tcu::Vec4> drawBuffer;
458 std::vector<TriangleSceneSpec::SceneTriangle> triangles;
459
460 generateTriangles(m_iteration, drawBuffer, triangles);
461
462 // draw image
463 drawPrimitives(resultImage, drawBuffer, m_primitiveDrawType);
464
465 // compare
466 {
467 bool compareOk;
468 RasterizationArguments args;
469 TriangleSceneSpec scene;
470
471 args.numSamples = m_numSamples;
472 args.subpixelBits = m_subpixelBits;
473 args.redBits = getPixelFormat().redBits;
474 args.greenBits = getPixelFormat().greenBits;
475 args.blueBits = getPixelFormat().blueBits;
476
477 scene.triangles.swap(triangles);
478
479 compareOk = verifyTriangleGroupRasterization(resultImage, scene, args, m_testCtx.getLog());
480
481 if (!compareOk)
482 m_allIterationsPassed = false;
483 }
484
485 // result
486 if (++m_iteration == m_iterationCount)
487 {
488 if (m_allIterationsPassed)
489 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
490 else
491 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rasterization");
492
493 return STOP;
494 }
495 else
496 return CONTINUE;
497 }
498
499 class BaseLineCase : public BaseRenderingCase
500 {
501 public:
502 BaseLineCase (Context& context, const char* name, const char* desc, glw::GLenum primitiveDrawType, PrimitiveWideness wideness, BaseRenderingCase::RenderTarget renderTarget, int numSamples);
503 ~BaseLineCase (void);
504
505 void init (void);
506 IterateResult iterate (void);
507 float getLineWidth (void) const;
508
509 private:
510 virtual void generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines) = DE_NULL;
511
512 int m_iteration;
513 const int m_iterationCount;
514 const glw::GLenum m_primitiveDrawType;
515 const PrimitiveWideness m_primitiveWideness;
516 bool m_allIterationsPassed;
517 bool m_multisampleRelaxationRequired;
518 float m_maxLineWidth;
519 std::vector<float> m_lineWidths;
520 };
521
BaseLineCase(Context & context,const char * name,const char * desc,glw::GLenum primitiveDrawType,PrimitiveWideness wideness,BaseRenderingCase::RenderTarget renderTarget,int numSamples)522 BaseLineCase::BaseLineCase (Context& context, const char* name, const char* desc, glw::GLenum primitiveDrawType, PrimitiveWideness wideness, BaseRenderingCase::RenderTarget renderTarget, int numSamples)
523 : BaseRenderingCase (context, name, desc, renderTarget, numSamples, DEFAULT_RENDER_SIZE)
524 , m_iteration (0)
525 , m_iterationCount (3)
526 , m_primitiveDrawType (primitiveDrawType)
527 , m_primitiveWideness (wideness)
528 , m_allIterationsPassed (true)
529 , m_multisampleRelaxationRequired (false)
530 , m_maxLineWidth (1.0f)
531 {
532 DE_ASSERT(m_primitiveWideness < PRIMITIVEWIDENESS_LAST);
533 }
534
~BaseLineCase(void)535 BaseLineCase::~BaseLineCase (void)
536 {
537 }
538
init(void)539 void BaseLineCase::init (void)
540 {
541 // create line widths
542 if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW)
543 {
544 m_lineWidths.resize(m_iterationCount, 1.0f);
545 }
546 else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE)
547 {
548 float range[2] = { 0.0f, 0.0f };
549 m_context.getRenderContext().getFunctions().getFloatv(GL_ALIASED_LINE_WIDTH_RANGE, range);
550
551 m_testCtx.getLog() << tcu::TestLog::Message << "ALIASED_LINE_WIDTH_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
552
553 // no wide line support
554 if (range[1] <= 1.0f)
555 throw tcu::NotSupportedError("wide line support required");
556
557 // set hand picked sizes
558 m_lineWidths.push_back(5.0f);
559 m_lineWidths.push_back(10.0f);
560 m_lineWidths.push_back(range[1]);
561 DE_ASSERT((int)m_lineWidths.size() == m_iterationCount);
562
563 m_maxLineWidth = range[1];
564 }
565 else
566 DE_ASSERT(false);
567
568 // init parent
569 BaseRenderingCase::init();
570 }
571
iterate(void)572 BaseLineCase::IterateResult BaseLineCase::iterate (void)
573 {
574 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
575 const tcu::ScopedLogSection section (m_testCtx.getLog(), iterationDescription, iterationDescription);
576 const float lineWidth = getLineWidth();
577 tcu::Surface resultImage (m_renderSize, m_renderSize);
578 std::vector<tcu::Vec4> drawBuffer;
579 std::vector<LineSceneSpec::SceneLine> lines;
580
581 // supported?
582 if (lineWidth <= m_maxLineWidth)
583 {
584 // gen data
585 generateLines(m_iteration, drawBuffer, lines);
586
587 // draw image
588 drawPrimitives(resultImage, drawBuffer, m_primitiveDrawType);
589
590 // compare
591 {
592 bool compareOk;
593 RasterizationArguments args;
594 LineSceneSpec scene;
595
596 args.numSamples = m_numSamples;
597 args.subpixelBits = m_subpixelBits;
598 args.redBits = getPixelFormat().redBits;
599 args.greenBits = getPixelFormat().greenBits;
600 args.blueBits = getPixelFormat().blueBits;
601
602 scene.lines.swap(lines);
603 scene.lineWidth = lineWidth;
604
605 compareOk = verifyLineGroupRasterization(resultImage, scene, args, m_testCtx.getLog());
606
607 // multisampled wide lines might not be supported
608 if (scene.lineWidth != 1.0f && m_numSamples > 1 && !compareOk)
609 {
610 m_multisampleRelaxationRequired = true;
611 compareOk = true;
612 }
613
614 if (!compareOk)
615 m_allIterationsPassed = false;
616 }
617 }
618 else
619 m_testCtx.getLog() << tcu::TestLog::Message << "Line width " << lineWidth << " not supported, skipping iteration." << tcu::TestLog::EndMessage;
620
621 // result
622 if (++m_iteration == m_iterationCount)
623 {
624 if (m_allIterationsPassed && m_multisampleRelaxationRequired)
625 m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Rasterization of multisampled wide lines failed");
626 else if (m_allIterationsPassed)
627 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
628 else
629 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rasterization");
630
631 return STOP;
632 }
633 else
634 return CONTINUE;
635 }
636
getLineWidth(void) const637 float BaseLineCase::getLineWidth (void) const
638 {
639 return m_lineWidths[m_iteration];
640 }
641
642 class PointCase : public BaseRenderingCase
643 {
644 public:
645 PointCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness, BaseRenderingCase::RenderTarget renderTarget = RENDERTARGET_DEFAULT, int numSamples = -1);
646 ~PointCase (void);
647
648 void init (void);
649 IterateResult iterate (void);
650
651 protected:
652 float getPointSize (void) const;
653
654 private:
655 void generatePoints (int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints);
656
657 int m_iteration;
658 const int m_iterationCount;
659 const PrimitiveWideness m_primitiveWideness;
660 bool m_allIterationsPassed;
661
662 float m_maxPointSize;
663 std::vector<float> m_pointSizes;
664 };
665
PointCase(Context & context,const char * name,const char * desc,PrimitiveWideness wideness,BaseRenderingCase::RenderTarget renderTarget,int numSamples)666 PointCase::PointCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness, BaseRenderingCase::RenderTarget renderTarget, int numSamples)
667 : BaseRenderingCase (context, name, desc, renderTarget, numSamples, DEFAULT_RENDER_SIZE)
668 , m_iteration (0)
669 , m_iterationCount (3)
670 , m_primitiveWideness (wideness)
671 , m_allIterationsPassed (true)
672 , m_maxPointSize (1.0f)
673 {
674 }
675
~PointCase(void)676 PointCase::~PointCase (void)
677 {
678 }
679
init(void)680 void PointCase::init (void)
681 {
682 // create point sizes
683 if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW)
684 {
685 m_pointSizes.resize(m_iterationCount, 1.0f);
686 }
687 else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE)
688 {
689 float range[2] = { 0.0f, 0.0f };
690 m_context.getRenderContext().getFunctions().getFloatv(GL_ALIASED_POINT_SIZE_RANGE, range);
691
692 m_testCtx.getLog() << tcu::TestLog::Message << "GL_ALIASED_POINT_SIZE_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
693
694 // no wide line support
695 if (range[1] <= 1.0f)
696 throw tcu::NotSupportedError("wide point support required");
697
698 // set hand picked sizes
699 m_pointSizes.push_back(10.0f);
700 m_pointSizes.push_back(25.0f);
701 m_pointSizes.push_back(range[1]);
702 DE_ASSERT((int)m_pointSizes.size() == m_iterationCount);
703
704 m_maxPointSize = range[1];
705 }
706 else
707 DE_ASSERT(false);
708
709 // init parent
710 BaseRenderingCase::init();
711 }
712
iterate(void)713 PointCase::IterateResult PointCase::iterate (void)
714 {
715 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
716 const tcu::ScopedLogSection section (m_testCtx.getLog(), iterationDescription, iterationDescription);
717 const float pointSize = getPointSize();
718 tcu::Surface resultImage (m_renderSize, m_renderSize);
719 std::vector<tcu::Vec4> drawBuffer;
720 std::vector<PointSceneSpec::ScenePoint> points;
721
722 // supported?
723 if (pointSize <= m_maxPointSize)
724 {
725 // gen data
726 generatePoints(m_iteration, drawBuffer, points);
727
728 // draw image
729 drawPrimitives(resultImage, drawBuffer, GL_POINTS);
730
731 // compare
732 {
733 bool compareOk;
734 RasterizationArguments args;
735 PointSceneSpec scene;
736
737 args.numSamples = m_numSamples;
738 args.subpixelBits = m_subpixelBits;
739 args.redBits = getPixelFormat().redBits;
740 args.greenBits = getPixelFormat().greenBits;
741 args.blueBits = getPixelFormat().blueBits;
742
743 scene.points.swap(points);
744
745 compareOk = verifyPointGroupRasterization(resultImage, scene, args, m_testCtx.getLog());
746
747 if (!compareOk)
748 m_allIterationsPassed = false;
749 }
750 }
751 else
752 m_testCtx.getLog() << tcu::TestLog::Message << "Point size " << pointSize << " not supported, skipping iteration." << tcu::TestLog::EndMessage;
753
754 // result
755 if (++m_iteration == m_iterationCount)
756 {
757 if (m_allIterationsPassed)
758 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
759 else
760 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rasterization");
761
762 return STOP;
763 }
764 else
765 return CONTINUE;
766 }
767
getPointSize(void) const768 float PointCase::getPointSize (void) const
769 {
770 return m_pointSizes[m_iteration];
771 }
772
generatePoints(int iteration,std::vector<tcu::Vec4> & outData,std::vector<PointSceneSpec::ScenePoint> & outPoints)773 void PointCase::generatePoints (int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints)
774 {
775 outData.resize(6);
776
777 switch (iteration)
778 {
779 case 0:
780 // \note: these values are chosen arbitrarily
781 outData[0] = tcu::Vec4( 0.2f, 0.8f, 0.0f, 1.0f);
782 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f);
783 outData[2] = tcu::Vec4( 0.5f, 0.3f, 0.0f, 1.0f);
784 outData[3] = tcu::Vec4(-0.5f, 0.2f, 0.0f, 1.0f);
785 outData[4] = tcu::Vec4(-0.2f, -0.4f, 0.0f, 1.0f);
786 outData[5] = tcu::Vec4(-0.4f, 0.2f, 0.0f, 1.0f);
787 break;
788
789 case 1:
790 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
791 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f);
792 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f);
793 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
794 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f);
795 outData[5] = tcu::Vec4( 0.4f, 1.2f, 0.0f, 1.0f);
796 break;
797
798 case 2:
799 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
800 outData[1] = tcu::Vec4( 0.3f, -0.9f, 0.0f, 1.0f);
801 outData[2] = tcu::Vec4( -0.4f, -0.1f, 0.0f, 1.0f);
802 outData[3] = tcu::Vec4(-0.11f, 0.2f, 0.0f, 1.0f);
803 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f);
804 outData[5] = tcu::Vec4( -0.4f, 0.4f, 0.0f, 1.0f);
805 break;
806 }
807
808 outPoints.resize(outData.size());
809 for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
810 {
811 outPoints[pointNdx].position = outData[pointNdx];
812 outPoints[pointNdx].pointSize = getPointSize();
813 }
814
815 // log
816 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering " << outPoints.size() << " point(s): (point size = " << getPointSize() << ")" << tcu::TestLog::EndMessage;
817 for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
818 m_testCtx.getLog() << tcu::TestLog::Message << "Point " << (pointNdx+1) << ":\t" << outPoints[pointNdx].position << tcu::TestLog::EndMessage;
819 }
820
821 class TrianglesCase : public BaseTriangleCase
822 {
823 public:
824 TrianglesCase (Context& context, const char* name, const char* desc, BaseRenderingCase::RenderTarget renderTarget = RENDERTARGET_DEFAULT, int numSamples = -1);
825 ~TrianglesCase (void);
826
827 void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
828 };
829
TrianglesCase(Context & context,const char * name,const char * desc,BaseRenderingCase::RenderTarget renderTarget,int numSamples)830 TrianglesCase::TrianglesCase (Context& context, const char* name, const char* desc, BaseRenderingCase::RenderTarget renderTarget, int numSamples)
831 : BaseTriangleCase(context, name, desc, GL_TRIANGLES, renderTarget, numSamples)
832 {
833 }
834
~TrianglesCase(void)835 TrianglesCase::~TrianglesCase (void)
836 {
837
838 }
839
generateTriangles(int iteration,std::vector<tcu::Vec4> & outData,std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles)840 void TrianglesCase::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
841 {
842 outData.resize(6);
843
844 switch (iteration)
845 {
846 case 0:
847 // \note: these values are chosen arbitrarily
848 outData[0] = tcu::Vec4( 0.2f, 0.8f, 0.0f, 1.0f);
849 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f);
850 outData[2] = tcu::Vec4( 0.5f, 0.3f, 0.0f, 1.0f);
851 outData[3] = tcu::Vec4(-0.5f, 0.2f, 0.0f, 1.0f);
852 outData[4] = tcu::Vec4(-1.5f, -0.4f, 0.0f, 1.0f);
853 outData[5] = tcu::Vec4(-0.4f, 0.2f, 0.0f, 1.0f);
854 break;
855
856 case 1:
857 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
858 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f);
859 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f);
860 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
861 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f);
862 outData[5] = tcu::Vec4( 0.4f, 1.2f, 0.0f, 1.0f);
863 break;
864
865 case 2:
866 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
867 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f);
868 outData[2] = tcu::Vec4( -1.1f, -0.1f, 0.0f, 1.0f);
869 outData[3] = tcu::Vec4(-0.11f, 0.2f, 0.0f, 1.0f);
870 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f);
871 outData[5] = tcu::Vec4( -0.4f, 0.4f, 0.0f, 1.0f);
872 break;
873 }
874
875 outTriangles.resize(2);
876 outTriangles[0].positions[0] = outData[0]; outTriangles[0].sharedEdge[0] = false;
877 outTriangles[0].positions[1] = outData[1]; outTriangles[0].sharedEdge[1] = false;
878 outTriangles[0].positions[2] = outData[2]; outTriangles[0].sharedEdge[2] = false;
879
880 outTriangles[1].positions[0] = outData[3]; outTriangles[1].sharedEdge[0] = false;
881 outTriangles[1].positions[1] = outData[4]; outTriangles[1].sharedEdge[1] = false;
882 outTriangles[1].positions[2] = outData[5]; outTriangles[1].sharedEdge[2] = false;
883
884 // log
885 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering " << outTriangles.size() << " triangle(s):" << tcu::TestLog::EndMessage;
886 for (int triangleNdx = 0; triangleNdx < (int)outTriangles.size(); ++triangleNdx)
887 {
888 m_testCtx.getLog()
889 << tcu::TestLog::Message
890 << "Triangle " << (triangleNdx+1) << ":"
891 << "\n\t" << outTriangles[triangleNdx].positions[0]
892 << "\n\t" << outTriangles[triangleNdx].positions[1]
893 << "\n\t" << outTriangles[triangleNdx].positions[2]
894 << tcu::TestLog::EndMessage;
895 }
896 }
897
898 class TriangleStripCase : public BaseTriangleCase
899 {
900 public:
901 TriangleStripCase (Context& context, const char* name, const char* desc, BaseRenderingCase::RenderTarget renderTarget = RENDERTARGET_DEFAULT, int numSamples = -1);
902
903 void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
904 };
905
TriangleStripCase(Context & context,const char * name,const char * desc,BaseRenderingCase::RenderTarget renderTarget,int numSamples)906 TriangleStripCase::TriangleStripCase (Context& context, const char* name, const char* desc, BaseRenderingCase::RenderTarget renderTarget, int numSamples)
907 : BaseTriangleCase(context, name, desc, GL_TRIANGLE_STRIP, renderTarget, numSamples)
908 {
909 }
910
generateTriangles(int iteration,std::vector<tcu::Vec4> & outData,std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles)911 void TriangleStripCase::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
912 {
913 outData.resize(5);
914
915 switch (iteration)
916 {
917 case 0:
918 // \note: these values are chosen arbitrarily
919 outData[0] = tcu::Vec4(-0.504f, 0.8f, 0.0f, 1.0f);
920 outData[1] = tcu::Vec4(-0.2f, -0.2f, 0.0f, 1.0f);
921 outData[2] = tcu::Vec4(-0.2f, 0.199f, 0.0f, 1.0f);
922 outData[3] = tcu::Vec4( 0.5f, 0.201f, 0.0f, 1.0f);
923 outData[4] = tcu::Vec4( 1.5f, 0.4f, 0.0f, 1.0f);
924 break;
925
926 case 1:
927 outData[0] = tcu::Vec4(-0.499f, 0.129f, 0.0f, 1.0f);
928 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f);
929 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f);
930 outData[3] = tcu::Vec4( 0.11f, -0.31f, 0.0f, 1.0f);
931 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f);
932 break;
933
934 case 2:
935 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
936 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f);
937 outData[2] = tcu::Vec4(-0.87f, -0.1f, 0.0f, 1.0f);
938 outData[3] = tcu::Vec4(-0.11f, 0.19f, 0.0f, 1.0f);
939 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f);
940 break;
941 }
942
943 outTriangles.resize(3);
944 outTriangles[0].positions[0] = outData[0]; outTriangles[0].sharedEdge[0] = false;
945 outTriangles[0].positions[1] = outData[1]; outTriangles[0].sharedEdge[1] = true;
946 outTriangles[0].positions[2] = outData[2]; outTriangles[0].sharedEdge[2] = false;
947
948 outTriangles[1].positions[0] = outData[2]; outTriangles[1].sharedEdge[0] = true;
949 outTriangles[1].positions[1] = outData[1]; outTriangles[1].sharedEdge[1] = false;
950 outTriangles[1].positions[2] = outData[3]; outTriangles[1].sharedEdge[2] = true;
951
952 outTriangles[2].positions[0] = outData[2]; outTriangles[2].sharedEdge[0] = true;
953 outTriangles[2].positions[1] = outData[3]; outTriangles[2].sharedEdge[1] = false;
954 outTriangles[2].positions[2] = outData[4]; outTriangles[2].sharedEdge[2] = false;
955
956 // log
957 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering triangle strip, " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
958 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
959 {
960 m_testCtx.getLog()
961 << tcu::TestLog::Message
962 << "\t" << outData[vtxNdx]
963 << tcu::TestLog::EndMessage;
964 }
965 }
966
967 class TriangleFanCase : public BaseTriangleCase
968 {
969 public:
970 TriangleFanCase (Context& context, const char* name, const char* desc, BaseRenderingCase::RenderTarget renderTarget = RENDERTARGET_DEFAULT, int numSamples = -1);
971
972 void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
973 };
974
TriangleFanCase(Context & context,const char * name,const char * desc,BaseRenderingCase::RenderTarget renderTarget,int numSamples)975 TriangleFanCase::TriangleFanCase (Context& context, const char* name, const char* desc, BaseRenderingCase::RenderTarget renderTarget, int numSamples)
976 : BaseTriangleCase(context, name, desc, GL_TRIANGLE_FAN, renderTarget, numSamples)
977 {
978 }
979
generateTriangles(int iteration,std::vector<tcu::Vec4> & outData,std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles)980 void TriangleFanCase::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
981 {
982 outData.resize(5);
983
984 switch (iteration)
985 {
986 case 0:
987 // \note: these values are chosen arbitrarily
988 outData[0] = tcu::Vec4( 0.01f, 0.0f, 0.0f, 1.0f);
989 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f);
990 outData[2] = tcu::Vec4( 0.46f, 0.3f, 0.0f, 1.0f);
991 outData[3] = tcu::Vec4(-0.5f, 0.2f, 0.0f, 1.0f);
992 outData[4] = tcu::Vec4(-1.5f, -0.4f, 0.0f, 1.0f);
993 break;
994
995 case 1:
996 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
997 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f);
998 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f);
999 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
1000 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f);
1001 break;
1002
1003 case 2:
1004 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
1005 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f);
1006 outData[2] = tcu::Vec4( 0.7f, -0.1f, 0.0f, 1.0f);
1007 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
1008 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f);
1009 break;
1010 }
1011
1012 outTriangles.resize(3);
1013 outTriangles[0].positions[0] = outData[0]; outTriangles[0].sharedEdge[0] = false;
1014 outTriangles[0].positions[1] = outData[1]; outTriangles[0].sharedEdge[1] = false;
1015 outTriangles[0].positions[2] = outData[2]; outTriangles[0].sharedEdge[2] = true;
1016
1017 outTriangles[1].positions[0] = outData[0]; outTriangles[1].sharedEdge[0] = true;
1018 outTriangles[1].positions[1] = outData[2]; outTriangles[1].sharedEdge[1] = false;
1019 outTriangles[1].positions[2] = outData[3]; outTriangles[1].sharedEdge[2] = true;
1020
1021 outTriangles[2].positions[0] = outData[0]; outTriangles[2].sharedEdge[0] = true;
1022 outTriangles[2].positions[1] = outData[3]; outTriangles[2].sharedEdge[1] = false;
1023 outTriangles[2].positions[2] = outData[4]; outTriangles[2].sharedEdge[2] = false;
1024
1025 // log
1026 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering triangle fan, " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
1027 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
1028 {
1029 m_testCtx.getLog()
1030 << tcu::TestLog::Message
1031 << "\t" << outData[vtxNdx]
1032 << tcu::TestLog::EndMessage;
1033 }
1034 }
1035
1036 class LinesCase : public BaseLineCase
1037 {
1038 public:
1039 LinesCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness, BaseRenderingCase::RenderTarget renderTarget = RENDERTARGET_DEFAULT, int numSamples = -1);
1040
1041 void generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
1042 };
1043
LinesCase(Context & context,const char * name,const char * desc,PrimitiveWideness wideness,BaseRenderingCase::RenderTarget renderTarget,int numSamples)1044 LinesCase::LinesCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness, BaseRenderingCase::RenderTarget renderTarget, int numSamples)
1045 : BaseLineCase(context, name, desc, GL_LINES, wideness, renderTarget, numSamples)
1046 {
1047 }
1048
generateLines(int iteration,std::vector<tcu::Vec4> & outData,std::vector<LineSceneSpec::SceneLine> & outLines)1049 void LinesCase::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
1050 {
1051 outData.resize(6);
1052
1053 switch (iteration)
1054 {
1055 case 0:
1056 // \note: these values are chosen arbitrarily
1057 outData[0] = tcu::Vec4( 0.01f, 0.0f, 0.0f, 1.0f);
1058 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f);
1059 outData[2] = tcu::Vec4( 0.46f, 0.3f, 0.0f, 1.0f);
1060 outData[3] = tcu::Vec4(-0.3f, 0.2f, 0.0f, 1.0f);
1061 outData[4] = tcu::Vec4(-1.5f, -0.4f, 0.0f, 1.0f);
1062 outData[5] = tcu::Vec4( 0.1f, 0.5f, 0.0f, 1.0f);
1063 break;
1064
1065 case 1:
1066 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
1067 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f);
1068 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f);
1069 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
1070 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f);
1071 outData[5] = tcu::Vec4( 0.18f, -0.2f, 0.0f, 1.0f);
1072 break;
1073
1074 case 2:
1075 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
1076 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f);
1077 outData[2] = tcu::Vec4( 0.7f, -0.1f, 0.0f, 1.0f);
1078 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
1079 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f);
1080 outData[5] = tcu::Vec4( 0.8f, -0.7f, 0.0f, 1.0f);
1081 break;
1082 }
1083
1084 outLines.resize(3);
1085 outLines[0].positions[0] = outData[0];
1086 outLines[0].positions[1] = outData[1];
1087 outLines[1].positions[0] = outData[2];
1088 outLines[1].positions[1] = outData[3];
1089 outLines[2].positions[0] = outData[4];
1090 outLines[2].positions[1] = outData[5];
1091
1092 // log
1093 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering " << outLines.size() << " lines(s): (width = " << getLineWidth() << ")" << tcu::TestLog::EndMessage;
1094 for (int lineNdx = 0; lineNdx < (int)outLines.size(); ++lineNdx)
1095 {
1096 m_testCtx.getLog()
1097 << tcu::TestLog::Message
1098 << "Line " << (lineNdx+1) << ":"
1099 << "\n\t" << outLines[lineNdx].positions[0]
1100 << "\n\t" << outLines[lineNdx].positions[1]
1101 << tcu::TestLog::EndMessage;
1102 }
1103 }
1104
1105 class LineStripCase : public BaseLineCase
1106 {
1107 public:
1108 LineStripCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness, BaseRenderingCase::RenderTarget renderTarget = RENDERTARGET_DEFAULT, int numSamples = -1);
1109
1110 void generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
1111 };
1112
LineStripCase(Context & context,const char * name,const char * desc,PrimitiveWideness wideness,BaseRenderingCase::RenderTarget renderTarget,int numSamples)1113 LineStripCase::LineStripCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness, BaseRenderingCase::RenderTarget renderTarget, int numSamples)
1114 : BaseLineCase(context, name, desc, GL_LINE_STRIP, wideness, renderTarget, numSamples)
1115 {
1116 }
1117
generateLines(int iteration,std::vector<tcu::Vec4> & outData,std::vector<LineSceneSpec::SceneLine> & outLines)1118 void LineStripCase::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
1119 {
1120 outData.resize(4);
1121
1122 switch (iteration)
1123 {
1124 case 0:
1125 // \note: these values are chosen arbitrarily
1126 outData[0] = tcu::Vec4( 0.01f, 0.0f, 0.0f, 1.0f);
1127 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f);
1128 outData[2] = tcu::Vec4( 0.46f, 0.3f, 0.0f, 1.0f);
1129 outData[3] = tcu::Vec4(-0.5f, 0.2f, 0.0f, 1.0f);
1130 break;
1131
1132 case 1:
1133 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
1134 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f);
1135 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f);
1136 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
1137 break;
1138
1139 case 2:
1140 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
1141 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f);
1142 outData[2] = tcu::Vec4( 0.7f, -0.1f, 0.0f, 1.0f);
1143 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
1144 break;
1145 }
1146
1147 outLines.resize(3);
1148 outLines[0].positions[0] = outData[0];
1149 outLines[0].positions[1] = outData[1];
1150 outLines[1].positions[0] = outData[1];
1151 outLines[1].positions[1] = outData[2];
1152 outLines[2].positions[0] = outData[2];
1153 outLines[2].positions[1] = outData[3];
1154
1155 // log
1156 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering line strip, width = " << getLineWidth() << ", " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
1157 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
1158 {
1159 m_testCtx.getLog()
1160 << tcu::TestLog::Message
1161 << "\t" << outData[vtxNdx]
1162 << tcu::TestLog::EndMessage;
1163 }
1164 }
1165
1166 class LineLoopCase : public BaseLineCase
1167 {
1168 public:
1169 LineLoopCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness, BaseRenderingCase::RenderTarget renderTarget = RENDERTARGET_DEFAULT, int numSamples = -1);
1170
1171 void generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
1172 };
1173
LineLoopCase(Context & context,const char * name,const char * desc,PrimitiveWideness wideness,BaseRenderingCase::RenderTarget renderTarget,int numSamples)1174 LineLoopCase::LineLoopCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness, BaseRenderingCase::RenderTarget renderTarget, int numSamples)
1175 : BaseLineCase(context, name, desc, GL_LINE_LOOP, wideness, renderTarget, numSamples)
1176 {
1177 }
1178
generateLines(int iteration,std::vector<tcu::Vec4> & outData,std::vector<LineSceneSpec::SceneLine> & outLines)1179 void LineLoopCase::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
1180 {
1181 outData.resize(4);
1182
1183 switch (iteration)
1184 {
1185 case 0:
1186 // \note: these values are chosen arbitrarily
1187 outData[0] = tcu::Vec4( 0.01f, 0.0f, 0.0f, 1.0f);
1188 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f);
1189 outData[2] = tcu::Vec4( 0.46f, 0.3f, 0.0f, 1.0f);
1190 outData[3] = tcu::Vec4(-0.5f, 0.2f, 0.0f, 1.0f);
1191 break;
1192
1193 case 1:
1194 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
1195 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f);
1196 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f);
1197 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
1198 break;
1199
1200 case 2:
1201 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
1202 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f);
1203 outData[2] = tcu::Vec4( 0.7f, -0.1f, 0.0f, 1.0f);
1204 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
1205 break;
1206 }
1207
1208 outLines.resize(4);
1209 outLines[0].positions[0] = outData[0];
1210 outLines[0].positions[1] = outData[1];
1211 outLines[1].positions[0] = outData[1];
1212 outLines[1].positions[1] = outData[2];
1213 outLines[2].positions[0] = outData[2];
1214 outLines[2].positions[1] = outData[3];
1215 outLines[3].positions[0] = outData[3];
1216 outLines[3].positions[1] = outData[0];
1217
1218 // log
1219 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering line loop, width = " << getLineWidth() << ", " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
1220 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
1221 {
1222 m_testCtx.getLog()
1223 << tcu::TestLog::Message
1224 << "\t" << outData[vtxNdx]
1225 << tcu::TestLog::EndMessage;
1226 }
1227 }
1228
1229 class FillRuleCase : public BaseRenderingCase
1230 {
1231 public:
1232 enum FillRuleCaseType
1233 {
1234 FILLRULECASE_BASIC = 0,
1235 FILLRULECASE_REVERSED,
1236 FILLRULECASE_CLIPPED_FULL,
1237 FILLRULECASE_CLIPPED_PARTIAL,
1238 FILLRULECASE_PROJECTED,
1239
1240 FILLRULECASE_LAST
1241 };
1242
1243 FillRuleCase (Context& ctx, const char* name, const char* desc, FillRuleCaseType type, RenderTarget renderTarget = RENDERTARGET_DEFAULT, int numSamples = -1);
1244 ~FillRuleCase (void);
1245 IterateResult iterate (void);
1246
1247 private:
1248 int getRenderSize (FillRuleCase::FillRuleCaseType type) const;
1249 int getNumIterations (FillRuleCase::FillRuleCaseType type) const;
1250 void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData) const;
1251
1252 const FillRuleCaseType m_caseType;
1253 int m_iteration;
1254 const int m_iterationCount;
1255 bool m_allIterationsPassed;
1256
1257 };
1258
FillRuleCase(Context & ctx,const char * name,const char * desc,FillRuleCaseType type,RenderTarget renderTarget,int numSamples)1259 FillRuleCase::FillRuleCase (Context& ctx, const char* name, const char* desc, FillRuleCaseType type, RenderTarget renderTarget, int numSamples)
1260 : BaseRenderingCase (ctx, name, desc, renderTarget, numSamples, getRenderSize(type))
1261 , m_caseType (type)
1262 , m_iteration (0)
1263 , m_iterationCount (getNumIterations(type))
1264 , m_allIterationsPassed (true)
1265 {
1266 DE_ASSERT(type < FILLRULECASE_LAST);
1267 }
1268
~FillRuleCase(void)1269 FillRuleCase::~FillRuleCase (void)
1270 {
1271 deinit();
1272 }
1273
iterate(void)1274 FillRuleCase::IterateResult FillRuleCase::iterate (void)
1275 {
1276 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
1277 const tcu::ScopedLogSection section (m_testCtx.getLog(), iterationDescription, iterationDescription);
1278 const int thresholdRed = 1 << (8 - getPixelFormat().redBits);
1279 const int thresholdGreen = 1 << (8 - getPixelFormat().greenBits);
1280 const int thresholdBlue = 1 << (8 - getPixelFormat().blueBits);
1281 tcu::Surface resultImage (m_renderSize, m_renderSize);
1282 std::vector<tcu::Vec4> drawBuffer;
1283 bool imageShown = false;
1284
1285 generateTriangles(m_iteration, drawBuffer);
1286
1287 // draw image
1288 {
1289 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1290 const std::vector<tcu::Vec4> colorBuffer (drawBuffer.size(), tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f));
1291
1292 m_testCtx.getLog() << tcu::TestLog::Message << "Drawing gray triangles with shared edges.\nEnabling additive blending to detect overlapping fragments." << tcu::TestLog::EndMessage;
1293
1294 gl.enable(GL_BLEND);
1295 gl.blendEquation(GL_FUNC_ADD);
1296 gl.blendFunc(GL_ONE, GL_ONE);
1297 drawPrimitives(resultImage, drawBuffer, colorBuffer, GL_TRIANGLES);
1298 }
1299
1300 // verify no overdraw
1301 {
1302 const tcu::RGBA triangleColor = tcu::RGBA(127, 127, 127, 255);
1303 bool overdraw = false;
1304
1305 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying result." << tcu::TestLog::EndMessage;
1306
1307 for (int y = 0; y < resultImage.getHeight(); ++y)
1308 for (int x = 0; x < resultImage.getWidth(); ++x)
1309 {
1310 const tcu::RGBA color = resultImage.getPixel(x, y);
1311
1312 // color values are greater than triangle color? Allow lower values for multisampled edges and background.
1313 if ((color.getRed() - triangleColor.getRed()) > thresholdRed ||
1314 (color.getGreen() - triangleColor.getGreen()) > thresholdGreen ||
1315 (color.getBlue() - triangleColor.getBlue()) > thresholdBlue)
1316 overdraw = true;
1317 }
1318
1319 // results
1320 if (!overdraw)
1321 m_testCtx.getLog() << tcu::TestLog::Message << "No overlapping fragments detected." << tcu::TestLog::EndMessage;
1322 else
1323 {
1324 m_testCtx.getLog() << tcu::TestLog::Message << "Overlapping fragments detected, image is not valid." << tcu::TestLog::EndMessage;
1325 m_testCtx.getLog() << tcu::TestLog::ImageSet("Result of rendering", "Result of rendering")
1326 << tcu::TestLog::Image("Result", "Result", resultImage)
1327 << tcu::TestLog::EndImageSet;
1328
1329 imageShown = true;
1330 m_allIterationsPassed = false;
1331 }
1332 }
1333
1334 // verify no missing fragments in the full viewport case
1335 if (m_caseType == FILLRULECASE_CLIPPED_FULL)
1336 {
1337 bool missingFragments = false;
1338
1339 m_testCtx.getLog() << tcu::TestLog::Message << "Searching missing fragments." << tcu::TestLog::EndMessage;
1340
1341 for (int y = 0; y < resultImage.getHeight(); ++y)
1342 for (int x = 0; x < resultImage.getWidth(); ++x)
1343 {
1344 const tcu::RGBA color = resultImage.getPixel(x, y);
1345
1346 // black? (background)
1347 if (color.getRed() <= thresholdRed ||
1348 color.getGreen() <= thresholdGreen ||
1349 color.getBlue() <= thresholdBlue)
1350 missingFragments = true;
1351 }
1352
1353 // results
1354 if (!missingFragments)
1355 m_testCtx.getLog() << tcu::TestLog::Message << "No missing fragments detected." << tcu::TestLog::EndMessage;
1356 else
1357 {
1358 m_testCtx.getLog() << tcu::TestLog::Message << "Missing fragments detected, image is not valid." << tcu::TestLog::EndMessage;
1359
1360 if (!imageShown)
1361 {
1362 m_testCtx.getLog() << tcu::TestLog::ImageSet("Result of rendering", "Result of rendering")
1363 << tcu::TestLog::Image("Result", "Result", resultImage)
1364 << tcu::TestLog::EndImageSet;
1365 }
1366
1367 m_allIterationsPassed = false;
1368 }
1369 }
1370
1371 // result
1372 if (++m_iteration == m_iterationCount)
1373 {
1374 if (m_allIterationsPassed)
1375 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1376 else
1377 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Found invalid pixels");
1378
1379 return STOP;
1380 }
1381 else
1382 return CONTINUE;
1383 }
1384
getRenderSize(FillRuleCase::FillRuleCaseType type) const1385 int FillRuleCase::getRenderSize (FillRuleCase::FillRuleCaseType type) const
1386 {
1387 if (type == FILLRULECASE_CLIPPED_FULL || type == FILLRULECASE_CLIPPED_PARTIAL)
1388 return DEFAULT_RENDER_SIZE / 4;
1389 else
1390 return DEFAULT_RENDER_SIZE;
1391 }
1392
getNumIterations(FillRuleCase::FillRuleCaseType type) const1393 int FillRuleCase::getNumIterations (FillRuleCase::FillRuleCaseType type) const
1394 {
1395 if (type == FILLRULECASE_CLIPPED_FULL || type == FILLRULECASE_CLIPPED_PARTIAL)
1396 return 15;
1397 else
1398 return 2;
1399 }
1400
generateTriangles(int iteration,std::vector<tcu::Vec4> & outData) const1401 void FillRuleCase::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData) const
1402 {
1403 switch (m_caseType)
1404 {
1405 case FILLRULECASE_BASIC:
1406 case FILLRULECASE_REVERSED:
1407 case FILLRULECASE_PROJECTED:
1408 {
1409 const int numRows = 4;
1410 const int numColumns = 4;
1411 const float quadSide = 0.15f;
1412 de::Random rnd (0xabcd);
1413
1414 outData.resize(6 * numRows * numColumns);
1415
1416 for (int col = 0; col < numColumns; ++col)
1417 for (int row = 0; row < numRows; ++row)
1418 {
1419 const tcu::Vec2 center = tcu::Vec2(((float)row + 0.5f) / (float)numRows * 2.0f - 1.0f, ((float)col + 0.5f) / (float)numColumns * 2.0f - 1.0f);
1420 const float rotation = (float)(iteration * numColumns * numRows + col * numRows + row) / (float)(m_iterationCount * numColumns * numRows) * DE_PI / 2.0f;
1421 const tcu::Vec2 sideH = quadSide * tcu::Vec2(deFloatCos(rotation), deFloatSin(rotation));
1422 const tcu::Vec2 sideV = tcu::Vec2(sideH.y(), -sideH.x());
1423 const tcu::Vec2 quad[4] =
1424 {
1425 center + sideH + sideV,
1426 center + sideH - sideV,
1427 center - sideH - sideV,
1428 center - sideH + sideV,
1429 };
1430
1431 if (m_caseType == FILLRULECASE_BASIC)
1432 {
1433 outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1434 outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
1435 outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1436 outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1437 outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1438 outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
1439 }
1440 else if (m_caseType == FILLRULECASE_REVERSED)
1441 {
1442 outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1443 outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
1444 outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1445 outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1446 outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1447 outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
1448 }
1449 else if (m_caseType == FILLRULECASE_PROJECTED)
1450 {
1451 const float w0 = rnd.getFloat(0.1f, 4.0f);
1452 const float w1 = rnd.getFloat(0.1f, 4.0f);
1453 const float w2 = rnd.getFloat(0.1f, 4.0f);
1454 const float w3 = rnd.getFloat(0.1f, 4.0f);
1455
1456 outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x() * w0, quad[0].y() * w0, 0.0f, w0);
1457 outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x() * w1, quad[1].y() * w1, 0.0f, w1);
1458 outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x() * w2, quad[2].y() * w2, 0.0f, w2);
1459 outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[2].x() * w2, quad[2].y() * w2, 0.0f, w2);
1460 outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[0].x() * w0, quad[0].y() * w0, 0.0f, w0);
1461 outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x() * w3, quad[3].y() * w3, 0.0f, w3);
1462 }
1463 else
1464 DE_ASSERT(DE_FALSE);
1465 }
1466
1467 break;
1468 }
1469
1470 case FILLRULECASE_CLIPPED_PARTIAL:
1471 case FILLRULECASE_CLIPPED_FULL:
1472 {
1473 const float quadSide = (m_caseType == FILLRULECASE_CLIPPED_PARTIAL) ? (1.0f) : (2.0f);
1474 const tcu::Vec2 center = (m_caseType == FILLRULECASE_CLIPPED_PARTIAL) ? (tcu::Vec2(0.5f, 0.5f)) : (tcu::Vec2(0.0f, 0.0f));
1475 const float rotation = (float)(iteration) / (float)(m_iterationCount - 1) * DE_PI / 2.0f;
1476 const tcu::Vec2 sideH = quadSide * tcu::Vec2(deFloatCos(rotation), deFloatSin(rotation));
1477 const tcu::Vec2 sideV = tcu::Vec2(sideH.y(), -sideH.x());
1478 const tcu::Vec2 quad[4] =
1479 {
1480 center + sideH + sideV,
1481 center + sideH - sideV,
1482 center - sideH - sideV,
1483 center - sideH + sideV,
1484 };
1485
1486 outData.resize(6);
1487 outData[0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1488 outData[1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
1489 outData[2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1490 outData[3] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1491 outData[4] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1492 outData[5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
1493 break;
1494 }
1495
1496 default:
1497 DE_ASSERT(DE_FALSE);
1498 }
1499 }
1500
1501 class CullingTest : public BaseRenderingCase
1502 {
1503 public:
1504 CullingTest (Context& ctx, const char* name, const char* desc, glw::GLenum cullMode, glw::GLenum primitive, glw::GLenum faceOrder);
1505 ~CullingTest (void);
1506 IterateResult iterate (void);
1507
1508 private:
1509 void generateVertices (std::vector<tcu::Vec4>& outData) const;
1510 void extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const;
1511 bool triangleOrder (const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) const;
1512
1513 const glw::GLenum m_cullMode;
1514 const glw::GLenum m_primitive;
1515 const glw::GLenum m_faceOrder;
1516 };
1517
CullingTest(Context & ctx,const char * name,const char * desc,glw::GLenum cullMode,glw::GLenum primitive,glw::GLenum faceOrder)1518 CullingTest::CullingTest (Context& ctx, const char* name, const char* desc, glw::GLenum cullMode, glw::GLenum primitive, glw::GLenum faceOrder)
1519 : BaseRenderingCase (ctx, name, desc, RENDERTARGET_DEFAULT, -1, DEFAULT_RENDER_SIZE)
1520 , m_cullMode (cullMode)
1521 , m_primitive (primitive)
1522 , m_faceOrder (faceOrder)
1523 {
1524 }
1525
~CullingTest(void)1526 CullingTest::~CullingTest (void)
1527 {
1528 }
1529
iterate(void)1530 CullingTest::IterateResult CullingTest::iterate (void)
1531 {
1532 tcu::Surface resultImage(m_renderSize, m_renderSize);
1533 std::vector<tcu::Vec4> drawBuffer;
1534 std::vector<TriangleSceneSpec::SceneTriangle> triangles;
1535
1536 // generate scene
1537 generateVertices(drawBuffer);
1538 extractTriangles(triangles, drawBuffer);
1539
1540 // draw image
1541 {
1542 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1543
1544 gl.enable(GL_CULL_FACE);
1545 gl.cullFace(m_cullMode);
1546 gl.frontFace(m_faceOrder);
1547
1548 m_testCtx.getLog() << tcu::TestLog::Message << "Setting front face to " << glu::getWindingName(m_faceOrder) << tcu::TestLog::EndMessage;
1549 m_testCtx.getLog() << tcu::TestLog::Message << "Setting cull face to " << glu::getFaceName(m_cullMode) << tcu::TestLog::EndMessage;
1550 m_testCtx.getLog() << tcu::TestLog::Message << "Drawing test pattern (" << glu::getPrimitiveTypeName(m_primitive) << ")" << tcu::TestLog::EndMessage;
1551
1552 drawPrimitives(resultImage, drawBuffer, m_primitive);
1553 }
1554
1555 // compare
1556 {
1557 RasterizationArguments args;
1558 TriangleSceneSpec scene;
1559
1560 args.numSamples = m_numSamples;
1561 args.subpixelBits = m_subpixelBits;
1562 args.redBits = getPixelFormat().redBits;
1563 args.greenBits = getPixelFormat().greenBits;
1564 args.blueBits = getPixelFormat().blueBits;
1565
1566 scene.triangles.swap(triangles);
1567
1568 if (verifyTriangleGroupRasterization(resultImage, scene, args, m_testCtx.getLog(), tcu::VERIFICATIONMODE_WEAK))
1569 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1570 else
1571 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rendering");
1572 }
1573
1574 return STOP;
1575 }
1576
generateVertices(std::vector<tcu::Vec4> & outData) const1577 void CullingTest::generateVertices (std::vector<tcu::Vec4>& outData) const
1578 {
1579 de::Random rnd(543210);
1580
1581 outData.resize(6);
1582 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
1583 {
1584 outData[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
1585 outData[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
1586 outData[vtxNdx].z() = 0.0f;
1587 outData[vtxNdx].w() = 1.0f;
1588 }
1589 }
1590
extractTriangles(std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles,const std::vector<tcu::Vec4> & vertices) const1591 void CullingTest::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const
1592 {
1593 const bool cullDirection = (m_cullMode == GL_FRONT) ^ (m_faceOrder == GL_CCW);
1594
1595 // No triangles
1596 if (m_cullMode == GL_FRONT_AND_BACK)
1597 return;
1598
1599 switch (m_primitive)
1600 {
1601 case GL_TRIANGLES:
1602 {
1603 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
1604 {
1605 const tcu::Vec4& v0 = vertices[vtxNdx + 0];
1606 const tcu::Vec4& v1 = vertices[vtxNdx + 1];
1607 const tcu::Vec4& v2 = vertices[vtxNdx + 2];
1608
1609 if (triangleOrder(v0, v1, v2) != cullDirection)
1610 {
1611 TriangleSceneSpec::SceneTriangle tri;
1612 tri.positions[0] = v0; tri.sharedEdge[0] = false;
1613 tri.positions[1] = v1; tri.sharedEdge[1] = false;
1614 tri.positions[2] = v2; tri.sharedEdge[2] = false;
1615
1616 outTriangles.push_back(tri);
1617 }
1618 }
1619 break;
1620 }
1621
1622 case GL_TRIANGLE_STRIP:
1623 {
1624 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
1625 {
1626 const tcu::Vec4& v0 = vertices[vtxNdx + 0];
1627 const tcu::Vec4& v1 = vertices[vtxNdx + 1];
1628 const tcu::Vec4& v2 = vertices[vtxNdx + 2];
1629
1630 if (triangleOrder(v0, v1, v2) != (cullDirection ^ (vtxNdx % 2 != 0)))
1631 {
1632 TriangleSceneSpec::SceneTriangle tri;
1633 tri.positions[0] = v0; tri.sharedEdge[0] = false;
1634 tri.positions[1] = v1; tri.sharedEdge[1] = false;
1635 tri.positions[2] = v2; tri.sharedEdge[2] = false;
1636
1637 outTriangles.push_back(tri);
1638 }
1639 }
1640 break;
1641 }
1642
1643 case GL_TRIANGLE_FAN:
1644 {
1645 for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
1646 {
1647 const tcu::Vec4& v0 = vertices[0];
1648 const tcu::Vec4& v1 = vertices[vtxNdx + 0];
1649 const tcu::Vec4& v2 = vertices[vtxNdx + 1];
1650
1651 if (triangleOrder(v0, v1, v2) != cullDirection)
1652 {
1653 TriangleSceneSpec::SceneTriangle tri;
1654 tri.positions[0] = v0; tri.sharedEdge[0] = false;
1655 tri.positions[1] = v1; tri.sharedEdge[1] = false;
1656 tri.positions[2] = v2; tri.sharedEdge[2] = false;
1657
1658 outTriangles.push_back(tri);
1659 }
1660 }
1661 break;
1662 }
1663
1664 default:
1665 DE_ASSERT(false);
1666 }
1667 }
1668
triangleOrder(const tcu::Vec4 & v0,const tcu::Vec4 & v1,const tcu::Vec4 & v2) const1669 bool CullingTest::triangleOrder (const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) const
1670 {
1671 const tcu::Vec2 s0 = v0.swizzle(0, 1) / v0.w();
1672 const tcu::Vec2 s1 = v1.swizzle(0, 1) / v1.w();
1673 const tcu::Vec2 s2 = v2.swizzle(0, 1) / v2.w();
1674
1675 // cross
1676 return ((s1.x() - s0.x()) * (s2.y() - s0.y()) - (s2.x() - s0.x()) * (s1.y() - s0.y())) < 0;
1677 }
1678
1679 class TriangleInterpolationTest : public BaseRenderingCase
1680 {
1681 public:
1682 TriangleInterpolationTest (Context& ctx, const char* name, const char* desc, glw::GLenum primitive, int flags, RenderTarget renderTarget = RENDERTARGET_DEFAULT, int numSamples = -1);
1683 ~TriangleInterpolationTest (void);
1684 IterateResult iterate (void);
1685
1686 private:
1687 void generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const;
1688 void extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
1689
1690 const glw::GLenum m_primitive;
1691 const bool m_projective;
1692 const int m_iterationCount;
1693
1694 int m_iteration;
1695 bool m_allIterationsPassed;
1696 };
1697
TriangleInterpolationTest(Context & ctx,const char * name,const char * desc,glw::GLenum primitive,int flags,RenderTarget renderTarget,int numSamples)1698 TriangleInterpolationTest::TriangleInterpolationTest (Context& ctx, const char* name, const char* desc, glw::GLenum primitive, int flags, RenderTarget renderTarget, int numSamples)
1699 : BaseRenderingCase (ctx, name, desc, renderTarget, numSamples, DEFAULT_RENDER_SIZE)
1700 , m_primitive (primitive)
1701 , m_projective ((flags & INTERPOLATIONFLAGS_PROJECTED) != 0)
1702 , m_iterationCount (3)
1703 , m_iteration (0)
1704 , m_allIterationsPassed (true)
1705 {
1706 m_flatshade = ((flags & INTERPOLATIONFLAGS_FLATSHADE) != 0);
1707 }
1708
~TriangleInterpolationTest(void)1709 TriangleInterpolationTest::~TriangleInterpolationTest (void)
1710 {
1711 deinit();
1712 }
1713
iterate(void)1714 TriangleInterpolationTest::IterateResult TriangleInterpolationTest::iterate (void)
1715 {
1716 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
1717 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription);
1718 tcu::Surface resultImage (m_renderSize, m_renderSize);
1719 std::vector<tcu::Vec4> drawBuffer;
1720 std::vector<tcu::Vec4> colorBuffer;
1721 std::vector<TriangleSceneSpec::SceneTriangle> triangles;
1722
1723 // generate scene
1724 generateVertices(m_iteration, drawBuffer, colorBuffer);
1725 extractTriangles(triangles, drawBuffer, colorBuffer);
1726
1727 // log
1728 {
1729 m_testCtx.getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage;
1730 for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx)
1731 m_testCtx.getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage;
1732 }
1733
1734 // draw image
1735 drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitive);
1736
1737 // compare
1738 {
1739 RasterizationArguments args;
1740 TriangleSceneSpec scene;
1741
1742 args.numSamples = m_numSamples;
1743 args.subpixelBits = m_subpixelBits;
1744 args.redBits = getPixelFormat().redBits;
1745 args.greenBits = getPixelFormat().greenBits;
1746 args.blueBits = getPixelFormat().blueBits;
1747
1748 scene.triangles.swap(triangles);
1749
1750 if (!verifyTriangleGroupInterpolation(resultImage, scene, args, m_testCtx.getLog()))
1751 m_allIterationsPassed = false;
1752 }
1753
1754 // result
1755 if (++m_iteration == m_iterationCount)
1756 {
1757 if (m_allIterationsPassed)
1758 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1759 else
1760 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Found invalid pixel values");
1761
1762 return STOP;
1763 }
1764 else
1765 return CONTINUE;
1766 }
1767
generateVertices(int iteration,std::vector<tcu::Vec4> & outVertices,std::vector<tcu::Vec4> & outColors) const1768 void TriangleInterpolationTest::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const
1769 {
1770 // use only red, green and blue
1771 const tcu::Vec4 colors[] =
1772 {
1773 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
1774 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
1775 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
1776 };
1777
1778 de::Random rnd(123 + iteration * 1000 + (int)m_primitive);
1779
1780 outVertices.resize(6);
1781 outColors.resize(6);
1782
1783 for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx)
1784 {
1785 outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
1786 outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
1787 outVertices[vtxNdx].z() = 0.0f;
1788
1789 if (!m_projective)
1790 outVertices[vtxNdx].w() = 1.0f;
1791 else
1792 {
1793 const float w = rnd.getFloat(0.2f, 4.0f);
1794
1795 outVertices[vtxNdx].x() *= w;
1796 outVertices[vtxNdx].y() *= w;
1797 outVertices[vtxNdx].z() *= w;
1798 outVertices[vtxNdx].w() = w;
1799 }
1800
1801 outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)];
1802 }
1803 }
1804
extractTriangles(std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles,const std::vector<tcu::Vec4> & vertices,const std::vector<tcu::Vec4> & colors) const1805 void TriangleInterpolationTest::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
1806 {
1807 switch (m_primitive)
1808 {
1809 case GL_TRIANGLES:
1810 {
1811 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
1812 {
1813 TriangleSceneSpec::SceneTriangle tri;
1814 tri.positions[0] = vertices[vtxNdx + 0];
1815 tri.positions[1] = vertices[vtxNdx + 1];
1816 tri.positions[2] = vertices[vtxNdx + 2];
1817 tri.sharedEdge[0] = false;
1818 tri.sharedEdge[1] = false;
1819 tri.sharedEdge[2] = false;
1820
1821 if (m_flatshade)
1822 {
1823 tri.colors[0] = colors[vtxNdx + 2];
1824 tri.colors[1] = colors[vtxNdx + 2];
1825 tri.colors[2] = colors[vtxNdx + 2];
1826 }
1827 else
1828 {
1829 tri.colors[0] = colors[vtxNdx + 0];
1830 tri.colors[1] = colors[vtxNdx + 1];
1831 tri.colors[2] = colors[vtxNdx + 2];
1832 }
1833
1834 outTriangles.push_back(tri);
1835 }
1836 break;
1837 }
1838
1839 case GL_TRIANGLE_STRIP:
1840 {
1841 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
1842 {
1843 TriangleSceneSpec::SceneTriangle tri;
1844 tri.positions[0] = vertices[vtxNdx + 0];
1845 tri.positions[1] = vertices[vtxNdx + 1];
1846 tri.positions[2] = vertices[vtxNdx + 2];
1847 tri.sharedEdge[0] = false;
1848 tri.sharedEdge[1] = false;
1849 tri.sharedEdge[2] = false;
1850
1851 if (m_flatshade)
1852 {
1853 tri.colors[0] = colors[vtxNdx + 2];
1854 tri.colors[1] = colors[vtxNdx + 2];
1855 tri.colors[2] = colors[vtxNdx + 2];
1856 }
1857 else
1858 {
1859 tri.colors[0] = colors[vtxNdx + 0];
1860 tri.colors[1] = colors[vtxNdx + 1];
1861 tri.colors[2] = colors[vtxNdx + 2];
1862 }
1863
1864 outTriangles.push_back(tri);
1865 }
1866 break;
1867 }
1868
1869 case GL_TRIANGLE_FAN:
1870 {
1871 for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
1872 {
1873 TriangleSceneSpec::SceneTriangle tri;
1874 tri.positions[0] = vertices[0];
1875 tri.positions[1] = vertices[vtxNdx + 0];
1876 tri.positions[2] = vertices[vtxNdx + 1];
1877 tri.sharedEdge[0] = false;
1878 tri.sharedEdge[1] = false;
1879 tri.sharedEdge[2] = false;
1880
1881 if (m_flatshade)
1882 {
1883 tri.colors[0] = colors[vtxNdx + 1];
1884 tri.colors[1] = colors[vtxNdx + 1];
1885 tri.colors[2] = colors[vtxNdx + 1];
1886 }
1887 else
1888 {
1889 tri.colors[0] = colors[0];
1890 tri.colors[1] = colors[vtxNdx + 0];
1891 tri.colors[2] = colors[vtxNdx + 1];
1892 }
1893
1894 outTriangles.push_back(tri);
1895 }
1896 break;
1897 }
1898
1899 default:
1900 DE_ASSERT(false);
1901 }
1902 }
1903
1904 class LineInterpolationTest : public BaseRenderingCase
1905 {
1906 public:
1907 LineInterpolationTest (Context& ctx, const char* name, const char* desc, glw::GLenum primitive, int flags, PrimitiveWideness wideness, RenderTarget renderTarget = RENDERTARGET_DEFAULT, int numSamples = -1);
1908 ~LineInterpolationTest (void);
1909
1910 void init (void);
1911 IterateResult iterate (void);
1912
1913 private:
1914 void generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const;
1915 void extractLines (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
1916 float getLineWidth (void) const;
1917
1918 const glw::GLenum m_primitive;
1919 const bool m_projective;
1920 const int m_iterationCount;
1921 const PrimitiveWideness m_primitiveWideness;
1922
1923 int m_iteration;
1924 tcu::ResultCollector m_result;
1925 float m_maxLineWidth;
1926 std::vector<float> m_lineWidths;
1927 };
1928
LineInterpolationTest(Context & ctx,const char * name,const char * desc,glw::GLenum primitive,int flags,PrimitiveWideness wideness,RenderTarget renderTarget,int numSamples)1929 LineInterpolationTest::LineInterpolationTest (Context& ctx, const char* name, const char* desc, glw::GLenum primitive, int flags, PrimitiveWideness wideness, RenderTarget renderTarget, int numSamples)
1930 : BaseRenderingCase (ctx, name, desc, renderTarget, numSamples, DEFAULT_RENDER_SIZE)
1931 , m_primitive (primitive)
1932 , m_projective ((flags & INTERPOLATIONFLAGS_PROJECTED) != 0)
1933 , m_iterationCount (3)
1934 , m_primitiveWideness (wideness)
1935 , m_iteration (0)
1936 , m_maxLineWidth (1.0f)
1937 {
1938 m_flatshade = ((flags & INTERPOLATIONFLAGS_FLATSHADE) != 0);
1939 }
1940
~LineInterpolationTest(void)1941 LineInterpolationTest::~LineInterpolationTest (void)
1942 {
1943 deinit();
1944 }
1945
init(void)1946 void LineInterpolationTest::init (void)
1947 {
1948 // create line widths
1949 if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW)
1950 {
1951 m_lineWidths.resize(m_iterationCount, 1.0f);
1952 }
1953 else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE)
1954 {
1955 float range[2] = { 0.0f, 0.0f };
1956 m_context.getRenderContext().getFunctions().getFloatv(GL_ALIASED_LINE_WIDTH_RANGE, range);
1957
1958 m_testCtx.getLog() << tcu::TestLog::Message << "ALIASED_LINE_WIDTH_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
1959
1960 // no wide line support
1961 if (range[1] <= 1.0f)
1962 throw tcu::NotSupportedError("wide line support required");
1963
1964 // set hand picked sizes
1965 m_lineWidths.push_back(5.0f);
1966 m_lineWidths.push_back(10.0f);
1967 m_lineWidths.push_back(range[1]);
1968 DE_ASSERT((int)m_lineWidths.size() == m_iterationCount);
1969
1970 m_maxLineWidth = range[1];
1971 }
1972 else
1973 DE_ASSERT(false);
1974
1975 // init parent
1976 BaseRenderingCase::init();
1977 }
1978
iterate(void)1979 LineInterpolationTest::IterateResult LineInterpolationTest::iterate (void)
1980 {
1981 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
1982 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription);
1983 const float lineWidth = getLineWidth();
1984 tcu::Surface resultImage (m_renderSize, m_renderSize);
1985 std::vector<tcu::Vec4> drawBuffer;
1986 std::vector<tcu::Vec4> colorBuffer;
1987 std::vector<LineSceneSpec::SceneLine> lines;
1988
1989 // supported?
1990 if (lineWidth <= m_maxLineWidth)
1991 {
1992 // generate scene
1993 generateVertices(m_iteration, drawBuffer, colorBuffer);
1994 extractLines(lines, drawBuffer, colorBuffer);
1995
1996 // log
1997 {
1998 m_testCtx.getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage;
1999 for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx)
2000 m_testCtx.getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage;
2001 }
2002
2003 // draw image
2004 drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitive);
2005
2006 // compare
2007 {
2008 RasterizationArguments args;
2009 LineSceneSpec scene;
2010 LineInterpolationMethod iterationResult;
2011
2012 args.numSamples = m_numSamples;
2013 args.subpixelBits = m_subpixelBits;
2014 args.redBits = getPixelFormat().redBits;
2015 args.greenBits = getPixelFormat().greenBits;
2016 args.blueBits = getPixelFormat().blueBits;
2017
2018 scene.lines.swap(lines);
2019 scene.lineWidth = getLineWidth();
2020
2021 iterationResult = verifyLineGroupInterpolation(resultImage, scene, args, m_testCtx.getLog());
2022 switch (iterationResult)
2023 {
2024 case tcu::LINEINTERPOLATION_STRICTLY_CORRECT:
2025 // line interpolation matches the specification
2026 m_result.addResult(QP_TEST_RESULT_PASS, "Pass");
2027 break;
2028
2029 case tcu::LINEINTERPOLATION_PROJECTED:
2030 // line interpolation weights are otherwise correct, but they are projected onto major axis
2031 m_testCtx.getLog() << tcu::TestLog::Message
2032 << "Interpolation was calculated using coordinates projected onto major axis. "
2033 "This method does not produce the same values as the non-projecting method defined in the specification."
2034 << tcu::TestLog::EndMessage;
2035 m_result.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Interpolation was calculated using projected coordinateds");
2036 break;
2037
2038 case tcu::LINEINTERPOLATION_INCORRECT:
2039 if (scene.lineWidth != 1.0f && m_numSamples > 1)
2040 {
2041 // multisampled wide lines might not be supported
2042 m_result.addResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Interpolation of multisampled wide lines failed");
2043 }
2044 else
2045 {
2046 // line interpolation is incorrect
2047 m_result.addResult(QP_TEST_RESULT_FAIL, "Found invalid pixel values");
2048 }
2049 break;
2050
2051 default:
2052 DE_ASSERT(false);
2053 break;
2054 }
2055 }
2056 }
2057 else
2058 m_testCtx.getLog() << tcu::TestLog::Message << "Line width " << lineWidth << " not supported, skipping iteration." << tcu::TestLog::EndMessage;
2059
2060 // result
2061 if (++m_iteration == m_iterationCount)
2062 {
2063 m_result.setTestContextResult(m_testCtx);
2064 return STOP;
2065 }
2066 else
2067 return CONTINUE;
2068 }
2069
generateVertices(int iteration,std::vector<tcu::Vec4> & outVertices,std::vector<tcu::Vec4> & outColors) const2070 void LineInterpolationTest::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const
2071 {
2072 // use only red, green and blue
2073 const tcu::Vec4 colors[] =
2074 {
2075 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
2076 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
2077 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
2078 };
2079
2080 de::Random rnd(123 + iteration * 1000 + (int)m_primitive);
2081
2082 outVertices.resize(6);
2083 outColors.resize(6);
2084
2085 for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx)
2086 {
2087 outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
2088 outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
2089 outVertices[vtxNdx].z() = 0.0f;
2090
2091 if (!m_projective)
2092 outVertices[vtxNdx].w() = 1.0f;
2093 else
2094 {
2095 const float w = rnd.getFloat(0.2f, 4.0f);
2096
2097 outVertices[vtxNdx].x() *= w;
2098 outVertices[vtxNdx].y() *= w;
2099 outVertices[vtxNdx].z() *= w;
2100 outVertices[vtxNdx].w() = w;
2101 }
2102
2103 outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)];
2104 }
2105 }
2106
extractLines(std::vector<LineSceneSpec::SceneLine> & outLines,const std::vector<tcu::Vec4> & vertices,const std::vector<tcu::Vec4> & colors) const2107 void LineInterpolationTest::extractLines (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
2108 {
2109 switch (m_primitive)
2110 {
2111 case GL_LINES:
2112 {
2113 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; vtxNdx += 2)
2114 {
2115 LineSceneSpec::SceneLine line;
2116 line.positions[0] = vertices[vtxNdx + 0];
2117 line.positions[1] = vertices[vtxNdx + 1];
2118
2119 if (m_flatshade)
2120 {
2121 line.colors[0] = colors[vtxNdx + 1];
2122 line.colors[1] = colors[vtxNdx + 1];
2123 }
2124 else
2125 {
2126 line.colors[0] = colors[vtxNdx + 0];
2127 line.colors[1] = colors[vtxNdx + 1];
2128 }
2129
2130 outLines.push_back(line);
2131 }
2132 break;
2133 }
2134
2135 case GL_LINE_STRIP:
2136 {
2137 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
2138 {
2139 LineSceneSpec::SceneLine line;
2140 line.positions[0] = vertices[vtxNdx + 0];
2141 line.positions[1] = vertices[vtxNdx + 1];
2142
2143 if (m_flatshade)
2144 {
2145 line.colors[0] = colors[vtxNdx + 1];
2146 line.colors[1] = colors[vtxNdx + 1];
2147 }
2148 else
2149 {
2150 line.colors[0] = colors[vtxNdx + 0];
2151 line.colors[1] = colors[vtxNdx + 1];
2152 }
2153
2154 outLines.push_back(line);
2155 }
2156 break;
2157 }
2158
2159 case GL_LINE_LOOP:
2160 {
2161 for (int vtxNdx = 0; vtxNdx < (int)vertices.size(); ++vtxNdx)
2162 {
2163 LineSceneSpec::SceneLine line;
2164 line.positions[0] = vertices[(vtxNdx + 0) % (int)vertices.size()];
2165 line.positions[1] = vertices[(vtxNdx + 1) % (int)vertices.size()];
2166
2167 if (m_flatshade)
2168 {
2169 line.colors[0] = colors[(vtxNdx + 1) % (int)vertices.size()];
2170 line.colors[1] = colors[(vtxNdx + 1) % (int)vertices.size()];
2171 }
2172 else
2173 {
2174 line.colors[0] = colors[(vtxNdx + 0) % (int)vertices.size()];
2175 line.colors[1] = colors[(vtxNdx + 1) % (int)vertices.size()];
2176 }
2177
2178 outLines.push_back(line);
2179 }
2180 break;
2181 }
2182
2183 default:
2184 DE_ASSERT(false);
2185 }
2186 }
2187
getLineWidth(void) const2188 float LineInterpolationTest::getLineWidth (void) const
2189 {
2190 return m_lineWidths[m_iteration];
2191 }
2192
2193 } // anonymous
2194
RasterizationTests(Context & context)2195 RasterizationTests::RasterizationTests (Context& context)
2196 : TestCaseGroup(context, "rasterization", "Rasterization Tests")
2197 {
2198 }
2199
~RasterizationTests(void)2200 RasterizationTests::~RasterizationTests (void)
2201 {
2202 }
2203
init(void)2204 void RasterizationTests::init (void)
2205 {
2206 // .primitives
2207 {
2208 tcu::TestCaseGroup* const primitives = new tcu::TestCaseGroup(m_testCtx, "primitives", "Primitive rasterization");
2209
2210 addChild(primitives);
2211
2212 primitives->addChild(new TrianglesCase (m_context, "triangles", "Render primitives as GL_TRIANGLES, verify rasterization result"));
2213 primitives->addChild(new TriangleStripCase (m_context, "triangle_strip", "Render primitives as GL_TRIANGLE_STRIP, verify rasterization result"));
2214 primitives->addChild(new TriangleFanCase (m_context, "triangle_fan", "Render primitives as GL_TRIANGLE_FAN, verify rasterization result"));
2215 primitives->addChild(new LinesCase (m_context, "lines", "Render primitives as GL_LINES, verify rasterization result", PRIMITIVEWIDENESS_NARROW));
2216 primitives->addChild(new LineStripCase (m_context, "line_strip", "Render primitives as GL_LINE_STRIP, verify rasterization result", PRIMITIVEWIDENESS_NARROW));
2217 primitives->addChild(new LineLoopCase (m_context, "line_loop", "Render primitives as GL_LINE_LOOP, verify rasterization result", PRIMITIVEWIDENESS_NARROW));
2218 primitives->addChild(new LinesCase (m_context, "lines_wide", "Render primitives as GL_LINES with wide lines, verify rasterization result", PRIMITIVEWIDENESS_WIDE));
2219 primitives->addChild(new LineStripCase (m_context, "line_strip_wide", "Render primitives as GL_LINE_STRIP with wide lines, verify rasterization result", PRIMITIVEWIDENESS_WIDE));
2220 primitives->addChild(new LineLoopCase (m_context, "line_loop_wide", "Render primitives as GL_LINE_LOOP with wide lines, verify rasterization result", PRIMITIVEWIDENESS_WIDE));
2221 primitives->addChild(new PointCase (m_context, "points", "Render primitives as GL_POINTS, verify rasterization result", PRIMITIVEWIDENESS_WIDE));
2222 }
2223
2224 // .fill_rules
2225 {
2226 tcu::TestCaseGroup* const fillRules = new tcu::TestCaseGroup(m_testCtx, "fill_rules", "Primitive fill rules");
2227
2228 addChild(fillRules);
2229
2230 fillRules->addChild(new FillRuleCase(m_context, "basic_quad", "Verify fill rules", FillRuleCase::FILLRULECASE_BASIC));
2231 fillRules->addChild(new FillRuleCase(m_context, "basic_quad_reverse", "Verify fill rules", FillRuleCase::FILLRULECASE_REVERSED));
2232 fillRules->addChild(new FillRuleCase(m_context, "clipped_full", "Verify fill rules", FillRuleCase::FILLRULECASE_CLIPPED_FULL));
2233 fillRules->addChild(new FillRuleCase(m_context, "clipped_partly", "Verify fill rules", FillRuleCase::FILLRULECASE_CLIPPED_PARTIAL));
2234 fillRules->addChild(new FillRuleCase(m_context, "projected", "Verify fill rules", FillRuleCase::FILLRULECASE_PROJECTED));
2235 }
2236
2237 // .culling
2238 {
2239 static const struct CullMode
2240 {
2241 glw::GLenum mode;
2242 const char* prefix;
2243 } cullModes[] =
2244 {
2245 { GL_FRONT, "front_" },
2246 { GL_BACK, "back_" },
2247 { GL_FRONT_AND_BACK, "both_" },
2248 };
2249 static const struct PrimitiveType
2250 {
2251 glw::GLenum type;
2252 const char* name;
2253 } primitiveTypes[] =
2254 {
2255 { GL_TRIANGLES, "triangles" },
2256 { GL_TRIANGLE_STRIP, "triangle_strip" },
2257 { GL_TRIANGLE_FAN, "triangle_fan" },
2258 };
2259 static const struct FrontFaceOrder
2260 {
2261 glw::GLenum mode;
2262 const char* postfix;
2263 } frontOrders[] =
2264 {
2265 { GL_CCW, "" },
2266 { GL_CW, "_reverse" },
2267 };
2268
2269 tcu::TestCaseGroup* const culling = new tcu::TestCaseGroup(m_testCtx, "culling", "Culling");
2270
2271 addChild(culling);
2272
2273 for (int cullModeNdx = 0; cullModeNdx < DE_LENGTH_OF_ARRAY(cullModes); ++cullModeNdx)
2274 for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); ++primitiveNdx)
2275 for (int frontOrderNdx = 0; frontOrderNdx < DE_LENGTH_OF_ARRAY(frontOrders); ++frontOrderNdx)
2276 {
2277 const std::string name = std::string(cullModes[cullModeNdx].prefix) + primitiveTypes[primitiveNdx].name + frontOrders[frontOrderNdx].postfix;
2278
2279 culling->addChild(new CullingTest(m_context, name.c_str(), "Test primitive culling.", cullModes[cullModeNdx].mode, primitiveTypes[primitiveNdx].type, frontOrders[frontOrderNdx].mode));
2280 }
2281 }
2282
2283 // .interpolation
2284 {
2285 tcu::TestCaseGroup* const interpolation = new tcu::TestCaseGroup(m_testCtx, "interpolation", "Test interpolation");
2286
2287 addChild(interpolation);
2288
2289 // .basic
2290 {
2291 tcu::TestCaseGroup* const basic = new tcu::TestCaseGroup(m_testCtx, "basic", "Non-projective interpolation");
2292
2293 interpolation->addChild(basic);
2294
2295 basic->addChild(new TriangleInterpolationTest (m_context, "triangles", "Verify triangle interpolation", GL_TRIANGLES, INTERPOLATIONFLAGS_NONE));
2296 basic->addChild(new TriangleInterpolationTest (m_context, "triangle_strip", "Verify triangle strip interpolation", GL_TRIANGLE_STRIP, INTERPOLATIONFLAGS_NONE));
2297 basic->addChild(new TriangleInterpolationTest (m_context, "triangle_fan", "Verify triangle fan interpolation", GL_TRIANGLE_FAN, INTERPOLATIONFLAGS_NONE));
2298 basic->addChild(new LineInterpolationTest (m_context, "lines", "Verify line interpolation", GL_LINES, INTERPOLATIONFLAGS_NONE, PRIMITIVEWIDENESS_NARROW));
2299 basic->addChild(new LineInterpolationTest (m_context, "line_strip", "Verify line strip interpolation", GL_LINE_STRIP, INTERPOLATIONFLAGS_NONE, PRIMITIVEWIDENESS_NARROW));
2300 basic->addChild(new LineInterpolationTest (m_context, "line_loop", "Verify line loop interpolation", GL_LINE_LOOP, INTERPOLATIONFLAGS_NONE, PRIMITIVEWIDENESS_NARROW));
2301 basic->addChild(new LineInterpolationTest (m_context, "lines_wide", "Verify wide line interpolation", GL_LINES, INTERPOLATIONFLAGS_NONE, PRIMITIVEWIDENESS_WIDE));
2302 basic->addChild(new LineInterpolationTest (m_context, "line_strip_wide", "Verify wide line strip interpolation", GL_LINE_STRIP, INTERPOLATIONFLAGS_NONE, PRIMITIVEWIDENESS_WIDE));
2303 basic->addChild(new LineInterpolationTest (m_context, "line_loop_wide", "Verify wide line loop interpolation", GL_LINE_LOOP, INTERPOLATIONFLAGS_NONE, PRIMITIVEWIDENESS_WIDE));
2304 }
2305
2306 // .projected
2307 {
2308 tcu::TestCaseGroup* const projected = new tcu::TestCaseGroup(m_testCtx, "projected", "Projective interpolation");
2309
2310 interpolation->addChild(projected);
2311
2312 projected->addChild(new TriangleInterpolationTest (m_context, "triangles", "Verify triangle interpolation", GL_TRIANGLES, INTERPOLATIONFLAGS_PROJECTED));
2313 projected->addChild(new TriangleInterpolationTest (m_context, "triangle_strip", "Verify triangle strip interpolation", GL_TRIANGLE_STRIP, INTERPOLATIONFLAGS_PROJECTED));
2314 projected->addChild(new TriangleInterpolationTest (m_context, "triangle_fan", "Verify triangle fan interpolation", GL_TRIANGLE_FAN, INTERPOLATIONFLAGS_PROJECTED));
2315 projected->addChild(new LineInterpolationTest (m_context, "lines", "Verify line interpolation", GL_LINES, INTERPOLATIONFLAGS_PROJECTED, PRIMITIVEWIDENESS_NARROW));
2316 projected->addChild(new LineInterpolationTest (m_context, "line_strip", "Verify line strip interpolation", GL_LINE_STRIP, INTERPOLATIONFLAGS_PROJECTED, PRIMITIVEWIDENESS_NARROW));
2317 projected->addChild(new LineInterpolationTest (m_context, "line_loop", "Verify line loop interpolation", GL_LINE_LOOP, INTERPOLATIONFLAGS_PROJECTED, PRIMITIVEWIDENESS_NARROW));
2318 projected->addChild(new LineInterpolationTest (m_context, "lines_wide", "Verify wide line interpolation", GL_LINES, INTERPOLATIONFLAGS_PROJECTED, PRIMITIVEWIDENESS_WIDE));
2319 projected->addChild(new LineInterpolationTest (m_context, "line_strip_wide", "Verify wide line strip interpolation", GL_LINE_STRIP, INTERPOLATIONFLAGS_PROJECTED, PRIMITIVEWIDENESS_WIDE));
2320 projected->addChild(new LineInterpolationTest (m_context, "line_loop_wide", "Verify wide line loop interpolation", GL_LINE_LOOP, INTERPOLATIONFLAGS_PROJECTED, PRIMITIVEWIDENESS_WIDE));
2321 }
2322 }
2323
2324 // .flatshading
2325 {
2326 tcu::TestCaseGroup* const flatshading = new tcu::TestCaseGroup(m_testCtx, "flatshading", "Test flatshading");
2327
2328 addChild(flatshading);
2329
2330 flatshading->addChild(new TriangleInterpolationTest (m_context, "triangles", "Verify triangle flatshading", GL_TRIANGLES, INTERPOLATIONFLAGS_FLATSHADE));
2331 flatshading->addChild(new TriangleInterpolationTest (m_context, "triangle_strip", "Verify triangle strip flatshading", GL_TRIANGLE_STRIP, INTERPOLATIONFLAGS_FLATSHADE));
2332 flatshading->addChild(new TriangleInterpolationTest (m_context, "triangle_fan", "Verify triangle fan flatshading", GL_TRIANGLE_FAN, INTERPOLATIONFLAGS_FLATSHADE));
2333 flatshading->addChild(new LineInterpolationTest (m_context, "lines", "Verify line flatshading", GL_LINES, INTERPOLATIONFLAGS_FLATSHADE, PRIMITIVEWIDENESS_NARROW));
2334 flatshading->addChild(new LineInterpolationTest (m_context, "line_strip", "Verify line strip flatshading", GL_LINE_STRIP, INTERPOLATIONFLAGS_FLATSHADE, PRIMITIVEWIDENESS_NARROW));
2335 flatshading->addChild(new LineInterpolationTest (m_context, "line_loop", "Verify line loop flatshading", GL_LINE_LOOP, INTERPOLATIONFLAGS_FLATSHADE, PRIMITIVEWIDENESS_NARROW));
2336 flatshading->addChild(new LineInterpolationTest (m_context, "lines_wide", "Verify wide line flatshading", GL_LINES, INTERPOLATIONFLAGS_FLATSHADE, PRIMITIVEWIDENESS_WIDE));
2337 flatshading->addChild(new LineInterpolationTest (m_context, "line_strip_wide", "Verify wide line strip flatshading", GL_LINE_STRIP, INTERPOLATIONFLAGS_FLATSHADE, PRIMITIVEWIDENESS_WIDE));
2338 flatshading->addChild(new LineInterpolationTest (m_context, "line_loop_wide", "Verify wide line loop flatshading", GL_LINE_LOOP, INTERPOLATIONFLAGS_FLATSHADE, PRIMITIVEWIDENESS_WIDE));
2339 }
2340
2341 // .fbo
2342 {
2343 static const struct
2344 {
2345 const char* name;
2346 BaseRenderingCase::RenderTarget target;
2347 int numSamples;
2348 } renderTargets[] =
2349 {
2350 { "texture_2d", BaseRenderingCase::RENDERTARGET_TEXTURE_2D, -1 },
2351 { "rbo_singlesample", BaseRenderingCase::RENDERTARGET_RBO_SINGLESAMPLE, -1 },
2352 { "rbo_multisample_4", BaseRenderingCase::RENDERTARGET_RBO_MULTISAMPLE, 4 },
2353 { "rbo_multisample_max", BaseRenderingCase::RENDERTARGET_RBO_MULTISAMPLE, BaseRenderingCase::SAMPLE_COUNT_MAX },
2354 };
2355
2356 tcu::TestCaseGroup* const fboGroup = new tcu::TestCaseGroup(m_testCtx, "fbo", "Test using framebuffer objects");
2357 addChild(fboGroup);
2358
2359 // .texture_2d
2360 // .rbo_singlesample
2361 // .rbo_multisample_4
2362 // .rbo_multisample_max
2363 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(renderTargets); ++targetNdx)
2364 {
2365 tcu::TestCaseGroup* const colorAttachmentGroup = new tcu::TestCaseGroup(m_testCtx, renderTargets[targetNdx].name, ("Test using " + std::string(renderTargets[targetNdx].name) + " color attachment").c_str());
2366 fboGroup->addChild(colorAttachmentGroup);
2367
2368 // .primitives
2369 {
2370 tcu::TestCaseGroup* const primitiveGroup = new tcu::TestCaseGroup(m_testCtx, "primitives", "Primitive rasterization");
2371 colorAttachmentGroup->addChild(primitiveGroup);
2372
2373 primitiveGroup->addChild(new TrianglesCase (m_context, "triangles", "Render primitives as GL_TRIANGLES, verify rasterization result", renderTargets[targetNdx].target, renderTargets[targetNdx].numSamples));
2374 primitiveGroup->addChild(new LinesCase (m_context, "lines", "Render primitives as GL_LINES, verify rasterization result", PRIMITIVEWIDENESS_NARROW, renderTargets[targetNdx].target, renderTargets[targetNdx].numSamples));
2375 primitiveGroup->addChild(new LinesCase (m_context, "lines_wide", "Render primitives as GL_LINES with wide lines, verify rasterization result", PRIMITIVEWIDENESS_WIDE, renderTargets[targetNdx].target, renderTargets[targetNdx].numSamples));
2376 primitiveGroup->addChild(new PointCase (m_context, "points", "Render primitives as GL_POINTS, verify rasterization result", PRIMITIVEWIDENESS_WIDE, renderTargets[targetNdx].target, renderTargets[targetNdx].numSamples));
2377 }
2378
2379 // .fill_rules
2380 {
2381 tcu::TestCaseGroup* const fillRules = new tcu::TestCaseGroup(m_testCtx, "fill_rules", "Primitive fill rules");
2382
2383 colorAttachmentGroup->addChild(fillRules);
2384
2385 fillRules->addChild(new FillRuleCase(m_context, "basic_quad", "Verify fill rules", FillRuleCase::FILLRULECASE_BASIC, renderTargets[targetNdx].target, renderTargets[targetNdx].numSamples));
2386 fillRules->addChild(new FillRuleCase(m_context, "basic_quad_reverse", "Verify fill rules", FillRuleCase::FILLRULECASE_REVERSED, renderTargets[targetNdx].target, renderTargets[targetNdx].numSamples));
2387 fillRules->addChild(new FillRuleCase(m_context, "clipped_full", "Verify fill rules", FillRuleCase::FILLRULECASE_CLIPPED_FULL, renderTargets[targetNdx].target, renderTargets[targetNdx].numSamples));
2388 fillRules->addChild(new FillRuleCase(m_context, "clipped_partly", "Verify fill rules", FillRuleCase::FILLRULECASE_CLIPPED_PARTIAL, renderTargets[targetNdx].target, renderTargets[targetNdx].numSamples));
2389 fillRules->addChild(new FillRuleCase(m_context, "projected", "Verify fill rules", FillRuleCase::FILLRULECASE_PROJECTED, renderTargets[targetNdx].target, renderTargets[targetNdx].numSamples));
2390 }
2391
2392 // .interpolation
2393 {
2394 tcu::TestCaseGroup* const interpolation = new tcu::TestCaseGroup(m_testCtx, "interpolation", "Non-projective interpolation");
2395
2396 colorAttachmentGroup->addChild(interpolation);
2397
2398 interpolation->addChild(new TriangleInterpolationTest (m_context, "triangles", "Verify triangle interpolation", GL_TRIANGLES, INTERPOLATIONFLAGS_NONE, renderTargets[targetNdx].target, renderTargets[targetNdx].numSamples));
2399 interpolation->addChild(new LineInterpolationTest (m_context, "lines", "Verify line interpolation", GL_LINES, INTERPOLATIONFLAGS_NONE, PRIMITIVEWIDENESS_NARROW, renderTargets[targetNdx].target, renderTargets[targetNdx].numSamples));
2400 interpolation->addChild(new LineInterpolationTest (m_context, "lines_wide", "Verify wide line interpolation", GL_LINES, INTERPOLATIONFLAGS_NONE, PRIMITIVEWIDENESS_WIDE, renderTargets[targetNdx].target, renderTargets[targetNdx].numSamples));
2401 }
2402 }
2403 }
2404 }
2405
2406 } // Functional
2407 } // gles3
2408 } // deqp
2409