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
36namespace deqp
37{
38namespace gles3
39{
40namespace Functional
41{
42
43using std::string;
44using std::vector;
45using tcu::Vec2;
46using tcu::Vec3;
47using tcu::Vec4;
48using tcu::IVec2;
49using tcu::IVec3;
50using tcu::IVec4;
51using tcu::UVec4;
52using namespace FboTestUtil;
53
54static 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
70static 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
88static inline bool hasAttachment (const std::vector<deUint32>& attachmentList, deUint32 attachment)
89{
90	return std::find(attachmentList.begin(), attachmentList.end(), attachment) != attachmentList.end();
91}
92
93static 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
117static 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
135class InvalidateDefaultFramebufferRenderCase : public FboTestCase
136{
137public:
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
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
199private:
200	deUint32 m_buffers;
201	deUint32 m_fboTarget;
202};
203
204class InvalidateDefaultFramebufferBindCase : public FboTestCase
205{
206public:
207	InvalidateDefaultFramebufferBindCase (Context& context, const char* name, const char* description, deUint32 buffers)
208		: FboTestCase	(context, name, description)
209		, m_buffers		(buffers)
210	{
211	}
212
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
294private:
295	deUint32 m_buffers;
296};
297
298class InvalidateDefaultSubFramebufferRenderCase : public FboTestCase
299{
300public:
301	InvalidateDefaultSubFramebufferRenderCase (Context& context, const char* name, const char* description, deUint32 buffers)
302		: FboTestCase	(context, name, description)
303		, m_buffers		(buffers)
304	{
305	}
306
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
348private:
349	deUint32 m_buffers;
350};
351
352class InvalidateDefaultSubFramebufferBindCase : public FboTestCase
353{
354public:
355	InvalidateDefaultSubFramebufferBindCase (Context& context, const char* name, const char* description, deUint32 buffers)
356		: FboTestCase	(context, name, description)
357		, m_buffers		(buffers)
358	{
359	}
360
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
438private:
439	deUint32 m_buffers;
440};
441
442class InvalidateFboRenderCase : public FboTestCase
443{
444public:
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
453protected:
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
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
548private:
549	deUint32	m_colorFmt;
550	deUint32	m_depthStencilFmt;
551	deUint32	m_invalidateBuffers;
552};
553
554class InvalidateFboUnbindReadCase : public FboTestCase
555{
556public:
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
566protected:
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
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
664private:
665	deUint32	m_colorFmt;
666	deUint32	m_depthStencilFmt;
667	deUint32	m_invalidateBuffers;
668};
669
670class InvalidateFboUnbindBlitCase : public FboTestCase
671{
672public:
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
687protected:
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
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*quadSizePixels.x()/getWidth(), 2.0f*quadSizePixels.y()/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
802private:
803	deUint32	m_colorFmt;
804	deUint32	m_depthStencilFmt;
805	int			m_numSamples;
806	deUint32	m_invalidateBuffers;
807};
808
809class InvalidateSubFboRenderCase : public FboTestCase
810{
811public:
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
820protected:
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
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
904private:
905	deUint32	m_colorFmt;
906	deUint32	m_depthStencilFmt;
907	deUint32	m_invalidateBuffers;
908};
909
910class InvalidateSubFboUnbindReadCase : public FboTestCase
911{
912public:
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
922protected:
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
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
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
1043private:
1044	deUint32	m_colorFmt;
1045	deUint32	m_depthStencilFmt;
1046	deUint32	m_invalidateBuffers;
1047};
1048
1049class InvalidateSubFboUnbindBlitCase : public FboTestCase
1050{
1051public:
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
1066protected:
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
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*quadSizePixels.x()/getWidth(), 2.0f*quadSizePixels.y()/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
1187private:
1188	deUint32	m_colorFmt;
1189	deUint32	m_depthStencilFmt;
1190	int			m_numSamples;
1191	deUint32	m_invalidateBuffers;
1192};
1193
1194class InvalidateFboTargetCase : public FboTestCase
1195{
1196public:
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
1205protected:
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
1314private:
1315	deUint32				m_boundTarget;
1316	deUint32				m_invalidateTarget;
1317	std::vector<deUint32>	m_invalidateAttachments;
1318};
1319
1320FboInvalidateTests::FboInvalidateTests (Context& context)
1321	: TestCaseGroup(context, "invalidate", "Framebuffer invalidate tests")
1322{
1323}
1324
1325FboInvalidateTests::~FboInvalidateTests (void)
1326{
1327}
1328
1329void 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