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