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