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