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
33 using namespace glw; // GLint and other GL types
34 using deqp::gls::StateQueryUtil::StateQueryMemoryWriteGuard;
35
36 namespace deqp
37 {
38 namespace gles3
39 {
40 namespace Functional
41 {
42 namespace
43 {
44
checkRenderbufferComponentSize(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,int r,int g,int b,int a,int d,int s)45 void checkRenderbufferComponentSize(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, int r, int g, int b, int a,
46 int d, int s)
47 {
48 using tcu::TestLog;
49
50 const int referenceSizes[] = {r, g, b, a, d, s};
51 const GLenum paramNames[] = {GL_RENDERBUFFER_RED_SIZE, GL_RENDERBUFFER_GREEN_SIZE, GL_RENDERBUFFER_BLUE_SIZE,
52 GL_RENDERBUFFER_ALPHA_SIZE, GL_RENDERBUFFER_DEPTH_SIZE, GL_RENDERBUFFER_STENCIL_SIZE};
53
54 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(referenceSizes) == DE_LENGTH_OF_ARRAY(paramNames));
55
56 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(referenceSizes); ++ndx)
57 {
58 if (referenceSizes[ndx] == -1)
59 continue;
60
61 StateQueryMemoryWriteGuard<GLint> state;
62 gl.glGetRenderbufferParameteriv(GL_RENDERBUFFER, paramNames[ndx], &state);
63
64 if (!state.verifyValidity(testCtx))
65 return;
66
67 if (state < referenceSizes[ndx])
68 {
69 testCtx.getLog() << TestLog::Message << "// ERROR: Expected greater or equal to " << referenceSizes[ndx]
70 << "; got " << state << TestLog::EndMessage;
71 if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
72 testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value");
73 }
74 }
75 }
76
checkIntEquals(tcu::TestContext & testCtx,GLint got,GLint expected)77 void checkIntEquals(tcu::TestContext &testCtx, GLint got, GLint expected)
78 {
79 using tcu::TestLog;
80
81 if (got != expected)
82 {
83 testCtx.getLog() << TestLog::Message << "// ERROR: Expected " << expected << "; got " << got
84 << TestLog::EndMessage;
85 if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
86 testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value");
87 }
88 }
89
checkIntGreaterOrEqual(tcu::TestContext & testCtx,GLint got,GLint expected)90 void checkIntGreaterOrEqual(tcu::TestContext &testCtx, GLint got, GLint expected)
91 {
92 using tcu::TestLog;
93
94 if (got < expected)
95 {
96 testCtx.getLog() << TestLog::Message << "// ERROR: Expected greater or equal to " << expected << "; got " << got
97 << TestLog::EndMessage;
98 if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
99 testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value");
100 }
101 }
102
checkRenderbufferParam(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLenum pname,GLenum reference)103 void checkRenderbufferParam(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLenum pname, GLenum reference)
104 {
105 StateQueryMemoryWriteGuard<GLint> state;
106 gl.glGetRenderbufferParameteriv(GL_RENDERBUFFER, pname, &state);
107
108 if (state.verifyValidity(testCtx))
109 checkIntEquals(testCtx, state, reference);
110 }
111
checkRenderbufferParamGreaterOrEqual(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLenum pname,GLenum reference)112 void checkRenderbufferParamGreaterOrEqual(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLenum pname,
113 GLenum reference)
114 {
115 StateQueryMemoryWriteGuard<GLint> state;
116 gl.glGetRenderbufferParameteriv(GL_RENDERBUFFER, pname, &state);
117
118 if (state.verifyValidity(testCtx))
119 checkIntGreaterOrEqual(testCtx, state, reference);
120 }
121
122 class RboSizeCase : public ApiCase
123 {
124 public:
RboSizeCase(Context & context,const char * name,const char * description)125 RboSizeCase(Context &context, const char *name, const char *description) : ApiCase(context, name, description)
126 {
127 }
128
test(void)129 void test(void)
130 {
131 de::Random rnd(0xabcdef);
132
133 GLuint renderbufferID = 0;
134 glGenRenderbuffers(1, &renderbufferID);
135 glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID);
136 expectError(GL_NO_ERROR);
137
138 checkRenderbufferParam(m_testCtx, *this, GL_RENDERBUFFER_WIDTH, 0);
139 checkRenderbufferParam(m_testCtx, *this, GL_RENDERBUFFER_HEIGHT, 0);
140 expectError(GL_NO_ERROR);
141
142 const int numIterations = 60;
143 for (int i = 0; i < numIterations; ++i)
144 {
145 const GLint w = rnd.getInt(0, 128);
146 const GLint h = rnd.getInt(0, 128);
147
148 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8, w, h);
149
150 checkRenderbufferParam(m_testCtx, *this, GL_RENDERBUFFER_WIDTH, w);
151 checkRenderbufferParam(m_testCtx, *this, GL_RENDERBUFFER_HEIGHT, h);
152 }
153
154 glDeleteRenderbuffers(1, &renderbufferID);
155 }
156 };
157
158 class RboInternalFormatCase : public ApiCase
159 {
160 public:
RboInternalFormatCase(Context & context,const char * name,const char * description)161 RboInternalFormatCase(Context &context, const char *name, const char *description)
162 : ApiCase(context, name, description)
163 {
164 }
165
test(void)166 void test(void)
167 {
168 GLuint renderbufferID = 0;
169 glGenRenderbuffers(1, &renderbufferID);
170 glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID);
171 expectError(GL_NO_ERROR);
172
173 const glu::ContextType &contextType = m_context.getRenderContext().getType();
174 const bool isCoreGL45 = glu::contextSupports(contextType, glu::ApiType::core(4, 5));
175
176 GLenum initialValue = isCoreGL45 ? GL_RGBA : GL_RGBA4;
177 checkRenderbufferParam(m_testCtx, *this, GL_RENDERBUFFER_INTERNAL_FORMAT, initialValue);
178 expectError(GL_NO_ERROR);
179
180 const GLenum requiredColorformats[] = {
181 GL_R8, GL_RG8, GL_RGB8, GL_RGB565, GL_RGBA4, GL_RGB5_A1, GL_RGBA8,
182 GL_RGB10_A2, GL_RGB10_A2UI, GL_SRGB8_ALPHA8, GL_R8I, GL_R8UI, GL_R16I, GL_R16UI,
183 GL_R32I, GL_R32UI, GL_RG8I, GL_RG8UI, GL_RG16I, GL_RG16UI, GL_RG32I,
184 GL_RG32UI, GL_RGBA8I, GL_RGBA8UI, GL_RGBA16I, GL_RGBA16UI, GL_RGBA32I, GL_RGBA32UI};
185
186 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(requiredColorformats); ++ndx)
187 {
188 glRenderbufferStorage(GL_RENDERBUFFER, requiredColorformats[ndx], 128, 128);
189 expectError(GL_NO_ERROR);
190
191 checkRenderbufferParam(m_testCtx, *this, GL_RENDERBUFFER_INTERNAL_FORMAT, requiredColorformats[ndx]);
192 }
193
194 glDeleteRenderbuffers(1, &renderbufferID);
195 }
196 };
197
198 class RboComponentSizeColorCase : public ApiCase
199 {
200 public:
RboComponentSizeColorCase(Context & context,const char * name,const char * description)201 RboComponentSizeColorCase(Context &context, const char *name, const char *description)
202 : ApiCase(context, name, description)
203 {
204 }
205
test(void)206 void test(void)
207 {
208 GLuint renderbufferID = 0;
209 glGenRenderbuffers(1, &renderbufferID);
210 glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID);
211 expectError(GL_NO_ERROR);
212
213 checkRenderbufferComponentSize(m_testCtx, *this, 0, 0, 0, 0, 0, 0);
214 expectError(GL_NO_ERROR);
215
216 const struct ColorFormat
217 {
218 GLenum internalFormat;
219 int bitsR, bitsG, bitsB, bitsA;
220 } requiredColorFormats[] = {
221 {GL_R8, 8, 0, 0, 0}, {GL_RG8, 8, 8, 0, 0}, {GL_RGB8, 8, 8, 8, 0},
222 {GL_RGB565, 5, 6, 5, 0}, {GL_RGBA4, 4, 4, 4, 4}, {GL_RGB5_A1, 5, 5, 5, 1},
223 {GL_RGBA8, 8, 8, 8, 8}, {GL_RGB10_A2, 10, 10, 10, 2}, {GL_RGB10_A2UI, 10, 10, 10, 2},
224 {GL_SRGB8_ALPHA8, 8, 8, 8, 8}, {GL_R8I, 8, 0, 0, 0}, {GL_R8UI, 8, 0, 0, 0},
225 {GL_R16I, 16, 0, 0, 0}, {GL_R16UI, 16, 0, 0, 0}, {GL_R32I, 32, 0, 0, 0},
226 {GL_R32UI, 32, 0, 0, 0}, {GL_RG8I, 8, 8, 0, 0}, {GL_RG8UI, 8, 8, 0, 0},
227 {GL_RG16I, 16, 16, 0, 0}, {GL_RG16UI, 16, 16, 0, 0}, {GL_RG32I, 32, 32, 0, 0},
228 {GL_RG32UI, 32, 32, 0, 0}, {GL_RGBA8I, 8, 8, 8, 8}, {GL_RGBA8UI, 8, 8, 8, 8},
229 {GL_RGBA16I, 16, 16, 16, 16}, {GL_RGBA16UI, 16, 16, 16, 16}, {GL_RGBA32I, 32, 32, 32, 32},
230 {GL_RGBA32UI, 32, 32, 32, 32}};
231
232 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(requiredColorFormats); ++ndx)
233 {
234 glRenderbufferStorage(GL_RENDERBUFFER, requiredColorFormats[ndx].internalFormat, 128, 128);
235 expectError(GL_NO_ERROR);
236
237 checkRenderbufferComponentSize(m_testCtx, *this, requiredColorFormats[ndx].bitsR,
238 requiredColorFormats[ndx].bitsG, requiredColorFormats[ndx].bitsB,
239 requiredColorFormats[ndx].bitsA, -1, -1);
240 }
241
242 glDeleteRenderbuffers(1, &renderbufferID);
243 }
244 };
245
246 class RboComponentSizeDepthCase : public ApiCase
247 {
248 public:
RboComponentSizeDepthCase(Context & context,const char * name,const char * description)249 RboComponentSizeDepthCase(Context &context, const char *name, const char *description)
250 : ApiCase(context, name, description)
251 {
252 }
253
test(void)254 void test(void)
255 {
256 using tcu::TestLog;
257
258 GLuint renderbufferID = 0;
259 glGenRenderbuffers(1, &renderbufferID);
260 glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID);
261 expectError(GL_NO_ERROR);
262
263 const struct DepthFormat
264 {
265 GLenum internalFormat;
266 int dbits;
267 int sbits;
268 } requiredDepthFormats[] = {
269 {GL_DEPTH_COMPONENT16, 16, 0}, {GL_DEPTH_COMPONENT24, 24, 0}, {GL_DEPTH_COMPONENT32F, 32, 0},
270 {GL_DEPTH24_STENCIL8, 24, 8}, {GL_DEPTH32F_STENCIL8, 32, 8},
271 };
272
273 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(requiredDepthFormats); ++ndx)
274 {
275 glRenderbufferStorage(GL_RENDERBUFFER, requiredDepthFormats[ndx].internalFormat, 128, 128);
276 expectError(GL_NO_ERROR);
277
278 checkRenderbufferComponentSize(m_testCtx, *this, -1, -1, -1, -1, requiredDepthFormats[ndx].dbits,
279 requiredDepthFormats[ndx].sbits);
280 }
281
282 // STENCIL_INDEX8 is required, in that case sBits >= 8
283 {
284 glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, 128, 128);
285 expectError(GL_NO_ERROR);
286
287 StateQueryMemoryWriteGuard<GLint> state;
288 glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_STENCIL_SIZE, &state);
289
290 if (state.verifyValidity(m_testCtx) && state < 8)
291 {
292 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected greater or equal to 8; got " << state
293 << TestLog::EndMessage;
294 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
295 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value");
296 }
297 }
298
299 glDeleteRenderbuffers(1, &renderbufferID);
300 }
301 };
302
303 class RboSamplesCase : public ApiCase
304 {
305 public:
RboSamplesCase(Context & context,const char * name,const char * description)306 RboSamplesCase(Context &context, const char *name, const char *description) : ApiCase(context, name, description)
307 {
308 }
309
test(void)310 void test(void)
311 {
312 GLuint renderbufferID = 0;
313 glGenRenderbuffers(1, &renderbufferID);
314 glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID);
315 expectError(GL_NO_ERROR);
316
317 checkRenderbufferParam(m_testCtx, *this, GL_RENDERBUFFER_SAMPLES, 0);
318 expectError(GL_NO_ERROR);
319
320 StateQueryMemoryWriteGuard<GLint> max_samples;
321 glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
322 if (!max_samples.verifyValidity(m_testCtx))
323 return;
324
325 // 0 samples is a special case
326 {
327 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 0, GL_RGBA8, 128, 128);
328 expectError(GL_NO_ERROR);
329
330 checkRenderbufferParam(m_testCtx, *this, GL_RENDERBUFFER_SAMPLES, 0);
331 }
332
333 // test [1, n] samples
334 for (int samples = 1; samples <= max_samples; ++samples)
335 {
336 glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_RGBA8, 128, 128);
337 expectError(GL_NO_ERROR);
338
339 checkRenderbufferParamGreaterOrEqual(m_testCtx, *this, GL_RENDERBUFFER_SAMPLES, samples);
340 }
341
342 glDeleteRenderbuffers(1, &renderbufferID);
343 }
344 };
345
346 } // namespace
347
RboStateQueryTests(Context & context)348 RboStateQueryTests::RboStateQueryTests(Context &context) : TestCaseGroup(context, "rbo", "Rbo State Query tests")
349 {
350 }
351
init(void)352 void RboStateQueryTests::init(void)
353 {
354 addChild(new RboSizeCase(m_context, "renderbuffer_size", "RENDERBUFFER_WIDTH and RENDERBUFFER_HEIGHT"));
355 addChild(new RboInternalFormatCase(m_context, "renderbuffer_internal_format", "RENDERBUFFER_INTERNAL_FORMAT"));
356 addChild(new RboComponentSizeColorCase(m_context, "renderbuffer_component_size_color", "RENDERBUFFER_x_SIZE"));
357 addChild(new RboComponentSizeDepthCase(m_context, "renderbuffer_component_size_depth", "RENDERBUFFER_x_SIZE"));
358 addChild(new RboSamplesCase(m_context, "renderbuffer_samples", "RENDERBUFFER_SAMPLES"));
359 }
360
361 } // namespace Functional
362 } // namespace gles3
363 } // namespace deqp
364