/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 3.1 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 Base class for FBO tests.
 *//*--------------------------------------------------------------------*/

#include "es31fFboTestCase.hpp"
#include "es31fFboTestUtil.hpp"
#include "tcuTestLog.hpp"
#include "tcuImageCompare.hpp"
#include "tcuRenderTarget.hpp"
#include "sglrGLContext.hpp"
#include "sglrReferenceContext.hpp"
#include "gluStrUtil.hpp"
#include "gluContextInfo.hpp"
#include "deRandom.hpp"
#include "glwEnums.hpp"
#include "glwFunctions.hpp"

#include <algorithm>

namespace deqp
{
namespace gles31
{
namespace Functional
{

using tcu::TestLog;
using std::string;

FboTestCase::FboTestCase (Context& context, const char* name, const char* description, bool useScreenSizedViewport)
	: TestCase			(context, name, description)
	, m_viewportWidth	(useScreenSizedViewport ? context.getRenderTarget().getWidth() : 128)
	, m_viewportHeight	(useScreenSizedViewport ? context.getRenderTarget().getHeight() : 128)
{
}

FboTestCase::~FboTestCase (void)
{
}

FboTestCase::IterateResult FboTestCase::iterate (void)
{
	glu::RenderContext&			renderCtx		= TestCase::m_context.getRenderContext();
	const tcu::RenderTarget&	renderTarget	= renderCtx.getRenderTarget();
	TestLog&					log				= m_testCtx.getLog();

	// Viewport.
	de::Random					rnd				(deStringHash(getName()));
	int							width			= deMin32(renderTarget.getWidth(),	m_viewportWidth);
	int							height			= deMin32(renderTarget.getHeight(),	m_viewportHeight);
	int							x				= rnd.getInt(0, renderTarget.getWidth()		- width);
	int							y				= rnd.getInt(0, renderTarget.getHeight()	- height);

	// Surface format and storage is choosen by render().
	tcu::Surface				reference;
	tcu::Surface				result;

	// Call preCheck() that can throw exception if some requirement is not met.
	preCheck();

	log << TestLog::Message << "Rendering with GL driver" << TestLog::EndMessage;

	// Render using GLES3.1
	try
	{
		sglr::GLContext context(renderCtx, log, 0, tcu::IVec4(x, y, width, height));
		setContext(&context);
		render(result);

		// Check error.
		deUint32 err = glGetError();
		if (err != GL_NO_ERROR)
			throw glu::Error(err, glu::getErrorStr(err).toString().c_str(), DE_NULL, __FILE__, __LINE__);

		setContext(DE_NULL);
	}
	catch (const FboTestUtil::FboIncompleteException& e)
	{
		if (e.getReason() == GL_FRAMEBUFFER_UNSUPPORTED)
		{
			log << e;
			m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
			return STOP;
		}
		else
			throw;
	}

	log << TestLog::Message << "Rendering reference image" << TestLog::EndMessage;

	// Render reference.
	{
		sglr::ReferenceContextBuffers	buffers	(tcu::PixelFormat(8,8,8,renderTarget.getPixelFormat().alphaBits?8:0), renderTarget.getDepthBits(), renderTarget.getStencilBits(), width, height);
		sglr::ReferenceContext			context	(sglr::ReferenceContextLimits(renderCtx), buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer());

		setContext(&context);
		render(reference);
		setContext(DE_NULL);
	}

	bool isOk = compare(reference, result);
	m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
							isOk ? "Pass"				: "Image comparison failed");
	return STOP;
}

bool FboTestCase::compare (const tcu::Surface& reference, const tcu::Surface& result)
{
	return tcu::fuzzyCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference, result, 0.05f, tcu::COMPARE_LOG_RESULT);
}

void FboTestCase::readPixels (tcu::Surface& dst, int x, int y, int width, int height, const tcu::TextureFormat& format, const tcu::Vec4& scale, const tcu::Vec4& bias)
{
	FboTestUtil::readPixels(*getCurrentContext(), dst, x, y, width, height, format, scale, bias);
}

void FboTestCase::readPixels (tcu::Surface& dst, int x, int y, int width, int height)
{
	getCurrentContext()->readPixels(dst, x, y, width, height);
}

void FboTestCase::checkFramebufferStatus (deUint32 target)
{
	deUint32 status = glCheckFramebufferStatus(target);
	if (status != GL_FRAMEBUFFER_COMPLETE)
		throw FboTestUtil::FboIncompleteException(status, __FILE__, __LINE__);
}

void FboTestCase::checkError (void)
{
	deUint32 err = glGetError();
	if (err != GL_NO_ERROR)
		throw glu::Error((int)err, (string("Got ") + glu::getErrorStr(err).toString()).c_str(), DE_NULL, __FILE__, __LINE__);
}

static bool isRequiredFormat (deUint32 format, glu::RenderContext& renderContext)
{
	const bool supportsES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));
	switch (format)
	{
		// Color-renderable formats
		case GL_RGBA32I:
		case GL_RGBA32UI:
		case GL_RGBA16I:
		case GL_RGBA16UI:
		case GL_RGBA8:
		case GL_RGBA8I:
		case GL_RGBA8UI:
		case GL_SRGB8_ALPHA8:
		case GL_RGB10_A2:
		case GL_RGB10_A2UI:
		case GL_RGBA4:
		case GL_RGB5_A1:
		case GL_RGB8:
		case GL_RGB565:
		case GL_RG32I:
		case GL_RG32UI:
		case GL_RG16I:
		case GL_RG16UI:
		case GL_RG8:
		case GL_RG8I:
		case GL_RG8UI:
		case GL_R32I:
		case GL_R32UI:
		case GL_R16I:
		case GL_R16UI:
		case GL_R8:
		case GL_R8I:
		case GL_R8UI:
			return true;

		// Depth formats
		case GL_DEPTH_COMPONENT32F:
		case GL_DEPTH_COMPONENT24:
		case GL_DEPTH_COMPONENT16:
			return true;

		// Depth+stencil formats
		case GL_DEPTH32F_STENCIL8:
		case GL_DEPTH24_STENCIL8:
			return true;

		// Stencil formats
		case GL_STENCIL_INDEX8:
			return true;

		// Float format
		case GL_RGBA32F:
		case GL_R11F_G11F_B10F:
		case GL_RG32F:
		case GL_R32F:
		case GL_RGBA16F:
		case GL_RG16F:
		case GL_R16F:
			return supportsES32;

		default:
			return false;
	}
}

static std::vector<std::string> getEnablingExtensions (deUint32 format, glu::RenderContext& renderContext)
{
	const bool					supportsES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));
	std::vector<std::string>	out;

	DE_ASSERT(!isRequiredFormat(format, renderContext));

	switch (format)
	{
		case GL_RGB16F:
			out.push_back("GL_EXT_color_buffer_half_float");
			break;

		case GL_RGB32F:
			out.push_back("GL_EXT_color_buffer_float");
			break;

		case GL_RGBA16F:
		case GL_RG16F:
		case GL_R16F:
			if (!supportsES32)
				out.push_back("GL_EXT_color_buffer_half_float");
			break;

		case GL_RGBA32F:
		case GL_R11F_G11F_B10F:
		case GL_RG32F:
		case GL_R32F:
			if (!supportsES32)
				out.push_back("GL_EXT_color_buffer_float");
			break;

		case GL_R16:
		case GL_RG16:
		case GL_RGBA16:
			out.push_back("GL_EXT_texture_norm16");
			break;

		default:
			break;
	}

	return out;
}

static bool isAnyExtensionSupported (Context& context, const std::vector<std::string>& requiredExts)
{
	for (std::vector<std::string>::const_iterator iter = requiredExts.begin(); iter != requiredExts.end(); iter++)
	{
		const std::string& extension = *iter;

		if (context.getContextInfo().isExtensionSupported(extension.c_str()))
			return true;
	}

	return false;
}

void FboTestCase::checkFormatSupport (deUint32 sizedFormat)
{
	const bool						isCoreFormat	= isRequiredFormat(sizedFormat, m_context.getRenderContext());
	const std::vector<std::string>	requiredExts	= (!isCoreFormat) ? getEnablingExtensions(sizedFormat, m_context.getRenderContext()) : std::vector<std::string>();

	// Check that we don't try to use invalid formats.
	DE_ASSERT(isCoreFormat || !requiredExts.empty());

	if (!requiredExts.empty() && !isAnyExtensionSupported(m_context, requiredExts))
		throw tcu::NotSupportedError("Format not supported");
}

static int getMinimumSampleCount (deUint32 format)
{
	switch (format)
	{
		// Core formats
		case GL_RGBA32I:
		case GL_RGBA32UI:
		case GL_RGBA16I:
		case GL_RGBA16UI:
		case GL_RGBA8:
		case GL_RGBA8I:
		case GL_RGBA8UI:
		case GL_SRGB8_ALPHA8:
		case GL_RGB10_A2:
		case GL_RGB10_A2UI:
		case GL_RGBA4:
		case GL_RGB5_A1:
		case GL_RGB8:
		case GL_RGB565:
		case GL_RG32I:
		case GL_RG32UI:
		case GL_RG16I:
		case GL_RG16UI:
		case GL_RG8:
		case GL_RG8I:
		case GL_RG8UI:
		case GL_R32I:
		case GL_R32UI:
		case GL_R16I:
		case GL_R16UI:
		case GL_R8:
		case GL_R8I:
		case GL_R8UI:
		case GL_DEPTH_COMPONENT32F:
		case GL_DEPTH_COMPONENT24:
		case GL_DEPTH_COMPONENT16:
		case GL_DEPTH32F_STENCIL8:
		case GL_DEPTH24_STENCIL8:
		case GL_STENCIL_INDEX8:
			return 4;

		// GL_EXT_color_buffer_float
		case GL_R11F_G11F_B10F:
		case GL_RG16F:
		case GL_R16F:
			return 4;

		case GL_RGBA32F:
		case GL_RGBA16F:
		case GL_RG32F:
		case GL_R32F:
			return 0;

		// GL_EXT_color_buffer_half_float
		case GL_RGB16F:
			return 0;

		default:
			DE_FATAL("Unknown format");
			return 0;
	}
}

static std::vector<int> querySampleCounts (const glw::Functions& gl, deUint32 format)
{
	int					numSampleCounts		= 0;
	std::vector<int>	sampleCounts;

	gl.getInternalformativ(GL_RENDERBUFFER, format, GL_NUM_SAMPLE_COUNTS, 1, &numSampleCounts);

	if (numSampleCounts > 0)
	{
		sampleCounts.resize(numSampleCounts);
		gl.getInternalformativ(GL_RENDERBUFFER, format, GL_SAMPLES, (glw::GLsizei)sampleCounts.size(), &sampleCounts[0]);
	}

	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to query sample counts for format");

	return sampleCounts;
}

void FboTestCase::checkSampleCount (deUint32 sizedFormat, int numSamples)
{
	const int minSampleCount = getMinimumSampleCount(sizedFormat);

	if (numSamples > minSampleCount)
	{
		// Exceeds spec-mandated minimum - need to check.
		const std::vector<int> supportedSampleCounts = querySampleCounts(m_context.getRenderContext().getFunctions(), sizedFormat);

		if (std::find(supportedSampleCounts.begin(), supportedSampleCounts.end(), numSamples) == supportedSampleCounts.end())
			throw tcu::NotSupportedError("Sample count not supported");
	}
}

void FboTestCase::clearColorBuffer (const tcu::TextureFormat& format, const tcu::Vec4& value)
{
	FboTestUtil::clearColorBuffer(*getCurrentContext(), format, value);
}

} // Functional
} // gles31
} // deqp
