|
|
/******************************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
|