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