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) : v0(DE_NULL), v1(DE_NULL), v2(DE_NULL), provokingIndex(-1) 42 { 43 } 44 Trianglerr::pa::Triangle45 Triangle(VertexPacket *v0_, VertexPacket *v1_, VertexPacket *v2_, int provokingIndex_) 46 : v0(v0_) 47 , v1(v1_) 48 , v2(v2_) 49 , provokingIndex(provokingIndex_) 50 { 51 } 52 getProvokingVertexrr::pa::Triangle53 VertexPacket *getProvokingVertex(void) 54 { 55 switch (provokingIndex) 56 { 57 case 0: 58 return v0; 59 case 1: 60 return v1; 61 case 2: 62 return v2; 63 default: 64 DE_ASSERT(false); 65 return DE_NULL; 66 } 67 } 68 69 VertexPacket *v0; 70 VertexPacket *v1; 71 VertexPacket *v2; 72 73 int provokingIndex; 74 } DE_WARN_UNUSED_TYPE; 75 76 struct Triangles 77 { 78 template <typename Iterator> execrr::pa::Triangles79 static void exec(Iterator outputIterator, VertexPacket *const *vertices, size_t numVertices, 80 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, 98 rr::ProvokingVertex provokingConvention) 99 { 100 if (numVertices < 3) 101 { 102 } 103 else 104 { 105 VertexPacket *vert0 = vertices[0]; 106 VertexPacket *vert1 = vertices[1]; 107 size_t ndx = 2; 108 109 for (;;) 110 { 111 { 112 if (ndx >= numVertices) 113 break; 114 115 *(outputIterator++) = Triangle(vert0, vert1, vertices[ndx], 116 (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (2)); 117 vert0 = vertices[ndx]; 118 119 ndx++; 120 } 121 122 { 123 if (ndx >= numVertices) 124 break; 125 126 *(outputIterator++) = Triangle(vert0, vert1, vertices[ndx], 127 (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (1) : (2)); 128 vert1 = vertices[ndx]; 129 130 ndx++; 131 } 132 } 133 } 134 } 135 getPrimitiveCountrr::pa::TriangleStrip136 static size_t getPrimitiveCount(size_t vertices) 137 { 138 return (vertices < 3) ? (0) : (vertices - 2); 139 } 140 } DE_WARN_UNUSED_TYPE; 141 142 struct TriangleFan 143 { 144 template <typename Iterator> execrr::pa::TriangleFan145 static void exec(Iterator outputIterator, VertexPacket *const *vertices, size_t numVertices, 146 rr::ProvokingVertex provokingConvention) 147 { 148 if (numVertices == 0) 149 { 150 } 151 else 152 { 153 const int provokingOffset = (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (1) : (2); 154 VertexPacket *const first = vertices[0]; 155 156 for (size_t ndx = 1; ndx + 1 < numVertices; ++ndx) 157 *(outputIterator++) = Triangle(first, vertices[ndx], vertices[ndx + 1], provokingOffset); 158 } 159 } 160 getPrimitiveCountrr::pa::TriangleFan161 static size_t getPrimitiveCount(size_t vertices) 162 { 163 return (vertices < 3) ? (0) : (vertices - 2); 164 } 165 } DE_WARN_UNUSED_TYPE; 166 167 struct Line 168 { 169 enum 170 { 171 NUM_VERTICES = 2 172 }; 173 Linerr::pa::Line174 Line(void) : v0(DE_NULL), v1(DE_NULL), provokingIndex(-1) 175 { 176 } 177 Linerr::pa::Line178 Line(VertexPacket *v0_, VertexPacket *v1_, int provokingIndex_) : v0(v0_), v1(v1_), provokingIndex(provokingIndex_) 179 { 180 } 181 getProvokingVertexrr::pa::Line182 VertexPacket *getProvokingVertex(void) 183 { 184 switch (provokingIndex) 185 { 186 case 0: 187 return v0; 188 case 1: 189 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, 206 rr::ProvokingVertex provokingConvention) 207 { 208 const int provokingOffset = (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (1); 209 210 for (size_t ndx = 0; ndx + 1 < numVertices; ndx += 2) 211 *(outputIterator++) = Line(vertices[ndx], vertices[ndx + 1], provokingOffset); 212 } 213 getPrimitiveCountrr::pa::Lines214 static size_t getPrimitiveCount(size_t vertices) 215 { 216 return vertices / 2; 217 } 218 } DE_WARN_UNUSED_TYPE; 219 220 struct LineStrip 221 { 222 template <typename Iterator> execrr::pa::LineStrip223 static void exec(Iterator outputIterator, VertexPacket *const *vertices, size_t numVertices, 224 rr::ProvokingVertex provokingConvention) 225 { 226 if (numVertices == 0) 227 { 228 } 229 else 230 { 231 VertexPacket *prev = vertices[0]; 232 233 for (size_t ndx = 1; ndx < numVertices; ++ndx) 234 { 235 *(outputIterator++) = 236 Line(prev, vertices[ndx], (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (1)); 237 prev = vertices[ndx]; 238 } 239 } 240 } 241 getPrimitiveCountrr::pa::LineStrip242 static size_t getPrimitiveCount(size_t vertices) 243 { 244 return (vertices < 2) ? (0) : (vertices - 1); 245 } 246 } DE_WARN_UNUSED_TYPE; 247 248 struct LineLoop 249 { 250 template <typename Iterator> execrr::pa::LineLoop251 static void exec(Iterator outputIterator, VertexPacket *const *vertices, size_t numVertices, 252 rr::ProvokingVertex provokingConvention) 253 { 254 if (numVertices < 2) 255 { 256 } 257 else 258 { 259 VertexPacket *prev = vertices[0]; 260 261 for (size_t ndx = 1; ndx < numVertices; ++ndx) 262 { 263 *(outputIterator++) = 264 Line(prev, vertices[ndx], (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (1)); 265 prev = vertices[ndx]; 266 } 267 268 *(outputIterator++) = 269 Line(prev, vertices[0], (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (1)); 270 } 271 } 272 getPrimitiveCountrr::pa::LineLoop273 static size_t getPrimitiveCount(size_t vertices) 274 { 275 return (vertices < 2) ? (0) : (vertices); 276 } 277 } DE_WARN_UNUSED_TYPE; 278 279 struct Point 280 { 281 enum 282 { 283 NUM_VERTICES = 1 284 }; 285 Pointrr::pa::Point286 Point(void) : v0(DE_NULL) 287 { 288 } 289 Pointrr::pa::Point290 Point(VertexPacket *v0_) : v0(v0_) 291 { 292 } 293 294 VertexPacket *v0; 295 } DE_WARN_UNUSED_TYPE; 296 297 struct Points 298 { 299 template <typename Iterator> execrr::pa::Points300 static void exec(Iterator outputIterator, VertexPacket *const *vertices, size_t numVertices, 301 rr::ProvokingVertex provokingConvention) 302 { 303 DE_UNREF(provokingConvention); 304 305 for (size_t ndx = 0; ndx < numVertices; ++ndx) 306 *(outputIterator++) = Point(vertices[ndx]); 307 } 308 getPrimitiveCountrr::pa::Points309 static size_t getPrimitiveCount(size_t vertices) 310 { 311 return (vertices); 312 } 313 } DE_WARN_UNUSED_TYPE; 314 315 struct LineAdjacency 316 { 317 enum 318 { 319 NUM_VERTICES = 4 320 }; 321 LineAdjacencyrr::pa::LineAdjacency322 LineAdjacency(void) : v0(DE_NULL), v1(DE_NULL), v2(DE_NULL), v3(DE_NULL), 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: 340 return v1; 341 case 2: 342 return v2; 343 default: 344 DE_ASSERT(false); 345 return DE_NULL; 346 } 347 } 348 349 VertexPacket *v0; 350 VertexPacket *v1; 351 VertexPacket *v2; 352 VertexPacket *v3; 353 354 int provokingIndex; 355 } DE_WARN_UNUSED_TYPE; 356 357 struct LinesAdjacency 358 { 359 template <typename Iterator> execrr::pa::LinesAdjacency360 static void exec(Iterator outputIterator, VertexPacket *const *vertices, size_t numVertices, 361 rr::ProvokingVertex provokingConvention) 362 { 363 const int provokingOffset = (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (1) : (2); 364 365 for (size_t ndx = 0; ndx + 3 < numVertices; ndx += 4) 366 *(outputIterator++) = 367 LineAdjacency(vertices[ndx], vertices[ndx + 1], vertices[ndx + 2], vertices[ndx + 3], provokingOffset); 368 } 369 getPrimitiveCountrr::pa::LinesAdjacency370 static size_t getPrimitiveCount(size_t vertices) 371 { 372 return vertices / 4; 373 } 374 } DE_WARN_UNUSED_TYPE; 375 376 struct LineStripAdjacency 377 { 378 template <typename Iterator> execrr::pa::LineStripAdjacency379 static void exec(Iterator outputIterator, VertexPacket *const *vertices, size_t numVertices, 380 rr::ProvokingVertex provokingConvention) 381 { 382 const int provokingOffset = (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (1) : (2); 383 384 for (size_t ndx = 0; ndx + 3 < numVertices; ++ndx) 385 *(outputIterator++) = 386 LineAdjacency(vertices[ndx], vertices[ndx + 1], vertices[ndx + 2], vertices[ndx + 3], provokingOffset); 387 } 388 getPrimitiveCountrr::pa::LineStripAdjacency389 static size_t getPrimitiveCount(size_t vertices) 390 { 391 return (vertices < 4) ? (0) : (vertices - 3); 392 } 393 } DE_WARN_UNUSED_TYPE; 394 395 struct TriangleAdjacency 396 { 397 enum 398 { 399 NUM_VERTICES = 6 400 }; 401 TriangleAdjacencyrr::pa::TriangleAdjacency402 TriangleAdjacency(void) 403 : v0(DE_NULL) 404 , v1(DE_NULL) 405 , v2(DE_NULL) 406 , v3(DE_NULL) 407 , v4(DE_NULL) 408 , v5(DE_NULL) 409 , provokingIndex(-1) 410 { 411 } 412 TriangleAdjacencyrr::pa::TriangleAdjacency413 TriangleAdjacency(VertexPacket *v0_, VertexPacket *v1_, VertexPacket *v2_, VertexPacket *v3_, VertexPacket *v4_, 414 VertexPacket *v5_, int provokingIndex_) 415 : v0(v0_) 416 , v1(v1_) 417 , v2(v2_) 418 , v3(v3_) 419 , v4(v4_) 420 , v5(v5_) 421 , provokingIndex(provokingIndex_) 422 { 423 } 424 getProvokingVertexrr::pa::TriangleAdjacency425 VertexPacket *getProvokingVertex(void) 426 { 427 switch (provokingIndex) 428 { 429 case 0: 430 return v0; 431 case 2: 432 return v2; 433 case 4: 434 return v4; 435 default: 436 DE_ASSERT(false); 437 return DE_NULL; 438 } 439 } 440 441 VertexPacket *v0; 442 VertexPacket *v1; //!< adjacent 443 VertexPacket *v2; 444 VertexPacket *v3; //!< adjacent 445 VertexPacket *v4; 446 VertexPacket *v5; //!< adjacent 447 448 int provokingIndex; 449 } DE_WARN_UNUSED_TYPE; 450 451 struct TrianglesAdjacency 452 { 453 template <typename Iterator> execrr::pa::TrianglesAdjacency454 static void exec(Iterator outputIterator, VertexPacket *const *vertices, size_t numVertices, 455 rr::ProvokingVertex provokingConvention) 456 { 457 const int provokingOffset = (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (4); 458 459 for (size_t ndx = 0; ndx + 5 < numVertices; ndx += 6) 460 *(outputIterator++) = 461 TriangleAdjacency(vertices[ndx], vertices[ndx + 1], vertices[ndx + 2], vertices[ndx + 3], 462 vertices[ndx + 4], vertices[ndx + 5], provokingOffset); 463 } 464 getPrimitiveCountrr::pa::TrianglesAdjacency465 static size_t getPrimitiveCount(size_t vertices) 466 { 467 return vertices / 6; 468 } 469 } DE_WARN_UNUSED_TYPE; 470 471 struct TriangleStripAdjacency 472 { 473 template <typename Iterator> execrr::pa::TriangleStripAdjacency474 static void exec(Iterator outputIterator, VertexPacket *const *vertices, size_t numVertices, 475 rr::ProvokingVertex provokingConvention) 476 { 477 if (numVertices < 6) 478 { 479 } 480 else if (numVertices < 8) 481 { 482 *(outputIterator++) = 483 TriangleAdjacency(vertices[0], vertices[1], vertices[2], vertices[5], vertices[4], vertices[3], 484 (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (4)); 485 } 486 else 487 { 488 const size_t primitiveCount = getPrimitiveCount(numVertices); 489 size_t i; 490 491 // first 492 *(outputIterator++) = 493 TriangleAdjacency(vertices[0], vertices[1], vertices[2], vertices[6], vertices[4], vertices[3], 494 (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (4)); 495 496 // middle 497 for (i = 1; i + 1 < primitiveCount; ++i) 498 { 499 // odd 500 if (i % 2 == 1) 501 { 502 *(outputIterator++) = 503 TriangleAdjacency(vertices[2 * i + 2], vertices[2 * i - 2], vertices[2 * i + 0], 504 vertices[2 * i + 3], vertices[2 * i + 4], vertices[2 * i + 6], 505 (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (2) : (4)); 506 } 507 // even 508 else 509 { 510 *(outputIterator++) = 511 TriangleAdjacency(vertices[2 * i + 0], vertices[2 * i - 2], vertices[2 * i + 2], 512 vertices[2 * i + 6], vertices[2 * i + 4], vertices[2 * i + 3], 513 (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (4)); 514 } 515 } 516 517 // last 518 519 // odd 520 if (i % 2 == 1) 521 *(outputIterator++) = TriangleAdjacency(vertices[2 * i + 2], vertices[2 * i - 2], vertices[2 * i + 0], 522 vertices[2 * i + 3], vertices[2 * i + 4], vertices[2 * i + 5], 523 (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (2) : (4)); 524 // even 525 else 526 *(outputIterator++) = TriangleAdjacency(vertices[2 * i + 0], vertices[2 * i - 2], vertices[2 * i + 2], 527 vertices[2 * i + 5], vertices[2 * i + 4], vertices[2 * i + 3], 528 (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (4)); 529 } 530 } 531 getPrimitiveCountrr::pa::TriangleStripAdjacency532 static size_t getPrimitiveCount(size_t vertices) 533 { 534 return (vertices < 6) ? 0 : ((vertices - 4) / 2); 535 } 536 } DE_WARN_UNUSED_TYPE; 537 538 } // namespace pa 539 } // namespace rr 540 541 #endif // _RRPRIMITIVEASSEMBLER_HPP 542