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 const char* getAttachmentName (GLenum attachment)
73{
74	switch (attachment)
75	{
76		case GL_COLOR_ATTACHMENT0:	return "GL_COLOR_ATTACHMENT0";
77		case GL_DEPTH_ATTACHMENT:	return "GL_DEPTH_ATTACHMENT";
78		case GL_STENCIL_ATTACHMENT:	return "GL_STENCIL_ATTACHMENT";
79		default: throw tcu::InternalError("Unknown attachment", "", __FILE__, __LINE__);
80	}
81}
82
83static const char* getAttachmentParameterName (GLenum pname)
84{
85	switch (pname)
86	{
87		case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:				return "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE";
88		case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:				return "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME";
89		case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:			return "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL";
90		case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:	return "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE";
91		default: throw tcu::InternalError("Unknown parameter", "", __FILE__, __LINE__);
92	}
93}
94
95static string getAttachmentParameterValueName (GLint value)
96{
97	switch (value)
98	{
99		case 0:									return "GL_NONE(0)";
100		case GL_TEXTURE:						return "GL_TEXTURE";
101		case GL_RENDERBUFFER:					return "GL_RENDERBUFFER";
102		case GL_TEXTURE_CUBE_MAP_POSITIVE_X:	return "GL_TEXTURE_CUBE_MAP_POSITIVE_X";
103		case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:	return "GL_TEXTURE_CUBE_MAP_NEGATIVE_X";
104		case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:	return "GL_TEXTURE_CUBE_MAP_POSITIVE_Y";
105		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:	return "GL_TEXTURE_CUBE_MAP_NEGATIVE_Y";
106		case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:	return "GL_TEXTURE_CUBE_MAP_POSITIVE_Z";
107		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:	return "GL_TEXTURE_CUBE_MAP_NEGATIVE_Z";
108		default:
109		{
110			char tmp[64];
111			deSprintf(tmp, sizeof(tmp), "0x%x", value);
112			return string(tmp);
113		}
114	}
115}
116
117static void checkFboAttachmentParam (tcu::TestContext& testCtx, sglr::Context& ctx, GLenum attachment, GLenum pname, GLint expectedValue)
118{
119	TestLog& log = testCtx.getLog();
120	log << TestLog::Message << "// Querying " << getAttachmentName(attachment) << " " << getAttachmentParameterName(pname) << TestLog::EndMessage;
121
122	GLint value = 0xcdcdcdcd;
123	ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, attachment, pname, &value);
124
125	GLenum err = ctx.getError();
126
127	if (value == expectedValue && err == GL_NO_ERROR)
128		log << TestLog::Message << "// Pass" << TestLog::EndMessage;
129	else
130	{
131		log << TestLog::Message << "// Fail, expected " << getAttachmentParameterValueName(expectedValue) << " without error" << TestLog::EndMessage;
132		testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid result for attachment param query");
133	}
134}
135
136static void notSupportedTest (tcu::TestContext& testCtx, sglr::Context& context)
137{
138	DE_UNREF(testCtx);
139	DE_UNREF(context);
140	throw tcu::NotSupportedError("Not supported", "", __FILE__, __LINE__);
141}
142
143static void textureLevelsTest (tcu::TestContext& testCtx, sglr::Context& context)
144{
145	deUint32	tex		= 1;
146	deUint32	fbo		= 1;
147
148	context.bindTexture(GL_TEXTURE_2D, tex);
149	context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256);
150	context.texImage2D(GL_TEXTURE_2D, 1, GL_RGB, 128, 128);
151
152	context.bindFramebuffer(GL_FRAMEBUFFER, fbo);
153
154	static int levels[] = { 2, 1, 0, -1, 0x7fffffff, 0, 1 };
155
156	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(levels); ndx++)
157	{
158		context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, levels[ndx]);
159		checkError(testCtx, context, levels[ndx] == 0 ? GL_NO_ERROR : GL_INVALID_VALUE);
160	}
161}
162
163static void textureLevelsWithRenderToMipmapTest (tcu::TestContext& testCtx, sglr::Context& context)
164{
165	deUint32	tex		= 1;
166	deUint32	fbo		= 1;
167
168	context.bindTexture(GL_TEXTURE_2D, tex);
169	context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256);
170	context.texImage2D(GL_TEXTURE_2D, 1, GL_RGB, 128, 128);
171
172	context.bindFramebuffer(GL_FRAMEBUFFER, fbo);
173
174	static int levels[] = { 2, 1, 0, -1, 0x7fffffff, 0, 1 };
175
176	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(levels); ndx++)
177	{
178		context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, levels[ndx]);
179		checkError(testCtx, context, de::inBounds(levels[ndx], 0, 16) ? GL_NO_ERROR : GL_INVALID_VALUE);
180	}
181}
182
183static void validTex2DAttachmentsTest (tcu::TestContext& testCtx, sglr::Context& context)
184{
185	context.bindFramebuffer(GL_FRAMEBUFFER, 1);
186	static const GLenum attachmentPoints[] =
187	{
188		GL_COLOR_ATTACHMENT0,
189		GL_DEPTH_ATTACHMENT,
190		GL_STENCIL_ATTACHMENT
191	};
192
193	// Texture2D
194	deUint32 tex2D = 1;
195	context.bindTexture(GL_TEXTURE_2D, tex2D);
196	for (int pointNdx = 0; pointNdx < DE_LENGTH_OF_ARRAY(attachmentPoints); pointNdx++)
197	{
198		context.framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoints[pointNdx], GL_TEXTURE_2D, tex2D, 0);
199		checkError(testCtx, context, GL_NO_ERROR);
200	}
201}
202
203static void validTexCubeAttachmentsTest (tcu::TestContext& testCtx, sglr::Context& context)
204{
205	static const GLenum attachmentPoints[] =
206	{
207		GL_COLOR_ATTACHMENT0,
208		GL_DEPTH_ATTACHMENT,
209		GL_STENCIL_ATTACHMENT
210	};
211	static const GLenum cubeTargets[] =
212	{
213		GL_TEXTURE_CUBE_MAP_POSITIVE_X,
214		GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
215		GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
216		GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
217		GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
218		GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
219	};
220
221	context.bindFramebuffer(GL_FRAMEBUFFER, 1);
222
223	// TextureCube
224	deUint32 texCube = 2;
225	context.bindTexture(GL_TEXTURE_CUBE_MAP, texCube);
226	for (int pointNdx = 0; pointNdx < DE_LENGTH_OF_ARRAY(attachmentPoints); pointNdx++)
227	{
228		for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(cubeTargets); targetNdx++)
229		{
230			context.framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoints[pointNdx], cubeTargets[targetNdx], texCube, 0);
231			checkError(testCtx, context, GL_NO_ERROR);
232		}
233	}
234}
235
236static void validRboAttachmentsTest (tcu::TestContext& testCtx, sglr::Context& context)
237{
238	static const GLenum attachmentPoints[] =
239	{
240		GL_COLOR_ATTACHMENT0,
241		GL_DEPTH_ATTACHMENT,
242		GL_STENCIL_ATTACHMENT
243	};
244
245	context.bindFramebuffer(GL_FRAMEBUFFER, 1);
246
247	// Renderbuffer
248	deUint32 rbo = 3;
249	context.bindRenderbuffer(GL_RENDERBUFFER, rbo);
250	for (int pointNdx = 0; pointNdx < DE_LENGTH_OF_ARRAY(attachmentPoints); pointNdx++)
251	{
252		context.framebufferRenderbuffer(GL_FRAMEBUFFER, attachmentPoints[pointNdx], GL_RENDERBUFFER, rbo);
253		checkError(testCtx, context, GL_NO_ERROR);
254	}
255}
256
257static void attachToDefaultFramebufferTest (tcu::TestContext& testCtx, sglr::Context& context)
258{
259	logComment(testCtx, "Attaching 2D texture to default framebuffer");
260
261	deUint32 tex2D = 1;
262	context.bindTexture(GL_TEXTURE_2D, tex2D);
263	context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2D, 0);
264	checkError(testCtx, context, GL_INVALID_OPERATION);
265
266	logComment(testCtx, "Attaching renderbuffer to default framebuffer");
267
268	deUint32 rbo = 1;
269	context.bindRenderbuffer(GL_RENDERBUFFER, rbo);
270	context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo);
271	checkError(testCtx, context, GL_INVALID_OPERATION);
272}
273
274static void invalidTex2DAttachmentTest (tcu::TestContext& testCtx, sglr::Context& context)
275{
276	context.bindFramebuffer(GL_FRAMEBUFFER, 1);
277
278	logComment(testCtx, "Attaching 2D texture using GL_TEXTURE_CUBE_MAP_NEGATIVE_X texture target");
279
280	deUint32 tex2D = 1;
281	context.bindTexture(GL_TEXTURE_2D, tex2D);
282	context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, tex2D, 0);
283	checkError(testCtx, context, GL_INVALID_OPERATION);
284
285	logComment(testCtx, "Attaching deleted 2D texture object");
286	context.deleteTextures(1, &tex2D);
287	context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2D, 0);
288	checkError(testCtx, context, GL_INVALID_OPERATION);
289}
290
291static void invalidTexCubeAttachmentTest (tcu::TestContext& testCtx, sglr::Context& context)
292{
293	context.bindFramebuffer(GL_FRAMEBUFFER, 1);
294
295	logComment(testCtx, "Attaching cube texture using GL_TEXTURE_2D texture target");
296	deUint32 texCube = 2;
297	context.bindTexture(GL_TEXTURE_CUBE_MAP, texCube);
298	context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texCube, 0);
299	checkError(testCtx, context, GL_INVALID_OPERATION);
300
301	logComment(testCtx, "Attaching deleted cube texture object");
302	context.deleteTextures(1, &texCube);
303	context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X, texCube, 0);
304	checkError(testCtx, context, GL_INVALID_OPERATION);
305}
306
307static void invalidRboAttachmentTest (tcu::TestContext& testCtx, sglr::Context& context)
308{
309	context.bindFramebuffer(GL_FRAMEBUFFER, 1);
310
311	logComment(testCtx, "Attaching renderbuffer using GL_FRAMEBUFFER renderbuffer target");
312	deUint32 rbo = 3;
313	context.bindRenderbuffer(GL_RENDERBUFFER, rbo);
314	context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER, rbo);
315	checkError(testCtx, context, GL_INVALID_ENUM);
316
317	logComment(testCtx, "Attaching deleted renderbuffer object");
318	context.deleteRenderbuffers(1, &rbo);
319	context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
320	checkError(testCtx, context, GL_INVALID_OPERATION);
321}
322
323static void attachNamesTest (tcu::TestContext& testCtx, sglr::Context& context)
324{
325	context.bindFramebuffer(GL_FRAMEBUFFER, 1);
326
327	// Just allocate some names, don't bind for storage
328	deUint32 reservedTexName;
329	context.genTextures(1, &reservedTexName);
330
331	logComment(testCtx, "Attaching allocated texture name to 2D target");
332	context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, reservedTexName, 0);
333	checkError(testCtx, context, GL_INVALID_OPERATION);
334
335	logComment(testCtx, "Attaching allocated texture name to cube target");
336	context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, reservedTexName, 0);
337	checkError(testCtx, context, GL_INVALID_OPERATION);
338
339	deUint32 reservedRboName;
340	context.genRenderbuffers(1, &reservedRboName);
341
342	logComment(testCtx, "Attaching allocated renderbuffer name");
343	context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, reservedRboName);
344	checkError(testCtx, context, GL_INVALID_OPERATION);
345}
346
347static void attachmentQueryDefaultFboTest (tcu::TestContext& testCtx, sglr::Context& ctx)
348{
349	// Check that proper error codes are returned
350	GLint unused = 1;
351	ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &unused);
352	checkError(testCtx, ctx, GL_INVALID_OPERATION);
353	ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &unused);
354	checkError(testCtx, ctx, GL_INVALID_OPERATION);
355	ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, &unused);
356	checkError(testCtx, ctx, GL_INVALID_OPERATION);
357	ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, &unused);
358	checkError(testCtx, ctx, GL_INVALID_OPERATION);
359}
360
361static void attachmentQueryEmptyFboTest (tcu::TestContext& testCtx, sglr::Context& ctx)
362{
363	static const GLenum attachmentPoints[] =
364	{
365		GL_COLOR_ATTACHMENT0,
366		GL_DEPTH_ATTACHMENT,
367		GL_STENCIL_ATTACHMENT
368	};
369
370	ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
371
372	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(attachmentPoints); ndx++)
373		checkFboAttachmentParam(testCtx, ctx, attachmentPoints[ndx], GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_NONE);
374
375	// Check that proper error codes are returned
376	GLint unused = -1;
377	ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &unused);
378	checkError(testCtx, ctx, GL_INVALID_ENUM);
379	ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, &unused);
380	checkError(testCtx, ctx, GL_INVALID_ENUM);
381	ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, &unused);
382	checkError(testCtx, ctx, GL_INVALID_ENUM);
383}
384
385static void attachmentQueryTex2DTest (tcu::TestContext& testCtx, sglr::Context& ctx)
386{
387	ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
388
389	ctx.bindTexture(GL_TEXTURE_2D, 1);
390	ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 1, 0);
391
392	checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_TEXTURE);
393	checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, 1);
394	checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, 0);
395	checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, 0);
396}
397
398static void attachmentQueryTexCubeTest (tcu::TestContext& testCtx, sglr::Context& ctx)
399{
400	ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
401
402	ctx.bindTexture(GL_TEXTURE_CUBE_MAP, 2);
403	ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 2, 0);
404
405	checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_TEXTURE);
406	checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, 2);
407	checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, 0);
408	checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y);
409}
410
411static void attachmentQueryRboTest (tcu::TestContext& testCtx, sglr::Context& ctx)
412{
413	ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
414
415	ctx.bindRenderbuffer(GL_RENDERBUFFER, 3);
416	ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 3);
417
418	checkFboAttachmentParam(testCtx, ctx, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_RENDERBUFFER);
419	checkFboAttachmentParam(testCtx, ctx, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, 3);
420
421	GLint unused = 0;
422	ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, &unused);
423	checkError(testCtx, ctx, GL_INVALID_ENUM);
424	ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, &unused);
425	checkError(testCtx, ctx, GL_INVALID_ENUM);
426}
427
428static void deleteTex2DAttachedToBoundFboTest (tcu::TestContext& testCtx, sglr::Context& ctx)
429{
430	ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
431
432	deUint32 tex2D = 1;
433	ctx.bindTexture(GL_TEXTURE_2D, tex2D);
434	ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2D, 0);
435
436	checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_TEXTURE);
437	checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, tex2D);
438
439	ctx.deleteTextures(1, &tex2D);
440
441	checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_NONE);
442}
443
444static void deleteTexCubeAttachedToBoundFboTest (tcu::TestContext& testCtx, sglr::Context& ctx)
445{
446	ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
447
448	deUint32 texCube = 1;
449	ctx.bindTexture(GL_TEXTURE_CUBE_MAP, texCube);
450	ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X, texCube, 0);
451
452	checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_TEXTURE);
453	checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, texCube);
454
455	ctx.deleteTextures(1, &texCube);
456
457	checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_NONE);
458}
459
460static void deleteRboAttachedToBoundFboTest (tcu::TestContext& testCtx, sglr::Context& ctx)
461{
462	ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
463
464	deUint32 rbo = 1;
465	ctx.bindRenderbuffer(GL_RENDERBUFFER, rbo);
466	ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
467
468	checkFboAttachmentParam(testCtx, ctx, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_RENDERBUFFER);
469	checkFboAttachmentParam(testCtx, ctx, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, rbo);
470
471	ctx.deleteRenderbuffers(1, &rbo);
472
473	checkFboAttachmentParam(testCtx, ctx, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_NONE);
474}
475
476static void deleteTex2DAttachedToNotBoundFboTest (tcu::TestContext& testCtx, sglr::Context& ctx)
477{
478	ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
479
480	deUint32 tex2D = 1;
481	ctx.bindTexture(GL_TEXTURE_2D, tex2D);
482	ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2D, 0);
483
484	checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_TEXTURE);
485	checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, tex2D);
486
487	ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
488
489	ctx.deleteTextures(1, &tex2D);
490
491	ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
492
493	checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_TEXTURE);
494	checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, tex2D);
495}
496
497static void deleteTexCubeAttachedToNotBoundFboTest (tcu::TestContext& testCtx, sglr::Context& ctx)
498{
499	ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
500
501	deUint32 texCube = 1;
502	ctx.bindTexture(GL_TEXTURE_CUBE_MAP, texCube);
503	ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X, texCube, 0);
504
505	checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_TEXTURE);
506	checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, texCube);
507
508	ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
509
510	ctx.deleteTextures(1, &texCube);
511
512	ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
513
514	checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_TEXTURE);
515	checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, texCube);
516}
517
518static void deleteRboAttachedToNotBoundFboTest (tcu::TestContext& testCtx, sglr::Context& ctx)
519{
520	ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
521
522	deUint32 rbo = 1;
523	ctx.bindRenderbuffer(GL_RENDERBUFFER, rbo);
524	ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
525
526	checkFboAttachmentParam(testCtx, ctx, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_RENDERBUFFER);
527	checkFboAttachmentParam(testCtx, ctx, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, rbo);
528
529	ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
530
531	ctx.deleteRenderbuffers(1, &rbo);
532
533	ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
534
535	checkFboAttachmentParam(testCtx, ctx, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_RENDERBUFFER);
536	checkFboAttachmentParam(testCtx, ctx, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, rbo);
537}
538
539class FboApiCase : public TestCase
540{
541public:
542	typedef void (*TestFunc) (tcu::TestContext& testCtx, sglr::Context& context);
543
544								FboApiCase				(Context& context, const char* name, const char* description, TestFunc test);
545	virtual						~FboApiCase				(void);
546
547	virtual IterateResult		iterate					(void);
548
549private:
550								FboApiCase				(const FboApiCase& other);
551	FboApiCase&					operator=				(const FboApiCase& other);
552
553	TestFunc					m_testFunc;
554};
555
556FboApiCase::FboApiCase (Context& context, const char* name, const char* description, TestFunc test)
557	: TestCase		(context, name, description)
558	, m_testFunc	(test)
559{
560}
561
562FboApiCase::~FboApiCase (void)
563{
564}
565
566TestCase::IterateResult FboApiCase::iterate (void)
567{
568	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
569
570	GLU_EXPECT_NO_ERROR(gl.getError(), "Before test case");
571
572	// Initialize result to PASS
573	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
574
575	// Execute test case
576	{
577		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()));
578		m_testFunc(m_testCtx, context);
579	}
580
581	GLU_EXPECT_NO_ERROR(gl.getError(), "After test case");
582
583	return STOP;
584}
585
586FboApiTestGroup::FboApiTestGroup (Context& context)
587	: TestCaseGroup(context, "api", "API Tests")
588{
589}
590
591FboApiTestGroup::~FboApiTestGroup (void)
592{
593}
594
595void FboApiTestGroup::init (void)
596{
597	std::set<std::string> extensions;
598	std::copy(m_context.getContextInfo().getExtensions().begin(), m_context.getContextInfo().getExtensions().end(), std::inserter(extensions, extensions.begin()));
599
600	bool	defaultFboIsZero	= m_context.getRenderContext().getDefaultFramebuffer() == 0;
601	bool	hasRenderToMipmap	= extensions.find("GL_OES_fbo_render_mipmap") != extensions.end();
602
603	// Valid attachments
604	addChild(new FboApiCase(m_context, "valid_tex2d_attachments",					"Valid 2D texture attachments",							validTex2DAttachmentsTest));
605	addChild(new FboApiCase(m_context, "valid_texcube_attachments",					"Valid cubemap attachments",							validTexCubeAttachmentsTest));
606	addChild(new FboApiCase(m_context, "valid_rbo_attachments",						"Valid renderbuffer attachments",						validRboAttachmentsTest));
607
608	// Invalid attachments
609	addChild(new FboApiCase(m_context, "attach_to_default_fbo",						"Invalid usage: attaching to default FBO",				defaultFboIsZero ? attachToDefaultFramebufferTest : notSupportedTest));
610	addChild(new FboApiCase(m_context, "invalid_tex2d_attachments",					"Invalid 2D texture attachments",						invalidTex2DAttachmentTest));
611	addChild(new FboApiCase(m_context, "invalid_texcube_attachments",				"Invalid cubemap attachments",							invalidTexCubeAttachmentTest));
612	addChild(new FboApiCase(m_context, "invalid_rbo_attachments",					"Invalid renderbuffer attachments",						invalidRboAttachmentTest));
613	addChild(new FboApiCase(m_context, "attach_names",								"Attach allocated names without objects",				attachNamesTest));
614
615	addChild(new FboApiCase(m_context, "texture_levels",							"Valid and invalid texturel levels",					hasRenderToMipmap ? textureLevelsWithRenderToMipmapTest : textureLevelsTest));
616
617	// Attachment queries
618	addChild(new FboApiCase(m_context, "attachment_query_default_fbo",				"Query attachments from default FBO",					defaultFboIsZero ? attachmentQueryDefaultFboTest : notSupportedTest));
619	addChild(new FboApiCase(m_context, "attachment_query_empty_fbo",				"Query attachments from empty FBO",						attachmentQueryEmptyFboTest));
620	addChild(new FboApiCase(m_context, "attachment_query_tex2d",					"Query 2d texture attachment properties",				attachmentQueryTex2DTest));
621	addChild(new FboApiCase(m_context, "attachment_query_texcube",					"Query cubemap attachment properties",					attachmentQueryTexCubeTest));
622	addChild(new FboApiCase(m_context, "attachment_query_rbo",						"Query renderbuffer attachment properties",				attachmentQueryRboTest));
623
624	// Delete attachments
625	addChild(new FboApiCase(m_context, "delete_tex_2d_attached_to_bound_fbo",		"Delete 2d texture attached to currently bound FBO",	deleteTex2DAttachedToBoundFboTest));
626	addChild(new FboApiCase(m_context, "delete_tex_cube_attached_to_bound_fbo",		"Delete cubemap attached to currently bound FBO",		deleteTexCubeAttachedToBoundFboTest));
627	addChild(new FboApiCase(m_context, "delete_rbo_attached_to_bound_fbo",			"Delete renderbuffer attached to currently bound FBO",	deleteRboAttachedToBoundFboTest));
628
629	addChild(new FboApiCase(m_context, "delete_tex_2d_attached_to_not_bound_fbo",	"Delete 2d texture attached to FBO",					deleteTex2DAttachedToNotBoundFboTest));
630	addChild(new FboApiCase(m_context, "delete_tex_cube_attached_to_not_bound_fbo",	"Delete cubemap attached to FBO",						deleteTexCubeAttachedToNotBoundFboTest));
631	addChild(new FboApiCase(m_context, "delete_rbo_attached_to_not_bound_fbo",		"Delete renderbuffer attached to FBO",					deleteRboAttachedToNotBoundFboTest));
632}
633
634} // Functional
635} // gles2
636} // deqp
637