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