xref: /aosp_15_r20/external/deqp/modules/gles3/functional/es3fFboInvalidateTests.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 FBO invalidate tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es3fFboInvalidateTests.hpp"
25 #include "es3fFboTestCase.hpp"
26 #include "es3fFboTestUtil.hpp"
27 #include "gluTextureUtil.hpp"
28 #include "tcuImageCompare.hpp"
29 #include "tcuTextureUtil.hpp"
30 #include "sglrContextUtil.hpp"
31 
32 #include "glwEnums.hpp"
33 
34 #include <algorithm>
35 
36 namespace deqp
37 {
38 namespace gles3
39 {
40 namespace Functional
41 {
42 
43 using std::string;
44 using std::vector;
45 using tcu::IVec2;
46 using tcu::IVec3;
47 using tcu::IVec4;
48 using tcu::UVec4;
49 using tcu::Vec2;
50 using tcu::Vec3;
51 using tcu::Vec4;
52 using namespace FboTestUtil;
53 
getDefaultFBDiscardAttachments(uint32_t discardBufferBits)54 static std::vector<uint32_t> getDefaultFBDiscardAttachments(uint32_t discardBufferBits)
55 {
56     vector<uint32_t> attachments;
57 
58     if (discardBufferBits & GL_COLOR_BUFFER_BIT)
59         attachments.push_back(GL_COLOR);
60 
61     if (discardBufferBits & GL_DEPTH_BUFFER_BIT)
62         attachments.push_back(GL_DEPTH);
63 
64     if (discardBufferBits & GL_STENCIL_BUFFER_BIT)
65         attachments.push_back(GL_STENCIL);
66 
67     return attachments;
68 }
69 
getFBODiscardAttachments(uint32_t discardBufferBits)70 static std::vector<uint32_t> getFBODiscardAttachments(uint32_t discardBufferBits)
71 {
72     vector<uint32_t> attachments;
73 
74     if (discardBufferBits & GL_COLOR_BUFFER_BIT)
75         attachments.push_back(GL_COLOR_ATTACHMENT0);
76 
77     // \note DEPTH_STENCIL_ATTACHMENT is allowed when discarding FBO, but not with default FB
78     if ((discardBufferBits & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) ==
79         (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
80         attachments.push_back(GL_DEPTH_STENCIL_ATTACHMENT);
81     else if (discardBufferBits & GL_DEPTH_BUFFER_BIT)
82         attachments.push_back(GL_DEPTH_ATTACHMENT);
83     else if (discardBufferBits & GL_STENCIL_BUFFER_BIT)
84         attachments.push_back(GL_STENCIL_ATTACHMENT);
85 
86     return attachments;
87 }
88 
hasAttachment(const std::vector<uint32_t> & attachmentList,uint32_t attachment)89 static inline bool hasAttachment(const std::vector<uint32_t> &attachmentList, uint32_t attachment)
90 {
91     return std::find(attachmentList.begin(), attachmentList.end(), attachment) != attachmentList.end();
92 }
93 
getCompatibleColorFormat(const tcu::RenderTarget & renderTargetInfo)94 static uint32_t getCompatibleColorFormat(const tcu::RenderTarget &renderTargetInfo)
95 {
96     const tcu::PixelFormat &pxFmt = renderTargetInfo.getPixelFormat();
97     DE_ASSERT(de::inBounds(pxFmt.redBits, 0, 0xff) && de::inBounds(pxFmt.greenBits, 0, 0xff) &&
98               de::inBounds(pxFmt.blueBits, 0, 0xff) && de::inBounds(pxFmt.alphaBits, 0, 0xff));
99 
100 #define PACK_FMT(R, G, B, A) (((R) << 24) | ((G) << 16) | ((B) << 8) | (A))
101 
102     // \note [pyry] This may not hold true on some implementations - best effort guess only.
103     switch (PACK_FMT(pxFmt.redBits, pxFmt.greenBits, pxFmt.blueBits, pxFmt.alphaBits))
104     {
105     case PACK_FMT(8, 8, 8, 8):
106         return GL_RGBA8;
107     case PACK_FMT(8, 8, 8, 0):
108         return GL_RGB8;
109     case PACK_FMT(4, 4, 4, 4):
110         return GL_RGBA4;
111     case PACK_FMT(5, 5, 5, 1):
112         return GL_RGB5_A1;
113     case PACK_FMT(5, 6, 5, 0):
114         return GL_RGB565;
115     default:
116         return GL_NONE;
117     }
118 
119 #undef PACK_FMT
120 }
121 
getCompatibleDepthStencilFormat(const tcu::RenderTarget & renderTargetInfo)122 static uint32_t getCompatibleDepthStencilFormat(const tcu::RenderTarget &renderTargetInfo)
123 {
124     const int depthBits   = renderTargetInfo.getDepthBits();
125     const int stencilBits = renderTargetInfo.getStencilBits();
126     const bool hasDepth   = depthBits > 0;
127     const bool hasStencil = stencilBits > 0;
128 
129     if (!hasDepth || !hasStencil || (stencilBits != 8))
130         return GL_NONE;
131 
132     if (depthBits == 32)
133         return GL_DEPTH32F_STENCIL8;
134     else if (depthBits == 24)
135         return GL_DEPTH24_STENCIL8;
136     else
137         return GL_NONE;
138 }
139 
140 class InvalidateDefaultFramebufferRenderCase : public FboTestCase
141 {
142 public:
InvalidateDefaultFramebufferRenderCase(Context & context,const char * name,const char * description,uint32_t buffers,uint32_t fboTarget=GL_FRAMEBUFFER)143     InvalidateDefaultFramebufferRenderCase(Context &context, const char *name, const char *description,
144                                            uint32_t buffers, uint32_t fboTarget = GL_FRAMEBUFFER)
145         : FboTestCase(context, name, description)
146         , m_buffers(buffers)
147         , m_fboTarget(fboTarget)
148     {
149     }
150 
render(tcu::Surface & dst)151     void render(tcu::Surface &dst)
152     {
153         FlatColorShader flatShader(glu::TYPE_FLOAT_VEC4);
154         vector<uint32_t> attachments = getDefaultFBDiscardAttachments(m_buffers);
155         uint32_t flatShaderID        = getCurrentContext()->createProgram(&flatShader);
156 
157         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
158         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
159 
160         glEnable(GL_DEPTH_TEST);
161         glEnable(GL_STENCIL_TEST);
162         glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
163         glStencilFunc(GL_ALWAYS, 1, 0xff);
164 
165         flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f));
166         sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
167 
168         glInvalidateFramebuffer(m_fboTarget, (int)attachments.size(), attachments.empty() ? DE_NULL : &attachments[0]);
169 
170         if ((m_buffers & GL_COLOR_BUFFER_BIT) != 0)
171         {
172             // Color was not preserved - fill with green.
173             glDisable(GL_DEPTH_TEST);
174             glDisable(GL_STENCIL_TEST);
175 
176             flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
177             sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
178 
179             glEnable(GL_DEPTH_TEST);
180             glEnable(GL_STENCIL_TEST);
181         }
182 
183         if ((m_buffers & GL_DEPTH_BUFFER_BIT) != 0)
184         {
185             // Depth was not preserved.
186             glDepthFunc(GL_ALWAYS);
187         }
188 
189         if ((m_buffers & GL_STENCIL_BUFFER_BIT) == 0)
190         {
191             // Stencil was preserved.
192             glStencilFunc(GL_EQUAL, 1, 0xff);
193         }
194 
195         glEnable(GL_BLEND);
196         glBlendFunc(GL_ONE, GL_ONE);
197         glBlendEquation(GL_FUNC_ADD);
198 
199         flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f));
200         sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
201 
202         readPixels(dst, 0, 0, getWidth(), getHeight());
203     }
204 
205 private:
206     uint32_t m_buffers;
207     uint32_t m_fboTarget;
208 };
209 
210 class InvalidateDefaultFramebufferBindCase : public FboTestCase
211 {
212 public:
InvalidateDefaultFramebufferBindCase(Context & context,const char * name,const char * description,uint32_t buffers)213     InvalidateDefaultFramebufferBindCase(Context &context, const char *name, const char *description, uint32_t buffers)
214         : FboTestCase(context, name, description)
215         , m_buffers(buffers)
216     {
217     }
218 
render(tcu::Surface & dst)219     void render(tcu::Surface &dst)
220     {
221         uint32_t fbo = 0;
222         uint32_t tex = 0;
223         FlatColorShader flatShader(glu::TYPE_FLOAT_VEC4);
224         Texture2DShader texShader(DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4);
225         GradientShader gradShader(glu::TYPE_FLOAT_VEC4);
226         vector<uint32_t> attachments = getDefaultFBDiscardAttachments(m_buffers);
227         uint32_t flatShaderID        = getCurrentContext()->createProgram(&flatShader);
228         uint32_t texShaderID         = getCurrentContext()->createProgram(&texShader);
229         uint32_t gradShaderID        = getCurrentContext()->createProgram(&gradShader);
230 
231         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
232         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
233 
234         // Create fbo.
235         glGenFramebuffers(1, &fbo);
236         glGenTextures(1, &tex);
237         glBindTexture(GL_TEXTURE_2D, tex);
238         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWidth(), getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
239         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
240         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
241         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
242         glBindTexture(GL_TEXTURE_2D, 0);
243         checkFramebufferStatus(GL_FRAMEBUFFER);
244 
245         glBindFramebuffer(GL_FRAMEBUFFER, 0);
246 
247         glEnable(GL_DEPTH_TEST);
248         glEnable(GL_STENCIL_TEST);
249         glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
250         glStencilFunc(GL_ALWAYS, 1, 0xff);
251 
252         flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f));
253         sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
254 
255         glInvalidateFramebuffer(GL_FRAMEBUFFER, (int)attachments.size(),
256                                 attachments.empty() ? DE_NULL : &attachments[0]);
257 
258         // Switch to fbo and render gradient into it.
259         glDisable(GL_DEPTH_TEST);
260         glDisable(GL_STENCIL_TEST);
261         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
262 
263         gradShader.setGradient(*getCurrentContext(), gradShaderID, Vec4(0.0f), Vec4(1.0f));
264         sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
265 
266         // Restore default fbo.
267         glBindFramebuffer(GL_FRAMEBUFFER, 0);
268 
269         if ((m_buffers & GL_COLOR_BUFFER_BIT) != 0)
270         {
271             // Color was not preserved - fill with green.
272             flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
273             sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
274         }
275 
276         if ((m_buffers & GL_DEPTH_BUFFER_BIT) != 0)
277         {
278             // Depth was not preserved.
279             glDepthFunc(GL_ALWAYS);
280         }
281 
282         if ((m_buffers & GL_STENCIL_BUFFER_BIT) == 0)
283         {
284             // Stencil was preserved.
285             glStencilFunc(GL_EQUAL, 1, 0xff);
286         }
287 
288         glEnable(GL_DEPTH_TEST);
289         glEnable(GL_STENCIL_TEST);
290         glEnable(GL_BLEND);
291         glBlendFunc(GL_ONE, GL_ONE);
292         glBlendEquation(GL_FUNC_ADD);
293         glBindTexture(GL_TEXTURE_2D, tex);
294 
295         texShader.setUniforms(*getCurrentContext(), texShaderID);
296         sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
297 
298         readPixels(dst, 0, 0, getWidth(), getHeight());
299     }
300 
301 private:
302     uint32_t m_buffers;
303 };
304 
305 class InvalidateDefaultSubFramebufferRenderCase : public FboTestCase
306 {
307 public:
InvalidateDefaultSubFramebufferRenderCase(Context & context,const char * name,const char * description,uint32_t buffers)308     InvalidateDefaultSubFramebufferRenderCase(Context &context, const char *name, const char *description,
309                                               uint32_t buffers)
310         : FboTestCase(context, name, description)
311         , m_buffers(buffers)
312     {
313     }
314 
render(tcu::Surface & dst)315     void render(tcu::Surface &dst)
316     {
317         int invalidateX = getWidth() / 4;
318         int invalidateY = getHeight() / 4;
319         int invalidateW = getWidth() / 2;
320         int invalidateH = getHeight() / 2;
321         FlatColorShader flatShader(glu::TYPE_FLOAT_VEC4);
322         vector<uint32_t> attachments = getDefaultFBDiscardAttachments(m_buffers);
323         uint32_t flatShaderID        = getCurrentContext()->createProgram(&flatShader);
324 
325         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
326         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
327 
328         glEnable(GL_DEPTH_TEST);
329         glEnable(GL_STENCIL_TEST);
330         glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
331         glStencilFunc(GL_ALWAYS, 1, 0xff);
332 
333         flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f));
334         sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
335 
336         glInvalidateSubFramebuffer(GL_FRAMEBUFFER, (int)attachments.size(), &attachments[0], invalidateX, invalidateY,
337                                    invalidateW, invalidateH);
338 
339         // Clear invalidated buffers.
340         glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
341         glClearStencil(1);
342         glScissor(invalidateX, invalidateY, invalidateW, invalidateH);
343         glEnable(GL_SCISSOR_TEST);
344         glClear(m_buffers);
345         glDisable(GL_SCISSOR_TEST);
346 
347         glEnable(GL_BLEND);
348         glBlendFunc(GL_ONE, GL_ONE);
349         glBlendEquation(GL_FUNC_ADD);
350 
351         flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f));
352         sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
353 
354         readPixels(dst, 0, 0, getWidth(), getHeight());
355     }
356 
357 private:
358     uint32_t m_buffers;
359 };
360 
361 class InvalidateDefaultSubFramebufferBindCase : public FboTestCase
362 {
363 public:
InvalidateDefaultSubFramebufferBindCase(Context & context,const char * name,const char * description,uint32_t buffers)364     InvalidateDefaultSubFramebufferBindCase(Context &context, const char *name, const char *description,
365                                             uint32_t buffers)
366         : FboTestCase(context, name, description)
367         , m_buffers(buffers)
368     {
369     }
370 
render(tcu::Surface & dst)371     void render(tcu::Surface &dst)
372     {
373         uint32_t fbo = 0;
374         uint32_t tex = 0;
375         FlatColorShader flatShader(glu::TYPE_FLOAT_VEC4);
376         Texture2DShader texShader(DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4);
377         GradientShader gradShader(glu::TYPE_FLOAT_VEC4);
378         vector<uint32_t> attachments = getDefaultFBDiscardAttachments(m_buffers);
379         uint32_t flatShaderID        = getCurrentContext()->createProgram(&flatShader);
380         uint32_t texShaderID         = getCurrentContext()->createProgram(&texShader);
381         uint32_t gradShaderID        = getCurrentContext()->createProgram(&gradShader);
382 
383         int invalidateX = getWidth() / 4;
384         int invalidateY = getHeight() / 4;
385         int invalidateW = getWidth() / 2;
386         int invalidateH = getHeight() / 2;
387 
388         flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f));
389         texShader.setUniforms(*getCurrentContext(), texShaderID);
390         gradShader.setGradient(*getCurrentContext(), gradShaderID, Vec4(0.0f), Vec4(1.0f));
391 
392         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
393         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
394 
395         // Create fbo.
396         glGenFramebuffers(1, &fbo);
397         glGenTextures(1, &tex);
398         glBindTexture(GL_TEXTURE_2D, tex);
399         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWidth(), getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
400         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
401         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
402         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
403         glBindTexture(GL_TEXTURE_2D, 0);
404         checkFramebufferStatus(GL_FRAMEBUFFER);
405 
406         glBindFramebuffer(GL_FRAMEBUFFER, 0);
407 
408         glEnable(GL_DEPTH_TEST);
409         glEnable(GL_STENCIL_TEST);
410         glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
411         glStencilFunc(GL_ALWAYS, 1, 0xff);
412 
413         sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
414 
415         glInvalidateSubFramebuffer(GL_FRAMEBUFFER, (int)attachments.size(), &attachments[0], invalidateX, invalidateY,
416                                    invalidateW, invalidateH);
417 
418         // Switch to fbo and render gradient into it.
419         glDisable(GL_DEPTH_TEST);
420         glDisable(GL_STENCIL_TEST);
421         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
422 
423         sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
424 
425         // Restore default fbo.
426         glBindFramebuffer(GL_FRAMEBUFFER, 0);
427 
428         // Clear invalidated buffers.
429         glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
430         glClearStencil(1);
431         glScissor(invalidateX, invalidateY, invalidateW, invalidateH);
432         glEnable(GL_SCISSOR_TEST);
433         glClear(m_buffers);
434         glDisable(GL_SCISSOR_TEST);
435 
436         glEnable(GL_DEPTH_TEST);
437         glEnable(GL_STENCIL_TEST);
438         glEnable(GL_BLEND);
439         glBlendFunc(GL_ONE, GL_ONE);
440         glBlendEquation(GL_FUNC_ADD);
441         glBindTexture(GL_TEXTURE_2D, tex);
442 
443         sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
444 
445         readPixels(dst, 0, 0, getWidth(), getHeight());
446     }
447 
448 private:
449     uint32_t m_buffers;
450 };
451 
452 class InvalidateFboRenderCase : public FboTestCase
453 {
454 public:
InvalidateFboRenderCase(Context & context,const char * name,const char * description,uint32_t colorFmt,uint32_t depthStencilFmt,uint32_t invalidateBuffers)455     InvalidateFboRenderCase(Context &context, const char *name, const char *description, uint32_t colorFmt,
456                             uint32_t depthStencilFmt, uint32_t invalidateBuffers)
457         : FboTestCase(context, name, description)
458         , m_colorFmt(colorFmt)
459         , m_depthStencilFmt(depthStencilFmt)
460         , m_invalidateBuffers(invalidateBuffers)
461     {
462     }
463 
464 protected:
preCheck(void)465     void preCheck(void)
466     {
467         if (m_colorFmt != GL_NONE)
468             checkFormatSupport(m_colorFmt);
469         if (m_depthStencilFmt != GL_NONE)
470             checkFormatSupport(m_depthStencilFmt);
471     }
472 
render(tcu::Surface & dst)473     void render(tcu::Surface &dst)
474     {
475         tcu::TextureFormat colorFmt = glu::mapGLInternalFormat(m_colorFmt);
476         tcu::TextureFormat depthStencilFmt =
477             m_depthStencilFmt != GL_NONE ? glu::mapGLInternalFormat(m_depthStencilFmt) : tcu::TextureFormat();
478         tcu::TextureFormatInfo colorFmtInfo = tcu::getTextureFormatInfo(colorFmt);
479         bool depth = depthStencilFmt.order == tcu::TextureFormat::D || depthStencilFmt.order == tcu::TextureFormat::DS;
480         bool stencil =
481             depthStencilFmt.order == tcu::TextureFormat::S || depthStencilFmt.order == tcu::TextureFormat::DS;
482         const tcu::Vec4 &cBias   = colorFmtInfo.valueMin;
483         tcu::Vec4 cScale         = colorFmtInfo.valueMax - colorFmtInfo.valueMin;
484         uint32_t fbo             = 0;
485         uint32_t colorRbo        = 0;
486         uint32_t depthStencilRbo = 0;
487         FlatColorShader flatShader(glu::TYPE_FLOAT_VEC4);
488         vector<uint32_t> attachments = getFBODiscardAttachments(m_invalidateBuffers);
489         uint32_t flatShaderID        = getCurrentContext()->createProgram(&flatShader);
490 
491         // Create fbo.
492         glGenRenderbuffers(1, &colorRbo);
493         glBindRenderbuffer(GL_RENDERBUFFER, colorRbo);
494         glRenderbufferStorage(GL_RENDERBUFFER, m_colorFmt, getWidth(), getHeight());
495 
496         if (m_depthStencilFmt != GL_NONE)
497         {
498             glGenRenderbuffers(1, &depthStencilRbo);
499             glBindRenderbuffer(GL_RENDERBUFFER, depthStencilRbo);
500             glRenderbufferStorage(GL_RENDERBUFFER, m_depthStencilFmt, getWidth(), getHeight());
501         }
502 
503         glGenFramebuffers(1, &fbo);
504         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
505         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo);
506 
507         if (depth)
508             glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);
509 
510         if (stencil)
511             glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);
512 
513         checkFramebufferStatus(GL_FRAMEBUFFER);
514 
515         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
516         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
517 
518         glEnable(GL_DEPTH_TEST);
519         glEnable(GL_STENCIL_TEST);
520         glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
521         glStencilFunc(GL_ALWAYS, 1, 0xff);
522 
523         flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias);
524         sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
525 
526         glInvalidateFramebuffer(GL_FRAMEBUFFER, (int)attachments.size(),
527                                 attachments.empty() ? DE_NULL : &attachments[0]);
528 
529         if ((m_invalidateBuffers & GL_COLOR_BUFFER_BIT) != 0)
530         {
531             // Color was not preserved - fill with green.
532             glDisable(GL_DEPTH_TEST);
533             glDisable(GL_STENCIL_TEST);
534 
535             flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f) * cScale + cBias);
536             sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
537 
538             glEnable(GL_DEPTH_TEST);
539             glEnable(GL_STENCIL_TEST);
540         }
541 
542         if ((m_invalidateBuffers & GL_DEPTH_BUFFER_BIT) != 0)
543         {
544             // Depth was not preserved.
545             glDepthFunc(GL_ALWAYS);
546         }
547 
548         if ((m_invalidateBuffers & GL_STENCIL_BUFFER_BIT) == 0)
549         {
550             // Stencil was preserved.
551             glStencilFunc(GL_EQUAL, 1, 0xff);
552         }
553 
554         glEnable(GL_BLEND);
555         glBlendFunc(GL_ONE, GL_ONE);
556         glBlendEquation(GL_FUNC_ADD);
557 
558         flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f) * cScale + cBias);
559         sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
560 
561         readPixels(dst, 0, 0, getWidth(), getHeight(), colorFmt, colorFmtInfo.lookupScale, colorFmtInfo.lookupBias);
562     }
563 
564 private:
565     uint32_t m_colorFmt;
566     uint32_t m_depthStencilFmt;
567     uint32_t m_invalidateBuffers;
568 };
569 
570 class InvalidateFboUnbindReadCase : public FboTestCase
571 {
572 public:
InvalidateFboUnbindReadCase(Context & context,const char * name,const char * description,uint32_t colorFmt,uint32_t depthStencilFmt,uint32_t invalidateBuffers)573     InvalidateFboUnbindReadCase(Context &context, const char *name, const char *description, uint32_t colorFmt,
574                                 uint32_t depthStencilFmt, uint32_t invalidateBuffers)
575         : FboTestCase(context, name, description)
576         , m_colorFmt(colorFmt)
577         , m_depthStencilFmt(depthStencilFmt)
578         , m_invalidateBuffers(invalidateBuffers)
579     {
580         DE_ASSERT((m_invalidateBuffers & (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) !=
581                   (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
582     }
583 
584 protected:
preCheck(void)585     void preCheck(void)
586     {
587         if (m_colorFmt != GL_NONE)
588             checkFormatSupport(m_colorFmt);
589         if (m_depthStencilFmt != GL_NONE)
590             checkFormatSupport(m_depthStencilFmt);
591     }
592 
render(tcu::Surface & dst)593     void render(tcu::Surface &dst)
594     {
595         tcu::TextureFormat colorFmt = glu::mapGLInternalFormat(m_colorFmt);
596         tcu::TextureFormat depthStencilFmt =
597             m_depthStencilFmt != GL_NONE ? glu::mapGLInternalFormat(m_depthStencilFmt) : tcu::TextureFormat();
598         tcu::TextureFormatInfo colorFmtInfo = tcu::getTextureFormatInfo(colorFmt);
599         bool depth = depthStencilFmt.order == tcu::TextureFormat::D || depthStencilFmt.order == tcu::TextureFormat::DS;
600         bool stencil =
601             depthStencilFmt.order == tcu::TextureFormat::S || depthStencilFmt.order == tcu::TextureFormat::DS;
602         uint32_t fbo             = 0;
603         uint32_t colorTex        = 0;
604         uint32_t depthStencilTex = 0;
605         GradientShader gradShader(getFragmentOutputType(colorFmt));
606         vector<uint32_t> attachments = getFBODiscardAttachments(m_invalidateBuffers);
607         uint32_t gradShaderID        = getCurrentContext()->createProgram(&gradShader);
608 
609         // Create fbo.
610         {
611             glu::TransferFormat transferFmt = glu::getTransferFormat(colorFmt);
612 
613             glGenTextures(1, &colorTex);
614             glBindTexture(GL_TEXTURE_2D, colorTex);
615             glTexImage2D(GL_TEXTURE_2D, 0, m_colorFmt, getWidth(), getHeight(), 0, transferFmt.format,
616                          transferFmt.dataType, DE_NULL);
617             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
618         }
619 
620         if (m_depthStencilFmt != GL_NONE)
621         {
622             glu::TransferFormat transferFmt = glu::getTransferFormat(depthStencilFmt);
623 
624             glGenTextures(1, &depthStencilTex);
625             glBindTexture(GL_TEXTURE_2D, depthStencilTex);
626             glTexImage2D(GL_TEXTURE_2D, 0, m_depthStencilFmt, getWidth(), getHeight(), 0, transferFmt.format,
627                          transferFmt.dataType, DE_NULL);
628             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
629             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
630         }
631 
632         glGenFramebuffers(1, &fbo);
633         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
634         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0);
635 
636         if (depth)
637             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthStencilTex, 0);
638 
639         if (stencil)
640             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depthStencilTex, 0);
641 
642         checkFramebufferStatus(GL_FRAMEBUFFER);
643 
644         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
645         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
646 
647         glEnable(GL_DEPTH_TEST);
648         glEnable(GL_STENCIL_TEST);
649         glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
650         glStencilFunc(GL_ALWAYS, 1, 0xff);
651 
652         gradShader.setGradient(*getCurrentContext(), gradShaderID, colorFmtInfo.valueMin, colorFmtInfo.valueMax);
653         sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
654 
655         glInvalidateFramebuffer(GL_FRAMEBUFFER, (int)attachments.size(), &attachments[0]);
656 
657         glBindFramebuffer(GL_FRAMEBUFFER, 0);
658         glDisable(GL_DEPTH_TEST);
659         glDisable(GL_STENCIL_TEST);
660 
661         if ((m_invalidateBuffers & GL_DEPTH_BUFFER_BIT) != 0)
662         {
663             // Render color.
664             Texture2DShader texShader(DataTypes() << glu::getSampler2DType(colorFmt), glu::TYPE_FLOAT_VEC4);
665             uint32_t texShaderID = getCurrentContext()->createProgram(&texShader);
666 
667             texShader.setTexScaleBias(0, colorFmtInfo.lookupScale, colorFmtInfo.lookupBias);
668             texShader.setUniforms(*getCurrentContext(), texShaderID);
669 
670             glBindTexture(GL_TEXTURE_2D, colorTex);
671             sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
672         }
673         else
674         {
675             // Render depth.
676             Texture2DShader texShader(DataTypes() << glu::getSampler2DType(depthStencilFmt), glu::TYPE_FLOAT_VEC4);
677             uint32_t texShaderID = getCurrentContext()->createProgram(&texShader);
678 
679             texShader.setUniforms(*getCurrentContext(), texShaderID);
680 
681             glBindTexture(GL_TEXTURE_2D, depthStencilTex);
682             sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
683         }
684 
685         readPixels(dst, 0, 0, getWidth(), getHeight());
686     }
687 
688 private:
689     uint32_t m_colorFmt;
690     uint32_t m_depthStencilFmt;
691     uint32_t m_invalidateBuffers;
692 };
693 
694 class InvalidateFboUnbindBlitCase : public FboTestCase
695 {
696 public:
InvalidateFboUnbindBlitCase(Context & context,const char * name,const char * description,int numSamples,uint32_t invalidateBuffers)697     InvalidateFboUnbindBlitCase(Context &context, const char *name, const char *description, int numSamples,
698                                 uint32_t invalidateBuffers)
699         : FboTestCase(context, name, description,
700                       numSamples >
701                           0) // \note Use fullscreen viewport when multisampling - we can't allow GLES3Context do its
702         //         behing-the-scenes viewport position randomization, because with glBlitFramebuffer,
703         //         source and destination rectangles must match when multisampling.
704         , m_colorFmt(0)
705         , m_depthStencilFmt(0)
706         , m_numSamples(numSamples)
707         , m_invalidateBuffers(invalidateBuffers)
708     {
709         // Figure out formats that are compatible with default framebuffer.
710         m_colorFmt        = getCompatibleColorFormat(m_context.getRenderTarget());
711         m_depthStencilFmt = getCompatibleDepthStencilFormat(m_context.getRenderTarget());
712     }
713 
714 protected:
preCheck(void)715     void preCheck(void)
716     {
717         if (m_context.getRenderTarget().getNumSamples() > 0)
718             throw tcu::NotSupportedError("Not supported in MSAA config");
719 
720         if (m_colorFmt == GL_NONE)
721             throw tcu::NotSupportedError("Unsupported color format");
722 
723         if (m_depthStencilFmt == GL_NONE)
724             throw tcu::NotSupportedError("Unsupported depth/stencil format");
725 
726         checkFormatSupport(m_colorFmt);
727         checkFormatSupport(m_depthStencilFmt);
728     }
729 
render(tcu::Surface & dst)730     void render(tcu::Surface &dst)
731     {
732         // \note When using fullscreen viewport (when m_numSamples > 0), still only use a 128x128 pixel quad at most.
733         IVec2 quadSizePixels(m_numSamples == 0 ? getWidth() : de::min(128, getWidth()),
734                              m_numSamples == 0 ? getHeight() : de::min(128, getHeight()));
735         Vec2 quadNDCLeftBottomXY(-1.0f, -1.0f);
736         Vec2 quadNDCSize(2.0f * (float)quadSizePixels.x() / (float)getWidth(),
737                          2.0f * (float)quadSizePixels.y() / (float)getHeight());
738         Vec2 quadNDCRightTopXY = quadNDCLeftBottomXY + quadNDCSize;
739         tcu::TextureFormat depthStencilFmt =
740             m_depthStencilFmt != GL_NONE ? glu::mapGLInternalFormat(m_depthStencilFmt) : tcu::TextureFormat();
741         bool depth = depthStencilFmt.order == tcu::TextureFormat::D || depthStencilFmt.order == tcu::TextureFormat::DS;
742         bool stencil =
743             depthStencilFmt.order == tcu::TextureFormat::S || depthStencilFmt.order == tcu::TextureFormat::DS;
744         uint32_t fbo             = 0;
745         uint32_t colorRbo        = 0;
746         uint32_t depthStencilRbo = 0;
747         FlatColorShader flatShader(glu::TYPE_FLOAT_VEC4);
748         vector<uint32_t> attachments = getFBODiscardAttachments(m_invalidateBuffers);
749         uint32_t flatShaderID        = getCurrentContext()->createProgram(&flatShader);
750 
751         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
752         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
753 
754         // Create fbo.
755         glGenRenderbuffers(1, &colorRbo);
756         glBindRenderbuffer(GL_RENDERBUFFER, colorRbo);
757         glRenderbufferStorageMultisample(GL_RENDERBUFFER, m_numSamples, m_colorFmt, quadSizePixels.x(),
758                                          quadSizePixels.y());
759 
760         if (m_depthStencilFmt != GL_NONE)
761         {
762             glGenRenderbuffers(1, &depthStencilRbo);
763             glBindRenderbuffer(GL_RENDERBUFFER, depthStencilRbo);
764             glRenderbufferStorageMultisample(GL_RENDERBUFFER, m_numSamples, m_depthStencilFmt, quadSizePixels.x(),
765                                              quadSizePixels.y());
766         }
767 
768         glGenFramebuffers(1, &fbo);
769         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
770         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo);
771 
772         if (depth)
773             glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);
774 
775         if (stencil)
776             glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);
777 
778         checkFramebufferStatus(GL_FRAMEBUFFER);
779 
780         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
781 
782         glEnable(GL_DEPTH_TEST);
783         glEnable(GL_STENCIL_TEST);
784         glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
785         glStencilFunc(GL_ALWAYS, 1, 0xff);
786 
787         flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f));
788         sglr::drawQuad(*getCurrentContext(), flatShaderID,
789                        Vec3(quadNDCLeftBottomXY.x(), quadNDCLeftBottomXY.y(), -1.0f),
790                        Vec3(quadNDCRightTopXY.x(), quadNDCRightTopXY.y(), 1.0f));
791 
792         glInvalidateFramebuffer(GL_FRAMEBUFFER, (int)attachments.size(), &attachments[0]);
793 
794         // Set default framebuffer as draw framebuffer and blit preserved buffers.
795         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
796         glBlitFramebuffer(0, 0, quadSizePixels.x(), quadSizePixels.y(), 0, 0, quadSizePixels.x(), quadSizePixels.y(),
797                           (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT) & ~m_invalidateBuffers,
798                           GL_NEAREST);
799         glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
800 
801         if ((m_invalidateBuffers & GL_COLOR_BUFFER_BIT) != 0)
802         {
803             // Color was not preserved - fill with green.
804             glDisable(GL_DEPTH_TEST);
805             glDisable(GL_STENCIL_TEST);
806 
807             flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
808             sglr::drawQuad(*getCurrentContext(), flatShaderID,
809                            Vec3(quadNDCLeftBottomXY.x(), quadNDCLeftBottomXY.y(), 0.0f),
810                            Vec3(quadNDCRightTopXY.x(), quadNDCRightTopXY.y(), 0.0f));
811 
812             glEnable(GL_DEPTH_TEST);
813             glEnable(GL_STENCIL_TEST);
814         }
815 
816         if ((m_invalidateBuffers & GL_DEPTH_BUFFER_BIT) != 0)
817         {
818             // Depth was not preserved.
819             glDepthFunc(GL_ALWAYS);
820         }
821 
822         if ((m_invalidateBuffers & GL_STENCIL_BUFFER_BIT) == 0)
823         {
824             // Stencil was preserved.
825             glStencilFunc(GL_EQUAL, 1, 0xff);
826         }
827 
828         glEnable(GL_BLEND);
829         glBlendFunc(GL_ONE, GL_ONE);
830         glBlendEquation(GL_FUNC_ADD);
831 
832         flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f));
833         sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(quadNDCLeftBottomXY.x(), quadNDCLeftBottomXY.y(), 0.0f),
834                        Vec3(quadNDCRightTopXY.x(), quadNDCRightTopXY.y(), 0.0f));
835 
836         readPixels(dst, 0, 0, quadSizePixels.x(), quadSizePixels.y());
837     }
838 
839 private:
840     uint32_t m_colorFmt;
841     uint32_t m_depthStencilFmt;
842     int m_numSamples;
843     uint32_t m_invalidateBuffers;
844 };
845 
846 class InvalidateSubFboRenderCase : public FboTestCase
847 {
848 public:
InvalidateSubFboRenderCase(Context & context,const char * name,const char * description,uint32_t colorFmt,uint32_t depthStencilFmt,uint32_t invalidateBuffers)849     InvalidateSubFboRenderCase(Context &context, const char *name, const char *description, uint32_t colorFmt,
850                                uint32_t depthStencilFmt, uint32_t invalidateBuffers)
851         : FboTestCase(context, name, description)
852         , m_colorFmt(colorFmt)
853         , m_depthStencilFmt(depthStencilFmt)
854         , m_invalidateBuffers(invalidateBuffers)
855     {
856     }
857 
858 protected:
preCheck(void)859     void preCheck(void)
860     {
861         if (m_colorFmt != GL_NONE)
862             checkFormatSupport(m_colorFmt);
863         if (m_depthStencilFmt != GL_NONE)
864             checkFormatSupport(m_depthStencilFmt);
865     }
866 
render(tcu::Surface & dst)867     void render(tcu::Surface &dst)
868     {
869         tcu::TextureFormat colorFmt = glu::mapGLInternalFormat(m_colorFmt);
870         tcu::TextureFormat depthStencilFmt =
871             m_depthStencilFmt != GL_NONE ? glu::mapGLInternalFormat(m_depthStencilFmt) : tcu::TextureFormat();
872         tcu::TextureFormatInfo colorFmtInfo = tcu::getTextureFormatInfo(colorFmt);
873         bool depth = depthStencilFmt.order == tcu::TextureFormat::D || depthStencilFmt.order == tcu::TextureFormat::DS;
874         bool stencil =
875             depthStencilFmt.order == tcu::TextureFormat::S || depthStencilFmt.order == tcu::TextureFormat::DS;
876         const tcu::Vec4 &cBias   = colorFmtInfo.valueMin;
877         tcu::Vec4 cScale         = colorFmtInfo.valueMax - colorFmtInfo.valueMin;
878         uint32_t fbo             = 0;
879         uint32_t colorRbo        = 0;
880         uint32_t depthStencilRbo = 0;
881         int invalidateX          = getWidth() / 4;
882         int invalidateY          = getHeight() / 4;
883         int invalidateW          = getWidth() / 2;
884         int invalidateH          = getHeight() / 2;
885         FlatColorShader flatShader(glu::TYPE_FLOAT_VEC4);
886         vector<uint32_t> attachments = getFBODiscardAttachments(m_invalidateBuffers);
887         uint32_t flatShaderID        = getCurrentContext()->createProgram(&flatShader);
888 
889         // Create fbo.
890         glGenRenderbuffers(1, &colorRbo);
891         glBindRenderbuffer(GL_RENDERBUFFER, colorRbo);
892         glRenderbufferStorage(GL_RENDERBUFFER, m_colorFmt, getWidth(), getHeight());
893 
894         if (m_depthStencilFmt != GL_NONE)
895         {
896             glGenRenderbuffers(1, &depthStencilRbo);
897             glBindRenderbuffer(GL_RENDERBUFFER, depthStencilRbo);
898             glRenderbufferStorage(GL_RENDERBUFFER, m_depthStencilFmt, getWidth(), getHeight());
899         }
900 
901         glGenFramebuffers(1, &fbo);
902         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
903         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo);
904 
905         if (depth)
906             glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);
907 
908         if (stencil)
909             glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);
910 
911         checkFramebufferStatus(GL_FRAMEBUFFER);
912 
913         glClearBufferfv(GL_COLOR, 0, (Vec4(0.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias).getPtr());
914         glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0f, 0);
915 
916         glEnable(GL_DEPTH_TEST);
917         glEnable(GL_STENCIL_TEST);
918         glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
919         glStencilFunc(GL_ALWAYS, 1, 0xff);
920 
921         flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias);
922         sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
923 
924         glInvalidateSubFramebuffer(GL_FRAMEBUFFER, (int)attachments.size(),
925                                    attachments.empty() ? DE_NULL : &attachments[0], invalidateX, invalidateY,
926                                    invalidateW, invalidateH);
927 
928         // Clear invalidated buffers.
929         glScissor(invalidateX, invalidateY, invalidateW, invalidateH);
930         glEnable(GL_SCISSOR_TEST);
931 
932         if (m_invalidateBuffers & GL_COLOR_BUFFER_BIT)
933             glClearBufferfv(GL_COLOR, 0, (Vec4(0.0f, 1.0f, 0.0f, 1.0f) * cScale + cBias).getPtr());
934 
935         glClear(m_invalidateBuffers & ~GL_COLOR_BUFFER_BIT);
936         glDisable(GL_SCISSOR_TEST);
937 
938         glEnable(GL_BLEND);
939         glBlendFunc(GL_ONE, GL_ONE);
940         glBlendEquation(GL_FUNC_ADD);
941 
942         flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f) * cScale + cBias);
943         sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
944 
945         readPixels(dst, 0, 0, getWidth(), getHeight(), colorFmt, colorFmtInfo.lookupScale, colorFmtInfo.lookupBias);
946     }
947 
948 private:
949     uint32_t m_colorFmt;
950     uint32_t m_depthStencilFmt;
951     uint32_t m_invalidateBuffers;
952 };
953 
954 class InvalidateSubFboUnbindReadCase : public FboTestCase
955 {
956 public:
InvalidateSubFboUnbindReadCase(Context & context,const char * name,const char * description,uint32_t colorFmt,uint32_t depthStencilFmt,uint32_t invalidateBuffers)957     InvalidateSubFboUnbindReadCase(Context &context, const char *name, const char *description, uint32_t colorFmt,
958                                    uint32_t depthStencilFmt, uint32_t invalidateBuffers)
959         : FboTestCase(context, name, description)
960         , m_colorFmt(colorFmt)
961         , m_depthStencilFmt(depthStencilFmt)
962         , m_invalidateBuffers(invalidateBuffers)
963     {
964         DE_ASSERT((m_invalidateBuffers & (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) !=
965                   (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
966     }
967 
968 protected:
preCheck(void)969     void preCheck(void)
970     {
971         if (m_colorFmt != GL_NONE)
972             checkFormatSupport(m_colorFmt);
973         if (m_depthStencilFmt != GL_NONE)
974             checkFormatSupport(m_depthStencilFmt);
975     }
976 
render(tcu::Surface & dst)977     void render(tcu::Surface &dst)
978     {
979         tcu::TextureFormat colorFmt = glu::mapGLInternalFormat(m_colorFmt);
980         tcu::TextureFormat depthStencilFmt =
981             m_depthStencilFmt != GL_NONE ? glu::mapGLInternalFormat(m_depthStencilFmt) : tcu::TextureFormat();
982         tcu::TextureFormatInfo colorFmtInfo = tcu::getTextureFormatInfo(colorFmt);
983         bool depth = depthStencilFmt.order == tcu::TextureFormat::D || depthStencilFmt.order == tcu::TextureFormat::DS;
984         bool stencil =
985             depthStencilFmt.order == tcu::TextureFormat::S || depthStencilFmt.order == tcu::TextureFormat::DS;
986         uint32_t fbo             = 0;
987         uint32_t colorTex        = 0;
988         uint32_t depthStencilTex = 0;
989         int invalidateX          = 0;
990         int invalidateY          = 0;
991         int invalidateW          = getWidth() / 2;
992         int invalidateH          = getHeight();
993         int readX                = invalidateW;
994         int readY                = 0;
995         int readW                = getWidth() / 2;
996         int readH                = getHeight();
997         GradientShader gradShader(getFragmentOutputType(colorFmt));
998         vector<uint32_t> attachments = getFBODiscardAttachments(m_invalidateBuffers);
999         uint32_t gradShaderID        = getCurrentContext()->createProgram(&gradShader);
1000 
1001         // Create fbo.
1002         {
1003             glu::TransferFormat transferFmt = glu::getTransferFormat(colorFmt);
1004 
1005             glGenTextures(1, &colorTex);
1006             glBindTexture(GL_TEXTURE_2D, colorTex);
1007             glTexImage2D(GL_TEXTURE_2D, 0, m_colorFmt, getWidth(), getHeight(), 0, transferFmt.format,
1008                          transferFmt.dataType, DE_NULL);
1009             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1010             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1011         }
1012 
1013         if (m_depthStencilFmt != GL_NONE)
1014         {
1015             glu::TransferFormat transferFmt = glu::getTransferFormat(depthStencilFmt);
1016 
1017             glGenTextures(1, &depthStencilTex);
1018             glBindTexture(GL_TEXTURE_2D, depthStencilTex);
1019             glTexImage2D(GL_TEXTURE_2D, 0, m_depthStencilFmt, getWidth(), getHeight(), 0, transferFmt.format,
1020                          transferFmt.dataType, DE_NULL);
1021             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1022             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1023         }
1024 
1025         glGenFramebuffers(1, &fbo);
1026         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1027         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0);
1028 
1029         if (depth)
1030             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthStencilTex, 0);
1031 
1032         if (stencil)
1033             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depthStencilTex, 0);
1034 
1035         checkFramebufferStatus(GL_FRAMEBUFFER);
1036 
1037         clearColorBuffer(colorFmt, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
1038         glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1039 
1040         glEnable(GL_DEPTH_TEST);
1041         glEnable(GL_STENCIL_TEST);
1042         glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1043         glStencilFunc(GL_ALWAYS, 1, 0xff);
1044 
1045         gradShader.setGradient(*getCurrentContext(), gradShaderID, colorFmtInfo.valueMin, colorFmtInfo.valueMax);
1046         sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
1047 
1048         glInvalidateSubFramebuffer(GL_FRAMEBUFFER, (int)attachments.size(), &attachments[0], invalidateX, invalidateY,
1049                                    invalidateW, invalidateH);
1050 
1051         glBindFramebuffer(GL_FRAMEBUFFER, 0);
1052         glDisable(GL_DEPTH_TEST);
1053         glDisable(GL_STENCIL_TEST);
1054 
1055         glClearColor(0.25f, 0.5f, 0.75f, 1.0f);
1056         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1057 
1058         // Limit read area using scissor.
1059         glScissor(readX, readY, readW, readH);
1060         glEnable(GL_SCISSOR_TEST);
1061 
1062         if ((m_invalidateBuffers & GL_COLOR_BUFFER_BIT) != 0)
1063         {
1064             // Render color.
1065             Texture2DShader texShader(DataTypes() << glu::getSampler2DType(colorFmt), glu::TYPE_FLOAT_VEC4);
1066             uint32_t texShaderID = getCurrentContext()->createProgram(&texShader);
1067 
1068             texShader.setTexScaleBias(0, colorFmtInfo.lookupScale, colorFmtInfo.lookupBias);
1069             texShader.setUniforms(*getCurrentContext(), texShaderID);
1070 
1071             glBindTexture(GL_TEXTURE_2D, colorTex);
1072             sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1073         }
1074         else
1075         {
1076             // Render depth.
1077             Texture2DShader texShader(DataTypes() << glu::getSampler2DType(depthStencilFmt), glu::TYPE_FLOAT_VEC4);
1078             uint32_t texShaderID = getCurrentContext()->createProgram(&texShader);
1079 
1080             texShader.setUniforms(*getCurrentContext(), texShaderID);
1081 
1082             glBindTexture(GL_TEXTURE_2D, depthStencilTex);
1083             sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1084         }
1085 
1086         readPixels(dst, 0, 0, getWidth(), getHeight());
1087     }
1088 
compare(const tcu::Surface & reference,const tcu::Surface & result)1089     bool compare(const tcu::Surface &reference, const tcu::Surface &result)
1090     {
1091         const tcu::RGBA threshold(tcu::max(getFormatThreshold(m_colorFmt), tcu::RGBA(12, 12, 12, 12)));
1092 
1093         return tcu::bilinearCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference.getAccess(),
1094                                     result.getAccess(), threshold, tcu::COMPARE_LOG_RESULT);
1095     }
1096 
1097 private:
1098     uint32_t m_colorFmt;
1099     uint32_t m_depthStencilFmt;
1100     uint32_t m_invalidateBuffers;
1101 };
1102 
1103 class InvalidateSubFboUnbindBlitCase : public FboTestCase
1104 {
1105 public:
InvalidateSubFboUnbindBlitCase(Context & context,const char * name,const char * description,int numSamples,uint32_t invalidateBuffers)1106     InvalidateSubFboUnbindBlitCase(Context &context, const char *name, const char *description, int numSamples,
1107                                    uint32_t invalidateBuffers)
1108         : FboTestCase(context, name, description,
1109                       numSamples >
1110                           0) // \note Use fullscreen viewport when multisampling - we can't allow GLES3Context do its
1111         //         behing-the-scenes viewport position randomization, because with glBlitFramebuffer,
1112         //         source and destination rectangles must match when multisampling.
1113         , m_colorFmt(0)
1114         , m_depthStencilFmt(0)
1115         , m_numSamples(numSamples)
1116         , m_invalidateBuffers(invalidateBuffers)
1117     {
1118         // Figure out formats that are compatible with default framebuffer.
1119         m_colorFmt        = getCompatibleColorFormat(m_context.getRenderTarget());
1120         m_depthStencilFmt = getCompatibleDepthStencilFormat(m_context.getRenderTarget());
1121     }
1122 
1123 protected:
preCheck(void)1124     void preCheck(void)
1125     {
1126         if (m_context.getRenderTarget().getNumSamples() > 0)
1127             throw tcu::NotSupportedError("Not supported in MSAA config");
1128 
1129         if (m_colorFmt == GL_NONE)
1130             throw tcu::NotSupportedError("Unsupported color format");
1131 
1132         if (m_depthStencilFmt == GL_NONE)
1133             throw tcu::NotSupportedError("Unsupported depth/stencil format");
1134 
1135         checkFormatSupport(m_colorFmt);
1136         checkFormatSupport(m_depthStencilFmt);
1137     }
1138 
render(tcu::Surface & dst)1139     void render(tcu::Surface &dst)
1140     {
1141         // \note When using fullscreen viewport (when m_numSamples > 0), still only use a 128x128 pixel quad at most.
1142         IVec2 quadSizePixels(m_numSamples == 0 ? getWidth() : de::min(128, getWidth()),
1143                              m_numSamples == 0 ? getHeight() : de::min(128, getHeight()));
1144         Vec2 quadNDCLeftBottomXY(-1.0f, -1.0f);
1145         Vec2 quadNDCSize(2.0f * (float)quadSizePixels.x() / (float)getWidth(),
1146                          2.0f * (float)quadSizePixels.y() / (float)getHeight());
1147         Vec2 quadNDCRightTopXY = quadNDCLeftBottomXY + quadNDCSize;
1148         tcu::TextureFormat depthStencilFmt =
1149             m_depthStencilFmt != GL_NONE ? glu::mapGLInternalFormat(m_depthStencilFmt) : tcu::TextureFormat();
1150         bool depth = depthStencilFmt.order == tcu::TextureFormat::D || depthStencilFmt.order == tcu::TextureFormat::DS;
1151         bool stencil =
1152             depthStencilFmt.order == tcu::TextureFormat::S || depthStencilFmt.order == tcu::TextureFormat::DS;
1153         uint32_t fbo             = 0;
1154         uint32_t colorRbo        = 0;
1155         uint32_t depthStencilRbo = 0;
1156         int invalidateX          = 0;
1157         int invalidateY          = 0;
1158         int invalidateW          = quadSizePixels.x() / 2;
1159         int invalidateH          = quadSizePixels.y();
1160         int blitX0               = invalidateW;
1161         int blitY0               = 0;
1162         int blitX1               = blitX0 + quadSizePixels.x() / 2;
1163         int blitY1               = blitY0 + quadSizePixels.y();
1164         FlatColorShader flatShader(glu::TYPE_FLOAT_VEC4);
1165         vector<uint32_t> attachments = getFBODiscardAttachments(m_invalidateBuffers);
1166         uint32_t flatShaderID        = getCurrentContext()->createProgram(&flatShader);
1167 
1168         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
1169         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1170 
1171         // Create fbo.
1172         glGenRenderbuffers(1, &colorRbo);
1173         glBindRenderbuffer(GL_RENDERBUFFER, colorRbo);
1174         glRenderbufferStorageMultisample(GL_RENDERBUFFER, m_numSamples, m_colorFmt, quadSizePixels.x(),
1175                                          quadSizePixels.y());
1176 
1177         if (m_depthStencilFmt != GL_NONE)
1178         {
1179             glGenRenderbuffers(1, &depthStencilRbo);
1180             glBindRenderbuffer(GL_RENDERBUFFER, depthStencilRbo);
1181             glRenderbufferStorageMultisample(GL_RENDERBUFFER, m_numSamples, m_depthStencilFmt, quadSizePixels.x(),
1182                                              quadSizePixels.y());
1183         }
1184 
1185         glGenFramebuffers(1, &fbo);
1186         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1187         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo);
1188 
1189         if (depth)
1190             glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);
1191 
1192         if (stencil)
1193             glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);
1194 
1195         checkFramebufferStatus(GL_FRAMEBUFFER);
1196 
1197         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1198 
1199         glEnable(GL_DEPTH_TEST);
1200         glEnable(GL_STENCIL_TEST);
1201         glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1202         glStencilFunc(GL_ALWAYS, 1, 0xff);
1203 
1204         flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f));
1205         sglr::drawQuad(*getCurrentContext(), flatShaderID,
1206                        Vec3(quadNDCLeftBottomXY.x(), quadNDCLeftBottomXY.y(), -1.0f),
1207                        Vec3(quadNDCRightTopXY.x(), quadNDCRightTopXY.y(), 1.0f));
1208 
1209         glInvalidateSubFramebuffer(GL_FRAMEBUFFER, (int)attachments.size(), &attachments[0], invalidateX, invalidateY,
1210                                    invalidateW, invalidateH);
1211 
1212         // Set default framebuffer as draw framebuffer and blit preserved buffers.
1213         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1214         glBlitFramebuffer(blitX0, blitY0, blitX1, blitY1, blitX0, blitY0, blitX1, blitY1,
1215                           (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT) & ~m_invalidateBuffers,
1216                           GL_NEAREST);
1217         glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
1218 
1219         if ((m_invalidateBuffers & GL_COLOR_BUFFER_BIT) != 0)
1220         {
1221             // Color was not preserved - fill with green.
1222             glDisable(GL_DEPTH_TEST);
1223             glDisable(GL_STENCIL_TEST);
1224 
1225             flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
1226             sglr::drawQuad(*getCurrentContext(), flatShaderID,
1227                            Vec3(quadNDCLeftBottomXY.x(), quadNDCLeftBottomXY.y(), 0.0f),
1228                            Vec3(quadNDCRightTopXY.x(), quadNDCRightTopXY.y(), 0.0f));
1229 
1230             glEnable(GL_DEPTH_TEST);
1231             glEnable(GL_STENCIL_TEST);
1232         }
1233 
1234         if ((m_invalidateBuffers & GL_DEPTH_BUFFER_BIT) != 0)
1235         {
1236             // Depth was not preserved.
1237             glDepthFunc(GL_ALWAYS);
1238         }
1239 
1240         if ((m_invalidateBuffers & GL_STENCIL_BUFFER_BIT) == 0)
1241         {
1242             // Stencil was preserved.
1243             glStencilFunc(GL_EQUAL, 1, 0xff);
1244         }
1245 
1246         glEnable(GL_BLEND);
1247         glBlendFunc(GL_ONE, GL_ONE);
1248         glBlendEquation(GL_FUNC_ADD);
1249 
1250         flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f));
1251         sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(quadNDCLeftBottomXY.x(), quadNDCLeftBottomXY.y(), 0.0f),
1252                        Vec3(quadNDCRightTopXY.x(), quadNDCRightTopXY.y(), 0.0f));
1253 
1254         readPixels(dst, 0, 0, quadSizePixels.x(), quadSizePixels.y());
1255     }
1256 
1257 private:
1258     uint32_t m_colorFmt;
1259     uint32_t m_depthStencilFmt;
1260     int m_numSamples;
1261     uint32_t m_invalidateBuffers;
1262 };
1263 
1264 class InvalidateFboTargetCase : public FboTestCase
1265 {
1266 public:
InvalidateFboTargetCase(Context & context,const char * name,const char * description,uint32_t boundTarget,uint32_t invalidateTarget,const uint32_t * invalidateAttachments,int numAttachments)1267     InvalidateFboTargetCase(Context &context, const char *name, const char *description, uint32_t boundTarget,
1268                             uint32_t invalidateTarget, const uint32_t *invalidateAttachments, int numAttachments)
1269         : FboTestCase(context, name, description)
1270         , m_boundTarget(boundTarget)
1271         , m_invalidateTarget(invalidateTarget)
1272         , m_invalidateAttachments(invalidateAttachments, invalidateAttachments + numAttachments)
1273     {
1274     }
1275 
1276 protected:
render(tcu::Surface & dst)1277     void render(tcu::Surface &dst)
1278     {
1279         const uint32_t colorFormat                = GL_RGBA8;
1280         const uint32_t depthStencilFormat         = GL_DEPTH24_STENCIL8;
1281         const tcu::TextureFormat colorFmt         = glu::mapGLInternalFormat(colorFormat);
1282         const tcu::TextureFormatInfo colorFmtInfo = tcu::getTextureFormatInfo(colorFmt);
1283         const tcu::Vec4 &cBias                    = colorFmtInfo.valueMin;
1284         const tcu::Vec4 cScale                    = colorFmtInfo.valueMax - colorFmtInfo.valueMin;
1285         const bool isDiscarded                    = (m_boundTarget == GL_FRAMEBUFFER) ||
1286                                  (m_invalidateTarget == GL_FRAMEBUFFER && m_boundTarget == GL_DRAW_FRAMEBUFFER) ||
1287                                  (m_invalidateTarget == m_boundTarget);
1288         const bool isColorDiscarded = isDiscarded && hasAttachment(m_invalidateAttachments, GL_COLOR_ATTACHMENT0);
1289         const bool isDepthDiscarded =
1290             isDiscarded && (hasAttachment(m_invalidateAttachments, GL_DEPTH_ATTACHMENT) ||
1291                             hasAttachment(m_invalidateAttachments, GL_DEPTH_STENCIL_ATTACHMENT));
1292         const bool isStencilDiscarded =
1293             isDiscarded && (hasAttachment(m_invalidateAttachments, GL_STENCIL_ATTACHMENT) ||
1294                             hasAttachment(m_invalidateAttachments, GL_DEPTH_STENCIL_ATTACHMENT));
1295 
1296         uint32_t fbo             = 0;
1297         uint32_t colorRbo        = 0;
1298         uint32_t depthStencilRbo = 0;
1299         FlatColorShader flatShader(glu::TYPE_FLOAT_VEC4);
1300         uint32_t flatShaderID = getCurrentContext()->createProgram(&flatShader);
1301 
1302         // Create fbo.
1303         glGenRenderbuffers(1, &colorRbo);
1304         glBindRenderbuffer(GL_RENDERBUFFER, colorRbo);
1305         glRenderbufferStorage(GL_RENDERBUFFER, colorFormat, getWidth(), getHeight());
1306 
1307         glGenRenderbuffers(1, &depthStencilRbo);
1308         glBindRenderbuffer(GL_RENDERBUFFER, depthStencilRbo);
1309         glRenderbufferStorage(GL_RENDERBUFFER, depthStencilFormat, getWidth(), getHeight());
1310 
1311         glGenFramebuffers(1, &fbo);
1312         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1313         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo);
1314         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);
1315         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);
1316 
1317         checkFramebufferStatus(GL_FRAMEBUFFER);
1318 
1319         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
1320         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1321 
1322         glEnable(GL_DEPTH_TEST);
1323         glEnable(GL_STENCIL_TEST);
1324         glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1325         glStencilFunc(GL_ALWAYS, 1, 0xff);
1326 
1327         flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias);
1328         sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
1329 
1330         // Bound FBO to test target and default to other
1331         if (m_boundTarget != GL_FRAMEBUFFER)
1332         {
1333             // Unused fbo is used as complemeting target (read when discarding draw for example).
1334             // \note Framework takes care of deleting objects at the end of test case.
1335             const uint32_t unusedTarget =
1336                 m_boundTarget == GL_DRAW_FRAMEBUFFER ? GL_READ_FRAMEBUFFER : GL_DRAW_FRAMEBUFFER;
1337             uint32_t unusedFbo      = 0;
1338             uint32_t unusedColorRbo = 0;
1339 
1340             glGenRenderbuffers(1, &unusedColorRbo);
1341             glBindRenderbuffer(GL_RENDERBUFFER, unusedColorRbo);
1342             glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 64, 64);
1343             glGenFramebuffers(1, &unusedFbo);
1344             glBindFramebuffer(unusedTarget, unusedFbo);
1345             glFramebufferRenderbuffer(unusedTarget, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, unusedColorRbo);
1346 
1347             glBindFramebuffer(m_boundTarget, fbo);
1348         }
1349 
1350         glInvalidateFramebuffer(m_invalidateTarget, (int)m_invalidateAttachments.size(),
1351                                 m_invalidateAttachments.empty() ? DE_NULL : &m_invalidateAttachments[0]);
1352 
1353         if (m_boundTarget != GL_FRAMEBUFFER)
1354             glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1355 
1356         if (isColorDiscarded)
1357         {
1358             // Color was not preserved - fill with green.
1359             glDisable(GL_DEPTH_TEST);
1360             glDisable(GL_STENCIL_TEST);
1361 
1362             flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f) * cScale + cBias);
1363             sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1364 
1365             glEnable(GL_DEPTH_TEST);
1366             glEnable(GL_STENCIL_TEST);
1367         }
1368 
1369         if (isDepthDiscarded)
1370         {
1371             // Depth was not preserved.
1372             glDepthFunc(GL_ALWAYS);
1373         }
1374 
1375         if (!isStencilDiscarded)
1376         {
1377             // Stencil was preserved.
1378             glStencilFunc(GL_EQUAL, 1, 0xff);
1379         }
1380 
1381         glEnable(GL_BLEND);
1382         glBlendFunc(GL_ONE, GL_ONE);
1383         glBlendEquation(GL_FUNC_ADD);
1384 
1385         flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f) * cScale + cBias);
1386         sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1387 
1388         readPixels(dst, 0, 0, getWidth(), getHeight(), colorFmt, colorFmtInfo.lookupScale, colorFmtInfo.lookupBias);
1389     }
1390 
1391 private:
1392     uint32_t m_boundTarget;
1393     uint32_t m_invalidateTarget;
1394     std::vector<uint32_t> m_invalidateAttachments;
1395 };
1396 
FboInvalidateTests(Context & context)1397 FboInvalidateTests::FboInvalidateTests(Context &context)
1398     : TestCaseGroup(context, "invalidate", "Framebuffer invalidate tests")
1399 {
1400 }
1401 
~FboInvalidateTests(void)1402 FboInvalidateTests::~FboInvalidateTests(void)
1403 {
1404 }
1405 
init(void)1406 void FboInvalidateTests::init(void)
1407 {
1408     // invalidate.default.
1409     {
1410         tcu::TestCaseGroup *defaultFbGroup =
1411             new tcu::TestCaseGroup(m_testCtx, "default", "Default framebuffer invalidate tests");
1412         addChild(defaultFbGroup);
1413 
1414         defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase(m_context, "render_none",
1415                                                                             "Invalidating no framebuffers (ref)", 0));
1416         defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase(
1417             m_context, "render_color", "Rendering after invalidating colorbuffer", GL_COLOR_BUFFER_BIT));
1418         defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase(
1419             m_context, "render_depth", "Rendering after invalidating depthbuffer", GL_DEPTH_BUFFER_BIT));
1420         defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase(
1421             m_context, "render_stencil", "Rendering after invalidating stencilbuffer", GL_STENCIL_BUFFER_BIT));
1422         defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase(
1423             m_context, "render_depth_stencil", "Rendering after invalidating depth- and stencilbuffers",
1424             GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
1425         defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase(
1426             m_context, "render_all", "Rendering after invalidating all buffers",
1427             GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
1428 
1429         defaultFbGroup->addChild(new InvalidateDefaultFramebufferBindCase(
1430             m_context, "bind_color", "Binding fbo after invalidating colorbuffer", GL_COLOR_BUFFER_BIT));
1431         defaultFbGroup->addChild(new InvalidateDefaultFramebufferBindCase(
1432             m_context, "bind_depth", "Binding fbo after invalidating depthbuffer", GL_DEPTH_BUFFER_BIT));
1433         defaultFbGroup->addChild(new InvalidateDefaultFramebufferBindCase(
1434             m_context, "bind_stencil", "Binding fbo after invalidating stencilbuffer", GL_STENCIL_BUFFER_BIT));
1435         defaultFbGroup->addChild(new InvalidateDefaultFramebufferBindCase(
1436             m_context, "bind_depth_stencil", "Binding fbo after invalidating depth- and stencilbuffers",
1437             GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
1438         defaultFbGroup->addChild(new InvalidateDefaultFramebufferBindCase(
1439             m_context, "bind_all", "Binding fbo after invalidating all buffers",
1440             GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
1441 
1442         defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferRenderCase(
1443             m_context, "sub_render_color", "Rendering after invalidating colorbuffer", GL_COLOR_BUFFER_BIT));
1444         defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferRenderCase(
1445             m_context, "sub_render_depth", "Rendering after invalidating depthbuffer", GL_DEPTH_BUFFER_BIT));
1446         defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferRenderCase(
1447             m_context, "sub_render_stencil", "Rendering after invalidating stencilbuffer", GL_STENCIL_BUFFER_BIT));
1448         defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferRenderCase(
1449             m_context, "sub_render_depth_stencil", "Rendering after invalidating depth- and stencilbuffers",
1450             GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
1451         defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferRenderCase(
1452             m_context, "sub_render_all", "Rendering after invalidating all buffers",
1453             GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
1454 
1455         defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferBindCase(
1456             m_context, "sub_bind_color", "Binding fbo after invalidating colorbuffer", GL_COLOR_BUFFER_BIT));
1457         defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferBindCase(
1458             m_context, "sub_bind_depth", "Binding fbo after invalidating depthbuffer", GL_DEPTH_BUFFER_BIT));
1459         defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferBindCase(
1460             m_context, "sub_bind_stencil", "Binding fbo after invalidating stencilbuffer", GL_STENCIL_BUFFER_BIT));
1461         defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferBindCase(
1462             m_context, "sub_bind_depth_stencil", "Binding fbo after invalidating depth- and stencilbuffers",
1463             GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
1464         defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferBindCase(
1465             m_context, "sub_bind_all", "Binding fbo after invalidating all buffers",
1466             GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
1467 
1468         defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase(
1469             m_context, "draw_framebuffer_color", "Invalidating GL_COLOR in GL_DRAW_FRAMEBUFFER", GL_COLOR_BUFFER_BIT,
1470             GL_DRAW_FRAMEBUFFER));
1471         defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase(
1472             m_context, "draw_framebuffer_all", "Invalidating all in GL_DRAW_FRAMEBUFFER",
1473             GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_DRAW_FRAMEBUFFER));
1474         defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase(
1475             m_context, "read_framebuffer_color", "Invalidating GL_COLOR in GL_READ_FRAMEBUFFER", GL_COLOR_BUFFER_BIT,
1476             GL_READ_FRAMEBUFFER));
1477         defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase(
1478             m_context, "read_framebuffer_all", "Invalidating all in GL_READ_FRAMEBUFFER",
1479             GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_READ_FRAMEBUFFER));
1480     }
1481 
1482     // invalidate.whole.
1483     {
1484         tcu::TestCaseGroup *wholeFboGroup =
1485             new tcu::TestCaseGroup(m_testCtx, "whole", "Invalidating whole framebuffer object");
1486         addChild(wholeFboGroup);
1487 
1488         wholeFboGroup->addChild(
1489             new InvalidateFboRenderCase(m_context, "render_none", "", GL_RGBA8, GL_DEPTH24_STENCIL8, 0));
1490         wholeFboGroup->addChild(new InvalidateFboRenderCase(m_context, "render_color", "", GL_RGBA8,
1491                                                             GL_DEPTH24_STENCIL8, GL_COLOR_BUFFER_BIT));
1492         wholeFboGroup->addChild(new InvalidateFboRenderCase(m_context, "render_depth", "", GL_RGBA8,
1493                                                             GL_DEPTH24_STENCIL8, GL_DEPTH_BUFFER_BIT));
1494         wholeFboGroup->addChild(new InvalidateFboRenderCase(m_context, "render_stencil", "", GL_RGBA8,
1495                                                             GL_DEPTH24_STENCIL8, GL_STENCIL_BUFFER_BIT));
1496         wholeFboGroup->addChild(new InvalidateFboRenderCase(m_context, "render_depth_stencil", "", GL_RGBA8,
1497                                                             GL_DEPTH24_STENCIL8,
1498                                                             GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
1499         wholeFboGroup->addChild(
1500             new InvalidateFboRenderCase(m_context, "render_all", "", GL_RGBA8, GL_DEPTH24_STENCIL8,
1501                                         GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
1502 
1503         wholeFboGroup->addChild(new InvalidateFboUnbindReadCase(m_context, "unbind_read_color", "", GL_RGBA8,
1504                                                                 GL_DEPTH24_STENCIL8, GL_COLOR_BUFFER_BIT));
1505         wholeFboGroup->addChild(new InvalidateFboUnbindReadCase(m_context, "unbind_read_depth", "", GL_RGBA8,
1506                                                                 GL_DEPTH24_STENCIL8, GL_DEPTH_BUFFER_BIT));
1507         wholeFboGroup->addChild(new InvalidateFboUnbindReadCase(m_context, "unbind_read_stencil", "", GL_RGBA8,
1508                                                                 GL_DEPTH24_STENCIL8, GL_STENCIL_BUFFER_BIT));
1509         wholeFboGroup->addChild(new InvalidateFboUnbindReadCase(m_context, "unbind_read_depth_stencil", "", GL_RGBA8,
1510                                                                 GL_DEPTH24_STENCIL8,
1511                                                                 GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
1512         wholeFboGroup->addChild(new InvalidateFboUnbindReadCase(m_context, "unbind_read_color_stencil", "", GL_RGBA8,
1513                                                                 GL_DEPTH24_STENCIL8,
1514                                                                 GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
1515 
1516         wholeFboGroup->addChild(
1517             new InvalidateFboUnbindBlitCase(m_context, "unbind_blit_color", "", 0, GL_COLOR_BUFFER_BIT));
1518         wholeFboGroup->addChild(
1519             new InvalidateFboUnbindBlitCase(m_context, "unbind_blit_depth", "", 0, GL_DEPTH_BUFFER_BIT));
1520         wholeFboGroup->addChild(
1521             new InvalidateFboUnbindBlitCase(m_context, "unbind_blit_stencil", "", 0, GL_STENCIL_BUFFER_BIT));
1522         wholeFboGroup->addChild(new InvalidateFboUnbindBlitCase(m_context, "unbind_blit_depth_stencil", "", 0,
1523                                                                 GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
1524 
1525         wholeFboGroup->addChild(
1526             new InvalidateFboUnbindBlitCase(m_context, "unbind_blit_msaa_color", "", 4, GL_COLOR_BUFFER_BIT));
1527         wholeFboGroup->addChild(
1528             new InvalidateFboUnbindBlitCase(m_context, "unbind_blit_msaa_depth", "", 4, GL_DEPTH_BUFFER_BIT));
1529         wholeFboGroup->addChild(
1530             new InvalidateFboUnbindBlitCase(m_context, "unbind_blit_msaa_stencil", "", 4, GL_STENCIL_BUFFER_BIT));
1531         wholeFboGroup->addChild(new InvalidateFboUnbindBlitCase(m_context, "unbind_blit_msaa_depth_stencil", "", 4,
1532                                                                 GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
1533     }
1534 
1535     // invalidate.sub.
1536     {
1537         tcu::TestCaseGroup *subFboGroup =
1538             new tcu::TestCaseGroup(m_testCtx, "sub", "Invalidating subsection of framebuffer object");
1539         addChild(subFboGroup);
1540 
1541         subFboGroup->addChild(
1542             new InvalidateSubFboRenderCase(m_context, "render_none", "", GL_RGBA8, GL_DEPTH24_STENCIL8, 0));
1543         subFboGroup->addChild(new InvalidateSubFboRenderCase(m_context, "render_color", "", GL_RGBA8,
1544                                                              GL_DEPTH24_STENCIL8, GL_COLOR_BUFFER_BIT));
1545         subFboGroup->addChild(new InvalidateSubFboRenderCase(m_context, "render_depth", "", GL_RGBA8,
1546                                                              GL_DEPTH24_STENCIL8, GL_DEPTH_BUFFER_BIT));
1547         subFboGroup->addChild(new InvalidateSubFboRenderCase(m_context, "render_stencil", "", GL_RGBA8,
1548                                                              GL_DEPTH24_STENCIL8, GL_STENCIL_BUFFER_BIT));
1549         subFboGroup->addChild(new InvalidateSubFboRenderCase(m_context, "render_depth_stencil", "", GL_RGBA8,
1550                                                              GL_DEPTH24_STENCIL8,
1551                                                              GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
1552         subFboGroup->addChild(
1553             new InvalidateSubFboRenderCase(m_context, "render_all", "", GL_RGBA8, GL_DEPTH24_STENCIL8,
1554                                            GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
1555 
1556         subFboGroup->addChild(new InvalidateSubFboUnbindReadCase(m_context, "unbind_read_color", "", GL_RGBA8,
1557                                                                  GL_DEPTH24_STENCIL8, GL_COLOR_BUFFER_BIT));
1558         subFboGroup->addChild(new InvalidateSubFboUnbindReadCase(m_context, "unbind_read_depth", "", GL_RGBA8,
1559                                                                  GL_DEPTH24_STENCIL8, GL_DEPTH_BUFFER_BIT));
1560         subFboGroup->addChild(new InvalidateSubFboUnbindReadCase(m_context, "unbind_read_stencil", "", GL_RGBA8,
1561                                                                  GL_DEPTH24_STENCIL8, GL_STENCIL_BUFFER_BIT));
1562         subFboGroup->addChild(new InvalidateSubFboUnbindReadCase(m_context, "unbind_read_depth_stencil", "", GL_RGBA8,
1563                                                                  GL_DEPTH24_STENCIL8,
1564                                                                  GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
1565         subFboGroup->addChild(new InvalidateSubFboUnbindReadCase(m_context, "unbind_read_color_stencil", "", GL_RGBA8,
1566                                                                  GL_DEPTH24_STENCIL8,
1567                                                                  GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
1568 
1569         subFboGroup->addChild(
1570             new InvalidateSubFboUnbindBlitCase(m_context, "unbind_blit_color", "", 0, GL_COLOR_BUFFER_BIT));
1571         subFboGroup->addChild(
1572             new InvalidateSubFboUnbindBlitCase(m_context, "unbind_blit_depth", "", 0, GL_DEPTH_BUFFER_BIT));
1573         subFboGroup->addChild(
1574             new InvalidateSubFboUnbindBlitCase(m_context, "unbind_blit_stencil", "", 0, GL_STENCIL_BUFFER_BIT));
1575         subFboGroup->addChild(new InvalidateSubFboUnbindBlitCase(m_context, "unbind_blit_depth_stencil", "", 0,
1576                                                                  GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
1577 
1578         subFboGroup->addChild(
1579             new InvalidateSubFboUnbindBlitCase(m_context, "unbind_blit_msaa_color", "", 4, GL_COLOR_BUFFER_BIT));
1580         subFboGroup->addChild(
1581             new InvalidateSubFboUnbindBlitCase(m_context, "unbind_blit_msaa_depth", "", 4, GL_DEPTH_BUFFER_BIT));
1582         subFboGroup->addChild(
1583             new InvalidateSubFboUnbindBlitCase(m_context, "unbind_blit_msaa_stencil", "", 4, GL_STENCIL_BUFFER_BIT));
1584         subFboGroup->addChild(new InvalidateSubFboUnbindBlitCase(m_context, "unbind_blit_msaa_depth_stencil", "", 4,
1585                                                                  GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
1586     }
1587 
1588     // invalidate.format.
1589     {
1590         tcu::TestCaseGroup *formatGroup =
1591             new tcu::TestCaseGroup(m_testCtx, "format", "Invalidating framebuffers with selected formats");
1592         addChild(formatGroup);
1593 
1594         // Color buffer formats.
1595         static const uint32_t colorFormats[] = {
1596             // RGBA formats
1597             GL_RGBA32I, GL_RGBA32UI, GL_RGBA16I, GL_RGBA16UI, GL_RGBA8, GL_RGBA8I, GL_RGBA8UI, GL_SRGB8_ALPHA8,
1598             GL_RGB10_A2, GL_RGB10_A2UI, GL_RGBA4, GL_RGB5_A1,
1599 
1600             // RGB formats
1601             GL_RGB8, GL_RGB565,
1602 
1603             // RG formats
1604             GL_RG32I, GL_RG32UI, GL_RG16I, GL_RG16UI, GL_RG8, GL_RG8I, GL_RG8UI,
1605 
1606             // R formats
1607             GL_R32I, GL_R32UI, GL_R16I, GL_R16UI, GL_R8, GL_R8I, GL_R8UI,
1608 
1609             // GL_EXT_color_buffer_float
1610             GL_RGBA32F, GL_RGBA16F, GL_R11F_G11F_B10F, GL_RG32F, GL_RG16F, GL_R32F, GL_R16F};
1611 
1612         // Depth/stencilbuffer formats.
1613         static const uint32_t depthStencilFormats[] = {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT24,
1614                                                        GL_DEPTH_COMPONENT16,  GL_DEPTH32F_STENCIL8,
1615                                                        GL_DEPTH24_STENCIL8,   GL_STENCIL_INDEX8};
1616 
1617         // Colorbuffer tests use invalidate, unbind, read test.
1618         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(colorFormats); ndx++)
1619             formatGroup->addChild(new InvalidateSubFboUnbindReadCase(m_context, getFormatName(colorFormats[ndx]), "",
1620                                                                      colorFormats[ndx], GL_NONE, GL_COLOR_BUFFER_BIT));
1621 
1622         // Depth/stencilbuffer tests use invalidate, render test.
1623         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthStencilFormats); ndx++)
1624             formatGroup->addChild(new InvalidateSubFboRenderCase(m_context, getFormatName(depthStencilFormats[ndx]), "",
1625                                                                  GL_RGBA8, depthStencilFormats[ndx],
1626                                                                  GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
1627     }
1628 
1629     // invalidate.target
1630     {
1631         tcu::TestCaseGroup *targetGroup = new tcu::TestCaseGroup(m_testCtx, "target", "Invalidate target");
1632         addChild(targetGroup);
1633 
1634         static const struct
1635         {
1636             const char *name;
1637             uint32_t invalidateTarget;
1638             uint32_t boundTarget;
1639         } s_targetCases[] = {
1640             {"framebuffer_framebuffer", GL_FRAMEBUFFER, GL_FRAMEBUFFER},
1641             {"framebuffer_read_framebuffer", GL_FRAMEBUFFER, GL_READ_FRAMEBUFFER},
1642             {"framebuffer_draw_framebuffer", GL_FRAMEBUFFER, GL_DRAW_FRAMEBUFFER},
1643             {"read_framebuffer_framebuffer", GL_READ_FRAMEBUFFER, GL_FRAMEBUFFER},
1644             {"read_framebuffer_read_framebuffer", GL_READ_FRAMEBUFFER, GL_READ_FRAMEBUFFER},
1645             {"read_framebuffer_draw_framebuffer", GL_READ_FRAMEBUFFER, GL_DRAW_FRAMEBUFFER},
1646             {"draw_framebuffer_framebuffer", GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER},
1647             {"draw_framebuffer_read_framebuffer", GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER},
1648             {"draw_framebuffer_draw_framebuffer", GL_DRAW_FRAMEBUFFER, GL_DRAW_FRAMEBUFFER},
1649         };
1650 
1651         static const uint32_t colorAttachment[]        = {GL_COLOR_ATTACHMENT0};
1652         static const uint32_t depthStencilAttachment[] = {GL_DEPTH_STENCIL_ATTACHMENT};
1653         static const uint32_t allAttachments[] = {GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1654 
1655         for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(s_targetCases); caseNdx++)
1656         {
1657             const std::string baseName = s_targetCases[caseNdx].name;
1658             const uint32_t invalidateT = s_targetCases[caseNdx].invalidateTarget;
1659             const uint32_t boundT      = s_targetCases[caseNdx].boundTarget;
1660 
1661             targetGroup->addChild(new InvalidateFboTargetCase(m_context, (baseName + "_color").c_str(), "", boundT,
1662                                                               invalidateT, &colorAttachment[0],
1663                                                               DE_LENGTH_OF_ARRAY(colorAttachment)));
1664             targetGroup->addChild(new InvalidateFboTargetCase(m_context, (baseName + "_depth_stencil").c_str(), "",
1665                                                               boundT, invalidateT, &depthStencilAttachment[0],
1666                                                               DE_LENGTH_OF_ARRAY(depthStencilAttachment)));
1667             targetGroup->addChild(new InvalidateFboTargetCase(m_context, (baseName + "_all").c_str(), "", boundT,
1668                                                               invalidateT, &allAttachments[0],
1669                                                               DE_LENGTH_OF_ARRAY(allAttachments)));
1670         }
1671     }
1672 }
1673 
1674 } // namespace Functional
1675 } // namespace gles3
1676 } // namespace deqp
1677