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  es31cTextureStorageMultisampleDependenciesTests.cpp
27 * \brief Implements conformance tests that verify dependencies of
28 *        multisample textures on other parts of core ES3.1 API
29 *        (ES3.1 only)
30 */ /*-------------------------------------------------------------------*/
31
32#include "es31cTextureStorageMultisampleDependenciesTests.hpp"
33#include "gluContextInfo.hpp"
34#include "gluDefs.hpp"
35#include "glwEnums.hpp"
36#include "glwFunctions.hpp"
37#include "tcuRenderTarget.hpp"
38#include "tcuTestLog.hpp"
39
40#include <cmath>
41#include <memory.h>
42#include <string>
43#include <vector>
44
45namespace glcts
46{
47/** Constructor.
48 *
49 *  @param context CTS context handle.
50 **/
51MultisampleTextureDependenciesFBOIncompleteness1Test::MultisampleTextureDependenciesFBOIncompleteness1Test(
52	Context& context)
53	: TestCase(context, "fbo_with_attachments_of_varying_amount_of_samples",
54			   "FBOs with multisample texture attachments, whose amount"
55			   " of samples differs between attachments, should be "
56			   "considered incomplete")
57	, fbo_id(0)
58	, to_id_multisample_2d_array(0)
59{
60	memset(to_ids_multisample_2d, 0, sizeof(to_ids_multisample_2d));
61}
62
63/** Deinitializes ES objects created during test execution */
64void MultisampleTextureDependenciesFBOIncompleteness1Test::deinit()
65{
66	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
67
68	if (fbo_id != 0)
69	{
70		gl.deleteFramebuffers(1, &fbo_id);
71
72		fbo_id = 0;
73	}
74
75	if (to_ids_multisample_2d[0] != 0)
76	{
77		gl.deleteTextures(1, to_ids_multisample_2d + 0);
78
79		to_ids_multisample_2d[0] = 0;
80	}
81
82	if (to_ids_multisample_2d[1] != 0)
83	{
84		gl.deleteTextures(1, to_ids_multisample_2d + 1);
85
86		to_ids_multisample_2d[1] = 0;
87	}
88
89	if (to_id_multisample_2d_array != 0)
90	{
91		gl.deleteTextures(1, &to_id_multisample_2d_array);
92
93		to_id_multisample_2d_array = 0;
94	}
95
96	/* Call base class' deinit() */
97	TestCase::deinit();
98}
99
100/** Executes test iteration.
101 *
102 *  @return Returns STOP when test has finished executing.
103 */
104tcu::TestNode::IterateResult MultisampleTextureDependenciesFBOIncompleteness1Test::iterate()
105{
106	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
107	bool				  are_2d_ms_array_tos_supported =
108		m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array");
109
110	/* Set up texture objects */
111	gl.genTextures(1, to_ids_multisample_2d);
112
113	if (are_2d_ms_array_tos_supported)
114	{
115		gl.genTextures(1, &to_id_multisample_2d_array);
116		gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, to_id_multisample_2d_array);
117	}
118	else
119	{
120		gl.genTextures(1, to_ids_multisample_2d + 1);
121	}
122
123	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture objects");
124
125	/* Query possible sample count values for both texture targets
126	 and format used in test */
127	glw::GLint num_sample_counts_2dms   = 1;
128	glw::GLint num_sample_counts_2dms_a = 1;
129
130	gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, 1, &num_sample_counts_2dms);
131
132	if (are_2d_ms_array_tos_supported)
133	{
134		gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, 1,
135							   &num_sample_counts_2dms_a);
136	}
137
138	std::vector<glw::GLint> sample_counts_2dms(num_sample_counts_2dms);
139	std::vector<glw::GLint> sample_counts_2dms_a(num_sample_counts_2dms_a);
140
141	gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, num_sample_counts_2dms,
142						   &sample_counts_2dms[0]);
143
144	if (are_2d_ms_array_tos_supported)
145	{
146		gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_RGBA8, GL_SAMPLES, num_sample_counts_2dms_a,
147							   &sample_counts_2dms_a[0]);
148	}
149
150	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set query internal formats");
151
152	/* This will store actual sample counts to be used in test */
153	glw::GLint samples_attachment_1 = 0;
154	glw::GLint samples_attachment_2 = 0;
155
156	/* Choose two different sample counts, supported by implementation */
157	if (are_2d_ms_array_tos_supported)
158	{
159		for (glw::GLint i_2dms = 0; i_2dms < num_sample_counts_2dms; i_2dms++)
160		{
161			for (glw::GLint i_2dms_a = 0; i_2dms_a < num_sample_counts_2dms_a; i_2dms_a++)
162			{
163				if (sample_counts_2dms[i_2dms] != sample_counts_2dms_a[i_2dms_a] && sample_counts_2dms[i_2dms] != 1 &&
164					sample_counts_2dms_a[i_2dms_a] != 1)
165				{
166					/* found two differing non-1 sample counts ! */
167					samples_attachment_1 = sample_counts_2dms[i_2dms];
168					samples_attachment_2 = sample_counts_2dms_a[i_2dms_a];
169				}
170			}
171		}
172	} /* if (are_2d_ms_array_tos_supported) */
173	else
174	{
175		for (glw::GLuint index = 1; index < sample_counts_2dms.size(); ++index)
176		{
177			if (sample_counts_2dms[index - 1] != 1 && sample_counts_2dms[index] != 1 &&
178				sample_counts_2dms[index - 1] != sample_counts_2dms[index])
179			{
180				samples_attachment_1 = sample_counts_2dms[index - 1];
181				samples_attachment_2 = sample_counts_2dms[index];
182
183				break;
184			}
185		}
186	}
187
188	if (samples_attachment_1 == 0 || samples_attachment_2 == 0)
189	{
190		/* It may be the case implementation support only one
191		 sample count on both targets with used format.
192
193		 In such case cannot perform the test - cannot make
194		 FBO incomplete due to sample count mismatch
195		 */
196		m_testCtx.setTestResult(
197			QP_TEST_RESULT_NOT_SUPPORTED,
198			"Can't test incomplete FBO due to mismatch sample count: only 1 sample count available");
199
200		return STOP;
201	}
202
203	for (int n_texture_2d = 0; n_texture_2d < (are_2d_ms_array_tos_supported ? 1 : 2); ++n_texture_2d)
204	{
205		gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_ids_multisample_2d[n_texture_2d]);
206		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
207
208		gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE,
209								   (n_texture_2d == 0) ? samples_attachment_1 : samples_attachment_2, GL_RGBA8,
210								   2,		  /* width */
211								   2,		  /* height */
212								   GL_FALSE); /* fixedsamplelocations */
213
214		GLU_EXPECT_NO_ERROR(gl.getError(),
215							"glTexStorage2DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE texture target");
216	}
217
218	if (are_2d_ms_array_tos_supported)
219	{
220		gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samples_attachment_2, /* samples */
221								   GL_RGBA8, 2,												  /* width */
222								   2,														  /* height */
223								   2,														  /* depth */
224								   GL_FALSE);												  /* fixedsamplelocations */
225
226		GLU_EXPECT_NO_ERROR(
227			gl.getError(),
228			"gltexStorage3DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES texture target");
229	}
230
231	/* Set up a framebuffer object */
232	gl.genFramebuffers(1, &fbo_id);
233	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id);
234
235	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a framebuffer object");
236
237	/* Set up FBO attachments */
238	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
239							to_ids_multisample_2d[0], 0); /* level */
240
241	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up zeroth color attachment");
242
243	if (are_2d_ms_array_tos_supported)
244	{
245		gl.framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, to_id_multisample_2d_array, 0, /* level */
246								   0);																		 /* layer */
247	}
248	else
249	{
250		gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
251								to_ids_multisample_2d[1], 0); /* level */
252	}
253
254	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up first color attachment");
255
256	/* Make sure the draw framebuffer is considered incomplete */
257	glw::GLenum fbo_status = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
258
259	if (fbo_status != GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE)
260	{
261		m_testCtx.getLog() << tcu::TestLog::Message << "Draw framebuffer's completeness status is: " << fbo_status
262						   << "as opposed to expected status: GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE"
263						   << tcu::TestLog::EndMessage;
264
265		TCU_FAIL("Invalid FBO completeness status reported.");
266	}
267
268	/* All done */
269	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
270
271	return STOP;
272}
273
274/** Constructor.
275 *
276 *  @param context CTS context handle.
277 **/
278MultisampleTextureDependenciesFBOIncompleteness2Test::MultisampleTextureDependenciesFBOIncompleteness2Test(
279	Context& context)
280	: TestCase(context, "fbo_with_single_and_multisample_attachments",
281			   "FBOs with multisample texture and normal 2D texture attachments "
282			   "should be considered incomplete")
283	, fbo_id(0)
284	, to_id_2d(0)
285	, to_id_multisample_2d(0)
286	, to_id_multisample_2d_array(0)
287{
288	/* Left blank on purpose */
289}
290
291/** Deinitializes ES objects created during test execution */
292void MultisampleTextureDependenciesFBOIncompleteness2Test::deinit()
293{
294	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
295
296	if (fbo_id != 0)
297	{
298		gl.deleteFramebuffers(1, &fbo_id);
299
300		fbo_id = 0;
301	}
302
303	if (to_id_2d != 0)
304	{
305		gl.deleteTextures(1, &to_id_2d);
306
307		to_id_2d = 0;
308	}
309
310	if (to_id_multisample_2d != 0)
311	{
312		gl.deleteTextures(1, &to_id_multisample_2d);
313
314		to_id_multisample_2d = 0;
315	}
316
317	if (to_id_multisample_2d_array != 0)
318	{
319		gl.deleteTextures(1, &to_id_multisample_2d_array);
320
321		to_id_multisample_2d_array = 0;
322	}
323
324	/* Call base class' deinit() */
325	TestCase::deinit();
326}
327
328/** Executes test iteration.
329 *
330 *  @return Returns STOP when test has finished executing.
331 */
332tcu::TestNode::IterateResult MultisampleTextureDependenciesFBOIncompleteness2Test::iterate()
333{
334	bool are_2d_ms_array_tos_supported =
335		m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array");
336	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
337
338	/* Set up texture objects */
339	gl.genTextures(1, &to_id_2d);
340	gl.genTextures(1, &to_id_multisample_2d);
341
342	if (are_2d_ms_array_tos_supported)
343	{
344		gl.genTextures(1, &to_id_multisample_2d_array);
345	}
346
347	gl.bindTexture(GL_TEXTURE_2D, to_id_2d);
348	gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id_multisample_2d);
349
350	if (are_2d_ms_array_tos_supported)
351	{
352		gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, to_id_multisample_2d_array);
353	}
354
355	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture objects");
356
357	gl.texImage2D(GL_TEXTURE_2D, 0, /* level */
358				  GL_RGB565, 2,		/* width */
359				  2,				/* height */
360				  0,				/* border */
361				  GL_RGB,			/* format */
362				  GL_UNSIGNED_BYTE, /* type */
363				  NULL);			/* pixels */
364
365	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage2D() call failed for GL_TEXTURE_2D texture target");
366
367	gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */
368							   GL_RGB565, 2,				 /* width */
369							   2,							 /* height */
370							   GL_FALSE);					 /* fixedsamplelocations */
371
372	GLU_EXPECT_NO_ERROR(gl.getError(),
373						"glTexStorage2DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE texture target");
374
375	if (are_2d_ms_array_tos_supported)
376	{
377		gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, /* samples */
378								   GL_RGB565, 2,						   /* width */
379								   2,									   /* height */
380								   2,									   /* depth */
381								   GL_FALSE);							   /* fixedsamplelocations */
382
383		GLU_EXPECT_NO_ERROR(
384			gl.getError(),
385			"gltexStorage3DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES texture target");
386	}
387
388	/* Set up a framebuffer object */
389	gl.genFramebuffers(1, &fbo_id);
390	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id);
391
392	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a framebuffer object");
393
394	/* Set up FBO attachments */
395	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, to_id_2d, 0); /* level */
396
397	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up zeroth color attachment");
398
399	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE, to_id_multisample_2d,
400							0); /* level */
401
402	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up first color attachment");
403
404	/* Make sure the draw framebuffer is considered incomplete */
405	glw::GLenum fbo_status = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
406
407	if (fbo_status != GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE)
408	{
409		m_testCtx.getLog() << tcu::TestLog::Message << "Draw framebuffer's completeness status is: " << fbo_status
410						   << "as opposed to expected status: GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE"
411						   << tcu::TestLog::EndMessage;
412
413		TCU_FAIL("Invalid FBO completeness status reported.");
414	}
415
416	/* Detach the first color attachment */
417	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE, 0, /* texture */
418							0);																		 /* level */
419
420	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not detach first color attachment from the draw FBO");
421
422	/* Verify the FBO is now considered complete */
423	fbo_status = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
424
425	if (fbo_status != GL_FRAMEBUFFER_COMPLETE)
426	{
427		m_testCtx.getLog() << tcu::TestLog::Message << "Draw framebuffer's completeness status is: " << fbo_status
428						   << "as opposed to expected status: GL_FRAMEBUFFER_COMPLETE" << tcu::TestLog::EndMessage;
429
430		TCU_FAIL("Invalid FBO completeness status reported.");
431	}
432
433	if (are_2d_ms_array_tos_supported)
434	{
435		/* Attach the arrayed multisample texture object */
436		gl.framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, to_id_multisample_2d_array, 0, /* level */
437								   0);																		 /* layer */
438
439		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up first color attachment");
440
441		/* Make sure the draw framebuffer is considered incomplete */
442		fbo_status = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
443
444		if (fbo_status != GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE)
445		{
446			m_testCtx.getLog() << tcu::TestLog::Message << "Draw framebuffer's completeness status is: " << fbo_status
447							   << "as opposed to expected status: GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE"
448							   << tcu::TestLog::EndMessage;
449
450			TCU_FAIL("Invalid FBO completeness status reported.");
451		}
452	}
453
454	/* All done */
455	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
456
457	return STOP;
458}
459
460/** Constructor.
461 *
462 *  @param context CTS context handle.
463 **/
464MultisampleTextureDependenciesFBOIncompleteness3Test::MultisampleTextureDependenciesFBOIncompleteness3Test(
465	Context& context)
466	: TestCase(context, "fbo_with_fixed_and_varying_sample_locations_attachments",
467			   "FBOs with multisample texture attachments of different fixed "
468			   "sample location settings should be considered incomplete")
469	, fbo_id(0)
470	, to_id_2d_multisample_color_1(0)
471	, to_id_2d_multisample_color_2(0)
472	, to_id_2d_multisample_depth(0)
473	, to_id_2d_multisample_depth_stencil(0)
474{
475	/* Left blank on purpose */
476}
477
478/** Deinitializes ES objects created during test execution */
479void MultisampleTextureDependenciesFBOIncompleteness3Test::deinit()
480{
481	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
482
483	if (fbo_id != 0)
484	{
485		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
486		gl.deleteFramebuffers(1, &fbo_id);
487
488		fbo_id = 0;
489	}
490
491	if (to_id_2d_multisample_color_1 != 0)
492	{
493		gl.deleteTextures(1, &to_id_2d_multisample_color_1);
494
495		to_id_2d_multisample_color_1 = 0;
496	}
497
498	if (to_id_2d_multisample_color_2 != 0)
499	{
500		gl.deleteTextures(1, &to_id_2d_multisample_color_2);
501
502		to_id_2d_multisample_color_2 = 0;
503	}
504
505	if (to_id_2d_multisample_depth != 0)
506	{
507		gl.deleteTextures(1, &to_id_2d_multisample_depth);
508
509		to_id_2d_multisample_depth = 0;
510	}
511
512	if (to_id_2d_multisample_depth_stencil != 0)
513	{
514		gl.deleteTextures(1, &to_id_2d_multisample_depth_stencil);
515
516		to_id_2d_multisample_depth_stencil = 0;
517	}
518
519	/* Call base class' deinit() */
520	TestCase::deinit();
521}
522
523/** Executes test iteration.
524 *
525 *  @return Returns STOP when test has finished executing.
526 */
527tcu::TestNode::IterateResult MultisampleTextureDependenciesFBOIncompleteness3Test::iterate()
528{
529	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
530
531	/* Only execute if GL_MAX_SAMPLES pname value >= 2 */
532	glw::GLint gl_max_samples_value = 0;
533
534	gl.getIntegerv(GL_MAX_SAMPLES, &gl_max_samples_value);
535	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() generated an error for GL_MAX_SAMPLES pname");
536
537	if (gl_max_samples_value < 2)
538	{
539		throw tcu::NotSupportedError("GL_MAX_SAMPLES pname value < 2, skipping");
540	}
541
542	/* Only execute if GL_RGBA8, GL_DEPTH_COMPONENT16, GL_DEPTH24_STENCIL8 internalformats
543	 * can be rendered to with at least 2 samples per fragment.
544	 */
545	glw::GLint depth_component16_internalformat_max_samples = 0;
546	glw::GLint depth24_stencil8_internalformat_max_samples  = 0;
547	glw::GLint rgba8_internalformat_max_samples				= 0;
548
549	gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_DEPTH_COMPONENT16, GL_SAMPLES, 1, /* bufSize */
550						   &depth_component16_internalformat_max_samples);
551	gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_DEPTH24_STENCIL8, GL_SAMPLES, 1, /* bufSize */
552						   &depth24_stencil8_internalformat_max_samples);
553	gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, 1, /* bufSize */
554						   &rgba8_internalformat_max_samples);
555
556	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInternalformativ() failed for at least one GL_SAMPLES query");
557
558	if (depth_component16_internalformat_max_samples < 2)
559	{
560		throw tcu::NotSupportedError("GL_SAMPLES is lower than 2 for GL_DEPTH_COMPONENT16 internalformat");
561	}
562
563	if (depth24_stencil8_internalformat_max_samples < 2)
564	{
565		throw tcu::NotSupportedError("GL_SAMPLES is lower than 2 for GL_DEPTH24_STENCIL8 internalformat");
566	}
567
568	if (rgba8_internalformat_max_samples < 2)
569	{
570		throw tcu::NotSupportedError("GL_SAMPLES is lower than 2 for GL_RGBA8 internalformat");
571	}
572
573	/* Set up texture objects */
574	gl.genTextures(1, &to_id_2d_multisample_color_1);
575	gl.genTextures(1, &to_id_2d_multisample_color_2);
576	gl.genTextures(1, &to_id_2d_multisample_depth);
577	gl.genTextures(1, &to_id_2d_multisample_depth_stencil);
578
579	GLU_EXPECT_NO_ERROR(gl.getError(), "At least one glGenTextures() call failed");
580
581	/* Set up a framebuffer object */
582	gl.genFramebuffers(1, &fbo_id);
583	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id);
584
585	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a framebuffer object");
586
587	/* Set up first GL_RGBA8 multisample texture storage */
588	gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id_2d_multisample_color_1);
589	gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */
590							   GL_RGBA8, 2,					 /* width */
591							   2,							 /* height */
592							   GL_FALSE);					 /* fixedsamplelocations */
593
594	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up first GL_RGBA8 multisample texture storage.");
595
596	/* Set up second GL_RGBA8 multisample texture storage */
597	gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id_2d_multisample_color_2);
598	gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */
599							   GL_RGBA8, 2,					 /* width */
600							   2,							 /* height */
601							   GL_TRUE);					 /* fixedsamplelocations */
602
603	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up second GL_RGBA8 multisample texture storage.");
604
605	/* Set up GL_DEPTH_COMPONENT16 multisample texture storage */
606	gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id_2d_multisample_depth);
607	gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */
608							   GL_DEPTH_COMPONENT16, 2,		 /* width */
609							   2,							 /* height */
610							   GL_TRUE);					 /* fixedsamplelocations */
611
612	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up GL_DEPTH_COMPONENT16 multisample texture storage.");
613
614	/* Set up GL_DEPTH24_STENCIL8 multisample texture storage */
615	gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id_2d_multisample_depth_stencil);
616	gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */
617							   GL_DEPTH24_STENCIL8, 2,		 /* width */
618							   2,							 /* height */
619							   GL_TRUE);					 /* fixedsamplelocations */
620
621	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up GL_DEPTH24_STENCIL8 multisample texture storage.");
622
623	/* Set up FBO's zeroth color attachment */
624	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
625							to_id_2d_multisample_color_1, 0); /* level */
626
627	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
628							to_id_2d_multisample_color_2, 0); /* level */
629
630	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up FBO color attachments");
631
632	/* FBO should now be considered incomplete */
633	glw::GLenum fbo_completeness = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
634
635	if (fbo_completeness != GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE)
636	{
637		m_testCtx.getLog() << tcu::TestLog::Message << "Invalid FBO completeness status reported:" << fbo_completeness
638						   << " expected: GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE" << tcu::TestLog::EndMessage;
639
640		TCU_FAIL("Invalid FBO completeness status reported.");
641	}
642
643	/* Detach the first color attachment */
644	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, 0, /* texture */
645							0);															 /* level */
646
647	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not detach FBO's first color attachment");
648
649	/* Configure FBO's depth attachment */
650	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE,
651							to_id_2d_multisample_depth, 0); /* level */
652
653	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure FBO's depth attachment");
654
655	/* FBO should now be considered incomplete */
656	fbo_completeness = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
657
658	if (fbo_completeness != GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE)
659	{
660		m_testCtx.getLog() << tcu::TestLog::Message << "Invalid FBO completeness status reported:" << fbo_completeness
661						   << " expected: GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE" << tcu::TestLog::EndMessage;
662
663		TCU_FAIL("Invalid FBO completeness status reported.");
664	}
665
666	/* Detach depth attachment */
667	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, /* texture */
668							0);															/* level */
669
670	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not detach FBO's depth attachment");
671
672	/* Configure FBO's depth+stencil attachment */
673	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE,
674							to_id_2d_multisample_depth_stencil, 0); /* level */
675
676	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure FBO's depth+stencil attachment");
677
678	/* FBO should now be considered incomplete */
679	fbo_completeness = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
680
681	if (fbo_completeness != GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE)
682	{
683		m_testCtx.getLog() << tcu::TestLog::Message << "Invalid FBO completeness status reported:" << fbo_completeness
684						   << " expected: GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE" << tcu::TestLog::EndMessage;
685
686		TCU_FAIL("Invalid FBO completeness status reported.");
687	}
688
689	/* All done */
690	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
691
692	return STOP;
693}
694
695/** Constructor.
696 *
697 *  @param context CTS context handle.
698 **/
699MultisampleTextureDependenciesFBOIncompleteness4Test::MultisampleTextureDependenciesFBOIncompleteness4Test(
700	Context& context)
701	: TestCase(context, "fbo_with_different_fixedsamplelocations_texture_and_renderbuffer_attachments",
702			   "FBOs with multisample texture attachments of different 'fixed sample location' "
703			   "settings and with multisampled renderbuffers (of the same amount of samples)"
704			   "should be considered incomplete")
705	, fbo_id(0)
706	, rbo_id(0)
707	, to_id_2d_multisample_array_color(0)
708	, to_id_2d_multisample_color(0)
709{
710	/* Left blank on purpose */
711}
712
713/** Deinitializes ES objects created during test execution */
714void MultisampleTextureDependenciesFBOIncompleteness4Test::deinit()
715{
716	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
717
718	if (fbo_id != 0)
719	{
720		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
721		gl.deleteFramebuffers(1, &fbo_id);
722
723		fbo_id = 0;
724	}
725
726	if (rbo_id != 0)
727	{
728		gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
729		gl.deleteRenderbuffers(1, &rbo_id);
730	}
731
732	if (to_id_2d_multisample_color != 0)
733	{
734		gl.deleteTextures(1, &to_id_2d_multisample_color);
735
736		to_id_2d_multisample_color = 0;
737	}
738
739	if (to_id_2d_multisample_array_color != 0)
740	{
741		gl.deleteTextures(1, &to_id_2d_multisample_array_color);
742
743		to_id_2d_multisample_array_color = 0;
744	}
745
746	/* Call base class' deinit() */
747	TestCase::deinit();
748}
749
750/** Executes test iteration.
751 *
752 *  @return Returns STOP when test has finished executing.
753 */
754tcu::TestNode::IterateResult MultisampleTextureDependenciesFBOIncompleteness4Test::iterate()
755{
756	bool are_2d_ms_array_tos_supported =
757		m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array");
758	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
759
760	/* Only execute if GL_MAX_SAMPLES pname value >= 3 */
761	glw::GLint gl_max_samples_value = 0;
762
763	gl.getIntegerv(GL_MAX_SAMPLES, &gl_max_samples_value);
764	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() generated an error for GL_MAX_SAMPLES pname");
765
766	if (gl_max_samples_value < 3)
767	{
768		throw tcu::NotSupportedError("GL_MAX_SAMPLES pname value < 3, skipping");
769	}
770
771	/* Set up texture objects */
772	if (are_2d_ms_array_tos_supported)
773	{
774		gl.genTextures(1, &to_id_2d_multisample_array_color);
775	}
776
777	gl.genTextures(1, &to_id_2d_multisample_color);
778
779	GLU_EXPECT_NO_ERROR(gl.getError(), "At least one glGenTextures() call failed");
780
781	/* Set up a framebuffer object */
782	gl.genFramebuffers(1, &fbo_id);
783	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id);
784
785	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a framebuffer object");
786
787	/* Set up a renderbuffer object */
788	gl.genRenderbuffers(1, &rbo_id);
789	gl.bindRenderbuffer(GL_RENDERBUFFER, rbo_id);
790
791	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a renderbuffer object");
792
793	/* Set up first GL_RGBA8 multisample texture storage */
794	gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id_2d_multisample_color);
795	gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */
796							   GL_RGBA8, 2,					 /* width */
797							   2,							 /* height */
798							   GL_FALSE);					 /* fixedsamplelocations */
799
800	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up GL_RGBA8 multisample texture storage.");
801
802	if (are_2d_ms_array_tos_supported)
803	{
804		/* Set up second GL_RGBA8 multisample texture storage */
805		gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, to_id_2d_multisample_array_color);
806		gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, /* samples */
807								   GL_RGBA8, 2,							   /* width */
808								   2,									   /* height */
809								   2,									   /* depth */
810								   GL_TRUE);							   /* fixedsamplelocations */
811
812		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up second GL_RGBA8 multisample texture storage.");
813	}
814
815	/* Set up renderbuffer storage */
816	gl.renderbufferStorageMultisample(GL_RENDERBUFFER, 3, /* samples */
817									  GL_RGBA8, 2,		  /* width */
818									  2);				  /* height */
819
820	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up renderbuffer storage.");
821
822	/* Set up FBO's zeroth color attachment */
823	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
824							to_id_2d_multisample_color, 0); /* level */
825
826	/* Make sure FBO is considered complete at this point */
827	glw::GLenum fbo_completeness = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
828
829	if (fbo_completeness != GL_FRAMEBUFFER_COMPLETE)
830	{
831		m_testCtx.getLog() << tcu::TestLog::Message << "Invalid FBO completeness status reported:" << fbo_completeness
832						   << " expected: GL_FRAMEBUFFER_COMPLETE" << tcu::TestLog::EndMessage;
833
834		TCU_FAIL("Invalid FBO completeness status reported.");
835	}
836
837	if (are_2d_ms_array_tos_supported)
838	{
839		/* Set up FBO's first color attachment */
840		gl.framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, to_id_2d_multisample_array_color,
841								   0,  /* level */
842								   0); /* layer */
843
844		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up FBO color attachments");
845
846		/* FBO should now be considered incomplete */
847		fbo_completeness = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
848
849		if (fbo_completeness != GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE)
850		{
851			m_testCtx.getLog() << tcu::TestLog::Message
852							   << "Invalid FBO completeness status reported:" << fbo_completeness
853							   << " expected: GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE" << tcu::TestLog::EndMessage;
854
855			TCU_FAIL("Invalid FBO completeness status reported.");
856		}
857	}
858
859	/* Set up FBO's second color attachment */
860	gl.framebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_RENDERBUFFER, rbo_id);
861
862	/* FBO should now be considered incomplete */
863	fbo_completeness = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
864
865	if (fbo_completeness != GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE)
866	{
867		m_testCtx.getLog() << tcu::TestLog::Message << "Invalid FBO completeness status reported:" << fbo_completeness
868						   << " expected: GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE" << tcu::TestLog::EndMessage;
869
870		TCU_FAIL("Invalid FBO completeness status reported.");
871	}
872
873	/* All done */
874	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
875
876	return STOP;
877}
878
879/** Constructor.
880 *
881 *  @param context CTS context handle.
882 **/
883MultisampleTextureDependenciesFBOIncompleteness5Test::MultisampleTextureDependenciesFBOIncompleteness5Test(
884	Context& context)
885	: TestCase(context, "fbo_with_renderbuffer_and_multisample_texture_attachments_with_different_number_of_samples",
886			   "FBOs with renderbuffer and multisample texture attachments, where amount "
887			   "of samples used for multisample texture attachments differs from the "
888			   "amount of samples used for renderbuffer attachments, should be considered "
889			   "incomplete")
890	, fbo_id(0)
891	, rbo_id(0)
892	, to_id_multisample_2d(0)
893	, to_id_multisample_2d_array(0)
894{
895	/* Left blank on purpose */
896}
897
898/** Deinitializes ES objects created during test execution */
899void MultisampleTextureDependenciesFBOIncompleteness5Test::deinit()
900{
901	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
902
903	if (fbo_id != 0)
904	{
905		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
906		gl.deleteFramebuffers(1, &fbo_id);
907
908		fbo_id = 0;
909	}
910
911	if (rbo_id != 0)
912	{
913		gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
914		gl.deleteRenderbuffers(1, &rbo_id);
915	}
916
917	if (to_id_multisample_2d != 0)
918	{
919		gl.deleteTextures(1, &to_id_multisample_2d);
920
921		to_id_multisample_2d = 0;
922	}
923
924	if (to_id_multisample_2d_array != 0)
925	{
926		gl.deleteTextures(1, &to_id_multisample_2d_array);
927
928		to_id_multisample_2d_array = 0;
929	}
930
931	/* Call base class' deinit() */
932	TestCase::deinit();
933}
934
935/** Executes test iteration.
936 *
937 *  @return Returns STOP when test has finished executing.
938 */
939tcu::TestNode::IterateResult MultisampleTextureDependenciesFBOIncompleteness5Test::iterate()
940{
941	bool are_multisample_2d_array_tos_supported =
942		m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array");
943	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
944
945	/* Retrieve GL_MAX_INTEGER_SAMPLES and GL_MAX_SAMPLES values */
946	glw::GLint gl_max_integer_samples_value = 0;
947	glw::GLint gl_max_samples_value			= 0;
948
949	gl.getIntegerv(GL_MAX_INTEGER_SAMPLES, &gl_max_integer_samples_value);
950	gl.getIntegerv(GL_MAX_SAMPLES, &gl_max_samples_value);
951	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() generated an error");
952
953	/* Set up texture objects */
954	gl.genTextures(1, &to_id_multisample_2d);
955
956	if (are_multisample_2d_array_tos_supported)
957	{
958		gl.genTextures(1, &to_id_multisample_2d_array);
959	}
960
961	GLU_EXPECT_NO_ERROR(gl.getError(), "At least one glGenTextures() call failed");
962
963	/* Set up a framebuffer object */
964	gl.genFramebuffers(1, &fbo_id);
965	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id);
966
967	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a framebuffer object");
968
969	/* Set up a renderbuffer object */
970	gl.genRenderbuffers(1, &rbo_id);
971	gl.bindRenderbuffer(GL_RENDERBUFFER, rbo_id);
972
973	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a renderbuffer object");
974
975	/* Bind texture objects to relevant texture targets */
976	gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id_multisample_2d);
977
978	if (are_multisample_2d_array_tos_supported)
979	{
980		gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, to_id_multisample_2d_array);
981	}
982
983	GLU_EXPECT_NO_ERROR(gl.getError(), "At least one glBindTexture() call failed.");
984
985	/* Iterate through internalformats. Current internalformat will be used
986	 * by the 2D multisample attachment */
987	const glw::GLenum  internalformats[] = { GL_R8, GL_RGB565, GL_RGB10_A2UI, GL_SRGB8_ALPHA8, GL_R8I };
988	const unsigned int n_internalformats = sizeof(internalformats) / sizeof(internalformats[0]);
989
990	for (unsigned int n_2d_multisample_internalformat = 0; n_2d_multisample_internalformat < n_internalformats;
991		 ++n_2d_multisample_internalformat)
992	{
993		glw::GLenum internalformat_2d_multisample = internalformats[n_2d_multisample_internalformat];
994
995		/* Query sample counts supported for 2DMS texture on given internal format */
996		glw::GLint num_sample_counts_2dms;
997
998		gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, internalformat_2d_multisample, GL_NUM_SAMPLE_COUNTS, 1,
999							   &num_sample_counts_2dms);
1000
1001		std::vector<glw::GLint> sample_counts_2dms(num_sample_counts_2dms);
1002
1003		gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, internalformat_2d_multisample, GL_SAMPLES,
1004							   num_sample_counts_2dms, &sample_counts_2dms[0]);
1005
1006		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve sample counts supported for 2DMS");
1007
1008		/* Iterate again through the internalformats. This internalformat will be used
1009		 * by the 2D multisample array attacmhent.
1010		 *
1011		 * NOTE: Under implementations which do not support 2DMS Array textures, we will
1012		 *       not attach the 2DMS Array textures to the FBO at all. This fits the conformance
1013		 *       test idea and does not break existing test implementation.
1014		 *       However, since 2DMS Array textures are unavailable, we only run a single inner
1015		 *       loop iteration. More iterations would not bring anything to the table at all.
1016		 */
1017		for (unsigned int n_2d_multisample_array_internalformat = 0;
1018			 n_2d_multisample_array_internalformat < ((are_multisample_2d_array_tos_supported) ? n_internalformats : 1);
1019			 ++n_2d_multisample_array_internalformat)
1020		{
1021			glw::GLenum internalformat_2d_multisample_array = internalformats[n_2d_multisample_array_internalformat];
1022			glw::GLint  num_sample_counts_2dms_array		= 1;
1023			std::vector<glw::GLint> sample_counts_2dms_array(num_sample_counts_2dms_array);
1024
1025			if (are_multisample_2d_array_tos_supported)
1026			{
1027				/* Query sample counts supported for 2DMS_ARRAY texture on given internal format */
1028				gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, internalformat_2d_multisample_array,
1029									   GL_NUM_SAMPLE_COUNTS, 1, &num_sample_counts_2dms_array);
1030
1031				sample_counts_2dms_array.resize(num_sample_counts_2dms_array);
1032
1033				gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, internalformat_2d_multisample_array,
1034									   GL_SAMPLES, num_sample_counts_2dms_array, &sample_counts_2dms_array[0]);
1035
1036				GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve sample counts supported for 2DMS_ARRAY");
1037			}
1038			else
1039			{
1040				/* Add a single entry to the 2d ms sample count array */
1041				num_sample_counts_2dms_array = 1;
1042				sample_counts_2dms_array[0]  = 0;
1043			}
1044
1045			/* One more iteration for renderbuffer attachment */
1046			for (unsigned int n_rbo_internalformat = 0; n_rbo_internalformat < n_internalformats;
1047				 ++n_rbo_internalformat)
1048			{
1049				glw::GLenum internalformat_rbo = internalformats[n_rbo_internalformat];
1050
1051				/* Query sample counts supported for RBO on given internal format */
1052				glw::GLint num_sample_counts_rbo;
1053
1054				gl.getInternalformativ(GL_RENDERBUFFER, internalformat_rbo, GL_NUM_SAMPLE_COUNTS, 1,
1055									   &num_sample_counts_rbo);
1056
1057				std::vector<glw::GLint> sample_counts_rbo(num_sample_counts_rbo);
1058
1059				gl.getInternalformativ(GL_RENDERBUFFER, internalformat_rbo, GL_SAMPLES, num_sample_counts_rbo,
1060									   &sample_counts_rbo[0]);
1061
1062				GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve sample counts supported for rbo");
1063
1064				/* Now iterate over all samples argument we will use for the 2D multisample attachment */
1065				for (int i_2dms = 0; i_2dms < num_sample_counts_2dms; ++i_2dms)
1066				{
1067					int samples_2d_multisample = sample_counts_2dms[i_2dms];
1068
1069					/* ..and yet another iteration for the 2D multisample array attachment */
1070					for (int i_2dms_array = 0; i_2dms_array < num_sample_counts_2dms_array; ++i_2dms_array)
1071					{
1072						int samples_2d_multisample_array = sample_counts_2dms_array[i_2dms_array];
1073
1074						/* Finally, iterate over values to be used for samples argument of
1075						 * a glRenderbufferStorageMultisample() call.
1076						 */
1077						for (int i_rbo = 0; i_rbo < num_sample_counts_rbo; ++i_rbo)
1078						{
1079							int samples_rbo = sample_counts_rbo[i_rbo];
1080
1081							/* This is a negative test. Hence, skip an iteration where all the
1082							 * samples arguments used for the multisample 2d/multisample 2d array/rbo
1083							 * triple match.
1084							 */
1085							if (((samples_rbo == samples_2d_multisample) &&
1086								 (samples_rbo == samples_2d_multisample_array)) ||
1087								(samples_rbo == 1) || (samples_2d_multisample == 1) ||
1088								(samples_2d_multisample_array == 1))
1089							{
1090								/* Skip the iteration */
1091								continue;
1092							}
1093
1094							/* Set up 2D multisample texture storage. */
1095							gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples_2d_multisample,
1096													   internalformat_2d_multisample, 2, /* width */
1097													   2,								 /* height */
1098													   GL_FALSE);
1099							GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() call failed.");
1100
1101							if (are_multisample_2d_array_tos_supported)
1102							{
1103								/* Set up 2D multisample array texture storage. */
1104								gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES,
1105														   samples_2d_multisample_array,
1106														   internalformat_2d_multisample_array, 2, /* width */
1107														   2,									   /* height */
1108														   2,									   /* depth */
1109														   GL_FALSE);
1110								GLU_EXPECT_NO_ERROR(gl.getError(), "gltexStorage3DMultisample() call failed.");
1111							}
1112
1113							/* Set up renderbuffer storage */
1114							gl.renderbufferStorageMultisample(GL_RENDERBUFFER, samples_rbo, internalformat_rbo,
1115															  2,  /* width */
1116															  2); /* height */
1117							GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorageMultisample() call failed.");
1118
1119							/* Set up FBO's color attachments */
1120							gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1121													GL_TEXTURE_2D_MULTISAMPLE, to_id_multisample_2d, 0); /* level */
1122							GLU_EXPECT_NO_ERROR(
1123								gl.getError(),
1124								"glFramebufferTexture2D() call failed for GL_COLOR_ATTACHMENT0 color attachment.");
1125
1126							if (are_multisample_2d_array_tos_supported)
1127							{
1128								gl.framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1,
1129														   to_id_multisample_2d_array, 0, /* level */
1130														   0);							  /* layer */
1131								GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTextureLayer() call failed for "
1132																   "GL_COLOR_ATTACHMENT1 color attachment.");
1133							}
1134
1135							gl.framebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_RENDERBUFFER,
1136													   rbo_id);
1137							GLU_EXPECT_NO_ERROR(
1138								gl.getError(),
1139								"glFramebufferRenderbuffer() call failed for GL_COLOR_ATTACHMENT2 color attachment.");
1140
1141							/* Make sure the FBO is incomplete */
1142							glw::GLenum fbo_completeness_status = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
1143
1144							if (fbo_completeness_status != GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE)
1145							{
1146								m_testCtx.getLog() << tcu::TestLog::Message
1147												   << "Invalid FBO completeness status reported ["
1148												   << fbo_completeness_status
1149												   << "]"
1150													  " instead of expected GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE."
1151												   << " Sample count 2D_MS:" << samples_2d_multisample
1152												   << " Sample count 2D_MS_ARRAY:" << samples_2d_multisample_array
1153												   << " Sample count RBO:" << samples_rbo << tcu::TestLog::EndMessage;
1154
1155								TCU_FAIL("Invalid FBO completeness status reported.");
1156							}
1157
1158							/* Re-create texture objects */
1159							gl.deleteTextures(1, &to_id_multisample_2d);
1160
1161							if (are_multisample_2d_array_tos_supported)
1162							{
1163								gl.deleteTextures(1, &to_id_multisample_2d_array);
1164							}
1165
1166							GLU_EXPECT_NO_ERROR(gl.getError(), "At least one glDeleteTextures() call failed.");
1167
1168							gl.genTextures(1, &to_id_multisample_2d);
1169
1170							if (are_multisample_2d_array_tos_supported)
1171							{
1172								gl.genTextures(1, &to_id_multisample_2d_array);
1173							}
1174
1175							GLU_EXPECT_NO_ERROR(gl.getError(), "At least one glGenTextures() call failed.");
1176
1177							gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id_multisample_2d);
1178
1179							if (are_multisample_2d_array_tos_supported)
1180							{
1181								gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, to_id_multisample_2d_array);
1182							}
1183
1184							GLU_EXPECT_NO_ERROR(gl.getError(), "At least one glBindTexture() call failed.");
1185						} /* for (all samples argument values to be used for renderbuffer attachment) */
1186					}	 /* for (all samples argument values to be used for 2D multisample array attachment) */
1187				}		  /* for (all samples argument values to be used for 2D multisample attachment) */
1188			}			  /* for (all internalformats used by renderbuffer attachment) */
1189		}				  /* for (all internalformats used by 2D multisample array attachment) */
1190	}					  /* for (all internalformats used by 2D multisample attachment) */
1191
1192	/* All done */
1193	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1194
1195	return STOP;
1196}
1197
1198/** Constructor.
1199 *
1200 *  @param context CTS context handle.
1201 **/
1202MultisampleTextureDependenciesInvalidFramebufferTexture2DCalls1Test::
1203	MultisampleTextureDependenciesInvalidFramebufferTexture2DCalls1Test(Context& context)
1204	: TestCase(context, "framebuffer_texture2d_used_with_invalid_texture_target",
1205			   "Checks GL_INVALID_OPERATION is reported if 2D or cube-map texture "
1206			   "target is used with a multisample 2D texture for a "
1207			   "glFramebufferTexture2D() call")
1208	, fbo_id(0)
1209	, to_id(0)
1210{
1211	/* Left blank on purpose */
1212}
1213
1214/** Deinitializes ES objects created during test execution */
1215void MultisampleTextureDependenciesInvalidFramebufferTexture2DCalls1Test::deinit()
1216{
1217	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1218
1219	if (fbo_id != 0)
1220	{
1221		gl.deleteFramebuffers(1, &fbo_id);
1222
1223		fbo_id = 0;
1224	}
1225
1226	if (to_id != 0)
1227	{
1228		gl.deleteTextures(1, &to_id);
1229
1230		to_id = 0;
1231	}
1232
1233	/* Call base class' deinit() */
1234	TestCase::deinit();
1235}
1236
1237/** Initializes ES objects created during test execution */
1238void MultisampleTextureDependenciesInvalidFramebufferTexture2DCalls1Test::initInternals()
1239{
1240	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1241
1242	/* Generate and bind a framebuffer object */
1243	gl.genFramebuffers(1, &fbo_id);
1244	gl.bindFramebuffer(GL_FRAMEBUFFER, fbo_id);
1245
1246	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a framebuffer object");
1247
1248	/* Generate and bind a texture object to GL_TEXTURE_2D_MULTISAMPLE texture target */
1249	gl.genTextures(1, &to_id);
1250	gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id);
1251
1252	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a texture object");
1253}
1254
1255/** Executes test iteration.
1256 *
1257 *  @return Returns STOP when test has finished executing.
1258 */
1259tcu::TestNode::IterateResult MultisampleTextureDependenciesInvalidFramebufferTexture2DCalls1Test::iterate()
1260{
1261	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1262
1263	initInternals();
1264
1265	/* For storing internalformat specific maximum number of samples */
1266	glw::GLint gl_max_internalformat_samples = 0;
1267
1268	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve GL_MAX_INTEGER_SAMPLES and/or GL_MAX_SAMPLES values");
1269
1270	/* Iterate through all internalformats to be used for the test */
1271	const glw::GLenum internalformats[] = {
1272		GL_RGB8, GL_RGB565, GL_SRGB8_ALPHA8, GL_DEPTH_COMPONENT32F, GL_DEPTH24_STENCIL8, GL_RGBA32I
1273	};
1274
1275	const unsigned int n_internalformats = sizeof(internalformats) / sizeof(internalformats[0]);
1276
1277	for (unsigned int n_internalformat = 0; n_internalformat < n_internalformats; ++n_internalformat)
1278	{
1279		glw::GLenum internalformat				= internalformats[n_internalformat];
1280		bool		is_color_renderable			= false;
1281		bool		is_depth_stencil_renderable = false;
1282
1283		if (internalformat == GL_DEPTH24_STENCIL8)
1284		{
1285			is_depth_stencil_renderable = true;
1286		}
1287		else if (internalformat != GL_DEPTH_COMPONENT32F)
1288		{
1289			is_color_renderable = true;
1290		}
1291
1292		/* Determine a value to be used for samples argument in subsequent
1293		 * glTexStorage2DMultisample() call. */
1294		gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, internalformat, GL_SAMPLES, 1,
1295							   &gl_max_internalformat_samples);
1296
1297		GLU_EXPECT_NO_ERROR(gl.getError(),
1298							"Could not retrieve maximum supported amount of samples for internal format");
1299
1300		glw::GLint samples = gl_max_internalformat_samples;
1301
1302		/* Skip formats that are not multisampled in the implementation */
1303		if (samples <= 1)
1304		{
1305			continue;
1306		}
1307
1308		/* Set the texture object storage up */
1309		gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, internalformat, 1, /* width */
1310								   1,													  /* height */
1311								   GL_FALSE);											  /* fixedsamplelocations */
1312
1313		GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() call generated an unexpected error.");
1314
1315		/* Try to issue the invalid glFramebufferTexture2D() call */
1316		glw::GLenum attachment = (is_color_renderable) ?
1317									 GL_COLOR_ATTACHMENT0 :
1318									 (is_depth_stencil_renderable) ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
1319
1320		gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, GL_TEXTURE_2D, to_id, 0); /* level */
1321
1322		/* Make sure GL_INVALID_OPERATION error was generated */
1323		glw::GLenum error_code = gl.getError();
1324
1325		if (error_code != GL_INVALID_OPERATION)
1326		{
1327			m_testCtx.getLog()
1328				<< tcu::TestLog::Message << "An unexpected error code " << error_code
1329				<< " instead of GL_INVALID_OPERATION was generated by an invalid glFramebufferTexture2D() call"
1330				<< tcu::TestLog::EndMessage;
1331
1332			TCU_FAIL("Invalid error code reported by glFramebufferTexture2D() call.");
1333		}
1334
1335		/* Re-create the texture object */
1336		gl.deleteTextures(1, &to_id);
1337		gl.genTextures(1, &to_id);
1338		gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id);
1339
1340		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not re-create the texture object.");
1341	} /* for (all internalformats) */
1342
1343	/* All done */
1344	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1345
1346	return STOP;
1347}
1348
1349/** Constructor.
1350 *
1351 *  @param context CTS context handle.
1352 **/
1353MultisampleTextureDependenciesInvalidFramebufferTexture2DCalls2Test::
1354	MultisampleTextureDependenciesInvalidFramebufferTexture2DCalls2Test(Context& context)
1355	: TestCase(context, "framebuffer_texture2d_used_with_invalid_level",
1356			   "Checks GL_INVALID_VALUE is reported if glFramebufferTexture2D() "
1357			   "is called with invalid level argument.")
1358	, fbo_id(0)
1359	, to_id(0)
1360{
1361	/* Left blank on purpose */
1362}
1363
1364/** Deinitializes ES objects created during test execution */
1365void MultisampleTextureDependenciesInvalidFramebufferTexture2DCalls2Test::deinit()
1366{
1367	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1368
1369	if (fbo_id != 0)
1370	{
1371		gl.deleteFramebuffers(1, &fbo_id);
1372
1373		fbo_id = 0;
1374	}
1375
1376	if (to_id != 0)
1377	{
1378		gl.deleteTextures(1, &to_id);
1379
1380		to_id = 0;
1381	}
1382
1383	/* Call base class' deinit() */
1384	TestCase::deinit();
1385}
1386
1387/** Initializes ES objects created during test execution */
1388void MultisampleTextureDependenciesInvalidFramebufferTexture2DCalls2Test::initInternals()
1389{
1390	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1391
1392	/* Generate and bind a framebuffer object */
1393	gl.genFramebuffers(1, &fbo_id);
1394	gl.bindFramebuffer(GL_FRAMEBUFFER, fbo_id);
1395
1396	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a framebuffer object");
1397
1398	/* Generate and bind a texture object to GL_TEXTURE_2D_MULTISAMPLE texture target */
1399	gl.genTextures(1, &to_id);
1400	gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id);
1401
1402	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a texture object");
1403}
1404
1405/** Executes test iteration.
1406 *
1407 *  @return Returns STOP when test has finished executing.
1408 */
1409tcu::TestNode::IterateResult MultisampleTextureDependenciesInvalidFramebufferTexture2DCalls2Test::iterate()
1410{
1411	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1412
1413	initInternals();
1414
1415	/* For storing format specific maximum number of samples */
1416	glw::GLint gl_max_internalformat_samples = 0;
1417
1418	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve GL_MAX_INTEGER_SAMPLES and/or GL_MAX_SAMPLE values");
1419
1420	/* Iterate through all internalformats to be used for the test */
1421	const glw::GLenum internalformats[] = {
1422		GL_RGB8, GL_RGB565, GL_SRGB8_ALPHA8, GL_DEPTH_COMPONENT32F, GL_DEPTH24_STENCIL8, GL_RGBA32I
1423	};
1424	const unsigned int n_internalformats = sizeof(internalformats) / sizeof(internalformats[0]);
1425
1426	for (unsigned int n_internalformat = 0; n_internalformat < n_internalformats; ++n_internalformat)
1427	{
1428		glw::GLenum internalformat		= internalformats[n_internalformat];
1429		bool		is_color_renderable = false;
1430		bool		is_depth_renderable = false;
1431
1432		if (internalformat == GL_DEPTH_COMPONENT32F)
1433		{
1434			is_depth_renderable = true;
1435		}
1436		else if (internalformat != GL_DEPTH24_STENCIL8)
1437		{
1438			is_color_renderable = true;
1439		}
1440
1441		/* Determine a value to be used for samples argument in subsequent
1442		 * glTexStorage2DMultisample() call. */
1443		gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, internalformat, GL_SAMPLES, 1,
1444							   &gl_max_internalformat_samples);
1445
1446		GLU_EXPECT_NO_ERROR(gl.getError(),
1447							"Could not retrieve maximum supported amount of samples for internal format");
1448
1449		glw::GLint samples = gl_max_internalformat_samples;
1450
1451		/* Skip formats that are not multisampled in implementation */
1452		if (samples <= 1)
1453		{
1454			continue;
1455		}
1456
1457		/* Set the texture object storage up */
1458		gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, internalformat, 1, /* width */
1459								   1,													  /* height */
1460								   GL_FALSE);											  /* fixedsamplelocations */
1461
1462		GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() call generated an unexpected error.");
1463
1464		/* Try to issue the invalid glFramebufferTexture2D() call */
1465		glw::GLenum attachment = (is_color_renderable) ?
1466									 GL_COLOR_ATTACHMENT0 :
1467									 (is_depth_renderable) ? GL_DEPTH_ATTACHMENT : GL_DEPTH_STENCIL_ATTACHMENT;
1468
1469		/* From spec:
1470		 *
1471		 * If textarget is TEXTURE_2D_MULTISAMPLE, then level must be zero. If textarget
1472		 * is one of the cube map face targets from table 3.21, then level must be greater
1473		 * than or equal to zero and less than or equal to log2 of the value of MAX_CUBE_-
1474		 * MAP_TEXTURE_SIZE. If textarget is TEXTURE_2D, level must be greater than or
1475		 * equal to zero and no larger than log2 of the value of MAX_TEXTURE_SIZE.
1476		 */
1477		gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, GL_TEXTURE_2D_MULTISAMPLE, to_id, 1); /* level */
1478
1479		/* Make sure GL_INVALID_VALUE error was generated */
1480		glw::GLenum error_code = gl.getError();
1481
1482		if (error_code != GL_INVALID_VALUE)
1483		{
1484			m_testCtx.getLog()
1485				<< tcu::TestLog::Message << "An unexpected error code " << error_code
1486				<< " instead of GL_INVALID_VALUE was generated by an invalid glFramebufferTexture2D() call"
1487				<< tcu::TestLog::EndMessage;
1488
1489			TCU_FAIL("Invalid error code reported by glFramebufferTexture2D() call.");
1490		}
1491
1492		/* Re-create the texture object */
1493		gl.deleteTextures(1, &to_id);
1494		gl.genTextures(1, &to_id);
1495		gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id);
1496
1497		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not re-create the texture object.");
1498	} /* for (all internalformats) */
1499
1500	/* All done */
1501	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1502
1503	return STOP;
1504}
1505
1506/** Constructor.
1507 *
1508 *  @param context CTS context handle.
1509 **/
1510MultisampleTextureDependenciesInvalidFramebufferTextureLayerCalls1Test::
1511	MultisampleTextureDependenciesInvalidFramebufferTextureLayerCalls1Test(Context& context)
1512	: TestCase(context, "framebuffer_texture_layer_used_for_invalid_texture_target",
1513			   "Checks GL_INVALID_OPERATION is reported if 2D multisample texture is used for a "
1514			   "glFramebufferTextureLayer() call")
1515	, fbo_id(0)
1516	, to_id(0)
1517{
1518	/* Left blank on purpose */
1519}
1520
1521/** Deinitializes ES objects created during test execution */
1522void MultisampleTextureDependenciesInvalidFramebufferTextureLayerCalls1Test::deinit()
1523{
1524	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1525
1526	if (fbo_id != 0)
1527	{
1528		gl.deleteFramebuffers(1, &fbo_id);
1529
1530		fbo_id = 0;
1531	}
1532
1533	if (to_id != 0)
1534	{
1535		gl.deleteTextures(1, &to_id);
1536
1537		to_id = 0;
1538	}
1539
1540	/* Call base class' deinit() */
1541	TestCase::deinit();
1542}
1543
1544/** Initializes ES objects created during test execution */
1545void MultisampleTextureDependenciesInvalidFramebufferTextureLayerCalls1Test::initInternals()
1546{
1547	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1548
1549	/* Generate and bind a framebuffer object */
1550	gl.genFramebuffers(1, &fbo_id);
1551	gl.bindFramebuffer(GL_FRAMEBUFFER, fbo_id);
1552
1553	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a framebuffer object");
1554
1555	/* Generate and bind a texture object to GL_TEXTURE_2D_MULTISAMPLE texture target */
1556	gl.genTextures(1, &to_id);
1557	gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id);
1558
1559	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a texture object");
1560}
1561
1562/** Executes test iteration.
1563 *
1564 *  @return Returns STOP when test has finished executing.
1565 */
1566tcu::TestNode::IterateResult MultisampleTextureDependenciesInvalidFramebufferTextureLayerCalls1Test::iterate()
1567{
1568	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1569
1570	initInternals();
1571
1572	/* For storing format specific maximum number of samples */
1573	glw::GLint gl_max_internalformat_samples = 0;
1574
1575	/* Iterate through all internalformats to be used for the test */
1576	const glw::GLenum internalformats[] = {
1577		GL_RGB8, GL_RGB565, GL_SRGB8_ALPHA8, GL_DEPTH_COMPONENT32F, GL_DEPTH24_STENCIL8, GL_RGBA32I
1578	};
1579	const unsigned int n_internalformats = sizeof(internalformats) / sizeof(internalformats[0]);
1580
1581	for (unsigned int n_internalformat = 0; n_internalformat < n_internalformats; ++n_internalformat)
1582	{
1583		glw::GLenum internalformat		= internalformats[n_internalformat];
1584		bool		is_color_renderable = false;
1585		bool		is_depth_renderable = false;
1586
1587		if (internalformat == GL_DEPTH_COMPONENT32F)
1588		{
1589			is_depth_renderable = true;
1590		}
1591		else if (internalformat != GL_DEPTH24_STENCIL8)
1592		{
1593			is_color_renderable = true;
1594		}
1595
1596		/* Determine a value to be used for samples argument in subsequent
1597		 * glTexStorage2DMultisample() call. */
1598		gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, internalformat, GL_SAMPLES, 1,
1599							   &gl_max_internalformat_samples);
1600
1601		GLU_EXPECT_NO_ERROR(gl.getError(),
1602							"Could not retrieve maximum supported amount of samples for internal format");
1603
1604		glw::GLint samples = gl_max_internalformat_samples;
1605
1606		/* Skip formats that are not multisampled in implementation */
1607		if (samples <= 1)
1608		{
1609			continue;
1610		}
1611
1612		/* Set the texture object storage up */
1613		gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, internalformat, 2, /* width */
1614								   2,													  /* height */
1615								   GL_FALSE);											  /* fixedsamplelocations */
1616
1617		GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() call generated an unexpected error.");
1618
1619		/* Try to issue the invalid glFramebufferTextureLayer() call */
1620		glw::GLenum attachment = (is_color_renderable) ?
1621									 GL_COLOR_ATTACHMENT0 :
1622									 (is_depth_renderable) ? GL_DEPTH_ATTACHMENT : GL_DEPTH_STENCIL_ATTACHMENT;
1623
1624		gl.framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, attachment, to_id, 0, /* level */
1625								   0);										  /* layer */
1626
1627		/* Make sure GL_INVALID_OPERATION error was generated */
1628		glw::GLenum error_code = gl.getError();
1629
1630		if (error_code != GL_INVALID_OPERATION)
1631		{
1632			m_testCtx.getLog()
1633				<< tcu::TestLog::Message << "An unexpected error code " << error_code
1634				<< " instead of GL_INVALID_OPERATION was generated by an invalid glFramebufferTextureLayer() call"
1635				<< tcu::TestLog::EndMessage;
1636
1637			TCU_FAIL("Invalid error code reported by glFramebufferTextureLayer() call.");
1638		}
1639
1640		/* Re-create the texture object */
1641		gl.deleteTextures(1, &to_id);
1642		gl.genTextures(1, &to_id);
1643		gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id);
1644
1645		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not re-create the texture object.");
1646	} /* for (all internalformats) */
1647
1648	/* All done */
1649	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1650
1651	return STOP;
1652}
1653
1654/** Constructor.
1655 *
1656 *  @param context CTS context handle.
1657 **/
1658MultisampleTextureDependenciesInvalidFramebufferTextureLayerCalls2Test::
1659	MultisampleTextureDependenciesInvalidFramebufferTextureLayerCalls2Test(Context& context)
1660	: TestCase(context, "framebuffer_texture_layer_used_with_invalid_level_argument",
1661			   "Checks GL_INVALID_VALUE error is reported if a glFramebufferTextureLayer() call"
1662			   " is made with level exceeding amount of layers defined for a 2D multisample"
1663			   " array texture")
1664	, fbo_id(0)
1665	, to_id(0)
1666{
1667	/* Left blank on purpose */
1668}
1669
1670/** Deinitializes ES objects created during test execution */
1671void MultisampleTextureDependenciesInvalidFramebufferTextureLayerCalls2Test::deinit()
1672{
1673	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1674
1675	if (fbo_id != 0)
1676	{
1677		gl.deleteFramebuffers(1, &fbo_id);
1678
1679		fbo_id = 0;
1680	}
1681
1682	if (to_id != 0)
1683	{
1684		gl.deleteTextures(1, &to_id);
1685
1686		to_id = 0;
1687	}
1688
1689	/* Call base class' deinit() */
1690	TestCase::deinit();
1691}
1692
1693/** Initializes ES objects created during test execution */
1694void MultisampleTextureDependenciesInvalidFramebufferTextureLayerCalls2Test::initInternals()
1695{
1696	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1697
1698	/* Generate and bind a framebuffer object */
1699	gl.genFramebuffers(1, &fbo_id);
1700	gl.bindFramebuffer(GL_FRAMEBUFFER, fbo_id);
1701
1702	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a framebuffer object");
1703
1704	/* Generate and bind a texture object to GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES texture target */
1705	gl.genTextures(1, &to_id);
1706	gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, to_id);
1707
1708	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a texture object");
1709}
1710
1711/** Executes test iteration.
1712 *
1713 *  @return Returns STOP when test has finished executing.
1714 */
1715tcu::TestNode::IterateResult MultisampleTextureDependenciesInvalidFramebufferTextureLayerCalls2Test::iterate()
1716{
1717	if (!m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array"))
1718	{
1719		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "OES_texture_storage_multisample_2d_array");
1720
1721		return STOP;
1722	}
1723
1724	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1725
1726	initInternals();
1727
1728	/* For storing format specific maximum number of samples */
1729	glw::GLint gl_max_internalformat_samples = 0;
1730
1731	/* Iterate through all internalformats to be used for the test */
1732	const glw::GLenum internalformats[] = {
1733		GL_RGB8, GL_RGB565, GL_SRGB8_ALPHA8, GL_DEPTH_COMPONENT32F, GL_DEPTH24_STENCIL8, GL_RGBA32I
1734	};
1735	const unsigned int n_internalformats = sizeof(internalformats) / sizeof(internalformats[0]);
1736
1737	for (unsigned int n_internalformat = 0; n_internalformat < n_internalformats; ++n_internalformat)
1738	{
1739		glw::GLenum internalformat		= internalformats[n_internalformat];
1740		bool		is_color_renderable = false;
1741		bool		is_depth_renderable = false;
1742
1743		if (internalformat == GL_DEPTH_COMPONENT32F)
1744		{
1745			is_depth_renderable = true;
1746		}
1747		else if (internalformat != GL_DEPTH24_STENCIL8)
1748		{
1749			is_color_renderable = true;
1750		}
1751
1752		/* Determine a value to be used for samples argument in subsequent
1753		 * glTexStorage2DMultisample() call. */
1754		gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, internalformat, GL_SAMPLES, 1,
1755							   &gl_max_internalformat_samples);
1756
1757		/* Get MAX_TEXTURE_SIZE and calculate max level */
1758		glw::GLint gl_max_texture_size = 0;
1759		gl.getIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max_texture_size);
1760		const glw::GLint max_level = glw::GLint(log(double(gl_max_texture_size)) / log(2.0));
1761
1762		GLU_EXPECT_NO_ERROR(gl.getError(),
1763							"Could not retrieve maximum supported amount of samples for internal format");
1764
1765		glw::GLint samples = gl_max_internalformat_samples;
1766
1767		/* Set the texture object storage up */
1768		gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samples, internalformat, 2, /* width */
1769								   2,																/* height */
1770								   2,																/* depth */
1771								   GL_FALSE); /* fixedsamplelocations */
1772
1773		GLU_EXPECT_NO_ERROR(gl.getError(), "gltexStorage3DMultisample() call generated an unexpected error.");
1774
1775		/* Try to issue the invalid glFramebufferTextureLayer() call */
1776		glw::GLenum attachment = (is_color_renderable) ?
1777									 GL_COLOR_ATTACHMENT0 :
1778									 (is_depth_renderable) ? GL_DEPTH_ATTACHMENT : GL_DEPTH_STENCIL_ATTACHMENT;
1779
1780		gl.framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, attachment, to_id,
1781								   max_level + 1, /* level - must be <= log_2(MAX_TEXTURE_SIZE) */
1782								   0);			  /* layer */
1783
1784		/* Make sure GL_INVALID_VALUE error was generated */
1785		glw::GLenum error_code = gl.getError();
1786
1787		if (error_code != GL_INVALID_VALUE)
1788		{
1789			m_testCtx.getLog()
1790				<< tcu::TestLog::Message << "An unexpected error code " << error_code
1791				<< " instead of GL_INVALID_VALUE was generated by an invalid glFramebufferTextureLayer() call"
1792				<< tcu::TestLog::EndMessage;
1793
1794			TCU_FAIL("Invalid error code reported by glFramebufferTextureLayer() call.");
1795		}
1796
1797		/* Re-create the texture object */
1798		gl.deleteTextures(1, &to_id);
1799		gl.genTextures(1, &to_id);
1800		gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, to_id);
1801
1802		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not re-create the texture object.");
1803	} /* for (all internalformats) */
1804
1805	/* All done */
1806	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1807
1808	return STOP;
1809}
1810
1811/** Constructor.
1812 *
1813 *  @param context CTS context handle.
1814 **/
1815MultisampleTextureDependenciesInvalidRenderbufferStorageMultisampleCalls1Test::
1816	MultisampleTextureDependenciesInvalidRenderbufferStorageMultisampleCalls1Test(Context& context)
1817	: TestCase(context, "renderbuffer_storage_multisample_invalid_samples_argument_for_noninteger_internalformats",
1818			   "GL_INVALID_OPERATION error is reported for glRenderbufferStorageMultisample() "
1819			   "calls, for which samples argument > MAX_SAMPLES for non-integer internalformats")
1820	, rbo_id(0)
1821{
1822	/* Left blank on purpose */
1823}
1824
1825/** Deinitializes ES objects created during test execution */
1826void MultisampleTextureDependenciesInvalidRenderbufferStorageMultisampleCalls1Test::deinit()
1827{
1828	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1829
1830	if (rbo_id != 0)
1831	{
1832		gl.deleteRenderbuffers(1, &rbo_id);
1833
1834		rbo_id = 0;
1835	}
1836
1837	/* Call base class' deinit() */
1838	TestCase::deinit();
1839}
1840
1841/** Initializes ES objects created during test execution */
1842void MultisampleTextureDependenciesInvalidRenderbufferStorageMultisampleCalls1Test::initInternals()
1843{
1844	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1845
1846	gl.genRenderbuffers(1, &rbo_id);
1847	gl.bindRenderbuffer(GL_RENDERBUFFER, rbo_id);
1848
1849	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a renderbuffer object");
1850}
1851
1852/** Executes test iteration.
1853 *
1854 *  @return Returns STOP when test has finished executing.
1855 */
1856tcu::TestNode::IterateResult MultisampleTextureDependenciesInvalidRenderbufferStorageMultisampleCalls1Test::iterate()
1857{
1858	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1859
1860	initInternals();
1861
1862	/* Retrieve GL_MAX_SAMPLES pname value */
1863	glw::GLint gl_max_samples_value = 0;
1864
1865	gl.getIntegerv(GL_MAX_SAMPLES, &gl_max_samples_value);
1866	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve GL_MAX_SAMPLES value.");
1867
1868	/* Iterate through a set of valid non-integer internalformats */
1869	const glw::GLenum noninteger_internalformats[] = {
1870		GL_RGB8, GL_RGB565, GL_SRGB8_ALPHA8, GL_DEPTH_COMPONENT32F, GL_DEPTH24_STENCIL8, GL_STENCIL_INDEX8
1871	};
1872	const unsigned int n_noninteger_internalformats =
1873		sizeof(noninteger_internalformats) / sizeof(noninteger_internalformats[0]);
1874
1875	for (unsigned int n_internalformat = 0; n_internalformat < n_noninteger_internalformats; ++n_internalformat)
1876	{
1877		glw::GLenum		  error_code						  = GL_NO_ERROR;
1878		const glw::GLenum internalformat					  = noninteger_internalformats[n_internalformat];
1879		glw::GLint		  gl_max_internalformat_samples_value = -1;
1880
1881		/* Retrieve maximum amount of samples available for the texture target considered */
1882		gl.getInternalformativ(GL_RENDERBUFFER, internalformat, GL_SAMPLES, 1, &gl_max_internalformat_samples_value);
1883		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInternalformativ() failed to retrieve GL_SAMPLES");
1884
1885		/* Execute the test */
1886		gl.renderbufferStorageMultisample(GL_RENDERBUFFER, gl_max_internalformat_samples_value + 1, internalformat,
1887										  1,  /* width */
1888										  1); /* height */
1889
1890		error_code = gl.getError();
1891		if (error_code != GL_INVALID_OPERATION)
1892		{
1893			m_testCtx.getLog() << tcu::TestLog::Message << "glRenderbufferStorageMultisample() generated error code "
1894							   << error_code << " when GL_INVALID_OPERATION was expected." << tcu::TestLog::EndMessage;
1895
1896			TCU_FAIL("Invalid error code generated by glRenderbufferStorageMultisample() call.");
1897		}
1898	} /* for (all internalformats) */
1899
1900	/* All done */
1901	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1902
1903	return STOP;
1904}
1905
1906/** Constructor.
1907 *
1908 *  @param context CTS context handle.
1909 **/
1910MultisampleTextureDependenciesInvalidRenderbufferStorageMultisampleCalls2Test::
1911	MultisampleTextureDependenciesInvalidRenderbufferStorageMultisampleCalls2Test(Context& context)
1912	: TestCase(context, "renderbuffer_storage_multisample_invalid_samples_argument_for_integer_internalformats",
1913			   "GL_INVALID_OPERATION error is reported for glRenderbufferStorageMultisample() calls, "
1914			   "for which samples argument > MAX_INTEGER_SAMPLES for integer internalformats")
1915	, rbo_id(0)
1916{
1917	/* Left blank on purpose */
1918}
1919
1920/** Deinitializes ES objects created during test execution */
1921void MultisampleTextureDependenciesInvalidRenderbufferStorageMultisampleCalls2Test::deinit()
1922{
1923	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1924
1925	if (rbo_id != 0)
1926	{
1927		gl.deleteRenderbuffers(1, &rbo_id);
1928
1929		rbo_id = 0;
1930	}
1931
1932	/* Call base class' deinit() */
1933	TestCase::deinit();
1934}
1935
1936/** Initializes ES objects created during test execution */
1937void MultisampleTextureDependenciesInvalidRenderbufferStorageMultisampleCalls2Test::initInternals()
1938{
1939	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1940
1941	gl.genRenderbuffers(1, &rbo_id);
1942	gl.bindRenderbuffer(GL_RENDERBUFFER, rbo_id);
1943
1944	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a renderbuffer object");
1945}
1946
1947/** Executes test iteration.
1948 *
1949 *  @return Returns STOP when test has finished executing.
1950 */
1951tcu::TestNode::IterateResult MultisampleTextureDependenciesInvalidRenderbufferStorageMultisampleCalls2Test::iterate()
1952{
1953	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1954
1955	initInternals();
1956
1957	/* Retrieve GL_MAX_INTEGER_SAMPLES pname value */
1958	glw::GLint gl_max_integer_samples_value = 0;
1959
1960	gl.getIntegerv(GL_MAX_INTEGER_SAMPLES, &gl_max_integer_samples_value);
1961	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve GL_MAX_INTEGER_SAMPLES value.");
1962
1963	/* Iterate through a set of valid integer internalformats */
1964	const glw::GLenum  integer_internalformats[] = { GL_RG8UI, GL_RGBA32I };
1965	const unsigned int n_integer_internalformats = sizeof(integer_internalformats) / sizeof(integer_internalformats[0]);
1966
1967	for (unsigned int n_internalformat = 0; n_internalformat < n_integer_internalformats; ++n_internalformat)
1968	{
1969		glw::GLenum		  error_code	 = GL_NO_ERROR;
1970		const glw::GLenum internalformat = integer_internalformats[n_internalformat];
1971
1972		/* Execute the test */
1973		gl.renderbufferStorageMultisample(GL_RENDERBUFFER, gl_max_integer_samples_value + 1, internalformat,
1974										  1,  /* width */
1975										  1); /* height */
1976
1977		error_code = gl.getError();
1978		if (error_code != GL_INVALID_OPERATION)
1979		{
1980			m_testCtx.getLog() << tcu::TestLog::Message << "glRenderbufferStorageMultisample() generated error code "
1981							   << error_code << " when GL_INVALID_OPERATION was expected." << tcu::TestLog::EndMessage;
1982
1983			TCU_FAIL("Invalid error code generated by glRenderbufferStorageMultisample() call.");
1984		}
1985	} /* for (all internalformats) */
1986
1987	/* All done */
1988	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1989
1990	return STOP;
1991}
1992
1993/** Constructor.
1994 *
1995 *  @param context CTS context handle.
1996 **/
1997MultisampleTextureDependenciesNoErrorGeneratedForValidFramebufferTexture2DCallsTest::
1998	MultisampleTextureDependenciesNoErrorGeneratedForValidFramebufferTexture2DCallsTest(Context& context)
1999	: TestCase(context, "no_error_generated_for_valid_framebuffer_texture2d_calls",
2000			   "No error is reported for glFramebufferTexture2D() calls using "
2001			   "GL_TEXTURE_2D_MULTISAMPLE texture target.")
2002	, fbo_id(0)
2003	, to_id(0)
2004{
2005	/* Left blank on purpose */
2006}
2007
2008/** Deinitializes ES objects created during test execution */
2009void MultisampleTextureDependenciesNoErrorGeneratedForValidFramebufferTexture2DCallsTest::deinit()
2010{
2011	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2012
2013	if (fbo_id != 0)
2014	{
2015		gl.deleteFramebuffers(1, &fbo_id);
2016
2017		fbo_id = 0;
2018	}
2019
2020	if (to_id != 0)
2021	{
2022		gl.deleteTextures(1, &to_id);
2023
2024		to_id = 0;
2025	}
2026
2027	/* Call base class' deinit() */
2028	TestCase::deinit();
2029}
2030
2031/** Initializes ES objects created during test execution */
2032void MultisampleTextureDependenciesNoErrorGeneratedForValidFramebufferTexture2DCallsTest::initInternals()
2033{
2034	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2035
2036	/* Set up a framebuffer object */
2037	gl.genFramebuffers(1, &fbo_id);
2038	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id);
2039
2040	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a framebuffer object");
2041}
2042
2043/** Executes test iteration.
2044 *
2045 *  @return Returns STOP when test has finished executing.
2046 */
2047tcu::TestNode::IterateResult MultisampleTextureDependenciesNoErrorGeneratedForValidFramebufferTexture2DCallsTest::
2048	iterate()
2049{
2050	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2051
2052	initInternals();
2053
2054	/* For storing format specific maximum number of samples */
2055	glw::GLint gl_max_internalformat_samples = 0;
2056
2057	/* Iterate through all internalformats */
2058	const glw::GLenum internalformats[] = {
2059		GL_RGB8, GL_RGB565, GL_SRGB8_ALPHA8, GL_DEPTH_COMPONENT32F, GL_DEPTH24_STENCIL8, GL_RGBA32I
2060	};
2061	const unsigned int n_internalformats = sizeof(internalformats) / sizeof(internalformats[0]);
2062
2063	for (unsigned int n_internalformat = 0; n_internalformat < n_internalformats; ++n_internalformat)
2064	{
2065		glw::GLenum internalformat = internalformats[n_internalformat];
2066
2067		/* Determine a value to be used for samples argument in subsequent
2068		 * glTexStorage2DMultisample() call. */
2069		gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, internalformat, GL_SAMPLES, 1,
2070							   &gl_max_internalformat_samples);
2071
2072		GLU_EXPECT_NO_ERROR(gl.getError(),
2073							"Could not retrieve maximum supported amount of samples for internal format");
2074
2075		glw::GLint samples = gl_max_internalformat_samples;
2076
2077		/* Skip formats that are not multisampled in implementation */
2078		if (samples <= 1)
2079		{
2080			continue;
2081		}
2082
2083		/* Set up a texture object. */
2084		gl.genTextures(1, &to_id);
2085		gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id);
2086
2087		gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, internalformat, 1, /* width */
2088								   1,													  /* height */
2089								   GL_FALSE);											  /* fixedsamplelocations */
2090
2091		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a texture object");
2092
2093		/* Determine attachment type for internalformat considered */
2094		glw::GLenum attachment_type = GL_COLOR_ATTACHMENT0;
2095
2096		if (internalformat == GL_DEPTH_COMPONENT32F)
2097		{
2098			attachment_type = GL_DEPTH_ATTACHMENT;
2099		}
2100		else if (internalformat == GL_DEPTH24_STENCIL8)
2101		{
2102			attachment_type = GL_DEPTH_STENCIL_ATTACHMENT;
2103		}
2104
2105		/* Attach it to the FBO */
2106		gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment_type, GL_TEXTURE_2D_MULTISAMPLE, to_id, 0); /* level */
2107
2108		GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
2109
2110		/* Release the texture object */
2111		gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
2112		gl.deleteTextures(1, &to_id);
2113
2114		to_id = 0;
2115
2116		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not release the texture object");
2117	} /* for (all internalformats) */
2118
2119	/* All done */
2120	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2121
2122	return STOP;
2123}
2124
2125/** Constructor.
2126 *
2127 *  @param context CTS context handle.
2128 **/
2129MultisampleTextureDependenciesNoErrorGeneratedForValidRenderbufferStorageMultisampleCallsTest::
2130	MultisampleTextureDependenciesNoErrorGeneratedForValidRenderbufferStorageMultisampleCallsTest(Context& context)
2131	: TestCase(context, "no_error_generated_for_valid_renderbuffer_storage_multisample_calls",
2132			   "No error is reported for valid glRenderbufferStorageMultisample() calls.")
2133	, rbo_id(0)
2134{
2135	/* Left blank on purpose */
2136}
2137
2138/** Deinitializes ES objects created during test execution */
2139void MultisampleTextureDependenciesNoErrorGeneratedForValidRenderbufferStorageMultisampleCallsTest::deinit()
2140{
2141	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2142
2143	if (rbo_id != 0)
2144	{
2145		gl.deleteRenderbuffers(1, &rbo_id);
2146
2147		rbo_id = 0;
2148	}
2149
2150	/* Call base class' deinit() */
2151	TestCase::deinit();
2152}
2153
2154/** Initializes ES objects created during test execution */
2155void MultisampleTextureDependenciesNoErrorGeneratedForValidRenderbufferStorageMultisampleCallsTest::initInternals()
2156{
2157	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2158
2159	gl.genRenderbuffers(1, &rbo_id);
2160	gl.bindRenderbuffer(GL_RENDERBUFFER, rbo_id);
2161
2162	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a renderbuffer object");
2163}
2164
2165/** Executes test iteration.
2166 *
2167 *  @return Returns STOP when test has finished executing.
2168 */
2169tcu::TestNode::IterateResult MultisampleTextureDependenciesNoErrorGeneratedForValidRenderbufferStorageMultisampleCallsTest::
2170	iterate()
2171{
2172	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2173
2174	initInternals();
2175
2176	/* For storing format specific maximum number of samples */
2177	glw::GLint gl_max_internalformat_samples = 0;
2178
2179	/* Iterate through a set of valid non-integer and integer
2180	 internalformats and a set of all legal samples argument values */
2181	const glw::GLenum internalformats[] = {
2182		GL_RGB8,		   GL_RGB565, GL_SRGB8_ALPHA8, GL_DEPTH_COMPONENT32F, GL_DEPTH24_STENCIL8,
2183		GL_STENCIL_INDEX8, GL_RG8UI,  GL_RGBA32I
2184	};
2185	const unsigned int n_internalformats = sizeof(internalformats) / sizeof(internalformats[0]);
2186
2187	for (unsigned int n_internalformat = 0; n_internalformat < n_internalformats; ++n_internalformat)
2188	{
2189		glw::GLenum internalformat = internalformats[n_internalformat];
2190
2191		/* Determine a value to be used for samples argument in subsequent
2192		 * glTexStorage2DMultisample() call. */
2193		gl.getInternalformativ(GL_RENDERBUFFER, internalformat, GL_SAMPLES, 1, &gl_max_internalformat_samples);
2194
2195		GLU_EXPECT_NO_ERROR(gl.getError(),
2196							"Could not retrieve maximum supported amount of samples for internal format");
2197
2198		for (int samples = 1; samples <= gl_max_internalformat_samples; ++samples)
2199		{
2200			/* Execute the test */
2201			gl.renderbufferStorageMultisample(GL_RENDERBUFFER, samples, internalformat, 1, 1);
2202
2203			GLU_EXPECT_NO_ERROR(gl.getError(),
2204								"A valid glRenderbufferStorageMultisample() call has reported an error.");
2205		} /* for (all legal samples argument values) */
2206	}	 /* for (all internalformats) */
2207
2208	/* All done */
2209	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2210
2211	return STOP;
2212}
2213
2214/** Constructor.
2215 *
2216 *  @param context CTS context handle.
2217 **/
2218MultisampleTextureDependenciesTexParameterTest::MultisampleTextureDependenciesTexParameterTest(Context& context)
2219	: TestCase(context, "tex_parameter_support",
2220			   "Verifies glTexParameter*() behavior when used against multisample texture targets")
2221	, to_id_multisample_2d(0)
2222	, to_id_multisample_2d_array(0)
2223{
2224	/* Left blank on purpose */
2225}
2226
2227/* Calls glTexParameterf(), glTexParameterfv(), glTexParameteri() and
2228 * glTexParameteriv(). For each invocation, the function checks if
2229 * the error code reported after each call matches the expected value.
2230 * If the values differ, an info message is logged and TestError exception
2231 * is thrown.
2232 *
2233 * @param expected_error_code Expected GL error code.
2234 * @param value               Integer value to use. For glTexParameterf()
2235 *                            or glTexParameterfv(), the value will be cast
2236 *                            onto a float type prior to calling.
2237 * @param pname               GL pname to use for glTexParameter*() calls.
2238 * @param texture_target      Texture target to use for glTexParameter*() calls.
2239 */
2240void MultisampleTextureDependenciesTexParameterTest::checkAllTexParameterInvocations(glw::GLenum expected_error_code,
2241																					 glw::GLint  value,
2242																					 glw::GLenum pname,
2243																					 glw::GLenum texture_target)
2244{
2245	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2246
2247	glw::GLenum		   error_code  = GL_NO_ERROR;
2248	const glw::GLfloat float_value = (glw::GLfloat)value;
2249	const glw::GLint   int_value   = value;
2250
2251	/* glTexParameterf() */
2252	gl.texParameterf(texture_target, pname, float_value);
2253
2254	error_code = gl.getError();
2255
2256	if (error_code != expected_error_code)
2257	{
2258		m_testCtx.getLog() << tcu::TestLog::Message << "glTexParameterf() call generated an error " << error_code
2259						   << " instead of the expected error code " << expected_error_code << tcu::TestLog::EndMessage;
2260
2261		TCU_FAIL("glTexParameterf() call generated an unexpected error.");
2262	}
2263
2264	/* glTexParameteri() */
2265	gl.texParameteri(texture_target, pname, int_value);
2266
2267	error_code = gl.getError();
2268
2269	if (error_code != expected_error_code)
2270	{
2271		m_testCtx.getLog() << tcu::TestLog::Message << "glTexParameteri() call generated an error " << error_code
2272						   << " instead of the expected error code " << expected_error_code << tcu::TestLog::EndMessage;
2273
2274		TCU_FAIL("glTexParameterf() call generated an unexpected error.");
2275	}
2276
2277	/* glTexParameterfv() */
2278	gl.texParameterfv(texture_target, pname, &float_value);
2279
2280	error_code = gl.getError();
2281
2282	if (error_code != expected_error_code)
2283	{
2284		m_testCtx.getLog() << tcu::TestLog::Message << "glTexParameterfv() call generated an error " << error_code
2285						   << " instead of the expected error code " << expected_error_code << tcu::TestLog::EndMessage;
2286
2287		TCU_FAIL("glTexParameterfv() call generated an unexpected error.");
2288	}
2289
2290	/* glTexParameteriv() */
2291	gl.texParameteriv(texture_target, pname, &int_value);
2292
2293	error_code = gl.getError();
2294
2295	if (error_code != expected_error_code)
2296	{
2297		m_testCtx.getLog() << tcu::TestLog::Message << "glTexParameteriv() call generated an error " << error_code
2298						   << " instead of the expected error code " << expected_error_code << tcu::TestLog::EndMessage;
2299
2300		TCU_FAIL("glTexParameteriv() call generated an unexpected error.");
2301	}
2302}
2303
2304/** Deinitializes ES objects created during test execution */
2305void MultisampleTextureDependenciesTexParameterTest::deinit()
2306{
2307	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2308
2309	if (to_id_multisample_2d != 0)
2310	{
2311		gl.deleteTextures(1, &to_id_multisample_2d);
2312
2313		to_id_multisample_2d = 0;
2314	}
2315
2316	if (to_id_multisample_2d_array != 0)
2317	{
2318		gl.deleteTextures(1, &to_id_multisample_2d_array);
2319
2320		to_id_multisample_2d_array = 0;
2321	}
2322
2323	/* Call base class' deinit() */
2324	TestCase::deinit();
2325}
2326
2327/** Executes test iteration.
2328 *
2329 *  @return Returns STOP when test has finished executing.
2330 */
2331tcu::TestNode::IterateResult MultisampleTextureDependenciesTexParameterTest::iterate()
2332{
2333	bool are_multisample_2d_array_tos_supported =
2334		m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array");
2335	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2336
2337	/* Set up texture objects */
2338	gl.genTextures(1, &to_id_multisample_2d);
2339	gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id_multisample_2d);
2340
2341	if (are_multisample_2d_array_tos_supported)
2342	{
2343		gl.genTextures(1, &to_id_multisample_2d_array);
2344		gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, to_id_multisample_2d_array);
2345	}
2346
2347	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture objects");
2348
2349	gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, /* samples */
2350							   GL_RGBA8, 1,					 /* width */
2351							   1,							 /* height */
2352							   GL_FALSE);					 /* fixedsamplelocations */
2353
2354	GLU_EXPECT_NO_ERROR(gl.getError(),
2355						"glTexStorage2DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE texture target");
2356
2357	if (are_multisample_2d_array_tos_supported)
2358	{
2359		gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 1, /* samples */
2360								   GL_RGBA8, 1,							   /* width */
2361								   1,									   /* height */
2362								   1,									   /* depth */
2363								   GL_FALSE);							   /* fixedsamplelocations */
2364
2365		GLU_EXPECT_NO_ERROR(
2366			gl.getError(),
2367			"gltexStorage3DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES texture target");
2368	}
2369
2370	/* Run the test for both multisample texture targets */
2371	const glw::GLenum  texture_targets[] = { GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES };
2372	const unsigned int n_texture_targets = sizeof(texture_targets) / sizeof(texture_targets[0]);
2373
2374	for (unsigned int n_texture_target = 0; n_texture_target < n_texture_targets; ++n_texture_target)
2375	{
2376		glw::GLenum texture_target = texture_targets[n_texture_target];
2377
2378		if (!are_multisample_2d_array_tos_supported && texture_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES)
2379		{
2380			/* Skip the iteration */
2381			continue;
2382		}
2383
2384		/* Verify that setting GL_TEXTURE_BASE_LEVEL to 0 does not generate any 0. Using any other
2385		 * value should generate GL_INVALID_OPERATION
2386		 */
2387		for (int n_iteration = 0; n_iteration < 2 /* iterations */; ++n_iteration)
2388		{
2389			glw::GLenum expected_error_code = (n_iteration == 0) ? GL_NO_ERROR : GL_INVALID_OPERATION;
2390			glw::GLint  int_value			= (n_iteration == 0) ? 0 : 1;
2391
2392			checkAllTexParameterInvocations(expected_error_code, int_value, GL_TEXTURE_BASE_LEVEL, texture_target);
2393		} /* for (all iterations) */
2394	}	 /* for (both texture targets) */
2395
2396	/* Make sure that modifying sampler state information results in an error
2397	 * for multisample texture targets. */
2398	const glw::GLenum sampler_pnames[] = { GL_TEXTURE_MIN_FILTER, GL_TEXTURE_MAG_FILTER,   GL_TEXTURE_WRAP_S,
2399										   GL_TEXTURE_WRAP_T,	 GL_TEXTURE_WRAP_R,	   GL_TEXTURE_MIN_LOD,
2400										   GL_TEXTURE_MAX_LOD,	GL_TEXTURE_COMPARE_MODE, GL_TEXTURE_COMPARE_FUNC };
2401	const unsigned int n_sampler_pnames = sizeof(sampler_pnames) / sizeof(sampler_pnames[0]);
2402
2403	for (unsigned int n_sampler_pname = 0; n_sampler_pname < n_sampler_pnames; ++n_sampler_pname)
2404	{
2405		glw::GLenum pname = sampler_pnames[n_sampler_pname];
2406
2407		for (unsigned int n_texture_target = 0; n_texture_target < n_texture_targets; ++n_texture_target)
2408		{
2409			glw::GLenum texture_target = texture_targets[n_texture_target];
2410
2411			if (!are_multisample_2d_array_tos_supported && texture_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES)
2412			{
2413				/* Skip the iteration */
2414				continue;
2415			}
2416
2417			/* When <target> is TEXTURE_2D_MULTISAMPLE or
2418			 TEXTURE_2D_MULTISAMPLE_ARRAY, certain texture parameters may not be
2419			 specified. In this case, an INVALID_ENUM */
2420			checkAllTexParameterInvocations(GL_INVALID_ENUM, 0, pname, texture_target);
2421
2422		} /* for (all texture targets) */
2423	}	 /* for (all sampler properties) */
2424
2425	/* Make sure that modifying remaining texture parameters does not result in an error for
2426	 * multisample texture targets. */
2427	for (unsigned int n_texture_target = 0; n_texture_target < n_texture_targets; ++n_texture_target)
2428	{
2429		glw::GLenum texture_target = texture_targets[n_texture_target];
2430
2431		if (!are_multisample_2d_array_tos_supported && texture_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES)
2432		{
2433			/* Skip the iteration */
2434			continue;
2435		}
2436
2437		checkAllTexParameterInvocations(GL_NO_ERROR, 10, GL_TEXTURE_MAX_LEVEL, texture_target);
2438		checkAllTexParameterInvocations(GL_NO_ERROR, GL_GREEN, GL_TEXTURE_SWIZZLE_R, texture_target);
2439		checkAllTexParameterInvocations(GL_NO_ERROR, GL_BLUE, GL_TEXTURE_SWIZZLE_G, texture_target);
2440		checkAllTexParameterInvocations(GL_NO_ERROR, GL_ALPHA, GL_TEXTURE_SWIZZLE_B, texture_target);
2441		checkAllTexParameterInvocations(GL_NO_ERROR, GL_RED, GL_TEXTURE_SWIZZLE_A, texture_target);
2442	}
2443
2444	/* All done */
2445	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2446
2447	return STOP;
2448}
2449} /* glcts namespace */
2450