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 
32 namespace rr
33 {
34 
35 //! Rasterizer configuration
36 enum
37 {
38 	RASTERIZER_MAX_SAMPLES_PER_FRAGMENT	= 16
39 };
40 
41 //! Get coverage bit value.
getCoverageBit(int numSamples, int x, int y, int sampleNdx)42 inline 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
getCoverageFragmentSampleBits(int numSamples, int x, int y)52 inline 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.
setCoverageValue(deUint64 mask, int numSamples, int x, int y, int sampleNdx, bool val)60 inline 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.
getCoverageValue(deUint64 mask, int numSamples, int x, int y, int sampleNdx)67 inline 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
getCoverageAnyFragmentSampleLive(deUint64 mask, int numSamples, int x, int y)73 inline 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)).
getCoverageOffset(int numSamples, int x, int y)79 inline 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  *//*--------------------------------------------------------------------*/
97 struct EdgeFunction
98 {
EdgeFunctionrr::EdgeFunction99 	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  *//*--------------------------------------------------------------------*/
126 class TriangleRasterizer
127 {
128 public:
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()
getVisibleFace(void) const134 	FaceType				getVisibleFace			(void) const { return m_face; }
135 	void					rasterize				(FragmentPacket* const fragmentPackets, float* const depthValues, const int maxFragmentPackets, int& numPacketsRasterized);
136 
137 private:
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  *//*--------------------------------------------------------------------*/
178 class SingleSampleLineRasterizer
179 {
180 public:
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 
resetStipple()189 	void							resetStipple				() { m_stippleCounter = 0; }
190 
191 private:
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  *//*--------------------------------------------------------------------*/
225 class MultiSampleLineRasterizer
226 {
227 public:
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 
236 private:
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  *//*--------------------------------------------------------------------*/
254 struct 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  *//*--------------------------------------------------------------------*/
268 class LineExitDiamondGenerator
269 {
270 public:
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 
279 private:
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