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