Home | History | Annotate | Download | only in referencerenderer
      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 
     41 	Triangle (void)
     42 		: v0				(DE_NULL)
     43 		, v1				(DE_NULL)
     44 		, v2				(DE_NULL)
     45 		, provokingIndex	(-1)
     46 	{
     47 	}
     48 
     49 	Triangle (VertexPacket* v0_, VertexPacket* v1_, VertexPacket* v2_, int provokingIndex_)
     50 		: v0				(v0_)
     51 		, v1				(v1_)
     52 		, v2				(v2_)
     53 		, provokingIndex	(provokingIndex_)
     54 	{
     55 	}
     56 
     57 	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>
     80 	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 
     88 	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>
     97 	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 
    133 	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>
    142 	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 
    157 	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 
    170 	Line (void)
    171 		: v0				(DE_NULL)
    172 		, v1				(DE_NULL)
    173 		, provokingIndex	(-1)
    174 	{
    175 	}
    176 
    177 	Line (VertexPacket* v0_, VertexPacket* v1_, int provokingIndex_)
    178 		: v0				(v0_)
    179 		, v1				(v1_)
    180 		, provokingIndex	(provokingIndex_)
    181 	{
    182 	}
    183 
    184 	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>
    205 	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 
    213 	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>
    222 	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 
    239 	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>
    248 	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 
    267 	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 
    280 	Point (void)
    281 		: v0(DE_NULL)
    282 	{
    283 	}
    284 
    285 	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>
    296 	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 
    304 	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 
    317 	LineAdjacency (void)
    318 		: v0				(DE_NULL)
    319 		, v1				(DE_NULL)
    320 		, v2				(DE_NULL)
    321 		, v3				(DE_NULL)
    322 		, provokingIndex	(-1)
    323 	{
    324 	}
    325 
    326 	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 
    335 	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>
    358 	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 
    366 	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>
    375 	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 
    383 	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 
    396 	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 
    407 	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 
    418 	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>
    444 	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 
    452 	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>
    461 	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 
    504 	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