148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos/*-------------------------------------------------------------------------
248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * OpenGL Conformance Test Suite
348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * -----------------------------
448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos *
548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * Copyright (c) 2014-2016 The Khronos Group Inc.
648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos *
748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * Licensed under the Apache License, Version 2.0 (the "License");
848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * you may not use this file except in compliance with the License.
948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * You may obtain a copy of the License at
1048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos *
1148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos *      http://www.apache.org/licenses/LICENSE-2.0
1248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos *
1348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * Unless required by applicable law or agreed to in writing, software
1448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * distributed under the License is distributed on an "AS IS" BASIS,
1548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * See the License for the specific language governing permissions and
1748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * limitations under the License.
1848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos *
1984322c9402f810da3cd80b52e9f9ef72150a9004Alexander Galazin */ /*!
2048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * \file
2148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * \brief
2284322c9402f810da3cd80b52e9f9ef72150a9004Alexander Galazin */ /*-------------------------------------------------------------------*/
2348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
2448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos/**
2548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * \file  gl4GPUShaderFP64Tests.cpp
2648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * \brief Implements conformance tests for "GPU Shader FP64" functionality.
2784322c9402f810da3cd80b52e9f9ef72150a9004Alexander Galazin */ /*-------------------------------------------------------------------*/
2848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
2948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "gl4cClipControlTests.hpp"
3048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
3148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "deSharedPtr.hpp"
3248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
3348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "gluContextInfo.hpp"
3448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "gluDefs.hpp"
3548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "gluPixelTransfer.hpp"
3648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "gluShaderProgram.hpp"
3748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
3848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "tcuFuzzyImageCompare.hpp"
3948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "tcuImageCompare.hpp"
4048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "tcuRenderTarget.hpp"
4148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "tcuSurface.hpp"
4248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "tcuTestLog.hpp"
4348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
4448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "glw.h"
4548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "glwFunctions.hpp"
4648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
4748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include <cmath>
4848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
4948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosnamespace gl4cts
5048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
5148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
5248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass ClipControlApi
5348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
5448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
5548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	ClipControlApi(deqp::Context& context, ClipControlTests::API api) : m_context(context)
5648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
5748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!Supported(m_context, api))
5848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
5948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			throw tcu::NotSupportedError("Required clip_control extension is not supported");
6048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
6148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
6248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		switch (api)
6348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
6448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case ClipControlTests::API_GL_ARB_clip_control:
6548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case ClipControlTests::API_GL_45core: //fall through
6648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			clipControl = context.getRenderContext().getFunctions().clipControl;
6748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
6848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
6948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
7048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
7148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	static bool Supported(deqp::Context& context, ClipControlTests::API api)
7248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
7348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return (api == ClipControlTests::API_GL_ARB_clip_control &&
7448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				context.getContextInfo().isExtensionSupported("GL_ARB_clip_control")) ||
7548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   api == ClipControlTests::API_GL_45core;
7648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
7748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
7848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	glw::glClipControlFunc clipControl;
7948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
8048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
8148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	deqp::Context& m_context;
8248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
8348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
8448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass ClipControlBaseTest : public deqp::TestCase
8548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
8648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprotected:
8748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	ClipControlBaseTest(deqp::Context& context, ClipControlTests::API api, const char* name, const char* description)
8848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		: TestCase(context, name, description), m_api(api)
8948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
9048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
9148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
9248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void init()
9348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
9448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ClipControlApi(m_context, m_api);
9548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
9648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
9748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool verifyState(glw::GLenum origin, glw::GLenum depth)
9848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
9948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
10148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		bool ret = true;
10248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
10348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glw::GLint retI;
10448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.getIntegerv(GL_CLIP_ORIGIN, &retI);
10548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		GLU_EXPECT_NO_ERROR(gl.getError(), "get GL_CLIP_ORIGIN");
10648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
10748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ret &= (static_cast<glw::GLenum>(retI) == origin);
10848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
10948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.getIntegerv(GL_CLIP_DEPTH_MODE, &retI);
11048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		GLU_EXPECT_NO_ERROR(gl.getError(), "get GL_CLIP_DEPTH_MODE");
11148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
11248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ret &= (static_cast<glw::GLenum>(retI) == depth);
11348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
11448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return ret;
11548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
11648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
11748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprotected:
11848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const ClipControlTests::API m_api;
11948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
12048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
12148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass ClipControlRenderBaseTest : public ClipControlBaseTest
12248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
12348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprotected:
12448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	ClipControlRenderBaseTest(deqp::Context& context, ClipControlTests::API api, const char* name,
12548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							  const char* description)
12648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		: ClipControlBaseTest(context, api, name, description), m_fbo(0), m_rboC(0), m_rboD(0)
12748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
12848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
12948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
13048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const char* fsh()
13148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
13248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return "#version 400"
13348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
13448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "out vec4 FragColor;"
13548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
13648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "void main() {"
13748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
13848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "    FragColor = vec4(0.0, 1.0, 0.0, 1.0);"
13948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
14048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "}";
14148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
14248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
14348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool fuzzyDepthCompare(tcu::TestLog& log, const char* imageSetName, const char* imageSetDesc,
14448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						   const tcu::TextureLevel& reference, const tcu::TextureLevel& result, float threshold,
14548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						   const tcu::TextureLevel* importanceMask = NULL)
14648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
14748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		(void)imageSetName;
14848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		(void)imageSetDesc;
14948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		bool  depthOk	= true;
15048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		float difference = 0.0f;
15148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
15248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (int y = 0; y < result.getHeight() && depthOk; y++)
15348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
15448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (int x = 0; x < result.getWidth() && depthOk; x++)
15548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
15648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				float ref  = reference.getAccess().getPixDepth(x, y);
15748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				float res  = result.getAccess().getPixDepth(x, y);
15848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				difference = std::abs(ref - res);
15948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (importanceMask)
16048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
16148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					difference *= importanceMask->getAccess().getPixDepth(x, y);
16248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
16348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				depthOk &= (difference < threshold);
16448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
16548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
16648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
16748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!depthOk)
16848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			log << tcu::TestLog::Message << "Image comparison failed: difference = " << difference
16948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				<< ", threshold = " << threshold << tcu::TestLog::EndMessage;
17048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::Vec4 pixelBias(0.0f, 0.0f, 0.0f, 0.0f);
17148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::Vec4 pixelScale(1.0f, 1.0f, 1.0f, 1.0f);
17248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		log << tcu::TestLog::ImageSet("Result", "Depth image comparison result")
17348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			<< tcu::TestLog::Image("Result", "Result", result.getAccess(), pixelScale, pixelBias)
17448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			<< tcu::TestLog::Image("Reference", "Reference", reference.getAccess(), pixelScale, pixelBias);
17548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (importanceMask)
17648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
17748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			log << tcu::TestLog::Image("Importance mask", "mask", importanceMask->getAccess(), pixelScale, pixelBias);
17848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
17948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		log << tcu::TestLog::EndImageSet;
18048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
18148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return depthOk;
18248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
18348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
18448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual void init(void)
18548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
18648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
18748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glw::GLuint				 viewportW	= renderTarget.getWidth();
18848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glw::GLuint				 viewportH	= renderTarget.getHeight();
18948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const glw::Functions&	gl			  = m_context.getRenderContext().getFunctions();
19048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
19148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.genFramebuffers(1, &m_fbo);
19248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.genRenderbuffers(1, &m_rboC);
19348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.genRenderbuffers(1, &m_rboD);
19448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
19548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.bindRenderbuffer(GL_RENDERBUFFER, m_rboC);
19648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, viewportW, viewportH);
19748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.bindRenderbuffer(GL_RENDERBUFFER, m_rboD);
19848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, viewportW, viewportH);
19948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
20048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
20148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rboC);
20248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_rboD);
20348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
20448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
20548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual void deinit(void)
20648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
20748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
20848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.deleteFramebuffers(1, &m_fbo);
20948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.deleteRenderbuffers(1, &m_rboC);
21048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.deleteRenderbuffers(1, &m_rboD);
21148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
21248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
21348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
21448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
21548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	GLuint m_fbo, m_rboC, m_rboD;
21648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
21748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
21848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos/*
21948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos Verify the following state values are implemented and return a valid
22048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos initial value by calling GetIntegerv:
22148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
22248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos Get Value                                 Initial Value
22348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos -------------------------------------------------------
22448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos CLIP_ORIGIN                                  LOWER_LEFT
22548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos CLIP_DEPTH_MODE                     NEGATIVE_ONE_TO_ONE
22648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
22748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos Verify no GL error is generated.
22848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos */
22948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass ClipControlInitialState : public ClipControlBaseTest
23048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
23148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
23248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	ClipControlInitialState(deqp::Context& context, ClipControlTests::API api, const char* name)
23348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		: ClipControlBaseTest(context, api, name, "Verify initial state")
23448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
23548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
23648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
23748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	IterateResult iterate()
23848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
23948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!verifyState(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE))
24048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
24148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			TCU_FAIL("Wrong intitial state: GL_CLIP_ORIGIN should be GL_LOWER_LEFT,"
24248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					 " GL_CLIP_ORIGIN should be NEGATIVE_ONE_TO_ONE");
24348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
24448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
24548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, qpGetTestResultName(QP_TEST_RESULT_PASS));
24648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return STOP;
24748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
24848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
24948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
25048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos/*
25148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos Modify the state to each of the following combinations and after each
25248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos state change verify the state values:
25348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
25448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos ClipControl(UPPER_LEFT, ZERO_TO_ONE)
25548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos ClipControl(UPPER_LEFT, NEGATIVE_ONE_TO_ONE)
25648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos ClipControl(LOWER_LEFT, ZERO_TO_ONE)
25748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos ClipControl(LOWER_LEFT, NEGATIVE_ONE_TO_ONE)
25848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
25948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos Verify no GL error is generated.
26048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
26148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos */
26248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass ClipControlModifyGetState : public ClipControlBaseTest
26348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
26448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
26548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	ClipControlModifyGetState(deqp::Context& context, ClipControlTests::API api, const char* name)
26648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		: ClipControlBaseTest(context, api, name, "Verify initial state")
26748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
26848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
26948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
27048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void deinit()
27148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
27248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (ClipControlApi::Supported(m_context, m_api))
27348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
27448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			ClipControlApi cc(m_context, m_api);
27548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			cc.clipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE);
27648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
27748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
27848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
27948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	IterateResult iterate()
28048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
28148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
28248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ClipControlApi		  cc(m_context, m_api);
28348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
28448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		GLenum cases[4][2] = {
28548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{ GL_UPPER_LEFT, GL_ZERO_TO_ONE },
28648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{ GL_UPPER_LEFT, GL_NEGATIVE_ONE_TO_ONE },
28748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{ GL_LOWER_LEFT, GL_ZERO_TO_ONE },
28848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{ GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE },
28948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		};
29048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
29148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(cases); i++)
29248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
29348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			cc.clipControl(cases[i][0], cases[i][1]);
29448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			GLU_EXPECT_NO_ERROR(gl.getError(), "ClipControl()");
29548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (!verifyState(cases[i][0], cases[i][1]))
29648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
29748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				TCU_FAIL("Wrong ClipControl state after ClipControl() call");
29848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
29948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
30048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
30148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, qpGetTestResultName(QP_TEST_RESULT_PASS));
30248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return STOP;
30348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
30448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
30548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
30648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos/*
30748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos Check that ClipControl generate an GL_INVALID_ENUM error if origin is
30848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos not GL_LOWER_LEFT or GL_UPPER_LEFT.
30948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
31048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos Check that ClipControl generate an GL_INVALID_ENUM error if depth is
31148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos not GL_NEGATIVE_ONE_TO_ONE or GL_ZERO_TO_ONE.
31248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
31348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos Test is based on OpenGL 4.5 Core Profile Specification May 28th Section
31448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos 13.5 Primitive Clipping:
31548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos "An INVALID_ENUM error is generated if origin is not LOWER_LEFT or
31648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos UPPER_LEFT.
31748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos An INVALID_ENUM error is generated if depth is not NEGATIVE_ONE_-
31848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos TO_ONE or ZERO_TO_ONE."
31948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos */
32048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass ClipControlErrors : public ClipControlBaseTest
32148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
32248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
32348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	ClipControlErrors(deqp::Context& context, ClipControlTests::API api, const char* name)
32448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		: ClipControlBaseTest(context, api, name, "Verify that proper errors are generated when using ClipControl.")
32548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
32648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
32748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
32848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void deinit()
32948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
33048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (ClipControlApi::Supported(m_context, m_api))
33148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
33248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			ClipControlApi cc(m_context, m_api);
33348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			cc.clipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE);
33448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
33548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
33648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
33748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	IterateResult iterate()
33848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
33948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		/* API query */
34048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::TestLog&		  log = m_testCtx.getLog();
34148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const glw::Functions& gl  = m_context.getRenderContext().getFunctions();
34248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ClipControlApi		  cc(m_context, m_api);
34348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
34448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		/* Finding improper value. */
34548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		GLenum improper_value = GL_NONE;
34648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
34748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		while ((GL_UPPER_LEFT == improper_value) || (GL_LOWER_LEFT == improper_value) ||
34848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   (GL_ZERO_TO_ONE == improper_value) || (GL_NEGATIVE_ONE_TO_ONE == improper_value))
34948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
35048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			++improper_value;
35148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
35248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
35348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		/* Test setup. */
35448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		GLenum cases[5][2] = { { GL_UPPER_LEFT, improper_value },
35548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							   { GL_LOWER_LEFT, improper_value },
35648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							   { improper_value, GL_ZERO_TO_ONE },
35748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							   { improper_value, GL_NEGATIVE_ONE_TO_ONE },
35848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							   { improper_value, improper_value } };
35948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
36048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		/* Test iterations. */
36148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(cases); i++)
36248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
36348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			cc.clipControl(cases[i][0], cases[i][1]);
36448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
36548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (GL_INVALID_ENUM != gl.getError())
36648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
36748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, qpGetTestResultName(QP_TEST_RESULT_FAIL));
36848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
36948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				log << tcu::TestLog::Message
37048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					<< "ClipControl have not generated GL_INVALID_ENUM error when called with invalid value ("
37148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					<< cases[i][0] << ", " << cases[i][1] << ")." << tcu::TestLog::EndMessage;
37248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
37348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
37448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
37548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, qpGetTestResultName(QP_TEST_RESULT_PASS));
37648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return STOP;
37748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
37848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
37948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
38048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos/*
38148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos Clip Control Origin Test
38248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
38348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * Basic <origin> behavior can be tested by rendering to a viewport with
38448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos clip coordinates where -1.0 <= x_c <= 0.0 and -1.0 <= y_c <= 0.0.
38548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos When <origin> is LOWER_LEFT the "bottom left" portion of the window
38648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos is rendered and when UPPER_LEFT is used the "top left" portion of the
38748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos window is rendered. The default framebuffer should be bound. Here is the
38848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos basic outline of the test:
38948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
39048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Clear the default framebuffer to red (1,0,0).
39148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Set ClipControl(UPPER_LEFT, NEGATIVE_ONE_TO_ONE)
39248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Render a triangle fan covering (-1.0, -1.0) to (0.0, 0.0) and
39348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos write a pixel value of green (0,1,0).
39448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Read back the default framebuffer with ReadPixels
39548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Verify the green pixels at the top and red at the bottom.
39648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
39748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos Repeat the above test with LOWER_LEFT and verify green at the bottom
39848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos and red at the top.
39948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos */
40048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass ClipControlOriginTest : public ClipControlRenderBaseTest
40148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
40248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
40348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	ClipControlOriginTest(deqp::Context& context, ClipControlTests::API api, const char* name)
40448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		: ClipControlRenderBaseTest(context, api, name, "Clip Control Origin Test"), m_vao(0), m_vbo(0)
40548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
40648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
40748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
40848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void deinit()
40948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
41048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ClipControlRenderBaseTest::deinit();
41148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
41248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
41348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (ClipControlApi::Supported(m_context, m_api))
41448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
41548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			ClipControlApi cc(m_context, m_api);
41648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			cc.clipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE);
41748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
41848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
41948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.clearColor(0.0, 0.0, 0.0, 0.0);
42048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (m_vao)
42148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
42248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl.deleteVertexArrays(1, &m_vao);
42348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
42448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (m_vbo)
42548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
42648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl.deleteBuffers(1, &m_vbo);
42748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
42848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
42948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
43048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	IterateResult iterate()
43148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
43248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
43348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::TestLog&		  log = m_testCtx.getLog();
43448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const glw::Functions& gl  = m_context.getRenderContext().getFunctions();
43548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ClipControlApi		  cc(m_context, m_api);
43648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
43748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//Render a triangle fan covering(-1.0, -1.0) to(1.0, 0.0) and
43848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//write a pixel value of green(0, 1, 0).
43948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
44048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		de::SharedPtr<glu::ShaderProgram> program(
44148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vsh(), fsh())));
44248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
44348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		log << (*program);
44448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!program->isOk())
44548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
44648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			TCU_FAIL("Program compilation failed");
44748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
44848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
44948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.genVertexArrays(1, &m_vao);
45048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.bindVertexArray(m_vao);
45148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
45248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.genBuffers(1, &m_vbo);
45348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
45448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const float vertex_data0[] = { -1.0, -1.0, 0.0, -1.0, -1.0, 0.0, 0.0, 0.0 };
45548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
45648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.bindBuffer(GL_ARRAY_BUFFER, m_vbo);
45748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertex_data0), vertex_data0, GL_STATIC_DRAW);
45848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
45948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.vertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
46048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.enableVertexAttribArray(0);
46148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
46248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.useProgram(program->getProgram());
46348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
46448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glw::GLenum origins[] = { GL_UPPER_LEFT, GL_LOWER_LEFT };
46548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
46648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		qpTestResult result = QP_TEST_RESULT_PASS;
46748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
46848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (size_t orig = 0; orig < DE_LENGTH_OF_ARRAY(origins); orig++)
46948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
47048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			//Clear the default framebuffer to red(1, 0, 0).
47148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl.clearColor(1.0, 0.0, 0.0, 1.0);
47248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl.clear(GL_COLOR_BUFFER_BIT);
47348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
47448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			//Set ClipControl(UPPER_LEFT, NEGATIVE_ONE_TO_ONE)
47548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			cc.clipControl(origins[orig], GL_NEGATIVE_ONE_TO_ONE);
47648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			GLU_EXPECT_NO_ERROR(gl.getError(), "ClipControl()");
47748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
47848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			//test method modification: use GL_TRIANGLE_STRIP, not FAN.
47948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
48048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
48148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			//Read back the default framebuffer with ReadPixels
48248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			//Verify the green pixels at the top and red at the bottom.
48348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			qpTestResult loopResult = ValidateFramebuffer(m_context, origins[orig]);
48448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (loopResult != QP_TEST_RESULT_PASS)
48548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
48648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				result = loopResult;
48748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
48848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
48948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
49048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		m_testCtx.setTestResult(result, qpGetTestResultName(result));
49148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
49248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return STOP;
49348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
49448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
49548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const char* vsh()
49648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
49748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return "#version 400"
49848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
49948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "in vec2 Position;"
50048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
50148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "void main() {"
50248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
50348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "    gl_Position = vec4(Position, 0.0, 1.0);"
50448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
50548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "}";
50648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
50748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
50848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	qpTestResult ValidateFramebuffer(deqp::Context& context, glw::GLenum origin)
50948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
51048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const tcu::RenderTarget& renderTarget = context.getRenderContext().getRenderTarget();
51148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glw::GLuint				 viewportW	= renderTarget.getWidth();
51248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glw::GLuint				 viewportH	= renderTarget.getHeight();
51348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::Surface			 renderedFrame(viewportW, viewportH);
51448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::Surface			 referenceFrame(viewportW, viewportH);
51548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
51648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::TestLog& log = context.getTestContext().getLog();
51748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
51848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (int y = 0; y < renderedFrame.getHeight(); y++)
51948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
52048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			float yCoord = (float)(y) / (float)renderedFrame.getHeight();
52148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
52248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (int x = 0; x < renderedFrame.getWidth(); x++)
52348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
52448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
52548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				float xCoord = (float)(x) / (float)renderedFrame.getWidth();
52648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
52748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				bool greenQuadrant;
52848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
52948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (origin == GL_UPPER_LEFT)
53048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
53148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					greenQuadrant = (yCoord > 0.5 && xCoord <= 0.5);
53248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
53348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				else
53448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
53548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					greenQuadrant = (yCoord <= 0.5 && xCoord <= 0.5);
53648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
53748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
53848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (greenQuadrant)
53948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
54048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					referenceFrame.setPixel(x, y, tcu::RGBA::green());
54148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
54248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				else
54348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
54448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					referenceFrame.setPixel(x, y, tcu::RGBA::red());
54548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
54648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
54748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
54848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
54948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glu::readPixels(context.getRenderContext(), 0, 0, renderedFrame.getAccess());
55048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
55148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (tcu::fuzzyCompare(log, "Result", "Image comparison result", referenceFrame, renderedFrame, 0.05f,
55248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							  tcu::COMPARE_LOG_RESULT))
55348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
55448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return QP_TEST_RESULT_PASS;
55548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
55648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
55748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
55848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return QP_TEST_RESULT_FAIL;
55948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
56048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
56148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
56248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	glw::GLuint m_vao, m_vbo;
56348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
56448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
56548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos/*   Depth Mode Test
56648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
56748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * Basic <depth> behavior can be tested by writing specific z_c (z
56848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos clip coordinates) and observing its clipping and transformation.
56948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos Create and bind a framebuffer object with a floating-point depth
57048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos buffer attachment. Make sure depth clamping is disabled. The best
57148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos steps for verifying the correct depth mode:
57248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
57348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Clear the depth buffer to 0.5.
57448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Set ClipControl(LOWER_LEFT, ZERO_TO_ONE)
57548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Enable(DEPTH_TEST) with DepthFunc(ALWAYS)
57648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Render a triangle fan coverage (-1.0,-1.0,-1.0) to (1.0,1.0,1.0).
57748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Read back the floating-point depth buffer with ReadPixels
57848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Verify that the pixels with a Z clip coordinate less than 0.0 are
57948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos clipped and those coordinates from 0.0 to 1.0 update the depth
58048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos buffer with values 0.0 to 1.0.
58148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos */
58248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass ClipControlDepthModeZeroToOneTest : public ClipControlRenderBaseTest
58348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
58448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
58548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	ClipControlDepthModeZeroToOneTest(deqp::Context& context, ClipControlTests::API api, const char* name)
58648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		: ClipControlRenderBaseTest(context, api, name, "Depth Mode Test, ZERO_TO_ONE"), m_vao(0), m_vbo(0)
58748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
58848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
58948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
59048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void deinit()
59148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
59248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ClipControlRenderBaseTest::deinit();
59348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
59448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
59548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
59648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (ClipControlApi::Supported(m_context, m_api))
59748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
59848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			ClipControlApi cc(m_context, m_api);
59948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			cc.clipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE);
60048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
60148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
60248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.clearDepth(0.0);
60348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.clearColor(0.0, 0.0, 0.0, 0.0);
60448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
60548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.disable(GL_DEPTH_TEST);
60648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.depthFunc(GL_LESS);
60748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
60848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (m_vao)
60948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
61048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl.deleteVertexArrays(1, &m_vao);
61148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
61248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (m_vbo)
61348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
61448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl.deleteBuffers(1, &m_vbo);
61548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
61648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
61748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
61848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	IterateResult iterate()
61948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
62048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
62148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::TestLog&		  log = m_testCtx.getLog();
62248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const glw::Functions& gl  = m_context.getRenderContext().getFunctions();
62348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ClipControlApi		  cc(m_context, m_api);
62448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
62548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.clearColor(1.0, 0.0, 0.0, 1.0);
62648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.clear(GL_COLOR_BUFFER_BIT);
62748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
62848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//Clear the depth buffer to 0.5.
62948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.clearDepth(0.5);
63048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.clear(GL_DEPTH_BUFFER_BIT);
63148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
63248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//Set ClipControl(LOWER_LEFT, ZERO_TO_ONE)
63348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		cc.clipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE);
63448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		GLU_EXPECT_NO_ERROR(gl.getError(), "ClipControl()");
63548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
63648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//Enable(DEPTH_TEST) with DepthFunc(ALWAYS)
63748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.enable(GL_DEPTH_TEST);
63848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.depthFunc(GL_ALWAYS);
63948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
64048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//Render a triangle fan coverage (-1.0,-1.0,-1.0) to (1.0,1.0,1.0).
64148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		de::SharedPtr<glu::ShaderProgram> program(
64248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vsh(), fsh())));
64348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
64448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		log << (*program);
64548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!program->isOk())
64648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
64748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			TCU_FAIL("Program compilation failed");
64848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
64948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
65048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.genVertexArrays(1, &m_vao);
65148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.bindVertexArray(m_vao);
65248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
65348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.genBuffers(1, &m_vbo);
65448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
65548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const float vertex_data0[] = {
65648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			-1.0, -1.0, -1.0, 1.0, -1.0, 0.0, -1.0, 1.0, 0.0, 1.0, 1.0, 1.0,
65748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		};
65848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
65948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.bindBuffer(GL_ARRAY_BUFFER, m_vbo);
66048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertex_data0), vertex_data0, GL_STATIC_DRAW);
66148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
66248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
66348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.enableVertexAttribArray(0);
66448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
66548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.useProgram(program->getProgram());
66648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
66748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//test method modification: use GL_TRIANGLE_STRIP, not FAN.
66848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
66948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
67048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//Read back the floating-point depth buffer with ReadPixels
67148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//Verify that the pixels with a Z clip coordinate less than 0.0 are
67248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//  clipped and those coordinates from 0.0 to 1.0 update the depth
67348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//  buffer with values 0.0 to 1.0.
67448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		qpTestResult result = ValidateFramebuffer(m_context);
67548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		m_testCtx.setTestResult(result, qpGetTestResultName(result));
67648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
67748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return STOP;
67848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
67948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
68048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const char* vsh()
68148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
68248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return "#version 400"
68348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
68448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "in vec3 Position;"
68548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
68648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "void main() {"
68748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
68848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "    gl_Position = vec4(Position, 1.0);"
68948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
69048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "}";
69148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
69248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
69348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	qpTestResult ValidateFramebuffer(deqp::Context& context)
69448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
69548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const tcu::RenderTarget& renderTarget = context.getRenderContext().getRenderTarget();
69648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glw::GLuint				 viewportW	= renderTarget.getWidth();
69748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glw::GLuint				 viewportH	= renderTarget.getHeight();
69848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::Surface			 renderedColorFrame(viewportW, viewportH);
69948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::Surface			 referenceColorFrame(viewportW, viewportH);
70048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::TextureFormat		 depthFormat(tcu::TextureFormat::D, tcu::TextureFormat::FLOAT);
70148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::TextureLevel		 renderedDepthFrame(depthFormat, viewportW, viewportH);
70248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::TextureLevel		 referenceDepthFrame(depthFormat, viewportW, viewportH);
70348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::TextureLevel		 importanceMaskFrame(depthFormat, viewportW, viewportH);
70448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
70548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::TestLog& log = context.getTestContext().getLog();
70648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
70748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const float rasterizationError =
70848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			2.0f / (float)renderedColorFrame.getHeight() + 2.0f / (float)renderedColorFrame.getWidth();
70948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
71048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (int y = 0; y < renderedColorFrame.getHeight(); y++)
71148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
71248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			float yCoord = ((float)(y) + 0.5f) / (float)renderedColorFrame.getHeight();
71348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
71448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (int x = 0; x < renderedColorFrame.getWidth(); x++)
71548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
71648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				float xCoord = ((float)(x) + 0.5f) / (float)renderedColorFrame.getWidth();
71748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
71848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (yCoord >= 1.0 - xCoord - rasterizationError && yCoord <= 1.0 - xCoord + rasterizationError)
71948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
72048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					importanceMaskFrame.getAccess().setPixDepth(0.0f, x, y);
72148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
72248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				else
72348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
72448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					importanceMaskFrame.getAccess().setPixDepth(1.0f, x, y);
72548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
72648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
72748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (yCoord < 1.0 - xCoord)
72848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
72948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					referenceColorFrame.setPixel(x, y, tcu::RGBA::red());
73048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					referenceDepthFrame.getAccess().setPixDepth(0.5f, x, y);
73148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
73248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				else
73348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
73448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					referenceColorFrame.setPixel(x, y, tcu::RGBA::green());
73548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
73648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					referenceDepthFrame.getAccess().setPixDepth(-1.0f + xCoord + yCoord, x, y);
73748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
73848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
73948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
74048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
74148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glu::readPixels(context.getRenderContext(), 0, 0, renderedColorFrame.getAccess());
74248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!tcu::fuzzyCompare(log, "Result", "Color image comparison result", referenceColorFrame, renderedColorFrame,
74348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							   0.05f, tcu::COMPARE_LOG_RESULT))
74448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
74548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
74648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return QP_TEST_RESULT_FAIL;
74748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
74848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
74948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glu::readPixels(context.getRenderContext(), 0, 0, renderedDepthFrame.getAccess());
75048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!fuzzyDepthCompare(log, "Result", "Depth image comparison result", referenceDepthFrame, renderedDepthFrame,
75148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							   0.05f, &importanceMaskFrame))
75248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
75348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return QP_TEST_RESULT_FAIL;
75448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
75548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return QP_TEST_RESULT_PASS;
75648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
75748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
75848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	glw::GLuint m_vao, m_vbo;
75948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
76048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
76148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos/*
76248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos Do the same as above, but use the default NEGATIVE_ONE_TO_ONE depth mode:
76348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
76448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Clear the depth buffer to 0.5.
76548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Set ClipControl(LOWER_LEFT, NEGATIVE_ONE_TO_ONE)
76648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Enable(DEPTH_TEST) with DepthFunc(ALWAYS)
76748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Render a triangle fan coverage (-1.0,-1.0,-1.0) to (1.0,1.0,1.0).
76848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Read back the floating-point depth buffer with ReadPixels
76948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Verify that no pixels are clipped and the depth buffer contains
77048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos values from 0.0 to 1.0.
77148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos */
77248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass ClipControlDepthModeOneToOneTest : public ClipControlRenderBaseTest
77348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
77448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
77548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	ClipControlDepthModeOneToOneTest(deqp::Context& context, ClipControlTests::API api, const char* name)
77648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		: ClipControlRenderBaseTest(context, api, name, "Depth Mode Test, ZERO_TO_ONE"), m_vao(0), m_vbo(0)
77748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
77848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
77948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
78048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void deinit()
78148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
78248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ClipControlRenderBaseTest::deinit();
78348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
78448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
78548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
78648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (ClipControlApi::Supported(m_context, m_api))
78748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
78848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			ClipControlApi cc(m_context, m_api);
78948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			cc.clipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE);
79048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
79148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
79248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.clearDepth(0.0);
79348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.clearColor(0.0, 0.0, 0.0, 0.0);
79448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
79548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.disable(GL_DEPTH_TEST);
79648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.depthFunc(GL_LESS);
79748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
79848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (m_vao)
79948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
80048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl.deleteVertexArrays(1, &m_vao);
80148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
80248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (m_vbo)
80348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
80448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl.deleteBuffers(1, &m_vbo);
80548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
80648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
80748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
80848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	IterateResult iterate()
80948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
81048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::TestLog&		  log = m_testCtx.getLog();
81148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const glw::Functions& gl  = m_context.getRenderContext().getFunctions();
81248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ClipControlApi		  cc(m_context, m_api);
81348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
81448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.clearColor(1.0, 0.0, 0.0, 1.0);
81548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.clear(GL_COLOR_BUFFER_BIT);
81648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
81748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//Clear the depth buffer to 0.5.
81848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.clearDepth(0.5);
81948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.clear(GL_DEPTH_BUFFER_BIT);
82048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
82148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//Set ClipControl(LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE)
82248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		cc.clipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE);
82348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		GLU_EXPECT_NO_ERROR(gl.getError(), "ClipControl()");
82448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
82548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//Enable(DEPTH_TEST) with DepthFunc(ALWAYS)
82648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.enable(GL_DEPTH_TEST);
82748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.depthFunc(GL_ALWAYS);
82848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
82948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//Render a triangle fan coverage (-1.0,-1.0,-1.0) to (1.0,1.0,1.0).
83048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		de::SharedPtr<glu::ShaderProgram> program(
83148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vsh(), fsh())));
83248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
83348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		log << (*program);
83448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!program->isOk())
83548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
83648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			TCU_FAIL("Program compilation failed");
83748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
83848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
83948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.genVertexArrays(1, &m_vao);
84048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.bindVertexArray(m_vao);
84148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
84248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.genBuffers(1, &m_vbo);
84348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
84448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const float vertex_data0[] = {
84548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			-1.0, -1.0, -1.0, 1.0, -1.0, 0.0, -1.0, 1.0, 0.0, 1.0, 1.0, 1.0,
84648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		};
84748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
84848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.bindBuffer(GL_ARRAY_BUFFER, m_vbo);
84948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertex_data0), vertex_data0, GL_STATIC_DRAW);
85048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
85148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
85248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.enableVertexAttribArray(0);
85348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
85448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.useProgram(program->getProgram());
85548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
85648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//test method modification: use GL_TRIANGLE_STRIP, not FAN.
85748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
85848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
85948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//Read back the floating-point depth buffer with ReadPixels
86048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//Verify that the pixels with a Z clip coordinate less than 0.0 are
86148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//  clipped and those coordinates from 0.0 to 1.0 update the depth
86248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//  buffer with values 0.0 to 1.0.
86348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		qpTestResult result = ValidateFramebuffer(m_context);
86448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		m_testCtx.setTestResult(result, qpGetTestResultName(result));
86548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
86648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return STOP;
86748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
86848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
86948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const char* vsh()
87048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
87148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return "#version 400"
87248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
87348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "in vec3 Position;"
87448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
87548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "void main() {"
87648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
87748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "    gl_Position = vec4(Position, 1.0);"
87848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
87948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "}";
88048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
88148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
88248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	qpTestResult ValidateFramebuffer(deqp::Context& context)
88348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
88448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const tcu::RenderTarget& renderTarget = context.getRenderContext().getRenderTarget();
88548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glw::GLuint				 viewportW	= renderTarget.getWidth();
88648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glw::GLuint				 viewportH	= renderTarget.getHeight();
88748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::Surface			 renderedColorFrame(viewportW, viewportH);
88848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::Surface			 referenceColorFrame(viewportW, viewportH);
88948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::TextureFormat		 depthFormat(tcu::TextureFormat::D, tcu::TextureFormat::FLOAT);
89048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::TextureLevel		 renderedDepthFrame(depthFormat, viewportW, viewportH);
89148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::TextureLevel		 referenceDepthFrame(depthFormat, viewportW, viewportH);
89248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
89348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::TestLog& log = context.getTestContext().getLog();
89448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
89548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (int y = 0; y < renderedColorFrame.getHeight(); y++)
89648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
89748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			float yCoord = (float)(y) / (float)renderedColorFrame.getHeight();
89848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (int x = 0; x < renderedColorFrame.getWidth(); x++)
89948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
90048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				float xCoord = (float)(x) / (float)renderedColorFrame.getWidth();
90148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
90248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				referenceColorFrame.setPixel(x, y, tcu::RGBA::green());
90348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				referenceDepthFrame.getAccess().setPixDepth((xCoord + yCoord) * 0.5f, x, y);
90448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
90548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
90648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
90748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glu::readPixels(context.getRenderContext(), 0, 0, renderedColorFrame.getAccess());
90848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!tcu::fuzzyCompare(log, "Result", "Color image comparison result", referenceColorFrame, renderedColorFrame,
90948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							   0.05f, tcu::COMPARE_LOG_RESULT))
91048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
91148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
91248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return QP_TEST_RESULT_FAIL;
91348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
91448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glu::readPixels(context.getRenderContext(), 0, 0, renderedDepthFrame.getAccess());
91548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!fuzzyDepthCompare(log, "Result", "Depth image comparison result", referenceDepthFrame, renderedDepthFrame,
91648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							   0.05f))
91748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
91848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
91948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return QP_TEST_RESULT_FAIL;
92048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
92148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
92248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return QP_TEST_RESULT_PASS;
92348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
92448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
92548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	glw::GLuint m_vao, m_vbo;
92648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
92748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
92848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos/*
92948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos Clip Control Origin With Face Culling Test
93048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
93148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * Face culling should be tested with both <origin> settings.
93248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos The reason for that is, when doing Y-inversion, implementation
93348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos should not flip the calculated area sign for the triangle.
93448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos In other words, culling of CCW and CW triangles should
93548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos be orthogonal to used <origin> mode. Both triangle windings
93648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos and both <origin> modes should be tested. Here is the basic
93748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos outline of the test:
93848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
93948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Clear the framebuffer to red (1,0,0).
94048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Enable GL_CULL_FACE, leave default front face & cull face (CCW, BACK)
94148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Set ClipControl(UPPER_LEFT, NEGATIVE_ONE_TO_ONE)
94248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Render a counter-clockwise triangles covering
94348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos (-1.0, -1.0) to (0.0, 1.0) and write a pixel value of green (0,1,0).
94448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Render a clockwise triangles covering
94548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos (0.0, -1.0) to (1.0, 1.0) and write a pixel value of green (0,1,0).
94648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Read back the framebuffer with ReadPixels
94748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Verify the green pixels at the left and red at the right.
94848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
94948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos Repeat above test for ClipControl(LOWER_LEFT, NEGATIVE_ONE_TO_ONE)
95048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos */
95148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass ClipControlFaceCulling : public ClipControlRenderBaseTest
95248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
95348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
95448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	ClipControlFaceCulling(deqp::Context& context, ClipControlTests::API api, const char* name)
95548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		: ClipControlRenderBaseTest(context, api, name, "Face culling test, both origins"), m_vao(0), m_vbo(0)
95648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
95748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
95848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
95948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void deinit()
96048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
96148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ClipControlRenderBaseTest::deinit();
96248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
96348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
96448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
96548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (ClipControlApi::Supported(m_context, m_api))
96648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
96748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			ClipControlApi cc(m_context, m_api);
96848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			cc.clipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE);
96948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
97048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
97148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.disable(GL_CULL_FACE);
97248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
97348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.clearDepth(0.0);
97448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.clearColor(0.0, 0.0, 0.0, 0.0);
97548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
97648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.disable(GL_DEPTH_TEST);
97748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.depthFunc(GL_LESS);
97848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
97948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (m_vao)
98048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
98148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl.deleteVertexArrays(1, &m_vao);
98248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
98348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (m_vbo)
98448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
98548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl.deleteBuffers(1, &m_vbo);
98648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
98748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
98848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
98948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	IterateResult iterate()
99048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
99148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
99248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::TestLog&		  log = m_testCtx.getLog();
99348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const glw::Functions& gl  = m_context.getRenderContext().getFunctions();
99448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ClipControlApi		  cc(m_context, m_api);
99548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
99648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//Enable GL_CULL_FACE, leave default front face & cull face(CCW, BACK)
99748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.enable(GL_CULL_FACE);
99848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
99948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//Render a counter-clockwise triangles covering
100048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//(-1.0, -1.0) to(0.0, 1.0) and write a pixel value of green(0, 1, 0).
100148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//Render a clockwise triangles covering
100248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//(0.0, -1.0) to(1.0, 1.0) and write a pixel value of green(0, 1, 0).
100348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		de::SharedPtr<glu::ShaderProgram> program(
100448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vsh(), fsh())));
100548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
100648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		log << (*program);
100748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!program->isOk())
100848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
100948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			TCU_FAIL("Program compilation failed");
101048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
101148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
101248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.genVertexArrays(1, &m_vao);
101348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.bindVertexArray(m_vao);
101448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
101548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.genBuffers(1, &m_vbo);
101648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
101748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const float vertex_data0[] = {
101848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			//CCW
101948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			-1.0, -1.0, 0.0, -1.0, -1.0, 1.0, 0.0, -1.0, 0.0, 1.0, -1.0, 1.0,
102048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			//CW
102148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			0.0, -1.0, 0.0, 1.0, 1.0, -1.0, 1.0, -1.0, 0.0, 1.0, 1.0, 1.0,
102248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		};
102348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
102448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.bindBuffer(GL_ARRAY_BUFFER, m_vbo);
102548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertex_data0), vertex_data0, GL_STATIC_DRAW);
102648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
102748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.vertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
102848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.enableVertexAttribArray(0);
102948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
103048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.useProgram(program->getProgram());
103148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
103248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glw::GLenum origins[] = { GL_UPPER_LEFT, GL_LOWER_LEFT };
103348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
103448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		qpTestResult result = QP_TEST_RESULT_PASS;
103548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
103648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (size_t orig = 0; orig < DE_LENGTH_OF_ARRAY(origins); orig++)
103748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
103848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			//Clear the framebuffer to red (1,0,0).
103948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl.clearColor(1.0, 0.0, 0.0, 1.0);
104048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl.clear(GL_COLOR_BUFFER_BIT);
104148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
104248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl.drawArrays(GL_TRIANGLES, 0, 12);
104348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
104448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			//Set ClipControl(<origin>, NEGATIVE_ONE_TO_ONE)
104548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			cc.clipControl(origins[orig], GL_NEGATIVE_ONE_TO_ONE);
104648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			GLU_EXPECT_NO_ERROR(gl.getError(), "ClipControl()");
104748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
104848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			//Read back the framebuffer with ReadPixels
104948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			//Verify the green pixels at the left and red at the right.
105048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			qpTestResult loopResult = ValidateFramebuffer(m_context);
105148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (loopResult != QP_TEST_RESULT_PASS)
105248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
105348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				result = loopResult;
105448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
105548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
105648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		m_testCtx.setTestResult(result, qpGetTestResultName(result));
105748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
105848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return STOP;
105948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
106048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
106148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const char* vsh()
106248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
106348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return "#version 400"
106448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
106548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "in vec3 Position;"
106648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
106748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "void main() {"
106848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
106948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "    gl_Position = vec4(Position, 1.0);"
107048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
107148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "}";
107248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
107348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
107448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	qpTestResult ValidateFramebuffer(deqp::Context& context)
107548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
107648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const tcu::RenderTarget& renderTarget = context.getRenderContext().getRenderTarget();
107748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glw::GLuint				 viewportW	= renderTarget.getWidth();
107848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glw::GLuint				 viewportH	= renderTarget.getHeight();
107948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::Surface			 renderedColorFrame(viewportW, viewportH);
108048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::Surface			 referenceColorFrame(viewportW, viewportH);
108148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::TestLog&			 log = context.getTestContext().getLog();
108248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
108348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (int y = 0; y < renderedColorFrame.getHeight(); y++)
108448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
108548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (int x = 0; x < renderedColorFrame.getWidth(); x++)
108648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
108748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				float xCoord = (float)(x) / (float)renderedColorFrame.getWidth();
108848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
108948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (xCoord < 0.5)
109048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
109148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					referenceColorFrame.setPixel(x, y, tcu::RGBA::green());
109248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
109348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				else
109448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
109548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					referenceColorFrame.setPixel(x, y, tcu::RGBA::red());
109648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
109748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
109848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
109948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
110048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glu::readPixels(context.getRenderContext(), 0, 0, renderedColorFrame.getAccess());
110148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!tcu::fuzzyCompare(log, "Result", "Color image comparison result", referenceColorFrame, renderedColorFrame,
110248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							   0.05f, tcu::COMPARE_LOG_RESULT))
110348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
110448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
110548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return QP_TEST_RESULT_FAIL;
110648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
110748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return QP_TEST_RESULT_PASS;
110848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
110948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
111048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	glw::GLuint m_vao, m_vbo;
111148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
111248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
111348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos/*
111448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos Viewport Bounds Test
111548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
111648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * Viewport bounds should be tested, to ensure that rendering with flipped
111748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos origin affects only viewport area.
111848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
111948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos This can be done by clearing the window to blue, making viewport
112048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos a non-symmetric-in-any-way subset of the window, than rendering
112148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos full-viewport multiple color quad. The (-1.0, -1.0)..(0.0, 0.0) quadrant
112248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos of a quad is red, the rest is green.
112348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos Whatever the origin is, the area outside of the viewport should stay blue.
112448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos If origin is LOWER_LEFT the "lower left" portion of the viewport is red,
112548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos if origin is UPPER_LEFT the "top left" portion of the viewport is red
112648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos (and in both cases the rest of viewport is green).
112748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
112848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos Here is the basic outline of the test:
112948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
113048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Clear the default framebuffer to blue (0,0,1).
113148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Set viewport to A = (x, y, w, h) = (1/8, 1/4, 1/2, 1/4)  in terms of proportional window size
113248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Set ClipControl(UPPER_LEFT, NEGATIVE_ONE_TO_ONE)
113348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Render a triangle strip covering (-1.0, -1.0) to (1.0, 1.0).
113448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos Write a pixel value of red (0,1,0) to (-1.0, -1.0)..(0.0, 0.0), other parts are green
113548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Reset viewport to defaults
113648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Read back the default framebuffer with ReadPixels
113748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Verify:
113848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - regions outside A viewport are green
113948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos - Inside A viewport upper upper left portion is red, rest is green.
114048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
114148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos Repeat the above test with LOWER_LEFT origin and lower left portion of A is red,
114248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos rest is green.
114348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos */
114448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass ClipControlViewportBounds : public ClipControlRenderBaseTest
114548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
114648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
114748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	ClipControlViewportBounds(deqp::Context& context, ClipControlTests::API api, const char* name)
114848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		: ClipControlRenderBaseTest(context, api, name, "Clip Control Origin Test"), m_vao(0), m_vbo(0)
114948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
115048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
115148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
115248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void deinit()
115348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
115448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ClipControlRenderBaseTest::deinit();
115548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
115648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
115748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glw::GLuint				 windowW	  = renderTarget.getWidth();
115848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glw::GLuint				 windowH	  = renderTarget.getHeight();
115948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const glw::Functions&	gl			  = m_context.getRenderContext().getFunctions();
116048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
116148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (ClipControlApi::Supported(m_context, m_api))
116248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
116348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			ClipControlApi cc(m_context, m_api);
116448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			cc.clipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE);
116548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
116648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
116748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.clearColor(0.0, 0.0, 0.0, 0.0);
116848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.viewport(0, 0, windowW, windowH);
116948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
117048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (m_vao)
117148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
117248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl.deleteVertexArrays(1, &m_vao);
117348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
117448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (m_vbo)
117548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
117648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl.deleteBuffers(1, &m_vbo);
117748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
117848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
117948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
118048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	IterateResult iterate()
118148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
118248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::TestLog&			 log		  = m_testCtx.getLog();
118348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const glw::Functions&	gl			  = m_context.getRenderContext().getFunctions();
118448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
118548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glw::GLuint				 windowW	  = renderTarget.getWidth();
118648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glw::GLuint				 windowH	  = renderTarget.getHeight();
118748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ClipControlApi			 cc(m_context, m_api);
118848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
118948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//Clear the default framebuffer to blue (0,0,1).
119048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.clearColor(0.0, 0.0, 1.0, 1.0);
119148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.clear(GL_COLOR_BUFFER_BIT);
119248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
119348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		de::SharedPtr<glu::ShaderProgram> program(
119448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vsh(), fsh())));
119548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
119648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		log << (*program);
119748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!program->isOk())
119848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
119948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			TCU_FAIL("Program compilation failed");
120048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
120148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.genVertexArrays(1, &m_vao);
120248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.bindVertexArray(m_vao);
120348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
120448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.genBuffers(1, &m_vbo);
120548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
120648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const float vertex_data0[] = { -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0 };
120748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
120848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.bindBuffer(GL_ARRAY_BUFFER, m_vbo);
120948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertex_data0), vertex_data0, GL_STATIC_DRAW);
121048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
121148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.vertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
121248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.enableVertexAttribArray(0);
121348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
121448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl.useProgram(program->getProgram());
121548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
121648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glw::GLenum origins[] = { GL_UPPER_LEFT, GL_LOWER_LEFT };
121748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
121848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		qpTestResult result = QP_TEST_RESULT_PASS;
121948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
122048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (size_t orig = 0; orig < DE_LENGTH_OF_ARRAY(origins); orig++)
122148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
122248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			//Set viewport to A = (x, y, w, h) = (1/8, 1/4, 1/2, 1/4) in terms of proportional window size
122348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl.viewport((glw::GLint)(0.125f * (float)windowW), (glw::GLint)(0.25f * (float)windowH),
122448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						(glw::GLsizei)(0.5f * (float)windowW), (glw::GLsizei)(0.25f * (float)windowH));
122548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
122648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			//Set ClipControl(<origin>, NEGATIVE_ONE_TO_ONE)
122748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			cc.clipControl(origins[orig], GL_NEGATIVE_ONE_TO_ONE);
122848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			GLU_EXPECT_NO_ERROR(gl.getError(), "ClipControl()");
122948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
123048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			//Render a triangle strip covering (-1.0, -1.0) to (1.0, 1.0).
123148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			//Write a pixel value of red (0,1,0) to (-1.0, -1.0)..(0.0, 0.0), other parts are green
123248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
123348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
123448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl.viewport(0, 0, windowW, windowH);
123548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
123648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			//Read back the default framebuffer with ReadPixels
123748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			//Verify the green pixels at the top and red at the bottom.
123848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			qpTestResult loopResult = ValidateFramebuffer(m_context, origins[orig]);
123948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (loopResult != QP_TEST_RESULT_PASS)
124048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
124148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				result = loopResult;
124248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
124348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
124448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		m_testCtx.setTestResult(result, qpGetTestResultName(result));
124548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return STOP;
124648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
124748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
124848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const char* vsh()
124948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
125048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return "#version 400"
125148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
125248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "in  vec2 Position;"
125348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
125448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "out vec2 PositionOut;"
125548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
125648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "void main() {"
125748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
125848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "    gl_Position = vec4(Position, 0.0, 1.0);"
125948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
126048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "    PositionOut = Position;"
126148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
126248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "}";
126348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
126448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
126548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const char* fsh()
126648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
126748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return "#version 400"
126848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
126948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "in  vec2 PositionOut;"
127048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
127148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "out vec4 FragColor;"
127248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
127348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "void main() {"
127448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
127548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "    if (PositionOut.x < 0.0 && PositionOut.y < 0.0)"
127648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
127748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "       FragColor = vec4(0.0, 1.0, 0.0, 1.0);"
127848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
127948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "    else"
128048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
128148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "       FragColor = vec4(1.0, 0.0, 0.0, 1.0);"
128248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "\n"
128348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "}";
128448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
128548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
128648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	qpTestResult ValidateFramebuffer(deqp::Context& context, glw::GLenum origin)
128748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
128848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const tcu::RenderTarget& renderTarget = context.getRenderContext().getRenderTarget();
128948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glw::GLuint				 windowW	  = renderTarget.getWidth();
129048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glw::GLuint				 windowH	  = renderTarget.getHeight();
129148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::Surface			 renderedFrame(windowW, windowH);
129248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::Surface			 referenceFrame(windowW, windowH);
129348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
129448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::TestLog& log = context.getTestContext().getLog();
129548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
129648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (int y = 0; y < renderedFrame.getHeight(); y++)
129748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
129848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			float yCoord   = (float)(y) / (float)renderedFrame.getHeight();
129948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			float yVPCoord = (yCoord - 0.25f) * 4.0f;
130048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
130148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (int x = 0; x < renderedFrame.getWidth(); x++)
130248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
130348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				float xCoord   = (float)(x) / (float)renderedFrame.getWidth();
130448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				float xVPCoord = (xCoord - 0.125f) * 2.0f;
130548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
130648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (xVPCoord > 0.0f && xVPCoord < 1.0f && yVPCoord > 0.0f && yVPCoord < 1.0f)
130748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
130848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
130948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					bool greenQuadrant;
131048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
131148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					//inside viewport
131248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					if (origin == GL_UPPER_LEFT)
131348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
131448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						greenQuadrant = (yVPCoord > 0.5f && xVPCoord <= 0.5f);
131548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
131648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					else
131748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
131848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						greenQuadrant = (yVPCoord <= 0.5f && xVPCoord <= 0.5f);
131948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
132048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
132148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					if (greenQuadrant)
132248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
132348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						referenceFrame.setPixel(x, y, tcu::RGBA::green());
132448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
132548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					else
132648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
132748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						referenceFrame.setPixel(x, y, tcu::RGBA::red());
132848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
132948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
133048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				else
133148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
133248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					//outside viewport
133348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					referenceFrame.setPixel(x, y, tcu::RGBA::blue());
133448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
133548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
133648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
133748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
133848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glu::readPixels(context.getRenderContext(), 0, 0, renderedFrame.getAccess());
133948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
134048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (tcu::fuzzyCompare(log, "Result", "Image comparison result", referenceFrame, renderedFrame, 0.05f,
134148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							  tcu::COMPARE_LOG_RESULT))
134248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
134348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return QP_TEST_RESULT_PASS;
134448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
134548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
134648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
134748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return QP_TEST_RESULT_FAIL;
134848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
134948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
135048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
135148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	glw::GLuint m_vao, m_vbo;
135248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
135348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
135448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosconst char* apiToTestName(ClipControlTests::API api)
135548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
135648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	switch (api)
135748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
135848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	case ClipControlTests::API_GL_45core:
135948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return "clip_control";
136048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	case ClipControlTests::API_GL_ARB_clip_control:
136148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return "clip_control_ARB";
136248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
136348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	DE_ASSERT(0);
136448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	return "";
136548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
136648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
136748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos/** Constructor.
136848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos *
136948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos *  @param context Rendering context.
137048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos **/
137148087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosClipControlTests::ClipControlTests(deqp::Context& context, API api)
137248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	: TestCaseGroup(context, apiToTestName(api), "Verifies \"clip_control\" functionality"), m_api(api)
137348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
137448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/* Left blank on purpose */
137548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
137648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
137748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos/** Destructor.
137848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos *
137948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos **/
138048087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosClipControlTests::~ClipControlTests()
138148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
138248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
138348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
138448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos/** Initializes a texture_storage_multisample test group.
138548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos *
138648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos **/
138748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosvoid ClipControlTests::init(void)
138848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
138948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new ClipControlInitialState(m_context, m_api, "initial"));
139048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new ClipControlModifyGetState(m_context, m_api, "modify_get"));
139148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new ClipControlErrors(m_context, m_api, "errors"));
139248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new ClipControlOriginTest(m_context, m_api, "origin"));
139348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new ClipControlDepthModeZeroToOneTest(m_context, m_api, "depth_mode_zero_to_one"));
139448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new ClipControlDepthModeOneToOneTest(m_context, m_api, "depth_mode_one_to_one"));
139548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new ClipControlFaceCulling(m_context, m_api, "face_culling"));
139648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new ClipControlViewportBounds(m_context, m_api, "viewport_bounds"));
139748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
139848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos} /* deqp namespace */
1399