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.
885 lines
29 KiB
885 lines
29 KiB
///////////////////////////////////////////////////////////////////////////////
|
|
// Copyright (C) Microsoft Corporation, 1998.
|
|
//
|
|
// refrast.cpp
|
|
//
|
|
// Direct3D Reference Rasterizer - public interface
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#include "pch.cpp"
|
|
#pragma hdrstop
|
|
|
|
// This is a global static array of the block sizes in bytes for the
|
|
// various S3 compression formats
|
|
int g_DXTBlkSize[NUM_DXT_FORMATS] =
|
|
{
|
|
sizeof(DXTBlockRGB),
|
|
sizeof(DXTBlockAlpha4),
|
|
sizeof(DXTBlockAlpha4),
|
|
sizeof(DXTBlockAlpha3),
|
|
sizeof(DXTBlockAlpha3),
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Memory management function installation
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// global pointers to memory allocation functions (used through MEM* macros)
|
|
LPVOID (__cdecl *g_pfnMemAlloc)( size_t size ) = NULL;
|
|
void (__cdecl *g_pfnMemFree)( LPVOID lptr ) = NULL;
|
|
LPVOID (__cdecl *g_pfnMemReAlloc)( LPVOID ptr, size_t size ) = NULL;
|
|
|
|
// install memory management functions - must be called before instancing
|
|
// rasterizer object
|
|
void RefRastSetMemif(
|
|
LPVOID(__cdecl *pfnMemAlloc)(size_t),
|
|
void(__cdecl *pfnMemFree)(LPVOID),
|
|
LPVOID(__cdecl *pfnMemReAlloc)(LPVOID,size_t))
|
|
{
|
|
DPFRR(1, "RefRastSetMemif %08x %08x %08x\n",
|
|
pfnMemAlloc,pfnMemFree,pfnMemReAlloc);
|
|
g_pfnMemAlloc = pfnMemAlloc;
|
|
g_pfnMemFree = pfnMemFree;
|
|
g_pfnMemReAlloc = pfnMemReAlloc;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Public Interface Methods //
|
|
// //
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// SetRenderTarget -
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void
|
|
ReferenceRasterizer::SetRenderTarget( RRRenderTarget* pRenderTarget )
|
|
{
|
|
m_pRenderTarget = pRenderTarget;
|
|
|
|
// update the W scaling values for mapping interpolated W's into buffer range
|
|
m_fWBufferNorm[0] = pRenderTarget->m_fWRange[0];
|
|
FLOAT fWRange = pRenderTarget->m_fWRange[1] - pRenderTarget->m_fWRange[0];
|
|
m_fWBufferNorm[1] = ( 0. != fWRange ) ? ( 1./fWRange ) : ( 1. );
|
|
|
|
// free fragment buffer array - will reallocate with new size when needed
|
|
if (pRenderTarget->m_iWidth != m_iFragBufWidth ||
|
|
pRenderTarget->m_iHeight != m_iFragBufHeight)
|
|
{
|
|
MEMFREE( m_ppFragBuf ); m_ppFragBuf = NULL;
|
|
m_iFragBufWidth = pRenderTarget->m_iWidth;
|
|
m_iFragBufHeight = pRenderTarget->m_iHeight;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// SetTextureStageState -
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void
|
|
ReferenceRasterizer::SetTextureStageState(
|
|
DWORD dwStage, DWORD dwStageState, DWORD dwValue )
|
|
{
|
|
// check for range before continuing
|
|
if ( dwStage >= D3DHAL_TSS_MAXSTAGES )
|
|
{
|
|
return;
|
|
}
|
|
if ( dwStageState > D3DTSS_MAX )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// set in internal per-stage state
|
|
m_TextureStageState[dwStage].m_dwVal[dwStageState] = dwValue;
|
|
|
|
switch ( dwStageState )
|
|
{
|
|
|
|
case D3DTSS_TEXTUREMAP:
|
|
|
|
// bind texture indicated by handle to m_pTexture array
|
|
if (IsDriverDX6AndBefore() || IsInterfaceDX6AndBefore())
|
|
{
|
|
// This is the legacy behavior (prev. to DX7)
|
|
MapTextureHandleToDevice( dwStage );
|
|
}
|
|
else
|
|
{
|
|
// This is the new behavior (DX7 and beyond)
|
|
SetTextureHandle( dwStage, dwValue );
|
|
}
|
|
break;
|
|
|
|
case D3DTSS_COLOROP:
|
|
// may need to recompute count of active textures based on COLOROP change
|
|
UpdateActiveTexStageCount();
|
|
break;
|
|
|
|
case D3DTSS_ADDRESS:
|
|
// map single set ADDRESS to both U and V controls
|
|
m_TextureStageState[dwStage].m_dwVal[D3DTSS_ADDRESSU] = dwValue;
|
|
m_TextureStageState[dwStage].m_dwVal[D3DTSS_ADDRESSV] = dwValue;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// TextureCreate - Instantiates new RRTexture object, computes texture handle
|
|
// to associate with it, and returns both to caller. Note that texture handle
|
|
// is a pointer and can be used to get at the corresponding texture object.
|
|
//
|
|
// TODO: this is not 64 bit clean
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
BOOL
|
|
ReferenceRasterizer::TextureCreate(
|
|
LPD3DTEXTUREHANDLE phTex, RRTexture** ppTex )
|
|
{
|
|
// allocate internal texture structure
|
|
*ppTex = new RRTexture( );
|
|
_ASSERTa( NULL != *ppTex, "new failure on texture create", return FALSE; );
|
|
|
|
// use separately allocated pointer for handle
|
|
RRTexture** ppTexForHandle = (RRTexture**)MEMALLOC( sizeof(RRTexture*) );
|
|
_ASSERTa( NULL != ppTexForHandle, "malloc failure on texture create", return FALSE; );
|
|
*ppTexForHandle = *ppTex;
|
|
|
|
// return texture handle
|
|
(*ppTex)->m_hTex = (ULONG_PTR)ppTexForHandle;
|
|
*phTex = (*ppTex)->m_hTex;
|
|
|
|
return TRUE;
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// TextureCreate -
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
BOOL
|
|
ReferenceRasterizer::TextureCreate(
|
|
DWORD dwHandle, RRTexture** ppTex )
|
|
{
|
|
// allocate internal texture structure
|
|
*ppTex = new RRTexture( );
|
|
_ASSERTa( NULL != *ppTex, "new failure on texture create", return FALSE; );
|
|
|
|
// assign texture handle
|
|
(*ppTex)->m_hTex = dwHandle;
|
|
|
|
return TRUE;
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// TextureDestroy -
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
BOOL
|
|
ReferenceRasterizer::TextureDestroy( D3DTEXTUREHANDLE hTex )
|
|
{
|
|
// first check if texture about to be destroyed is mapped - if so then
|
|
// unmap it
|
|
for ( int iStage=0; iStage<D3DHAL_TSS_MAXSTAGES; iStage++ )
|
|
{
|
|
if ( hTex == m_TextureStageState[iStage].m_dwVal[D3DTSS_TEXTUREMAP] )
|
|
{
|
|
SetTextureStageState( iStage, D3DTSS_TEXTUREMAP, 0x0 );
|
|
}
|
|
}
|
|
|
|
// resolve handle to RRTexture pointer
|
|
RRTexture* pTex = MapHandleToTexture( hTex );
|
|
if ( NULL == pTex ) { return FALSE; }
|
|
|
|
// free the handle pointer
|
|
RRTexture** ppTex = (RRTexture**)ULongToPtr(hTex);
|
|
if ( NULL != ppTex) { MEMFREE( ppTex ); }
|
|
|
|
// free the RRTexture
|
|
delete pTex;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// TextureGetSurf -
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
DWORD
|
|
ReferenceRasterizer::TextureGetSurf( D3DTEXTUREHANDLE hTex )
|
|
{
|
|
RRTexture* pTex = MapHandleToTexture(hTex);
|
|
if ( NULL == pTex ) { return 0x0; }
|
|
return (ULONG_PTR)( pTex->m_pDDSLcl[0] );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// GetCurrentTextureMaps - This function fills in a passed array texture handles
|
|
// and pointers. The array should be sized by D3DHAL_TSS_MAXSTAGES.
|
|
//
|
|
// This is used to facilitate external locking/unlocking of surfaces used for
|
|
// textures.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
int
|
|
ReferenceRasterizer::GetCurrentTextureMaps(
|
|
D3DTEXTUREHANDLE *phTex, RRTexture** pTex)
|
|
{
|
|
UpdateActiveTexStageCount();
|
|
|
|
for ( int i=0; i<m_cActiveTextureStages; i++ )
|
|
{
|
|
if ( NULL == m_pTexture[i] )
|
|
{
|
|
phTex[i] = 0x0;
|
|
pTex[i] = NULL;
|
|
}
|
|
else
|
|
{
|
|
phTex[i] = m_pTexture[i]->m_hTex;
|
|
pTex[i] = m_pTexture[i];
|
|
}
|
|
}
|
|
return m_cActiveTextureStages;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// SceneCapture - Used to trigger fragment buffer resolve.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void
|
|
ReferenceRasterizer::SceneCapture( DWORD dwFlags )
|
|
{
|
|
switch (dwFlags)
|
|
{
|
|
case D3DHAL_SCENE_CAPTURE_START:
|
|
break;
|
|
case D3DHAL_SCENE_CAPTURE_END:
|
|
DoBufferResolve();
|
|
break;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Query functions to get pointer to current render target and render state.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
RRRenderTarget*
|
|
ReferenceRasterizer::GetRenderTarget(void)
|
|
{
|
|
return m_pRenderTarget;
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
DWORD*
|
|
ReferenceRasterizer::GetRenderState(void)
|
|
{
|
|
return &(m_dwRenderState[0]);
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
DWORD*
|
|
ReferenceRasterizer::GetTextureStageState(DWORD dwStage)
|
|
{
|
|
return &(m_TextureStageState[dwStage].m_dwVal[0]);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Begin/End bracket functions - Called before/after a list of primitives are
|
|
// rendered.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT
|
|
ReferenceRasterizer::BeginRendering( DWORD dwFVFControl )
|
|
{
|
|
// set FVF control word - this specifies the vertex types for this
|
|
// begin/end sequence
|
|
if ( dwFVFControl )
|
|
{
|
|
m_qwFVFControl = dwFVFControl;
|
|
}
|
|
else
|
|
{
|
|
// Legacy TLVERTEX's
|
|
m_qwFVFControl = D3DFVF_TLVERTEX;
|
|
}
|
|
|
|
// set colorkey enable
|
|
for (INT32 i = 0; i < m_cActiveTextureStages; i++)
|
|
{
|
|
if ( m_pTexture[i] != NULL )
|
|
{
|
|
m_pTexture[i]->m_bDoColorKeyKill = FALSE;
|
|
m_pTexture[i]->m_bDoColorKeyZero = FALSE;
|
|
if ( m_pTexture[i]->m_uFlags & RR_TEXTURE_HAS_CK)
|
|
{
|
|
if ( m_dwRenderState[D3DRENDERSTATE_COLORKEYBLENDENABLE] )
|
|
{
|
|
m_pTexture[i]->m_bDoColorKeyZero = TRUE;
|
|
}
|
|
else
|
|
{
|
|
if ( m_dwRenderState[D3DRENDERSTATE_COLORKEYENABLE] )
|
|
{
|
|
m_pTexture[i]->m_bDoColorKeyKill = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef _X86_
|
|
// save floating point mode and set to extended precision mode
|
|
{
|
|
WORD wTemp, wSave;
|
|
__asm
|
|
{
|
|
fstcw wSave
|
|
mov ax, wSave
|
|
or ax, 300h ;; extended precision mode
|
|
mov wTemp, ax
|
|
fldcw wTemp
|
|
}
|
|
m_wSaveFP = wSave;
|
|
}
|
|
#endif
|
|
|
|
m_bInBegin = TRUE;
|
|
return S_OK;
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT
|
|
ReferenceRasterizer::EndRendering( void )
|
|
{
|
|
if ( m_bInBegin )
|
|
{
|
|
|
|
#ifdef _X86_
|
|
// restore floating point mode
|
|
{
|
|
WORD wSave = m_wSaveFP;
|
|
__asm {fldcw wSave}
|
|
}
|
|
#endif
|
|
|
|
m_bInBegin = FALSE;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Clear specified rectangles in the render target
|
|
// Directly handles the command from the DP2 stream
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT ReferenceRasterizer::Clear(LPD3DHAL_DP2COMMAND pCmd)
|
|
{
|
|
LPD3DHAL_DP2CLEAR pData = (LPD3DHAL_DP2CLEAR)(pCmd + 1);
|
|
WORD i;
|
|
INT32 x,y;
|
|
RRColor fillColor(pData->dwFillColor);
|
|
RRDepth fillDepth(m_pRenderTarget->m_DepthSType);
|
|
|
|
fillDepth = pData->dvFillDepth;
|
|
|
|
#ifdef _X86_
|
|
// Float to integer conversion routines for 24+ bit buffers work
|
|
// only with extended FPU mode.
|
|
//
|
|
WORD wSaveFP;
|
|
// save floating point mode and set to extended precision mode
|
|
{
|
|
WORD wTemp, wSave;
|
|
__asm
|
|
{
|
|
fstcw wSaveFP
|
|
mov ax, wSaveFP
|
|
or ax, 300h ;; extended precision mode
|
|
mov wTemp, ax
|
|
fldcw wTemp
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if(pData->dwFlags & D3DCLEAR_TARGET)
|
|
{
|
|
if (m_dwRenderState[D3DRENDERSTATE_DITHERENABLE] == FALSE)
|
|
{
|
|
m_pRenderTarget->Clear(fillColor, pCmd);
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < pCmd->wStateCount; i++)
|
|
{
|
|
for (y = pData->Rects[i].top; y < pData->Rects[i].bottom; ++y)
|
|
{
|
|
for (x = pData->Rects[i].left; x < pData->Rects[i].right; ++x)
|
|
{
|
|
m_pRenderTarget->WritePixelColor(x, y, fillColor, TRUE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
switch (pData->dwFlags & (D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL))
|
|
{
|
|
case (D3DCLEAR_ZBUFFER):
|
|
m_pRenderTarget->ClearDepth(fillDepth, pCmd);
|
|
break;
|
|
case (D3DCLEAR_STENCIL):
|
|
m_pRenderTarget->ClearStencil(pData->dwFillStencil, pCmd);
|
|
break;
|
|
case (D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL):
|
|
m_pRenderTarget->ClearDepthStencil(fillDepth, pData->dwFillStencil, pCmd);
|
|
break;
|
|
}
|
|
|
|
#ifdef _X86_
|
|
// restore floating point mode
|
|
{
|
|
__asm {fldcw wSaveFP}
|
|
}
|
|
#endif
|
|
return D3D_OK;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Clear specified rectangles in the render target
|
|
// Directly handles the command from the DP2 stream
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void RRRenderTarget::Clear(RRColor fillColor, LPD3DHAL_DP2COMMAND pCmd)
|
|
{
|
|
LPD3DHAL_DP2CLEAR pData = (LPD3DHAL_DP2CLEAR)(pCmd + 1);
|
|
UINT32 dwColor = 0;
|
|
fillColor.ConvertTo( m_ColorSType, 0.5f, (char*)&dwColor);
|
|
|
|
for (DWORD i = 0; i < pCmd->wStateCount; i++)
|
|
{
|
|
DWORD x0 = pData->Rects[i].left;
|
|
DWORD y0 = pData->Rects[i].top;
|
|
DWORD dwWidth = pData->Rects[i].right - x0;
|
|
DWORD dwHeight = pData->Rects[i].bottom - y0;
|
|
char* pSurface = PixelAddress( x0, y0, m_pColorBufBits, m_iColorBufPitch, m_ColorSType );
|
|
switch ( m_ColorSType )
|
|
{
|
|
case RR_STYPE_B8G8R8A8:
|
|
case RR_STYPE_B8G8R8X8:
|
|
{
|
|
for (DWORD y = dwHeight; y > 0; y--)
|
|
{
|
|
UINT32 *p = (UINT32*)pSurface;
|
|
for (DWORD x = dwWidth; x > 0; x--)
|
|
{
|
|
*p++ = dwColor;
|
|
}
|
|
pSurface += m_iColorBufPitch;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case RR_STYPE_B8G8R8:
|
|
{
|
|
for (DWORD y = dwHeight; y > 0; y--)
|
|
{
|
|
UINT8 *p = (UINT8*)pSurface;
|
|
for (DWORD x = dwWidth; x > 0; x--)
|
|
{
|
|
*p++ = ((UINT8*)&dwColor)[0];
|
|
*p++ = ((UINT8*)&dwColor)[1];
|
|
*p++ = ((UINT8*)&dwColor)[2];
|
|
}
|
|
pSurface += m_iColorBufPitch;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case RR_STYPE_B4G4R4A4:
|
|
case RR_STYPE_B5G6R5:
|
|
case RR_STYPE_B5G5R5A1:
|
|
case RR_STYPE_B5G5R5:
|
|
{
|
|
for (DWORD y = dwHeight; y > 0; y--)
|
|
{
|
|
UINT16 *p = (UINT16*)pSurface;
|
|
for (DWORD x = dwWidth; x > 0; x--)
|
|
{
|
|
*p++ = (UINT16)dwColor;
|
|
}
|
|
pSurface += m_iColorBufPitch;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case RR_STYPE_B2G3R3:
|
|
{
|
|
for (DWORD y = dwHeight; y > 0; y--)
|
|
{
|
|
UINT8 *p = (UINT8*)pSurface;
|
|
for (DWORD x = dwWidth; x > 0; x--)
|
|
{
|
|
*p++ = (UINT8)dwColor;
|
|
}
|
|
pSurface += m_iColorBufPitch;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
for (int y = y0; y < pData->Rects[i].bottom; ++y)
|
|
{
|
|
for (int x = x0; x < pData->Rects[i].right; ++x)
|
|
{
|
|
this->WritePixelColor(x, y, fillColor, TRUE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Clear specified rectangles in the depth buffer
|
|
// Directly handles the command from the DP2 stream
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void RRRenderTarget::ClearDepth(RRDepth fillDepth, LPD3DHAL_DP2COMMAND pCmd)
|
|
{
|
|
LPD3DHAL_DP2CLEAR pData = (LPD3DHAL_DP2CLEAR)(pCmd + 1);
|
|
|
|
for (DWORD i = 0; i < pCmd->wStateCount; i++)
|
|
{
|
|
DWORD x0 = pData->Rects[i].left;
|
|
DWORD y0 = pData->Rects[i].top;
|
|
DWORD dwWidth = pData->Rects[i].right - x0;
|
|
DWORD dwHeight = pData->Rects[i].bottom - y0;
|
|
char* pSurface = PixelAddress( x0, y0, m_pDepthBufBits, m_iDepthBufPitch, m_DepthSType);
|
|
switch (m_DepthSType)
|
|
{
|
|
case RR_STYPE_Z16S0:
|
|
{
|
|
UINT16 Depth = UINT16(fillDepth);
|
|
for (DWORD y = dwHeight; y > 0; y--)
|
|
{
|
|
UINT16 *p = (UINT16*)pSurface;
|
|
for (DWORD x = dwWidth; x > 0; x--)
|
|
{
|
|
*p++ = Depth;
|
|
}
|
|
pSurface += m_iDepthBufPitch;
|
|
}
|
|
}
|
|
break;
|
|
case RR_STYPE_Z24S8:
|
|
case RR_STYPE_Z24S4:
|
|
{
|
|
UINT32 Depth = UINT32(fillDepth) << 8;
|
|
for (DWORD y = dwHeight; y > 0; y--)
|
|
{
|
|
UINT32 *p = (UINT32*)pSurface;
|
|
for (DWORD x = dwWidth; x > 0; x--)
|
|
{
|
|
// need to do read-modify-write to not step on stencil
|
|
*p++ = (*p & ~(0xffffff00)) | Depth;
|
|
}
|
|
pSurface += m_iDepthBufPitch;
|
|
}
|
|
}
|
|
break;
|
|
case RR_STYPE_S8Z24:
|
|
case RR_STYPE_S4Z24:
|
|
{
|
|
UINT32 Depth = UINT32(fillDepth) & 0x00ffffff;
|
|
for (DWORD y = dwHeight; y > 0; y--)
|
|
{
|
|
UINT32 *p = (UINT32*)pSurface;
|
|
for (DWORD x = dwWidth; x > 0; x--)
|
|
{
|
|
// need to do read-modify-write to not step on stencil
|
|
*p++ = (*p & ~(0x00ffffff)) | Depth;
|
|
}
|
|
pSurface += m_iDepthBufPitch;
|
|
}
|
|
}
|
|
break;
|
|
case RR_STYPE_Z15S1:
|
|
{
|
|
UINT16 Depth = UINT16(fillDepth) << 1;
|
|
for (DWORD y = dwHeight; y > 0; y--)
|
|
{
|
|
UINT16 *p = (UINT16*)pSurface;
|
|
for (DWORD x = dwWidth; x > 0; x--)
|
|
{
|
|
// need to do read-modify-write to not step on stencil
|
|
*p++ = (*p & ~(0xfffe)) | Depth;
|
|
}
|
|
pSurface += m_iDepthBufPitch;
|
|
}
|
|
}
|
|
break;
|
|
case RR_STYPE_S1Z15:
|
|
{
|
|
UINT16 Depth = UINT16(fillDepth) & 0x7fff;
|
|
for (DWORD y = dwHeight; y > 0; y--)
|
|
{
|
|
UINT16 *p = (UINT16*)pSurface;
|
|
for (DWORD x = dwWidth; x > 0; x--)
|
|
{
|
|
// need to do read-modify-write to not step on stencil
|
|
*p++ = (*p & ~(0x7fff)) | Depth;
|
|
}
|
|
pSurface += m_iDepthBufPitch;
|
|
}
|
|
}
|
|
break;
|
|
case RR_STYPE_Z32S0:
|
|
{
|
|
UINT32 Depth = UINT32(fillDepth);
|
|
for (DWORD y = dwHeight; y > 0; y--)
|
|
{
|
|
UINT32 *p = (UINT32*)pSurface;
|
|
for (DWORD x = dwWidth; x > 0; x--)
|
|
{
|
|
*p++ = Depth;
|
|
}
|
|
pSurface += m_iDepthBufPitch;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
for (int y = y0; y < pData->Rects[i].bottom; ++y)
|
|
{
|
|
for (int x = x0; x < pData->Rects[i].right; ++x)
|
|
{
|
|
this->WritePixelDepth(x, y, fillDepth);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Clear specified rectangles in the stencil buffer
|
|
// Directly handles the command from the DP2 stream
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void RRRenderTarget::ClearStencil(UINT8 uStencil, LPD3DHAL_DP2COMMAND pCmd)
|
|
{
|
|
LPD3DHAL_DP2CLEAR pData = (LPD3DHAL_DP2CLEAR)(pCmd + 1);
|
|
|
|
for (DWORD i = 0; i < pCmd->wStateCount; i++)
|
|
{
|
|
DWORD x0 = pData->Rects[i].left;
|
|
DWORD y0 = pData->Rects[i].top;
|
|
DWORD dwWidth = pData->Rects[i].right - x0;
|
|
DWORD dwHeight = pData->Rects[i].bottom - y0;
|
|
char* pSurface = PixelAddress( x0, y0, m_pDepthBufBits, m_iDepthBufPitch, m_DepthSType);
|
|
switch (m_DepthSType)
|
|
{
|
|
case RR_STYPE_Z24S8:
|
|
{
|
|
for (DWORD y = dwHeight; y > 0; y--)
|
|
{
|
|
UINT8 *p = (UINT8*)pSurface;
|
|
for (DWORD x = dwWidth; x > 0; x--)
|
|
{
|
|
*p = uStencil;
|
|
p += 4;
|
|
}
|
|
pSurface += m_iDepthBufPitch;
|
|
}
|
|
}
|
|
break;
|
|
case RR_STYPE_S8Z24:
|
|
{
|
|
for (DWORD y = dwHeight; y > 0; y--)
|
|
{
|
|
UINT8 *p = (UINT8*)&pSurface[3];
|
|
for (DWORD x = dwWidth; x > 0; x--)
|
|
{
|
|
*p = uStencil;
|
|
p += 4;
|
|
}
|
|
pSurface += m_iDepthBufPitch;
|
|
}
|
|
}
|
|
break;
|
|
case RR_STYPE_Z24S4:
|
|
{
|
|
UINT32 stencil = uStencil & 0xf;
|
|
for (DWORD y = dwHeight; y > 0; y--)
|
|
{
|
|
UINT32 *p = (UINT32*)pSurface;
|
|
for (DWORD x = dwWidth; x > 0; x--)
|
|
{
|
|
// need to do read-modify-write to not step on depth
|
|
*p++ = (*p & ~(0x000000ff)) | stencil;
|
|
}
|
|
pSurface += m_iDepthBufPitch;
|
|
}
|
|
}
|
|
break;
|
|
case RR_STYPE_S4Z24:
|
|
{
|
|
UINT32 stencil = (uStencil & 0xf) << 24;
|
|
for (DWORD y = dwHeight; y > 0; y--)
|
|
{
|
|
UINT32 *p = (UINT32*)pSurface;
|
|
for (DWORD x = dwWidth; x > 0; x--)
|
|
{
|
|
// need to do read-modify-write to not step on depth
|
|
*p++ = (*p & ~(0xff000000)) | stencil;
|
|
}
|
|
pSurface += m_iDepthBufPitch;
|
|
}
|
|
}
|
|
break;
|
|
case RR_STYPE_Z15S1:
|
|
{
|
|
UINT16 stencil = uStencil & 0x1;
|
|
for (DWORD y = dwHeight; y > 0; y--)
|
|
{
|
|
UINT16 *p = (UINT16*)pSurface;
|
|
for (DWORD x = dwWidth; x > 0; x--)
|
|
{
|
|
// need to do read-modify-write to not step on depth
|
|
*p++ = (*p & ~(0x0001)) | stencil;
|
|
}
|
|
pSurface += m_iDepthBufPitch;
|
|
}
|
|
}
|
|
break;
|
|
case RR_STYPE_S1Z15:
|
|
{
|
|
UINT16 stencil = uStencil << 15;
|
|
for (DWORD y = dwHeight; y > 0; y--)
|
|
{
|
|
UINT16 *p = (UINT16*)pSurface;
|
|
for (DWORD x = dwWidth; x > 0; x--)
|
|
{
|
|
// need to do read-modify-write to not step on depth
|
|
*p++ = (*p & ~(0x8000)) | stencil;
|
|
}
|
|
pSurface += m_iDepthBufPitch;
|
|
}
|
|
}
|
|
break;
|
|
case RR_STYPE_Z16S0:
|
|
case RR_STYPE_Z32S0:
|
|
break;
|
|
default:
|
|
{
|
|
for (int y = y0; y < pData->Rects[i].bottom; ++y)
|
|
{
|
|
for (int x = x0; x < pData->Rects[i].right; ++x)
|
|
{
|
|
this->WritePixelStencil(x, y, uStencil);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Clear specified rectangles in the depth and stencil buffers
|
|
// Directly handles the command from the DP2 stream
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void RRRenderTarget::ClearDepthStencil(RRDepth fillDepth, UINT8 uStencil, LPD3DHAL_DP2COMMAND pCmd)
|
|
{
|
|
LPD3DHAL_DP2CLEAR pData = (LPD3DHAL_DP2CLEAR)(pCmd + 1);
|
|
|
|
for (DWORD i = 0; i < pCmd->wStateCount; i++)
|
|
{
|
|
DWORD x0 = pData->Rects[i].left;
|
|
DWORD y0 = pData->Rects[i].top;
|
|
DWORD dwWidth = pData->Rects[i].right - x0;
|
|
DWORD dwHeight = pData->Rects[i].bottom - y0;
|
|
char* pSurface = PixelAddress( x0, y0, m_pDepthBufBits, m_iDepthBufPitch, m_DepthSType);
|
|
switch (m_DepthSType)
|
|
{
|
|
case RR_STYPE_Z16S0:
|
|
case RR_STYPE_Z32S0:
|
|
break;
|
|
case RR_STYPE_Z24S8:
|
|
case RR_STYPE_S8Z24:
|
|
case RR_STYPE_Z24S4:
|
|
case RR_STYPE_S4Z24:
|
|
{
|
|
UINT32 v;
|
|
switch (m_DepthSType)
|
|
{
|
|
case RR_STYPE_Z24S8: v = (UINT32(fillDepth) << 8) + uStencil; break;
|
|
case RR_STYPE_S8Z24: v = (UINT32(fillDepth) & 0x00ffffff) + (uStencil << 24); break;
|
|
case RR_STYPE_Z24S4: v = (UINT32(fillDepth) << 8) + (uStencil & 0xf); break;
|
|
case RR_STYPE_S4Z24: v = (UINT32(fillDepth) & 0x00ffffff) + ((uStencil & 0xf) << 24); break;
|
|
}
|
|
for (DWORD y = dwHeight; y > 0; y--)
|
|
{
|
|
UINT32 *p = (UINT32*)pSurface;
|
|
for (DWORD x = dwWidth; x > 0; x--)
|
|
{
|
|
*p++ = v;
|
|
}
|
|
pSurface += m_iDepthBufPitch;
|
|
}
|
|
}
|
|
break;
|
|
case RR_STYPE_Z15S1:
|
|
case RR_STYPE_S1Z15:
|
|
{
|
|
UINT16 v;
|
|
switch (m_DepthSType)
|
|
{
|
|
case RR_STYPE_Z15S1: v = (UINT16(fillDepth) << 1) + (uStencil & 0x1); break;
|
|
case RR_STYPE_S1Z15: v = (UINT16(fillDepth) & 0x7fff) + (uStencil << 15); break;
|
|
}
|
|
for (DWORD y = dwHeight; y > 0; y--)
|
|
{
|
|
UINT16 *p = (UINT16*)pSurface;
|
|
for (DWORD x = dwWidth; x > 0; x--)
|
|
{
|
|
*p++ = v;
|
|
}
|
|
pSurface += m_iDepthBufPitch;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
for (int y = y0; y < pData->Rects[i].bottom; ++y)
|
|
{
|
|
for (int x = x0; x < pData->Rects[i].right; ++x)
|
|
{
|
|
this->WritePixelDepth(x, y, fillDepth);
|
|
this->WritePixelStencil(x, y, uStencil);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// end
|
|
|