501 lines
13 KiB
C++
501 lines
13 KiB
C++
![]() |
/**********************************************************************
|
||
|
|
||
|
Filename : GFxVertex.cpp
|
||
|
Content : Variable-format vertex array implementation.
|
||
|
Created : June 25, 2006
|
||
|
Authors : Michael Antonov
|
||
|
|
||
|
Copyright : (c) 2001-2006 Scaleform Corp. All Rights Reserved.
|
||
|
|
||
|
Notes :
|
||
|
|
||
|
Licensees may use this file in accordance with the valid Scaleform
|
||
|
Commercial License Agreement provided with the software.
|
||
|
|
||
|
This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
|
||
|
THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR ANY PURPOSE.
|
||
|
|
||
|
**********************************************************************/
|
||
|
|
||
|
#include "GFxVertex.h"
|
||
|
#include "GRenderer.h"
|
||
|
|
||
|
// ***** Default GFxVertexInterface
|
||
|
|
||
|
void GFxVertexInterface::InitVertex(GFxVertexType* pvertex, Float x, Float y, UInt32 color)
|
||
|
{ GUNUSED4(pvertex, x, y, color); }
|
||
|
void GFxVertexInterface::SetXY(GFxVertexType* pvertex, Float x, Float y)
|
||
|
{ GUNUSED3(pvertex, x, y); }
|
||
|
void GFxVertexInterface::GetXY(GFxVertexType* pvertex, Float *px, Float *py)
|
||
|
{
|
||
|
GUNUSED(pvertex);
|
||
|
*px = 0.0f;
|
||
|
*py = 0.0f;
|
||
|
}
|
||
|
void GFxVertexInterface::SetColor(GFxVertexType* pvertex, UInt32 color)
|
||
|
{ GUNUSED2(pvertex, color); }
|
||
|
void GFxVertexInterface::SetFactor(GFxVertexType* pvertex, UInt32 factor)
|
||
|
{ GUNUSED2(pvertex, factor); }
|
||
|
UInt32 GFxVertexInterface::GetColor(GFxVertexType* pvertex)
|
||
|
{
|
||
|
GUNUSED(pvertex);
|
||
|
return 0;
|
||
|
}
|
||
|
UInt32 GFxVertexInterface::GetFactor(GFxVertexType* pvertex)
|
||
|
{
|
||
|
GUNUSED(pvertex);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
// *** Other format vertex interfaces.
|
||
|
|
||
|
#ifdef GFC_OS_PSP
|
||
|
# define GFC_VERTEX_Z
|
||
|
#endif
|
||
|
|
||
|
#if (GFC_BYTE_ORDER == GFC_BIG_ENDIAN) && !defined(GFC_OS_XBOX360) && !defined(GFC_OS_PS3) && !defined(GFC_OS_WII)
|
||
|
#define SWAPCOLOR(color) ((color >> 24) | ((color >> 8) & 0xff00) | ((color & 0xff00) << 8) | ((color & 0xff) << 24))
|
||
|
#else
|
||
|
#define SWAPCOLOR(color) color
|
||
|
#endif
|
||
|
|
||
|
|
||
|
class GFxVertexInterface_XY16i : public GFxVertexInterface
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
struct Vertex
|
||
|
{
|
||
|
SInt16 x;
|
||
|
SInt16 y;
|
||
|
#ifdef GFC_VERTEX_Z
|
||
|
SInt16 z;
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
virtual void InitVertex(GFxVertexType* pvertex, Float x, Float y, UInt32 color)
|
||
|
{
|
||
|
GUNUSED(color);
|
||
|
Vertex *p = reinterpret_cast<Vertex*>(pvertex);
|
||
|
p->x = (SInt16) x;
|
||
|
p->y = (SInt16) y;
|
||
|
#ifdef GFC_VERTEX_Z
|
||
|
p->z = 0;
|
||
|
#endif
|
||
|
}
|
||
|
virtual void SetXY(GFxVertexType* pvertex, Float x, Float y)
|
||
|
{
|
||
|
Vertex *p = reinterpret_cast<Vertex*>(pvertex);
|
||
|
p->x = (SInt16) x;
|
||
|
p->y = (SInt16) y;
|
||
|
#ifdef GFC_VERTEX_Z
|
||
|
p->z = 0;
|
||
|
#endif
|
||
|
}
|
||
|
virtual void GetXY(GFxVertexType* pvertex, Float *px, Float *py)
|
||
|
{
|
||
|
Vertex *p = reinterpret_cast<Vertex*>(pvertex);
|
||
|
*px = (Float) p->x;
|
||
|
*py = (Float) p->y;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
class GFxVertexInterface_XY32f : public GFxVertexInterface
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
struct Vertex
|
||
|
{
|
||
|
Float x;
|
||
|
Float y;
|
||
|
#ifdef GFC_VERTEX_Z
|
||
|
Float z;
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
virtual void InitVertex(GFxVertexType* pvertex, Float x, Float y, UInt32 color)
|
||
|
{
|
||
|
GUNUSED(color);
|
||
|
Vertex *p = reinterpret_cast<Vertex*>(pvertex);
|
||
|
p->x = x;
|
||
|
p->y = y;
|
||
|
#ifdef GFC_VERTEX_Z
|
||
|
p->z = 0;
|
||
|
#endif
|
||
|
}
|
||
|
virtual void SetXY(GFxVertexType* pvertex, Float x, Float y)
|
||
|
{
|
||
|
Vertex *p = reinterpret_cast<Vertex*>(pvertex);
|
||
|
p->x = x;
|
||
|
p->y = y;
|
||
|
#ifdef GFC_VERTEX_Z
|
||
|
p->z = 0;
|
||
|
#endif
|
||
|
}
|
||
|
virtual void GetXY(GFxVertexType* pvertex, Float *px, Float *py)
|
||
|
{
|
||
|
Vertex *p = reinterpret_cast<Vertex*>(pvertex);
|
||
|
*px = p->x;
|
||
|
*py = p->y;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
#ifndef GFC_NO_FXPLAYER_EDGEAA
|
||
|
|
||
|
class GFxVertexInterface_XY16iC32 : public GFxVertexInterface
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
typedef GRenderer::VertexXY16iC32 Vertex;
|
||
|
|
||
|
virtual void InitVertex(GFxVertexType* pvertex, Float x, Float y, UInt32 color)
|
||
|
{
|
||
|
Vertex *p = reinterpret_cast<Vertex*>(pvertex);
|
||
|
p->x = (SInt16) x;
|
||
|
p->y = (SInt16) y;
|
||
|
#ifdef GFC_VERTEX_Z
|
||
|
p->z = 0;
|
||
|
#endif
|
||
|
p->Color = SWAPCOLOR(color);
|
||
|
}
|
||
|
virtual void SetXY(GFxVertexType* pvertex, Float x, Float y)
|
||
|
{
|
||
|
Vertex *p = reinterpret_cast<Vertex*>(pvertex);
|
||
|
p->x = (SInt16) x;
|
||
|
p->y = (SInt16) y;
|
||
|
#ifdef GFC_VERTEX_Z
|
||
|
p->z = 0;
|
||
|
#endif
|
||
|
}
|
||
|
virtual void GetXY(GFxVertexType* pvertex, Float *px, Float *py)
|
||
|
{
|
||
|
Vertex *p = reinterpret_cast<Vertex*>(pvertex);
|
||
|
*px = (Float) p->x;
|
||
|
*py = (Float) p->y;
|
||
|
}
|
||
|
|
||
|
virtual void SetColor(GFxVertexType* pvertex, UInt32 color)
|
||
|
{
|
||
|
Vertex *p = reinterpret_cast<Vertex*>(pvertex);
|
||
|
p->Color = SWAPCOLOR(color);
|
||
|
}
|
||
|
virtual UInt32 GetColor(GFxVertexType* pvertex)
|
||
|
{
|
||
|
Vertex *p = reinterpret_cast<Vertex*>(pvertex);
|
||
|
return SWAPCOLOR(p->Color);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
class GFxVertexInterface_XY16iCF32 : public GFxVertexInterface
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
struct Vertex
|
||
|
{
|
||
|
SInt16 x;
|
||
|
SInt16 y;
|
||
|
#ifdef GFC_VERTEX_Z
|
||
|
SInt16 z;
|
||
|
#endif
|
||
|
UInt32 Color;
|
||
|
UInt32 Factor;
|
||
|
};
|
||
|
|
||
|
virtual void InitVertex(GFxVertexType* pvertex, Float x, Float y, UInt32 color)
|
||
|
{
|
||
|
Vertex *p = reinterpret_cast<Vertex*>(pvertex);
|
||
|
p->x = (SInt16) x;
|
||
|
p->y = (SInt16) y;
|
||
|
#ifdef GFC_VERTEX_Z
|
||
|
p->z = 0;
|
||
|
#endif
|
||
|
p->Color = SWAPCOLOR(color);
|
||
|
p->Factor = 0;
|
||
|
}
|
||
|
virtual void SetXY(GFxVertexType* pvertex, Float x, Float y)
|
||
|
{
|
||
|
Vertex *p = reinterpret_cast<Vertex*>(pvertex);
|
||
|
p->x = (SInt16) x;
|
||
|
p->y = (SInt16) y;
|
||
|
#ifdef GFC_VERTEX_Z
|
||
|
p->z = 0;
|
||
|
#endif
|
||
|
}
|
||
|
virtual void GetXY(GFxVertexType* pvertex, Float *px, Float *py)
|
||
|
{
|
||
|
Vertex *p = reinterpret_cast<Vertex*>(pvertex);
|
||
|
*px = (Float) p->x;
|
||
|
*py = (Float) p->y;
|
||
|
}
|
||
|
|
||
|
virtual void SetColor(GFxVertexType* pvertex, UInt32 color)
|
||
|
{
|
||
|
Vertex *p = reinterpret_cast<Vertex*>(pvertex);
|
||
|
p->Color = SWAPCOLOR(color);
|
||
|
}
|
||
|
virtual UInt32 GetColor(GFxVertexType* pvertex)
|
||
|
{
|
||
|
Vertex *p = reinterpret_cast<Vertex*>(pvertex);
|
||
|
return SWAPCOLOR(p->Color);
|
||
|
}
|
||
|
|
||
|
virtual void SetFactor(GFxVertexType* pvertex, UInt32 factor)
|
||
|
{
|
||
|
Vertex *p = reinterpret_cast<Vertex*>(pvertex);
|
||
|
p->Factor = SWAPCOLOR(factor);
|
||
|
}
|
||
|
virtual UInt32 GetFactor(GFxVertexType* pvertex)
|
||
|
{
|
||
|
Vertex *p = reinterpret_cast<Vertex*>(pvertex);
|
||
|
return SWAPCOLOR(p->Factor);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
#endif // #ifndef GFC_NO_FXPLAYER_EDGEAA
|
||
|
|
||
|
|
||
|
// Gets a descriptor for format
|
||
|
GFxVertexDesc* GFxVertexArray::GetFormatDesc(VertexFormat vf)
|
||
|
{
|
||
|
static GFxVertexInterface viNone;
|
||
|
static GFxVertexInterface_XY16i viXY16i;
|
||
|
static GFxVertexInterface_XY32f viXY32f;
|
||
|
|
||
|
#ifndef GFC_NO_FXPLAYER_EDGEAA
|
||
|
static GFxVertexInterface_XY16iC32 viXY16iC32;
|
||
|
static GFxVertexInterface_XY16iCF32 viXY16iCF32;
|
||
|
#endif
|
||
|
|
||
|
static GFxVertexDesc descTable[] =
|
||
|
{
|
||
|
{ GRenderer::Vertex_None, 0, &viNone },
|
||
|
{ GRenderer::Vertex_XY16i, sizeof(GFxVertexInterface_XY16i::Vertex), &viXY16i },
|
||
|
{ GRenderer::Vertex_XY32f, sizeof(GFxVertexInterface_XY32f::Vertex), &viXY32f },
|
||
|
#ifndef GFC_NO_FXPLAYER_EDGEAA
|
||
|
{ GRenderer::Vertex_XY16iC32, sizeof(GFxVertexInterface_XY16iC32::Vertex), &viXY16iC32 },
|
||
|
{ GRenderer::Vertex_XY16iCF32, sizeof(GFxVertexInterface_XY16iCF32::Vertex), &viXY16iCF32 }
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
switch(vf)
|
||
|
{
|
||
|
case GRenderer::Vertex_None: return &descTable[0];
|
||
|
case GRenderer::Vertex_XY16i: return &descTable[1];
|
||
|
case GRenderer::Vertex_XY32f: return &descTable[2];
|
||
|
|
||
|
#ifndef GFC_NO_FXPLAYER_EDGEAA
|
||
|
case GRenderer::Vertex_XY16iC32: return &descTable[3];
|
||
|
case GRenderer::Vertex_XY16iCF32: return &descTable[4];
|
||
|
#endif
|
||
|
default: break;
|
||
|
}
|
||
|
|
||
|
// Unsupported format requested.
|
||
|
GASSERT(0);
|
||
|
return &descTable[0];
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
GFxVertexArray::GFxVertexArray(GMemoryHeap *pheap, VertexFormat vf, UInt size)
|
||
|
{
|
||
|
pHeap = pheap ? pheap : GMemory::GetHeapByAddress(this);
|
||
|
Size = AllocSize = 0;
|
||
|
pData = 0;
|
||
|
pVertexDesc = GetFormatDesc(vf);
|
||
|
Resize(size);
|
||
|
}
|
||
|
|
||
|
GFxVertexArray::GFxVertexArray(GMemoryHeap *pheap, const GFxVertexArray& src)
|
||
|
{
|
||
|
pHeap = pheap ? pheap : GMemory::GetHeapByAddress(this);
|
||
|
Size = AllocSize = 0;
|
||
|
pData = 0;
|
||
|
pVertexDesc = src.pVertexDesc;
|
||
|
AppendVertices(src);
|
||
|
}
|
||
|
|
||
|
const GFxVertexArray& GFxVertexArray::operator = (const GFxVertexArray& src)
|
||
|
{
|
||
|
// Clear buffer
|
||
|
if (AllocSize*GetVertexSize() > src.GetSize()*src.GetVertexSize()*2)
|
||
|
Clear();
|
||
|
else
|
||
|
Resize(0);
|
||
|
|
||
|
// Important to call this since it also updates AllocSize
|
||
|
SetFormat(src.GetFormat());
|
||
|
AppendVertices(src);
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
GFxVertexArray::~GFxVertexArray()
|
||
|
{
|
||
|
if (pData)
|
||
|
GFREE(pData);
|
||
|
}
|
||
|
|
||
|
|
||
|
// Note: SetFormat only works when size is 0.
|
||
|
bool GFxVertexArray::SetFormat(VertexFormat vf)
|
||
|
{
|
||
|
if (Size != 0)
|
||
|
{
|
||
|
GFC_DEBUG_WARNING(1, "GFxVertexArray::SetFormat called on a non-zero size array");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
UInt oldSize = AllocSize * pVertexDesc->VertexSize;
|
||
|
|
||
|
pVertexDesc = GetFormatDesc(vf);
|
||
|
AllocSize = oldSize / pVertexDesc->VertexSize;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
void GFxVertexArray::Resize(UInt vertexCount)
|
||
|
{
|
||
|
if (vertexCount == Size) // Takes care of 0 case to avoid warning below.
|
||
|
return;
|
||
|
if (pVertexDesc->VFormat == GRenderer::Vertex_None)
|
||
|
{
|
||
|
GFC_DEBUG_WARNING(1, "GFxVertexArray::Resize called on an array with no vertex format");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// If already allocated, done
|
||
|
if (vertexCount <= AllocSize)
|
||
|
{
|
||
|
Size = vertexCount;
|
||
|
return;
|
||
|
}
|
||
|
if (vertexCount <= Size)
|
||
|
{
|
||
|
Size = vertexCount;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Must re-allocate
|
||
|
#ifdef GFC_OS_PS3
|
||
|
UByte* pnewData = (UByte*)GHEAP_ALLOC(pHeap, 12 + vertexCount * pVertexDesc->VertexSize,
|
||
|
StatType);
|
||
|
#else
|
||
|
UByte* pnewData = (UByte*)GHEAP_ALLOC(pHeap, vertexCount * pVertexDesc->VertexSize,
|
||
|
StatType);
|
||
|
#endif
|
||
|
if (pData)
|
||
|
{
|
||
|
if (pnewData)
|
||
|
memcpy(pnewData, pData, Size * pVertexDesc->VertexSize);
|
||
|
GFREE(pData);
|
||
|
}
|
||
|
|
||
|
Size = AllocSize = vertexCount;
|
||
|
pData = pnewData;
|
||
|
}
|
||
|
|
||
|
|
||
|
void GFxVertexArray::Reserve(UInt reserveVertexCount, bool shrinkReserve)
|
||
|
{
|
||
|
if (reserveVertexCount == AllocSize)
|
||
|
return;
|
||
|
if (pVertexDesc->VFormat == GRenderer::Vertex_None)
|
||
|
{
|
||
|
GFC_DEBUG_WARNING(1, "GFxVertexArray::Reserve called on an array with no vertex format");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (reserveVertexCount < Size)
|
||
|
reserveVertexCount = Size;
|
||
|
|
||
|
// If already allocated, done
|
||
|
if (reserveVertexCount <= AllocSize)
|
||
|
{
|
||
|
if (!shrinkReserve || (AllocSize == reserveVertexCount))
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Must re-allocate
|
||
|
#ifdef GFC_OS_PS3
|
||
|
UByte* pnewData = reserveVertexCount ? (UByte*)
|
||
|
GHEAP_ALLOC(pHeap, 12 + reserveVertexCount * pVertexDesc->VertexSize,
|
||
|
StatType) : (UByte*)0;
|
||
|
#else
|
||
|
UByte* pnewData = reserveVertexCount ? (UByte*)
|
||
|
GHEAP_ALLOC(pHeap, reserveVertexCount * pVertexDesc->VertexSize,
|
||
|
StatType) : (UByte*)0;
|
||
|
#endif
|
||
|
if (pData)
|
||
|
{
|
||
|
if (pnewData)
|
||
|
memcpy(pnewData, pData, Size * pVertexDesc->VertexSize);
|
||
|
GFREE(pData);
|
||
|
}
|
||
|
|
||
|
// Size remains the same
|
||
|
AllocSize = reserveVertexCount;
|
||
|
pData = pnewData;
|
||
|
}
|
||
|
|
||
|
|
||
|
void GFxVertexArray::Clear()
|
||
|
{
|
||
|
Resize(0);
|
||
|
Reserve(0, 1);
|
||
|
}
|
||
|
|
||
|
|
||
|
// Appends a vertex an returns a pointer used to initialize it.
|
||
|
GFxVertexRef GFxVertexArray::AppendVertex()
|
||
|
{
|
||
|
if (AllocSize <= Size)
|
||
|
Reserve(Size + 16);
|
||
|
|
||
|
if (AllocSize > Size)
|
||
|
{
|
||
|
Size++;
|
||
|
return GetVertexRef(Size-1);
|
||
|
}
|
||
|
|
||
|
// Memory failure!
|
||
|
GASSERT(0);
|
||
|
static GFxVertexInterface viNone;
|
||
|
return GFxVertexRef(0, &viNone);
|
||
|
}
|
||
|
|
||
|
|
||
|
// Appends another array to us, must be in the same format.
|
||
|
void GFxVertexArray::AppendVertices(const GFxVertexArray& src)
|
||
|
{
|
||
|
if (pVertexDesc->VFormat != src.pVertexDesc->VFormat)
|
||
|
{
|
||
|
GFC_DEBUG_WARNING(1, "GFxVertexArray::AppendVertices fails - vertex formats of arrays do not match");
|
||
|
return;
|
||
|
}
|
||
|
if (pVertexDesc->VFormat == GRenderer::Vertex_None)
|
||
|
{
|
||
|
// These arrays can have no data; so no-op.
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Reserve(Size + src.Size);
|
||
|
|
||
|
if (AllocSize >= (Size + src.Size))
|
||
|
{
|
||
|
Size += src.Size; // Increment before copy to avoid ASSERT in GetVertexPtr.
|
||
|
|
||
|
if (src.Size)
|
||
|
memcpy(GetVertexPtr(Size - src.Size), src.GetVertexPtr(0),
|
||
|
src.Size * pVertexDesc->VertexSize);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void GFxVertexArray::ApplyToRenderer(GRenderer *prenderer, GRenderer::CacheProvider *pcp) const
|
||
|
{
|
||
|
prenderer->SetVertexData(GetVertexPtr(0), GetSize(), GetFormat(), pcp);
|
||
|
}
|
||
|
|
||
|
|