190 lines
5.0 KiB
C++
190 lines
5.0 KiB
C++
#include "pch.cpp"
|
|
#pragma hdrstop
|
|
|
|
#include "glrend.h"
|
|
#include "util.h"
|
|
|
|
GlExecuteBuffer::GlExecuteBuffer(void)
|
|
{
|
|
_pbData = NULL;
|
|
_dlist = 0;
|
|
}
|
|
|
|
BOOL GlExecuteBuffer::Initialize(UINT cbSize, UINT uiFlags)
|
|
{
|
|
_pbData = new BYTE[cbSize];
|
|
if (_pbData == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
_nVertices = 0;
|
|
_cbStart = 0;
|
|
_cbSize = cbSize;
|
|
return TRUE;
|
|
}
|
|
|
|
GlExecuteBuffer::~GlExecuteBuffer(void)
|
|
{
|
|
D3DINSTRUCTION* pdinst;
|
|
BOOL bExit;
|
|
|
|
if (_pbData != NULL)
|
|
{
|
|
pdinst = (D3DINSTRUCTION *)(_pbData+_cbStart);
|
|
bExit = FALSE;
|
|
// This loop will stop at the first exit so any exits
|
|
// that are skipped by branching during execution will
|
|
// cause problems
|
|
// This is safer than not checking for exit, though,
|
|
// and no branching is currently used
|
|
while (!bExit && (BYTE *)pdinst < (_pbData+_cbStart+_cbSize))
|
|
{
|
|
switch(pdinst->bOpcode)
|
|
{
|
|
case D3DOP_EXIT:
|
|
bExit = TRUE;
|
|
break;
|
|
case PROCESSED_TRIANGLE:
|
|
delete [] *(GLuint **)(pdinst+1);
|
|
break;
|
|
}
|
|
|
|
pdinst = NEXT_PDINST(pdinst);
|
|
}
|
|
}
|
|
|
|
delete [] _pbData;
|
|
|
|
if (_dlist != 0)
|
|
{
|
|
glDeleteLists(_dlist, 1);
|
|
}
|
|
}
|
|
|
|
void GlExecuteBuffer::Release(void)
|
|
{
|
|
delete this;
|
|
}
|
|
|
|
void* GlExecuteBuffer::Lock(void)
|
|
{
|
|
// Invalidate the display list since the buffer data is changing
|
|
if (_dlist != 0)
|
|
{
|
|
glDeleteLists(_dlist, 1);
|
|
_dlist = 0;
|
|
}
|
|
|
|
return _pbData;
|
|
}
|
|
|
|
void GlExecuteBuffer::Unlock(void)
|
|
{
|
|
// Nothing to do
|
|
}
|
|
|
|
void GlExecuteBuffer::SetData(UINT nVertices, UINT cbStart, UINT cbSize)
|
|
{
|
|
_nVertices = nVertices;
|
|
_cbStart = cbStart;
|
|
_cbSize = cbSize;
|
|
}
|
|
|
|
BOOL GlExecuteBuffer::Process(void)
|
|
{
|
|
D3DINSTRUCTION* pdinst;
|
|
D3DTRIANGLE* pdtri;
|
|
GLuint* puiIndices,* pui;
|
|
ULONG i;
|
|
BOOL bExit;
|
|
|
|
// ATTENTION - This can easily be broken by applications which
|
|
// make changes to their execute buffers which change or
|
|
// move the instructions
|
|
// If only the vertex data changes this works and that's all
|
|
// we need right now
|
|
pdinst = (D3DINSTRUCTION *)(_pbData+_cbStart);
|
|
bExit = FALSE;
|
|
// This loop will stop at the first exit so any exits
|
|
// that are skipped by branching during execution will
|
|
// cause problems
|
|
// This is safer than not checking for exit, though,
|
|
// and no branching is currently used
|
|
while (!bExit && (BYTE *)pdinst < (_pbData+_cbStart+_cbSize))
|
|
{
|
|
switch(pdinst->bOpcode)
|
|
{
|
|
case D3DOP_TRIANGLE:
|
|
if (pdinst->wCount < 1)
|
|
{
|
|
break;
|
|
}
|
|
|
|
puiIndices = new GLuint[pdinst->wCount*3L];
|
|
if (puiIndices == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pui = puiIndices;
|
|
pdtri = (D3DTRIANGLE *)(pdinst+1);
|
|
for (i = 0; i < pdinst->wCount; i++)
|
|
{
|
|
// Reverse the triangle vertex order to account
|
|
// for right vs. left-handed coordinates
|
|
*pui++ = pdtri->v1;
|
|
*pui++ = pdtri->v3;
|
|
*pui++ = pdtri->v2;
|
|
pdtri++;
|
|
}
|
|
|
|
pdinst->bOpcode = PROCESSED_TRIANGLE;
|
|
*(GLuint **)(pdinst+1) = puiIndices;
|
|
break;
|
|
|
|
case D3DOP_PROCESSVERTICES:
|
|
D3DPROCESSVERTICES* pdpv;
|
|
|
|
pdpv = (D3DPROCESSVERTICES *)(pdinst+1);
|
|
for (i = 0; i < pdinst->wCount; i++)
|
|
{
|
|
if ((pdpv->dwFlags & D3DPROCESSVERTICES_OPMASK) ==
|
|
D3DPROCESSVERTICES_COPY &&
|
|
(pdpv->dwFlags & PROCESSED_TLVERTEX) == 0)
|
|
{
|
|
DWORD v;
|
|
|
|
D3DTLVERTEX* pdtlvtx;
|
|
|
|
pdtlvtx = (D3DTLVERTEX *)(_pbData+pdpv->wStart);
|
|
for (v = 0; v < pdpv->dwCount; v++)
|
|
{
|
|
// Flip color ordering from D3D's BGRA to
|
|
// OpenGL's RGBA
|
|
pdtlvtx->color =
|
|
(((pdtlvtx->color >> 24) & 0xff) << 24) |
|
|
(((pdtlvtx->color >> 16) & 0xff) << 0) |
|
|
(((pdtlvtx->color >> 8) & 0xff) << 8) |
|
|
(((pdtlvtx->color >> 0) & 0xff) << 16);
|
|
pdtlvtx++;
|
|
}
|
|
|
|
pdpv->dwFlags |= PROCESSED_TLVERTEX;
|
|
}
|
|
|
|
pdpv++;
|
|
}
|
|
break;
|
|
|
|
case D3DOP_EXIT:
|
|
bExit = TRUE;
|
|
break;
|
|
}
|
|
|
|
pdinst = NEXT_PDINST(pdinst);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|