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

882 lines
25 KiB
C++

#include "pch.cpp"
#pragma hdrstop
#include "glrend.h"
#include "util.h"
#include "globals.h"
#include "gltk.h"
// #define NO_LIGHTING
// Translation tables for D3D -> OpenGL
GLenum eDepthFuncTranslate[] =
{
0,
GL_NEVER,
GL_LESS,
GL_EQUAL,
GL_LEQUAL,
GL_GREATER,
GL_NOTEQUAL,
GL_GEQUAL,
GL_ALWAYS
};
GLenum eTextureFilterTranslate[] =
{
0,
GL_NEAREST,
GL_LINEAR,
GL_NEAREST_MIPMAP_NEAREST,
GL_NEAREST_MIPMAP_LINEAR,
GL_LINEAR_MIPMAP_NEAREST,
GL_LINEAR_MIPMAP_LINEAR
};
GLenum eBlendFuncTranslate[] =
{
0,
GL_ZERO,
GL_ONE,
GL_SRC_COLOR,
GL_ONE_MINUS_SRC_COLOR,
GL_SRC_ALPHA,
GL_ONE_MINUS_SRC_ALPHA,
GL_DST_ALPHA,
GL_ONE_MINUS_DST_ALPHA,
GL_DST_COLOR,
GL_ONE_MINUS_DST_COLOR,
GL_SRC_ALPHA_SATURATE
};
GlWindow::GlWindow(void)
{
_iLight = 0;
memset(&_drcBound, 0, sizeof(_drcBound));
_dmView = dmIdentity;
_dmProjection = dmIdentity;
_pfWorld = NULL;
_pfView = NULL;
_pfProjection = NULL;
memset(&_gltkw, 0, sizeof(_gltkw));
_hrc = NULL;
}
BOOL GlWindow::Initialize(int x, int y,
UINT uiWidth, UINT uiHeight, UINT uiBuffers)
{
PIXELFORMATDESCRIPTOR pfd;
int iFmt;
if (gltkCreateWindow(app.hDlg, "OpenGL Performance Test",
x, y, uiWidth, uiHeight, &_gltkw) == NULL)
{
return FALSE;
}
memset(&pfd, 0, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
if (uiBuffers & REND_BUFFER_BACK)
{
pfd.dwFlags |= PFD_DOUBLEBUFFER;
}
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = GetDeviceCaps(_gltkw.hdc, BITSPIXEL)*
GetDeviceCaps(_gltkw.hdc, PLANES);
if (uiBuffers & REND_BUFFER_Z)
{
pfd.cDepthBits = 16;
}
pfd.cAuxBuffers = 0;
pfd.iLayerType = PFD_MAIN_PLANE;
iFmt = ChoosePixelFormat(_gltkw.hdc, &pfd);
if (iFmt == 0)
{
return FALSE;
}
if (DescribePixelFormat(_gltkw.hdc, iFmt, sizeof(pfd), &pfd) == 0)
{
return FALSE;
}
if (!SetPixelFormat(_gltkw.hdc, iFmt, &pfd))
{
return FALSE;
}
if ((pfd.dwFlags & PFD_NEED_PALETTE) &&
gltkCreateRGBPalette(&_gltkw) == NULL)
{
return FALSE;
}
_hrc = wglCreateContext(_gltkw.hdc);
if (_hrc == NULL)
{
return FALSE;
}
if (!wglMakeCurrent(_gltkw.hdc, _hrc))
{
return FALSE;
}
if (!SetViewport(0, 0, uiWidth, uiHeight))
{
return FALSE;
}
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
#if 0
// Unclear what D3D's model is
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
#endif
return TRUE;
}
GlWindow::~GlWindow(void)
{
if (_hrc != NULL)
{
wglDeleteContext(_hrc);
}
if (_gltkw.hwnd != NULL)
{
DestroyWindow(_gltkw.hwnd);
}
}
void GlWindow::Release(void)
{
delete this;
}
BOOL GlWindow::SetViewport(int x, int y, UINT uiWidth, UINT uiHeight)
{
_drcBound.x1 = x;
_drcBound.y1 = y;
_drcBound.x2 = x+uiWidth;
_drcBound.y2 = y+uiHeight;
glViewport(x, y, uiWidth, uiHeight);
return TRUE;
}
RendLight* GlWindow::NewLight(int iType)
{
GlLight* prlight;
GLenum eLight;
eLight = GL_LIGHT0+_iLight;
prlight = new GlLight(iType, eLight);
if (prlight != NULL)
{
_iLight++;
}
return prlight;
}
RendTexture* GlWindow::NewTexture(char* pszFile, UINT uiFlags)
{
GlTexture* pgtex;
GLuint uiTexObj;
Image im;
ImageFormat ifmt;
pgtex = new GlTexture;
if (pgtex == NULL)
{
return NULL;
}
if (!pgtex->Initialize(pszFile))
{
delete pgtex;
return NULL;
}
return pgtex;
}
RendExecuteBuffer* GlWindow::NewExecuteBuffer(UINT cbSize, UINT uiFlags)
{
GlExecuteBuffer* pgeb;
pgeb = new GlExecuteBuffer;
if (pgeb == NULL)
{
return NULL;
}
if (!pgeb->Initialize(cbSize, uiFlags))
{
delete pgeb;
return NULL;
}
return pgeb;
}
RendMatrix* GlWindow::NewMatrix(void)
{
return new GlMatrix(this);
}
RendMaterial* GlWindow::NewMaterial(UINT nColorEntries)
{
return new GlMaterial;
}
BOOL GlWindow::BeginScene(void)
{
_eTexMin = DEF_TEX_MIN;
_eTexMag = DEF_TEX_MAG;
_eSrcBlend = GL_ONE;
_eDstBlend = GL_ZERO;
glDisable(GL_TEXTURE_2D);
return TRUE;
}
BOOL GlWindow::Execute(RendExecuteBuffer* preb)
{
BOOL bSucc;
#ifdef GL_EXT_clip_volume_hint
int i;
glGetIntegerv(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, &i);
glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, GL_FASTEST);
#endif
bSucc = DoExecute(preb);
#ifdef GL_EXT_clip_volume_hint
glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, i);
#endif
return bSucc;
}
BOOL GlWindow::ExecuteClipped(RendExecuteBuffer* preb)
{
return DoExecute(preb);
}
BOOL GlWindow::EndScene(D3DRECT* pdrcBound)
{
if (pdrcBound != NULL)
{
if (app.uiCurrentTest == THROUGHPUT_TEST)
{
// The throughput test only draws on a small portion of the
// viewport so it's critical that we provide a small
// bound
pdrcBound->x1 = _drcBound.x1+(WIN_WIDTH*34/100);
pdrcBound->y1 = _drcBound.y1+(WIN_HEIGHT*34/100);
pdrcBound->x2 = _drcBound.x2-(WIN_WIDTH*34/100);
pdrcBound->y2 = _drcBound.y2-(WIN_HEIGHT*34/100);
}
else
{
// All other tests fill the whole viewport
*pdrcBound = _drcBound;
}
}
return TRUE;
}
BOOL GlWindow::Clear(UINT uiBuffers, D3DRECT* pdrc)
{
GLbitfield grfMask;
if (pdrc != NULL)
{
glEnable(GL_SCISSOR_TEST);
glScissor(pdrc->x1, pdrc->y1, pdrc->x2-pdrc->x1, pdrc->y2-pdrc->y1);
}
// Assumes window is always double-buffered
if (uiBuffers & REND_BUFFER_FRONT)
{
glDrawBuffer(GL_FRONT);
glClear(GL_COLOR_BUFFER_BIT);
glDrawBuffer(GL_BACK);
}
grfMask = 0;
if (uiBuffers & REND_BUFFER_BACK)
{
grfMask |= GL_COLOR_BUFFER_BIT;
}
if (uiBuffers & REND_BUFFER_Z)
{
grfMask |= GL_DEPTH_BUFFER_BIT;
}
glClear(grfMask);
if (pdrc != NULL)
{
glDisable(GL_SCISSOR_TEST);
}
return TRUE;
}
BOOL GlWindow::Flip(void)
{
SwapBuffers(_gltkw.hdc);
return TRUE;
}
// #define SHOW_BOUND
BOOL GlWindow::CopyForward(D3DRECT* pdrc)
{
#ifdef GL_WIN_swap_hint
if (pdrc != NULL && glAddSwapHintRectWIN != NULL)
{
glAddSwapHintRectWIN(pdrc->x1, pdrc->y1,
pdrc->x2-pdrc->x1, pdrc->y2-pdrc->y1);
}
#endif
SwapBuffers(_gltkw.hdc);
#ifdef SHOW_BOUND
SelectObject(_gltkw.hdc, GetStockObject(WHITE_PEN));
MoveToEx(_gltkw.hdc, pdrc->x1, pdrc->y1, NULL);
LineTo(_gltkw.hdc, pdrc->x1, pdrc->y2);
LineTo(_gltkw.hdc, pdrc->x2, pdrc->y2);
LineTo(_gltkw.hdc, pdrc->x2, pdrc->y1);
LineTo(_gltkw.hdc, pdrc->x1, pdrc->y1);
#endif
return TRUE;
}
HWND GlWindow::Handle(void)
{
return _gltkw.hwnd;
}
static D3DMATRIX dmFlipZ =
{
D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0),
D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0),
D3DVAL(0.0), D3DVAL(0.0), D3DVAL(-1.0), D3DVAL(0.0),
D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1.0)
};
void GlWindow::ChangeWorld(float *pfMatrix)
{
glLoadMatrixf(pfMatrix);
_pfWorld = pfMatrix;
}
void GlWindow::ChangeView(float *pfMatrix)
{
memcpy(&_dmView, pfMatrix, sizeof(_dmView));
glMatrixMode(GL_PROJECTION);
glLoadMatrixf((float *)&_dmProjection);
glMultMatrixf((float *)&_dmView);
glMatrixMode(GL_MODELVIEW);
_pfView = pfMatrix;
}
void GlWindow::ChangeProjection(float *pfMatrix)
{
// D3D is left-handed while OpenGL is right-handed
// Flip the Z direction to account for this
// Could just change row three's signs but this
// matrix doesn't change often
MultiplyD3DMATRIX(&_dmProjection, (D3DMATRIX *)pfMatrix, &dmFlipZ);
glMatrixMode(GL_PROJECTION);
glLoadMatrixf((float *)&_dmProjection);
glMultMatrixf((float *)&_dmView);
glMatrixMode(GL_MODELVIEW);
_pfProjection = pfMatrix;
}
void GlWindow::MatrixChanged(float *pfMatrix)
{
if (pfMatrix == _pfWorld)
{
ChangeWorld(pfMatrix);
}
else if (pfMatrix == _pfView)
{
ChangeView(pfMatrix);
}
else if (pfMatrix == _pfProjection)
{
ChangeProjection(pfMatrix);
}
}
BOOL GlWindow::DoExecute(RendExecuteBuffer* preb)
{
D3DINSTRUCTION* pdinst;
GlExecuteBuffer* pgeb;
BOOL bExit;
ULONG i;
D3DSTATE* pdst;
float fv4[4];
BOOL bProcessedVertices;
BOOL bDisplayList;
#if DBG
D3DINSTRUCTION *pdinstPrev;
#endif
pgeb = (GlExecuteBuffer *)preb;
bDisplayList = FALSE;
if (pgeb->_dlist != 0)
{
glCallList(pgeb->_dlist);
return TRUE;
}
else if (pgeb->_nVertices > 0)
{
// Create a display list for any execute buffer with vertices
// This is a performance win for glDrawElements
// This is wasted time in the full fill test since
// the vertex data changes all the time
if (app.uiCurrentTest != FILL_RATE_TEST)
{
pgeb->_dlist = glGenLists(1);
glNewList(pgeb->_dlist, GL_COMPILE_AND_EXECUTE);
bDisplayList = TRUE;
}
}
pdinst = (D3DINSTRUCTION *)(pgeb->_pbData+pgeb->_cbStart);
bProcessedVertices = FALSE;
// Account for RH vs. LH
glDepthRange(1, 0);
glEnableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
#ifndef NO_LIGHTING
if (_iLight > 0)
{
glEnable(GL_LIGHTING);
}
#endif
bExit = FALSE;
#if DBG
pdinstPrev = NULL;
#endif
while (!bExit &&
(BYTE *)pdinst < (pgeb->_pbData+pgeb->_cbStart+pgeb->_cbSize))
{
#if 0
printf("Op %d, size %d, count %d\n",
pdinst->bOpcode, pdinst->bSize, pdinst->wCount);
#endif
switch(pdinst->bOpcode)
{
case D3DOP_POINT:
// Consider implementing
break;
case D3DOP_LINE:
// Consider implementing
break;
case D3DOP_TRIANGLE:
if (pdinst->wCount > 0)
{
Msg("Unprocessed execute buffer");
return FALSE;
}
break;
case D3DOP_MATRIXLOAD:
D3DMATRIXLOAD* pdml;
pdml = (D3DMATRIXLOAD *)(pdinst+1);
for (i = 0; i < pdinst->wCount; i++)
{
memcpy((BYTE *)pdml->hDestMatrix,
(BYTE *)pdml->hSrcMatrix,
sizeof(D3DMATRIX));
#if 0
// Should we check here also?
MatrixChanged((float *)pdml->hDestMatrix);
#endif
pdml++;
}
break;
case D3DOP_MATRIXMULTIPLY:
D3DMATRIXMULTIPLY* pdmm;
pdmm = (D3DMATRIXMULTIPLY *)(pdinst+1);
for (i = 0; i < pdinst->wCount; i++)
{
MultiplyD3DMATRIX((D3DMATRIX *)pdmm->hDestMatrix,
(D3DMATRIX *)pdmm->hSrcMatrix1,
(D3DMATRIX *)pdmm->hSrcMatrix2);
#if 0
// Should we check here also?
MatrixChanged((float *)pdmm->hDestMatrix);
#endif
pdmm++;
}
break;
case D3DOP_STATETRANSFORM:
pdst = (D3DSTATE *)(pdinst+1);
for (i = 0; i < pdinst->wCount; i++)
{
switch(pdst->dtstTransformStateType)
{
case D3DTRANSFORMSTATE_WORLD:
ChangeWorld((float *)pdst->dwArg[0]);
break;
case D3DTRANSFORMSTATE_VIEW:
ChangeView((float *)pdst->dwArg[0]);
break;
case D3DTRANSFORMSTATE_PROJECTION:
ChangeProjection((float *)pdst->dwArg[0]);
break;
}
pdst++;
}
break;
case D3DOP_STATELIGHT:
pdst = (D3DSTATE *)(pdinst+1);
for (i = 0; i < pdinst->wCount; i++)
{
switch(pdst->dlstLightStateType)
{
case D3DLIGHTSTATE_MATERIAL:
// Should probably optimize this so
// that work is done only when material properties
// change
((GlMaterial *)pdst->dwArg[0])->Apply();
break;
case D3DLIGHTSTATE_AMBIENT:
fv4[0] = (float)((pdst->dwArg[0] >> 16) & 0xff) / 255.0f;
fv4[1] = (float)((pdst->dwArg[0] >> 8) & 0xff) / 255.0f;
fv4[2] = (float)((pdst->dwArg[0] >> 0) & 0xff) / 255.0f;
fv4[3] = (float)((pdst->dwArg[0] >> 24) & 0xff) / 255.0f;
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, fv4);
break;
// Others
}
pdst++;
}
break;
case D3DOP_STATERENDER:
pdst = (D3DSTATE *)(pdinst+1);
for (i = 0; i < pdinst->wCount; i++)
{
switch(pdst->drstRenderStateType)
{
// Many to implement but all currently
// used values are handled
case D3DRENDERSTATE_TEXTUREHANDLE:
if (pdst->dwArg[0] == 0)
{
glDisable(GL_TEXTURE_2D);
}
else
{
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, (GLuint)pdst->dwArg[0]);
// Establish current texture params
glTexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_MIN_FILTER, _eTexMin);
glTexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_MAG_FILTER, _eTexMag);
}
break;
case D3DRENDERSTATE_WRAPU:
case D3DRENDERSTATE_WRAPV:
// These should probably be supported
// but it's non-trivial plus the default state
// is currently wrap and that's what the tests
// care about
break;
case D3DRENDERSTATE_SHADEMODE:
switch(pdst->dwArg[0])
{
case D3DSHADE_FLAT:
glShadeModel(GL_FLAT);
break;
case D3DSHADE_GOURAUD:
glShadeModel(GL_SMOOTH);
break;
default:
Msg("Unsupported SHADEMODE %d", pdst->dwArg[0]);
return FALSE;
}
break;
case D3DRENDERSTATE_TEXTUREMAPBLEND:
GLenum eTexMode;
switch(pdst->dwArg[0])
{
case D3DTBLEND_DECAL:
// Technically D3DTBLEND_DECAL doesn't match
// GL_DECAL, but it's close enough
case D3DTBLEND_DECALALPHA:
eTexMode = GL_DECAL;
break;
case D3DTBLEND_MODULATE:
// Technically D3DTBLEND_MODULATE doesn't match
// GL_MODULATE, but it's close enough
case D3DTBLEND_MODULATEALPHA:
eTexMode = GL_MODULATE;
break;
case D3DTBLEND_COPY:
eTexMode = GL_REPLACE;
break;
default:
Msg("Unsupported TEXTUREMAPBLEND %d", pdst->dwArg[0]);
return FALSE;
}
if (eTexMode != DEF_TEX_MODE)
{
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
eTexMode);
}
break;
case D3DRENDERSTATE_TEXTUREPERSPECTIVE:
glHint(GL_PERSPECTIVE_CORRECTION_HINT,
pdst->dwArg[0] ? GL_NICEST : GL_FASTEST);
break;
case D3DRENDERSTATE_ZENABLE:
if (pdst->dwArg[0])
{
glEnable(GL_DEPTH_TEST);
}
else
{
glDisable(GL_DEPTH_TEST);
}
break;
case D3DRENDERSTATE_ZWRITEENABLE:
glDepthMask((GLboolean)pdst->dwArg[0]);
break;
case D3DRENDERSTATE_ZFUNC:
glDepthFunc(eDepthFuncTranslate[pdst->dwArg[0]]);
break;
case D3DRENDERSTATE_TEXTUREMAG:
_eTexMag = eTextureFilterTranslate[pdst->dwArg[0]];
break;
case D3DRENDERSTATE_TEXTUREMIN:
_eTexMin = eTextureFilterTranslate[pdst->dwArg[0]];
break;
case D3DRENDERSTATE_DITHERENABLE:
if (pdst->dwArg[0])
{
glEnable(GL_DITHER);
break;
}
else
{
glDisable(GL_DITHER);
break;
}
break;
case D3DRENDERSTATE_BLENDENABLE:
if (pdst->dwArg[0])
{
glEnable(GL_BLEND);
break;
}
else
{
glDisable(GL_BLEND);
break;
}
break;
case D3DRENDERSTATE_SRCBLEND:
if (pdst->dwArg[0] == D3DBLEND_BOTHSRCALPHA)
{
_eSrcBlend = GL_SRC_ALPHA;
_eDstBlend = GL_ONE_MINUS_SRC_ALPHA;
}
else if (pdst->dwArg[0] == D3DBLEND_BOTHINVSRCALPHA)
{
_eSrcBlend = GL_ONE_MINUS_SRC_ALPHA;
_eDstBlend = GL_SRC_ALPHA;
}
else
{
_eSrcBlend = eBlendFuncTranslate[pdst->dwArg[0]];
}
glBlendFunc(_eSrcBlend, _eDstBlend);
break;
case D3DRENDERSTATE_DESTBLEND:
_eDstBlend = eBlendFuncTranslate[pdst->dwArg[0]];
glBlendFunc(_eSrcBlend, _eDstBlend);
break;
case D3DRENDERSTATE_SPECULARENABLE:
// Can't turn this off
break;
case D3DRENDERSTATE_MONOENABLE:
if (pdst->dwArg[0] != 0)
{
Msg("Can't render in MONO mode");
}
break;
default:
Msg("Unhandled RENDERSTATE %d", pdst->drstRenderStateType);
break;
}
pdst++;
}
break;
case D3DOP_PROCESSVERTICES:
D3DPROCESSVERTICES* pdpv;
pdpv = (D3DPROCESSVERTICES *)(pdinst+1);
for (i = 0; i < pdinst->wCount; i++)
{
if (bProcessedVertices)
{
Msg("Multiple PROCESSVERTICES in execute buffer");
return FALSE;
}
switch(pdpv->dwFlags & D3DPROCESSVERTICES_OPMASK)
{
case D3DPROCESSVERTICES_TRANSFORMLIGHT:
D3DVERTEX* pdvtx;
pdvtx = (D3DVERTEX *)(pgeb->_pbData+pdpv->wStart);
glVertexPointer(3, GL_FLOAT, sizeof(D3DVERTEX),
&pdvtx[0].x);
glNormalPointer(GL_FLOAT, sizeof(D3DVERTEX), &pdvtx[0].nx);
glTexCoordPointer(2, GL_FLOAT, sizeof(D3DVERTEX),
&pdvtx[0].tu);
break;
case D3DPROCESSVERTICES_COPY:
D3DTLVERTEX* pdtlvtx;
pdtlvtx = (D3DTLVERTEX *)(pgeb->_pbData+pdpv->wStart);
glVertexPointer(3, GL_FLOAT, sizeof(D3DTLVERTEX),
&pdtlvtx[0].sx);
glTexCoordPointer(2, GL_FLOAT, sizeof(D3DTLVERTEX),
&pdtlvtx[0].tu);
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(D3DTLVERTEX),
&pdtlvtx[0].color);
glDisableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glDisable(GL_LIGHTING);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Flip Y, Z to match D3D
glOrtho(0, WIN_WIDTH, WIN_HEIGHT, 0, 0, 1);
// Flip Z to match D3D
glMultMatrixf((float *)&dmFlipZ);
glDepthRange(0, 1);
glMatrixMode(GL_MODELVIEW);
break;
default:
Msg("Unsupported vertex processing type %X",
pdpv->dwFlags & D3DPROCESSVERTICES_OPMASK);
return FALSE;
}
bProcessedVertices = TRUE;
pdpv++;
}
break;
case D3DOP_TEXTURELOAD:
D3DTEXTURELOAD* pdtl;
pdtl = (D3DTEXTURELOAD *)(pdinst+1);
for (i = 0; i < pdinst->wCount; i++)
{
// Consider implementing
pdtl++;
}
break;
case D3DOP_EXIT:
bExit = TRUE;
break;
case D3DOP_BRANCHFORWARD:
// Consider implementing
break;
case D3DOP_SPAN:
// Consider implementing
break;
case D3DOP_SETSTATUS:
// Consider implementing
break;
case PROCESSED_TRIANGLE:
if (!bProcessedVertices)
{
Msg("Triangles without vertex data");
return FALSE;
}
glDrawElements(GL_TRIANGLES, pdinst->wCount*3L, GL_UNSIGNED_INT,
*(GLuint **)(pdinst+1));
break;
default:
#if DBG
if (pdinstPrev != NULL)
{
Msg("Invalid execute buffer opcode %d:%d (%08lX), "
"prev %d:%d (%08lX)",
pdinst->bOpcode, pdinst->wCount, pdinst,
pdinstPrev->bOpcode, pdinstPrev->wCount, pdinstPrev);
}
else
{
Msg("Invalid execute buffer opcode %d", pdinst->bOpcode);
}
#else
Msg("Invalid execute buffer opcode %d", pdinst->bOpcode);
#endif
return FALSE;
}
#if DBG
pdinstPrev = pdinst;
#endif
// Could eliminate this, it has a multiply
pdinst = NEXT_PDINST(pdinst);
}
if (bDisplayList)
{
glEndList();
}
return TRUE;
}