1/*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.0 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Rbo state query tests.
22 *//*--------------------------------------------------------------------*/
23
24#include "es3fRboStateQueryTests.hpp"
25#include "glsStateQueryUtil.hpp"
26#include "es3fApiCase.hpp"
27#include "gluRenderContext.hpp"
28#include "glwEnums.hpp"
29#include "glwFunctions.hpp"
30#include "deRandom.hpp"
31#include "deMath.h"
32
33using namespace glw; // GLint and other GL types
34using deqp::gls::StateQueryUtil::StateQueryMemoryWriteGuard;
35
36
37namespace deqp
38{
39namespace gles3
40{
41namespace Functional
42{
43namespace
44{
45
46void checkRenderbufferComponentSize (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, int r, int g, int b, int a, int d, int s)
47{
48	using tcu::TestLog;
49
50	const int referenceSizes[] = {r, g, b, a, d, s};
51	const GLenum paramNames[] =
52	{
53		GL_RENDERBUFFER_RED_SIZE,
54		GL_RENDERBUFFER_GREEN_SIZE,
55		GL_RENDERBUFFER_BLUE_SIZE,
56		GL_RENDERBUFFER_ALPHA_SIZE,
57		GL_RENDERBUFFER_DEPTH_SIZE,
58		GL_RENDERBUFFER_STENCIL_SIZE
59	};
60
61	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(referenceSizes) == DE_LENGTH_OF_ARRAY(paramNames));
62
63	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(referenceSizes); ++ndx)
64	{
65		if (referenceSizes[ndx] == -1)
66			continue;
67
68		StateQueryMemoryWriteGuard<GLint> state;
69		gl.glGetRenderbufferParameteriv(GL_RENDERBUFFER, paramNames[ndx], &state);
70
71		if (!state.verifyValidity(testCtx))
72			return;
73
74		if (state < referenceSizes[ndx])
75		{
76			testCtx.getLog() << TestLog::Message << "// ERROR: Expected greater or equal to " << referenceSizes[ndx] << "; got " << state << TestLog::EndMessage;
77			if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
78				testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value");
79		}
80	}
81}
82
83void checkIntEquals (tcu::TestContext& testCtx, GLint got, GLint expected)
84{
85	using tcu::TestLog;
86
87	if (got != expected)
88	{
89		testCtx.getLog() << TestLog::Message << "// ERROR: Expected " << expected << "; got " << got << TestLog::EndMessage;
90		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
91			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value");
92	}
93}
94
95void checkIntGreaterOrEqual (tcu::TestContext& testCtx, GLint got, GLint expected)
96{
97	using tcu::TestLog;
98
99	if (got < expected)
100	{
101		testCtx.getLog() << TestLog::Message << "// ERROR: Expected greater or equal to " << expected << "; got " << got << TestLog::EndMessage;
102		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
103			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value");
104	}
105}
106
107void checkRenderbufferParam (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLenum pname, GLenum reference)
108{
109	StateQueryMemoryWriteGuard<GLint> state;
110	gl.glGetRenderbufferParameteriv(GL_RENDERBUFFER, pname, &state);
111
112	if (state.verifyValidity(testCtx))
113		checkIntEquals(testCtx, state, reference);
114}
115
116void checkRenderbufferParamGreaterOrEqual (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLenum pname, GLenum reference)
117{
118	StateQueryMemoryWriteGuard<GLint> state;
119	gl.glGetRenderbufferParameteriv(GL_RENDERBUFFER, pname, &state);
120
121	if (state.verifyValidity(testCtx))
122		checkIntGreaterOrEqual(testCtx, state, reference);
123}
124
125class RboSizeCase : public ApiCase
126{
127public:
128	RboSizeCase (Context& context, const char* name, const char* description)
129		: ApiCase(context, name, description)
130	{
131	}
132
133	void test (void)
134	{
135		de::Random rnd(0xabcdef);
136
137		GLuint renderbufferID = 0;
138		glGenRenderbuffers(1, &renderbufferID);
139		glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID);
140		expectError(GL_NO_ERROR);
141
142		checkRenderbufferParam(m_testCtx, *this, GL_RENDERBUFFER_WIDTH,		0);
143		checkRenderbufferParam(m_testCtx, *this, GL_RENDERBUFFER_HEIGHT,	0);
144		expectError(GL_NO_ERROR);
145
146		const int numIterations = 60;
147		for (int i = 0; i < numIterations; ++i)
148		{
149			const GLint w = rnd.getInt(0, 128);
150			const GLint h = rnd.getInt(0, 128);
151
152			glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8, w, h);
153
154			checkRenderbufferParam(m_testCtx, *this, GL_RENDERBUFFER_WIDTH,		w);
155			checkRenderbufferParam(m_testCtx, *this, GL_RENDERBUFFER_HEIGHT,	h);
156		}
157
158		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0);
159		glDeleteRenderbuffers(1, &renderbufferID);
160	}
161};
162
163class RboInternalFormatCase : public ApiCase
164{
165public:
166	RboInternalFormatCase (Context& context, const char* name, const char* description)
167		: ApiCase(context, name, description)
168	{
169	}
170
171	void test (void)
172	{
173		GLuint renderbufferID = 0;
174		glGenRenderbuffers(1, &renderbufferID);
175		glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID);
176		expectError(GL_NO_ERROR);
177
178		checkRenderbufferParam(m_testCtx, *this, GL_RENDERBUFFER_INTERNAL_FORMAT, GL_RGBA4);
179		expectError(GL_NO_ERROR);
180
181		const GLenum requiredColorformats[] =
182		{
183			GL_R8, GL_RG8, GL_RGB8, GL_RGB565, GL_RGBA4, GL_RGB5_A1, GL_RGBA8, GL_RGB10_A2,
184			GL_RGB10_A2UI, GL_SRGB8_ALPHA8, GL_R8I, GL_R8UI, GL_R16I, GL_R16UI, GL_R32I, GL_R32UI,
185			GL_RG8I, GL_RG8UI, GL_RG16I, GL_RG16UI, GL_RG32I, GL_RG32UI, GL_RGBA8I, GL_RGBA8UI,
186			GL_RGBA16I, GL_RGBA16UI, GL_RGBA32I, GL_RGBA32UI
187		};
188
189		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(requiredColorformats); ++ndx)
190		{
191			glRenderbufferStorage(GL_RENDERBUFFER, requiredColorformats[ndx], 128, 128);
192			expectError(GL_NO_ERROR);
193
194			checkRenderbufferParam(m_testCtx, *this, GL_RENDERBUFFER_INTERNAL_FORMAT, requiredColorformats[ndx]);
195		}
196
197		glDeleteRenderbuffers(1, &renderbufferID);
198	}
199};
200
201class RboComponentSizeColorCase : public ApiCase
202{
203public:
204	RboComponentSizeColorCase (Context& context, const char* name, const char* description)
205		: ApiCase(context, name, description)
206	{
207	}
208
209	void test (void)
210	{
211		GLuint renderbufferID = 0;
212		glGenRenderbuffers(1, &renderbufferID);
213		glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID);
214		expectError(GL_NO_ERROR);
215
216		checkRenderbufferComponentSize(m_testCtx, *this, 0, 0, 0, 0, 0, 0);
217		expectError(GL_NO_ERROR);
218
219		const struct ColorFormat
220		{
221			GLenum	internalFormat;
222			int		bitsR, bitsG, bitsB, bitsA;
223		} requiredColorFormats[] =
224		{
225			{ GL_R8,			8,	0,	0,	0	},
226			{ GL_RG8,			8,	8,	0,	0	},
227			{ GL_RGB8,			8,	8,	8,	0	},
228			{ GL_RGB565,		5,	6,	5,	0	},
229			{ GL_RGBA4,			4,	4,	4,	4	},
230			{ GL_RGB5_A1, 		5,	5,	5,	1	},
231			{ GL_RGBA8,			8,	8,	8,	8	},
232			{ GL_RGB10_A2,		10, 10, 10, 2	},
233			{ GL_RGB10_A2UI,	10, 10, 10, 2	},
234			{ GL_SRGB8_ALPHA8,	8,	8,	8,	8	},
235			{ GL_R8I,			8,	0,	0,	0	},
236			{ GL_R8UI,			8,	0,	0,	0	},
237			{ GL_R16I,			16, 0,	0,	0	},
238			{ GL_R16UI,			16, 0,	0,	0	},
239			{ GL_R32I,			32, 0,	0,	0	},
240			{ GL_R32UI,			32, 0,	0,	0	},
241			{ GL_RG8I,			8,	8,	0,	0	},
242			{ GL_RG8UI,			8,	8,	0,	0	},
243			{ GL_RG16I,			16, 16, 0,	0	},
244			{ GL_RG16UI,		16, 16, 0,	0	},
245			{ GL_RG32I,			32, 32, 0,	0	},
246			{ GL_RG32UI,		32, 32, 0,	0	},
247			{ GL_RGBA8I,		8,	8,	8,	8	},
248			{ GL_RGBA8UI,		8,	8,	8,	8	},
249			{ GL_RGBA16I,		16, 16, 16, 16	},
250			{ GL_RGBA16UI,		16, 16, 16, 16	},
251			{ GL_RGBA32I,		32, 32, 32, 32	},
252			{ GL_RGBA32UI,		32, 32, 32, 32	}
253		};
254
255		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(requiredColorFormats); ++ndx)
256		{
257			glRenderbufferStorage(GL_RENDERBUFFER, requiredColorFormats[ndx].internalFormat, 128, 128);
258			expectError(GL_NO_ERROR);
259
260			checkRenderbufferComponentSize(m_testCtx, *this, requiredColorFormats[ndx].bitsR, requiredColorFormats[ndx].bitsG, requiredColorFormats[ndx].bitsB, requiredColorFormats[ndx].bitsA, -1, -1);
261		}
262
263		glDeleteRenderbuffers(1, &renderbufferID);
264	}
265};
266
267class RboComponentSizeDepthCase : public ApiCase
268{
269public:
270	RboComponentSizeDepthCase (Context& context, const char* name, const char* description)
271		: ApiCase(context, name, description)
272	{
273	}
274
275	void test (void)
276	{
277		using tcu::TestLog;
278
279		GLuint renderbufferID = 0;
280		glGenRenderbuffers(1, &renderbufferID);
281		glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID);
282		expectError(GL_NO_ERROR);
283
284		const struct DepthFormat
285		{
286			GLenum	internalFormat;
287			int		dbits;
288			int		sbits;
289		} requiredDepthFormats[] =
290		{
291			{ GL_DEPTH_COMPONENT16,		16, 0 },
292			{ GL_DEPTH_COMPONENT24,		24, 0 },
293			{ GL_DEPTH_COMPONENT32F,	32, 0 },
294			{ GL_DEPTH24_STENCIL8,		24, 8 },
295			{ GL_DEPTH32F_STENCIL8,		32, 8 },
296		};
297
298		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(requiredDepthFormats); ++ndx)
299		{
300			glRenderbufferStorage(GL_RENDERBUFFER, requiredDepthFormats[ndx].internalFormat, 128, 128);
301			expectError(GL_NO_ERROR);
302
303			checkRenderbufferComponentSize(m_testCtx, *this, -1, -1, -1, -1, requiredDepthFormats[ndx].dbits, requiredDepthFormats[ndx].sbits);
304		}
305
306		// STENCIL_INDEX8 is required, in that case sBits >= 8
307		{
308			glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, 128, 128);
309			expectError(GL_NO_ERROR);
310
311			StateQueryMemoryWriteGuard<GLint> state;
312			glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_STENCIL_SIZE, &state);
313
314			if (state.verifyValidity(m_testCtx) && state < 8)
315			{
316				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected greater or equal to 8; got " << state << TestLog::EndMessage;
317				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
318					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value");
319			}
320		}
321
322		glDeleteRenderbuffers(1, &renderbufferID);
323	}
324};
325
326class RboSamplesCase : public ApiCase
327{
328public:
329	RboSamplesCase (Context& context, const char* name, const char* description)
330		: ApiCase(context, name, description)
331	{
332	}
333
334	void test (void)
335	{
336		de::Random rnd(0xabcdef);
337
338		GLuint renderbufferID = 0;
339		glGenRenderbuffers(1, &renderbufferID);
340		glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID);
341		expectError(GL_NO_ERROR);
342
343		checkRenderbufferParam(m_testCtx, *this, GL_RENDERBUFFER_SAMPLES, 0);
344		expectError(GL_NO_ERROR);
345
346		StateQueryMemoryWriteGuard<GLint> max_samples;
347		glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
348		if (!max_samples.verifyValidity(m_testCtx))
349			return;
350
351		// 0 samples is a special case
352		{
353			glRenderbufferStorageMultisample(GL_RENDERBUFFER, 0, GL_RGBA8, 128, 128);
354			expectError(GL_NO_ERROR);
355
356			checkRenderbufferParam(m_testCtx, *this, GL_RENDERBUFFER_SAMPLES, 0);
357		}
358
359		// test [1, n] samples
360		for (int samples = 1; samples <= max_samples; ++samples)
361		{
362			glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_RGBA8, 128, 128);
363			expectError(GL_NO_ERROR);
364
365			checkRenderbufferParamGreaterOrEqual(m_testCtx, *this, GL_RENDERBUFFER_SAMPLES, samples);
366		}
367
368		glDeleteRenderbuffers(1, &renderbufferID);
369	}
370};
371
372} // anonymous
373
374
375RboStateQueryTests::RboStateQueryTests (Context& context)
376	: TestCaseGroup(context, "rbo", "Rbo State Query tests")
377{
378}
379
380void RboStateQueryTests::init (void)
381{
382	addChild(new RboSizeCase				(m_context, "renderbuffer_size",					"RENDERBUFFER_WIDTH and RENDERBUFFER_HEIGHT"));
383	addChild(new RboInternalFormatCase		(m_context, "renderbuffer_internal_format",			"RENDERBUFFER_INTERNAL_FORMAT"));
384	addChild(new RboComponentSizeColorCase	(m_context, "renderbuffer_component_size_color",	"RENDERBUFFER_x_SIZE"));
385	addChild(new RboComponentSizeDepthCase	(m_context, "renderbuffer_component_size_depth",	"RENDERBUFFER_x_SIZE"));
386	addChild(new RboSamplesCase				(m_context, "renderbuffer_samples",					"RENDERBUFFER_SAMPLES"));
387}
388
389} // Functional
390} // gles3
391} // deqp
392