xref: /aosp_15_r20/external/deqp/modules/gles31/functional/es31fFboTestCase.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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