1/*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 2.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 "es2fRboStateQueryTests.hpp"
25#include "glsStateQueryUtil.hpp"
26#include "es2fApiCase.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 gles2
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 checkRenderbufferParam (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLenum pname, GLenum reference)
96{
97	StateQueryMemoryWriteGuard<GLint> state;
98	gl.glGetRenderbufferParameteriv(GL_RENDERBUFFER, pname, &state);
99
100	if (state.verifyValidity(testCtx))
101		checkIntEquals(testCtx, state, reference);
102}
103
104class RboSizeCase : public ApiCase
105{
106public:
107	RboSizeCase (Context& context, const char* name, const char* description)
108		: ApiCase(context, name, description)
109	{
110	}
111
112	void test (void)
113	{
114		de::Random rnd(0xabcdef);
115
116		GLuint renderbufferID = 0;
117		glGenRenderbuffers(1, &renderbufferID);
118		glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID);
119		expectError(GL_NO_ERROR);
120
121		checkRenderbufferParam(m_testCtx, *this, GL_RENDERBUFFER_WIDTH,		0);
122		checkRenderbufferParam(m_testCtx, *this, GL_RENDERBUFFER_HEIGHT,	0);
123		expectError(GL_NO_ERROR);
124
125		const int numIterations = 30;
126		for (int i = 0; i < numIterations; ++i)
127		{
128			const GLint w = rnd.getInt(0, 128);
129			const GLint h = rnd.getInt(0, 128);
130
131			glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, w, h);
132			expectError(GL_NO_ERROR);
133
134			checkRenderbufferParam(m_testCtx, *this, GL_RENDERBUFFER_WIDTH,		w);
135			checkRenderbufferParam(m_testCtx, *this, GL_RENDERBUFFER_HEIGHT,	h);
136		}
137
138		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0);
139		glDeleteRenderbuffers(1, &renderbufferID);
140	}
141};
142
143class RboInternalFormatCase : public ApiCase
144{
145public:
146	RboInternalFormatCase (Context& context, const char* name, const char* description)
147		: ApiCase(context, name, description)
148	{
149	}
150
151	void test (void)
152	{
153		GLuint renderbufferID = 0;
154		glGenRenderbuffers(1, &renderbufferID);
155		glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID);
156		expectError(GL_NO_ERROR);
157
158		checkRenderbufferParam(m_testCtx, *this, GL_RENDERBUFFER_INTERNAL_FORMAT, GL_RGBA4);
159		expectError(GL_NO_ERROR);
160
161		const GLenum requiredColorformats[] =
162		{
163			GL_RGBA4, GL_RGB5_A1, GL_RGB565
164		};
165
166		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(requiredColorformats); ++ndx)
167		{
168			glRenderbufferStorage(GL_RENDERBUFFER, requiredColorformats[ndx], 1, 1);
169			expectError(GL_NO_ERROR);
170
171			checkRenderbufferParam(m_testCtx, *this, GL_RENDERBUFFER_INTERNAL_FORMAT, requiredColorformats[ndx]);
172		}
173
174		glDeleteRenderbuffers(1, &renderbufferID);
175	}
176};
177
178class RboComponentSizeColorCase : public ApiCase
179{
180public:
181	RboComponentSizeColorCase (Context& context, const char* name, const char* description)
182		: ApiCase(context, name, description)
183	{
184	}
185
186	void test (void)
187	{
188		GLuint renderbufferID = 0;
189		glGenRenderbuffers(1, &renderbufferID);
190		glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID);
191		expectError(GL_NO_ERROR);
192
193		checkRenderbufferComponentSize(m_testCtx, *this, 0, 0, 0, 0, 0, 0);
194		expectError(GL_NO_ERROR);
195
196		const struct ColorFormat
197		{
198			GLenum	internalFormat;
199			int		bitsR, bitsG, bitsB, bitsA;
200		} requiredColorFormats[] =
201		{
202			{ GL_RGBA4,			4,	4,	4,	4	},
203			{ GL_RGB5_A1,		5,	5,	5,	1	},
204			{ GL_RGB565,		5,	6,	5,	0	},
205		};
206
207		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(requiredColorFormats); ++ndx)
208		{
209			glRenderbufferStorage(GL_RENDERBUFFER, requiredColorFormats[ndx].internalFormat, 1, 1);
210			expectError(GL_NO_ERROR);
211
212			checkRenderbufferComponentSize(m_testCtx, *this, requiredColorFormats[ndx].bitsR, requiredColorFormats[ndx].bitsG, requiredColorFormats[ndx].bitsB, requiredColorFormats[ndx].bitsA, -1, -1);
213		}
214
215		glDeleteRenderbuffers(1, &renderbufferID);
216	}
217};
218
219class RboComponentSizeDepthCase : public ApiCase
220{
221public:
222	RboComponentSizeDepthCase (Context& context, const char* name, const char* description)
223		: ApiCase(context, name, description)
224	{
225	}
226
227	void test (void)
228	{
229		using tcu::TestLog;
230
231		GLuint renderbufferID = 0;
232		glGenRenderbuffers(1, &renderbufferID);
233		glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID);
234		expectError(GL_NO_ERROR);
235
236		const struct DepthFormat
237		{
238			GLenum	internalFormat;
239			int		dbits;
240			int		sbits;
241		} requiredDepthFormats[] =
242		{
243			{ GL_DEPTH_COMPONENT16,		16, 0 },
244		};
245
246		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(requiredDepthFormats); ++ndx)
247		{
248			glRenderbufferStorage(GL_RENDERBUFFER, requiredDepthFormats[ndx].internalFormat, 1, 1);
249			expectError(GL_NO_ERROR);
250
251			checkRenderbufferComponentSize(m_testCtx, *this, -1, -1, -1, -1, requiredDepthFormats[ndx].dbits, requiredDepthFormats[ndx].sbits);
252		}
253
254		// STENCIL_INDEX8 is required, in that case sBits >= 8
255		{
256			glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, 1, 1);
257			expectError(GL_NO_ERROR);
258
259			StateQueryMemoryWriteGuard<GLint> state;
260			glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_STENCIL_SIZE, &state);
261
262			if (state.verifyValidity(m_testCtx) && state < 8)
263			{
264				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected greater or equal to 8; got " << state << TestLog::EndMessage;
265				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
266					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value");
267			}
268		}
269
270		glDeleteRenderbuffers(1, &renderbufferID);
271	}
272};
273
274} // anonymous
275
276
277RboStateQueryTests::RboStateQueryTests (Context& context)
278	: TestCaseGroup(context, "rbo", "Rbo State Query tests")
279{
280}
281
282void RboStateQueryTests::init (void)
283{
284	addChild(new RboSizeCase				(m_context, "renderbuffer_size",					"RENDERBUFFER_WIDTH and RENDERBUFFER_HEIGHT"));
285	addChild(new RboInternalFormatCase		(m_context, "renderbuffer_internal_format",			"RENDERBUFFER_INTERNAL_FORMAT"));
286	addChild(new RboComponentSizeColorCase	(m_context, "renderbuffer_component_size_color",	"RENDERBUFFER_x_SIZE"));
287	addChild(new RboComponentSizeDepthCase	(m_context, "renderbuffer_component_size_depth",	"RENDERBUFFER_x_SIZE"));
288}
289
290} // Functional
291} // gles2
292} // deqp
293