xref: /aosp_15_r20/external/deqp/modules/gles3/functional/es3fFboRenderTest.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 Framebuffer Object Tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es3fFboRenderTest.hpp"
25 #include "sglrContextUtil.hpp"
26 #include "sglrGLContext.hpp"
27 #include "sglrReferenceContext.hpp"
28 #include "es3fFboTestUtil.hpp"
29 #include "tcuSurface.hpp"
30 #include "tcuImageCompare.hpp"
31 #include "tcuTextureUtil.hpp"
32 #include "tcuVectorUtil.hpp"
33 #include "tcuRenderTarget.hpp"
34 #include "gluPixelTransfer.hpp"
35 #include "gluTextureUtil.hpp"
36 #include "gluStrUtil.hpp"
37 #include "deRandom.h"
38 #include "deString.h"
39 #include "glwDefs.hpp"
40 #include "glwEnums.hpp"
41 
42 #include <sstream>
43 
44 using std::string;
45 using std::vector;
46 using tcu::IVec2;
47 using tcu::IVec3;
48 using tcu::IVec4;
49 using tcu::RGBA;
50 using tcu::Surface;
51 using tcu::TestLog;
52 using tcu::Vec2;
53 using tcu::Vec3;
54 using tcu::Vec4;
55 
56 namespace deqp
57 {
58 namespace gles3
59 {
60 namespace Functional
61 {
62 
63 using glw::GLenum;
64 using namespace FboTestUtil;
65 
66 class FboConfig
67 {
68 public:
FboConfig(uint32_t buffers_,uint32_t colorType_,uint32_t colorFormat_,uint32_t depthStencilType_,uint32_t depthStencilFormat_,int width_=0,int height_=0,int samples_=0)69     FboConfig(uint32_t buffers_, uint32_t colorType_, uint32_t colorFormat_, uint32_t depthStencilType_,
70               uint32_t depthStencilFormat_, int width_ = 0, int height_ = 0, int samples_ = 0)
71         : buffers(buffers_)
72         , colorType(colorType_)
73         , colorFormat(colorFormat_)
74         , depthStencilType(depthStencilType_)
75         , depthStencilFormat(depthStencilFormat_)
76         , width(width_)
77         , height(height_)
78         , samples(samples_)
79     {
80     }
81 
FboConfig(void)82     FboConfig(void)
83         : buffers(0)
84         , colorType(GL_NONE)
85         , colorFormat(GL_NONE)
86         , depthStencilType(GL_NONE)
87         , depthStencilFormat(GL_NONE)
88         , width(0)
89         , height(0)
90         , samples(0)
91     {
92     }
93 
94     std::string getName(void) const;
95 
96     uint32_t buffers; //!< Buffer bit mask (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|...)
97 
98     GLenum colorType;   //!< GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP, GL_RENDERBUFFER
99     GLenum colorFormat; //!< Internal format for color buffer texture or renderbuffer
100 
101     GLenum depthStencilType;
102     GLenum depthStencilFormat;
103 
104     int width;
105     int height;
106     int samples;
107 };
108 
getTypeName(GLenum type)109 static const char *getTypeName(GLenum type)
110 {
111     switch (type)
112     {
113     case GL_TEXTURE_2D:
114         return "tex2d";
115     case GL_RENDERBUFFER:
116         return "rbo";
117     default:
118         TCU_FAIL("Unknown type");
119     }
120 }
121 
getName(void) const122 std::string FboConfig::getName(void) const
123 {
124     std::ostringstream name;
125 
126     DE_ASSERT(buffers & GL_COLOR_BUFFER_BIT);
127     name << getTypeName(colorType) << "_" << getFormatName(colorFormat);
128 
129     if (buffers & GL_DEPTH_BUFFER_BIT)
130         name << "_depth";
131     if (buffers & GL_STENCIL_BUFFER_BIT)
132         name << "_stencil";
133 
134     if (buffers & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
135         name << "_" << getTypeName(depthStencilType) << "_" << getFormatName(depthStencilFormat);
136 
137     return name.str();
138 }
139 
140 class Framebuffer
141 {
142 public:
143     Framebuffer(sglr::Context &context, const FboConfig &config, int width, int height, uint32_t fbo = 0,
144                 uint32_t colorBuffer = 0, uint32_t depthStencilBuffer = 0);
145     ~Framebuffer(void);
146 
getConfig(void) const147     const FboConfig &getConfig(void) const
148     {
149         return m_config;
150     }
getFramebuffer(void) const151     uint32_t getFramebuffer(void) const
152     {
153         return m_framebuffer;
154     }
getColorBuffer(void) const155     uint32_t getColorBuffer(void) const
156     {
157         return m_colorBuffer;
158     }
getDepthStencilBuffer(void) const159     uint32_t getDepthStencilBuffer(void) const
160     {
161         return m_depthStencilBuffer;
162     }
163 
164     void checkCompleteness(void);
165 
166 private:
167     uint32_t createTex2D(uint32_t name, GLenum format, int width, int height);
168     uint32_t createRbo(uint32_t name, GLenum format, int width, int height);
169     void destroyBuffer(uint32_t name, GLenum type);
170 
171     FboConfig m_config;
172     sglr::Context &m_context;
173     uint32_t m_framebuffer;
174     uint32_t m_colorBuffer;
175     uint32_t m_depthStencilBuffer;
176 };
177 
getEnablingExtensions(uint32_t format)178 static std::vector<std::string> getEnablingExtensions(uint32_t format)
179 {
180     std::vector<std::string> out;
181 
182     switch (format)
183     {
184     case GL_RGB16F:
185         out.push_back("GL_EXT_color_buffer_half_float");
186         break;
187 
188     case GL_RGBA16F:
189     case GL_RG16F:
190     case GL_R16F:
191         out.push_back("GL_EXT_color_buffer_half_float");
192         // Fallthrough
193 
194     case GL_RGBA32F:
195     case GL_RGB32F:
196     case GL_R11F_G11F_B10F:
197     case GL_RG32F:
198     case GL_R32F:
199         out.push_back("GL_EXT_color_buffer_float");
200         break;
201 
202     default:
203         break;
204     }
205 
206     return out;
207 }
208 
isExtensionSupported(sglr::Context & context,const char * name)209 static bool isExtensionSupported(sglr::Context &context, const char *name)
210 {
211     std::istringstream extensions(context.getString(GL_EXTENSIONS));
212     std::string extension;
213 
214     while (std::getline(extensions, extension, ' '))
215     {
216         if (extension == name)
217             return true;
218     }
219 
220     return false;
221 }
222 
isAnyExtensionSupported(sglr::Context & context,const std::vector<std::string> & requiredExts)223 static bool isAnyExtensionSupported(sglr::Context &context, const std::vector<std::string> &requiredExts)
224 {
225     if (requiredExts.empty())
226         return true;
227 
228     for (std::vector<std::string>::const_iterator iter = requiredExts.begin(); iter != requiredExts.end(); iter++)
229     {
230         const std::string &extension = *iter;
231 
232         if (isExtensionSupported(context, extension.c_str()))
233             return true;
234     }
235 
236     return false;
237 }
238 
239 template <typename T>
join(const std::vector<T> & list,const std::string & sep)240 static std::string join(const std::vector<T> &list, const std::string &sep)
241 {
242     std::ostringstream out;
243 
244     for (typename std::vector<T>::const_iterator iter = list.begin(); iter != list.end(); iter++)
245     {
246         if (iter != list.begin())
247             out << sep;
248         out << *iter;
249     }
250 
251     return out.str();
252 }
253 
checkColorFormatSupport(sglr::Context & context,uint32_t sizedFormat)254 static void checkColorFormatSupport(sglr::Context &context, uint32_t sizedFormat)
255 {
256     const std::vector<std::string> requiredExts = getEnablingExtensions(sizedFormat);
257 
258     if (!isAnyExtensionSupported(context, requiredExts))
259     {
260         std::string errMsg =
261             "Format not supported, requires " +
262             ((requiredExts.size() == 1) ? requiredExts[0] : " one of the following: " + join(requiredExts, ", "));
263 
264         throw tcu::NotSupportedError(errMsg);
265     }
266 }
267 
Framebuffer(sglr::Context & context,const FboConfig & config,int width,int height,uint32_t fbo,uint32_t colorBufferName,uint32_t depthStencilBufferName)268 Framebuffer::Framebuffer(sglr::Context &context, const FboConfig &config, int width, int height, uint32_t fbo,
269                          uint32_t colorBufferName, uint32_t depthStencilBufferName)
270     : m_config(config)
271     , m_context(context)
272     , m_framebuffer(fbo)
273     , m_colorBuffer(0)
274     , m_depthStencilBuffer(0)
275 {
276     // Verify that color format is supported
277     checkColorFormatSupport(context, config.colorFormat);
278 
279     if (m_framebuffer == 0)
280         context.genFramebuffers(1, &m_framebuffer);
281     context.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
282 
283     if (m_config.buffers & (GL_COLOR_BUFFER_BIT))
284     {
285         switch (m_config.colorType)
286         {
287         case GL_TEXTURE_2D:
288             m_colorBuffer = createTex2D(colorBufferName, m_config.colorFormat, width, height);
289             context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer, 0);
290             break;
291 
292         case GL_RENDERBUFFER:
293             m_colorBuffer = createRbo(colorBufferName, m_config.colorFormat, width, height);
294             context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorBuffer);
295             break;
296 
297         default:
298             TCU_FAIL("Unsupported type");
299         }
300     }
301 
302     if (m_config.buffers & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
303     {
304         switch (m_config.depthStencilType)
305         {
306         case GL_TEXTURE_2D:
307             m_depthStencilBuffer = createTex2D(depthStencilBufferName, m_config.depthStencilFormat, width, height);
308             break;
309         case GL_RENDERBUFFER:
310             m_depthStencilBuffer = createRbo(depthStencilBufferName, m_config.depthStencilFormat, width, height);
311             break;
312         default:
313             TCU_FAIL("Unsupported type");
314         }
315     }
316 
317     for (int ndx = 0; ndx < 2; ndx++)
318     {
319         uint32_t bit   = ndx ? GL_STENCIL_BUFFER_BIT : GL_DEPTH_BUFFER_BIT;
320         uint32_t point = ndx ? GL_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
321 
322         if ((m_config.buffers & bit) == 0)
323             continue; /* Not used. */
324 
325         switch (m_config.depthStencilType)
326         {
327         case GL_TEXTURE_2D:
328             context.framebufferTexture2D(GL_FRAMEBUFFER, point, GL_TEXTURE_2D, m_depthStencilBuffer, 0);
329             break;
330         case GL_RENDERBUFFER:
331             context.framebufferRenderbuffer(GL_FRAMEBUFFER, point, GL_RENDERBUFFER, m_depthStencilBuffer);
332             break;
333         default:
334             DE_ASSERT(false);
335         }
336     }
337 
338     GLenum err = m_context.getError();
339     if (err != GL_NO_ERROR)
340         throw glu::Error(err, glu::getErrorStr(err).toString().c_str(), "", __FILE__, __LINE__);
341 
342     context.bindFramebuffer(GL_FRAMEBUFFER, 0);
343 }
344 
~Framebuffer(void)345 Framebuffer::~Framebuffer(void)
346 {
347     m_context.deleteFramebuffers(1, &m_framebuffer);
348     destroyBuffer(m_colorBuffer, m_config.colorType);
349     destroyBuffer(m_depthStencilBuffer, m_config.depthStencilType);
350 }
351 
checkCompleteness(void)352 void Framebuffer::checkCompleteness(void)
353 {
354     m_context.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
355     GLenum status = m_context.checkFramebufferStatus(GL_FRAMEBUFFER);
356     m_context.bindFramebuffer(GL_FRAMEBUFFER, 0);
357     if (status != GL_FRAMEBUFFER_COMPLETE)
358         throw FboIncompleteException(status, __FILE__, __LINE__);
359 }
360 
createTex2D(uint32_t name,GLenum format,int width,int height)361 uint32_t Framebuffer::createTex2D(uint32_t name, GLenum format, int width, int height)
362 {
363     if (name == 0)
364         m_context.genTextures(1, &name);
365 
366     m_context.bindTexture(GL_TEXTURE_2D, name);
367     m_context.texImage2D(GL_TEXTURE_2D, 0, format, width, height);
368 
369     if (!deIsPowerOfTwo32(width) || !deIsPowerOfTwo32(height))
370     {
371         // Set wrap mode to clamp for NPOT FBOs
372         m_context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
373         m_context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
374     }
375 
376     m_context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
377     m_context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
378 
379     return name;
380 }
381 
createRbo(uint32_t name,GLenum format,int width,int height)382 uint32_t Framebuffer::createRbo(uint32_t name, GLenum format, int width, int height)
383 {
384     if (name == 0)
385         m_context.genRenderbuffers(1, &name);
386 
387     m_context.bindRenderbuffer(GL_RENDERBUFFER, name);
388     m_context.renderbufferStorage(GL_RENDERBUFFER, format, width, height);
389 
390     return name;
391 }
392 
destroyBuffer(uint32_t name,GLenum type)393 void Framebuffer::destroyBuffer(uint32_t name, GLenum type)
394 {
395     if (type == GL_TEXTURE_2D || type == GL_TEXTURE_CUBE_MAP)
396         m_context.deleteTextures(1, &name);
397     else if (type == GL_RENDERBUFFER)
398         m_context.deleteRenderbuffers(1, &name);
399     else
400         DE_ASSERT(type == GL_NONE);
401 }
402 
createMetaballsTex2D(sglr::Context & context,uint32_t name,GLenum format,GLenum dataType,int width,int height)403 static void createMetaballsTex2D(sglr::Context &context, uint32_t name, GLenum format, GLenum dataType, int width,
404                                  int height)
405 {
406     tcu::TextureFormat texFormat = glu::mapGLTransferFormat(format, dataType);
407     tcu::TextureLevel level(texFormat, width, height);
408 
409     tcu::fillWithMetaballs(level.getAccess(), 5, name ^ width ^ height);
410 
411     context.bindTexture(GL_TEXTURE_2D, name);
412     context.texImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, dataType, level.getAccess().getDataPtr());
413     context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
414 }
415 
createQuadsTex2D(sglr::Context & context,uint32_t name,GLenum format,GLenum dataType,int width,int height)416 static void createQuadsTex2D(sglr::Context &context, uint32_t name, GLenum format, GLenum dataType, int width,
417                              int height)
418 {
419     tcu::TextureFormat texFormat = glu::mapGLTransferFormat(format, dataType);
420     tcu::TextureLevel level(texFormat, width, height);
421 
422     tcu::fillWithRGBAQuads(level.getAccess());
423 
424     context.bindTexture(GL_TEXTURE_2D, name);
425     context.texImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, dataType, level.getAccess().getDataPtr());
426     context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
427 }
428 
429 class FboRenderCase : public TestCase
430 {
431 public:
432     FboRenderCase(Context &context, const char *name, const char *description, const FboConfig &config);
~FboRenderCase(void)433     virtual ~FboRenderCase(void)
434     {
435     }
436 
437     virtual IterateResult iterate(void);
438     virtual void render(sglr::Context &fboContext, Surface &dst) = DE_NULL;
439 
440     bool compare(const tcu::Surface &reference, const tcu::Surface &result);
441 
442 protected:
443     const FboConfig m_config;
444 };
445 
FboRenderCase(Context & context,const char * name,const char * description,const FboConfig & config)446 FboRenderCase::FboRenderCase(Context &context, const char *name, const char *description, const FboConfig &config)
447     : TestCase(context, name, description)
448     , m_config(config)
449 {
450 }
451 
iterate(void)452 TestCase::IterateResult FboRenderCase::iterate(void)
453 {
454     tcu::Vec4 clearColor                  = tcu::Vec4(0.125f, 0.25f, 0.5f, 1.0f);
455     glu::RenderContext &renderCtx         = m_context.getRenderContext();
456     const tcu::RenderTarget &renderTarget = renderCtx.getRenderTarget();
457     tcu::TestLog &log                     = m_testCtx.getLog();
458     const char *failReason                = DE_NULL;
459 
460     // Position & size for context
461     deRandom rnd;
462     deRandom_init(&rnd, deStringHash(getName()));
463 
464     int width  = deMin32(renderTarget.getWidth(), 128);
465     int height = deMin32(renderTarget.getHeight(), 128);
466     int xMax   = renderTarget.getWidth() - width + 1;
467     int yMax   = renderTarget.getHeight() - height + 1;
468     int x      = deRandom_getUint32(&rnd) % xMax;
469     int y      = deRandom_getUint32(&rnd) % yMax;
470 
471     tcu::Surface gles3Frame(width, height);
472     tcu::Surface refFrame(width, height);
473     GLenum gles3Error;
474     GLenum refError;
475 
476     // Render using GLES3
477     try
478     {
479         sglr::GLContext context(renderCtx, log, sglr::GLCONTEXT_LOG_CALLS, tcu::IVec4(x, y, width, height));
480 
481         context.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
482         context.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
483 
484         render(context, gles3Frame); // Call actual render func
485         gles3Error = context.getError();
486     }
487     catch (const FboIncompleteException &e)
488     {
489         if (e.getReason() == GL_FRAMEBUFFER_UNSUPPORTED)
490         {
491             // Mark test case as unsupported
492             log << e;
493             m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
494             return STOP;
495         }
496         else
497             throw; // Propagate error
498     }
499 
500     // Render reference image
501     {
502         sglr::ReferenceContextBuffers buffers(
503             tcu::PixelFormat(8, 8, 8, renderTarget.getPixelFormat().alphaBits ? 8 : 0), renderTarget.getDepthBits(),
504             renderTarget.getStencilBits(), width, height);
505         sglr::ReferenceContext context(sglr::ReferenceContextLimits(renderCtx), buffers.getColorbuffer(),
506                                        buffers.getDepthbuffer(), buffers.getStencilbuffer());
507 
508         context.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
509         context.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
510 
511         render(context, refFrame);
512         refError = context.getError();
513     }
514 
515     // Compare error codes
516     bool errorCodesOk = (gles3Error == refError);
517 
518     if (!errorCodesOk)
519     {
520         log << tcu::TestLog::Message << "Error code mismatch: got " << glu::getErrorStr(gles3Error) << ", expected "
521             << glu::getErrorStr(refError) << tcu::TestLog::EndMessage;
522         failReason = "Got unexpected error";
523     }
524 
525     // Compare images
526     bool imagesOk = compare(refFrame, gles3Frame);
527 
528     if (!imagesOk && !failReason)
529         failReason = "Image comparison failed";
530 
531     // Store test result
532     bool isOk = errorCodesOk && imagesOk;
533     m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, isOk ? "Pass" : failReason);
534 
535     return STOP;
536 }
537 
compare(const tcu::Surface & reference,const tcu::Surface & result)538 bool FboRenderCase::compare(const tcu::Surface &reference, const tcu::Surface &result)
539 {
540     const tcu::RGBA threshold(tcu::max(getFormatThreshold(m_config.colorFormat), tcu::RGBA(12, 12, 12, 12)));
541 
542     return tcu::bilinearCompare(m_testCtx.getLog(), "ComparisonResult", "Image comparison result",
543                                 reference.getAccess(), result.getAccess(), threshold, tcu::COMPARE_LOG_RESULT);
544 }
545 
546 namespace FboCases
547 {
548 
549 class StencilClearsTest : public FboRenderCase
550 {
551 public:
552     StencilClearsTest(Context &context, const FboConfig &config);
~StencilClearsTest(void)553     virtual ~StencilClearsTest(void)
554     {
555     }
556 
557     void render(sglr::Context &context, Surface &dst);
558 };
559 
StencilClearsTest(Context & context,const FboConfig & config)560 StencilClearsTest::StencilClearsTest(Context &context, const FboConfig &config)
561     : FboRenderCase(context, config.getName().c_str(), "Stencil clears", config)
562 {
563 }
564 
render(sglr::Context & context,Surface & dst)565 void StencilClearsTest::render(sglr::Context &context, Surface &dst)
566 {
567     tcu::TextureFormat colorFormat      = glu::mapGLInternalFormat(m_config.colorFormat);
568     glu::DataType fboSamplerType        = glu::getSampler2DType(colorFormat);
569     glu::DataType fboOutputType         = getFragmentOutputType(colorFormat);
570     tcu::TextureFormatInfo fboRangeInfo = tcu::getTextureFormatInfo(colorFormat);
571     Vec4 fboOutScale                    = fboRangeInfo.valueMax - fboRangeInfo.valueMin;
572     Vec4 fboOutBias                     = fboRangeInfo.valueMin;
573 
574     Texture2DShader texToFboShader(DataTypes() << glu::TYPE_SAMPLER_2D, fboOutputType);
575     Texture2DShader texFromFboShader(DataTypes() << fboSamplerType, glu::TYPE_FLOAT_VEC4);
576 
577     uint32_t texToFboShaderID   = context.createProgram(&texToFboShader);
578     uint32_t texFromFboShaderID = context.createProgram(&texFromFboShader);
579 
580     uint32_t metaballsTex = 1;
581     uint32_t quadsTex     = 2;
582     int width             = 128;
583     int height            = 128;
584 
585     texToFboShader.setOutScaleBias(fboOutScale, fboOutBias);
586     texFromFboShader.setTexScaleBias(0, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);
587 
588     createQuadsTex2D(context, quadsTex, GL_RGBA, GL_UNSIGNED_BYTE, width, height);
589     createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, width, height);
590 
591     Framebuffer fbo(context, m_config, width, height);
592     fbo.checkCompleteness();
593 
594     // Bind framebuffer and clear
595     context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
596     context.viewport(0, 0, width, height);
597     context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
598     context.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
599 
600     // Do stencil clears
601     context.enable(GL_SCISSOR_TEST);
602     context.scissor(10, 16, 32, 120);
603     context.clearStencil(1);
604     context.clear(GL_STENCIL_BUFFER_BIT);
605     context.scissor(16, 32, 100, 64);
606     context.clearStencil(2);
607     context.clear(GL_STENCIL_BUFFER_BIT);
608     context.disable(GL_SCISSOR_TEST);
609 
610     // Draw 2 textures with stecil tests
611     context.enable(GL_STENCIL_TEST);
612 
613     context.bindTexture(GL_TEXTURE_2D, quadsTex);
614     context.stencilFunc(GL_EQUAL, 1, 0xffu);
615 
616     texToFboShader.setUniforms(context, texToFboShaderID);
617     sglr::drawQuad(context, texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
618 
619     context.bindTexture(GL_TEXTURE_2D, metaballsTex);
620     context.stencilFunc(GL_EQUAL, 2, 0xffu);
621 
622     texToFboShader.setUniforms(context, texToFboShaderID);
623     sglr::drawQuad(context, texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
624 
625     context.disable(GL_STENCIL_TEST);
626 
627     if (fbo.getConfig().colorType == GL_TEXTURE_2D)
628     {
629         context.bindFramebuffer(GL_FRAMEBUFFER, 0);
630         context.bindTexture(GL_TEXTURE_2D, fbo.getColorBuffer());
631         context.viewport(0, 0, context.getWidth(), context.getHeight());
632 
633         texFromFboShader.setUniforms(context, texFromFboShaderID);
634         sglr::drawQuad(context, texFromFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
635 
636         context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
637     }
638     else
639         readPixels(context, dst, 0, 0, width, height, colorFormat, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);
640 }
641 
642 class SharedColorbufferTest : public FboRenderCase
643 {
644 public:
645     SharedColorbufferTest(Context &context, const FboConfig &config);
~SharedColorbufferTest(void)646     virtual ~SharedColorbufferTest(void)
647     {
648     }
649 
650     void render(sglr::Context &context, Surface &dst);
651 };
652 
SharedColorbufferTest(Context & context,const FboConfig & config)653 SharedColorbufferTest::SharedColorbufferTest(Context &context, const FboConfig &config)
654     : FboRenderCase(context, config.getName().c_str(), "Shared colorbuffer", config)
655 {
656 }
657 
render(sglr::Context & context,Surface & dst)658 void SharedColorbufferTest::render(sglr::Context &context, Surface &dst)
659 {
660     Texture2DShader texShader(DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4);
661     FlatColorShader flatShader(glu::TYPE_FLOAT_VEC4);
662     uint32_t texShaderID  = context.createProgram(&texShader);
663     uint32_t flatShaderID = context.createProgram(&flatShader);
664 
665     int width             = 128;
666     int height            = 128;
667     uint32_t quadsTex     = 1;
668     uint32_t metaballsTex = 2;
669     bool stencil          = (m_config.buffers & GL_STENCIL_BUFFER_BIT) != 0;
670 
671     context.disable(GL_DITHER);
672 
673     // Textures
674     createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
675     createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, 64, 64);
676 
677     context.viewport(0, 0, width, height);
678 
679     // Fbo A
680     Framebuffer fboA(context, m_config, width, height);
681     fboA.checkCompleteness();
682 
683     // Fbo B - don't create colorbuffer
684     FboConfig cfg = m_config;
685     cfg.buffers &= ~GL_COLOR_BUFFER_BIT;
686     cfg.colorType   = GL_NONE;
687     cfg.colorFormat = GL_NONE;
688     Framebuffer fboB(context, cfg, width, height);
689 
690     // Attach color buffer from fbo A
691     context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
692     switch (m_config.colorType)
693     {
694     case GL_TEXTURE_2D:
695         context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboA.getColorBuffer(), 0);
696         break;
697 
698     case GL_RENDERBUFFER:
699         context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fboA.getColorBuffer());
700         break;
701 
702     default:
703         DE_ASSERT(false);
704     }
705 
706     // Clear depth and stencil in fbo B
707     context.clear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
708 
709     // Render quads to fbo 1, with depth 0.0
710     context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer());
711     context.bindTexture(GL_TEXTURE_2D, quadsTex);
712     context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
713     context.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
714 
715     if (stencil)
716     {
717         // Stencil to 1 in fbo A
718         context.clearStencil(1);
719         context.clear(GL_STENCIL_BUFFER_BIT);
720     }
721 
722     texShader.setUniforms(context, texShaderID);
723 
724     context.enable(GL_DEPTH_TEST);
725     sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
726     context.disable(GL_DEPTH_TEST);
727 
728     // Blend metaballs to fbo 2
729     context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
730     context.bindTexture(GL_TEXTURE_2D, metaballsTex);
731     context.enable(GL_BLEND);
732     context.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
733     sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
734 
735     // Render small quad that is only visible if depth buffer is not shared with fbo A - or there is no depth bits
736     context.bindTexture(GL_TEXTURE_2D, quadsTex);
737     context.enable(GL_DEPTH_TEST);
738     sglr::drawQuad(context, texShaderID, Vec3(0.5f, 0.5f, 0.5f), Vec3(1.0f, 1.0f, 0.5f));
739     context.disable(GL_DEPTH_TEST);
740 
741     if (stencil)
742     {
743         flatShader.setColor(context, flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
744 
745         // Clear subset of stencil buffer to 1
746         context.enable(GL_SCISSOR_TEST);
747         context.scissor(10, 10, 12, 25);
748         context.clearStencil(1);
749         context.clear(GL_STENCIL_BUFFER_BIT);
750         context.disable(GL_SCISSOR_TEST);
751 
752         // Render quad with stencil mask == 1
753         context.enable(GL_STENCIL_TEST);
754         context.stencilFunc(GL_EQUAL, 1, 0xffu);
755         sglr::drawQuad(context, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
756         context.disable(GL_STENCIL_TEST);
757     }
758 
759     // Get results
760     if (fboA.getConfig().colorType == GL_TEXTURE_2D)
761     {
762         texShader.setUniforms(context, texShaderID);
763 
764         context.bindFramebuffer(GL_FRAMEBUFFER, 0);
765         context.bindTexture(GL_TEXTURE_2D, fboA.getColorBuffer());
766         context.viewport(0, 0, context.getWidth(), context.getHeight());
767         sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
768         context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
769     }
770     else
771         readPixels(context, dst, 0, 0, width, height, glu::mapGLInternalFormat(fboA.getConfig().colorFormat),
772                    Vec4(1.0f), Vec4(0.0f));
773 }
774 
775 class SharedColorbufferClearsTest : public FboRenderCase
776 {
777 public:
778     SharedColorbufferClearsTest(Context &context, const FboConfig &config);
~SharedColorbufferClearsTest(void)779     virtual ~SharedColorbufferClearsTest(void)
780     {
781     }
782 
783     void render(sglr::Context &context, Surface &dst);
784 };
785 
SharedColorbufferClearsTest(Context & context,const FboConfig & config)786 SharedColorbufferClearsTest::SharedColorbufferClearsTest(Context &context, const FboConfig &config)
787     : FboRenderCase(context, config.getName().c_str(), "Shared colorbuffer clears", config)
788 {
789 }
790 
render(sglr::Context & context,Surface & dst)791 void SharedColorbufferClearsTest::render(sglr::Context &context, Surface &dst)
792 {
793     tcu::TextureFormat colorFormat = glu::mapGLInternalFormat(m_config.colorFormat);
794     glu::DataType fboSamplerType   = glu::getSampler2DType(colorFormat);
795     int width                      = 128;
796     int height                     = 128;
797     uint32_t colorbuffer           = 1;
798 
799     // Check for format support.
800     checkColorFormatSupport(context, m_config.colorFormat);
801 
802     // Single colorbuffer
803     if (m_config.colorType == GL_TEXTURE_2D)
804     {
805         context.bindTexture(GL_TEXTURE_2D, colorbuffer);
806         context.texImage2D(GL_TEXTURE_2D, 0, m_config.colorFormat, width, height);
807         context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
808         context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
809     }
810     else
811     {
812         DE_ASSERT(m_config.colorType == GL_RENDERBUFFER);
813         context.bindRenderbuffer(GL_RENDERBUFFER, colorbuffer);
814         context.renderbufferStorage(GL_RENDERBUFFER, m_config.colorFormat, width, height);
815     }
816 
817     // Multiple framebuffers sharing the colorbuffer
818     for (int fbo = 1; fbo <= 3; fbo++)
819     {
820         context.bindFramebuffer(GL_FRAMEBUFFER, fbo);
821 
822         if (m_config.colorType == GL_TEXTURE_2D)
823             context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer, 0);
824         else
825             context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuffer);
826     }
827 
828     context.bindFramebuffer(GL_FRAMEBUFFER, 1);
829 
830     // Check completeness
831     {
832         GLenum status = context.checkFramebufferStatus(GL_FRAMEBUFFER);
833         if (status != GL_FRAMEBUFFER_COMPLETE)
834             throw FboIncompleteException(status, __FILE__, __LINE__);
835     }
836 
837     // Render to them
838     context.viewport(0, 0, width, height);
839     context.clearColor(0.0f, 0.0f, 1.0f, 1.0f);
840     context.clear(GL_COLOR_BUFFER_BIT);
841 
842     context.enable(GL_SCISSOR_TEST);
843 
844     context.bindFramebuffer(GL_FRAMEBUFFER, 2);
845     context.clearColor(0.6f, 0.0f, 0.0f, 1.0f);
846     context.scissor(10, 10, 64, 64);
847     context.clear(GL_COLOR_BUFFER_BIT);
848     context.clearColor(0.0f, 0.6f, 0.0f, 1.0f);
849     context.scissor(60, 60, 40, 20);
850     context.clear(GL_COLOR_BUFFER_BIT);
851 
852     context.bindFramebuffer(GL_FRAMEBUFFER, 3);
853     context.clearColor(0.0f, 0.0f, 0.6f, 1.0f);
854     context.scissor(20, 20, 100, 10);
855     context.clear(GL_COLOR_BUFFER_BIT);
856 
857     context.bindFramebuffer(GL_FRAMEBUFFER, 1);
858     context.clearColor(0.6f, 0.0f, 0.6f, 1.0f);
859     context.scissor(20, 20, 5, 100);
860     context.clear(GL_COLOR_BUFFER_BIT);
861 
862     context.disable(GL_SCISSOR_TEST);
863 
864     if (m_config.colorType == GL_TEXTURE_2D)
865     {
866         Texture2DShader shader(DataTypes() << fboSamplerType, glu::TYPE_FLOAT_VEC4);
867         uint32_t shaderID = context.createProgram(&shader);
868 
869         shader.setUniforms(context, shaderID);
870 
871         context.bindFramebuffer(GL_FRAMEBUFFER, 0);
872         context.viewport(0, 0, context.getWidth(), context.getHeight());
873         sglr::drawQuad(context, shaderID, Vec3(-0.9f, -0.9f, 0.0f), Vec3(0.9f, 0.9f, 0.0f));
874         context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
875     }
876     else
877         readPixels(context, dst, 0, 0, width, height, colorFormat, Vec4(1.0f), Vec4(0.0f));
878 }
879 
880 class SharedDepthStencilTest : public FboRenderCase
881 {
882 public:
883     SharedDepthStencilTest(Context &context, const FboConfig &config);
~SharedDepthStencilTest(void)884     virtual ~SharedDepthStencilTest(void)
885     {
886     }
887 
888     static bool isConfigSupported(const FboConfig &config);
889     void render(sglr::Context &context, Surface &dst);
890 };
891 
SharedDepthStencilTest(Context & context,const FboConfig & config)892 SharedDepthStencilTest::SharedDepthStencilTest(Context &context, const FboConfig &config)
893     : FboRenderCase(context, config.getName().c_str(), "Shared depth/stencilbuffer", config)
894 {
895 }
896 
isConfigSupported(const FboConfig & config)897 bool SharedDepthStencilTest::isConfigSupported(const FboConfig &config)
898 {
899     return (config.buffers & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0;
900 }
901 
render(sglr::Context & context,Surface & dst)902 void SharedDepthStencilTest::render(sglr::Context &context, Surface &dst)
903 {
904     Texture2DShader texShader(DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4);
905     FlatColorShader flatShader(glu::TYPE_FLOAT_VEC4);
906     uint32_t texShaderID  = context.createProgram(&texShader);
907     uint32_t flatShaderID = context.createProgram(&flatShader);
908     int width             = 128;
909     int height            = 128;
910     // bool depth = (m_config.buffers & GL_DEPTH_BUFFER_BIT) != 0;
911     bool stencil = (m_config.buffers & GL_STENCIL_BUFFER_BIT) != 0;
912 
913     // Textures
914     uint32_t metaballsTex = 5;
915     uint32_t quadsTex     = 6;
916     createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
917     createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
918 
919     context.viewport(0, 0, width, height);
920 
921     // Fbo A
922     Framebuffer fboA(context, m_config, width, height);
923     fboA.checkCompleteness();
924 
925     // Fbo B
926     FboConfig cfg = m_config;
927     cfg.buffers &= ~(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
928     cfg.depthStencilType   = GL_NONE;
929     cfg.depthStencilFormat = GL_NONE;
930     Framebuffer fboB(context, cfg, width, height);
931 
932     // Bind depth/stencil buffers from fbo A to fbo B
933     context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
934     for (int ndx = 0; ndx < 2; ndx++)
935     {
936         uint32_t bit   = ndx ? GL_STENCIL_BUFFER_BIT : GL_DEPTH_BUFFER_BIT;
937         uint32_t point = ndx ? GL_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
938 
939         if ((m_config.buffers & bit) == 0)
940             continue;
941 
942         switch (m_config.depthStencilType)
943         {
944         case GL_TEXTURE_2D:
945             context.framebufferTexture2D(GL_FRAMEBUFFER, point, GL_TEXTURE_2D, fboA.getDepthStencilBuffer(), 0);
946             break;
947         case GL_RENDERBUFFER:
948             context.framebufferRenderbuffer(GL_FRAMEBUFFER, point, GL_RENDERBUFFER, fboA.getDepthStencilBuffer());
949             break;
950         default:
951             TCU_FAIL("Not implemented");
952         }
953     }
954 
955     // Setup uniforms
956     texShader.setUniforms(context, texShaderID);
957 
958     // Clear color to red and stencil to 1 in fbo B.
959     context.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
960     context.clearStencil(1);
961     context.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
962 
963     context.enable(GL_DEPTH_TEST);
964 
965     // Render quad to fbo A
966     context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer());
967     context.bindTexture(GL_TEXTURE_2D, quadsTex);
968     sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
969 
970     if (stencil)
971     {
972         // Clear subset of stencil buffer to 0 in fbo A
973         context.enable(GL_SCISSOR_TEST);
974         context.scissor(10, 10, 12, 25);
975         context.clearStencil(0);
976         context.clear(GL_STENCIL_BUFFER_BIT);
977         context.disable(GL_SCISSOR_TEST);
978     }
979 
980     // Render metaballs to fbo B
981     context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
982     context.bindTexture(GL_TEXTURE_2D, metaballsTex);
983     sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
984 
985     context.disable(GL_DEPTH_TEST);
986 
987     if (stencil)
988     {
989         // Render quad with stencil mask == 0
990         context.enable(GL_STENCIL_TEST);
991         context.stencilFunc(GL_EQUAL, 0, 0xffu);
992         context.useProgram(flatShaderID);
993         flatShader.setColor(context, flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
994         sglr::drawQuad(context, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
995         context.disable(GL_STENCIL_TEST);
996     }
997 
998     if (m_config.colorType == GL_TEXTURE_2D)
999     {
1000         // Render both to screen
1001         context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1002         context.viewport(0, 0, context.getWidth(), context.getHeight());
1003         context.bindTexture(GL_TEXTURE_2D, fboA.getColorBuffer());
1004         sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(0.0f, 1.0f, 0.0f));
1005         context.bindTexture(GL_TEXTURE_2D, fboB.getColorBuffer());
1006         sglr::drawQuad(context, texShaderID, Vec3(0.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1007 
1008         context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1009     }
1010     else
1011     {
1012         // Read results from fbo B
1013         readPixels(context, dst, 0, 0, width, height, glu::mapGLInternalFormat(m_config.colorFormat), Vec4(1.0f),
1014                    Vec4(0.0f));
1015     }
1016 }
1017 
1018 #if 0
1019 class TexSubImageAfterRenderTest : public FboRenderCase
1020 {
1021 public:
1022                     TexSubImageAfterRenderTest        (Context& context, const FboConfig& config);
1023     virtual            ~TexSubImageAfterRenderTest        (void) {}
1024 
1025     void            render                            (sglr::Context& context, Surface& dst);
1026 };
1027 
1028 TexSubImageAfterRenderTest::TexSubImageAfterRenderTest (Context& context, const FboConfig& config)
1029     : FboRenderCase(context, (string("after_render_") + config.getName()).c_str(), "TexSubImage after rendering to texture", config)
1030 {
1031 }
1032 
1033 void TexSubImageAfterRenderTest::render (sglr::Context& context, Surface& dst)
1034 {
1035     using sglr::TexturedQuadOp;
1036 
1037     bool isRGBA = true;
1038 
1039     Surface fourQuads(Surface::PIXELFORMAT_RGB, 64, 64);
1040     tcu::SurfaceUtil::fillWithFourQuads(fourQuads);
1041 
1042     Surface metaballs(isRGBA ? Surface::PIXELFORMAT_RGBA : Surface::PIXELFORMAT_RGB, 64, 64);
1043     tcu::SurfaceUtil::fillWithMetaballs(metaballs, 5, 3);
1044 
1045     uint32_t fourQuadsTex = 1;
1046     context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
1047     context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1048     context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, fourQuads);
1049 
1050     context.bindFramebuffer(GL_FRAMEBUFFER, 1);
1051 
1052     uint32_t fboTex = 2;
1053     context.bindTexture(GL_TEXTURE_2D, fboTex);
1054     context.texImage2D(GL_TEXTURE_2D, 0, isRGBA ? GL_RGBA : GL_RGB, 128, 128);
1055     context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1056     context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);
1057 
1058     // Render to fbo
1059     context.viewport(0, 0, 128, 128);
1060     context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
1061     context.draw(TexturedQuadOp(-1.0f, -1.0f, 1.0f, 1.0f, 0));
1062 
1063     // Update texture using TexSubImage2D
1064     context.bindTexture(GL_TEXTURE_2D, fboTex);
1065     context.texSubImage2D(GL_TEXTURE_2D, 0, 32, 32, metaballs);
1066 
1067     // Draw to screen
1068     context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1069     context.viewport(0, 0, context.getWidth(), context.getHeight());
1070     context.draw(TexturedQuadOp(-1.0f, -1.0f, 1.0f, 1.0f, 0));
1071     context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1072 }
1073 
1074 class TexSubImageBetweenRenderTest : public FboRenderCase
1075 {
1076 public:
1077                     TexSubImageBetweenRenderTest        (Context& context, const FboConfig& config);
1078     virtual            ~TexSubImageBetweenRenderTest        (void) {}
1079 
1080     void            render                                (sglr::Context& context, Surface& dst);
1081 };
1082 
1083 TexSubImageBetweenRenderTest::TexSubImageBetweenRenderTest (Context& context, const FboConfig& config)
1084     : FboRenderCase(context, (string("between_render_") + config.getName()).c_str(), "TexSubImage between rendering calls", config)
1085 {
1086 }
1087 
1088 void TexSubImageBetweenRenderTest::render (sglr::Context& context, Surface& dst)
1089 {
1090     using sglr::TexturedQuadOp;
1091     using sglr::BlendTextureOp;
1092 
1093     bool isRGBA = true;
1094 
1095     Surface fourQuads(Surface::PIXELFORMAT_RGB, 64, 64);
1096     tcu::SurfaceUtil::fillWithFourQuads(fourQuads);
1097 
1098     Surface metaballs(isRGBA ? Surface::PIXELFORMAT_RGBA : Surface::PIXELFORMAT_RGB, 64, 64);
1099     tcu::SurfaceUtil::fillWithMetaballs(metaballs, 5, 3);
1100 
1101     Surface metaballs2(Surface::PIXELFORMAT_RGBA, 64, 64);
1102     tcu::SurfaceUtil::fillWithMetaballs(metaballs2, 5, 4);
1103 
1104     uint32_t metaballsTex = 3;
1105     context.bindTexture(GL_TEXTURE_2D, metaballsTex);
1106     context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1107     context.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, metaballs2);
1108 
1109     uint32_t fourQuadsTex = 1;
1110     context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
1111     context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1112     context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, fourQuads);
1113 
1114     context.bindFramebuffer(GL_FRAMEBUFFER, 1);
1115 
1116     uint32_t fboTex = 2;
1117     context.bindTexture(GL_TEXTURE_2D, fboTex);
1118     context.texImage2D(GL_TEXTURE_2D, 0, isRGBA ? GL_RGBA : GL_RGB, 128, 128);
1119     context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1120     context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);
1121 
1122     // Render to fbo
1123     context.viewport(0, 0, 128, 128);
1124     context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
1125     context.draw(TexturedQuadOp(-1.0f, -1.0f, 1.0f, 1.0f, 0));
1126 
1127     // Update texture using TexSubImage2D
1128     context.bindTexture(GL_TEXTURE_2D, fboTex);
1129     context.texSubImage2D(GL_TEXTURE_2D, 0, 32, 32, metaballs);
1130 
1131     // Render again to fbo
1132     context.bindTexture(GL_TEXTURE_2D, metaballsTex);
1133     context.draw(BlendTextureOp(0));
1134 
1135     // Draw to screen
1136     context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1137     context.viewport(0, 0, context.getWidth(), context.getHeight());
1138     context.bindTexture(GL_TEXTURE_2D, fboTex);
1139     context.draw(TexturedQuadOp(-1.0f, -1.0f, 1.0f, 1.0f, 0));
1140 
1141     context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1142 }
1143 #endif
1144 
1145 class ResizeTest : public FboRenderCase
1146 {
1147 public:
1148     ResizeTest(Context &context, const FboConfig &config);
~ResizeTest(void)1149     virtual ~ResizeTest(void)
1150     {
1151     }
1152 
1153     void render(sglr::Context &context, Surface &dst);
1154 };
1155 
ResizeTest(Context & context,const FboConfig & config)1156 ResizeTest::ResizeTest(Context &context, const FboConfig &config)
1157     : FboRenderCase(context, config.getName().c_str(), "Resize framebuffer", config)
1158 {
1159 }
1160 
render(sglr::Context & context,Surface & dst)1161 void ResizeTest::render(sglr::Context &context, Surface &dst)
1162 {
1163     tcu::TextureFormat colorFormat      = glu::mapGLInternalFormat(m_config.colorFormat);
1164     glu::DataType fboSamplerType        = glu::getSampler2DType(colorFormat);
1165     glu::DataType fboOutputType         = getFragmentOutputType(colorFormat);
1166     tcu::TextureFormatInfo fboRangeInfo = tcu::getTextureFormatInfo(colorFormat);
1167     Vec4 fboOutScale                    = fboRangeInfo.valueMax - fboRangeInfo.valueMin;
1168     Vec4 fboOutBias                     = fboRangeInfo.valueMin;
1169 
1170     Texture2DShader texToFboShader(DataTypes() << glu::TYPE_SAMPLER_2D, fboOutputType);
1171     Texture2DShader texFromFboShader(DataTypes() << fboSamplerType, glu::TYPE_FLOAT_VEC4);
1172     FlatColorShader flatShader(fboOutputType);
1173     uint32_t texToFboShaderID   = context.createProgram(&texToFboShader);
1174     uint32_t texFromFboShaderID = context.createProgram(&texFromFboShader);
1175     uint32_t flatShaderID       = context.createProgram(&flatShader);
1176 
1177     uint32_t quadsTex     = 1;
1178     uint32_t metaballsTex = 2;
1179     bool depth            = (m_config.buffers & GL_DEPTH_BUFFER_BIT) != 0;
1180     bool stencil          = (m_config.buffers & GL_STENCIL_BUFFER_BIT) != 0;
1181     int initialWidth      = 128;
1182     int initialHeight     = 128;
1183     int newWidth          = 64;
1184     int newHeight         = 32;
1185 
1186     texToFboShader.setOutScaleBias(fboOutScale, fboOutBias);
1187     texFromFboShader.setTexScaleBias(0, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);
1188 
1189     createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1190     createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 32, 32);
1191 
1192     Framebuffer fbo(context, m_config, initialWidth, initialHeight);
1193     fbo.checkCompleteness();
1194 
1195     // Setup shaders
1196     texToFboShader.setUniforms(context, texToFboShaderID);
1197     texFromFboShader.setUniforms(context, texFromFboShaderID);
1198     flatShader.setColor(context, flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f) * fboOutScale + fboOutBias);
1199 
1200     // Render quads
1201     context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1202     context.viewport(0, 0, initialWidth, initialHeight);
1203     clearColorBuffer(context, colorFormat, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
1204     context.clear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1205     context.bindTexture(GL_TEXTURE_2D, quadsTex);
1206     sglr::drawQuad(context, texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1207 
1208     if (fbo.getConfig().colorType == GL_TEXTURE_2D)
1209     {
1210         // Render fbo to screen
1211         context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1212         context.viewport(0, 0, context.getWidth(), context.getHeight());
1213         context.bindTexture(GL_TEXTURE_2D, fbo.getColorBuffer());
1214         sglr::drawQuad(context, texFromFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1215 
1216         // Restore binding
1217         context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1218     }
1219 
1220     // Resize buffers
1221     switch (fbo.getConfig().colorType)
1222     {
1223     case GL_TEXTURE_2D:
1224         context.bindTexture(GL_TEXTURE_2D, fbo.getColorBuffer());
1225         context.texImage2D(GL_TEXTURE_2D, 0, fbo.getConfig().colorFormat, newWidth, newHeight);
1226         break;
1227 
1228     case GL_RENDERBUFFER:
1229         context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getColorBuffer());
1230         context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().colorFormat, newWidth, newHeight);
1231         break;
1232 
1233     default:
1234         DE_ASSERT(false);
1235     }
1236 
1237     if (depth || stencil)
1238     {
1239         switch (fbo.getConfig().depthStencilType)
1240         {
1241         case GL_TEXTURE_2D:
1242             context.bindTexture(GL_TEXTURE_2D, fbo.getDepthStencilBuffer());
1243             context.texImage2D(GL_TEXTURE_2D, 0, fbo.getConfig().depthStencilFormat, newWidth, newHeight);
1244             break;
1245 
1246         case GL_RENDERBUFFER:
1247             context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getDepthStencilBuffer());
1248             context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().depthStencilFormat, newWidth, newHeight);
1249             break;
1250 
1251         default:
1252             DE_ASSERT(false);
1253         }
1254     }
1255 
1256     // Render to resized fbo
1257     context.viewport(0, 0, newWidth, newHeight);
1258     clearColorBuffer(context, colorFormat, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
1259     context.clear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1260 
1261     context.enable(GL_DEPTH_TEST);
1262 
1263     context.bindTexture(GL_TEXTURE_2D, metaballsTex);
1264     sglr::drawQuad(context, texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
1265 
1266     context.bindTexture(GL_TEXTURE_2D, quadsTex);
1267     sglr::drawQuad(context, texToFboShaderID, Vec3(0.0f, 0.0f, -1.0f), Vec3(+1.0f, +1.0f, 1.0f));
1268 
1269     context.disable(GL_DEPTH_TEST);
1270 
1271     if (stencil)
1272     {
1273         context.enable(GL_SCISSOR_TEST);
1274         context.clearStencil(1);
1275         context.scissor(10, 10, 5, 15);
1276         context.clear(GL_STENCIL_BUFFER_BIT);
1277         context.disable(GL_SCISSOR_TEST);
1278 
1279         context.enable(GL_STENCIL_TEST);
1280         context.stencilFunc(GL_EQUAL, 1, 0xffu);
1281         sglr::drawQuad(context, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
1282         context.disable(GL_STENCIL_TEST);
1283     }
1284 
1285     if (m_config.colorType == GL_TEXTURE_2D)
1286     {
1287         context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1288         context.viewport(0, 0, context.getWidth(), context.getHeight());
1289         context.bindTexture(GL_TEXTURE_2D, fbo.getColorBuffer());
1290         sglr::drawQuad(context, texFromFboShaderID, Vec3(-0.5f, -0.5f, 0.0f), Vec3(0.5f, 0.5f, 0.0f));
1291         context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1292     }
1293     else
1294         readPixels(context, dst, 0, 0, newWidth, newHeight, colorFormat, fboRangeInfo.lookupScale,
1295                    fboRangeInfo.lookupBias);
1296 }
1297 
1298 class RecreateBuffersTest : public FboRenderCase
1299 {
1300 public:
1301     RecreateBuffersTest(Context &context, const FboConfig &config, uint32_t buffers, bool rebind);
~RecreateBuffersTest(void)1302     virtual ~RecreateBuffersTest(void)
1303     {
1304     }
1305 
1306     void render(sglr::Context &context, Surface &dst);
1307 
1308 private:
1309     uint32_t m_buffers;
1310     bool m_rebind;
1311 };
1312 
RecreateBuffersTest(Context & context,const FboConfig & config,uint32_t buffers,bool rebind)1313 RecreateBuffersTest::RecreateBuffersTest(Context &context, const FboConfig &config, uint32_t buffers, bool rebind)
1314     : FboRenderCase(context, (string(config.getName()) + (rebind ? "" : "_no_rebind")).c_str(), "Recreate buffers",
1315                     config)
1316     , m_buffers(buffers)
1317     , m_rebind(rebind)
1318 {
1319 }
1320 
render(sglr::Context & ctx,Surface & dst)1321 void RecreateBuffersTest::render(sglr::Context &ctx, Surface &dst)
1322 {
1323     tcu::TextureFormat colorFormat      = glu::mapGLInternalFormat(m_config.colorFormat);
1324     glu::DataType fboSamplerType        = glu::getSampler2DType(colorFormat);
1325     glu::DataType fboOutputType         = getFragmentOutputType(colorFormat);
1326     tcu::TextureFormatInfo fboRangeInfo = tcu::getTextureFormatInfo(colorFormat);
1327     Vec4 fboOutScale                    = fboRangeInfo.valueMax - fboRangeInfo.valueMin;
1328     Vec4 fboOutBias                     = fboRangeInfo.valueMin;
1329 
1330     Texture2DShader texToFboShader(DataTypes() << glu::TYPE_SAMPLER_2D, fboOutputType);
1331     Texture2DShader texFromFboShader(DataTypes() << fboSamplerType, glu::TYPE_FLOAT_VEC4);
1332     FlatColorShader flatShader(fboOutputType);
1333     uint32_t texToFboShaderID   = ctx.createProgram(&texToFboShader);
1334     uint32_t texFromFboShaderID = ctx.createProgram(&texFromFboShader);
1335     uint32_t flatShaderID       = ctx.createProgram(&flatShader);
1336 
1337     int width             = 128;
1338     int height            = 128;
1339     uint32_t metaballsTex = 1;
1340     uint32_t quadsTex     = 2;
1341     bool stencil          = (m_config.buffers & GL_STENCIL_BUFFER_BIT) != 0;
1342 
1343     createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1344     createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1345 
1346     Framebuffer fbo(ctx, m_config, width, height);
1347     fbo.checkCompleteness();
1348 
1349     // Setup shaders
1350     texToFboShader.setOutScaleBias(fboOutScale, fboOutBias);
1351     texFromFboShader.setTexScaleBias(0, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);
1352     texToFboShader.setUniforms(ctx, texToFboShaderID);
1353     texFromFboShader.setUniforms(ctx, texFromFboShaderID);
1354     flatShader.setColor(ctx, flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f) * fboOutScale + fboOutBias);
1355 
1356     // Draw scene
1357     ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1358     ctx.viewport(0, 0, width, height);
1359     clearColorBuffer(ctx, colorFormat, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
1360     ctx.clear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1361 
1362     ctx.enable(GL_DEPTH_TEST);
1363 
1364     ctx.bindTexture(GL_TEXTURE_2D, quadsTex);
1365     sglr::drawQuad(ctx, texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1366 
1367     ctx.disable(GL_DEPTH_TEST);
1368 
1369     if (stencil)
1370     {
1371         ctx.enable(GL_SCISSOR_TEST);
1372         ctx.scissor(width / 4, height / 4, width / 2, height / 2);
1373         ctx.clearStencil(1);
1374         ctx.clear(GL_STENCIL_BUFFER_BIT);
1375         ctx.disable(GL_SCISSOR_TEST);
1376     }
1377 
1378     // Recreate buffers
1379     if (!m_rebind)
1380         ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
1381 
1382     DE_ASSERT((m_buffers & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) == 0 ||
1383               (m_buffers & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) ==
1384                   (m_config.buffers & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)));
1385 
1386     // Recreate.
1387     for (int ndx = 0; ndx < 2; ndx++)
1388     {
1389         uint32_t bit    = ndx == 0 ? GL_COLOR_BUFFER_BIT : (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1390         uint32_t type   = ndx == 0 ? fbo.getConfig().colorType : fbo.getConfig().depthStencilType;
1391         uint32_t format = ndx == 0 ? fbo.getConfig().colorFormat : fbo.getConfig().depthStencilFormat;
1392         uint32_t buf    = ndx == 0 ? fbo.getColorBuffer() : fbo.getDepthStencilBuffer();
1393 
1394         if ((m_buffers & bit) == 0)
1395             continue;
1396 
1397         switch (type)
1398         {
1399         case GL_TEXTURE_2D:
1400             ctx.deleteTextures(1, &buf);
1401             ctx.bindTexture(GL_TEXTURE_2D, buf);
1402             ctx.texImage2D(GL_TEXTURE_2D, 0, format, width, height);
1403             ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1404             ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1405             break;
1406 
1407         case GL_RENDERBUFFER:
1408             ctx.deleteRenderbuffers(1, &buf);
1409             ctx.bindRenderbuffer(GL_RENDERBUFFER, buf);
1410             ctx.renderbufferStorage(GL_RENDERBUFFER, format, width, height);
1411             break;
1412 
1413         default:
1414             DE_ASSERT(false);
1415         }
1416     }
1417 
1418     // Rebind.
1419     if (m_rebind)
1420     {
1421         for (int ndx = 0; ndx < 3; ndx++)
1422         {
1423             uint32_t bit   = ndx == 0 ? GL_COLOR_BUFFER_BIT :
1424                              ndx == 1 ? GL_DEPTH_BUFFER_BIT :
1425                              ndx == 2 ? GL_STENCIL_BUFFER_BIT :
1426                                         0;
1427             uint32_t point = ndx == 0 ? GL_COLOR_ATTACHMENT0 :
1428                              ndx == 1 ? GL_DEPTH_ATTACHMENT :
1429                              ndx == 2 ? GL_STENCIL_ATTACHMENT :
1430                                         0;
1431             uint32_t type  = ndx == 0 ? fbo.getConfig().colorType : fbo.getConfig().depthStencilType;
1432             uint32_t buf   = ndx == 0 ? fbo.getColorBuffer() : fbo.getDepthStencilBuffer();
1433 
1434             if ((m_buffers & bit) == 0)
1435                 continue;
1436 
1437             switch (type)
1438             {
1439             case GL_TEXTURE_2D:
1440                 ctx.framebufferTexture2D(GL_FRAMEBUFFER, point, GL_TEXTURE_2D, buf, 0);
1441                 break;
1442 
1443             case GL_RENDERBUFFER:
1444                 ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, point, GL_RENDERBUFFER, buf);
1445                 break;
1446 
1447             default:
1448                 DE_ASSERT(false);
1449             }
1450         }
1451     }
1452 
1453     if (!m_rebind)
1454         ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1455 
1456     ctx.clearStencil(0);
1457     ctx.clear(m_buffers &
1458               (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)); // \note Clear only buffers that were re-created
1459     if (m_buffers & GL_COLOR_BUFFER_BIT)
1460     {
1461         // Clearing of integer buffers is undefined so do clearing by rendering flat color.
1462         sglr::drawQuad(ctx, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1463     }
1464 
1465     ctx.enable(GL_DEPTH_TEST);
1466 
1467     if (stencil)
1468     {
1469         // \note Stencil test enabled only if we have stencil buffer
1470         ctx.enable(GL_STENCIL_TEST);
1471         ctx.stencilFunc(GL_EQUAL, 0, 0xffu);
1472     }
1473     ctx.bindTexture(GL_TEXTURE_2D, metaballsTex);
1474     sglr::drawQuad(ctx, texToFboShaderID, Vec3(-1.0f, -1.0f, 1.0f), Vec3(1.0f, 1.0f, -1.0f));
1475     if (stencil)
1476         ctx.disable(GL_STENCIL_TEST);
1477 
1478     ctx.disable(GL_DEPTH_TEST);
1479 
1480     if (fbo.getConfig().colorType == GL_TEXTURE_2D)
1481     {
1482         // Unbind fbo
1483         ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
1484 
1485         // Draw to screen
1486         ctx.bindTexture(GL_TEXTURE_2D, fbo.getColorBuffer());
1487         ctx.viewport(0, 0, ctx.getWidth(), ctx.getHeight());
1488         sglr::drawQuad(ctx, texFromFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1489 
1490         // Read from screen
1491         ctx.readPixels(dst, 0, 0, ctx.getWidth(), ctx.getHeight());
1492     }
1493     else
1494     {
1495         // Read from fbo
1496         readPixels(ctx, dst, 0, 0, width, height, colorFormat, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);
1497     }
1498 }
1499 
1500 } // namespace FboCases
1501 
FboRenderTestGroup(Context & context)1502 FboRenderTestGroup::FboRenderTestGroup(Context &context) : TestCaseGroup(context, "render", "Rendering Tests")
1503 {
1504 }
1505 
~FboRenderTestGroup(void)1506 FboRenderTestGroup::~FboRenderTestGroup(void)
1507 {
1508 }
1509 
init(void)1510 void FboRenderTestGroup::init(void)
1511 {
1512     static const uint32_t objectTypes[] = {GL_TEXTURE_2D, GL_RENDERBUFFER};
1513 
1514     enum FormatType
1515     {
1516         FORMATTYPE_FLOAT = 0,
1517         FORMATTYPE_FIXED,
1518         FORMATTYPE_INT,
1519         FORMATTYPE_UINT,
1520 
1521         FORMATTYPE_LAST
1522     };
1523 
1524     // Required by specification.
1525     static const struct
1526     {
1527         uint32_t format;
1528         FormatType type;
1529     } colorFormats[] = {{GL_RGBA32F, FORMATTYPE_FLOAT},
1530                         {GL_RGBA32I, FORMATTYPE_INT},
1531                         {GL_RGBA32UI, FORMATTYPE_UINT},
1532                         {GL_RGBA16F, FORMATTYPE_FLOAT},
1533                         {GL_RGBA16I, FORMATTYPE_INT},
1534                         {GL_RGBA16UI, FORMATTYPE_UINT},
1535                         {GL_RGB16F, FORMATTYPE_FLOAT},
1536                         {GL_RGBA8, FORMATTYPE_FIXED},
1537                         {GL_RGBA8I, FORMATTYPE_INT},
1538                         {GL_RGBA8UI, FORMATTYPE_UINT},
1539                         {GL_SRGB8_ALPHA8, FORMATTYPE_FIXED},
1540                         {GL_RGB10_A2, FORMATTYPE_FIXED},
1541                         {GL_RGB10_A2UI, FORMATTYPE_UINT},
1542                         {GL_RGBA4, FORMATTYPE_FIXED},
1543                         {GL_RGB5_A1, FORMATTYPE_FIXED},
1544                         {GL_RGB8, FORMATTYPE_FIXED},
1545                         {GL_RGB565, FORMATTYPE_FIXED},
1546                         {GL_R11F_G11F_B10F, FORMATTYPE_FLOAT},
1547                         {GL_RG32F, FORMATTYPE_FLOAT},
1548                         {GL_RG32I, FORMATTYPE_INT},
1549                         {GL_RG32UI, FORMATTYPE_UINT},
1550                         {GL_RG16F, FORMATTYPE_FLOAT},
1551                         {GL_RG16I, FORMATTYPE_INT},
1552                         {GL_RG16UI, FORMATTYPE_UINT},
1553                         {GL_RG8, FORMATTYPE_FLOAT},
1554                         {GL_RG8I, FORMATTYPE_INT},
1555                         {GL_RG8UI, FORMATTYPE_UINT},
1556                         {GL_R32F, FORMATTYPE_FLOAT},
1557                         {GL_R32I, FORMATTYPE_INT},
1558                         {GL_R32UI, FORMATTYPE_UINT},
1559                         {GL_R16F, FORMATTYPE_FLOAT},
1560                         {GL_R16I, FORMATTYPE_INT},
1561                         {GL_R16UI, FORMATTYPE_UINT},
1562                         {GL_R8, FORMATTYPE_FLOAT},
1563                         {GL_R8I, FORMATTYPE_INT},
1564                         {GL_R8UI, FORMATTYPE_UINT}};
1565 
1566     static const struct
1567     {
1568         uint32_t format;
1569         bool depth;
1570         bool stencil;
1571     } depthStencilFormats[] = {{GL_DEPTH_COMPONENT32F, true, false}, {GL_DEPTH_COMPONENT24, true, false},
1572                                {GL_DEPTH_COMPONENT16, true, false},  {GL_DEPTH32F_STENCIL8, true, true},
1573                                {GL_DEPTH24_STENCIL8, true, true},    {GL_STENCIL_INDEX8, false, true}};
1574 
1575     using namespace FboCases;
1576 
1577     // .stencil_clear
1578     tcu::TestCaseGroup *stencilClearGroup = new tcu::TestCaseGroup(m_testCtx, "stencil_clear", "Stencil buffer clears");
1579     addChild(stencilClearGroup);
1580     for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); fmtNdx++)
1581     {
1582         uint32_t colorType   = GL_TEXTURE_2D;
1583         uint32_t stencilType = GL_RENDERBUFFER;
1584         uint32_t colorFmt    = GL_RGBA8;
1585 
1586         if (!depthStencilFormats[fmtNdx].stencil)
1587             continue;
1588 
1589         FboConfig config(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, colorType, colorFmt, stencilType,
1590                          depthStencilFormats[fmtNdx].format);
1591         stencilClearGroup->addChild(new StencilClearsTest(m_context, config));
1592     }
1593 
1594     // .shared_colorbuffer_clear
1595     tcu::TestCaseGroup *sharedColorbufferClearGroup =
1596         new tcu::TestCaseGroup(m_testCtx, "shared_colorbuffer_clear", "Shader colorbuffer clears");
1597     addChild(sharedColorbufferClearGroup);
1598     for (int colorFmtNdx = 0; colorFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); colorFmtNdx++)
1599     {
1600         // Clearing of integer buffers is undefined.
1601         if (colorFormats[colorFmtNdx].type == FORMATTYPE_INT || colorFormats[colorFmtNdx].type == FORMATTYPE_UINT)
1602             continue;
1603 
1604         for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
1605         {
1606             FboConfig config(GL_COLOR_BUFFER_BIT, objectTypes[typeNdx], colorFormats[colorFmtNdx].format, GL_NONE,
1607                              GL_NONE);
1608             sharedColorbufferClearGroup->addChild(new SharedColorbufferClearsTest(m_context, config));
1609         }
1610     }
1611 
1612     // .shared_colorbuffer
1613     tcu::TestCaseGroup *sharedColorbufferGroup =
1614         new tcu::TestCaseGroup(m_testCtx, "shared_colorbuffer", "Shared colorbuffer tests");
1615     addChild(sharedColorbufferGroup);
1616     for (int colorFmtNdx = 0; colorFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); colorFmtNdx++)
1617     {
1618         uint32_t depthStencilType   = GL_RENDERBUFFER;
1619         uint32_t depthStencilFormat = GL_DEPTH24_STENCIL8;
1620 
1621         // Blending with integer buffers and fp32 targets is not supported.
1622         if (colorFormats[colorFmtNdx].type == FORMATTYPE_INT || colorFormats[colorFmtNdx].type == FORMATTYPE_UINT ||
1623             colorFormats[colorFmtNdx].format == GL_RGBA32F || colorFormats[colorFmtNdx].format == GL_RGB32F ||
1624             colorFormats[colorFmtNdx].format == GL_RG32F || colorFormats[colorFmtNdx].format == GL_R32F)
1625             continue;
1626 
1627         for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
1628         {
1629             FboConfig colorOnlyConfig(GL_COLOR_BUFFER_BIT, objectTypes[typeNdx], colorFormats[colorFmtNdx].format,
1630                                       GL_NONE, GL_NONE);
1631             FboConfig colorDepthConfig(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, objectTypes[typeNdx],
1632                                        colorFormats[colorFmtNdx].format, depthStencilType, depthStencilFormat);
1633             FboConfig colorDepthStencilConfig(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
1634                                               objectTypes[typeNdx], colorFormats[colorFmtNdx].format, depthStencilType,
1635                                               depthStencilFormat);
1636 
1637             sharedColorbufferGroup->addChild(new SharedColorbufferTest(m_context, colorOnlyConfig));
1638             sharedColorbufferGroup->addChild(new SharedColorbufferTest(m_context, colorDepthConfig));
1639             sharedColorbufferGroup->addChild(new SharedColorbufferTest(m_context, colorDepthStencilConfig));
1640         }
1641     }
1642 
1643     // .shared_depth_stencil
1644     tcu::TestCaseGroup *sharedDepthStencilGroup =
1645         new tcu::TestCaseGroup(m_testCtx, "shared_depth_stencil", "Shared depth and stencil buffers");
1646     addChild(sharedDepthStencilGroup);
1647     for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); fmtNdx++)
1648     {
1649         uint32_t colorType = GL_TEXTURE_2D;
1650         uint32_t colorFmt  = GL_RGBA8;
1651         bool depth         = depthStencilFormats[fmtNdx].depth;
1652         bool stencil       = depthStencilFormats[fmtNdx].stencil;
1653 
1654         if (!depth)
1655             continue; // Not verified.
1656 
1657         // Depth and stencil: both rbo and textures
1658         for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
1659         {
1660             FboConfig config(GL_COLOR_BUFFER_BIT | (depth ? GL_DEPTH_BUFFER_BIT : 0) |
1661                                  (stencil ? GL_STENCIL_BUFFER_BIT : 0),
1662                              colorType, colorFmt, objectTypes[typeNdx], depthStencilFormats[fmtNdx].format);
1663             sharedDepthStencilGroup->addChild(new SharedDepthStencilTest(m_context, config));
1664         }
1665     }
1666 
1667     // .resize
1668     tcu::TestCaseGroup *resizeGroup = new tcu::TestCaseGroup(m_testCtx, "resize", "FBO resize tests");
1669     addChild(resizeGroup);
1670     for (int colorFmtNdx = 0; colorFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); colorFmtNdx++)
1671     {
1672         uint32_t colorFormat = colorFormats[colorFmtNdx].format;
1673 
1674         // Color-only.
1675         for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
1676         {
1677             FboConfig config(GL_COLOR_BUFFER_BIT, objectTypes[typeNdx], colorFormat, GL_NONE, GL_NONE);
1678             resizeGroup->addChild(new ResizeTest(m_context, config));
1679         }
1680 
1681         // For selected color formats tests depth & stencil variants.
1682         if (colorFormat == GL_RGBA8 || colorFormat == GL_RGBA16F)
1683         {
1684             for (int depthStencilFmtNdx = 0; depthStencilFmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats);
1685                  depthStencilFmtNdx++)
1686             {
1687                 uint32_t colorType = GL_TEXTURE_2D;
1688                 bool depth         = depthStencilFormats[depthStencilFmtNdx].depth;
1689                 bool stencil       = depthStencilFormats[depthStencilFmtNdx].stencil;
1690 
1691                 // Depth and stencil: both rbo and textures
1692                 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
1693                 {
1694                     if (!depth && objectTypes[typeNdx] != GL_RENDERBUFFER)
1695                         continue; // Not supported.
1696 
1697                     FboConfig config(
1698                         GL_COLOR_BUFFER_BIT | (depth ? GL_DEPTH_BUFFER_BIT : 0) | (stencil ? GL_STENCIL_BUFFER_BIT : 0),
1699                         colorType, colorFormat, objectTypes[typeNdx], depthStencilFormats[depthStencilFmtNdx].format);
1700                     resizeGroup->addChild(new ResizeTest(m_context, config));
1701                 }
1702             }
1703         }
1704     }
1705 
1706     // .recreate_color
1707     tcu::TestCaseGroup *recreateColorGroup =
1708         new tcu::TestCaseGroup(m_testCtx, "recreate_color", "Recreate colorbuffer tests");
1709     addChild(recreateColorGroup);
1710     for (int colorFmtNdx = 0; colorFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); colorFmtNdx++)
1711     {
1712         uint32_t colorFormat        = colorFormats[colorFmtNdx].format;
1713         uint32_t depthStencilFormat = GL_DEPTH24_STENCIL8;
1714         uint32_t depthStencilType   = GL_RENDERBUFFER;
1715 
1716         // Color-only.
1717         for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
1718         {
1719             FboConfig config(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, objectTypes[typeNdx],
1720                              colorFormat, depthStencilType, depthStencilFormat);
1721             recreateColorGroup->addChild(
1722                 new RecreateBuffersTest(m_context, config, GL_COLOR_BUFFER_BIT, true /* rebind */));
1723         }
1724     }
1725 
1726     // .recreate_depth_stencil
1727     tcu::TestCaseGroup *recreateDepthStencilGroup =
1728         new tcu::TestCaseGroup(m_testCtx, "recreate_depth_stencil", "Recreate depth and stencil buffers");
1729     addChild(recreateDepthStencilGroup);
1730     for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); fmtNdx++)
1731     {
1732         uint32_t colorType = GL_TEXTURE_2D;
1733         uint32_t colorFmt  = GL_RGBA8;
1734         bool depth         = depthStencilFormats[fmtNdx].depth;
1735         bool stencil       = depthStencilFormats[fmtNdx].stencil;
1736 
1737         // Depth and stencil: both rbo and textures
1738         for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
1739         {
1740             if (!depth && objectTypes[typeNdx] != GL_RENDERBUFFER)
1741                 continue;
1742 
1743             FboConfig config(GL_COLOR_BUFFER_BIT | (depth ? GL_DEPTH_BUFFER_BIT : 0) |
1744                                  (stencil ? GL_STENCIL_BUFFER_BIT : 0),
1745                              colorType, colorFmt, objectTypes[typeNdx], depthStencilFormats[fmtNdx].format);
1746             recreateDepthStencilGroup->addChild(new RecreateBuffersTest(
1747                 m_context, config, (depth ? GL_DEPTH_BUFFER_BIT : 0) | (stencil ? GL_STENCIL_BUFFER_BIT : 0),
1748                 true /* rebind */));
1749         }
1750     }
1751 }
1752 
1753 } // namespace Functional
1754 } // namespace gles3
1755 } // namespace deqp
1756