697 lines
17 KiB
C
697 lines
17 KiB
C
|
/******************************Module*Header*******************************\
|
||
|
* Module Name: mcdprim.c
|
||
|
*
|
||
|
* These routines process the OpenGL rendering commands that appear in an
|
||
|
* MCDrvDraw() batch. Note that the only OpenGL primitive which is invalid
|
||
|
* is LineLoop. This gets decomposed by the caller into a LineStrip command.
|
||
|
*
|
||
|
* Copyright (c) 1996 Microsoft Corporation
|
||
|
\**************************************************************************/
|
||
|
|
||
|
#include "precomp.h"
|
||
|
|
||
|
#include "mcdhw.h"
|
||
|
#include "mcdutil.h"
|
||
|
|
||
|
#define MEMCHECK_VERTEX(p)\
|
||
|
if (((UCHAR *)p < pRc->pMemMin) ||\
|
||
|
((UCHAR *)p > pRc->pMemMax)) {\
|
||
|
MCDBG_PRINT("Invalid MCD vertex pointer!");\
|
||
|
return NULL;\
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// The functions below are local rendering-helper functions which call
|
||
|
// the real rendering routines in the driver.
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
VOID static FASTCALL __MCDRenderPoint(DEVRC *pRc, MCDVERTEX *v)
|
||
|
{
|
||
|
if (v->clipCode == 0)
|
||
|
(*pRc->renderPoint)(pRc, v);
|
||
|
}
|
||
|
|
||
|
VOID static FASTCALL __MCDRenderLine(DEVRC *pRc, MCDVERTEX *v0,
|
||
|
MCDVERTEX *v1, BOOL bResetLine)
|
||
|
{
|
||
|
if (v0->clipCode | v1->clipCode)
|
||
|
{
|
||
|
/*
|
||
|
* The line must be clipped more carefully. Cannot
|
||
|
* trivially accept the lines.
|
||
|
*
|
||
|
* If anding the codes is non-zero then every vertex
|
||
|
* in the line is outside of the same set of clipping
|
||
|
* planes (at least one). Trivially reject the line.
|
||
|
*/
|
||
|
if ((v0->clipCode & v1->clipCode) == 0)
|
||
|
(*pRc->clipLine)(pRc, v0, v1, bResetLine);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Line is trivially accepted so render it
|
||
|
(*pRc->renderLine)(pRc, v0, v1, bResetLine);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VOID static FASTCALL __MCDRenderTriangle(DEVRC *pRc, MCDVERTEX *v0,
|
||
|
MCDVERTEX *v1, MCDVERTEX *v2)
|
||
|
{
|
||
|
ULONG orCodes;
|
||
|
|
||
|
/* Clip check */
|
||
|
orCodes = v0->clipCode | v1->clipCode | v2->clipCode;
|
||
|
if (orCodes)
|
||
|
{
|
||
|
/* Some kind of clipping is needed.
|
||
|
*
|
||
|
* If anding the codes is non-zero then every vertex
|
||
|
* in the triangle is outside of the same set of
|
||
|
* clipping planes (at least one). Trivially reject
|
||
|
* the triangle.
|
||
|
*/
|
||
|
if (!(v0->clipCode & v1->clipCode & v2->clipCode))
|
||
|
(*pRc->clipTri)(pRc, v0, v1, v2, orCodes);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
(*pRc->renderTri)(pRc, v0, v1, v2);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VOID static FASTCALL __MCDRenderQuad(DEVRC *pRc, MCDVERTEX *v0,
|
||
|
MCDVERTEX *v1, MCDVERTEX *v2, MCDVERTEX *v3)
|
||
|
{
|
||
|
// Vertex ordering is important. Line stippling uses it.
|
||
|
|
||
|
ULONG savedTag;
|
||
|
|
||
|
/* Render the quad as two triangles */
|
||
|
savedTag = v2->flags & MCDVERTEX_EDGEFLAG;
|
||
|
v2->flags &= ~MCDVERTEX_EDGEFLAG;
|
||
|
(*pRc->renderTri)(pRc, v0, v1, v2);
|
||
|
v2->flags |= savedTag;
|
||
|
savedTag = v0->flags & MCDVERTEX_EDGEFLAG;
|
||
|
v0->flags &= ~MCDVERTEX_EDGEFLAG;
|
||
|
(*pRc->renderTri)(pRc, v2, v3, v0);
|
||
|
v0->flags |= savedTag;
|
||
|
}
|
||
|
|
||
|
VOID static FASTCALL __MCDRenderClippedQuad(DEVRC *pRc, MCDVERTEX *v0,
|
||
|
MCDVERTEX *v1, MCDVERTEX *v2, MCDVERTEX *v3)
|
||
|
{
|
||
|
ULONG orCodes;
|
||
|
|
||
|
orCodes = v0->clipCode | v1->clipCode | v2->clipCode | v3->clipCode;
|
||
|
|
||
|
if (orCodes)
|
||
|
{
|
||
|
/* Some kind of clipping is needed.
|
||
|
*
|
||
|
* If anding the codes is non-zero then every vertex
|
||
|
* in the quad is outside of the same set of
|
||
|
* clipping planes (at least one). Trivially reject
|
||
|
* the quad.
|
||
|
*/
|
||
|
if (!(v0->clipCode & v1->clipCode & v2->clipCode & v3->clipCode))
|
||
|
{
|
||
|
/* Clip the quad as a polygon */
|
||
|
MCDVERTEX *iv[4];
|
||
|
|
||
|
iv[0] = v0;
|
||
|
iv[1] = v1;
|
||
|
iv[2] = v2;
|
||
|
iv[3] = v3;
|
||
|
(pRc->doClippedPoly)(pRc, &iv[0], 4, orCodes);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
__MCDRenderQuad(pRc, v0, v1, v2, v3);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// The functions below handle the processing of all of the primitives
|
||
|
// which may appear in an MCDCOMMAND. This includes all of the OpenGL
|
||
|
// primitives, with the exception of line loops which are handled as
|
||
|
// line strips.
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
MCDCOMMAND * FASTCALL __MCDPrimDrawPoints(DEVRC *pRc, MCDCOMMAND *pCmd)
|
||
|
{
|
||
|
LONG i, nIndices;
|
||
|
MCDVERTEX *pv;
|
||
|
VOID (FASTCALL *rp)(DEVRC *pRc, MCDVERTEX *v);
|
||
|
|
||
|
// Index mapping is always identity in Points.
|
||
|
|
||
|
// ASSERTOPENGL(!pa->aIndices, "Index mapping must be identity\n");
|
||
|
|
||
|
if (pCmd->clipCodes)
|
||
|
rp = __MCDRenderPoint;
|
||
|
else
|
||
|
rp = pRc->renderPoint;
|
||
|
|
||
|
(*pRc->beginPointDrawing)(pRc);
|
||
|
|
||
|
// Render the points:
|
||
|
|
||
|
pv = pCmd->pStartVertex;
|
||
|
MEMCHECK_VERTEX(pv);
|
||
|
i = pCmd->numIndices;
|
||
|
MEMCHECK_VERTEX(pv + (i - 1));
|
||
|
|
||
|
for (; i > 0; i--, pv++)
|
||
|
(*rp)(pRc, pv);
|
||
|
|
||
|
return pCmd->pNextCmd;
|
||
|
}
|
||
|
|
||
|
|
||
|
MCDCOMMAND * FASTCALL __MCDPrimDrawLines(DEVRC *pRc, MCDCOMMAND *pCmd)
|
||
|
{
|
||
|
LONG i, iLast2;
|
||
|
UCHAR *pIndices;
|
||
|
MCDVERTEX *pv, *pv0, *pv1;
|
||
|
VOID (FASTCALL *rl)(DEVRC *pRc, MCDVERTEX *pv1, MCDVERTEX *pv2, BOOL bResetLine);
|
||
|
|
||
|
iLast2 = pCmd->numIndices - 2;
|
||
|
pv = pCmd->pStartVertex;
|
||
|
rl = pCmd->clipCodes ? __MCDRenderLine : pRc->renderLine;
|
||
|
|
||
|
(*pRc->beginLineDrawing)(pRc);
|
||
|
|
||
|
if (!(pIndices = pCmd->pIndices))
|
||
|
{
|
||
|
// Identity mapping
|
||
|
|
||
|
MEMCHECK_VERTEX(pv);
|
||
|
MEMCHECK_VERTEX(pv + (iLast2 + 1));
|
||
|
|
||
|
for (i = 0; i <= iLast2; i += 2)
|
||
|
{
|
||
|
/* setup for rendering this line */
|
||
|
|
||
|
pRc->resetLineStipple = TRUE;
|
||
|
|
||
|
(*rl)(pRc, &pv[i], &pv[i+1], TRUE);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (i = 0; i <= iLast2; i += 2)
|
||
|
{
|
||
|
pv0 = &pv[pIndices[i]];
|
||
|
pv1 = &pv[pIndices[i+1]];
|
||
|
MEMCHECK_VERTEX(pv0);
|
||
|
MEMCHECK_VERTEX(pv1);
|
||
|
|
||
|
/* setup for rendering this line */
|
||
|
|
||
|
pRc->resetLineStipple = TRUE;
|
||
|
|
||
|
(*rl)(pRc, pv0, pv1, TRUE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
(*pRc->endLineDrawing)(pRc);
|
||
|
|
||
|
return pCmd->pNextCmd;
|
||
|
}
|
||
|
|
||
|
|
||
|
MCDCOMMAND * FASTCALL __MCDPrimDrawLineLoop(DEVRC *pRc, MCDCOMMAND *pCmd)
|
||
|
{
|
||
|
// NOTE:
|
||
|
// Line loops are always converted tp line strips at the OpenGL
|
||
|
// API level. This routine is currently not used.
|
||
|
|
||
|
MCDBG_PRINT("MCDPrimLineLoop: Invalid MCD command!");
|
||
|
|
||
|
return pCmd->pNextCmd;
|
||
|
}
|
||
|
|
||
|
|
||
|
MCDCOMMAND * FASTCALL __MCDPrimDrawLineStrip(DEVRC *pRc, MCDCOMMAND *pCmd)
|
||
|
{
|
||
|
LONG i, iLast;
|
||
|
UCHAR *pIndices;
|
||
|
MCDVERTEX *pv, *pv0, *pv1;
|
||
|
MCDVERTEX *vOld;
|
||
|
VOID (FASTCALL *rl)(DEVRC *pRc, MCDVERTEX *pv1, MCDVERTEX *pv2, BOOL bResetLine);
|
||
|
|
||
|
iLast = pCmd->numIndices - 1;
|
||
|
pv = pCmd->pStartVertex;
|
||
|
rl = pCmd->clipCodes ? __MCDRenderLine : pRc->renderLine;
|
||
|
if (iLast <= 0)
|
||
|
return pCmd->pNextCmd;
|
||
|
|
||
|
if (pCmd->flags & MCDCOMMAND_RESET_STIPPLE)
|
||
|
pRc->resetLineStipple = TRUE;
|
||
|
|
||
|
(*pRc->beginLineDrawing)(pRc);
|
||
|
|
||
|
if (!(pIndices = pCmd->pIndices))
|
||
|
{
|
||
|
// Identity mapping
|
||
|
// Add first line segment (NOTE: 0, 1)
|
||
|
|
||
|
MEMCHECK_VERTEX(pv);
|
||
|
MEMCHECK_VERTEX(pv + iLast);
|
||
|
|
||
|
(*rl)(pRc, &pv[0], &pv[1], TRUE);
|
||
|
|
||
|
// Add subsequent line segments (NOTE: i, i+1)
|
||
|
for (i = 1; i < iLast; i++) {
|
||
|
(*rl)(pRc, &pv[i], &pv[i+1], FALSE);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Add first line segment (NOTE: 0, 1)
|
||
|
|
||
|
pv0 = &pv[pIndices[0]];
|
||
|
pv1 = &pv[pIndices[1]];
|
||
|
(*rl)(pRc, pv0, pv1, TRUE);
|
||
|
|
||
|
// Add subsequent line segments (NOTE: i, i+1)
|
||
|
|
||
|
for (i = 1; i < iLast; i++) {
|
||
|
pv0 = pv1;
|
||
|
pv1 = &pv[pIndices[i+1]];
|
||
|
MEMCHECK_VERTEX(pv1);
|
||
|
(*rl)(pRc, pv0, pv1, FALSE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
(*pRc->endLineDrawing)(pRc);
|
||
|
|
||
|
return pCmd->pNextCmd;
|
||
|
}
|
||
|
|
||
|
|
||
|
MCDCOMMAND * FASTCALL __MCDPrimDrawTriangles(DEVRC *pRc, MCDCOMMAND *pCmd)
|
||
|
{
|
||
|
LONG i, iLast3;
|
||
|
UCHAR *pIndices;
|
||
|
MCDVERTEX *pv, *pv0, *pv1, *pv2;
|
||
|
VOID (FASTCALL *rt)(DEVRC *pRc, MCDVERTEX *v0, MCDVERTEX *v1, MCDVERTEX *v2);
|
||
|
|
||
|
iLast3 = pCmd->numIndices - 3;
|
||
|
pv = pCmd->pStartVertex;
|
||
|
if (pCmd->clipCodes)
|
||
|
rt = __MCDRenderTriangle;
|
||
|
else
|
||
|
rt = pRc->renderTri;
|
||
|
|
||
|
|
||
|
if (!(pIndices = pCmd->pIndices))
|
||
|
{
|
||
|
// Identity mapping
|
||
|
|
||
|
MEMCHECK_VERTEX(pv);
|
||
|
MEMCHECK_VERTEX(pv + (iLast3 + 2));
|
||
|
|
||
|
for (i = 0; i <= iLast3; i += 3)
|
||
|
{
|
||
|
/* setup for rendering this triangle */
|
||
|
|
||
|
pRc->resetLineStipple = TRUE;
|
||
|
pRc->pvProvoking = &pv[i+2];
|
||
|
|
||
|
/* Render the triangle (NOTE: i, i+1, i+2) */
|
||
|
(*rt)(pRc, &pv[i], &pv[i+1], &pv[i+2]);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (i = 0; i <= iLast3; i += 3)
|
||
|
{
|
||
|
/* setup for rendering this triangle */
|
||
|
|
||
|
pv0 = &pv[pIndices[i ]];
|
||
|
pv1 = &pv[pIndices[i+1]];
|
||
|
pv2 = &pv[pIndices[i+2]];
|
||
|
|
||
|
MEMCHECK_VERTEX(pv0);
|
||
|
MEMCHECK_VERTEX(pv1);
|
||
|
MEMCHECK_VERTEX(pv2);
|
||
|
|
||
|
pRc->resetLineStipple = TRUE;
|
||
|
pRc->pvProvoking = pv2;
|
||
|
|
||
|
/* Render the triangle (NOTE: i, i+1, i+2) */
|
||
|
(*rt)(pRc, pv0, pv1, pv2);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return pCmd->pNextCmd;
|
||
|
}
|
||
|
|
||
|
|
||
|
MCDCOMMAND * FASTCALL __MCDPrimDrawTriangleStrip(DEVRC *pRc, MCDCOMMAND *pCmd)
|
||
|
{
|
||
|
LONG i, iLast3;
|
||
|
UCHAR *pIndices;
|
||
|
MCDVERTEX *pv, *pv0, *pv1, *pv2;
|
||
|
VOID (FASTCALL *rt)(DEVRC *pRc, MCDVERTEX *v0, MCDVERTEX *v1, MCDVERTEX *v2);
|
||
|
|
||
|
iLast3 = pCmd->numIndices - 3;
|
||
|
pv = pCmd->pStartVertex;
|
||
|
if (pCmd->clipCodes)
|
||
|
rt = __MCDRenderTriangle;
|
||
|
else
|
||
|
rt = pRc->renderTri;
|
||
|
|
||
|
if (iLast3 < 0)
|
||
|
return pCmd->pNextCmd;
|
||
|
|
||
|
if (!(pIndices = pCmd->pIndices))
|
||
|
{
|
||
|
// Identity mapping
|
||
|
|
||
|
MEMCHECK_VERTEX(pv);
|
||
|
MEMCHECK_VERTEX(pv + (iLast3 + 2));
|
||
|
|
||
|
pv[0].flags |= MCDVERTEX_EDGEFLAG;
|
||
|
pv[1].flags |= MCDVERTEX_EDGEFLAG;
|
||
|
|
||
|
for (i = 0; i <= iLast3; i++)
|
||
|
{
|
||
|
/* setup for rendering this triangle */
|
||
|
|
||
|
pRc->resetLineStipple = TRUE;
|
||
|
pRc->pvProvoking = &pv[i+2];
|
||
|
pv[i+2].flags |= MCDVERTEX_EDGEFLAG;
|
||
|
|
||
|
/* Render the triangle (NOTE: i, i+1, i+2) */
|
||
|
(*rt)(pRc, &pv[i], &pv[i+1], &pv[i+2]);
|
||
|
|
||
|
if (++i > iLast3)
|
||
|
break;
|
||
|
|
||
|
pRc->resetLineStipple = TRUE;
|
||
|
pRc->pvProvoking = &pv[i+2];
|
||
|
pv[i+2].flags |= MCDVERTEX_EDGEFLAG;
|
||
|
|
||
|
/* Render the triangle (NOTE: i+1, i, i+2) */
|
||
|
(*rt)(pRc, &pv[i+1], &pv[i], &pv[i+2]);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
|
||
|
pv1 = &pv[pIndices[0]];
|
||
|
MEMCHECK_VERTEX(pv1);
|
||
|
pv1->flags |= MCDVERTEX_EDGEFLAG;
|
||
|
|
||
|
pv2 = &pv[pIndices[1]];
|
||
|
MEMCHECK_VERTEX(pv2);
|
||
|
pv2->flags |= MCDVERTEX_EDGEFLAG;
|
||
|
|
||
|
for (i = 0; i <= iLast3; i++)
|
||
|
{
|
||
|
/* setup for rendering this triangle */
|
||
|
|
||
|
pRc->resetLineStipple = TRUE;
|
||
|
|
||
|
pv0 = pv1;
|
||
|
pv1 = pv2;
|
||
|
|
||
|
pv2 = &pv[pIndices[i+2]];
|
||
|
MEMCHECK_VERTEX(pv2);
|
||
|
pv2->flags |= MCDVERTEX_EDGEFLAG;
|
||
|
|
||
|
pRc->resetLineStipple = TRUE;
|
||
|
pRc->pvProvoking = pv2;
|
||
|
|
||
|
/* Render the triangle (NOTE: i, i+1, i+2) */
|
||
|
(*rt)(pRc, pv0, pv1, pv2);
|
||
|
|
||
|
if (++i > iLast3)
|
||
|
break;
|
||
|
|
||
|
pv0 = pv1;
|
||
|
pv1 = pv2;
|
||
|
|
||
|
pv2 = &pv[pIndices[i+2]];
|
||
|
MEMCHECK_VERTEX(pv2);
|
||
|
pv2->flags |= MCDVERTEX_EDGEFLAG;
|
||
|
|
||
|
/* setup for rendering this triangle */
|
||
|
|
||
|
pRc->resetLineStipple = TRUE;
|
||
|
pRc->pvProvoking = pv2;
|
||
|
|
||
|
/* Render the triangle (NOTE: i+1, i, i+2) */
|
||
|
(*rt)(pRc, pv1, pv0, pv2);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return pCmd->pNextCmd;
|
||
|
}
|
||
|
|
||
|
|
||
|
MCDCOMMAND * FASTCALL __MCDPrimDrawTriangleFan(DEVRC *pRc, MCDCOMMAND *pCmd)
|
||
|
{
|
||
|
LONG i, iLast2;
|
||
|
UCHAR *pIndices;
|
||
|
MCDVERTEX *pv, *pv0, *pv1, *pv2;
|
||
|
VOID (FASTCALL *rt)(DEVRC *pRc, MCDVERTEX *v0, MCDVERTEX *v1, MCDVERTEX *v2);
|
||
|
|
||
|
iLast2 = pCmd->numIndices - 2;
|
||
|
pv = pCmd->pStartVertex;
|
||
|
if (pCmd->clipCodes)
|
||
|
rt = __MCDRenderTriangle;
|
||
|
else
|
||
|
rt = pRc->renderTri;
|
||
|
|
||
|
if (iLast2 <= 0)
|
||
|
return pCmd->pNextCmd;
|
||
|
|
||
|
if (!(pIndices = pCmd->pIndices))
|
||
|
{
|
||
|
// Identity mapping
|
||
|
|
||
|
MEMCHECK_VERTEX(pv);
|
||
|
MEMCHECK_VERTEX(pv + (iLast2 + 1));
|
||
|
|
||
|
pv[0].flags |= MCDVERTEX_EDGEFLAG;
|
||
|
pv[1].flags |= MCDVERTEX_EDGEFLAG;
|
||
|
|
||
|
for (i = 1; i <= iLast2; i++)
|
||
|
{
|
||
|
/* setup for rendering this triangle */
|
||
|
|
||
|
pRc->resetLineStipple = TRUE;
|
||
|
pRc->pvProvoking = &pv[i+1];
|
||
|
pv[i+1].flags |= MCDVERTEX_EDGEFLAG;
|
||
|
|
||
|
/* Render the triangle (NOTE: 0, i, i+1) */
|
||
|
(*rt)(pRc, &pv[0], &pv[i], &pv[i+1]);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Initialize first 2 vertices so we can start rendering the tfan
|
||
|
// below. The edge flags are not modified by our lower level routines.
|
||
|
|
||
|
pv0 = &pv[pIndices[0]];
|
||
|
MEMCHECK_VERTEX(pv0);
|
||
|
pv0->flags |= MCDVERTEX_EDGEFLAG;
|
||
|
|
||
|
pv2 = &pv[pIndices[1]];
|
||
|
MEMCHECK_VERTEX(pv2);
|
||
|
pv2->flags |= MCDVERTEX_EDGEFLAG;
|
||
|
|
||
|
for (i = 1; i <= iLast2; i++)
|
||
|
{
|
||
|
pv1 = pv2;
|
||
|
|
||
|
pv2 = &pv[pIndices[i+1]];
|
||
|
MEMCHECK_VERTEX(pv2);
|
||
|
pv2->flags |= MCDVERTEX_EDGEFLAG;
|
||
|
|
||
|
/* setup for rendering this triangle */
|
||
|
pRc->resetLineStipple = TRUE;
|
||
|
pRc->pvProvoking = pv2;
|
||
|
|
||
|
/* Render the triangle (NOTE: 0, i, i+1) */
|
||
|
(*rt)(pRc, pv0, pv1, pv2);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return pCmd->pNextCmd;
|
||
|
}
|
||
|
|
||
|
|
||
|
MCDCOMMAND * FASTCALL __MCDPrimDrawQuads(DEVRC *pRc, MCDCOMMAND *pCmd)
|
||
|
{
|
||
|
LONG i, iLast4;
|
||
|
UCHAR *pIndices;
|
||
|
MCDVERTEX *pv, *pv0, *pv1, *pv2, *pv3;
|
||
|
VOID (FASTCALL *rq)(DEVRC *pRc, MCDVERTEX *v0, MCDVERTEX *v1, MCDVERTEX *v2,
|
||
|
MCDVERTEX *v3);
|
||
|
|
||
|
iLast4 = pCmd->numIndices - 4;
|
||
|
pv = pCmd->pStartVertex;
|
||
|
|
||
|
if (pCmd->clipCodes)
|
||
|
rq = __MCDRenderClippedQuad;
|
||
|
else
|
||
|
rq = __MCDRenderQuad;
|
||
|
|
||
|
if (!(pIndices = pCmd->pIndices))
|
||
|
{
|
||
|
|
||
|
MEMCHECK_VERTEX(pv);
|
||
|
MEMCHECK_VERTEX(pv + (iLast4 + 3));
|
||
|
|
||
|
// Identity mapping
|
||
|
for (i = 0; i <= iLast4; i += 4)
|
||
|
{
|
||
|
pRc->resetLineStipple = TRUE;
|
||
|
pRc->pvProvoking = &pv[i+3];
|
||
|
|
||
|
/* Render the quad (NOTE: i, i+1, i+2, i+3) */
|
||
|
(*rq)(pRc, &pv[i], &pv[i+1], &pv[i+2], &pv[i+3]);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (i = 0; i <= iLast4; i += 4)
|
||
|
{
|
||
|
|
||
|
pv0 = &pv[pIndices[i ]];
|
||
|
pv1 = &pv[pIndices[i+1]];
|
||
|
pv2 = &pv[pIndices[i+2]];
|
||
|
pv3 = &pv[pIndices[i+3]];
|
||
|
|
||
|
MEMCHECK_VERTEX(pv0);
|
||
|
MEMCHECK_VERTEX(pv1);
|
||
|
MEMCHECK_VERTEX(pv2);
|
||
|
MEMCHECK_VERTEX(pv3);
|
||
|
|
||
|
|
||
|
pRc->resetLineStipple = TRUE;
|
||
|
pRc->pvProvoking = pv3;
|
||
|
|
||
|
/* Render the quad (NOTE: i, i+1, i+2, i+3) */
|
||
|
(*rq)(pRc, pv0, pv1, pv2, pv3);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return pCmd->pNextCmd;
|
||
|
}
|
||
|
|
||
|
|
||
|
MCDCOMMAND * FASTCALL __MCDPrimDrawQuadStrip(DEVRC *pRc, MCDCOMMAND *pCmd)
|
||
|
{
|
||
|
ULONG i, iLast4;
|
||
|
UCHAR *pIndices;
|
||
|
MCDVERTEX *pv, *pv0, *pv1, *pv2, *pv3;
|
||
|
VOID (FASTCALL *rq)(DEVRC *pRc, MCDVERTEX *v0, MCDVERTEX *v1, MCDVERTEX *v2,
|
||
|
MCDVERTEX *v3);
|
||
|
|
||
|
iLast4 = pCmd->numIndices - 4;
|
||
|
pv = pCmd->pStartVertex;
|
||
|
if (pCmd->clipCodes)
|
||
|
rq = __MCDRenderClippedQuad;
|
||
|
else
|
||
|
rq = __MCDRenderQuad;
|
||
|
|
||
|
// Vertex ordering is important. Line stippling uses it.
|
||
|
|
||
|
if (!(pIndices = pCmd->pIndices))
|
||
|
{
|
||
|
// Identity mapping
|
||
|
|
||
|
MEMCHECK_VERTEX(pv);
|
||
|
MEMCHECK_VERTEX(pv + (iLast4 + 3));
|
||
|
|
||
|
pv[0].flags |= MCDVERTEX_EDGEFLAG;
|
||
|
pv[1].flags |= MCDVERTEX_EDGEFLAG;
|
||
|
|
||
|
for (i = 0; i <= iLast4; i += 2)
|
||
|
{
|
||
|
pv[i+2].flags |= MCDVERTEX_EDGEFLAG;
|
||
|
pv[i+3].flags |= MCDVERTEX_EDGEFLAG;
|
||
|
|
||
|
/* setup for rendering this quad */
|
||
|
|
||
|
pRc->pvProvoking = &pv[i+3];
|
||
|
pRc->resetLineStipple = TRUE;
|
||
|
|
||
|
/* Render the quad (NOTE: i, i+1, i+3, i+2) */
|
||
|
(*rq)(pRc, &pv[i], &pv[i+1], &pv[i+3], &pv[i+2]);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Initialize first 2 vertices so we can start rendering the quad
|
||
|
// below. The edge flags are not modified by our lower level routines.
|
||
|
|
||
|
pv2 = &pv[pIndices[0]];
|
||
|
MEMCHECK_VERTEX(pv2);
|
||
|
pv2->flags |= MCDVERTEX_EDGEFLAG;
|
||
|
|
||
|
pv3 = &pv[pIndices[1]];
|
||
|
MEMCHECK_VERTEX(pv3);
|
||
|
pv3->flags |= MCDVERTEX_EDGEFLAG;
|
||
|
|
||
|
for (i = 0; i <= iLast4; i += 2)
|
||
|
{
|
||
|
|
||
|
pv0 = pv2;
|
||
|
pv1 = pv3;
|
||
|
|
||
|
pv2 = &pv[pIndices[i+2]];
|
||
|
MEMCHECK_VERTEX(pv2);
|
||
|
pv2->flags |= MCDVERTEX_EDGEFLAG;
|
||
|
|
||
|
pv3 = &pv[pIndices[i+3]];
|
||
|
MEMCHECK_VERTEX(pv3);
|
||
|
pv3->flags |= MCDVERTEX_EDGEFLAG;
|
||
|
|
||
|
/* setup for rendering this quad */
|
||
|
|
||
|
pRc->resetLineStipple = TRUE;
|
||
|
pRc->pvProvoking = pv3;
|
||
|
|
||
|
/* Render the quad (NOTE: i, i+1, i+3, i+2) */
|
||
|
|
||
|
(*rq)(pRc, pv0, pv1, pv3, pv2);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return pCmd->pNextCmd;
|
||
|
}
|
||
|
|
||
|
|
||
|
MCDCOMMAND * FASTCALL __MCDPrimDrawPolygon(DEVRC *pRc, MCDCOMMAND *pCmd)
|
||
|
{
|
||
|
|
||
|
// ASSERTOPENGL(!pCmd->pIndices, "Index mapping must be identity\n");
|
||
|
|
||
|
// Reset the line stipple if this is a new polygon:
|
||
|
|
||
|
if (pCmd->flags & MCDCOMMAND_RESET_STIPPLE)
|
||
|
pRc->resetLineStipple = TRUE;
|
||
|
|
||
|
// Note that the provoking vertex is set in clipPolygon:
|
||
|
|
||
|
MEMCHECK_VERTEX(pCmd->pStartVertex);
|
||
|
MEMCHECK_VERTEX(pCmd->pStartVertex + (pCmd->numIndices-1));
|
||
|
|
||
|
(*pRc->clipPoly)(pRc, pCmd->pStartVertex, pCmd->numIndices);
|
||
|
|
||
|
return pCmd->pNextCmd;
|
||
|
}
|