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