blob: 8db991c8a30232cee90c18278c0e59cefa4fa4f7 [file] [log] [blame]
#ifndef _RRPRIMITIVEASSEMBLER_HPP
#define _RRPRIMITIVEASSEMBLER_HPP
/*-------------------------------------------------------------------------
* drawElements Quality Program Reference Renderer
* -----------------------------------------------
*
* Copyright 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*//*!
* \file
* \brief Primitive assembler
*//*--------------------------------------------------------------------*/
#include "rrDefs.hpp"
#include "rrVertexPacket.hpp"
namespace rr
{
namespace pa
{
struct Triangle
{
enum
{
NUM_VERTICES = 3
};
Triangle(void) : v0(DE_NULL), v1(DE_NULL), v2(DE_NULL), provokingIndex(-1)
{
}
Triangle(VertexPacket *v0_, VertexPacket *v1_, VertexPacket *v2_, int provokingIndex_)
: v0(v0_)
, v1(v1_)
, v2(v2_)
, provokingIndex(provokingIndex_)
{
}
VertexPacket *getProvokingVertex(void)
{
switch (provokingIndex)
{
case 0:
return v0;
case 1:
return v1;
case 2:
return v2;
default:
DE_ASSERT(false);
return DE_NULL;
}
}
VertexPacket *v0;
VertexPacket *v1;
VertexPacket *v2;
int provokingIndex;
} DE_WARN_UNUSED_TYPE;
struct Triangles
{
template <typename Iterator>
static void exec(Iterator outputIterator, VertexPacket *const *vertices, size_t numVertices,
rr::ProvokingVertex provokingConvention)
{
const int provokingOffset = (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (2);
for (size_t ndx = 0; ndx + 2 < numVertices; ndx += 3)
*(outputIterator++) = Triangle(vertices[ndx], vertices[ndx + 1], vertices[ndx + 2], provokingOffset);
}
static size_t getPrimitiveCount(size_t vertices)
{
return vertices / 3;
}
} DE_WARN_UNUSED_TYPE;
struct TriangleStrip
{
template <typename Iterator>
static void exec(Iterator outputIterator, VertexPacket *const *vertices, size_t numVertices,
rr::ProvokingVertex provokingConvention)
{
if (numVertices < 3)
{
}
else
{
VertexPacket *vert0 = vertices[0];
VertexPacket *vert1 = vertices[1];
size_t ndx = 2;
for (;;)
{
{
if (ndx >= numVertices)
break;
*(outputIterator++) = Triangle(vert0, vert1, vertices[ndx],
(provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (2));
vert0 = vertices[ndx];
ndx++;
}
{
if (ndx >= numVertices)
break;
*(outputIterator++) = Triangle(vert0, vert1, vertices[ndx],
(provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (1) : (2));
vert1 = vertices[ndx];
ndx++;
}
}
}
}
static size_t getPrimitiveCount(size_t vertices)
{
return (vertices < 3) ? (0) : (vertices - 2);
}
} DE_WARN_UNUSED_TYPE;
struct TriangleFan
{
template <typename Iterator>
static void exec(Iterator outputIterator, VertexPacket *const *vertices, size_t numVertices,
rr::ProvokingVertex provokingConvention)
{
if (numVertices == 0)
{
}
else
{
const int provokingOffset = (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (1) : (2);
VertexPacket *const first = vertices[0];
for (size_t ndx = 1; ndx + 1 < numVertices; ++ndx)
*(outputIterator++) = Triangle(first, vertices[ndx], vertices[ndx + 1], provokingOffset);
}
}
static size_t getPrimitiveCount(size_t vertices)
{
return (vertices < 3) ? (0) : (vertices - 2);
}
} DE_WARN_UNUSED_TYPE;
struct Line
{
enum
{
NUM_VERTICES = 2
};
Line(void) : v0(DE_NULL), v1(DE_NULL), provokingIndex(-1)
{
}
Line(VertexPacket *v0_, VertexPacket *v1_, int provokingIndex_) : v0(v0_), v1(v1_), provokingIndex(provokingIndex_)
{
}
VertexPacket *getProvokingVertex(void)
{
switch (provokingIndex)
{
case 0:
return v0;
case 1:
return v1;
default:
DE_ASSERT(false);
return DE_NULL;
}
}
VertexPacket *v0;
VertexPacket *v1;
int provokingIndex;
} DE_WARN_UNUSED_TYPE;
struct Lines
{
template <typename Iterator>
static void exec(Iterator outputIterator, VertexPacket *const *vertices, size_t numVertices,
rr::ProvokingVertex provokingConvention)
{
const int provokingOffset = (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (1);
for (size_t ndx = 0; ndx + 1 < numVertices; ndx += 2)
*(outputIterator++) = Line(vertices[ndx], vertices[ndx + 1], provokingOffset);
}
static size_t getPrimitiveCount(size_t vertices)
{
return vertices / 2;
}
} DE_WARN_UNUSED_TYPE;
struct LineStrip
{
template <typename Iterator>
static void exec(Iterator outputIterator, VertexPacket *const *vertices, size_t numVertices,
rr::ProvokingVertex provokingConvention)
{
if (numVertices == 0)
{
}
else
{
VertexPacket *prev = vertices[0];
for (size_t ndx = 1; ndx < numVertices; ++ndx)
{
*(outputIterator++) =
Line(prev, vertices[ndx], (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (1));
prev = vertices[ndx];
}
}
}
static size_t getPrimitiveCount(size_t vertices)
{
return (vertices < 2) ? (0) : (vertices - 1);
}
} DE_WARN_UNUSED_TYPE;
struct LineLoop
{
template <typename Iterator>
static void exec(Iterator outputIterator, VertexPacket *const *vertices, size_t numVertices,
rr::ProvokingVertex provokingConvention)
{
if (numVertices < 2)
{
}
else
{
VertexPacket *prev = vertices[0];
for (size_t ndx = 1; ndx < numVertices; ++ndx)
{
*(outputIterator++) =
Line(prev, vertices[ndx], (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (1));
prev = vertices[ndx];
}
*(outputIterator++) =
Line(prev, vertices[0], (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (1));
}
}
static size_t getPrimitiveCount(size_t vertices)
{
return (vertices < 2) ? (0) : (vertices);
}
} DE_WARN_UNUSED_TYPE;
struct Point
{
enum
{
NUM_VERTICES = 1
};
Point(void) : v0(DE_NULL)
{
}
Point(VertexPacket *v0_) : v0(v0_)
{
}
VertexPacket *v0;
} DE_WARN_UNUSED_TYPE;
struct Points
{
template <typename Iterator>
static void exec(Iterator outputIterator, VertexPacket *const *vertices, size_t numVertices,
rr::ProvokingVertex provokingConvention)
{
DE_UNREF(provokingConvention);
for (size_t ndx = 0; ndx < numVertices; ++ndx)
*(outputIterator++) = Point(vertices[ndx]);
}
static size_t getPrimitiveCount(size_t vertices)
{
return (vertices);
}
} DE_WARN_UNUSED_TYPE;
struct LineAdjacency
{
enum
{
NUM_VERTICES = 4
};
LineAdjacency(void) : v0(DE_NULL), v1(DE_NULL), v2(DE_NULL), v3(DE_NULL), provokingIndex(-1)
{
}
LineAdjacency(VertexPacket *v0_, VertexPacket *v1_, VertexPacket *v2_, VertexPacket *v3_, int provokingIndex_)
: v0(v0_)
, v1(v1_)
, v2(v2_)
, v3(v3_)
, provokingIndex(provokingIndex_)
{
}
VertexPacket *getProvokingVertex(void)
{
switch (provokingIndex)
{
case 1:
return v1;
case 2:
return v2;
default:
DE_ASSERT(false);
return DE_NULL;
}
}
VertexPacket *v0;
VertexPacket *v1;
VertexPacket *v2;
VertexPacket *v3;
int provokingIndex;
} DE_WARN_UNUSED_TYPE;
struct LinesAdjacency
{
template <typename Iterator>
static void exec(Iterator outputIterator, VertexPacket *const *vertices, size_t numVertices,
rr::ProvokingVertex provokingConvention)
{
const int provokingOffset = (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (1) : (2);
for (size_t ndx = 0; ndx + 3 < numVertices; ndx += 4)
*(outputIterator++) =
LineAdjacency(vertices[ndx], vertices[ndx + 1], vertices[ndx + 2], vertices[ndx + 3], provokingOffset);
}
static size_t getPrimitiveCount(size_t vertices)
{
return vertices / 4;
}
} DE_WARN_UNUSED_TYPE;
struct LineStripAdjacency
{
template <typename Iterator>
static void exec(Iterator outputIterator, VertexPacket *const *vertices, size_t numVertices,
rr::ProvokingVertex provokingConvention)
{
const int provokingOffset = (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (1) : (2);
for (size_t ndx = 0; ndx + 3 < numVertices; ++ndx)
*(outputIterator++) =
LineAdjacency(vertices[ndx], vertices[ndx + 1], vertices[ndx + 2], vertices[ndx + 3], provokingOffset);
}
static size_t getPrimitiveCount(size_t vertices)
{
return (vertices < 4) ? (0) : (vertices - 3);
}
} DE_WARN_UNUSED_TYPE;
struct TriangleAdjacency
{
enum
{
NUM_VERTICES = 6
};
TriangleAdjacency(void)
: v0(DE_NULL)
, v1(DE_NULL)
, v2(DE_NULL)
, v3(DE_NULL)
, v4(DE_NULL)
, v5(DE_NULL)
, provokingIndex(-1)
{
}
TriangleAdjacency(VertexPacket *v0_, VertexPacket *v1_, VertexPacket *v2_, VertexPacket *v3_, VertexPacket *v4_,
VertexPacket *v5_, int provokingIndex_)
: v0(v0_)
, v1(v1_)
, v2(v2_)
, v3(v3_)
, v4(v4_)
, v5(v5_)
, provokingIndex(provokingIndex_)
{
}
VertexPacket *getProvokingVertex(void)
{
switch (provokingIndex)
{
case 0:
return v0;
case 2:
return v2;
case 4:
return v4;
default:
DE_ASSERT(false);
return DE_NULL;
}
}
VertexPacket *v0;
VertexPacket *v1; //!< adjacent
VertexPacket *v2;
VertexPacket *v3; //!< adjacent
VertexPacket *v4;
VertexPacket *v5; //!< adjacent
int provokingIndex;
} DE_WARN_UNUSED_TYPE;
struct TrianglesAdjacency
{
template <typename Iterator>
static void exec(Iterator outputIterator, VertexPacket *const *vertices, size_t numVertices,
rr::ProvokingVertex provokingConvention)
{
const int provokingOffset = (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (4);
for (size_t ndx = 0; ndx + 5 < numVertices; ndx += 6)
*(outputIterator++) =
TriangleAdjacency(vertices[ndx], vertices[ndx + 1], vertices[ndx + 2], vertices[ndx + 3],
vertices[ndx + 4], vertices[ndx + 5], provokingOffset);
}
static size_t getPrimitiveCount(size_t vertices)
{
return vertices / 6;
}
} DE_WARN_UNUSED_TYPE;
struct TriangleStripAdjacency
{
template <typename Iterator>
static void exec(Iterator outputIterator, VertexPacket *const *vertices, size_t numVertices,
rr::ProvokingVertex provokingConvention)
{
if (numVertices < 6)
{
}
else if (numVertices < 8)
{
*(outputIterator++) =
TriangleAdjacency(vertices[0], vertices[1], vertices[2], vertices[5], vertices[4], vertices[3],
(provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (4));
}
else
{
const size_t primitiveCount = getPrimitiveCount(numVertices);
size_t i;
// first
*(outputIterator++) =
TriangleAdjacency(vertices[0], vertices[1], vertices[2], vertices[6], vertices[4], vertices[3],
(provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (4));
// middle
for (i = 1; i + 1 < primitiveCount; ++i)
{
// odd
if (i % 2 == 1)
{
*(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));
}
// even
else
{
*(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));
}
}
// last
// odd
if (i % 2 == 1)
*(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));
// even
else
*(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));
}
}
static size_t getPrimitiveCount(size_t vertices)
{
return (vertices < 6) ? 0 : ((vertices - 4) / 2);
}
} DE_WARN_UNUSED_TYPE;
} // namespace pa
} // namespace rr
#endif // _RRPRIMITIVEASSEMBLER_HPP