Leaked source code of windows server 2003
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.
 
 
 
 
 
 

3213 lines
122 KiB

/******************************Module*Header**********************************\
*
* *******************
* * D3D SAMPLE CODE *
* *******************
*
* Module Name: d3ddp2op.c
*
* Content: D3D DrawPrimitives2 command buffer operations support
*
* Copyright (c) 1994-1999 3Dlabs Inc. Ltd. All rights reserved.
* Copyright (c) 1995-2003 Microsoft Corporation. All rights reserved.
\*****************************************************************************/
#include "glint.h"
#include "dma.h"
#include "tag.h"
//-----------------------------------------------------------------------------
//
// __OP_IntersectRectl
//
// This function intersects two RECTLs. If no intersection exists returns FALSE
//
//-----------------------------------------------------------------------------
BOOL
__OP_IntersectRectl(
RECTL* prcresult,
RECTL* prcin1,
RECT* prcin2)
{
prcresult->left = max(prcin1->left, prcin2->left);
prcresult->right = min(prcin1->right, prcin2->right);
if (prcresult->left < prcresult->right)
{
prcresult->top = max(prcin1->top, prcin2->top);
prcresult->bottom = min(prcin1->bottom, prcin2->bottom);
if (prcresult->top < prcresult->bottom)
{
return TRUE;
}
}
return FALSE;
} // __OP_IntersectRectl
#if DX7_TEXMANAGEMENT
VOID __OP_MarkManagedSurfDirty(P3_D3DCONTEXT* pContext,
DWORD dwSurfHandle,
P3_SURF_INTERNAL* pTexture);
#endif
//-----------------------------------------------------------------------------
//
// _D3D_OP_Clear2
//
// This function processes the D3DDP2OP_CLEAR DP2 command token.
//
// It builds a mask and a value for the stencil/depth clears. The mask is used
// to stop unwanted bits being updated during the clear. The value is scaled in
// the case of the Z depth, and is shifted in the case of the stencil. This
// results in the correct value being written, at the correct location in the
// ZBuffer, while doing fast-block fills through SGRAM
//-----------------------------------------------------------------------------
#define P3RX_UPDATE_WRITE_MASK(a) \
if (dwCurrentMask != a) \
{ \
P3_DMA_GET_BUFFER_ENTRIES(2); \
SEND_P3_DATA(FBHardwareWriteMask, a); \
P3_DMA_COMMIT_BUFFER(); \
dwCurrentMask = a; \
}
VOID
_D3D_OP_Clear2(
P3_D3DCONTEXT* pContext,
D3DHAL_DP2CLEAR* lpcd2,
DWORD dwNumRects)
{
DWORD i;
RECTL rect, rect_vwport;
DWORD dwDepthValue;
DWORD dwStencilValue;
DWORD dwStencilMask;
DWORD dwDepthMask;
DWORD color;
DWORD dwCurrentMask = 0xFFFFFFFF;
BOOL bNoBlockFillZ = FALSE;
BOOL bNoBlockFillStencil = FALSE;
BOOL bComputeIntersections = FALSE;
BYTE Bytes[4];
P3_THUNKEDDATA* pThisDisplay = pContext->pThisDisplay;
HRESULT ddrval;
D3DHAL_DP2CLEAR WholeViewport;
P3_DMA_DEFS();
DBG_CB_ENTRY(_D3D_OP_Clear2);
// Check if we were asked to clear a valid buffer
if ( (lpcd2->dwFlags & (D3DCLEAR_TARGET |
D3DCLEAR_ZBUFFER |
D3DCLEAR_STENCIL) ) == 0)
{
// We have been asked to do nothing - and that's what we've done.
DBG_CB_EXIT(_D3D_OP_Clear2, DD_OK);
return;
}
#if DX8_DDI
// When zero clear rects is passed to a DX8 driver with D3DDP2OP_CLEAR
// token, the driver should clear the whole viewport. The zero number
// of rects could be passed only if D3D is using a pure device.
// D3DCLEAR_COMPUTERECTS has been added to the dwFlags of D3DHAL_CLEARDATA.
// When set, the flag means that user provided clear rects should be
// culled against the current viewport.
if (!(lpcd2->dwFlags & D3DCLEAR_COMPUTERECTS))
{
// Do nothing for non-pure device
}
else
if (dwNumRects == 0)
{
// When wStateCount is zero we need to clear whole viewport
WholeViewport.dwFlags = lpcd2->dwFlags;
WholeViewport.dwFillColor = lpcd2->dwFillColor;
WholeViewport.dvFillDepth = lpcd2->dvFillDepth;
WholeViewport.dwFillStencil = lpcd2->dwFillStencil;
WholeViewport.Rects[0].left = pContext->ViewportInfo.dwX;
WholeViewport.Rects[0].top = pContext->ViewportInfo.dwY;
WholeViewport.Rects[0].right = pContext->ViewportInfo.dwX +
pContext->ViewportInfo.dwWidth;
WholeViewport.Rects[0].bottom = pContext->ViewportInfo.dwY +
pContext->ViewportInfo.dwHeight;
// Replace pointers and continue as usual
lpcd2 = &WholeViewport;
dwNumRects = 1;
}
else
{
// We need to cull all rects against the current viewport
// but in order not to allocate a temporary RECT array in
// kernel heap we'll compute this inside the clearing loop
rect_vwport.left = pContext->ViewportInfo.dwX;
rect_vwport.top = pContext->ViewportInfo.dwY;
rect_vwport.right = pContext->ViewportInfo.dwX +
pContext->ViewportInfo.dwWidth;
rect_vwport.bottom = pContext->ViewportInfo.dwY +
pContext->ViewportInfo.dwHeight;
bComputeIntersections = TRUE;
}
#endif // DX8_DDI
// Check if there is any rect to clear at all
if ( dwNumRects == 0)
{
// We have been asked to do nothing - and that's what we've done.
DBG_CB_EXIT(_D3D_OP_Clear2, DD_OK);
return;
}
// Wait until we have we finished flipping before clearing anything
do
{
ddrval =
_DX_QueryFlipStatus(pContext->pThisDisplay,
pContext->pSurfRenderInt->fpVidMem,
TRUE);
} while ( FAILED (ddrval) );
// Switch to hw Ddraw context in order to do the clears
DDRAW_OPERATION(pContext, pThisDisplay);
// Prepare any data necessary to clear the render target
if ((lpcd2->dwFlags & D3DCLEAR_TARGET) &&
(pContext->pSurfRenderInt != NULL))
{
color = lpcd2->dwFillColor;
// Clear depending on depth
switch (pContext->pSurfRenderInt->dwPixelSize)
{
// 16 Bit colors come in as 32 Bit RGB Values
// Color will be packed in the clear function
case __GLINT_16BITPIXEL:
if (pThisDisplay->ddpfDisplay.dwRBitMask == 0x7C00)
{
color = ((color & 0xf8) >> 3) |
((color & 0xf800) >> (16 - 10)) |
((color & 0xf80000) >> (24 - 15));
}
else
{
color = ((color & 0xff) >> 3) |
((color & 0xfc00) >> (16 - 11)) |
((color & 0xf80000) >> (24 - 16));
}
break;
case __GLINT_24BITPIXEL:
DISPDBG((ERRLVL,"P3 doesn't support 24 bpp render target"));
break;
default:
break;
}
} // if (lpcd2->dwFlags & D3DCLEAR_TARGET)
// Prepare any data necessary to clear the depth buffer
if ((lpcd2->dwFlags & D3DCLEAR_ZBUFFER) &&
(pContext->pSurfZBufferInt != NULL))
{
float fDepth;
DDPIXELFORMAT* pPixFormat = &pContext->pSurfZBufferInt->pixFmt;
DWORD dwZBitDepth = pPixFormat->dwZBufferBitDepth;
// Find the depth bits, remembering to remove any stencil bits.
if (pPixFormat->dwFlags & DDPF_STENCILBUFFER)
{
dwZBitDepth -= pPixFormat->dwStencilBitDepth;
}
dwDepthMask = (0xFFFFFFFF >> (32 - dwZBitDepth));
// 32 bit depth buffers on Perm3 are really
// limited to 31 bits of precision
if (dwZBitDepth == 32)
{
dwDepthMask = dwDepthMask >> 1;
}
if (lpcd2->dvFillDepth == 1.0f)
{
dwDepthValue = dwDepthMask;
}
else
{
fDepth = lpcd2->dvFillDepth * (float)dwDepthMask;
// This is a hardware dependency on how the Perm3 handles the
// limited precision of 32bit floats(24 bits of mantissa) and
// converts the value into a 32bit z buffer value. This doesn't
// happen with any other z bit depth but 32.
if (dwZBitDepth == 32)
{
fDepth += 0.5f;
}
myFtoi((int*)&dwDepthValue, fDepth);
}
// As we are fast-block filling, make sure we copy the
// Mask to the top bits.
switch (pContext->pSurfZBufferInt->dwPixelSize)
{
case __GLINT_16BITPIXEL:
dwDepthMask &= 0xFFFF;
dwDepthMask |= (dwDepthMask << 16);
break;
case __GLINT_8BITPIXEL:
dwDepthMask &= 0xFF;
dwDepthMask |= dwDepthMask << 8;
dwDepthMask |= dwDepthMask << 16;
break;
}
if (pThisDisplay->pGLInfo->bDRAMBoard)
{
// Check for a DRAM fill that the chip isn't emulating.
Bytes[0] = (BYTE)(dwDepthMask & 0xFF);
Bytes[1] = (BYTE)((dwDepthMask & 0xFF00) >> 8);
Bytes[2] = (BYTE)((dwDepthMask & 0xFF0000) >> 16);
Bytes[3] = (BYTE)((dwDepthMask & 0xFF000000) >> 24);
if (((Bytes[0] != 0) && (Bytes[0] != 0xFF)) ||
((Bytes[1] != 0) && (Bytes[1] != 0xFF)) ||
((Bytes[2] != 0) && (Bytes[2] != 0xFF)) ||
((Bytes[3] != 0) && (Bytes[3] != 0xFF)))
{
bNoBlockFillZ = TRUE;
}
}
DISPDBG((DBGLVL,"ZClear Value = 0x%x, ZClear Mask = 0x%x",
dwDepthValue, dwDepthMask));
} // if (lpcd2->dwFlags & D3DCLEAR_ZBUFFER)
// Prepare any data necessary to clear the stencil buffer
if ((lpcd2->dwFlags & D3DCLEAR_STENCIL) &&
(pContext->pSurfZBufferInt != NULL))
{
int dwShiftCount = 0;
DDPIXELFORMAT* pPixFormat = &pContext->pSurfZBufferInt->pixFmt;
// Find out where to shift the
dwStencilMask = pPixFormat->dwStencilBitMask;
if (dwStencilMask != 0)
{
while ((dwStencilMask & 0x1) == 0)
{
dwStencilMask >>= 1;
dwShiftCount++;
}
dwStencilValue = (lpcd2->dwFillStencil << dwShiftCount);
dwStencilMask = pPixFormat->dwStencilBitMask;
// As we are fast-block filling, make sure we copy the
// Mask to the top bits.
switch (pContext->pSurfZBufferInt->dwPixelSize)
{
case __GLINT_16BITPIXEL:
dwStencilMask &= 0xFFFF;
dwStencilMask |= (dwStencilMask << 16);
break;
case __GLINT_8BITPIXEL:
dwStencilMask &= 0xFF;
dwStencilMask |= dwStencilMask << 8;
dwStencilMask |= dwStencilMask << 16;
break;
}
DISPDBG((DBGLVL,"Stencil Clear Value = 0x%x, Stencil Mask = 0x%x",
dwStencilValue, dwStencilMask));
}
else
{
DISPDBG((ERRLVL,"ERROR: Stencil mask is not valid!"));
dwStencilValue = 0;
dwStencilMask = 0;
}
if (pThisDisplay->pGLInfo->bDRAMBoard)
{
// Check for a DRAM fill that the chip isn't emulating.
Bytes[0] = (BYTE)(dwStencilMask & 0xFF);
Bytes[1] = (BYTE)((dwStencilMask & 0xFF00) >> 8);
Bytes[2] = (BYTE)((dwStencilMask & 0xFF0000) >> 16);
Bytes[3] = (BYTE)((dwStencilMask & 0xFF000000) >> 24);
if (((Bytes[0] != 0) && (Bytes[0] != 0xFF)) ||
((Bytes[1] != 0) && (Bytes[1] != 0xFF)) ||
((Bytes[2] != 0) && (Bytes[2] != 0xFF)) ||
((Bytes[3] != 0) && (Bytes[3] != 0xFF)))
{
bNoBlockFillStencil = TRUE;
}
}
} // if (lpcd2->dwFlags & D3DCLEAR_STENCIL)
// Loop through each clearing rect and perform the clearing hw operations
i = dwNumRects;
while (i-- > 0)
{
if (bComputeIntersections)
{
// Compute intersection between the viewport and the incoming
// RECTLs. If no intersection exists skip into next one.
if (!__OP_IntersectRectl(&rect, &rect_vwport, &lpcd2->Rects[i]))
{
// No intersection, so skip it
goto Next_Rectl_To_Clear;
}
}
else
{
// We already have the rects we need to clear, so
// just use them in reverse order
rect.left = lpcd2->Rects[i].left;
rect.right = lpcd2->Rects[i].right;
rect.top = lpcd2->Rects[i].top;
rect.bottom = lpcd2->Rects[i].bottom;
}
// Clear the frame buffer
if ((lpcd2->dwFlags & D3DCLEAR_TARGET) &&
(pContext->pSurfRenderInt != NULL))
{
P3RX_UPDATE_WRITE_MASK(__GLINT_ALL_WRITEMASKS_SET);
#if DX8_MULTISAMPLING || DX7_ANTIALIAS
if (pContext->Flags & SURFACE_ANTIALIAS)
{
RECTL Temp = rect;
Temp.left *= 2;
Temp.right *= 2;
Temp.top *= 2;
Temp.bottom *= 2;
_DD_BLT_P3Clear_AA(pThisDisplay,
&Temp,
pContext->dwAliasBackBuffer -
pThisDisplay->dwScreenFlatAddr,
color,
FALSE,
pContext->pSurfRenderInt->dwPatchMode,
pContext->pSurfRenderInt->dwPixelPitch,
pContext->pSurfRenderInt->pixFmt.dwRGBBitCount,
pContext->pSurfRenderInt->ddsCapsInt);
}
else
#endif // DX8_MULTISAMPLING || DX7_ANTIALIAS
{
_DD_BLT_P3Clear(pThisDisplay,
&rect,
color,
FALSE,
FALSE,
pContext->pSurfRenderInt->fpVidMem,
pContext->pSurfRenderInt->dwPatchMode,
pContext->pSurfRenderInt->dwPixelPitch,
pContext->pSurfRenderInt->pixFmt.dwRGBBitCount);
}
}
// Clear the z buffer
if ((lpcd2->dwFlags & D3DCLEAR_ZBUFFER) &&
(pContext->pSurfZBufferInt != NULL) )
{
P3RX_UPDATE_WRITE_MASK(dwDepthMask);
if (bNoBlockFillZ)
{
P3_DMA_GET_BUFFER_ENTRIES(4);
SEND_P3_DATA(FBSoftwareWriteMask, dwDepthMask);
SEND_P3_DATA(FBDestReadMode,
P3RX_FBDESTREAD_READENABLE(__PERMEDIA_ENABLE) |
P3RX_FBDESTREAD_ENABLE0(__PERMEDIA_ENABLE));
P3_DMA_COMMIT_BUFFER();
}
#if DX8_MULTISAMPLING || DX7_ANTIALIAS
if (pContext->Flags & SURFACE_ANTIALIAS)
{
RECTL Temp = rect;
Temp.left *= 2;
Temp.right *= 2;
Temp.top *= 2;
Temp.bottom *= 2;
_DD_BLT_P3Clear_AA(pThisDisplay,
&Temp,
pContext->dwAliasZBuffer -
pThisDisplay->dwScreenFlatAddr,
dwDepthValue,
bNoBlockFillZ,
pContext->pSurfZBufferInt->dwPatchMode,
pContext->pSurfZBufferInt->dwPixelPitch,
pContext->pSurfZBufferInt->pixFmt.dwRGBBitCount,
pContext->pSurfZBufferInt->ddsCapsInt);
}
else
#endif // DX8_MULTISAMPLING || DX7_ANTIALIAS
{
_DD_BLT_P3Clear(pThisDisplay,
&rect,
dwDepthValue,
bNoBlockFillZ,
TRUE,
pContext->pSurfZBufferInt->fpVidMem,
pContext->pSurfZBufferInt->dwPatchMode,
pContext->pSurfZBufferInt->dwPixelPitch,
pContext->pSurfZBufferInt->pixFmt.dwRGBBitCount
);
}
if (bNoBlockFillZ)
{
P3_DMA_GET_BUFFER_ENTRIES(4);
SEND_P3_DATA(FBSoftwareWriteMask, __GLINT_ALL_WRITEMASKS_SET);
SEND_P3_DATA(FBDestReadMode, __PERMEDIA_DISABLE);
P3_DMA_COMMIT_BUFFER();
}
}
// Clear the stencil buffer
if ((lpcd2->dwFlags & D3DCLEAR_STENCIL) &&
(pContext->pSurfZBufferInt != NULL) )
{
P3RX_UPDATE_WRITE_MASK(dwStencilMask);
if (bNoBlockFillStencil)
{
P3_DMA_GET_BUFFER_ENTRIES(4);
SEND_P3_DATA(FBSoftwareWriteMask, dwStencilMask);
SEND_P3_DATA(FBDestReadMode,
P3RX_FBDESTREAD_READENABLE(__PERMEDIA_ENABLE) |
P3RX_FBDESTREAD_ENABLE0(__PERMEDIA_ENABLE));
P3_DMA_COMMIT_BUFFER();
}
#if DX8_MULTISAMPLING || DX7_ANTIALIAS
if (pContext->Flags & SURFACE_ANTIALIAS)
{
RECTL Temp = rect;
Temp.left *= 2;
Temp.right *= 2;
Temp.top *= 2;
Temp.bottom *= 2;
_DD_BLT_P3Clear_AA(pThisDisplay,
&Temp,
pContext->dwAliasZBuffer -
pThisDisplay->dwScreenFlatAddr,
dwStencilValue,
bNoBlockFillStencil,
pContext->pSurfZBufferInt->dwPatchMode,
pContext->pSurfZBufferInt->dwPixelPitch,
pContext->pSurfZBufferInt->pixFmt.dwRGBBitCount,
pContext->pSurfZBufferInt->ddsCapsInt
);
}
else
#endif // DX8_MULTISAMPLING || DX7_ANTIALIAS
{
_DD_BLT_P3Clear(pThisDisplay,
&rect,
dwStencilValue,
bNoBlockFillStencil,
TRUE,
pContext->pSurfZBufferInt->fpVidMem,
pContext->pSurfZBufferInt->dwPatchMode,
pContext->pSurfZBufferInt->dwPixelPitch,
pContext->pSurfZBufferInt->pixFmt.dwRGBBitCount
);
}
if (bNoBlockFillStencil)
{
P3_DMA_GET_BUFFER_ENTRIES(4);
SEND_P3_DATA(FBSoftwareWriteMask, __GLINT_ALL_WRITEMASKS_SET);
SEND_P3_DATA(FBDestReadMode, __PERMEDIA_DISABLE);
P3_DMA_COMMIT_BUFFER();
}
}
Next_Rectl_To_Clear:
;
} // while
// Make sure the WriteMask is reset to it's default value
{
P3_DMA_GET_BUFFER_ENTRIES(4);
SEND_P3_DATA(FBHardwareWriteMask, __GLINT_ALL_WRITEMASKS_SET);
SEND_P3_DATA(FBDestReadMode, __PERMEDIA_DISABLE);
P3_DMA_COMMIT_BUFFER();
}
DBG_CB_EXIT(_D3D_OP_Clear2, DD_OK);
return;
} // _D3D_OP_Clear2
//-----------------------------------------------------------------------------
//
// _D3D_OP_TextureBlt
//
// This function processes the D3DDP2OP_TEXBLT DP2 command token.
//
//-----------------------------------------------------------------------------
VOID _D3D_OP_TextureBlt(P3_D3DCONTEXT* pContext,
P3_THUNKEDDATA*pThisDisplay,
D3DHAL_DP2TEXBLT* pBlt)
{
LPDDRAWI_DDRAWSURFACE_LCL pSrcLcl;
LPDDRAWI_DDRAWSURFACE_LCL pDestLcl;
P3_SURF_INTERNAL* pSrcTexture;
P3_SURF_INTERNAL* pDestTexture;
P3_SURF_FORMAT* pFormatSource;
P3_SURF_FORMAT* pFormatDest;
MIPTEXTURE *pSrcMipLevel, *pDstMipLevel;
RECTL rSrc, rDest;
int iMaxLogWidth, iCurrLogWidth;
int iSrcLOD, iDestLOD, iCurrSrcLOD, iCurrDstLOD;
BOOL bMipMap, bMipMapLevelsMatch;
DISPDBG((DBGLVL, "TextureBlt Source %d Dest %d",
pBlt->dwDDSrcSurface,
pBlt->dwDDDestSurface));
if (0 == pBlt->dwDDSrcSurface)
{
DISPDBG((ERRLVL,"Invalid handle TexBlt from %08lx to %08lx",
pBlt->dwDDSrcSurface,pBlt->dwDDDestSurface));
return;
}
// Get the source texture structure pointer
pSrcTexture = GetSurfaceFromHandle(pContext, pBlt->dwDDSrcSurface);
// Check that the source texture is valid
if (pSrcTexture == NULL)
{
DISPDBG((ERRLVL, "ERROR: Source texture %d is invalid!",
pBlt->dwDDSrcSurface));
return;
}
// Validate the destination texture handle
if (0 == pBlt->dwDDDestSurface)
{
#if DX7_TEXMANAGEMENT
// If we do texture management then a destination handle of 0
// has the special meaning of preloading the source texture.
if (!_D3D_TM_Preload_Tex_IntoVidMem(pContext, pSrcTexture))
{
DISPDBG((ERRLVL,"_D3D_OP_TextureBlt unable to "
"preload texture"));
}
return;
#else
// If there's no driver texture managament support we can't go
// on if the destination handle is 0
DISPDBG((ERRLVL,"Invalid handle TexBlt from %08lx to %08lx",
pBlt->dwDDSrcSurface,pBlt->dwDDDestSurface));
return;
#endif
}
// Get the destination texture structure pointer for regular TexBlts
pDestTexture = GetSurfaceFromHandle(pContext, pBlt->dwDDDestSurface);
// Check that the destination texture is valid
if (pDestTexture == NULL)
{
DISPDBG((ERRLVL, "ERROR: Dest texture %d is invalid!",
pBlt->dwDDDestSurface));
return;
}
// Make sure the textures are of the same proportion
if ((pSrcTexture->wWidth * pDestTexture->wHeight) !=
(pSrcTexture->wHeight * pDestTexture->wWidth))
{
DISPDBG((ERRLVL, "ERROR: TEXBLT the src and dest textures are not of the same proportion"));
return;
}
// It is possible that the source and destination textures may contain
// different number of mipmap levels. In this case, the driver is
// expected to BitBlt the common levels. For example, if a 256x256 source
// texture has 8 mipmap levels, and if the destination is a 64x64 texture
// with 6 levels, then the driver should BitBlt the 6 corresponding levels
// from the source. The driver can expect the dimensions of the top mip
// level of destination texture to be always equal to or lesser than the
// dimensions of the top mip level of the source texture.
// It might also be the case that only one of the textures is mipmapped
// Since we keep all relevant info also in the MipLevels substructre for
// the surface, we can treat both surfaces as mipmapped even if only
// one of them was created as such and proceed with the TexBlt.
if (pSrcTexture->bMipMap || pDestTexture->bMipMap)
{
bMipMap = TRUE;
iMaxLogWidth = max(pSrcTexture->logWidth, pDestTexture->logWidth);
iCurrLogWidth = iMaxLogWidth;
iSrcLOD = 0; // start LOD for src
iDestLOD = 0; // start LOD for dest
}
else
{
// just one level
bMipMap = FALSE; // No mipmapping cases to be handled
iMaxLogWidth = iCurrLogWidth = iSrcLOD = iDestLOD = 0;
}
// Init the rects from and into which we will blt . This is top level
// mipmap or non-mipmap texture, just use rect from Blt.
rSrc = pBlt->rSrc;
// Create a destination rectangle for compatibility
// with the DD blitting function we are calling.
rDest.left = pBlt->pDest.x;
rDest.top = pBlt->pDest.y;
rDest.right = (pBlt->rSrc.right - pBlt->rSrc.left) + rDest.left;
rDest.bottom = (pBlt->rSrc.bottom - pBlt->rSrc.top) + rDest.top;
// Traverse all the mip map levels and try to match them for a blt to be
// done. If no mipmaps are present just do for the "first" and only
// levels present.
do
{
DISPDBG((DBGLVL,"TEXBLT iteration %d %d %d %d",
iMaxLogWidth,iCurrLogWidth,iSrcLOD,iDestLOD));
// Get the local surface pointers and make sure the level sizes
// match in the case of mip map Texblts.
if (bMipMap)
{
bMipMapLevelsMatch = FALSE;
// Verify you only look at valid mipmap levels - they might
// be incomplete (and we want not to AV or access garbage!)
// for example, a source 256x256 texture may contain 5 levels,
// but the destination 256x256 texture may contain 8. The
// driver is expected to safely handle this case, but it is
// not expected to produce correct results
if ((iSrcLOD < pSrcTexture->iMipLevels) &&
(iDestLOD < pDestTexture->iMipLevels))
{
DISPDBG((DBGLVL,"Checking match! %d vs. %d",
pSrcTexture->MipLevels[iSrcLOD].logWidth,
pDestTexture->MipLevels[iDestLOD].logWidth));
// Do we currently have two levels that match in size ?
bMipMapLevelsMatch =
( pSrcTexture->MipLevels[iSrcLOD].logWidth ==
pDestTexture->MipLevels[iDestLOD].logWidth);
}
// Record which levels are we currently blitting
iCurrSrcLOD = iSrcLOD;
iCurrDstLOD = iDestLOD;
// Get ready for next loop by updating the LODs to use
// increment LOD# if we are currently looking at a level
// equal or smaller to mip maps level 0 size
if (iCurrLogWidth <= pSrcTexture->logWidth)
{
iSrcLOD++;
}
if (iCurrLogWidth <= pDestTexture->logWidth)
{
iDestLOD++;
}
// Decrease the width into next smaller level
iCurrLogWidth--;
}
else
{
// Single level blt - we set bMipMapLevelsMatch in order to blt it!
bMipMapLevelsMatch = TRUE;
iCurrSrcLOD = 0;
iCurrDstLOD = 0;
}
if (bMipMapLevelsMatch)
{
// Switch to the DirectDraw context
DDRAW_OPERATION(pContext, pThisDisplay);
DISPDBG((DBGLVL,"Blitting level %d into level %d",
iCurrSrcLOD,
iCurrDstLOD));
pSrcMipLevel = &pSrcTexture->MipLevels[iCurrSrcLOD];
pDstMipLevel = &pDestTexture->MipLevels[iCurrDstLOD];
///////////////////////////////////////////////////////////////////
// Here we handle all possible blt cases between different types
// of memory and different scenarios of managed/unmanaged surfaces
///////////////////////////////////////////////////////////////////
#if DX7_TEXMANAGEMENT
if ((0 == (pDestTexture->dwCaps2 & DDSCAPS2_TEXTUREMANAGE)) &&
(0 == (pSrcTexture->dwCaps2 & DDSCAPS2_TEXTUREMANAGE)) )
#endif // DX7_TEXMANAGEMENT
{
//----------------------------------
//----------------------------------
// TEXBLT among non-managed textures
//----------------------------------
//----------------------------------
if ((pSrcTexture->Location == SystemMemory) &&
(pDestTexture->Location == VideoMemory))
{
//----------------------------
// Do the system->videomem blt
//----------------------------
_DD_P3Download(pThisDisplay,
pSrcMipLevel->fpVidMem,
pDstMipLevel->fpVidMem,
pSrcTexture->dwPatchMode,
pDestTexture->dwPatchMode,
pSrcMipLevel->lPitch,
pDstMipLevel->lPitch,
pDstMipLevel->P3RXTextureMapWidth.Width,
pDestTexture->dwPixelSize,
&rSrc,
&rDest);
}
else if ((pSrcTexture->Location == VideoMemory) &&
(pDestTexture->Location == VideoMemory))
{
//------------------------------
// Do the videomem->videomem blt
//------------------------------
_DD_BLT_P3CopyBlt(pThisDisplay,
pSrcMipLevel->fpVidMem,
pDstMipLevel->fpVidMem,
pSrcTexture->dwPatchMode,
pDestTexture->dwPatchMode,
pSrcMipLevel->P3RXTextureMapWidth.Width,
pDstMipLevel->P3RXTextureMapWidth.Width,
pSrcMipLevel->dwOffsetFromMemoryBase,
pDstMipLevel->dwOffsetFromMemoryBase,
pDestTexture->dwPixelSize,
&rSrc,
&rDest);
}
else if ((pSrcTexture->Location == AGPMemory) &&
(pDestTexture->Location == VideoMemory))
{
//-------------------------------
// Do the AGP mem -> videomem blt
//-------------------------------
DDCOLORKEY ddck_dummy = { 0 , 0 };
// We use the strecth blt because it handles AGP source
// surfaces, not becuase we should stretch the surface in any way
_DD_P3BltStretchSrcChDstCh(
pThisDisplay,
// src data
pSrcMipLevel->fpVidMem,
pSrcTexture->pFormatSurface,
pSrcTexture->dwPixelSize,
pSrcMipLevel->wWidth,
pSrcMipLevel->wHeight,
pSrcMipLevel->P3RXTextureMapWidth.Width,
pSrcMipLevel->P3RXTextureMapWidth.Layout,
pSrcMipLevel->dwOffsetFromMemoryBase,
pSrcTexture->dwFlagsInt,
&pSrcTexture->pixFmt,
1, // src IS AGP, otherwise we
//would'nt call this
// dest data
pDstMipLevel->fpVidMem,
pDestTexture->pFormatSurface,
pDestTexture->dwPixelSize,
pDstMipLevel->wWidth,
pDstMipLevel->wHeight,
pDstMipLevel->P3RXTextureMapWidth.Width,
pDstMipLevel->P3RXTextureMapWidth.Layout,
pDstMipLevel->dwOffsetFromMemoryBase,
0, // dwBltFlags no special blt effects
0, // dwBltDDFX no special effects info
ddck_dummy, // BltSrcColorKey dummy arg
ddck_dummy, // BltDestColorKey dummy arg
&rSrc,
&rDest
);
}
else
{
DISPDBG((ERRLVL,"Non-managed Tex Blt variation unimplemented! "
"(from %d into %d)",
pSrcTexture->Location,
pDestTexture->Location));
}
}
#if DX7_TEXMANAGEMENT
else if (pSrcTexture->dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
{
//----------------------------------
//----------------------------------
// TEXBLT from a managed texture
//----------------------------------
//----------------------------------
if ((pDestTexture->Location == SystemMemory) ||
(pDestTexture->dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
{
//-------------------------------------------------
// Do the Managed surf -> sysmem | managed surf blt
//-------------------------------------------------
// make sure we'll reload the vidmem copy of the dest surf
if (pDestTexture->dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
{
__OP_MarkManagedSurfDirty(pContext,
pBlt->dwDDDestSurface,
pDestTexture);
}
_DD_BLT_SysMemToSysMemCopy(
pSrcMipLevel->fpVidMem,
pSrcMipLevel->lPitch,
pSrcTexture->dwBitDepth,
pDstMipLevel->fpVidMem,
pDstMipLevel->lPitch,
pDestTexture->dwBitDepth,
&rSrc,
&rDest);
}
else if (pDestTexture->Location == VideoMemory)
{
//-------------------------------------------------
// Do the Managed surf -> vidmem surf blt
//-------------------------------------------------
// This might be optimized by doing a vidmem->vidmem
// when the source managed texture has a vidmem copy
_DD_P3Download(pThisDisplay,
pSrcMipLevel->fpVidMem,
pDstMipLevel->fpVidMem,
pSrcTexture->dwPatchMode,
pDestTexture->dwPatchMode,
pSrcMipLevel->lPitch,
pDstMipLevel->lPitch,
pDstMipLevel->P3RXTextureMapWidth.Width,
pDestTexture->dwPixelSize,
&rSrc,
&rDest);
}
else
{
DISPDBG((ERRLVL,"Src-managed Tex Blt variation unimplemented! "
"(from %d into %d)",
pSrcTexture->Location,
pDestTexture->Location));
}
}
else if (pDestTexture->dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
{
//--------------------------------------------------------------
//--------------------------------------------------------------
// TEXBLT into a managed texture (except from a managed texture)
//--------------------------------------------------------------
//--------------------------------------------------------------
// managed->managed is handled in the previous case
if (pSrcTexture->Location == SystemMemory)
{
//-------------------------------------------------
// Do the sysmem surf -> managed surf blt
//-------------------------------------------------
// make sure we'll reload the vidmem copy of the dest surf
__OP_MarkManagedSurfDirty(pContext,
pBlt->dwDDDestSurface,
pDestTexture);
_DD_BLT_SysMemToSysMemCopy(
pSrcMipLevel->fpVidMem,
pSrcMipLevel->lPitch,
pSrcTexture->dwBitDepth,
pDstMipLevel->fpVidMem,
pDstMipLevel->lPitch,
pDestTexture->dwBitDepth,
&rSrc,
&rDest);
}
else if (pSrcTexture->Location == VideoMemory)
{
//-------------------------------------------------
// Do the vidmem surf -> Managed surf blt
//-------------------------------------------------
if (0 != pSrcMipLevel->fpVidMemTM)
{
// Destination is already in vidmem so instead of
// "dirtying" the managed texture lets do the
// vidmem->vidmem blt which is faster than doing the
// update later (in the hope we'll really use it)
_DD_BLT_P3CopyBlt(pThisDisplay,
pSrcMipLevel->fpVidMem,
pDstMipLevel->fpVidMemTM,
pSrcTexture->dwPatchMode,
pDestTexture->dwPatchMode,
pSrcMipLevel->P3RXTextureMapWidth.Width,
pDstMipLevel->P3RXTextureMapWidth.Width,
pSrcMipLevel->dwOffsetFromMemoryBase,
pDstMipLevel->dwOffsetFromMemoryBase,
pDestTexture->dwPixelSize,
&rSrc,
&rDest);
}
else
{
// make sure we'll reload the
// vidmem copy of the dest surf
__OP_MarkManagedSurfDirty(pContext,
pBlt->dwDDDestSurface,
pDestTexture);
}
// Do slow mem mapped framebuffer blt into sysmem
// The source surface lives in video mem so we need to get a
// "real" sysmem address for it:
_DD_BLT_SysMemToSysMemCopy(
D3DMIPLVL_GETPOINTER(pSrcMipLevel, pThisDisplay),
pSrcMipLevel->lPitch,
pSrcTexture->dwBitDepth,
pDstMipLevel->fpVidMem,
pDstMipLevel->lPitch,
pDestTexture->dwBitDepth,
&rSrc,
&rDest);
}
else if (pSrcTexture->Location == AGPMemory)
{
// make sure we'll reload the vidmem copy of the dest surf
__OP_MarkManagedSurfDirty(pContext,
pBlt->dwDDDestSurface,
pDestTexture);
_DD_BLT_SysMemToSysMemCopy(
pSrcMipLevel->fpVidMem,
pSrcMipLevel->lPitch,
pSrcTexture->dwBitDepth,
pDstMipLevel->fpVidMem,
pDstMipLevel->lPitch,
pDestTexture->dwBitDepth,
&rSrc,
&rDest);
}
else
{
DISPDBG((ERRLVL,"Dest-managed Tex Blt variation unimplemented! "
"(from %d into %d)",
pSrcTexture->Location,
pDestTexture->Location));
}
}
else
{
DISPDBG((ERRLVL,"Tex Blt variation unimplemented! "
"(from %d into %d)",
pSrcTexture->Location,
pDestTexture->Location));
}
#endif // DX7_TEXMANAGEMENT
// Switch back to the Direct3D context
D3D_OPERATION(pContext, pThisDisplay);
} // if (bMipMapLevelsMatch)
// Update transfer rectangles if mip mapping
if (bMipMap)
{
DWORD right, bottom;
// Update source rectangle , the regions to be copied in mipmap
// sub-levels can be obtained by dividing rSrc and pDest by
// 2 at each level.
rSrc.left >>= 1;
rSrc.top >>= 1;
right = (rSrc.right + 1) >> 1;
bottom = (rSrc.bottom + 1) >> 1;
rSrc.right = ((right - rSrc.left) < 1) ? (rSrc.left + 1) : (right);
rSrc.bottom = ((bottom - rSrc.top ) < 1) ? (rSrc.top + 1) : (bottom);
// Update destination rectangle
rDest.left >>= 1;
rDest.top >>= 1;
right = (rDest.right + 1) >> 1;
bottom = (rDest.bottom + 1) >> 1;
rDest.right = ((right - rDest.left) < 1) ? (rDest.left + 1) : (right);
rDest.bottom = ((bottom - rDest.top ) < 1) ? (rDest.top + 1) : (bottom);
}
} while (bMipMap && ((iSrcLOD < pSrcTexture->iMipLevels) &&
(iDestLOD < pDestTexture->iMipLevels))); // do until we're done looking at 1x1
} // _D3D_OP_TextureBlt
//-----------------------------------------------------------------------------
//
// _D3D_OP_SetRenderTarget
//
// Sets up the hw for the chosen render target and depth buffer
//
//-----------------------------------------------------------------------------
HRESULT
_D3D_OP_SetRenderTarget(
P3_D3DCONTEXT* pContext,
P3_SURF_INTERNAL* pRenderInt,
P3_SURF_INTERNAL* pZBufferInt,
BOOL bNewAliasBuffers)
{
P3_SOFTWARECOPY* pSoftP3RX = &pContext->SoftCopyGlint;
P3_THUNKEDDATA *pThisDisplay = pContext->pThisDisplay;
DWORD AAMultiplier = 1;
P3_DMA_DEFS();
DBG_ENTRY(_D3D_OP_SetRenderTarget);
// Verify the render target is in video memory
if (pRenderInt)
{
if (pRenderInt->ddsCapsInt.dwCaps & DDSCAPS_SYSTEMMEMORY)
{
DISPDBG((ERRLVL, "ERROR: Render Surface in SYSTEM MEMORY"));
return DDERR_GENERIC;
}
}
else
{
// Must have a render target
DISPDBG((ERRLVL, "ERROR: Render Surface is NULL"));
return DDERR_GENERIC;
}
// If a Z Buffer verify it
if (pZBufferInt)
{
if (pZBufferInt->ddsCapsInt.dwCaps & DDSCAPS_SYSTEMMEMORY)
{
DISPDBG((ERRLVL, "ERROR: Z Surface in SYSTEM MEMORY, failing"));
return DDERR_GENERIC;
}
}
// Validate the RenderTarget to be 32 bit or 16 bit 565
if ((pRenderInt->pixFmt.dwRGBBitCount == 32 ) &&
(pRenderInt->pixFmt.dwRBitMask == 0x00FF0000) &&
(pRenderInt->pixFmt.dwGBitMask == 0x0000FF00) &&
(pRenderInt->pixFmt.dwBBitMask == 0x000000FF))
{
// were OK at 32bpp
}
else
if ((pRenderInt->pixFmt.dwRGBBitCount == 16 ) &&
(pRenderInt->pixFmt.dwRBitMask == 0xF800) &&
(pRenderInt->pixFmt.dwGBitMask == 0x07E0) &&
(pRenderInt->pixFmt.dwBBitMask == 0x001F))
{
// were OK at 16bpp
}
else
{
// we cant set our render target to this format !!!
DISPDBG((WRNLVL, " SRT Error !!!"));
DISPDBG((WRNLVL, " dwRGBBitCount: 0x%x",
pRenderInt->pixFmt.dwRGBBitCount));
DISPDBG((WRNLVL, " dwR/Y BitMask: 0x%x",
pRenderInt->pixFmt.dwRBitMask));
DISPDBG((WRNLVL, " dwG/U BitMask: 0x%x",
pRenderInt->pixFmt.dwGBitMask));
DISPDBG((WRNLVL, " dwB/V BitMask: 0x%x",
pRenderInt->pixFmt.dwBBitMask));
DISPDBG((WRNLVL, " dwRGBAlphaBitMask: 0x%x",
pRenderInt->pixFmt.dwRGBAlphaBitMask));
return DDERR_GENERIC;
}
#if DX8_MULTISAMPLING
// Decide whether antialising is requested and can be handled
if ((pContext->pSurfRenderInt->dwSampling) &&
(! _D3D_ST_CanRenderAntialiased(pContext, bNewAliasBuffers)))
{
return DDERR_OUTOFMEMORY;
}
#endif // DX8_MULTISAMPLING
// If we page flipped, clear the flag
pThisDisplay->bFlippedSurface = FALSE;
P3_DMA_GET_BUFFER();
P3_ENSURE_DX_SPACE(46);
WAIT_FIFO(26);
pContext->pSurfRenderInt = pRenderInt;
pContext->pSurfZBufferInt = pZBufferInt;
// Check for Z Buffer
if (pZBufferInt)
{
DDPIXELFORMAT* pZFormat = &pZBufferInt->pixFmt;
if( pThisDisplay->dwDXVersion >= DX6_RUNTIME)
{
// On DX6 we look in the pixel format for the depth and stencil info.
switch(pZFormat->dwZBufferBitDepth)
{
default:
DISPDBG((ERRLVL,"ERROR: Unknown Z Pixel format!"));
// Regard the buffer as 16 bit one and fall through
case 16:
if (pZFormat->dwStencilBitDepth == 1)
{
// 15 bit Z, 1 bit stencil
pSoftP3RX->P3RXLBReadFormat.StencilPosition = 0; // Ignored in this mode
pSoftP3RX->P3RXLBReadFormat.StencilWidth = P3RX_STENCIL_WIDTH_1;
pSoftP3RX->P3RXLBReadFormat.DepthWidth = P3RX_DEPTH_WIDTH_15;
pSoftP3RX->P3RXStencilMode.StencilWidth = P3RX_STENCIL_WIDTH_1;
pSoftP3RX->P3RXLBWriteFormat.StencilPosition = 0; // Ignored in this mode
pSoftP3RX->P3RXLBWriteFormat.StencilWidth = P3RX_STENCIL_WIDTH_1;
pSoftP3RX->P3RXLBWriteFormat.DepthWidth = P3RX_DEPTH_WIDTH_15;
pSoftP3RX->P3RXDepthMode.Width = P3RX_DEPTH_WIDTH_15;
pSoftP3RX->P3RXLBSourceReadMode.Packed16 = 1;
pSoftP3RX->P3RXLBDestReadMode.Packed16 = 1;
pSoftP3RX->P3RXLBWriteMode.Packed16 = 1;
pSoftP3RX->P3RXLBWriteMode.ByteEnables = 0x3;
}
else
{
// 16 bit Z, no stencil
pSoftP3RX->P3RXLBReadFormat.StencilPosition = 0; // Ignored in this mode
pSoftP3RX->P3RXLBReadFormat.StencilWidth = P3RX_STENCIL_WIDTH_0;
pSoftP3RX->P3RXStencilMode.StencilWidth = P3RX_STENCIL_WIDTH_0;
pSoftP3RX->P3RXLBReadFormat.DepthWidth = P3RX_DEPTH_WIDTH_16;
pSoftP3RX->P3RXLBWriteFormat.StencilPosition = 0; // Ignored in this mode
pSoftP3RX->P3RXLBWriteFormat.StencilWidth = P3RX_STENCIL_WIDTH_0;
pSoftP3RX->P3RXLBWriteFormat.DepthWidth = P3RX_DEPTH_WIDTH_16;
pSoftP3RX->P3RXDepthMode.Width = P3RX_DEPTH_WIDTH_16;
pSoftP3RX->P3RXLBWriteMode.ByteEnables = 0x3;
pSoftP3RX->P3RXLBSourceReadMode.Packed16 = 1;
pSoftP3RX->P3RXLBDestReadMode.Packed16 = 1;
pSoftP3RX->P3RXLBWriteMode.Packed16 = 1;
}
break;
case 32:
if (pZFormat->dwStencilBitDepth == 8)
{
// 24 bit Z, 8 bit stencil
pSoftP3RX->P3RXLBReadFormat.StencilPosition = P3RX_STENCIL_POSITION_24;
pSoftP3RX->P3RXLBReadFormat.StencilWidth = P3RX_STENCIL_WIDTH_8;
pSoftP3RX->P3RXStencilMode.StencilWidth = P3RX_STENCIL_WIDTH_8;
pSoftP3RX->P3RXLBReadFormat.DepthWidth = P3RX_DEPTH_WIDTH_24;
pSoftP3RX->P3RXLBWriteFormat.StencilPosition = P3RX_STENCIL_POSITION_24;
pSoftP3RX->P3RXLBWriteFormat.StencilWidth = P3RX_STENCIL_WIDTH_8;
pSoftP3RX->P3RXLBWriteFormat.DepthWidth = P3RX_DEPTH_WIDTH_24;
pSoftP3RX->P3RXDepthMode.Width = P3RX_DEPTH_WIDTH_24;
pSoftP3RX->P3RXLBWriteMode.ByteEnables = 0xF;
pSoftP3RX->P3RXLBSourceReadMode.Packed16 = 0;
pSoftP3RX->P3RXLBDestReadMode.Packed16 = 0;
pSoftP3RX->P3RXLBWriteMode.Packed16 = 0;
}
else
{
// 32 bit Z, no stencil
pSoftP3RX->P3RXLBReadFormat.StencilPosition = 0;
pSoftP3RX->P3RXLBReadFormat.StencilWidth = P3RX_STENCIL_WIDTH_0;
pSoftP3RX->P3RXStencilMode.StencilWidth = P3RX_STENCIL_WIDTH_0;
pSoftP3RX->P3RXLBReadFormat.DepthWidth = P3RX_DEPTH_WIDTH_32;
pSoftP3RX->P3RXLBWriteFormat.StencilPosition = 0;
pSoftP3RX->P3RXLBWriteFormat.StencilWidth = P3RX_STENCIL_WIDTH_0;
pSoftP3RX->P3RXLBWriteFormat.DepthWidth = P3RX_DEPTH_WIDTH_32;
pSoftP3RX->P3RXDepthMode.Width = P3RX_DEPTH_WIDTH_32;
pSoftP3RX->P3RXLBWriteMode.ByteEnables = 0xF;
pSoftP3RX->P3RXLBSourceReadMode.Packed16 = 0;
pSoftP3RX->P3RXLBDestReadMode.Packed16 = 0;
pSoftP3RX->P3RXLBWriteMode.Packed16 = 0;
}
break;
}
}
else
// On DX5 we don't look at the pixel format, just the depth of the Z Buffer.
{
// Choose the correct Z Buffer depth
switch(pZBufferInt->pixFmt.dwRGBBitCount)
{
default:
DISPDBG((ERRLVL,"ERROR: Unknown depth format in _D3D_OP_SetRenderTarget!"));
// Regard the buffer as 16 bit one and fall through
case 16:
pSoftP3RX->P3RXLBReadFormat.DepthWidth = __GLINT_DEPTH_WIDTH_16;
pSoftP3RX->P3RXLBWriteFormat.DepthWidth = __GLINT_DEPTH_WIDTH_16;
pSoftP3RX->P3RXDepthMode.Width = __GLINT_DEPTH_WIDTH_16;
pSoftP3RX->P3RXLBWriteMode.ByteEnables = 0x3;
pSoftP3RX->P3RXLBSourceReadMode.Packed16 = 1;
pSoftP3RX->P3RXLBDestReadMode.Packed16 = 1;
pSoftP3RX->P3RXLBWriteMode.Packed16 = 1;
break;
case 24:
pSoftP3RX->P3RXLBReadFormat.DepthWidth = __GLINT_DEPTH_WIDTH_24;
pSoftP3RX->P3RXLBWriteFormat.DepthWidth = __GLINT_DEPTH_WIDTH_24;
pSoftP3RX->P3RXDepthMode.Width = __GLINT_DEPTH_WIDTH_24;
pSoftP3RX->P3RXLBWriteMode.ByteEnables = 0x7;
pSoftP3RX->P3RXLBSourceReadMode.Packed16 = 0;
pSoftP3RX->P3RXLBDestReadMode.Packed16 = 0;
pSoftP3RX->P3RXLBWriteMode.Packed16 = 0;
break;
case 32:
pSoftP3RX->P3RXLBReadFormat.DepthWidth = __GLINT_DEPTH_WIDTH_32;
pSoftP3RX->P3RXLBWriteFormat.DepthWidth = __GLINT_DEPTH_WIDTH_32;
pSoftP3RX->P3RXDepthMode.Width = __GLINT_DEPTH_WIDTH_32;
pSoftP3RX->P3RXLBWriteMode.ByteEnables = 0xF;
pSoftP3RX->P3RXLBSourceReadMode.Packed16 = 0;
pSoftP3RX->P3RXLBDestReadMode.Packed16 = 0;
pSoftP3RX->P3RXLBWriteMode.Packed16 = 0;
break;
}
}
pSoftP3RX->P3RXLBSourceReadMode.Layout = pZBufferInt->dwPatchMode;
pSoftP3RX->P3RXLBDestReadMode.Layout = pZBufferInt->dwPatchMode;
pSoftP3RX->P3RXLBWriteMode.Layout = pZBufferInt->dwPatchMode;
} // if (pZBufferInt)
switch (pRenderInt->dwPixelSize)
{
case __GLINT_8BITPIXEL:
// 8 Bit color index mode
pSoftP3RX->DitherMode.ColorFormat =
pSoftP3RX->P3RXAlphaBlendColorMode.ColorFormat = P3RX_ALPHABLENDMODE_COLORFORMAT_CI;
SEND_P3_DATA(PixelSize, 2 - __GLINT_8BITPIXEL);
break;
case __GLINT_16BITPIXEL:
if (pThisDisplay->ddpfDisplay.dwRBitMask == 0x7C00)
{
// 5551 format
pSoftP3RX->DitherMode.ColorFormat = P3RX_DITHERMODE_COLORFORMAT_5551;
pSoftP3RX->P3RXAlphaBlendColorMode.ColorFormat = P3RX_ALPHABLENDMODE_COLORFORMAT_5551;
}
else
{
// 565 format
pSoftP3RX->DitherMode.ColorFormat = P3RX_DITHERMODE_COLORFORMAT_565;
pSoftP3RX->P3RXAlphaBlendColorMode.ColorFormat = P3RX_ALPHABLENDMODE_COLORFORMAT_565;
}
SEND_P3_DATA(PixelSize, 2 - __GLINT_16BITPIXEL);
break;
case __GLINT_24BITPIXEL:
case __GLINT_32BITPIXEL:
// 32 Bit Color Index mode
pSoftP3RX->DitherMode.ColorFormat =
pSoftP3RX->P3RXAlphaBlendColorMode.ColorFormat = P3RX_ALPHABLENDMODE_COLORFORMAT_8888;
SEND_P3_DATA(PixelSize, 2 - __GLINT_32BITPIXEL);
break;
}
pSoftP3RX->P3RXFBDestReadMode.Layout0 = pRenderInt->dwPatchMode;
pSoftP3RX->P3RXFBWriteMode.Layout0 = pRenderInt->dwPatchMode;
pSoftP3RX->P3RXFBSourceReadMode.Layout = pRenderInt->dwPatchMode;
COPY_P3_DATA(FBWriteMode, pSoftP3RX->P3RXFBWriteMode);
COPY_P3_DATA(FBDestReadMode, pSoftP3RX->P3RXFBDestReadMode);
COPY_P3_DATA(FBSourceReadMode, pSoftP3RX->P3RXFBSourceReadMode);
#if DX8_MULTISAMPLING || DX7_ANTIALIAS
if (!(pContext->Flags & SURFACE_ANTIALIAS) ||
(pContext->dwAliasBackBuffer == 0))
{
#endif // DX8_MULTISAMPLING || DX7_ANTIALIAS
pContext->PixelOffset = (DWORD)(pRenderInt->fpVidMem -
pThisDisplay->dwScreenFlatAddr );
if (pContext->pSurfZBufferInt)
{
pContext->ZPixelOffset = (DWORD)(pZBufferInt->fpVidMem -
pThisDisplay->dwScreenFlatAddr);
}
AAMultiplier = 1;
SEND_P3_DATA(PixelSize, (2 - pRenderInt->dwPixelSize));
#if DX8_MULTISAMPLING || DX7_ANTIALIAS
}
else
{
pContext->PixelOffset = pContext->dwAliasPixelOffset;
pContext->ZPixelOffset = pContext->dwAliasZPixelOffset;
AAMultiplier = 2;
}
#endif // DX8_MULTISAMPLING || DX7_ANTIALIAS
COPY_P3_DATA(AlphaBlendColorMode, pSoftP3RX->P3RXAlphaBlendColorMode);
COPY_P3_DATA(DitherMode, pSoftP3RX->DitherMode);
SEND_P3_DATA(FBWriteBufferAddr0, pContext->PixelOffset);
SEND_P3_DATA(FBDestReadBufferAddr0, pContext->PixelOffset);
SEND_P3_DATA(FBSourceReadBufferAddr, pContext->PixelOffset);
SEND_P3_DATA(FBWriteBufferWidth0,
pContext->pSurfRenderInt->dwPixelPitch * AAMultiplier);
SEND_P3_DATA(FBDestReadBufferWidth0,
pContext->pSurfRenderInt->dwPixelPitch * AAMultiplier);
SEND_P3_DATA(FBSourceReadBufferWidth,
pContext->pSurfRenderInt->dwPixelPitch * AAMultiplier);
WAIT_FIFO(20);
// Is there a Z Buffer?
if (pContext->pSurfZBufferInt != NULL)
{
// Offset is in BYTES
SEND_P3_DATA(LBSourceReadBufferAddr, pContext->ZPixelOffset);
SEND_P3_DATA(LBDestReadBufferAddr, pContext->ZPixelOffset);
SEND_P3_DATA(LBWriteBufferAddr, pContext->ZPixelOffset);
pSoftP3RX->P3RXLBWriteMode.Width =
pContext->pSurfZBufferInt->dwPixelPitch * AAMultiplier;
pSoftP3RX->P3RXLBSourceReadMode.Width =
pContext->pSurfZBufferInt->dwPixelPitch * AAMultiplier;
pSoftP3RX->P3RXLBDestReadMode.Width =
pContext->pSurfZBufferInt->dwPixelPitch * AAMultiplier;
COPY_P3_DATA(LBDestReadMode, pSoftP3RX->P3RXLBDestReadMode);
COPY_P3_DATA(LBSourceReadMode, pSoftP3RX->P3RXLBSourceReadMode);
COPY_P3_DATA(LBWriteMode, pSoftP3RX->P3RXLBWriteMode);
COPY_P3_DATA(StencilMode, pSoftP3RX->P3RXStencilMode);
COPY_P3_DATA(LBReadFormat, pSoftP3RX->P3RXLBReadFormat);
COPY_P3_DATA(LBWriteFormat, pSoftP3RX->P3RXLBWriteFormat);
COPY_P3_DATA(DepthMode, pSoftP3RX->P3RXDepthMode);
}
DIRTY_VIEWPORT(pContext);
P3_DMA_COMMIT_BUFFER();
DBG_EXIT(_D3D_OP_SetRenderTarget,0);
return DD_OK;
} // _D3D_OP_SetRenderTarget
//-----------------------------------------------------------------------------
//
// _D3D_OP_SceneCapture
//
// This function is called twice, once at the start of the rendering,
// and once at the end of the rendering. The start is ignored, but
// the end might be used to ensure that the DMA buffer has been flushed.
// This is needed for the case where a scene has little in it, and
// doesn't fill the buffer up.
//
//-----------------------------------------------------------------------------
VOID
_D3D_OP_SceneCapture(
P3_D3DCONTEXT *pContext,
DWORD dwFlag)
{
P3_THUNKEDDATA *pThisDisplay;
pThisDisplay = pContext->pThisDisplay;
if (dwFlag == D3DHAL_SCENE_CAPTURE_START)
{
DISPDBG((DBGLVL,"Scene Start"));
}
else if (dwFlag == D3DHAL_SCENE_CAPTURE_END)
{
#if DX8_MULTISAMPLING || DX7_ANTIALIAS
if (pContext->Flags & SURFACE_ANTIALIAS)
{
// Since we were antialiasing we need to put the data where
// the user asked which requires a copy from our AA buffer
// into the true target buffer
// P3 Shrinking is done in the DDRAW context. This means you
// don't have to save and restore the state around the call
// - the next D3D_OPERATION will recover for you
DDRAW_OPERATION(pContext, pThisDisplay);
P3RX_AA_Shrink(pContext);
}
#endif // DX8_MULTISAMPLING || DX7_ANTIALIAS
DISPDBG((DBGLVL,"Scene End"));
}
return;
} // _D3D_OP_SceneCapture
#if DX7_TEXMANAGEMENT
//-----------------------------------------------------------------------------
//
// __OP_MarkManagedSurfDirty
//
// Make sure textures are setup again if the texture is being used in any of
// the texture stages (for reloading purpouses) and make sure we mark it as
// dirty (since we're modifying the sysmem copy of the texture)
//
//-----------------------------------------------------------------------------
VOID __OP_MarkManagedSurfDirty(P3_D3DCONTEXT* pContext,
DWORD dwSurfHandle,
P3_SURF_INTERNAL* pTexture)
{
// If the destination texture is in use in any of the texture
// stages, make sure hw gets re-setup again before using it.
if ((pContext->TextureStageState[0].m_dwVal[D3DTSS_TEXTUREMAP]
== dwSurfHandle) ||
(pContext->TextureStageState[1].m_dwVal[D3DTSS_TEXTUREMAP]
== dwSurfHandle))
{
DIRTY_TEXTURE(pContext);
}
// Mark the destination texture as needing to be updated
// into vidmem before using it.
pTexture->m_bTMNeedUpdate = TRUE;
} // __OP_MarkManagedSurfDirty
//-----------------------------------------------------------------------------
//
// _D3D_OP_SetTexLod
//
// This function processes the D3DDP2OP_SETTEXLOD DP2 command token.
// This communicates to the texture manager the most detailed mip map level
// required to load for a given managed surface.
//
//-----------------------------------------------------------------------------
VOID
_D3D_OP_SetTexLod(
P3_D3DCONTEXT *pContext,
D3DHAL_DP2SETTEXLOD* pSetTexLod)
{
P3_SURF_INTERNAL* pTexture;
// Get the source texture structure pointer
pTexture = GetSurfaceFromHandle(pContext, pSetTexLod->dwDDSurface);
if (pTexture == NULL)
{
return;
}
// Set up the HW texture states again if this texture is in use
// and the new LOD value is smaller than the current setting.
if (((pContext->TextureStageState[0].m_dwVal[D3DTSS_TEXTUREMAP]
== pSetTexLod->dwDDSurface) ||
(pContext->TextureStageState[1].m_dwVal[D3DTSS_TEXTUREMAP]
== pSetTexLod->dwDDSurface)) &&
(pSetTexLod->dwLOD < pTexture->m_dwTexLOD))
{
DIRTY_TEXTURE(pContext);
}
// Change the texture's largest level to be actually used
pTexture->m_dwTexLOD = pSetTexLod->dwLOD;
} // _D3D_OP_SetTexLod
//-----------------------------------------------------------------------------
//
// _D3D_OP_SetPriority
//
// This function processes the D3DDP2OP_SETPRIORITY DP2 command token.
//
//-----------------------------------------------------------------------------
VOID
_D3D_OP_SetPriority(
P3_D3DCONTEXT *pContext,
D3DHAL_DP2SETPRIORITY* pSetPriority)
{
P3_SURF_INTERNAL* pTexture;
// Get the source texture structure pointer
#if WNT_DDRAW
pTexture = GetSurfaceFromHandle(pContext, pSetPriority->dwDDDestSurface);
#else
pTexture = GetSurfaceFromHandle(pContext, pSetPriority->dwDDSurface);
#endif
if (NULL != pTexture)
{
// Managed resources should be evicted depending on their priorities.
// If of same priority then LRU is used to break the tie.
pTexture->m_dwPriority = pSetPriority->dwPriority;
}
} // _D3D_OP_SetPriority
#if DX8_DDI
//-----------------------------------------------------------------------------
//
// _D3D_OP_AddDirtyRect
//
// This function processes the D3DDP2OP_ADDDIRTYRECT DP2 command token.
//
//-----------------------------------------------------------------------------
VOID
_D3D_OP_AddDirtyRect(
P3_D3DCONTEXT *pContext,
D3DHAL_DP2ADDDIRTYRECT* pAddDirtyRect)
{
P3_SURF_INTERNAL* pTexture;
// Get the source texture structure pointer
pTexture = GetSurfaceFromHandle(pContext, pAddDirtyRect->dwSurface);
if (NULL != pTexture)
{
//azn TODO
// As a first implementation in this driver we mark the whole surface
// as dirty instead of marking just the indicated rect - which could be
// transferred more efficiently
__OP_MarkManagedSurfDirty(pContext,
pAddDirtyRect->dwSurface,
pTexture);
}
} // _D3D_OP_AddDirtyRect
//-----------------------------------------------------------------------------
//
// _D3D_OP_AddDirtyBox
//
// This function processes the D3DDP2OP_ADDDIRTYBOX DP2 command token.
//
//-----------------------------------------------------------------------------
VOID
_D3D_OP_AddDirtyBox(
P3_D3DCONTEXT *pContext,
D3DHAL_DP2ADDDIRTYBOX* pAddDirtyBox)
{
P3_SURF_INTERNAL* pTexture;
// Get the source texture structure pointer
pTexture = GetSurfaceFromHandle(pContext, pAddDirtyBox->dwSurface);
if (NULL != pTexture)
{
//azn TODO
// As a first implementation in this driver we mark the whole surface
// as dirty instead of marking just the indicated rect - which could be
// transferred more efficiently
__OP_MarkManagedSurfDirty(pContext,
pAddDirtyBox->dwSurface,
pTexture);
}
} // _D3D_OP_AddDirtyBox
#endif
#endif // DX7_TEXMANAGEMENT
#if DX8_3DTEXTURES
//-----------------------------------------------------------------------------
//
// __OP_BasicVolumeBlt
//
// This function blts one single level/slice at a time for volume textures
//
//-----------------------------------------------------------------------------
VOID __OP_BasicVolumeBlt(P3_D3DCONTEXT* pContext,
P3_THUNKEDDATA*pThisDisplay,
P3_SURF_INTERNAL* pSrcTexture,
P3_SURF_INTERNAL* pDestTexture,
DWORD dwDestSurfHandle,
RECTL *prSrc,
RECTL *prDest)
{
#if DX7_TEXMANAGEMENT
if ((0 == (pDestTexture->dwCaps2 & DDSCAPS2_TEXTUREMANAGE)) &&
(0 == (pSrcTexture->dwCaps2 & DDSCAPS2_TEXTUREMANAGE)) )
#endif // DX7_TEXMANAGEMENT
{
if ((pSrcTexture->Location == SystemMemory) &&
(pDestTexture->Location == VideoMemory))
{
//----------------------------
// Do the system->videomem blt
//----------------------------
_DD_P3Download(pThisDisplay,
pSrcTexture->fpVidMem,
pDestTexture->fpVidMem,
pSrcTexture->dwPatchMode,
pDestTexture->dwPatchMode,
pSrcTexture->lPitch,
pDestTexture->lPitch,
pDestTexture->dwPixelPitch,
pDestTexture->dwPixelSize,
prSrc,
prDest);
}
else
{
DISPDBG((ERRLVL, "ERROR: __OP_BasicVolumeBlt b3DTexture (%d -> %d)"
"not suported yet!",
pSrcTexture->Location,
pDestTexture->Location));
}
}
#if DX7_TEXMANAGEMENT
else if (pSrcTexture->dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
{
//----------------------------------
//----------------------------------
// TEXBLT from a managed texture
//----------------------------------
//----------------------------------
if ((pDestTexture->Location == SystemMemory) ||
(pDestTexture->dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
{
//-------------------------------------------------
// Do the Managed surf -> sysmem | managed surf blt
//-------------------------------------------------
// make sure we'll reload the vidmem copy of the dest surf
if (pDestTexture->dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
{
__OP_MarkManagedSurfDirty(pContext,
dwDestSurfHandle,
pDestTexture);
}
_DD_BLT_SysMemToSysMemCopy(
pSrcTexture->fpVidMem,
pSrcTexture->lPitch,
pSrcTexture->dwBitDepth,
pDestTexture->fpVidMem,
pDestTexture->lPitch,
pDestTexture->dwBitDepth,
prSrc,
prDest);
}
else if (pDestTexture->Location == VideoMemory)
{
//-------------------------------------------------
// Do the Managed surf -> vidmem surf blt
//-------------------------------------------------
// This might be optimized by doing a vidmem->vidmem
// when the source managed texture has a vidmem copy
_DD_P3Download(pThisDisplay,
pSrcTexture->fpVidMem,
pDestTexture->fpVidMem,
pSrcTexture->dwPatchMode,
pDestTexture->dwPatchMode,
pSrcTexture->lPitch,
pDestTexture->lPitch,
pDestTexture->dwPixelPitch,
pDestTexture->dwPixelSize,
prSrc,
prDest);
}
else
{
DISPDBG((ERRLVL,"Src-managed __OP_BasicVolumeBlt variation "
"unimplemented! (from %d into %d)",
pSrcTexture->Location,
pDestTexture->Location));
}
}
else if (pDestTexture->dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
{
//--------------------------------------------------------------
//--------------------------------------------------------------
// TEXBLT into a managed texture (except from a managed texture)
//--------------------------------------------------------------
//--------------------------------------------------------------
// managed->managed is handled in the previous case
if (pSrcTexture->Location == SystemMemory)
{
//-------------------------------------------------
// Do the sysmem surf -> managed surf blt
//-------------------------------------------------
// make sure we'll reload the vidmem copy of the dest surf
__OP_MarkManagedSurfDirty(pContext,
dwDestSurfHandle,
pDestTexture);
_DD_BLT_SysMemToSysMemCopy(
pSrcTexture->fpVidMem,
pSrcTexture->lPitch,
pSrcTexture->dwBitDepth,
pDestTexture->fpVidMem,
pDestTexture->lPitch,
pDestTexture->dwBitDepth,
prSrc,
prDest);
}
else if (pSrcTexture->Location == VideoMemory)
{
//-------------------------------------------------
// Do the vidmem surf -> Managed surf blt
//-------------------------------------------------
if (0 != pSrcTexture->MipLevels[0].fpVidMemTM)
{
// Destination is already in vidmem so instead of
// "dirtying" the managed texture lets do the
// vidmem->vidmem blt which is faster than doing the
// update later (in the hope we'll really use it)
_DD_BLT_P3CopyBlt(pThisDisplay,
pSrcTexture->fpVidMem,
pDestTexture->MipLevels[0].fpVidMemTM,
pSrcTexture->dwPatchMode,
pDestTexture->dwPatchMode,
pSrcTexture->dwPixelPitch,
pDestTexture->dwPixelPitch,
pSrcTexture->MipLevels[0].dwOffsetFromMemoryBase,
pDestTexture->MipLevels[0].dwOffsetFromMemoryBase,
pDestTexture->dwPixelSize,
prSrc,
prDest);
}
else
{
// make sure we'll reload the
// vidmem copy of the dest surf
__OP_MarkManagedSurfDirty(pContext,
dwDestSurfHandle,
pDestTexture);
}
// Do slow mem mapped framebuffer blt into sysmem
// The source surface lives in video mem so we need to get a
// "real" sysmem address for it:
_DD_BLT_SysMemToSysMemCopy(
D3DSURF_GETPOINTER(pSrcTexture, pThisDisplay),
pSrcTexture->lPitch,
pSrcTexture->dwBitDepth,
pDestTexture->fpVidMem,
pDestTexture->lPitch,
pDestTexture->dwBitDepth,
prSrc,
prDest);
}
else if (pSrcTexture->Location == AGPMemory)
{
// make sure we'll reload the vidmem copy of the dest surf
__OP_MarkManagedSurfDirty(pContext,
dwDestSurfHandle,
pDestTexture);
_DD_BLT_SysMemToSysMemCopy(
pSrcTexture->fpVidMem,
pSrcTexture->lPitch,
pSrcTexture->dwBitDepth,
pDestTexture->fpVidMem,
pDestTexture->lPitch,
pDestTexture->dwBitDepth,
prSrc,
prDest);
}
else
{
DISPDBG((ERRLVL,"Dest-managed __OP_BasicVolumeBlt variation "
"unimplemented! (from %d into %d)",
pSrcTexture->Location,
pDestTexture->Location));
}
}
else
{
DISPDBG((ERRLVL,"__OP_BasicVolumeBlt variation unimplemented! "
"(from %d into %d)",
pSrcTexture->Location,
pDestTexture->Location));
}
#endif // DX7_TEXMANAGEMENT
} // __OP_BasicVolumeBlt
//-----------------------------------------------------------------------------
//
// _D3D_OP_VolumeBlt
//
// This function processes the D3DDP2OP_VOLUMEBLT DP2 command token.
//
//-----------------------------------------------------------------------------
VOID _D3D_OP_VolumeBlt(P3_D3DCONTEXT* pContext,
P3_THUNKEDDATA*pThisDisplay,
D3DHAL_DP2VOLUMEBLT* pBlt)
{
LPDDRAWI_DDRAWSURFACE_LCL pSrcLcl;
LPDDRAWI_DDRAWSURFACE_LCL pDestLcl;
P3_SURF_INTERNAL* pSrcTexture;
P3_SURF_INTERNAL* pDestTexture;
P3_SURF_FORMAT* pFormatSource;
P3_SURF_FORMAT* pFormatDest;
RECTL rSrc, rDest;
DWORD dwSrcCurrDepth, dwDestCurrDepth, dwEndDepth;
// Get the texture structure pointers
pSrcTexture = GetSurfaceFromHandle(pContext, pBlt->dwDDSrcSurface);
pDestTexture = GetSurfaceFromHandle(pContext, pBlt->dwDDDestSurface);
// Check that the textures are valid
if (pSrcTexture == NULL)
{
DISPDBG((ERRLVL, "ERROR: Source texture %d is invalid!",
pBlt->dwDDSrcSurface));
return;
}
if (pDestTexture == NULL)
{
DISPDBG((ERRLVL, "ERROR: Dest texture %d is invalid!",
pBlt->dwDDDestSurface));
return;
}
// If we are going to blt 3D texture, both have to be 3D texture
if ((pSrcTexture->b3DTexture == FALSE) != (pDestTexture->b3DTexture == FALSE))
{
DISPDBG((ERRLVL, "ERROR: TEXBLT b3DTexture (%d %d)does not match!",
pSrcTexture->b3DTexture,
pDestTexture->b3DTexture));
return;
}
// Do we blt whole 3D texture ?
if ((pBlt->srcBox.Left == 0) &&
(pBlt->srcBox.Top == 0) &&
(pBlt->srcBox.Right == pSrcTexture->wWidth) &&
(pBlt->srcBox.Bottom == pSrcTexture->wHeight) &&
(pBlt->srcBox.Front == 0) &&
(pBlt->srcBox.Back == pSrcTexture->wDepth) &&
(pBlt->dwDestX == 0) &&
(pBlt->dwDestY == 0) &&
(pBlt->dwDestZ == 0) &&
(pSrcTexture->wWidth == pDestTexture->wWidth) &&
(pSrcTexture->wHeight == pDestTexture->wHeight) &&
(pSrcTexture->wDepth == pDestTexture->wDepth))
{
// Build source rectangle
rSrc.left = 0;
rSrc.top = 0;
rSrc.right = pBlt->srcBox.Right;
rSrc.bottom = pBlt->srcBox.Bottom * pBlt->srcBox.Back;
// Destination rectangle is same as source.
rDest = rSrc;
// Switch to the DirectDraw context
DDRAW_OPERATION(pContext, pThisDisplay);
// Do the Blt!
__OP_BasicVolumeBlt(pContext,
pThisDisplay,
pSrcTexture,
pDestTexture,
pBlt->dwDDDestSurface,
&rSrc,
&rDest);
// Switch back to the Direct3D context
D3D_OPERATION(pContext, pThisDisplay);
return;
}
// Build source rectangle.
rSrc.left = pBlt->srcBox.Left;
rSrc.top = pBlt->srcBox.Top;
rSrc.right = pBlt->srcBox.Right;
rSrc.bottom = pBlt->srcBox.Bottom;
// Build destination rectangle.
rDest.left = pBlt->dwDestX;
rDest.top = pBlt->dwDestY;
rDest.right = pBlt->dwDestX + (rSrc.right - rSrc.left);
rDest.bottom = pBlt->dwDestY + (rSrc.bottom - rSrc.top);
// Adjust rectangle if blt from non-1st slice.
if (pBlt->srcBox.Front)
{
ULONG ulOffset = pSrcTexture->wDepth * pBlt->srcBox.Front;
rSrc.top += ulOffset;
rSrc.bottom += ulOffset;
}
// Adjust rectangle if blt to non-1st slice.
if (pBlt->dwDestZ)
{
ULONG ulOffset = pDestTexture->wDepth * pBlt->dwDestZ;
rDest.top += ulOffset;
rDest.bottom += ulOffset;
}
dwSrcCurrDepth = pBlt->srcBox.Front;
dwDestCurrDepth = pBlt->dwDestZ;
dwEndDepth = min(pBlt->dwDestZ + (pBlt->srcBox.Back - pBlt->srcBox.Front),
pDestTexture->wDepth);
dwEndDepth = min(dwEndDepth, pSrcTexture->wDepth);
while(dwDestCurrDepth < dwEndDepth)
{
// Switch to the DirectDraw context
DDRAW_OPERATION(pContext, pThisDisplay);
// Do the Blt!
__OP_BasicVolumeBlt(pContext,
pThisDisplay,
pSrcTexture,
pDestTexture,
pBlt->dwDDDestSurface,
&rSrc,
&rDest);
// Switch back to the Direct3D context
D3D_OPERATION(pContext, pThisDisplay);
// Move the source and destination rect to next slice.
rSrc.top += pSrcTexture->wDepth;
rSrc.bottom += pSrcTexture->wDepth;
rDest.top += pDestTexture->wDepth;
rDest.bottom += pDestTexture->wDepth;
// Move on to next slice.
dwSrcCurrDepth++;
dwDestCurrDepth++;
}
} // _D3D_OP_VolumeBlt
#endif // DX8_3DTEXTURES
#if DX8_DDI
//-----------------------------------------------------------------------------
//
// _D3D_OP_BufferBlt
//
// This function processes the D3DDP2OP_BUFFERBLT DP2 command token.
//
//-----------------------------------------------------------------------------
VOID _D3D_OP_BufferBlt(P3_D3DCONTEXT* pContext,
P3_THUNKEDDATA*pThisDisplay,
D3DHAL_DP2BUFFERBLT* pBlt)
{
#if DX7_VERTEXBUFFERS
// This command token is only sent to drivers
// supporting videomemory vertexbuffers. That is
// why we won't see it come down to this driver.
#endif DX7_VERTEXBUFFERS
} // _D3D_OP_BufferBlt
#endif // DX8_DDI
#if DX8_VERTEXSHADERS
//-----------------------------------------------------------------------------
//
// _D3D_OP_VertexShader_Create
//
// This function processes the D3DDP2OP_CREATEVERTEXSHADER DP2 command token.
//
//-----------------------------------------------------------------------------
HRESULT
_D3D_OP_VertexShader_Create(
P3_D3DCONTEXT* pContext,
DWORD dwVtxShaderHandle,
DWORD dwDeclSize,
DWORD dwCodeSize,
BYTE *pShader)
{
// Here we would use the data passed by the vertex shader
// creation block in order to instantiate or compile the
// given vertex shader. Since this hardware can't support
// vertex shaders at this time, we just skip the data.
return DD_OK;
} // _D3D_OP_VertexShader_Create
//-----------------------------------------------------------------------------
//
// _D3D_OP_VertexShader_Delete
//
// This function processes the D3DDP2OP_DELETEVERTEXSHADER DP2 command token.
//
//-----------------------------------------------------------------------------
VOID
_D3D_OP_VertexShader_Delete(
P3_D3DCONTEXT* pContext,
DWORD dwVtxShaderHandle)
{
// Here we would use the data passed by the vertex shader
// delete block in order to destroy the given vertex shader.
// Since this hardware can't support vertex shaders at
// this time, we just skip the data.
} // _D3D_OP_VertexShader_Delete
#define RDVSD_ISLEGACY(ShaderHandle) !(ShaderHandle & D3DFVF_RESERVED0)
//-----------------------------------------------------------------------------
//
// _D3D_OP_VertexShader_Set
//
// This function processes the D3DDP2OP_SETVERTEXSHADER DP2 command token.
//
//-----------------------------------------------------------------------------
VOID
_D3D_OP_VertexShader_Set(
P3_D3DCONTEXT* pContext,
DWORD dwVtxShaderHandle)
{
// Here we would use the data passed by the vertex shader
// set block in order to setup the given vertex shader.
// Since this hardware can't support vertex shaders at
// this time, we usually just skip the data. However under
// the circumstances described below, we might be passed a
// FVF vertex format
DISPDBG((DBGLVL,"Setting up shader # 0x%x",dwVtxShaderHandle));
#if DX7_D3DSTATEBLOCKS
if ( pContext->bStateRecMode )
{
_D3D_SB_Record_VertexShader_Set(pContext, dwVtxShaderHandle);
return;
}
#endif // DX7_D3DSTATEBLOCKS
// Zero is a special handle that tells the driver to
// invalidate the currently set shader.
if( dwVtxShaderHandle == 0 )
{
DISPDBG((WRNLVL,"Invalidating the currently set shader"));
return ;
}
if( RDVSD_ISLEGACY(dwVtxShaderHandle) )
{
// Make it parse the FVF
pContext->dwVertexType = dwVtxShaderHandle;
}
else
{
DISPDBG((ERRLVL,"_D3D_OP_VertexShader_Set: Illegal shader handle "
"(This driver cant do vertex processing)"));
}
} // _D3D_OP_VertexShader_Set
//-----------------------------------------------------------------------------
//
// _D3D_OP_VertexShader_SetConst
//
// This function processes the D3DDP2OP_SETVERTEXSHADERCONST DP2 command token.
//
//-----------------------------------------------------------------------------
VOID
_D3D_OP_VertexShader_SetConst(
P3_D3DCONTEXT* pContext,
DWORD dwRegister,
DWORD dwConst,
DWORD *pdwValues)
{
// Here we would use the data passed by the vertex shader
// constant block in order to set up the constant entry.
// Since this hardware can't support vertex shaders at
// this time, we just skip the data.
} // _D3D_OP_VertexShader_SetConst
#endif // DX8_VERTEXSHADERS
#if DX8_PIXELSHADERS
//-----------------------------------------------------------------------------
//
// _D3D_OP_PixelShader_Create
//
// This function processes the D3DDP2OP_CREATEPIXELSHADER DP2 command token.
//
//-----------------------------------------------------------------------------
HRESULT
_D3D_OP_PixelShader_Create(
P3_D3DCONTEXT* pContext,
DWORD dwPxlShaderHandle,
DWORD dwCodeSize,
BYTE *pShader)
{
// Here we would use the data passed by the pixel shader
// creation block in order to instantiate or compile the
// given pixel shader.
// Since this hardware can't support pixel shaders at this
// time, we fail the call in case we're called to create a
// 255.255 version shader!
return D3DERR_DRIVERINVALIDCALL;
} // _D3D_OP_PixelShader_Create
//-----------------------------------------------------------------------------
//
// _D3D_OP_PixelShader_Delete
//
// This function processes the D3DDP2OP_DELETEPIXELSHADER DP2 command token.
//
//-----------------------------------------------------------------------------
VOID
_D3D_OP_PixelShader_Delete(
P3_D3DCONTEXT* pContext,
DWORD dwPxlShaderHandle)
{
// Here we would use the data passed by the pixel shader
// delete block in order to destroy the given pixel shader.
// Since this hardware can't support pixel shaders at
// this time, we just skip the data.
} // _D3D_OP_PixelShader_Delete
//-----------------------------------------------------------------------------
//
// _D3D_OP_PixelShader_Set
//
// This function processes the D3DDP2OP_SETPIXELSHADER DP2 command token.
//
//-----------------------------------------------------------------------------
VOID
_D3D_OP_PixelShader_Set(
P3_D3DCONTEXT* pContext,
DWORD dwPxlShaderHandle)
{
// Here we would use the data passed by the pixel shader
// set block in order to setup the given pixel shader.
// Since this hardware can't support pixel shaders at
// this time, we just skip the data.
} // _D3D_OP_PixelShader_Set
//-----------------------------------------------------------------------------
//
// _D3D_OP_PixelShader_SetConst
//
// This function processes the D3DDP2OP_SETPIXELSHADERCONST DP2 command token.
//
//-----------------------------------------------------------------------------
VOID
_D3D_OP_PixelShader_SetConst(
P3_D3DCONTEXT* pContext,
DWORD dwRegister,
DWORD dwCount,
DWORD *pdwValues)
{
// Here we would use the data passed by the pixel shader
// set block in order to setup the given pixel shader constants.
// Since this hardware can't support pixel shaders at
// this time, we just skip the data.
} // _D3D_OP_PixelShader_SetConst
#endif // DX8_PIXELSHADERS
#if DX8_MULTSTREAMS
//-----------------------------------------------------------------------------
//
// _D3D_OP_MStream_SetSrc
//
// This function processes the D3DDP2OP_SETSTREAMSOURCE DP2 command token.
//
//-----------------------------------------------------------------------------
VOID
_D3D_OP_MStream_SetSrc(
P3_D3DCONTEXT* pContext,
DWORD dwStream,
DWORD dwVBHandle,
DWORD dwStride)
{
P3_SURF_INTERNAL *pSrcStream;
DBG_ENTRY(_D3D_OP_MStream_SetSrc);
#if DX7_D3DSTATEBLOCKS
if ( pContext->bStateRecMode )
{
_D3D_SB_Record_MStream_SetSrc(pContext, dwStream, dwVBHandle, dwStride);
return;
}
#endif // DX7_D3DSTATEBLOCKS
if (dwVBHandle != 0)
{
if (dwStream == 0)
{
// Get the surface structure pointers for stream #0
pSrcStream = GetSurfaceFromHandle(pContext, dwVBHandle);
if (pSrcStream)
{
DISPDBG((DBGLVL,"Address of VB = 0x%x "
"dwVBHandle = %d , dwStride = %d",
pSrcStream->fpVidMem,dwVBHandle, dwStride));
pContext->lpVertices = (LPDWORD)pSrcStream->fpVidMem;
pContext->dwVerticesStride = dwStride;
if (dwStride > 0)
{
// DX8 has mixed types of vertices in one VB, size in bytes
// of the vertex buffer must be preserved
pContext->dwVBSizeInBytes = pSrcStream->lPitch;
// for VBs the wHeight should always be == 1.
// dwNumVertices stores the # of vertices in the VB
// On Win2K, both wWidth and lPitch are the buffer size
// On Win9x, only lPitch is the buffer size, wWidth is 0
// The same fact is also true for the index buffer
pContext->dwNumVertices = pSrcStream->lPitch / dwStride;
DISPDBG((DBGLVL,"dwVBHandle pContext->dwNumVertices = "
"pSrcStream->lPitch / dwStride = %d %d %d %d",
dwVBHandle,
pContext->dwNumVertices,
pSrcStream->lPitch,dwStride));
#if DX7_D3DSTATEBLOCKS
pContext->dwVBHandle = dwVBHandle;
#endif // DX7_D3DSTATEBLOCKS
}
else
{
pContext->dwVBSizeInBytes = 0;
pContext->dwNumVertices = 0;
DISPDBG((ERRLVL,"INVALID Stride is 0. VB Size undefined"));
}
}
else
{
DISPDBG((ERRLVL,"ERROR Address of VB is NULL, "
"dwStream = %d dwVBHandle = %d , dwStride = %d",
dwStream, dwVBHandle, dwStride));
}
}
else
{
DISPDBG((WRNLVL,"We don't handle other streams than #0"));
}
}
else
{
// We are unsetting the stream
pContext->lpVertices = NULL;
DISPDBG((WRNLVL,"Unsetting a stream: "
"dwStream = %d dwVBHandle = %d , dwStride = %d",
dwStream, dwVBHandle, dwStride));
}
DBG_EXIT(_D3D_OP_MStream_SetSrc, 0);
} // _D3D_OP_MStream_SetSrc
//-----------------------------------------------------------------------------
//
// _D3D_OP_MStream_SetSrcUM
//
// This function processes the D3DDP2OP_SETSTREAMSOURCEUM DP2 command token.
//
//-----------------------------------------------------------------------------
VOID
_D3D_OP_MStream_SetSrcUM(
P3_D3DCONTEXT* pContext,
DWORD dwStream,
DWORD dwStride,
LPBYTE pUMVtx,
DWORD dwVBSize)
{
DBG_ENTRY(_D3D_OP_MStream_SetSrcUM);
if (dwStream == 0)
{
// Set the stream # 0 information
DISPDBG((DBGLVL,"_D3D_OP_MStream_SetSrcUM: "
"Setting VB@ 0x%x dwstride=%d", pUMVtx, dwStride));
pContext->lpVertices = (LPDWORD)pUMVtx;
pContext->dwVerticesStride = dwStride;
pContext->dwVBSizeInBytes = dwVBSize * dwStride;
pContext->dwNumVertices = dwVBSize ; // comes from the DP2 data
// structure
}
else
{
DISPDBG((WRNLVL,"_D3D_OP_MStream_SetSrcUM: "
"We don't handle other streams than #0"));
}
DBG_EXIT(_D3D_OP_MStream_SetSrcUM, 0);
} // _D3D_OP_MStream_SetSrcUM
//-----------------------------------------------------------------------------
//
// _D3D_OP_MStream_SetIndices
//
// This function processes the D3DDP2OP_SETINDICES DP2 command token.
//
//-----------------------------------------------------------------------------
VOID
_D3D_OP_MStream_SetIndices(
P3_D3DCONTEXT* pContext,
DWORD dwVBHandle,
DWORD dwStride)
{
P3_SURF_INTERNAL *pIndxStream;
DBG_ENTRY(_D3D_OP_MStream_SetIndices);
#if DX7_D3DSTATEBLOCKS
if ( pContext->bStateRecMode )
{
_D3D_SB_Record_MStream_SetIndices(pContext, dwVBHandle, dwStride);
return;
}
#endif // DX7_D3DSTATEBLOCKS
// NULL dwVBHandle just means that the Index should be unset
if (dwVBHandle != 0)
{
// Get the indices surface structure pointer
pIndxStream = GetSurfaceFromHandle(pContext, dwVBHandle);
if (pIndxStream)
{
DISPDBG((DBGLVL,"Address of VB = 0x%x", pIndxStream->fpVidMem));
pContext->lpIndices = (LPDWORD)pIndxStream->fpVidMem;
pContext->dwIndicesStride = dwStride; // 2 or 4 for 16/32bit indices
#if DX7_D3DSTATEBLOCKS
pContext->dwIndexHandle = dwVBHandle; // Index buffer handle
#endif
}
else
{
DISPDBG((ERRLVL,"ERROR Address of Index Surface is NULL, "
"dwVBHandle = %d , dwStride = %d",
dwVBHandle, dwStride));
}
}
else
{
// We are unsetting the stream
pContext->lpIndices = NULL;
DISPDBG((WRNLVL,"Unsetting an index stream: "
"dwVBHandle = %d , dwStride = %d",
dwVBHandle, dwStride));
}
DBG_EXIT(_D3D_OP_MStream_SetIndices, 0);
} // _D3D_OP_MStream_SetIndices
//-----------------------------------------------------------------------------
//
// _D3D_OP_MStream_DrawPrim
//
// This function processes the D3DDP2OP_DRAWPRIMITIVE DP2 command token.
//
//-----------------------------------------------------------------------------
VOID
_D3D_OP_MStream_DrawPrim(
P3_D3DCONTEXT* pContext,
D3DPRIMITIVETYPE primType,
DWORD VStart,
DWORD PrimitiveCount)
{
DBG_ENTRY(_D3D_OP_MStream_DrawPrim);
DISPDBG((DBGLVL,"_D3D_OP_MStream_DrawPrim "
"primType=0x%x VStart=%d PrimitiveCount=%d",
primType, VStart, PrimitiveCount));
_D3D_OP_MStream_DrawPrim2(pContext,
primType,
VStart * pContext->FVFData.dwStride,
PrimitiveCount);
DBG_EXIT(_D3D_OP_MStream_DrawPrim, 0);
} // _D3D_OP_MStream_DrawPrim
//-----------------------------------------------------------------------------
//
// _D3D_OP_MStream_DrawIndxP
//
// This function processes the D3DDP2OP_DRAWINDEXEDPRIMITIVE DP2 command token.
//
//-----------------------------------------------------------------------------
VOID
_D3D_OP_MStream_DrawIndxP(
P3_D3DCONTEXT* pContext,
D3DPRIMITIVETYPE primType,
DWORD BaseVertexIndex,
DWORD MinIndex,
DWORD NumVertices,
DWORD StartIndex,
DWORD PrimitiveCount)
{
DBG_ENTRY(_D3D_OP_MStream_DrawIndxP);
DISPDBG((DBGLVL,"_D3D_OP_MStream_DrawIndxP "
"primType=0x%x BaseVertexIndex=%d MinIndex=%d"
"NumVertices =%d StartIndex=%d PrimitiveCount=%d",
primType, BaseVertexIndex, MinIndex,
NumVertices, StartIndex, PrimitiveCount));
_D3D_OP_MStream_DrawIndxP2(pContext,
primType,
BaseVertexIndex * pContext->FVFData.dwStride,
MinIndex,
NumVertices,
StartIndex * pContext->dwIndicesStride,
PrimitiveCount);
DBG_EXIT(_D3D_OP_MStream_DrawIndxP, 0);
} // _D3D_OP_MStream_DrawIndxP
//-----------------------------------------------------------------------------
//
// Validate the context settings to use the current streams
//
//-----------------------------------------------------------------------------
BOOL
__OP_ValidateStreams(
P3_D3DCONTEXT* pContext,
BOOL bCheckIndexStream)
{
if ((pContext->dwVerticesStride == 0) ||
(pContext->FVFData.dwStride == 0))
{
DISPDBG((ERRLVL,"The zero'th stream is doesn't have a valid VB set"));
return FALSE;
}
if (pContext->dwVerticesStride < pContext->FVFData.dwStride)
{
DISPDBG((ERRLVL,"The stride set for the vertex stream is "
"less than the FVF vertex size"));
return FALSE;
}
//@@BEGIN_DDKSPLIT
// This shouldn't happen, but lets watch for it since it would show
// up as weird mangled & distorted triangles
if (pContext->dwVerticesStride != pContext->FVFData.dwStride)
{
DISPDBG((ERRLVL,"Strides(indx-prim) <> %d %d ",
pContext->dwVerticesStride,pContext->FVFData.dwStride));
}
//@@END_DDKSPLIT
if ((bCheckIndexStream) && (NULL == pContext->lpIndices))
{
DISPDBG((ERRLVL,"Pointer to index buffer is null"));
return FALSE;
}
if (NULL == pContext->lpVertices)
{
DISPDBG((ERRLVL,"Pointer to vertex buffer is null"));
return FALSE;
}
return TRUE;
} // __OP_ValidateStreams
//-----------------------------------------------------------------------------
//
// _D3D_OP_MStream_DrawPrim2
//
// This function processes the D3DDP2OP_DRAWPRIMITIVE2 DP2 command token.
//
//-----------------------------------------------------------------------------
VOID
_D3D_OP_MStream_DrawPrim2(
P3_D3DCONTEXT* pContext,
D3DPRIMITIVETYPE primType,
DWORD FirstVertexOffset,
DWORD PrimitiveCount)
{
BOOL bError;
WORD wVStart;
DWORD dwFillMode = pContext->RenderStates[D3DRENDERSTATE_FILLMODE];
LPBYTE lpVertices;
DWORD dwNumVertices;
DBG_ENTRY(_D3D_OP_MStream_DrawPrim2);
DISPDBG((DBGLVL ,"_D3D_OP_MStream_DrawPrim2 "
"primType=0x%x FirstVertexOffset=%d PrimitiveCount=%d",
primType, FirstVertexOffset, PrimitiveCount));
if (!__OP_ValidateStreams(pContext, FALSE))
{
return;
}
// Watchout: Sometimes (particularly when CLIPPEDTRIFAN are drawn),
// FirstVertexOffset might not be divided evenly by the dwStride
lpVertices = ((LPBYTE)pContext->lpVertices) + FirstVertexOffset;
dwNumVertices = pContext->dwVBSizeInBytes - FirstVertexOffset;
dwNumVertices /= pContext->dwVerticesStride;
wVStart = 0;
switch(primType)
{
case D3DPT_POINTLIST:
{
D3DHAL_DP2POINTS dp2Points;
dp2Points.wVStart = wVStart;
#if DX8_POINTSPRITES
if(IS_POINTSPRITE_ACTIVE(pContext))
{
_D3D_R3_DP2_PointsSprite_DWCount(pContext,
PrimitiveCount,
(LPBYTE)&dp2Points,
(LPD3DTLVERTEX)lpVertices,
dwNumVertices,
&bError);
}
else
#endif // DX8_POINTSPRITES
{
_D3D_R3_DP2_Points_DWCount(pContext,
PrimitiveCount,
(LPBYTE)&dp2Points,
(LPD3DTLVERTEX)lpVertices,
dwNumVertices,
&bError);
}
}
break;
case D3DPT_LINELIST:
_D3D_R3_DP2_LineList(pContext,
PrimitiveCount,
(LPBYTE)&wVStart,
(LPD3DTLVERTEX)lpVertices,
dwNumVertices,
&bError);
break;
case D3DPT_LINESTRIP:
_D3D_R3_DP2_LineStrip(pContext,
PrimitiveCount,
(LPBYTE)&wVStart,
(LPD3DTLVERTEX)lpVertices,
dwNumVertices,
&bError);
break;
case D3DPT_TRIANGLELIST:
_D3D_R3_DP2_TriangleList(pContext,
PrimitiveCount,
(LPBYTE)&wVStart,
(LPD3DTLVERTEX)lpVertices,
dwNumVertices,
&bError);
break;
case D3DPT_TRIANGLESTRIP:
_D3D_R3_DP2_TriangleStrip(pContext,
PrimitiveCount,
(LPBYTE)&wVStart,
(LPD3DTLVERTEX)lpVertices,
dwNumVertices,
&bError);
break;
case D3DPT_TRIANGLEFAN:
_D3D_R3_DP2_TriangleFan(pContext,
PrimitiveCount,
(LPBYTE)&wVStart,
(LPD3DTLVERTEX)lpVertices,
dwNumVertices,
&bError);
break;
}
DBG_EXIT(_D3D_OP_MStream_DrawPrim2, 0);
} // _D3D_OP_MStream_DrawPrim2
//-----------------------------------------------------------------------------
//
// _D3D_OP_MStream_DrawIndxP2
//
// This function processes the D3DDP2OP_DRAWINDEXEDPRIMITIVE2 DP2 command token.
//
//-----------------------------------------------------------------------------
VOID
_D3D_OP_MStream_DrawIndxP2(
P3_D3DCONTEXT* pContext,
D3DPRIMITIVETYPE primType,
INT BaseVertexOffset,
DWORD MinIndex,
DWORD NumVertices,
DWORD StartIndexOffset,
DWORD PrimitiveCount)
{
INT BaseIndexOffset;
LPDWORD lpVertices;
LPBYTE lpIndices;
BOOL bError;
R3_DP2_PRIM_TYPE_MS *pRenderFunc;
DBG_ENTRY(_D3D_OP_MStream_DrawIndxP2);
DISPDBG((DBGLVL,"_D3D_OP_MStream_DrawIndxP2 "
"primType=0x%x BaseVertexOffset=%d MinIndex=%d "
"NumVertices=%d StartIndexOffset=%d PrimitiveCount=%d",
primType, BaseVertexOffset, MinIndex,
NumVertices, StartIndexOffset, PrimitiveCount));
if (!__OP_ValidateStreams(pContext, TRUE))
{
return;
}
// The MinIndex and NumVertices parameters specify the range of vertex i
// ndices used for each DrawIndexedPrimitive call. These are used to
// optimize vertex processing of indexed primitives by processing a
// sequential range of vertices prior to indexing into these vertices
// ********** IMPORTANT NOTE **********
//
// BaseVertexOffset is a signed quantity (INT) unlike the other parameters
// to this call which are DWORDS. This may appear strange. Why would
// the offset into the vertex buffer be negative? Clearly you cannot access
// vertex data before the start of the vertex buffer, and indeed, you never
// do. When you have a negative BaseVertexOffset you will also receive
// indices which are large enough that when applied to the start pointer
// (obtained from adding a negative BaseVertexOffset to the vertex data
// pointer) which fall within the correct range of the vertices in the
// actual vertex buffer, i.e., the indices "undo" any negative vertex offset
// and vertex accesses will end up being in the legal range for that vertex
// buffer.
//
// Hence, you must write your driver code with this in mind. For example,
// you can't assume that given an index i and with a current vertex buffer
// of size v:
//
// ((StartIndexOffset + i) >= 0) && ((StartIndexOffset + i) < v)
//
// Your code needs to take into account that your indices are not offsets
// from the start of the vertex buffer but rather from the start of the
// vertex buffer plus BaseVertexOffset and that furthermore BaseVertexOffset
// may be negative.
//
// The reason BaseVertexOffset can be negative is that it provides a
// significant advantage to the runtime in certain vertex processing scenarios.
lpVertices = (LPDWORD)((LPBYTE)pContext->lpVertices + BaseVertexOffset);
lpIndices = (LPBYTE)pContext->lpIndices + StartIndexOffset;
// Select the appropriate rendering function
pRenderFunc = NULL;
if (pContext->dwIndicesStride == 2)
{
// Handle 16 bit indices
switch(primType)
{
case D3DPT_LINELIST:
pRenderFunc = _D3D_R3_DP2_IndexedLineList_MS_16IND;
break;
case D3DPT_LINESTRIP:
pRenderFunc = _D3D_R3_DP2_IndexedLineStrip_MS_16IND;
break;
case D3DPT_TRIANGLELIST:
pRenderFunc = _D3D_R3_DP2_IndexedTriangleList_MS_16IND;
break;
case D3DPT_TRIANGLESTRIP:
pRenderFunc = _D3D_R3_DP2_IndexedTriangleStrip_MS_16IND;
break;
case D3DPT_TRIANGLEFAN:
pRenderFunc = _D3D_R3_DP2_IndexedTriangleFan_MS_16IND;
break;
}
}
else
{
// Handle 32 bit indices
switch(primType)
{
case D3DPT_LINELIST:
pRenderFunc = _D3D_R3_DP2_IndexedLineList_MS_32IND;
break;
case D3DPT_LINESTRIP:
pRenderFunc = _D3D_R3_DP2_IndexedLineStrip_MS_32IND;
break;
case D3DPT_TRIANGLELIST:
pRenderFunc = _D3D_R3_DP2_IndexedTriangleList_MS_32IND;
break;
case D3DPT_TRIANGLESTRIP:
pRenderFunc = _D3D_R3_DP2_IndexedTriangleStrip_MS_32IND;
break;
case D3DPT_TRIANGLEFAN:
pRenderFunc = _D3D_R3_DP2_IndexedTriangleFan_MS_32IND;
break;
}
}
// Call our rendering function
if (pRenderFunc)
{
// As mentioned above, the actual range of indices seen by the driver
// doesn't necessarily lie within the range zero to one less than
// the number of vertices in the vertex buffer due to BaseVertexOffset.
// If BaseVertexOffset is positive the range of valid indices is
// smaller than the size of the vertex buffer (the vertices that
// lie in the vertex buffer before the BaseVertexOffset are not
// considered). Furthermore, if BaseVertexOffset a valid index can
// actually by greater than the number of vertices in the vertex
// buffer.
//
// To assist with the validation performed by the rendering functions
// we here compute a minimum and maximum index which take into
// account the value of BaseVertexOffset. Thus a test for a valid
// index becomes:
//
// ((BaseIndexOffset + StartIndexOffset + Index) >= 0) &&
// ((BaseIndexOffset + StartIndexOffset + Index) < VertexCount)
BaseIndexOffset = (BaseVertexOffset / (int)pContext->dwVerticesStride);
DISPDBG((DBGLVL,"_D3D_OP_MStream_DrawIndxP2 BaseIndexOffset = %d",
BaseIndexOffset));
(*pRenderFunc)(pContext,
PrimitiveCount,
(LPBYTE)lpIndices,
(LPD3DTLVERTEX)lpVertices,
BaseIndexOffset,
pContext->dwNumVertices,
&bError);
}
DBG_EXIT(_D3D_OP_MStream_DrawIndxP2, 0);
} // _D3D_OP_MStream_DrawIndxP2
//-----------------------------------------------------------------------------
//
// _D3D_OP_MStream_ClipTriFan
//
// This function processes the D3DDP2OP_CLIPPEDTRIANGLEFAN DP2 command token.
//
//-----------------------------------------------------------------------------
VOID
_D3D_OP_MStream_ClipTriFan(
P3_D3DCONTEXT* pContext,
DWORD FirstVertexOffset,
DWORD dwEdgeFlags,
DWORD PrimitiveCount)
{
BOOL bError;
DBG_ENTRY(_D3D_OP_MStream_ClipTriFan);
DISPDBG((DBGLVL,"_D3D_OP_MStream_ClipTriFan "
"FirstVertexOffset=%d dwEdgeFlags=0x%x PrimitiveCount=%d",
FirstVertexOffset, dwEdgeFlags, PrimitiveCount));
if (pContext->RenderStates[D3DRENDERSTATE_FILLMODE] == D3DFILL_WIREFRAME)
{
D3DHAL_DP2TRIANGLEFAN_IMM dp2TriFanWire;
if (!__OP_ValidateStreams(pContext, FALSE))
{
DBG_EXIT(_D3D_OP_MStream_ClipTriFan, 0);
return;
}
dp2TriFanWire.dwEdgeFlags = dwEdgeFlags;
_D3D_R3_DP2_TriangleFanImm(pContext,
(WORD)PrimitiveCount,
(LPBYTE)&dp2TriFanWire,
(LPD3DTLVERTEX)pContext->lpVertices,
pContext->dwNumVertices,
&bError);
}
else
{
_D3D_OP_MStream_DrawPrim2(pContext,
D3DPT_TRIANGLEFAN,
FirstVertexOffset,
PrimitiveCount);
}
DBG_EXIT(_D3D_OP_MStream_ClipTriFan, 0);
} // _D3D_OP_MStream_ClipTriFan
//-----------------------------------------------------------------------------
//
// _D3D_OP_MStream_DrawRectSurface
//
// This function processes the D3DDP2OP_DRAWRECTSURFACE DP2 command token.
//
//-----------------------------------------------------------------------------
VOID _D3D_OP_MStream_DrawRectSurface(P3_D3DCONTEXT* pContext,
DWORD Handle,
DWORD Flags,
PVOID lpPrim)
{
// High order surfaces are only supported for hw/drivers with
// TnL support and 1.0 vertex shader support
} // _D3D_OP_MStream_DrawRectSurface
//-----------------------------------------------------------------------------
//
// _D3D_OP_MStream_DrawTriSurface
//
// This function processes the D3DDP2OP_DRAWTRISURFACE DP2 command token.
//
//-----------------------------------------------------------------------------
VOID _D3D_OP_MStream_DrawTriSurface(P3_D3DCONTEXT* pContext,
DWORD Handle,
DWORD Flags,
PVOID lpPrim)
{
// High order surfaces are only supported for hw/drivers with
// TnL support and 1.0 vertex shader support
} // _D3D_OP_MStream_DrawTriSurface
#endif // DX8_MULTSTREAMS
//-----------------------------------------------------------------------------
//
// _D3D_OP_Viewport
//
// This function processes the D3DDP2OP_VIEWPORTINFO DP2 command token.
//
//-----------------------------------------------------------------------------
VOID _D3D_OP_Viewport(P3_D3DCONTEXT* pContext,
D3DHAL_DP2VIEWPORTINFO* lpvp)
{
#if DX7_D3DSTATEBLOCKS
if ( pContext->bStateRecMode )
{
_D3D_SB_Record_Viewport(pContext, lpvp);
}
else
#endif // DX7_D3DSTATEBLOCKS
{
pContext->ViewportInfo = *lpvp;
DIRTY_VIEWPORT(pContext);
}
} // _D3D_OP_Viewport
//-----------------------------------------------------------------------------
//
// _D3D_OP_ZRange
//
// This function processes the D3DDP2OP_ZRANGE DP2 command token.
//
//-----------------------------------------------------------------------------
VOID _D3D_OP_ZRange(P3_D3DCONTEXT* pContext,
D3DHAL_DP2ZRANGE* lpzr)
{
#if DX7_D3DSTATEBLOCKS
if ( pContext->bStateRecMode )
{
_D3D_SB_Record_ZRange(pContext, lpzr);
}
else
#endif // DX7_D3DSTATEBLOCKS
{
pContext->ZRange = *lpzr;
DIRTY_VIEWPORT(pContext);
}
} // _D3D_OP_ZRange
//-----------------------------------------------------------------------------
//
// _D3D_OP_UpdatePalette
//
// This function processes the D3DDP2OP_UPDATEPALETTE DP2 command token.
//
// Note : This function is need to skip D3DDP2OP_UPDATEPALETTE sent down
// by some DX6 apps, even if when PALETTE TEXTURE is not supported
// Also notice that for legacy DX apps, the palette doesn't get
// properly restored in another app transitions into full screen
// mode and back. This is because the (legacy) runtimes don't
// sent proper notification (through UpdatePalette/SetPalette) of
// this event
//
//-----------------------------------------------------------------------------
HRESULT _D3D_OP_UpdatePalette(P3_D3DCONTEXT* pContext,
D3DHAL_DP2UPDATEPALETTE* pUpdatePalette,
DWORD* pdwPalEntries)
{
#if DX7_PALETTETEXTURE
D3DHAL_DP2UPDATEPALETTE* pPalette;
P3_SURF_INTERNAL* pTexture;
// Find internal palette pointer from handle
pPalette = GetPaletteFromHandle(pContext,
pUpdatePalette->dwPaletteHandle);
// Palette doesn't exist
if (! pPalette)
{
DISPDBG((WRNLVL, "_D3D_OP_UpdatePalette : Can't find palette"));
return DDERR_INVALIDPARAMS;
}
// Check the range of palette entries
if (pUpdatePalette->wStartIndex > LUT_ENTRIES)
{
DISPDBG((WRNLVL,
"_D3D_OP_UpdatePalette : wStartIndex (%d) is bigger than 256",
pUpdatePalette->wStartIndex));
return DDERR_INVALIDPARAMS;
}
if ((pUpdatePalette->wStartIndex + pUpdatePalette->wNumEntries)
> LUT_ENTRIES)
{
DISPDBG((WRNLVL, "_D3D_OP_UpdatePalette : too many entries"));
return DDERR_INVALIDPARAMS;
}
// Each palette is ARGB 8:8:8:8
memcpy(((LPBYTE)(pPalette + 1)) + pUpdatePalette->wStartIndex*sizeof(DWORD),
pdwPalEntries,
pUpdatePalette->wNumEntries*sizeof(DWORD));
// Check if the palette is in use
// Palette Texture can not be used alone in the 2nd stage, so only the
// 1st stage must be checked.
if (pContext->TextureStageState[0].m_dwVal[D3DTSS_TEXTUREMAP])
{
pTexture = GetSurfaceFromHandle(pContext,
pContext->TextureStageState[0].m_dwVal[D3DTSS_TEXTUREMAP]);
if (pTexture)
{
if ((pTexture->pFormatSurface->DeviceFormat == SURF_CI8) &&
(pTexture->dwPaletteHandle == pUpdatePalette->dwPaletteHandle))
{
DIRTY_TEXTURE(pContext);
}
}
}
return DD_OK;
#else
return DD_OK;
#endif // DX7_PALETTETEXTURE
} // D3D_OP_UpdatePalette
//-----------------------------------------------------------------------------
//
// _D3D_OP_SetPalette
//
// This function processes the D3DDP2OP_SETPALETTE DP2 command token.
//
// Note : This function is need to skip D3DDP2OP_SETPALETTE sent down
// by some DX6 apps, even if when PALETTE TEXTURE is not supported
//
//-----------------------------------------------------------------------------
HRESULT _D3D_OP_SetPalettes(P3_D3DCONTEXT* pContext,
D3DHAL_DP2SETPALETTE* pSetPalettes,
int iNumSetPalettes)
{
#if DX7_PALETTETEXTURE
int i;
P3_SURF_INTERNAL* pTexture;
D3DHAL_DP2UPDATEPALETTE* pPalette;
// Loop to process N surface palette association
for (i = 0; i < iNumSetPalettes; i++, pSetPalettes++)
{
DISPDBG((DBGLVL,"SETPALETTE: Binding surf # %d to palette # %d",
pSetPalettes->dwSurfaceHandle,
pSetPalettes->dwPaletteHandle));
// Find internal surface pointer from handle
pTexture = GetSurfaceFromHandle(pContext,
pSetPalettes->dwSurfaceHandle);
if (! pTexture)
{
// Associated texture can't be found
DISPDBG((WRNLVL,
"SetPalettes : invalid texture handle %08lx",
pSetPalettes->dwSurfaceHandle));
return DDERR_INVALIDPARAMS;
}
// Create the internal palette structure if necessary
if (pSetPalettes->dwPaletteHandle)
{
// Find internal palette pointer from handle
pPalette = GetPaletteFromHandle(pContext,
pSetPalettes->dwPaletteHandle);
if (! pPalette)
{
pPalette = (D3DHAL_DP2UPDATEPALETTE *)
HEAP_ALLOC(FL_ZERO_MEMORY,
sizeof(D3DHAL_DP2UPDATEPALETTE)
+ LUT_ENTRIES*sizeof(DWORD),
ALLOC_TAG_DX(P));
// Out of memory case
if (! pPalette)
{
DISPDBG((WRNLVL, "_D3D_OP_SetPalettes : Out of memory."));
return DDERR_OUTOFMEMORY;
}
// Add this texture to the surface list
if (! PA_SetEntry(pContext->pPalettePointerArray,
pSetPalettes->dwPaletteHandle,
pPalette))
{
HEAP_FREE(pPalette);
DISPDBG((WRNLVL, "_D3D_OP_SetPalettes : "
"PA_SetEntry() failed."));
return DDERR_OUTOFMEMORY;
}
// Set up the internal data structure
pPalette->dwPaletteHandle = pSetPalettes->dwPaletteHandle;
pPalette->wStartIndex = 0;
pPalette->wNumEntries = LUT_ENTRIES;
}
}
// Record palette handle and flags in internal surface data
pTexture->dwPaletteHandle = pSetPalettes->dwPaletteHandle;
pTexture->dwPaletteFlags = pSetPalettes->dwPaletteFlags;
// Mark texture as dirty if current texture is affected
if ((pContext->TextureStageState[0].m_dwVal[D3DTSS_TEXTUREMAP] ==
pSetPalettes->dwSurfaceHandle) ||
(pContext->TextureStageState[1].m_dwVal[D3DTSS_TEXTUREMAP] ==
pSetPalettes->dwSurfaceHandle))
{
DIRTY_TEXTURE(pContext);
}
}
return DD_OK;
#else
return DD_OK;
#endif // DX7_PALETTETEXTURE
} // _D3D_OP_SetPalettes