You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
514 lines
12 KiB
514 lines
12 KiB
#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;
|
|
|
|
} // pa
|
|
} // rr
|
|
|
|
#endif // _RRPRIMITIVEASSEMBLER_HPP
|