/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL (ES) 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 State change performance tests.
 *//*--------------------------------------------------------------------*/

#include "glsStateChangePerfTestCases.hpp"

#include "tcuTestLog.hpp"

#include "gluDefs.hpp"
#include "gluRenderContext.hpp"
#include "gluShaderProgram.hpp"

#include "glwFunctions.hpp"
#include "glwEnums.hpp"

#include "deStringUtil.hpp"

#include "deClock.h"

#include <vector>
#include <algorithm>

using std::vector;
using std::string;
using tcu::TestLog;
using namespace glw;

namespace deqp
{
namespace gls
{

namespace
{

struct ResultStats
{
	double		median;
	double		mean;
	double		variance;

	deUint64	min;
	deUint64	max;
};

ResultStats calculateStats (const vector<deUint64>& values)
{
	ResultStats result = { 0.0, 0.0, 0.0, 0xFFFFFFFFFFFFFFFFu, 0 };

	deUint64 sum = 0;

	for (int i = 0; i < (int)values.size(); i++)
		sum += values[i];

	result.mean = ((double)sum) / (double)values.size();

	for (int i = 0; i < (int)values.size(); i++)
	{
		const double val = (double)values[i];
		result.variance += (val - result.mean) * (val - result.mean);
	}

	result.variance /= (double)values.size();

	{
		const int n = (int)(values.size()/2);

		vector<deUint64> sortedValues = values;

		std::sort(sortedValues.begin(), sortedValues.end());

		result.median = (double)sortedValues[n];
	}

	for (int i = 0; i < (int)values.size(); i++)
	{
		result.min = std::min(result.min, values[i]);
		result.max = std::max(result.max, values[i]);
	}

	return result;
}


void genIndices (vector<GLushort>& indices, int triangleCount)
{
	indices.reserve(triangleCount*3);

	for (int triangleNdx = 0; triangleNdx < triangleCount; triangleNdx++)
	{
		indices.push_back((GLushort)(triangleNdx*3));
		indices.push_back((GLushort)(triangleNdx*3+1));
		indices.push_back((GLushort)(triangleNdx*3+2));
	}
}

void genCoords (vector<GLfloat>& coords, int triangleCount)
{
	coords.reserve(triangleCount * 3 * 2);

	for (int triangleNdx = 0; triangleNdx < triangleCount; triangleNdx++)
	{
		if ((triangleNdx % 2) == 0)
		{
			// CW
			coords.push_back(-1.0f);
			coords.push_back(-1.0f);

			coords.push_back( 1.0f);
			coords.push_back(-1.0f);

			coords.push_back( 1.0f);
			coords.push_back( 1.0f);
		}
		else
		{
			// CCW
			coords.push_back(-1.0f);
			coords.push_back(-1.0f);

			coords.push_back(-1.0f);
			coords.push_back( 1.0f);

			coords.push_back( 1.0f);
			coords.push_back( 1.0f);
		}
	}
}

void genTextureData (vector<deUint8>& data, int width, int height)
{
	data.clear();
	data.reserve(width*height*4);

	for (int x = 0; x < width; x++)
	{
		for (int y = 0; y < height; y++)
		{
			data.push_back((deUint8)((255*x)/width));
			data.push_back((deUint8)((255*y)/width));
			data.push_back((deUint8)((255*x*y)/(width*height)));
			data.push_back(255);
		}
	}
}

double calculateVariance (const vector<deUint64>& values, double avg)
{
	double sum = 0.0;

	for (int valueNdx = 0; valueNdx < (int)values.size(); valueNdx++)
	{
		double value = (double)values[valueNdx];
		sum += (value - avg) * (value - avg);
	}

	return sum / (double)values.size();
}

deUint64 findMin (const vector<deUint64>& values)
{
	deUint64 min = ~0ull;

	for (int valueNdx = 0; valueNdx < (int)values.size(); valueNdx++)
		min = std::min(values[valueNdx], min);

	return min;
}

deUint64 findMax (const vector<deUint64>& values)
{
	deUint64 max = 0;

	for (int valueNdx = 0; valueNdx < (int)values.size(); valueNdx++)
		max = std::max(values[valueNdx], max);

	return max;
}

deUint64 findMedian (const vector<deUint64>& v)
{
	vector<deUint64> values = v;
	size_t n = values.size() / 2;

	std::nth_element(values.begin(), values.begin() + n, values.end());

	return values[n];
}

} // anonymous

StateChangePerformanceCase::StateChangePerformanceCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description, DrawType drawType, int drawCallCount, int triangleCount)
	: tcu::TestCase		(testCtx, tcu::NODETYPE_PERFORMANCE, name, description)
	, m_renderCtx		(renderCtx)
	, m_drawType		(drawType)
	, m_iterationCount	(100)
	, m_callCount		(drawCallCount)
	, m_triangleCount	(triangleCount)
{
}

StateChangePerformanceCase::~StateChangePerformanceCase (void)
{
	StateChangePerformanceCase::deinit();
}

void StateChangePerformanceCase::init (void)
{
	if (m_drawType == DRAWTYPE_INDEXED_USER_PTR)
		genIndices(m_indices, m_triangleCount);
}

void StateChangePerformanceCase::requireIndexBuffers (int count)
{
	const glw::Functions& gl = m_renderCtx.getFunctions();

	if ((int)m_indexBuffers.size() >= count)
		return;

	m_indexBuffers.reserve(count);

	vector<GLushort> indices;
	genIndices(indices, m_triangleCount);

	while ((int)m_indexBuffers.size() < count)
	{
		GLuint buffer;

		gl.genBuffers(1, &buffer);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers()");

		gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer()");
		gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(indices.size() * sizeof(GLushort)), &(indices[0]), GL_STATIC_DRAW);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData()");
		gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer()");

		m_indexBuffers.push_back(buffer);
	}
}

void StateChangePerformanceCase::requireCoordBuffers (int count)
{
	const glw::Functions& gl = m_renderCtx.getFunctions();

	if ((int)m_coordBuffers.size() >= count)
		return;

	m_coordBuffers.reserve(count);

	vector<GLfloat> coords;
	genCoords(coords, m_triangleCount);

	while ((int)m_coordBuffers.size() < count)
	{
		GLuint buffer;

		gl.genBuffers(1, &buffer);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers()");

		gl.bindBuffer(GL_ARRAY_BUFFER, buffer);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer()");
		gl.bufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(GLfloat)), &(coords[0]), GL_STATIC_DRAW);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData()");
		gl.bindBuffer(GL_ARRAY_BUFFER, 0);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer()");

		m_coordBuffers.push_back(buffer);
	}
}

void StateChangePerformanceCase::requirePrograms (int count)
{
	if ((int)m_programs.size() >= count)
		return;

	m_programs.reserve(count);

	while ((int)m_programs.size() < count)
	{
		string vertexShaderSource =
			"attribute mediump vec2 a_coord;\n"
			"varying mediump vec2 v_texCoord;\n"
			"void main (void)\n"
			"{\n"
			"\tv_texCoord = vec2(0.5) + 0.5" + de::toString(m_programs.size()) + " * a_coord.xy;\n"
			"\tgl_Position = vec4(a_coord, 0.5, 1.0);\n"
			"}";

		string fragmentShaderSource =
			"uniform sampler2D u_sampler;\n"
			"varying mediump vec2 v_texCoord;\n"
			"void main (void)\n"
			"{\n"
			"\tgl_FragColor = vec4(1.0" + de::toString(m_programs.size()) + " * texture2D(u_sampler, v_texCoord).xyz, 1.0);\n"
			"}";

		glu::ShaderProgram* program = new glu::ShaderProgram(m_renderCtx, glu::ProgramSources() << glu::VertexSource(vertexShaderSource) << glu::FragmentSource(fragmentShaderSource));

		if (!program->isOk())
		{
			m_testCtx.getLog() << *program;
			delete program;
			TCU_FAIL("Compile failed");
		}

		m_programs.push_back(program);
	}
}

void StateChangePerformanceCase::requireTextures (int count)
{
	const glw::Functions& gl = m_renderCtx.getFunctions();

	const int textureWidth	= 64;
	const int textureHeight	= 64;

	if ((int)m_textures.size() >= count)
		return;

	m_textures.reserve(count);

	vector<deUint8> textureData;
	genTextureData(textureData, textureWidth, textureHeight);

	DE_ASSERT(textureData.size() == textureWidth * textureHeight * 4);

	while ((int)m_textures.size() < count)
	{
		GLuint texture;

		gl.genTextures(1, &texture);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures()");

		gl.bindTexture(GL_TEXTURE_2D, texture);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture()");

		gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, &(textureData[0]));
		GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage2D()");

		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,	GL_NEAREST);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri()");
		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,	GL_NEAREST);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri()");
		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,		GL_REPEAT);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri()");
		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,		GL_REPEAT);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri()");

		gl.bindTexture(GL_TEXTURE_2D, 0);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture()");

		m_textures.push_back(texture);
	}
}

void StateChangePerformanceCase::requireFramebuffers (int count)
{
	const glw::Functions& gl = m_renderCtx.getFunctions();

	if ((int)m_framebuffers.size() >= count)
		return;

	m_framebuffers.reserve(count);

	requireRenderbuffers(count);

	while ((int)m_framebuffers.size() < count)
	{
		GLuint framebuffer;

		gl.genFramebuffers(1, &framebuffer);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers()");

		gl.bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer()");

		gl.bindRenderbuffer(GL_RENDERBUFFER, m_renderbuffers[m_framebuffers.size()]);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer()");

		gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_renderbuffers[m_framebuffers.size()]);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer()");

		gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer()");

		gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer()");

		m_framebuffers.push_back(framebuffer);
	}
}

void StateChangePerformanceCase::requireRenderbuffers (int count)
{
	const glw::Functions& gl = m_renderCtx.getFunctions();

	if ((int)m_renderbuffers.size() >= count)
		return;

	m_renderbuffers.reserve(count);

	while ((int)m_renderbuffers.size() < count)
	{
		GLuint renderbuffer;

		gl.genRenderbuffers(1, &renderbuffer);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers()");

		gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer()");

		gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGB565, 24, 24);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage()");

		gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer()");

		m_renderbuffers.push_back(renderbuffer);
	}
}

void StateChangePerformanceCase::requireSamplers (int count)
{
	const glw::Functions& gl = m_renderCtx.getFunctions();

	if ((int)m_samplers.size() >= count)
		return;

	m_samplers.reserve(count);

	while ((int)m_samplers.size() < count)
	{
		GLuint sampler;
		gl.genSamplers(1, &sampler);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenSamplers()");
		m_samplers.push_back(sampler);
	}
}

void StateChangePerformanceCase::requireVertexArrays (int count)
{
	const glw::Functions& gl = m_renderCtx.getFunctions();

	if ((int)m_vertexArrays.size() >= count)
		return;

	m_vertexArrays.reserve(count);

	while ((int)m_vertexArrays.size() < count)
	{
		GLuint vertexArray;
		gl.genVertexArrays(1, &vertexArray);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays()");
		m_vertexArrays.push_back(vertexArray);
	}
}

void StateChangePerformanceCase::deinit (void)
{
	m_indices.clear();
	m_interleavedResults.clear();
	m_batchedResults.clear();

	{
		const glw::Functions& gl = m_renderCtx.getFunctions();

		if (!m_indexBuffers.empty())
		{
			gl.deleteBuffers((GLsizei)m_indexBuffers.size(), &(m_indexBuffers[0]));
			m_indexBuffers.clear();
		}

		if (!m_coordBuffers.empty())
		{
			gl.deleteBuffers((GLsizei)m_coordBuffers.size(), &(m_coordBuffers[0]));
			m_coordBuffers.clear();
		}

		if (!m_textures.empty())
		{
			gl.deleteTextures((GLsizei)m_textures.size(), &(m_textures[0]));
			m_textures.clear();
		}

		if (!m_framebuffers.empty())
		{
			gl.deleteFramebuffers((GLsizei)m_framebuffers.size(), &(m_framebuffers[0]));
			m_framebuffers.clear();
		}

		if (!m_renderbuffers.empty())
		{
			gl.deleteRenderbuffers((GLsizei)m_renderbuffers.size(), &(m_renderbuffers[0]));
			m_renderbuffers.clear();
		}

		if (!m_samplers.empty())
		{
			gl.deleteSamplers((GLsizei)m_samplers.size(), &m_samplers[0]);
			m_samplers.clear();
		}

		if (!m_vertexArrays.empty())
		{
			gl.deleteVertexArrays((GLsizei)m_vertexArrays.size(), &m_vertexArrays[0]);
			m_vertexArrays.clear();
		}

		for (int programNdx = 0; programNdx < (int)m_programs.size(); programNdx++)
		{
			delete m_programs[programNdx];
			m_programs[programNdx] = NULL;
		}
		m_programs.clear();
	}
}

void StateChangePerformanceCase::logAndSetTestResult (void)
{
	TestLog&	log			= m_testCtx.getLog();

	ResultStats interleaved	= calculateStats(m_interleavedResults);
	ResultStats batched		= calculateStats(m_batchedResults);

	log << TestLog::Message << "Interleaved mean: "					<< interleaved.mean						<< TestLog::EndMessage;
	log << TestLog::Message << "Interleaved median: "				<< interleaved.median					<< TestLog::EndMessage;
	log << TestLog::Message << "Interleaved variance: "				<< interleaved.variance					<< TestLog::EndMessage;
	log << TestLog::Message << "Interleaved min: "					<< interleaved.min						<< TestLog::EndMessage;
	log << TestLog::Message << "Interleaved max: "					<< interleaved.max						<< TestLog::EndMessage;

	log << TestLog::Message << "Batched mean: "						<< batched.mean							<< TestLog::EndMessage;
	log << TestLog::Message << "Batched median: "					<< batched.median						<< TestLog::EndMessage;
	log << TestLog::Message << "Batched variance: "					<< batched.variance						<< TestLog::EndMessage;
	log << TestLog::Message << "Batched min: "						<< batched.min							<< TestLog::EndMessage;
	log << TestLog::Message << "Batched max: "						<< batched.max							<< TestLog::EndMessage;

	log << TestLog::Message << "Batched/Interleaved mean ratio: "	<< (interleaved.mean/batched.mean)		<< TestLog::EndMessage;
	log << TestLog::Message << "Batched/Interleaved median ratio: "	<< (interleaved.median/batched.median)	<< TestLog::EndMessage;

	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, de::floatToString((float)(((double)interleaved.median) / batched.median), 2).c_str());
}

tcu::TestCase::IterateResult StateChangePerformanceCase::iterate (void)
{
	if (m_interleavedResults.empty() && m_batchedResults.empty())
	{
		TestLog& log = m_testCtx.getLog();

		log << TestLog::Message << "Draw call count: " << m_callCount << TestLog::EndMessage;
		log << TestLog::Message << "Per call triangle count: " << m_triangleCount << TestLog::EndMessage;
	}

	// \note [mika] Interleave sampling to balance effects of powerstate etc.
	if ((int)m_interleavedResults.size() < m_iterationCount && m_batchedResults.size() >= m_interleavedResults.size())
	{
		const glw::Functions&	gl			= m_renderCtx.getFunctions();
		deUint64				resBeginUs	= 0;
		deUint64				resEndUs	= 0;

		setupInitialState(gl);
		gl.finish();
		GLU_EXPECT_NO_ERROR(gl.getError(), "glFinish()");

		// Render result
		resBeginUs = deGetMicroseconds();

		renderTest(gl);

		gl.finish();
		resEndUs = deGetMicroseconds();
		GLU_EXPECT_NO_ERROR(gl.getError(), "glFinish()");

		m_interleavedResults.push_back(resEndUs - resBeginUs);

		return CONTINUE;
	}
	else if ((int)m_batchedResults.size() < m_iterationCount)
	{
		const glw::Functions&	gl			= m_renderCtx.getFunctions();
		deUint64				refBeginUs	= 0;
		deUint64				refEndUs	= 0;

		setupInitialState(gl);
		gl.finish();
		GLU_EXPECT_NO_ERROR(gl.getError(), "glFinish()");

		// Render reference
		refBeginUs = deGetMicroseconds();

		renderReference(gl);

		gl.finish();
		refEndUs = deGetMicroseconds();
		GLU_EXPECT_NO_ERROR(gl.getError(), "glFinish()");

		m_batchedResults.push_back(refEndUs - refBeginUs);

		return CONTINUE;
	}
	else
	{
		logAndSetTestResult();
		return STOP;
	}
}

void StateChangePerformanceCase::callDraw (const glw::Functions& gl)
{
	switch (m_drawType)
	{
		case DRAWTYPE_NOT_INDEXED:		gl.drawArrays(GL_TRIANGLES, 0, m_triangleCount * 3);									break;
		case DRAWTYPE_INDEXED_USER_PTR:	gl.drawElements(GL_TRIANGLES, m_triangleCount * 3, GL_UNSIGNED_SHORT, &m_indices[0]);	break;
		case DRAWTYPE_INDEXED_BUFFER:	gl.drawElements(GL_TRIANGLES, m_triangleCount * 3, GL_UNSIGNED_SHORT, NULL);			break;
		default:
			DE_ASSERT(false);
	}
}

// StateChangeCallPerformanceCase

StateChangeCallPerformanceCase::StateChangeCallPerformanceCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description)
	: tcu::TestCase		(testCtx, tcu::NODETYPE_PERFORMANCE, name, description)
	, m_renderCtx		(renderCtx)
	, m_iterationCount	(100)
	, m_callCount		(1000)
{
}

StateChangeCallPerformanceCase::~StateChangeCallPerformanceCase (void)
{
}

void StateChangeCallPerformanceCase::executeTest (void)
{
	const glw::Functions&	gl				= m_renderCtx.getFunctions();
	deUint64				beginTimeUs		= 0;
	deUint64				endTimeUs		= 0;

	beginTimeUs = deGetMicroseconds();

	execCalls(gl, (int)m_results.size(), m_callCount);

	endTimeUs = deGetMicroseconds();

	m_results.push_back(endTimeUs - beginTimeUs);
}

void StateChangeCallPerformanceCase::logTestCase (void)
{
	TestLog& log = m_testCtx.getLog();

	log << TestLog::Message << "Iteration count: " << m_iterationCount << TestLog::EndMessage;
	log << TestLog::Message << "Per iteration call count: " << m_callCount << TestLog::EndMessage;
}

double calculateAverage (const vector<deUint64>& values)
{
	deUint64 sum = 0;

	for (int valueNdx = 0; valueNdx < (int)values.size(); valueNdx++)
		sum += values[valueNdx];

	return ((double)sum) / (double)values.size();
}

void StateChangeCallPerformanceCase::logAndSetTestResult (void)
{
	TestLog&	log				= m_testCtx.getLog();

	deUint64	minUs			= findMin(m_results);
	deUint64	maxUs			= findMax(m_results);
	deUint64	medianUs		= findMedian(m_results);
	double		avgIterationUs	= calculateAverage(m_results);
	double		avgCallUs		= avgIterationUs / m_callCount;
	double		varIteration	= calculateVariance(m_results, avgIterationUs);
	double		avgMedianCallUs	= ((double)medianUs)/m_callCount;

	log << TestLog::Message << "Min iteration time: "						<< minUs << "us" << TestLog::EndMessage;
	log << TestLog::Message << "Max iteration time: "						<< maxUs << "us" << TestLog::EndMessage;
	log << TestLog::Message << "Average iteration time: "					<< avgIterationUs << "us" << TestLog::EndMessage;
	log << TestLog::Message << "Iteration variance time: "					<< varIteration << TestLog::EndMessage;
	log << TestLog::Message << "Median iteration time: "					<< medianUs << "us" << TestLog::EndMessage;
	log << TestLog::Message << "Average call time: "						<< avgCallUs << "us" << TestLog::EndMessage;
	log << TestLog::Message << "Average call time for median iteration: "	<< avgMedianCallUs << "us" << TestLog::EndMessage;

	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, de::floatToString((float)avgMedianCallUs, 3).c_str());
}

tcu::TestCase::IterateResult StateChangeCallPerformanceCase::iterate (void)
{
	if (m_results.empty())
		logTestCase();

	if ((int)m_results.size() < m_iterationCount)
	{
		executeTest();
		GLU_EXPECT_NO_ERROR(m_renderCtx.getFunctions().getError(), "Unexpected error");
		return CONTINUE;
	}
	else
	{
		logAndSetTestResult();
		return STOP;
	}
}

} // gls
} // deqp
