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