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 Internal Format Query tests.
22 *//*--------------------------------------------------------------------*/
23
24#include "es3fInternalFormatQueryTests.hpp"
25#include "glsStateQueryUtil.hpp"
26#include "es3fApiCase.hpp"
27#include "gluRenderContext.hpp"
28#include "glwEnums.hpp"
29#include "glwFunctions.hpp"
30#include "deMath.h"
31
32using namespace glw; // GLint and other GL types
33using deqp::gls::StateQueryUtil::StateQueryMemoryWriteGuard;
34
35namespace deqp
36{
37namespace gles3
38{
39namespace Functional
40{
41namespace
42{
43
44class SamplesCase : public ApiCase
45{
46public:
47	SamplesCase(Context& context, const char* name, const char* description, GLenum internalFormat, bool isIntegerInternalFormat)
48		: ApiCase					(context, name, description)
49		, m_internalFormat			(internalFormat)
50		, m_isIntegerInternalFormat	(isIntegerInternalFormat)
51	{
52	}
53
54	void test (void)
55	{
56		using tcu::TestLog;
57
58		StateQueryMemoryWriteGuard<GLint> sampleCounts;
59		glGetInternalformativ(GL_RENDERBUFFER, m_internalFormat, GL_NUM_SAMPLE_COUNTS, 1, &sampleCounts);
60		expectError(GL_NO_ERROR);
61
62		if (!sampleCounts.verifyValidity(m_testCtx))
63			return;
64
65		m_testCtx.getLog() << TestLog::Message << "// sample counts is " << sampleCounts << TestLog::EndMessage;
66
67		if (m_isIntegerInternalFormat && sampleCounts != 0)
68		{
69			// Since multisampling is not supported for signed and unsigned integer internal
70			// formats, the value of NUM_SAMPLE_COUNTS will be zero for such formats.
71			m_testCtx.getLog() << TestLog::Message << "// ERROR: integer internal formats should have NUM_SAMPLE_COUNTS = 0; got " << sampleCounts << TestLog::EndMessage;
72			if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
73				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value");
74		}
75
76		if (sampleCounts == 0)
77			return;
78
79		std::vector<GLint> samples;
80		samples.resize(sampleCounts, -1);
81		glGetInternalformativ(GL_RENDERBUFFER, m_internalFormat, GL_SAMPLES, sampleCounts, &samples[0]);
82		expectError(GL_NO_ERROR);
83
84		GLint prevSampleCount = 0;
85		GLint sampleCount = 0;
86		for (size_t ndx = 0; ndx < samples.size(); ++ndx, prevSampleCount = sampleCount)
87		{
88			sampleCount = samples[ndx];
89
90			// sample count must be > 0
91			if (sampleCount <= 0)
92			{
93				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected sample count to be at least one; got " << sampleCount << TestLog::EndMessage;
94				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
95					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value");
96			}
97
98			// samples must be ordered descending
99			if (ndx != 0 && !(sampleCount < prevSampleCount))
100			{
101				m_testCtx.getLog() << TestLog::Message
102					<< "// ERROR: Expected sample count to be ordered in descending order;"
103					<< "got " << prevSampleCount << " at index " << (ndx - 1) << ", and " << sampleCount << " at index " << ndx << TestLog::EndMessage;
104				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
105					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid order");
106			}
107		}
108
109		// the maximum value in SAMPLES is guaranteed to be at least the value of MAX_SAMPLES
110		StateQueryMemoryWriteGuard<GLint> maxSamples;
111		glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
112		expectError(GL_NO_ERROR);
113
114		if (maxSamples.verifyValidity(m_testCtx))
115		{
116			const GLint maximumFormatSampleCount = samples[0];
117			if (!(maximumFormatSampleCount >= maxSamples))
118			{
119				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected maximum value in SAMPLES (" << maximumFormatSampleCount << ") to be at least the value of MAX_SAMPLES (" << maxSamples << ")" << TestLog::EndMessage;
120				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
121					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid maximum sample count");
122			}
123		}
124	}
125
126private:
127	GLenum	m_internalFormat;
128	bool	m_isIntegerInternalFormat;
129};
130
131class SamplesBufferSizeCase : public ApiCase
132{
133public:
134	SamplesBufferSizeCase(Context& context, const char* name, const char* description, GLenum internalFormat)
135		: ApiCase			(context, name, description)
136		, m_internalFormat	(internalFormat)
137	{
138	}
139
140	void test (void)
141	{
142		using tcu::TestLog;
143
144		StateQueryMemoryWriteGuard<GLint> sampleCounts;
145		glGetInternalformativ(GL_RENDERBUFFER, m_internalFormat, GL_NUM_SAMPLE_COUNTS, 1, &sampleCounts);
146		expectError(GL_NO_ERROR);
147
148		if (!sampleCounts.verifyValidity(m_testCtx))
149			return;
150
151		// test with bufSize = 0
152		GLint queryTargetValue = -1;
153		glGetInternalformativ(GL_RENDERBUFFER, m_internalFormat, GL_NUM_SAMPLE_COUNTS, 0, &queryTargetValue);
154		expectError(GL_NO_ERROR);
155
156		if (queryTargetValue != -1)
157		{
158			m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected output variable not to be written to." << TestLog::EndMessage;
159			if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
160				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid write");
161		}
162	}
163
164private:
165	GLenum m_internalFormat;
166};
167
168} // anonymous
169
170
171InternalFormatQueryTests::InternalFormatQueryTests (Context& context)
172	: TestCaseGroup(context, "internal_format", "Internal Format Query tests.")
173{
174}
175
176void InternalFormatQueryTests::init (void)
177{
178	const struct InternalFormat
179	{
180		const char*	name;
181		GLenum		format;
182		bool		isIntegerFormat;
183	} internalFormats[] =
184	{
185		// color renderable and unsized
186		// \note These unsized formats seem to allowed by the spec, but they are not useful in any way. (You can't create a renderbuffer with such internalFormat)
187		{ "rgba",					GL_RGBA,				false	},
188		{ "rgb",					GL_RGB,					false	},
189
190		// color renderable
191		{ "r8",						GL_R8,					false	},
192		{ "rg8",					GL_RG8,					false	},
193		{ "rgb8",					GL_RGB8,				false	},
194		{ "rgb565",					GL_RGB565,				false	},
195		{ "rgba4",					GL_RGBA4,				false	},
196		{ "rgb5_a1",				GL_RGB5_A1,				false	},
197		{ "rgba8",					GL_RGBA8,				false	},
198		{ "rgb10_a2",				GL_RGB10_A2,			false	},
199		{ "rgb10_a2ui",				GL_RGB10_A2UI,			true	},
200		{ "srgb8_alpha8",			GL_SRGB8_ALPHA8,		false	},
201		{ "r8i",					GL_R8I,					true	},
202		{ "r8ui",					GL_R8UI,				true	},
203		{ "r16i",					GL_R16I,				true	},
204		{ "r16ui",					GL_R16UI,				true	},
205		{ "r32i",					GL_R32I,				true	},
206		{ "r32ui",					GL_R32UI,				true	},
207		{ "rg8i",					GL_RG8I,				true	},
208		{ "rg8ui",					GL_RG8UI,				true	},
209		{ "rg16i",					GL_RG16I,				true	},
210		{ "rg16ui",					GL_RG16UI,				true	},
211		{ "rg32i",					GL_RG32I,				true	},
212		{ "rg32ui",					GL_RG32UI,				true	},
213		{ "rgba8i",					GL_RGBA8I,				true	},
214		{ "rgba8ui",				GL_RGBA8UI,				true	},
215		{ "rgba16i",				GL_RGBA16I,				true	},
216		{ "rgba16ui",				GL_RGBA16UI,			true	},
217		{ "rgba32i",				GL_RGBA32I,				true	},
218		{ "rgba32ui",				GL_RGBA32UI,			true	},
219
220		// depth renderable
221		{ "depth_component16",		GL_DEPTH_COMPONENT16,	false	},
222		{ "depth_component24",		GL_DEPTH_COMPONENT24,	false	},
223		{ "depth_component32f",		GL_DEPTH_COMPONENT32F,	false	},
224		{ "depth24_stencil8",		GL_DEPTH24_STENCIL8,	false	},
225		{ "depth32f_stencil8",		GL_DEPTH32F_STENCIL8,	false	},
226
227		// stencil renderable
228		{ "stencil_index8",			GL_STENCIL_INDEX8,		false	}
229		// DEPTH24_STENCIL8,  duplicate
230		// DEPTH32F_STENCIL8  duplicate
231	};
232
233	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(internalFormats); ++ndx)
234	{
235		const InternalFormat internalFormat = internalFormats[ndx];
236
237		addChild(new SamplesCase(m_context, (std::string(internalFormat.name) + "_samples").c_str(), "SAMPLES and NUM_SAMPLE_COUNTS", internalFormat.format, internalFormat.isIntegerFormat));
238	}
239
240	addChild(new SamplesBufferSizeCase(m_context, "rgba8_samples_buffer", "SAMPLES bufSize parameter", GL_RGBA8));
241}
242
243} // Functional
244} // gles3
245} // deqp
246