1#ifndef _RRRASTERIZER_HPP
2#define _RRRASTERIZER_HPP
3/*-------------------------------------------------------------------------
4 * drawElements Quality Program Reference Renderer
5 * -----------------------------------------------
6 *
7 * Copyright 2014 The Android Open Source Project
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief Reference rasterizer
24 *//*--------------------------------------------------------------------*/
25
26#include "rrDefs.hpp"
27#include "tcuVector.hpp"
28#include "rrRenderState.hpp"
29#include "rrFragmentPacket.hpp"
30
31
32namespace rr
33{
34
35//! Rasterizer configuration
36enum
37{
38	RASTERIZER_MAX_SAMPLES_PER_FRAGMENT	= 16
39};
40
41//! Get coverage bit value.
42inline deUint64 getCoverageBit (int numSamples, int x, int y, int sampleNdx)
43{
44	const int	numBits		= (int)sizeof(deUint64)*8;
45	const int	maxSamples	= numBits/4;
46	DE_STATIC_ASSERT(maxSamples >= RASTERIZER_MAX_SAMPLES_PER_FRAGMENT);
47	DE_ASSERT(de::inRange(numSamples, 1, maxSamples) && de::inBounds(x, 0, 2) && de::inBounds(y, 0, 2));
48	return 1ull << ((x*2 + y)*numSamples + sampleNdx);
49}
50
51//! Get all sample bits for fragment
52inline deUint64 getCoverageFragmentSampleBits (int numSamples, int x, int y)
53{
54	DE_ASSERT(de::inBounds(x, 0, 2) && de::inBounds(y, 0, 2));
55	const deUint64 fragMask = (1ull << numSamples) - 1;
56	return fragMask << (x*2 + y)*numSamples;
57}
58
59//! Set bit in coverage mask.
60inline deUint64 setCoverageValue (deUint64 mask, int numSamples, int x, int y, int sampleNdx, bool val)
61{
62	const deUint64 bit = getCoverageBit(numSamples, x, y, sampleNdx);
63	return val ? (mask | bit) : (mask & ~bit);
64}
65
66//! Get coverage bit value in mask.
67inline bool getCoverageValue (deUint64 mask, int numSamples, int x, int y, int sampleNdx)
68{
69	return (mask & getCoverageBit(numSamples, x, y, sampleNdx)) != 0;
70}
71
72//! Test if any sample for fragment is live
73inline bool getCoverageAnyFragmentSampleLive (deUint64 mask, int numSamples, int x, int y)
74{
75	return (mask & getCoverageFragmentSampleBits(numSamples, x, y)) != 0;
76}
77
78//! Get position of first coverage bit of fragment - equivalent to deClz64(getCoverageFragmentSampleBits(numSamples, x, y)).
79inline int getCoverageOffset (int numSamples, int x, int y)
80{
81	return (x*2 + y)*numSamples;
82}
83
84/*--------------------------------------------------------------------*//*!
85 * \brief Edge function
86 *
87 * Edge function can be evaluated for point P (in fixed-point coordinates
88 * with SUBPIXEL_BITS fractional part) by computing
89 *  D = a*Px + b*Py + c
90 *
91 * D will be fixed-point value where lower (SUBPIXEL_BITS*2) bits will
92 * be fractional part.
93 *
94 * a and b are stored with SUBPIXEL_BITS fractional part, while c is stored
95 * with SUBPIXEL_BITS*2 fractional bits.
96 *//*--------------------------------------------------------------------*/
97struct EdgeFunction
98{
99	inline EdgeFunction (void) : a(0), b(0), c(0), inclusive(false) {}
100
101	deInt64			a;
102	deInt64			b;
103	deInt64			c;
104	bool			inclusive;	//!< True if edge is inclusive according to fill rules.
105};
106
107/*--------------------------------------------------------------------*//*!
108 * \brief Triangle rasterizer
109 *
110 * Triangle rasterizer implements following features:
111 *  - Rasterization using fixed-point coordinates
112 *  - 1, 4, and 16 -sample rasterization
113 *  - Depth interpolation
114 *  - Perspective-correct barycentric computation for interpolation
115 *  - Visible face determination
116 *
117 * It does not (and will not) implement following:
118 *  - Triangle setup
119 *  - Clipping
120 *  - Degenerate elimination
121 *  - Coordinate transformation (inputs are in screen-space)
122 *  - Culling - logic can be implemented outside by querying visible face
123 *  - Scissoring (this can be done by controlling viewport rectangle)
124 *  - Any per-fragment operations
125 *//*--------------------------------------------------------------------*/
126class TriangleRasterizer
127{
128public:
129							TriangleRasterizer		(const tcu::IVec4& viewport, const int numSamples, const RasterizationState& state, const int suppixelBits);
130
131	void					init					(const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2);
132
133	// Following functions are only available after init()
134	FaceType				getVisibleFace			(void) const { return m_face; }
135	void					rasterize				(FragmentPacket* const fragmentPackets, float* const depthValues, const int maxFragmentPackets, int& numPacketsRasterized);
136
137private:
138	void					rasterizeSingleSample	(FragmentPacket* const fragmentPackets, float* const depthValues, const int maxFragmentPackets, int& numPacketsRasterized);
139
140	template<int NumSamples>
141	void					rasterizeMultiSample	(FragmentPacket* const fragmentPackets, float* const depthValues, const int maxFragmentPackets, int& numPacketsRasterized);
142
143	// Constant rasterization state.
144	const tcu::IVec4		m_viewport;
145	const int				m_numSamples;
146	const Winding			m_winding;
147	const HorizontalFill	m_horizontalFill;
148	const VerticalFill		m_verticalFill;
149	const int				m_subpixelBits;
150
151	// Per-triangle rasterization state.
152	tcu::Vec4				m_v0;
153	tcu::Vec4				m_v1;
154	tcu::Vec4				m_v2;
155	EdgeFunction			m_edge01;
156	EdgeFunction			m_edge12;
157	EdgeFunction			m_edge20;
158	FaceType				m_face;					//!< Triangle orientation, eg. visible face.
159	tcu::IVec2				m_bboxMin;				//!< Bounding box min (inclusive).
160	tcu::IVec2				m_bboxMax;				//!< Bounding box max (inclusive).
161	tcu::IVec2				m_curPos;				//!< Current rasterization position.
162	ViewportOrientation		m_viewportOrientation;	//!< Direction of +x+y axis
163} DE_WARN_UNUSED_TYPE;
164
165
166/*--------------------------------------------------------------------*//*!
167 * \brief Single sample line rasterizer
168 *
169 * Line rasterizer implements following features:
170 *  - Rasterization using fixed-point coordinates
171 *  - Depth interpolation
172 *  - Perspective-correct interpolation
173 *
174 * It does not (and will not) implement following:
175 *  - Clipping
176 *  - Multisampled line rasterization
177 *//*--------------------------------------------------------------------*/
178class SingleSampleLineRasterizer
179{
180public:
181									SingleSampleLineRasterizer	(const tcu::IVec4& viewport, const int subpixelBits);
182									~SingleSampleLineRasterizer	(void);
183
184	void							init						(const tcu::Vec4& v0, const tcu::Vec4& v1, float lineWidth, deUint32 stippleFactor, deUint16 stipplePattern);
185
186	// only available after init()
187	void							rasterize					(FragmentPacket* const fragmentPackets, float* const depthValues, const int maxFragmentPackets, int& numPacketsRasterized);
188
189	void							resetStipple				() { m_stippleCounter = 0; }
190
191private:
192									SingleSampleLineRasterizer	(const SingleSampleLineRasterizer&); // not allowed
193	SingleSampleLineRasterizer&		operator=					(const SingleSampleLineRasterizer&); // not allowed
194
195	// Constant rasterization state.
196	const tcu::IVec4				m_viewport;
197	const int						m_subpixelBits;
198
199	// Per-line rasterization state.
200	tcu::Vec4						m_v0;
201	tcu::Vec4						m_v1;
202	tcu::IVec2						m_bboxMin;			//!< Bounding box min (inclusive).
203	tcu::IVec2						m_bboxMax;			//!< Bounding box max (inclusive).
204	tcu::IVec2						m_curPos;			//!< Current rasterization position.
205	deInt32							m_curRowFragment;	//!< Current rasterization position of one fragment in column of lineWidth fragments
206	float							m_lineWidth;
207	deUint32						m_stippleFactor;
208	deUint16						m_stipplePattern;
209	deUint32						m_stippleCounter;
210} DE_WARN_UNUSED_TYPE;
211
212
213/*--------------------------------------------------------------------*//*!
214 * \brief Multisampled line rasterizer
215 *
216 * Line rasterizer implements following features:
217 *  - Rasterization using fixed-point coordinates
218 *  - Depth interpolation
219 *  - Perspective-correct interpolation
220 *
221 * It does not (and will not) implement following:
222 *  - Clipping
223 *  - Aliased line rasterization
224 *//*--------------------------------------------------------------------*/
225class MultiSampleLineRasterizer
226{
227public:
228								MultiSampleLineRasterizer	(const int numSamples, const tcu::IVec4& viewport, const int subpixelBits);
229								~MultiSampleLineRasterizer	();
230
231	void						init						(const tcu::Vec4& v0, const tcu::Vec4& v1, float lineWidth);
232
233	// only available after init()
234	void						rasterize					(FragmentPacket* const fragmentPackets, float* const depthValues, const int maxFragmentPackets, int& numPacketsRasterized);
235
236private:
237								MultiSampleLineRasterizer	(const MultiSampleLineRasterizer&); // not allowed
238	MultiSampleLineRasterizer&	operator=					(const MultiSampleLineRasterizer&); // not allowed
239
240	// Constant rasterization state.
241	const int					m_numSamples;
242
243	// Per-line rasterization state.
244	TriangleRasterizer			m_triangleRasterizer0; //!< not in array because we want to initialize these in the initialization list
245	TriangleRasterizer			m_triangleRasterizer1;
246} DE_WARN_UNUSED_TYPE;
247
248
249/*--------------------------------------------------------------------*//*!
250 * \brief Pixel diamond
251 *
252 * Structure representing a diamond a line exits.
253 *//*--------------------------------------------------------------------*/
254struct LineExitDiamond
255{
256	tcu::IVec2	position;
257};
258
259/*--------------------------------------------------------------------*//*!
260 * \brief Line exit diamond generator
261 *
262 * For a given line, generates list of diamonds the line exits using the
263 * line-exit rules of the line rasterization. Does not do scissoring.
264 *
265 * \note Not used by rr, but provided to prevent test cases requiring
266 *       accurate diamonds from abusing SingleSampleLineRasterizer.
267 *//*--------------------------------------------------------------------*/
268class LineExitDiamondGenerator
269{
270public:
271									LineExitDiamondGenerator	(const int subpixelBits);
272									~LineExitDiamondGenerator	(void);
273
274	void							init						(const tcu::Vec4& v0, const tcu::Vec4& v1);
275
276	// only available after init()
277	void							rasterize					(LineExitDiamond* const lineDiamonds, const int maxDiamonds, int& numWritten);
278
279private:
280									LineExitDiamondGenerator	(const LineExitDiamondGenerator&); // not allowed
281	LineExitDiamondGenerator&		operator=					(const LineExitDiamondGenerator&); // not allowed
282
283	const int						m_subpixelBits;
284
285	// Per-line rasterization state.
286	tcu::Vec4						m_v0;
287	tcu::Vec4						m_v1;
288	tcu::IVec2						m_bboxMin;			//!< Bounding box min (inclusive).
289	tcu::IVec2						m_bboxMax;			//!< Bounding box max (inclusive).
290	tcu::IVec2						m_curPos;			//!< Current rasterization position.
291};
292
293} // rr
294
295#endif // _RRRASTERIZER_HPP
296