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 tcu::TestLog;
47 using std::string;
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 deUint32 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 (tcu::PixelFormat(8,8,8,renderTarget.getPixelFormat().alphaBits?8:0), renderTarget.getDepthBits(), renderTarget.getStencilBits(), width, height);
113 sglr::ReferenceContext context (sglr::ReferenceContextLimits(renderCtx), buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer());
114
115 setContext(&context);
116 render(reference);
117 setContext(DE_NULL);
118 }
119
120 bool isOk = compare(reference, result);
121 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
122 isOk ? "Pass" : "Image comparison failed");
123 return STOP;
124 }
125
compare(const tcu::Surface & reference,const tcu::Surface & result)126 bool FboTestCase::compare (const tcu::Surface& reference, const tcu::Surface& result)
127 {
128 return tcu::fuzzyCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference, result, 0.05f, tcu::COMPARE_LOG_RESULT);
129 }
130
readPixels(tcu::Surface & dst,int x,int y,int width,int height,const tcu::TextureFormat & format,const tcu::Vec4 & scale,const tcu::Vec4 & bias)131 void FboTestCase::readPixels (tcu::Surface& dst, int x, int y, int width, int height, const tcu::TextureFormat& format, const tcu::Vec4& scale, const tcu::Vec4& bias)
132 {
133 FboTestUtil::readPixels(*getCurrentContext(), dst, x, y, width, height, format, scale, bias);
134 }
135
readPixels(tcu::Surface & dst,int x,int y,int width,int height)136 void FboTestCase::readPixels (tcu::Surface& dst, int x, int y, int width, int height)
137 {
138 getCurrentContext()->readPixels(dst, x, y, width, height);
139 }
140
checkFramebufferStatus(deUint32 target)141 void FboTestCase::checkFramebufferStatus (deUint32 target)
142 {
143 deUint32 status = glCheckFramebufferStatus(target);
144 if (status != GL_FRAMEBUFFER_COMPLETE)
145 throw FboTestUtil::FboIncompleteException(status, __FILE__, __LINE__);
146 }
147
checkError(void)148 void FboTestCase::checkError (void)
149 {
150 deUint32 err = glGetError();
151 if (err != GL_NO_ERROR)
152 throw glu::Error((int)err, (string("Got ") + glu::getErrorStr(err).toString()).c_str(), DE_NULL, __FILE__, __LINE__);
153 }
154
isRequiredFormat(deUint32 format)155 static bool isRequiredFormat (deUint32 format)
156 {
157 switch (format)
158 {
159 // Color-renderable formats
160 case GL_RGBA32I:
161 case GL_RGBA32UI:
162 case GL_RGBA16I:
163 case GL_RGBA16UI:
164 case GL_RGBA8:
165 case GL_RGBA8I:
166 case GL_RGBA8UI:
167 case GL_SRGB8_ALPHA8:
168 case GL_RGB10_A2:
169 case GL_RGB10_A2UI:
170 case GL_RGBA4:
171 case GL_RGB5_A1:
172 case GL_RGB8:
173 case GL_RGB565:
174 case GL_RG32I:
175 case GL_RG32UI:
176 case GL_RG16I:
177 case GL_RG16UI:
178 case GL_RG8:
179 case GL_RG8I:
180 case GL_RG8UI:
181 case GL_R32I:
182 case GL_R32UI:
183 case GL_R16I:
184 case GL_R16UI:
185 case GL_R8:
186 case GL_R8I:
187 case GL_R8UI:
188 return true;
189
190 // Depth formats
191 case GL_DEPTH_COMPONENT32F:
192 case GL_DEPTH_COMPONENT24:
193 case GL_DEPTH_COMPONENT16:
194 return true;
195
196 // Depth+stencil formats
197 case GL_DEPTH32F_STENCIL8:
198 case GL_DEPTH24_STENCIL8:
199 return true;
200
201 // Stencil formats
202 case GL_STENCIL_INDEX8:
203 return true;
204
205 default:
206 return false;
207 }
208 }
209
getEnablingExtensions(deUint32 format)210 static std::vector<std::string> getEnablingExtensions (deUint32 format)
211 {
212 std::vector<std::string> out;
213
214 DE_ASSERT(!isRequiredFormat(format));
215
216 switch (format)
217 {
218 case GL_RGB16F:
219 out.push_back("GL_EXT_color_buffer_half_float");
220 break;
221
222 case GL_RGBA16F:
223 case GL_RG16F:
224 case GL_R16F:
225 out.push_back("GL_EXT_color_buffer_half_float");
226
227 case GL_RGBA32F:
228 case GL_RGB32F:
229 case GL_R11F_G11F_B10F:
230 case GL_RG32F:
231 case GL_R32F:
232 out.push_back("GL_EXT_color_buffer_float");
233 break;
234
235 default:
236 break;
237 }
238
239 return out;
240 }
241
isAnyExtensionSupported(Context & context,const std::vector<std::string> & requiredExts)242 static bool isAnyExtensionSupported (Context& context, const std::vector<std::string>& requiredExts)
243 {
244 for (std::vector<std::string>::const_iterator iter = requiredExts.begin(); iter != requiredExts.end(); iter++)
245 {
246 const std::string& extension = *iter;
247
248 if (context.getContextInfo().isExtensionSupported(extension.c_str()))
249 return true;
250 }
251
252 return false;
253 }
254
checkFormatSupport(deUint32 sizedFormat)255 void FboTestCase::checkFormatSupport (deUint32 sizedFormat)
256 {
257 const bool isCoreFormat = isRequiredFormat(sizedFormat);
258 const std::vector<std::string> requiredExts = (!isCoreFormat) ? getEnablingExtensions(sizedFormat) : std::vector<std::string>();
259
260 // Check that we don't try to use invalid formats.
261 DE_ASSERT(isCoreFormat || !requiredExts.empty());
262
263 if (!requiredExts.empty() && !isAnyExtensionSupported(m_context, requiredExts))
264 throw tcu::NotSupportedError("Format not supported");
265 }
266
getMinimumSampleCount(deUint32 format)267 static int getMinimumSampleCount (deUint32 format)
268 {
269 switch (format)
270 {
271 // Core formats
272 case GL_RGBA32I:
273 case GL_RGBA32UI:
274 case GL_RGBA16I:
275 case GL_RGBA16UI:
276 case GL_RGBA8:
277 case GL_RGBA8I:
278 case GL_RGBA8UI:
279 case GL_SRGB8_ALPHA8:
280 case GL_RGB10_A2:
281 case GL_RGB10_A2UI:
282 case GL_RGBA4:
283 case GL_RGB5_A1:
284 case GL_RGB8:
285 case GL_RGB565:
286 case GL_RG32I:
287 case GL_RG32UI:
288 case GL_RG16I:
289 case GL_RG16UI:
290 case GL_RG8:
291 case GL_RG8I:
292 case GL_RG8UI:
293 case GL_R32I:
294 case GL_R32UI:
295 case GL_R16I:
296 case GL_R16UI:
297 case GL_R8:
298 case GL_R8I:
299 case GL_R8UI:
300 case GL_DEPTH_COMPONENT32F:
301 case GL_DEPTH_COMPONENT24:
302 case GL_DEPTH_COMPONENT16:
303 case GL_DEPTH32F_STENCIL8:
304 case GL_DEPTH24_STENCIL8:
305 case GL_STENCIL_INDEX8:
306 return 4;
307
308 // GL_EXT_color_buffer_float
309 case GL_R11F_G11F_B10F:
310 case GL_RG16F:
311 case GL_R16F:
312 return 4;
313
314 case GL_RGBA32F:
315 case GL_RGBA16F:
316 case GL_RG32F:
317 case GL_R32F:
318 return 0;
319
320 // GL_EXT_color_buffer_half_float
321 case GL_RGB16F:
322 return 0;
323
324 default:
325 DE_ASSERT(!"Unknown format");
326 return 0;
327 }
328 }
329
querySampleCounts(const glw::Functions & gl,deUint32 format)330 static std::vector<int> querySampleCounts (const glw::Functions& gl, deUint32 format)
331 {
332 int numSampleCounts = 0;
333 std::vector<int> sampleCounts;
334
335 gl.getInternalformativ(GL_RENDERBUFFER, format, GL_NUM_SAMPLE_COUNTS, 1, &numSampleCounts);
336
337 if (numSampleCounts > 0)
338 {
339 sampleCounts.resize(numSampleCounts);
340 gl.getInternalformativ(GL_RENDERBUFFER, format, GL_SAMPLES, (glw::GLsizei)sampleCounts.size(), &sampleCounts[0]);
341 }
342
343 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to query sample counts for format");
344
345 return sampleCounts;
346 }
347
checkSampleCount(deUint32 sizedFormat,int numSamples)348 void FboTestCase::checkSampleCount (deUint32 sizedFormat, int numSamples)
349 {
350 const int minSampleCount = getMinimumSampleCount(sizedFormat);
351
352 if (numSamples > minSampleCount)
353 {
354 // Exceeds spec-mandated minimum - need to check.
355 const std::vector<int> supportedSampleCounts = querySampleCounts(m_context.getRenderContext().getFunctions(), sizedFormat);
356
357 if (std::find(supportedSampleCounts.begin(), supportedSampleCounts.end(), numSamples) == supportedSampleCounts.end())
358 throw tcu::NotSupportedError("Sample count not supported");
359 }
360 }
361
clearColorBuffer(const tcu::TextureFormat & format,const tcu::Vec4 & value)362 void FboTestCase::clearColorBuffer (const tcu::TextureFormat& format, const tcu::Vec4& value)
363 {
364 FboTestUtil::clearColorBuffer(*getCurrentContext(), format, value);
365 }
366
367 } // Functional
368 } // gles31
369 } // deqp
370