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 
44 namespace deqp
45 {
46 namespace gles2
47 {
48 namespace Functional
49 {
50 
51 using std::string;
52 using std::vector;
53 using tcu::TestLog;
54 
55 using glw::GLenum;
56 using glw::GLint;
57 
logComment(tcu::TestContext & testCtx,const char * comment)58 static void logComment (tcu::TestContext& testCtx, const char* comment)
59 {
60 	testCtx.getLog() << TestLog::Message << "// " << comment << TestLog::EndMessage;
61 }
62 
checkError(tcu::TestContext & testCtx,sglr::Context & ctx,GLenum expect)63 static 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 
checkEitherError(tcu::TestContext & testCtx,sglr::Context & ctx,GLenum expectA,GLenum expectB)72 static 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 
getAttachmentName(GLenum attachment)83 static 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 
getAttachmentParameterName(GLenum pname)94 static 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 
getAttachmentParameterValueName(GLint value)106 static 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 
checkFboAttachmentParam(tcu::TestContext & testCtx,sglr::Context & ctx,GLenum attachment,GLenum pname,GLint expectedValue)128 static 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 
notSupportedTest(tcu::TestContext & testCtx,sglr::Context & context)147 static 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 
textureLevelsTest(tcu::TestContext & testCtx,sglr::Context & context)154 static 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 
textureLevelsWithRenderToMipmapTest(tcu::TestContext & testCtx,sglr::Context & context)174 static 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 
validTex2DAttachmentsTest(tcu::TestContext & testCtx,sglr::Context & context)194 static 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 
validTexCubeAttachmentsTest(tcu::TestContext & testCtx,sglr::Context & context)214 static 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 
validRboAttachmentsTest(tcu::TestContext & testCtx,sglr::Context & context)247 static 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 
attachToDefaultFramebufferTest(tcu::TestContext & testCtx,sglr::Context & context)268 static 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 
invalidTex2DAttachmentTest(tcu::TestContext & testCtx,sglr::Context & context)285 static 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 
invalidTexCubeAttachmentTest(tcu::TestContext & testCtx,sglr::Context & context)302 static 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 
invalidRboAttachmentTest(tcu::TestContext & testCtx,sglr::Context & context)318 static 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 
attachNamesTest(tcu::TestContext & testCtx,sglr::Context & context)334 static 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 
attachmentQueryDefaultFboTest(tcu::TestContext & testCtx,sglr::Context & ctx)358 static 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 
attachmentQueryEmptyFboTest(tcu::TestContext & testCtx,sglr::Context & ctx)372 static 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 
attachmentQueryTex2DTest(tcu::TestContext & testCtx,sglr::Context & ctx)396 static 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 
attachmentQueryTexCubeTest(tcu::TestContext & testCtx,sglr::Context & ctx)409 static 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 
attachmentQueryRboTest(tcu::TestContext & testCtx,sglr::Context & ctx)422 static 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 
deleteTex2DAttachedToBoundFboTest(tcu::TestContext & testCtx,sglr::Context & ctx)439 static 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 
deleteTexCubeAttachedToBoundFboTest(tcu::TestContext & testCtx,sglr::Context & ctx)455 static 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 
deleteRboAttachedToBoundFboTest(tcu::TestContext & testCtx,sglr::Context & ctx)471 static 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 
deleteTex2DAttachedToNotBoundFboTest(tcu::TestContext & testCtx,sglr::Context & ctx)487 static 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 
deleteTexCubeAttachedToNotBoundFboTest(tcu::TestContext & testCtx,sglr::Context & ctx)508 static 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 
deleteRboAttachedToNotBoundFboTest(tcu::TestContext & testCtx,sglr::Context & ctx)529 static 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 
550 class FboApiCase : public TestCase
551 {
552 public:
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 
560 private:
561 								FboApiCase				(const FboApiCase& other);
562 	FboApiCase&					operator=				(const FboApiCase& other);
563 
564 	TestFunc					m_testFunc;
565 };
566 
FboApiCase(Context & context,const char * name,const char * description,TestFunc test)567 FboApiCase::FboApiCase (Context& context, const char* name, const char* description, TestFunc test)
568 	: TestCase		(context, name, description)
569 	, m_testFunc	(test)
570 {
571 }
572 
~FboApiCase(void)573 FboApiCase::~FboApiCase (void)
574 {
575 }
576 
iterate(void)577 TestCase::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 
FboApiTestGroup(Context & context)597 FboApiTestGroup::FboApiTestGroup (Context& context)
598 	: TestCaseGroup(context, "api", "API Tests")
599 {
600 }
601 
~FboApiTestGroup(void)602 FboApiTestGroup::~FboApiTestGroup (void)
603 {
604 }
605 
init(void)606 void 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