1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 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 Base class for FBO tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "es31fFboTestCase.hpp"
25 #include "es31fFboTestUtil.hpp"
26 #include "tcuTestLog.hpp"
27 #include "tcuImageCompare.hpp"
28 #include "tcuRenderTarget.hpp"
29 #include "sglrGLContext.hpp"
30 #include "sglrReferenceContext.hpp"
31 #include "gluStrUtil.hpp"
32 #include "gluContextInfo.hpp"
33 #include "deRandom.hpp"
34 #include "glwEnums.hpp"
35 #include "glwFunctions.hpp"
36
37 #include <algorithm>
38
39 namespace deqp
40 {
41 namespace gles31
42 {
43 namespace Functional
44 {
45
46 using std::string;
47 using tcu::TestLog;
48
FboTestCase(Context & context,const char * name,const char * description,bool useScreenSizedViewport)49 FboTestCase::FboTestCase(Context &context, const char *name, const char *description, bool useScreenSizedViewport)
50 : TestCase(context, name, description)
51 , m_viewportWidth(useScreenSizedViewport ? context.getRenderTarget().getWidth() : 128)
52 , m_viewportHeight(useScreenSizedViewport ? context.getRenderTarget().getHeight() : 128)
53 {
54 }
55
~FboTestCase(void)56 FboTestCase::~FboTestCase(void)
57 {
58 }
59
iterate(void)60 FboTestCase::IterateResult FboTestCase::iterate(void)
61 {
62 glu::RenderContext &renderCtx = TestCase::m_context.getRenderContext();
63 const tcu::RenderTarget &renderTarget = renderCtx.getRenderTarget();
64 TestLog &log = m_testCtx.getLog();
65
66 // Viewport.
67 de::Random rnd(deStringHash(getName()));
68 int width = deMin32(renderTarget.getWidth(), m_viewportWidth);
69 int height = deMin32(renderTarget.getHeight(), m_viewportHeight);
70 int x = rnd.getInt(0, renderTarget.getWidth() - width);
71 int y = rnd.getInt(0, renderTarget.getHeight() - height);
72
73 // Surface format and storage is choosen by render().
74 tcu::Surface reference;
75 tcu::Surface result;
76
77 // Call preCheck() that can throw exception if some requirement is not met.
78 preCheck();
79
80 log << TestLog::Message << "Rendering with GL driver" << TestLog::EndMessage;
81
82 // Render using GLES3.1
83 try
84 {
85 sglr::GLContext context(renderCtx, log, 0, tcu::IVec4(x, y, width, height));
86 setContext(&context);
87 render(result);
88
89 // Check error.
90 uint32_t err = glGetError();
91 if (err != GL_NO_ERROR)
92 throw glu::Error(err, glu::getErrorStr(err).toString().c_str(), DE_NULL, __FILE__, __LINE__);
93
94 setContext(DE_NULL);
95 }
96 catch (const FboTestUtil::FboIncompleteException &e)
97 {
98 if (e.getReason() == GL_FRAMEBUFFER_UNSUPPORTED)
99 {
100 log << e;
101 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
102 return STOP;
103 }
104 else
105 throw;
106 }
107
108 log << TestLog::Message << "Rendering reference image" << TestLog::EndMessage;
109
110 // Render reference.
111 {
112 sglr::ReferenceContextBuffers buffers(
113 tcu::PixelFormat(8, 8, 8, renderTarget.getPixelFormat().alphaBits ? 8 : 0), renderTarget.getDepthBits(),
114 renderTarget.getStencilBits(), width, height);
115 sglr::ReferenceContext context(sglr::ReferenceContextLimits(renderCtx), buffers.getColorbuffer(),
116 buffers.getDepthbuffer(), buffers.getStencilbuffer());
117
118 setContext(&context);
119 render(reference);
120 setContext(DE_NULL);
121 }
122
123 bool isOk = compare(reference, result);
124 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
125 isOk ? "Pass" : "Image comparison failed");
126 return STOP;
127 }
128
compare(const tcu::Surface & reference,const tcu::Surface & result)129 bool FboTestCase::compare(const tcu::Surface &reference, const tcu::Surface &result)
130 {
131 return tcu::fuzzyCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference, result, 0.05f,
132 tcu::COMPARE_LOG_RESULT);
133 }
134
readPixels(tcu::Surface & dst,int x,int y,int width,int height,const tcu::TextureFormat & format,const tcu::Vec4 & scale,const tcu::Vec4 & bias)135 void FboTestCase::readPixels(tcu::Surface &dst, int x, int y, int width, int height, const tcu::TextureFormat &format,
136 const tcu::Vec4 &scale, const tcu::Vec4 &bias)
137 {
138 FboTestUtil::readPixels(*getCurrentContext(), dst, x, y, width, height, format, scale, bias);
139 }
140
readPixels(tcu::Surface & dst,int x,int y,int width,int height)141 void FboTestCase::readPixels(tcu::Surface &dst, int x, int y, int width, int height)
142 {
143 getCurrentContext()->readPixels(dst, x, y, width, height);
144 }
145
checkFramebufferStatus(uint32_t target)146 void FboTestCase::checkFramebufferStatus(uint32_t target)
147 {
148 uint32_t status = glCheckFramebufferStatus(target);
149 if (status != GL_FRAMEBUFFER_COMPLETE)
150 throw FboTestUtil::FboIncompleteException(status, __FILE__, __LINE__);
151 }
152
checkError(void)153 void FboTestCase::checkError(void)
154 {
155 uint32_t err = glGetError();
156 if (err != GL_NO_ERROR)
157 throw glu::Error((int)err, (string("Got ") + glu::getErrorStr(err).toString()).c_str(), DE_NULL, __FILE__,
158 __LINE__);
159 }
160
isRequiredFormat(uint32_t format,glu::RenderContext & renderContext)161 static bool isRequiredFormat(uint32_t format, glu::RenderContext &renderContext)
162 {
163 const bool supportsES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));
164 const bool supportsGL45 = glu::contextSupports(renderContext.getType(), glu::ApiType::core(4, 5));
165 switch (format)
166 {
167 // Color-renderable formats
168 case GL_RGBA32I:
169 case GL_RGBA32UI:
170 case GL_RGBA16I:
171 case GL_RGBA16UI:
172 case GL_RGBA8:
173 case GL_RGBA8I:
174 case GL_RGBA8UI:
175 case GL_SRGB8_ALPHA8:
176 case GL_RGB10_A2:
177 case GL_RGB10_A2UI:
178 case GL_RGBA4:
179 case GL_RGB5_A1:
180 case GL_RGB8:
181 case GL_RGB565:
182 case GL_RG32I:
183 case GL_RG32UI:
184 case GL_RG16I:
185 case GL_RG16UI:
186 case GL_RG8:
187 case GL_RG8I:
188 case GL_RG8UI:
189 case GL_R32I:
190 case GL_R32UI:
191 case GL_R16I:
192 case GL_R16UI:
193 case GL_R8:
194 case GL_R8I:
195 case GL_R8UI:
196 return true;
197
198 // Depth formats
199 case GL_DEPTH_COMPONENT32F:
200 case GL_DEPTH_COMPONENT24:
201 case GL_DEPTH_COMPONENT16:
202 return true;
203
204 // Depth+stencil formats
205 case GL_DEPTH32F_STENCIL8:
206 case GL_DEPTH24_STENCIL8:
207 return true;
208
209 // Stencil formats
210 case GL_STENCIL_INDEX8:
211 return true;
212
213 // Float format
214 case GL_RGBA32F:
215 case GL_R11F_G11F_B10F:
216 case GL_RG32F:
217 case GL_R32F:
218 case GL_RGBA16F:
219 case GL_RG16F:
220 case GL_R16F:
221 return supportsES32 || supportsGL45;
222 case GL_RGB16F:
223 return supportsGL45;
224
225 default:
226 return false;
227 }
228 }
229
getEnablingExtensions(uint32_t format,glu::RenderContext & renderContext)230 static std::vector<std::string> getEnablingExtensions(uint32_t format, glu::RenderContext &renderContext)
231 {
232 const bool supportsES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));
233 std::vector<std::string> out;
234
235 DE_ASSERT(!isRequiredFormat(format, renderContext));
236
237 switch (format)
238 {
239 case GL_RGB16F:
240 out.push_back("GL_EXT_color_buffer_half_float");
241 break;
242
243 case GL_RGB32F:
244 out.push_back("GL_EXT_color_buffer_float");
245 break;
246
247 case GL_RGBA16F:
248 case GL_RG16F:
249 case GL_R16F:
250 if (!supportsES32)
251 out.push_back("GL_EXT_color_buffer_half_float");
252 break;
253
254 case GL_RGBA32F:
255 case GL_R11F_G11F_B10F:
256 case GL_RG32F:
257 case GL_R32F:
258 if (!supportsES32)
259 out.push_back("GL_EXT_color_buffer_float");
260 break;
261
262 case GL_R16:
263 case GL_RG16:
264 case GL_RGBA16:
265 out.push_back("GL_EXT_texture_norm16");
266 break;
267
268 default:
269 break;
270 }
271
272 return out;
273 }
274
isAnyExtensionSupported(Context & context,const std::vector<std::string> & requiredExts)275 static bool isAnyExtensionSupported(Context &context, const std::vector<std::string> &requiredExts)
276 {
277 for (std::vector<std::string>::const_iterator iter = requiredExts.begin(); iter != requiredExts.end(); iter++)
278 {
279 const std::string &extension = *iter;
280
281 if (context.getContextInfo().isExtensionSupported(extension.c_str()))
282 return true;
283 }
284
285 return false;
286 }
287
checkFormatSupport(uint32_t sizedFormat)288 void FboTestCase::checkFormatSupport(uint32_t sizedFormat)
289 {
290 const bool isCoreFormat = isRequiredFormat(sizedFormat, m_context.getRenderContext());
291 const std::vector<std::string> requiredExts =
292 (!isCoreFormat) ? getEnablingExtensions(sizedFormat, m_context.getRenderContext()) : std::vector<std::string>();
293
294 // Check that we don't try to use invalid formats.
295 DE_ASSERT(isCoreFormat || !requiredExts.empty());
296
297 if (!requiredExts.empty() && !isAnyExtensionSupported(m_context, requiredExts))
298 throw tcu::NotSupportedError("Format not supported");
299 }
300
getMinimumSampleCount(uint32_t format)301 static int getMinimumSampleCount(uint32_t format)
302 {
303 switch (format)
304 {
305 // Core formats
306 case GL_RGBA32I:
307 case GL_RGBA32UI:
308 case GL_RGBA16I:
309 case GL_RGBA16UI:
310 case GL_RGBA8:
311 case GL_RGBA8I:
312 case GL_RGBA8UI:
313 case GL_SRGB8_ALPHA8:
314 case GL_RGB10_A2:
315 case GL_RGB10_A2UI:
316 case GL_RGBA4:
317 case GL_RGB5_A1:
318 case GL_RGB8:
319 case GL_RGB565:
320 case GL_RG32I:
321 case GL_RG32UI:
322 case GL_RG16I:
323 case GL_RG16UI:
324 case GL_RG8:
325 case GL_RG8I:
326 case GL_RG8UI:
327 case GL_R32I:
328 case GL_R32UI:
329 case GL_R16I:
330 case GL_R16UI:
331 case GL_R8:
332 case GL_R8I:
333 case GL_R8UI:
334 case GL_DEPTH_COMPONENT32F:
335 case GL_DEPTH_COMPONENT24:
336 case GL_DEPTH_COMPONENT16:
337 case GL_DEPTH32F_STENCIL8:
338 case GL_DEPTH24_STENCIL8:
339 case GL_STENCIL_INDEX8:
340 return 4;
341
342 // GL_EXT_color_buffer_float
343 case GL_R11F_G11F_B10F:
344 case GL_RG16F:
345 case GL_R16F:
346 return 4;
347
348 case GL_RGBA32F:
349 case GL_RGBA16F:
350 case GL_RG32F:
351 case GL_R32F:
352 return 0;
353
354 // GL_EXT_color_buffer_half_float
355 case GL_RGB16F:
356 return 0;
357
358 default:
359 DE_FATAL("Unknown format");
360 return 0;
361 }
362 }
363
querySampleCounts(const glw::Functions & gl,uint32_t format)364 static std::vector<int> querySampleCounts(const glw::Functions &gl, uint32_t format)
365 {
366 int numSampleCounts = 0;
367 std::vector<int> sampleCounts;
368
369 gl.getInternalformativ(GL_RENDERBUFFER, format, GL_NUM_SAMPLE_COUNTS, 1, &numSampleCounts);
370
371 if (numSampleCounts > 0)
372 {
373 sampleCounts.resize(numSampleCounts);
374 gl.getInternalformativ(GL_RENDERBUFFER, format, GL_SAMPLES, (glw::GLsizei)sampleCounts.size(),
375 &sampleCounts[0]);
376 }
377
378 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to query sample counts for format");
379
380 return sampleCounts;
381 }
382
checkSampleCount(uint32_t sizedFormat,int numSamples)383 void FboTestCase::checkSampleCount(uint32_t sizedFormat, int numSamples)
384 {
385 const int minSampleCount = getMinimumSampleCount(sizedFormat);
386
387 if (numSamples > minSampleCount)
388 {
389 // Exceeds spec-mandated minimum - need to check.
390 const std::vector<int> supportedSampleCounts =
391 querySampleCounts(m_context.getRenderContext().getFunctions(), sizedFormat);
392
393 if (std::find(supportedSampleCounts.begin(), supportedSampleCounts.end(), numSamples) ==
394 supportedSampleCounts.end())
395 throw tcu::NotSupportedError("Sample count not supported");
396 }
397 }
398
clearColorBuffer(const tcu::TextureFormat & format,const tcu::Vec4 & value)399 void FboTestCase::clearColorBuffer(const tcu::TextureFormat &format, const tcu::Vec4 &value)
400 {
401 FboTestUtil::clearColorBuffer(*getCurrentContext(), format, value);
402 }
403
404 } // namespace Functional
405 } // namespace gles31
406 } // namespace deqp
407