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.
1058 lines
38 KiB
1058 lines
38 KiB
/*==========================================================================;
|
|
*
|
|
* Copyright (C) 1997 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: tldevice.cpp
|
|
*
|
|
* Content: Support code for device with transformation and lighting
|
|
*
|
|
***************************************************************************/
|
|
#include "pch.cpp"
|
|
#pragma hdrstop
|
|
|
|
#include "tlhal.h"
|
|
#include "drawprim.hpp"
|
|
#include "pvvid.h"
|
|
//=====================================================================
|
|
//
|
|
// CDirect3DDevice7 interface
|
|
//
|
|
//=====================================================================
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirect3DDevice7::Init"
|
|
|
|
HRESULT CDirect3DDevice7::Init(
|
|
REFCLSID riid, LPDIRECT3DI lpD3DI, LPDIRECTDRAWSURFACE lpDDS,
|
|
IUnknown* pUnkOuter, LPUNKNOWN* lplpD3DDevice)
|
|
{
|
|
#if 0
|
|
// Stateblocks are always emulated on DX7
|
|
DWORD value = 0;
|
|
GetD3DRegValue(REG_DWORD, "EmulateStateBlocks", &value, sizeof(DWORD));
|
|
if(value == 0)
|
|
{
|
|
// All DX7 devices should support state sets
|
|
this->dwFEFlags |= D3DFE_STATESETS;
|
|
}
|
|
#endif
|
|
|
|
HRESULT ret = CDirect3DDeviceIDP2::Init(riid, lpD3DI, lpDDS, pUnkOuter, lplpD3DDevice);
|
|
if (ret != D3D_OK)
|
|
return ret;
|
|
|
|
// Do device specific initialization here
|
|
return D3D_OK;
|
|
}
|
|
//---------------------------------------------------------------------
|
|
//
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirect3DDevice7::WriteStateSetToDevice"
|
|
|
|
void CDirect3DDevice7::WriteStateSetToDevice(D3DSTATEBLOCKTYPE sbt)
|
|
{
|
|
DWORD dwDeviceHandle;
|
|
LPVOID pBuffer;
|
|
DWORD dwBufferSize;
|
|
|
|
m_pStateSets->GetDeviceBufferInfo(&dwDeviceHandle, &pBuffer, &dwBufferSize);
|
|
|
|
// If device buffer is empty we do not create the set state macro in the device
|
|
if (dwBufferSize == 0)
|
|
return;
|
|
|
|
DWORD dwByteCount = dwBufferSize + (sizeof(D3DHAL_DP2STATESET) + sizeof(D3DHAL_DP2COMMAND)) * 2;
|
|
|
|
// Check to see if there is space to add a new command for space
|
|
if (dwByteCount + dwDP2CommandLength > dwDP2CommandBufSize)
|
|
{
|
|
// Request the driver to grow the command buffer upon flush
|
|
dp2data.dwReqCommandBufSize = dwByteCount;
|
|
dp2data.dwFlags |= D3DHALDP2_REQCOMMANDBUFSIZE;
|
|
HRESULT ret = FlushStates();
|
|
dp2data.dwFlags &= ~D3DHALDP2_REQCOMMANDBUFSIZE;
|
|
if (ret != D3D_OK)
|
|
throw ret;
|
|
// Check if the driver did give us what we need or do it ourselves
|
|
ret = GrowCommandBuffer(this->lpDirect3DI, dwByteCount);
|
|
if (ret != D3D_OK)
|
|
{
|
|
D3D_ERR("Could not grow Command Buffer");
|
|
throw ret;
|
|
}
|
|
}
|
|
|
|
lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)((LPBYTE)lpvDP2Commands +
|
|
dwDP2CommandLength + dp2data.dwCommandOffset);
|
|
lpDP2CurrCommand->bCommand = D3DDP2OP_STATESET;
|
|
lpDP2CurrCommand->bReserved = 0;
|
|
lpDP2CurrCommand->wStateCount = 1;
|
|
LPD3DHAL_DP2STATESET pData = (LPD3DHAL_DP2STATESET)(lpDP2CurrCommand + 1);
|
|
pData->dwOperation = D3DHAL_STATESETBEGIN;
|
|
pData->dwParam = dwDeviceHandle;
|
|
pData->sbType = sbt;
|
|
D3D_INFO(6, "Write Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
|
|
|
|
// Copy the entire state macro to the DP2 buffer
|
|
memcpy(pData + 1, pBuffer, dwBufferSize);
|
|
|
|
lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)((LPBYTE)(pData + 1) + dwBufferSize);
|
|
lpDP2CurrCommand->bCommand = D3DDP2OP_STATESET;
|
|
lpDP2CurrCommand->bReserved = 0;
|
|
lpDP2CurrCommand->wStateCount = 1;
|
|
pData = (LPD3DHAL_DP2STATESET)(lpDP2CurrCommand + 1);
|
|
pData->dwOperation = D3DHAL_STATESETEND;
|
|
pData->dwParam = dwDeviceHandle;
|
|
pData->sbType = sbt;
|
|
D3D_INFO(6, "Write Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
|
|
|
|
dwDP2CommandLength += dwByteCount;
|
|
|
|
HRESULT ret = FlushStates();
|
|
if (ret != D3D_OK)
|
|
{
|
|
D3D_ERR("Error trying to render batched commands in WriteStateSetToDevice");
|
|
throw ret;
|
|
}
|
|
else
|
|
{
|
|
if(this->dwFEFlags & D3DFE_LOSTSURFACES)
|
|
{
|
|
D3D_ERR("State blocks lost in WriteStateSetToDevice");
|
|
throw DDERR_SURFACELOST;
|
|
}
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------
|
|
//
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirect3DDevice7::TexBltI"
|
|
|
|
HRESULT CDirect3DDevice7::TexBltI(LPDDRAWI_DDRAWSURFACE_LCL lpDst,
|
|
LPDDRAWI_DDRAWSURFACE_LCL lpSrc,
|
|
LPPOINT p, RECTL *r, DWORD dwFlags)
|
|
{
|
|
HRESULT ret = D3D_OK;
|
|
#ifdef WINNT
|
|
// WINNT allows delay create of Kernel object
|
|
// if such a create fails, we can't pass handle to driver
|
|
if(dwFEFlags & D3DFE_REALHAL)
|
|
{
|
|
if (!lpSrc->hDDSurface && !CompleteCreateSysmemSurface(lpSrc))
|
|
{
|
|
return DDERR_GENERIC;
|
|
}
|
|
if (lpDst && !lpDst->hDDSurface && !CompleteCreateSysmemSurface(lpDst))
|
|
{
|
|
return DDERR_GENERIC;
|
|
}
|
|
}
|
|
#endif
|
|
// If the driver supports the GetSysmemBltStatus call, then the driver can
|
|
// do the Blt asynchronously. In this case, set the HARDWAREOP_STARTED
|
|
// flags so that Locks and Blts to the surface(s) in concern spin until
|
|
// the async Blt is finished.
|
|
if((lpSrc->lpSurfMore->lpDD_lcl->lpDDCB->HALDDMiscellaneous.GetSysmemBltStatus != NULL)
|
|
&& (lpSrc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY))
|
|
{
|
|
lpSrc->lpGbl->dwGlobalFlags |= DDRAWISURFGBL_HARDWAREOPSOURCE;
|
|
}
|
|
if (bDP2CurrCmdOP == D3DDP2OP_TEXBLT)
|
|
{ // Last instruction is a tex blt, append this one to it
|
|
if (dwDP2CommandLength + sizeof(D3DHAL_DP2TEXBLT) <= dwDP2CommandBufSize)
|
|
{
|
|
LPD3DHAL_DP2TEXBLT lpTexBlt = (LPD3DHAL_DP2TEXBLT)((LPBYTE)lpvDP2Commands +
|
|
dwDP2CommandLength + dp2data.dwCommandOffset);
|
|
lpDP2CurrCommand->wStateCount = ++wDP2CurrCmdCnt;
|
|
lpTexBlt->dwDDDestSurface = lpDst == NULL ? 0 : lpDst->lpSurfMore->dwSurfaceHandle;
|
|
lpTexBlt->dwDDSrcSurface = lpSrc->lpSurfMore->dwSurfaceHandle;
|
|
lpTexBlt->pDest = *p;
|
|
lpTexBlt->rSrc = *r;
|
|
lpTexBlt->dwFlags = dwFlags;
|
|
dwDP2CommandLength += sizeof(D3DHAL_DP2TEXBLT);
|
|
D3D_INFO(6, "Modify Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
|
|
return ret;
|
|
}
|
|
}
|
|
// Check for space
|
|
if (dwDP2CommandLength + sizeof(D3DHAL_DP2COMMAND) +
|
|
sizeof(D3DHAL_DP2TEXBLT) > dwDP2CommandBufSize)
|
|
{
|
|
ret = FlushStates();
|
|
if (ret != D3D_OK)
|
|
{
|
|
D3D_ERR("Error trying to render batched commands in TexBltI");
|
|
return ret;
|
|
}
|
|
}
|
|
// Add new renderstate instruction
|
|
lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)((LPBYTE)lpvDP2Commands +
|
|
dwDP2CommandLength + dp2data.dwCommandOffset);
|
|
lpDP2CurrCommand->bCommand = D3DDP2OP_TEXBLT;
|
|
bDP2CurrCmdOP = D3DDP2OP_TEXBLT;
|
|
lpDP2CurrCommand->bReserved = 0;
|
|
lpDP2CurrCommand->wStateCount = 1;
|
|
wDP2CurrCmdCnt = 1;
|
|
D3D_INFO(6, "Write Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
|
|
// Add texture blt data
|
|
LPD3DHAL_DP2TEXBLT lpTexBlt = (LPD3DHAL_DP2TEXBLT)(lpDP2CurrCommand + 1);
|
|
lpTexBlt->dwDDDestSurface = lpDst == NULL ? 0 : lpDst->lpSurfMore->dwSurfaceHandle;
|
|
lpTexBlt->dwDDSrcSurface = lpSrc->lpSurfMore->dwSurfaceHandle;
|
|
lpTexBlt->pDest = *p;
|
|
lpTexBlt->rSrc = *r;
|
|
lpTexBlt->dwFlags = dwFlags;
|
|
dwDP2CommandLength += sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2TEXBLT);
|
|
return ret;
|
|
}
|
|
//---------------------------------------------------------------------
|
|
//
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirect3DDevice7::SetPriorityI"
|
|
|
|
HRESULT CDirect3DDevice7::SetPriorityI(LPDDRAWI_DDRAWSURFACE_LCL lpDst, DWORD dwPriority)
|
|
{
|
|
HRESULT ret = D3D_OK;
|
|
if (bDP2CurrCmdOP == D3DDP2OP_SETPRIORITY)
|
|
{ // Last instruction is a set priority, append this one to it
|
|
if (dwDP2CommandLength + sizeof(D3DHAL_DP2SETPRIORITY) <= dwDP2CommandBufSize)
|
|
{
|
|
LPD3DHAL_DP2SETPRIORITY lpSetPriority = (LPD3DHAL_DP2SETPRIORITY)((LPBYTE)lpvDP2Commands +
|
|
dwDP2CommandLength + dp2data.dwCommandOffset);
|
|
lpDP2CurrCommand->wStateCount = ++wDP2CurrCmdCnt;
|
|
lpSetPriority->dwDDSurface = lpDst->lpSurfMore->dwSurfaceHandle;
|
|
lpSetPriority->dwPriority = dwPriority;
|
|
dwDP2CommandLength += sizeof(D3DHAL_DP2SETPRIORITY);
|
|
D3D_INFO(6, "Modify Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
|
|
return ret;
|
|
}
|
|
}
|
|
// Check for space
|
|
if (dwDP2CommandLength + sizeof(D3DHAL_DP2COMMAND) +
|
|
sizeof(D3DHAL_DP2SETPRIORITY) > dwDP2CommandBufSize)
|
|
{
|
|
ret = FlushStates();
|
|
if (ret != D3D_OK)
|
|
{
|
|
D3D_ERR("Error trying to render batched commands in SetPriorityI");
|
|
return ret;
|
|
}
|
|
}
|
|
// Add new setpriority instruction
|
|
lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)((LPBYTE)lpvDP2Commands +
|
|
dwDP2CommandLength + dp2data.dwCommandOffset);
|
|
lpDP2CurrCommand->bCommand = D3DDP2OP_SETPRIORITY;
|
|
bDP2CurrCmdOP = D3DDP2OP_SETPRIORITY;
|
|
lpDP2CurrCommand->bReserved = 0;
|
|
lpDP2CurrCommand->wStateCount = 1;
|
|
wDP2CurrCmdCnt = 1;
|
|
D3D_INFO(6, "Write Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
|
|
// Add texture blt data
|
|
LPD3DHAL_DP2SETPRIORITY lpSetPriority = (LPD3DHAL_DP2SETPRIORITY)(lpDP2CurrCommand + 1);
|
|
lpSetPriority->dwDDSurface = lpDst->lpSurfMore->dwSurfaceHandle;
|
|
lpSetPriority->dwPriority = dwPriority;
|
|
dwDP2CommandLength += sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2SETPRIORITY);
|
|
return ret;
|
|
}
|
|
//---------------------------------------------------------------------
|
|
//
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirect3DDevice7::SetTexLODI"
|
|
|
|
HRESULT CDirect3DDevice7::SetTexLODI(LPDDRAWI_DDRAWSURFACE_LCL lpDst, DWORD dwLOD)
|
|
{
|
|
HRESULT ret = D3D_OK;
|
|
if (bDP2CurrCmdOP == D3DDP2OP_SETTEXLOD)
|
|
{ // Last instruction is a set LOD, append this one to it
|
|
if (dwDP2CommandLength + sizeof(D3DHAL_DP2SETTEXLOD) <= dwDP2CommandBufSize)
|
|
{
|
|
LPD3DHAL_DP2SETTEXLOD lpSetTexLOD = (LPD3DHAL_DP2SETTEXLOD)((LPBYTE)lpvDP2Commands +
|
|
dwDP2CommandLength + dp2data.dwCommandOffset);
|
|
lpDP2CurrCommand->wStateCount = ++wDP2CurrCmdCnt;
|
|
lpSetTexLOD->dwDDSurface = lpDst->lpSurfMore->dwSurfaceHandle;
|
|
lpSetTexLOD->dwLOD = dwLOD;
|
|
dwDP2CommandLength += sizeof(D3DHAL_DP2SETTEXLOD);
|
|
D3D_INFO(6, "Modify Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
|
|
return ret;
|
|
}
|
|
}
|
|
// Check for space
|
|
if (dwDP2CommandLength + sizeof(D3DHAL_DP2COMMAND) +
|
|
sizeof(D3DHAL_DP2SETTEXLOD) > dwDP2CommandBufSize)
|
|
{
|
|
ret = FlushStates();
|
|
if (ret != D3D_OK)
|
|
{
|
|
D3D_ERR("Error trying to render batched commands in SetTexLODI");
|
|
return ret;
|
|
}
|
|
}
|
|
// Add new set LOD instruction
|
|
lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)((LPBYTE)lpvDP2Commands +
|
|
dwDP2CommandLength + dp2data.dwCommandOffset);
|
|
lpDP2CurrCommand->bCommand = D3DDP2OP_SETTEXLOD;
|
|
bDP2CurrCmdOP = D3DDP2OP_SETTEXLOD;
|
|
lpDP2CurrCommand->bReserved = 0;
|
|
lpDP2CurrCommand->wStateCount = 1;
|
|
wDP2CurrCmdCnt = 1;
|
|
D3D_INFO(6, "Write Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
|
|
// Add texture blt data
|
|
LPD3DHAL_DP2SETTEXLOD lpSetTexLOD = (LPD3DHAL_DP2SETTEXLOD)(lpDP2CurrCommand + 1);
|
|
lpSetTexLOD->dwDDSurface = lpDst->lpSurfMore->dwSurfaceHandle;
|
|
lpSetTexLOD->dwLOD = dwLOD;
|
|
dwDP2CommandLength += sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2SETTEXLOD);
|
|
return ret;
|
|
}
|
|
//---------------------------------------------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirect3DDevice7::UpdatePalette"
|
|
//---------------------------------------------------------------------
|
|
// This function should be called from PaletteUpdateNotify
|
|
//
|
|
HRESULT CDirect3DDevice7::UpdatePalette(
|
|
DWORD dwPaletteHandle,
|
|
DWORD dwStartIndex,
|
|
DWORD dwNumberOfIndices,
|
|
LPPALETTEENTRY pFirstIndex)
|
|
{
|
|
HRESULT ret = D3D_OK;
|
|
DWORD dwSizeChange=sizeof(D3DHAL_DP2COMMAND) +
|
|
sizeof(D3DHAL_DP2UPDATEPALETTE) + dwNumberOfIndices*sizeof(PALETTEENTRY);
|
|
if (bDP2CurrCmdOP == D3DDP2OP_UPDATEPALETTE)
|
|
{ // Last instruction is a tex blt, append this one to it
|
|
}
|
|
// Check for space
|
|
if (dwDP2CommandLength + dwSizeChange > dwDP2CommandBufSize)
|
|
{
|
|
ret = FlushStates();
|
|
if (ret != D3D_OK)
|
|
{
|
|
D3D_ERR("Error trying to render batched commands in TexBltI");
|
|
return ret;
|
|
}
|
|
}
|
|
// Add new renderstate instruction
|
|
lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)((LPBYTE)lpvDP2Commands +
|
|
dwDP2CommandLength + dp2data.dwCommandOffset);
|
|
lpDP2CurrCommand->bCommand = D3DDP2OP_UPDATEPALETTE;
|
|
bDP2CurrCmdOP = D3DDP2OP_UPDATEPALETTE;
|
|
lpDP2CurrCommand->bReserved = 0;
|
|
lpDP2CurrCommand->wStateCount = 1;
|
|
wDP2CurrCmdCnt = 1;
|
|
D3D_INFO(6, "Write Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
|
|
// Add texture blt data
|
|
LPD3DHAL_DP2UPDATEPALETTE lpUpdatePal = (LPD3DHAL_DP2UPDATEPALETTE)(lpDP2CurrCommand + 1);
|
|
lpUpdatePal->dwPaletteHandle=dwPaletteHandle;
|
|
lpUpdatePal->wStartIndex=(WORD)dwStartIndex;
|
|
lpUpdatePal->wNumEntries=(WORD)dwNumberOfIndices;
|
|
memcpy((LPVOID)(lpUpdatePal+1),(LPVOID)pFirstIndex,
|
|
dwNumberOfIndices*sizeof(PALETTEENTRY));
|
|
dwDP2CommandLength += dwSizeChange;
|
|
return ret;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirect3DDevice7::SetPalette"
|
|
//---------------------------------------------------------------------
|
|
// This function should be called from PaletteAssociateNotify
|
|
//
|
|
HRESULT CDirect3DDevice7::SetPalette(DWORD dwPaletteHandle,
|
|
DWORD dwPaletteFlags,
|
|
DWORD dwSurfaceHandle )
|
|
{
|
|
HRESULT ret = D3D_OK;
|
|
DWORD dwSizeChange;
|
|
if (bDP2CurrCmdOP == D3DDP2OP_SETPALETTE)
|
|
{ // Last instruction is a tex blt, append this one to it
|
|
}
|
|
|
|
dwSizeChange=sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2SETPALETTE);
|
|
// Check for space
|
|
if (dwDP2CommandLength + dwSizeChange > dwDP2CommandBufSize)
|
|
{
|
|
ret = FlushStates();
|
|
if (ret != D3D_OK)
|
|
{
|
|
D3D_ERR("Error trying to render batched commands in TexBltI");
|
|
return ret;
|
|
}
|
|
}
|
|
// Add new renderstate instruction
|
|
lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)((LPBYTE)lpvDP2Commands +
|
|
dwDP2CommandLength + dp2data.dwCommandOffset);
|
|
lpDP2CurrCommand->bCommand = D3DDP2OP_SETPALETTE;
|
|
bDP2CurrCmdOP = D3DDP2OP_UPDATEPALETTE;
|
|
lpDP2CurrCommand->bReserved = 0;
|
|
lpDP2CurrCommand->wStateCount = 1;
|
|
wDP2CurrCmdCnt = 1;
|
|
D3D_INFO(6, "Write Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
|
|
LPD3DHAL_DP2SETPALETTE lpSetPal = (LPD3DHAL_DP2SETPALETTE)(lpDP2CurrCommand + 1);
|
|
lpSetPal->dwPaletteHandle=dwPaletteHandle;
|
|
lpSetPal->dwPaletteFlags=dwPaletteFlags;
|
|
lpSetPal->dwSurfaceHandle=dwSurfaceHandle;
|
|
dwDP2CommandLength += dwSizeChange;
|
|
return ret;
|
|
}
|
|
//---------------------------------------------------------------------
|
|
//
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirect3DDevice7::UpdateTextures"
|
|
|
|
HRESULT CDirect3DDevice7::UpdateTextures()
|
|
{
|
|
HRESULT result = D3D_OK;
|
|
DWORD dwSavedFlags = this->dwFlags;
|
|
this->dwFlags |= D3DPV_WITHINPRIMITIVE;
|
|
for (DWORD dwStage = 0; dwStage < this->dwMaxTextureBlendStages; dwStage++)
|
|
{
|
|
D3DTEXTUREHANDLE dwDDIHandle;
|
|
LPDIRECT3DTEXTUREI lpTexI = this->lpD3DMappedTexI[dwStage];
|
|
if(lpTexI)
|
|
{
|
|
if (lpTexI->InVidmem())
|
|
{
|
|
if (lpTexI->bDirty)
|
|
{
|
|
|
|
CLockD3DST lockObject(this, DPF_MODNAME, REMIND("")); // we access DDraw gbl in CopySurface
|
|
// 0xFFFFFFFF is equivalent to ALL_FACES, but in addition indicates to CopySurface
|
|
// that this is a sysmem -> vidmem transfer.
|
|
result = CopySurface(lpTexI->lpDDS,NULL,lpTexI->lpDDSSys,NULL,0xFFFFFFFF);
|
|
if (DD_OK != result)
|
|
{
|
|
D3D_ERR("Error copying surface while updating textures");
|
|
goto l_exit;
|
|
}
|
|
else
|
|
{
|
|
lpTexI->bDirty=FALSE;
|
|
D3D_INFO(4,"UpdateTextures: Dirty texture updated");
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(lpTexI->D3DManaged())
|
|
{
|
|
// Not in vidmem, so we need to call GetTextureDDIHandle
|
|
m_dwStageDirty |= (1 << dwStage);
|
|
}
|
|
}
|
|
if (m_dwStageDirty & (1 << dwStage))
|
|
{
|
|
result = GetTextureDDIHandle(lpTexI, &dwDDIHandle);
|
|
if (result != D3D_OK)
|
|
{
|
|
D3D_ERR("Failed to get texture handle");
|
|
goto l_exit;
|
|
}
|
|
BatchTexture(((LPDDRAWI_DDRAWSURFACE_INT)lpTexI->lpDDS)->lpLcl);
|
|
m_dwStageDirty &= ~(1 << dwStage); // reset stage dirty
|
|
}
|
|
else
|
|
{
|
|
continue; // Ok, then nothing needs to be done further
|
|
}
|
|
}
|
|
else if (m_dwStageDirty & (1 << dwStage))
|
|
{
|
|
dwDDIHandle = 0; //tell driver to disable this texture
|
|
m_dwStageDirty &= ~(1 << dwStage); // reset stage dirty
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
result = SetTSSI(dwStage, (D3DTEXTURESTAGESTATETYPE)D3DTSS_TEXTUREMAP, dwDDIHandle);
|
|
if(result != D3D_OK)
|
|
{
|
|
D3D_ERR("Failed to batch set texture instruction");
|
|
goto l_exit;
|
|
}
|
|
// Update runtime copy of state.
|
|
this->tsstates[dwStage][D3DTSS_TEXTUREMAP] = dwDDIHandle;
|
|
}
|
|
l_exit:
|
|
this->dwFlags = dwSavedFlags;
|
|
return result;
|
|
}
|
|
//---------------------------------------------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirect3DDevice7::GetTextureDDIHandle"
|
|
|
|
HRESULT CDirect3DDevice7::GetTextureDDIHandle(LPDIRECT3DTEXTUREI lpTexI, D3DTEXTUREHANDLE *phTex)
|
|
{
|
|
if(lpTexI->D3DManaged())
|
|
{
|
|
if(!lpTexI->InVidmem())
|
|
{
|
|
HRESULT ret = lpDirect3DI->lpTextureManager->allocNode(lpTexI, this);
|
|
if (D3D_OK != ret)
|
|
{
|
|
D3D_ERR("Failed to create video memory surface");
|
|
return ret;
|
|
}
|
|
}
|
|
lpDirect3DI->lpTextureManager->TimeStamp(lpTexI);
|
|
}
|
|
*phTex = lpTexI->m_hTex;
|
|
return D3D_OK;
|
|
}
|
|
|
|
void CDirect3DDevice7::SetRenderTargetI(LPDIRECTDRAWSURFACE pRenderTarget, LPDIRECTDRAWSURFACE pZBuffer)
|
|
{
|
|
LPD3DHAL_DP2SETRENDERTARGET pData;
|
|
pData = (LPD3DHAL_DP2SETRENDERTARGET)GetHalBufferPointer(D3DDP2OP_SETRENDERTARGET, sizeof(*pData));
|
|
pData->hRenderTarget = ((LPDDRAWI_DDRAWSURFACE_INT)pRenderTarget)->lpLcl->lpSurfMore->dwSurfaceHandle;
|
|
if (pZBuffer)
|
|
pData->hZBuffer = ((LPDDRAWI_DDRAWSURFACE_INT)pZBuffer)->lpLcl->lpSurfMore->dwSurfaceHandle;
|
|
else
|
|
pData->hZBuffer = 0;
|
|
|
|
// Flush before switching RenderTarget..
|
|
HRESULT ret = FlushStates();
|
|
if (ret != D3D_OK)
|
|
{
|
|
D3D_ERR("Error trying to FlushStates in SetRenderTarget");
|
|
throw ret;
|
|
}
|
|
|
|
}
|
|
void CDirect3DDevice7::SetRenderTargetINoFlush(LPDIRECTDRAWSURFACE pRenderTarget, LPDIRECTDRAWSURFACE pZBuffer)
|
|
{
|
|
LPD3DHAL_DP2SETRENDERTARGET pData;
|
|
pData = (LPD3DHAL_DP2SETRENDERTARGET)GetHalBufferPointer(D3DDP2OP_SETRENDERTARGET, sizeof(*pData));
|
|
pData->hRenderTarget = ((LPDDRAWI_DDRAWSURFACE_INT)pRenderTarget)->lpLcl->lpSurfMore->dwSurfaceHandle;
|
|
if (pZBuffer)
|
|
pData->hZBuffer = ((LPDDRAWI_DDRAWSURFACE_INT)pZBuffer)->lpLcl->lpSurfMore->dwSurfaceHandle;
|
|
else
|
|
pData->hZBuffer = 0;
|
|
}
|
|
//---------------------------------------------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirect3DDevice7::CanDoTexBlt"
|
|
|
|
bool CDirect3DDevice7::CanDoTexBlt(LPDDRAWI_DDRAWSURFACE_LCL lpDDSSrcSubFace_lcl,
|
|
LPDDRAWI_DDRAWSURFACE_LCL lpDDSDstSubFace_lcl)
|
|
{
|
|
if(dwFEFlags & D3DFE_REALHAL)
|
|
{
|
|
DWORD &srccaps = lpDDSSrcSubFace_lcl->ddsCaps.dwCaps;
|
|
DWORD &dstcaps = lpDDSDstSubFace_lcl->ddsCaps.dwCaps;
|
|
DDCORECAPS &ddcaps = ((LPDDRAWI_DIRECTDRAW_INT)(lpDirect3DI->lpDD7))->lpLcl->lpGbl->ddCaps;
|
|
if(srccaps & DDSCAPS_VIDEOPORT)
|
|
{
|
|
return false;
|
|
}
|
|
DDPIXELFORMAT &srcpf = PixelFormat(lpDDSSrcSubFace_lcl);
|
|
DDPIXELFORMAT &dstpf = PixelFormat(lpDDSDstSubFace_lcl);
|
|
if(!MatchDDPIXELFORMAT(&srcpf, &dstpf))
|
|
{
|
|
return false;
|
|
}
|
|
else if((srcpf.dwFlags & DDPF_FOURCC) && srcpf.dwFourCC == dstpf.dwFourCC &&
|
|
!(ddcaps.dwCaps2 & DDCAPS2_COPYFOURCC))
|
|
{
|
|
return false;
|
|
}
|
|
if(ddcaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEMCAPS)
|
|
{
|
|
if(srccaps & DDSCAPS_SYSTEMMEMORY)
|
|
{
|
|
if((dstcaps & DDSCAPS_NONLOCALVIDMEM) && (this->d3dDevDesc.dwDevCaps & D3DDEVCAPS_CANBLTSYSTONONLOCAL))
|
|
{
|
|
return true;
|
|
}
|
|
else if((dstcaps & DDSCAPS_LOCALVIDMEM) && (ddcaps.dwSVBCaps & DDCAPS_BLT))
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else if(srccaps & DDSCAPS_NONLOCALVIDMEM)
|
|
{
|
|
LPDDNONLOCALVIDMEMCAPS &lpnlvcaps = ((LPDDRAWI_DIRECTDRAW_INT)lpDirect3DI->lpDD7)->lpLcl->lpGbl->lpddNLVCaps;
|
|
DDASSERT(lpnlvcaps);
|
|
if((dstcaps & DDSCAPS_LOCALVIDMEM) && (lpnlvcaps->dwNLVBCaps & DDCAPS_BLT))
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else if(srccaps & DDSCAPS_LOCALVIDMEM)
|
|
{
|
|
if((dstcaps & DDSCAPS_LOCALVIDMEM) && (ddcaps.dwCaps & DDCAPS_BLT))
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(srccaps & DDSCAPS_SYSTEMMEMORY)
|
|
{
|
|
if((dstcaps & DDSCAPS_VIDEOMEMORY) && (ddcaps.dwSVBCaps & DDCAPS_BLT))
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else if(srccaps & DDSCAPS_VIDEOMEMORY)
|
|
{
|
|
if((dstcaps & DDSCAPS_VIDEOMEMORY) && (ddcaps.dwCaps & DDCAPS_BLT))
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirect3DDevice7::ClearI"
|
|
|
|
void CDirect3DDevice7::ClearI(DWORD dwFlags, DWORD clrCount, D3DCOLOR dwColor, D3DVALUE dvZ, DWORD dwStencil)
|
|
{
|
|
DWORD dwCommandSize = sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2CLEAR) + sizeof(RECT) * (clrCount - 1);
|
|
|
|
// Check to see if there is space to add a new command for space
|
|
if (dwCommandSize + dwDP2CommandLength > dwDP2CommandBufSize)
|
|
{
|
|
HRESULT ret = FlushStates();
|
|
if (ret != D3D_OK)
|
|
{
|
|
D3D_ERR("Error trying to render batched commands in CDirect3DDevice7::ClearI");
|
|
throw ret;
|
|
}
|
|
}
|
|
lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)((LPBYTE)lpvDP2Commands +
|
|
dwDP2CommandLength + dp2data.dwCommandOffset);
|
|
lpDP2CurrCommand->bCommand = D3DDP2OP_CLEAR;
|
|
bDP2CurrCmdOP = D3DDP2OP_CLEAR;
|
|
lpDP2CurrCommand->bReserved = 0;
|
|
wDP2CurrCmdCnt = (WORD)clrCount;
|
|
lpDP2CurrCommand->wStateCount = wDP2CurrCmdCnt;
|
|
D3D_INFO(6, "Write Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
|
|
dwDP2CommandLength += dwCommandSize;
|
|
|
|
// Write data
|
|
LPD3DHAL_DP2CLEAR pData = (LPD3DHAL_DP2CLEAR)(lpDP2CurrCommand + 1);
|
|
pData->dwFlags = dwFlags;
|
|
pData->dwFillColor = dwColor;
|
|
pData->dvFillDepth = dvZ;
|
|
pData->dwFillStencil = dwStencil;
|
|
memcpy(pData->Rects, clrRects, clrCount * sizeof(D3DRECT));
|
|
}
|
|
//---------------------------------------------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirect3DDevice7::GetInfo"
|
|
|
|
HRESULT D3DAPI CDirect3DDevice7::GetInfo(DWORD dwDevInfoID, LPVOID pDevInfoStruct, DWORD dwSize)
|
|
{
|
|
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
|
|
// Release in the destructor
|
|
if (!VALID_DIRECT3DDEVICE_PTR(this))
|
|
{
|
|
D3D_ERR( "Invalid DIRECT3DDEVICE7 pointer" );
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
if (dwSize == 0 || !VALID_D3DDEVINFOSTRUCT_PTR(pDevInfoStruct, dwSize))
|
|
{
|
|
D3D_ERR( "Invalid structure pointer or size" );
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
memset(pDevInfoStruct, 0, dwSize);
|
|
#if DBG
|
|
if (this->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INSCENE)
|
|
{
|
|
D3D_WARN( 2, "GetInfo called within a scene" );
|
|
}
|
|
if( this->pfnGetDriverState == NULL )
|
|
{
|
|
D3D_ERR( "GetDriverState not implemented by the driver" );
|
|
DDASSERT( this->pfnGetDriverState );
|
|
}
|
|
#endif
|
|
try
|
|
{
|
|
switch(dwDevInfoID)
|
|
{
|
|
#if COLLECTSTATS
|
|
case D3DDEVINFOID_TEXTUREMANAGER:
|
|
if(!(((LPDDRAWI_DIRECTDRAW_INT)(this->lpDirect3DI->lpDD7))->lpLcl->lpGbl->ddCaps.dwCaps2 & DDCAPS2_CANMANAGETEXTURE))
|
|
{
|
|
lpDirect3DI->lpTextureManager->GetStats((LPD3DDEVINFO_TEXTUREMANAGER)pDevInfoStruct);
|
|
return D3D_OK;
|
|
}
|
|
break;
|
|
#else
|
|
case D3DDEVINFOID_TEXTUREMANAGER:
|
|
D3D_WARN( 0, "Stats not collected in this build" );
|
|
return S_FALSE;
|
|
#endif
|
|
default:
|
|
if(GetInfoInternal(dwDevInfoID, pDevInfoStruct, dwSize))
|
|
return D3D_OK;
|
|
}
|
|
|
|
HRESULT hr = FlushStates();
|
|
if(hr != D3D_OK)
|
|
{
|
|
D3D_ERR("Error flushing device");
|
|
return hr;
|
|
}
|
|
}
|
|
catch(HRESULT ret)
|
|
{
|
|
memset(pDevInfoStruct, 0, dwSize);
|
|
return ret;
|
|
}
|
|
|
|
HRESULT hr;
|
|
DDHAL_GETDRIVERSTATEDATA dsd;
|
|
dsd.dwFlags = dwDevInfoID;
|
|
dsd.dwhContext = this->dwhContext;
|
|
dsd.lpdwStates = (LPDWORD)pDevInfoStruct;
|
|
dsd.dwLength = dwSize;
|
|
LOCK_HAL(hr, this);
|
|
hr = this->pfnGetDriverState(&dsd);
|
|
UNLOCK_HAL(this);
|
|
if (hr != DDHAL_DRIVER_HANDLED)
|
|
{
|
|
D3D_WARN( 1, "Device information query unsupported" );
|
|
memset(pDevInfoStruct, 0, dwSize);
|
|
return S_FALSE;
|
|
}
|
|
else if (dsd.ddRVal != DD_OK)
|
|
{
|
|
D3D_INFO(1,"Driver failed GetInfo");
|
|
memset(pDevInfoStruct, 0, dwSize);
|
|
return E_FAIL;
|
|
}
|
|
|
|
return D3D_OK;
|
|
}
|
|
//=====================================================================
|
|
//
|
|
// CDirect3DDeviceTL interface
|
|
//
|
|
//=====================================================================
|
|
CDirect3DDeviceTL::CDirect3DDeviceTL()
|
|
{
|
|
deviceType = D3DDEVTYPE_DX7TLHAL;
|
|
m_rsMax = D3D_MAXRENDERSTATES;
|
|
}
|
|
//---------------------------------------------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirect3DDeviceTL::Init"
|
|
|
|
HRESULT CDirect3DDeviceTL::Init(
|
|
REFCLSID riid, LPDIRECT3DI lpD3DI, LPDIRECTDRAWSURFACE lpDDS,
|
|
IUnknown* pUnkOuter, LPUNKNOWN* lplpD3DDevice)
|
|
{
|
|
this->dwFEFlags |= D3DFE_TLHAL;
|
|
|
|
#if 0
|
|
// Stateblocks are always emulated on DX7
|
|
DWORD value = 0;
|
|
GetD3DRegValue(REG_DWORD, "EmulateStateBlocks", &value, sizeof(DWORD));
|
|
if(value == 0)
|
|
{
|
|
// All DX7 devices should support state sets
|
|
this->dwFEFlags |= D3DFE_STATESETS;
|
|
}
|
|
#endif
|
|
|
|
HRESULT ret = CDirect3DDevice7::Init(riid, lpD3DI, lpDDS, pUnkOuter, lplpD3DDevice);
|
|
if (ret != D3D_OK)
|
|
return ret;
|
|
|
|
// Do device specific initialization here
|
|
return D3D_OK;
|
|
}
|
|
//---------------------------------------------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirect3DDeviceTL::MaterialChanged"
|
|
|
|
void CDirect3DDeviceTL::MaterialChanged()
|
|
{
|
|
// Update front-end state (for ProcessVertices calls)
|
|
DIRECT3DDEVICEI::MaterialChanged();
|
|
|
|
// Driver should not be called because it will execute the macro)
|
|
if (this->dwFEFlags & D3DFE_EXECUTESTATEMODE)
|
|
return;
|
|
|
|
LPD3DHAL_DP2SETMATERIAL pData;
|
|
pData = (LPD3DHAL_DP2SETMATERIAL)GetHalBufferPointer(D3DDP2OP_SETMATERIAL, sizeof(*pData));
|
|
*pData = this->lighting.material;
|
|
}
|
|
//---------------------------------------------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirect3DDeviceTL::SetClipPlaneI"
|
|
|
|
void CDirect3DDeviceTL::SetClipPlaneI(DWORD dwPlaneIndex, D3DVALUE* pPlaneEquation)
|
|
{
|
|
// Update front-end state (for DrawPrimitiveStrided calls)
|
|
DIRECT3DDEVICEI::SetClipPlaneI(dwPlaneIndex, pPlaneEquation);
|
|
// Driver should not be called because it will execute the macro)
|
|
if (this->dwFEFlags & D3DFE_EXECUTESTATEMODE)
|
|
return;
|
|
#if DBG
|
|
if (dwPlaneIndex >= this->transform.dwMaxUserClipPlanes)
|
|
{
|
|
D3D_WARN(1, "Device does not support that many clipping planes");
|
|
return;
|
|
}
|
|
#endif
|
|
LPD3DHAL_DP2SETCLIPPLANE pData;
|
|
pData = (LPD3DHAL_DP2SETCLIPPLANE)GetHalBufferPointer(D3DDP2OP_SETCLIPPLANE, sizeof(*pData));
|
|
pData->dwIndex = dwPlaneIndex;
|
|
pData->plane[0] = pPlaneEquation[0];
|
|
pData->plane[1] = pPlaneEquation[1];
|
|
pData->plane[2] = pPlaneEquation[2];
|
|
pData->plane[3] = pPlaneEquation[3];
|
|
}
|
|
//---------------------------------------------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirect3DDeviceTL::LightChanged"
|
|
|
|
void CDirect3DDeviceTL::LightChanged(DWORD dwLightIndex)
|
|
{
|
|
// Update front-end state (for ProcessVertices calls)
|
|
LPDIRECT3DLIGHTI pLight = &m_pLights[dwLightIndex];
|
|
BOOL bValid = pLight->Valid(); // Valid bit will be set in LightChanged
|
|
DIRECT3DDEVICEI::LightChanged(dwLightIndex);
|
|
|
|
// If this is first time we set the light data, we call HALL to create
|
|
// light. HAL could grow the internal light list at this time
|
|
if (!bValid)
|
|
{
|
|
LPD3DHAL_DP2CREATELIGHT pData;
|
|
pData = (LPD3DHAL_DP2CREATELIGHT)GetHalBufferPointer(D3DDP2OP_CREATELIGHT, sizeof(*pData));
|
|
pData->dwIndex = dwLightIndex;
|
|
pLight->m_LightI.flags |= D3DLIGHTI_VALID;
|
|
}
|
|
|
|
if (this->dwFEFlags & D3DFE_EXECUTESTATEMODE)
|
|
return;
|
|
|
|
LPD3DHAL_DP2SETLIGHT pData;
|
|
pData = (LPD3DHAL_DP2SETLIGHT)GetHalBufferPointer(D3DDP2OP_SETLIGHT,
|
|
sizeof(*pData)+sizeof(D3DLIGHT7));
|
|
pData->dwIndex = dwLightIndex;
|
|
pData->dwDataType = D3DHAL_SETLIGHT_DATA;
|
|
*(D3DLIGHT7 *)((LPBYTE)pData + sizeof(D3DHAL_DP2SETLIGHT)) =
|
|
pLight->m_Light;
|
|
}
|
|
//---------------------------------------------------------------------
|
|
// Nothing to do here, because render state is used to enable/disable
|
|
// lights
|
|
//
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirect3DDeviceTL::LightEnableI"
|
|
|
|
void CDirect3DDeviceTL::LightEnableI(DWORD dwLightIndex, BOOL bEnable)
|
|
{
|
|
DIRECT3DDEVICEI::LightEnableI(dwLightIndex, bEnable);
|
|
if (!(this->dwFEFlags & D3DFE_EXECUTESTATEMODE))
|
|
{
|
|
LPD3DHAL_DP2SETLIGHT pData;
|
|
pData = (LPD3DHAL_DP2SETLIGHT)GetHalBufferPointer(D3DDP2OP_SETLIGHT, sizeof(*pData));
|
|
pData->dwIndex = dwLightIndex;
|
|
if (bEnable)
|
|
pData->dwDataType = D3DHAL_SETLIGHT_ENABLE;
|
|
else
|
|
pData->dwDataType = D3DHAL_SETLIGHT_DISABLE;
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirect3DDeviceTL::SetTransformI"
|
|
|
|
void CDirect3DDeviceTL::SetTransformI(D3DTRANSFORMSTATETYPE type,
|
|
LPD3DMATRIX pMat)
|
|
{
|
|
DDASSERT(pMat != NULL);
|
|
DIRECT3DDEVICEI::SetTransformI(type, pMat);
|
|
if (!(this->dwFEFlags & D3DFE_EXECUTESTATEMODE))
|
|
{
|
|
LPD3DHAL_DP2SETTRANSFORM pData;
|
|
pData = (LPD3DHAL_DP2SETTRANSFORM)GetHalBufferPointer(D3DDP2OP_SETTRANSFORM, sizeof(*pData));
|
|
pData->xfrmType = type;
|
|
pData->matrix = *pMat;
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------
|
|
// ProcessPrimitive processes indexed and non-indexed primitives
|
|
// as defined by "op"
|
|
// It is assumed that only untransformed vertices are passed to this function
|
|
//
|
|
// op = __PROCPRIMOP_NONINDEXEDPRIM by default
|
|
//
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirect3DDeviceTL::ProcessPrimitive"
|
|
|
|
HRESULT CDirect3DDeviceTL::ProcessPrimitive(__PROCPRIMOP op)
|
|
{
|
|
HRESULT ret;
|
|
|
|
#if DBG
|
|
// Do some validation
|
|
if (!FVF_TRANSFORMED(this->dwVIDIn))
|
|
{
|
|
if (this->rstates[D3DRENDERSTATE_VERTEXBLEND])
|
|
{
|
|
if(this->rstates[D3DRENDERSTATE_VERTEXBLEND] + 1 > this->d3dDevDesc.wMaxVertexBlendMatrices)
|
|
{
|
|
D3D_WARN(1, "Device does not support that many blend weights");
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
this->dwVIDOut = this->dwVIDIn;
|
|
if (this->dwDeviceFlags & D3DDEV_STRIDE)
|
|
{
|
|
DWORD dwTexCoordSizeDummy[8];
|
|
DWORD dwFVF = this->dwVIDIn;
|
|
DWORD dwPositionSize = GetPositionSizeFVF(dwFVF);
|
|
DWORD dwVertexSize = GetVertexSizeFVF(dwFVF) +
|
|
ComputeTextureCoordSize(dwFVF, dwTexCoordSizeDummy);
|
|
this->dwOutputSize = dwVertexSize;
|
|
this->dwVertexPoolSize = this->dwNumVertices * dwVertexSize;
|
|
if (this->TLVbuf_Grow(this->dwVertexPoolSize, true) != D3D_OK)
|
|
{
|
|
D3D_ERR( "Could not grow TL vertex buffer" );
|
|
return DDERR_OUTOFMEMORY;
|
|
}
|
|
ret = this->StartPrimVB(this->TLVbuf_GetVBI(), 0);
|
|
if (ret != D3D_OK)
|
|
return ret;
|
|
D3DVALUE *p = (D3DVALUE*)this->TLVbuf_GetAddress();
|
|
for (DWORD n = this->dwNumVertices; n; n--)
|
|
{
|
|
// XYZ and wheights
|
|
memcpy(p, this->position.lpvData, dwPositionSize);
|
|
p = (D3DVALUE*)((BYTE*)p + dwPositionSize);
|
|
this->position.lpvData = (char*)this->position.lpvData + this->position.dwStride;
|
|
if (dwFVF & D3DFVF_NORMAL)
|
|
{
|
|
*p++ = ((D3DVALUE*)this->normal.lpvData)[0];
|
|
*p++ = ((D3DVALUE*)this->normal.lpvData)[1];
|
|
*p++ = ((D3DVALUE*)this->normal.lpvData)[2];
|
|
this->normal.lpvData = (char*)this->normal.lpvData + this->normal.dwStride;
|
|
}
|
|
if (dwFVF & D3DFVF_RESERVED1)
|
|
{
|
|
*p++ = 0;
|
|
}
|
|
if (dwFVF & D3DFVF_DIFFUSE)
|
|
{
|
|
*p++ = *(D3DVALUE*)this->diffuse.lpvData;
|
|
this->diffuse.lpvData = (char*)this->diffuse.lpvData + this->diffuse.dwStride;
|
|
}
|
|
if (dwFVF & D3DFVF_SPECULAR)
|
|
{
|
|
*p++ = *(D3DVALUE*)this->specular.lpvData;
|
|
this->specular.lpvData = (char*)this->specular.lpvData + this->specular.dwStride;
|
|
}
|
|
for (DWORD i=0; i < this->nTexCoord; i++)
|
|
{
|
|
DWORD dwSize = dwTexCoordSizeDummy[i];
|
|
memcpy(p, this->textures[i].lpvData, dwSize);
|
|
this->textures[i].lpvData = (char*)this->textures[i].lpvData + this->textures[i].dwStride;
|
|
p = (D3DVALUE*)((char*)p + dwSize);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Pass vertices directly from the user memory
|
|
this->dwOutputSize = this->position.dwStride;
|
|
this->lpvOut = this->position.lpvData;
|
|
this->dwVertexPoolSize = this->dwNumVertices * this->dwOutputSize;
|
|
|
|
ret = this->StartPrimUserMem(this->position.lpvData);
|
|
if (ret != D3D_OK)
|
|
return ret;
|
|
}
|
|
|
|
if (op == __PROCPRIMOP_INDEXEDPRIM)
|
|
{
|
|
ret = this->DrawIndexPrim();
|
|
}
|
|
else
|
|
{ // Non indexed primitive
|
|
ret = this->DrawPrim();
|
|
}
|
|
if (ret != D3D_OK)
|
|
return ret;
|
|
return this->EndPrim();
|
|
}
|
|
//---------------------------------------------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirect3DDeviceTL::UpdateDrvViewInfo"
|
|
|
|
void CDirect3DDeviceTL::UpdateDrvViewInfo(LPD3DVIEWPORT7 lpVwpData)
|
|
{
|
|
// Update viewport size
|
|
CDirect3DDeviceIDP2::UpdateDrvViewInfo(lpVwpData);
|
|
|
|
// Update Z range
|
|
LPD3DHAL_DP2ZRANGE pData;
|
|
pData = (LPD3DHAL_DP2ZRANGE)GetHalBufferPointer(D3DDP2OP_ZRANGE, sizeof(*pData));
|
|
pData->dvMinZ = lpVwpData->dvMinZ;
|
|
pData->dvMaxZ = lpVwpData->dvMaxZ;
|
|
}
|
|
//---------------------------------------------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirect3DDeviceTL::SetupFVFData"
|
|
|
|
HRESULT CDirect3DDeviceTL::SetupFVFData(DWORD *pdwInpVertexSize)
|
|
{
|
|
this->dwFEFlags &= ~D3DFE_FVF_DIRTY;
|
|
this->nTexCoord = FVF_TEXCOORD_NUMBER(this->dwVIDIn);
|
|
DWORD dwSize = GetVertexSizeFVF(this->dwVIDIn);
|
|
// Add size of texture coordinates
|
|
DWORD dwTextureFormats = this->dwVIDIn >> 16;
|
|
for (DWORD i=this->nTexCoord; i; i--)
|
|
{
|
|
dwSize += g_TextureSize[dwTextureFormats & 0x3];
|
|
dwTextureFormats >>= 2;
|
|
}
|
|
if (pdwInpVertexSize)
|
|
*pdwInpVertexSize = dwSize;
|
|
|
|
// In case if COLORVERTEX is TRUE, the vertexAlpha could be overriden
|
|
// by vertex alpha
|
|
this->lighting.alpha = (DWORD)this->lighting.materialAlpha;
|
|
this->lighting.alphaSpecular = (DWORD)this->lighting.materialAlphaS;
|
|
|
|
return D3D_OK;
|
|
}
|