2025-04-27 07:49:33 -04:00

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;
}