1/*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 2.0 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Framebuffer Object API Tests.
22 *
23 * Notes:
24 *   All gl calls are passed thru sgl2::Context class. Reasons:
25 *    + Name, object allocation is tracked and live resources are freed
26 *      when Context is destroyed.
27 *    + Makes it possible to easily log all relevant calls into test log.
28 *      \todo [pyry] This is not implemented yet
29 *//*--------------------------------------------------------------------*/
30
31#include "es2fFboApiTest.hpp"
32#include "sglrGLContext.hpp"
33#include "gluDefs.hpp"
34#include "gluContextInfo.hpp"
35#include "gluStrUtil.hpp"
36#include "tcuRenderTarget.hpp"
37#include "deString.h"
38#include "glwFunctions.hpp"
39#include "glwEnums.hpp"
40
41#include <iterator>
42#include <algorithm>
43
44namespace deqp
45{
46namespace gles2
47{
48namespace Functional
49{
50
51using std::string;
52using std::vector;
53using tcu::TestLog;
54
55using glw::GLenum;
56using glw::GLint;
57
58static void logComment (tcu::TestContext& testCtx, const char* comment)
59{
60	testCtx.getLog() << TestLog::Message << "// " << comment << TestLog::EndMessage;
61}
62
63static void checkError (tcu::TestContext& testCtx, sglr::Context& ctx, GLenum expect)
64{
65	GLenum result = ctx.getError();
66	testCtx.getLog() << TestLog::Message << "// " << (result == expect ? "Pass" : "Fail") << ", expected " << glu::getErrorStr(expect) << TestLog::EndMessage;
67
68	if (result != expect)
69		testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Error code mismatch");
70}
71
72static void checkEitherError (tcu::TestContext& testCtx, sglr::Context& ctx, GLenum expectA, GLenum expectB)
73{
74	GLenum	result	= ctx.getError();
75	bool	isOk	= (result == expectA || result == expectB);
76
77	testCtx.getLog() << TestLog::Message << "// " << (isOk ? "Pass" : "Fail") << ", expected " << glu::getErrorStr(expectA) << " or " << glu::getErrorStr(expectB) << TestLog::EndMessage;
78
79	if (!isOk)
80		testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Error code mismatch");
81}
82
83static const char* getAttachmentName (GLenum attachment)
84{
85	switch (attachment)
86	{
87		case GL_COLOR_ATTACHMENT0:	return "GL_COLOR_ATTACHMENT0";
88		case GL_DEPTH_ATTACHMENT:	return "GL_DEPTH_ATTACHMENT";
89		case GL_STENCIL_ATTACHMENT:	return "GL_STENCIL_ATTACHMENT";
90		default: throw tcu::InternalError("Unknown attachment", "", __FILE__, __LINE__);
91	}
92}
93
94static const char* getAttachmentParameterName (GLenum pname)
95{
96	switch (pname)
97	{
98		case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:				return "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE";
99		case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:				return "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME";
100		case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:			return "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL";
101		case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:	return "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE";
102		default: throw tcu::InternalError("Unknown parameter", "", __FILE__, __LINE__);
103	}
104}
105
106static string getAttachmentParameterValueName (GLint value)
107{
108	switch (value)
109	{
110		case 0:									return "GL_NONE(0)";
111		case GL_TEXTURE:						return "GL_TEXTURE";
112		case GL_RENDERBUFFER:					return "GL_RENDERBUFFER";
113		case GL_TEXTURE_CUBE_MAP_POSITIVE_X:	return "GL_TEXTURE_CUBE_MAP_POSITIVE_X";
114		case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:	return "GL_TEXTURE_CUBE_MAP_NEGATIVE_X";
115		case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:	return "GL_TEXTURE_CUBE_MAP_POSITIVE_Y";
116		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:	return "GL_TEXTURE_CUBE_MAP_NEGATIVE_Y";
117		case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:	return "GL_TEXTURE_CUBE_MAP_POSITIVE_Z";
118		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:	return "GL_TEXTURE_CUBE_MAP_NEGATIVE_Z";
119		default:
120		{
121			char tmp[64];
122			deSprintf(tmp, sizeof(tmp), "0x%x", value);
123			return string(tmp);
124		}
125	}
126}
127
128static void checkFboAttachmentParam (tcu::TestContext& testCtx, sglr::Context& ctx, GLenum attachment, GLenum pname, GLint expectedValue)
129{
130	TestLog& log = testCtx.getLog();
131	log << TestLog::Message << "// Querying " << getAttachmentName(attachment) << " " << getAttachmentParameterName(pname) << TestLog::EndMessage;
132
133	GLint value = 0xcdcdcdcd;
134	ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, attachment, pname, &value);
135
136	GLenum err = ctx.getError();
137
138	if (value == expectedValue && err == GL_NO_ERROR)
139		log << TestLog::Message << "// Pass" << TestLog::EndMessage;
140	else
141	{
142		log << TestLog::Message << "// Fail, expected " << getAttachmentParameterValueName(expectedValue) << " without error" << TestLog::EndMessage;
143		testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid result for attachment param query");
144	}
145}
146
147static void notSupportedTest (tcu::TestContext& testCtx, sglr::Context& context)
148{
149	DE_UNREF(testCtx);
150	DE_UNREF(context);
151	throw tcu::NotSupportedError("Not supported", "", __FILE__, __LINE__);
152}
153
154static void textureLevelsTest (tcu::TestContext& testCtx, sglr::Context& context)
155{
156	deUint32	tex		= 1;
157	deUint32	fbo		= 1;
158
159	context.bindTexture(GL_TEXTURE_2D, tex);
160	context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256);
161	context.texImage2D(GL_TEXTURE_2D, 1, GL_RGB, 128, 128);
162
163	context.bindFramebuffer(GL_FRAMEBUFFER, fbo);
164
165	static int levels[] = { 2, 1, 0, -1, 0x7fffffff, 0, 1 };
166
167	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(levels); ndx++)
168	{
169		context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, levels[ndx]);
170		checkError(testCtx, context, levels[ndx] == 0 ? GL_NO_ERROR : GL_INVALID_VALUE);
171	}
172}
173
174static void textureLevelsWithRenderToMipmapTest (tcu::TestContext& testCtx, sglr::Context& context)
175{
176	deUint32	tex		= 1;
177	deUint32	fbo		= 1;
178
179	context.bindTexture(GL_TEXTURE_2D, tex);
180	context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256);
181	context.texImage2D(GL_TEXTURE_2D, 1, GL_RGB, 128, 128);
182
183	context.bindFramebuffer(GL_FRAMEBUFFER, fbo);
184
185	static int levels[] = { 2, 1, 0, -1, 0x7fffffff, 0, 1 };
186
187	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(levels); ndx++)
188	{
189		context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, levels[ndx]);
190		checkError(testCtx, context, de::inBounds(levels[ndx], 0, 16) ? GL_NO_ERROR : GL_INVALID_VALUE);
191	}
192}
193
194static void validTex2DAttachmentsTest (tcu::TestContext& testCtx, sglr::Context& context)
195{
196	context.bindFramebuffer(GL_FRAMEBUFFER, 1);
197	static const GLenum attachmentPoints[] =
198	{
199		GL_COLOR_ATTACHMENT0,
200		GL_DEPTH_ATTACHMENT,
201		GL_STENCIL_ATTACHMENT
202	};
203
204	// Texture2D
205	deUint32 tex2D = 1;
206	context.bindTexture(GL_TEXTURE_2D, tex2D);
207	for (int pointNdx = 0; pointNdx < DE_LENGTH_OF_ARRAY(attachmentPoints); pointNdx++)
208	{
209		context.framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoints[pointNdx], GL_TEXTURE_2D, tex2D, 0);
210		checkError(testCtx, context, GL_NO_ERROR);
211	}
212}
213
214static void validTexCubeAttachmentsTest (tcu::TestContext& testCtx, sglr::Context& context)
215{
216	static const GLenum attachmentPoints[] =
217	{
218		GL_COLOR_ATTACHMENT0,
219		GL_DEPTH_ATTACHMENT,
220		GL_STENCIL_ATTACHMENT
221	};
222	static const GLenum cubeTargets[] =
223	{
224		GL_TEXTURE_CUBE_MAP_POSITIVE_X,
225		GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
226		GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
227		GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
228		GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
229		GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
230	};
231
232	context.bindFramebuffer(GL_FRAMEBUFFER, 1);
233
234	// TextureCube
235	deUint32 texCube = 2;
236	context.bindTexture(GL_TEXTURE_CUBE_MAP, texCube);
237	for (int pointNdx = 0; pointNdx < DE_LENGTH_OF_ARRAY(attachmentPoints); pointNdx++)
238	{
239		for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(cubeTargets); targetNdx++)
240		{
241			context.framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoints[pointNdx], cubeTargets[targetNdx], texCube, 0);
242			checkError(testCtx, context, GL_NO_ERROR);
243		}
244	}
245}
246
247static void validRboAttachmentsTest (tcu::TestContext& testCtx, sglr::Context& context)
248{
249	static const GLenum attachmentPoints[] =
250	{
251		GL_COLOR_ATTACHMENT0,
252		GL_DEPTH_ATTACHMENT,
253		GL_STENCIL_ATTACHMENT
254	};
255
256	context.bindFramebuffer(GL_FRAMEBUFFER, 1);
257
258	// Renderbuffer
259	deUint32 rbo = 3;
260	context.bindRenderbuffer(GL_RENDERBUFFER, rbo);
261	for (int pointNdx = 0; pointNdx < DE_LENGTH_OF_ARRAY(attachmentPoints); pointNdx++)
262	{
263		context.framebufferRenderbuffer(GL_FRAMEBUFFER, attachmentPoints[pointNdx], GL_RENDERBUFFER, rbo);
264		checkError(testCtx, context, GL_NO_ERROR);
265	}
266}
267
268static void attachToDefaultFramebufferTest (tcu::TestContext& testCtx, sglr::Context& context)
269{
270	logComment(testCtx, "Attaching 2D texture to default framebuffer");
271
272	deUint32 tex2D = 1;
273	context.bindTexture(GL_TEXTURE_2D, tex2D);
274	context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2D, 0);
275	checkError(testCtx, context, GL_INVALID_OPERATION);
276
277	logComment(testCtx, "Attaching renderbuffer to default framebuffer");
278
279	deUint32 rbo = 1;
280	context.bindRenderbuffer(GL_RENDERBUFFER, rbo);
281	context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo);
282	checkError(testCtx, context, GL_INVALID_OPERATION);
283}
284
285static void invalidTex2DAttachmentTest (tcu::TestContext& testCtx, sglr::Context& context)
286{
287	context.bindFramebuffer(GL_FRAMEBUFFER, 1);
288
289	logComment(testCtx, "Attaching 2D texture using GL_TEXTURE_CUBE_MAP_NEGATIVE_X texture target");
290
291	deUint32 tex2D = 1;
292	context.bindTexture(GL_TEXTURE_2D, tex2D);
293	context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, tex2D, 0);
294	checkError(testCtx, context, GL_INVALID_OPERATION);
295
296	logComment(testCtx, "Attaching deleted 2D texture object");
297	context.deleteTextures(1, &tex2D);
298	context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2D, 0);
299	checkError(testCtx, context, GL_INVALID_OPERATION);
300}
301
302static void invalidTexCubeAttachmentTest (tcu::TestContext& testCtx, sglr::Context& context)
303{
304	context.bindFramebuffer(GL_FRAMEBUFFER, 1);
305
306	logComment(testCtx, "Attaching cube texture using GL_TEXTURE_2D texture target");
307	deUint32 texCube = 2;
308	context.bindTexture(GL_TEXTURE_CUBE_MAP, texCube);
309	context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texCube, 0);
310	checkError(testCtx, context, GL_INVALID_OPERATION);
311
312	logComment(testCtx, "Attaching deleted cube texture object");
313	context.deleteTextures(1, &texCube);
314	context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X, texCube, 0);
315	checkError(testCtx, context, GL_INVALID_OPERATION);
316}
317
318static void invalidRboAttachmentTest (tcu::TestContext& testCtx, sglr::Context& context)
319{
320	context.bindFramebuffer(GL_FRAMEBUFFER, 1);
321
322	logComment(testCtx, "Attaching renderbuffer using GL_FRAMEBUFFER renderbuffer target");
323	deUint32 rbo = 3;
324	context.bindRenderbuffer(GL_RENDERBUFFER, rbo);
325	context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER, rbo);
326	checkError(testCtx, context, GL_INVALID_ENUM);
327
328	logComment(testCtx, "Attaching deleted renderbuffer object");
329	context.deleteRenderbuffers(1, &rbo);
330	context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
331	checkError(testCtx, context, GL_INVALID_OPERATION);
332}
333
334static void attachNamesTest (tcu::TestContext& testCtx, sglr::Context& context)
335{
336	context.bindFramebuffer(GL_FRAMEBUFFER, 1);
337
338	// Just allocate some names, don't bind for storage
339	deUint32 reservedTexName;
340	context.genTextures(1, &reservedTexName);
341
342	logComment(testCtx, "Attaching allocated texture name to 2D target");
343	context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, reservedTexName, 0);
344	checkError(testCtx, context, GL_INVALID_OPERATION);
345
346	logComment(testCtx, "Attaching allocated texture name to cube target");
347	context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, reservedTexName, 0);
348	checkError(testCtx, context, GL_INVALID_OPERATION);
349
350	deUint32 reservedRboName;
351	context.genRenderbuffers(1, &reservedRboName);
352
353	logComment(testCtx, "Attaching allocated renderbuffer name");
354	context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, reservedRboName);
355	checkError(testCtx, context, GL_INVALID_OPERATION);
356}
357
358static void attachmentQueryDefaultFboTest (tcu::TestContext& testCtx, sglr::Context& ctx)
359{
360	// Check that proper error codes are returned
361	GLint unused = 1;
362	ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &unused);
363	checkEitherError(testCtx, ctx, GL_INVALID_ENUM, GL_INVALID_OPERATION);
364	ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &unused);
365	checkEitherError(testCtx, ctx, GL_INVALID_ENUM, GL_INVALID_OPERATION);
366	ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, &unused);
367	checkEitherError(testCtx, ctx, GL_INVALID_ENUM, GL_INVALID_OPERATION);
368	ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, &unused);
369	checkEitherError(testCtx, ctx, GL_INVALID_ENUM, GL_INVALID_OPERATION);
370}
371
372static void attachmentQueryEmptyFboTest (tcu::TestContext& testCtx, sglr::Context& ctx)
373{
374	static const GLenum attachmentPoints[] =
375	{
376		GL_COLOR_ATTACHMENT0,
377		GL_DEPTH_ATTACHMENT,
378		GL_STENCIL_ATTACHMENT
379	};
380
381	ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
382
383	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(attachmentPoints); ndx++)
384		checkFboAttachmentParam(testCtx, ctx, attachmentPoints[ndx], GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_NONE);
385
386	// Check that proper error codes are returned
387	GLint unused = -1;
388	ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &unused);
389	checkError(testCtx, ctx, GL_INVALID_ENUM);
390	ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, &unused);
391	checkError(testCtx, ctx, GL_INVALID_ENUM);
392	ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, &unused);
393	checkError(testCtx, ctx, GL_INVALID_ENUM);
394}
395
396static void attachmentQueryTex2DTest (tcu::TestContext& testCtx, sglr::Context& ctx)
397{
398	ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
399
400	ctx.bindTexture(GL_TEXTURE_2D, 1);
401	ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 1, 0);
402
403	checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_TEXTURE);
404	checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, 1);
405	checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, 0);
406	checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, 0);
407}
408
409static void attachmentQueryTexCubeTest (tcu::TestContext& testCtx, sglr::Context& ctx)
410{
411	ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
412
413	ctx.bindTexture(GL_TEXTURE_CUBE_MAP, 2);
414	ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 2, 0);
415
416	checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_TEXTURE);
417	checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, 2);
418	checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, 0);
419	checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y);
420}
421
422static void attachmentQueryRboTest (tcu::TestContext& testCtx, sglr::Context& ctx)
423{
424	ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
425
426	ctx.bindRenderbuffer(GL_RENDERBUFFER, 3);
427	ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 3);
428
429	checkFboAttachmentParam(testCtx, ctx, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_RENDERBUFFER);
430	checkFboAttachmentParam(testCtx, ctx, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, 3);
431
432	GLint unused = 0;
433	ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, &unused);
434	checkError(testCtx, ctx, GL_INVALID_ENUM);
435	ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, &unused);
436	checkError(testCtx, ctx, GL_INVALID_ENUM);
437}
438
439static void deleteTex2DAttachedToBoundFboTest (tcu::TestContext& testCtx, sglr::Context& ctx)
440{
441	ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
442
443	deUint32 tex2D = 1;
444	ctx.bindTexture(GL_TEXTURE_2D, tex2D);
445	ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2D, 0);
446
447	checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_TEXTURE);
448	checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, tex2D);
449
450	ctx.deleteTextures(1, &tex2D);
451
452	checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_NONE);
453}
454
455static void deleteTexCubeAttachedToBoundFboTest (tcu::TestContext& testCtx, sglr::Context& ctx)
456{
457	ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
458
459	deUint32 texCube = 1;
460	ctx.bindTexture(GL_TEXTURE_CUBE_MAP, texCube);
461	ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X, texCube, 0);
462
463	checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_TEXTURE);
464	checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, texCube);
465
466	ctx.deleteTextures(1, &texCube);
467
468	checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_NONE);
469}
470
471static void deleteRboAttachedToBoundFboTest (tcu::TestContext& testCtx, sglr::Context& ctx)
472{
473	ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
474
475	deUint32 rbo = 1;
476	ctx.bindRenderbuffer(GL_RENDERBUFFER, rbo);
477	ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
478
479	checkFboAttachmentParam(testCtx, ctx, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_RENDERBUFFER);
480	checkFboAttachmentParam(testCtx, ctx, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, rbo);
481
482	ctx.deleteRenderbuffers(1, &rbo);
483
484	checkFboAttachmentParam(testCtx, ctx, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_NONE);
485}
486
487static void deleteTex2DAttachedToNotBoundFboTest (tcu::TestContext& testCtx, sglr::Context& ctx)
488{
489	ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
490
491	deUint32 tex2D = 1;
492	ctx.bindTexture(GL_TEXTURE_2D, tex2D);
493	ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2D, 0);
494
495	checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_TEXTURE);
496	checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, tex2D);
497
498	ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
499
500	ctx.deleteTextures(1, &tex2D);
501
502	ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
503
504	checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_TEXTURE);
505	checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, tex2D);
506}
507
508static void deleteTexCubeAttachedToNotBoundFboTest (tcu::TestContext& testCtx, sglr::Context& ctx)
509{
510	ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
511
512	deUint32 texCube = 1;
513	ctx.bindTexture(GL_TEXTURE_CUBE_MAP, texCube);
514	ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X, texCube, 0);
515
516	checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_TEXTURE);
517	checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, texCube);
518
519	ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
520
521	ctx.deleteTextures(1, &texCube);
522
523	ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
524
525	checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_TEXTURE);
526	checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, texCube);
527}
528
529static void deleteRboAttachedToNotBoundFboTest (tcu::TestContext& testCtx, sglr::Context& ctx)
530{
531	ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
532
533	deUint32 rbo = 1;
534	ctx.bindRenderbuffer(GL_RENDERBUFFER, rbo);
535	ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
536
537	checkFboAttachmentParam(testCtx, ctx, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_RENDERBUFFER);
538	checkFboAttachmentParam(testCtx, ctx, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, rbo);
539
540	ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
541
542	ctx.deleteRenderbuffers(1, &rbo);
543
544	ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
545
546	checkFboAttachmentParam(testCtx, ctx, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_RENDERBUFFER);
547	checkFboAttachmentParam(testCtx, ctx, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, rbo);
548}
549
550class FboApiCase : public TestCase
551{
552public:
553	typedef void (*TestFunc) (tcu::TestContext& testCtx, sglr::Context& context);
554
555								FboApiCase				(Context& context, const char* name, const char* description, TestFunc test);
556	virtual						~FboApiCase				(void);
557
558	virtual IterateResult		iterate					(void);
559
560private:
561								FboApiCase				(const FboApiCase& other);
562	FboApiCase&					operator=				(const FboApiCase& other);
563
564	TestFunc					m_testFunc;
565};
566
567FboApiCase::FboApiCase (Context& context, const char* name, const char* description, TestFunc test)
568	: TestCase		(context, name, description)
569	, m_testFunc	(test)
570{
571}
572
573FboApiCase::~FboApiCase (void)
574{
575}
576
577TestCase::IterateResult FboApiCase::iterate (void)
578{
579	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
580
581	GLU_EXPECT_NO_ERROR(gl.getError(), "Before test case");
582
583	// Initialize result to PASS
584	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
585
586	// Execute test case
587	{
588		sglr::GLContext context(m_context.getRenderContext(), m_testCtx.getLog(), sglr::GLCONTEXT_LOG_CALLS, tcu::IVec4(0, 0, m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight()));
589		m_testFunc(m_testCtx, context);
590	}
591
592	GLU_EXPECT_NO_ERROR(gl.getError(), "After test case");
593
594	return STOP;
595}
596
597FboApiTestGroup::FboApiTestGroup (Context& context)
598	: TestCaseGroup(context, "api", "API Tests")
599{
600}
601
602FboApiTestGroup::~FboApiTestGroup (void)
603{
604}
605
606void FboApiTestGroup::init (void)
607{
608	std::set<std::string> extensions;
609	std::copy(m_context.getContextInfo().getExtensions().begin(), m_context.getContextInfo().getExtensions().end(), std::inserter(extensions, extensions.begin()));
610
611	bool	defaultFboIsZero	= m_context.getRenderContext().getDefaultFramebuffer() == 0;
612	bool	hasRenderToMipmap	= extensions.find("GL_OES_fbo_render_mipmap") != extensions.end();
613
614	// Valid attachments
615	addChild(new FboApiCase(m_context, "valid_tex2d_attachments",					"Valid 2D texture attachments",							validTex2DAttachmentsTest));
616	addChild(new FboApiCase(m_context, "valid_texcube_attachments",					"Valid cubemap attachments",							validTexCubeAttachmentsTest));
617	addChild(new FboApiCase(m_context, "valid_rbo_attachments",						"Valid renderbuffer attachments",						validRboAttachmentsTest));
618
619	// Invalid attachments
620	addChild(new FboApiCase(m_context, "attach_to_default_fbo",						"Invalid usage: attaching to default FBO",				defaultFboIsZero ? attachToDefaultFramebufferTest : notSupportedTest));
621	addChild(new FboApiCase(m_context, "invalid_tex2d_attachments",					"Invalid 2D texture attachments",						invalidTex2DAttachmentTest));
622	addChild(new FboApiCase(m_context, "invalid_texcube_attachments",				"Invalid cubemap attachments",							invalidTexCubeAttachmentTest));
623	addChild(new FboApiCase(m_context, "invalid_rbo_attachments",					"Invalid renderbuffer attachments",						invalidRboAttachmentTest));
624	addChild(new FboApiCase(m_context, "attach_names",								"Attach allocated names without objects",				attachNamesTest));
625
626	addChild(new FboApiCase(m_context, "texture_levels",							"Valid and invalid texturel levels",					hasRenderToMipmap ? textureLevelsWithRenderToMipmapTest : textureLevelsTest));
627
628	// Attachment queries
629	addChild(new FboApiCase(m_context, "attachment_query_default_fbo",				"Query attachments from default FBO",					defaultFboIsZero ? attachmentQueryDefaultFboTest : notSupportedTest));
630	addChild(new FboApiCase(m_context, "attachment_query_empty_fbo",				"Query attachments from empty FBO",						attachmentQueryEmptyFboTest));
631	addChild(new FboApiCase(m_context, "attachment_query_tex2d",					"Query 2d texture attachment properties",				attachmentQueryTex2DTest));
632	addChild(new FboApiCase(m_context, "attachment_query_texcube",					"Query cubemap attachment properties",					attachmentQueryTexCubeTest));
633	addChild(new FboApiCase(m_context, "attachment_query_rbo",						"Query renderbuffer attachment properties",				attachmentQueryRboTest));
634
635	// Delete attachments
636	addChild(new FboApiCase(m_context, "delete_tex_2d_attached_to_bound_fbo",		"Delete 2d texture attached to currently bound FBO",	deleteTex2DAttachedToBoundFboTest));
637	addChild(new FboApiCase(m_context, "delete_tex_cube_attached_to_bound_fbo",		"Delete cubemap attached to currently bound FBO",		deleteTexCubeAttachedToBoundFboTest));
638	addChild(new FboApiCase(m_context, "delete_rbo_attached_to_bound_fbo",			"Delete renderbuffer attached to currently bound FBO",	deleteRboAttachedToBoundFboTest));
639
640	addChild(new FboApiCase(m_context, "delete_tex_2d_attached_to_not_bound_fbo",	"Delete 2d texture attached to FBO",					deleteTex2DAttachedToNotBoundFboTest));
641	addChild(new FboApiCase(m_context, "delete_tex_cube_attached_to_not_bound_fbo",	"Delete cubemap attached to FBO",						deleteTexCubeAttachedToNotBoundFboTest));
642	addChild(new FboApiCase(m_context, "delete_rbo_attached_to_not_bound_fbo",		"Delete renderbuffer attached to FBO",					deleteRboAttachedToNotBoundFboTest));
643}
644
645} // Functional
646} // gles2
647} // deqp
648