|
|
/*==========================================================================;
* * Copyright (C) 1997 Microsoft Corporation. All Rights Reserved. * * File: dphal.c * Content: DrawPrimitive implementation for DrawPrimitive HALs * ***************************************************************************/
#include "pch.cpp"
#pragma hdrstop
#ifdef WIN95
#include "drawprim.hpp"
#include "clipfunc.h"
#include "d3dfei.h"
#define LOWVERTICESNUMBERDP 20
extern void SetDebugRenderState(DWORD value);
#define ALIGN32(x) x = ((DWORD)(x + 31)) & (~31);
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "MapFVFtoTLVertex1"
inline void MapFVFtoTLVertex1(LPDIRECT3DDEVICEI lpDevI, D3DTLVERTEX *pOut, DWORD *pIn) { // Copy position
pOut->sx = *(D3DVALUE*)pIn++; pOut->sy = *(D3DVALUE*)pIn++; pOut->sz = *(D3DVALUE*)pIn++; pOut->rhw = *(D3DVALUE*)pIn++; // Other fields: diffuse, specular, texture
if (lpDevI->dwVIDOut & D3DFVF_DIFFUSE) pOut->color = *pIn++; else { pOut->color = __DEFAULT_DIFFUSE; } if (lpDevI->dwVIDOut & D3DFVF_SPECULAR) pOut->specular = *pIn++; else { pOut->specular= __DEFAULT_SPECULAR; } if (lpDevI->nOutTexCoord) { pIn = &pIn[lpDevI->dwTextureIndexToCopy << 1]; pOut->tu = *(D3DVALUE*)&pIn[0]; pOut->tv = *(D3DVALUE*)&pIn[1]; } else { pOut->tu = 0; pOut->tv = 0; } } //---------------------------------------------------------------------
// All vertices from lpDevI->lpVout are copied to the output buffer, expanding
// to D3DTLVERTEX.
// The output buffer is lpAddress if it is not NULL, otherwise it is TLVbuf
//
#undef DPF_MODNAME
#define DPF_MODNAME "MapFVFtoTLVertex"
HRESULT CDirect3DDeviceIHW::MapFVFtoTLVertex(LPVOID lpAddress) { int i; DWORD size = this->dwNumVertices * sizeof(D3DTLVERTEX); D3DTLVERTEX *pOut; if (lpAddress) pOut = (D3DTLVERTEX*)lpAddress; else { // See if TL buffer has sufficient space
if (size > this->TLVbuf.GetSize()) { if (this->TLVbuf.Grow(this, size) != D3D_OK) { D3D_ERR( "Could not grow TL vertex buffer" ); return DDERR_OUTOFMEMORY; } } pOut = (D3DTLVERTEX*)this->TLVbuf.GetAddress(); } // Map vertices
DWORD *pIn = (DWORD*)this->lpvOut; for (i=this->dwNumVertices; i; i--) { MapFVFtoTLVertex1(this, pOut, pIn); pOut++; pIn = (DWORD*)((char*)pIn + this->dwOutputSize); } return D3D_OK; } //---------------------------------------------------------------------
// Vertices, corresponding to the primitive's indices, are converted to D3DTLVERTEX
// and copied to the TL buffer
//
#undef DPF_MODNAME
#define DPF_MODNAME "MapFVFtoTLVertexIndexed"
HRESULT CDirect3DDeviceIHW::MapFVFtoTLVertexIndexed() { DWORD size = this->dwNumVertices * sizeof(D3DTLVERTEX); D3DTLVERTEX *pOut; // See if TL buffer has sufficient space
if (size > this->TLVbuf.GetSize()) { if (this->TLVbuf.Grow(this, size) != D3D_OK) { D3D_ERR( "Could not grow TL vertex buffer" ); return DDERR_OUTOFMEMORY; } } pOut = (D3DTLVERTEX*)this->TLVbuf.GetAddress(); // Map vertices
DWORD *pIn = (DWORD*)this->lpvOut; for (DWORD i = 0; i < this->dwNumIndices; i++) { DWORD *pInpVertex = (DWORD*)((BYTE*)pIn + this->lpwIndices[i] * this->dwOutputSize); MapFVFtoTLVertex1(this, &pOut[this->lpwIndices[i]], pInpVertex); } return D3D_OK; } //---------------------------------------------------------------------
// Draws non-indexed primitives which do not require clipping
//
#undef DPF_MODNAME
#define DPF_MODNAME "DrawPrim"
#define __DRAWPRIMFUNC
#include "dpgen.h"
//---------------------------------------------------------------------
// Draws indexed primitives which do not require clipping
//
#undef DPF_MODNAME
#define DPF_MODNAME "DrawIndexedPrim"
#define __DRAWPRIMFUNC
#define __DRAWPRIMINDEX
#include "dpgen.h"
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CDirect3DDeviceIDP::Init"
HRESULT CDirect3DDeviceIDP::Init(REFCLSID riid, LPDIRECT3DI lpD3DI, LPDIRECTDRAWSURFACE lpDDS, IUnknown* pUnkOuter, LPUNKNOWN* lplpD3DDevice) { HRESULT ret; ret = CDirect3DDeviceIHW::Init(riid, lpD3DI, lpDDS, pUnkOuter, lplpD3DDevice); if (ret != D3D_OK) return ret;
return D3D_OK; } //---------------------------------------------------------------------
// ATTENTION - These two functions should be combined into one as soon
// as ContextCreate has the new private data mechanism built in.
#undef DPF_MODNAME
#define DPF_MODNAME "CDirect3DDeviceIDP::halCreateContext"
HRESULT CDirect3DDeviceIDP::halCreateContext() { HRESULT ret; ret = DIRECT3DDEVICEI::halCreateContext(); if (ret != D3D_OK) return ret;
this->lpDPPrimCounts = (LPD3DHAL_DRAWPRIMCOUNTS)this->lpwDPBuffer; memset( (char *)this->lpwDPBuffer, 0, sizeof(D3DHAL_DRAWPRIMCOUNTS));
this->dwDPOffset = sizeof(D3DHAL_DRAWPRIMCOUNTS); this->dwDPMaxOffset = dwD3DTriBatchSize * sizeof(D3DTRIANGLE)-sizeof(D3DTLVERTEX);
return (D3D_OK); } //---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "FlushStatesDP"
HRESULT CDirect3DDeviceIDP::FlushStates(bool bWithinPrimitive) { HRESULT dwRet=D3D_OK; if (this->dwDPOffset>sizeof(D3DHAL_DRAWPRIMCOUNTS)) { ++m_qwBatch; // So that currently bound textures get rebatched
for (DWORD dwStage = 0; dwStage < this->dwMaxTextureBlendStages; dwStage++) { LPDIRECT3DTEXTUREI lpTexI = this->lpD3DMappedTexI[dwStage]; if (NULL != lpTexI) { if(lpTexI->lpDDS != NULL) { BatchTexture(((LPDDRAWI_DDRAWSURFACE_INT)(lpTexI->lpDDS))->lpLcl); } } } if ((dwRet=CheckSurfaces()) != D3D_OK) { this->dwDPOffset = sizeof(D3DHAL_DRAWPRIMCOUNTS); this->lpDPPrimCounts = (LPD3DHAL_DRAWPRIMCOUNTS)this->lpwDPBuffer; memset( (char *)this->lpwDPBuffer,0,sizeof(D3DHAL_DRAWPRIMCOUNTS)); //Clear header also
if (dwRet == DDERR_SURFACELOST) { this->dwFEFlags |= D3DFE_LOSTSURFACES; return D3D_OK; } return dwRet; }
D3DHAL_DRAWPRIMITIVESDATA dpData; DWORD dwDPOffset; if (this->lpDPPrimCounts->wNumVertices) //this->lpDPPrimCounts->wNumVertices==0 means the end
{ //force it if not
memset(((LPBYTE)this->lpwDPBuffer+this->dwDPOffset),0,sizeof(D3DHAL_DRAWPRIMCOUNTS)); } dpData.dwhContext = this->dwhContext; dpData.dwFlags = 0; dpData.lpvData = this->lpwDPBuffer; if (FVF_DRIVERSUPPORTED(this)) dpData.dwFVFControl = this->dwCurrentBatchVID; else { if (this->dwDebugFlags & D3DDEBUG_DISABLEFVF) dpData.dwFVFControl = D3DFVF_TLVERTEX; else dpData.dwFVFControl = 0; //always zero for non-FVF drivers
} dpData.ddrval = 0; dwDPOffset=this->dwDPOffset; //save it in case Flush returns prematurely
#if 0
if (D3DRENDERSTATE_TEXTUREHANDLE==*((DWORD*)this->lpwDPBuffer+2)) DPF(0,"Flushing dwDPOffset=%08lx ddihandle=%08lx",dwDPOffset,*((DWORD*)this->lpwDPBuffer+3)); #endif //0
//we clear this to break re-entering as SW rasterizer needs to lock DDRAWSURFACE
this->dwDPOffset = sizeof(D3DHAL_DRAWPRIMCOUNTS);
// Spin waiting on the driver if wait requested
#if _D3D_FORCEDOUBLE
CD3DForceFPUDouble ForceFPUDouble(this); #endif //_D3D_FORCEDOUBLE
do { #ifndef WIN95
if((dwRet = CheckContextSurface(this)) != D3D_OK) { this->dwDPOffset = dwDPOffset; return (dwRet); } #endif //WIN95
CALL_HAL2ONLY(dwRet, this, DrawPrimitives, &dpData); if (dwRet != DDHAL_DRIVER_HANDLED) { D3D_ERR ( "Driver call for DrawOnePrimitive failed" ); // Need sensible return value in this case,
// currently we return whatever the driver stuck in here.
} } while (dpData.ddrval == DDERR_WASSTILLDRAWING); this->lpDPPrimCounts = (LPD3DHAL_DRAWPRIMCOUNTS)this->lpwDPBuffer; memset( (char *)this->lpwDPBuffer,0,sizeof(D3DHAL_DRAWPRIMCOUNTS)); //Clear header also
dwRet= dpData.ddrval; this->dwCurrentBatchVID = this->dwVIDOut; } return dwRet; }
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CDirect3DDeviceIDP::SetRenderStateI"
HRESULT CDirect3DDeviceIDP::SetRenderStateI(D3DRENDERSTATETYPE dwStateType, DWORD value) { LPD3DHAL_DRAWPRIMCOUNTS lpPC; LPDWORD lpStateChange; HRESULT ret; // map WRAP0 into legacy renderstate
if (D3DRENDERSTATE_WRAP0 == dwStateType) { BOOLEAN ustate = (value & D3DWRAP_U) ? TRUE : FALSE; BOOLEAN vstate = (value & D3DWRAP_V) ? TRUE : FALSE; SetRenderStateI(D3DRENDERSTATE_WRAPU, ustate); SetRenderStateI(D3DRENDERSTATE_WRAPV, vstate); return D3D_OK; } if (dwStateType > D3DRENDERSTATE_STIPPLEPATTERN31) { D3D_WARN(4,"Trying to send invalid state %d to legacy driver",dwStateType); return D3D_OK; } if (dwStateType > D3DRENDERSTATE_FLUSHBATCH && dwStateType < D3DRENDERSTATE_STIPPLEPATTERN00) { D3D_WARN(4,"Trying to send invalid state %d to legacy driver",dwStateType); return D3D_OK; }
lpPC = this->lpDPPrimCounts; if (lpPC->wNumVertices) //Do we already have Vertices filled in for this count ?
{ //Yes, then Increment count
lpPC=this->lpDPPrimCounts=(LPD3DHAL_DRAWPRIMCOUNTS)((LPBYTE)this->lpwDPBuffer+this->dwDPOffset); memset( (char *)lpPC,0,sizeof(D3DHAL_DRAWPRIMCOUNTS)); this->dwDPOffset += sizeof(D3DHAL_DRAWPRIMCOUNTS); } if (this->dwDPOffset + 2*sizeof(DWORD) > this->dwDPMaxOffset ) { CLockD3DST lockObject(this, DPF_MODNAME, REMIND("")); // Takes D3D lock (ST only).
ret = FlushStates(); if (ret != D3D_OK) { D3D_ERR("Error trying to render batched commands in SetRenderStateI"); return ret; } } lpStateChange=(LPDWORD)((char *)this->lpwDPBuffer + this->dwDPOffset); *lpStateChange=dwStateType; lpStateChange ++; *lpStateChange=value; this->lpDPPrimCounts->wNumStateChanges ++; this->dwDPOffset += 2*sizeof(DWORD); #if 0
if (dwStateType == D3DRENDERSTATE_TEXTUREHANDLE && this->dwDPOffset== 0x10){ DPF(0,"SRdwDPOffset=%08lx, dwStateType=%08lx value=%08lx ddihandle=%08lx lpStateChange=%08lx lpDPPrimCounts=%08lx", this->dwDPOffset,dwStateType,value,*lpStateChange,lpStateChange,this->lpDPPrimCounts); _asm int 3 } #endif //0
return D3D_OK; }
#endif // WIN95
|