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.
 
 
 
 
 
 

2333 lines
91 KiB

/******************************Module*Header**********************************\
*
* *******************
* * D3D SAMPLE CODE *
* *******************
*
* Module Name: d3d.c
*
* Content: Main context and texture management callbacks for D3D
*
* Copyright (c) 1994-1998 3Dlabs Inc. Ltd. All rights reserved.
* Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved.
\*****************************************************************************/
#include "precomp.h"
#include "d3dhw.h"
#include "d3dcntxt.h"
#include "d3ddelta.h"
#include "d3dtxman.h"
#define ALLOC_TAG ALLOC_TAG_3D2P
BOOL D3DInitialised = FALSE;
//-----------------------------Public Routine----------------------------------
//
// DWORD D3DContextCreate
//
// The ContextCreate callback is invoked when a new Direct3D device is being
// created by a Direct3D application. The driver is required to generate a
// unique context id for this new context. Direct3D will then use this context
// id in every subsequent callback invocation for this Direct3D device.
//
// Context is the current rasterization state. For instance, if there are 3
// applications running, each will have a different state at any point in time.
// When each one is running, the hardware has to make sure that the context,
// (whether doing Gouraud shading, for example) is the same as the last time
// that application got a time slice.
//
// State is anything that the particular device needs to know per context
// i.e. what surface is being rendered to, shading, texture, texture handles,
// what physical surfaces those texture handles represent, etc. The context
// encapsulates all state for the Direct3D device - state is not shared
// between contexts. Therefore the driver needs to maintain full state
// information for each context. This state will be changed by calls to the
// RenderState callback. In the case of rasterization only hardware, the
// driver need only maintain rasterization state. As well as state, the driver
// will also want to store the lpDDS, lpDDSZ, and dwPid from the callback
// data argument.
//
// The driver should not create a context handle of zero. This is guaranteed
// to be an invalid context handle.
//
// Parameters
// pccd
// Pointer to a structure containing things including the current
// rendering surface, the current Z surface, and the DirectX object
// handle, etc.
//
// .lpDDGbl
// Points to the DirectDraw structure representing the
// DirectDraw object.
// .lpDDLcl(replaces lpDDGbl in DX7)
// Points to the DirectDraw structure representing the
// DirectDraw object.
// .lpDDS
// This is the surface that is to be used as the rendering
// target, i.e., the 3D accelerator sprays its bits at this
// surface.
// .lpDDSZ
// The surface that is to be used as the Z buffer. If this
// is NULL, no Z buffering is to be performed.
// .dwPid
// The process id of the Direct3D application that initiated
// the creation of the Direct3D device.
// .dwhContext
// The driver should place the context ID that it wants Direct3D
// to use when communicating with the driver. This should be
// unique.
// .ddrval
// Return code. DD_OK indicates success.
//
// Return Value
// Returns one of the following values:
// DDHAL_DRIVER_HANDLED
// DDHAL_DRIVER_NOTHANDLED
//
//-----------------------------------------------------------------------------
TextureCacheManager P2TextureManager;
DWORD P2TMcount = 0;
DWORD CALLBACK
D3DContextCreate(LPD3DHAL_CONTEXTCREATEDATA pccd)
{
PERMEDIA_D3DCONTEXT* pContext;
PermediaSurfaceData* pPrivateData;
DWORD dwSlotNum;
LPDDRAWI_DIRECTDRAW_GBL lpDDGbl=pccd->lpDDLcl->lpGbl;
// Remember the global data for this context.
PPDev ppdev = (PPDev)lpDDGbl->dhpdev;
PERMEDIA_DEFS(ppdev);
DBG_D3D((6,"Entering D3DContextCreate"));
// Find an empty slot in the global D3D context table
for (dwSlotNum = 1; dwSlotNum < MAX_CONTEXT_NUM; dwSlotNum++)
{
if (ContextSlots[dwSlotNum] == 0)
break;
}
// return if we have no contexts left
if (dwSlotNum == MAX_CONTEXT_NUM)
{
pccd->ddrval = D3DHAL_OUTOFCONTEXTS;
return (DDHAL_DRIVER_HANDLED);
}
// Now allocate the drivers D3D context memory. Simply a chunk of
// RAM with the relevent data in it.
pContext = (PERMEDIA_D3DCONTEXT *)
ENGALLOCMEM( FL_ZERO_MEMORY, sizeof(PERMEDIA_D3DCONTEXT), ALLOC_TAG);
if (pContext == NULL)
{
DBG_D3D((0,"ERROR: Couldn't allocate Context mem"));
pccd->ddrval = DDERR_OUTOFMEMORY;
return (DDHAL_DRIVER_HANDLED);
}
else
{
DBG_D3D((4,"Allocated Context Mem"));
memset((void *)pContext, 0, sizeof(PERMEDIA_D3DCONTEXT));
}
// Setup the drivers's D3D context
pContext->Hdr.pSelf = (UINT_PTR)pContext;
// Set up the DRIVER rendering context structure for sanity checks
pContext->Hdr.MagicNo = RC_MAGIC_NO;
// Remember the card we are running on
pContext->ppdev = ppdev;
// Set context handle in driver's D3D context
pccd->dwhContext = dwSlotNum; //out:Context handle
ContextSlots[dwSlotNum] = (UINT_PTR)pContext;
DBG_D3D((4,"Allocated Direct3D context: 0x%x",pccd->dwhContext));
// Allocate a register context
P2CtxtPtr pP2ctxt;
pP2ctxt = P2AllocateNewContext( pContext->ppdev, NULL, 0, P2CtxtWriteOnly);
if (pP2ctxt == NULL)
{
DBG_D3D((0,"ERROR: Couldn't allocate Register Context"));
CleanDirect3DContext(pContext, pccd->dwhContext);
pccd->ddrval = DDERR_OUTOFMEMORY;
return (DDHAL_DRIVER_HANDLED);
}
else
{
DBG_D3D((4,"Allocated Register context: 0x%x",pP2ctxt));
// Record the register context in the window render context
pContext->hPermediaContext = pP2ctxt;
}
// No texture at present
pContext->CurrentTextureHandle = 0;
// Initialize texture management for this context
if (0 == P2TMcount)
{
if ( FAILED(TextureCacheManagerInitialize(&P2TextureManager)) )
{
DBG_D3D((0,"ERROR: Couldn't initialize TextureCacheManager"));
CleanDirect3DContext(pContext, pccd->dwhContext);
pccd->ddrval = DDERR_OUTOFMEMORY;
return (DDHAL_DRIVER_HANDLED);
}
}
P2TMcount++;
pContext->pTextureManager = &P2TextureManager;
// Remember the local DD object and get the
// correct array of surfaces for this context
pContext->pDDLcl = pccd->lpDDLcl;
pContext->pHandleList = GetSurfaceHandleList(pccd->lpDDLcl);
if (pContext->pHandleList == NULL)
{
DBG_D3D((0,"ERROR: Couldn't get a surface handle for lpDDLcl"));
CleanDirect3DContext(pContext, pccd->dwhContext);
pccd->ddrval = DDERR_OUTOFMEMORY;
return (DDHAL_DRIVER_HANDLED);
}
DBG_D3D((4,"Getting pHandleList=%08lx for pDDLcl %08lx",
pContext->pHandleList,pccd->dwPID));
pContext->RenderSurfaceHandle = DDS_LCL(pccd->lpDDS)->lpSurfMore->dwSurfaceHandle;
if (NULL != pccd->lpDDSZ)
pContext->ZBufferHandle = DDS_LCL(pccd->lpDDSZ)->lpSurfMore->dwSurfaceHandle;
else
pContext->ZBufferHandle = 0;
// Now write the default setup to the chip.
if ( FAILED(InitPermediaContext(pContext)) )
{
DBG_D3D((0,"ERROR: D3DContextCreate receives bad parameters "));
CleanDirect3DContext(pContext, pccd->dwhContext);
pccd->ddrval = D3DHAL_CONTEXT_BAD;
return (DDHAL_DRIVER_HANDLED);
}
// ---------------- Setup default states in driver ------------------------
// On context creation, no render states are overridden
STATESET_INIT(pContext->overrides);
#if D3D_STATEBLOCKS
// Default state block recording mode = no recording
pContext->bStateRecMode = FALSE;
pContext->pCurrSS = NULL;
pContext->pIndexTableSS = NULL;
pContext->dwMaxSSIndex = 0;
#endif //D3D_STATEBLOCKS
pContext->Hdr.Flags = CTXT_HAS_GOURAUD_ENABLED ;
pContext->CullMode = D3DCULL_CCW;
// Set the last alpha value to 16 to force a new
// send of the flat stipple patterns.
pContext->LastAlpha = 16;
pContext->bKeptStipple = FALSE; // By default, stippling is off
pContext->bCanChromaKey = FALSE; // Turn Chroma keying off by default
pContext->LowerChromaColor = 0x0; // These are the default chromakey values
pContext->UpperChromaColor = 0x0;
pContext->FakeBlendNum = 0; // No need to emulate any blend mode
//@@BEGIN_DDKSPLIT
#if D3D_POINTSPRITES
pContext->bPointSpriteEnabled = FALSE; // Point sprite defaults
pContext->fPointSize = 1.0f;
#endif // D3D_POINTSPRITES
//@@END_DDKSPLIT
// Initialise the RenderCommand. States will add to this
pContext->RenderCommand = 0;
RENDER_SUB_PIXEL_CORRECTION_ENABLE(pContext->RenderCommand);
// Setup TSS defaults for stage 0
pContext->TssStates[D3DTSS_TEXTUREMAP] = 0;
pContext->TssStates[D3DTSS_COLOROP] = D3DTOP_MODULATE;
pContext->TssStates[D3DTSS_ALPHAOP] = D3DTOP_SELECTARG1;
pContext->TssStates[D3DTSS_COLORARG1] = D3DTA_TEXTURE;
pContext->TssStates[D3DTSS_COLORARG2] = D3DTA_CURRENT;
pContext->TssStates[D3DTSS_ALPHAARG1] = D3DTA_TEXTURE;
pContext->TssStates[D3DTSS_ALPHAARG2] = D3DTA_CURRENT;
pContext->TssStates[D3DTSS_TEXCOORDINDEX] = 0;
pContext->TssStates[D3DTSS_ADDRESS] = D3DTADDRESS_WRAP;
pContext->TssStates[D3DTSS_ADDRESSU] = D3DTADDRESS_WRAP;
pContext->TssStates[D3DTSS_ADDRESSV] = D3DTADDRESS_WRAP;
pContext->TssStates[D3DTSS_MAGFILTER] = D3DTFG_POINT;
pContext->TssStates[D3DTSS_MINFILTER] = D3DTFN_POINT;
pContext->TssStates[D3DTSS_MIPFILTER] = D3DTFP_NONE;
pContext->TssStates[D3DTSS_BUMPENVMAT00] = 0; // info we don't use
pContext->TssStates[D3DTSS_BUMPENVMAT01] = 0; // in this sample
pContext->TssStates[D3DTSS_BUMPENVMAT10] = 0;
pContext->TssStates[D3DTSS_BUMPENVMAT11] = 0;
pContext->TssStates[D3DTSS_BUMPENVLSCALE] = 0;
pContext->TssStates[D3DTSS_BUMPENVLOFFSET] = 0;
pContext->TssStates[D3DTSS_BORDERCOLOR] = 0x00000000;
pContext->TssStates[D3DTSS_MAXMIPLEVEL] = 0;
pContext->TssStates[D3DTSS_MAXANISOTROPY] = 1;
// Force a change in texture before any
// rendering takes place for this context
DIRTY_TEXTURE;
DBG_D3D((6,"Exiting D3DContextCreate"));
pccd->ddrval = DD_OK;
return (DDHAL_DRIVER_HANDLED);
} // D3DContextCreate
//-----------------------------Public Routine----------------------------------
//
// DWORD D3DContextDestroy
//
// This callback is invoked when a Direct3D Device is being destroyed. As each
// device is represented by a context ID, the driver is passed a context to
// destroy.
//
// The driver should free all resources it allocated to the context being
// deleted. For example, the driver should free any texture resources it
// associated with the context. The driver should not free the DirectDraw
// surface(s) associated with the context because these will be freed by
// DirectDraw in response to an application or Direct3D runtime request.
//
// Parameters
// pcdd
// Pointer to Context destroy information.
//
// .dwhContext
// The ID of the context to be destroyed.
// .ddrval
// Return code. DD_OK indicates success.
//
// Return Value
// Returns one of the following values:
// DDHAL_DRIVER_HANDLED
// DDHAL_DRIVER_NOTHANDLED
//
//-----------------------------------------------------------------------------
DWORD CALLBACK
D3DContextDestroy(LPD3DHAL_CONTEXTDESTROYDATA pcdd)
{
PERMEDIA_D3DCONTEXT *pContext;
// Deleting context
DBG_D3D((6,"Entering D3DContextDestroy, context = %08lx",pcdd->dwhContext));
pContext = (PERMEDIA_D3DCONTEXT *)ContextSlots[pcdd->dwhContext] ;
if ( pContext != NULL && pContext->Hdr.MagicNo == RC_MAGIC_DISABLE)
// render context has been deliberately disabled.
// set the magic number back to valid to allow the cleanup
// to proceed in the normal way.
pContext->Hdr.MagicNo = RC_MAGIC_NO ;
CHK_CONTEXT( pContext, pcdd->ddrval, "D3DContextDestroy");
DBG_D3D((4,"Freeing context resources"));
CleanDirect3DContext(pContext, pcdd->dwhContext);
pcdd->ddrval = DD_OK;
DBG_D3D((6,"Exiting D3DContextDestroy"));
return (DDHAL_DRIVER_HANDLED);
} // D3DContextDestroy
//-----------------------------------------------------------------------------
//
// void __InitD3DTextureWithDDSurfInfo
//
//-----------------------------------------------------------------------------
void
__InitD3DTextureWithDDSurfInfo(PPERMEDIA_D3DTEXTURE pTexture,
LPDDRAWI_DDRAWSURFACE_LCL lpSurf,
PPDev ppdev)
{
DBG_D3D((10,"Entering lpSurf=%08lx %08lx",lpSurf,lpSurf->lpGbl->fpVidMem));
pTexture->pTextureSurface =
(PermediaSurfaceData*)lpSurf->lpGbl->dwReserved1;
if (NULL != pTexture->pTextureSurface)
{
pTexture->pTextureSurface->dwFlags |= P2_SURFACE_NEEDUPDATE;
// need to recover this as CreateSurfaceEx may call us during TextureSwap()
pTexture->dwPaletteHandle = pTexture->pTextureSurface->dwPaletteHandle;
}
// Need to remember the sizes and the log of the sizes of the maps
pTexture->fpVidMem = lpSurf->lpGbl->fpVidMem;
pTexture->lPitch = lpSurf->lpGbl->lPitch;
pTexture->wWidth = (WORD)(lpSurf->lpGbl->wWidth);
pTexture->wHeight = (WORD)(lpSurf->lpGbl->wHeight);
pTexture->dwRGBBitCount=lpSurf->lpGbl->ddpfSurface.dwRGBBitCount;
pTexture->m_dwBytes = pTexture->wHeight * pTexture->lPitch;
// Magic number for validity check
pTexture->MagicNo = TC_MAGIC_NO;
pTexture->dwFlags = lpSurf->dwFlags;
pTexture->dwCaps = lpSurf->ddsCaps.dwCaps;
pTexture->dwCaps2= lpSurf->lpSurfMore->ddsCapsEx.dwCaps2;
if (DDRAWISURF_HASCKEYSRCBLT & pTexture->dwFlags)
{
pTexture->dwKeyLow = lpSurf->ddckCKSrcBlt.dwColorSpaceLowValue;
pTexture->dwKeyHigh = lpSurf->ddckCKSrcBlt.dwColorSpaceHighValue;
DBG_D3D((4, "ColorKey exists (%08lx %08lx) on surface %d",
pTexture->dwKeyLow,pTexture->dwKeyHigh,
lpSurf->lpSurfMore->dwSurfaceHandle));
}
if (DD_P2AGPCAPABLE(ppdev) && pTexture->dwCaps & DDSCAPS_NONLOCALVIDMEM)
{
pTexture->lSurfaceOffset = DD_AGPSURFBASEOFFSET(lpSurf->lpGbl);
}
#if D3D_MIPMAPPING
// Verify if texture has mip maps atteched
if (lpSurf->ddsCaps.dwCaps & DDSCAPS_MIPMAP)
{
LPDDRAWI_DDRAWSURFACE_LCL lpNextSurf;
int LOD;
lpNextSurf = lpSurf;
LOD = 0;
pTexture->bMipMap = TRUE;
// Calculate the number of mipmap levels (if this is a mipmap)
pTexture->iMipLevels = (DWORD)((pTexture->wWidth > pTexture->wHeight) ?
log2((int)pTexture->wWidth) :
log2((int)pTexture->wHeight)) + 1;
// Walk the chain of surfaces and find all of the mipmap levels
for (LOD = 0; LOD < pTexture->iMipLevels; LOD++)
{
DBG_D3D((4, "Loading texture LOD:%d, Ptr:0x%x",
LOD, lpNextSurf->lpGbl->fpVidMem));
// Store the offsets for each of the mipmap levels
StorePermediaLODLevel(ppdev, pTexture, lpNextSurf, LOD);
// Is there another surface in the chain?
if (lpNextSurf->lpAttachList)
{
lpNextSurf = lpNextSurf->lpAttachList->lpAttached;
if (lpNextSurf == NULL)
break;
}
else
break;
}
// This isn't really a MipMap if LOD is 0
if (LOD == 0)
{
DBG_D3D((4, "Texture was not a mipmap - only 1 level"));
pTexture->bMipMap = FALSE;
pTexture->iMipLevels = 1;
}
else
{
// Fill in the remaining levels with the smallest LOD
// (this is for applications that haven't bothered to
// pass us all of the LOD's).
if (LOD < (pTexture->iMipLevels - 1))
{
int iLastLOD = LOD;
DBG_D3D((4,"Filling in missing mipmaps!"));
for (;LOD < MAX_MIP_LEVELS; LOD++)
{
pTexture->MipLevels[LOD] = pTexture->MipLevels[iLastLOD];
}
}
}
}
else
#endif //D3D_MIPMAPPING
{
// NOT A MIPMAP, simply store away the offset of level 0
pTexture->bMipMap = FALSE;
pTexture->iMipLevels = 1;
StorePermediaLODLevel(ppdev, pTexture, lpSurf, 0);
}
// If debugging show what has just been created
DISPTEXTURE((ppdev, pTexture, &lpSurf->lpGbl->ddpfSurface));
DBG_D3D((10,"Exiting __InitD3DTextureWithDDSurfInfo"));
} // __InitD3DTextureWithDDSurfInfo
//@@BEGIN_DDKSPLIT
#if MULTITHREADED
//-----------------------------------------------------------------------------
//
// Multithread support wrappers for D3D callback functions
//
//-----------------------------------------------------------------------------
//DWORD CALLBACK MtD3DContextCreate(LPD3DHAL_CONTEXTCREATEDATA pccd);
WRAPMTDXCALLBACK(D3D, D3DContextCreate, LPD3DHAL_CONTEXTCREATEDATA, pccd,
pccd->lpDDLcl->lpGbl->dhpdev)
//DWORD CALLBACK MtD3DContextDestroy(LPD3DHAL_CONTEXTDESTROYDATA pcdd);
WRAPMTDXCALLBACK(D3D, D3DContextDestroy, LPD3DHAL_CONTEXTDESTROYDATA, pcdd,
((PERMEDIA_D3DCONTEXT *)ContextSlots[pcdd->dwhContext])->ppdev)
#endif MULTITHREADED
//@@END_DDKSPLIT
//-----------------------------------------------------------------------------
// Direct3D HAL Table.
//
// This table contains all of the HAL calls that this driver supports in the
// D3DHAL_Callbacks structure. These calls pertain to device context, scene
// capture, execution, textures, transform, lighting, and pipeline state.
// None of this is emulation code. The calls take the form of a return code
// equal to: HalCall(HalCallData* lpData). All of the information in this
// table will be implementation specific according to the specifications of
// the hardware.
//
//-----------------------------------------------------------------------------
#define PermediaTriCaps { \
sizeof(D3DPRIMCAPS), \
D3DPMISCCAPS_CULLCCW | /* miscCaps */ \
D3DPMISCCAPS_CULLCW | \
D3DPMISCCAPS_CULLNONE | \
D3DPMISCCAPS_MASKPLANES | \
D3DPMISCCAPS_MASKZ, \
D3DPRASTERCAPS_DITHER | /* rasterCaps */ \
D3DPRASTERCAPS_SUBPIXEL | \
D3DPRASTERCAPS_ZTEST | \
D3DPRASTERCAPS_FOGVERTEX | \
D3DPRASTERCAPS_STIPPLE, \
D3DPCMPCAPS_NEVER | \
D3DPCMPCAPS_LESS | \
D3DPCMPCAPS_EQUAL | \
D3DPCMPCAPS_LESSEQUAL | \
D3DPCMPCAPS_GREATER | \
D3DPCMPCAPS_NOTEQUAL | \
D3DPCMPCAPS_GREATEREQUAL | \
D3DPCMPCAPS_ALWAYS | \
D3DPCMPCAPS_LESSEQUAL, /* zCmpCaps */ \
D3DPBLENDCAPS_SRCALPHA | /* sourceBlendCaps */ \
D3DPBLENDCAPS_ONE, \
D3DPBLENDCAPS_INVSRCALPHA | /* destBlendCaps */ \
D3DPBLENDCAPS_ZERO | \
D3DPBLENDCAPS_ONE, \
0, /* alphatestCaps */ \
D3DPSHADECAPS_COLORFLATRGB| /* shadeCaps */ \
D3DPSHADECAPS_COLORGOURAUDRGB | \
D3DPSHADECAPS_SPECULARFLATRGB | \
D3DPSHADECAPS_SPECULARGOURAUDRGB | \
D3DPSHADECAPS_FOGFLAT | \
D3DPSHADECAPS_FOGGOURAUD | \
D3DPSHADECAPS_ALPHAFLATBLEND | \
D3DPSHADECAPS_ALPHAFLATSTIPPLED, \
D3DPTEXTURECAPS_PERSPECTIVE | /* textureCaps */ \
D3DPTEXTURECAPS_ALPHA | \
D3DPTEXTURECAPS_POW2 | \
D3DPTEXTURECAPS_TRANSPARENCY, \
D3DPTFILTERCAPS_NEAREST | /* textureFilterCaps*/ \
D3DPTFILTERCAPS_LINEAR, \
D3DPTBLENDCAPS_DECAL | /* textureBlendCaps */ \
D3DPTBLENDCAPS_DECALALPHA | \
D3DPTBLENDCAPS_MODULATE | \
D3DPTBLENDCAPS_MODULATEALPHA | \
D3DPTBLENDCAPS_COPY, \
D3DPTADDRESSCAPS_WRAP | /* textureAddressCaps */\
D3DPTADDRESSCAPS_MIRROR | \
D3DPTADDRESSCAPS_CLAMP | \
D3DPTADDRESSCAPS_INDEPENDENTUV, \
8, /* stippleWidth */ \
8 /* stippleHeight */ \
}
static D3DDEVICEDESC_V1 PermediaCaps = {
sizeof(D3DDEVICEDESC_V1), /* dwSize */
D3DDD_COLORMODEL | /* dwFlags */
D3DDD_DEVCAPS |
D3DDD_TRICAPS |
D3DDD_LINECAPS |
D3DDD_DEVICERENDERBITDEPTH |
D3DDD_DEVICEZBUFFERBITDEPTH,
D3DCOLOR_RGB /*| D3DCOLOR_MONO*/, /* dcmColorModel */
D3DDEVCAPS_FLOATTLVERTEX | /* devCaps */
D3DDEVCAPS_DRAWPRIMITIVES2 |
D3DDEVCAPS_DRAWPRIMITIVES2EX |
#if D3DDX7_TL
D3DDEVCAPS_HWTRANSFORMANDLIGHT |
#endif //D3DDX7_TL
D3DDEVCAPS_SORTINCREASINGZ |
D3DDEVCAPS_SORTEXACT |
D3DDEVCAPS_TLVERTEXSYSTEMMEMORY |
D3DDEVCAPS_EXECUTESYSTEMMEMORY |
D3DDEVCAPS_TEXTUREVIDEOMEMORY,
{ sizeof(D3DTRANSFORMCAPS),
0 }, /* transformCaps */
FALSE, /* bClipping */
{ sizeof(D3DLIGHTINGCAPS),
0 }, /* lightingCaps */
PermediaTriCaps, /* lineCaps */
PermediaTriCaps, /* triCaps */
DDBD_16 | DDBD_32, /* dwDeviceRenderBitDepth */
DDBD_16, /* Z Bit depths */
0, /* dwMaxBufferSize */
0 /* dwMaxVertexCount */
};
// Alpha Stipple patterns from Foley And Van Dam
DWORD FlatStipplePatterns[128] =
{
//Pattern 0
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Pattern 1
0x88, 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00,
// Pattern 2
0xAA, 0x00, 0x22, 0x00, 0xAA, 0x00, 0x22, 0x00,
// Pattern 3
0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00,
// Pattern 4
0xAA, 0x44, 0xAA, 0x00, 0xAA, 0x44, 0xAA, 0x00,
// Pattern 5
0xAA, 0x44, 0xAA, 0x11, 0xAA, 0x44, 0xAA, 0x11,
// Pattern 6
0xAA, 0x55, 0xAA, 0x11, 0xAA, 0x55, 0xAA, 0x11,
// Pattern 7
0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55,
// Pattern 8
0xEE, 0x55, 0xAA, 0x55, 0xEE, 0x55, 0xAA, 0x55,
// Pattern 9
0xEE, 0x55, 0xBB, 0x55, 0xEE, 0x55, 0xBB, 0x55,
// Pattern 10
0xFF, 0x55, 0xBB, 0x55, 0xFF, 0x55, 0xBB, 0x55,
// Pattern 11
0xFF, 0x55, 0xFF, 0x55, 0xFF, 0x55, 0xFF, 0x55,
// Pattern 12
0xFF, 0xdd, 0xFF, 0x55, 0xFF, 0xdd, 0xFF, 0x55,
// Pattern 13
0xFF, 0xdd, 0xFF, 0x77, 0xFF, 0xdd, 0xFF, 0x77,
// Pattern 14
0xFF, 0xFF, 0xFF, 0x77, 0xFF, 0xFF, 0xFF, 0x77,
// Pattern 15
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
//-----------------------------------------------------------------------------
// gD3DTextureFormats is a static structure which contains information
// pertaining to pixel format, dimensions, bit depth, surface requirements,
// overlays, and FOURCC codes of the supported texture formats. These texture
// formats will vary with the driver implementation according to the
// capabilities of the hardware.
//-----------------------------------------------------------------------------
DDSURFACEDESC gD3DTextureFormats [] =
{
// 5:5:5 RGB format
{
sizeof(DDSURFACEDESC), // dwSize
DDSD_CAPS | DDSD_PIXELFORMAT, // dwFlags
0, // dwHeight
0, // dwWidth
0, // lPitch
0, // dwBackBufferCount
0, // dwZBufferBitDepth
0, // dwAlphaBitDepth
0, // dwReserved
NULL, // lpSurface
{ 0, 0 }, // ddckCKDestOverlay
{ 0, 0 }, // ddckCKDestBlt
{ 0, 0 }, // ddckCKSrcOverlay
{ 0, 0 }, // ddckCKSrcBlt
{
sizeof(DDPIXELFORMAT), // ddpfPixelFormat.dwSize
DDPF_RGB, // ddpfPixelFormat.dwFlags
0, // ddpfPixelFormat.dwFourCC
16, // ddpfPixelFormat.dwRGBBitCount
0x7c00, // ddpfPixelFormat.dwRBitMask
0x03e0, // ddpfPixelFormat.dwGBitMask
0x001f, // ddpfPixelFormat.dwBBitMask
0 // ddpfPixelFormat.dwAlphaBitMask
},
DDSCAPS_TEXTURE, // ddscaps.dwCaps
},
// 1:5:5:5 ARGB format
{
sizeof(DDSURFACEDESC), // dwSize
DDSD_CAPS | DDSD_PIXELFORMAT, // dwFlags
0, // dwHeight
0, // dwWidth
0, // lPitch
0, // dwBackBufferCount
0, // dwZBufferBitDepth
0, // dwAlphaBitDepth
0, // dwReserved
NULL, // lpSurface
{ 0, 0 }, // ddckCKDestOverlay
{ 0, 0 }, // ddckCKDestBlt
{ 0, 0 }, // ddckCKSrcOverlay
{ 0, 0 }, // ddckCKSrcBlt
{
sizeof(DDPIXELFORMAT), // ddpfPixelFormat.dwSize
DDPF_RGB | DDPF_ALPHAPIXELS, // ddpfPixelFormat.dwFlags
0, // ddpfPixelFormat.dwFourCC
16, // ddpfPixelFormat.dwRGBBitCount
0x7c00, // ddpfPixelFormat.dwRBitMask
0x03e0, // ddpfPixelFormat.dwGBitMask
0x001f, // ddpfPixelFormat.dwBBitMask
0x8000 // ddpfPixelFormat.dwAlphaBitMask
},
DDSCAPS_TEXTURE, // ddscaps.dwCaps
},
// 5:6:5 RGB format
{
sizeof(DDSURFACEDESC), // dwSize
DDSD_CAPS | DDSD_PIXELFORMAT, // dwFlags
0, // dwHeight
0, // dwWidth
0, // lPitch
0, // dwBackBufferCount
0, // dwZBufferBitDepth
0, // dwAlphaBitDepth
0, // dwReserved
NULL, // lpSurface
{ 0, 0 }, // ddckCKDestOverlay
{ 0, 0 }, // ddckCKDestBlt
{ 0, 0 }, // ddckCKSrcOverlay
{ 0, 0 }, // ddckCKSrcBlt
{
sizeof(DDPIXELFORMAT), // ddpfPixelFormat.dwSize
DDPF_RGB, // ddpfPixelFormat.dwFlags
0, // ddpfPixelFormat.dwFourCC
16, // ddpfPixelFormat.dwRGBBitCount
0xf800, // ddpfPixelFormat.dwRBitMask
0x07e0, // ddpfPixelFormat.dwGBitMask
0x001f, // ddpfPixelFormat.dwBBitMask
0 // ddpfPixelFormat.dwAlphaBitMask
},
DDSCAPS_TEXTURE, // ddscaps.dwCaps
},
// 4:4:4:4 ARGB format
{
sizeof(DDSURFACEDESC), // dwSize
DDSD_CAPS | DDSD_PIXELFORMAT, // dwFlags
0, // dwHeight
0, // dwWidth
0, // lPitch
0, // dwBackBufferCount
0, // dwZBufferBitDepth
0, // dwAlphaBitDepth
0, // dwReserved
NULL, // lpSurface
{ 0, 0 }, // ddckCKDestOverlay
{ 0, 0 }, // ddckCKDestBlt
{ 0, 0 }, // ddckCKSrcOverlay
{ 0, 0 }, // ddckCKSrcBlt
{
sizeof(DDPIXELFORMAT), // ddpfPixelFormat.dwSize
DDPF_RGB | DDPF_ALPHAPIXELS, // ddpfPixelFormat.dwFlags
0, // ddpfPixelFormat.dwFourCC
16, // ddpfPixelFormat.dwRGBBitCount
0x0f00, // ddpfPixelFormat.dwRBitMask
0x00f0, // ddpfPixelFormat.dwGBitMask
0x000f, // ddpfPixelFormat.dwBBitMask
0xf000 // ddpfPixelFormat.dwAlphaBitMask
},
DDSCAPS_TEXTURE, // ddscaps.dwCaps
},
// 8:8:8 RGB format
{
sizeof(DDSURFACEDESC), // dwSize
DDSD_CAPS | DDSD_PIXELFORMAT, // dwFlags
0, // dwHeight
0, // dwWidth
0, // lPitch
0, // dwBackBufferCount
0, // dwZBufferBitDepth
0, // dwAlphaBitDepth
0, // dwReserved
NULL, // lpSurface
{ 0, 0 }, // ddckCKDestOverlay
{ 0, 0 }, // ddckCKDestBlt
{ 0, 0 }, // ddckCKSrcOverlay
{ 0, 0 }, // ddckCKSrcBlt
{
sizeof(DDPIXELFORMAT), // ddpfPixelFormat.dwSize
DDPF_RGB, // ddpfPixelFormat.dwFlags
0, // ddpfPixelFormat.dwFourCC
32, // ddpfPixelFormat.dwRGBBitCount
0x00ff0000, // ddpfPixelFormat.dwRBitMask
0x0000ff00, // ddpfPixelFormat.dwGBitMask
0x000000ff, // ddpfPixelFormat.dwBBitMask
0 // ddpfPixelFormat.dwAlphaBitMask
},
DDSCAPS_TEXTURE, // ddscaps.dwCaps
},
// 8:8:8:8 ARGB format
{
sizeof(DDSURFACEDESC), // dwSize
DDSD_CAPS | DDSD_PIXELFORMAT, // dwFlags
0, // dwHeight
0, // dwWidth
0, // lPitch
0, // dwBackBufferCount
0, // dwZBufferBitDepth
0, // dwAlphaBitDepth
0, // dwReserved
NULL, // lpSurface
{ 0, 0 }, // ddckCKDestOverlay
{ 0, 0 }, // ddckCKDestBlt
{ 0, 0 }, // ddckCKSrcOverlay
{ 0, 0 }, // ddckCKSrcBlt
{
sizeof(DDPIXELFORMAT), // ddpfPixelFormat.dwSize
DDPF_RGB | DDPF_ALPHAPIXELS, // ddpfPixelFormat.dwFlags
0, // ddpfPixelFormat.dwFourCC
32, // ddpfPixelFormat.dwRGBBitCount
0x00ff0000, // ddpfPixelFormat.dwRBitMask
0x0000ff00, // ddpfPixelFormat.dwGBitMask
0x000000ff, // ddpfPixelFormat.dwBBitMask
0xff000000 // ddpfPixelFormat.dwAlphaBitMask
},
DDSCAPS_TEXTURE, // ddscaps.dwCaps
},
// 4 bit palettized format
{
sizeof(DDSURFACEDESC), // dwSize
DDSD_CAPS | DDSD_PIXELFORMAT, // dwFlags
0, // dwHeight
0, // dwWidth
0, // lPitch
0, // dwBackBufferCount
0, // dwZBufferBitDepth
0, // dwAlphaBitDepth
0, // dwReserved
NULL, // lpSurface
{ 0, 0 }, // ddckCKDestOverlay
{ 0, 0 }, // ddckCKDestBlt
{ 0, 0 }, // ddckCKSrcOverlay
{ 0, 0 }, // ddckCKSrcBlt
{
sizeof(DDPIXELFORMAT), // ddpfPixelFormat.dwSize
DDPF_RGB | DDPF_PALETTEINDEXED4, // ddpfPixelFormat.dwFlags
0, // ddpfPixelFormat.dwFourCC
4, // ddpfPixelFormat.dwRGBBitCount
0x00, // ddpfPixelFormat.dwRBitMask
0x00, // ddpfPixelFormat.dwGBitMask
0x00, // ddpfPixelFormat.dwBBitMask
0x00 // ddpfPixelFormat.dwAlphaBitMask
},
DDSCAPS_TEXTURE, // ddscaps.dwCaps
},
// 8 bit palettized format
{
sizeof(DDSURFACEDESC), // dwSize
DDSD_CAPS | DDSD_PIXELFORMAT, // dwFlags
0, // dwHeight
0, // dwWidth
0, // lPitch
0, // dwBackBufferCount
0, // dwZBufferBitDepth
0, // dwAlphaBitDepth
0, // dwReserved
NULL, // lpSurface
{ 0, 0 }, // ddckCKDestOverlay
{ 0, 0 }, // ddckCKDestBlt
{ 0, 0 }, // ddckCKSrcOverlay
{ 0, 0 }, // ddckCKSrcBlt
{
sizeof(DDPIXELFORMAT), // ddpfPixelFormat.dwSize
DDPF_RGB | DDPF_PALETTEINDEXED8, // ddpfPixelFormat.dwFlags
0, // ddpfPixelFormat.dwFourCC
8, // ddpfPixelFormat.dwRGBBitCount
0x00, // ddpfPixelFormat.dwRBitMask
0x00, // ddpfPixelFormat.dwGBitMask
0x00, // ddpfPixelFormat.dwBBitMask
0x00 // ddpfPixelFormat.dwAlphaBitMask
},
DDSCAPS_TEXTURE, // ddscaps.dwCaps
},
};
ULONG gD3DNumberOfTextureFormats =
sizeof(gD3DTextureFormats) / sizeof(DDSURFACEDESC);
//------------------------------------------------------------------------------
// D3D working structures for callbacks and global data
//------------------------------------------------------------------------------
// D3D callbacks and global data
D3DHAL_GLOBALDRIVERDATA gD3DGlobalDriverData;
D3DHAL_CALLBACKS gD3DCallBacks;
// D3D contexts table
// each entry points to a valid PERMEDIA_D3DCONTEXT structure
UINT_PTR ContextSlots[MAX_CONTEXT_NUM] = {0};
// Handles table
// each entry is a DWLIST structure (*dwSurfaceList,*dwPaletteList;pDDLcl)
DWLIST HandleList[MAX_CONTEXT_NUM] = {0};
//-----------------------------------------------------------------------------
//
// void D3DHALCreateDriver
//
// The main D3D Callback.
// Clears contexts
// Fills in entry points to D3D driver.
// Generates texture formats.
//
//-----------------------------------------------------------------------------
void CALLBACK
D3DHALCreateDriver(PPDev ppdev,
LPD3DHAL_GLOBALDRIVERDATA* lpD3DGlobalDriverData,
LPD3DHAL_CALLBACKS* lpD3DHALCallbacks,
LPDDHAL_D3DBUFCALLBACKS* lpDDExeBufCallbacks)
{
D3DHAL_GLOBALDRIVERDATA deviceD3DGlobal;
D3DHAL_CALLBACKS deviceD3DHALCallbacks;
DBG_D3D((6,"Entering D3DHALCreateDriver"));
// Contexts are cleared out. It is allright to use the D3DInitialised BOOL,
// because it is global, and therefore forced into shared data segment by
// the build.
if (D3DInitialised == FALSE)
{
// Clear the contexts.
memset(ContextSlots, 0, (sizeof(ContextSlots[0]) * MAX_CONTEXT_NUM) );
memset(HandleList, 0, (sizeof(HandleList[0]) * MAX_CONTEXT_NUM) );
D3DInitialised = TRUE;
}
// Here we fill in the supplied structures.
// Can disable D3D HAL in registry if we are in the wrong mode
if (ppdev->iBitmapFormat == BMF_8BPP )
{
*lpD3DGlobalDriverData = NULL;
*lpD3DHALCallbacks = NULL;
*lpDDExeBufCallbacks = NULL;
DBG_D3D((0, "D3DHALCreateDriver: Disabled"));
return;
}
// Set the pointers for D3D global data
ppdev->pD3DDriverData32 = (UINT_PTR)&gD3DGlobalDriverData;
ppdev->pD3DHALCallbacks32 = (UINT_PTR)&gD3DCallBacks;
// Clear the global data
memset(&deviceD3DGlobal, 0, sizeof(D3DHAL_GLOBALDRIVERDATA));
deviceD3DGlobal.dwSize = sizeof(D3DHAL_GLOBALDRIVERDATA);
// Clear the call-backs
memset(&deviceD3DHALCallbacks, 0, sizeof(D3DHAL_CALLBACKS));
deviceD3DHALCallbacks.dwSize = sizeof(D3DHAL_CALLBACKS);
deviceD3DGlobal.dwNumVertices = 0; // We don't parse execute buffers
deviceD3DGlobal.dwNumClipVertices = 0;
#if D3D_MIPMAPPING
// Add mipmapping cap bits to our texturing capabilities
PermediaCaps.dpcTriCaps.dwTextureFilterCaps |=
D3DPTFILTERCAPS_MIPNEAREST |
D3DPTFILTERCAPS_MIPLINEAR |
D3DPTFILTERCAPS_LINEARMIPNEAREST |
D3DPTFILTERCAPS_LINEARMIPLINEAR;
PermediaCaps.dpcTriCaps.dwRasterCaps |= D3DPRASTERCAPS_MIPMAPLODBIAS;
#endif
// Can do packed 24 bit on P2.
PermediaCaps.dwDeviceRenderBitDepth |= DDBD_24;
if (DD_P2AGPCAPABLE(ppdev))
PermediaCaps.dwDevCaps |= D3DDEVCAPS_TEXTURENONLOCALVIDMEM;
PermediaCaps.dwDevCaps |= D3DDEVCAPS_DRAWPRIMTLVERTEX;
deviceD3DGlobal.hwCaps = PermediaCaps;
deviceD3DGlobal.dwNumTextureFormats = gD3DNumberOfTextureFormats;
deviceD3DGlobal.lpTextureFormats = &gD3DTextureFormats[0];
// D3D Context callbacks
//@@BEGIN_DDKSPLIT
#if MULTITHREADED
deviceD3DHALCallbacks.ContextCreate = MtD3DContextCreate;
deviceD3DHALCallbacks.ContextDestroy = MtD3DContextDestroy;
#else
//@@END_DDKSPLIT
deviceD3DHALCallbacks.ContextCreate = D3DContextCreate;
deviceD3DHALCallbacks.ContextDestroy = D3DContextDestroy;
//@@BEGIN_DDKSPLIT
#endif MULTITHREADED
//@@END_DDKSPLIT
//
// Return the HAL table.
//
memcpy(&gD3DGlobalDriverData, &deviceD3DGlobal, sizeof(D3DHAL_GLOBALDRIVERDATA));
memcpy(&gD3DCallBacks, &deviceD3DHALCallbacks, sizeof(D3DHAL_CALLBACKS));
*lpD3DGlobalDriverData = &gD3DGlobalDriverData;
*lpD3DHALCallbacks = &gD3DCallBacks;
*lpDDExeBufCallbacks = NULL;
DBG_D3D((6,"Exiting D3DHALCreateDriver"));
return;
} // D3DHALCreateDriver
//-----------------------------------------------------------------------------
//
// void CleanDirect3DContext
//
// After it has been decided that a context is indeed still active
// and is being freed, this function walks along cleaning everything
// up. Note it can be called either as a result of a D3DContextDestroy,
// or as a result of the app exiting without freeing the context, or
// as the result of an error whilst creating the context.
//
//-----------------------------------------------------------------------------
void
CleanDirect3DContext(PERMEDIA_D3DCONTEXT* pContext, ULONG_PTR dwhContext)
{
PERMEDIA_D3DTEXTURE* pTexture;
DWORD dwSlotNum = 1;
PPDev ppdev = pContext->ppdev;
DBG_D3D((10,"Entering CleanDirect3DContext"));
// free up Permedia register context id (resources)
if (pContext->hPermediaContext)
{
P2FreeContext( ppdev, pContext->hPermediaContext);
}
// clean up texture manager stuff it is already allocated for this context
if (pContext->pTextureManager)
{
pContext->pTextureManager = NULL;
P2TMcount--;
if (0 == P2TMcount)
{
if (0 != P2TextureManager.m_heap.m_data_p)
{
TextureCacheManagerEvictTextures(&P2TextureManager);
ENGFREEMEM(P2TextureManager.m_heap.m_data_p);
P2TextureManager.m_heap.m_data_p=NULL;
}
}
}
#if D3D_STATEBLOCKS
// Free up any remaining state sets
__DeleteAllStateSets(pContext);
#endif //D3D_STATEBLOCKS
// Finally, free up the rendering context structure itself
ENGFREEMEM((PVOID)pContext->Hdr.pSelf);
// Mark the context as now empty!
ContextSlots[dwhContext] = 0;
DBG_D3D((10,"Exiting CleanDirect3DContext, Context 0x%x deleted.",
dwhContext));
} // CleanDirect3DContext
//-----------------------------------------------------------------------------
//
// HRESULT InitPermediaContext
//
// Given a valid context, this sets up the rest of the chip, and
// enables the relevent units. There is a software copy of most things.
//
//-----------------------------------------------------------------------------
HRESULT
InitPermediaContext(PERMEDIA_D3DCONTEXT* pContext)
{
PPDev ppdev = pContext->ppdev;
DBG_D3D((10,"Entering InitPermediaContext"));
SET_CURRENT_D3D_CONTEXT(pContext->hPermediaContext);
// Initially turn off all.units
__PermediaDisableUnits(pContext);
// Setup initial state of Permedia 2 registers for this D3D context
SetupDefaultsPermediaContext(pContext);
DBG_D3D((10,"Exiting InitPermediaContext"));
// Setup the correct surface (render & depth buffer) characteristics
return SetupPermediaRenderTarget(pContext);
} // InitPermediaContext
//-----------------------------------------------------------------------------
//
// BOOL: SetupDefaultsPermediaContext
//
// Sets up the Permedia HW context(chip.registers) according to some D3D and
// some HW specific defaults. Done only when initializing the context
//
//-----------------------------------------------------------------------------
BOOL
SetupDefaultsPermediaContext(PERMEDIA_D3DCONTEXT* pContext)
{
__P2RegsSoftwareCopy* pSoftPermedia = &pContext->Hdr.SoftCopyP2Regs;
PERMEDIA_DEFS(pContext->ppdev);
DBG_D3D((10,"Entering SetupDefaultsPermediaContext"));
//=========================================================================
// Initialize our software copy of some registers for their default values
//=========================================================================
// Setup the default & constant ( Z Buffer) LB settings
// this will be updated into the chip in SetupPermediaRenderTarget
pSoftPermedia->LBReadMode.WindowOrigin = __PERMEDIA_TOP_LEFT_WINDOW_ORIGIN;
pSoftPermedia->LBReadMode.DataType = __PERMEDIA_LBDEFAULT; // default
pSoftPermedia->LBReadMode.ReadSourceEnable = __PERMEDIA_DISABLE;
pSoftPermedia->LBReadMode.ReadDestinationEnable = __PERMEDIA_DISABLE;
pSoftPermedia->LBReadMode.PatchMode = 0;
// Setup the default & constant FB settings
// this will be updated into the chip in SetupPermediaRenderTarget
pSoftPermedia->FBReadMode.ReadSourceEnable = __PERMEDIA_DISABLE;
pSoftPermedia->FBReadMode.ReadDestinationEnable = __PERMEDIA_DISABLE;
pSoftPermedia->FBReadMode.DataType = __PERMEDIA_FBDATA;
// Top Left for D3D origin
pSoftPermedia->FBReadMode.WindowOrigin = __PERMEDIA_TOP_LEFT_WINDOW_ORIGIN;
pSoftPermedia->FBReadMode.PatchMode = 0;
pSoftPermedia->FBReadMode.PackedData = 0;
pSoftPermedia->FBReadMode.RelativeOffset = 0;
// Setup the default & constant Alpha Blend Mode settings
// this will be updated into the chip in SetupPermediaRenderTarget
pSoftPermedia->AlphaBlendMode.AlphaBlendEnable = 0;
pSoftPermedia->AlphaBlendMode.SourceBlend = __PERMEDIA_BLEND_FUNC_ONE;
pSoftPermedia->AlphaBlendMode.DestinationBlend = __PERMEDIA_BLEND_FUNC_ZERO;
pSoftPermedia->AlphaBlendMode.NoAlphaBuffer = 0;
pSoftPermedia->AlphaBlendMode.ColorOrder = COLOR_MODE;
pSoftPermedia->AlphaBlendMode.BlendType = 0;
pSoftPermedia->AlphaBlendMode.ColorConversion = 1;
pSoftPermedia->AlphaBlendMode.AlphaConversion = 1;
// Setup the default & constant Dither Mode settings
// this will be updated into the chip in SetupPermediaRenderTarget
pSoftPermedia->DitherMode.ColorOrder = COLOR_MODE;
pSoftPermedia->DitherMode.XOffset = DITHER_XOFFSET;
pSoftPermedia->DitherMode.YOffset = DITHER_YOFFSET;
pSoftPermedia->DitherMode.UnitEnable = __PERMEDIA_ENABLE;
pSoftPermedia->DitherMode.ForceAlpha = 0;
//=========================================================================
// Find out info for memory widths
//=========================================================================
PPDev ppdev = pContext->ppdev;
DBG_D3D((4, "ScreenWidth %d, ScreenHeight %d, Bytes/Pixel %d",
ppdev->cxScreen, ppdev->cyScreen,
ppdev->ddpfDisplay.dwRGBBitCount >> 3));
vCalcPackedPP( ppdev->cxMemory, NULL, &pContext->ulPackedPP);
DBG_D3D((4, "PackedPP = %04x", pContext->ulPackedPP));
//=========================================================================
// Initialize hardware registers to their default values
//=========================================================================
// Number of registers we are going to set up
RESERVEDMAPTR(34);
// ----------------- Render and Depth Buffer setup ----------------------
// Setup default offset of render buffer in video memory
SEND_PERMEDIA_DATA(FBWindowBase, 0x0);
// Setup offset from destination to source for copy operations
SEND_PERMEDIA_DATA(FBSourceOffset, 0x0);
// Render buffer Write Mode setup
pSoftPermedia->FBWriteMode.UnitEnable = __PERMEDIA_ENABLE;
COPY_PERMEDIA_DATA(FBWriteMode, pSoftPermedia->FBWriteMode);
// Render buffer Write Masks (write to all bits in the pixel)
SEND_PERMEDIA_DATA(FBSoftwareWriteMask, __PERMEDIA_ALL_WRITEMASKS_SET);
SEND_PERMEDIA_DATA(FBHardwareWriteMask, __PERMEDIA_ALL_WRITEMASKS_SET);
// Set block fill colour to black
SEND_PERMEDIA_DATA(FBBlockColor, 0x0);
// Set window origin offsets to (0,0)
SEND_PERMEDIA_DATA(WindowOrigin, 0x0);
// WindowSetup
pSoftPermedia->Window.ForceLBUpdate = 0;
pSoftPermedia->Window.LBUpdateSource = 0;
pSoftPermedia->Window.DisableLBUpdate = 0;
COPY_PERMEDIA_DATA(Window, pSoftPermedia->Window);
// Disable Screen Scissor unit
SEND_PERMEDIA_DATA(ScissorMode, __PERMEDIA_DISABLE);
// Depth Buffer offset
SEND_PERMEDIA_DATA(LBSourceOffset, 0);
// Depth Buffer Write mode (initially allow LB Writes)
pSoftPermedia->LBWriteMode.WriteEnable = __PERMEDIA_DISABLE;
COPY_PERMEDIA_DATA(LBWriteMode, pSoftPermedia->LBWriteMode);
// Depth comparisons
pSoftPermedia->DepthMode.WriteMask = __PERMEDIA_ENABLE;
pSoftPermedia->DepthMode.CompareMode =
__PERMEDIA_DEPTH_COMPARE_MODE_LESS_OR_EQUAL;
pSoftPermedia->DepthMode.NewDepthSource = __PERMEDIA_DEPTH_SOURCE_DDA;
pSoftPermedia->DepthMode.UnitEnable = __PERMEDIA_DISABLE;
COPY_PERMEDIA_DATA(DepthMode, pSoftPermedia->DepthMode);
// ----------------- Texture units setup -----------------------------
// Enable texture address unit, disable perspective correction
pSoftPermedia->TextureAddressMode.Enable = 1;
pSoftPermedia->TextureAddressMode.PerspectiveCorrection = 0;
pSoftPermedia->TextureAddressMode.DeltaFormat = 0;
COPY_PERMEDIA_DATA(TextureAddressMode, pSoftPermedia->TextureAddressMode);
// Enable texture color mode unit, set modulation blending, no specular
// as defaults
pSoftPermedia->TextureColorMode.TextureEnable = 1;
pSoftPermedia->TextureColorMode.ApplicationMode = _P2_TEXTURE_MODULATE;
pSoftPermedia->TextureColorMode.TextureType = 0;
pSoftPermedia->TextureColorMode.KdDDA = 0;
pSoftPermedia->TextureColorMode.KsDDA = 0;
COPY_PERMEDIA_DATA(TextureColorMode, pSoftPermedia->TextureColorMode);
// Enable texture mapping unit, set frame buffer size as default texture
// map size (to be oevrriden in EnableTexturePermedia)
pSoftPermedia->TextureMapFormat.PackedPP = pContext->ulPackedPP;
pSoftPermedia->TextureMapFormat.WindowOrigin =
__PERMEDIA_TOP_LEFT_WINDOW_ORIGIN; //top left
pSoftPermedia->TextureMapFormat.SubPatchMode = 0;
pSoftPermedia->TextureMapFormat.TexelSize = 1;
COPY_PERMEDIA_DATA(TextureMapFormat, pSoftPermedia->TextureMapFormat);
// Setup Textura data format (to be oevrriden in EnableTexturePermedia)
pSoftPermedia->TextureDataFormat.TextureFormat = 1;
pSoftPermedia->TextureDataFormat.NoAlphaBuffer = 1;
pSoftPermedia->TextureDataFormat.ColorOrder = COLOR_MODE;
COPY_PERMEDIA_DATA(TextureDataFormat, pSoftPermedia->TextureDataFormat);
// Setup default texture map base address (in video memory)
SEND_PERMEDIA_DATA(TextureBaseAddress, 0);
// Setup texture reading defaults: Repeat s,t wrapping, 256x256 texture
// no texture filtering set up.
pSoftPermedia->TextureReadMode.PackedData = 0;
pSoftPermedia->TextureReadMode.FilterMode = 0;
pSoftPermedia->TextureReadMode.Height = 8;
pSoftPermedia->TextureReadMode.Width = 8;
pSoftPermedia->TextureReadMode.pad1 = 0;
pSoftPermedia->TextureReadMode.pad2 = 0;
pSoftPermedia->TextureReadMode.TWrapMode = _P2_TEXTURE_REPEAT;
pSoftPermedia->TextureReadMode.SWrapMode = _P2_TEXTURE_REPEAT;
pSoftPermedia->TextureReadMode.Enable = 1;
COPY_PERMEDIA_DATA(TextureReadMode, pSoftPermedia->TextureReadMode);
// Disable Texture LUT unit for palettized textures
SEND_PERMEDIA_DATA(TexelLUTMode, __PERMEDIA_DISABLE);
// -------------- Other rendering units setup ----------------
// Setup defaults of YUV units used for chromakey testing
pSoftPermedia->YUVMode.Enable = __PERMEDIA_DISABLE;
pSoftPermedia->YUVMode.TestMode = PM_YUVMODE_CHROMATEST_DISABLE;
pSoftPermedia->YUVMode.TestData = PM_YUVMODE_TESTDATA_INPUT;
pSoftPermedia->YUVMode.RejectTexel = FALSE;
pSoftPermedia->YUVMode.TexelDisableUpdate = FALSE;
COPY_PERMEDIA_DATA(YUVMode, pSoftPermedia->YUVMode);
// Chromakey values initially black
SEND_PERMEDIA_DATA(ChromaUpperBound, 0x00000000);
SEND_PERMEDIA_DATA(ChromaLowerBound, 0x00000000);
SEND_PERMEDIA_DATA(AlphaMapUpperBound, 0xFFFFFFFF);
SEND_PERMEDIA_DATA(AlphaMapLowerBound, 0x11000000);
// Default Fog color is white
pSoftPermedia->FogColor = 0xFFFFFFFF;
SEND_PERMEDIA_DATA(FogColor, pSoftPermedia->FogColor);
// Fog setup
pSoftPermedia->FogMode.FogEnable = 1;
COPY_PERMEDIA_DATA(FogMode, pSoftPermedia->FogMode);
// Stencil mode setup
pSoftPermedia->StencilMode.DPFail = __PERMEDIA_STENCIL_METHOD_KEEP;
pSoftPermedia->StencilMode.DPPass = __PERMEDIA_STENCIL_METHOD_KEEP;
pSoftPermedia->StencilMode.UnitEnable = __PERMEDIA_DISABLE;
pSoftPermedia->StencilMode.StencilSource =
__PERMEDIA_STENCIL_SOURCE_TEST_LOGIC;
COPY_PERMEDIA_DATA(StencilMode, pSoftPermedia->StencilMode);
// Host out unit , disable read backs
SEND_PERMEDIA_DATA(FilterMode, __PERMEDIA_DISABLE);
// Disable statistics unit
SEND_PERMEDIA_DATA(StatisticMode, __PERMEDIA_DISABLE);
// ----------------- Rasterization setup -----------------------------
// Setup Rasterizer units defaults
SEND_PERMEDIA_DATA(RasterizerMode, 0);
// Setup a step of -1, as this doesn't change very much
SEND_PERMEDIA_DATA(dY, 0xFFFF0000);
// Setup for Gourand shaded colour model, and enable unit
pContext->Hdr.SoftCopyP2Regs.ColorDDAMode.UnitEnable = 1;
pContext->Hdr.SoftCopyP2Regs.ColorDDAMode.ShadeMode = 1;
COPY_PERMEDIA_DATA(ColorDDAMode, pContext->Hdr.SoftCopyP2Regs.ColorDDAMode);
// Disable stippling unit
SEND_PERMEDIA_DATA(AreaStippleMode, 0x0); //AZN
// Setup the Delta setup chip for rasterization
pSoftPermedia->DeltaMode.TargetChip = 2;
pSoftPermedia->DeltaMode.SpecularTextureEnable = 0;
// The below changes to normalize in the perspective case
// It must not be on in the non-perspective case as the bad Q's will
// get used in the normalisation.
pSoftPermedia->DeltaMode.TextureParameterMode = 1;
pSoftPermedia->DeltaMode.TextureEnable = 1;
pSoftPermedia->DeltaMode.DiffuseTextureEnable = 0;
pSoftPermedia->DeltaMode.FogEnable = 1;
pSoftPermedia->DeltaMode.SmoothShadingEnable = 1;
pSoftPermedia->DeltaMode.DepthEnable = 0;
pSoftPermedia->DeltaMode.SubPixelCorrectionEnable = 1;
pSoftPermedia->DeltaMode.DiamondExit = 1;
pSoftPermedia->DeltaMode.NoDraw = 0;
pSoftPermedia->DeltaMode.ClampEnable = 0;
pSoftPermedia->DeltaMode.FillDirection = 0;
#ifndef P2_CHIP_CULLING
pSoftPermedia->DeltaMode.BackfaceCull = 0;
#else
pSoftPermedia->DeltaMode.BackfaceCull = 1;
#endif
pSoftPermedia->DeltaMode.ColorOrder = COLOR_MODE;
COPY_PERMEDIA_DATA(DeltaMode, pSoftPermedia->DeltaMode);
// Send all this data to Permedia2
COMMITDMAPTR();
FLUSHDMA();
DBG_D3D((10,"Exiting SetupDefaultsPermediaContext"));
return TRUE;
} // SetupDefaultsPermediaContext
//-----------------------------------------------------------------------------
//
// void SetupPermediaRenderTarget
//
// Sets up the correct surface characteristics (format, stride, etc) of the
// render buffer and the depth buffer in the Permedia registers
//
//-----------------------------------------------------------------------------
HRESULT
SetupPermediaRenderTarget(PERMEDIA_D3DCONTEXT* pContext)
{
__P2RegsSoftwareCopy* pSoftPermedia = &pContext->Hdr.SoftCopyP2Regs;
PPDev ppdev = pContext->ppdev;
PPERMEDIA_D3DTEXTURE pSurfRender,pSurfZBuffer;
PermediaSurfaceData* pPrivateRender;
PERMEDIA_DEFS(pContext->ppdev);
DBG_D3D((10,"Entering SetupPermediaRenderTarget"));
pSurfRender =
TextureHandleToPtr(pContext->RenderSurfaceHandle, pContext);
if (!CHECK_D3DSURFACE_VALIDITY(pSurfRender))
{
DBG_D3D((0,"ERROR: SetupPermediaRenderTarget"
" Invalid pSurfRender handle=%08lx",
pContext->RenderSurfaceHandle));
return DDERR_INVALIDPARAMS;
}
if (DDSCAPS_SYSTEMMEMORY & pSurfRender->dwCaps)
{
DBG_D3D((0, "ERROR: SetupPermediaRenderTarget"
" Render Surface in SYSTEMMEMORY handle=%08lx",
pContext->RenderSurfaceHandle));
return DDERR_INVALIDPARAMS;
}
pPrivateRender=pSurfRender->pTextureSurface;
if (!CHECK_P2_SURFACEDATA_VALIDITY(pPrivateRender))
{
DBG_D3D((0,"ERROR: SetupPermediaRenderTarget"
" invalid pSurfRender->pTextureSurface handle=%08lx",
pContext->RenderSurfaceHandle));
return DDERR_INVALIDPARAMS;
}
if (0 != pContext->ZBufferHandle)
{
pSurfZBuffer =
TextureHandleToPtr(pContext->ZBufferHandle, pContext);
if (!CHECK_D3DSURFACE_VALIDITY(pSurfZBuffer))
{
DBG_D3D((0,"ERROR: SetupPermediaRenderTarget"
" invalid pSurfZBuffer handle=%08lx",
pContext->ZBufferHandle));
pContext->ZBufferHandle = 0;
}
else
if (DDSCAPS_SYSTEMMEMORY & pSurfZBuffer->dwCaps)
{
DBG_D3D((0, "ERROR: SetupPermediaRenderTarget"
" pSurfZBuffer in SYSTEMMEMORY handle=%08lx",
pContext->ZBufferHandle));
pContext->ZBufferHandle = 0;
}
else
if (!CHECK_P2_SURFACEDATA_VALIDITY(pSurfZBuffer->pTextureSurface))
{
DBG_D3D((0,"ERROR: SetupPermediaRenderTarget"
" invalid pSurfZBuffer->pTextureSurface handle=%08lx",
pContext->ZBufferHandle));
pContext->ZBufferHandle = 0;
}
}
// The default is linear surfaces...
DBG_D3D((4,"Rendered surface Width: %d", pSurfRender->wWidth));
pSoftPermedia->FBReadMode.PackedPP = pSurfRender->pTextureSurface->ulPackedPP;
pContext->PixelOffset =
(DWORD)((UINT_PTR)pSurfRender->fpVidMem>>(pSurfRender->dwRGBBitCount>>4));
DBG_D3D((4,"Setting FBReadMode: 0x%x",pSoftPermedia->FBReadMode));
// Record the surface information
RESERVEDMAPTR(10);
// If there is a Z Buffer, then we must setup the Partial products to be
// the same as those chosen when it was allocated.
if (0 != pContext->ZBufferHandle)
{
PermediaSurfaceData* pPrivateZ = pSurfZBuffer->pTextureSurface;
pSoftPermedia->LBReadMode.PackedPP = pPrivateZ->ulPackedPP;
//actually check dwStencilBitMask
if (0==pPrivateZ->SurfaceFormat.BlueMask)
{
pSoftPermedia->LBReadFormat.DepthWidth = 0; // 16 bits
pSoftPermedia->LBReadFormat.StencilWidth = 0; // No Stencil
pSoftPermedia->DeltaMode.DepthFormat = 1; //PM_DELTAMODE_DEPTHWIDTH_16
}
else
{
pSoftPermedia->LBReadFormat.DepthWidth = 3; // 15 bits
pSoftPermedia->LBReadFormat.StencilWidth = 3; // 1 Stencil
pSoftPermedia->DeltaMode.DepthFormat = 0; //PM_DELTAMODE_DEPTHWIDTH_15
}
SEND_PERMEDIA_DATA(LBWindowBase,
(DWORD)((UINT_PTR)pSurfZBuffer->fpVidMem>>P2DEPTH16));
COPY_PERMEDIA_DATA(LBReadFormat, pSoftPermedia->LBReadFormat);
COPY_PERMEDIA_DATA(LBWriteFormat, pSoftPermedia->LBReadFormat);
DBG_D3D((4,"Setting LBReadMode: 0x%x",pSoftPermedia->LBReadMode));
}
else
{ // No Z Buffer, just stuff the same Partial products as the desktop.
pSoftPermedia->LBReadMode.PackedPP = pContext->ulPackedPP;
}
COPY_PERMEDIA_DATA(FBReadMode, pSoftPermedia->FBReadMode);
COPY_PERMEDIA_DATA(LBReadMode, pSoftPermedia->LBReadMode);
// Set up the screen dimensions to be the same size as the surface.
SEND_PERMEDIA_DATA(ScreenSize,
(pSurfRender->wWidth & 0xFFFF) | (pSurfRender->wHeight << 16));
// DitherMode and AlphaBlendMode both depend on the surface pixel format
// being correct.
pSoftPermedia->DitherMode.ColorFormat =
pSoftPermedia->AlphaBlendMode.ColorFormat=
pPrivateRender->SurfaceFormat.Format;
pSoftPermedia->DitherMode.ColorFormatExtension =
pSoftPermedia->AlphaBlendMode.ColorFormatExtension =
pPrivateRender->SurfaceFormat.FormatExtension;
pSoftPermedia->FBReadPixel = pPrivateRender->SurfaceFormat.FBReadPixel;
SEND_PERMEDIA_DATA(FBReadPixel, pSoftPermedia->FBReadPixel);
SEND_PERMEDIA_DATA(FBPixelOffset, pContext->PixelOffset);
COPY_PERMEDIA_DATA(AlphaBlendMode, pSoftPermedia->AlphaBlendMode);
COPY_PERMEDIA_DATA(DitherMode, pSoftPermedia->DitherMode);
COMMITDMAPTR();
DBG_D3D((10,"Exiting SetupPermediaRenderTarget"));
return DD_OK;
} // SetupPermediaRenderTarget
//=============================================================================
//
// In the new DX7 DDI we don't have the Texture Create/Destroy/Swap calls
// anymore, so now we need a mechanism for generating texture handles. This
// is done by the runtime, which will associate a surface handle for each
// surface created with the DD local object, and will get our D3DCreateSurfaceEx
// callback called.
//
// Since this creation can very well happen before we create a D3D context, we
// need to keep track of this association, and when we do get called to create
// a D3D context, we will now be given the relevant DD local object pointer to
// resolve which handles are ours (and to which private texture structures we
// need to use).
//
// This mechanism is also used to associate a palette to a texture
//
//=============================================================================
//-----------------------------------------------------------------------------
//
// BOOL SetTextureSlot
//
// In the handle list element corresponding to this local DD object, store or
// update the pointer to the pTexture associated to the surface handle
// from the lpDDSLcl surface.
//
//-----------------------------------------------------------------------------
BOOL
SetTextureSlot(LPVOID pDDLcl,
LPDDRAWI_DDRAWSURFACE_LCL lpDDSLcl,
PPERMEDIA_D3DTEXTURE pTexture)
{
int i,j= -1;
DWORD dwSurfaceHandle;
DBG_D3D((10,"Entering SetTextureSlot"));
ASSERTDD(NULL != pDDLcl && NULL != lpDDSLcl && NULL != pTexture,
"SetTextureSlot invalid input");
dwSurfaceHandle = lpDDSLcl->lpSurfMore->dwSurfaceHandle;
// Find the handle list element associated with the local DD object,
// if there's none then select an empty one to be used
for (i = 0; i < MAX_CONTEXT_NUM;i++)
{
if (pDDLcl == HandleList[i].pDDLcl)
{
break; // found the right slot
}
else
if (0 == HandleList[i].pDDLcl && -1 == j)
{
j=i; // first empty slot !
}
}
// If we overrun the existing handle list elements, we need to
// initialize an existing empty slot or return an error.
if (i >= MAX_CONTEXT_NUM)
{
if (-1 != j)
{
//has an empty slot for this process, so use it
i = j;
HandleList[j].pDDLcl = pDDLcl;
ASSERTDD(NULL == HandleList[j].dwSurfaceList,"in SetTextureSlot");
}
else
{
//all process slots has been used, fail
DBG_D3D((0,"SetTextureSlot failed with pDDLcl=%x "
"dwSurfaceHandle=%08lx pTexture=%x",
pDDLcl,dwSurfaceHandle,pTexture));
return false;
}
}
ASSERTDD(i < MAX_CONTEXT_NUM, "in SetTextureSlot");
if ( NULL == HandleList[i].dwSurfaceList ||
dwSurfaceHandle >= PtrToUlong(HandleList[i].dwSurfaceList[0]))
{
// dwSurfaceHandle numbers are going to be ordinal numbers starting
// at one, so we use this number to figure out a "good" size for
// our new list.
DWORD newsize = ((dwSurfaceHandle + LISTGROWSIZE) / LISTGROWSIZE)
* LISTGROWSIZE;
PPERMEDIA_D3DTEXTURE *newlist= (PPERMEDIA_D3DTEXTURE *)
ENGALLOCMEM( FL_ZERO_MEMORY,
sizeof(PPERMEDIA_D3DTEXTURE)*newsize,
ALLOC_TAG);
DBG_D3D((4,"Growing pDDLcl=%x's SurfaceList[%x] size to %08lx",
pDDLcl,newlist,newsize));
if (NULL == newlist)
{
DBG_D3D((0,"SetTextureSlot failed to increase "
"HandleList[%d].dwSurfaceList",i));
return false;
}
memset(newlist,0,newsize);
// we had a formerly valid surfacehandle list, so we now must
// copy it over and free the memory allocated for it
if (NULL != HandleList[i].dwSurfaceList)
{
memcpy(newlist,HandleList[i].dwSurfaceList,
PtrToUlong(HandleList[i].dwSurfaceList[0]) *
sizeof(PPERMEDIA_D3DTEXTURE));
ENGFREEMEM(HandleList[i].dwSurfaceList);
DBG_D3D((4,"Freeing pDDLcl=%x's old SurfaceList[%x]",
pDDLcl,HandleList[i].dwSurfaceList));
}
HandleList[i].dwSurfaceList = newlist;
//store size in dwSurfaceList[0]
*(DWORD*)HandleList[i].dwSurfaceList = newsize;
}
// Store a pointer to the pTexture associated to this surface handle
HandleList[i].dwSurfaceList[dwSurfaceHandle] = pTexture;
pTexture->HandleListIndex = i; //store index here to facilitate search
DBG_D3D((4,"Set pDDLcl=%x Handle=%08lx pTexture = %x",
pDDLcl, dwSurfaceHandle, pTexture));
DBG_D3D((10,"Exiting SetTextureSlot"));
return true;
} // SetTextureSlot
//-----------------------------------------------------------------------------
//
// PPERMEDIA_D3DTEXTURE GetTextureSlot
//
// Find the pointer to the PPERMEDIA_D3DTEXTURE associated to the
// dwSurfaceHandle corresponding to the given local DD object
//
//-----------------------------------------------------------------------------
PPERMEDIA_D3DTEXTURE
GetTextureSlot(LPVOID pDDLcl, DWORD dwSurfaceHandle)
{
DBG_D3D((10,"Entering GetTextureSlot"));
DWORD i;
for (i = 0; i < MAX_CONTEXT_NUM; i++)
{
if (HandleList[i].pDDLcl == pDDLcl)
{
if (HandleList[i].dwSurfaceList &&
PtrToUlong(HandleList[i].dwSurfaceList[0]) > dwSurfaceHandle )
{
return HandleList[i].dwSurfaceList[dwSurfaceHandle];
}
else
break;
}
}
DBG_D3D((10,"Exiting GetTextureSlot"));
return NULL; //Not found
} // GetTextureSlot
//-----------------------------------------------------------------------------
//
// LPDWLIST GetSurfaceHandleList
//
// Get the handle list which is associated to a specific PDD_DIRECTDRAW_LOCAL
// pDDLcl. It is called from D3DContextCreate to get the handle list associated
// to the pDDLcl with which the context is being created.
//
//-----------------------------------------------------------------------------
LPDWLIST
GetSurfaceHandleList(LPVOID pDDLcl)
{
DWORD i;
DBG_D3D((10,"Entering GetSurfaceHandleList"));
ASSERTDD(NULL != pDDLcl, "GetSurfaceHandleList get NULL==pDDLcl");
for (i = 0; i < MAX_CONTEXT_NUM;i++)
{
if (HandleList[i].pDDLcl == pDDLcl)
{
DBG_D3D((4,"Getting pHandleList=%08lx for pDDLcl %x",
&HandleList[i],pDDLcl));
return &HandleList[i];
}
}
DBG_D3D((10,"Exiting GetSurfaceHandleList"));
return NULL; //No surface handle available yet
} // GetSurfaceHandleList
//-----------------------------------------------------------------------------
//
// void ReleaseSurfaceHandleList
//
// Free all the associated surface handle and palette memory pools associated
// to a given DD local object.
//
//-----------------------------------------------------------------------------
void
ReleaseSurfaceHandleList(LPVOID pDDLcl)
{
DWORD i;
DBG_D3D((10,"Entering ReleaseSurfaceHandleList"));
ASSERTDD(NULL != pDDLcl, "ReleaseSurfaceHandleList get NULL==pDDLcl");
for (i = 0; i < MAX_CONTEXT_NUM; i++)
{
if (HandleList[i].pDDLcl == pDDLcl)
{
DWORD j;
if (NULL != HandleList[i].dwSurfaceList)
{
DBG_D3D((4,"Releasing HandleList[%d].dwSurfaceList[%x] "
"for pDDLcl %x", i, HandleList[i].dwSurfaceList,
pDDLcl));
for (j = 1; j < PtrToUlong(HandleList[i].dwSurfaceList[0]); j++)
{
PERMEDIA_D3DTEXTURE* pTexture =
(PERMEDIA_D3DTEXTURE*)HandleList[i].dwSurfaceList[j];
if (NULL != pTexture)
{
PermediaSurfaceData *pPrivateData=
pTexture->pTextureSurface;
if (CHECK_P2_SURFACEDATA_VALIDITY(pPrivateData) &&
(pPrivateData->fpVidMem))
{
TextureCacheManagerRemove(&P2TextureManager,
pTexture);
}
ENGFREEMEM(pTexture);
}
}
ENGFREEMEM(HandleList[i].dwSurfaceList);
HandleList[i].dwSurfaceList = NULL;
}
HandleList[i].pDDLcl = NULL;
if (NULL != HandleList[i].dwPaletteList)
{
DBG_D3D((4,"Releasing dwPaletteList %x for pDDLcl %x",
HandleList[i].dwPaletteList,pDDLcl));
for (j = 1; j < PtrToUlong(HandleList[i].dwPaletteList[0]); j++)
{
LPVOID pPalette = (LPVOID)HandleList[i].dwPaletteList[j];
if (NULL != pPalette)
ENGFREEMEM(pPalette);
}
ENGFREEMEM(HandleList[i].dwPaletteList);
HandleList[i].dwPaletteList = NULL;
}
break;
}
}
DBG_D3D((10,"Exiting ReleaseSurfaceHandleList"));
} // ReleaseSurfaceHandleList
//-----------------------------Public Routine----------------------------------
//
// DWORD D3DGetDriverState
//
// This callback is used by both the DirectDraw and Direct3D runtimes to obtain
// information from the driver about its current state.
//
// Parameters
//
// lpgdsd
// pointer to GetDriverState data structure
//
// dwFlags
// Flags to indicate the data required
// dwhContext
// The ID of the context for which information
// is being requested
// lpdwStates
// Pointer to the state data to be filled in by the driver
// dwLength
// Length of the state data buffer to be filled
// in by the driver
// ddRVal
// Return value
//
// Return Value
//
// DDHAL_DRIVER_HANDLED
// DDHAL_DRIVER_NOTHANDLED
//-----------------------------------------------------------------------------
DWORD CALLBACK
D3DGetDriverState( LPDDHAL_GETDRIVERSTATEDATA lpgdsd )
{
PERMEDIA_D3DCONTEXT *pContext;
DBG_D3D((6,"Entering D3DGetDriverState"));
if (lpgdsd->dwFlags != D3DDEVINFOID_TEXTUREMANAGER)
{
DBG_D3D((0,"D3DGetDriverState DEVICEINFOID=%08lx not supported",
lpgdsd->dwFlags));
return DDHAL_DRIVER_NOTHANDLED;
}
if (lpgdsd->dwLength < sizeof(D3DDEVINFO_TEXTUREMANAGER))
{
DBG_D3D((0,"D3DGetDriverState dwLength=%d is not sufficient",
lpgdsd->dwLength));
return DDHAL_DRIVER_NOTHANDLED;
}
pContext = (PERMEDIA_D3DCONTEXT *)ContextSlots[lpgdsd->dwhContext] ;
// Check if we got a valid context handle.
CHK_CONTEXT(pContext, lpgdsd->ddRVal, "D3DGetDriverState");
TextureCacheManagerGetStats(pContext,
(LPD3DDEVINFO_TEXTUREMANAGER)lpgdsd->lpdwStates);
lpgdsd->ddRVal = DD_OK;
DBG_D3D((6,"Exiitng D3DGetDriverState"));
return DDHAL_DRIVER_HANDLED;
} // D3DGetDriverState
//-----------------------------------------------------------------------------
//
// __CreateSurfaceHandle
//
// allocate a new surface handle
//
// return value
//
// DD_OK -- no error
// DDERR_OUTOFMEMORY -- allocation of texture handle failed
//
//-----------------------------------------------------------------------------
DWORD __CreateSurfaceHandle( PPDev ppdev,
LPVOID pDDLcl,
LPDDRAWI_DDRAWSURFACE_LCL lpDDSLcl)
{
PPERMEDIA_D3DTEXTURE pTexture;
DUMPSURFACE(10, lpDDSLcl, NULL);
if (0 == lpDDSLcl->lpSurfMore->dwSurfaceHandle)
{
DBG_D3D((0,"D3DCreateSurfaceEx got 0 surfacehandle dwCaps=%08lx",
lpDDSLcl->ddsCaps.dwCaps));
return DD_OK;
}
pTexture =
GetTextureSlot(pDDLcl,lpDDSLcl->lpSurfMore->dwSurfaceHandle);
if ((0 == lpDDSLcl->lpGbl->fpVidMem) &&
(DDSCAPS_SYSTEMMEMORY & lpDDSLcl->ddsCaps.dwCaps))
{
// this is a system memory destroy notification
// so go ahead free the slot for this surface if we have it
if (NULL != pTexture)
{
ASSERTDD(HandleList[pTexture->HandleListIndex].dwSurfaceList
[lpDDSLcl->lpSurfMore->dwSurfaceHandle] == pTexture,
"__CreateSurfaceHandle: mismatching pTexture in HandleList");
HandleList[pTexture->HandleListIndex].dwSurfaceList
[lpDDSLcl->lpSurfMore->dwSurfaceHandle]=0;
ENGFREEMEM(pTexture);
DBG_D3D((8,"D3DCreateSurfaceEx freeing handle=%08lx dwCaps=%08lx",
lpDDSLcl->lpSurfMore->dwSurfaceHandle,lpDDSLcl->ddsCaps.dwCaps));
}
return DD_OK;
}
if (NULL == pTexture)
{
pTexture =
(PERMEDIA_D3DTEXTURE*)ENGALLOCMEM( FL_ZERO_MEMORY,
sizeof(PERMEDIA_D3DTEXTURE),
ALLOC_TAG);
if (NULL != pTexture)
{
if (!SetTextureSlot(pDDLcl,lpDDSLcl,pTexture))
{
// Free texture structure since we won't be able to remember it
// in order to later delete it. We must do it now.
ENGFREEMEM(pTexture);
return DDERR_OUTOFMEMORY;
}
}
else
{
DBG_D3D((0,"ERROR: Couldn't allocate Texture data mem"));
return DDERR_OUTOFMEMORY;
}
}
lpDDSLcl->dwReserved1=pTexture->HandleListIndex;
__InitD3DTextureWithDDSurfInfo(pTexture,lpDDSLcl,ppdev);
if (pTexture->dwCaps & DDSCAPS_TEXTURE)
{
for (int i = 1; i < MAX_CONTEXT_NUM; i++)
{
PERMEDIA_D3DCONTEXT *pContext =
(PERMEDIA_D3DCONTEXT *)ContextSlots[i];
if (IS_D3DCONTEXT_VALID(pContext))
{
DBG_D3D((4," Context 0x%x, Pointer 0x%x",
(DWORD)i, pContext));
if ((pContext->pDDLcl == pDDLcl)
&& (pContext->CurrentTextureHandle ==
lpDDSLcl->lpSurfMore->dwSurfaceHandle)
)
{
// If the texture being swapped is
// currently being used then we need
// to change the chip setup to reflect this.
DIRTY_TEXTURE;
}
}
}
}
return DD_OK;
}
//-----------------------------------------------------------------------------
//
// __CreateSurfaceHandleLoop
//
// allocate a list of new surface handles by traversing AttachList
// recursively and calling __CreateSurfaceHandle()
// only exceptions are for MIPMAP and CUBMAP, which we only
// use one handle to the root to represent the whole surface
// return value
//
// DD_OK -- no error
// DDERR_OUTOFMEMORY -- allocation of texture handle failed
//
//-----------------------------------------------------------------------------
DWORD __CreateSurfaceHandleLoop( PPDev ppdev,
LPVOID pDDLcl,
LPDDRAWI_DDRAWSURFACE_LCL lpDDSLclroot,
LPDDRAWI_DDRAWSURFACE_LCL lpDDSLcl)
{
LPATTACHLIST curr;
DWORD ddRVal=DD_OK;
// Now allocate the texture data space
if (0 == lpDDSLcl->lpSurfMore->dwSurfaceHandle)
{
DBG_D3D((0,"__CreateSurfaceHandleLoop got 0 handle dwCaps=%08lx",
lpDDSLcl->ddsCaps.dwCaps));
return DD_OK;
}
if ((0 == lpDDSLcl->lpGbl->dwReserved1) &&
(DDSCAPS_VIDEOMEMORY & lpDDSLcl->ddsCaps.dwCaps)
)
{
DBG_D3D((4,"__CreateSurfaceHandleLoop got "
"handle=%08lx dwCaps=%08lx not yet created",
lpDDSLcl->lpSurfMore->dwSurfaceHandle,lpDDSLcl->ddsCaps.dwCaps));
return DD_OK;
}
DBG_D3D((4,"** In __CreateSurfaceHandleLoop %08lx %08lx %08lx %08lx %x",
lpDDSLcl->ddsCaps.dwCaps,lpDDSLcl->lpSurfMore->dwSurfaceHandle,
lpDDSLcl->dwFlags,lpDDSLcl->lpGbl->dwReserved1,
lpDDSLcl->lpGbl->fpVidMem));
ddRVal=__CreateSurfaceHandle( ppdev, pDDLcl, lpDDSLcl);
if (DD_OK != ddRVal)
{
return ddRVal;
}
// for some surfaces other than MIPMAP or CUBEMAP, such as
// flipping chains, we make a slot for every surface, as
// they are not as interleaved
if ((lpDDSLcl->ddsCaps.dwCaps & DDSCAPS_MIPMAP) ||
(lpDDSLcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_CUBEMAP)
)
{
return DD_OK;
}
curr = lpDDSLcl->lpAttachList;
if (NULL == curr)
return DD_OK;
// check if there is another surface attached!
if (curr->lpLink)
{
lpDDSLcl=curr->lpLink->lpAttached;
if (NULL != lpDDSLcl && lpDDSLcl != lpDDSLclroot)
{
ddRVal=__CreateSurfaceHandleLoop( ppdev, pDDLcl,
lpDDSLclroot, lpDDSLcl);
if (DD_OK != ddRVal)
{
return ddRVal;
}
}
}
lpDDSLcl=curr->lpAttached;
if (NULL != lpDDSLcl && lpDDSLcl != lpDDSLclroot)
ddRVal=__CreateSurfaceHandleLoop( ppdev, pDDLcl,
lpDDSLclroot, lpDDSLcl);
return ddRVal;
}
//-----------------------------Public Routine----------------------------------
//
// DWORD D3DCreateSurfaceEx
//
// D3dCreateSurfaceEx creates a Direct3D surface from a DirectDraw surface and
// associates a requested handle value to it.
//
// All Direct3D drivers must support D3dCreateSurfaceEx.
//
// D3dCreateSurfaceEx creates an association between a DirectDraw surface and
// a small integer surface handle. By creating these associations between a
// handle and a DirectDraw surface, D3dCreateSurfaceEx allows a surface handle
// to be imbedded in the Direct3D command stream. For example when the
// D3DDP2OP_TEXBLT command token is sent to D3dDrawPrimitives2 to load a texture
// map, it uses a source handle and destination handle which were associated
// with a DirectDraw surface through D3dCreateSurfaceEx.
//
// For every DirectDraw surface created under the local DirectDraw object, the
// runtime generates a valid handle that uniquely identifies the surface and
// places it in pcsxd->lpDDSLcl->lpSurfMore->dwSurfaceHandle. This handle value
// is also used with the D3DRENDERSTATE_TEXTUREHANDLE render state to enable
// texturing, and with the D3DDP2OP_SETRENDERTARGET and D3DDP2OP_CLEAR commands
// to set and/or clear new rendering and depth buffers. The driver should fail
// the call and return DDHAL_DRIVER_HANDLE if it cannot create the Direct3D
// surface.
//
// As appropriate, the driver should also store any surface-related information
// that it will subsequently need when using the surface. The driver must create
// a new surface table for each new lpDDLcl and implicitly grow the table when
// necessary to accommodate more surfaces. Typically this is done with an
// exponential growth algorithm so that you don't have to grow the table too
// often. Direct3D calls D3dCreateSurfaceEx after the surface is created by
// DirectDraw by request of the Direct3D runtime or the application.
//
// Parameters
//
// lpcsxd
// pointer to CreateSurfaceEx structure that contains the information
// required for the driver to create the surface (described below).
//
// dwFlags
// Currently unused
// lpDDLcl
// Handle to the DirectDraw object created by the application.
// This is the scope within which the lpDDSLcl handles exist.
// A DD_DIRECTDRAW_LOCAL structure describes the driver.
// lpDDSLcl
// Handle to the DirectDraw surface we are being asked to
// create for Direct3D. These handles are unique within each
// different DD_DIRECTDRAW_LOCAL. A DD_SURFACE_LOCAL structure
// represents the created surface object.
// ddRVal
// Specifies the location in which the driver writes the return
// value of the D3dCreateSurfaceEx callback. A return code of
// DD_OK indicates success.
//
// Return Value
//
// DDHAL_DRIVER_HANDLE
// DDHAL_DRIVER_NOTHANDLE
//
//-----------------------------------------------------------------------------
DWORD CALLBACK
D3DCreateSurfaceEx( LPDDHAL_CREATESURFACEEXDATA lpcsxd )
{
PPERMEDIA_D3DTEXTURE pTexture;
LPVOID pDDLcl= (LPVOID)lpcsxd->lpDDLcl;
LPDDRAWI_DDRAWSURFACE_LCL lpDDSLcl=lpcsxd->lpDDSLcl;
LPATTACHLIST curr;
DBG_D3D((6,"Entering D3DCreateSurfaceEx"));
lpcsxd->ddRVal = DD_OK;
if (NULL == lpDDSLcl || NULL == pDDLcl)
{
DBG_D3D((0,"D3DCreateSurfaceEx received 0 lpDDLcl or lpDDSLcl pointer"));
return DDHAL_DRIVER_HANDLED;
}
// We check that what we are handling is a texture, zbuffer or a rendering
// target buffer. We don't check if it is however stored in local video
// memory since it might also be a system memory texture that we will later
// blt with __TextureBlt.
// also if your driver supports DDSCAPS_EXECUTEBUFFER create itself, it must
// process DDSCAPS_EXECUTEBUFFER here as well.
if (!(lpDDSLcl->ddsCaps.dwCaps &
(DDSCAPS_TEXTURE |
DDSCAPS_3DDEVICE |
DDSCAPS_ZBUFFER))
)
{
DBG_D3D((2,"D3DCreateSurfaceEx w/o "
"DDSCAPS_TEXTURE/3DDEVICE/ZBUFFER Ignored"
"dwCaps=%08lx dwSurfaceHandle=%08lx",
lpDDSLcl->ddsCaps.dwCaps,
lpDDSLcl->lpSurfMore->dwSurfaceHandle));
return DDHAL_DRIVER_HANDLED;
}
DBG_D3D((4,"Entering D3DCreateSurfaceEx handle=%08lx",
lpDDSLcl->lpSurfMore->dwSurfaceHandle));
PPDev ppdev=(PPDev)lpcsxd->lpDDLcl->lpGbl->dhpdev;
PERMEDIA_DEFS(ppdev);
//@@BEGIN_DDKSPLIT
#if MULTITHREADED
if(ppdev->ulLockCount)
{
DBG_D3D((MT_LOG_LEVEL, "D3DCreateSurfaceEx: re-entry! %d", ppdev->ulLockCount));
}
EngAcquireSemaphore(ppdev->hsemLock);
ppdev->ulLockCount++;
#endif
//@@END_DDKSPLIT
// Now allocate the texture data space
lpcsxd->ddRVal = __CreateSurfaceHandleLoop( ppdev, pDDLcl, lpDDSLcl, lpDDSLcl);
DBG_D3D((4,"Exiting D3DCreateSurfaceEx"));
//@@BEGIN_DDKSPLIT
#if MULTITHREADED
ppdev->ulLockCount--;
EngReleaseSemaphore(ppdev->hsemLock);
#endif
//@@END_DDKSPLIT
return DDHAL_DRIVER_HANDLED;
} // D3DCreateSurfaceEx
//-----------------------------Public Routine----------------------------------
//
// DWORD D3DDestroyDDLocal
//
// D3dDestroyDDLocal destroys all the Direct3D surfaces previously created by
// D3DCreateSurfaceEx that belong to the same given local DirectDraw object.
//
// All Direct3D drivers must support D3dDestroyDDLocal.
// Direct3D calls D3dDestroyDDLocal when the application indicates that the
// Direct3D context is no longer required and it will be destroyed along with
// all surfaces associated to it. The association comes through the pointer to
// the local DirectDraw object. The driver must free any memory that the
// driver's D3dCreateSurfaceExDDK_D3dCreateSurfaceEx_GG callback allocated for
// each surface if necessary. The driver should not destroy the DirectDraw
// surfaces associated with these Direct3D surfaces; this is the application's
// responsibility.
//
// Parameters
//
// lpdddd
// Pointer to the DestoryLocalDD structure that contains the
// information required for the driver to destroy the surfaces.
//
// dwFlags
// Currently unused
// pDDLcl
// Pointer to the local Direct Draw object which serves as a
// reference for all the D3D surfaces that have to be destroyed.
// ddRVal
// Specifies the location in which the driver writes the return
// value of D3dDestroyDDLocal. A return code of DD_OK indicates
// success.
//
// Return Value
//
// DDHAL_DRIVER_HANDLED
// DDHAL_DRIVER_NOTHANDLED
//-----------------------------------------------------------------------------
DWORD CALLBACK
D3DDestroyDDLocal( LPDDHAL_DESTROYDDLOCALDATA lpdddd )
{
DBG_D3D((6,"Entering D3DDestroyDDLocal"));
//@@BEGIN_DDKSPLIT
#if MULTITHREADED
PPDev ppdev=(PPDev)lpdddd->pDDLcl->lpGbl->dhpdev;
if(ppdev->ulLockCount)
{
DBG_D3D((MT_LOG_LEVEL, "D3DCreateSurfaceEx: re-entry! %d", ppdev->ulLockCount));
}
EngAcquireSemaphore(ppdev->hsemLock);
ppdev->ulLockCount++;
#endif
//@@END_DDKSPLIT
ReleaseSurfaceHandleList(LPVOID(lpdddd->pDDLcl));
lpdddd->ddRVal = DD_OK;
DBG_D3D((6,"Exiting D3DDestroyDDLocal"));
//@@BEGIN_DDKSPLIT
#if MULTITHREADED
ppdev->ulLockCount--;
EngReleaseSemaphore(ppdev->hsemLock);
#endif
//@@END_DDKSPLIT
return DDHAL_DRIVER_HANDLED;
} // D3DDestroyDDLocal
//-----------------------------Public Routine----------------------------------
//
// DdSetColorkey
//
// DirectDraw SetColorkey callback
//
// Parameters
// lpSetColorKey
// Pointer to the LPDDHAL_SETCOLORKEYDATA parameters structure
//
// lpDDSurface
// Surface struct
// dwFlags
// Flags
// ckNew
// New chroma key color values
// ddRVal
// Return value
// SetColorKey
// Unused: Win95 compatibility
//
//-----------------------------------------------------------------------------
DWORD CALLBACK
DdSetColorKey(LPDDHAL_SETCOLORKEYDATA lpSetColorKey)
{
DWORD dwSurfaceHandle =
lpSetColorKey->lpDDSurface->lpSurfMore->dwSurfaceHandle;
DWORD index = (DWORD)lpSetColorKey->lpDDSurface->dwReserved1;
DBG_D3D((6,"Entering DdSetColorKey dwSurfaceHandle=%d index=%d",
dwSurfaceHandle, index));
lpSetColorKey->ddRVal = DD_OK;
// We don't have to do anything for normal blt source colour keys:
if (!(DDSCAPS_TEXTURE & lpSetColorKey->lpDDSurface->ddsCaps.dwCaps) ||
!(DDSCAPS_VIDEOMEMORY & lpSetColorKey->lpDDSurface->ddsCaps.dwCaps)
)
{
return(DDHAL_DRIVER_HANDLED);
}
if (0 != dwSurfaceHandle && NULL != HandleList[index].dwSurfaceList)
{
PERMEDIA_D3DTEXTURE *pTexture =
HandleList[index].dwSurfaceList[dwSurfaceHandle];
ASSERTDD(PtrToUlong(HandleList[index].dwSurfaceList[0]) > dwSurfaceHandle,
"SetColorKey: incorrect dwSurfaceHandle");
if (NULL != pTexture)
{
DBG_D3D((4, "DdSetColorKey surface=%08lx KeyLow=%08lx",
dwSurfaceHandle,pTexture->dwKeyLow));
pTexture->dwFlags |= DDRAWISURF_HASCKEYSRCBLT;
pTexture->dwKeyLow = lpSetColorKey->ckNew.dwColorSpaceLowValue;
pTexture->dwKeyHigh = lpSetColorKey->ckNew.dwColorSpaceHighValue;
}
}
else
{
lpSetColorKey->ddRVal = DDERR_INVALIDPARAMS;
}
DBG_D3D((6,"Exiting DdSetColorKey"));
return DDHAL_DRIVER_HANDLED;
} // DdSetColorKey
//@@BEGIN_DDKSPLIT
#if MULTITHREADED
//-----------------------------------------------------------------------------
//
// Multithread support wrappers for D3D callback functions
//
//-----------------------------------------------------------------------------
//DWORD CALLBACK MtD3DDrawPrimitives2(LPD3DNTHAL_DRAWPRIMITIVES2DATA pdp2);,
WRAPMTDXCALLBACK(D3D, D3DDrawPrimitives2, LPD3DNTHAL_DRAWPRIMITIVES2DATA, pdp2,
((PERMEDIA_D3DCONTEXT *)ContextSlots[pdp2->dwhContext])->ppdev)
//DWORD CALLBACK MtDdSetColorKey(LPDDHAL_SETCOLORKEYDATA lpSetColorKey);
WRAPMTDXCALLBACK(D3D, DdSetColorKey, LPDDHAL_SETCOLORKEYDATA, lpSetColorKey,
lpSetColorKey->lpDD->dhpdev);
#endif MULTITHREADED
//@@END_DDKSPLIT