/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 2.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 "es2fFboStateQueryTests.hpp"
#include "glsStateQueryUtil.hpp"
#include "es2fApiCase.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 gles2
{
namespace Functional
{
namespace
{

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 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 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);

		// texture
		{
			GLuint textureID = 0;
			glGenTextures(1, &textureID);
			glBindTexture(GL_TEXTURE_2D, textureID);
			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 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_RGBA4, 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);

		// GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL can only be 0
		{
			GLuint textureID = 0;

			glGenTextures(1, &textureID);
			glBindTexture(GL_TEXTURE_2D, textureID);
			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 64, 64, 0, GL_RGB, 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_TEXTURE_LEVEL, 0);

			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);

			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)
				glTexImage2D(faces[ndx], 0, GL_RGB, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE, DE_NULL);
			expectError(GL_NO_ERROR);

			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);
	}
};

} // anonymous


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

void FboStateQueryTests::init (void)
{
	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"));
}

} // Functional
} // gles2
} // deqp
