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  */ /*!
26  * \file  es31cTextureStorageMultisampleFunctionalTests.cpp
27  * \brief Implements conformance tests that verify behavior of
28  *        multisample texture functionality (ES3.1 only).
29  */ /*-------------------------------------------------------------------*/
30 
31 #include "es31cTextureStorageMultisampleFunctionalTests.hpp"
32 #include "gluContextInfo.hpp"
33 #include "gluDefs.hpp"
34 #include "glwEnums.hpp"
35 #include "glwFunctions.hpp"
36 #include "tcuRenderTarget.hpp"
37 #include "tcuTestLog.hpp"
38 
39 #include <algorithm>
40 #include <string.h>
41 #include <string>
42 #include <vector>
43 
44 namespace glcts
45 {
46 /** Constructor.
47  *
48  *  @param context CTS context handle.
49  **/
MultisampleTextureFunctionalTestsBlittingTest(Context & context)50 MultisampleTextureFunctionalTestsBlittingTest::MultisampleTextureFunctionalTestsBlittingTest(Context& context)
51 	: TestCase(context, "multisampled_fbo_to_singlesampled_fbo_blit",
52 			   "Verifies that blitting from a multi-sampled framebuffer object "
53 			   "to a single-sampled framebuffer object does not generate an error.")
54 	, dst_fbo_id(0)
55 	, dst_to_color_id(0)
56 	, dst_to_depth_stencil_id(0)
57 	, src_fbo_id(0)
58 	, src_to_color_id(0)
59 	, src_to_depth_stencil_id(0)
60 {
61 	/* Left blank on purpose */
62 }
63 
64 /** Deinitializes ES objects created during test execution */
deinit()65 void MultisampleTextureFunctionalTestsBlittingTest::deinit()
66 {
67 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
68 
69 	if (dst_fbo_id != 0)
70 	{
71 		gl.deleteFramebuffers(1, &dst_fbo_id);
72 
73 		dst_fbo_id = 0;
74 	}
75 
76 	if (src_fbo_id != 0)
77 	{
78 		gl.deleteFramebuffers(1, &src_fbo_id);
79 
80 		src_fbo_id = 0;
81 	}
82 
83 	if (dst_to_color_id != 0)
84 	{
85 		gl.deleteTextures(1, &dst_to_color_id);
86 
87 		dst_to_color_id = 0;
88 	}
89 
90 	if (dst_to_depth_stencil_id != 0)
91 	{
92 		gl.deleteTextures(1, &dst_to_depth_stencil_id);
93 
94 		dst_to_depth_stencil_id = 0;
95 	}
96 
97 	if (src_to_color_id != 0)
98 	{
99 		gl.deleteTextures(1, &src_to_color_id);
100 
101 		src_to_color_id = 0;
102 	}
103 
104 	if (src_to_depth_stencil_id != 0)
105 	{
106 		gl.deleteTextures(1, &src_to_depth_stencil_id);
107 
108 		src_to_depth_stencil_id = 0;
109 	}
110 
111 	/* Call base class' deinit() */
112 	TestCase::deinit();
113 }
114 
115 /** Executes test iteration.
116  *
117  *  @return Returns STOP when test has finished executing.
118  */
iterate()119 tcu::TestNode::IterateResult MultisampleTextureFunctionalTestsBlittingTest::iterate()
120 {
121 	bool are_2d_ms_array_tos_supported =
122 		m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array");
123 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
124 
125 	/* Set up texture objects */
126 	gl.genTextures(1, &dst_to_color_id);
127 	gl.genTextures(1, &dst_to_depth_stencil_id);
128 	gl.genTextures(1, &src_to_color_id);
129 	gl.genTextures(1, &src_to_depth_stencil_id);
130 
131 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture objects");
132 
133 	if (are_2d_ms_array_tos_supported)
134 	{
135 		gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, src_to_color_id);
136 		gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, /* samples */
137 								   GL_RGBA8, 4,							   /* width */
138 								   4,									   /* height */
139 								   4,									   /* depth */
140 								   GL_TRUE);							   /* fixedsamplelocations */
141 		GLU_EXPECT_NO_ERROR(gl.getError(),
142 							"gltexStorage3DMultisample() call failed for texture object src_to_color_id");
143 	}
144 	else
145 	{
146 		gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, src_to_color_id);
147 		gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */
148 								   GL_RGBA8, 4,					 /* width */
149 								   4,							 /* height */
150 								   GL_TRUE);					 /* fixedsamplelocations */
151 
152 		GLU_EXPECT_NO_ERROR(gl.getError(),
153 							"gltexStorage3DMultisample() call failed for texture object src_to_color_id");
154 	}
155 
156 	gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, src_to_depth_stencil_id);
157 	gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */
158 							   GL_DEPTH32F_STENCIL8, 4,		 /* width */
159 							   4,							 /* height */
160 							   GL_TRUE);					 /* fixedsamplelocations */
161 	GLU_EXPECT_NO_ERROR(gl.getError(),
162 						"glTexStorage2DMultisample() call failed for texture object src_to_depth_stencil_id");
163 
164 	gl.bindTexture(GL_TEXTURE_2D, dst_to_color_id);
165 	gl.texImage2D(GL_TEXTURE_2D, 0,					/* level */
166 				  GL_RGBA8, 4,						/* width */
167 				  4,								/* height */
168 				  0,								/* border */
169 				  GL_RGBA, GL_UNSIGNED_BYTE, NULL); /* data */
170 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage2D() call failed for texture object dst_to_color_id");
171 
172 	gl.bindTexture(GL_TEXTURE_2D_ARRAY, dst_to_depth_stencil_id);
173 	gl.texImage3D(GL_TEXTURE_2D_ARRAY, 0,									  /* level */
174 				  GL_DEPTH32F_STENCIL8, 4,									  /* width */
175 				  4,														  /* height */
176 				  4,														  /* depth */
177 				  0,														  /* border */
178 				  GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, NULL); /* data */
179 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage3D9) call failed for texture object dst_to_depth_stencil_id");
180 
181 	/* Set up framebuffer objects */
182 	gl.genFramebuffers(1, &dst_fbo_id);
183 	gl.genFramebuffers(1, &src_fbo_id);
184 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, dst_fbo_id);
185 	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, src_fbo_id);
186 
187 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up framebuffer objects");
188 
189 	/* Set up source FBO attachments. */
190 	glw::GLenum fbo_completeness_status = 0;
191 
192 	if (are_2d_ms_array_tos_supported)
193 	{
194 		gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, src_to_color_id, 0, /* level */
195 								   0);															  /* layer */
196 	}
197 	else
198 	{
199 		gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, src_to_color_id,
200 								0); /* level */
201 	}
202 
203 	gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE,
204 							src_to_depth_stencil_id, 0); /* level */
205 
206 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up source framebuffer's attachments");
207 
208 	fbo_completeness_status = gl.checkFramebufferStatus(GL_READ_FRAMEBUFFER);
209 
210 	if (fbo_completeness_status != GL_FRAMEBUFFER_COMPLETE)
211 	{
212 		m_testCtx.getLog() << tcu::TestLog::Message << "Source FBO completeness status is: " << fbo_completeness_status
213 						   << ", expected: GL_FRAMEBUFFER_COMPLETE" << tcu::TestLog::EndMessage;
214 
215 		TCU_FAIL("Source FBO is considered incomplete which is invalid");
216 	}
217 
218 	/* Set up draw FBO attachments */
219 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_to_color_id, 0);   /* level */
220 	gl.framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, dst_to_depth_stencil_id, 0, /* level */
221 							   0);																			 /* layer */
222 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up draw framebuffer's attachments");
223 
224 	fbo_completeness_status = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
225 
226 	if (fbo_completeness_status != GL_FRAMEBUFFER_COMPLETE)
227 	{
228 		m_testCtx.getLog() << tcu::TestLog::Message << "Draw FBO completeness status is: " << fbo_completeness_status
229 						   << ", expected: GL_FRAMEBUFFER_COMPLETE" << tcu::TestLog::EndMessage;
230 
231 		TCU_FAIL("Draw FBO is considered incomplete which is invalid");
232 	}
233 
234 	/* Perform the blitting operation */
235 	gl.blitFramebuffer(0, /* srcX0 */
236 					   0, /* srcY0 */
237 					   4, /* srcX1 */
238 					   4, /* srcY1 */
239 					   0, /* dstX0 */
240 					   0, /* dstY0 */
241 					   4, /* dstX1 */
242 					   4, /* dstY1 */
243 					   GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
244 					   GL_NEAREST); /* An INVALID_OPERATION error is generated if ...., and filter is not NEAREST. */
245 
246 	/* Make sure no error was generated */
247 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBlitFramebuffer() call failed.");
248 
249 	/* All done */
250 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
251 
252 	return STOP;
253 }
254 
255 /** Constructor.
256  *
257  *  @param context CTS context handle.
258  **/
259 MultisampleTextureFunctionalTestsBlittingMultisampledDepthAttachmentTest::
MultisampleTextureFunctionalTestsBlittingMultisampledDepthAttachmentTest(Context & context)260 	MultisampleTextureFunctionalTestsBlittingMultisampledDepthAttachmentTest(Context& context)
261 	: TestCase(context, "blitting_multisampled_depth_attachment",
262 			   "Verifies that blitting a multi-sampled depth attachment to "
263 			   "a single-sampled depth attachment gives valid results")
264 	, fbo_dst_id(0)
265 	, fbo_src_id(0)
266 	, fs_depth_preview_id(0)
267 	, fs_id(0)
268 	, po_depth_preview_id(0)
269 	, po_id(0)
270 	, to_dst_preview_id(0)
271 	, to_dst_id(0)
272 	, to_src_id(0)
273 	, vao_id(0)
274 	, vs_id(0)
275 {
276 	/* Left blank on purpose */
277 }
278 
279 /** Deinitializes ES objects created during test execution */
deinit()280 void MultisampleTextureFunctionalTestsBlittingMultisampledDepthAttachmentTest::deinit()
281 {
282 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
283 
284 	if (fbo_dst_id != 0)
285 	{
286 		gl.deleteFramebuffers(1, &fbo_dst_id);
287 
288 		fbo_dst_id = 0;
289 	}
290 
291 	if (fbo_src_id != 0)
292 	{
293 		gl.deleteFramebuffers(1, &fbo_src_id);
294 
295 		fbo_src_id = 0;
296 	}
297 
298 	if (to_dst_preview_id != 0)
299 	{
300 		gl.deleteTextures(1, &to_dst_preview_id);
301 
302 		to_dst_preview_id = 0;
303 	}
304 
305 	if (to_dst_id != 0)
306 	{
307 		gl.deleteTextures(1, &to_dst_id);
308 
309 		to_dst_id = 0;
310 	}
311 
312 	if (to_src_id != 0)
313 	{
314 		gl.deleteTextures(1, &to_src_id);
315 
316 		to_src_id = 0;
317 	}
318 
319 	if (fs_id != 0)
320 	{
321 		gl.deleteShader(fs_id);
322 
323 		fs_id = 0;
324 	}
325 
326 	if (fs_depth_preview_id != 0)
327 	{
328 		gl.deleteShader(fs_depth_preview_id);
329 
330 		fs_depth_preview_id = 0;
331 	}
332 
333 	if (po_depth_preview_id != 0)
334 	{
335 		gl.deleteProgram(po_depth_preview_id);
336 
337 		po_depth_preview_id = 0;
338 	}
339 
340 	if (po_id != 0)
341 	{
342 		gl.deleteProgram(po_id);
343 
344 		po_id = 0;
345 	}
346 
347 	if (vao_id != 0)
348 	{
349 		gl.deleteVertexArrays(1, &vao_id);
350 
351 		vao_id = 0;
352 	}
353 
354 	if (vs_id != 0)
355 	{
356 		gl.deleteShader(vs_id);
357 
358 		vs_id = 0;
359 	}
360 
361 	/* Call base class' deinit() */
362 	TestCase::deinit();
363 }
364 
365 /** Executes test iteration.
366  *
367  *  @return Returns STOP when test has finished executing.
368  */
iterate()369 tcu::TestNode::IterateResult MultisampleTextureFunctionalTestsBlittingMultisampledDepthAttachmentTest::iterate()
370 {
371 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
372 
373 	/* Generate all objects this test will use */
374 	fs_depth_preview_id = gl.createShader(GL_FRAGMENT_SHADER);
375 	fs_id				= gl.createShader(GL_FRAGMENT_SHADER);
376 	vs_id				= gl.createShader(GL_VERTEX_SHADER);
377 
378 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed");
379 
380 	po_depth_preview_id = gl.createProgram();
381 	po_id				= gl.createProgram();
382 
383 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed");
384 
385 	gl.genTextures(1, &to_src_id);
386 	gl.genTextures(1, &to_dst_preview_id);
387 	gl.genTextures(1, &to_dst_id);
388 
389 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
390 
391 	gl.genFramebuffers(1, &fbo_src_id);
392 	gl.genFramebuffers(1, &fbo_dst_id);
393 
394 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() failed");
395 
396 	gl.genVertexArrays(1, &vao_id);
397 
398 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() failed");
399 
400 	/* Bind FBOs to relevant FB targets */
401 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_dst_id);
402 	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, fbo_src_id);
403 
404 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call(s) failed");
405 
406 	/* Configure body of vs_id vertex shader */
407 	const glw::GLchar* vs_body = "#version 310 es\n"
408 								 "\n"
409 								 "precision highp float;\n"
410 								 "\n"
411 								 "out vec2 uv;\n"
412 								 "\n"
413 								 "void main()\n"
414 								 "{\n"
415 								 "    switch(gl_VertexID)\n"
416 								 "    {\n"
417 								 "        case 0: gl_Position = vec4(-1, -1, 0, 1); uv = vec2(0, 0); break;\n"
418 								 "        case 1: gl_Position = vec4(-1,  1, 0, 1); uv = vec2(0, 1); break;\n"
419 								 "        case 2: gl_Position = vec4( 1,  1, 0, 1); uv = vec2(1, 1); break;\n"
420 								 "        case 3: gl_Position = vec4( 1, -1, 0, 1); uv = vec2(1, 0); break;\n"
421 								 "    }\n"
422 								 "}\n";
423 
424 	gl.shaderSource(vs_id, 1 /* count */, &vs_body, NULL);
425 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for vertex shader of vs_id id");
426 
427 	/* Configure body of fs_id fragment shader */
428 	const glw::GLchar* fs_body = "#version 310 es\n"
429 								 "\n"
430 								 "precision highp float;\n"
431 								 "\n"
432 								 "in vec2 uv;\n"
433 								 "\n"
434 								 "void main()\n"
435 								 "{\n"
436 								 "    gl_FragDepth = uv.x * uv.y;\n"
437 								 "}\n";
438 
439 	gl.shaderSource(fs_id, 1 /* count */, &fs_body, NULL);
440 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for fragment shader of fs_id id");
441 
442 	/* Configure body of fs_depth_preview_id fragment shader */
443 	const glw::GLchar* fs_depth_preview_body = "#version 310 es\n"
444 											   "\n"
445 											   "precision highp int;\n"
446 											   "precision highp float;\n"
447 											   "\n"
448 											   "in      vec2      uv;\n"
449 											   "out     uint      result;\n"
450 											   "uniform sampler2D tex;\n"
451 											   "\n"
452 											   "void main()\n"
453 											   "{\n"
454 											   "    result = floatBitsToUint(textureLod(tex, uv, 0.0).x);\n"
455 											   "}\n";
456 
457 	gl.shaderSource(fs_depth_preview_id, 1 /* count */, &fs_depth_preview_body, NULL);
458 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for fragment shader of fs_depth_preview_id id");
459 
460 	/* Compile all the shaders */
461 	const glw::GLuint  shader_ids[] = { fs_id, fs_depth_preview_id, vs_id };
462 	const unsigned int n_shader_ids = sizeof(shader_ids) / sizeof(shader_ids[0]);
463 
464 	for (unsigned int n_shader_id = 0; n_shader_id < n_shader_ids; ++n_shader_id)
465 	{
466 		glw::GLint compile_status = GL_FALSE;
467 
468 		gl.compileShader(shader_ids[n_shader_id]);
469 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() failed");
470 
471 		gl.getShaderiv(shader_ids[n_shader_id], GL_COMPILE_STATUS, &compile_status);
472 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() failed");
473 
474 		if (compile_status != GL_TRUE)
475 		{
476 			TCU_FAIL("Shader compilation failure");
477 		}
478 	} /* for (all shader ids) */
479 
480 	/* Configure and link both program objects */
481 	const glw::GLuint  program_ids[] = { po_depth_preview_id, po_id };
482 	const unsigned int n_program_ids = sizeof(program_ids) / sizeof(program_ids[0]);
483 
484 	gl.attachShader(po_depth_preview_id, fs_depth_preview_id);
485 	gl.attachShader(po_depth_preview_id, vs_id);
486 	gl.attachShader(po_id, fs_id);
487 	gl.attachShader(po_id, vs_id);
488 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() failed");
489 
490 	for (unsigned int n_program_id = 0; n_program_id < n_program_ids; ++n_program_id)
491 	{
492 		glw::GLint link_status = GL_FALSE;
493 
494 		gl.linkProgram(program_ids[n_program_id]);
495 		GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() failed");
496 
497 		gl.getProgramiv(program_ids[n_program_id], GL_LINK_STATUS, &link_status);
498 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed");
499 
500 		if (link_status != GL_TRUE)
501 		{
502 			TCU_FAIL("Program linking failure");
503 		}
504 	} /* for (all program ids) */
505 
506 	/* Retrieve maximum amount of samples that can be used for GL_DEPTH_COMPONENT32F internalformat */
507 	glw::GLint n_depth_component32f_max_samples = 0;
508 
509 	gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_DEPTH_COMPONENT32F, GL_SAMPLES, 1, /* bufSize */
510 						   &n_depth_component32f_max_samples);
511 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInternalformativ() failed");
512 
513 	/* Configure texture storage for to_src_id */
514 	gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_src_id);
515 	gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, n_depth_component32f_max_samples, GL_DEPTH_COMPONENT32F,
516 							   64,		  /* width */
517 							   64,		  /* height */
518 							   GL_FALSE); /* fixedsamplelocations */
519 
520 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure texture storage for texture object to_src_id");
521 
522 	gl.texParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
523 
524 	/* When <target> is TEXTURE_2D_MULTISAMPLE  or
525 	 TEXTURE_2D_MULTISAMPLE_ARRAY_XXX, certain texture parameters may not be
526 	 specified. In this case, an INVALID_ENUM error is generated if the
527 	 parameter is any sampler state value from table 6.10. */
528 	glw::GLenum error_code = gl.getError();
529 	if (error_code != GL_INVALID_ENUM)
530 	{
531 		m_testCtx.getLog() << tcu::TestLog::Message << "glTexParameteri() call generated an error " << error_code
532 						   << " instead of the expected error code " << GL_INVALID_ENUM << tcu::TestLog::EndMessage;
533 
534 		TCU_FAIL("glTexParameterf() with target GL_TEXTURE_2D_MULTISAMPLE and pname=GL_TEXTURE_MIN_FILTER did not "
535 				 "generate GL_INVALID_ENUM.");
536 	}
537 
538 	/* Configure texture storage for to_dst_id */
539 	gl.bindTexture(GL_TEXTURE_2D, to_dst_id);
540 	gl.texStorage2D(GL_TEXTURE_2D, 1,		   /* levels */
541 					GL_DEPTH_COMPONENT32F, 64, /* width */
542 					64);					   /* height */
543 
544 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure texture storage for texture object to_dst_id");
545 
546 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
547 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set nearest minification filter for texture object to_dst_id");
548 
549 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
550 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set nearest magnification filter for texture object to_dst_id");
551 
552 	/* Configure draw framebuffer */
553 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, to_src_id,
554 							0); /* level */
555 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure draw framebuffer for depth data rendering");
556 
557 	/* Render the test geometry.
558 	 *
559 	 * NOTE: Original test spec rendered to fbo_dst_id which would have been invalid,
560 	 *       since fbo_dst_id is the assumed destination for the blitting operation.
561 	 *       Actual FBO management code has been rewritten to improve code clarity.
562 	 *
563 	 * NOTE: Original test spec didn't enable the depth tests, which are necessary
564 	 *       for the depth buffer to be updated.
565 	 **/
566 	gl.viewport(0, 0, 64 /* rt width */, 64 /* rt height */);
567 	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() failed");
568 
569 	gl.enable(GL_DEPTH_TEST);
570 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_DEPTH_TEST) failed");
571 
572 	gl.depthFunc(GL_ALWAYS);
573 	GLU_EXPECT_NO_ERROR(gl.getError(), "gldepthFunc(GL_ALWAYS) failed");
574 
575 	gl.useProgram(po_id);
576 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() for program object po_id failed");
577 
578 	gl.bindVertexArray(vao_id);
579 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() failed");
580 
581 	gl.drawArrays(GL_TRIANGLE_FAN, 0 /* first */, 4 /* count */);
582 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed");
583 
584 	/* Configure FBOs for blitting */
585 	gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, to_src_id,
586 							0); /* level */
587 
588 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, to_dst_id, 0); /* level */
589 
590 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure FBOs for blitting");
591 
592 	/* Blit source FBO to destination FBO */
593 	gl.blitFramebuffer(0,  /* srcX0 */
594 					   0,  /* srcY0 */
595 					   64, /* srcX1 */
596 					   64, /* srcY1 */
597 					   0,  /* dstX0 */
598 					   0,  /* dstY0 */
599 					   64, /* dstX1 */
600 					   64, /* dstY1 */
601 					   GL_DEPTH_BUFFER_BIT, GL_NEAREST);
602 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBlitFramebuffer() failed");
603 
604 	/* Single-sampled depth data is now stored in dst_to_id in GL_DEPTH_COMPONENT32F which may
605 	 * not work too well with glReadPixels().
606 	 *
607 	 * We will now convert it to GL_R32UI using the other program */
608 	gl.useProgram(po_depth_preview_id);
609 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed for program object po_depth_preview_id");
610 
611 	/* Configure texture storage for the destination texture object */
612 	gl.bindTexture(GL_TEXTURE_2D, to_dst_preview_id);
613 	gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */
614 					GL_R32UI, 64,	 /* width */
615 					64);			  /* height */
616 
617 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texcture storage for texture object to_dst_preview_id");
618 
619 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
620 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() failed for texture object to_dst_preview_id");
621 
622 	/* Update draw framebuffer configuration */
623 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, /* texture */
624 							0);															/* level */
625 
626 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, to_dst_preview_id, 0); /* level */
627 
628 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() failed for depth preview pass");
629 
630 	/* Render a full-screen quad */
631 	gl.bindTexture(GL_TEXTURE_2D, to_dst_id);
632 
633 	gl.drawArrays(GL_TRIANGLE_FAN, 0 /* first */, 4 /* count */);
634 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed for depth preview pass");
635 
636 	/* to_dst_id now contains the result data.
637 	 *
638 	 * Before we do a glReadPixels() call, we need to re-configure the read FBO */
639 	gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, /* texture */
640 							0);															/* level */
641 
642 	gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, to_dst_preview_id, 0); /* level */
643 
644 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() failed for depth data download pass");
645 
646 	/* Read the data */
647 	unsigned int buffer[64 /* width */ * 64 /* height */ * 4 /* components */];
648 
649 	gl.readPixels(0,  /* x */
650 				  0,  /* y */
651 				  64, /* width */
652 				  64, /* height */
653 				  GL_RGBA_INTEGER, GL_UNSIGNED_INT, buffer);
654 	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() failed for depth data download pass");
655 
656 	/* Verify the rendered data */
657 	const float epsilon = 1.0f / 64.0f + (float)1e-5;
658 
659 	for (int y = 0; y < 64 /* height */; ++y)
660 	{
661 		/* NOTE: data_y is used to take the bottom-top orientation of the data downloaded
662 		 *       by glReadPixels() into account.
663 		 */
664 		const int data_y	 = (64 /* height */ - y - 1 /* counting starts from 0 */);
665 		const int pixel_size = 4; /* components */
666 		const int row_width  = 64 /* width */ * pixel_size;
667 		float*	row_ptr	= (float*)buffer + row_width * data_y;
668 
669 		for (int x = 0; x < 64 /* width */; ++x)
670 		{
671 			float* data_ptr			  = row_ptr + x * pixel_size;
672 			float  depth			  = data_ptr[0];
673 			float  expected_value_max = float(x) * float(data_y) / (64.0f * 64.0f) + epsilon;
674 			float  expected_value_min = float(x) * float(data_y) / (64.0f * 64.0f) - epsilon;
675 
676 			if (!(depth >= expected_value_min && depth <= expected_value_max))
677 			{
678 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid data rendered at (" << x << ", " << y << "): "
679 								   << "Expected value from " << expected_value_min << " to " << expected_value_max
680 								   << ", "
681 								   << "rendered: " << depth << tcu::TestLog::EndMessage;
682 
683 				TCU_FAIL("Invalid data rendered");
684 			}
685 		} /* for (all x argument values) */
686 	}	 /* for (all y argument values) */
687 
688 	/* All done */
689 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
690 
691 	return STOP;
692 }
693 
694 /** Constructor.
695  *
696  *  @param context CTS context handle.
697  **/
698 MultisampleTextureFunctionalTestsBlittingMultisampledIntegerAttachmentTest::
MultisampleTextureFunctionalTestsBlittingMultisampledIntegerAttachmentTest(Context & context)699 	MultisampleTextureFunctionalTestsBlittingMultisampledIntegerAttachmentTest(Context& context)
700 	: TestCase(context, "blitting_multisampled_integer_attachment",
701 			   "Verifies that blitting a multi-sampled integer attachment "
702 			   "to a single-sampled integer attachment gives valid results")
703 	, dst_to_id(0)
704 	, fbo_draw_id(0)
705 	, fbo_read_id(0)
706 	, fs_id(0)
707 	, po_id(0)
708 	, src_to_id(0)
709 	, vs_id(0)
710 {
711 	/* Left blank on purpose */
712 }
713 
714 /** Deinitializes ES objects created during test execution */
deinit()715 void MultisampleTextureFunctionalTestsBlittingMultisampledIntegerAttachmentTest::deinit()
716 {
717 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
718 
719 	if (fbo_draw_id != 0)
720 	{
721 		gl.deleteFramebuffers(1, &fbo_draw_id);
722 
723 		fbo_draw_id = 0;
724 	}
725 
726 	if (fbo_read_id != 0)
727 	{
728 		gl.deleteFramebuffers(1, &fbo_read_id);
729 
730 		fbo_read_id = 0;
731 	}
732 
733 	if (dst_to_id != 0)
734 	{
735 		gl.deleteTextures(1, &dst_to_id);
736 
737 		dst_to_id = 0;
738 	}
739 
740 	if (src_to_id != 0)
741 	{
742 		gl.deleteTextures(1, &src_to_id);
743 
744 		src_to_id = 0;
745 	}
746 
747 	if (fs_id != 0)
748 	{
749 		gl.deleteShader(fs_id);
750 
751 		fs_id = 0;
752 	}
753 
754 	if (po_id != 0)
755 	{
756 		gl.deleteProgram(po_id);
757 
758 		po_id = 0;
759 	}
760 
761 	if (vs_id != 0)
762 	{
763 		gl.deleteShader(vs_id);
764 
765 		vs_id = 0;
766 	}
767 
768 	/* Call base class' deinit() */
769 	TestCase::deinit();
770 }
771 
772 /** Executes test iteration.
773  *
774  *  @return Returns STOP when test has finished executing.
775  */
iterate()776 tcu::TestNode::IterateResult MultisampleTextureFunctionalTestsBlittingMultisampledIntegerAttachmentTest::iterate()
777 {
778 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
779 
780 	/* Make sure GL_MAX_INTEGER_SAMPLES is at least 2 */
781 	glw::GLint gl_max_integer_samples_value = 0;
782 
783 	gl.getIntegerv(GL_MAX_INTEGER_SAMPLES, &gl_max_integer_samples_value);
784 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not query GL_MAX_INTEGER_SAMPLES pname value");
785 
786 	if (gl_max_integer_samples_value < 2)
787 	{
788 		throw tcu::NotSupportedError("GL_MAX_INTEGER_SAMPLES is lower than 2");
789 	}
790 
791 	/* Retrieve maximum amount of samples for GL_R16UI internalformat */
792 	glw::GLint r16ui_max_samples = 0;
793 
794 	gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_R16UI, GL_SAMPLES, 1 /* bufSize */, &r16ui_max_samples);
795 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInternalformativ() call failed.");
796 
797 	/* Set up texture objects */
798 	gl.genTextures(1, &dst_to_id);
799 	gl.genTextures(1, &src_to_id);
800 
801 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture objects");
802 
803 	gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, src_to_id);
804 	gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, r16ui_max_samples, GL_R16UI, 16, /* width */
805 							   16,														   /* height */
806 							   GL_FALSE);												   /* fixedsamplelocations */
807 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() call failed for texture object src_to_id");
808 
809 	gl.bindTexture(GL_TEXTURE_2D, dst_to_id);
810 	gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */
811 					GL_R16UI, 16,	 /* width */
812 					16);			  /* height */
813 
814 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed for texture object dst_to_id");
815 
816 	/* Create a program object */
817 	po_id = gl.createProgram();
818 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed");
819 
820 	/* Create two shader objects */
821 	fs_id = gl.createShader(GL_FRAGMENT_SHADER);
822 	vs_id = gl.createShader(GL_VERTEX_SHADER);
823 
824 	GLU_EXPECT_NO_ERROR(gl.getError(), "Either of the glCreateShader() calls failed");
825 
826 	/* Set up framebuffer objects */
827 	gl.genFramebuffers(1, &fbo_draw_id);
828 	gl.genFramebuffers(1, &fbo_read_id);
829 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_draw_id);
830 	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, fbo_read_id);
831 
832 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up framebuffer objects");
833 
834 	/* Set up draw FBO's color attachment. */
835 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, src_to_id,
836 							0); /* level */
837 
838 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed");
839 
840 	/* Set up shader objects.
841 	 *
842 	 * NOTE: Original test spec specified an invalid case 3 for the vertex shader.
843 	 * NOTE: Original test case used a float output value. This would not be valid,
844 	 *       as the color buffer's attachment uses GL_R16UI format.
845 	 */
846 	glw::GLint		   compile_status = GL_FALSE;
847 	static const char* fs_body		  = "#version 310 es\n"
848 								 "\n"
849 								 "precision highp float;\n"
850 								 "\n"
851 								 "uniform uint  n_sample;\n"
852 								 "uniform uint  n_max_samples;\n"
853 								 "uniform highp uvec2 x1y1;\n"
854 								 "out     uint  result;\n"
855 								 "\n"
856 								 "void main()\n"
857 								 "{\n"
858 								 "    uint row_index    = x1y1.y;\n"
859 								 "    uint column_index = x1y1.x;\n"
860 								 "\n"
861 								 "    if (n_sample < n_max_samples / 2u)\n"
862 								 "    {\n"
863 								 "        result = row_index * 16u + column_index;\n"
864 								 "    }\n"
865 								 "    else\n"
866 								 "    {\n"
867 								 "        result = row_index * 16u + column_index + 1u;\n"
868 								 "    }\n"
869 								 "}\n";
870 	static const char* vs_body = "#version 310 es\n"
871 								 "\n"
872 								 "uniform uvec2 x1y1;\n"
873 								 "\n"
874 								 "void main()\n"
875 								 "{\n"
876 								 "    switch (gl_VertexID)\n"
877 								 "    {\n"
878 								 "        case 0: gl_Position = vec4( (float(x1y1.x) + 0.0 - 8.0)/8.0, (float(x1y1.y) "
879 								 "+ 0.0 - 8.0)/8.0, 0.0, 1.0); break;\n"
880 								 "        case 1: gl_Position = vec4( (float(x1y1.x) + 1.0 - 8.0)/8.0, (float(x1y1.y) "
881 								 "+ 0.0 - 8.0)/8.0, 0.0, 1.0); break;\n"
882 								 "        case 2: gl_Position = vec4( (float(x1y1.x) + 1.0 - 8.0)/8.0, (float(x1y1.y) "
883 								 "+ 1.0 - 8.0)/8.0, 0.0, 1.0); break;\n"
884 								 "        case 3: gl_Position = vec4( (float(x1y1.x) + 0.0 - 8.0)/8.0, (float(x1y1.y) "
885 								 "+ 1.0 - 8.0)/8.0, 0.0, 1.0); break;\n"
886 								 "    }\n"
887 								 "}\n";
888 
889 	gl.attachShader(po_id, fs_id);
890 	gl.attachShader(po_id, vs_id);
891 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
892 
893 	gl.shaderSource(fs_id, 1 /* count */, &fs_body, NULL);
894 	gl.shaderSource(vs_id, 1 /* count */, &vs_body, NULL);
895 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
896 
897 	gl.compileShader(fs_id);
898 	gl.compileShader(vs_id);
899 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call(s) failed.");
900 
901 	gl.getShaderiv(fs_id, GL_COMPILE_STATUS, &compile_status);
902 	if (compile_status != GL_TRUE)
903 	{
904 		TCU_FAIL("Could not compile fragment shader");
905 	}
906 
907 	gl.getShaderiv(vs_id, GL_COMPILE_STATUS, &compile_status);
908 	if (compile_status != GL_TRUE)
909 	{
910 		/* Retrieve and dump compilation fail reason */
911 		char		 infoLog[1024];
912 		glw::GLsizei length = 0;
913 
914 		gl.getShaderInfoLog(vs_id, 1024, &length, infoLog);
915 
916 		m_testCtx.getLog() << tcu::TestLog::Message << "Vertex shader compilation failed, infoLog: " << infoLog
917 						   << tcu::TestLog::EndMessage;
918 
919 		TCU_FAIL("Could not compile vertex shader");
920 	}
921 
922 	/* Link the program object */
923 	glw::GLint link_status = GL_FALSE;
924 
925 	gl.linkProgram(po_id);
926 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() failed");
927 
928 	gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status);
929 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed");
930 
931 	if (link_status != GL_TRUE)
932 	{
933 		TCU_FAIL("Could not link program object");
934 	}
935 
936 	/* Enable GL_SAMPLE_MASK mode */
937 	gl.enable(GL_SAMPLE_MASK);
938 
939 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_SAMPLE_MASK) call generated an unexpected error");
940 
941 	/* Prepare for rendering */
942 	glw::GLint n_max_samples_uniform_location = gl.getUniformLocation(po_id, "n_max_samples");
943 	glw::GLint n_sample_uniform_location	  = gl.getUniformLocation(po_id, "n_sample");
944 	glw::GLint x1y1_uniform_location		  = gl.getUniformLocation(po_id, "x1y1");
945 
946 	if (n_max_samples_uniform_location == -1)
947 	{
948 		TCU_FAIL("n_max_samples is not considered an active uniform.");
949 	}
950 
951 	if (n_sample_uniform_location == -1)
952 	{
953 		TCU_FAIL("n_sample is not considered an active uniform.");
954 	}
955 
956 	if (x1y1_uniform_location == -1)
957 	{
958 		TCU_FAIL("x1y1 is not considered an active uniform.");
959 	}
960 
961 	gl.viewport(0 /* x */, 0 /* y */, 16 /* width */, 16 /* height */);
962 	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed");
963 
964 	gl.useProgram(po_id);
965 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed");
966 
967 	gl.uniform1ui(n_max_samples_uniform_location, r16ui_max_samples);
968 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1ui() call failed");
969 
970 	/* Clear color buffer before drawing to it, not strictly neccesary
971 	 * but helps debugging */
972 	glw::GLuint clear_color_src[] = { 11, 22, 33, 44 };
973 
974 	gl.clearBufferuiv(GL_COLOR, 0, clear_color_src);
975 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClearBufferiv() call failed");
976 
977 	/* Render */
978 	for (int x = 0; x < 16 /* width */; ++x)
979 	{
980 		for (int y = 0; y < 16 /* height */; ++y)
981 		{
982 			for (int n_sample = 0; n_sample < r16ui_max_samples; ++n_sample)
983 			{
984 				gl.uniform1ui(n_sample_uniform_location, n_sample);
985 				GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1ui() call failed");
986 
987 				gl.uniform2ui(x1y1_uniform_location, x, y);
988 				GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform2f() call failed");
989 
990 				gl.sampleMaski(n_sample / 32, 1 << (n_sample % 32));
991 				GLU_EXPECT_NO_ERROR(gl.getError(), "glSampleMaski() call failed.");
992 
993 				gl.drawArrays(GL_TRIANGLE_FAN, 0 /* first */, 4 /* count */);
994 				GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
995 			} /* for (all n_sample values) */
996 		}	 /* for (all y values) */
997 	}		  /* for (all x values) */
998 
999 	/* Now, configure the framebuffer binding points for the blitting operation */
1000 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_to_id, 0); /* level */
1001 	gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, src_to_id,
1002 							0); /* level */
1003 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up framebuffer objects for the blitting operation");
1004 
1005 	/* Clear color buffer before drawing to it, not strictly neccesary
1006 	 * but helps debugging */
1007 	glw::GLuint clear_color_dst[] = { 55, 66, 77, 88 };
1008 
1009 	gl.clearBufferuiv(GL_COLOR, 0, clear_color_dst);
1010 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClearBufferiv() call failed");
1011 
1012 	/* Blit the data.
1013 	 *
1014 	 * NOTE: Original test spec specified GL_LINEAR filter which would not have worked
1015 	 *       because the read buffer contains integer data.
1016 	 **/
1017 	gl.blitFramebuffer(0,  /* srcX0 */
1018 					   0,  /* srcY0 */
1019 					   16, /* srcX1 */
1020 					   16, /* srcY1 */
1021 					   0,  /* dstX0 */
1022 					   0,  /* dstY0 */
1023 					   16, /* dstX1 */
1024 					   16, /* dstY1 */
1025 					   GL_COLOR_BUFFER_BIT, GL_NEAREST);
1026 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBlitFramebuffer() call failed.");
1027 
1028 	/* Configure the read framebuffer for upcoming glReadPixels() call */
1029 	gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_to_id, 0); /* level */
1030 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure the read framebuffer");
1031 
1032 	/* Allocate a buffer to hold the result data and then download the result texture's
1033 	 * contents */
1034 	unsigned int* buffer = new unsigned int[16 /* width */ * 16 /* height */ * 4 /* components */];
1035 
1036 	gl.readPixels(0,  /* x */
1037 				  0,  /* y */
1038 				  16, /* width */
1039 				  16, /* height */
1040 				  GL_RGBA_INTEGER, GL_UNSIGNED_INT, buffer);
1041 	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed");
1042 
1043 	/* Verify the downloaded contents */
1044 	int has_test_fail = 0;
1045 	int pixel_size	= sizeof(unsigned int) * 4 /* components */;
1046 	int row_width	 = pixel_size * 16 /* width */;
1047 
1048 	for (unsigned int y = 0; y < 16 /* height */; ++y)
1049 	{
1050 		/* NOTE: Vertical flipping should not be needed, but we cannot confirm this at the moment.
1051 		 *       Should it be the case, please change data_y to 15 - y */
1052 		/* TODO: Remove NOTE above when verified on actual ES3.1 implementation */
1053 		unsigned int		data_y  = y;
1054 		const unsigned int* row_ptr = (unsigned int*)((char*)buffer + data_y * row_width);
1055 
1056 		for (unsigned int x = 0; x < 16 /* width */; ++x)
1057 		{
1058 			const unsigned int* data_ptr   = (unsigned int*)((char*)row_ptr + x * pixel_size);
1059 			const unsigned int  r		   = data_ptr[0];
1060 			const unsigned int  g		   = data_ptr[1];
1061 			const unsigned int  b		   = data_ptr[2];
1062 			const unsigned int  a		   = data_ptr[3];
1063 			bool				is_r_valid = (r == (data_y * 16 + x)) || (r == (data_y * 16 + x + 1));
1064 			bool				is_g_valid = (g == 0);
1065 			bool				is_b_valid = (b == 0);
1066 			bool				is_a_valid = (a == 1);
1067 
1068 			if (!is_r_valid || !is_g_valid || !is_b_valid || !is_a_valid)
1069 			{
1070 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid texture data at (" << x << ", " << y << "):"
1071 								   << " Expected (" << (data_y * 16 + x) << ", 0, 0, 1)"
1072 								   << " or (" << (data_y * 16 + x + 1) << ", 0, 0, 1)"
1073 								   << ", found (" << r << ", " << g << ", " << b << ", " << a << ")."
1074 								   << tcu::TestLog::EndMessage;
1075 
1076 				has_test_fail++;
1077 			}
1078 		} /* for (all x values) */
1079 	}	 /* for (all y values) */
1080 
1081 	if (has_test_fail)
1082 	{
1083 		TCU_FAIL("Invalid texture data");
1084 	}
1085 
1086 	/* All done */
1087 	if (buffer != NULL)
1088 	{
1089 		delete[] buffer;
1090 		buffer = NULL;
1091 	}
1092 
1093 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1094 
1095 	return STOP;
1096 }
1097 
1098 /** Constructor.
1099  *
1100  *  @param context CTS context handle.
1101  **/
1102 MultisampleTextureFunctionalTestsBlittingToMultisampledFBOIsForbiddenTest::
MultisampleTextureFunctionalTestsBlittingToMultisampledFBOIsForbiddenTest(Context & context)1103 	MultisampleTextureFunctionalTestsBlittingToMultisampledFBOIsForbiddenTest(Context& context)
1104 	: TestCase(context, "blitting_to_multisampled_fbo_is_forbidden",
1105 			   "Verifies that blitting to a multisampled framebuffer "
1106 			   "object results in a GL_INVALID_OPERATION error.")
1107 	, dst_to_id(0)
1108 	, fbo_draw_id(0)
1109 	, fbo_read_id(0)
1110 	, src_to_id(0)
1111 {
1112 	/* Left blank on purpose */
1113 }
1114 
1115 /** Deinitializes ES objects created during test execution */
deinit()1116 void MultisampleTextureFunctionalTestsBlittingToMultisampledFBOIsForbiddenTest::deinit()
1117 {
1118 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1119 
1120 	if (fbo_draw_id != 0)
1121 	{
1122 		gl.deleteFramebuffers(1, &fbo_draw_id);
1123 
1124 		fbo_draw_id = 0;
1125 	}
1126 
1127 	if (fbo_read_id != 0)
1128 	{
1129 		gl.deleteFramebuffers(1, &fbo_read_id);
1130 
1131 		fbo_read_id = 0;
1132 	}
1133 
1134 	if (dst_to_id != 0)
1135 	{
1136 		gl.deleteTextures(1, &dst_to_id);
1137 
1138 		dst_to_id = 0;
1139 	}
1140 
1141 	if (src_to_id != 0)
1142 	{
1143 		gl.deleteTextures(1, &src_to_id);
1144 
1145 		src_to_id = 0;
1146 	}
1147 
1148 	/* Call base class' deinit() */
1149 	TestCase::deinit();
1150 }
1151 
1152 /** Executes test iteration.
1153  *
1154  *  @return Returns STOP when test has finished executing.
1155  */
iterate()1156 tcu::TestNode::IterateResult MultisampleTextureFunctionalTestsBlittingToMultisampledFBOIsForbiddenTest::iterate()
1157 {
1158 	const std::vector<std::string>& exts = m_context.getContextInfo().getExtensions();
1159 	const bool has_NV_framebuffer_blit   = std::find(exts.begin(), exts.end(), "GL_NV_framebuffer_blit") != exts.end();
1160 	const glw::Functions& gl			 = m_context.getRenderContext().getFunctions();
1161 
1162 	/* Set up texture objects */
1163 	gl.genTextures(1, &dst_to_id);
1164 	gl.genTextures(1, &src_to_id);
1165 
1166 	gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, dst_to_id);
1167 	gl.bindTexture(GL_TEXTURE_2D, src_to_id);
1168 
1169 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture objects");
1170 
1171 	gl.texStorage2D(GL_TEXTURE_2D, 2, /* levels */
1172 					GL_RGB10_A2, 64,  /* width */
1173 					64);			  /* height */
1174 
1175 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed for GL_TEXTURE_2D texture target");
1176 
1177 	gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */
1178 							   GL_RGB10_A2, 64,				 /* width */
1179 							   64,							 /* height */
1180 							   GL_FALSE);					 /* fixedsamplelocations */
1181 
1182 	GLU_EXPECT_NO_ERROR(gl.getError(),
1183 						"gl.texStorage2DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE texture target");
1184 
1185 	/* Set up framebuffer objects */
1186 	gl.genFramebuffers(1, &fbo_draw_id);
1187 	gl.genFramebuffers(1, &fbo_read_id);
1188 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_draw_id);
1189 	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, fbo_read_id);
1190 
1191 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up framebuffer objects");
1192 
1193 	/* Set up FBO attachments.
1194 	 *
1195 	 * NOTE: The draw/read FBO configuration in original test spec was the other
1196 	 *       way around which was wrong.
1197 	 */
1198 	gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, src_to_id, 0); /* level */
1199 
1200 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up read framebuffer's attachments");
1201 
1202 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1203 							dst_to_id, /* texture */
1204 							0);		   /* layer */
1205 
1206 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up draw framebuffer's attachments");
1207 
1208 	/* Try to perform blitting operations. */
1209 	const glw::GLenum  filters[] = { GL_NEAREST, GL_LINEAR };
1210 	const unsigned int n_filters = sizeof(filters) / sizeof(filters[0]);
1211 
1212 	for (unsigned int n_filter = 0; n_filter < n_filters; ++n_filter)
1213 	{
1214 		glw::GLenum filter = filters[n_filter];
1215 
1216 		// This blit would be supported by NV_framebuffer_blit if sizes match.
1217 		// Alter the size of destination if extension is present to make it invalid.
1218 		int dstY1 = has_NV_framebuffer_blit ? 63 : 64;
1219 		gl.blitFramebuffer(0,	 /* srcX0 */
1220 						   0,	 /* srcY0 */
1221 						   64,	/* srcX1 */
1222 						   64,	/* srcY1 */
1223 						   0,	 /* dstX0 */
1224 						   0,	 /* dstY0 */
1225 						   64,	/* dstX1 */
1226 						   dstY1, /* dstY1 */
1227 						   GL_COLOR_BUFFER_BIT, filter);
1228 
1229 		/* Verify GL_INVALID_OPERATION was returned */
1230 		glw::GLenum error_code = gl.getError();
1231 
1232 		if (error_code != GL_INVALID_OPERATION)
1233 		{
1234 			m_testCtx.getLog() << tcu::TestLog::Message << "Invalid glBlitFramebuffer() call for filter argument ["
1235 							   << filter << "]"
1236 											"should have generated a GL_INVALID_OPERATION error. Instead, "
1237 											"["
1238 							   << error_code << "] error was reported." << tcu::TestLog::EndMessage;
1239 
1240 			TCU_FAIL("GL_INVALID_OPERATION was not returned by invalid glBlitFramebuffer() call.");
1241 		}
1242 	} /* for (all valid filter argument values) */
1243 
1244 	/* All done */
1245 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1246 
1247 	return STOP;
1248 }
1249 
1250 /** Constructor.
1251  *
1252  *  @param context Rendering context handle.
1253  **/
1254 MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest::
MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest(Context & context)1255 	MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest(Context& context)
1256 	: TestCase(context, "verify_sample_masking_for_non_integer_color_renderable_internalformats",
1257 			   "Verifies sample masking mechanism for non-integer color-renderable "
1258 			   "internalformats used for 2D multisample textures")
1259 	, bo_id(0)
1260 	, fbo_id(0)
1261 	, fs_draw_id(0)
1262 	, po_draw_id(0)
1263 	, po_verify_id(0)
1264 	, tfo_id(0)
1265 	, to_2d_multisample_id(0)
1266 	, vs_draw_id(0)
1267 	, vs_verify_id(0)
1268 {
1269 	/* Left blank on purpose */
1270 }
1271 
1272 /** Deinitializes ES objects created during test execution */
deinit()1273 void MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest::deinit()
1274 {
1275 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1276 
1277 	/* Unset used program */
1278 	gl.useProgram(0);
1279 
1280 	/* Unbind transform feedback object bound to GL_TRANSFORM_FEEDBACK target */
1281 	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
1282 
1283 	/* Unbind buffer object bound to GL_TRANSFORM_FEEDBACK_BUFFER target */
1284 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
1285 
1286 	/* Unbind framebuffer object bound to GL_DRAW_FRAMEBUFFER target */
1287 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1288 
1289 	/* Unbind texture object bound to GL_TEXTURE_2D_MULTISAMPLE texture target */
1290 	gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
1291 
1292 	/* Delete a 2D multisample texture object of id to_2d_multisample_id */
1293 	if (to_2d_multisample_id != 0)
1294 	{
1295 		gl.deleteTextures(1, &to_2d_multisample_id);
1296 
1297 		to_2d_multisample_id = 0;
1298 	}
1299 
1300 	/* Delete a buffer object of id bo_id */
1301 	if (bo_id != 0)
1302 	{
1303 		gl.deleteBuffers(1, &bo_id);
1304 
1305 		bo_id = 0;
1306 	}
1307 
1308 	/* Delete a framebuffer object of id fbo_id */
1309 	if (fbo_id != 0)
1310 	{
1311 		gl.deleteFramebuffers(1, &fbo_id);
1312 
1313 		fbo_id = 0;
1314 	}
1315 
1316 	/* Delete a transform feedback object of id tfo_id */
1317 	if (tfo_id != 0)
1318 	{
1319 		gl.deleteTransformFeedbacks(1, &tfo_id);
1320 
1321 		tfo_id = 0;
1322 	}
1323 
1324 	/* Delete fs_draw_id shader */
1325 	if (fs_draw_id != 0)
1326 	{
1327 		gl.deleteShader(fs_draw_id);
1328 
1329 		fs_draw_id = 0;
1330 	}
1331 
1332 	/* Delete vs_verify_id shader */
1333 	if (vs_verify_id != 0)
1334 	{
1335 		gl.deleteShader(vs_verify_id);
1336 
1337 		vs_verify_id = 0;
1338 	}
1339 
1340 	/* Delete vs_draw_id shader */
1341 	if (vs_draw_id != 0)
1342 	{
1343 		gl.deleteShader(vs_draw_id);
1344 
1345 		vs_draw_id = 0;
1346 	}
1347 
1348 	/* Delete program objects po_verify_id */
1349 	if (po_verify_id != 0)
1350 	{
1351 		gl.deleteProgram(po_verify_id);
1352 
1353 		po_verify_id = 0;
1354 	}
1355 
1356 	/* Delete program objects po_draw_id */
1357 	if (po_draw_id != 0)
1358 	{
1359 		gl.deleteProgram(po_draw_id);
1360 
1361 		po_draw_id = 0;
1362 	}
1363 
1364 	/* Call base class' deinit() */
1365 	TestCase::deinit();
1366 }
1367 
1368 /** Initializes test-specific ES objects */
initInternals()1369 void MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest::initInternals()
1370 {
1371 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1372 
1373 	/* Generate a 2D multisample texture object of id to_2d_multisample_id */
1374 	gl.genTextures(1, &to_2d_multisample_id);
1375 
1376 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
1377 
1378 	if (to_2d_multisample_id == 0)
1379 	{
1380 		TCU_FAIL("Texture object has not been generated properly");
1381 	}
1382 
1383 	/* Generate a buffer object of id bo_id */
1384 	gl.genBuffers(1, &bo_id);
1385 
1386 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed");
1387 
1388 	if (bo_id == 0)
1389 	{
1390 		TCU_FAIL("Buffer object has not been generated properly");
1391 	}
1392 
1393 	/* Generate a framebuffer object of id fbo_id */
1394 	gl.genFramebuffers(1, &fbo_id);
1395 
1396 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed");
1397 
1398 	if (fbo_id == 0)
1399 	{
1400 		TCU_FAIL("Framebuffer object has not been generated properly");
1401 	}
1402 
1403 	/* Generate a transform feedback object of id tfo_id */
1404 	gl.genTransformFeedbacks(1, &tfo_id);
1405 
1406 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks() call failed");
1407 
1408 	if (tfo_id == 0)
1409 	{
1410 		TCU_FAIL("Transform feedback object has not been generated properly");
1411 	}
1412 
1413 	/* Create a vertex shader vs_draw_id */
1414 	vs_draw_id = gl.createShader(GL_VERTEX_SHADER);
1415 
1416 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed for vs_draw_id");
1417 
1418 	/* Create a vertex shader vs_verify_id */
1419 	vs_verify_id = gl.createShader(GL_VERTEX_SHADER);
1420 
1421 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed for vs_verify_id");
1422 
1423 	/* Create a fragment shader fs_draw_id */
1424 	fs_draw_id = gl.createShader(GL_FRAGMENT_SHADER);
1425 
1426 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed for fs_draw_id");
1427 
1428 	/* Create program objects po_draw_id */
1429 	po_draw_id = gl.createProgram();
1430 
1431 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed for po_draw_id");
1432 
1433 	/* Create program objects po_verify_id */
1434 	po_verify_id = gl.createProgram();
1435 
1436 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed for po_verify_id");
1437 }
1438 
1439 /** Executes test iteration.
1440  *
1441  *  @return Always STOP.
1442  */
1443 tcu::TestNode::IterateResult MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest::
iterate()1444 	iterate()
1445 {
1446 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1447 
1448 	initInternals();
1449 
1450 	/* Constants */
1451 	const glw::GLfloat epsilon		  = 1e-5f;
1452 	const glw::GLfloat expected_value = 1.0f;
1453 	const glw::GLchar* fs_draw_body   = "#version 310 es\n"
1454 									  "\n"
1455 									  "precision highp float;\n"
1456 									  "\n"
1457 									  "out vec4 out_color;\n"
1458 									  "\n"
1459 									  "void main()\n"
1460 									  "{\n"
1461 									  "    out_color = vec4(1, 1, 1, 1);\n"
1462 									  "}\n";
1463 
1464 	const glw::GLchar* vs_draw_body = "#version 310 es\n"
1465 									  "\n"
1466 									  "precision highp float;\n"
1467 									  "\n"
1468 									  "void main()\n"
1469 									  "{\n"
1470 									  "    switch (gl_VertexID)\n"
1471 									  "    {\n"
1472 									  "        case 0: gl_Position = vec4(-1,  1, 0, 1); break;\n"
1473 									  "        case 1: gl_Position = vec4( 1,  1, 0, 1); break;\n"
1474 									  "        case 2: gl_Position = vec4( 1, -1, 0, 1); break;\n"
1475 									  "        case 3: gl_Position = vec4(-1, -1, 0, 1); break;\n"
1476 									  "    }\n"
1477 									  "}\n";
1478 
1479 	const glw::GLchar* vs_verify_body = "#version 310 es\n"
1480 										"\n"
1481 										"precision highp float;\n"
1482 										"\n"
1483 										"uniform uint              n_bit_on;\n"
1484 										"uniform uint              n_bits;\n"
1485 										"uniform highp sampler2DMS sampler;\n"
1486 										"\n"
1487 										"out float result;\n"
1488 										"\n"
1489 										"void main()\n"
1490 										"{\n"
1491 										"    vec4 one  = vec4(1);\n"
1492 										"    vec4 zero = vec4(0.0, 0.0, 0.0, 1.0);\n"
1493 										"\n"
1494 										"    result = 1.0;\n"
1495 										"\n"
1496 										"    for (uint n_current_bit = 0u; n_current_bit < n_bits; n_current_bit++)\n"
1497 										"    {\n"
1498 										"        vec4 value = texelFetch(sampler, ivec2(0), int(n_current_bit));\n"
1499 										"\n"
1500 										"        if (n_bit_on == n_current_bit)\n"
1501 										"        {\n"
1502 										"            if (any(notEqual(value, one)))\n"
1503 										"            {\n"
1504 										"                result = 0.1 + float(n_current_bit)/1000.0;\n"
1505 										"                break;\n"
1506 										"            }\n"
1507 										"        }\n"
1508 										"        else\n"
1509 										"        {\n"
1510 										"            if (any(notEqual(value, zero)))\n"
1511 										"            {\n"
1512 										"                result = 0.2 + float(n_current_bit)/1000.0;\n"
1513 										"                break;\n"
1514 										"            }\n"
1515 										"        }\n"
1516 										"    }\n"
1517 										"}\n";
1518 
1519 	/* Configure the vertex shader vs_draw_id */
1520 	compileShader(vs_draw_id, vs_draw_body);
1521 
1522 	/* Configure the vertex shader vs_verify_id */
1523 	compileShader(vs_verify_id, vs_verify_body);
1524 
1525 	/* Configure the fragment shader fs_draw_id */
1526 	compileShader(fs_draw_id, fs_draw_body);
1527 
1528 	/* Attach the shaders vs_draw_id and fs_draw_id to program object po_draw_id */
1529 	gl.attachShader(po_draw_id, vs_draw_id);
1530 	gl.attachShader(po_draw_id, fs_draw_id);
1531 
1532 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure po_draw_id program object");
1533 
1534 	/* Attach the shaders vs_verify_id and fs_draw_id to program object po_verify_id */
1535 	gl.attachShader(po_verify_id, vs_verify_id);
1536 	gl.attachShader(po_verify_id, fs_draw_id);
1537 
1538 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure po_verify_id program object");
1539 
1540 	/* Configure vs_verify_id for transform feedback - our varying of choice is result and we're happy to use either of the TF modes since we'll be outputting a single float anyway. */
1541 	const glw::GLchar* vs_verify_varying_name = "result";
1542 
1543 	gl.transformFeedbackVaryings(po_verify_id, 1, &vs_verify_varying_name, GL_SEPARATE_ATTRIBS);
1544 
1545 	/* Link the program objects po_draw_id */
1546 	linkProgram(po_draw_id);
1547 
1548 	/* Link the program objects po_verify_id */
1549 	linkProgram(po_verify_id);
1550 
1551 	/* Retrieve uniform locations */
1552 	glw::GLuint n_bits_location   = gl.getUniformLocation(po_verify_id, "n_bits");
1553 	glw::GLuint n_bit_on_location = gl.getUniformLocation(po_verify_id, "n_bit_on");
1554 
1555 	/* Bind the to_2d_multisample_id texture object to GL_TEXTURE_2D_MULTISAMPLE texture target */
1556 	gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id);
1557 
1558 	/* Bind the fbo_id framebuffer object to GL_DRAW_FRAMEBUFFER target */
1559 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id);
1560 
1561 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a framebuffer object");
1562 
1563 	/* Bind the bo_id buffer object to GL_TRANSFORM_FEEDBACK_BUFFER generic target */
1564 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, bo_id);
1565 
1566 	/* Bind the tfo_id transform feedback object go GL_TRANSFORM_FEEDBACK target */
1567 	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfo_id);
1568 
1569 	/* Bind the bo_id buffer object to zeroth binding point of GL_TRANSFORM_FEEDBACK_BUFFER */
1570 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, bo_id);
1571 
1572 	/* Initialize buffer object's storage to hold a total of 4 bytes (sizeof(float) );*/
1573 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(glw::GLfloat), NULL, GL_STATIC_DRAW);
1574 
1575 	/* Attach the 2D multisample texture object to the framebuffer object's zeroth color attachment */
1576 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id,
1577 							0); /* level */
1578 
1579 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up zeroth color attachment");
1580 
1581 	/* Enable GL_SAMPLE_MASK mode */
1582 	gl.enable(GL_SAMPLE_MASK);
1583 
1584 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_SAMPLE_MASK) call generated an unexpected error");
1585 
1586 	/* Color-renderable internalformats to test, note that GL_R8 will not work since sampling from
1587 	 * such format will never return {1,1,1,1} or {0,0,0,1} which current shader uses for sample validation */
1588 	const glw::GLenum internalformat_list[]		= { GL_RGBA8, GL_RGB565, GL_SRGB8_ALPHA8 };
1589 	const int		  internalformat_list_count = sizeof(internalformat_list) / sizeof(internalformat_list[0]);
1590 
1591 	/* Get GL_MAX_SAMPLES value */
1592 	glw::GLint gl_max_samples_value = 0;
1593 
1594 	gl.getIntegerv(GL_MAX_SAMPLES, &gl_max_samples_value);
1595 
1596 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to retrieve GL_MAX_SAMPLES value");
1597 
1598 	if (gl_max_samples_value > 32)
1599 	{
1600 		m_testCtx.getLog() << tcu::TestLog::Message << "The test case checks only first 32 samples out of "
1601 						   << gl_max_samples_value << " reported by GL_MAX_SAMPLES." << tcu::TestLog::EndMessage;
1602 	}
1603 
1604 	/* Work with no more than 32 bits of mask's first word */
1605 	const glw::GLint mask_bits_to_check = de::min(gl_max_samples_value, 32);
1606 
1607 	/* Keep the results but continue running all cases */
1608 	bool test_fail = false;
1609 
1610 	/* Iterate through all internal formats test case should check */
1611 	for (int internalformat_index = 0; internalformat_index < internalformat_list_count; internalformat_index++)
1612 	{
1613 		/* Configure the texture object storage */
1614 		gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, mask_bits_to_check, /* samples */
1615 								   internalformat_list[internalformat_index], 1,  /* width */
1616 								   1,											  /* height */
1617 								   GL_TRUE);									  /* fixedsamplelocations */
1618 
1619 		/* Make sure no errors were reported. The framebuffer should be considered complete at this moment. */
1620 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() call failed");
1621 
1622 		/* Following code does not affect test method. Just checks if FBO is complete
1623 		 To catch errors earlier */
1624 
1625 		glw::GLenum fbo_completeness_status = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
1626 
1627 		if (fbo_completeness_status != GL_FRAMEBUFFER_COMPLETE)
1628 		{
1629 			m_testCtx.getLog() << tcu::TestLog::Message
1630 							   << "Draw FBO completeness status is: " << fbo_completeness_status
1631 							   << ", expected: GL_FRAMEBUFFER_COMPLETE" << tcu::TestLog::EndMessage;
1632 
1633 			TCU_FAIL("Draw FBO is considered incomplete which is invalid");
1634 		}
1635 
1636 		/* For all values of n_bit from range <0, GL_MAX_SAMPLES pname value) */
1637 		for (int n_bit = 0; n_bit < mask_bits_to_check; n_bit++)
1638 		{
1639 
1640 			/* We need to clear render buffer, otherwise masked samples will have undefined values */
1641 			glw::GLfloat clear_color_src[] = { 0.0f, 0.0f, 0.0f, 1.0f };
1642 
1643 			gl.clearBufferfv(GL_COLOR, 0, clear_color_src);
1644 			GLU_EXPECT_NO_ERROR(gl.getError(), "clearBufferfv() call failed");
1645 
1646 			/* Use program object po_draw_id */
1647 			gl.useProgram(po_draw_id);
1648 
1649 			/* Configure sample mask to only render n_bit-th sample using glSampleMaski() function */
1650 			gl.sampleMaski(0, 1 << n_bit);
1651 
1652 			/* Draw a triangle fan of 4 vertices. This fills to_2d_id with multisampled data.
1653 			 * However, due to active GL_SAMPLE_MASK and the way we configured it, only one sample should have been rendered.
1654 			 * The only way we can check if this is the case is by using a special shader,
1655 			 * because we have no way of downloading multisampled data to process space in ES3.0+.
1656 			 */
1657 			gl.drawArrays(GL_TRIANGLE_FAN, 0, /* first */
1658 						  4 /* count */);
1659 
1660 			/* Unbind fbo_id before sourcing from the texture attached to it */
1661 			gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1662 
1663 			/* Enable GL_RASTERIZER_DISCARD mode */
1664 			gl.enable(GL_RASTERIZER_DISCARD);
1665 			{
1666 				/* Use program object po_verify_id */
1667 				gl.useProgram(po_verify_id);
1668 
1669 				/* Specify input arguments for vertex shader */
1670 				gl.uniform1ui(n_bits_location, mask_bits_to_check);
1671 				gl.uniform1ui(n_bit_on_location, n_bit);
1672 
1673 				/* Bind to_2d_multisample_id to GL_TEXTURE_2D_MULTISAMPLE texture target. Current texture unit is GL_TEXTURE0 */
1674 				gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id);
1675 
1676 				/* Begin transform feedback (primitiveMode: GL_POINTS) */
1677 				gl.beginTransformFeedback(GL_POINTS);
1678 				{
1679 					/* Draw a single point. This will fill our transform feedback buffer with result */
1680 					gl.drawArrays(GL_POINTS, 0, 1);
1681 				}
1682 				/* End transform feedback */
1683 				gl.endTransformFeedback();
1684 			}
1685 			/* Disable GL_RASTERIZER_DISCARD mode */
1686 			gl.disable(GL_RASTERIZER_DISCARD);
1687 
1688 			/* Make sure no errors were generated */
1689 			GLU_EXPECT_NO_ERROR(gl.getError(), "Transform feedback failed");
1690 
1691 			/* Rebind the fbo_id framebuffer object to GL_DRAW_FRAMEBUFFER target */
1692 			gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id);
1693 
1694 			/* Map buffer object bo_id's contents to user-space */
1695 			const glw::GLfloat* mapped_bo =
1696 				(glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 4, GL_MAP_READ_BIT);
1697 
1698 			GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed");
1699 
1700 			/* Copy result from buffer */
1701 			glw::GLfloat result = *mapped_bo;
1702 
1703 			/* Unmap the buffer object */
1704 			gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
1705 
1706 			GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed");
1707 
1708 			/* Verify the value stored by verification program is not 0. If it is 0, the test has failed. */
1709 			if (de::abs(result - expected_value) > epsilon)
1710 			{
1711 				m_testCtx.getLog() << tcu::TestLog::Message << "Unexpected value stored by verification program: ["
1712 								   << result << "],"
1713 								   << "Format index: " << internalformat_index << ", "
1714 								   << "Bit to check: [" << n_bit << "." << tcu::TestLog::EndMessage;
1715 				/* Notice test failure */
1716 				test_fail = true;
1717 			}
1718 		}
1719 
1720 		/* Delete the 2D multisample texture object with glDeleteTextures() call and re-bind the object to a GL_TEXTURE_2D_MULTISAMPLE texture target with a glBindTexture() call */
1721 		gl.deleteTextures(1, &to_2d_multisample_id);
1722 
1723 		to_2d_multisample_id = 0;
1724 
1725 		/* Recreate to_2d_multisample_id texture object. */
1726 		/* Generate a 2D multisample texture object of id to_2d_multisample_id */
1727 		gl.genTextures(1, &to_2d_multisample_id);
1728 
1729 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
1730 
1731 		if (to_2d_multisample_id == 0)
1732 		{
1733 			TCU_FAIL("Texture object has not been generated properly");
1734 		}
1735 
1736 		/* Bind the to_2d_id texture object to GL_TEXTURE_2D_MULTISAMPLE texture target */
1737 		gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id);
1738 
1739 		/* Attach the 2D multisample texture object to the framebuffer object's zeroth color attachment */
1740 		gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1741 								to_2d_multisample_id, 0); /* level */
1742 
1743 		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up zeroth color attachment");
1744 	}
1745 
1746 	if (test_fail)
1747 	{
1748 		TCU_FAIL("Value stored by verification program is not 1.0. Test has failed.");
1749 	}
1750 
1751 	/* Test case passed */
1752 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1753 
1754 	return STOP;
1755 }
1756 
1757 /** Links a program object. Shaders should be attached to program id before call.
1758  *  If an error reported throws an exception.
1759  *
1760  *  @param id Program id
1761  */
linkProgram(glw::GLuint id)1762 void MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest::linkProgram(glw::GLuint id)
1763 {
1764 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1765 
1766 	/* Link the test program object */
1767 	glw::GLint link_status = GL_FALSE;
1768 
1769 	gl.linkProgram(id);
1770 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed");
1771 
1772 	gl.getProgramiv(id, GL_LINK_STATUS, &link_status);
1773 
1774 	if (link_status != GL_TRUE)
1775 	{
1776 		TCU_FAIL("Program linking failed");
1777 	}
1778 }
1779 
1780 /** Compiles the shader. Should the shader not compile, a TestError exception will be thrown.
1781  *
1782  *  @param id     Generated shader id
1783  *  @param source NULL-terminated shader source code string
1784  */
compileShader(glw::GLuint id,const glw::GLchar * source)1785 void MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest::compileShader(
1786 	glw::GLuint id, const glw::GLchar* source)
1787 {
1788 	glw::GLint			  compile_status = GL_FALSE;
1789 	const glw::Functions& gl			 = m_context.getRenderContext().getFunctions();
1790 
1791 	gl.shaderSource(id, 1, &source, NULL);
1792 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
1793 
1794 	gl.compileShader(id);
1795 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
1796 
1797 	gl.getShaderiv(id, GL_COMPILE_STATUS, &compile_status);
1798 
1799 	if (compile_status != GL_TRUE)
1800 	{
1801 		/* Retrieve adn dump compliation fail reason */
1802 		char		 infoLog[1024];
1803 		glw::GLsizei length = 0;
1804 
1805 		gl.getShaderInfoLog(id, 1024, &length, infoLog);
1806 
1807 		m_testCtx.getLog() << tcu::TestLog::Message << "Shader compilation failed, shader id=" << id
1808 						   << ", infoLog: " << infoLog << tcu::TestLog::EndMessage;
1809 
1810 		TCU_FAIL("Shader compilation failed");
1811 	}
1812 }
1813 
1814 /** Constructor.
1815  *
1816  *  @param context Rendering context handle.
1817  **/
MultisampleTextureFunctionalTestsSampleMaskingTexturesTest(Context & context)1818 MultisampleTextureFunctionalTestsSampleMaskingTexturesTest::MultisampleTextureFunctionalTestsSampleMaskingTexturesTest(
1819 	Context& context)
1820 	: TestCase(context, "verify_sample_masking_textures",
1821 			   "Verifies sample masking mechanism for non-integer, integer/unsigned, "
1822 			   "integer/signed color-renderable internalformats and "
1823 			   "depth-renderable internalformats. All internalformats "
1824 			   "are used for 2D multisample textures.")
1825 	, bo_id(0)
1826 	, fbo_id(0)
1827 	, fs_draw_id(0)
1828 	, po_draw_id(0)
1829 	, po_verify_id(0)
1830 	, tfo_id(0)
1831 	, to_2d_multisample_id(0)
1832 	, vs_draw_id(0)
1833 	, vs_verify_id(0)
1834 {
1835 	/* Left blank on purpose */
1836 }
1837 
1838 /** Deinitializes ES objects created during test execution */
deinit()1839 void MultisampleTextureFunctionalTestsSampleMaskingTexturesTest::deinit()
1840 {
1841 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1842 
1843 	/* Unset used program */
1844 	gl.useProgram(0);
1845 
1846 	/* Unbind transform feedback object bound to GL_TRANSFORM_FEEDBACK target */
1847 	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
1848 
1849 	/* Unbind buffer object bound to GL_TRANSFORM_FEEDBACK_BUFFER target */
1850 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
1851 
1852 	/* Unbind framebuffer object bound to GL_DRAW_FRAMEBUFFER target */
1853 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1854 
1855 	/* Unbind texture object bound to GL_TEXTURE_2D_MULTISAMPLE texture target */
1856 	gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
1857 
1858 	/* Delete a 2D multisample texture object of id to_2d_multisample_id */
1859 	if (to_2d_multisample_id != 0)
1860 	{
1861 		gl.deleteTextures(1, &to_2d_multisample_id);
1862 
1863 		to_2d_multisample_id = 0;
1864 	}
1865 
1866 	/* Delete a buffer object of id bo_id */
1867 	if (bo_id != 0)
1868 	{
1869 		gl.deleteBuffers(1, &bo_id);
1870 
1871 		bo_id = 0;
1872 	}
1873 
1874 	/* Delete a framebuffer object of id fbo_id */
1875 	if (fbo_id != 0)
1876 	{
1877 		gl.deleteFramebuffers(1, &fbo_id);
1878 
1879 		fbo_id = 0;
1880 	}
1881 
1882 	/* Delete a transform feedback object of id tfo_id */
1883 	if (tfo_id != 0)
1884 	{
1885 		gl.deleteTransformFeedbacks(1, &tfo_id);
1886 
1887 		tfo_id = 0;
1888 	}
1889 
1890 	/* Delete fs_draw_id shader */
1891 	if (fs_draw_id != 0)
1892 	{
1893 		gl.deleteShader(fs_draw_id);
1894 
1895 		fs_draw_id = 0;
1896 	}
1897 
1898 	/* Delete vs_verify_id shader */
1899 	if (vs_verify_id != 0)
1900 	{
1901 		gl.deleteShader(vs_verify_id);
1902 
1903 		vs_verify_id = 0;
1904 	}
1905 
1906 	/* Delete vs_draw_id shader */
1907 	if (vs_draw_id != 0)
1908 	{
1909 		gl.deleteShader(vs_draw_id);
1910 
1911 		vs_draw_id = 0;
1912 	}
1913 
1914 	/* Delete program objects po_verify_id */
1915 	if (po_verify_id != 0)
1916 	{
1917 		gl.deleteProgram(po_verify_id);
1918 
1919 		po_verify_id = 0;
1920 	}
1921 
1922 	/* Delete program objects po_draw_id */
1923 	if (po_draw_id != 0)
1924 	{
1925 		gl.deleteProgram(po_draw_id);
1926 
1927 		po_draw_id = 0;
1928 	}
1929 
1930 	/* Call base class' deinit() */
1931 	TestCase::deinit();
1932 }
1933 
1934 /** Initializes test-specific ES objects */
initInternals()1935 void MultisampleTextureFunctionalTestsSampleMaskingTexturesTest::initInternals()
1936 {
1937 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1938 
1939 	/* Generate a 2D multisample texture object of id to_2d_multisample_id */
1940 	gl.genTextures(1, &to_2d_multisample_id);
1941 
1942 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
1943 
1944 	if (to_2d_multisample_id == 0)
1945 	{
1946 		TCU_FAIL("Texture object has not been generated properly");
1947 	}
1948 
1949 	/* Generate a buffer object of id bo_id */
1950 	gl.genBuffers(1, &bo_id);
1951 
1952 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed");
1953 
1954 	if (bo_id == 0)
1955 	{
1956 		TCU_FAIL("Buffer object has not been generated properly");
1957 	}
1958 
1959 	/* Generate a framebuffer object of id fbo_id */
1960 	gl.genFramebuffers(1, &fbo_id);
1961 
1962 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed");
1963 
1964 	if (fbo_id == 0)
1965 	{
1966 		TCU_FAIL("Framebuffer object has not been generated properly");
1967 	}
1968 
1969 	/* Generate a transform feedback object of id tfo_id */
1970 	gl.genTransformFeedbacks(1, &tfo_id);
1971 
1972 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks() call failed");
1973 
1974 	if (tfo_id == 0)
1975 	{
1976 		TCU_FAIL("Transform feedback object has not been generated properly");
1977 	}
1978 
1979 	/* Create a vertex shader vs_draw_id */
1980 	vs_draw_id = gl.createShader(GL_VERTEX_SHADER);
1981 
1982 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed for vs_draw_id");
1983 
1984 	/* Create a vertex shader vs_verify_id */
1985 	vs_verify_id = gl.createShader(GL_VERTEX_SHADER);
1986 
1987 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed for vs_verify_id");
1988 
1989 	/* Create a fragment shader fs_draw_id */
1990 	fs_draw_id = gl.createShader(GL_FRAGMENT_SHADER);
1991 
1992 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed for fs_draw_id");
1993 
1994 	/* Create program objects po_draw_id */
1995 	po_draw_id = gl.createProgram();
1996 
1997 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed for po_draw_id");
1998 
1999 	/* Create program objects po_verify_id */
2000 	po_verify_id = gl.createProgram();
2001 
2002 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed for po_verify_id");
2003 }
2004 
2005 /** Executes test iteration.
2006  *
2007  *  @return Always STOP.
2008  */
iterate()2009 tcu::TestNode::IterateResult MultisampleTextureFunctionalTestsSampleMaskingTexturesTest::iterate()
2010 {
2011 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2012 
2013 	initInternals();
2014 
2015 	/* Constants */
2016 	const glw::GLfloat epsilon		= 1e-5f;
2017 	const glw::GLchar* fs_draw_body = "#version 310 es\n"
2018 									  "\n"
2019 									  "out vec4 out_color;\n"
2020 									  "\n"
2021 									  "void main()\n"
2022 									  "{\n"
2023 									  "    out_color = vec4(1, 1, 1, 1);\n"
2024 									  "}\n";
2025 
2026 	const glw::GLchar* vs_draw_body = "#version 310 es\n"
2027 									  "\n"
2028 									  "void main()\n"
2029 									  "{\n"
2030 									  "    switch (gl_VertexID)\n"
2031 									  "    {\n"
2032 									  "        case 0: gl_Position = vec4(-1,  1, 0, 1); break;\n"
2033 									  "        case 1: gl_Position = vec4( 1,  1, 0, 1); break;\n"
2034 									  "        case 2: gl_Position = vec4( 1, -1, 0, 1); break;\n"
2035 									  "        case 3: gl_Position = vec4(-1, -1, 0, 1); break;\n"
2036 									  "    }\n"
2037 									  "}\n";
2038 
2039 	const glw::GLchar* vs_verify_body = "#version 310 es\n"
2040 										"\n"
2041 										"precision highp float;\n"
2042 										"\n"
2043 										"uniform uint              n_bit_on;\n"
2044 										"uniform uint              n_bits;\n"
2045 										"uniform highp sampler2DMS sampler;\n"
2046 										"\n"
2047 										"out float result;\n"
2048 										"\n"
2049 										"void main()\n"
2050 										"{\n"
2051 										"    vec4 one  = vec4(1);\n"
2052 										"    vec4 zero = vec4(0);\n"
2053 										"\n"
2054 										"    result = 1.0;\n"
2055 										"\n"
2056 										"    for (uint n_current_bit = 0u; n_current_bit < n_bits; n_current_bit++)\n"
2057 										"    {\n"
2058 										"        vec4 value = texelFetch(sampler, ivec2(0), int(n_current_bit));\n"
2059 										"\n"
2060 										"        if (n_bit_on == n_current_bit)\n"
2061 										"        {\n"
2062 										"            if (any(notEqual(value, one)))\n"
2063 										"            {\n"
2064 										"                result = 0.0;\n"
2065 										"            }\n"
2066 										"        }\n"
2067 										"        else\n"
2068 										"        {\n"
2069 										"            if (any(notEqual(value, zero)))\n"
2070 										"            {\n"
2071 										"                result = 0.0;\n"
2072 										"            }\n"
2073 										"        }\n"
2074 										"    }\n"
2075 										"}\n";
2076 
2077 	/* Configure the vertex shader vs_draw_id */
2078 	compileShader(vs_draw_id, vs_draw_body);
2079 
2080 	/* Configure the vertex shader vs_verify_id */
2081 	compileShader(vs_verify_id, vs_verify_body);
2082 
2083 	/* Configure the fragment shader fs_draw_id */
2084 	compileShader(fs_draw_id, fs_draw_body);
2085 
2086 	/* Attach the shaders vs_draw_id and fs_draw_id to program object po_draw_id */
2087 	gl.attachShader(po_draw_id, vs_draw_id);
2088 	gl.attachShader(po_draw_id, fs_draw_id);
2089 
2090 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure po_draw_id program object");
2091 
2092 	/* Attach the shaders vs_verify_id and fs_draw_id to program object po_verify_id */
2093 	gl.attachShader(po_verify_id, vs_verify_id);
2094 	gl.attachShader(po_verify_id, fs_draw_id);
2095 
2096 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure po_verify_id program object");
2097 
2098 	/* Configure vs_verify_id for transform feedback - our varying of choice is result and we're happy to use either of the TF modes since we'll be outputting a single float anyway. */
2099 	const glw::GLchar* vs_verify_varying_name = "result";
2100 
2101 	gl.transformFeedbackVaryings(po_verify_id, 1, &vs_verify_varying_name, GL_SEPARATE_ATTRIBS);
2102 
2103 	/* Link the program objects po_draw_id */
2104 	linkProgram(po_draw_id);
2105 
2106 	/* Link the program objects po_verify_id */
2107 	linkProgram(po_verify_id);
2108 
2109 	/* Retrieve uniform locations */
2110 	glw::GLuint n_bits_location   = gl.getUniformLocation(po_verify_id, "n_bits");
2111 	glw::GLuint n_bit_on_location = gl.getUniformLocation(po_verify_id, "n_bit_on");
2112 
2113 	/* Bind the to_2d_multisample_id texture object to GL_TEXTURE_2D_MULTISAMPLE texture target */
2114 	gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id);
2115 
2116 	/* Bind the fbo_id framebuffer object to GL_DRAW_FRAMEBUFFER target */
2117 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id);
2118 
2119 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a framebuffer object");
2120 
2121 	/* Bind the bo_id buffer object to GL_TRANSFORM_FEEDBACK_BUFFER generic target */
2122 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, bo_id);
2123 
2124 	/* Bind the bo_id buffer object to zeroth binding point of GL_TRANSFORM_FEEDBACK_BUFFER */
2125 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, bo_id);
2126 
2127 	/* Bind the tfo_id transform feedback object go GL_TRANSFORM_FEEDBACK target */
2128 	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfo_id);
2129 
2130 	/* Initialize buffer object's storage to hold a total of 4 bytes (sizeof(float) );*/
2131 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(glw::GLfloat), NULL, GL_STATIC_DRAW);
2132 
2133 	/* Attach the 2D multisample texture object to the framebuffer object's zeroth color attachment */
2134 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id,
2135 							0); /* level */
2136 
2137 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up zeroth color attachment");
2138 
2139 	/* Enable GL_SAMPLE_MASK mode */
2140 	gl.enable(GL_SAMPLE_MASK);
2141 
2142 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_SAMPLE_MASK) call generated an unexpected error");
2143 
2144 	/* Iterate through color-normalized-, color-unsigned-integer-, color-signed-integer- and depth-renderable internalformats */
2145 	const glw::GLenum  normalized_color_internalformats[] = { GL_R8, GL_RGB565, GL_SRGB8_ALPHA8 };
2146 	const glw::GLenum  unsigned_color_internalformats[]   = { GL_RGBA32UI, GL_RG16UI };
2147 	const glw::GLenum  signed_color_internalformats[]	 = { GL_RGBA32I, GL_RG16I };
2148 	const glw::GLenum  depth_internalformats[]			  = { GL_DEPTH_COMPONENT32F };
2149 	const unsigned int n_normalized_color_internalformats =
2150 		sizeof(normalized_color_internalformats) / sizeof(normalized_color_internalformats[0]);
2151 	const unsigned int n_unsigned_color_internalformats =
2152 		sizeof(unsigned_color_internalformats) / sizeof(unsigned_color_internalformats[0]);
2153 	const unsigned int n_signed_color_internalformats =
2154 		sizeof(signed_color_internalformats) / sizeof(signed_color_internalformats[0]);
2155 	const unsigned int n_depth_internalformats = sizeof(depth_internalformats) / sizeof(depth_internalformats[0]);
2156 
2157 	for (unsigned int n_iteration = 0; n_iteration < 4 /* normalized/unsigned/signed/depth */; ++n_iteration)
2158 	{
2159 		glw::GLenum		   attachment		 = 0;
2160 		const glw::GLenum* internalformats   = NULL;
2161 		unsigned int	   n_internalformats = 0;
2162 
2163 		switch (n_iteration)
2164 		{
2165 		case 0:
2166 		{
2167 			attachment		  = GL_COLOR_ATTACHMENT0;
2168 			internalformats   = normalized_color_internalformats;
2169 			n_internalformats = n_normalized_color_internalformats;
2170 
2171 			break;
2172 		}
2173 
2174 		case 1:
2175 		{
2176 			attachment		  = GL_COLOR_ATTACHMENT0;
2177 			internalformats   = unsigned_color_internalformats;
2178 			n_internalformats = n_unsigned_color_internalformats;
2179 
2180 			break;
2181 		}
2182 
2183 		case 2:
2184 		{
2185 			attachment		  = GL_COLOR_ATTACHMENT0;
2186 			internalformats   = signed_color_internalformats;
2187 			n_internalformats = n_signed_color_internalformats;
2188 
2189 			break;
2190 		}
2191 
2192 		case 3:
2193 		{
2194 			attachment		  = GL_DEPTH_ATTACHMENT;
2195 			internalformats   = depth_internalformats;
2196 			n_internalformats = n_depth_internalformats;
2197 
2198 			break;
2199 		}
2200 
2201 		default:
2202 		{
2203 			TCU_FAIL("Unrecognized iteration index");
2204 		}
2205 		} /* switch (n_iteration) */
2206 
2207 		/* Iterate through internalformats */
2208 		for (unsigned int n_internalformat = 0; n_internalformat < n_internalformats; ++n_internalformat)
2209 		{
2210 			glw::GLenum internalformat			   = internalformats[n_internalformat];
2211 			glw::GLint  internalformat_max_samples = 0;
2212 
2213 			/* Retrieve internalformat-specific GL_MAX_SAMPLES value */
2214 			gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE,	 /* target */
2215 								   internalformat, GL_SAMPLES, 1, /* bufSize */
2216 								   &internalformat_max_samples);
2217 
2218 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInternalformativ() failed");
2219 
2220 			if (internalformat_max_samples > 32)
2221 			{
2222 				m_testCtx.getLog() << tcu::TestLog::Message << "The test case checks only first 32 samples out of "
2223 								   << internalformat_max_samples
2224 								   << " reported by GL_SAMPLES reported by getInternalformativ() "
2225 								   << "for internalformat " << internalformat << "." << tcu::TestLog::EndMessage;
2226 			}
2227 
2228 			/* Work with no more than 32 bits of mask's first word */
2229 			const glw::GLint mask_bits_to_check = de::min(internalformat_max_samples, 32);
2230 
2231 			/* Recreate to_2d_multisample_id texture object. */
2232 			if (to_2d_multisample_id == 0)
2233 			{
2234 				/* Generate a 2D multisample texture object of id to_2d_multisample_id */
2235 				gl.genTextures(1, &to_2d_multisample_id);
2236 
2237 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
2238 
2239 				if (to_2d_multisample_id == 0)
2240 				{
2241 					TCU_FAIL("Texture object has not been generated properly");
2242 				}
2243 
2244 				/* Bind the to_2d_id texture object to GL_TEXTURE_2D_MULTISAMPLE texture target */
2245 				gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id);
2246 
2247 				/* Attach the 2D multisample texture object to the framebuffer object's attachment */
2248 				gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, GL_TEXTURE_2D_MULTISAMPLE,
2249 										to_2d_multisample_id, 0); /* level */
2250 
2251 				GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up attachment");
2252 			}
2253 
2254 			/* Configure the texture object storage */
2255 			gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, internalformat_max_samples, /* samples */
2256 									   internalformat, 1,									  /* width */
2257 									   1,													  /* height */
2258 									   GL_TRUE);											  /* fixedsamplelocations */
2259 
2260 			/* Make sure no errors were reported. The framebuffer should be considered complete at this moment. */
2261 			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() call failed");
2262 
2263 			/* For all values of n_bit from range <0, GL_MAX_SAMPLES pname value) */
2264 			for (int n_bit = 0; n_bit < mask_bits_to_check; n_bit++)
2265 			{
2266 				/* Use program object po_draw_id */
2267 				gl.useProgram(po_draw_id);
2268 
2269 				/* Configure sample mask to only render n_bit-th sample using glSampleMaski() function */
2270 				gl.sampleMaski(0, 1 << n_bit);
2271 
2272 				/* Draw a triangle fan of 4 vertices. This fills to_2d_id with multisampled data.
2273 				 * However, due to active GL_SAMPLE_MASK and the way we configured it, only one sample should have been rendered.
2274 				 * The only way we can check if this is the case is by using a special shader,
2275 				 * because we have no way of downloading multisampled data to process space in ES3.0+.
2276 				 */
2277 				gl.drawArrays(GL_TRIANGLE_FAN, 0, /* first */
2278 							  4 /* count */);
2279 
2280 				/* Enable GL_RASTERIZER_DISCARD mode */
2281 				gl.enable(GL_RASTERIZER_DISCARD);
2282 				{
2283 					/* Use program object po_verify_id */
2284 					gl.useProgram(po_verify_id);
2285 
2286 					/* Specify input arguments for vertex shader */
2287 					gl.uniform1i(n_bits_location, mask_bits_to_check);
2288 					gl.uniform1i(n_bit_on_location, n_bit);
2289 
2290 					/* Bind to_2d_multisample_id to GL_TEXTURE_2D_MULTISAMPLE texture target. Current texture unit is GL_TEXTURE0 */
2291 					gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id);
2292 
2293 					/* Begin transform feedback (primitiveMode: GL_POINTS) */
2294 					gl.beginTransformFeedback(GL_POINTS);
2295 					{
2296 						/* Draw a single point. This will fill our transform feedback buffer with result */
2297 						gl.drawArrays(GL_POINTS, 0, 1);
2298 					}
2299 					/* End transform feedback */
2300 					gl.endTransformFeedback();
2301 				}
2302 				/* Disable GL_RASTERIZER_DISCARD mode */
2303 				gl.disable(GL_RASTERIZER_DISCARD);
2304 
2305 				/* Make sure no errors were generated */
2306 				GLU_EXPECT_NO_ERROR(gl.getError(), "Transform feedback failed");
2307 
2308 				/* Map buffer object bo_id's contents to user-space */
2309 				const glw::GLfloat* mapped_bo = (glw::GLfloat*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
2310 
2311 				GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed");
2312 
2313 				/* Copy result from buffer */
2314 				glw::GLfloat result = *mapped_bo;
2315 
2316 				/* Unmap the buffer object */
2317 				gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
2318 
2319 				GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed");
2320 
2321 				/* Verify the value stored by verification program is not 0. If it is 0, the test has failed. */
2322 				if (de::abs(result) < epsilon)
2323 				{
2324 					TCU_FAIL("Value stored by verification program is zero. Test has failed.");
2325 				}
2326 			}
2327 
2328 			/* Delete the 2D multisample texture object with glDeleteTextures() call and re-bind the object to a GL_TEXTURE_2D_MULTISAMPLE texture target with a glBindTexture() call */
2329 			gl.deleteTextures(1, &to_2d_multisample_id);
2330 
2331 			to_2d_multisample_id = 0;
2332 		} /* for (all renderable internalformats) */
2333 	}	 /* for (all iterations) */
2334 
2335 	/* Test case passed */
2336 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2337 
2338 	return STOP;
2339 }
2340 
2341 /** Links a program object. Shaders should be attached to program id before call.
2342  *  If an error reported throws an exception.
2343  *
2344  *  @param id Program id
2345  */
linkProgram(glw::GLuint id)2346 void MultisampleTextureFunctionalTestsSampleMaskingTexturesTest::linkProgram(glw::GLuint id)
2347 {
2348 	/* Link the test program object */
2349 	const glw::Functions& gl		  = m_context.getRenderContext().getFunctions();
2350 	glw::GLint			  link_status = GL_FALSE;
2351 
2352 	gl.linkProgram(id);
2353 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed");
2354 
2355 	gl.getProgramiv(id, GL_LINK_STATUS, &link_status);
2356 
2357 	if (link_status != GL_TRUE)
2358 	{
2359 		TCU_FAIL("Program linking failed");
2360 	}
2361 }
2362 
2363 /** Compiles the shader. Should the shader not compile, a TestError exception will be thrown.
2364  *
2365  *  @param id     Generated shader id
2366  *  @param source NULL-terminated shader source code string
2367  */
compileShader(glw::GLuint id,const glw::GLchar * source)2368 void MultisampleTextureFunctionalTestsSampleMaskingTexturesTest::compileShader(glw::GLuint		  id,
2369 																			   const glw::GLchar* source)
2370 {
2371 	glw::GLint			  compile_status = GL_FALSE;
2372 	const glw::Functions& gl			 = m_context.getRenderContext().getFunctions();
2373 
2374 	gl.shaderSource(id, 1, &source, NULL);
2375 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
2376 
2377 	gl.compileShader(id);
2378 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
2379 
2380 	gl.getShaderiv(id, GL_COMPILE_STATUS, &compile_status);
2381 
2382 	if (compile_status != GL_TRUE)
2383 	{
2384 		TCU_FAIL("Shader compilation failed");
2385 	}
2386 }
2387 
2388 /** Constructor.
2389  *
2390  *  @param context CTS context handle.
2391  **/
2392 MultisampleTextureFunctionalTestsTextureSizeFragmentShadersTest::
MultisampleTextureFunctionalTestsTextureSizeFragmentShadersTest(Context & context)2393 	MultisampleTextureFunctionalTestsTextureSizeFragmentShadersTest(Context& context)
2394 	: TestCase(context, "texture_size_in_fragment_shaders",
2395 			   "Verifies textureSize() works for multisample textures when used in fragment shaders")
2396 	, fbo_id(0)
2397 	, fs_id(0)
2398 	, po_id(0)
2399 	, to_2d_multisample_id(0)
2400 	, to_2d_multisample_array_id(0)
2401 	, vs_id(0)
2402 {
2403 	/* Left blank on purpose */
2404 }
2405 
2406 /** Deinitializes ES objects created during test execution */
deinit()2407 void MultisampleTextureFunctionalTestsTextureSizeFragmentShadersTest::deinit()
2408 {
2409 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2410 
2411 	if (fbo_id != 0)
2412 	{
2413 		gl.deleteFramebuffers(1, &fbo_id);
2414 
2415 		fbo_id = 0;
2416 	}
2417 
2418 	if (fs_id != 0)
2419 	{
2420 		gl.deleteShader(fs_id);
2421 
2422 		fs_id = 0;
2423 	}
2424 
2425 	if (po_id != 0)
2426 	{
2427 		gl.deleteProgram(po_id);
2428 
2429 		po_id = 0;
2430 	}
2431 
2432 	if (to_2d_multisample_id != 0)
2433 	{
2434 		gl.deleteTextures(1, &to_2d_multisample_id);
2435 
2436 		to_2d_multisample_id = 0;
2437 	}
2438 
2439 	if (to_2d_multisample_array_id != 0)
2440 	{
2441 		gl.deleteTextures(1, &to_2d_multisample_array_id);
2442 
2443 		to_2d_multisample_array_id = 0;
2444 	}
2445 
2446 	if (vs_id != 0)
2447 	{
2448 		gl.deleteShader(vs_id);
2449 
2450 		vs_id = 0;
2451 	}
2452 
2453 	/* Call base class' deinit() */
2454 	TestCase::deinit();
2455 }
2456 
2457 /** Executes test iteration.
2458  *
2459  *  @return Returns STOP when test has finished executing.
2460  */
iterate()2461 tcu::TestNode::IterateResult MultisampleTextureFunctionalTestsTextureSizeFragmentShadersTest::iterate()
2462 {
2463 	bool are_2d_array_ms_tos_supported =
2464 		m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array");
2465 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2466 
2467 	/* Set up texture objects */
2468 	if (are_2d_array_ms_tos_supported)
2469 	{
2470 		gl.genTextures(1, &to_2d_multisample_array_id);
2471 	}
2472 
2473 	gl.genTextures(1, &to_2d_multisample_id);
2474 
2475 	if (are_2d_array_ms_tos_supported)
2476 	{
2477 		gl.activeTexture(GL_TEXTURE0);
2478 		gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, to_2d_multisample_array_id);
2479 		gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, /* samples */
2480 								   GL_RGBA8, 16,						   /* width */
2481 								   32,									   /* height */
2482 								   8,									   /* depth */
2483 								   GL_TRUE);							   /* fixedsamplelocations */
2484 
2485 		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up 2D multisample array texture storage");
2486 	}
2487 
2488 	gl.activeTexture(GL_TEXTURE1);
2489 	gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id);
2490 	gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */
2491 							   GL_RGBA8, 16,				 /* width */
2492 							   32,							 /* height */
2493 							   GL_TRUE);
2494 
2495 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up 2D multisample texture storage");
2496 
2497 	/* Set up a fragment shader */
2498 	static const char* fs_body =
2499 		"#version 310 es\n"
2500 		"\n"
2501 		"#ifdef GL_OES_texture_storage_multisample_2d_array\n"
2502 		"    #extension GL_OES_texture_storage_multisample_2d_array : enable\n"
2503 		"#endif\n"
2504 		"\n"
2505 		"precision highp float;\n"
2506 		"\n"
2507 		"uniform highp sampler2DMS sampler_2d;\n"
2508 		"\n"
2509 		"#ifdef GL_OES_texture_storage_multisample_2d_array\n"
2510 		"    uniform highp sampler2DMSArray sampler_2d_array;\n"
2511 		"#endif"
2512 		"\n"
2513 		"out vec4 result;\n"
2514 		"\n"
2515 		"void main()\n"
2516 		"{\n"
2517 		"    #ifdef GL_OES_texture_storage_multisample_2d_array\n"
2518 		"        ivec3 sampler_2d_array_size = textureSize(sampler_2d_array);\n"
2519 		"    #else\n"
2520 		"        ivec3 sampler_2d_array_size = ivec3(16, 32, 8);\n"
2521 		"    #endif\n"
2522 		"\n"
2523 		"    ivec2 sampler_2d_size = textureSize(sampler_2d);\n"
2524 		"\n"
2525 		"    if (sampler_2d_size.x       == 16 && sampler_2d_size.y       == 32 &&\n"
2526 		"        sampler_2d_array_size.x == 16 && sampler_2d_array_size.y == 32 && sampler_2d_array_size.z == 8)\n"
2527 		"    {\n"
2528 		"        result = vec4(0, 1, 0, 0);\n"
2529 		"    }\n"
2530 		"    else\n"
2531 		"    {\n"
2532 		"        result = vec4(1, 0, 0, 0);\n"
2533 		"    }\n"
2534 		"}\n";
2535 	glw::GLint compile_status = GL_FALSE;
2536 
2537 	fs_id = gl.createShader(GL_FRAGMENT_SHADER);
2538 
2539 	gl.shaderSource(fs_id, 1 /* count */, &fs_body, NULL);
2540 	gl.compileShader(fs_id);
2541 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a fragment shader");
2542 
2543 	gl.getShaderiv(fs_id, GL_COMPILE_STATUS, &compile_status);
2544 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not query fragment shader's compile status");
2545 
2546 	if (compile_status == GL_FALSE)
2547 	{
2548 		TCU_FAIL("Could not compile fragment shader");
2549 	}
2550 
2551 	/* Set up a vertex shader for 2D multisample texture case */
2552 	static const char* vs_body = "#version 310 es\n"
2553 								 "\n"
2554 								 "precision highp float;\n"
2555 								 "\n"
2556 								 "void main()\n"
2557 								 "{\n"
2558 								 "   switch (gl_VertexID)\n"
2559 								 "   {\n"
2560 								 "       case 0: gl_Position = vec4(-1, -1, 0, 1); break;\n"
2561 								 "       case 1: gl_Position = vec4(-1,  1, 0, 1); break;\n"
2562 								 "       case 2: gl_Position = vec4( 1,  1, 0, 1); break;\n"
2563 								 "       case 3: gl_Position = vec4( 1, -1, 0, 1); break;\n"
2564 								 "   }\n"
2565 								 "}\n";
2566 
2567 	vs_id = gl.createShader(GL_VERTEX_SHADER);
2568 
2569 	gl.shaderSource(vs_id, 1 /* count */, &vs_body, NULL);
2570 	gl.compileShader(vs_id);
2571 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a vertex shader");
2572 
2573 	gl.getShaderiv(vs_id, GL_COMPILE_STATUS, &compile_status);
2574 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not query vertex shader's compile status");
2575 
2576 	if (compile_status == GL_FALSE)
2577 	{
2578 		TCU_FAIL("Could not compile vertex shader");
2579 	}
2580 
2581 	/* Set up a program object */
2582 	po_id = gl.createProgram();
2583 
2584 	gl.attachShader(po_id, fs_id);
2585 	gl.attachShader(po_id, vs_id);
2586 
2587 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a program object");
2588 
2589 	/* Link the program object */
2590 	glw::GLint link_status = GL_FALSE;
2591 
2592 	gl.linkProgram(po_id);
2593 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
2594 
2595 	gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status);
2596 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
2597 
2598 	if (link_status != GL_TRUE)
2599 	{
2600 		TCU_FAIL("Program object linking failed");
2601 	}
2602 
2603 	/* Set up uniforms */
2604 	glw::GLint sampler_2d_array_location = gl.getUniformLocation(po_id, "sampler_2d_array");
2605 	glw::GLint sampler_2d_location		 = gl.getUniformLocation(po_id, "sampler_2d");
2606 
2607 	if ((sampler_2d_array_location == -1 && are_2d_array_ms_tos_supported) || sampler_2d_location == -1)
2608 	{
2609 		TCU_FAIL("At least one of the required uniforms is not considered active");
2610 	}
2611 
2612 	gl.useProgram(po_id);
2613 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2614 
2615 	gl.uniform1i(sampler_2d_array_location, 0);
2616 	gl.uniform1i(sampler_2d_location, 1);
2617 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call(s) failed.");
2618 
2619 	/* Render a full-screen quad */
2620 	gl.drawArrays(GL_TRIANGLE_FAN, 0 /* first */, 4 /* count */);
2621 	GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed");
2622 
2623 	/* Verify the results */
2624 	const tcu::RenderTarget& rt = m_context.getRenderContext().getRenderTarget();
2625 
2626 	unsigned char* buffer		 = NULL;
2627 	unsigned char* data_ptr		 = NULL;
2628 	int			   rt_bits_alpha = 0;
2629 	int			   rt_bits_blue  = 0;
2630 	int			   rt_bits_green = 0;
2631 	int			   rt_bits_red   = 0;
2632 	int			   rt_height	 = rt.getHeight();
2633 	int			   rt_width		 = rt.getWidth();
2634 	const int	  row_width	 = 4 /* RGBA */ * rt_width;
2635 
2636 	gl.getIntegerv(GL_ALPHA_BITS, &rt_bits_alpha);
2637 	gl.getIntegerv(GL_BLUE_BITS, &rt_bits_blue);
2638 	gl.getIntegerv(GL_GREEN_BITS, &rt_bits_green);
2639 	gl.getIntegerv(GL_RED_BITS, &rt_bits_red);
2640 
2641 	buffer = new unsigned char[rt_height * rt_width * 4];
2642 
2643 	gl.readPixels(0, 0, rt_width, rt_height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
2644 	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed");
2645 
2646 	data_ptr = buffer + row_width * (rt_height / 2) + rt_width / 2 * 4;
2647 
2648 	if (((data_ptr[0] != 0) && (rt_bits_red != 0)) || ((data_ptr[1] != 255) && (rt_bits_green != 0)) ||
2649 		((data_ptr[2] != 0) && (rt_bits_blue != 0)) || ((data_ptr[3] != 0) && (rt_bits_alpha != 0)))
2650 	{
2651 		m_testCtx.getLog() << tcu::TestLog::Message << "Invalid data rendered: expected:(0, 255, 0, 0) rendered:"
2652 						   << "(" << data_ptr[0] << ", " << data_ptr[1] << ", " << data_ptr[2] << ", " << data_ptr[3]
2653 						   << ")" << tcu::TestLog::EndMessage;
2654 
2655 		delete[] buffer;
2656 		buffer = NULL;
2657 
2658 		TCU_FAIL("Invalid data rendered");
2659 	}
2660 
2661 	if (buffer != NULL)
2662 	{
2663 		delete[] buffer;
2664 		buffer = NULL;
2665 	}
2666 
2667 	/* All done */
2668 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2669 
2670 	return STOP;
2671 }
2672 
2673 /** Constructor.
2674  *
2675  *  @param context CTS context handle.
2676  **/
2677 MultisampleTextureFunctionalTestsTextureSizeVertexShadersTest::
MultisampleTextureFunctionalTestsTextureSizeVertexShadersTest(Context & context)2678 	MultisampleTextureFunctionalTestsTextureSizeVertexShadersTest(Context& context)
2679 	: TestCase(context, "texture_size_in_vertex_shaders",
2680 			   "Verifies textureSize() works for multisample textures when used in vertex shaders")
2681 	, bo_id(0)
2682 	, fbo_id(0)
2683 	, fs_id(0)
2684 	, po_id(0)
2685 	, tfo_id(0)
2686 	, to_2d_multisample_id(0)
2687 	, to_2d_multisample_array_id(0)
2688 	, vs_2d_array_id(0)
2689 	, vs_2d_id(0)
2690 {
2691 	/* Left blank on purpose */
2692 }
2693 
2694 /** Deinitializes ES objects created during test execution */
deinit()2695 void MultisampleTextureFunctionalTestsTextureSizeVertexShadersTest::deinit()
2696 {
2697 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2698 
2699 	if (bo_id != 0)
2700 	{
2701 		gl.deleteBuffers(1, &bo_id);
2702 
2703 		bo_id = 0;
2704 	}
2705 
2706 	if (fbo_id != 0)
2707 	{
2708 		gl.deleteFramebuffers(1, &fbo_id);
2709 
2710 		fbo_id = 0;
2711 	}
2712 
2713 	if (fs_id != 0)
2714 	{
2715 		gl.deleteShader(fs_id);
2716 
2717 		fs_id = 0;
2718 	}
2719 
2720 	if (po_id != 0)
2721 	{
2722 		gl.deleteProgram(po_id);
2723 
2724 		po_id = 0;
2725 	}
2726 
2727 	if (tfo_id != 0)
2728 	{
2729 		gl.deleteTransformFeedbacks(1, &tfo_id);
2730 
2731 		tfo_id = 0;
2732 	}
2733 
2734 	if (to_2d_multisample_id != 0)
2735 	{
2736 		gl.deleteTextures(1, &to_2d_multisample_id);
2737 
2738 		to_2d_multisample_id = 0;
2739 	}
2740 
2741 	if (to_2d_multisample_array_id != 0)
2742 	{
2743 		gl.deleteTextures(1, &to_2d_multisample_array_id);
2744 
2745 		to_2d_multisample_array_id = 0;
2746 	}
2747 
2748 	if (vs_2d_id != 0)
2749 	{
2750 		gl.deleteShader(vs_2d_id);
2751 
2752 		vs_2d_id = 0;
2753 	}
2754 
2755 	if (vs_2d_array_id != 0)
2756 	{
2757 		gl.deleteShader(vs_2d_array_id);
2758 
2759 		vs_2d_array_id = 0;
2760 	}
2761 
2762 	/* Call base class' deinit() */
2763 	TestCase::deinit();
2764 }
2765 
2766 /** Executes test iteration.
2767  *
2768  *  @return Returns STOP when test has finished executing.
2769  */
iterate()2770 tcu::TestNode::IterateResult MultisampleTextureFunctionalTestsTextureSizeVertexShadersTest::iterate()
2771 {
2772 	bool are_multisample_2d_array_tos_supported =
2773 		m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array");
2774 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2775 
2776 	/* Set up a TFO */
2777 	gl.genTransformFeedbacks(1, &tfo_id);
2778 	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfo_id);
2779 
2780 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a transform feedback object");
2781 
2782 	/* Set up a buffer object */
2783 	gl.genBuffers(1, &bo_id);
2784 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, bo_id);
2785 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(float), NULL, GL_STATIC_READ);
2786 
2787 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a buffer object");
2788 
2789 	/* Set up texture objects */
2790 	if (are_multisample_2d_array_tos_supported)
2791 	{
2792 		gl.genTextures(1, &to_2d_multisample_array_id);
2793 	}
2794 
2795 	gl.genTextures(1, &to_2d_multisample_id);
2796 
2797 	/* NOTE: Since we're binding the textures to zero texture unit,
2798 	 *       we don't need to do glUniform1i() calls to configure
2799 	 *       the texture samplers in the vertex shaders later on.
2800 	 */
2801 	if (are_multisample_2d_array_tos_supported)
2802 	{
2803 		gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, to_2d_multisample_array_id);
2804 	}
2805 
2806 	gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id);
2807 
2808 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture objects");
2809 
2810 	gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */
2811 							   GL_RGBA8, 16,				 /* width */
2812 							   32,							 /* height */
2813 							   GL_TRUE);
2814 	GLU_EXPECT_NO_ERROR(gl.getError(),
2815 						"glTexStorage2DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE texture target");
2816 
2817 	if (are_multisample_2d_array_tos_supported)
2818 	{
2819 		gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, /* samples */
2820 								   GL_RGBA8, 16,						   /* width */
2821 								   32,									   /* height */
2822 								   8,									   /* depth */
2823 								   GL_TRUE);							   /* fixedsamplelocations */
2824 		GLU_EXPECT_NO_ERROR(
2825 			gl.getError(),
2826 			"gltexStorage3DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES texture target");
2827 	}
2828 
2829 	/* Set up a fragment shader */
2830 	glw::GLint		   compile_status = GL_FALSE;
2831 	static const char* fs_body		  = "#version 310 es\n"
2832 								 "\n"
2833 								 "void main()\n"
2834 								 "{\n"
2835 								 "}\n";
2836 
2837 	fs_id = gl.createShader(GL_FRAGMENT_SHADER);
2838 
2839 	gl.shaderSource(fs_id, 1 /* count */, &fs_body, NULL);
2840 	gl.compileShader(fs_id);
2841 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a fragment shader");
2842 
2843 	gl.getShaderiv(fs_id, GL_COMPILE_STATUS, &compile_status);
2844 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not query fragment shader's compile status");
2845 
2846 	if (compile_status == GL_FALSE)
2847 	{
2848 		TCU_FAIL("Could not compile fragment shader");
2849 	}
2850 
2851 	/* Set up a vertex shader for 2D multisample texture case */
2852 	static const char* vs_2d_body = "#version 310 es\n"
2853 									"\n"
2854 									"precision highp float;\n"
2855 									"\n"
2856 									"uniform highp sampler2DMS sampler;\n"
2857 									"out           float       is_size_correct;\n"
2858 									"\n"
2859 									"void main()\n"
2860 									"{\n"
2861 									"    ivec2 size = textureSize(sampler);\n"
2862 									"\n"
2863 									"    if (size.x == 16 && size.y == 32)\n"
2864 									"    {\n"
2865 									"        is_size_correct = 1.0f;\n"
2866 									"    }\n"
2867 									"    else\n"
2868 									"    {\n"
2869 									"        is_size_correct = 0.0f;\n"
2870 									"    }\n"
2871 									"}\n";
2872 
2873 	vs_2d_id = gl.createShader(GL_VERTEX_SHADER);
2874 
2875 	gl.shaderSource(vs_2d_id, 1 /* count */, &vs_2d_body, NULL);
2876 	gl.compileShader(vs_2d_id);
2877 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a vertex shader for 2D multisample texture case");
2878 
2879 	gl.getShaderiv(vs_2d_id, GL_COMPILE_STATUS, &compile_status);
2880 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not query 2D multisample texture vertex shader's compile status");
2881 
2882 	if (compile_status == GL_FALSE)
2883 	{
2884 		TCU_FAIL("Could not compile vertex shader for 2D multisample texture");
2885 	}
2886 
2887 	/* Set up a vertex shader for 2D multisample array texture case */
2888 	if (are_multisample_2d_array_tos_supported)
2889 	{
2890 		static const char* vs_2d_array_body = "#version 310 es\n"
2891 											  "\n"
2892 											  "#extension GL_OES_texture_storage_multisample_2d_array : enable\n"
2893 											  "precision highp float;\n"
2894 											  "\n"
2895 											  "uniform highp sampler2DMSArray sampler;\n"
2896 											  "out           float            is_size_correct;\n"
2897 											  "\n"
2898 											  "void main()\n"
2899 											  "{\n"
2900 											  "    ivec3 size = textureSize(sampler);\n"
2901 											  "\n"
2902 											  "    if (size.x == 16 && size.y == 32 && size.z == 8)\n"
2903 											  "    {\n"
2904 											  "        is_size_correct = 1.0f;\n"
2905 											  "    }\n"
2906 											  "    else\n"
2907 											  "    {\n"
2908 											  "        is_size_correct = 0.0f;\n"
2909 											  "    }\n"
2910 											  "}\n";
2911 
2912 		vs_2d_array_id = gl.createShader(GL_VERTEX_SHADER);
2913 
2914 		gl.shaderSource(vs_2d_array_id, 1 /* count */, &vs_2d_array_body, NULL);
2915 		gl.compileShader(vs_2d_array_id);
2916 		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a vertex shader for 2D multisample array texture case");
2917 
2918 		gl.getShaderiv(vs_2d_array_id, GL_COMPILE_STATUS, &compile_status);
2919 		GLU_EXPECT_NO_ERROR(gl.getError(),
2920 							"Could not query 2D multisample array texture vertex shader's compile status");
2921 
2922 		if (compile_status == GL_FALSE)
2923 		{
2924 			TCU_FAIL("Could not compile vertex shader for 2D multisample array texture");
2925 		}
2926 	}
2927 
2928 	/* Execute two iterations:
2929 	 *
2930 	 * a) Create a program object using fs and vs_2d shaders;
2931 	 * b) Create a program object using fs and vs_2d_array shaders.
2932 	 *
2933 	 * Case b) should only be executed if 2D Array MS textures are
2934 	 * supported.
2935 	 */
2936 	for (int n_iteration = 0; n_iteration < 2 /* iterations */; ++n_iteration)
2937 	{
2938 		if (n_iteration == 1 && !are_multisample_2d_array_tos_supported)
2939 		{
2940 			/* Skip the iteration */
2941 			continue;
2942 		}
2943 
2944 		if (po_id != 0)
2945 		{
2946 			gl.deleteProgram(po_id);
2947 
2948 			po_id = 0;
2949 		}
2950 
2951 		po_id = gl.createProgram();
2952 
2953 		/* Attach iteration-specific shaders */
2954 		switch (n_iteration)
2955 		{
2956 		case 0:
2957 		{
2958 			gl.attachShader(po_id, fs_id);
2959 			gl.attachShader(po_id, vs_2d_id);
2960 
2961 			break;
2962 		}
2963 
2964 		case 1:
2965 		{
2966 			gl.attachShader(po_id, fs_id);
2967 			gl.attachShader(po_id, vs_2d_array_id);
2968 
2969 			break;
2970 		}
2971 
2972 		default:
2973 			TCU_FAIL("Unrecognized iteration index");
2974 		}
2975 
2976 		GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
2977 
2978 		/* Configure the program object for XFB */
2979 		const char* varying_name = "is_size_correct";
2980 
2981 		gl.transformFeedbackVaryings(po_id, 1 /* count */, &varying_name, GL_INTERLEAVED_ATTRIBS);
2982 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
2983 
2984 		/* Link the program object */
2985 		glw::GLint link_status = GL_FALSE;
2986 
2987 		gl.linkProgram(po_id);
2988 		GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
2989 
2990 		gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status);
2991 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
2992 
2993 		if (link_status != GL_TRUE)
2994 		{
2995 			m_testCtx.getLog() << tcu::TestLog::Message << "Linking failed for program object in iteration "
2996 							   << n_iteration << tcu::TestLog::EndMessage;
2997 
2998 			TCU_FAIL("Program object linking failed");
2999 		}
3000 
3001 		/* Render a point using the program */
3002 		gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, bo_id);
3003 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed");
3004 
3005 		gl.useProgram(po_id);
3006 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
3007 
3008 		gl.beginTransformFeedback(GL_POINTS);
3009 		{
3010 			gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
3011 		}
3012 		gl.endTransformFeedback();
3013 
3014 		GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed");
3015 
3016 		/* Read the captured data. Reset the contents of the BO before the buffer
3017 		 * object is unmapped.
3018 		 */
3019 		void*		data_ptr = NULL;
3020 		const float epsilon  = (float)1e-5;
3021 		float		result   = 0.0f;
3022 
3023 		data_ptr = gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* offset */, sizeof(float) /* size */,
3024 									 GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
3025 		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed");
3026 
3027 		result = *((const float*)data_ptr);
3028 		memset(data_ptr, 0, sizeof(float));
3029 
3030 		gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
3031 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed");
3032 
3033 		if (de::abs(result - 1.0f) > epsilon)
3034 		{
3035 			m_testCtx.getLog() << tcu::TestLog::Message << "Retrieved value: " << result << ", expected: 1.0"
3036 							   << tcu::TestLog::EndMessage;
3037 
3038 			TCU_FAIL("Invalid value reported.");
3039 		}
3040 	}
3041 
3042 	/* All done */
3043 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3044 
3045 	return STOP;
3046 }
3047 } /* glcts namespace */
3048