1 #ifndef _RRPRIMITIVEASSEMBLER_HPP
2 #define _RRPRIMITIVEASSEMBLER_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 Primitive assembler
24  *//*--------------------------------------------------------------------*/
25 
26 #include "rrDefs.hpp"
27 #include "rrVertexPacket.hpp"
28 
29 namespace rr
30 {
31 namespace pa
32 {
33 
34 struct Triangle
35 {
36 	enum
37 	{
38 		NUM_VERTICES = 3
39 	};
40 
Trianglerr::pa::Triangle41 	Triangle (void)
42 		: v0				(DE_NULL)
43 		, v1				(DE_NULL)
44 		, v2				(DE_NULL)
45 		, provokingIndex	(-1)
46 	{
47 	}
48 
Trianglerr::pa::Triangle49 	Triangle (VertexPacket* v0_, VertexPacket* v1_, VertexPacket* v2_, int provokingIndex_)
50 		: v0				(v0_)
51 		, v1				(v1_)
52 		, v2				(v2_)
53 		, provokingIndex	(provokingIndex_)
54 	{
55 	}
56 
getProvokingVertexrr::pa::Triangle57 	VertexPacket* getProvokingVertex (void)
58 	{
59 		switch (provokingIndex)
60 		{
61 			case 0: return v0;
62 			case 1: return v1;
63 			case 2: return v2;
64 			default:
65 				DE_ASSERT(false);
66 				return DE_NULL;
67 		}
68 	}
69 
70 	VertexPacket*	v0;
71 	VertexPacket*	v1;
72 	VertexPacket*	v2;
73 
74 	int				provokingIndex;
75 } DE_WARN_UNUSED_TYPE;
76 
77 struct Triangles
78 {
79 	template <typename Iterator>
execrr::pa::Triangles80 	static void exec (Iterator outputIterator, VertexPacket* const* vertices, size_t numVertices, rr::ProvokingVertex provokingConvention)
81 	{
82 		const int provokingOffset = (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (2);
83 
84 		for (size_t ndx = 0; ndx + 2 < numVertices; ndx += 3)
85 			*(outputIterator++) = Triangle(vertices[ndx], vertices[ndx+1], vertices[ndx+2], provokingOffset);
86 	}
87 
getPrimitiveCountrr::pa::Triangles88 	static size_t getPrimitiveCount (size_t vertices)
89 	{
90 		return vertices / 3;
91 	}
92 } DE_WARN_UNUSED_TYPE;
93 
94 struct TriangleStrip
95 {
96 	template <typename Iterator>
execrr::pa::TriangleStrip97 	static void exec (Iterator outputIterator, VertexPacket* const* vertices, size_t numVertices, rr::ProvokingVertex provokingConvention)
98 	{
99 		if (numVertices < 3)
100 		{
101 		}
102 		else
103 		{
104 			VertexPacket* vert0 = vertices[0];
105 			VertexPacket* vert1 = vertices[1];
106 			size_t ndx = 2;
107 
108 			for (;;)
109 			{
110 				{
111 					if (ndx >= numVertices)
112 						break;
113 
114 					*(outputIterator++) = Triangle(vert0, vert1, vertices[ndx], (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (2));
115 					vert0 = vertices[ndx];
116 
117 					ndx++;
118 				}
119 
120 				{
121 					if (ndx >= numVertices)
122 						break;
123 
124 					*(outputIterator++) = Triangle(vert0, vert1, vertices[ndx], (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (1) : (2));
125 					vert1 = vertices[ndx];
126 
127 					ndx++;
128 				}
129 			}
130 		}
131 	}
132 
getPrimitiveCountrr::pa::TriangleStrip133 	static size_t getPrimitiveCount (size_t vertices)
134 	{
135 		return (vertices < 3) ? (0) : (vertices - 2);
136 	}
137 } DE_WARN_UNUSED_TYPE;
138 
139 struct TriangleFan
140 {
141 	template <typename Iterator>
execrr::pa::TriangleFan142 	static void exec (Iterator outputIterator, VertexPacket* const* vertices, size_t numVertices, rr::ProvokingVertex provokingConvention)
143 	{
144 		if (numVertices == 0)
145 		{
146 		}
147 		else
148 		{
149 			const int			provokingOffset	= (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (1) : (2);
150 			VertexPacket* const	first			= vertices[0];
151 
152 			for (size_t ndx = 1; ndx + 1 < numVertices; ++ndx)
153 				*(outputIterator++) = Triangle(first, vertices[ndx], vertices[ndx+1], provokingOffset);
154 		}
155 	}
156 
getPrimitiveCountrr::pa::TriangleFan157 	static size_t getPrimitiveCount (size_t vertices)
158 	{
159 		return (vertices < 3) ? (0) : (vertices - 2);
160 	}
161 } DE_WARN_UNUSED_TYPE;
162 
163 struct Line
164 {
165 	enum
166 	{
167 		NUM_VERTICES = 2
168 	};
169 
Linerr::pa::Line170 	Line (void)
171 		: v0				(DE_NULL)
172 		, v1				(DE_NULL)
173 		, provokingIndex	(-1)
174 	{
175 	}
176 
Linerr::pa::Line177 	Line (VertexPacket* v0_, VertexPacket* v1_, int provokingIndex_)
178 		: v0				(v0_)
179 		, v1				(v1_)
180 		, provokingIndex	(provokingIndex_)
181 	{
182 	}
183 
getProvokingVertexrr::pa::Line184 	VertexPacket* getProvokingVertex (void)
185 	{
186 		switch (provokingIndex)
187 		{
188 			case 0: return v0;
189 			case 1: return v1;
190 			default:
191 				DE_ASSERT(false);
192 				return DE_NULL;
193 		}
194 	}
195 
196 	VertexPacket*	v0;
197 	VertexPacket*	v1;
198 
199 	int				provokingIndex;
200 } DE_WARN_UNUSED_TYPE;
201 
202 struct Lines
203 {
204 	template <typename Iterator>
execrr::pa::Lines205 	static void exec (Iterator outputIterator, VertexPacket* const* vertices, size_t numVertices, rr::ProvokingVertex provokingConvention)
206 	{
207 		const int provokingOffset = (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (1);
208 
209 		for (size_t ndx = 0; ndx + 1 < numVertices; ndx += 2)
210 			*(outputIterator++) = Line(vertices[ndx], vertices[ndx+1], provokingOffset);
211 	}
212 
getPrimitiveCountrr::pa::Lines213 	static size_t getPrimitiveCount (size_t vertices)
214 	{
215 		return vertices / 2;
216 	}
217 } DE_WARN_UNUSED_TYPE;
218 
219 struct LineStrip
220 {
221 	template <typename Iterator>
execrr::pa::LineStrip222 	static void exec (Iterator outputIterator, VertexPacket* const* vertices, size_t numVertices, rr::ProvokingVertex provokingConvention)
223 	{
224 		if (numVertices == 0)
225 		{
226 		}
227 		else
228 		{
229 			VertexPacket* prev = vertices[0];
230 
231 			for (size_t ndx = 1; ndx < numVertices; ++ndx)
232 			{
233 				*(outputIterator++) = Line(prev, vertices[ndx], (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (1));
234 				prev = vertices[ndx];
235 			}
236 		}
237 	}
238 
getPrimitiveCountrr::pa::LineStrip239 	static size_t getPrimitiveCount (size_t vertices)
240 	{
241 		return (vertices < 2) ? (0) : (vertices - 1);
242 	}
243 } DE_WARN_UNUSED_TYPE;
244 
245 struct LineLoop
246 {
247 	template <typename Iterator>
execrr::pa::LineLoop248 	static void exec (Iterator outputIterator, VertexPacket* const* vertices, size_t numVertices, rr::ProvokingVertex provokingConvention)
249 	{
250 		if (numVertices < 2)
251 		{
252 		}
253 		else
254 		{
255 			VertexPacket* prev = vertices[0];
256 
257 			for (size_t ndx = 1; ndx < numVertices; ++ndx)
258 			{
259 				*(outputIterator++) = Line(prev, vertices[ndx], (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (1));
260 				prev = vertices[ndx];
261 			}
262 
263 			*(outputIterator++) = Line(prev, vertices[0], (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (1));
264 		}
265 	}
266 
getPrimitiveCountrr::pa::LineLoop267 	static size_t getPrimitiveCount (size_t vertices)
268 	{
269 		return (vertices < 2) ? (0) : (vertices);
270 	}
271 } DE_WARN_UNUSED_TYPE;
272 
273 struct Point
274 {
275 	enum
276 	{
277 		NUM_VERTICES = 1
278 	};
279 
Pointrr::pa::Point280 	Point (void)
281 		: v0(DE_NULL)
282 	{
283 	}
284 
Pointrr::pa::Point285 	Point (VertexPacket* v0_)
286 		: v0(v0_)
287 	{
288 	}
289 
290 	VertexPacket* v0;
291 } DE_WARN_UNUSED_TYPE;
292 
293 struct Points
294 {
295 	template <typename Iterator>
execrr::pa::Points296 	static void exec (Iterator outputIterator, VertexPacket* const* vertices, size_t numVertices, rr::ProvokingVertex provokingConvention)
297 	{
298 		DE_UNREF(provokingConvention);
299 
300 		for (size_t ndx = 0; ndx < numVertices; ++ndx)
301 			*(outputIterator++) = Point(vertices[ndx]);
302 	}
303 
getPrimitiveCountrr::pa::Points304 	static size_t getPrimitiveCount (size_t vertices)
305 	{
306 		return (vertices);
307 	}
308 } DE_WARN_UNUSED_TYPE;
309 
310 struct LineAdjacency
311 {
312 	enum
313 	{
314 		NUM_VERTICES = 4
315 	};
316 
LineAdjacencyrr::pa::LineAdjacency317 	LineAdjacency (void)
318 		: v0				(DE_NULL)
319 		, v1				(DE_NULL)
320 		, v2				(DE_NULL)
321 		, v3				(DE_NULL)
322 		, provokingIndex	(-1)
323 	{
324 	}
325 
LineAdjacencyrr::pa::LineAdjacency326 	LineAdjacency (VertexPacket* v0_, VertexPacket* v1_, VertexPacket* v2_, VertexPacket* v3_, int provokingIndex_)
327 		: v0				(v0_)
328 		, v1				(v1_)
329 		, v2				(v2_)
330 		, v3				(v3_)
331 		, provokingIndex	(provokingIndex_)
332 	{
333 	}
334 
getProvokingVertexrr::pa::LineAdjacency335 	VertexPacket* getProvokingVertex (void)
336 	{
337 		switch (provokingIndex)
338 		{
339 			case 1: return v1;
340 			case 2: return v2;
341 			default:
342 				DE_ASSERT(false);
343 				return DE_NULL;
344 		}
345 	}
346 
347 	VertexPacket*	v0;
348 	VertexPacket*	v1;
349 	VertexPacket*	v2;
350 	VertexPacket*	v3;
351 
352 	int				provokingIndex;
353 } DE_WARN_UNUSED_TYPE;
354 
355 struct LinesAdjacency
356 {
357 	template <typename Iterator>
execrr::pa::LinesAdjacency358 	static void exec (Iterator outputIterator, VertexPacket* const* vertices, size_t numVertices, rr::ProvokingVertex provokingConvention)
359 	{
360 		const int provokingOffset = (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (1) : (2);
361 
362 		for (size_t ndx = 0; ndx + 3 < numVertices; ndx += 4)
363 			*(outputIterator++) = LineAdjacency(vertices[ndx], vertices[ndx+1], vertices[ndx+2], vertices[ndx+3], provokingOffset);
364 	}
365 
getPrimitiveCountrr::pa::LinesAdjacency366 	static size_t getPrimitiveCount (size_t vertices)
367 	{
368 		return vertices / 4;
369 	}
370 } DE_WARN_UNUSED_TYPE;
371 
372 struct LineStripAdjacency
373 {
374 	template <typename Iterator>
execrr::pa::LineStripAdjacency375 	static void exec (Iterator outputIterator, VertexPacket* const* vertices, size_t numVertices, rr::ProvokingVertex provokingConvention)
376 	{
377 		const int provokingOffset = (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (1) : (2);
378 
379 		for (size_t ndx = 0; ndx + 3 < numVertices; ++ndx)
380 			*(outputIterator++) = LineAdjacency(vertices[ndx], vertices[ndx+1], vertices[ndx+2], vertices[ndx+3], provokingOffset);
381 	}
382 
getPrimitiveCountrr::pa::LineStripAdjacency383 	static size_t getPrimitiveCount (size_t vertices)
384 	{
385 		return (vertices < 4) ? (0) : (vertices - 3);
386 	}
387 } DE_WARN_UNUSED_TYPE;
388 
389 struct TriangleAdjacency
390 {
391 	enum
392 	{
393 		NUM_VERTICES = 6
394 	};
395 
TriangleAdjacencyrr::pa::TriangleAdjacency396 	TriangleAdjacency (void)
397 		: v0				(DE_NULL)
398 		, v1				(DE_NULL)
399 		, v2				(DE_NULL)
400 		, v3				(DE_NULL)
401 		, v4				(DE_NULL)
402 		, v5				(DE_NULL)
403 		, provokingIndex	(-1)
404 	{
405 	}
406 
TriangleAdjacencyrr::pa::TriangleAdjacency407 	TriangleAdjacency (VertexPacket* v0_, VertexPacket* v1_, VertexPacket* v2_, VertexPacket* v3_, VertexPacket* v4_, VertexPacket* v5_, int provokingIndex_)
408 		: v0				(v0_)
409 		, v1				(v1_)
410 		, v2				(v2_)
411 		, v3				(v3_)
412 		, v4				(v4_)
413 		, v5				(v5_)
414 		, provokingIndex	(provokingIndex_)
415 	{
416 	}
417 
getProvokingVertexrr::pa::TriangleAdjacency418 	VertexPacket* getProvokingVertex (void)
419 	{
420 		switch (provokingIndex)
421 		{
422 			case 0: return v0;
423 			case 2: return v2;
424 			case 4: return v4;
425 			default:
426 				DE_ASSERT(false);
427 				return DE_NULL;
428 		}
429 	}
430 
431 	VertexPacket*	v0;
432 	VertexPacket*	v1;	//!< adjacent
433 	VertexPacket*	v2;
434 	VertexPacket*	v3;	//!< adjacent
435 	VertexPacket*	v4;
436 	VertexPacket*	v5;	//!< adjacent
437 
438 	int				provokingIndex;
439 } DE_WARN_UNUSED_TYPE;
440 
441 struct TrianglesAdjacency
442 {
443 	template <typename Iterator>
execrr::pa::TrianglesAdjacency444 	static void exec (Iterator outputIterator, VertexPacket* const* vertices, size_t numVertices, rr::ProvokingVertex provokingConvention)
445 	{
446 		const int provokingOffset = (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (4);
447 
448 		for (size_t ndx = 0; ndx + 5 < numVertices; ndx += 6)
449 			*(outputIterator++) = TriangleAdjacency(vertices[ndx], vertices[ndx+1], vertices[ndx+2], vertices[ndx+3], vertices[ndx+4], vertices[ndx+5], provokingOffset);
450 	}
451 
getPrimitiveCountrr::pa::TrianglesAdjacency452 	static size_t getPrimitiveCount (size_t vertices)
453 	{
454 		return vertices / 6;
455 	}
456 } DE_WARN_UNUSED_TYPE;
457 
458 struct TriangleStripAdjacency
459 {
460 	template <typename Iterator>
execrr::pa::TriangleStripAdjacency461 	static void exec (Iterator outputIterator, VertexPacket* const* vertices, size_t numVertices, rr::ProvokingVertex provokingConvention)
462 	{
463 		if (numVertices < 6)
464 		{
465 		}
466 		else if (numVertices < 8)
467 		{
468 			*(outputIterator++) = TriangleAdjacency(vertices[0], vertices[1], vertices[2], vertices[5], vertices[4], vertices[3], (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (4));
469 		}
470 		else
471 		{
472 			const size_t primitiveCount = getPrimitiveCount(numVertices);
473 			size_t i;
474 
475 			// first
476 			*(outputIterator++) = TriangleAdjacency(vertices[0], vertices[1], vertices[2], vertices[6], vertices[4], vertices[3], (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (4));
477 
478 			// middle
479 			for (i = 1; i + 1 < primitiveCount; ++i)
480 			{
481 				// odd
482 				if (i % 2 == 1)
483 				{
484 					*(outputIterator++) = TriangleAdjacency(vertices[2*i+2], vertices[2*i-2], vertices[2*i+0], vertices[2*i+3], vertices[2*i+4], vertices[2*i+6], (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (2) : (4));
485 				}
486 				// even
487 				else
488 				{
489 					*(outputIterator++) = TriangleAdjacency(vertices[2*i+0], vertices[2*i-2], vertices[2*i+2], vertices[2*i+6], vertices[2*i+4], vertices[2*i+3], (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (4));
490 				}
491 			}
492 
493 			// last
494 
495 			// odd
496 			if (i % 2 == 1)
497 				*(outputIterator++) = TriangleAdjacency(vertices[2*i+2], vertices[2*i-2], vertices[2*i+0], vertices[2*i+3], vertices[2*i+4], vertices[2*i+5], (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (2) : (4));
498 			// even
499 			else
500 				*(outputIterator++) = TriangleAdjacency(vertices[2*i+0], vertices[2*i-2], vertices[2*i+2], vertices[2*i+5], vertices[2*i+4], vertices[2*i+3], (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (4));
501 		}
502 	}
503 
getPrimitiveCountrr::pa::TriangleStripAdjacency504 	static size_t getPrimitiveCount (size_t vertices)
505 	{
506 		return (vertices < 6) ? 0 : ((vertices - 4) / 2);
507 	}
508 } DE_WARN_UNUSED_TYPE;
509 
510 } // pa
511 } // rr
512 
513 #endif // _RRPRIMITIVEASSEMBLER_HPP
514