/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 3.0 Module
 * -------------------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Fbo state query tests.
 *//*--------------------------------------------------------------------*/

#include "es3fFboStateQueryTests.hpp"
#include "glsStateQueryUtil.hpp"
#include "es3fApiCase.hpp"
#include "gluRenderContext.hpp"
#include "glwEnums.hpp"
#include "glwFunctions.hpp"
#include "tcuRenderTarget.hpp"
#include "deMath.h"

using namespace glw; // GLint and other GL types
using deqp::gls::StateQueryUtil::StateQueryMemoryWriteGuard;


namespace deqp
{
namespace gles3
{
namespace Functional
{
namespace
{

void checkAttachmentComponentSizeAtLeast (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLenum target, GLenum attachment, int r, int g, int b, int a, int d, int s)
{
	using tcu::TestLog;

	const int referenceSizes[] = {r, g, b, a, d, s};
	const GLenum paramNames[] =
	{
		GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE,	GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE,
		GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE, GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE,
		GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
	};

	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(referenceSizes) == DE_LENGTH_OF_ARRAY(paramNames));

	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(referenceSizes); ++ndx)
	{
		if (referenceSizes[ndx] == -1)
			continue;

		StateQueryMemoryWriteGuard<GLint> state;
		gl.glGetFramebufferAttachmentParameteriv(target, attachment, paramNames[ndx], &state);

		if (!state.verifyValidity(testCtx))
		{
			gl.glGetError(); // just log the error
			continue;
		}

		if (state < referenceSizes[ndx])
		{
			testCtx.getLog() << TestLog::Message << "// ERROR: Expected greater or equal to " << referenceSizes[ndx] << "; got " << state << TestLog::EndMessage;
			if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
				testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value");
		}
	}
}

void checkAttachmentComponentSizeExactly (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLenum target, GLenum attachment, int r, int g, int b, int a, int d, int s)
{
	using tcu::TestLog;

	const int referenceSizes[] = {r, g, b, a, d, s};
	const GLenum paramNames[] =
	{
		GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE,	GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE,
		GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE, GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE,
		GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
	};

	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(referenceSizes) == DE_LENGTH_OF_ARRAY(paramNames));

	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(referenceSizes); ++ndx)
	{
		if (referenceSizes[ndx] == -1)
			continue;

		StateQueryMemoryWriteGuard<GLint> state;
		gl.glGetFramebufferAttachmentParameteriv(target, attachment, paramNames[ndx], &state);

		if (!state.verifyValidity(testCtx))
		{
			gl.glGetError(); // just log the error
			continue;
		}

		if (state != referenceSizes[ndx])
		{
			testCtx.getLog() << TestLog::Message << "// ERROR: Expected " << referenceSizes[ndx] << "; got " << state << TestLog::EndMessage;
			if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
				testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value");
		}
	}
}

void checkIntEquals (tcu::TestContext& testCtx, GLint got, GLint expected)
{
	using tcu::TestLog;

	if (got != expected)
	{
		testCtx.getLog() << TestLog::Message << "// ERROR: Expected " << expected << "; got " << got << TestLog::EndMessage;
		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value");
	}
}

void checkIntEqualsAny (tcu::TestContext& testCtx, GLint got, GLint expected0, GLint expected1)
{
	using tcu::TestLog;

	if (got != expected0 && got != expected1)
	{
		testCtx.getLog() << TestLog::Message << "// ERROR: Expected " << expected0 << " or " << expected1 << "; got " << got << TestLog::EndMessage;
		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value");
	}
}

void checkAttachmentParam(tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLenum target, GLenum attachment, GLenum pname, GLenum reference)
{
	StateQueryMemoryWriteGuard<GLint> state;
	gl.glGetFramebufferAttachmentParameteriv(target, attachment, pname, &state);

	if (state.verifyValidity(testCtx))
		checkIntEquals(testCtx, state, reference);
}

void checkColorAttachmentParam(tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLenum target, GLenum pname, GLenum reference)
{
	checkAttachmentParam(testCtx, gl, target, GL_COLOR_ATTACHMENT0, pname, reference);
}

class DefaultFramebufferCase : public ApiCase
{
public:
	DefaultFramebufferCase (Context& context, const char* name, const char* description, GLenum framebufferTarget)
		: ApiCase				(context, name, description)
		, m_framebufferTarget	(framebufferTarget)
	{
	}

	void test (void)
	{
		const bool		hasColorBuffer =	m_context.getRenderTarget().getPixelFormat().redBits   > 0 ||
											m_context.getRenderTarget().getPixelFormat().greenBits > 0 ||
											m_context.getRenderTarget().getPixelFormat().blueBits  > 0 ||
											m_context.getRenderTarget().getPixelFormat().alphaBits > 0;
		const GLenum	attachments[] =
		{
			GL_BACK,
			GL_DEPTH,
			GL_STENCIL
		};
		const bool		attachmentExists[] =
		{
			hasColorBuffer,
			m_context.getRenderTarget().getDepthBits() > 0,
			m_context.getRenderTarget().getStencilBits() > 0
		};

		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(attachments); ++ndx)
		{
			StateQueryMemoryWriteGuard<GLint> state;
			glGetFramebufferAttachmentParameteriv(m_framebufferTarget, attachments[ndx], GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &state);
			expectError(GL_NO_ERROR);

			if (state.verifyValidity(m_testCtx))
			{
				if (attachmentExists[ndx])
				{
					checkIntEquals(m_testCtx, state, GL_FRAMEBUFFER_DEFAULT);
				}
				else
				{
					// \note [jarkko] FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE "identifes the type of object which contains the attached image". However, it
					// is unclear if an object of type FRAMEBUFFER_DEFAULT can contain a null image (or a 0-bits-per-pixel image). Accept both
					// FRAMEBUFFER_DEFAULT and NONE as valid results in these cases.
					checkIntEqualsAny(m_testCtx, state, GL_FRAMEBUFFER_DEFAULT, GL_NONE);
				}
			}
		}
	}

private:
	GLenum m_framebufferTarget;
};

class AttachmentObjectCase : public ApiCase
{
public:
	AttachmentObjectCase (Context& context, const char* name, const char* description)
		: ApiCase(context, name, description)
	{
	}

	void test (void)
	{
		GLuint framebufferID = 0;
		glGenFramebuffers(1, &framebufferID);
		glBindFramebuffer(GL_FRAMEBUFFER, framebufferID);
		expectError(GL_NO_ERROR);

		// initial
		{
			checkAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_NONE);
			checkAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, 0);
			expectError(GL_NO_ERROR);
		}

		// texture
		{
			GLuint textureID = 0;
			glGenTextures(1, &textureID);
			glBindTexture(GL_TEXTURE_2D, textureID);
			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
			expectError(GL_NO_ERROR);

			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, 0);
			expectError(GL_NO_ERROR);

			checkColorAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_TEXTURE);
			checkColorAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, textureID);

			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
			glDeleteTextures(1, &textureID);
		}

		// rb
		{
			GLuint renderbufferID = 0;
			glGenRenderbuffers(1, &renderbufferID);
			glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID);
			glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8, 128, 128);
			expectError(GL_NO_ERROR);

			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbufferID);
			expectError(GL_NO_ERROR);

			checkColorAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_RENDERBUFFER);
			checkColorAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, renderbufferID);

			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0);
			glDeleteRenderbuffers(1, &renderbufferID);
		}

		glDeleteFramebuffers(1, &framebufferID);
		expectError(GL_NO_ERROR);
	}
};

class AttachmentTextureLevelCase : public ApiCase
{
public:
	AttachmentTextureLevelCase (Context& context, const char* name, const char* description)
		: ApiCase(context, name, description)
	{
	}

	void test (void)
	{
		GLuint framebufferID = 0;
		glGenFramebuffers(1, &framebufferID);
		glBindFramebuffer(GL_FRAMEBUFFER, framebufferID);
		expectError(GL_NO_ERROR);

		for (int mipmapLevel = 0; mipmapLevel < 7; ++mipmapLevel)
		{
			GLuint textureID = 0;
			glGenTextures(1, &textureID);
			glBindTexture(GL_TEXTURE_2D, textureID);
			glTexStorage2D(GL_TEXTURE_2D, 7, GL_RGB8, 128, 128);
			expectError(GL_NO_ERROR);

			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, mipmapLevel);
			expectError(GL_NO_ERROR);

			checkColorAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, mipmapLevel);

			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
			glDeleteTextures(1, &textureID);
		}

		glDeleteFramebuffers(1, &framebufferID);
		expectError(GL_NO_ERROR);
	}
};

class AttachmentTextureCubeMapFaceCase : public ApiCase
{
public:
	AttachmentTextureCubeMapFaceCase (Context& context, const char* name, const char* description)
		: ApiCase(context, name, description)
	{
	}

	void test (void)
	{
		GLuint framebufferID = 0;
		glGenFramebuffers(1, &framebufferID);
		glBindFramebuffer(GL_FRAMEBUFFER, framebufferID);
		expectError(GL_NO_ERROR);

		{
			GLuint textureID = 0;
			glGenTextures(1, &textureID);
			glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);
			expectError(GL_NO_ERROR);

			glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_RGB8, 128, 128);
			expectError(GL_NO_ERROR);

			const GLenum faces[] =
			{
				GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
				GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
				GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
			};

			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(faces); ++ndx)
			{
				glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, faces[ndx], textureID, 0);
				checkColorAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, faces[ndx]);
			}

			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
			glDeleteTextures(1, &textureID);
		}

		glDeleteFramebuffers(1, &framebufferID);
		expectError(GL_NO_ERROR);
	}
};

class AttachmentTextureLayerCase : public ApiCase
{
public:
	AttachmentTextureLayerCase (Context& context, const char* name, const char* description)
		: ApiCase(context, name, description)
	{
	}

	void test (void)
	{
		GLuint framebufferID = 0;
		glGenFramebuffers(1, &framebufferID);
		glBindFramebuffer(GL_FRAMEBUFFER, framebufferID);
		expectError(GL_NO_ERROR);

		// tex3d
		{
			GLuint textureID = 0;
			glGenTextures(1, &textureID);
			glBindTexture(GL_TEXTURE_3D, textureID);
			glTexStorage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 16, 16, 16);

			for (int layer = 0; layer < 16; ++layer)
			{
				glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureID, 0, layer);
				checkColorAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER, layer);
			}

			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
			glDeleteTextures(1, &textureID);
		}
		// tex2d array
		{
			GLuint textureID = 0;
			glGenTextures(1, &textureID);
			glBindTexture(GL_TEXTURE_2D_ARRAY, textureID);
			glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 16, 16, 16);

			for (int layer = 0; layer < 16; ++layer)
			{
				glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureID, 0, layer);
				checkColorAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER, layer);
			}

			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
			glDeleteTextures(1, &textureID);
		}

		glDeleteFramebuffers(1, &framebufferID);
		expectError(GL_NO_ERROR);
	}
};

class AttachmentTextureColorCodingCase : public ApiCase
{
public:
	AttachmentTextureColorCodingCase (Context& context, const char* name, const char* description)
		: ApiCase(context, name, description)
	{
	}

	void test (void)
	{
		GLuint framebufferID = 0;
		glGenFramebuffers(1, &framebufferID);
		glBindFramebuffer(GL_FRAMEBUFFER, framebufferID);
		expectError(GL_NO_ERROR);

		// rgb8 color
		{
			GLuint renderbufferID = 0;
			glGenRenderbuffers(1, &renderbufferID);
			glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID);
			glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8, 128, 128);
			expectError(GL_NO_ERROR);

			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbufferID);
			expectError(GL_NO_ERROR);

			checkColorAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, GL_LINEAR);

			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0);
			glDeleteRenderbuffers(1, &renderbufferID);
		}

		// srgb8_alpha8 color
		{
			GLuint renderbufferID = 0;
			glGenRenderbuffers(1, &renderbufferID);
			glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID);
			glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8_ALPHA8, 128, 128);
			expectError(GL_NO_ERROR);

			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbufferID);
			expectError(GL_NO_ERROR);

			checkColorAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, GL_SRGB);

			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0);
			glDeleteRenderbuffers(1, &renderbufferID);
		}

		// depth
		{
			GLuint renderbufferID = 0;
			glGenRenderbuffers(1, &renderbufferID);
			glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID);
			glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 128, 128);
			expectError(GL_NO_ERROR);

			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbufferID);
			expectError(GL_NO_ERROR);

			checkAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, GL_LINEAR);

			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0);
			glDeleteRenderbuffers(1, &renderbufferID);
		}

		glDeleteFramebuffers(1, &framebufferID);
		expectError(GL_NO_ERROR);
	}
};

class AttachmentTextureComponentTypeCase : public ApiCase
{
public:
	AttachmentTextureComponentTypeCase (Context& context, const char* name, const char* description)
		: ApiCase(context, name, description)
	{
	}

	void test (void)
	{
		GLuint framebufferID = 0;
		glGenFramebuffers(1, &framebufferID);
		glBindFramebuffer(GL_FRAMEBUFFER, framebufferID);
		expectError(GL_NO_ERROR);

		// color-renderable required texture formats
		const struct RequiredColorFormat
		{
			GLenum internalFormat;
			GLenum componentType;
		} requiredColorformats[] =
		{
			{ GL_R8,			GL_UNSIGNED_NORMALIZED	},
			{ GL_RG8,			GL_UNSIGNED_NORMALIZED	},
			{ GL_RGB8,			GL_UNSIGNED_NORMALIZED	},
			{ GL_RGB565,		GL_UNSIGNED_NORMALIZED	},
			{ GL_RGBA4,			GL_UNSIGNED_NORMALIZED	},
			{ GL_RGB5_A1,		GL_UNSIGNED_NORMALIZED	},
			{ GL_RGBA8,			GL_UNSIGNED_NORMALIZED	},
			{ GL_RGB10_A2,		GL_UNSIGNED_NORMALIZED	},
			{ GL_RGB10_A2UI,	GL_UNSIGNED_INT			},
			{ GL_SRGB8_ALPHA8,	GL_UNSIGNED_NORMALIZED	},
			{ GL_R8I,			GL_INT					},
			{ GL_R8UI,			GL_UNSIGNED_INT			},
			{ GL_R16I,			GL_INT					},
			{ GL_R16UI,			GL_UNSIGNED_INT			},
			{ GL_R32I,			GL_INT					},
			{ GL_R32UI,			GL_UNSIGNED_INT			},
			{ GL_RG8I,			GL_INT					},
			{ GL_RG8UI,			GL_UNSIGNED_INT			},
			{ GL_RG16I,			GL_INT					},
			{ GL_RG16UI,		GL_UNSIGNED_INT			},
			{ GL_RG32I,			GL_INT					},
			{ GL_RG32UI,		GL_UNSIGNED_INT			},
			{ GL_RGBA8I,		GL_INT					},
			{ GL_RGBA8UI,		GL_UNSIGNED_INT			},
			{ GL_RGBA16I,		GL_INT					},
			{ GL_RGBA16UI,		GL_UNSIGNED_INT			},
			{ GL_RGBA32I,		GL_INT					},
			{ GL_RGBA32UI,		GL_UNSIGNED_INT			}
		};

		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(requiredColorformats); ++ndx)
		{
			const GLenum colorFormat = requiredColorformats[ndx].internalFormat;

			GLuint textureID = 0;
			glGenTextures(1, &textureID);
			glBindTexture(GL_TEXTURE_2D, textureID);
			glTexStorage2D(GL_TEXTURE_2D, 1, colorFormat, 128, 128);
			expectError(GL_NO_ERROR);

			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, 0);
			expectError(GL_NO_ERROR);

			checkColorAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, requiredColorformats[ndx].componentType);

			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
			glDeleteTextures(1, &textureID);
		}

		glDeleteFramebuffers(1, &framebufferID);
		expectError(GL_NO_ERROR);
	}
};

class AttachmentSizeInitialCase : public ApiCase
{
public:
	AttachmentSizeInitialCase (Context& context, const char* name, const char* description)
		: ApiCase(context, name, description)
	{
	}

	void test (void)
	{
		// check default
		if (attachmentExists(GL_BACK))
		{
			checkAttachmentComponentSizeAtLeast(
				m_testCtx,
				*this,
				GL_FRAMEBUFFER,
				GL_BACK,
				m_context.getRenderTarget().getPixelFormat().redBits,
				m_context.getRenderTarget().getPixelFormat().greenBits,
				m_context.getRenderTarget().getPixelFormat().blueBits,
				m_context.getRenderTarget().getPixelFormat().alphaBits,
				-1,
				-1);
			expectError(GL_NO_ERROR);
		}

		if (attachmentExists(GL_DEPTH))
		{
			checkAttachmentComponentSizeAtLeast(
				m_testCtx,
				*this,
				GL_FRAMEBUFFER,
				GL_DEPTH,
				-1,
				-1,
				-1,
				-1,
				m_context.getRenderTarget().getDepthBits(),
				-1);
			expectError(GL_NO_ERROR);
		}

		if (attachmentExists(GL_STENCIL))
		{
			checkAttachmentComponentSizeAtLeast(
				m_testCtx,
				*this,
				GL_FRAMEBUFFER,
				GL_STENCIL,
				-1,
				-1,
				-1,
				-1,
				-1,
				m_context.getRenderTarget().getStencilBits());
			expectError(GL_NO_ERROR);
		}
	}

	bool attachmentExists (GLenum attachment)
	{
		StateQueryMemoryWriteGuard<GLint> state;
		glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &state);
		expectError(GL_NO_ERROR);

		return !state.isUndefined() && state != GL_NONE;
	}
};

class AttachmentSizeCase : public ApiCase
{
public:
	AttachmentSizeCase (Context& context, const char* name, const char* description)
		: ApiCase(context, name, description)
	{
	}

	virtual void testColorAttachment (GLenum internalFormat, GLenum attachment, GLint bitsR, GLint bitsG, GLint bitsB, GLint bitsA) = DE_NULL;

	virtual void testDepthAttachment (GLenum internalFormat, GLenum attachment, GLint bitsD, GLint bitsS) = DE_NULL;

	void test (void)
	{
		GLuint framebufferID = 0;
		glGenFramebuffers(1, &framebufferID);
		glBindFramebuffer(GL_FRAMEBUFFER, framebufferID);
		expectError(GL_NO_ERROR);

		// check some color targets

		const struct ColorAttachment
		{
			GLenum	internalFormat;
			int		bitsR, bitsG, bitsB, bitsA;
		} colorAttachments[] =
		{
			{ GL_RGBA8,		8,	8,	8,	8 },
			{ GL_RGB565,	5,	6,	5,	0 },
			{ GL_RGBA4,		4,	4,	4,	4 },
			{ GL_RGB5_A1,	5,	5,	5,	1 },
			{ GL_RGBA8I,	8,	8,	8,	8 },
			{ GL_RG32UI,	32,	32,	0,	0 }
		};
		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(colorAttachments); ++ndx)
			testColorAttachment(colorAttachments[ndx].internalFormat, GL_COLOR_ATTACHMENT0, colorAttachments[ndx].bitsR, colorAttachments[ndx].bitsG, colorAttachments[ndx].bitsB, colorAttachments[ndx].bitsA);

		// check some depth targets

		const struct DepthAttachment
		{
			GLenum	internalFormat;
			GLenum	attachment;
			int		dbits;
			int		sbits;
		} depthAttachments[] =
		{
			{ GL_DEPTH_COMPONENT16,		GL_DEPTH_ATTACHMENT,			16, 0 },
			{ GL_DEPTH_COMPONENT24,		GL_DEPTH_ATTACHMENT,			24, 0 },
			{ GL_DEPTH_COMPONENT32F,	GL_DEPTH_ATTACHMENT,			32, 0 },
			{ GL_DEPTH24_STENCIL8,		GL_DEPTH_STENCIL_ATTACHMENT,	24, 8 },
			{ GL_DEPTH32F_STENCIL8,		GL_DEPTH_STENCIL_ATTACHMENT,	32, 8 },
		};
		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthAttachments); ++ndx)
			testDepthAttachment(depthAttachments[ndx].internalFormat, depthAttachments[ndx].attachment, depthAttachments[ndx].dbits, depthAttachments[ndx].sbits);

		glDeleteFramebuffers(1, &framebufferID);
		expectError(GL_NO_ERROR);
	}
};

class AttachmentSizeRboCase : public AttachmentSizeCase
{
public:
	AttachmentSizeRboCase (Context& context, const char* name, const char* description)
		: AttachmentSizeCase(context, name, description)
	{
	}

	void testColorAttachment (GLenum internalFormat, GLenum attachment, GLint bitsR, GLint bitsG, GLint bitsB, GLint bitsA)
	{
		GLuint renderbufferID = 0;
		glGenRenderbuffers(1, &renderbufferID);
		glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID);
		glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, 128, 128);
		expectError(GL_NO_ERROR);

		glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, renderbufferID);
		expectError(GL_NO_ERROR);

		checkAttachmentComponentSizeAtLeast	(m_testCtx, *this, GL_FRAMEBUFFER, attachment, bitsR, bitsG, bitsB, bitsA, -1, -1);
		checkAttachmentComponentSizeExactly	(m_testCtx, *this, GL_FRAMEBUFFER, attachment, -1, -1, -1, -1, 0, 0);

		glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, 0);
		glDeleteRenderbuffers(1, &renderbufferID);
	}

	void testDepthAttachment (GLenum internalFormat, GLenum attachment, GLint bitsD, GLint bitsS)
	{
		GLuint renderbufferID = 0;
		glGenRenderbuffers(1, &renderbufferID);
		glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID);
		glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, 128, 128);
		expectError(GL_NO_ERROR);

		glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, renderbufferID);
		expectError(GL_NO_ERROR);

		checkAttachmentComponentSizeAtLeast	(m_testCtx, *this, GL_FRAMEBUFFER, attachment, -1, -1, -1, -1, bitsD, bitsS);
		checkAttachmentComponentSizeExactly	(m_testCtx, *this, GL_FRAMEBUFFER, attachment, 0, 0, 0, 0, -1, -1);

		glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, 0);
		glDeleteRenderbuffers(1, &renderbufferID);
	}
};

class AttachmentSizeTextureCase : public AttachmentSizeCase
{
public:
	AttachmentSizeTextureCase (Context& context, const char* name, const char* description)
		: AttachmentSizeCase(context, name, description)
	{
	}

	void testColorAttachment (GLenum internalFormat, GLenum attachment, GLint bitsR, GLint bitsG, GLint bitsB, GLint bitsA)
	{
		GLuint textureID = 0;
		glGenTextures(1, &textureID);
		glBindTexture(GL_TEXTURE_2D, textureID);
		glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, 128, 128);
		expectError(GL_NO_ERROR);

		glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, textureID, 0);
		expectError(GL_NO_ERROR);

		checkAttachmentComponentSizeAtLeast	(m_testCtx, *this, GL_FRAMEBUFFER, attachment, bitsR, bitsG, bitsB, bitsA, -1, -1);
		checkAttachmentComponentSizeExactly	(m_testCtx, *this, GL_FRAMEBUFFER, attachment, -1, -1, -1, -1, 0, 0);

		glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, 0, 0);
		glDeleteTextures(1, &textureID);
	}

	void testDepthAttachment (GLenum internalFormat, GLenum attachment, GLint bitsD, GLint bitsS)
	{
		// don't test stencil formats with textures
		if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
			return;

		GLuint textureID = 0;
		glGenTextures(1, &textureID);
		glBindTexture(GL_TEXTURE_2D, textureID);
		glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, 128, 128);
		expectError(GL_NO_ERROR);

		glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, textureID, 0);
		expectError(GL_NO_ERROR);

		checkAttachmentComponentSizeAtLeast	(m_testCtx, *this, GL_FRAMEBUFFER, attachment, -1, -1, -1, -1, bitsD, bitsS);
		checkAttachmentComponentSizeExactly	(m_testCtx, *this, GL_FRAMEBUFFER, attachment, 0, 0, 0, 0, -1, -1);

		glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, 0, 0);
		glDeleteTextures(1, &textureID);
	}
};

class UnspecifiedAttachmentTextureColorCodingCase : public ApiCase
{
public:
	UnspecifiedAttachmentTextureColorCodingCase (Context& context, const char* name, const char* description)
		: ApiCase(context, name, description)
	{
	}

	void test (void)
	{
		GLuint framebufferID = 0;
		glGenFramebuffers(1, &framebufferID);
		glBindFramebuffer(GL_FRAMEBUFFER, framebufferID);
		expectError(GL_NO_ERROR);

		// color
		{
			GLuint renderbufferID = 0;
			glGenRenderbuffers(1, &renderbufferID);
			glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID);
			expectError(GL_NO_ERROR);

			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbufferID);
			expectError(GL_NO_ERROR);

			checkColorAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, GL_LINEAR);
			expectError(GL_NO_ERROR);

			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0);
			glDeleteRenderbuffers(1, &renderbufferID);
		}

		// depth
		{
			GLuint renderbufferID = 0;
			glGenRenderbuffers(1, &renderbufferID);
			glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID);
			expectError(GL_NO_ERROR);

			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbufferID);
			expectError(GL_NO_ERROR);

			checkAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, GL_LINEAR);

			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0);
			glDeleteRenderbuffers(1, &renderbufferID);
		}

		glDeleteFramebuffers(1, &framebufferID);
		expectError(GL_NO_ERROR);
	}
};

class UnspecifiedAttachmentTextureComponentTypeCase : public ApiCase
{
public:
	UnspecifiedAttachmentTextureComponentTypeCase (Context& context, const char* name, const char* description)
		: ApiCase(context, name, description)
	{
	}

	void test (void)
	{
		GLuint framebufferID = 0;
		glGenFramebuffers(1, &framebufferID);
		glBindFramebuffer(GL_FRAMEBUFFER, framebufferID);
		expectError(GL_NO_ERROR);

		{
			GLuint textureID = 0;
			glGenTextures(1, &textureID);
			glBindTexture(GL_TEXTURE_2D, textureID);
			expectError(GL_NO_ERROR);

			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, 0);
			expectError(GL_NO_ERROR);

			checkColorAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, GL_NONE);
			expectError(GL_NO_ERROR);

			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
			glDeleteTextures(1, &textureID);
		}

		glDeleteFramebuffers(1, &framebufferID);
		expectError(GL_NO_ERROR);
	}
};

class UnspecifiedAttachmentSizeCase : public ApiCase
{
public:
	UnspecifiedAttachmentSizeCase (Context& context, const char* name, const char* description)
		: ApiCase(context, name, description)
	{
	}

	virtual void testColorAttachment (void) = DE_NULL;

	virtual void testDepthAttachment (void) = DE_NULL;

	void test (void)
	{
		GLuint framebufferID = 0;
		glGenFramebuffers(1, &framebufferID);
		glBindFramebuffer(GL_FRAMEBUFFER, framebufferID);
		expectError(GL_NO_ERROR);

		// check color target
		testColorAttachment();

		// check depth target
		testDepthAttachment();

		glDeleteFramebuffers(1, &framebufferID);
		expectError(GL_NO_ERROR);
	}
};

class UnspecifiedAttachmentSizeRboCase : public UnspecifiedAttachmentSizeCase
{
public:
	UnspecifiedAttachmentSizeRboCase (Context& context, const char* name, const char* description)
		: UnspecifiedAttachmentSizeCase(context, name, description)
	{
	}

	void testColorAttachment (void)
	{
		GLuint renderbufferID = 0;
		glGenRenderbuffers(1, &renderbufferID);
		glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID);
		expectError(GL_NO_ERROR);

		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbufferID);
		expectError(GL_NO_ERROR);

		checkAttachmentComponentSizeExactly	(m_testCtx, *this, GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0, 0, 0, 0);
		expectError(GL_NO_ERROR);

		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0);
		glDeleteRenderbuffers(1, &renderbufferID);
	}

	void testDepthAttachment (void)
	{
		GLuint renderbufferID = 0;
		glGenRenderbuffers(1, &renderbufferID);
		glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID);
		expectError(GL_NO_ERROR);

		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbufferID);
		expectError(GL_NO_ERROR);

		checkAttachmentComponentSizeExactly	(m_testCtx, *this, GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 0, 0, 0, 0, 0, 0);
		expectError(GL_NO_ERROR);

		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
		glDeleteRenderbuffers(1, &renderbufferID);
	}
};

class UnspecifiedAttachmentSizeTextureCase : public UnspecifiedAttachmentSizeCase
{
public:
	UnspecifiedAttachmentSizeTextureCase (Context& context, const char* name, const char* description)
		: UnspecifiedAttachmentSizeCase(context, name, description)
	{
	}

	void testColorAttachment (void)
	{
		GLuint textureID = 0;
		glGenTextures(1, &textureID);
		glBindTexture(GL_TEXTURE_2D, textureID);
		expectError(GL_NO_ERROR);

		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, 0);
		expectError(GL_NO_ERROR);

		checkAttachmentComponentSizeExactly	(m_testCtx, *this, GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0, 0, 0, 0);
		expectError(GL_NO_ERROR);

		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
		glDeleteTextures(1, &textureID);
	}

	void testDepthAttachment (void)
	{
		GLuint textureID = 0;
		glGenTextures(1, &textureID);
		glBindTexture(GL_TEXTURE_2D, textureID);
		expectError(GL_NO_ERROR);

		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, textureID, 0);
		expectError(GL_NO_ERROR);

		checkAttachmentComponentSizeExactly	(m_testCtx, *this, GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 0, 0, 0, 0, 0, 0);
		expectError(GL_NO_ERROR);

		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
		glDeleteTextures(1, &textureID);
	}
};

} // anonymous


FboStateQueryTests::FboStateQueryTests (Context& context)
	: TestCaseGroup(context, "fbo", "Fbo State Query tests")
{
}

void FboStateQueryTests::init (void)
{
	const struct FramebufferTarget
	{
		const char*	name;
		GLenum		target;
	} fboTargets[] =
	{
		{ "draw_framebuffer_", GL_DRAW_FRAMEBUFFER },
		{ "read_framebuffer_", GL_READ_FRAMEBUFFER }
	};

	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(fboTargets); ++ndx)
		addChild(new DefaultFramebufferCase(m_context, (std::string(fboTargets[ndx].name) + "default_framebuffer").c_str(), "default framebuffer", fboTargets[ndx].target));

	addChild(new AttachmentObjectCase							(m_context, "framebuffer_attachment_object",							"FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE and FRAMEBUFFER_ATTACHMENT_OBJECT_NAME"));
	addChild(new AttachmentTextureLevelCase						(m_context, "framebuffer_attachment_texture_level",						"FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL"));
	addChild(new AttachmentTextureCubeMapFaceCase				(m_context, "framebuffer_attachment_texture_cube_map_face",				"FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE"));
	addChild(new AttachmentTextureLayerCase						(m_context, "framebuffer_attachment_texture_layer",						"FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER"));
	addChild(new AttachmentTextureColorCodingCase				(m_context, "framebuffer_attachment_color_encoding",					"FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING"));
	addChild(new AttachmentTextureComponentTypeCase				(m_context, "framebuffer_attachment_component_type",					"FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE"));
	addChild(new AttachmentSizeInitialCase						(m_context, "framebuffer_attachment_x_size_initial",					"FRAMEBUFFER_ATTACHMENT_x_SIZE"));
	addChild(new AttachmentSizeRboCase							(m_context, "framebuffer_attachment_x_size_rbo",						"FRAMEBUFFER_ATTACHMENT_x_SIZE"));
	addChild(new AttachmentSizeTextureCase						(m_context, "framebuffer_attachment_x_size_texture",					"FRAMEBUFFER_ATTACHMENT_x_SIZE"));

	addChild(new UnspecifiedAttachmentTextureColorCodingCase	(m_context, "framebuffer_unspecified_attachment_color_encoding",		"FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING"));
	addChild(new UnspecifiedAttachmentTextureComponentTypeCase	(m_context, "framebuffer_unspecified_attachment_component_type",		"FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE"));
	addChild(new UnspecifiedAttachmentSizeRboCase				(m_context, "framebuffer_unspecified_attachment_x_size_rbo",			"FRAMEBUFFER_ATTACHMENT_x_SIZE"));
	addChild(new UnspecifiedAttachmentSizeTextureCase			(m_context, "framebuffer_unspecified_attachment_x_size_texture",		"FRAMEBUFFER_ATTACHMENT_x_SIZE"));
}

} // Functional
} // gles3
} // deqp
