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