You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
277 lines
7.9 KiB
277 lines
7.9 KiB
//----------------------------------------------------------------------------
|
|
//
|
|
// line.cpp
|
|
//
|
|
// Line processing.
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1997.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "pch.cpp"
|
|
#pragma hdrstop
|
|
|
|
DBG_DECLARE_FILE();
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// LinePatternStateMachine
|
|
//
|
|
// Runs the line pattern state machine and returns TRUE if the pixel is to be
|
|
// drawn, false otherwise.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
static inline BOOL LinePatternStateMachine(WORD wRepeatFactor, WORD wLinePattern, WORD& wRepeati, WORD& wPatterni)
|
|
{
|
|
if (wRepeatFactor == 0)
|
|
{
|
|
return TRUE;
|
|
}
|
|
WORD wBit = (wLinePattern >> wPatterni) & 1;
|
|
if (++wRepeati >= wRepeatFactor)
|
|
{
|
|
wRepeati = 0;
|
|
wPatterni = (wPatterni+1) & 0xf;
|
|
}
|
|
return (BOOL)wBit;
|
|
}
|
|
|
|
#define CLAMP_COLOR(fVal, uVal) \
|
|
if (FLOAT_LTZ(fVal)) \
|
|
{ \
|
|
uVal = 0; \
|
|
} \
|
|
else \
|
|
{ \
|
|
if (uVal > 0xffff) \
|
|
{ \
|
|
uVal = 0xffff; \
|
|
} \
|
|
} \
|
|
|
|
#define CLAMP_Z(fVal, uVal) \
|
|
if (FLOAT_LTZ(fVal)) \
|
|
{ \
|
|
uVal = 0; \
|
|
} \
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// ClampPixel
|
|
//
|
|
// Clamp color, specular and z(if any) of a pixel. Right now, it's done for
|
|
// first and last pixel of a line only.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
inline void
|
|
ClampPixel(PATTRSET pAttrs, PD3DI_RASTSPAN pSpan)
|
|
{
|
|
CLAMP_COLOR(pAttrs->fB, pSpan->uB);
|
|
CLAMP_COLOR(pAttrs->fG, pSpan->uG);
|
|
CLAMP_COLOR(pAttrs->fR, pSpan->uR);
|
|
CLAMP_COLOR(pAttrs->fA, pSpan->uA);
|
|
CLAMP_COLOR(pAttrs->fBS, pSpan->uBS);
|
|
CLAMP_COLOR(pAttrs->fGS, pSpan->uGS);
|
|
CLAMP_COLOR(pAttrs->fRS, pSpan->uRS);
|
|
CLAMP_Z(pAttrs->fZ, pSpan->uZ);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// WalkLinePattern
|
|
//
|
|
// Walks a line and generates the pixels touched according to the pattern.
|
|
// If wRepeatFactor >= 1, we are patterning, otherwise, we are not
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
WalkLinePattern(PSETUPCTX pStpCtx, WORD wRepeatFactor, WORD wLinePattern)
|
|
{
|
|
HRESULT hr;
|
|
UINT uSpansAvail;
|
|
PD3DI_RASTSPAN pSpan;
|
|
WORD wRepeati = 0;
|
|
WORD wPatterni = 0;
|
|
BOOL bFirst = TRUE;
|
|
|
|
RSASSERT(pStpCtx->cLinePix > 0);
|
|
|
|
hr = D3D_OK;
|
|
uSpansAvail = 0;
|
|
|
|
RSASSERT((pStpCtx->uFlags & PRIMSF_LOD_USED) == 0);
|
|
#ifdef PWL_FOG
|
|
pStpCtx->uPwlFlags = PWL_NO_NEXT_FOG;
|
|
#endif
|
|
|
|
for (;;)
|
|
{
|
|
if (pStpCtx->iX >= pStpCtx->pCtx->Clip.left &&
|
|
pStpCtx->iX < pStpCtx->pCtx->Clip.right &&
|
|
pStpCtx->iY >= pStpCtx->pCtx->Clip.top &&
|
|
pStpCtx->iY < pStpCtx->pCtx->Clip.bottom)
|
|
{
|
|
if (LinePatternStateMachine(wRepeatFactor, wLinePattern, wRepeati, wPatterni))
|
|
{
|
|
if (uSpansAvail == 0)
|
|
{
|
|
uSpansAvail = pStpCtx->cLinePix;
|
|
hr = ALLOC_SPANS(pStpCtx, &uSpansAvail, &pSpan);
|
|
if (hr != D3D_OK)
|
|
{
|
|
// uSpansAvail is set to zero on failure.
|
|
goto EH_Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pSpan++;
|
|
}
|
|
uSpansAvail--;
|
|
pStpCtx->pPrim->uSpans++;
|
|
|
|
pSpan->uPix = 1;
|
|
pSpan->uX = (UINT16)pStpCtx->iX;
|
|
pSpan->uY = (UINT16)pStpCtx->iY;
|
|
|
|
pStpCtx->pfnFillSpanAttrs(&pStpCtx->Attr, pSpan, pStpCtx, 1);
|
|
// Clamp first/last pixel
|
|
if (bFirst || pStpCtx->cLinePix == 1)
|
|
{
|
|
bFirst = FALSE;
|
|
ClampPixel(&pStpCtx->Attr, pSpan);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (--pStpCtx->cLinePix == 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
#ifdef VERBOSE_LINES
|
|
RSDPF((" %4d,%4d: %10d %11d => ",
|
|
pStpCtx->iX, pStpCtx->iY,
|
|
pStpCtx->iLineFrac, pStpCtx->iLineFrac + pStpCtx->iDLineFrac));
|
|
#endif
|
|
|
|
pStpCtx->iLineFrac += pStpCtx->iDLineFrac;
|
|
if (pStpCtx->iLineFrac < 0)
|
|
{
|
|
pStpCtx->iLineFrac &= 0x7fffffff;
|
|
|
|
pStpCtx->iX += pStpCtx->iDXCY;
|
|
pStpCtx->iY += pStpCtx->iDYCY;
|
|
|
|
pStpCtx->DAttrDMajor.ipSurface = pStpCtx->DAttrCY.ipSurface;
|
|
pStpCtx->DAttrDMajor.ipZ = pStpCtx->DAttrCY.ipZ;
|
|
}
|
|
else
|
|
{
|
|
pStpCtx->iX += pStpCtx->iDXNC;
|
|
pStpCtx->iY += pStpCtx->iDYNC;
|
|
|
|
pStpCtx->DAttrDMajor.ipSurface = pStpCtx->DAttrNC.ipSurface;
|
|
pStpCtx->DAttrDMajor.ipZ = pStpCtx->DAttrNC.ipZ;
|
|
}
|
|
|
|
#ifdef VERBOSE_LINES
|
|
RSDPFM((DBG_MASK_FORCE | DBG_MASK_NO_PREFIX, "%4d,%4d: %10d\n",
|
|
pStpCtx->iX, pStpCtx->iY,
|
|
pStpCtx->iLineFrac));
|
|
#endif
|
|
|
|
pStpCtx->pfnAddAttrs(&pStpCtx->Attr, &pStpCtx->DAttrDMajor, pStpCtx);
|
|
}
|
|
|
|
EH_Exit:
|
|
if (uSpansAvail > 0)
|
|
{
|
|
FREE_SPANS(pStpCtx, uSpansAvail);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// PrimProcessor::Line
|
|
//
|
|
// Provides a line for processing.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
PrimProcessor::Line(LPD3DTLVERTEX pV0,
|
|
LPD3DTLVERTEX pV1,
|
|
LPD3DTLVERTEX pFlatVtx)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = D3D_OK;
|
|
|
|
#if DBG
|
|
hr = ValidateVertex(pV0);
|
|
if (hr != D3D_OK)
|
|
{
|
|
return hr;
|
|
}
|
|
hr = ValidateVertex(pV1);
|
|
if (hr != D3D_OK)
|
|
{
|
|
return hr;
|
|
}
|
|
#endif
|
|
|
|
// Clear per-line flags.
|
|
m_StpCtx.uFlags &= ~(PRIMF_ALL | LNF_ALL);
|
|
|
|
RSDPFM((RSM_FLAGS, "m_uPpFlags: 0x%08X, m_StpCtx.uFlags: 0x%08X\n",
|
|
m_uPpFlags, m_StpCtx.uFlags));
|
|
|
|
RSDPFM((RSM_LINES, "Line\n"));
|
|
RSDPFM((RSM_LINES, " V0 (%f,%f,%f)\n",
|
|
pV0->dvSX, pV0->dvSY, pV0->dvSZ));
|
|
RSDPFM((RSM_LINES, " V1 (%f,%f,%f)\n",
|
|
pV1->dvSX, pV1->dvSY, pV1->dvSZ));
|
|
|
|
// Remember flat color controlling vertex for setup.
|
|
m_StpCtx.pFlatVtx = pFlatVtx;
|
|
|
|
if (LineSetup(pV0, pV1))
|
|
{
|
|
// Compute initial buffer pointers for the scanline.
|
|
m_StpCtx.Attr.pSurface = m_StpCtx.pCtx->pSurfaceBits +
|
|
m_StpCtx.iX * m_StpCtx.pCtx->iSurfaceStep +
|
|
m_StpCtx.iY * m_StpCtx.pCtx->iSurfaceStride;
|
|
if (m_StpCtx.uFlags & PRIMSF_Z_USED)
|
|
{
|
|
m_StpCtx.Attr.pZ = m_StpCtx.pCtx->pZBits +
|
|
m_StpCtx.iX * m_StpCtx.pCtx->iZStep +
|
|
m_StpCtx.iY * m_StpCtx.pCtx->iZStride;
|
|
}
|
|
|
|
// Line walking only generates single-pixel spans so
|
|
// the prim deltas are unused. Therefore, line spans
|
|
// are simply added to whatever primitive happens to
|
|
// be sitting in the buffer.
|
|
|
|
hr = AppendPrim();
|
|
if (hr != D3D_OK)
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
union
|
|
{
|
|
D3DLINEPATTERN LPat;
|
|
DWORD dwLPat;
|
|
} LinePat;
|
|
LinePat.dwLPat = m_StpCtx.pCtx->pdwRenderState[D3DRENDERSTATE_LINEPATTERN];
|
|
hr = WalkLinePattern(&m_StpCtx, LinePat.LPat.wRepeatFactor, LinePat.LPat.wLinePattern);
|
|
}
|
|
|
|
return hr;
|
|
}
|