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