1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2014-2016 The Khronos Group Inc.
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
22 */ /*-------------------------------------------------------------------*/
23
24 /**
25 * \file glcViewportArrayTests.cpp
26 * \brief Implements conformance tests for "Viewport Array" functionality.
27 */ /*-------------------------------------------------------------------*/
28
29 #include "glcViewportArrayTests.hpp"
30
31 #include "gluContextInfo.hpp"
32 #include "gluDefs.hpp"
33 #include "gluStrUtil.hpp"
34 #include "glwEnums.hpp"
35 #include "glwFunctions.hpp"
36 #include "tcuRenderTarget.hpp"
37 #include "tcuTestLog.hpp"
38
39 #include <algorithm>
40 #include <iomanip>
41 #include <string>
42 #include <vector>
43
44 using namespace glw;
45
46 namespace glcts
47 {
48
49 namespace ViewportArray
50 {
51 /** Constructor.
52 *
53 * @param context CTS context.
54 **/
buffer(deqp::Context & context)55 Utils::buffer::buffer(deqp::Context& context) : m_id(0), m_context(context), m_target(0)
56 {
57 }
58
59 /** Destructor
60 *
61 **/
~buffer()62 Utils::buffer::~buffer()
63 {
64 if (0 != m_id)
65 {
66 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
67
68 gl.deleteBuffers(1, &m_id);
69 m_id = 0;
70 }
71 }
72
73 /** Execute BindBuffer
74 *
75 **/
bind() const76 void Utils::buffer::bind() const
77 {
78 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
79
80 gl.bindBuffer(m_target, m_id);
81 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
82 }
83
84 /** Execute BindBufferRange
85 *
86 * @param index <index> parameter
87 * @param offset <offset> parameter
88 * @param size <size> parameter
89 **/
bindRange(glw::GLuint index,glw::GLintptr offset,glw::GLsizeiptr size)90 void Utils::buffer::bindRange(glw::GLuint index, glw::GLintptr offset, glw::GLsizeiptr size)
91 {
92 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
93
94 gl.bindBufferRange(m_target, index, m_id, offset, size);
95 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
96 }
97
98 /** Execute GenBuffer
99 *
100 * @param target Target that will be used by this buffer
101 **/
generate(glw::GLenum target)102 void Utils::buffer::generate(glw::GLenum target)
103 {
104 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
105
106 m_target = target;
107
108 gl.genBuffers(1, &m_id);
109 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
110 }
111
112 /** Maps buffer content
113 *
114 * @param access Access rights for mapped region
115 *
116 * @return Mapped memory
117 **/
map(GLenum access) const118 void* Utils::buffer::map(GLenum access) const
119 {
120 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
121
122 gl.bindBuffer(m_target, m_id);
123 GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer");
124
125 void* result = gl.mapBuffer(m_target, access);
126 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
127
128 return result;
129 }
130
131 /** Unmaps buffer
132 *
133 **/
unmap() const134 void Utils::buffer::unmap() const
135 {
136 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
137
138 gl.bindBuffer(m_target, m_id);
139 GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer");
140
141 gl.unmapBuffer(m_target);
142 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
143 }
144
145 /** Execute BufferData
146 *
147 * @param size <size> parameter
148 * @param data <data> parameter
149 * @param usage <usage> parameter
150 **/
update(glw::GLsizeiptr size,glw::GLvoid * data,glw::GLenum usage)151 void Utils::buffer::update(glw::GLsizeiptr size, glw::GLvoid* data, glw::GLenum usage)
152 {
153 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
154
155 gl.bindBuffer(m_target, m_id);
156 GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer");
157
158 gl.bufferData(m_target, size, data, usage);
159 GLU_EXPECT_NO_ERROR(gl.getError(), "bufferData");
160 }
161
162 /** Constructor
163 *
164 * @param context CTS context
165 **/
framebuffer(deqp::Context & context)166 Utils::framebuffer::framebuffer(deqp::Context& context) : m_id(0), m_context(context)
167 {
168 /* Nothing to be done here */
169 }
170
171 /** Destructor
172 *
173 **/
~framebuffer()174 Utils::framebuffer::~framebuffer()
175 {
176 if (0 != m_id)
177 {
178 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
179
180 gl.deleteFramebuffers(1, &m_id);
181 m_id = 0;
182 }
183 }
184
185 /** Attach texture to specified attachment
186 *
187 * @param attachment Attachment
188 * @param texture_id Texture id
189 * @param width Texture width
190 * @param height Texture height
191 **/
attachTexture(glw::GLenum attachment,glw::GLuint texture_id,glw::GLuint width,glw::GLuint height)192 void Utils::framebuffer::attachTexture(glw::GLenum attachment, glw::GLuint texture_id, glw::GLuint width,
193 glw::GLuint height)
194 {
195 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
196
197 bind();
198
199 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, attachment, texture_id, 0 /* level */);
200 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture");
201
202 gl.viewport(0 /* x */, 0 /* y */, width, height);
203 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
204 }
205
206 /** Binds framebuffer to DRAW_FRAMEBUFFER
207 *
208 **/
bind()209 void Utils::framebuffer::bind()
210 {
211 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
212
213 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_id);
214 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
215 }
216
217 /** Clear framebuffer
218 *
219 * @param mask <mask> parameter of glClear. Decides which shall be cleared
220 **/
clear(glw::GLenum mask)221 void Utils::framebuffer::clear(glw::GLenum mask)
222 {
223 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
224
225 gl.clear(mask);
226 GLU_EXPECT_NO_ERROR(gl.getError(), "Clear");
227 }
228
229 /** Specifies clear color
230 *
231 * @param red Red channel
232 * @param green Green channel
233 * @param blue Blue channel
234 * @param alpha Alpha channel
235 **/
clearColor(GLfloat red,GLfloat green,GLfloat blue,GLfloat alpha)236 void Utils::framebuffer::clearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
237 {
238 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
239
240 gl.clearColor(red, green, blue, alpha);
241 GLU_EXPECT_NO_ERROR(gl.getError(), "ClearColor");
242 }
243
244 /** Generate framebuffer
245 *
246 **/
generate()247 void Utils::framebuffer::generate()
248 {
249 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
250
251 gl.genFramebuffers(1, &m_id);
252 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
253 }
254
shaderCompilationException(const glw::GLchar * source,const glw::GLchar * message)255 Utils::shaderCompilationException::shaderCompilationException(const glw::GLchar* source, const glw::GLchar* message)
256 : m_shader_source(source), m_error_message(message)
257 {
258 /* Nothing to be done */
259 }
260
what() const261 const char* Utils::shaderCompilationException::what() const throw()
262 {
263 return "Shader compilation failed";
264 }
265
programLinkageException(const glw::GLchar * message)266 Utils::programLinkageException::programLinkageException(const glw::GLchar* message) : m_error_message(message)
267 {
268 /* Nothing to be done */
269 }
270
what() const271 const char* Utils::programLinkageException::what() const throw()
272 {
273 return "Program linking failed";
274 }
275
276 const glw::GLenum Utils::program::ARB_COMPUTE_SHADER = 0x91B9;
277
278 /** Constructor.
279 *
280 * @param context CTS context.
281 **/
program(deqp::Context & context)282 Utils::program::program(deqp::Context& context)
283 : m_compute_shader_id(0)
284 , m_fragment_shader_id(0)
285 , m_geometry_shader_id(0)
286 , m_program_object_id(0)
287 , m_tesselation_control_shader_id(0)
288 , m_tesselation_evaluation_shader_id(0)
289 , m_vertex_shader_id(0)
290 , m_context(context)
291 {
292 /* Nothing to be done here */
293 }
294
295 /** Destructor
296 *
297 **/
~program()298 Utils::program::~program()
299 {
300 remove();
301 }
302
303 /** Build program
304 *
305 * @param compute_shader_code Compute shader source code
306 * @param fragment_shader_code Fragment shader source code
307 * @param geometry_shader_code Geometry shader source code
308 * @param tesselation_control_shader_code Tesselation control shader source code
309 * @param tesselation_evaluation_shader_code Tesselation evaluation shader source code
310 * @param vertex_shader_code Vertex shader source code
311 * @param varying_names Array of strings containing names of varyings to be captured with transfrom feedback
312 * @param n_varying_names Number of varyings to be captured with transfrom feedback
313 * @param is_separable Selects if monolithis or separable program should be built. Defaults to false
314 **/
build(const glw::GLchar * compute_shader_code,const glw::GLchar * fragment_shader_code,const glw::GLchar * geometry_shader_code,const glw::GLchar * tesselation_control_shader_code,const glw::GLchar * tesselation_evaluation_shader_code,const glw::GLchar * vertex_shader_code,const glw::GLchar * const * varying_names,glw::GLuint n_varying_names,bool is_separable)315 void Utils::program::build(const glw::GLchar* compute_shader_code, const glw::GLchar* fragment_shader_code,
316 const glw::GLchar* geometry_shader_code, const glw::GLchar* tesselation_control_shader_code,
317 const glw::GLchar* tesselation_evaluation_shader_code, const glw::GLchar* vertex_shader_code,
318 const glw::GLchar* const* varying_names, glw::GLuint n_varying_names, bool is_separable)
319 {
320 /* GL entry points */
321 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
322
323 /* Create shader objects and compile */
324 if (0 != compute_shader_code)
325 {
326 m_compute_shader_id = gl.createShader(ARB_COMPUTE_SHADER);
327 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
328
329 compile(m_compute_shader_id, compute_shader_code);
330 }
331
332 if (0 != fragment_shader_code)
333 {
334 m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
335 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
336
337 compile(m_fragment_shader_id, fragment_shader_code);
338 }
339
340 if (0 != geometry_shader_code)
341 {
342 m_geometry_shader_id = gl.createShader(GL_GEOMETRY_SHADER);
343 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
344
345 compile(m_geometry_shader_id, geometry_shader_code);
346 }
347
348 if (0 != tesselation_control_shader_code)
349 {
350 m_tesselation_control_shader_id = gl.createShader(GL_TESS_CONTROL_SHADER);
351 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
352
353 compile(m_tesselation_control_shader_id, tesselation_control_shader_code);
354 }
355
356 if (0 != tesselation_evaluation_shader_code)
357 {
358 m_tesselation_evaluation_shader_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
359 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
360
361 compile(m_tesselation_evaluation_shader_id, tesselation_evaluation_shader_code);
362 }
363
364 if (0 != vertex_shader_code)
365 {
366 m_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER);
367 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
368
369 compile(m_vertex_shader_id, vertex_shader_code);
370 }
371
372 /* Create program object */
373 m_program_object_id = gl.createProgram();
374 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
375
376 /* Set up captyured varyings' names */
377 if (0 != n_varying_names)
378 {
379 gl.transformFeedbackVaryings(m_program_object_id, n_varying_names, varying_names, GL_INTERLEAVED_ATTRIBS);
380 GLU_EXPECT_NO_ERROR(gl.getError(), "TransformFeedbackVaryings");
381 }
382
383 /* Set separable parameter */
384 if (true == is_separable)
385 {
386 gl.programParameteri(m_program_object_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
387 GLU_EXPECT_NO_ERROR(gl.getError(), "ProgramParameteri");
388 }
389
390 /* Link program */
391 link();
392 }
393
compile(GLuint shader_id,const GLchar * source) const394 void Utils::program::compile(GLuint shader_id, const GLchar* source) const
395 {
396 /* GL entry points */
397 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
398
399 /* Compilation status */
400 glw::GLint status = GL_FALSE;
401
402 /* Set source code */
403 gl.shaderSource(shader_id, 1 /* count */, &source, 0 /* lengths */);
404 GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
405
406 /* Compile */
407 gl.compileShader(shader_id);
408 GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
409
410 /* Get compilation status */
411 gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &status);
412 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
413
414 /* Log compilation error */
415 if (GL_TRUE != status)
416 {
417 glw::GLint length = 0;
418 std::vector<glw::GLchar> message;
419
420 /* Error log length */
421 gl.getShaderiv(shader_id, GL_INFO_LOG_LENGTH, &length);
422 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
423
424 /* Prepare storage */
425 message.resize(length);
426
427 /* Get error log */
428 gl.getShaderInfoLog(shader_id, length, 0, &message[0]);
429 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
430
431 throw shaderCompilationException(source, &message[0]);
432 }
433 }
434
getAttribLocation(const glw::GLchar * name) const435 glw::GLint Utils::program::getAttribLocation(const glw::GLchar* name) const
436 {
437 /* GL entry points */
438 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
439
440 GLint location = gl.getAttribLocation(m_program_object_id, name);
441 GLU_EXPECT_NO_ERROR(gl.getError(), "GetAttribLocation");
442
443 return location;
444 }
445
446 /** Get subroutine index
447 *
448 * @param subroutine_name Subroutine name
449 *
450 * @return Index of subroutine
451 **/
getSubroutineIndex(const glw::GLchar * subroutine_name,glw::GLenum shader_stage) const452 GLuint Utils::program::getSubroutineIndex(const glw::GLchar* subroutine_name, glw::GLenum shader_stage) const
453 {
454 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
455 GLuint index = -1;
456
457 index = gl.getSubroutineIndex(m_program_object_id, shader_stage, subroutine_name);
458 GLU_EXPECT_NO_ERROR(gl.getError(), "GetSubroutineIndex");
459
460 if (GL_INVALID_INDEX == index)
461 {
462 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Subroutine: " << subroutine_name
463 << " is not available" << tcu::TestLog::EndMessage;
464
465 TCU_FAIL("Subroutine is not available");
466 }
467
468 return index;
469 }
470
471 /** Get subroutine uniform location
472 *
473 * @param uniform_name Subroutine uniform name
474 *
475 * @return Location of subroutine uniform
476 **/
getSubroutineUniformLocation(const glw::GLchar * uniform_name,glw::GLenum shader_stage) const477 GLint Utils::program::getSubroutineUniformLocation(const glw::GLchar* uniform_name, glw::GLenum shader_stage) const
478 {
479 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
480 GLint location = -1;
481
482 location = gl.getSubroutineUniformLocation(m_program_object_id, shader_stage, uniform_name);
483 GLU_EXPECT_NO_ERROR(gl.getError(), "GetSubroutineUniformLocation");
484
485 if (-1 == location)
486 {
487 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Subroutine uniform: " << uniform_name
488 << " is not available" << tcu::TestLog::EndMessage;
489
490 TCU_FAIL("Subroutine uniform is not available");
491 }
492
493 return location;
494 }
495
496 /** Get uniform location
497 *
498 * @param uniform_name Subroutine uniform name
499 *
500 * @return Location of uniform
501 **/
getUniformLocation(const glw::GLchar * uniform_name) const502 GLint Utils::program::getUniformLocation(const glw::GLchar* uniform_name) const
503 {
504 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
505 GLint location = -1;
506
507 location = gl.getUniformLocation(m_program_object_id, uniform_name);
508 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
509
510 if (-1 == location)
511 {
512 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Uniform: " << uniform_name
513 << " is not available" << tcu::TestLog::EndMessage;
514
515 TCU_FAIL("Uniform is not available");
516 }
517
518 return location;
519 }
520
521 /** Attach shaders and link program
522 *
523 **/
link() const524 void Utils::program::link() const
525 {
526 /* GL entry points */
527 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
528
529 /* Link status */
530 glw::GLint status = GL_FALSE;
531
532 /* Attach shaders */
533 if (0 != m_compute_shader_id)
534 {
535 gl.attachShader(m_program_object_id, m_compute_shader_id);
536 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
537 }
538
539 if (0 != m_fragment_shader_id)
540 {
541 gl.attachShader(m_program_object_id, m_fragment_shader_id);
542 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
543 }
544
545 if (0 != m_geometry_shader_id)
546 {
547 gl.attachShader(m_program_object_id, m_geometry_shader_id);
548 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
549 }
550
551 if (0 != m_tesselation_control_shader_id)
552 {
553 gl.attachShader(m_program_object_id, m_tesselation_control_shader_id);
554 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
555 }
556
557 if (0 != m_tesselation_evaluation_shader_id)
558 {
559 gl.attachShader(m_program_object_id, m_tesselation_evaluation_shader_id);
560 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
561 }
562
563 if (0 != m_vertex_shader_id)
564 {
565 gl.attachShader(m_program_object_id, m_vertex_shader_id);
566 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
567 }
568
569 /* Link */
570 gl.linkProgram(m_program_object_id);
571 GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
572
573 /* Get link status */
574 gl.getProgramiv(m_program_object_id, GL_LINK_STATUS, &status);
575 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
576
577 /* Log link error */
578 if (GL_TRUE != status)
579 {
580 glw::GLint length = 0;
581 std::vector<glw::GLchar> message;
582
583 /* Get error log length */
584 gl.getProgramiv(m_program_object_id, GL_INFO_LOG_LENGTH, &length);
585 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
586
587 message.resize(length);
588
589 /* Get error log */
590 gl.getProgramInfoLog(m_program_object_id, length, 0, &message[0]);
591 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
592
593 throw programLinkageException(&message[0]);
594 }
595 }
596
597 /** Delete program object and all attached shaders
598 *
599 **/
remove()600 void Utils::program::remove()
601 {
602 /* GL entry points */
603 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
604
605 /* Make sure program object is no longer used by GL */
606 gl.useProgram(0);
607
608 /* Clean program object */
609 if (0 != m_program_object_id)
610 {
611 gl.deleteProgram(m_program_object_id);
612 m_program_object_id = 0;
613 }
614
615 /* Clean shaders */
616 if (0 != m_compute_shader_id)
617 {
618 gl.deleteShader(m_compute_shader_id);
619 m_compute_shader_id = 0;
620 }
621
622 if (0 != m_fragment_shader_id)
623 {
624 gl.deleteShader(m_fragment_shader_id);
625 m_fragment_shader_id = 0;
626 }
627
628 if (0 != m_geometry_shader_id)
629 {
630 gl.deleteShader(m_geometry_shader_id);
631 m_geometry_shader_id = 0;
632 }
633
634 if (0 != m_tesselation_control_shader_id)
635 {
636 gl.deleteShader(m_tesselation_control_shader_id);
637 m_tesselation_control_shader_id = 0;
638 }
639
640 if (0 != m_tesselation_evaluation_shader_id)
641 {
642 gl.deleteShader(m_tesselation_evaluation_shader_id);
643 m_tesselation_evaluation_shader_id = 0;
644 }
645
646 if (0 != m_vertex_shader_id)
647 {
648 gl.deleteShader(m_vertex_shader_id);
649 m_vertex_shader_id = 0;
650 }
651 }
652
653 /** Execute UseProgram
654 *
655 **/
use() const656 void Utils::program::use() const
657 {
658 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
659
660 gl.useProgram(m_program_object_id);
661 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
662 }
663
printShaderSource(const GLchar * source,tcu::MessageBuilder & log)664 void Utils::program::printShaderSource(const GLchar* source, tcu::MessageBuilder& log)
665 {
666 GLuint line_number = 0;
667
668 log << "Shader source.";
669
670 log << "\nLine||Source\n";
671
672 while (0 != source)
673 {
674 std::string line;
675 const GLchar* next_line = strchr(source, '\n');
676
677 if (0 != next_line)
678 {
679 next_line += 1;
680 line.assign(source, next_line - source);
681 }
682 else
683 {
684 line = source;
685 }
686
687 if (0 != *source)
688 {
689 log << std::setw(4) << line_number << "||" << line;
690 }
691
692 source = next_line;
693 line_number += 1;
694 }
695 }
696
697 /** Constructor.
698 *
699 * @param context CTS context.
700 **/
texture(deqp::Context & context)701 Utils::texture::texture(deqp::Context& context)
702 : m_id(0), m_width(0), m_height(0), m_depth(0), m_context(context), m_is_array(false)
703 {
704 /* Nothing to done here */
705 }
706
707 /** Destructor
708 *
709 **/
~texture()710 Utils::texture::~texture()
711 {
712 release();
713 }
714
715 /** Bind texture to GL_TEXTURE_2D
716 *
717 **/
bind() const718 void Utils::texture::bind() const
719 {
720 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
721
722 if (false == m_is_array)
723 {
724 gl.bindTexture(GL_TEXTURE_2D, m_id);
725 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
726 }
727 else
728 {
729 gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_id);
730 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
731 }
732 }
733
734 /** Create 2d texture
735 *
736 * @param width Width of texture
737 * @param height Height of texture
738 * @param internal_format Internal format of texture
739 **/
create(GLuint width,GLuint height,GLenum internal_format)740 void Utils::texture::create(GLuint width, GLuint height, GLenum internal_format)
741 {
742 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
743
744 release();
745
746 m_width = width;
747 m_height = height;
748 m_depth = 1;
749 m_is_array = false;
750
751 gl.genTextures(1, &m_id);
752 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
753
754 bind();
755
756 gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, internal_format, width, height);
757 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
758 }
759
760 /** Create 2d texture array
761 *
762 * @param width Width of texture
763 * @param height Height of texture
764 * @param depth Depth of texture
765 * @param internal_format Internal format of texture
766 **/
create(GLuint width,GLuint height,GLuint depth,GLenum internal_format)767 void Utils::texture::create(GLuint width, GLuint height, GLuint depth, GLenum internal_format)
768 {
769 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
770
771 release();
772
773 m_width = width;
774 m_height = height;
775 m_depth = depth;
776 m_is_array = true;
777
778 gl.genTextures(1, &m_id);
779 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
780
781 bind();
782
783 gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1 /* levels */, internal_format, width, height, depth);
784 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3D");
785 }
786
787 /** Get contents of texture
788 *
789 * @param format Format of image
790 * @param type Type of image
791 * @param out_data Buffer for image
792 **/
get(glw::GLenum format,glw::GLenum type,glw::GLvoid * out_data) const793 void Utils::texture::get(glw::GLenum format, glw::GLenum type, glw::GLvoid* out_data) const
794 {
795 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
796 const glu::ContextType& context_type = m_context.getRenderContext().getType();
797
798 bind();
799
800 GLenum textarget = GL_TEXTURE_2D;
801
802 if (true == m_is_array)
803 {
804 textarget = GL_TEXTURE_2D_ARRAY;
805 }
806
807 if (glu::isContextTypeGLCore(context_type))
808 {
809 gl.getTexImage(textarget, 0 /* level */, format, type, out_data);
810 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
811 }
812 else
813 {
814 DE_ASSERT(glu::isContextTypeES(context_type));
815
816 GLuint temp_fbo = 0;
817 gl.genFramebuffers(1, &temp_fbo);
818 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, temp_fbo);
819
820 /* OpenGL ES only guarantees support for RGBA formats of each type.
821 Since the tests are only expecting single-channel formats, we read them back
822 in RGBA to a temporary buffer and then copy only the first component
823 to the actual output buffer */
824 GLenum read_format = format;
825 switch (format)
826 {
827 case GL_RED:
828 read_format = GL_RGBA;
829 break;
830 case GL_RED_INTEGER:
831 read_format = GL_RGBA_INTEGER;
832 break;
833 default:
834 TCU_FAIL("unexpected format");
835 }
836 /* we can get away just handling one type of data, as long as the components are the same size */
837 if (type != GL_INT && type != GL_FLOAT)
838 {
839 TCU_FAIL("unexpected type");
840 }
841 std::vector<GLint> read_data;
842 const GLuint layer_size = m_width * m_height * 4;
843 read_data.resize(layer_size * m_depth);
844
845 if (m_is_array)
846 {
847 for (GLuint layer = 0; layer < m_depth; ++layer)
848 {
849 gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_id, 0, layer);
850 gl.readPixels(0, 0, m_width, m_height, read_format, type, &read_data[layer * layer_size]);
851 }
852 }
853 else
854 {
855 gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textarget, m_id, 0);
856 gl.readPixels(0, 0, m_width, m_height, read_format, type, &read_data[0]);
857 }
858 GLU_EXPECT_NO_ERROR(gl.getError(), "ReadPixels");
859 gl.deleteFramebuffers(1, &temp_fbo);
860
861 /* copy the first channel from the readback buffer to the output buffer */
862 GLint* out_data_int = (GLint*)out_data;
863 for (GLuint elem = 0; elem < (m_width * m_height * m_depth); ++elem)
864 {
865 out_data_int[elem] = read_data[elem * 4];
866 }
867 }
868 }
869
870 /** Delete texture
871 *
872 **/
release()873 void Utils::texture::release()
874 {
875 if (0 != m_id)
876 {
877 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
878
879 gl.deleteTextures(1, &m_id);
880 m_id = 0;
881 }
882 }
883
884 /** Update contents of texture
885 *
886 * @param width Width of texture
887 * @param height Height of texture
888 * @param depth Depth of texture
889 * @param format Format of data
890 * @param type Type of data
891 * @param data Buffer with image
892 **/
update(glw::GLuint width,glw::GLuint height,glw::GLuint depth,glw::GLenum format,glw::GLenum type,glw::GLvoid * data)893 void Utils::texture::update(glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format,
894 glw::GLenum type, glw::GLvoid* data)
895 {
896 static const GLuint level = 0;
897
898 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
899
900 bind();
901
902 if (false == m_is_array)
903 {
904 gl.texSubImage2D(GL_TEXTURE_2D, level, 0 /* x */, 0 /* y */, width, height, format, type, data);
905 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
906 }
907 else
908 {
909 gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, level, 0 /* x */, 0 /* y */, 0 /* z */, width, height, depth, format,
910 type, data);
911 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
912 }
913 }
914
915 /** Constructor.
916 *
917 * @param context CTS context.
918 **/
vertexArray(deqp::Context & context)919 Utils::vertexArray::vertexArray(deqp::Context& context) : m_id(0), m_context(context)
920 {
921 }
922
923 /** Destructor
924 *
925 **/
~vertexArray()926 Utils::vertexArray::~vertexArray()
927 {
928 if (0 != m_id)
929 {
930 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
931
932 gl.deleteVertexArrays(1, &m_id);
933
934 m_id = 0;
935 }
936 }
937
938 /** Execute BindVertexArray
939 *
940 **/
bind()941 void Utils::vertexArray::bind()
942 {
943 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
944
945 gl.bindVertexArray(m_id);
946 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
947 }
948
949 /** Execute GenVertexArrays
950 *
951 **/
generate()952 void Utils::vertexArray::generate()
953 {
954 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
955
956 gl.genVertexArrays(1, &m_id);
957 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
958 }
959
960 /** Constructor
961 *
962 * @param context Test context
963 **/
APIErrors(deqp::Context & context,const glcts::ExtParameters & extParams)964 APIErrors::APIErrors(deqp::Context& context, const glcts::ExtParameters& extParams)
965 : TestCaseBase(context, extParams, "api_errors", "Test verifies error generated by API")
966 {
967 /* Nothing to be done here */
968 }
969
970 template <typename T>
depthRangeArrayHelper(Utils::DepthFuncWrapper & depthFunc,GLint max_viewports,bool & test_result,T *)971 void APIErrors::depthRangeArrayHelper(Utils::DepthFuncWrapper& depthFunc, GLint max_viewports, bool& test_result, T*)
972 {
973 std::vector<T> data;
974 data.resize(max_viewports * 2 /* near + far */);
975
976 for (GLint i = 0; i < max_viewports; ++i)
977 {
978 data[i * 2] = (T)0.0;
979 data[i * 2 + 1] = (T)1.0;
980 }
981
982 depthFunc.depthRangeArray(0, max_viewports - 1, &data[0]);
983 checkGLError(GL_NO_ERROR, "depthRangeArray, correct parameters", test_result);
984
985 depthFunc.depthRangeArray(max_viewports, 1, &data[0]);
986 checkGLError(GL_INVALID_VALUE, "depthRangeArray, <first> == GL_MAX_VIEWPORTS", test_result);
987
988 depthFunc.depthRangeArray(1, max_viewports - 1, &data[0]);
989 checkGLError(GL_NO_ERROR, "depthRangeArray, <first> + <count> == GL_MAX_VIEWPORTS", test_result);
990
991 depthFunc.depthRangeArray(1, max_viewports, &data[0]);
992 checkGLError(GL_INVALID_VALUE, "depthRangeArray, <first> + <count> > GL_MAX_VIEWPORTS", test_result);
993 }
994
995 template <typename T>
depthRangeIndexedHelper(Utils::DepthFuncWrapper & depthFunc,GLint max_viewports,bool & test_result,T *)996 void APIErrors::depthRangeIndexedHelper(Utils::DepthFuncWrapper& depthFunc, GLint max_viewports, bool& test_result, T*)
997 {
998 depthFunc.depthRangeIndexed(0 /* index */, (T)0.0, (T)1.0);
999 checkGLError(GL_NO_ERROR, "depthRangeIndexed, <index> == 0", test_result);
1000
1001 depthFunc.depthRangeIndexed(max_viewports - 1 /* index */, (T)0.0, (T)1.0);
1002 checkGLError(GL_NO_ERROR, "depthRangeIndexed, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1003
1004 depthFunc.depthRangeIndexed(max_viewports /* index */, (T)0.0, (T)1.0);
1005 checkGLError(GL_INVALID_VALUE, "depthRangeIndexed, <index> == GL_MAX_VIEWPORTS", test_result);
1006
1007 depthFunc.depthRangeIndexed(max_viewports + 1 /* index */, (T)0.0, (T)1.0);
1008 checkGLError(GL_INVALID_VALUE, "depthRangeIndexed, <index> > GL_MAX_VIEWPORTS", test_result);
1009 }
1010
1011 template <typename T>
getDepthHelper(Utils::DepthFuncWrapper & depthFunc,GLint max_viewports,bool & test_result,T *)1012 void APIErrors::getDepthHelper(Utils::DepthFuncWrapper& depthFunc, GLint max_viewports, bool& test_result, T*)
1013 {
1014 T data[4];
1015
1016 depthFunc.getDepthi_v(GL_DEPTH_RANGE, max_viewports - 1, data);
1017 checkGLError(GL_NO_ERROR, "getDouble/Floati_v, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1018
1019 depthFunc.getDepthi_v(GL_DEPTH_RANGE, max_viewports, data);
1020 checkGLError(GL_INVALID_VALUE, "getDouble/Floati_v, <index> == GL_MAX_VIEWPORTS", test_result);
1021 }
1022
1023 /** Execute test
1024 *
1025 * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
1026 **/
iterate()1027 tcu::TestNode::IterateResult APIErrors::iterate()
1028 {
1029 if (!m_is_viewport_array_supported)
1030 {
1031 throw tcu::NotSupportedError(VIEWPORT_ARRAY_NOT_SUPPORTED, "", __FILE__, __LINE__);
1032 }
1033
1034 /* GL entry points */
1035 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1036 const glu::ContextType& context_type = m_context.getRenderContext().getType();
1037 Utils::DepthFuncWrapper depthFunc(m_context);
1038
1039 /* Test result */
1040 bool test_result = true;
1041
1042 GLint max_viewports = 0;
1043 gl.getIntegerv(GL_MAX_VIEWPORTS, &max_viewports);
1044 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1045
1046 /*
1047 * * DepthRangeArrayv generates INVALID_VALUE when <first> + <count> is greater
1048 * than or equal to the value of MAX_VIEWPORTS;
1049 */
1050 if (glu::isContextTypeGLCore(context_type))
1051 {
1052 depthRangeArrayHelper<GLdouble>(depthFunc, max_viewports, test_result);
1053 }
1054 else
1055 {
1056 DE_ASSERT(glu::isContextTypeES(context_type));
1057 depthRangeArrayHelper<GLfloat>(depthFunc, max_viewports, test_result);
1058 }
1059
1060 /*
1061 * * DepthRangeIndexed generates INVALID_VALUE when <index> is greater than or
1062 * equal to the value of MAX_VIEWPORTS;
1063 */
1064 if (glu::isContextTypeGLCore(context_type))
1065 {
1066 depthRangeIndexedHelper<GLdouble>(depthFunc, max_viewports, test_result);
1067 }
1068 else
1069 {
1070 DE_ASSERT(glu::isContextTypeES(context_type));
1071 depthRangeIndexedHelper<GLfloat>(depthFunc, max_viewports, test_result);
1072 }
1073
1074 /*
1075 * * ViewportArrayv generates INVALID_VALUE when <first> + <count> is greater
1076 * than or equal to the value of MAX_VIEWPORTS;
1077 */
1078 {
1079 std::vector<GLfloat> data;
1080 data.resize(max_viewports * 4 /* x + y + w + h */);
1081
1082 for (GLint i = 0; i < max_viewports; ++i)
1083 {
1084 data[i * 4 + 0] = 0.0f;
1085 data[i * 4 + 1] = 0.0f;
1086 data[i * 4 + 2] = 1.0f;
1087 data[i * 4 + 3] = 1.0f;
1088 }
1089
1090 gl.viewportArrayv(0, max_viewports - 1, &data[0]);
1091 checkGLError(GL_NO_ERROR, "viewportArrayv, correct parameters", test_result);
1092
1093 gl.viewportArrayv(max_viewports, 1, &data[0]);
1094 checkGLError(GL_INVALID_VALUE, "viewportArrayv, <first> == GL_MAX_VIEWPORTS", test_result);
1095
1096 gl.viewportArrayv(1, max_viewports - 1, &data[0]);
1097 checkGLError(GL_NO_ERROR, "viewportArrayv, <first> + <count> == GL_MAX_VIEWPORTS", test_result);
1098
1099 gl.viewportArrayv(1, max_viewports, &data[0]);
1100 checkGLError(GL_INVALID_VALUE, "viewportArrayv, <first> + <count> > GL_MAX_VIEWPORTS", test_result);
1101 }
1102
1103 /*
1104 * * ViewportIndexedf and ViewportIndexedfv generate INVALID_VALUE when <index>
1105 * is greater than or equal to the value of MAX_VIEWPORTS;
1106 */
1107 {
1108 GLfloat data[4 /* x + y + w + h */];
1109
1110 data[0] = 0.0f;
1111 data[1] = 0.0f;
1112 data[2] = 1.0f;
1113 data[3] = 1.0f;
1114
1115 gl.viewportIndexedf(0 /* index */, 0.0f, 0.0f, 1.0f, 1.0f);
1116 checkGLError(GL_NO_ERROR, "viewportIndexedf, <index> == 0", test_result);
1117
1118 gl.viewportIndexedf(max_viewports - 1 /* index */, 0.0f, 0.0f, 1.0f, 1.0f);
1119 checkGLError(GL_NO_ERROR, "viewportIndexedf, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1120
1121 gl.viewportIndexedf(max_viewports /* index */, 0.0f, 0.0f, 1.0f, 1.0f);
1122 checkGLError(GL_INVALID_VALUE, "viewportIndexedf, <index> == GL_MAX_VIEWPORTS", test_result);
1123
1124 gl.viewportIndexedf(max_viewports + 1 /* index */, 0.0f, 0.0f, 1.0f, 1.0f);
1125 checkGLError(GL_INVALID_VALUE, "viewportIndexedf, <index> > GL_MAX_VIEWPORTS", test_result);
1126
1127 gl.viewportIndexedfv(0 /* index */, data);
1128 checkGLError(GL_NO_ERROR, "viewportIndexedfv, <index> == 0", test_result);
1129
1130 gl.viewportIndexedfv(max_viewports - 1 /* index */, data);
1131 checkGLError(GL_NO_ERROR, "viewportIndexedfv, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1132
1133 gl.viewportIndexedfv(max_viewports /* index */, data);
1134 checkGLError(GL_INVALID_VALUE, "viewportIndexedfv, <index> == GL_MAX_VIEWPORTS", test_result);
1135
1136 gl.viewportIndexedfv(max_viewports + 1 /* index */, data);
1137 checkGLError(GL_INVALID_VALUE, "viewportIndexedfv, <index> > GL_MAX_VIEWPORTS", test_result);
1138 }
1139
1140 /*
1141 * * ViewportArrayv, Viewport, ViewportIndexedf and ViewportIndexedfv generate
1142 * INVALID_VALUE when <w> or <h> values are negative;
1143 */
1144 {
1145 gl.viewport(0, 0, -1, 1);
1146 checkGLError(GL_INVALID_VALUE, "viewport, negative width", test_result);
1147
1148 gl.viewport(0, 0, 1, -1);
1149 checkGLError(GL_INVALID_VALUE, "viewport, negative height", test_result);
1150
1151 for (GLint i = 0; i < max_viewports; ++i)
1152 {
1153 std::vector<GLfloat> data;
1154 data.resize(max_viewports * 4 /* x + y + w + h */);
1155
1156 for (GLint j = 0; j < max_viewports; ++j)
1157 {
1158 data[j * 4 + 0] = 0.0f;
1159 data[j * 4 + 1] = 0.0f;
1160 data[j * 4 + 2] = 1.0f;
1161 data[j * 4 + 3] = 1.0f;
1162 }
1163
1164 /* Set width to -1 */
1165 data[i * 4 + 2] = -1.0f;
1166
1167 gl.viewportArrayv(0, max_viewports, &data[0]);
1168 checkGLError(GL_INVALID_VALUE, "viewportArrayv, negative width", test_result);
1169
1170 gl.viewportIndexedf(i /* index */, 0.0f, 0.0f, -1.0f, 1.0f);
1171 checkGLError(GL_INVALID_VALUE, "viewportIndexedf, negative width", test_result);
1172
1173 gl.viewportIndexedfv(i /* index */, &data[i * 4]);
1174 checkGLError(GL_INVALID_VALUE, "viewportIndexedfv, negative width", test_result);
1175
1176 /* Set width to 1 and height to -1*/
1177 data[i * 4 + 2] = 1.0f;
1178 data[i * 4 + 3] = -1.0f;
1179
1180 gl.viewportArrayv(0, max_viewports, &data[0]);
1181 checkGLError(GL_INVALID_VALUE, "viewportArrayv, negative height", test_result);
1182
1183 gl.viewportIndexedf(i /* index */, 0.0f, 0.0f, 1.0f, -1.0f);
1184 checkGLError(GL_INVALID_VALUE, "viewportIndexedf, negative height", test_result);
1185
1186 gl.viewportIndexedfv(i /* index */, &data[i * 4]);
1187 checkGLError(GL_INVALID_VALUE, "viewportIndexedfv, negative height", test_result);
1188 }
1189 }
1190
1191 /*
1192 * * ScissorArrayv generates INVALID_VALUE when <first> + <count> is greater
1193 * than or equal to the value of MAX_VIEWPORTS;
1194 */
1195 {
1196 std::vector<GLint> data;
1197 data.resize(max_viewports * 4 /* x + y + w + h */);
1198
1199 for (GLint i = 0; i < max_viewports; ++i)
1200 {
1201 data[i * 4 + 0] = 0;
1202 data[i * 4 + 1] = 0;
1203 data[i * 4 + 2] = 1;
1204 data[i * 4 + 3] = 1;
1205 }
1206
1207 gl.scissorArrayv(0, max_viewports - 1, &data[0]);
1208 checkGLError(GL_NO_ERROR, "scissorArrayv, correct parameters", test_result);
1209
1210 gl.scissorArrayv(max_viewports, 1, &data[0]);
1211 checkGLError(GL_INVALID_VALUE, "scissorArrayv, <first> == GL_MAX_VIEWPORTS", test_result);
1212
1213 gl.scissorArrayv(1, max_viewports - 1, &data[0]);
1214 checkGLError(GL_NO_ERROR, "scissorArrayv, <first> + <count> == GL_MAX_VIEWPORTS", test_result);
1215
1216 gl.scissorArrayv(1, max_viewports, &data[0]);
1217 checkGLError(GL_INVALID_VALUE, "scissorArrayv, <first> + <count> > GL_MAX_VIEWPORTS", test_result);
1218 }
1219
1220 /*
1221 * * ScissorIndexed and ScissorIndexedv generate INVALID_VALUE when <index> is
1222 * greater than or equal to the value of MAX_VIEWPORTS;
1223 */
1224 {
1225 GLint data[4 /* x + y + w + h */];
1226
1227 data[0] = 0;
1228 data[1] = 0;
1229 data[2] = 1;
1230 data[3] = 1;
1231
1232 gl.scissorIndexed(0 /* index */, 0, 0, 1, 1);
1233 checkGLError(GL_NO_ERROR, "scissorIndexed, <index> == 0", test_result);
1234
1235 gl.scissorIndexed(max_viewports - 1 /* index */, 0, 0, 1, 1);
1236 checkGLError(GL_NO_ERROR, "scissorIndexed, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1237
1238 gl.scissorIndexed(max_viewports /* index */, 0, 0, 1, 1);
1239 checkGLError(GL_INVALID_VALUE, "scissorIndexed, <index> == GL_MAX_VIEWPORTS", test_result);
1240
1241 gl.scissorIndexed(max_viewports + 1 /* index */, 0, 0, 1, 1);
1242 checkGLError(GL_INVALID_VALUE, "scissorIndexed, <index> > GL_MAX_VIEWPORTS", test_result);
1243
1244 gl.scissorIndexedv(0 /* index */, data);
1245 checkGLError(GL_NO_ERROR, "scissorIndexedv, <index> == 0", test_result);
1246
1247 gl.scissorIndexedv(max_viewports - 1 /* index */, data);
1248 checkGLError(GL_NO_ERROR, "scissorIndexedv, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1249
1250 gl.scissorIndexedv(max_viewports /* index */, data);
1251 checkGLError(GL_INVALID_VALUE, "scissorIndexedv, <index> == GL_MAX_VIEWPORTS", test_result);
1252
1253 gl.scissorIndexedv(max_viewports + 1 /* index */, data);
1254 checkGLError(GL_INVALID_VALUE, "scissorIndexedv, <index> > GL_MAX_VIEWPORTS", test_result);
1255 }
1256
1257 /*
1258 * * ScissorArrayv, ScissorIndexed, ScissorIndexedv and Scissor generate
1259 * INVALID_VALUE when <width> or <height> values are negative;
1260 */
1261 {
1262 gl.scissor(0, 0, -1, 1);
1263 checkGLError(GL_INVALID_VALUE, "scissor, negative width", test_result);
1264
1265 gl.scissor(0, 0, 1, -1);
1266 checkGLError(GL_INVALID_VALUE, "scissor, negative height", test_result);
1267
1268 for (GLint i = 0; i < max_viewports; ++i)
1269 {
1270 std::vector<GLint> data;
1271 data.resize(max_viewports * 4 /* x + y + w + h */);
1272
1273 for (GLint j = 0; j < max_viewports; ++j)
1274 {
1275 data[j * 4 + 0] = 0;
1276 data[j * 4 + 1] = 0;
1277 data[j * 4 + 2] = 1;
1278 data[j * 4 + 3] = 1;
1279 }
1280
1281 /* Set width to -1 */
1282 data[i * 4 + 2] = -1;
1283
1284 gl.scissorArrayv(0, max_viewports, &data[0]);
1285 checkGLError(GL_INVALID_VALUE, "scissorArrayv, negative width", test_result);
1286
1287 gl.scissorIndexed(i /* index */, 0, 0, -1, 1);
1288 checkGLError(GL_INVALID_VALUE, "scissorIndexed, negative width", test_result);
1289
1290 gl.scissorIndexedv(i /* index */, &data[i * 4]);
1291 checkGLError(GL_INVALID_VALUE, "scissorIndexedv, negative width", test_result);
1292
1293 /* Set width to 1 and height to -1*/
1294 data[i * 4 + 2] = 1;
1295 data[i * 4 + 3] = -1;
1296
1297 gl.scissorArrayv(0, max_viewports, &data[0]);
1298 checkGLError(GL_INVALID_VALUE, "scissorArrayv, negative height", test_result);
1299
1300 gl.scissorIndexed(i /* index */, 0, 0, 1, -1);
1301 checkGLError(GL_INVALID_VALUE, "scissorIndexed, negative height", test_result);
1302
1303 gl.scissorIndexedv(i /* index */, &data[i * 4]);
1304 checkGLError(GL_INVALID_VALUE, "scissorIndexedv, negative height", test_result);
1305 }
1306 }
1307
1308 /*
1309 * * Disablei, Enablei and IsEnabledi generate INVALID_VALUE when <cap> is
1310 * SCISSOR_TEST and <index> is greater than or equal to the
1311 * value of MAX_VIEWPORTS;
1312 */
1313 {
1314 gl.disablei(GL_SCISSOR_TEST, max_viewports - 1);
1315 checkGLError(GL_NO_ERROR, "disablei, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1316
1317 gl.disablei(GL_SCISSOR_TEST, max_viewports);
1318 checkGLError(GL_INVALID_VALUE, "disablei, <index> == GL_MAX_VIEWPORTS", test_result);
1319
1320 gl.enablei(GL_SCISSOR_TEST, max_viewports - 1);
1321 checkGLError(GL_NO_ERROR, "enablei, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1322
1323 gl.enablei(GL_SCISSOR_TEST, max_viewports);
1324 checkGLError(GL_INVALID_VALUE, "enablei, <index> == GL_MAX_VIEWPORTS", test_result);
1325
1326 gl.isEnabledi(GL_SCISSOR_TEST, max_viewports - 1);
1327 checkGLError(GL_NO_ERROR, "isEnabledi, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1328
1329 gl.isEnabledi(GL_SCISSOR_TEST, max_viewports);
1330 checkGLError(GL_INVALID_VALUE, "isEnabledi, <index> == GL_MAX_VIEWPORTS", test_result);
1331 }
1332
1333 /*
1334 * * GetIntegeri_v generates INVALID_VALUE when <target> is SCISSOR_BOX and
1335 * <index> is greater than or equal to the value of MAX_VIEWPORTS;
1336 */
1337 {
1338 GLint data[4];
1339
1340 gl.getIntegeri_v(GL_SCISSOR_BOX, max_viewports - 1, data);
1341 checkGLError(GL_NO_ERROR, "getIntegeri_v, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1342
1343 gl.getIntegeri_v(GL_SCISSOR_BOX, max_viewports, data);
1344 checkGLError(GL_INVALID_VALUE, "getIntegeri_v, <index> == GL_MAX_VIEWPORTS", test_result);
1345 }
1346
1347 /*
1348 * * GetFloati_v generates INVALID_VALUE when <target> is VIEWPORT and <index>
1349 * is greater than or equal to the value of MAX_VIEWPORTS;
1350 */
1351 {
1352 GLfloat data[4];
1353
1354 gl.getFloati_v(GL_VIEWPORT, max_viewports - 1, data);
1355 checkGLError(GL_NO_ERROR, "getFloati_v, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1356
1357 gl.getFloati_v(GL_VIEWPORT, max_viewports, data);
1358 checkGLError(GL_INVALID_VALUE, "getFloati_v, <index> == GL_MAX_VIEWPORTS", test_result);
1359 }
1360
1361 /*
1362 * * GetDoublei_v generates INVALID_VALUE when <target> is DEPTH_RANGE and
1363 * <index> is greater than or equal to the value of MAX_VIEWPORTS;
1364 */
1365 if (glu::isContextTypeGLCore(context_type))
1366 {
1367 getDepthHelper<GLdouble>(depthFunc, max_viewports, test_result);
1368 }
1369 else
1370 {
1371 DE_ASSERT(glu::isContextTypeES(context_type));
1372 getDepthHelper<GLfloat>(depthFunc, max_viewports, test_result);
1373 }
1374
1375 /* Set result */
1376 if (true == test_result)
1377 {
1378 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1379 }
1380 else
1381 {
1382 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1383 }
1384
1385 /* Done */
1386 return tcu::TestNode::STOP;
1387 }
1388
1389 /** Check if glGetError returns expected error
1390 *
1391 * @param expected_error Expected error code
1392 * @param description Description of test case
1393 * @param out_result Set to false if the current error is not equal to expected one
1394 **/
checkGLError(GLenum expected_error,const GLchar * description,bool & out_result)1395 void APIErrors::checkGLError(GLenum expected_error, const GLchar* description, bool& out_result)
1396 {
1397 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1398
1399 GLenum error = gl.getError();
1400
1401 if (expected_error != error)
1402 {
1403 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case fail. Description: " << description
1404 << " Invalid error: " << glu::getErrorStr(error)
1405 << " expected: " << glu::getErrorStr(expected_error)
1406 << tcu::TestLog::EndMessage;
1407
1408 out_result = false;
1409 }
1410 }
1411
1412 /** Constructor
1413 *
1414 * @param context Test context
1415 **/
Queries(deqp::Context & context,const glcts::ExtParameters & extParams)1416 Queries::Queries(deqp::Context& context, const glcts::ExtParameters& extParams)
1417 : TestCaseBase(context, extParams, "queries", "Test verifies initial state of API")
1418 {
1419 /* Nothing to be done here */
1420 }
1421
1422 template <typename T>
depthRangeInitialValuesHelper(Utils::DepthFuncWrapper & depthFunc,GLint max_viewports,bool & test_result,T *)1423 void Queries::depthRangeInitialValuesHelper(Utils::DepthFuncWrapper& depthFunc, GLint max_viewports, bool& test_result,
1424 T*)
1425 {
1426 std::vector<T> data;
1427 data.resize(max_viewports * 2 /* near + far */);
1428
1429 for (GLint i = 0; i < max_viewports; ++i)
1430 {
1431 depthFunc.getDepthi_v(GL_DEPTH_RANGE, i, &data[i * 2]);
1432 GLU_EXPECT_NO_ERROR(depthFunc.getFunctions().getError(), "getDouble/Floati_v");
1433 }
1434
1435 for (GLint i = 0; i < max_viewports; ++i)
1436 {
1437 GLint near = (GLint)data[2 * i + 0];
1438 GLint far = (GLint)data[2 * i + 1];
1439
1440 if ((0.0 != near) || (1.0 != far))
1441 {
1442 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid initial depth range [" << i
1443 << "]: " << near << " : " << far << " expected: 0.0 : 1.0"
1444 << tcu::TestLog::EndMessage;
1445
1446 test_result = false;
1447 break;
1448 }
1449 }
1450 }
1451 /** Execute test
1452 *
1453 * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
1454 **/
iterate()1455 tcu::TestNode::IterateResult Queries::iterate()
1456 {
1457 if (!m_is_viewport_array_supported)
1458 {
1459 throw tcu::NotSupportedError(VIEWPORT_ARRAY_NOT_SUPPORTED, "", __FILE__, __LINE__);
1460 }
1461
1462 /* GL entry points */
1463 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1464 const glu::ContextType& context_type = m_context.getRenderContext().getType();
1465 Utils::DepthFuncWrapper depthFunc(m_context);
1466
1467 /* Test result */
1468 bool test_result = true;
1469
1470 GLint layer_provoking_vertex = 0;
1471 GLint max_viewports = 0;
1472 GLfloat max_renderbuffer_size = 0.0f;
1473 GLfloat max_viewport_dims[2] = { 0.0f, 0.0f };
1474 GLfloat viewport_bounds_range[2] = { 0.0, 0.0f };
1475 GLint viewport_provoking_vertex = 0;
1476 GLint viewport_subpixel_bits = -1;
1477
1478 gl.getIntegerv(GL_LAYER_PROVOKING_VERTEX, &layer_provoking_vertex);
1479 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1480
1481 gl.getIntegerv(GL_MAX_VIEWPORTS, &max_viewports);
1482 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1483
1484 gl.getFloatv(GL_MAX_RENDERBUFFER_SIZE, &max_renderbuffer_size);
1485 GLU_EXPECT_NO_ERROR(gl.getError(), "getFloatv");
1486
1487 gl.getFloatv(GL_MAX_VIEWPORT_DIMS, max_viewport_dims);
1488 GLU_EXPECT_NO_ERROR(gl.getError(), "GetFloatv");
1489
1490 gl.getFloatv(GL_VIEWPORT_BOUNDS_RANGE, viewport_bounds_range);
1491 GLU_EXPECT_NO_ERROR(gl.getError(), "GetFloatv");
1492
1493 gl.getIntegerv(GL_VIEWPORT_INDEX_PROVOKING_VERTEX, &viewport_provoking_vertex);
1494 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1495
1496 gl.getIntegerv(GL_VIEWPORT_SUBPIXEL_BITS, &viewport_subpixel_bits);
1497 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1498
1499 const GLint window_width = m_context.getRenderContext().getRenderTarget().getWidth();
1500 const GLint window_height = m_context.getRenderContext().getRenderTarget().getHeight();
1501
1502 /*
1503 * * Initial dimensions of VIEWPORT returned by GetFloati_v match dimensions of
1504 * the window into which GL is rendering;
1505 */
1506 {
1507 std::vector<GLfloat> data;
1508 data.resize(max_viewports * 4 /* x + y + w+ h */);
1509
1510 for (GLint i = 0; i < max_viewports; ++i)
1511 {
1512 gl.getFloati_v(GL_VIEWPORT, i, &data[i * 4]);
1513 GLU_EXPECT_NO_ERROR(gl.getError(), "GetFloati_v");
1514 }
1515
1516 for (GLint i = 0; i < max_viewports; ++i)
1517 {
1518 GLint viewport_width = (GLint)data[4 * i + 2];
1519 GLint viewport_height = (GLint)data[4 * i + 3];
1520
1521 if ((window_width != viewport_width) || (window_height != viewport_height))
1522 {
1523 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid initial viewport [" << i
1524 << "] dimennsions: " << viewport_width << " x " << viewport_height
1525 << " expected: " << window_width << " x " << window_height
1526 << tcu::TestLog::EndMessage;
1527
1528 test_result = false;
1529 break;
1530 }
1531 }
1532 }
1533
1534 /*
1535 * * Initial values of DEPTH_RANGE returned by GetDoublei_v are [0, 1];
1536 */
1537 if (glu::isContextTypeGLCore(context_type))
1538 {
1539 depthRangeInitialValuesHelper<GLdouble>(depthFunc, max_viewports, test_result);
1540 }
1541 else
1542 {
1543 DE_ASSERT(glu::isContextTypeES(context_type));
1544 depthRangeInitialValuesHelper<GLfloat>(depthFunc, max_viewports, test_result);
1545 }
1546
1547 /*
1548 * * Initial state of SCISSOR_TEST returned by IsEnabledi is FALSE;
1549 */
1550 {
1551 for (GLint i = 0; i < max_viewports; ++i)
1552 {
1553 if (GL_FALSE != gl.isEnabledi(GL_SCISSOR_TEST, i))
1554 {
1555 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Scissor test is enabled at " << i
1556 << ". Expected disabled." << tcu::TestLog::EndMessage;
1557
1558 test_result = false;
1559 break;
1560 }
1561 }
1562 }
1563
1564 /*
1565 * * Initial dimensions of SCISSOR_BOX returned by GetIntegeri_v are either
1566 * zeros or match dimensions of the window into which GL is rendering;
1567 */
1568 {
1569 std::vector<GLint> data;
1570 data.resize(max_viewports * 4 /* x + y + w+ h */);
1571
1572 for (GLint i = 0; i < max_viewports; ++i)
1573 {
1574 gl.getIntegeri_v(GL_SCISSOR_BOX, i, &data[i * 4]);
1575 GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegeri_v");
1576 }
1577
1578 for (GLint i = 0; i < max_viewports; ++i)
1579 {
1580 GLint scissor_width = data[4 * i + 2];
1581 GLint scissor_height = data[4 * i + 3];
1582
1583 if ((window_width != scissor_width) || (window_height != scissor_height))
1584 {
1585 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid initial scissor box [" << i
1586 << "] dimennsions: " << scissor_width << " x " << scissor_height
1587 << " expected: " << window_width << " x " << window_height
1588 << tcu::TestLog::EndMessage;
1589
1590 test_result = false;
1591 break;
1592 }
1593 }
1594 }
1595
1596 /*
1597 * * Dimensions of MAX_VIEWPORT_DIMS returned by GetFloati_v are at least
1598 * as big as supported dimensions of render buffers, see MAX_RENDERBUFFER_SIZE;
1599 */
1600 {
1601 if ((max_viewport_dims[0] < max_renderbuffer_size) || (max_viewport_dims[1] < max_renderbuffer_size))
1602 {
1603 m_context.getTestContext().getLog()
1604 << tcu::TestLog::Message << "Invalid MAX_VIEWPORT_DIMS: " << max_viewport_dims[0] << " x "
1605 << max_viewport_dims[1] << " expected: " << max_renderbuffer_size << " x " << max_renderbuffer_size
1606 << tcu::TestLog::EndMessage;
1607
1608 test_result = false;
1609 }
1610 }
1611
1612 /*
1613 * * Value of MAX_VIEWPORTS returned by GetIntegeri_v is at least 16;
1614 */
1615 {
1616 if (16 > max_viewports)
1617 {
1618 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid MAX_VIEWPORTS: " << max_viewports
1619 << " expected at least 16." << tcu::TestLog::EndMessage;
1620
1621 test_result = false;
1622 }
1623 }
1624
1625 /*
1626 * * Value of VIEWPORT_SUBPIXEL_BITS returned by GetIntegeri_v is at least 0;
1627 */
1628 {
1629 if (0 > viewport_subpixel_bits)
1630 {
1631 m_context.getTestContext().getLog() << tcu::TestLog::Message
1632 << "Invalid VIEWPORT_SUBPIXEL_BITS: " << viewport_subpixel_bits
1633 << " expected at least 0." << tcu::TestLog::EndMessage;
1634
1635 test_result = false;
1636 }
1637 }
1638
1639 /*
1640 * * Values of VIEWPORT_BOUNDS_RANGE returned by GetFloatv are
1641 * at least [-32768, 32767];
1642 */
1643 {
1644 if ((-32768.0f < viewport_bounds_range[0]) || (32767.0f > viewport_bounds_range[1]))
1645 {
1646 m_context.getTestContext().getLog()
1647 << tcu::TestLog::Message << "Invalid VIEWPORT_BOUNDS_RANGE: " << viewport_bounds_range[0] << " : "
1648 << viewport_bounds_range[1] << " expected at least: -32768.0f : 32767.0f" << tcu::TestLog::EndMessage;
1649
1650 test_result = false;
1651 }
1652 }
1653
1654 /*
1655 * * Values of LAYER_PROVOKING_VERTEX and VIEWPORT_INDEX_PROVOKING_VERTEX
1656 * returned by GetIntegerv are located in the following set
1657 * { FIRST_VERTEX_CONVENTION, LAST_VERTEX_CONVENTION, PROVOKING_VERTEX,
1658 * UNDEFINED_VERTEX };
1659 */
1660 {
1661 switch (layer_provoking_vertex)
1662 {
1663 case GL_FIRST_VERTEX_CONVENTION:
1664 case GL_LAST_VERTEX_CONVENTION:
1665 case GL_PROVOKING_VERTEX:
1666 case GL_UNDEFINED_VERTEX:
1667 break;
1668 default:
1669 m_context.getTestContext().getLog() << tcu::TestLog::Message
1670 << "Invalid LAYER_PROVOKING_VERTEX: " << layer_provoking_vertex
1671 << tcu::TestLog::EndMessage;
1672
1673 test_result = false;
1674 }
1675
1676 switch (viewport_provoking_vertex)
1677 {
1678 case GL_FIRST_VERTEX_CONVENTION:
1679 case GL_LAST_VERTEX_CONVENTION:
1680 case GL_PROVOKING_VERTEX:
1681 case GL_UNDEFINED_VERTEX:
1682 break;
1683 default:
1684 m_context.getTestContext().getLog() << tcu::TestLog::Message
1685 << "Invalid LAYER_PROVOKING_VERTEX: " << layer_provoking_vertex
1686 << tcu::TestLog::EndMessage;
1687
1688 test_result = false;
1689 }
1690 }
1691
1692 /* Set result */
1693 if (true == test_result)
1694 {
1695 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1696 }
1697 else
1698 {
1699 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1700 }
1701
1702 /* Done */
1703 return tcu::TestNode::STOP;
1704 }
1705
1706 /* Constants used by ViewportAPI */
1707 const GLuint ViewportAPI::m_n_elements = 4;
1708
1709 /** Constructor
1710 *
1711 * @param context Test context
1712 **/
ViewportAPI(deqp::Context & context,const glcts::ExtParameters & extParams)1713 ViewportAPI::ViewportAPI(deqp::Context& context, const glcts::ExtParameters& extParams)
1714 : TestCaseBase(context, extParams, "viewport_api", "Test verifies that \viewport api\" works as expected")
1715 {
1716 /* Nothing to be done here */
1717 }
1718
1719 /** Execute test
1720 *
1721 * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
1722 **/
iterate()1723 tcu::TestNode::IterateResult ViewportAPI::iterate()
1724 {
1725 if (!m_is_viewport_array_supported)
1726 {
1727 throw tcu::NotSupportedError(VIEWPORT_ARRAY_NOT_SUPPORTED, "", __FILE__, __LINE__);
1728 }
1729
1730 /* GL entry points */
1731 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1732
1733 /* Test result */
1734 bool test_result = true;
1735
1736 GLint max_viewports = 0;
1737
1738 gl.getIntegerv(GL_MAX_VIEWPORTS, &max_viewports);
1739 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1740
1741 std::vector<GLfloat> scissor_box_data_a;
1742 std::vector<GLfloat> scissor_box_data_b;
1743
1744 scissor_box_data_a.resize(max_viewports * m_n_elements);
1745 scissor_box_data_b.resize(max_viewports * m_n_elements);
1746
1747 /*
1748 * - get initial dimensions of VIEWPORT for all MAX_VIEWPORTS indices;
1749 * - change location and dimensions of all indices at once with
1750 * ViewportArrayv;
1751 * - get VIEWPORT for all MAX_VIEWPORTS indices and verify results;
1752 */
1753 getViewports(max_viewports, scissor_box_data_a);
1754
1755 for (GLint i = 0; i < max_viewports; ++i)
1756 {
1757 scissor_box_data_a[i * m_n_elements + 0] += 0.125f;
1758 scissor_box_data_a[i * m_n_elements + 1] += 0.125f;
1759 scissor_box_data_a[i * m_n_elements + 2] -= 0.125f;
1760 scissor_box_data_a[i * m_n_elements + 3] -= 0.125f;
1761 }
1762
1763 gl.viewportArrayv(0, max_viewports, &scissor_box_data_a[0]);
1764 GLU_EXPECT_NO_ERROR(gl.getError(), "viewportArrayv");
1765
1766 getViewports(max_viewports, scissor_box_data_b);
1767 compareViewports(scissor_box_data_a, scissor_box_data_b, "viewportArrayv", test_result);
1768
1769 /*
1770 * - for each index:
1771 * * modify with ViewportIndexedf,
1772 * * get VIEWPORT for all MAX_VIEWPORTS indices and verify results;
1773 */
1774 for (GLint i = 0; i < max_viewports; ++i)
1775 {
1776 scissor_box_data_b[i * m_n_elements + 0] = 0.25f;
1777 scissor_box_data_b[i * m_n_elements + 1] = 0.25f;
1778 scissor_box_data_b[i * m_n_elements + 2] = 0.75f;
1779 scissor_box_data_b[i * m_n_elements + 3] = 0.75f;
1780
1781 gl.viewportIndexedf(i, 0.25f, 0.25f, 0.75f, 0.75f);
1782 GLU_EXPECT_NO_ERROR(gl.getError(), "viewportIndexedf");
1783
1784 getViewports(max_viewports, scissor_box_data_a);
1785 compareViewports(scissor_box_data_a, scissor_box_data_b, "viewportIndexedf", test_result);
1786 }
1787
1788 /*
1789 * - for each index:
1790 * * modify with ViewportIndexedfv,
1791 * * get VIEWPORT for all MAX_VIEWPORTS indices and verify results;
1792 */
1793 for (GLint i = 0; i < max_viewports; ++i)
1794 {
1795 scissor_box_data_a[i * m_n_elements + 0] = 0.375f;
1796 scissor_box_data_a[i * m_n_elements + 1] = 0.375f;
1797 scissor_box_data_a[i * m_n_elements + 2] = 0.625f;
1798 scissor_box_data_a[i * m_n_elements + 3] = 0.625f;
1799
1800 gl.viewportIndexedfv(i, &scissor_box_data_a[i * m_n_elements]);
1801 GLU_EXPECT_NO_ERROR(gl.getError(), "viewportIndexedfv");
1802
1803 getViewports(max_viewports, scissor_box_data_b);
1804 compareViewports(scissor_box_data_a, scissor_box_data_b, "viewportIndexedfv", test_result);
1805 }
1806
1807 /*
1808 * - for each index:
1809 * * modify all indices before and after current one with ViewportArrayv,
1810 * * get VIEWPORT for all MAX_VIEWPORTS indices and verify results;
1811 */
1812 for (GLint i = 0; i < max_viewports; ++i)
1813 {
1814 const GLfloat value = (0 == i % 2) ? 1.0f : 0.25f;
1815
1816 for (GLint j = 0; j < i; ++j)
1817 {
1818 scissor_box_data_b[j * m_n_elements + 0] = value;
1819 scissor_box_data_b[j * m_n_elements + 1] = value;
1820 scissor_box_data_b[j * m_n_elements + 2] = value;
1821 scissor_box_data_b[j * m_n_elements + 3] = value;
1822 }
1823
1824 for (GLint j = i + 1; j < max_viewports; ++j)
1825 {
1826 scissor_box_data_b[j * m_n_elements + 0] = value;
1827 scissor_box_data_b[j * m_n_elements + 1] = value;
1828 scissor_box_data_b[j * m_n_elements + 2] = value;
1829 scissor_box_data_b[j * m_n_elements + 3] = value;
1830 }
1831
1832 gl.viewportArrayv(0, max_viewports, &scissor_box_data_b[0]);
1833 GLU_EXPECT_NO_ERROR(gl.getError(), "viewportArrayv");
1834
1835 getViewports(max_viewports, scissor_box_data_a);
1836 compareViewports(scissor_box_data_a, scissor_box_data_b, "viewportArrayv", test_result);
1837 }
1838
1839 /*
1840 * - change location and dimensions of all indices at once with Viewport;
1841 * - get VIEWPORT for all MAX_VIEWPORTS indices and verify results;
1842 */
1843 for (GLint i = 0; i < max_viewports; ++i)
1844 {
1845 scissor_box_data_a[i * m_n_elements + 0] = 0.0f;
1846 scissor_box_data_a[i * m_n_elements + 1] = 0.0f;
1847 scissor_box_data_a[i * m_n_elements + 2] = 1.0f;
1848 scissor_box_data_a[i * m_n_elements + 3] = 1.0f;
1849 }
1850
1851 gl.viewport(0, 0, 1, 1);
1852 GLU_EXPECT_NO_ERROR(gl.getError(), "viewport");
1853
1854 getViewports(max_viewports, scissor_box_data_b);
1855 compareViewports(scissor_box_data_a, scissor_box_data_b, "viewport", test_result);
1856
1857 /* Set result */
1858 if (true == test_result)
1859 {
1860 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1861 }
1862 else
1863 {
1864 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1865 }
1866
1867 /* Done */
1868 return tcu::TestNode::STOP;
1869 }
1870
1871 /** Compare two sets of viewport data (simple vector comparison)
1872 *
1873 * @param left Left set
1874 * @param right Right set
1875 * @param description Test case description
1876 * @param out_result Set to false if sets are different, not modified otherwise
1877 **/
compareViewports(std::vector<GLfloat> & left,std::vector<GLfloat> & right,const GLchar * description,bool & out_result)1878 void ViewportAPI::compareViewports(std::vector<GLfloat>& left, std::vector<GLfloat>& right, const GLchar* description,
1879 bool& out_result)
1880 {
1881 for (size_t i = 0; i < left.size(); ++i)
1882 {
1883 if (left[i] != right[i])
1884 {
1885 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << description
1886 << " Invalid values [" << i << "] " << left[i] << " " << right[i]
1887 << tcu::TestLog::EndMessage;
1888
1889 out_result = false;
1890 }
1891 }
1892 }
1893
1894 /** Get position of all viewports
1895 *
1896 * @param max_viewports Number of viewports to capture, MAX_VIEWPORTS
1897 * @param data Memory buffer prepared for captured data
1898 **/
getViewports(GLint max_viewports,std::vector<GLfloat> & out_data)1899 void ViewportAPI::getViewports(GLint max_viewports, std::vector<GLfloat>& out_data)
1900 {
1901 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1902
1903 for (GLint i = 0; i < max_viewports; ++i)
1904 {
1905 gl.getFloati_v(GL_VIEWPORT, i, &out_data[i * 4]);
1906 GLU_EXPECT_NO_ERROR(gl.getError(), "getFloati_v");
1907 }
1908 }
1909
1910 /* Constants used by ScissorAPI */
1911 const GLuint ScissorAPI::m_n_elements = 4;
1912
1913 /** Constructor
1914 *
1915 * @param context Test context
1916 **/
ScissorAPI(deqp::Context & context,const glcts::ExtParameters & extParams)1917 ScissorAPI::ScissorAPI(deqp::Context& context, const glcts::ExtParameters& extParams)
1918 : TestCaseBase(context, extParams, "scissor_api", "Test verifies that \"scissor api\" works as expected")
1919 {
1920 /* Nothing to be done here */
1921 }
1922
1923 /** Execute test
1924 *
1925 * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
1926 **/
iterate()1927 tcu::TestNode::IterateResult ScissorAPI::iterate()
1928 {
1929 if (!m_is_viewport_array_supported)
1930 {
1931 throw tcu::NotSupportedError(VIEWPORT_ARRAY_NOT_SUPPORTED, "", __FILE__, __LINE__);
1932 }
1933
1934 /* GL entry points */
1935 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1936
1937 /* Test result */
1938 bool test_result = true;
1939
1940 GLint max_viewports = 0;
1941
1942 gl.getIntegerv(GL_MAX_VIEWPORTS, &max_viewports);
1943 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1944
1945 std::vector<GLint> scissor_box_data_a;
1946 std::vector<GLint> scissor_box_data_b;
1947
1948 scissor_box_data_a.resize(max_viewports * m_n_elements);
1949 scissor_box_data_b.resize(max_viewports * m_n_elements);
1950
1951 /*
1952 * - get initial dimensions of SCISSOR_BOX for all MAX_VIEWPORTS indices;
1953 * - change location and dimensions of all indices at once with
1954 * ScissorArrayv;
1955 * - get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results;
1956 */
1957 getScissorBoxes(max_viewports, scissor_box_data_a);
1958
1959 for (GLint i = 0; i < max_viewports; ++i)
1960 {
1961 scissor_box_data_a[i * m_n_elements + 0] += 1;
1962 scissor_box_data_a[i * m_n_elements + 1] += 1;
1963 scissor_box_data_a[i * m_n_elements + 2] -= 1;
1964 scissor_box_data_a[i * m_n_elements + 3] -= 1;
1965 }
1966
1967 gl.scissorArrayv(0, max_viewports, &scissor_box_data_a[0]);
1968 GLU_EXPECT_NO_ERROR(gl.getError(), "scissorArrayv");
1969
1970 getScissorBoxes(max_viewports, scissor_box_data_b);
1971 compareScissorBoxes(scissor_box_data_a, scissor_box_data_b, "scissorArrayv", test_result);
1972
1973 /*
1974 * - for each index:
1975 * * modify with ScissorIndexed,
1976 * * get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results;
1977 */
1978 for (GLint i = 0; i < max_viewports; ++i)
1979 {
1980 scissor_box_data_b[i * m_n_elements + 0] = 4;
1981 scissor_box_data_b[i * m_n_elements + 1] = 4;
1982 scissor_box_data_b[i * m_n_elements + 2] = 8;
1983 scissor_box_data_b[i * m_n_elements + 3] = 8;
1984
1985 gl.scissorIndexed(i, 4, 4, 8, 8);
1986 GLU_EXPECT_NO_ERROR(gl.getError(), "scissorIndexed");
1987
1988 getScissorBoxes(max_viewports, scissor_box_data_a);
1989 compareScissorBoxes(scissor_box_data_a, scissor_box_data_b, "scissorIndexed", test_result);
1990 }
1991
1992 /*
1993 * - for each index:
1994 * * modify with ScissorIndexedv,
1995 * * get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results;
1996 */
1997 for (GLint i = 0; i < max_viewports; ++i)
1998 {
1999 scissor_box_data_a[i * m_n_elements + 0] = 8;
2000 scissor_box_data_a[i * m_n_elements + 1] = 8;
2001 scissor_box_data_a[i * m_n_elements + 2] = 12;
2002 scissor_box_data_a[i * m_n_elements + 3] = 12;
2003
2004 gl.scissorIndexedv(i, &scissor_box_data_a[i * m_n_elements]);
2005 GLU_EXPECT_NO_ERROR(gl.getError(), "scissorIndexedv");
2006
2007 getScissorBoxes(max_viewports, scissor_box_data_b);
2008 compareScissorBoxes(scissor_box_data_a, scissor_box_data_b, "scissorIndexedv", test_result);
2009 }
2010
2011 /*
2012 * - for each index:
2013 * * modify all indices before and after current one with ScissorArrayv,
2014 * * get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results;
2015 */
2016 for (GLint i = 0; i < max_viewports; ++i)
2017 {
2018 const GLint value = (0 == i % 2) ? 1 : 4;
2019
2020 for (GLint j = 0; j < i; ++j)
2021 {
2022 scissor_box_data_b[j * m_n_elements + 0] = value;
2023 scissor_box_data_b[j * m_n_elements + 1] = value;
2024 scissor_box_data_b[j * m_n_elements + 2] = value;
2025 scissor_box_data_b[j * m_n_elements + 3] = value;
2026 }
2027
2028 for (GLint j = i + 1; j < max_viewports; ++j)
2029 {
2030 scissor_box_data_b[j * m_n_elements + 0] = value;
2031 scissor_box_data_b[j * m_n_elements + 1] = value;
2032 scissor_box_data_b[j * m_n_elements + 2] = value;
2033 scissor_box_data_b[j * m_n_elements + 3] = value;
2034 }
2035
2036 gl.scissorArrayv(0, max_viewports, &scissor_box_data_b[0]);
2037 GLU_EXPECT_NO_ERROR(gl.getError(), "scissorArrayv");
2038
2039 getScissorBoxes(max_viewports, scissor_box_data_a);
2040 compareScissorBoxes(scissor_box_data_a, scissor_box_data_b, "scissorArrayv", test_result);
2041 }
2042
2043 /*
2044 * - change location and dimensions of all indices at once with Scissor;
2045 * - get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results;
2046 */
2047 for (GLint i = 0; i < max_viewports; ++i)
2048 {
2049 scissor_box_data_a[i * m_n_elements + 0] = 0;
2050 scissor_box_data_a[i * m_n_elements + 1] = 0;
2051 scissor_box_data_a[i * m_n_elements + 2] = 1;
2052 scissor_box_data_a[i * m_n_elements + 3] = 1;
2053 }
2054
2055 gl.scissor(0, 0, 1, 1);
2056 GLU_EXPECT_NO_ERROR(gl.getError(), "scissor");
2057
2058 getScissorBoxes(max_viewports, scissor_box_data_b);
2059 compareScissorBoxes(scissor_box_data_a, scissor_box_data_b, "scissor", test_result);
2060
2061 /* Set result */
2062 if (true == test_result)
2063 {
2064 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2065 }
2066 else
2067 {
2068 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2069 }
2070
2071 /* Done */
2072 return tcu::TestNode::STOP;
2073 }
2074
2075 /** Compare two sets of scissor box data (simple vector comparison)
2076 *
2077 * @param left Left set
2078 * @param right Right set
2079 * @param description Test case description
2080 * @param out_result Set to false if sets are different, not modified otherwise
2081 **/
compareScissorBoxes(std::vector<GLint> & left,std::vector<GLint> & right,const GLchar * description,bool & out_result)2082 void ScissorAPI::compareScissorBoxes(std::vector<GLint>& left, std::vector<GLint>& right, const GLchar* description,
2083 bool& out_result)
2084 {
2085 for (size_t i = 0; i < left.size(); ++i)
2086 {
2087 if (left[i] != right[i])
2088 {
2089 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << description
2090 << " Invalid values [" << i << "] " << left[i] << " " << right[i]
2091 << tcu::TestLog::EndMessage;
2092
2093 out_result = false;
2094 }
2095 }
2096 }
2097
2098 /** Get position of all scissor boxes
2099 *
2100 * @param max_viewports Number of scissor boxes to capture, MAX_VIEWPORTS
2101 * @param data Memory buffer prepared for captured data
2102 **/
getScissorBoxes(GLint max_viewports,std::vector<GLint> & out_data)2103 void ScissorAPI::getScissorBoxes(GLint max_viewports, std::vector<GLint>& out_data)
2104 {
2105 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2106
2107 for (GLint i = 0; i < max_viewports; ++i)
2108 {
2109 gl.getIntegeri_v(GL_SCISSOR_BOX, i, &out_data[i * 4]);
2110 GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegeri_v");
2111 }
2112 }
2113
2114 /* Constants used by DepthRangeAPI */
2115 const GLuint DepthRangeAPI::m_n_elements = 2 /* near + far */;
2116
2117 /** Constructor
2118 *
2119 * @param context Test context
2120 **/
DepthRangeAPI(deqp::Context & context,const glcts::ExtParameters & extParams)2121 DepthRangeAPI::DepthRangeAPI(deqp::Context& context, const glcts::ExtParameters& extParams)
2122 : TestCaseBase(context, extParams, "depth_range_api", "Test verifies that \"depth range api\" works as expected")
2123 {
2124 /* Nothing to be done here */
2125 }
2126
2127 /** Execute test
2128 *
2129 * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
2130 **/
iterate()2131 tcu::TestNode::IterateResult DepthRangeAPI::iterate()
2132 {
2133 if (!m_is_viewport_array_supported)
2134 {
2135 throw tcu::NotSupportedError(VIEWPORT_ARRAY_NOT_SUPPORTED, "", __FILE__, __LINE__);
2136 }
2137
2138 bool test_result;
2139 const glu::ContextType& context_type = m_context.getRenderContext().getType();
2140
2141 if (glu::isContextTypeGLCore(context_type))
2142 {
2143 test_result = iterateHelper<GLdouble>();
2144 }
2145 else
2146 {
2147 DE_ASSERT(glu::isContextTypeES(context_type));
2148 test_result = iterateHelper<GLfloat>();
2149 }
2150
2151 /* Set result */
2152 if (true == test_result)
2153 {
2154 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2155 }
2156 else
2157 {
2158 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2159 }
2160
2161 /* Done */
2162 return tcu::TestNode::STOP;
2163 }
2164
2165 template <typename T>
iterateHelper(T *)2166 bool DepthRangeAPI::iterateHelper(T*)
2167 {
2168 /* GL entry points */
2169 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2170 Utils::DepthFuncWrapper depthFunc(m_context);
2171
2172 bool test_result = true;
2173
2174 GLint max_viewports = 0;
2175
2176 gl.getIntegerv(GL_MAX_VIEWPORTS, &max_viewports);
2177 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2178
2179 std::vector<T> depth_range_data_a;
2180 std::vector<T> depth_range_data_b;
2181
2182 depth_range_data_a.resize(max_viewports * m_n_elements);
2183 depth_range_data_b.resize(max_viewports * m_n_elements);
2184
2185 /*
2186 * - get initial values of DEPTH_RANGE for all MAX_VIEWPORTS indices;
2187 * - change values of all indices at once with DepthRangeArrayv;
2188 * - get DEPTH_RANGE for all MAX_VIEWPORTS indices and verify results;
2189 */
2190 getDepthRanges(depthFunc, max_viewports, depth_range_data_a);
2191
2192 for (GLint i = 0; i < max_viewports; ++i)
2193 {
2194 depth_range_data_a[i * m_n_elements + 0] += 0.125;
2195 depth_range_data_a[i * m_n_elements + 1] -= 0.125;
2196 }
2197
2198 depthFunc.depthRangeArray(0, max_viewports, &depth_range_data_a[0]);
2199 GLU_EXPECT_NO_ERROR(gl.getError(), "depthRangeArray");
2200
2201 getDepthRanges(depthFunc, max_viewports, depth_range_data_b);
2202 compareDepthRanges(depth_range_data_a, depth_range_data_b, "depthRangeArray", test_result);
2203
2204 /*
2205 * - for each index:
2206 * * modify with DepthRangeIndexed,
2207 * * get DEPTH_RANGE for all MAX_VIEWPORTS indices and verify results;
2208 */
2209 for (GLint i = 0; i < max_viewports; ++i)
2210 {
2211 depth_range_data_b[i * m_n_elements + 0] = 0.25;
2212 depth_range_data_b[i * m_n_elements + 1] = 0.75;
2213
2214 depthFunc.depthRangeIndexed(i, (T)0.25, (T)0.75);
2215 GLU_EXPECT_NO_ERROR(gl.getError(), "depthRangeIndexed");
2216
2217 getDepthRanges(depthFunc, max_viewports, depth_range_data_a);
2218 compareDepthRanges(depth_range_data_a, depth_range_data_b, "depthRangeIndexed", test_result);
2219 }
2220
2221 /*
2222 * - for each index:
2223 * * modify all indices before and after current one with DepthRangeArrayv,
2224 * * get DEPTH_RANGE for all MAX_VIEWPORTS indices and verify results;
2225 */
2226 for (GLint i = 0; i < max_viewports; ++i)
2227 {
2228 const T value = (0 == i % 2) ? T(1.0) : T(0.25);
2229
2230 for (GLint j = 0; j < i; ++j)
2231 {
2232 depth_range_data_b[j * m_n_elements + 0] = value;
2233 depth_range_data_b[j * m_n_elements + 1] = value;
2234 }
2235
2236 for (GLint j = i + 1; j < max_viewports; ++j)
2237 {
2238 depth_range_data_b[j * m_n_elements + 0] = value;
2239 depth_range_data_b[j * m_n_elements + 1] = value;
2240 }
2241
2242 depthFunc.depthRangeArray(0, max_viewports, &depth_range_data_b[0]);
2243 GLU_EXPECT_NO_ERROR(gl.getError(), "depthRangeArray");
2244
2245 getDepthRanges(depthFunc, max_viewports, depth_range_data_a);
2246 compareDepthRanges(depth_range_data_a, depth_range_data_b, "depthRangeArray", test_result);
2247 }
2248
2249 /*
2250 * - change values of all indices at once with DepthRange;
2251 * - get DEPTH_RANGE for all MAX_VIEWPORTS indices and verify results;
2252 */
2253 for (GLint i = 0; i < max_viewports; ++i)
2254 {
2255 depth_range_data_a[i * m_n_elements + 0] = 0.0f;
2256 depth_range_data_a[i * m_n_elements + 1] = 1.0f;
2257 }
2258
2259 depthFunc.depthRange((T)0.0, (T)1.0);
2260 GLU_EXPECT_NO_ERROR(gl.getError(), "depthRange");
2261
2262 getDepthRanges(depthFunc, max_viewports, depth_range_data_b);
2263 compareDepthRanges(depth_range_data_a, depth_range_data_b, "depthRange", test_result);
2264
2265 return test_result;
2266 }
2267
2268 /** Compare two sets of depth range data (simple vector comparison)
2269 *
2270 * @param left Left set
2271 * @param right Right set
2272 * @param description Test case description
2273 * @param out_result Set to false if sets are different, not modified otherwise
2274 **/
2275 template <typename T>
compareDepthRanges(std::vector<T> & left,std::vector<T> & right,const GLchar * description,bool & out_result)2276 void DepthRangeAPI::compareDepthRanges(std::vector<T>& left, std::vector<T>& right, const GLchar* description,
2277 bool& out_result)
2278 {
2279 for (size_t i = 0; i < left.size(); ++i)
2280 {
2281 if (left[i] != right[i])
2282 {
2283 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << description
2284 << " Invalid values [" << i << "] " << left[i] << " " << right[i]
2285 << tcu::TestLog::EndMessage;
2286 out_result = false;
2287 }
2288 }
2289 }
2290
2291 /** Get all depth ranges
2292 *
2293 * @param max_viewports Number of viewports to capture, MAX_VIEWPORTS
2294 * @param data Memory buffer prepared for captured data
2295 **/
2296 template <typename T>
getDepthRanges(Utils::DepthFuncWrapper & depthFunc,GLint max_viewports,std::vector<T> & out_data)2297 void DepthRangeAPI::getDepthRanges(Utils::DepthFuncWrapper& depthFunc, GLint max_viewports, std::vector<T>& out_data)
2298 {
2299 for (GLint i = 0; i < max_viewports; ++i)
2300 {
2301 depthFunc.getDepthi_v(GL_DEPTH_RANGE, i, &out_data[i * m_n_elements]);
2302 GLU_EXPECT_NO_ERROR(depthFunc.getFunctions().getError(), "getDouble/Floati_v");
2303 }
2304 }
2305
2306 /** Constructor
2307 *
2308 * @param context Test context
2309 **/
ScissorTestStateAPI(deqp::Context & context,const glcts::ExtParameters & extParams)2310 ScissorTestStateAPI::ScissorTestStateAPI(deqp::Context& context, const glcts::ExtParameters& extParams)
2311 : TestCaseBase(context, extParams, "scissor_test_state_api",
2312 "Test verifies that \"enable/disable api\" works as expected for scissor test")
2313 {
2314 /* Nothing to be done here */
2315 }
2316
2317 /** Execute test
2318 *
2319 * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
2320 **/
iterate()2321 tcu::TestNode::IterateResult ScissorTestStateAPI::iterate()
2322 {
2323 if (!m_is_viewport_array_supported)
2324 {
2325 throw tcu::NotSupportedError(VIEWPORT_ARRAY_NOT_SUPPORTED, "", __FILE__, __LINE__);
2326 }
2327
2328 /* GL entry points */
2329 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2330
2331 /* Test result */
2332 bool test_result = true;
2333
2334 GLint max_viewports = 0;
2335
2336 gl.getIntegerv(GL_MAX_VIEWPORTS, &max_viewports);
2337 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2338
2339 std::vector<GLboolean> scissor_test_states_a;
2340 std::vector<GLboolean> scissor_test_states_b;
2341
2342 scissor_test_states_a.resize(max_viewports);
2343 scissor_test_states_b.resize(max_viewports);
2344
2345 /*
2346 * - get initial state of SCISSOR_TEST for all MAX_VIEWPORTS indices;
2347 * - for each index:
2348 * * toggle SCISSOR_TEST,
2349 * * get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify;
2350 * - for each index:
2351 * * toggle SCISSOR_TEST,
2352 * * get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify;
2353 */
2354 getScissorTestStates(max_viewports, scissor_test_states_a);
2355
2356 for (GLint i = 0; i < max_viewports; ++i)
2357 {
2358 if (GL_FALSE == scissor_test_states_a[i])
2359 {
2360 gl.enablei(GL_SCISSOR_TEST, i);
2361 GLU_EXPECT_NO_ERROR(gl.getError(), "Enablei");
2362
2363 scissor_test_states_a[i] = GL_TRUE;
2364 }
2365 else
2366 {
2367 gl.disablei(GL_SCISSOR_TEST, i);
2368 GLU_EXPECT_NO_ERROR(gl.getError(), "Disablei");
2369
2370 scissor_test_states_a[i] = GL_FALSE;
2371 }
2372
2373 getScissorTestStates(max_viewports, scissor_test_states_b);
2374 compareScissorTestStates(scissor_test_states_a, scissor_test_states_b, "1st toggle", test_result);
2375 }
2376
2377 for (GLint i = 0; i < max_viewports; ++i)
2378 {
2379 if (GL_FALSE == scissor_test_states_a[i])
2380 {
2381 gl.enablei(GL_SCISSOR_TEST, i);
2382 GLU_EXPECT_NO_ERROR(gl.getError(), "Enablei");
2383
2384 scissor_test_states_a[i] = GL_TRUE;
2385 }
2386 else
2387 {
2388 gl.disablei(GL_SCISSOR_TEST, i);
2389 GLU_EXPECT_NO_ERROR(gl.getError(), "Disablei");
2390
2391 scissor_test_states_a[i] = GL_FALSE;
2392 }
2393
2394 getScissorTestStates(max_viewports, scissor_test_states_b);
2395 compareScissorTestStates(scissor_test_states_a, scissor_test_states_b, "2nd toggle", test_result);
2396 }
2397
2398 /*
2399 * - enable SCISSOR_TEST for all indices at once with Enable;
2400 * - get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify;
2401 */
2402 for (GLint i = 0; i < max_viewports; ++i)
2403 {
2404 scissor_test_states_a[i] = GL_TRUE;
2405 }
2406
2407 gl.enable(GL_SCISSOR_TEST);
2408 GLU_EXPECT_NO_ERROR(gl.getError(), "Enable");
2409
2410 getScissorTestStates(max_viewports, scissor_test_states_b);
2411 compareScissorTestStates(scissor_test_states_a, scissor_test_states_b, "1st enable all", test_result);
2412
2413 /*
2414 * - disable SCISSOR_TEST for all indices at once with Disable;
2415 * - get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify;
2416 */
2417 for (GLint i = 0; i < max_viewports; ++i)
2418 {
2419 scissor_test_states_a[i] = GL_FALSE;
2420 }
2421
2422 gl.disable(GL_SCISSOR_TEST);
2423 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
2424
2425 getScissorTestStates(max_viewports, scissor_test_states_b);
2426 compareScissorTestStates(scissor_test_states_a, scissor_test_states_b, "Disable all", test_result);
2427
2428 /*
2429 * - enable SCISSOR_TEST for all indices at once with Enable;
2430 * - get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify;
2431 */
2432 for (GLint i = 0; i < max_viewports; ++i)
2433 {
2434 scissor_test_states_a[i] = GL_TRUE;
2435 }
2436
2437 gl.enable(GL_SCISSOR_TEST);
2438 GLU_EXPECT_NO_ERROR(gl.getError(), "Enable");
2439
2440 getScissorTestStates(max_viewports, scissor_test_states_b);
2441 compareScissorTestStates(scissor_test_states_a, scissor_test_states_b, "2nd enable all", test_result);
2442
2443 /* Set result */
2444 if (true == test_result)
2445 {
2446 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2447 }
2448 else
2449 {
2450 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2451 }
2452
2453 /* Done */
2454 return tcu::TestNode::STOP;
2455 }
2456
2457 /** Compare two sets of depth range data (simple vector comparison)
2458 *
2459 * @param left Left set
2460 * @param right Right set
2461 * @param description Test case description
2462 * @param out_result Set to false if sets are different, not modified otherwise
2463 **/
compareScissorTestStates(std::vector<GLboolean> & left,std::vector<GLboolean> & right,const GLchar * description,bool & out_result)2464 void ScissorTestStateAPI::compareScissorTestStates(std::vector<GLboolean>& left, std::vector<GLboolean>& right,
2465 const GLchar* description, bool& out_result)
2466 {
2467 for (size_t i = 0; i < left.size(); ++i)
2468 {
2469 if (left[i] != right[i])
2470 {
2471 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << description
2472 << " Invalid values [" << i << "] " << left[i] << " " << right[i]
2473 << tcu::TestLog::EndMessage;
2474
2475 out_result = false;
2476 }
2477 }
2478 }
2479
2480 /** Get all depth ranges
2481 *
2482 * @param max_viewports Number of viewports to capture, MAX_VIEWPORTS
2483 * @param data Memory buffer prepared for captured data
2484 **/
getScissorTestStates(GLint max_viewports,std::vector<GLboolean> & out_data)2485 void ScissorTestStateAPI::getScissorTestStates(GLint max_viewports, std::vector<GLboolean>& out_data)
2486 {
2487 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2488
2489 for (GLint i = 0; i < max_viewports; ++i)
2490 {
2491 out_data[i] = gl.isEnabledi(GL_SCISSOR_TEST, i);
2492 GLU_EXPECT_NO_ERROR(gl.getError(), "isEnabledi");
2493 }
2494 }
2495
2496 /* Constants used by DrawTestBase */
2497 const GLuint DrawTestBase::m_depth = 16;
2498 const GLuint DrawTestBase::m_height = 128;
2499 const GLuint DrawTestBase::m_width = 128;
2500 const GLuint DrawTestBase::m_r32f_height = 2;
2501 const GLuint DrawTestBase::m_r32f_width = 16;
2502 const GLuint DrawTestBase::m_r32ix4_depth = 4;
2503
2504 /** Constructor
2505 *
2506 * @param context Test context
2507 * @param test_name Test name
2508 * @param test_description Test description
2509 **/
DrawTestBase(deqp::Context & context,const glcts::ExtParameters & extParams,const GLchar * test_name,const GLchar * test_description)2510 DrawTestBase::DrawTestBase(deqp::Context& context, const glcts::ExtParameters& extParams, const GLchar* test_name,
2511 const GLchar* test_description)
2512 : TestCaseBase(context, extParams, test_name, test_description)
2513 {
2514 /* Nothing to be done here */
2515 }
2516
2517 /** Execute test
2518 *
2519 * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
2520 **/
iterate()2521 tcu::TestNode::IterateResult DrawTestBase::iterate()
2522 {
2523 if (!m_is_viewport_array_supported)
2524 {
2525 throw tcu::NotSupportedError(VIEWPORT_ARRAY_NOT_SUPPORTED, "", __FILE__, __LINE__);
2526 }
2527
2528 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2529 const glu::ContextType& context_type = m_context.getRenderContext().getType();
2530
2531 /* Test result */
2532 bool test_result = true;
2533
2534 /* Get type of test */
2535 const TEST_TYPE test_type = getTestType();
2536
2537 GLuint n_draw_calls = getDrawCallsNumber();
2538 GLuint n_iterations = 0;
2539 switch (test_type)
2540 {
2541 case VIEWPORT:
2542 case SCISSOR:
2543 n_iterations = 3;
2544 break;
2545 case DEPTHRANGE:
2546 case PROVOKING:
2547 n_iterations = 2;
2548 break;
2549 default:
2550 TCU_FAIL("Invalid enum");
2551 }
2552
2553 /* Get shader sources and specialize them */
2554 const std::string& frag = getFragmentShader();
2555 const std::string& geom = getGeometryShader();
2556 const std::string& vert = getVertexShader();
2557
2558 const GLchar* frag_template = frag.c_str();
2559 const GLchar* geom_template = geom.c_str();
2560 const GLchar* vert_template = vert.c_str();
2561
2562 std::string fragment = specializeShader(1, &frag_template);
2563 std::string geometry = specializeShader(1, &geom_template);
2564 std::string vertex = specializeShader(1, &vert_template);
2565
2566 /* Prepare program */
2567 Utils::program program(m_context);
2568
2569 try
2570 {
2571 program.build(0 /* compute */, fragment.c_str(), geometry.c_str(), 0 /* tess ctrl */, 0 /* tess eval */,
2572 vertex.c_str(), 0 /* varying names */, 0 /* n_varyings */);
2573 }
2574 catch (Utils::shaderCompilationException& exc)
2575 {
2576 /* Something wrong with compilation, test case failed */
2577 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
2578
2579 message << "Shader compilation failed. Error message: " << exc.m_error_message;
2580
2581 Utils::program::printShaderSource(exc.m_shader_source.c_str(), message);
2582
2583 message << tcu::TestLog::EndMessage;
2584
2585 TCU_FAIL("Shader compilation failed");
2586 }
2587 catch (Utils::programLinkageException& exc)
2588 {
2589 /* Something wrong with linking, test case failed */
2590 m_context.getTestContext().getLog() << tcu::TestLog::Message
2591 << "Program linking failed. Error message: " << exc.m_error_message
2592 << tcu::TestLog::EndMessage;
2593 TCU_FAIL("Program linking failed");
2594 }
2595
2596 program.use();
2597
2598 /* Prepare VAO */
2599 Utils::vertexArray vao(m_context);
2600 vao.generate();
2601 vao.bind();
2602
2603 /* For each iteration from test type */
2604 for (GLuint i = 0; i < n_iterations; ++i)
2605 {
2606 /* Prepare textures */
2607 Utils::texture texture_0(m_context);
2608 Utils::texture texture_1(m_context);
2609
2610 prepareTextures(texture_0, texture_1);
2611
2612 /* Prepare framebuffer */
2613 Utils::framebuffer framebuffer(m_context);
2614 framebuffer.generate();
2615 setupFramebuffer(framebuffer, texture_0, texture_1);
2616 framebuffer.bind();
2617
2618 /* Set up viewports */
2619 setupViewports(test_type, i);
2620
2621 if (false == isClearTest())
2622 {
2623 /* For each draw call */
2624 for (GLuint draw_call = 0; draw_call < n_draw_calls; ++draw_call)
2625 {
2626 prepareUniforms(program, draw_call);
2627
2628 bool is_clear;
2629 GLfloat depth_value;
2630
2631 getClearSettings(is_clear, draw_call, depth_value);
2632
2633 if (true == is_clear)
2634 {
2635 if (glu::isContextTypeGLCore(context_type))
2636 {
2637 gl.clearDepth((GLdouble)depth_value);
2638 }
2639 else
2640 {
2641 gl.clearDepthf(depth_value);
2642 }
2643 GLU_EXPECT_NO_ERROR(gl.getError(), "ClearDepth");
2644
2645 gl.clear(GL_DEPTH_BUFFER_BIT);
2646 GLU_EXPECT_NO_ERROR(gl.getError(), "Clear");
2647 }
2648
2649 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
2650 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
2651
2652 bool result = checkResults(texture_0, texture_1, draw_call);
2653
2654 if (false == result)
2655 {
2656 test_result = false;
2657 goto end;
2658 }
2659 }
2660 }
2661 else
2662 {
2663 gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
2664 GLU_EXPECT_NO_ERROR(gl.getError(), "ClearColor");
2665
2666 gl.clear(GL_COLOR_BUFFER_BIT);
2667 GLU_EXPECT_NO_ERROR(gl.getError(), "Clear");
2668
2669 bool result = checkResults(texture_0, texture_1, 0);
2670
2671 if (false == result)
2672 {
2673 test_result = false;
2674 goto end;
2675 }
2676 }
2677 }
2678
2679 end:
2680 /* Set result */
2681 if (true == test_result)
2682 {
2683 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2684 }
2685 else
2686 {
2687 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2688 }
2689
2690 /* Done */
2691 return tcu::TestNode::STOP;
2692 }
2693
2694 /** Check if R32I texture is filled with 4x4 regions of increasing values <0:15>
2695 *
2696 * @param texture_0 Verified texture
2697 * @param ignored
2698 * @param ignored
2699 *
2700 * @return True if texture_0 is filled with expected pattern
2701 **/
checkResults(Utils::texture & texture_0,Utils::texture &,GLuint)2702 bool DrawTestBase::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */, GLuint /*draw_call_index */)
2703 {
2704 bool check_result = true;
2705 GLint index = 0;
2706
2707 std::vector<GLint> texture_data;
2708 texture_data.resize(m_width * m_height);
2709 texture_0.get(GL_RED_INTEGER, GL_INT, &texture_data[0]);
2710
2711 for (GLuint y = 0; y < 4; ++y)
2712 {
2713 for (GLuint x = 0; x < 4; ++x)
2714 {
2715 bool result = checkRegionR32I(x, y, index, &texture_data[0]);
2716
2717 if (false == result)
2718 {
2719 check_result = false;
2720 goto end;
2721 }
2722
2723 index += 1;
2724 }
2725 }
2726
2727 end:
2728 return check_result;
2729 }
2730
2731 /** Get settings of clear operation
2732 *
2733 * @param clear_depth_before_draw Selects if clear depth should be executed before draw.
2734 * @param ignored
2735 * @param ignored
2736 **/
getClearSettings(bool & clear_depth_before_draw,GLuint,GLfloat &)2737 void DrawTestBase::getClearSettings(bool& clear_depth_before_draw, GLuint /* iteration_index */,
2738 GLfloat& /* depth_value */)
2739 {
2740 clear_depth_before_draw = false;
2741 }
2742
2743 /** Get number of draw call to be executed during test
2744 *
2745 * @return 1
2746 **/
getDrawCallsNumber()2747 GLuint DrawTestBase::getDrawCallsNumber()
2748 {
2749 return 1;
2750 }
2751
2752 /** Get test type
2753 *
2754 * @return VIEWPORT
2755 **/
getTestType()2756 DrawTestBase::TEST_TYPE DrawTestBase::getTestType()
2757 {
2758 return VIEWPORT;
2759 }
2760
2761 /** Selects if test should do draw or clear operation
2762 *
2763 * @return false - draw operation
2764 **/
isClearTest()2765 bool DrawTestBase::isClearTest()
2766 {
2767 return false;
2768 }
2769
2770 /** Prepare textures used as framebuffer's attachments for current draw call
2771 *
2772 * @param texture_0 R32I texture
2773 * @param ignored
2774 **/
prepareTextures(Utils::texture & texture_0,Utils::texture &)2775 void DrawTestBase::prepareTextures(Utils::texture& texture_0, Utils::texture& /* texture_1 */)
2776 {
2777 prepareTextureR32I(texture_0);
2778 }
2779
2780 /** Prepare uniforms for given draw call
2781 *
2782 * @param ignored
2783 * @param ignored
2784 **/
prepareUniforms(Utils::program &,GLuint)2785 void DrawTestBase::prepareUniforms(Utils::program& /* program */, GLuint /* draw_call_index */)
2786 {
2787 /* empty */
2788 }
2789
2790 /** Attach textures to framebuffer
2791 *
2792 * @param framebuffer Framebuffer instance
2793 * @param texture_0 Texture attached as color 0
2794 * @param ignored
2795 **/
setupFramebuffer(Utils::framebuffer & framebuffer,Utils::texture & texture_0,Utils::texture &)2796 void DrawTestBase::setupFramebuffer(Utils::framebuffer& framebuffer, Utils::texture& texture_0,
2797 Utils::texture& /* texture_1 */)
2798 {
2799 framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, texture_0.m_id, m_width, m_height);
2800 }
2801
2802 /** Check if region specified with <x and <y> is filled with expected value.
2803 * Note: there is assumption that there are 4x4 regions
2804 *
2805 * @param x X coordinate of region
2806 * @param y Y coordinate of region
2807 * @param expected_value Expected value
2808 * @param data Texture data (not region, but whole texture)
2809 *
2810 * @return True if region is filled with <expected_value>, false otherwise
2811 **/
checkRegionR32I(GLuint x,GLuint y,GLint expected_value,GLint * data)2812 bool DrawTestBase::checkRegionR32I(GLuint x, GLuint y, GLint expected_value, GLint* data)
2813 {
2814 static GLuint width = m_width / 4;
2815 static GLuint height = m_height / 4;
2816
2817 return checkRegionR32I(x, y, width, height, expected_value, data);
2818 }
2819
2820 /** Check if region specified with <x and <y> is filled with expected value.
2821 * Note: there is assumption that there are 4x4 regions
2822 *
2823 * @param x X coordinate of region
2824 * @param y Y coordinate of region
2825 * @param width Width of region
2826 * @param height Height of region
2827 * @param expected_value Expected value
2828 * @param data Texture data (not region, but whole texture)
2829 *
2830 * @return True if region is filled with <expected_value>, false otherwise
2831 **/
checkRegionR32I(GLuint x,GLuint y,GLuint width,GLuint height,GLint expected_value,GLint * data)2832 bool DrawTestBase::checkRegionR32I(GLuint x, GLuint y, GLuint width, GLuint height, GLint expected_value, GLint* data)
2833 {
2834 bool result = true;
2835
2836 const GLuint offset = (y * height * m_width) + (x * width);
2837
2838 for (GLuint line = 0; line < height; ++line)
2839 {
2840 const GLuint line_offset = offset + line * m_width;
2841
2842 for (GLuint texel = 0; texel < width; ++texel)
2843 {
2844 const GLuint texel_offset = line_offset + texel;
2845
2846 const GLint value = data[texel_offset];
2847
2848 if (expected_value != value)
2849 {
2850 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid result. Region (" << x << "x"
2851 << y << "). Expected: " << expected_value << " got " << value
2852 << tcu::TestLog::EndMessage;
2853
2854 result = false;
2855 goto end;
2856 }
2857 }
2858 }
2859
2860 end:
2861 return result;
2862 }
2863
2864 /** Return boiler-plate vertex shader
2865 *
2866 * @return Source code of vertex shader
2867 **/
getVertexShader()2868 std::string DrawTestBase::getVertexShader()
2869 {
2870 static const GLchar* source = "${VERSION}\n"
2871 "\n"
2872 "void main()\n"
2873 "{\n"
2874 " /* empty */;\n"
2875 "}\n"
2876 "\n";
2877
2878 std::string result = source;
2879
2880 return result;
2881 }
2882
2883 /** Set up viewports
2884 *
2885 * @param type Type of test
2886 * @param iteration_index Index of iteration for given test type
2887 **/
setupViewports(TEST_TYPE type,GLuint iteration_index)2888 void DrawTestBase::setupViewports(TEST_TYPE type, GLuint iteration_index)
2889 {
2890 switch (type)
2891 {
2892 case VIEWPORT:
2893 {
2894 VIEWPORT_METHOD method;
2895 switch (iteration_index)
2896 {
2897 case 0:
2898 case 1:
2899 case 2:
2900 method = (VIEWPORT_METHOD)iteration_index;
2901 break;
2902 default:
2903 TCU_FAIL("Invalid value");
2904 }
2905 setup4x4Viewport(method);
2906 }
2907 break;
2908 case SCISSOR:
2909 {
2910 SCISSOR_METHOD method;
2911 switch (iteration_index)
2912 {
2913 case 0:
2914 case 1:
2915 case 2:
2916 method = (SCISSOR_METHOD)iteration_index;
2917 break;
2918 default:
2919 TCU_FAIL("Invalid value");
2920 }
2921 setup4x4Scissor(method, false /* set_zeros */);
2922 }
2923 break;
2924 case DEPTHRANGE:
2925 {
2926 DEPTH_RANGE_METHOD method;
2927 switch (iteration_index)
2928 {
2929 case 0:
2930 case 1:
2931 method = (DEPTH_RANGE_METHOD)iteration_index;
2932 break;
2933 default:
2934 TCU_FAIL("Invalid value");
2935 }
2936 setup16x2Depths(method);
2937 }
2938 break;
2939 case PROVOKING:
2940 {
2941 PROVOKING_VERTEX provoking;
2942 switch (iteration_index)
2943 {
2944 case 0:
2945 case 1:
2946 provoking = (PROVOKING_VERTEX)iteration_index;
2947 break;
2948 default:
2949 TCU_FAIL("Invalid value");
2950 }
2951 setup2x2Viewport(provoking);
2952 }
2953 break;
2954 default:
2955 TCU_FAIL("Invalid enum");
2956 }
2957 }
2958
2959 /** Prepare R32I texture filled with value -1
2960 *
2961 * @param texture Texture instance
2962 **/
prepareTextureR32I(Utils::texture & texture)2963 void DrawTestBase::prepareTextureR32I(Utils::texture& texture)
2964 {
2965 static const GLuint size = m_width * m_height;
2966 GLint data[size];
2967
2968 for (GLuint i = 0; i < size; ++i)
2969 {
2970 data[i] = -1;
2971 }
2972
2973 texture.create(m_width, m_height, GL_R32I);
2974 texture.update(m_width, m_height, 0 /* depth */, GL_RED_INTEGER, GL_INT, data);
2975 }
2976
2977 /** Prepare R32I array texture filled with value -1, 4 layers
2978 *
2979 * @param texture Texture instance
2980 **/
prepareTextureR32Ix4(Utils::texture & texture)2981 void DrawTestBase::prepareTextureR32Ix4(Utils::texture& texture)
2982 {
2983 static const GLuint size = m_width * m_height * m_r32ix4_depth;
2984
2985 std::vector<GLint> data;
2986 data.resize(size);
2987
2988 for (GLuint i = 0; i < size; ++i)
2989 {
2990 data[i] = -1;
2991 }
2992
2993 texture.create(m_width, m_height, m_r32ix4_depth, GL_R32I);
2994 texture.update(m_width, m_height, m_r32ix4_depth, GL_RED_INTEGER, GL_INT, &data[0]);
2995 }
2996
2997 /** Prepare R32I array texture filled with value -1
2998 *
2999 * @param texture Texture instance
3000 **/
prepareTextureArrayR32I(Utils::texture & texture)3001 void DrawTestBase::prepareTextureArrayR32I(Utils::texture& texture)
3002 {
3003 static const GLuint size = m_width * m_height * m_depth;
3004
3005 std::vector<GLint> data;
3006 data.resize(size);
3007
3008 for (GLuint i = 0; i < size; ++i)
3009 {
3010 data[i] = -1;
3011 }
3012
3013 texture.create(m_width, m_height, m_depth, GL_R32I);
3014 texture.update(m_width, m_height, m_depth, GL_RED_INTEGER, GL_INT, &data[0]);
3015 }
3016
3017 /** Prepare R32F texture filled with value -1
3018 *
3019 * @param texture Texture instance
3020 **/
prepareTextureR32F(Utils::texture & texture)3021 void DrawTestBase::prepareTextureR32F(Utils::texture& texture)
3022 {
3023 static const GLuint size = m_r32f_width * m_r32f_height;
3024 GLfloat data[size];
3025
3026 for (GLuint i = 0; i < size; ++i)
3027 {
3028 data[i] = -1.0f;
3029 }
3030
3031 texture.create(m_r32f_width, m_r32f_height, GL_R32F);
3032 texture.update(m_r32f_width, m_r32f_height, 0 /* depth */, GL_RED, GL_FLOAT, data);
3033 }
3034
3035 /** Prepare D32F texture filled with value -1
3036 *
3037 * @param texture Texture instance
3038 **/
prepareTextureD32F(Utils::texture & texture)3039 void DrawTestBase::prepareTextureD32F(Utils::texture& texture)
3040 {
3041 static const GLuint size = m_width * m_height;
3042 GLfloat data[size];
3043
3044 for (GLuint i = 0; i < size; ++i)
3045 {
3046 data[i] = -1.0f;
3047 }
3048
3049 texture.create(m_width, m_height, GL_DEPTH_COMPONENT32F);
3050 texture.update(m_width, m_height, 0 /* depth */, GL_DEPTH_COMPONENT, GL_FLOAT, data);
3051 }
3052
3053 /** Set up 16 viewports and depth ranges horizontally
3054 *
3055 * @param method Method used to set depth ranges
3056 **/
setup16x2Depths(DEPTH_RANGE_METHOD method)3057 void DrawTestBase::setup16x2Depths(DEPTH_RANGE_METHOD method)
3058 {
3059 const glu::ContextType& context_type = m_context.getRenderContext().getType();
3060
3061 if (glu::isContextTypeGLCore(context_type))
3062 {
3063 setup16x2DepthsHelper<GLdouble>(method);
3064 }
3065 else
3066 {
3067 DE_ASSERT(glu::isContextTypeES(context_type));
3068 setup16x2DepthsHelper<GLfloat>(method);
3069 }
3070 }
3071
3072 template <typename T>
setup16x2DepthsHelper(DEPTH_RANGE_METHOD method,T *)3073 void DrawTestBase::setup16x2DepthsHelper(DEPTH_RANGE_METHOD method, T*)
3074 {
3075 static const T step = 1.0 / 16.0;
3076
3077 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3078 Utils::DepthFuncWrapper depthFunc(m_context);
3079
3080 T depth_data[16 * 2];
3081 GLfloat viewport_data[16 * 4];
3082
3083 for (GLuint i = 0; i < 16; ++i)
3084 {
3085 const T near = step * (T)i;
3086
3087 depth_data[i * 2 + 0] = near;
3088 depth_data[i * 2 + 1] = T(1.0) - near;
3089
3090 viewport_data[i * 4 + 0] = (GLfloat)i;
3091 viewport_data[i * 4 + 1] = 0.0f;
3092 viewport_data[i * 4 + 2] = 1.0f;
3093 viewport_data[i * 4 + 3] = 2.0f;
3094 }
3095
3096 gl.viewportArrayv(0 /* first */, 16 /* count */, viewport_data);
3097 GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportArrayv");
3098
3099 switch (method)
3100 {
3101 case DEPTHRANGEINDEXED:
3102 for (GLuint i = 0; i < 16; ++i)
3103 {
3104 depthFunc.depthRangeIndexed(i, depth_data[i * 2 + 0], depth_data[i * 2 + 1]);
3105 GLU_EXPECT_NO_ERROR(gl.getError(), "DepthRangeIndexed");
3106 }
3107 break;
3108
3109 case DEPTHRANGEARRAYV:
3110 depthFunc.depthRangeArray(0 /* first */, 16 /* count */, depth_data);
3111 GLU_EXPECT_NO_ERROR(gl.getError(), "DepthRangeArray");
3112 break;
3113
3114 default:
3115 TCU_FAIL("Invalid enum");
3116 }
3117 }
3118
3119 /** Set up 4x4 scissor boxes with enabled test
3120 *
3121 * @param method Method used to set scissor boxes
3122 * @param set_zeros Select if width and height should be 0 or image_dim / 4
3123 **/
setup4x4Scissor(SCISSOR_METHOD method,bool set_zeros)3124 void DrawTestBase::setup4x4Scissor(SCISSOR_METHOD method, bool set_zeros)
3125 {
3126 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3127
3128 for (GLuint i = 0; i < 16; ++i)
3129 {
3130 gl.enablei(GL_SCISSOR_TEST, i);
3131 GLU_EXPECT_NO_ERROR(gl.getError(), "Enablei");
3132 }
3133
3134 GLint index = 0;
3135 GLint data[16 * 4 /* 4x4 * (x + y + w + h) */];
3136
3137 GLint width = m_width / 4;
3138 GLint height = m_height / 4;
3139
3140 for (GLuint y = 0; y < 4; ++y)
3141 {
3142 for (GLuint x = 0; x < 4; ++x)
3143 {
3144 data[index * 4 + 0] = x * width;
3145 data[index * 4 + 1] = y * height;
3146 if (false == set_zeros)
3147 {
3148 data[index * 4 + 2] = width;
3149 data[index * 4 + 3] = height;
3150 }
3151 else
3152 {
3153 data[index * 4 + 2] = 0;
3154 data[index * 4 + 3] = 0;
3155 }
3156
3157 index += 1;
3158 }
3159 }
3160
3161 switch (method)
3162 {
3163 case SCISSORARRAYV:
3164 gl.scissorArrayv(0 /* first */, 16 /*count */, data);
3165 GLU_EXPECT_NO_ERROR(gl.getError(), "ScissorArrayv");
3166 break;
3167 case SCISSORINDEXEDF:
3168 for (GLuint i = 0; i < 16; ++i)
3169 {
3170 const GLint x = data[i * 4 + 0];
3171 const GLint y = data[i * 4 + 1];
3172 const GLint w = data[i * 4 + 2];
3173 const GLint h = data[i * 4 + 3];
3174
3175 gl.scissorIndexed(i, x, y, w, h);
3176 GLU_EXPECT_NO_ERROR(gl.getError(), "ScissorIndexed");
3177 }
3178 break;
3179 case SCISSORINDEXEDF_V:
3180 for (GLuint i = 0; i < 16; ++i)
3181 {
3182 gl.scissorIndexedv(i, &data[i * 4]);
3183 GLU_EXPECT_NO_ERROR(gl.getError(), "ScissorIndexedv");
3184 }
3185 break;
3186 default:
3187 TCU_FAIL("Invalid enum");
3188 }
3189 }
3190
3191 /** Set up 4x4 viewports
3192 *
3193 * @param method Method used to set viewports
3194 **/
setup4x4Viewport(VIEWPORT_METHOD method)3195 void DrawTestBase::setup4x4Viewport(VIEWPORT_METHOD method)
3196 {
3197 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3198
3199 GLint index = 0;
3200 GLfloat data[16 * 4 /* 4x4 * (x + y + w + h) */];
3201
3202 GLfloat width = (GLfloat)(m_width / 4);
3203 GLfloat height = (GLfloat)(m_height / 4);
3204
3205 for (GLuint y = 0; y < 4; ++y)
3206 {
3207 for (GLuint x = 0; x < 4; ++x)
3208 {
3209 data[index * 4 + 0] = (GLfloat)((GLfloat)x * width);
3210 data[index * 4 + 1] = (GLfloat)((GLfloat)y * height);
3211 data[index * 4 + 2] = width;
3212 data[index * 4 + 3] = height;
3213
3214 index += 1;
3215 }
3216 }
3217
3218 switch (method)
3219 {
3220 case VIEWPORTARRAYV:
3221 gl.viewportArrayv(0 /* first */, 16 /*count */, data);
3222 GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportArrayv");
3223 break;
3224 case VIEWPORTINDEXEDF:
3225 for (GLuint i = 0; i < 16; ++i)
3226 {
3227 const GLfloat x = data[i * 4 + 0];
3228 const GLfloat y = data[i * 4 + 1];
3229 const GLfloat w = data[i * 4 + 2];
3230 const GLfloat h = data[i * 4 + 3];
3231
3232 gl.viewportIndexedf(i, x, y, w, h);
3233 GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportIndexedf");
3234 }
3235 break;
3236 case VIEWPORTINDEXEDF_V:
3237 for (GLuint i = 0; i < 16; ++i)
3238 {
3239 gl.viewportIndexedfv(i, &data[i * 4]);
3240 GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportIndexedfv");
3241 }
3242 break;
3243 default:
3244 TCU_FAIL("Invalid enum");
3245 }
3246 }
3247
3248 /** Set up 4x4 viewports
3249 *
3250 * @param method Method used to set viewports
3251 **/
setup2x2Viewport(PROVOKING_VERTEX provoking)3252 void DrawTestBase::setup2x2Viewport(PROVOKING_VERTEX provoking)
3253 {
3254 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3255 const glu::ContextType& context_type = m_context.getRenderContext().getType();
3256
3257 GLint index = 0;
3258 GLfloat data[4 * 4 /* 4x4 * (x + y + w + h) */];
3259
3260 GLfloat width = (GLfloat)(m_width / 2);
3261 GLfloat height = (GLfloat)(m_height / 2);
3262
3263 for (GLuint y = 0; y < 2; ++y)
3264 {
3265 for (GLuint x = 0; x < 2; ++x)
3266 {
3267 data[index * 4 + 0] = (GLfloat)((GLfloat)x * width);
3268 data[index * 4 + 1] = (GLfloat)((GLfloat)y * height);
3269 data[index * 4 + 2] = width;
3270 data[index * 4 + 3] = height;
3271
3272 index += 1;
3273 }
3274 }
3275
3276 gl.viewportArrayv(0 /* first */, 4 /*count */, data);
3277 GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportArrayv");
3278
3279 if (glu::isContextTypeGLCore(context_type))
3280 {
3281 GLenum mode = 0;
3282 switch (provoking)
3283 {
3284 case FIRST:
3285 mode = GL_FIRST_VERTEX_CONVENTION;
3286 break;
3287 case LAST:
3288 mode = GL_LAST_VERTEX_CONVENTION;
3289 break;
3290 default:
3291 TCU_FAIL("Invalid enum");
3292 }
3293
3294 gl.provokingVertex(mode);
3295 GLU_EXPECT_NO_ERROR(gl.getError(), "ProvokingVertex");
3296 }
3297 else
3298 {
3299 /* can't control the provoking vertex in ES yet - it stays as LAST */
3300 DE_ASSERT(glu::isContextTypeES(context_type));
3301 DE_UNREF(provoking);
3302 }
3303 }
3304
3305 /** Constructor
3306 *
3307 * @param context Test context
3308 **/
DrawToSingleLayerWithMultipleViewports(deqp::Context & context,const glcts::ExtParameters & extParams)3309 DrawToSingleLayerWithMultipleViewports::DrawToSingleLayerWithMultipleViewports(deqp::Context& context,
3310 const glcts::ExtParameters& extParams)
3311 : DrawTestBase(context, extParams, "draw_to_single_layer_with_multiple_viewports",
3312 "Test verifies that multiple viewports can be used to draw to single layer")
3313 {
3314 /* Nothing to be done here */
3315 }
3316
3317 /** Get string with fragment shader source code
3318 *
3319 * @return Fragment shader source
3320 **/
getFragmentShader()3321 std::string DrawToSingleLayerWithMultipleViewports::getFragmentShader()
3322 {
3323 static const GLchar* source = "${VERSION}\n"
3324 "\n"
3325 "flat in int gs_fs_color;\n"
3326 " out int fs_out_color;\n"
3327 "\n"
3328 "void main()\n"
3329 "{\n"
3330 " fs_out_color = gs_fs_color;\n"
3331 "}\n"
3332 "\n";
3333
3334 std::string result = source;
3335
3336 return result;
3337 }
3338
3339 /** Get string with geometry shader source code
3340 *
3341 * @return Geometry shader source
3342 **/
getGeometryShader()3343 std::string DrawToSingleLayerWithMultipleViewports::getGeometryShader()
3344 {
3345 static const GLchar* source = "${VERSION}\n"
3346 "\n"
3347 "${GEOMETRY_SHADER_ENABLE}\n"
3348 "${VIEWPORT_ARRAY_ENABLE}\n"
3349 "\n"
3350 "layout(points, invocations = 16) in;\n"
3351 "layout(triangle_strip, max_vertices = 4) out;\n"
3352 "\n"
3353 "flat out int gs_fs_color;\n"
3354 "\n"
3355 "void main()\n"
3356 "{\n"
3357 " gs_fs_color = gl_InvocationID;\n"
3358 " gl_ViewportIndex = gl_InvocationID;\n"
3359 " gl_Position = vec4(-1, -1, 0, 1);\n"
3360 " EmitVertex();\n"
3361 " gs_fs_color = gl_InvocationID;\n"
3362 " gl_ViewportIndex = gl_InvocationID;\n"
3363 " gl_Position = vec4(-1, 1, 0, 1);\n"
3364 " EmitVertex();\n"
3365 " gs_fs_color = gl_InvocationID;\n"
3366 " gl_ViewportIndex = gl_InvocationID;\n"
3367 " gl_Position = vec4(1, -1, 0, 1);\n"
3368 " EmitVertex();\n"
3369 " gs_fs_color = gl_InvocationID;\n"
3370 " gl_ViewportIndex = gl_InvocationID;\n"
3371 " gl_Position = vec4(1, 1, 0, 1);\n"
3372 " EmitVertex();\n"
3373 "}\n"
3374 "\n";
3375
3376 std::string result = source;
3377
3378 return result;
3379 }
3380
3381 /** Constructor
3382 *
3383 * @param context Test context
3384 **/
DynamicViewportIndex(deqp::Context & context,const glcts::ExtParameters & extParams)3385 DynamicViewportIndex::DynamicViewportIndex(deqp::Context& context, const glcts::ExtParameters& extParams)
3386 : DrawTestBase(context, extParams, "dynamic_viewport_index",
3387 "Test verifies that gl_ViewportIndex can be assigned with dynamic value")
3388 {
3389 /* Nothing to be done here */
3390 }
3391
3392 /** Get string with fragment shader source code
3393 *
3394 * @return Fragment shader source
3395 **/
getFragmentShader()3396 std::string DynamicViewportIndex::getFragmentShader()
3397 {
3398 static const GLchar* source = "${VERSION}\n"
3399 "\n"
3400 "flat in int gs_fs_color;\n"
3401 " out int fs_out_color;\n"
3402 "\n"
3403 "void main()\n"
3404 "{\n"
3405 " fs_out_color = gs_fs_color;\n"
3406 "}\n"
3407 "\n";
3408
3409 std::string result = source;
3410
3411 return result;
3412 }
3413
3414 /** Get string with geometry shader source code
3415 *
3416 * @return Geometry shader source
3417 **/
getGeometryShader()3418 std::string DynamicViewportIndex::getGeometryShader()
3419 {
3420 static const GLchar* source = "${VERSION}\n"
3421 "\n"
3422 "${GEOMETRY_SHADER_ENABLE}\n"
3423 "${VIEWPORT_ARRAY_ENABLE}\n"
3424 "\n"
3425 "layout(points, invocations = 1) in;\n"
3426 "layout(triangle_strip, max_vertices = 4) out;\n"
3427 "\n"
3428 "uniform int uni_index;\n"
3429 "\n"
3430 "flat out int gs_fs_color;\n"
3431 "\n"
3432 "void main()\n"
3433 "{\n"
3434 " gs_fs_color = uni_index;\n"
3435 " gl_ViewportIndex = uni_index;\n"
3436 " gl_Position = vec4(-1, -1, 0, 1);\n"
3437 " EmitVertex();\n"
3438 " gs_fs_color = uni_index;\n"
3439 " gl_ViewportIndex = uni_index;\n"
3440 " gl_Position = vec4(-1, 1, 0, 1);\n"
3441 " EmitVertex();\n"
3442 " gs_fs_color = uni_index;\n"
3443 " gl_ViewportIndex = uni_index;\n"
3444 " gl_Position = vec4(1, -1, 0, 1);\n"
3445 " EmitVertex();\n"
3446 " gs_fs_color = uni_index;\n"
3447 " gl_ViewportIndex = uni_index;\n"
3448 " gl_Position = vec4(1, 1, 0, 1);\n"
3449 " EmitVertex();\n"
3450 "}\n"
3451 "\n";
3452
3453 std::string result = source;
3454
3455 return result;
3456 }
3457
3458 /** Check if R32I texture is filled with 4x4 regions of increasing values <0:15>
3459 *
3460 * @param texture_0 Verified texture
3461 * @param ignored
3462 * @param draw_call_index Draw call that was executed
3463 *
3464 * @return True if texture_0 is filled with expected pattern
3465 **/
checkResults(Utils::texture & texture_0,Utils::texture &,GLuint draw_call_index)3466 bool DynamicViewportIndex::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */,
3467 GLuint draw_call_index)
3468 {
3469 bool check_result = true;
3470 GLuint index = 0;
3471
3472 std::vector<GLint> texture_data;
3473 texture_data.resize(m_width * m_height);
3474 texture_0.get(GL_RED_INTEGER, GL_INT, &texture_data[0]);
3475
3476 for (GLuint y = 0; y < 4; ++y)
3477 {
3478 for (GLuint x = 0; x < 4; ++x)
3479 {
3480 GLint expected_value = -1;
3481 if (index <= draw_call_index)
3482 {
3483 expected_value = index;
3484 }
3485
3486 bool result = checkRegionR32I(x, y, expected_value, &texture_data[0]);
3487
3488 if (false == result)
3489 {
3490 check_result = false;
3491 goto end;
3492 }
3493
3494 index += 1;
3495 }
3496 }
3497
3498 end:
3499 return check_result;
3500 }
3501
3502 /** Get number of draw call to be executed during test
3503 *
3504 * @return 16
3505 **/
getDrawCallsNumber()3506 GLuint DynamicViewportIndex::getDrawCallsNumber()
3507 {
3508 return 16;
3509 }
3510
3511 /** Prepare uniforms for given draw call
3512 *
3513 * @param program Program object
3514 * @param draw_call_index Index of draw call to be executed
3515 **/
prepareUniforms(Utils::program & program,GLuint draw_call_index)3516 void DynamicViewportIndex::prepareUniforms(Utils::program& program, GLuint draw_call_index)
3517 {
3518 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3519
3520 GLint location = program.getUniformLocation("uni_index");
3521
3522 gl.uniform1i(location, (GLint)draw_call_index);
3523 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
3524 }
3525
3526 /** Constructor
3527 *
3528 * @param context Test context
3529 **/
DrawMulitpleViewportsWithSingleInvocation(deqp::Context & context,const glcts::ExtParameters & extParams)3530 DrawMulitpleViewportsWithSingleInvocation::DrawMulitpleViewportsWithSingleInvocation(
3531 deqp::Context& context, const glcts::ExtParameters& extParams)
3532 : DrawTestBase(context, extParams, "draw_mulitple_viewports_with_single_invocation",
3533 "Test verifies that single invocation can output to multiple viewports")
3534 {
3535 /* Nothing to be done here */
3536 }
3537
3538 /** Get string with fragment shader source code
3539 *
3540 * @return Fragment shader source
3541 **/
getFragmentShader()3542 std::string DrawMulitpleViewportsWithSingleInvocation::getFragmentShader()
3543 {
3544 static const GLchar* source = "${VERSION}\n"
3545 "\n"
3546 "flat in int gs_fs_color;\n"
3547 " out int fs_out_color;\n"
3548 "\n"
3549 "void main()\n"
3550 "{\n"
3551 " fs_out_color = gs_fs_color;\n"
3552 "}\n"
3553 "\n";
3554
3555 std::string result = source;
3556
3557 return result;
3558 }
3559
3560 /** Get string with geometry shader source code
3561 *
3562 * @return Geometry shader source
3563 **/
getGeometryShader()3564 std::string DrawMulitpleViewportsWithSingleInvocation::getGeometryShader()
3565 {
3566 static const GLchar* source = "${VERSION}\n"
3567 "\n"
3568 "${GEOMETRY_SHADER_ENABLE}\n"
3569 "${VIEWPORT_ARRAY_ENABLE}\n"
3570 "\n"
3571 "layout(points, invocations = 1) in;\n"
3572 "layout(triangle_strip, max_vertices = 64) out;\n"
3573 "\n"
3574 "flat out int gs_fs_color;\n"
3575 "\n"
3576 "void routine(int index)\n"
3577 "{\n"
3578 " gs_fs_color = index;\n"
3579 " gl_ViewportIndex = index;\n"
3580 " gl_Position = vec4(-1, -1, 0, 1);\n"
3581 " EmitVertex();\n"
3582 " gs_fs_color = index;\n"
3583 " gl_ViewportIndex = index;\n"
3584 " gl_Position = vec4(-1, 1, 0, 1);\n"
3585 " EmitVertex();\n"
3586 " gs_fs_color = index;\n"
3587 " gl_ViewportIndex = index;\n"
3588 " gl_Position = vec4(1, -1, 0, 1);\n"
3589 " EmitVertex();\n"
3590 " gs_fs_color = index;\n"
3591 " gl_ViewportIndex = index;\n"
3592 " gl_Position = vec4(1, 1, 0, 1);\n"
3593 " EmitVertex();\n"
3594 " EndPrimitive();\n"
3595 "}\n"
3596 "\n"
3597 "void main()\n"
3598 "{\n"
3599 " for(int i = 0; i < 16; ++i)\n"
3600 " {\n"
3601 " routine(i);\n"
3602 " }\n"
3603 "}\n"
3604 "\n";
3605
3606 std::string result = source;
3607
3608 return result;
3609 }
3610
3611 /** Constructor
3612 *
3613 * @param context Test context
3614 **/
ViewportIndexSubroutine(deqp::Context & context,const glcts::ExtParameters & extParams)3615 ViewportIndexSubroutine::ViewportIndexSubroutine(deqp::Context& context, const glcts::ExtParameters& extParams)
3616 : DrawTestBase(context, extParams, "viewport_index_subroutine",
3617 "Test verifies subroutines can be used to output data to specific viewport")
3618 {
3619 /* Nothing to be done here */
3620 }
3621
3622 /** Execute test
3623 *
3624 * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
3625 **/
iterate()3626 tcu::TestNode::IterateResult ViewportIndexSubroutine::iterate()
3627 {
3628 /* this exists solely to check for subroutine support, which is not supported in ES.
3629 The real work is done in DrawTestBase::iterate() */
3630 const glu::ContextType& context_type = m_context.getRenderContext().getType();
3631 if (!glu::isContextTypeGLCore(context_type))
3632 {
3633 throw tcu::NotSupportedError("Subroutines not supported", "", __FILE__, __LINE__);
3634 }
3635
3636 return DrawTestBase::iterate();
3637 }
3638
3639 /** Get string with fragment shader source code
3640 *
3641 * @return Fragment shader source
3642 **/
getFragmentShader()3643 std::string ViewportIndexSubroutine::getFragmentShader()
3644 {
3645 static const GLchar* source = "${VERSION}\n"
3646 "\n"
3647 "flat in int gs_fs_color;\n"
3648 " out int fs_out_color;\n"
3649 "\n"
3650 "void main()\n"
3651 "{\n"
3652 " fs_out_color = gs_fs_color;\n"
3653 "}\n"
3654 "\n";
3655
3656 std::string result = source;
3657
3658 return result;
3659 }
3660
3661 /** Get string with geometry shader source code
3662 *
3663 * @return Geometry shader source
3664 **/
getGeometryShader()3665 std::string ViewportIndexSubroutine::getGeometryShader()
3666 {
3667 static const GLchar* source = "${VERSION}\n"
3668 "\n"
3669 "${GEOMETRY_SHADER_ENABLE}\n"
3670 "${VIEWPORT_ARRAY_ENABLE}\n"
3671 "\n"
3672 "layout(points, invocations = 1) in;\n"
3673 "layout(triangle_strip, max_vertices = 4) out;\n"
3674 "\n"
3675 "flat out int gs_fs_color;\n"
3676 "\n"
3677 "subroutine void indexSetter(void);\n"
3678 "\n"
3679 "subroutine(indexSetter) void four()\n"
3680 "{\n"
3681 " gs_fs_color = 4;\n"
3682 " gl_ViewportIndex = 4;\n"
3683 "}\n"
3684 "\n"
3685 "subroutine(indexSetter) void five()\n"
3686 "{\n"
3687 " gs_fs_color = 5;\n"
3688 " gl_ViewportIndex = 5;\n"
3689 "}\n"
3690 "\n"
3691 "subroutine uniform indexSetter routine;\n"
3692 "\n"
3693 "void main()\n"
3694 "{\n"
3695 " routine();\n"
3696 " gl_Position = vec4(-1, -1, 0, 1);\n"
3697 " EmitVertex();\n"
3698 " routine();\n"
3699 " gl_Position = vec4(-1, 1, 0, 1);\n"
3700 " EmitVertex();\n"
3701 " routine();\n"
3702 " gl_Position = vec4(1, -1, 0, 1);\n"
3703 " EmitVertex();\n"
3704 " routine();\n"
3705 " gl_Position = vec4(1, 1, 0, 1);\n"
3706 " EmitVertex();\n"
3707 "}\n"
3708 "\n";
3709
3710 std::string result = source;
3711
3712 return result;
3713 }
3714
3715 /** Check if R32I texture is filled with two halves, left is 4, right is either -1 or 5
3716 *
3717 * @param texture_0 Verified texture
3718 * @param ignored
3719 * @param draw_call_index Draw call that was executed
3720 *
3721 * @return True if texture_0 is filled with expected pattern
3722 **/
checkResults(Utils::texture & texture_0,Utils::texture &,GLuint draw_call_index)3723 bool ViewportIndexSubroutine::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */,
3724 GLuint draw_call_index)
3725 {
3726 bool check_result = true;
3727
3728 std::vector<GLint> texture_data;
3729 texture_data.resize(m_width * m_height);
3730 texture_0.get(GL_RED_INTEGER, GL_INT, &texture_data[0]);
3731
3732 /* Left is 4 and right is -1, or left is 4 and right is 5 */
3733 GLint expected_left = 4;
3734 GLint expected_right = (1 == draw_call_index) ? 5 : -1;
3735
3736 for (GLuint y = 0; y < 4; ++y)
3737 {
3738 for (GLuint x = 0; x < 2; ++x)
3739 {
3740 bool result = checkRegionR32I(x, y, expected_left, &texture_data[0]);
3741
3742 if (false == result)
3743 {
3744 check_result = false;
3745 goto end;
3746 }
3747 }
3748 }
3749
3750 for (GLuint y = 0; y < 4; ++y)
3751 {
3752 for (GLuint x = 2; x < 4; ++x)
3753 {
3754 bool result = checkRegionR32I(x, y, expected_right, &texture_data[0]);
3755
3756 if (false == result)
3757 {
3758 check_result = false;
3759 goto end;
3760 }
3761 }
3762 }
3763
3764 end:
3765 return check_result;
3766 }
3767
3768 /** Get number of draw call to be executed during test
3769 *
3770 * @return 2
3771 **/
getDrawCallsNumber()3772 GLuint ViewportIndexSubroutine::getDrawCallsNumber()
3773 {
3774 return 2;
3775 }
3776
3777 /** Prepare uniforms for given draw call
3778 *
3779 * @param program Program object
3780 * @param draw_call_index Index of draw call to be executed
3781 **/
prepareUniforms(Utils::program & program,GLuint draw_call_index)3782 void ViewportIndexSubroutine::prepareUniforms(Utils::program& program, GLuint draw_call_index)
3783 {
3784 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3785
3786 const GLchar* subroutine_name = (0 == draw_call_index) ? "four" : "five";
3787
3788 GLint location = program.getSubroutineUniformLocation("routine", GL_GEOMETRY_SHADER);
3789 GLuint index = program.getSubroutineIndex(subroutine_name, GL_GEOMETRY_SHADER);
3790
3791 if (0 != location)
3792 {
3793 TCU_FAIL("Something wrong, subroutine uniform location is not 0. Mistake in geometry shader?");
3794 }
3795
3796 gl.uniformSubroutinesuiv(GL_GEOMETRY_SHADER, 1, &index);
3797 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
3798 }
3799
3800 /** Set 4th viewport on left half and 5 on right half of framebuffer. Rest span over whole image.
3801 *
3802 * @param ignored
3803 * @param iteration_index Index of iteration, used to select "viewport" method
3804 **/
setupViewports(TEST_TYPE,glw::GLuint iteration_index)3805 void ViewportIndexSubroutine::setupViewports(TEST_TYPE /* type */, glw::GLuint iteration_index)
3806 {
3807 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3808
3809 GLfloat data[2 * 4] = { 0.0f, 0.0f, 64.0f, 128.0f, 64.0f, 0.0f, 64.0f, 128.0f };
3810
3811 gl.viewport(0, 0, m_width, m_height);
3812 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
3813
3814 switch (iteration_index)
3815 {
3816 case 0:
3817
3818 gl.viewportArrayv(4, 2, data);
3819 GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportArrayv");
3820
3821 break;
3822
3823 case 1:
3824
3825 gl.viewportIndexedf(4, data[0], data[1], data[2], data[3]);
3826 GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportIndexedf");
3827
3828 gl.viewportIndexedf(5, data[4], data[5], data[6], data[7]);
3829 GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportIndexedf");
3830
3831 break;
3832
3833 case 2:
3834
3835 gl.viewportIndexedfv(4, &data[0]);
3836 GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportIndexedfv");
3837
3838 gl.viewportIndexedfv(5, &data[4]);
3839 GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportIndexedfv");
3840
3841 break;
3842
3843 default:
3844 TCU_FAIL("Invalid value");
3845 }
3846 }
3847
3848 /** Constructor
3849 *
3850 * @param context Test context
3851 **/
DrawMultipleLayers(deqp::Context & context,const glcts::ExtParameters & extParams)3852 DrawMultipleLayers::DrawMultipleLayers(deqp::Context& context, const glcts::ExtParameters& extParams)
3853 : DrawTestBase(context, extParams, "draw_multiple_layers",
3854 "Test verifies that single viewport affects multiple layers in the same way")
3855 {
3856 /* Nothing to be done here */
3857 }
3858
3859 /** Constructor
3860 *
3861 * @param context Test context
3862 * @param test_name Test name
3863 * @param test_description Test description
3864 **/
DrawMultipleLayers(deqp::Context & context,const glcts::ExtParameters & extParams,const GLchar * test_name,const GLchar * test_description)3865 DrawMultipleLayers::DrawMultipleLayers(deqp::Context& context, const glcts::ExtParameters& extParams,
3866 const GLchar* test_name, const GLchar* test_description)
3867 : DrawTestBase(context, extParams, test_name, test_description)
3868 {
3869 /* Nothing to be done here */
3870 }
3871
3872 /** Get string with fragment shader source code
3873 *
3874 * @return Fragment shader source
3875 **/
getFragmentShader()3876 std::string DrawMultipleLayers::getFragmentShader()
3877 {
3878 static const GLchar* source = "${VERSION}\n"
3879 "\n"
3880 "flat in int gs_fs_color;\n"
3881 " out int fs_out_color;\n"
3882 "\n"
3883 "void main()\n"
3884 "{\n"
3885 " fs_out_color = gs_fs_color;\n"
3886 "}\n"
3887 "\n";
3888
3889 std::string result = source;
3890
3891 return result;
3892 }
3893
3894 /** Get string with geometry shader source code
3895 *
3896 * @return Geometry shader source
3897 **/
getGeometryShader()3898 std::string DrawMultipleLayers::getGeometryShader()
3899 {
3900 static const GLchar* source = "${VERSION}\n"
3901 "\n"
3902 "${GEOMETRY_SHADER_ENABLE}\n"
3903 "${VIEWPORT_ARRAY_ENABLE}\n"
3904 "\n"
3905 "layout(points, invocations = 16) in;\n"
3906 "layout(triangle_strip, max_vertices = 4) out;\n"
3907 "\n"
3908 "flat out int gs_fs_color;\n"
3909 "\n"
3910 "void main()\n"
3911 "{\n"
3912 " gs_fs_color = gl_InvocationID;\n"
3913 " gl_ViewportIndex = gl_InvocationID;\n"
3914 " gl_Layer = gl_InvocationID;\n"
3915 " gl_Position = vec4(-1, -1, 0, 1);\n"
3916 " EmitVertex();\n"
3917 " gs_fs_color = gl_InvocationID;\n"
3918 " gl_ViewportIndex = gl_InvocationID;\n"
3919 " gl_Layer = gl_InvocationID;\n"
3920 " gl_Position = vec4(-1, 1, 0, 1);\n"
3921 " EmitVertex();\n"
3922 " gs_fs_color = gl_InvocationID;\n"
3923 " gl_ViewportIndex = gl_InvocationID;\n"
3924 " gl_Layer = gl_InvocationID;\n"
3925 " gl_Position = vec4(1, -1, 0, 1);\n"
3926 " EmitVertex();\n"
3927 " gs_fs_color = gl_InvocationID;\n"
3928 " gl_ViewportIndex = gl_InvocationID;\n"
3929 " gl_Layer = gl_InvocationID;\n"
3930 " gl_Position = vec4(1, 1, 0, 1);\n"
3931 " EmitVertex();\n"
3932 "}\n"
3933 "\n";
3934
3935 std::string result = source;
3936
3937 return result;
3938 }
3939
3940 /** Check if R32I texture is filled with 4x4 regions of increasing values <0:15>
3941 *
3942 * @param texture_0 Verified texture
3943 * @param ignored
3944 * @param ignored
3945 *
3946 * @return True if texture_0 is filled with expected pattern
3947 **/
checkResults(Utils::texture & texture_0,Utils::texture &,GLuint)3948 bool DrawMultipleLayers::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */,
3949 GLuint /* draw_call_index */)
3950 {
3951 static const GLuint layer_size = m_width * m_height;
3952
3953 bool check_result = true;
3954
3955 std::vector<GLint> texture_data;
3956 texture_data.resize(layer_size * m_depth);
3957 texture_0.get(GL_RED_INTEGER, GL_INT, &texture_data[0]);
3958
3959 /* 16 layers, only region corresponding with layer index should be modified */
3960 for (GLuint layer = 0; layer < m_depth; ++layer)
3961 {
3962 GLuint index = 0;
3963
3964 for (GLuint y = 0; y < 4; ++y)
3965 {
3966 for (GLuint x = 0; x < 4; ++x)
3967 {
3968 GLint* layer_data = &texture_data[layer * layer_size];
3969
3970 GLint expected_value = -1;
3971 if (index == layer)
3972 {
3973 expected_value = index;
3974 }
3975
3976 bool result = checkRegionR32I(x, y, expected_value, layer_data);
3977
3978 if (false == result)
3979 {
3980 check_result = false;
3981 goto end;
3982 }
3983
3984 index += 1;
3985 }
3986 }
3987 }
3988
3989 end:
3990 return check_result;
3991 }
3992
3993 /** Prepare textures used as framebuffer's attachments for current draw call
3994 *
3995 * @param texture_0 R32I texture
3996 * @param ignored
3997 **/
prepareTextures(Utils::texture & texture_0,Utils::texture &)3998 void DrawMultipleLayers::prepareTextures(Utils::texture& texture_0, Utils::texture& /* texture_1 */)
3999 {
4000 prepareTextureArrayR32I(texture_0);
4001 }
4002
4003 /** Constructor
4004 *
4005 * @param context Test context
4006 * @param test_name Test name
4007 * @param test_description Test description
4008 **/
Scissor(deqp::Context & context,const glcts::ExtParameters & extParams)4009 Scissor::Scissor(deqp::Context& context, const glcts::ExtParameters& extParams)
4010 : DrawMultipleLayers(context, extParams, "scissor", "Test verifies that scissor test is applied as expected")
4011 {
4012 /* Nothing to be done here */
4013 }
4014
4015 /** Get test type
4016 *
4017 * @return SCISSOR
4018 **/
getTestType()4019 DrawTestBase::TEST_TYPE Scissor::getTestType()
4020 {
4021 return SCISSOR;
4022 }
4023
4024 /** Constructor
4025 *
4026 * @param context Test context
4027 * @param test_name Test name
4028 * @param test_description Test description
4029 **/
ScissorZeroDimension(deqp::Context & context,const glcts::ExtParameters & extParams)4030 ScissorZeroDimension::ScissorZeroDimension(deqp::Context& context, const glcts::ExtParameters& extParams)
4031 : DrawMultipleLayers(context, extParams, "scissor_zero_dimension",
4032 "Test verifies that scissor test discard all fragments when width and height is set to zero")
4033 {
4034 /* Nothing to be done here */
4035 }
4036
4037 /** Check if R32I texture is filled with 4x4 regions of increasing values <0:15>
4038 *
4039 * @param texture_0 Verified texture
4040 * @param ignored
4041 * @param ignored
4042 *
4043 * @return True if texture_0 is filled with expected pattern
4044 **/
checkResults(Utils::texture & texture_0,Utils::texture &,GLuint)4045 bool ScissorZeroDimension::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */,
4046 GLuint /* draw_call_index */)
4047 {
4048 static const GLuint layer_size = m_width * m_height;
4049
4050 bool check_result = true;
4051
4052 std::vector<GLint> texture_data;
4053 texture_data.resize(layer_size * m_depth);
4054 texture_0.get(GL_RED_INTEGER, GL_INT, &texture_data[0]);
4055
4056 /* 16 layers, all regions were not modified */
4057 for (GLuint layer = 0; layer < m_depth; ++layer)
4058 {
4059 for (GLuint y = 0; y < 4; ++y)
4060 {
4061 for (GLuint x = 0; x < 4; ++x)
4062 {
4063 GLint* layer_data = &texture_data[layer * layer_size];
4064
4065 GLint expected_value = -1;
4066
4067 bool result = checkRegionR32I(x, y, expected_value, layer_data);
4068
4069 if (false == result)
4070 {
4071 check_result = false;
4072 goto end;
4073 }
4074 }
4075 }
4076 }
4077
4078 end:
4079 return check_result;
4080 }
4081
4082 /** Get test type
4083 *
4084 * @return SCISSOR
4085 **/
getTestType()4086 DrawTestBase::TEST_TYPE ScissorZeroDimension::getTestType()
4087 {
4088 return SCISSOR;
4089 }
4090
4091 /** Set up viewports
4092 *
4093 * @param Ignored
4094 * @param iteration_index Index of iteration for given test type
4095 **/
setupViewports(TEST_TYPE,GLuint iteration_index)4096 void ScissorZeroDimension::setupViewports(TEST_TYPE /* type */, GLuint iteration_index)
4097 {
4098 SCISSOR_METHOD method;
4099 switch (iteration_index)
4100 {
4101 case 0:
4102 case 1:
4103 case 2:
4104 method = (SCISSOR_METHOD)iteration_index;
4105 break;
4106 default:
4107 TCU_FAIL("Invalid value");
4108 }
4109
4110 setup4x4Scissor(method, true /* set_zeros */);
4111 }
4112
4113 /** Constructor
4114 *
4115 * @param context Test context
4116 * @param test_name Test name
4117 * @param test_description Test description
4118 **/
ScissorClear(deqp::Context & context,const glcts::ExtParameters & extParams)4119 ScissorClear::ScissorClear(deqp::Context& context, const glcts::ExtParameters& extParams)
4120 : DrawMultipleLayers(context, extParams, "scissor_clear",
4121 "Test verifies that Clear is affected only by settings of scissor test in first viewport")
4122 {
4123 /* Nothing to be done here */
4124 }
4125
4126 /** Check if R32I texture is filled with 4x4 regions of increasing values <0:15>
4127 *
4128 * @param texture_0 Verified texture
4129 * @param ignored
4130 * @param ignored
4131 *
4132 * @return True if texture_0 is filled with expected pattern
4133 **/
checkResults(Utils::texture & texture_0,Utils::texture &,GLuint)4134 bool ScissorClear::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */, GLuint /*draw_call_index */)
4135 {
4136 static const GLuint layer_size = m_width * m_height;
4137
4138 bool check_result = true;
4139
4140 std::vector<GLint> texture_data;
4141 texture_data.resize(layer_size * m_depth);
4142 texture_0.get(GL_RED_INTEGER, GL_INT, &texture_data[0]);
4143
4144 /* 16 layers, only region corresponding with scissor box 0 should be modified */
4145 for (GLuint layer = 0; layer < m_depth; ++layer)
4146 {
4147 for (GLuint y = 0; y < 4; ++y)
4148 {
4149 for (GLuint x = 0; x < 4; ++x)
4150 {
4151 GLint* layer_data = &texture_data[layer * layer_size];
4152
4153 GLint expected_value = -1;
4154 if ((0 == x) && (0 == y))
4155 {
4156 expected_value = 0;
4157 }
4158
4159 bool result = checkRegionR32I(x, y, expected_value, layer_data);
4160
4161 if (false == result)
4162 {
4163 check_result = false;
4164 goto end;
4165 }
4166 }
4167 }
4168 }
4169
4170 end:
4171 return check_result;
4172 }
4173
4174 /** Get test type
4175 *
4176 * @return SCISSOR
4177 **/
getTestType()4178 DrawTestBase::TEST_TYPE ScissorClear::getTestType()
4179 {
4180 return SCISSOR;
4181 }
4182
4183 /** Selects if test should do draw or clear operation
4184 *
4185 * @return true - clear operation
4186 **/
isClearTest()4187 bool ScissorClear::isClearTest()
4188 {
4189 return true;
4190 }
4191
4192 /** Constructor
4193 *
4194 * @param context Test context
4195 * @param test_name Test name
4196 * @param test_description Test description
4197 **/
DepthRange(deqp::Context & context,const glcts::ExtParameters & extParams)4198 DepthRange::DepthRange(deqp::Context& context, const glcts::ExtParameters& extParams)
4199 : DrawTestBase(context, extParams, "depth_range", "Test verifies that depth range is applied as expected")
4200 {
4201 /* Nothing to be done here */
4202 }
4203
4204 /** Check if R32F texture is filled with two rows, top with decreasing values, bottom with incresing values
4205 *
4206 * @param texture_0 Verified texture
4207 * @param ignored
4208 * @param ignored
4209 *
4210 * @return True if texture_0 is filled with expected pattern
4211 **/
checkResults(Utils::texture & texture_0,Utils::texture &,GLuint)4212 bool DepthRange::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */, GLuint /*draw_call_index */)
4213 {
4214 static const GLfloat step = 1.0f / 16.0f;
4215
4216 bool check_result = true;
4217
4218 std::vector<GLfloat> texture_data;
4219 texture_data.resize(m_r32f_width * m_r32f_height);
4220 texture_0.get(GL_RED, GL_FLOAT, &texture_data[0]);
4221
4222 GLfloat depth_data[16 * 2];
4223
4224 for (GLuint i = 0; i < 16; ++i)
4225 {
4226 const GLfloat near = step * (GLfloat)i;
4227
4228 depth_data[i * 2 + 0] = near;
4229 depth_data[i * 2 + 1] = 1.0f - near;
4230 }
4231
4232 for (GLuint i = 0; i < 16; ++i)
4233 {
4234 const GLfloat expected_near = depth_data[i * 2 + 0];
4235 const GLfloat expected_far = depth_data[i * 2 + 1];
4236
4237 /* Bottom row should contain near values, top one should contain far values */
4238 const GLfloat near = texture_data[i];
4239 const GLfloat far = texture_data[i + 16];
4240
4241 if ((expected_near != near) || (expected_far != far))
4242 {
4243 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid values at " << i << " expected ["
4244 << expected_near << ", " << expected_far << "] got [" << near << ", "
4245 << far << "]" << tcu::TestLog::EndMessage;
4246
4247 check_result = false;
4248 break;
4249 }
4250 }
4251
4252 return check_result;
4253 }
4254
4255 /** Get string with fragment shader source code
4256 *
4257 * @return Fragment shader source
4258 **/
getFragmentShader()4259 std::string DepthRange::getFragmentShader()
4260 {
4261 static const GLchar* source = "${VERSION}\n"
4262 "\n"
4263 "#ifdef GL_ES\n"
4264 "precision highp float;\n"
4265 "#endif\n"
4266 "out float fs_out_color;\n"
4267 "\n"
4268 "void main()\n"
4269 "{\n"
4270 " fs_out_color = gl_FragCoord.z;\n"
4271 "}\n"
4272 "\n";
4273
4274 std::string result = source;
4275
4276 return result;
4277 }
4278
4279 /** Get string with geometry shader source code
4280 *
4281 * @return Geometry shader source
4282 **/
getGeometryShader()4283 std::string DepthRange::getGeometryShader()
4284 {
4285 static const GLchar* source = "${VERSION}\n"
4286 "\n"
4287 "${GEOMETRY_SHADER_ENABLE}\n"
4288 "${VIEWPORT_ARRAY_ENABLE}\n"
4289 "\n"
4290 "layout(points, invocations = 16) in;\n"
4291 "layout(triangle_strip, max_vertices = 8) out;\n"
4292 "\n"
4293 "void main()\n"
4294 "{\n"
4295 " const float top_z = 1.0;\n"
4296 " const float bottom_z = -1.0;\n"
4297 "\n"
4298 " /* Bottom */\n"
4299 " gl_ViewportIndex = gl_InvocationID;\n"
4300 " gl_Position = vec4(-1, -1, bottom_z, 1);\n"
4301 " EmitVertex();\n"
4302 " gl_ViewportIndex = gl_InvocationID;\n"
4303 " gl_Position = vec4(-1, 0, bottom_z, 1);\n"
4304 " EmitVertex();\n"
4305 " gl_ViewportIndex = gl_InvocationID;\n"
4306 " gl_Position = vec4(1, -1, bottom_z, 1);\n"
4307 " EmitVertex();\n"
4308 " gl_ViewportIndex = gl_InvocationID;\n"
4309 " gl_Position = vec4(1, 0, bottom_z, 1);\n"
4310 " EmitVertex();\n"
4311 " EndPrimitive();\n"
4312 "\n"
4313 " /* Top */\n"
4314 " gl_ViewportIndex = gl_InvocationID;\n"
4315 " gl_Position = vec4(-1, 0, top_z, 1);\n"
4316 " EmitVertex();\n"
4317 " gl_ViewportIndex = gl_InvocationID;\n"
4318 " gl_Position = vec4(-1, 1, top_z, 1);\n"
4319 " EmitVertex();\n"
4320 " gl_ViewportIndex = gl_InvocationID;\n"
4321 " gl_Position = vec4(1, 0, top_z, 1);\n"
4322 " EmitVertex();\n"
4323 " gl_ViewportIndex = gl_InvocationID;\n"
4324 " gl_Position = vec4(1, 1, top_z, 1);\n"
4325 " EmitVertex();\n"
4326 " EndPrimitive();\n"
4327 "}\n"
4328 "\n";
4329
4330 std::string result = source;
4331
4332 return result;
4333 }
4334
4335 /** Get test type
4336 *
4337 * @return DEPTHRANGE
4338 **/
getTestType()4339 DrawTestBase::TEST_TYPE DepthRange::getTestType()
4340 {
4341 return DEPTHRANGE;
4342 }
4343
4344 /** Prepare textures used as framebuffer's attachments for current draw call
4345 *
4346 * @param texture_0 R32F texture
4347 * @param ignored
4348 **/
prepareTextures(Utils::texture & texture_0,Utils::texture &)4349 void DepthRange::prepareTextures(Utils::texture& texture_0, Utils::texture& /* texture_1 */)
4350 {
4351 prepareTextureR32F(texture_0);
4352 }
4353
4354 /** Constructor
4355 *
4356 * @param context Test context
4357 * @param test_name Test name
4358 * @param test_description Test description
4359 **/
DepthRangeDepthTest(deqp::Context & context,const glcts::ExtParameters & extParams)4360 DepthRangeDepthTest::DepthRangeDepthTest(deqp::Context& context, const glcts::ExtParameters& extParams)
4361 : DrawTestBase(context, extParams, "depth_range_depth_test",
4362 "Test verifies that depth test work as expected with multiple viewports")
4363 {
4364 /* Nothing to be done here */
4365 }
4366
4367 /** Check if R32F texture is filled with two rows of values less than expected depth
4368 *
4369 * @param texture_0 Verified texture
4370 * @param ignored
4371 * @param draw_call_index Index of draw call
4372 *
4373 * @return True if texture_0 is filled with expected pattern
4374 **/
checkResults(Utils::texture & texture_0,Utils::texture &,GLuint draw_call_index)4375 bool DepthRangeDepthTest::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */,
4376 GLuint draw_call_index)
4377 {
4378 static const GLfloat step = 1.0f / 16.0f;
4379
4380 const GLfloat depth_value = step * (GLfloat)draw_call_index;
4381
4382 bool check_result = true;
4383
4384 std::vector<GLfloat> texture_data;
4385 texture_data.resize(m_r32f_width * m_r32f_height);
4386 texture_0.get(GL_RED, GL_FLOAT, &texture_data[0]);
4387
4388 for (GLuint i = 0; i < 16; ++i)
4389 {
4390 /* Bottom row should contain near values, top one should contain far values */
4391 const GLfloat near = texture_data[i];
4392 const GLfloat far = texture_data[i + 16];
4393
4394 if ((depth_value <= near) || (depth_value <= far))
4395 {
4396 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid values at " << i << " depth value "
4397 << depth_value << " got [" << near << ", " << far << "]"
4398 << tcu::TestLog::EndMessage;
4399
4400 check_result = false;
4401 break;
4402 }
4403 }
4404
4405 return check_result;
4406 }
4407
4408 /** Get settings of clear operation
4409 *
4410 * @param clear_depth_before_draw Selects if clear should be executed before draw.
4411 * @param iteration_index Index of draw call
4412 * @param depth_value Value that will be used to clear depth buffer
4413 **/
getClearSettings(bool & clear_depth_before_draw,GLuint iteration_index,GLfloat & depth_value)4414 void DepthRangeDepthTest::getClearSettings(bool& clear_depth_before_draw, GLuint iteration_index, GLfloat& depth_value)
4415 {
4416 static const GLfloat step = 1.0 / 16.0;
4417
4418 clear_depth_before_draw = true;
4419
4420 depth_value = step * (GLfloat)iteration_index;
4421 }
4422
4423 /** Get number of draw call to be executed during test
4424 *
4425 * @return 18
4426 **/
getDrawCallsNumber()4427 GLuint DepthRangeDepthTest::getDrawCallsNumber()
4428 {
4429 return 18;
4430 }
4431
4432 /** Get string with fragment shader source code
4433 *
4434 * @return Fragment shader source
4435 **/
getFragmentShader()4436 std::string DepthRangeDepthTest::getFragmentShader()
4437 {
4438 static const GLchar* source = "${VERSION}\n"
4439 "\n"
4440 "#ifdef GL_ES\n"
4441 "precision highp float;\n"
4442 "#endif\n"
4443 "out float fs_out_color;\n"
4444 "\n"
4445 "void main()\n"
4446 "{\n"
4447 " fs_out_color = gl_FragCoord.z;\n"
4448 "}\n"
4449 "\n";
4450
4451 std::string result = source;
4452
4453 return result;
4454 }
4455
4456 /** Get string with geometry shader source code
4457 *
4458 * @return Geometry shader source
4459 **/
getGeometryShader()4460 std::string DepthRangeDepthTest::getGeometryShader()
4461 {
4462 static const GLchar* source = "${VERSION}\n"
4463 "\n"
4464 "${GEOMETRY_SHADER_ENABLE}\n"
4465 "${VIEWPORT_ARRAY_ENABLE}\n"
4466 "\n"
4467 "layout(points, invocations = 16) in;\n"
4468 "layout(triangle_strip, max_vertices = 8) out;\n"
4469 "\n"
4470 "void main()\n"
4471 "{\n"
4472 " const float top_z = 1.0;\n"
4473 " const float bottom_z = -1.0;\n"
4474 "\n"
4475 " /* Bottom */\n"
4476 " gl_ViewportIndex = gl_InvocationID;\n"
4477 " gl_Position = vec4(-1, -1, bottom_z, 1);\n"
4478 " EmitVertex();\n"
4479 " gl_ViewportIndex = gl_InvocationID;\n"
4480 " gl_Position = vec4(-1, 0, bottom_z, 1);\n"
4481 " EmitVertex();\n"
4482 " gl_ViewportIndex = gl_InvocationID;\n"
4483 " gl_Position = vec4(1, -1, bottom_z, 1);\n"
4484 " EmitVertex();\n"
4485 " gl_ViewportIndex = gl_InvocationID;\n"
4486 " gl_Position = vec4(1, 0, bottom_z, 1);\n"
4487 " EmitVertex();\n"
4488 "\n"
4489 " /* Top */\n"
4490 " gl_ViewportIndex = gl_InvocationID;\n"
4491 " gl_Position = vec4(-1, 0, top_z, 1);\n"
4492 " EmitVertex();\n"
4493 " gl_ViewportIndex = gl_InvocationID;\n"
4494 " gl_Position = vec4(-1, 1, top_z, 1);\n"
4495 " EmitVertex();\n"
4496 " gl_ViewportIndex = gl_InvocationID;\n"
4497 " gl_Position = vec4(1, 0, top_z, 1);\n"
4498 " EmitVertex();\n"
4499 " gl_ViewportIndex = gl_InvocationID;\n"
4500 " gl_Position = vec4(1, 1, top_z, 1);\n"
4501 " EmitVertex();\n"
4502 " EndPrimitive();\n"
4503 "}\n"
4504 "\n";
4505
4506 std::string result = source;
4507
4508 return result;
4509 }
4510
4511 /** Get test type
4512 *
4513 * @return DEPTHRANGE
4514 **/
getTestType()4515 DrawTestBase::TEST_TYPE DepthRangeDepthTest::getTestType()
4516 {
4517 return DEPTHRANGE;
4518 }
4519
4520 /** Prepare textures used as framebuffer's attachments for current draw call
4521 *
4522 * @param texture_0 R32F texture
4523 * @param texture_1 D32F texture
4524 **/
prepareTextures(Utils::texture & texture_0,Utils::texture & texture_1)4525 void DepthRangeDepthTest::prepareTextures(Utils::texture& texture_0, Utils::texture& texture_1)
4526 {
4527 prepareTextureR32F(texture_0);
4528 prepareTextureD32F(texture_1);
4529 }
4530
4531 /** Attach textures to framebuffer
4532 *
4533 * @param framebuffer Framebuffer instance
4534 * @param texture_0 Texture attached as color 0
4535 * @param texture_1 Texture attached as depth
4536 **/
setupFramebuffer(Utils::framebuffer & framebuffer,Utils::texture & texture_0,Utils::texture & texture_1)4537 void DepthRangeDepthTest::setupFramebuffer(Utils::framebuffer& framebuffer, Utils::texture& texture_0,
4538 Utils::texture& texture_1)
4539 {
4540 framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, texture_0.m_id, m_width, m_height);
4541 framebuffer.attachTexture(GL_DEPTH_ATTACHMENT, texture_1.m_id, m_width, m_height);
4542 }
4543
4544 /** Set up viewports
4545 *
4546 * @param ignored
4547 * @param iteration_index Index of iteration for given test type
4548 **/
setupViewports(TEST_TYPE,GLuint iteration_index)4549 void DepthRangeDepthTest::setupViewports(TEST_TYPE /* type */, GLuint iteration_index)
4550 {
4551 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4552
4553 DEPTH_RANGE_METHOD method;
4554 switch (iteration_index)
4555 {
4556 case 0:
4557 case 1:
4558 method = (DEPTH_RANGE_METHOD)iteration_index;
4559 break;
4560 default:
4561 TCU_FAIL("Invalid value");
4562 }
4563 setup16x2Depths(method);
4564
4565 gl.enable(GL_DEPTH_TEST);
4566 GLU_EXPECT_NO_ERROR(gl.getError(), "Enable");
4567 }
4568
4569 /** Constructor
4570 *
4571 * @param context Test context
4572 * @param test_name Test name
4573 * @param test_description Test description
4574 **/
ProvokingVertex(deqp::Context & context,const glcts::ExtParameters & extParams)4575 ProvokingVertex::ProvokingVertex(deqp::Context& context, const glcts::ExtParameters& extParams)
4576 : DrawTestBase(context, extParams, "provoking_vertex", "Test verifies that provoking vertex work as expected")
4577 {
4578 /* Nothing to be done here */
4579 }
4580
4581 /** Check if R32I texture is filled with 4x4 regions of increasing values <0:15>
4582 *
4583 * @param texture_0 Verified texture
4584 * @param ignored
4585 * @param ignored
4586 *
4587 * @return True if texture_0 is filled with expected pattern
4588 **/
checkResults(Utils::texture & texture_0,Utils::texture &,GLuint)4589 bool ProvokingVertex::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */,
4590 GLuint /*draw_call_index */)
4591 {
4592 static const GLuint layer_size = m_width * m_height;
4593
4594 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4595 const glu::ContextType& context_type = m_context.getRenderContext().getType();
4596
4597 GLint layer_mode = 0;
4598 GLint viewport_mode = 0;
4599 gl.getIntegerv(GL_LAYER_PROVOKING_VERTEX, &layer_mode);
4600 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
4601 gl.getIntegerv(GL_VIEWPORT_INDEX_PROVOKING_VERTEX, &viewport_mode);
4602 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
4603
4604 if ((GL_UNDEFINED_VERTEX == layer_mode) || (GL_UNDEFINED_VERTEX == viewport_mode))
4605 {
4606 /* Results are undefined, therefore it does not make sense to verify them */
4607 return true;
4608 }
4609
4610 bool check_result = true;
4611 GLint provoking = 0;
4612
4613 std::vector<GLint> texture_data;
4614 texture_data.resize(layer_size * m_r32ix4_depth);
4615 texture_0.get(GL_RED_INTEGER, GL_INT, &texture_data[0]);
4616
4617 if (glu::isContextTypeGLCore(context_type))
4618 {
4619 gl.getIntegerv(GL_PROVOKING_VERTEX, &provoking);
4620 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
4621 }
4622 else
4623 {
4624 DE_ASSERT(glu::isContextTypeES(context_type));
4625 /* ES doesn't have provoking vertex control, so it's always LAST */
4626 provoking = GL_LAST_VERTEX_CONVENTION;
4627 }
4628
4629 GLuint expected_layer = 0;
4630 GLint expected_viewport = 0;
4631
4632 /* Mode is 1st, or mode is provoking and provoking is 1st */
4633 if ((GL_FIRST_VERTEX_CONVENTION == layer_mode) ||
4634 ((GL_PROVOKING_VERTEX == layer_mode) && (GL_FIRST_VERTEX_CONVENTION == provoking)))
4635 {
4636 expected_layer = 0;
4637 }
4638 else
4639 {
4640 expected_layer = 2;
4641 }
4642
4643 if ((GL_FIRST_VERTEX_CONVENTION == viewport_mode) ||
4644 ((GL_PROVOKING_VERTEX == viewport_mode) && (GL_FIRST_VERTEX_CONVENTION == provoking)))
4645 {
4646 expected_viewport = 0;
4647 }
4648 else
4649 {
4650 expected_viewport = 2;
4651 }
4652
4653 for (GLuint layer = 0; layer < m_r32ix4_depth; ++layer)
4654 {
4655 GLint* layer_data = &texture_data[layer * layer_size];
4656 GLint viewport = 0;
4657
4658 for (GLuint y = 0; y < 2; ++y)
4659 {
4660 for (GLuint x = 0; x < 2; ++x)
4661 {
4662 /* If layer and viewport are expected ones, than result shall be 1, otherwise -1. */
4663 const GLint expected_value = ((expected_viewport == viewport) && (expected_layer == layer)) ? 1 : -1;
4664
4665 bool result = checkRegionR32I(x, y, m_width / 2, m_height / 2, expected_value, layer_data);
4666
4667 if (false == result)
4668 {
4669 check_result = false;
4670 goto end;
4671 }
4672
4673 viewport += 1;
4674 }
4675 }
4676 }
4677
4678 end:
4679 return check_result;
4680 }
4681
4682 /** Get string with fragment shader source code
4683 *
4684 * @return Fragment shader source
4685 **/
getFragmentShader()4686 std::string ProvokingVertex::getFragmentShader()
4687 {
4688 static const GLchar* source = "${VERSION}\n"
4689 "\n"
4690 "flat in int gs_fs_color;\n"
4691 " out int fs_out_color;\n"
4692 "\n"
4693 "void main()\n"
4694 "{\n"
4695 " fs_out_color = gs_fs_color;\n"
4696 "}\n"
4697 "\n";
4698
4699 std::string result = source;
4700
4701 return result;
4702 }
4703
4704 /** Get string with geometry shader source code
4705 *
4706 * @return Geometry shader source
4707 **/
getGeometryShader()4708 std::string ProvokingVertex::getGeometryShader()
4709 {
4710 static const GLchar* source = "${VERSION}\n"
4711 "\n"
4712 "${GEOMETRY_SHADER_ENABLE}\n"
4713 "${VIEWPORT_ARRAY_ENABLE}\n"
4714 "\n"
4715 "layout(points, invocations = 1) in;\n"
4716 "layout(triangle_strip, max_vertices = 6) out;\n"
4717 "\n"
4718 "flat out int gs_fs_color;\n"
4719 "\n"
4720 "void main()\n"
4721 "{\n"
4722 " /* Left-bottom half */\n"
4723 " gs_fs_color = 1;\n"
4724 " gl_ViewportIndex = 0;\n"
4725 " gl_Layer = 0;\n"
4726 " gl_Position = vec4(-1, -1, 0, 1);\n"
4727 " EmitVertex();\n"
4728 " gs_fs_color = 1;\n"
4729 " gl_ViewportIndex = 1;\n"
4730 " gl_Layer = 1;\n"
4731 " gl_Position = vec4(-1, 1, 0, 1);\n"
4732 " EmitVertex();\n"
4733 " gs_fs_color = 1;\n"
4734 " gl_ViewportIndex = 2;\n"
4735 " gl_Layer = 2;\n"
4736 " gl_Position = vec4(1, -1, 0, 1);\n"
4737 " EmitVertex();\n"
4738 " EndPrimitive();\n"
4739 "\n"
4740 " /* Right-top half */\n"
4741 " gs_fs_color = 1;\n"
4742 " gl_ViewportIndex = 0;\n"
4743 " gl_Layer = 0;\n"
4744 " gl_Position = vec4(-1, 1, 0, 1);\n"
4745 " EmitVertex();\n"
4746 " gs_fs_color = 1;\n"
4747 " gl_ViewportIndex = 1;\n"
4748 " gl_Layer = 1;\n"
4749 " gl_Position = vec4(1, 1, 0, 1);\n"
4750 " EmitVertex();\n"
4751 " gs_fs_color = 1;\n"
4752 " gl_ViewportIndex = 2;\n"
4753 " gl_Layer = 2;\n"
4754 " gl_Position = vec4(1, -1, 0, 1);\n"
4755 " EmitVertex();\n"
4756 " EndPrimitive();\n"
4757 "}\n"
4758 "\n";
4759
4760 std::string result = source;
4761
4762 return result;
4763 }
4764
4765 /** Get test type
4766 *
4767 * @return PROVOKING
4768 **/
getTestType()4769 DrawTestBase::TEST_TYPE ProvokingVertex::getTestType()
4770 {
4771 return PROVOKING;
4772 }
4773
4774 /** Prepare textures used as framebuffer's attachments for current draw call
4775 *
4776 * @param texture_0 R32I texture
4777 * @param ignored
4778 **/
prepareTextures(Utils::texture & texture_0,Utils::texture &)4779 void ProvokingVertex::prepareTextures(Utils::texture& texture_0, Utils::texture& /* texture_1 */)
4780 {
4781 prepareTextureR32Ix4(texture_0);
4782 }
4783
4784 } /* ViewportArray namespace */
4785
4786 /** Constructor.
4787 *
4788 * @param context Rendering context.
4789 **/
ViewportArrayTests(deqp::Context & context,const glcts::ExtParameters & extParams)4790 ViewportArrayTests::ViewportArrayTests(deqp::Context& context, const glcts::ExtParameters& extParams)
4791 : TestCaseGroupBase(context, extParams, "viewport_array", "Verifies \"viewport_array\" functionality")
4792 {
4793 /* Left blank on purpose */
4794 }
4795
4796 /** Initializes a texture_storage_multisample test group.
4797 *
4798 **/
init(void)4799 void ViewportArrayTests::init(void)
4800 {
4801 addChild(new ViewportArray::APIErrors(m_context, m_extParams));
4802 addChild(new ViewportArray::Queries(m_context, m_extParams));
4803 addChild(new ViewportArray::ViewportAPI(m_context, m_extParams));
4804 addChild(new ViewportArray::ScissorAPI(m_context, m_extParams));
4805 addChild(new ViewportArray::DepthRangeAPI(m_context, m_extParams));
4806 addChild(new ViewportArray::ScissorTestStateAPI(m_context, m_extParams));
4807 addChild(new ViewportArray::DrawToSingleLayerWithMultipleViewports(m_context, m_extParams));
4808 addChild(new ViewportArray::DynamicViewportIndex(m_context, m_extParams));
4809 addChild(new ViewportArray::DrawMulitpleViewportsWithSingleInvocation(m_context, m_extParams));
4810 addChild(new ViewportArray::ViewportIndexSubroutine(m_context, m_extParams));
4811 addChild(new ViewportArray::DrawMultipleLayers(m_context, m_extParams));
4812 addChild(new ViewportArray::Scissor(m_context, m_extParams));
4813 addChild(new ViewportArray::ScissorZeroDimension(m_context, m_extParams));
4814 addChild(new ViewportArray::ScissorClear(m_context, m_extParams));
4815 addChild(new ViewportArray::DepthRange(m_context, m_extParams));
4816 addChild(new ViewportArray::DepthRangeDepthTest(m_context, m_extParams));
4817 addChild(new ViewportArray::ProvokingVertex(m_context, m_extParams));
4818 }
4819
4820 } /* glcts namespace */
4821