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