13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program Reference Renderer
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * -----------------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Reference renderer interface.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "rrRenderer.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuVectorUtil.hpp"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTextureUtil.hpp"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuFloat.hpp"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "rrPrimitiveAssembler.hpp"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "rrFragmentOperations.hpp"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "rrRasterizer.hpp"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMemory.h"
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <set>
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace rr
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
408852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyrytypedef double ClipFloat; // floating point type used in clipping
418852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
428852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyrytypedef tcu::Vector<ClipFloat, 4> ClipVec4;
438852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct RasterizationInternalBuffers
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<FragmentPacket>		fragmentPackets;
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<GenericVec4>		shaderOutputs;
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<Fragment>			shadedFragments;
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float*							fragmentDepthBuffer;
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
523c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeUint32 readIndexArray (const IndexType type, const void* ptr, size_t ndx)
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (type)
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case INDEXTYPE_UINT8:
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return ((const deUint8*)ptr)[ndx];
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case INDEXTYPE_UINT16:
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint16 retVal;
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deMemcpy(&retVal, (const deUint8*)ptr + ndx * sizeof(deUint16), sizeof(deUint16));
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return retVal;
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case INDEXTYPE_UINT32:
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32 retVal;
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deMemcpy(&retVal, (const deUint8*)ptr + ndx * sizeof(deUint32), sizeof(deUint32));
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return retVal;
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return 0;
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytcu::IVec4 getBufferSize (const rr::MultisampleConstPixelBufferAccess& multisampleBuffer)
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tcu::IVec4(0, 0, multisampleBuffer.raw().getHeight(), multisampleBuffer.raw().getDepth());
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool isEmpty (const rr::MultisampleConstPixelBufferAccess& access)
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return access.raw().getWidth() == 0 || access.raw().getHeight() == 0 || access.raw().getDepth() == 0;
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct DrawContext
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int primitiveID;
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DrawContext (void)
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: primitiveID(0)
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Calculates intersection of two rects given as (left, bottom, width, height)
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytcu::IVec4 rectIntersection (const tcu::IVec4& a, const tcu::IVec4& b)
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec2 pos	= tcu::IVec2(de::max(a.x(), b.x()), de::max(a.y(), b.y()));
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec2 endPos	= tcu::IVec2(de::min(a.x() + a.z(), b.x() + b.z()), de::min(a.y() + a.w(), b.y() + b.w()));
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tcu::IVec4(pos.x(), pos.y(), endPos.x() - pos.x(), endPos.y() - pos.y());
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid convertPrimitiveToBaseType(std::vector<pa::Triangle>& output, std::vector<pa::Triangle>& input)
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::swap(output, input);
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid convertPrimitiveToBaseType(std::vector<pa::Line>& output, std::vector<pa::Line>& input)
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::swap(output, input);
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid convertPrimitiveToBaseType(std::vector<pa::Point>& output, std::vector<pa::Point>& input)
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::swap(output, input);
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid convertPrimitiveToBaseType(std::vector<pa::Line>& output, std::vector<pa::LineAdjacency>& input)
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	output.resize(input.size());
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (size_t i = 0; i < input.size(); ++i)
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int adjacentProvokingVertex	= input[i].provokingIndex;
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int baseProvokingVertexIndex	= adjacentProvokingVertex-1;
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		output[i] = pa::Line(input[i].v1, input[i].v2, baseProvokingVertexIndex);
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid convertPrimitiveToBaseType(std::vector<pa::Triangle>& output, std::vector<pa::TriangleAdjacency>& input)
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	output.resize(input.size());
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (size_t i = 0; i < input.size(); ++i)
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int adjacentProvokingVertex	= input[i].provokingIndex;
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int baseProvokingVertexIndex	= adjacentProvokingVertex/2;
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		output[i] = pa::Triangle(input[i].v0, input[i].v2, input[i].v4, baseProvokingVertexIndex);
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace cliputil
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Get clipped portion of the second endpoint
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
1558852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry * Calculate the intersection of line segment v0-v1 and a given plane. Line
1568852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry * segment is defined by a pair of one-dimensional homogeneous coordinates.
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
1598852c82a1ffa4760985c17cc6875d5d521daf343Jarkko PoyryClipFloat getSegmentVolumeEdgeClip (const ClipFloat v0,
1608852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry									const ClipFloat w0,
1618852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry									const ClipFloat v1,
1628852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry									const ClipFloat w1,
1638852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry									const ClipFloat plane)
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1658852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	return (plane*w0 - v0) / ((v1 - v0) - plane*(w1 - w0));
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Get clipped portion of the endpoint
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * How much (in [0-1] range) of a line segment v0-v1 would be clipped
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * of the v0 end of the line segment by clipping.
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
1748852c82a1ffa4760985c17cc6875d5d521daf343Jarkko PoyryClipFloat getLineEndpointClipping (const ClipVec4& v0, const ClipVec4& v1)
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1768852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const ClipFloat clipVolumeSize = (ClipFloat)1.0;
1778852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (v0.z() > v0.w())
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Clip +Z
1818852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		return getSegmentVolumeEdgeClip(v0.z(), v0.w(), v1.z(), v1.w(), clipVolumeSize);
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (v0.z() < -v0.w())
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Clip -Z
1868852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		return getSegmentVolumeEdgeClip(v0.z(), v0.w(), v1.z(), v1.w(), -clipVolumeSize);
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// no clipping
1918852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		return (ClipFloat)0.0;
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1958852c82a1ffa4760985c17cc6875d5d521daf343Jarkko PoyryClipVec4 vec4ToClipVec4 (const tcu::Vec4& v)
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1978852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	return ClipVec4((ClipFloat)v.x(), (ClipFloat)v.y(), (ClipFloat)v.z(), (ClipFloat)v.w());
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2008852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyrytcu::Vec4 clipVec4ToVec4 (const ClipVec4& v)
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2028852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	return tcu::Vec4((float)v.x(), (float)v.y(), (float)v.z(), (float)v.w());
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ClipVolumePlane
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
2088852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	virtual bool		pointInClipVolume			(const ClipVec4& p) const						= 0;
2098852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	virtual ClipFloat	clipLineSegmentEnd			(const ClipVec4& v0, const ClipVec4& v1) const	= 0;
2108852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	virtual ClipVec4	getLineIntersectionPoint	(const ClipVec4& v0, const ClipVec4& v1) const	= 0;
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2138852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyrytemplate <int Sign, int CompNdx>
2148852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyryclass ComponentPlane : public ClipVolumePlane
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2168852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	DE_STATIC_ASSERT(Sign == +1 || Sign == -1);
2178852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
2198852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	bool		pointInClipVolume			(const ClipVec4& p) const;
2208852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	ClipFloat	clipLineSegmentEnd			(const ClipVec4& v0, const ClipVec4& v1) const;
2218852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	ClipVec4	getLineIntersectionPoint	(const ClipVec4& v0, const ClipVec4& v1) const;
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2248852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyrytemplate <int Sign, int CompNdx>
2258852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyrybool ComponentPlane<Sign, CompNdx>::pointInClipVolume (const ClipVec4& p) const
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2278852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const ClipFloat clipVolumeSize = (ClipFloat)1.0;
2288852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
2298852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	return (ClipFloat)(Sign * p[CompNdx]) <= clipVolumeSize * p.w();
2308852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry}
2318852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
2328852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyrytemplate <int Sign, int CompNdx>
2338852c82a1ffa4760985c17cc6875d5d521daf343Jarkko PoyryClipFloat ComponentPlane<Sign, CompNdx>::clipLineSegmentEnd (const ClipVec4& v0, const ClipVec4& v1) const
2348852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry{
2358852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const ClipFloat clipVolumeSize = (ClipFloat)1.0;
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2378852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	return getSegmentVolumeEdgeClip(v0[CompNdx], v0.w(),
2388852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry									v1[CompNdx], v1.w(),
2398852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry									(ClipFloat)Sign * clipVolumeSize);
2408852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry}
2418852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
2428852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyrytemplate <int Sign, int CompNdx>
2438852c82a1ffa4760985c17cc6875d5d521daf343Jarkko PoyryClipVec4 ComponentPlane<Sign, CompNdx>::getLineIntersectionPoint (const ClipVec4& v0, const ClipVec4& v1) const
2448852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry{
2458852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	// A point on line might be far away, causing clipping ratio (clipLineSegmentEnd) to become extremely close to 1.0
2468852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	// even if the another point is not on the plane. Prevent clipping ratio from saturating by using points on line
2478852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	// that are (nearly) on this and (nearly) on the opposite plane.
2488852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
249919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry	const ClipVec4 	clippedV0	= tcu::mix(v0, v1, ComponentPlane<+1, CompNdx>().clipLineSegmentEnd(v0, v1));
250919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry	const ClipVec4 	clippedV1	= tcu::mix(v0, v1, ComponentPlane<-1, CompNdx>().clipLineSegmentEnd(v0, v1));
251919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry	const ClipFloat	clipRatio	= clipLineSegmentEnd(clippedV0, clippedV1);
252919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry
253919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry	// Find intersection point of line from v0 to v1 and the current plane. Avoid ratios near 1.0
254919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry	if (clipRatio <= (ClipFloat)0.5)
255919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		return tcu::mix(clippedV0, clippedV1, clipRatio);
256919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry	else
257919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry	{
258919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		const ClipFloat complementClipRatio = clipLineSegmentEnd(clippedV1, clippedV0);
259919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		return tcu::mix(clippedV1, clippedV0, complementClipRatio);
260919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry	}
2618852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry}
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct TriangleVertex
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2658852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	ClipVec4	position;
2668852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	ClipFloat	weight[3];		//!< barycentrics
2678852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry};
2688852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
2698852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyrystruct SubTriangle
2708852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry{
2718852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	TriangleVertex vertices[3];
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid clipTriangleOneVertex (std::vector<TriangleVertex>& clippedEdges, const ClipVolumePlane& plane, const TriangleVertex& clipped, const TriangleVertex& v1, const TriangleVertex& v2)
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2768852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const ClipFloat	degenerateLimit = (ClipFloat)1.0;
2778852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// calc clip pos
2798852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	TriangleVertex	mid1;
2808852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	TriangleVertex	mid2;
2818852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	bool			outputDegenerate = false;
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
284919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		const TriangleVertex&	inside	= v1;
285919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		const TriangleVertex&	outside	= clipped;
286919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		      TriangleVertex&	middle	= mid1;
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
288919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		const ClipFloat			hitDist	= plane.clipLineSegmentEnd(inside.position, outside.position);
2898852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
2908852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		if (hitDist >= degenerateLimit)
2918852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		{
2928852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			// do not generate degenerate triangles
2938852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			outputDegenerate = true;
2948852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		}
2958852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		else
2968852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		{
2978852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			const ClipVec4 approximatedClipPoint	= tcu::mix(inside.position, outside.position, hitDist);
2988852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			const ClipVec4 anotherPointOnLine		= (hitDist > (ClipFloat)0.5) ? (inside.position) : (outside.position);
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3008852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			middle.position = plane.getLineIntersectionPoint(approximatedClipPoint, anotherPointOnLine);
3018852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			middle.weight[0] = tcu::mix(inside.weight[0], outside.weight[0], hitDist);
3028852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			middle.weight[1] = tcu::mix(inside.weight[1], outside.weight[1], hitDist);
3038852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			middle.weight[2] = tcu::mix(inside.weight[2], outside.weight[2], hitDist);
3048852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		}
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
308919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		const TriangleVertex&	inside	= v2;
309919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		const TriangleVertex&	outside	= clipped;
310919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		      TriangleVertex&	middle	= mid2;
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
312919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		const ClipFloat			hitDist	= plane.clipLineSegmentEnd(inside.position, outside.position);
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3148852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		if (hitDist >= degenerateLimit)
3158852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		{
3168852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			// do not generate degenerate triangles
3178852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			outputDegenerate = true;
3188852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		}
3198852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		else
3208852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		{
3218852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			const ClipVec4 approximatedClipPoint	= tcu::mix(inside.position, outside.position, hitDist);
3228852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			const ClipVec4 anotherPointOnLine		= (hitDist > (ClipFloat)0.5) ? (inside.position) : (outside.position);
3238852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
3248852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			middle.position = plane.getLineIntersectionPoint(approximatedClipPoint, anotherPointOnLine);
3258852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			middle.weight[0] = tcu::mix(inside.weight[0], outside.weight[0], hitDist);
3268852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			middle.weight[1] = tcu::mix(inside.weight[1], outside.weight[1], hitDist);
3278852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			middle.weight[2] = tcu::mix(inside.weight[2], outside.weight[2], hitDist);
3288852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		}
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3318852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	if (!outputDegenerate)
3328852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	{
3338852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		// gen quad (v1) -> mid1 -> mid2 -> (v2)
3348852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		clippedEdges.push_back(v1);
3358852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		clippedEdges.push_back(mid1);
3368852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		clippedEdges.push_back(mid2);
3378852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		clippedEdges.push_back(v2);
3388852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	}
3398852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	else
3408852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	{
3418852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		// don't modify
3428852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		clippedEdges.push_back(v1);
3438852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		clippedEdges.push_back(clipped);
3448852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		clippedEdges.push_back(v2);
3458852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	}
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid clipTriangleTwoVertices (std::vector<TriangleVertex>& clippedEdges, const ClipVolumePlane& plane, const TriangleVertex& v0, const TriangleVertex& clipped1, const TriangleVertex& clipped2)
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
350919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry	const ClipFloat	unclippableLimit = (ClipFloat)1.0;
3518852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// calc clip pos
3538852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	TriangleVertex	mid1;
3548852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	TriangleVertex	mid2;
355919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry	bool			unclippableVertex1 = false;
356919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry	bool			unclippableVertex2 = false;
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
359919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		const TriangleVertex&	inside	= v0;
360919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		const TriangleVertex&	outside	= clipped1;
361919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		      TriangleVertex&	middle	= mid1;
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
363919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		const ClipFloat			hitDist	= plane.clipLineSegmentEnd(inside.position, outside.position);
3648852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
365919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		if (hitDist >= unclippableLimit)
3668852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		{
367919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry			// this edge cannot be clipped because the edge is really close to the volume boundary
368919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry			unclippableVertex1 = true;
3698852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		}
3708852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		else
3718852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		{
3728852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			const ClipVec4 approximatedClipPoint	= tcu::mix(inside.position, outside.position, hitDist);
3738852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			const ClipVec4 anotherPointOnLine		= (hitDist > (ClipFloat)0.5) ? (inside.position) : (outside.position);
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3758852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			middle.position = plane.getLineIntersectionPoint(approximatedClipPoint, anotherPointOnLine);
3768852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			middle.weight[0] = tcu::mix(inside.weight[0], outside.weight[0], hitDist);
3778852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			middle.weight[1] = tcu::mix(inside.weight[1], outside.weight[1], hitDist);
3788852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			middle.weight[2] = tcu::mix(inside.weight[2], outside.weight[2], hitDist);
3798852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		}
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
383919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		const TriangleVertex&	inside	= v0;
384919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		const TriangleVertex&	outside	= clipped2;
385919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		      TriangleVertex&	middle	= mid2;
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
387919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		const ClipFloat			hitDist	= plane.clipLineSegmentEnd(inside.position, outside.position);
3888852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
389919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		if (hitDist >= unclippableLimit)
3908852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		{
391919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry			// this edge cannot be clipped because the edge is really close to the volume boundary
392919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry			unclippableVertex2 = true;
3938852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		}
3948852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		else
3958852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		{
3968852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			const ClipVec4 approximatedClipPoint	= tcu::mix(inside.position, outside.position, hitDist);
3978852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			const ClipVec4 anotherPointOnLine		= (hitDist > (ClipFloat)0.5) ? (inside.position) : (outside.position);
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3998852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			middle.position = plane.getLineIntersectionPoint(approximatedClipPoint, anotherPointOnLine);
4008852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			middle.weight[0] = tcu::mix(inside.weight[0], outside.weight[0], hitDist);
4018852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			middle.weight[1] = tcu::mix(inside.weight[1], outside.weight[1], hitDist);
4028852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			middle.weight[2] = tcu::mix(inside.weight[2], outside.weight[2], hitDist);
4038852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		}
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
406919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry	if (!unclippableVertex1 && !unclippableVertex2)
4078852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	{
4088852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		// gen triangle (v0) -> mid1 -> mid2
4098852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		clippedEdges.push_back(v0);
4108852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		clippedEdges.push_back(mid1);
4118852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		clippedEdges.push_back(mid2);
4128852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	}
413919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry	else if (!unclippableVertex1 && unclippableVertex2)
414919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry	{
415919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		// clip just vertex 1
416919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		clippedEdges.push_back(v0);
417919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		clippedEdges.push_back(mid1);
418919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		clippedEdges.push_back(clipped2);
419919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry	}
420919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry	else if (unclippableVertex1 && !unclippableVertex2)
421919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry	{
422919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		// clip just vertex 2
423919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		clippedEdges.push_back(v0);
424919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		clippedEdges.push_back(clipped1);
425919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry		clippedEdges.push_back(mid2);
426919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry	}
4278852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	else
4288852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	{
4298852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		// don't modify
4308852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		clippedEdges.push_back(v0);
4318852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		clippedEdges.push_back(clipped1);
4328852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		clippedEdges.push_back(clipped2);
4338852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	}
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid clipTriangleToPlane (std::vector<TriangleVertex>& clippedEdges, const TriangleVertex* vertices, const ClipVolumePlane& plane)
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4388852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const bool v0Clipped = !plane.pointInClipVolume(vertices[0].position);
4398852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const bool v1Clipped = !plane.pointInClipVolume(vertices[1].position);
4408852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const bool v2Clipped = !plane.pointInClipVolume(vertices[2].position);
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int  clipCount = ((v0Clipped) ? (1) : (0)) + ((v1Clipped) ? (1) : (0)) + ((v2Clipped) ? (1) : (0));
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (clipCount == 0)
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// pass
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		clippedEdges.insert(clippedEdges.begin(), vertices, vertices + 3);
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (clipCount == 1)
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// clip one vertex
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (v0Clipped)			clipTriangleOneVertex(clippedEdges, plane, vertices[0], vertices[1], vertices[2]);
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (v1Clipped)		clipTriangleOneVertex(clippedEdges, plane, vertices[1], vertices[2], vertices[0]);
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else					clipTriangleOneVertex(clippedEdges, plane, vertices[2], vertices[0], vertices[1]);
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (clipCount == 2)
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// clip two vertices
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!v0Clipped)			clipTriangleTwoVertices(clippedEdges, plane, vertices[0], vertices[1], vertices[2]);
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (!v1Clipped)	clipTriangleTwoVertices(clippedEdges, plane, vertices[1], vertices[2], vertices[0]);
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else					clipTriangleTwoVertices(clippedEdges, plane, vertices[2], vertices[0], vertices[1]);
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (clipCount == 3)
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// discard
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // cliputil
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4748852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyrytcu::Vec2 to2DCartesian (const tcu::Vec4& p)
4758852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry{
4768852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	return tcu::Vec2(p.x(), p.y()) / p.w();
4778852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry}
4788852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
4798852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyryfloat cross2D (const tcu::Vec2& a, const tcu::Vec2& b)
4808852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry{
4818852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	return tcu::cross(tcu::Vec3(a.x(), a.y(), 0.0f), tcu::Vec3(b.x(), b.y(), 0.0f)).z();
4828852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry}
4838852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid flatshadePrimitiveVertices (pa::Triangle& target, size_t outputNdx)
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const rr::GenericVec4 flatValue = target.getProvokingVertex()->outputs[outputNdx];
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	target.v0->outputs[outputNdx] = flatValue;
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	target.v1->outputs[outputNdx] = flatValue;
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	target.v2->outputs[outputNdx] = flatValue;
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid flatshadePrimitiveVertices (pa::Line& target, size_t outputNdx)
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const rr::GenericVec4 flatValue = target.getProvokingVertex()->outputs[outputNdx];
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	target.v0->outputs[outputNdx] = flatValue;
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	target.v1->outputs[outputNdx] = flatValue;
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid flatshadePrimitiveVertices (pa::Point& target, size_t outputNdx)
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(target);
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(outputNdx);
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename ContainerType>
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid flatshadeVertices (const Program& program, ContainerType& list)
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// flatshade
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const std::vector<rr::VertexVaryingInfo>& fragInputs = (program.geometryShader) ? (program.geometryShader->getOutputs()) : (program.vertexShader->getOutputs());
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (size_t inputNdx = 0; inputNdx < fragInputs.size(); ++inputNdx)
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (fragInputs[inputNdx].flatshade)
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (typename ContainerType::iterator it = list.begin(); it != list.end(); ++it)
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				flatshadePrimitiveVertices(*it, inputNdx);
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5178852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry/*--------------------------------------------------------------------*//*!
5188852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry * Clip triangles to the clip volume.
5198852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry *//*--------------------------------------------------------------------*/
5208852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyryvoid clipPrimitives (std::vector<pa::Triangle>&		list,
5218852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					 const Program&					program,
5228852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					 bool							clipWithZPlanes,
5238852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					 VertexPacketAllocator&			vpalloc)
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using namespace cliputil;
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5278852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	cliputil::ComponentPlane<+1, 0> clipPosX;
5288852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	cliputil::ComponentPlane<-1, 0> clipNegX;
5298852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	cliputil::ComponentPlane<+1, 1> clipPosY;
5308852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	cliputil::ComponentPlane<-1, 1> clipNegY;
5318852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	cliputil::ComponentPlane<+1, 2> clipPosZ;
5328852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	cliputil::ComponentPlane<-1, 2> clipNegZ;
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const std::vector<rr::VertexVaryingInfo>&	fragInputs			= (program.geometryShader) ? (program.geometryShader->getOutputs()) : (program.vertexShader->getOutputs());
5358852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const ClipVolumePlane*						planes[]			= { &clipPosX, &clipNegX, &clipPosY, &clipNegY, &clipPosZ, &clipNegZ };
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int									numPlanes			= (clipWithZPlanes) ? (6) : (4);
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5388852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	std::vector<pa::Triangle>					outputTriangles;
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5408852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	for (int inputTriangleNdx = 0; inputTriangleNdx < (int)list.size(); ++inputTriangleNdx)
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5428852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		bool clippedByPlane[6];
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5448852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		// Needs clipping?
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5468852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			bool discardPrimitive	= false;
5478852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			bool fullyInClipVolume	= true;
5488852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
5498852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			for (int planeNdx = 0; planeNdx < numPlanes; ++planeNdx)
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
5518852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				const ClipVolumePlane*	plane			= planes[planeNdx];
5528852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				const bool				v0InsidePlane	= plane->pointInClipVolume(vec4ToClipVec4(list[inputTriangleNdx].v0->position));
5538852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				const bool				v1InsidePlane	= plane->pointInClipVolume(vec4ToClipVec4(list[inputTriangleNdx].v1->position));
5548852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				const bool				v2InsidePlane	= plane->pointInClipVolume(vec4ToClipVec4(list[inputTriangleNdx].v2->position));
5558852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
5568852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				// Fully outside
5578852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				if (!v0InsidePlane && !v1InsidePlane && !v2InsidePlane)
5588852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				{
5598852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					discardPrimitive = true;
5608852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					break;
5618852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				}
5628852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				// Partially outside
5638852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				else if (!v0InsidePlane || !v1InsidePlane || !v2InsidePlane)
5648852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				{
5658852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					clippedByPlane[planeNdx] = true;
5668852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					fullyInClipVolume = false;
5678852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				}
5688852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				// Fully inside
5698852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				else
5708852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					clippedByPlane[planeNdx] = false;
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5738852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			if (discardPrimitive)
5748852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				continue;
5758852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
5768852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			if (fullyInClipVolume)
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
5788852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				outputTriangles.push_back(list[inputTriangleNdx]);
5798852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				continue;
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
5818852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		}
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5838852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		// Clip
5848852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		{
5858852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			std::vector<SubTriangle>	subTriangles	(1);
5868852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			SubTriangle&				initialTri		= subTriangles[0];
5878852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
5888852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			initialTri.vertices[0].position = vec4ToClipVec4(list[inputTriangleNdx].v0->position);
5898852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			initialTri.vertices[0].weight[0] = (ClipFloat)1.0;
5908852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			initialTri.vertices[0].weight[1] = (ClipFloat)0.0;
5918852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			initialTri.vertices[0].weight[2] = (ClipFloat)0.0;
5928852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
5938852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			initialTri.vertices[1].position = vec4ToClipVec4(list[inputTriangleNdx].v1->position);
5948852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			initialTri.vertices[1].weight[0] = (ClipFloat)0.0;
5958852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			initialTri.vertices[1].weight[1] = (ClipFloat)1.0;
5968852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			initialTri.vertices[1].weight[2] = (ClipFloat)0.0;
5978852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
5988852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			initialTri.vertices[2].position = vec4ToClipVec4(list[inputTriangleNdx].v2->position);
5998852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			initialTri.vertices[2].weight[0] = (ClipFloat)0.0;
6008852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			initialTri.vertices[2].weight[1] = (ClipFloat)0.0;
6018852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			initialTri.vertices[2].weight[2] = (ClipFloat)1.0;
6028852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
6038852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			// Clip all subtriangles to all relevant planes
6048852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			for (int planeNdx = 0; planeNdx < numPlanes; ++planeNdx)
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
6068852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				std::vector<SubTriangle> nextPhaseSubTriangles;
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6088852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				if (!clippedByPlane[planeNdx])
6098852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					continue;
6108852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
6118852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				for (int subTriangleNdx = 0; subTriangleNdx < (int)subTriangles.size(); ++subTriangleNdx)
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
6138852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					std::vector<TriangleVertex> convexPrimitive;
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
615919f1341e41b3a1e31f5746b30db0f648c47b757Jarkko Pöyry					// Clip triangle and form a convex n-gon ( n c {3, 4} )
6168852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					clipTriangleToPlane(convexPrimitive, subTriangles[subTriangleNdx].vertices, *planes[planeNdx]);
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6188852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					// Subtriangle completely discarded
6198852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					if (convexPrimitive.empty())
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						continue;
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6228852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					DE_ASSERT(convexPrimitive.size() == 3 || convexPrimitive.size() == 4);
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6248852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					//Triangulate planar convex n-gon
6258852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					{
6268852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						TriangleVertex& v0 = convexPrimitive[0];
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6288852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						for (int subsubTriangleNdx = 1; subsubTriangleNdx + 1 < (int)convexPrimitive.size(); ++subsubTriangleNdx)
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						{
6308852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							const float				degenerateEpsilon	= 1.0e-6f;
6318852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							const TriangleVertex&	v1					= convexPrimitive[subsubTriangleNdx];
6328852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							const TriangleVertex&	v2					= convexPrimitive[subsubTriangleNdx + 1];
6338852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							const float				visibleArea			= de::abs(cross2D(to2DCartesian(clipVec4ToVec4(v1.position)) - to2DCartesian(clipVec4ToVec4(v0.position)),
6348852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry																						  to2DCartesian(clipVec4ToVec4(v2.position)) - to2DCartesian(clipVec4ToVec4(v0.position))));
6358852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
6368852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							// has surface area (is not a degenerate)
6378852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							if (visibleArea >= degenerateEpsilon)
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							{
6398852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry								SubTriangle subsubTriangle;
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6418852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry								subsubTriangle.vertices[0] = v0;
6428852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry								subsubTriangle.vertices[1] = v1;
6438852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry								subsubTriangle.vertices[2] = v2;
6448852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
6458852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry								nextPhaseSubTriangles.push_back(subsubTriangle);
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							}
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						}
6488852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					}
6498852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				}
6508852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
6518852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				subTriangles.swap(nextPhaseSubTriangles);
6528852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			}
6538852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
6548852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			// Rebuild pa::Triangles from subtriangles
6558852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			for (int subTriangleNdx = 0; subTriangleNdx < (int)subTriangles.size(); ++subTriangleNdx)
6568852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			{
6578852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				VertexPacket*	p0				= vpalloc.alloc();
6588852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				VertexPacket*	p1				= vpalloc.alloc();
6598852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				VertexPacket*	p2				= vpalloc.alloc();
6608852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				pa::Triangle	ngonFragment	(p0, p1, p2, -1);
6618852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
6628852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				p0->position = clipVec4ToVec4(subTriangles[subTriangleNdx].vertices[0].position);
6638852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				p1->position = clipVec4ToVec4(subTriangles[subTriangleNdx].vertices[1].position);
6648852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				p2->position = clipVec4ToVec4(subTriangles[subTriangleNdx].vertices[2].position);
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6668852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				for (size_t outputNdx = 0; outputNdx < fragInputs.size(); ++outputNdx)
6678852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				{
6688852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					if (fragInputs[outputNdx].type == GENERICVECTYPE_FLOAT)
6698852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					{
6708852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						const tcu::Vec4 out0 = list[inputTriangleNdx].v0->outputs[outputNdx].get<float>();
6718852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						const tcu::Vec4 out1 = list[inputTriangleNdx].v1->outputs[outputNdx].get<float>();
6728852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						const tcu::Vec4 out2 = list[inputTriangleNdx].v2->outputs[outputNdx].get<float>();
6738852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
6748852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						p0->outputs[outputNdx] = (float)subTriangles[subTriangleNdx].vertices[0].weight[0] * out0
6758852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry											   + (float)subTriangles[subTriangleNdx].vertices[0].weight[1] * out1
6768852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry											   + (float)subTriangles[subTriangleNdx].vertices[0].weight[2] * out2;
6778852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
6788852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						p1->outputs[outputNdx] = (float)subTriangles[subTriangleNdx].vertices[1].weight[0] * out0
6798852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry											   + (float)subTriangles[subTriangleNdx].vertices[1].weight[1] * out1
6808852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry											   + (float)subTriangles[subTriangleNdx].vertices[1].weight[2] * out2;
6818852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
6828852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						p2->outputs[outputNdx] = (float)subTriangles[subTriangleNdx].vertices[2].weight[0] * out0
6838852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry											   + (float)subTriangles[subTriangleNdx].vertices[2].weight[1] * out1
6848852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry											   + (float)subTriangles[subTriangleNdx].vertices[2].weight[2] * out2;
6858852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					}
6868852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					else
6878852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					{
6888852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						// only floats are interpolated, all others must be flatshaded then
6898852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						p0->outputs[outputNdx] = list[inputTriangleNdx].getProvokingVertex()->outputs[outputNdx];
6908852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						p1->outputs[outputNdx] = list[inputTriangleNdx].getProvokingVertex()->outputs[outputNdx];
6918852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						p2->outputs[outputNdx] = list[inputTriangleNdx].getProvokingVertex()->outputs[outputNdx];
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
6948852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
6958852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				outputTriangles.push_back(ngonFragment);
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7008852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	// output result
7018852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	list.swap(outputTriangles);
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7048852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry/*--------------------------------------------------------------------*//*!
7058852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry * Clip lines to the near and far clip planes.
7068852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry *
7078852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry * Clipping to other planes is a by-product of the viewport test  (i.e.
7088852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry * rasterization area selection).
7098852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry *//*--------------------------------------------------------------------*/
7108852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyryvoid clipPrimitives (std::vector<pa::Line>& 		list,
7118852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					 const Program& 				program,
7128852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					 bool 							clipWithZPlanes,
7138852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					 VertexPacketAllocator&			vpalloc)
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(vpalloc);
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using namespace cliputil;
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Lines are clipped only by the far and the near planes here. Line clipping by other planes done in the rasterization phase
7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const std::vector<rr::VertexVaryingInfo>&	fragInputs	= (program.geometryShader) ? (program.geometryShader->getOutputs()) : (program.vertexShader->getOutputs());
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<pa::Line>						visibleLines;
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Z-clipping disabled, don't do anything
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!clipWithZPlanes)
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return;
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (size_t ndx = 0; ndx < list.size(); ++ndx)
7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pa::Line& l = list[ndx];
7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Totally discarded?
7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if ((l.v0->position.z() < -l.v0->position.w() && l.v1->position.z() < -l.v1->position.w()) ||
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			(l.v0->position.z() >  l.v0->position.w() && l.v1->position.z() >  l.v1->position.w()))
7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			continue; // discard
7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Something is visible
7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7398852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		const ClipVec4	p0	= vec4ToClipVec4(l.v0->position);
7408852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		const ClipVec4	p1	= vec4ToClipVec4(l.v1->position);
7418852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		const ClipFloat	t0	= getLineEndpointClipping(p0, p1);
7428852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		const ClipFloat	t1	= getLineEndpointClipping(p1, p0);
7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Not clipped at all?
7458852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		if (t0 == (ClipFloat)0.0 && t1 == (ClipFloat)0.0)
7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			visibleLines.push_back(pa::Line(l.v0, l.v1, -1));
7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Clip position
7528852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			l.v0->position = clipVec4ToVec4(tcu::mix(p0, p1, t0));
7538852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			l.v1->position = clipVec4ToVec4(tcu::mix(p1, p0, t1));
7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Clip attributes
7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (size_t outputNdx = 0; outputNdx < fragInputs.size(); ++outputNdx)
7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// only floats are clipped, other types are flatshaded
7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (fragInputs[outputNdx].type == GENERICVECTYPE_FLOAT)
7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
7618852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					const tcu::Vec4 a0 = l.v0->outputs[outputNdx].get<float>();
7628852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					const tcu::Vec4 a1 = l.v1->outputs[outputNdx].get<float>();
7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7648852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					l.v0->outputs[outputNdx] = tcu::mix(a0, a1, (float)t0);
7658852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					l.v1->outputs[outputNdx] = tcu::mix(a1, a0, (float)t1);
7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			visibleLines.push_back(pa::Line(l.v0, l.v1, -1));
7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// return visible in list
7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::swap(visibleLines, list);
7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7778852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry/*--------------------------------------------------------------------*//*!
7788852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry * Discard points not within clip volume. Clipping is a by-product
7798852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry * of the viewport test.
7808852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry *//*--------------------------------------------------------------------*/
7818852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyryvoid clipPrimitives (std::vector<pa::Point>&		list,
7828852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					 const Program&					program,
7838852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					 bool							clipWithZPlanes,
7848852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					 VertexPacketAllocator&			vpalloc)
7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(vpalloc);
7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(program);
7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<pa::Point> visiblePoints;
7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Z-clipping disabled, don't do anything
7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!clipWithZPlanes)
7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return;
7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (size_t ndx = 0; ndx < list.size(); ++ndx)
7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pa::Point& p = list[ndx];
7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// points are discarded if Z is not in range. (Wide) point clipping is done in the rasterization phase
8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (de::inRange(p.v0->position.z(), -p.v0->position.w(), p.v0->position.w()))
8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			visiblePoints.push_back(pa::Point(p.v0));
8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// return visible in list
8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::swap(visiblePoints, list);
8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid transformVertexClipCoordsToWindowCoords (const RenderState& state, VertexPacket& packet)
8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// To normalized device coords
8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		packet.position = tcu::Vec4(packet.position.x()/packet.position.w(),
8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									packet.position.y()/packet.position.w(),
8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									packet.position.z()/packet.position.w(),
8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									1.0f               /packet.position.w());
8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// To window coords
8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const WindowRectangle&	viewport	= state.viewport.rect;
8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float				halfW		= (float)(viewport.width) / 2.0f;
8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float				halfH		= (float)(viewport.height) / 2.0f;
8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float				oX			= (float)viewport.left + halfW;
8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float				oY			= (float)viewport.bottom + halfH;
8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float				zn			= state.viewport.zn;
8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float				zf			= state.viewport.zf;
8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		packet.position = tcu::Vec4(packet.position.x()*halfW + oX,
8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									packet.position.y()*halfH + oY,
8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									packet.position.z()*(zf - zn)/2.0f + (zn + zf)/2.0f,
8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									packet.position.w());
8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid transformPrimitiveClipCoordsToWindowCoords (const RenderState& state, pa::Triangle& target)
8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	transformVertexClipCoordsToWindowCoords(state, *target.v0);
8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	transformVertexClipCoordsToWindowCoords(state, *target.v1);
8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	transformVertexClipCoordsToWindowCoords(state, *target.v2);
8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid transformPrimitiveClipCoordsToWindowCoords (const RenderState& state, pa::Line& target)
8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	transformVertexClipCoordsToWindowCoords(state, *target.v0);
8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	transformVertexClipCoordsToWindowCoords(state, *target.v1);
8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid transformPrimitiveClipCoordsToWindowCoords (const RenderState& state, pa::Point& target)
8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	transformVertexClipCoordsToWindowCoords(state, *target.v0);
8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename ContainerType>
8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid transformClipCoordsToWindowCoords (const RenderState& state, ContainerType& list)
8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (typename ContainerType::iterator it = list.begin(); it != list.end(); ++it)
8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		transformPrimitiveClipCoordsToWindowCoords(state, *it);
8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid makeSharedVerticeDistinct (VertexPacket*& packet, std::set<VertexPacket*, std::less<void*> >& vertices, VertexPacketAllocator& vpalloc)
8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// distinct
8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (vertices.find(packet) == vertices.end())
8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vertices.insert(packet);
8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		VertexPacket* newPacket = vpalloc.alloc();
8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// copy packet output values
8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		newPacket->position		= packet->position;
8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		newPacket->pointSize	= packet->pointSize;
8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		newPacket->primitiveID	= packet->primitiveID;
8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (size_t outputNdx = 0; outputNdx < vpalloc.getNumVertexOutputs(); ++outputNdx)
8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			newPacket->outputs[outputNdx] = packet->outputs[outputNdx];
8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// no need to insert new packet to "vertices" as newPacket is unique
8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		packet = newPacket;
8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid makeSharedVerticesDistinct (pa::Triangle& target, std::set<VertexPacket*, std::less<void*> >& vertices, VertexPacketAllocator& vpalloc)
8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	makeSharedVerticeDistinct(target.v0, vertices, vpalloc);
8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	makeSharedVerticeDistinct(target.v1, vertices, vpalloc);
8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	makeSharedVerticeDistinct(target.v2, vertices, vpalloc);
8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid makeSharedVerticesDistinct (pa::Line& target, std::set<VertexPacket*, std::less<void*> >& vertices, VertexPacketAllocator& vpalloc)
8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	makeSharedVerticeDistinct(target.v0, vertices, vpalloc);
8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	makeSharedVerticeDistinct(target.v1, vertices, vpalloc);
8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid makeSharedVerticesDistinct (pa::Point& target, std::set<VertexPacket*, std::less<void*> >& vertices, VertexPacketAllocator& vpalloc)
8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	makeSharedVerticeDistinct(target.v0, vertices, vpalloc);
9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename ContainerType>
9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid makeSharedVerticesDistinct (ContainerType& list, VertexPacketAllocator& vpalloc)
9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::set<VertexPacket*, std::less<void*> > vertices;
9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (typename ContainerType::iterator it = list.begin(); it != list.end(); ++it)
9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		makeSharedVerticesDistinct(*it, vertices, vpalloc);
9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9113c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid generatePrimitiveIDs (pa::Triangle& target, int id)
9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	target.v0->primitiveID = id;
9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	target.v1->primitiveID = id;
9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	target.v2->primitiveID = id;
9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid generatePrimitiveIDs (pa::Line& target, int id)
9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	target.v0->primitiveID = id;
9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	target.v1->primitiveID = id;
9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid generatePrimitiveIDs (pa::Point& target, int id)
9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	target.v0->primitiveID = id;
9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename ContainerType>
9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid generatePrimitiveIDs (ContainerType& list, DrawContext& drawContext)
9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (typename ContainerType::iterator it = list.begin(); it != list.end(); ++it)
9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		generatePrimitiveIDs(*it, drawContext.primitiveID++);
9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic float findTriangleVertexDepthSlope (const tcu::Vec4& p, const tcu::Vec4& v0, const tcu::Vec4& v1)
9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// screen space
9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3 ssp		=  p.swizzle(0, 1, 2);
9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3 ssv0	= v0.swizzle(0, 1, 2);
9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3 ssv1	= v1.swizzle(0, 1, 2);
9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// dx & dy
9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3 a		= ssv0.swizzle(0,1,2) - ssp.swizzle(0,1,2);
9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3 b		= ssv1.swizzle(0,1,2) - ssp.swizzle(0,1,2);
9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		epsilon	= 0.0001f;
9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		det		= (a.x() * b.y() - b.x() * a.y());
9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// degenerate triangle, it won't generate any fragments anyway. Return value doesn't matter
9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (de::abs(det) < epsilon)
9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 0.0f;
9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2	dxDir	= tcu::Vec2( b.y(), -a.y()) / det;
9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2	dyDir	= tcu::Vec2(-b.x(),  a.x()) / det;
9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		dzdx	= dxDir.x() * a.z() + dxDir.y() * b.z();
9583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		dzdy	= dyDir.x() * a.z() + dyDir.y() * b.z();
9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// approximate using max(|dz/dx|, |dz/dy|)
9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return de::max(de::abs(dzdx), de::abs(dzdy));
9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic float findPrimitiveMaximumDepthSlope (const pa::Triangle& triangle)
9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float d1 = findTriangleVertexDepthSlope(triangle.v0->position, triangle.v1->position, triangle.v2->position);
9673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float d2 = findTriangleVertexDepthSlope(triangle.v1->position, triangle.v2->position, triangle.v0->position);
9683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float d3 = findTriangleVertexDepthSlope(triangle.v2->position, triangle.v0->position, triangle.v1->position);
9693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return de::max(d1, de::max(d2, d3));
9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic float getFloatingPointMinimumResolvableDifference (float maxZValue, tcu::TextureFormat::ChannelType type)
9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (type == tcu::TextureFormat::FLOAT)
9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// 32f
9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int maxExponent = tcu::Float32(maxZValue).exponent();
9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return tcu::Float32::construct(+1, maxExponent - 23, 1 << 23).asFloat();
9803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// unexpected format
9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(false);
9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return 0.0f;
9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic float getFixedPointMinimumResolvableDifference (int numBits)
9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tcu::Float32::construct(+1, -numBits, 1 << 23).asFloat();
9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic float findPrimitiveMinimumResolvableDifference (const pa::Triangle& triangle, const rr::MultisampleConstPixelBufferAccess& depthAccess)
9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float								maxZvalue		= de::max(de::max(triangle.v0->position.z(), triangle.v1->position.z()), triangle.v2->position.z());
9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::TextureFormat				format			= depthAccess.raw().getFormat();
9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::TextureFormat::ChannelOrder	order			= format.order;
9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (order == tcu::TextureFormat::D)
9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// depth only
10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::TextureFormat::ChannelType	channelType		= format.type;
10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::TextureChannelClass			channelClass	= tcu::getTextureChannelClass(channelType);
10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int								numBits			= tcu::getTextureFormatBitDepth(format).x();
10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return getFloatingPointMinimumResolvableDifference(maxZvalue, channelType);
10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// \note channelClass might be CLASS_LAST but that's ok
10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return getFixedPointMinimumResolvableDifference(numBits);
10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (order == tcu::TextureFormat::DS)
10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// depth stencil, special cases for possible combined formats
10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (format.type == tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV)
10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return getFloatingPointMinimumResolvableDifference(maxZvalue, tcu::TextureFormat::FLOAT);
10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (format.type == tcu::TextureFormat::UNSIGNED_INT_24_8)
10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return getFixedPointMinimumResolvableDifference(24);
10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// unexpected format
10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(false);
10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return 0.0f;
10233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10258852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyryvoid writeFragmentPackets (const RenderState&					state,
10268852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						   const RenderTarget&					renderTarget,
10278852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						   const Program&						program,
10288852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						   const FragmentPacket*				fragmentPackets,
10298852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						   int									numRasterizedPackets,
10308852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						   rr::FaceType							facetype,
10318852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						   const std::vector<rr::GenericVec4>&	fragmentOutputArray,
10328852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						   const float*							depthValues,
10338852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						   std::vector<Fragment>&				fragmentBuffer)
10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			numSamples		= renderTarget.colorBuffers[0].getNumSamples();
10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const size_t		numOutputs		= program.fragmentShader->getOutputs().size();
10373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FragmentProcessor	fragProcessor;
10383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(fragmentOutputArray.size() >= (size_t)numRasterizedPackets*4*numOutputs);
10403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(fragmentBuffer.size()      >= (size_t)numRasterizedPackets*4);
10413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Translate fragments but do not set the value yet
10433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int	fragCount = 0;
10453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int packetNdx = 0; packetNdx < numRasterizedPackets; ++packetNdx)
10463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int fragNdx = 0; fragNdx < 4; fragNdx++)
10473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
10483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const FragmentPacket&	packet	= fragmentPackets[packetNdx];
10493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int				xo		= fragNdx%2;
10503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int				yo		= fragNdx/2;
10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (getCoverageAnyFragmentSampleLive(packet.coverage, numSamples, xo, yo))
10533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
10543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				Fragment& fragment		= fragmentBuffer[fragCount++];
10553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				fragment.pixelCoord		= packet.position + tcu::IVec2(xo, yo);
10573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				fragment.coverage		= (deUint32)((packet.coverage & getCoverageFragmentSampleBits(numSamples, xo, yo)) >> getCoverageOffset(numSamples, xo, yo));
10583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				fragment.sampleDepths	= (depthValues) ? (&depthValues[(packetNdx*4 + yo*2 + xo)*numSamples]) : (DE_NULL);
10593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
10603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
10613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Set per output output values
10643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		rr::FragmentOperationState noStencilDepthWriteState(state.fragOps);
10663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		noStencilDepthWriteState.depthMask						= false;
10673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		noStencilDepthWriteState.stencilStates[facetype].sFail	= STENCILOP_KEEP;
10683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		noStencilDepthWriteState.stencilStates[facetype].dpFail	= STENCILOP_KEEP;
10693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		noStencilDepthWriteState.stencilStates[facetype].dpPass	= STENCILOP_KEEP;
10703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int	fragCount = 0;
10723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (size_t outputNdx = 0; outputNdx < numOutputs; ++outputNdx)
10733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
10743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Only the last output-pass has default state, other passes have stencil & depth writemask=0
10753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const rr::FragmentOperationState& fragOpsState = (outputNdx == numOutputs-1) ? (state.fragOps) : (noStencilDepthWriteState);
10763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int packetNdx = 0; packetNdx < numRasterizedPackets; ++packetNdx)
10783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int fragNdx = 0; fragNdx < 4; fragNdx++)
10793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
10803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const FragmentPacket&	packet	= fragmentPackets[packetNdx];
10813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int				xo		= fragNdx%2;
10823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int				yo		= fragNdx/2;
10833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Add only fragments that have live samples to shaded fragments queue.
10853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (getCoverageAnyFragmentSampleLive(packet.coverage, numSamples, xo, yo))
10863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
10873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					Fragment& fragment		= fragmentBuffer[fragCount++];
10883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					fragment.value			= fragmentOutputArray[(packetNdx*4 + fragNdx) * numOutputs + outputNdx];
10893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
10903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
10913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Execute per-fragment ops and write
10933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			fragProcessor.render(renderTarget.colorBuffers[outputNdx], renderTarget.depthBuffer, renderTarget.stencilBuffer, &fragmentBuffer[0], fragCount, facetype, fragOpsState);
10943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
10953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10988852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyryvoid rasterizePrimitive (const RenderState&					state,
10998852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						 const RenderTarget&				renderTarget,
11008852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						 const Program&						program,
11018852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						 const pa::Triangle&				triangle,
11028852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						 const tcu::IVec4&					renderTargetRect,
11038852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						 RasterizationInternalBuffers&		buffers)
11043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			numSamples		= renderTarget.colorBuffers[0].getNumSamples();
11063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			depthClampMin	= de::min(state.viewport.zn, state.viewport.zf);
11073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			depthClampMax	= de::max(state.viewport.zn, state.viewport.zf);
11083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TriangleRasterizer	rasterizer		(renderTargetRect, numSamples, state.rasterization);
11093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float				depthOffset		= 0.0f;
11103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	rasterizer.init(triangle.v0->position, triangle.v1->position, triangle.v2->position);
11123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Culling
11143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const FaceType visibleFace = rasterizer.getVisibleFace();
11153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if ((state.cullMode == CULLMODE_FRONT	&& visibleFace == FACETYPE_FRONT) ||
11163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		(state.cullMode == CULLMODE_BACK	&& visibleFace == FACETYPE_BACK))
11173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return;
11183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Shading context
11203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FragmentShadingContext shadingContext(triangle.v0->outputs, triangle.v1->outputs, triangle.v2->outputs, &buffers.shaderOutputs[0], buffers.fragmentDepthBuffer, triangle.v2->primitiveID, (int)program.fragmentShader->getOutputs().size(), numSamples);
11213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Polygon offset
11233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (buffers.fragmentDepthBuffer && state.fragOps.polygonOffsetEnabled)
11243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float maximumDepthSlope			= findPrimitiveMaximumDepthSlope(triangle);
11263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float minimumResolvableDifference	= findPrimitiveMinimumResolvableDifference(triangle, renderTarget.depthBuffer);
11273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		depthOffset = maximumDepthSlope * state.fragOps.polygonOffsetFactor + minimumResolvableDifference * state.fragOps.polygonOffsetUnits;
11293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Execute rasterize - shade - write loop
11323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (;;)
11333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	maxFragmentPackets		= (int)buffers.fragmentPackets.size();
11353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int			numRasterizedPackets	= 0;
11363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Rasterize
11383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		rasterizer.rasterize(&buffers.fragmentPackets[0], buffers.fragmentDepthBuffer, maxFragmentPackets, numRasterizedPackets);
11403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// numRasterizedPackets is guaranteed to be greater than zero for shadeFragments()
11423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!numRasterizedPackets)
11443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break; // Rasterization finished.
11453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Polygon offset
11473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (buffers.fragmentDepthBuffer && state.fragOps.polygonOffsetEnabled)
11483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int sampleNdx = 0; sampleNdx < numRasterizedPackets * 4 * numSamples; ++sampleNdx)
11493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				buffers.fragmentDepthBuffer[sampleNdx] = de::clamp(buffers.fragmentDepthBuffer[sampleNdx] + depthOffset, 0.0f, 1.0f);
11503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Shade
11523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		program.fragmentShader->shadeFragments(&buffers.fragmentPackets[0], numRasterizedPackets, shadingContext);
11543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Depth clamp
11563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (buffers.fragmentDepthBuffer && state.fragOps.depthClampEnabled)
11573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int sampleNdx = 0; sampleNdx < numRasterizedPackets * 4 * numSamples; ++sampleNdx)
11583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				buffers.fragmentDepthBuffer[sampleNdx] = de::clamp(buffers.fragmentDepthBuffer[sampleNdx], depthClampMin, depthClampMax);
11593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Handle fragment shader outputs
11613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		writeFragmentPackets(state, renderTarget, program, &buffers.fragmentPackets[0], numRasterizedPackets, visibleFace, buffers.shaderOutputs, buffers.fragmentDepthBuffer, buffers.shadedFragments);
11633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11668852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyryvoid rasterizePrimitive (const RenderState&					state,
11678852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						 const RenderTarget&				renderTarget,
11688852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						 const Program&						program,
11698852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						 const pa::Line&					line,
11708852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						 const tcu::IVec4&					renderTargetRect,
11718852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						 RasterizationInternalBuffers&		buffers)
11723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int					numSamples			= renderTarget.colorBuffers[0].getNumSamples();
11743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float					depthClampMin		= de::min(state.viewport.zn, state.viewport.zf);
11753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float					depthClampMax		= de::max(state.viewport.zn, state.viewport.zf);
11763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool					msaa				= numSamples > 1;
11773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FragmentShadingContext		shadingContext		(line.v0->outputs, line.v1->outputs, DE_NULL, &buffers.shaderOutputs[0], buffers.fragmentDepthBuffer, line.v1->primitiveID, (int)program.fragmentShader->getOutputs().size(), numSamples);
11783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SingleSampleLineRasterizer	aliasedRasterizer	(renderTargetRect);
11793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MultiSampleLineRasterizer	msaaRasterizer		(numSamples, renderTargetRect);
11803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Initialize rasterization.
11823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (msaa)
11833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		msaaRasterizer.init(line.v0->position, line.v1->position, state.line.lineWidth);
11843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
11853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		aliasedRasterizer.init(line.v0->position, line.v1->position, state.line.lineWidth);
11863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (;;)
11883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	maxFragmentPackets		= (int)buffers.fragmentPackets.size();
11903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int			numRasterizedPackets	= 0;
11913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Rasterize
11933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (msaa)
11953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			msaaRasterizer.rasterize	(&buffers.fragmentPackets[0], buffers.fragmentDepthBuffer, maxFragmentPackets, numRasterizedPackets);
11963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
11973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			aliasedRasterizer.rasterize	(&buffers.fragmentPackets[0], buffers.fragmentDepthBuffer, maxFragmentPackets, numRasterizedPackets);
11983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// numRasterizedPackets is guaranteed to be greater than zero for shadeFragments()
12003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!numRasterizedPackets)
12023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break; // Rasterization finished.
12033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Shade
12053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		program.fragmentShader->shadeFragments(&buffers.fragmentPackets[0], numRasterizedPackets, shadingContext);
12073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Depth clamp
12093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (buffers.fragmentDepthBuffer && state.fragOps.depthClampEnabled)
12103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int sampleNdx = 0; sampleNdx < numRasterizedPackets * 4 * numSamples; ++sampleNdx)
12113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				buffers.fragmentDepthBuffer[sampleNdx] = de::clamp(buffers.fragmentDepthBuffer[sampleNdx], depthClampMin, depthClampMax);
12123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Handle fragment shader outputs
12143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		writeFragmentPackets(state, renderTarget, program, &buffers.fragmentPackets[0], numRasterizedPackets, rr::FACETYPE_FRONT, buffers.shaderOutputs, buffers.fragmentDepthBuffer, buffers.shadedFragments);
12163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12198852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyryvoid rasterizePrimitive (const RenderState&					state,
12208852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						 const RenderTarget&				renderTarget,
12218852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						 const Program&						program,
12228852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						 const pa::Point&					point,
12238852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						 const tcu::IVec4&					renderTargetRect,
12248852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						 RasterizationInternalBuffers&		buffers)
12253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			numSamples		= renderTarget.colorBuffers[0].getNumSamples();
12273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			depthClampMin	= de::min(state.viewport.zn, state.viewport.zf);
12283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			depthClampMax	= de::max(state.viewport.zn, state.viewport.zf);
12293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TriangleRasterizer	rasterizer1		(renderTargetRect, numSamples, state.rasterization);
12303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TriangleRasterizer	rasterizer2		(renderTargetRect, numSamples, state.rasterization);
12313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// draw point as two triangles
12333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float offset				= point.v0->pointSize / 2.0f;
12343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		w0			= tcu::Vec4(point.v0->position.x() + offset, point.v0->position.y() + offset, point.v0->position.z(), point.v0->position.w());
12353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		w1			= tcu::Vec4(point.v0->position.x() - offset, point.v0->position.y() + offset, point.v0->position.z(), point.v0->position.w());
12363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		w2			= tcu::Vec4(point.v0->position.x() - offset, point.v0->position.y() - offset, point.v0->position.z(), point.v0->position.w());
12373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		w3			= tcu::Vec4(point.v0->position.x() + offset, point.v0->position.y() - offset, point.v0->position.z(), point.v0->position.w());
12383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	rasterizer1.init(w0, w1, w2);
12403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	rasterizer2.init(w0, w2, w3);
12413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Shading context
12433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FragmentShadingContext shadingContext(point.v0->outputs, DE_NULL, DE_NULL, &buffers.shaderOutputs[0], buffers.fragmentDepthBuffer, point.v0->primitiveID, (int)program.fragmentShader->getOutputs().size(), numSamples);
12443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Execute rasterize - shade - write loop
12463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (;;)
12473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	maxFragmentPackets		= (int)buffers.fragmentPackets.size();
12493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int			numRasterizedPackets	= 0;
12503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Rasterize both triangles
12523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		rasterizer1.rasterize(&buffers.fragmentPackets[0], buffers.fragmentDepthBuffer, maxFragmentPackets, numRasterizedPackets);
12543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (numRasterizedPackets != maxFragmentPackets)
12553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float* const	depthBufferAppendPointer	= (buffers.fragmentDepthBuffer) ? (buffers.fragmentDepthBuffer + numRasterizedPackets*numSamples*4) : (DE_NULL);
12573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int				numRasterizedPackets2		= 0;
12583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			rasterizer2.rasterize(&buffers.fragmentPackets[numRasterizedPackets], depthBufferAppendPointer, maxFragmentPackets - numRasterizedPackets, numRasterizedPackets2);
12603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			numRasterizedPackets += numRasterizedPackets2;
12623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// numRasterizedPackets is guaranteed to be greater than zero for shadeFragments()
12653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!numRasterizedPackets)
12673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break; // Rasterization finished.
12683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Shade
12703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		program.fragmentShader->shadeFragments(&buffers.fragmentPackets[0], numRasterizedPackets, shadingContext);
12723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Depth clamp
12743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (buffers.fragmentDepthBuffer && state.fragOps.depthClampEnabled)
12753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int sampleNdx = 0; sampleNdx < numRasterizedPackets * 4 * numSamples; ++sampleNdx)
12763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				buffers.fragmentDepthBuffer[sampleNdx] = de::clamp(buffers.fragmentDepthBuffer[sampleNdx], depthClampMin, depthClampMax);
12773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Handle fragment shader outputs
12793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		writeFragmentPackets(state, renderTarget, program, &buffers.fragmentPackets[0], numRasterizedPackets, rr::FACETYPE_FRONT, buffers.shaderOutputs, buffers.fragmentDepthBuffer, buffers.shadedFragments);
12813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12843c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename ContainerType>
12858852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyryvoid rasterize (const RenderState&					state,
12868852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				const RenderTarget&					renderTarget,
12878852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				const Program&						program,
12888852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				const ContainerType&				list)
12893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						numSamples			= renderTarget.colorBuffers[0].getNumSamples();
12913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						numFragmentOutputs	= (int)program.fragmentShader->getOutputs().size();
12923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const size_t					maxFragmentPackets	= 128;
12933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec4				viewportRect		= tcu::IVec4(state.viewport.rect.left, state.viewport.rect.bottom, state.viewport.rect.width, state.viewport.rect.height);
12953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec4				bufferRect			= getBufferSize(renderTarget.colorBuffers[0]);
12963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec4				renderTargetRect	= rectIntersection(viewportRect, bufferRect);
12973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// shared buffers for all primitives
12993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<FragmentPacket>		fragmentPackets		(maxFragmentPackets);
13003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<GenericVec4>		shaderOutputs		(maxFragmentPackets*4*numFragmentOutputs);
13013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<Fragment>			shadedFragments		(maxFragmentPackets*4);
13023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<float>				depthValues			(0);
13033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float*							depthBufferPointer	= DE_NULL;
13043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	RasterizationInternalBuffers	buffers;
13063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13078852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	// calculate depth only if we have a depth buffer
13083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!isEmpty(renderTarget.depthBuffer))
13093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		depthValues.resize(maxFragmentPackets*4*numSamples);
13113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		depthBufferPointer = &depthValues[0];
13123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// set buffers
13153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buffers.fragmentPackets.swap(fragmentPackets);
13163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buffers.shaderOutputs.swap(shaderOutputs);
13173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buffers.shadedFragments.swap(shadedFragments);
13183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buffers.fragmentDepthBuffer = depthBufferPointer;
13193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// rasterize
13213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (typename ContainerType::const_iterator it = list.begin(); it != list.end(); ++it)
13223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		rasterizePrimitive(state, renderTarget, program, *it, renderTargetRect, buffers);
13233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
13263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Draws transformed triangles, lines or points to render target
13273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
13283c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename ContainerType>
13293c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid drawBasicPrimitives (const RenderState& state, const RenderTarget& renderTarget, const Program& program, ContainerType& primList, VertexPacketAllocator& vpalloc)
13303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool clipZ = !state.fragOps.depthClampEnabled;
13323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Transform feedback
13343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Flatshading
13363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	flatshadeVertices(program, primList);
13373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Clipping
13393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \todo [jarkko] is creating & swapping std::vectors really a good solution?
13403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	clipPrimitives(primList, program, clipZ, vpalloc);
13413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Transform vertices to window coords
13433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	transformClipCoordsToWindowCoords(state, primList);
13443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Rasterize and paint
13463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	rasterize(state, renderTarget, program, primList);
13473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13493c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid copyVertexPacketPointers(const VertexPacket** dst, const pa::Point& in)
13503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[0] = in.v0;
13523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13543c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid copyVertexPacketPointers(const VertexPacket** dst, const pa::Line& in)
13553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[0] = in.v0;
13573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[1] = in.v1;
13583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13603c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid copyVertexPacketPointers(const VertexPacket** dst, const pa::Triangle& in)
13613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[0] = in.v0;
13633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[1] = in.v1;
13643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[2] = in.v2;
13653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13673c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid copyVertexPacketPointers(const VertexPacket** dst, const pa::LineAdjacency& in)
13683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[0] = in.v0;
13703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[1] = in.v1;
13713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[2] = in.v2;
13723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[3] = in.v3;
13733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13753c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid copyVertexPacketPointers(const VertexPacket** dst, const pa::TriangleAdjacency& in)
13763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[0] = in.v0;
13783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[1] = in.v1;
13793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[2] = in.v2;
13803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[3] = in.v3;
13813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[4] = in.v4;
13823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[5] = in.v5;
13833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13853c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <PrimitiveType DrawPrimitiveType> // \note DrawPrimitiveType  can only be Points, line_strip, or triangle_strip
13868852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyryvoid drawGeometryShaderOutputAsPrimitives (const RenderState& state, const RenderTarget& renderTarget, const Program& program, VertexPacket* const* vertices, size_t numVertices, VertexPacketAllocator& vpalloc)
13873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Run primitive assembly for generated stream
13893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const size_t															assemblerPrimitiveCount		= PrimitiveTypeTraits<DrawPrimitiveType>::Assembler::getPrimitiveCount(numVertices);
13913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<typename PrimitiveTypeTraits<DrawPrimitiveType>::BaseType>	inputPrimitives				(assemblerPrimitiveCount);
13923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PrimitiveTypeTraits<DrawPrimitiveType>::Assembler::exec(inputPrimitives.begin(), vertices, numVertices, state.provokingVertexConvention); // \note input Primitives are baseType_t => only basic primitives (non adjacency) will compile
13943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Make shared vertices distinct
13963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	makeSharedVerticesDistinct(inputPrimitives, vpalloc);
13983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Draw assembled primitives
14003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	drawBasicPrimitives(state, renderTarget, program, inputPrimitives, vpalloc);
14023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14043c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <PrimitiveType DrawPrimitiveType>
14053c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid drawWithGeometryShader(const RenderState& state, const RenderTarget& renderTarget, const Program& program, std::vector<typename PrimitiveTypeTraits<DrawPrimitiveType>::Type>& input, DrawContext& drawContext)
14063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Vertices outputted by geometry shader may have different number of output variables than the original, create new memory allocator
14083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VertexPacketAllocator vpalloc(program.geometryShader->getOutputs().size());
14093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Run geometry shader for all primitives
14113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GeometryEmitter					emitter			(vpalloc, program.geometryShader->getNumVerticesOut());
14123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<PrimitivePacket>	primitives		(input.size());
14133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						numInvocations	= (int)program.geometryShader->getNumInvocations();
14143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						verticesIn		= PrimitiveTypeTraits<DrawPrimitiveType>::Type::NUM_VERTICES;
14153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (size_t primitiveNdx = 0; primitiveNdx < input.size(); ++primitiveNdx)
14173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		primitives[primitiveNdx].primitiveIDIn = drawContext.primitiveID++;
14193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		copyVertexPacketPointers(primitives[primitiveNdx].vertices, input[primitiveNdx]);
14203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (primitives.empty())
14233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return;
14243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int invocationNdx = 0; invocationNdx < numInvocations; ++invocationNdx)
14263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Shading invocation
14283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		program.geometryShader->shadePrimitives(emitter, verticesIn, &primitives[0], (int)primitives.size(), invocationNdx);
14303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Find primitives in the emitted vertices
14323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::vector<VertexPacket*> emitted;
14343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		emitter.moveEmittedTo(emitted);
14353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (size_t primitiveBegin = 0; primitiveBegin < emitted.size();)
14373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			size_t primitiveEnd;
14393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Find primitive begin
14413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!emitted[primitiveBegin])
14423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
14433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				++primitiveBegin;
14443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				continue;
14453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
14463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Find primitive end
14483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			primitiveEnd = primitiveBegin + 1;
14503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (; (primitiveEnd < emitted.size()) && emitted[primitiveEnd]; ++primitiveEnd); // find primitive end
14513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Draw range [begin, end)
14533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			switch (program.geometryShader->getOutputType())
14553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
14563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case rr::GEOMETRYSHADEROUTPUTTYPE_POINTS:			drawGeometryShaderOutputAsPrimitives<PRIMITIVETYPE_POINTS>			(state, renderTarget, program, &emitted[primitiveBegin], primitiveEnd-primitiveBegin, vpalloc); break;
14573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case rr::GEOMETRYSHADEROUTPUTTYPE_LINE_STRIP:		drawGeometryShaderOutputAsPrimitives<PRIMITIVETYPE_LINE_STRIP>		(state, renderTarget, program, &emitted[primitiveBegin], primitiveEnd-primitiveBegin, vpalloc); break;
14583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case rr::GEOMETRYSHADEROUTPUTTYPE_TRIANGLE_STRIP:	drawGeometryShaderOutputAsPrimitives<PRIMITIVETYPE_TRIANGLE_STRIP>	(state, renderTarget, program, &emitted[primitiveBegin], primitiveEnd-primitiveBegin, vpalloc); break;
14593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				default:
14603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					DE_ASSERT(DE_FALSE);
14613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
14623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Next primitive
14643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			primitiveBegin = primitiveEnd + 1;
14653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
14663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
14703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Assembles, tesselates, runs geometry shader and draws primitives of any type from vertex list.
14713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
14723c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <PrimitiveType DrawPrimitiveType>
14733c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid drawAsPrimitives (const RenderState& state, const RenderTarget& renderTarget, const Program& program, VertexPacket* const* vertices, int numVertices, DrawContext& drawContext, VertexPacketAllocator& vpalloc)
14743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Assemble primitives (deconstruct stips & loops)
14763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const size_t															assemblerPrimitiveCount		= PrimitiveTypeTraits<DrawPrimitiveType>::Assembler::getPrimitiveCount(numVertices);
14773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<typename PrimitiveTypeTraits<DrawPrimitiveType>::Type>		inputPrimitives				(assemblerPrimitiveCount);
14783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PrimitiveTypeTraits<DrawPrimitiveType>::Assembler::exec(inputPrimitives.begin(), vertices, (size_t)numVertices, state.provokingVertexConvention);
14803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Tesselate
14823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	//if (state.tesselation)
14833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	//	primList = state.tesselation.exec(primList);
14843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Geometry shader
14863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (program.geometryShader)
14873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// If there is an active geometry shader, it will convert any primitive type to basic types
14893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		drawWithGeometryShader<DrawPrimitiveType>(state, renderTarget, program, inputPrimitives, drawContext);
14903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
14923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::vector<typename PrimitiveTypeTraits<DrawPrimitiveType>::BaseType> basePrimitives;
14943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// convert types from X_adjacency to X
14963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		convertPrimitiveToBaseType(basePrimitives, inputPrimitives);
14973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Make shared vertices distinct. Needed for that the translation to screen space happens only once per vertex, and for flatshading
14993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		makeSharedVerticesDistinct(basePrimitives, vpalloc);
15003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// A primitive ID will be generated even if no geometry shader is active
15023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		generatePrimitiveIDs(basePrimitives, drawContext);
15033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Draw as a basic type
15053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		drawBasicPrimitives(state, renderTarget, program, basePrimitives, vpalloc);
15063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15093c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool isValidCommand (const DrawCommand& command, int numInstances)
15103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// numInstances should be valid
15123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numInstances < 1)
15133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
15143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Shaders should have the same varyings
15163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (command.program.geometryShader)
15173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (command.program.vertexShader->getOutputs() != command.program.geometryShader->getInputs())
15193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
15203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (command.program.geometryShader->getOutputs() != command.program.fragmentShader->getInputs())
15223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
15233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
15253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (command.program.vertexShader->getOutputs() != command.program.fragmentShader->getInputs())
15273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
15283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Shader input/output types are set
15313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (size_t varyingNdx = 0; varyingNdx < command.program.vertexShader->getInputs().size(); ++varyingNdx)
15323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (command.program.vertexShader->getInputs()[varyingNdx].type != GENERICVECTYPE_FLOAT &&
15333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			command.program.vertexShader->getInputs()[varyingNdx].type != GENERICVECTYPE_INT32 &&
15343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			command.program.vertexShader->getInputs()[varyingNdx].type != GENERICVECTYPE_UINT32)
15353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
15363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (size_t varyingNdx = 0; varyingNdx < command.program.vertexShader->getOutputs().size(); ++varyingNdx)
15373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (command.program.vertexShader->getOutputs()[varyingNdx].type != GENERICVECTYPE_FLOAT &&
15383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			command.program.vertexShader->getOutputs()[varyingNdx].type != GENERICVECTYPE_INT32 &&
15393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			command.program.vertexShader->getOutputs()[varyingNdx].type != GENERICVECTYPE_UINT32)
15403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
15413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (size_t varyingNdx = 0; varyingNdx < command.program.fragmentShader->getInputs().size(); ++varyingNdx)
15433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (command.program.fragmentShader->getInputs()[varyingNdx].type != GENERICVECTYPE_FLOAT &&
15443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			command.program.fragmentShader->getInputs()[varyingNdx].type != GENERICVECTYPE_INT32 &&
15453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			command.program.fragmentShader->getInputs()[varyingNdx].type != GENERICVECTYPE_UINT32)
15463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
15473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (size_t varyingNdx = 0; varyingNdx < command.program.fragmentShader->getOutputs().size(); ++varyingNdx)
15483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (command.program.fragmentShader->getOutputs()[varyingNdx].type != GENERICVECTYPE_FLOAT &&
15493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			command.program.fragmentShader->getOutputs()[varyingNdx].type != GENERICVECTYPE_INT32 &&
15503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			command.program.fragmentShader->getOutputs()[varyingNdx].type != GENERICVECTYPE_UINT32)
15513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
15523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (command.program.geometryShader)
15543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (size_t varyingNdx = 0; varyingNdx < command.program.geometryShader->getInputs().size(); ++varyingNdx)
15563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (command.program.geometryShader->getInputs()[varyingNdx].type != GENERICVECTYPE_FLOAT &&
15573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				command.program.geometryShader->getInputs()[varyingNdx].type != GENERICVECTYPE_INT32 &&
15583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				command.program.geometryShader->getInputs()[varyingNdx].type != GENERICVECTYPE_UINT32)
15593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
15603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (size_t varyingNdx = 0; varyingNdx < command.program.geometryShader->getOutputs().size(); ++varyingNdx)
15613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (command.program.geometryShader->getOutputs()[varyingNdx].type != GENERICVECTYPE_FLOAT &&
15623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				command.program.geometryShader->getOutputs()[varyingNdx].type != GENERICVECTYPE_INT32 &&
15633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				command.program.geometryShader->getOutputs()[varyingNdx].type != GENERICVECTYPE_UINT32)
15643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
15653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Enough vertex inputs?
15683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if ((size_t)command.numVertexAttribs < command.program.vertexShader->getInputs().size())
15693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
15703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// There is a fragment output sink for each output?
15723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if ((size_t)command.renderTarget.numColorBuffers < command.program.fragmentShader->getOutputs().size())
15733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
15743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// All destination buffers should have same number of samples and same size
15763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int outputNdx = 0; outputNdx < command.renderTarget.numColorBuffers; ++outputNdx)
15773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (getBufferSize(command.renderTarget.colorBuffers[0]) != getBufferSize(command.renderTarget.colorBuffers[outputNdx]))
15793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
15803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (command.renderTarget.colorBuffers[0].getNumSamples() != command.renderTarget.colorBuffers[outputNdx].getNumSamples())
15823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
15833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// All destination buffers should have same basic type as matching fragment output
15863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (size_t varyingNdx = 0; varyingNdx < command.program.fragmentShader->getOutputs().size(); ++varyingNdx)
15873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::TextureChannelClass	colorbufferClass = tcu::getTextureChannelClass(command.renderTarget.colorBuffers[varyingNdx].raw().getFormat().type);
15893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const GenericVecType			colorType		 = (colorbufferClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER) ? (rr::GENERICVECTYPE_INT32) : ((colorbufferClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) ? (rr::GENERICVECTYPE_UINT32) : (rr::GENERICVECTYPE_FLOAT));
15903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (command.program.fragmentShader->getOutputs()[varyingNdx].type != colorType)
15923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
15933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Integer values are flatshaded
15963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (size_t outputNdx = 0; outputNdx < command.program.vertexShader->getOutputs().size(); ++outputNdx)
15973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!command.program.vertexShader->getOutputs()[outputNdx].flatshade &&
15993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			(command.program.vertexShader->getOutputs()[outputNdx].type == GENERICVECTYPE_INT32 ||
16003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 command.program.vertexShader->getOutputs()[outputNdx].type == GENERICVECTYPE_UINT32))
16013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
16023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (command.program.geometryShader)
16043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (size_t outputNdx = 0; outputNdx < command.program.geometryShader->getOutputs().size(); ++outputNdx)
16053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!command.program.geometryShader->getOutputs()[outputNdx].flatshade &&
16073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				(command.program.geometryShader->getOutputs()[outputNdx].type == GENERICVECTYPE_INT32 ||
16083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				 command.program.geometryShader->getOutputs()[outputNdx].type == GENERICVECTYPE_UINT32))
16093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
16103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
16113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Draw primitive is valid for geometry shader
16133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (command.program.geometryShader)
16143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (command.program.geometryShader->getInputType() == rr::GEOMETRYSHADERINPUTTYPE_POINTS && command.primitives.getPrimitiveType() != PRIMITIVETYPE_POINTS)
16163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
16173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (command.program.geometryShader->getInputType() == rr::GEOMETRYSHADERINPUTTYPE_LINES &&
16193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			(command.primitives.getPrimitiveType() != PRIMITIVETYPE_LINES &&
16203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 command.primitives.getPrimitiveType() != PRIMITIVETYPE_LINE_STRIP &&
16213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 command.primitives.getPrimitiveType() != PRIMITIVETYPE_LINE_LOOP))
16223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
16233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (command.program.geometryShader->getInputType() == rr::GEOMETRYSHADERINPUTTYPE_TRIANGLES &&
16253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			(command.primitives.getPrimitiveType() != PRIMITIVETYPE_TRIANGLES &&
16263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 command.primitives.getPrimitiveType() != PRIMITIVETYPE_TRIANGLE_STRIP &&
16273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 command.primitives.getPrimitiveType() != PRIMITIVETYPE_TRIANGLE_FAN))
16283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
16293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (command.program.geometryShader->getInputType() == rr::GEOMETRYSHADERINPUTTYPE_LINES_ADJACENCY &&
16313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			(command.primitives.getPrimitiveType() != PRIMITIVETYPE_LINES_ADJACENCY &&
16323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 command.primitives.getPrimitiveType() != PRIMITIVETYPE_LINE_STRIP_ADJACENCY))
16333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
16343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (command.program.geometryShader->getInputType() == rr::GEOMETRYSHADERINPUTTYPE_TRIANGLES_ADJACENCY &&
16363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			(command.primitives.getPrimitiveType() != PRIMITIVETYPE_TRIANGLES_ADJACENCY &&
16373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 command.primitives.getPrimitiveType() != PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY))
16383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
16393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return true;
16423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // anonymous
16453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16463c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDrawIndices::DrawIndices (const deUint32* ptr, int baseVertex_)
16473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: indices	(ptr)
16483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, indexType	(INDEXTYPE_UINT32)
16493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, baseVertex(baseVertex_)
16503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16533c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDrawIndices::DrawIndices (const deUint16* ptr, int baseVertex_)
16543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: indices	(ptr)
16553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, indexType	(INDEXTYPE_UINT16)
16563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, baseVertex(baseVertex_)
16573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16603c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDrawIndices::DrawIndices (const deUint8* ptr, int baseVertex_)
16613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: indices	(ptr)
16623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, indexType	(INDEXTYPE_UINT8)
16633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, baseVertex(baseVertex_)
16643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16673c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDrawIndices::DrawIndices (const void* ptr, IndexType type, int baseVertex_)
16683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: indices	(ptr)
16693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, indexType	(type)
16703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, baseVertex(baseVertex_)
16713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16743c827367444ee418f129b2c238299f49d3264554Jarkko PoyryPrimitiveList::PrimitiveList (PrimitiveType primitiveType, int numElements, const int firstElement)
16753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_primitiveType	(primitiveType)
16763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_numElements		(numElements)
16773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_indices			(DE_NULL)
16783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_indexType		(INDEXTYPE_LAST)
16793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_baseVertex		(firstElement)
16803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(numElements >= 0 && "Invalid numElements");
16823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(firstElement >= 0 && "Invalid firstElement");
16833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16853c827367444ee418f129b2c238299f49d3264554Jarkko PoyryPrimitiveList::PrimitiveList (PrimitiveType primitiveType, int numElements, const DrawIndices& indices)
16863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_primitiveType	(primitiveType)
16873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_numElements		((size_t)numElements)
16883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_indices			(indices.indices)
16893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_indexType		(indices.indexType)
16903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_baseVertex		(indices.baseVertex)
16913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(numElements >= 0 && "Invalid numElements");
16933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16953c827367444ee418f129b2c238299f49d3264554Jarkko Poyrysize_t PrimitiveList::getIndex (size_t elementNdx) const
16963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// indices == DE_NULL interpreted as command.indices = [first (=baseVertex) + 0, first + 1, first + 2...]
16983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_indices)
16993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int index = m_baseVertex + (int)readIndexArray(m_indexType, m_indices, elementNdx);
17013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(index >= 0); // do not access indices < 0
17023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return (size_t)index;
17043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
17063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return (size_t)(m_baseVertex) + elementNdx;
17073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
17083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17093c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool PrimitiveList::isRestartIndex (size_t elementNdx, deUint32 restartIndex) const
17103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
17113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// implicit index or explicit index (without base vertex) equals restart
17123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_indices)
17133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return readIndexArray(m_indexType, m_indices, elementNdx) == restartIndex;
17143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
17153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return elementNdx == (size_t)restartIndex;
17163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
17173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17183c827367444ee418f129b2c238299f49d3264554Jarkko PoyryRenderer::Renderer (void)
17193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
17203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
17213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17223c827367444ee418f129b2c238299f49d3264554Jarkko PoyryRenderer::~Renderer (void)
17233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
17243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
17253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17263c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Renderer::draw (const DrawCommand& command) const
17273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
17283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	drawInstanced(command, 1);
17293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
17303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17313c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Renderer::drawInstanced (const DrawCommand& command, int numInstances) const
17323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
17333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Do not run bad commands
17343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool validCommand = isValidCommand(command, numInstances);
17363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!validCommand)
17373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
17383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
17393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return;
17403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
17413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Do not draw if nothing to draw
17443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (command.primitives.getNumElements() == 0 || numInstances == 0)
17463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return;
17473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Prepare transformation
17503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const size_t				numVaryings = command.program.vertexShader->getOutputs().size();
17523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VertexPacketAllocator		vpalloc(numVaryings);
17533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<VertexPacket*>	vertexPackets = vpalloc.allocArray(command.primitives.getNumElements());
17543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DrawContext					drawContext;
17553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int instanceID = 0; instanceID < numInstances; ++instanceID)
17573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Each instance has its own primitives
17593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		drawContext.primitiveID = 0;
17603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (size_t elementNdx = 0; elementNdx < command.primitives.getNumElements(); ++elementNdx)
17623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
17633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int numVertexPackets = 0;
17643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// collect primitive vertices until restart
17663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			while (elementNdx < command.primitives.getNumElements() &&
17683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					!(command.state.restart.enabled && command.primitives.isRestartIndex(elementNdx, command.state.restart.restartIndex)))
17693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
17703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// input
17713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				vertexPackets[numVertexPackets]->instanceNdx	= instanceID;
17723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				vertexPackets[numVertexPackets]->vertexNdx		= (int)command.primitives.getIndex(elementNdx);
17733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// output
17753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				vertexPackets[numVertexPackets]->pointSize		= command.state.point.pointSize;	// default value from the current state
17763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				vertexPackets[numVertexPackets]->position		= tcu::Vec4(0, 0, 0, 0);			// no undefined values
17773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				++numVertexPackets;
17793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				++elementNdx;
17803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
17813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Duplicated restart shade
17833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (numVertexPackets == 0)
17843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				continue;
17853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// \todo Vertex cache?
17873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Transform vertices
17893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			command.program.vertexShader->shadeVertices(command.vertexAttribs, &vertexPackets[0], numVertexPackets);
17913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Draw primitives
17933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			switch (command.primitives.getPrimitiveType())
17953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
17963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case PRIMITIVETYPE_TRIANGLES:				{ drawAsPrimitives<PRIMITIVETYPE_TRIANGLES>					(command.state, command.renderTarget, command.program, &vertexPackets[0], numVertexPackets, drawContext, vpalloc);	break; }
17973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case PRIMITIVETYPE_TRIANGLE_STRIP:			{ drawAsPrimitives<PRIMITIVETYPE_TRIANGLE_STRIP>			(command.state, command.renderTarget, command.program, &vertexPackets[0], numVertexPackets, drawContext, vpalloc);	break; }
17983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case PRIMITIVETYPE_TRIANGLE_FAN:			{ drawAsPrimitives<PRIMITIVETYPE_TRIANGLE_FAN>				(command.state, command.renderTarget, command.program, &vertexPackets[0], numVertexPackets, drawContext, vpalloc);	break; }
17993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case PRIMITIVETYPE_LINES:					{ drawAsPrimitives<PRIMITIVETYPE_LINES>						(command.state, command.renderTarget, command.program, &vertexPackets[0], numVertexPackets, drawContext, vpalloc);	break; }
18003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case PRIMITIVETYPE_LINE_STRIP:				{ drawAsPrimitives<PRIMITIVETYPE_LINE_STRIP>				(command.state, command.renderTarget, command.program, &vertexPackets[0], numVertexPackets, drawContext, vpalloc);	break; }
18013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case PRIMITIVETYPE_LINE_LOOP:				{ drawAsPrimitives<PRIMITIVETYPE_LINE_LOOP>					(command.state, command.renderTarget, command.program, &vertexPackets[0], numVertexPackets, drawContext, vpalloc);	break; }
18023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case PRIMITIVETYPE_POINTS:					{ drawAsPrimitives<PRIMITIVETYPE_POINTS>					(command.state, command.renderTarget, command.program, &vertexPackets[0], numVertexPackets, drawContext, vpalloc);	break; }
18033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case PRIMITIVETYPE_LINES_ADJACENCY:			{ drawAsPrimitives<PRIMITIVETYPE_LINES_ADJACENCY>			(command.state, command.renderTarget, command.program, &vertexPackets[0], numVertexPackets, drawContext, vpalloc);	break; }
18043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case PRIMITIVETYPE_LINE_STRIP_ADJACENCY:	{ drawAsPrimitives<PRIMITIVETYPE_LINE_STRIP_ADJACENCY>		(command.state, command.renderTarget, command.program, &vertexPackets[0], numVertexPackets, drawContext, vpalloc);	break; }
18053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case PRIMITIVETYPE_TRIANGLES_ADJACENCY:		{ drawAsPrimitives<PRIMITIVETYPE_TRIANGLES_ADJACENCY>		(command.state, command.renderTarget, command.program, &vertexPackets[0], numVertexPackets, drawContext, vpalloc);	break; }
18063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY:{ drawAsPrimitives<PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY>	(command.state, command.renderTarget, command.program, &vertexPackets[0], numVertexPackets, drawContext, vpalloc);	break; }
18073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				default:
18083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					DE_ASSERT(DE_FALSE);
18093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
18103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
18113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
18123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
18133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // rr
1815