|
|
/******************************Module*Header**********************************\
* * ************************** * * DirectDraw SAMPLE CODE * * ************************** * * Module Name: dd.c * * Content: * * Copyright (c) 1994-1998 3Dlabs Inc. Ltd. All rights reserved. * Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved. \*****************************************************************************/
#define INITGUID
#include "precomp.h"
#include <mmsystem.h>
#include "directx.h"
#include "dd.h"
#include "d3dhw.h"
#include "d3dtext.h"
#include "heap.h"
//-----------------------------------------------------------------------------
//
// use bits to indicate which ROPs you support.
//
// DWORD 0, bit 0 == ROP 0
// DWORD 8, bit 31 == ROP 255
//
//-----------------------------------------------------------------------------
static BYTE ropList[] = { SRCCOPY >> 16, };
static DWORD rops[DD_ROP_SPACE] = { 0 };
// The FourCC's we support
static DWORD fourCC[] = { FOURCC_YUV422 };
//-----------------------------------------------------------------------------
//
// setupRops
//
// build array for supported ROPS
//
//-----------------------------------------------------------------------------
VOID setupRops( LPBYTE proplist, LPDWORD proptable, int cnt ) { INT i; DWORD idx; DWORD bit; DWORD rop;
for(i=0; i<cnt; i++) { rop = proplist[i]; idx = rop / 32; bit = 1L << ((DWORD)(rop % 32)); proptable[idx] |= bit; }
} // setupRops
//-----------------------------------------------------------------------------
//
// P2DisableAllUnits
//
// reset permedia rasterizer to known state
//
//-----------------------------------------------------------------------------
VOID P2DisableAllUnits(PPDev ppdev) { PERMEDIA_DEFS(ppdev);
RESERVEDMAPTR(47); SEND_PERMEDIA_DATA(RasterizerMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(AreaStippleMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(ScissorMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(ColorDDAMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(FogMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(LBReadMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(Window, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(StencilMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(DepthMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(LBWriteMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(FBReadMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(DitherMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(LogicalOpMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(FBWriteMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(StatisticMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(AlphaBlendMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(FilterMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(FBSourceData, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(LBWriteFormat, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(TextureReadMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(TextureMapFormat, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(TextureDataFormat, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(TexelLUTMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(TextureColorMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(YUVMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(AStart, PM_BYTE_COLOR(0xFF)); SEND_PERMEDIA_DATA(TextureBaseAddress, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(TexelLUTIndex, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(TexelLUTTransfer, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(TextureAddressMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(AlphaMapUpperBound, 0); SEND_PERMEDIA_DATA(AlphaMapLowerBound, 0); SEND_PERMEDIA_DATA(Color, 0);
SEND_PERMEDIA_DATA(FBWriteMode, __PERMEDIA_ENABLE); SEND_PERMEDIA_DATA(FBPixelOffset, 0x0); SEND_PERMEDIA_DATA(FBHardwareWriteMask, __PERMEDIA_ALL_WRITEMASKS_SET); SEND_PERMEDIA_DATA(FBSoftwareWriteMask, __PERMEDIA_ALL_WRITEMASKS_SET);
// We sometimes use the scissor in DDRAW to scissor out unnecessary pixels.
SEND_PERMEDIA_DATA(ScissorMinXY, 0); SEND_PERMEDIA_DATA(ScissorMaxXY, (ppdev->cyMemory << 16) | (ppdev->cxMemory)); SEND_PERMEDIA_DATA(ScreenSize, (ppdev->cyMemory << 16) | (ppdev->cxMemory));
SEND_PERMEDIA_DATA(WindowOrigin, 0x0);
// DirectDraw might not need to set these up
SEND_PERMEDIA_DATA(dXDom, 0x0); SEND_PERMEDIA_DATA(dXSub, 0x0);
// set max size, no filtering
SEND_PERMEDIA_DATA(TextureReadMode, PM_TEXREADMODE_ENABLE(__PERMEDIA_ENABLE) | PM_TEXREADMODE_FILTER(__PERMEDIA_DISABLE) | PM_TEXREADMODE_WIDTH(11) | PM_TEXREADMODE_HEIGHT(11) );
// 16 bit Z, no other buffers
SEND_PERMEDIA_DATA(LBWriteFormat, __PERMEDIA_DEPTH_WIDTH_16);
// Ensure an extra LBData message doesn't flow through the core.
SEND_PERMEDIA_DATA(Window, PM_WINDOW_DISABLELBUPDATE(__PERMEDIA_ENABLE));
SEND_PERMEDIA_DATA(FBReadPixel, ppdev->bPixShift);
COMMITDMAPTR(); FLUSHDMA();
} // P2DisableAllUnits
//-----------------------------------------------------------------------------
//
// GetDDHALInfo
//
// Takes a pointer to a partially or fully filled in ppdev and a pointer
// to an empty DDHALINFO and fills in the DDHALINFO.
//
//-----------------------------------------------------------------------------
VOID GetDDHALInfo(PPDev ppdev, DDHALINFO* pHALInfo) { DWORD dwResult; BOOL bRet;
DBG_DD(( 5, "DDraw:GetDDHalInfo"));
// Setup the HAL driver caps.
memset( pHALInfo, 0, sizeof(DDHALINFO)); pHALInfo->dwSize = sizeof(DDHALINFO);
// Setup the ROPS we do.
setupRops( ropList, rops, sizeof(ropList)/sizeof(ropList[0]));
// The most basic DirectDraw functionality
pHALInfo->ddCaps.dwCaps = DDCAPS_BLT | DDCAPS_BLTQUEUE | DDCAPS_BLTCOLORFILL | DDCAPS_READSCANLINE;
pHALInfo->ddCaps.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP;
// add caps for D3D
pHALInfo->ddCaps.dwCaps |= DDCAPS_3D | DDCAPS_ALPHA | DDCAPS_BLTDEPTHFILL;
// add surface caps for D3D
pHALInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_ALPHA | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER;
// Permedia can do
// 1. Stretching/Shrinking
// 2. YUV->RGB conversion (only non paletted mode)
// 3. Mirroring in X and Y
// add Permedia caps to global caps
pHALInfo->ddCaps.dwCaps |= DDCAPS_BLTSTRETCH | DDCAPS_COLORKEY | DDCAPS_CANBLTSYSMEM;
#if DX7_STEREO
// check if mode supports stereo
DD_STEREOMODE DDStereoMode; DDStereoMode.dwHeight = ppdev->cyScreen; DDStereoMode.dwWidth = ppdev->cxScreen; DDStereoMode.dwBpp = ppdev->cBitsPerPel; DDStereoMode.dwRefreshRate= 0; ppdev->bCanDoStereo=bIsStereoMode(ppdev,&DDStereoMode);
// Stereo caps are set if the driver can do stereo in any mode:
pHALInfo->ddCaps.dwCaps2 |= DDCAPS2_STEREO; pHALInfo->ddCaps.dwSVCaps = DDSVCAPS_STEREOSEQUENTIAL; #endif
pHALInfo->ddCaps.dwCaps2 |= DDCAPS2_CANMANAGETEXTURE;
//declare we can handle textures wider than the primary
pHALInfo->ddCaps.dwCaps2 |= DDCAPS2_WIDESURFACES;
// Special effects caps
pHALInfo->ddCaps.dwFXCaps = DDFXCAPS_BLTSTRETCHY | DDFXCAPS_BLTSTRETCHX | DDFXCAPS_BLTSTRETCHYN | DDFXCAPS_BLTSTRETCHXN | DDFXCAPS_BLTSHRINKY | DDFXCAPS_BLTSHRINKX | DDFXCAPS_BLTSHRINKYN | DDFXCAPS_BLTSHRINKXN | DDFXCAPS_BLTMIRRORUPDOWN | DDFXCAPS_BLTMIRRORLEFTRIGHT;
// add AlphaBlt and Filter caps
pHALInfo->ddCaps.dwFXCaps |= DDFXCAPS_BLTALPHA | DDFXCAPS_BLTFILTER;
// colorkey caps, only src color key supported
pHALInfo->ddCaps.dwCKeyCaps = DDCKEYCAPS_SRCBLT | DDCKEYCAPS_SRCBLTCLRSPACE;
// We can do a texture from sysmem to video mem blt.
pHALInfo->ddCaps.dwSVBCaps = DDCAPS_BLT; pHALInfo->ddCaps.dwSVBCKeyCaps = 0; pHALInfo->ddCaps.dwSVBFXCaps = 0;
// Fill in the sysmem->vidmem rops (only can copy);
for(int i=0;i<DD_ROP_SPACE;i++ ) { pHALInfo->ddCaps.dwSVBRops[i] = rops[i]; }
if (ppdev->iBitmapFormat != BMF_8BPP) { pHALInfo->ddCaps.dwCaps |= DDCAPS_BLTFOURCC; pHALInfo->ddCaps.dwCKeyCaps |= DDCKEYCAPS_SRCBLTCLRSPACEYUV; }
pHALInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_TEXTURE;
// Z Buffer is only 16 Bits on Permedia
pHALInfo->ddCaps.dwZBufferBitDepths = DDBD_16;
#if D3D_MIPMAPPING
// Mip Mapping
pHALInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_MIPMAP; #endif
if (DD_P2AGPCAPABLE(ppdev)) { DBG_DD((1, "GetDDHALInfo: P2 AGP board - supports NONLOCALVIDMEM"));
pHALInfo->ddCaps.dwCaps2 |= DDCAPS2_NONLOCALVIDMEM | DDCAPS2_NONLOCALVIDMEMCAPS; pHALInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM; } else { DBG_DD((1,"GetDDHALInfo: P2 Board is NOT AGP")); }
// Won't do Video-Sys mem Blits.
pHALInfo->ddCaps.dwVSBCaps = 0; pHALInfo->ddCaps.dwVSBCKeyCaps = 0; pHALInfo->ddCaps.dwVSBFXCaps = 0; for( i=0;i<DD_ROP_SPACE;i++ ) { pHALInfo->ddCaps.dwVSBRops[i] = 0; }
// Won't do Sys-Sys mem Blits
pHALInfo->ddCaps.dwSSBCaps = 0; pHALInfo->ddCaps.dwSSBCKeyCaps = 0; pHALInfo->ddCaps.dwSSBFXCaps = 0; for( i=0;i<DD_ROP_SPACE;i++ ) { pHALInfo->ddCaps.dwSSBRops[i] = 0; }
// bit depths supported for alpha and Z
pHALInfo->ddCaps.dwAlphaBltConstBitDepths = DDBD_2 | DDBD_4 | DDBD_8; pHALInfo->ddCaps.dwAlphaBltPixelBitDepths = DDBD_1 | DDBD_8; pHALInfo->ddCaps.dwAlphaBltSurfaceBitDepths = DDBD_1 | DDBD_2 | DDBD_4 | DDBD_8; pHALInfo->ddCaps.dwAlphaOverlayConstBitDepths = DDBD_2 | DDBD_4 | DDBD_8; pHALInfo->ddCaps.dwAlphaOverlayPixelBitDepths = DDBD_1 | DDBD_8; pHALInfo->ddCaps.dwAlphaOverlaySurfaceBitDepths = DDBD_1 | DDBD_2 | DDBD_4 | DDBD_8;
// ROPS supported
for( i=0;i<DD_ROP_SPACE;i++ ) { pHALInfo->ddCaps.dwRops[i] = rops[i]; }
// For DX5 and beyond we support this new informational callback.
pHALInfo->GetDriverInfo = DdGetDriverInfo; pHALInfo->dwFlags |= DDHALINFO_GETDRIVERINFOSET;
// now setup D3D callbacks
D3DHALCreateDriver( ppdev, (LPD3DHAL_GLOBALDRIVERDATA*) &pHALInfo->lpD3DGlobalDriverData, (LPD3DHAL_CALLBACKS*) &pHALInfo->lpD3DHALCallbacks, (LPDDHAL_D3DBUFCALLBACKS*) &pHALInfo->lpD3DBufCallbacks);
if(pHALInfo->lpD3DGlobalDriverData == NULL) { // no D3D available - kill caps we set before
pHALInfo->ddCaps.dwCaps &= ~(DDCAPS_3D | DDCAPS_BLTDEPTHFILL); pHALInfo->ddCaps.ddsCaps.dwCaps &= ~(DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER); }
} // GetHALInfo
//-----------------------------------------------------------------------------
//
// Global DirectDraw Callbacks
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
// DdFlip
//
// This callback is invoked whenever we are about to flip to from
// one surface to another. lpFlipData->lpSurfCurr is the surface we were at,
// lpFlipData->lpSurfTarg is the one we are flipping to.
//
// You should point the hardware registers at the new surface, and
// also keep track of the surface that was flipped away from, so
// that if the user tries to lock it, you can be sure that it is done
// being displayed
//
//-----------------------------------------------------------------------------
DWORD CALLBACK DdFlip( LPDDHAL_FLIPDATA lpFlipData) { PPDev ppdev=(PPDev)lpFlipData->lpDD->dhpdev; PERMEDIA_DEFS(ppdev);
DWORD dwDDSurfaceOffset; HRESULT ddrval;
DBG_DD(( 3, "DDraw:Flip"));
// Switch to DirectDraw context
DDCONTEXT;
// is the previous Flip already done?
// check if the current surface is already displayed
ddrval = updateFlipStatus(ppdev); if( FAILED(ddrval) ) { lpFlipData->ddRVal = ddrval; return DDHAL_DRIVER_HANDLED; }
// everything is OK, do the flip.
// get offset for Permedia ScreenBase register
dwDDSurfaceOffset=(DWORD)lpFlipData->lpSurfTarg->lpGbl->fpVidMem;
#if DX7_STEREO
if (lpFlipData->dwFlags & DDFLIP_STEREO) // will be stereo
{ DBG_DD((4,"DDraw:Flip:Stereo")); DBG_DD((5,"ScreenBase: %08lx", dwDDSurfaceOffset));
if (lpFlipData->lpSurfTargLeft!=NULL) { DWORD dwDDLeftSurfaceOffset; dwDDLeftSurfaceOffset=(DWORD) lpFlipData->lpSurfTargLeft->lpGbl->fpVidMem; LD_PERMEDIA_REG(PREG_SCREENBASERIGHT,dwDDLeftSurfaceOffset>>3); DBG_DD((5,"ScreenBaseLeft: %08lx", dwDDLeftSurfaceOffset)); }
ULONG ulVControl=READ_PERMEDIA_REG(PREG_VIDEOCONTROL); if ((ulVControl&PREG_VC_STEREOENABLE)==0 || !ppdev->bDdStereoMode) { ppdev->bDdStereoMode=TRUE; LD_PERMEDIA_REG(PREG_VIDEOCONTROL, ulVControl | PREG_VC_STEREOENABLE); } } else #endif // DX7_STEREO
{ // append flip command to Permedia render pipeline
// that makes sure that all buffers are flushed before
// the flip occurs
#if DX7_STEREO
if (ppdev->bDdStereoMode) { ppdev->bDdStereoMode=FALSE; LD_PERMEDIA_REG(PREG_VIDEOCONTROL, READ_PERMEDIA_REG(PREG_VIDEOCONTROL)& ~PREG_VC_STEREOENABLE); } #endif
}
// adjust base address according to register spec.
dwDDSurfaceOffset>>=3;
// add new base address to render pipeline
RESERVEDMAPTR(1); LD_INPUT_FIFO(__Permedia2TagSuspendUntilFrameBlank, dwDDSurfaceOffset); COMMITDMAPTR(); FLUSHDMA();
// remember new Surface Offset for GetFlipStatus
ppdev->dwNewDDSurfaceOffset=dwDDSurfaceOffset;
lpFlipData->ddRVal = DD_OK; return DDHAL_DRIVER_HANDLED;
} // DdFlip
//-----------------------------------------------------------------------------
//
// DdWaitForVerticalBlank
//
// This callback is invoked to get information about the vertical blank
// status of the display or to wait until the display is at the begin or
// the end of the vertical blank
//
//-----------------------------------------------------------------------------
DWORD CALLBACK DdWaitForVerticalBlank(LPDDHAL_WAITFORVERTICALBLANKDATA lpWaitForVerticalBlank) { static int bInVBlank = FALSE; PPDev ppdev=(PPDev)lpWaitForVerticalBlank->lpDD->dhpdev;
DBG_DD(( 2, "DDraw:WaitForVerticalBlank"));
switch(lpWaitForVerticalBlank->dwFlags) {
case DDWAITVB_I_TESTVB:
// If the monitor is off, we don't always want to report
// the same status or else an app polling this status
// might hang
if( !(READ_PERMEDIA_REG(PREG_VIDEOCONTROL) & PREG_VC_VIDEO_ENABLE)) { lpWaitForVerticalBlank->bIsInVB = bInVBlank; bInVBlank = !bInVBlank; } else { // Just a request for current VBLANK status.
lpWaitForVerticalBlank->bIsInVB = IN_VRETRACE(ppdev); }
lpWaitForVerticalBlank->ddRVal = DD_OK; return DDHAL_DRIVER_HANDLED;
case DDWAITVB_BLOCKBEGIN:
// we don't care to wait if the monitor is off
if( READ_PERMEDIA_REG(PREG_VIDEOCONTROL) & PREG_VC_VIDEO_ENABLE) { // if blockbegin is requested we wait until the vertical retrace
// is over, and then wait for the display period to end.
while(IN_VRETRACE(ppdev)); while(IN_DISPLAY(ppdev)); }
lpWaitForVerticalBlank->ddRVal = DD_OK; return DDHAL_DRIVER_HANDLED;
case DDWAITVB_BLOCKEND:
// we don't care to wait if the monitor is off
if( READ_PERMEDIA_REG(PREG_VIDEOCONTROL) & PREG_VC_VIDEO_ENABLE) { // if blockend is requested we wait for the vblank interval to end.
if( IN_VRETRACE(ppdev) ) { while( IN_VRETRACE(ppdev) ); } else { while(IN_DISPLAY(ppdev)); while(IN_VRETRACE(ppdev)); } }
lpWaitForVerticalBlank->ddRVal = DD_OK; return DDHAL_DRIVER_HANDLED; }
return DDHAL_DRIVER_NOTHANDLED;
} // WaitForVerticalBlank
//-----------------------------------------------------------------------------
//
// Lock
//
// This call is invoked to lock a DirectDraw Videomemory surface. To make
// sure there are no pending drawing operations on the surface, flush all
// drawing operations and wait for a flip if it is still pending.
//
//-----------------------------------------------------------------------------
DWORD CALLBACK DdLock( LPDDHAL_LOCKDATA lpLockData ) { PPDev ppdev=(PPDev)lpLockData->lpDD->dhpdev; PERMEDIA_DEFS(ppdev);
HRESULT ddrval; DWORD pSurf;
DBG_DD(( 2, "DDraw:Lock"));
//
// Switch to DirectDraw context
//
DDCONTEXT;
// check to see if any pending physical flip has occurred
ddrval = updateFlipStatus(ppdev); if( FAILED(ddrval) ) { lpLockData->ddRVal = DDERR_WASSTILLDRAWING; return DDHAL_DRIVER_HANDLED; }
//
// don't allow a lock if a blt is in progress
//
if(DRAW_ENGINE_BUSY) { DBG_DD((2,"DDraw:Lock, DrawEngineBusy")); FLUSHDMA(); lpLockData->ddRVal = DDERR_WASSTILLDRAWING; return DDHAL_DRIVER_HANDLED; }
// send a flush and wait for outstanding operations
// before allowing surfaces to be locked.
SYNC_WITH_PERMEDIA;
// now check if the user wants to lock a texture surface,
// which was loaded as patched! In this case we have to to
// a blit to unpatch before we return it to the user
// This is not expensive, since we leave it unpatched for
// the future when the application decides to use it this way
LPDDRAWI_DDRAWSURFACE_LCL pLcl=lpLockData->lpDDSurface; LPDDRAWI_DDRAWSURFACE_GBL pGbl=pLcl->lpGbl; PermediaSurfaceData *pPrivate= (PermediaSurfaceData*)pGbl->dwReserved1;
//
// If the user attempts to lock a managed surface, mark it as dirty
// and return.
//
if (pLcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_TEXTUREMANAGE) { DBG_DD(( 3, "DDraw:Lock %08lx %08lx", pLcl->lpSurfMore->dwSurfaceHandle, pGbl->fpVidMem)); if (NULL != pPrivate) pPrivate->dwFlags |= P2_SURFACE_NEEDUPDATE; lpLockData->lpSurfData = (LPVOID)(pLcl->lpGbl->fpVidMem + (pLcl->lpGbl->lPitch * lpLockData->rArea.top) + (lpLockData->rArea.left << DDSurf_GetPixelShift(pLcl))); lpLockData->ddRVal = DD_OK; return DDHAL_DRIVER_HANDLED; }
DD_CHECK_PRIMARY_SURFACE_DATA(pLcl,pPrivate);
//
// We only need to unswizzle a surface if the
// PrivateData is in a format we know (pPrivate!=NULL)
//
if (pPrivate!=NULL) { //
// if the surface is a texture which was loaded in a swizzled
// format, we have to undo the swizzle before succeding the lock.
// In this driver, a texture remains unswizzled when a user
// attempted to lock it once.
//
if (pPrivate->dwFlags & P2_ISPATCHED) { //
// The scratchpad must be 32 lines high and should have
// the same width as our original surface.
//
PermediaSurfaceData ScratchData=*pPrivate; LONG lScratchDelta; VIDEOMEMORY* pvmHeap; ULONG ulScratchOffset= ulVidMemAllocate( ppdev, DDSurf_Width(pLcl), DDSurf_Height(pLcl), DDSurf_GetPixelShift(pLcl), &lScratchDelta, &pvmHeap, &ScratchData.ulPackedPP, FALSE);
DBG_DD(( 5, " unswizzle surface, scratchpad at: %08lx", ulScratchOffset)); if (ulScratchOffset!=0) { RECTL rSurfRect; RECTL rScratchRect;
rSurfRect.left=0; rSurfRect.top=0; rSurfRect.right=DDSurf_Width(pLcl); rSurfRect.bottom=32;
rScratchRect=rSurfRect;
// scratchpad should be non patched
ScratchData.dwFlags &= ~(P2_ISPATCHED|P2_CANPATCH);
LONG lSurfOffset; DWORD dwSurfBase=(DWORD)pGbl->fpVidMem >> DDSurf_GetPixelShift(pLcl); DWORD dwScratchBase=ulScratchOffset >> DDSurf_GetPixelShift(pLcl); lScratchDelta >>= DDSurf_GetPixelShift(pLcl); LONG lSurfDelta=DDSurf_Pitch(pLcl)>> DDSurf_GetPixelShift(pLcl);
for (DWORD i=0; i<DDSurf_Height(pLcl); i+=32) { lSurfOffset = dwSurfBase-dwScratchBase; // first do a patched to unpatched blt to the scratchpad
PermediaPatchedCopyBlt( ppdev, lScratchDelta, lSurfDelta, &ScratchData, pPrivate, &rScratchRect, &rSurfRect, dwScratchBase, lSurfOffset);
// then do a fast copyblt back to the original
// Packed blit ignores the ISPATCHED flag
lSurfOffset = dwScratchBase-dwSurfBase;
PermediaPackedCopyBlt( ppdev, lSurfDelta, lScratchDelta, pPrivate, &ScratchData, &rSurfRect, &rScratchRect, dwSurfBase, lSurfOffset);
rSurfRect.top += 32; rSurfRect.bottom += 32; }
pPrivate->dwFlags &= ~P2_ISPATCHED;
//
// free scratchpad memory
//
VidMemFree( pvmHeap->lpHeap, ulScratchOffset);
SYNC_WITH_PERMEDIA; } else { lpLockData->ddRVal = DDERR_OUTOFMEMORY; return DDHAL_DRIVER_HANDLED; } } }
// Because we correctly set 'fpVidMem' to be the offset into our frame
// buffer when we created the surface, DirectDraw will automatically take
// care of adding in the user-mode frame buffer address if we return
// DDHAL_DRIVER_NOTHANDLED:
return DDHAL_DRIVER_NOTHANDLED;
} // DdLock
//-----------------------------------------------------------------------------
//
// DdGetScanLine
//
// This callback is invoked to get the current scanline of our video display
//
//-----------------------------------------------------------------------------
DWORD CALLBACK DdGetScanLine(LPDDHAL_GETSCANLINEDATA lpGetScanLine) { PPDev ppdev=(PPDev)lpGetScanLine->lpDD->dhpdev;
DBG_DD(( 2, "DDraw:GetScanLine"));
// If a vertical blank is in progress the scan line is
// indeterminant. If the scan line is indeterminant we return
// the error code DDERR_VERTICALBLANKINPROGRESS.
// Otherwise we return the scan line and a success code
if( IN_VRETRACE(ppdev) ) { lpGetScanLine->ddRVal = DDERR_VERTICALBLANKINPROGRESS; lpGetScanLine->dwScanLine = 0; } else { lpGetScanLine->dwScanLine = CURRENT_VLINE(ppdev); lpGetScanLine->ddRVal = DD_OK; } return DDHAL_DRIVER_HANDLED;
} // DdGetScanLine
//-----------------------------------------------------------------------------
//
// DdGetBltStatus
//
// This callback is invoked to get the current blit status or to ask if the
// user can add the next blit.
//
//-----------------------------------------------------------------------------
DWORD CALLBACK DdGetBltStatus(LPDDHAL_GETBLTSTATUSDATA lpGetBltStatus ) { PPDev ppdev=(PPDev)lpGetBltStatus->lpDD->dhpdev; PERMEDIA_DEFS(ppdev);
DBG_DD(( 2, "DDraw:DdGetBltStatus"));
// CANBLT: can we add a blt?
// On the Permedia we can always add blits
if( lpGetBltStatus->dwFlags == DDGBS_CANBLT ) { lpGetBltStatus->ddRVal = DD_OK; } else { if( DRAW_ENGINE_BUSY ) {
//@@BEGIN_DDKSPLIT
#if MULTITHREADED
if(ppdev->ulLockCount) { DBG_DD((MT_LOG_LEVEL, "DdGetBltStatus: re-entry! %d", ppdev->ulLockCount)); } EngAcquireSemaphore(ppdev->hsemLock); ppdev->ulLockCount++; #endif
//@@END_DDKSPLIT
// switch to DDraw context if necessary
DDCONTEXT;
FLUSHDMA(); lpGetBltStatus->ddRVal = DDERR_WASSTILLDRAWING;
//@@BEGIN_DDKSPLIT
#if MULTITHREADED
ppdev->ulLockCount--; EngReleaseSemaphore(ppdev->hsemLock); #endif
//@@END_DDKSPLIT
} else { lpGetBltStatus->ddRVal = DD_OK; } }
return DDHAL_DRIVER_HANDLED;
} // DdGetBltStatus
//-----------------------------------------------------------------------------
//
// DdGetFlipStatus
//
// If the display has went through one refresh cycle since the flip
// occurred we return DD_OK. If it has not went through one refresh
// cycle we return DDERR_WASSTILLDRAWING to indicate that this surface
// is still busy "drawing" the flipped page. We also return
// DDERR_WASSTILLDRAWING if the bltter is busy and the caller wanted
// to know if they could flip yet
//
//-----------------------------------------------------------------------------
DWORD CALLBACK DdGetFlipStatus(LPDDHAL_GETFLIPSTATUSDATA lpGetFlipStatus ) { PPDev ppdev=(PPDev)lpGetFlipStatus->lpDD->dhpdev; PERMEDIA_DEFS(ppdev);
DBG_DD(( 2, "DDraw:GetFlipStatus"));
// switch to DDraw context if necessary
DDCONTEXT;
// we can always flip, since the flip is pipelined
// but we allow only one flip in advance
if( lpGetFlipStatus->dwFlags == DDGFS_CANFLIP ) { lpGetFlipStatus->ddRVal = updateFlipStatus(ppdev);
return DDHAL_DRIVER_HANDLED; }
// don't want a flip to work until after the last flip is done,
// so we ask for the general flip status and ignore the vmem
lpGetFlipStatus->ddRVal = updateFlipStatus(ppdev);
return DDHAL_DRIVER_HANDLED;
} // DdGetFlipStatus
//-----------------------------------------------------------------------------
//
// DdMapMemory
//
// This is a new DDI call specific to Windows NT that is used to map
// or unmap all the application modifiable portions of the frame buffer
// into the specified process's address space.
//
//-----------------------------------------------------------------------------
DWORD CALLBACK DdMapMemory(PDD_MAPMEMORYDATA lpMapMemory) { PDev* ppdev; VIDEO_SHARE_MEMORY ShareMemory; VIDEO_SHARE_MEMORY_INFORMATION ShareMemoryInformation; DWORD ReturnedDataLength;
DBG_DD(( 2, "DDraw:MapMemory"));
ppdev = (PDev*) lpMapMemory->lpDD->dhpdev;
if (lpMapMemory->bMap) { ShareMemory.ProcessHandle = lpMapMemory->hProcess;
// 'RequestedVirtualAddress' isn't actually used for the SHARE IOCTL:
ShareMemory.RequestedVirtualAddress = 0;
// We map in starting at the top of the frame buffer:
ShareMemory.ViewOffset = 0;
// We map down to the end of the frame buffer.
//
// Note: There is a 64k granularity on the mapping (meaning that
// we have to round up to 64k).
//
// Note: If there is any portion of the frame buffer that must
// not be modified by an application, that portion of memory
// MUST NOT be mapped in by this call. This would include
// any data that, if modified by a malicious application,
// would cause the driver to crash. This could include, for
// example, any DSP code that is kept in off-screen memory.
ShareMemory.ViewSize = ROUND_UP_TO_64K(ppdev->cyMemory * ppdev->lDelta);
if (EngDeviceIoControl(ppdev->hDriver, IOCTL_VIDEO_SHARE_VIDEO_MEMORY, &ShareMemory, sizeof(VIDEO_SHARE_MEMORY), &ShareMemoryInformation, sizeof(VIDEO_SHARE_MEMORY_INFORMATION), &ReturnedDataLength)) { DBG_DD((0, "Failed IOCTL_VIDEO_SHARE_MEMORY"));
lpMapMemory->ddRVal = DDERR_GENERIC;
return(DDHAL_DRIVER_HANDLED); }
lpMapMemory->fpProcess=(FLATPTR)ShareMemoryInformation.VirtualAddress;
} else { ShareMemory.ProcessHandle = lpMapMemory->hProcess; ShareMemory.ViewOffset = 0; ShareMemory.ViewSize = 0; ShareMemory.RequestedVirtualAddress = (VOID*) lpMapMemory->fpProcess;
if (EngDeviceIoControl(ppdev->hDriver, IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY, &ShareMemory, sizeof(VIDEO_SHARE_MEMORY), NULL, 0, &ReturnedDataLength)) { RIP("Failed IOCTL_VIDEO_UNSHARE_MEMORY"); } }
lpMapMemory->ddRVal = DD_OK;
return(DDHAL_DRIVER_HANDLED); }
//-----------------------------------------------------------------------------
//
// DdSetExclusiveMode
//
// This function is called by DirectDraw when we switch from the GDI surface,
// to DirectDraw exclusive mode, e.g. to run a game in fullcreen mode.
// You only need to implement this function when you are using the
// 'HeapVidMemAllocAligned' function and allocate memory for Device Bitmaps
// and DirectDraw surfaces from the same heap.
//
// We use this call to disable GDI DeviceBitMaps when we are running in
// DirectDraw exclusive mode. Otherwise a DD app gets confused if both GDI and
// DirectDraw allocate memory from the same heap.
//
// See also DdFlipToGDISurface.
//
//-----------------------------------------------------------------------------
DWORD CALLBACK DdSetExclusiveMode(PDD_SETEXCLUSIVEMODEDATA lpSetExclusiveMode) { PDev* ppdev=(PDev*)lpSetExclusiveMode->lpDD->dhpdev;
DBG_DD((6, "DDraw::DdSetExclusiveMode called"));
// remember setting of exclusive mode in ppdev,
// so GDI can stop to promote DeviceBitmaps into
// video memory
ppdev->bDdExclusiveMode = lpSetExclusiveMode->dwEnterExcl;
if (ppdev->bDdExclusiveMode) { // remove all GDI device bitmaps from video memory here
// and make sure they will not be promoted to videomemory
// until we leave exclusive mode.
bDemoteAll(ppdev); }
lpSetExclusiveMode->ddRVal=DD_OK;
return (DDHAL_DRIVER_HANDLED); }
//-----------------------------------------------------------------------------
//
// DWORD DdFlipToGDISurface
//
// This function is called by DirectDraw when it flips to the surface on which
// GDI can write to.
//
//-----------------------------------------------------------------------------
DWORD CALLBACK DdFlipToGDISurface(PDD_FLIPTOGDISURFACEDATA lpFlipToGDISurface) { PDev* ppdev=(PDev*)lpFlipToGDISurface->lpDD->dhpdev;
DBG_DD((6, "DDraw::DdFlipToGDISurface called"));
ppdev->dwNewDDSurfaceOffset=0xffffffff;
#if DX7_STEREO
if (ppdev->bDdStereoMode) { ppdev->bDdStereoMode=FALSE; LD_PERMEDIA_REG(PREG_VIDEOCONTROL, READ_PERMEDIA_REG(PREG_VIDEOCONTROL) & ~PREG_VC_STEREOENABLE); } #endif
lpFlipToGDISurface->ddRVal=DD_OK;
//
// we return NOTHANDLED, then the ddraw runtime takes
// care that we flip back to the primary...
//
return (DDHAL_DRIVER_NOTHANDLED); }
//-----------------------------------------------------------------------------
//
// DWORD DdFreeDriverMemory
//
// This function called by DirectDraw when it's running low on memory in
// our heap. You only need to implement this function if you use the
// DirectDraw 'HeapVidMemAllocAligned' function in your driver, and you
// can boot those allocations out of memory to make room for DirectDraw.
//
// We implement this function in the P2 driver because we have DirectDraw
// entirely manage our off-screen heap, and we use HeapVidMemAllocAligned
// to put GDI device-bitmaps in off-screen memory. DirectDraw applications
// have a higher priority for getting stuff into video memory, though, and
// so this function is used to boot those GDI surfaces out of memory in
// order to make room for DirectDraw.
//
//-----------------------------------------------------------------------------
DWORD CALLBACK DdFreeDriverMemory(PDD_FREEDRIVERMEMORYDATA lpFreeDriverMemory) { PDev* ppdev;
DBG_DD((6, "DDraw::DdFreeDriverMemory called"));
ppdev = (PDev*)lpFreeDriverMemory->lpDD->dhpdev;
lpFreeDriverMemory->ddRVal = DDERR_OUTOFMEMORY;
//@@BEGIN_DDKSPLIT
#if MULTITHREADED
if(ppdev->ulLockCount) { DBG_DD((MT_LOG_LEVEL, "DdFreeDriverMemory: re-entry! %d", ppdev->ulLockCount)); } EngAcquireSemaphore(ppdev->hsemLock); ppdev->ulLockCount++; #endif
//@@END_DDKSPLIT
//
// If we successfully freed up some memory, set the return value to
// 'DD_OK'. DirectDraw will try again to do its allocation, and
// will call us again if there's still not enough room. (It will
// call us until either there's enough room for its alocation to
// succeed, or until we return something other than DD_OK.)
//
if ( bMoveOldestBMPOut(ppdev) ) { lpFreeDriverMemory->ddRVal = DD_OK; }
//@@BEGIN_DDKSPLIT
#if MULTITHREADED
ppdev->ulLockCount--; EngReleaseSemaphore(ppdev->hsemLock); #endif
//@@END_DDKSPLIT
return (DDHAL_DRIVER_HANDLED); }// DdFreeDriverMemory()
//-----------------------------------------------------------------------------
//
// BOOL DrvGetDirectDrawInfo
//
// Function called by DirectDraw to returns the capabilities of the graphics
// hardware
//
// Parameters:
//
// dhpdev-------Is a handle to the PDEV returned by the driver's DrvEnablePDEV
// routine.
// pHalInfo-----Points to a DD_HALINFO structure in which the driver should
// return the hardware capabilities that it supports.
// pdwNumHeaps--Points to the location in which the driver should return the
// number of VIDEOMEMORY structures pointed to by pvmList.
// pvmList------Points to an array of VIDEOMEMORY structures in which the
// driver should return information about each video memory chunk
// that it controls. The driver should ignore this parameter when
// it is NULL.
// pdwNumFourCC-Points to the location in which the driver should return the
// number of DWORDs pointed to by pdwFourCC.
// pdwFourCC----Points to an array of DWORDs in which the driver should return
// information about each FOURCC that it supports. The driver
// should ignore this parameter when it is NULL.
//
// Return:
// Returns TRUE if it succeeds; otherwise, it returns FALSE
//
// Note:
// This function will be called twice before DrvEnableDirectDraw is called.
//
// Comments
// The driver's DrvGetDirectDrawInfo routine should do the following:
// 1)When pvmList and pdwFourCC are NULL:
// Reserve off-screen video memory for DirectDraw use. Write the number of
// driver video memory heaps and supported FOURCCs in pdwNumHeaps and
// pdwNumFourCC, respectively.
//
// 2)When pvmList and pdwFourCC are not NULL:
// Write the number of driver video memory heaps and supported FOURCCs in
// pdwNumHeaps and pdwNumFourCC, respectively.
// Get ptr to reserved offscreen mem?
// For each VIDEOMEMORY structure in the list to which pvmList points, fill in
// the appropriate members to describe a particular chunk of display memory.
// The list of structures provides DirectDraw with a complete description of
// the driver's off-screen memory.
//
// 3)Initialize the members of the DD_HALINFO structure with driver-specific
// information as follows:
// Initialize the appropriate members of the VIDEOMEMORYINFO structure to
// describe the general characteristics of the display's memory.
// Initialize the appropriate members of the DDNTCORECAPS structure to
// describe the capabilities of the hardware.
// If the driver implements a DdGetDriverInfo function, set GetDriverInfo to
// point to it and set dwFlags to DDHALINFO_GETDRIVERINFOSET
//
//-----------------------------------------------------------------------------
BOOL DrvGetDirectDrawInfo(DHPDEV dhpdev, DD_HALINFO* pHalInfo, DWORD* pdwNumHeaps, VIDEOMEMORY* pvmList, // Will be NULL on first call
DWORD* pdwNumFourCC, DWORD* pdwFourCC) // Will be NULL on first call
{ BOOL bCanFlip; BOOL bDefineAGPHeap = FALSE,bDefineDDrawHeap = FALSE; LONGLONG li; VIDEOMEMORY* pVm; DWORD cHeaps; DWORD dwRegistryValue;
DBG_DD((3, "DrvGetDirectDrawInfo Called"));
PDev *ppdev=(PDev*) dhpdev;
*pdwNumFourCC = 0; *pdwNumHeaps = 0;
//On the first call, setup the chip info
if(!(pvmList && pdwFourCC)) {
//
// Fill in the DDHAL Informational caps
//
GetDDHALInfo(ppdev, pHalInfo);
//
// Current primary surface attributes:
//
pHalInfo->vmiData.pvPrimary = ppdev->pjScreen; pHalInfo->vmiData.fpPrimary = 0; pHalInfo->vmiData.dwDisplayWidth = ppdev->cxScreen; pHalInfo->vmiData.dwDisplayHeight = ppdev->cyScreen; pHalInfo->vmiData.lDisplayPitch = ppdev->lDelta; pHalInfo->vmiData.ddpfDisplay.dwSize = sizeof(DDPIXELFORMAT); pHalInfo->vmiData.ddpfDisplay.dwFlags = DDPF_RGB; pHalInfo->vmiData.ddpfDisplay.dwRGBBitCount = ppdev->cjPelSize * 8;
if ( ppdev->iBitmapFormat == BMF_8BPP ) { //
// Tell DDRAW that the surface is 8-bit color indexed
//
pHalInfo->vmiData.ddpfDisplay.dwFlags |= DDPF_PALETTEINDEXED8; }
//
// These masks will be zero at 8bpp:
//
pHalInfo->vmiData.ddpfDisplay.dwRBitMask = ppdev->flRed; pHalInfo->vmiData.ddpfDisplay.dwGBitMask = ppdev->flGreen; pHalInfo->vmiData.ddpfDisplay.dwBBitMask = ppdev->flBlue;
//
// We have to tell DirectDraw our preferred off-screen alignment
//
pHalInfo->vmiData.dwOffscreenAlign = 4; pHalInfo->vmiData.dwZBufferAlign = 4; pHalInfo->vmiData.dwTextureAlign = 4;
pHalInfo->ddCaps.dwVidMemTotal = (ppdev->lVidMemHeight - ppdev->cyScreen) * ppdev->lDelta; }
cHeaps = 0;
//
// Determine the YUV modes for Video playback acceleration. We can do YUV
// conversions at any depth except 8 bits...
//
if (ppdev->iBitmapFormat != BMF_8BPP) { *pdwNumFourCC = sizeof( fourCC ) / sizeof( fourCC[0] ); }
if(DD_P2AGPCAPABLE(ppdev)) { bDefineAGPHeap = TRUE; cHeaps++; }
// Do we have sufficient videomemory to create an off-screen heap for
// DDraw? Test how much video memory is left after we subtract
// that which is being used for the screen.
if ( (ppdev->cxScreen < ppdev->lVidMemWidth) ||(ppdev->cyScreen < ppdev->lVidMemHeight)) { bDefineDDrawHeap = TRUE; cHeaps++; }
ppdev->cHeaps = cHeaps; *pdwNumHeaps = cHeaps;
// Define the fourCC's that we support
if (pdwFourCC) { memcpy(pdwFourCC, fourCC, sizeof(fourCC)); }
// If pvmList is not NULL then we can go ahead and fill out the VIDEOMEMORY
// structures which define our requested heaps.
if(pvmList) {
pVm=pvmList;
//
// Snag a pointer to the video-memory list so that we can use it to
// call back to DirectDraw to allocate video memory:
//
ppdev->pvmList = pVm;
//
// Create one heap to describe the unused portion of video memory for
// DirectDraw use
//
// Note: here lVidMemWidth is in "pixel" unit. So we should multiply it
// by cjPelSize to get actually BYTES of video memory
//
// fpStart---Points to the starting address of a memory range in the
// heap.
// fpEnd-----Points to the ending address of a memory range if the heap
// is linear. This address is inclusive, that is, it specifies the last
// valid address in the range. Thus, the number of bytes specified by
// fpStart and fpEnd is (fpEnd-fpStart+1).
//
// Define the heap for DirectDraw
//
if ( bDefineDDrawHeap ) { pVm->dwFlags = VIDMEM_ISLINEAR ; pVm->fpStart = ppdev->cyScreen * ppdev->lDelta; pVm->fpEnd = ppdev->lVidMemHeight * ppdev->lDelta - 1;
//
// DWORD align the size, the hardware should guarantee this
//
ASSERTDD(((pVm->fpEnd - pVm->fpStart + 1) & 3) == 0, "The off-screen heap size should be DWORD aligned");
pVm->ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; DBG_DD((7, "fpStart %ld fpEnd %ld", pVm->fpStart, pVm->fpEnd)); DBG_DD((7, "DrvGetDirectDrawInfo Creates 1 heap for DDRAW"));
pVm++;
}
//Define the AGP heap
if(bDefineAGPHeap) { DWORD dwAGPMemBytes; BOOL bSuccess;
// Request 32Mb of AGP Memory, DDRAW will allocate less
// if this amount is not available
dwAGPMemBytes = P2_AGP_HEAPSIZE*1024*1024;
DBG_DD((7, "Initialised AGP Heap for P2"));
// The start address of the heap,
// just set to zero as DDRAW handles the allocation
pVm->fpStart = 0; // Fetch the last byte of AGP memory
pVm->fpEnd = dwAGPMemBytes - 1;
// drivers can set VIDMEM_ISWC here,
// then memory will be write combined.
// but memory on AGP buses is always uncached
pVm->dwFlags = VIDMEM_ISNONLOCAL | VIDMEM_ISLINEAR | VIDMEM_ISWC;
// Only use AGP memory for textures and OFFSCREENPLAIN
pVm->ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER | DDSCAPS_ZBUFFER | DDSCAPS_3DDEVICE ;
pVm->ddsCapsAlt.dwCaps =DDSCAPS_OVERLAY | DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER | DDSCAPS_ZBUFFER | DDSCAPS_3DDEVICE ; ++pVm; }
}
DBG_DD((6, "DrvGetDirectDrawInfo return TRUE")); return(TRUE); }// DrvGetDirectDrawInfo()
//-----------------------------------------------------------------------------
//
// InitDDHAL
//
// do the final initialisation of the HAL:
// setup DDraw specific variables for the ppdev and fill in all callbacks
// for DirectDraw
//
// No Chip register setup is done here - it is all handled in the mode
// change code which this function calls
//
//-----------------------------------------------------------------------------
BOOL InitDDHAL(PPDev ppdev) { PERMEDIA_DEFS(ppdev);
DBG_DD((1, "DDraw:InitDDHAL*************************************" )); DBG_DD((1, " ScreenStart =%08lx", ppdev->dwScreenStart)); DBG_DD((1, " ScreenWidth=%08lx", ppdev->cxScreen )); DBG_DD((1, " ScreenHeight=%08lx", ppdev->cyScreen)); DBG_DD((1, " dwRGBBitCount=%ld", ppdev->ddpfDisplay.dwRGBBitCount )); DBG_DD((1, " RMask: 0x%x", ppdev->ddpfDisplay.dwRBitMask )); DBG_DD((1, " GMask: 0x%x", ppdev->ddpfDisplay.dwGBitMask )); DBG_DD((1, " BMask: 0x%x", ppdev->ddpfDisplay.dwBBitMask )); DBG_DD((1, "*****************************************************" ));
// Fill in the HAL Callback pointers
memset(&ppdev->DDHALCallbacks, 0, sizeof(DDHAL_DDCALLBACKS)); ppdev->DDHALCallbacks.dwSize = sizeof(DDHAL_DDCALLBACKS); ppdev->DDHALCallbacks.WaitForVerticalBlank = DdWaitForVerticalBlank; ppdev->DDHALCallbacks.CanCreateSurface = DdCanCreateSurface; ppdev->DDHALCallbacks.GetScanLine = DdGetScanLine; ppdev->DDHALCallbacks.MapMemory = DdMapMemory; //@@BEGIN_DDKSPLIT
#if MULTITHREADED
ppdev->DDHALCallbacks.CreateSurface = MtDdCreateSurface; #else
//@@END_DDKSPLIT
ppdev->DDHALCallbacks.CreateSurface = DdCreateSurface; //@@BEGIN_DDKSPLIT
#endif MULTITHREADED
//@@END_DDKSPLIT
// Fill in the HAL Callback flags
ppdev->DDHALCallbacks.dwFlags = DDHAL_CB32_WAITFORVERTICALBLANK | DDHAL_CB32_MAPMEMORY | DDHAL_CB32_GETSCANLINE | DDHAL_CB32_CANCREATESURFACE | DDHAL_CB32_CREATESURFACE;
// Fill in the Surface Callback pointers
memset(&ppdev->DDSurfCallbacks, 0, sizeof(DDHAL_DDSURFACECALLBACKS)); ppdev->DDSurfCallbacks.dwSize = sizeof(DDHAL_DDSURFACECALLBACKS); //@@BEGIN_DDKSPLIT
#if MULTITHREADED
ppdev->DDSurfCallbacks.DestroySurface = MtDdDestroySurface; ppdev->DDSurfCallbacks.Flip = MtDdFlip; ppdev->DDSurfCallbacks.Lock = MtDdLock; ppdev->DDSurfCallbacks.GetBltStatus = DdGetBltStatus; // Internally protected
ppdev->DDSurfCallbacks.GetFlipStatus = MtDdGetFlipStatus; ppdev->DDSurfCallbacks.Blt = MtDdBlt; #else
//@@END_DDKSPLIT
ppdev->DDSurfCallbacks.DestroySurface = DdDestroySurface; ppdev->DDSurfCallbacks.Flip = DdFlip; ppdev->DDSurfCallbacks.Lock = DdLock; ppdev->DDSurfCallbacks.GetBltStatus = DdGetBltStatus; ppdev->DDSurfCallbacks.GetFlipStatus = DdGetFlipStatus; ppdev->DDSurfCallbacks.Blt = DdBlt; //@@BEGIN_DDKSPLIT
#endif MULTITHREADED
//@@END_DDKSPLIT
ppdev->DDSurfCallbacks.dwFlags = DDHAL_SURFCB32_DESTROYSURFACE | DDHAL_SURFCB32_FLIP | DDHAL_SURFCB32_LOCK | DDHAL_SURFCB32_BLT | DDHAL_SURFCB32_GETBLTSTATUS | DDHAL_SURFCB32_GETFLIPSTATUS;
//@@BEGIN_DDKSPLIT
#if MULTITHREADED
ppdev->DDSurfCallbacks.SetColorKey = MtDdSetColorKey; #else
//@@END_DDKSPLIT
ppdev->DDSurfCallbacks.SetColorKey = DdSetColorKey; //@@BEGIN_DDKSPLIT
#endif MULTITHREADED
//@@END_DDKSPLIT
ppdev->DDSurfCallbacks.dwFlags |= DDHAL_SURFCB32_SETCOLORKEY;
// Fill in the DDHAL Informational caps
GetDDHALInfo(ppdev, &ppdev->ddhi32);
return (TRUE);
}// InitDDHAL()
//-----------------------------------------------------------------------------
//
// bIsStereoMode
//
// Decide if mode can be displayed as stereo mode. Here we limit stereo
// modes so that two front and two backbuffers can be created for rendering.
//
//-----------------------------------------------------------------------------
BOOL bIsStereoMode(PDev *ppdev, PDD_STEREOMODE pDDStereoMode) { pDDStereoMode->bSupported = FALSE;
// we need to check dwBpp for a valid value as PDD_STEREOMODE.dwBpp is a
// parameter passed on from the user mode API call
if ((pDDStereoMode->dwWidth >= 320) && (pDDStereoMode->dwHeight >= 240) && (pDDStereoMode->dwBpp >= 8) && (pDDStereoMode->dwBpp <= 32) ) { DWORD dwLines=ppdev->FrameBufferLength/ (pDDStereoMode->dwWidth*pDDStereoMode->dwBpp/8); if (dwLines > (pDDStereoMode->dwHeight*4)) { pDDStereoMode->bSupported = TRUE; } }
return pDDStereoMode->bSupported; }
//-----------------------------------------------------------------------------
//
// DdGetDriverInfo
//
// callback for various new HAL features, post DX3.
//
//-----------------------------------------------------------------------------
DWORD CALLBACK DdGetDriverInfo(LPDDHAL_GETDRIVERINFODATA lpData) { PPDev ppdev=(PPDev)lpData->dhpdev; PERMEDIA_DEFS(ppdev);
DWORD dwSize;
DBG_DD(( 2, "DDraw:GetDriverInfo"));
// Get a pointer to the chip we are on.
// Default to 'not supported'
lpData->ddRVal = DDERR_CURRENTLYNOTAVAIL; ppdev = (PDev*) lpData->dhpdev;
// fill in supported stuff
if (IsEqualIID(&lpData->guidInfo, &GUID_D3DCallbacks3)) { D3DHAL_CALLBACKS3 D3DCB3; DBG_DD((3," GUID_D3DCallbacks3"));
memset(&D3DCB3, 0, sizeof(D3DHAL_CALLBACKS3)); D3DCB3.dwSize = sizeof(D3DHAL_CALLBACKS3); D3DCB3.lpvReserved = NULL; D3DCB3.ValidateTextureStageState = D3DValidateTextureStageState; //@@BEGIN_DDKSPLIT
#if MULTITHREADED
D3DCB3.DrawPrimitives2 = MtD3DDrawPrimitives2; #else
//@@END_DDKSPLIT
D3DCB3.DrawPrimitives2 = D3DDrawPrimitives2; //@@BEGIN_DDKSPLIT
#endif MULTITHREADED
//@@END_DDKSPLIT
D3DCB3.dwFlags |= D3DHAL3_CB32_DRAWPRIMITIVES2 | D3DHAL3_CB32_VALIDATETEXTURESTAGESTATE | 0;
lpData->dwActualSize = sizeof(D3DHAL_CALLBACKS3); dwSize=min(lpData->dwExpectedSize,sizeof(D3DHAL_CALLBACKS3)); memcpy(lpData->lpvData, &D3DCB3, dwSize); lpData->ddRVal = DD_OK; } else if (IsEqualIID(&lpData->guidInfo, &GUID_D3DExtendedCaps)) { D3DNTHAL_D3DEXTENDEDCAPS D3DExtendedCaps; DBG_DD((3," GUID_D3DExtendedCaps"));
memset(&D3DExtendedCaps, 0, sizeof(D3DExtendedCaps)); dwSize=min(lpData->dwExpectedSize, sizeof(D3DExtendedCaps));
lpData->dwActualSize = dwSize; D3DExtendedCaps.dwSize = dwSize;
// number of (multi)textures we support simultaneusly for DX6
D3DExtendedCaps.dwFVFCaps = 1;
D3DExtendedCaps.dwMinTextureWidth = 1; D3DExtendedCaps.dwMinTextureHeight = 1; D3DExtendedCaps.dwMaxTextureWidth = 2048; D3DExtendedCaps.dwMaxTextureHeight = 2048;
D3DExtendedCaps.dwMinStippleWidth = 8; D3DExtendedCaps.dwMaxStippleWidth = 8; D3DExtendedCaps.dwMinStippleHeight = 8; D3DExtendedCaps.dwMaxStippleHeight = 8;
D3DExtendedCaps.dwTextureOpCaps = D3DTEXOPCAPS_DISABLE | D3DTEXOPCAPS_SELECTARG1 | D3DTEXOPCAPS_SELECTARG2 | D3DTEXOPCAPS_MODULATE | D3DTEXOPCAPS_ADD | D3DTEXOPCAPS_BLENDTEXTUREALPHA | 0;
D3DExtendedCaps.wMaxTextureBlendStages = 1; D3DExtendedCaps.wMaxSimultaneousTextures = 1;
// Full range of the integer (non-fractional) bits of the
// post-normalized texture indices. If the
// D3DDEVCAPS_TEXREPEATNOTSCALEDBYSIZE bit is set, the
// device defers scaling by the texture size until after
// the texture address mode is applied. If it isn't set,
// the device scales the texture indices by the texture size
// (largest level-of-detail) prior to interpolation.
D3DExtendedCaps.dwMaxTextureRepeat = 2048;
// In order to support stencil buffers in DX6 we need besides
// setting these caps and handling the proper renderstates to
// declare the appropriate z buffer pixel formats here in
// response to the GUID_ZPixelFormats and implement the
// Clear2 callback. Also , we need to be able to create the
// appropriate ddraw surfaces.
#if D3D_STENCIL
D3DExtendedCaps.dwStencilCaps = 0 | D3DSTENCILCAPS_KEEP | D3DSTENCILCAPS_ZERO | D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INVERT; #endif
#if D3DDX7_TL
// In order to use hw accelerated T&L we must declare
// how many simultaneously active lights we can handle.
D3DExtendedCaps.dwMaxActiveLights = 0; #endif //D3DDX7_TL
//@@BEGIN_DDKSPLIT
#if D3D_POINTSPRITES
// Parameter for point sprites
D3DExtendedCaps.dvMaxPointSize = 10.0; #endif // D3D_POINTSPRITES
//@@END_DDKSPLIT
memcpy(lpData->lpvData, &D3DExtendedCaps, dwSize); lpData->ddRVal = DD_OK; } else if (IsEqualIID(&lpData->guidInfo, &GUID_ZPixelFormats)) { DDPIXELFORMAT ddZBufPixelFormat[2]; DWORD dwNumZPixelFormats;
DBG_DD((3," GUID_ZPixelFormats"));
memset(ddZBufPixelFormat, 0, sizeof(ddZBufPixelFormat));
#if D3D_STENCIL
dwSize = (DWORD)min(lpData->dwExpectedSize, 2*sizeof(DDPIXELFORMAT)); lpData->dwActualSize = 2*sizeof(DDPIXELFORMAT) + sizeof(DWORD); #else
dwSize = (DWORD)min(lpData->dwExpectedSize, 1*sizeof(DDPIXELFORMAT)); lpData->dwActualSize = 1*sizeof(DDPIXELFORMAT) + sizeof(DWORD); #endif
// If we didn't support stencils, we would only fill one 16-bit
// Z Buffer format since that is all what the Permedia supports.
// Drivers that implement stencil buffer support (like this one)
// have to report here all Z Buffer formats supported since they
// have to support the Clear2 callback (or the D3DDP2OP_CLEAR
// token)
#if D3D_STENCIL
dwNumZPixelFormats = 2; #else
dwNumZPixelFormats = 1; #endif
ddZBufPixelFormat[0].dwSize = sizeof(DDPIXELFORMAT); ddZBufPixelFormat[0].dwFlags = DDPF_ZBUFFER; ddZBufPixelFormat[0].dwFourCC = 0; ddZBufPixelFormat[0].dwZBufferBitDepth = 16; ddZBufPixelFormat[0].dwStencilBitDepth = 0; ddZBufPixelFormat[0].dwZBitMask = 0xFFFF; ddZBufPixelFormat[0].dwStencilBitMask = 0x0000; ddZBufPixelFormat[0].dwRGBZBitMask = 0;
#if D3D_STENCIL
ddZBufPixelFormat[1].dwSize = sizeof(DDPIXELFORMAT); ddZBufPixelFormat[1].dwFlags = DDPF_ZBUFFER | DDPF_STENCILBUFFER; ddZBufPixelFormat[1].dwFourCC = 0; // The sum of the z buffer bit depth AND the stencil depth
// should be included here
ddZBufPixelFormat[1].dwZBufferBitDepth = 16; ddZBufPixelFormat[1].dwStencilBitDepth = 1; ddZBufPixelFormat[1].dwZBitMask = 0x7FFF; ddZBufPixelFormat[1].dwStencilBitMask = 0x8000; ddZBufPixelFormat[1].dwRGBZBitMask = 0; #endif
memcpy(lpData->lpvData, &dwNumZPixelFormats, sizeof(DWORD)); memcpy((LPVOID)((LPBYTE)(lpData->lpvData) + sizeof(DWORD)), ddZBufPixelFormat, dwSize);
lpData->ddRVal = DD_OK; } else if (IsEqualIID(&(lpData->guidInfo), &GUID_D3DParseUnknownCommandCallback)) { DBG_DD((3," GUID_D3DParseUnknownCommandCallback")); ppdev->pD3DParseUnknownCommand = (PFND3DNTPARSEUNKNOWNCOMMAND)(lpData->lpvData); lpData->ddRVal = DD_OK; } //@@BEGIN_DDKSPLIT
#if DX7_ALPHABLT
else if (IsEqualIID(&(lpData->guidInfo), &GUID_DDMoreCaps)) { DD_MORECAPS DDMoreCaps;
DBG_DD((3," GUID_DDMoreCaps"));
// here we set all the caps for the new
// DirectDraw 7 AlphaBlt callback
memset(&DDMoreCaps, 0, sizeof(DD_MORECAPS));
DDMoreCaps.dwSize=sizeof(DD_MORECAPS);
// alpha caps for Vmem->Vmem blts
// claim to do lots of stuff, we can still fail in callback
DDMoreCaps.dwAlphaCaps = DDALPHACAPS_BLTALPHAPIXELS | DDALPHACAPS_BLTSATURATE | DDALPHACAPS_BLTPREMULT | DDALPHACAPS_BLTNONPREMULT | DDALPHACAPS_BLTALPHAFILL | DDALPHACAPS_BLTARGBSCALE1F | DDALPHACAPS_BLTARGBSCALE2F | DDALPHACAPS_BLTARGBSCALE4F | DDALPHACAPS_BLTALPHAANDARGBSCALING;
DDMoreCaps.dwSVBAlphaCaps = 0; // alpha capabilities for System->Vmem blts
DDMoreCaps.dwVSBAlphaCaps = 0; // alpha capabilities for Vmem->System blts
DDMoreCaps.dwSSBAlphaCaps = 0; // alpha capabilities for System->System blts
// filter caps for Vmem->Vmem blts
DDMoreCaps.dwFilterCaps = DDFILTCAPS_BLTQUALITYFILTER | DDFILTCAPS_BLTCANDISABLEFILTER;
DDMoreCaps.dwSVBFilterCaps= 0; // filter capabilities for System->Vmem blts
DDMoreCaps.dwVSBFilterCaps= 0; // filter capabilities for Vmem->System blts
DDMoreCaps.dwSSBFilterCaps= 0; // filter capabilities for System->System blts
lpData->dwActualSize = sizeof(DDMoreCaps); dwSize=min( sizeof(DDMoreCaps), lpData->dwExpectedSize); memcpy(lpData->lpvData, &DDMoreCaps, dwSize); lpData->ddRVal = DD_OK; } #endif
//@@END_DDKSPLIT
else if (IsEqualIID(&(lpData->guidInfo), &GUID_Miscellaneous2Callbacks) ) { BOOL bRet; DWORD dwResult;
DDHAL_DDMISCELLANEOUS2CALLBACKS MISC2_CB;
DBG_DD((3," GUID_Miscellaneous2Callbacks2"));
memset(&MISC2_CB, 0, sizeof(DDHAL_DDMISCELLANEOUS2CALLBACKS)); MISC2_CB.dwSize = sizeof(DDHAL_DDMISCELLANEOUS2CALLBACKS);
MISC2_CB.dwFlags = 0 //@@BEGIN_DDKSPLIT
#if DX7_ALPHABLT
| DDHAL_MISC2CB32_ALPHABLT #endif
//@@END_DDKSPLIT
| DDHAL_MISC2CB32_CREATESURFACEEX | DDHAL_MISC2CB32_GETDRIVERSTATE | DDHAL_MISC2CB32_DESTROYDDLOCAL;
MISC2_CB.GetDriverState = D3DGetDriverState; MISC2_CB.CreateSurfaceEx = D3DCreateSurfaceEx; MISC2_CB.DestroyDDLocal = D3DDestroyDDLocal;
//@@BEGIN_DDKSPLIT
#if DX7_ALPHABLT
MISC2_CB.AlphaBlt = DdAlphaBlt; #endif
//@@END_DDKSPLIT
lpData->dwActualSize = sizeof(MISC2_CB); dwSize = min(sizeof(MISC2_CB),lpData->dwExpectedSize); memcpy(lpData->lpvData, &MISC2_CB, dwSize); lpData->ddRVal = DD_OK; } else if (IsEqualIID(&(lpData->guidInfo), &GUID_UpdateNonLocalHeap)) { LPDDHAL_UPDATENONLOCALHEAPDATA pDDNonLocalHeap;
DBG_DD((3," GUID_UpdateNonLocalHeap"));
pDDNonLocalHeap = (LPDDHAL_UPDATENONLOCALHEAPDATA)lpData->lpvData;
ppdev->dwGARTLinBase = pDDNonLocalHeap->fpGARTLin; ppdev->dwGARTDevBase = pDDNonLocalHeap->fpGARTDev;
// These values are used to specify the base address of the
// visible 8Mb window of AGP memory
ppdev->dwGARTLin = pDDNonLocalHeap->fpGARTLin; ppdev->dwGARTDev = pDDNonLocalHeap->fpGARTDev;
DDCONTEXT; SYNC_WITH_PERMEDIA;
LD_PERMEDIA_REG (PREG_AGPTEXBASEADDRESS,(ULONG)ppdev->dwGARTDev);
DBG_DD((3,"GartLin: 0x%x, GartDev: 0x%x", (ULONG)ppdev->dwGARTLin, ppdev->dwGARTDev));
lpData->ddRVal = DD_OK;
} else if (IsEqualIID(&(lpData->guidInfo), &GUID_GetHeapAlignment) ) {
LPDDHAL_GETHEAPALIGNMENTDATA lpFData= (LPDDHAL_GETHEAPALIGNMENTDATA) lpData->lpvData;
DBG_DD((3," GUID_GetHeapAlignment"));
lpData->ddRVal = DD_OK; } else if (IsEqualIID(&(lpData->guidInfo), &GUID_NTPrivateDriverCaps) ) { DD_NTPRIVATEDRIVERCAPS DDPrivateDriverCaps;
DBG_DD((3," GUID_NTPrivateDriverCaps"));
memset(&DDPrivateDriverCaps, 0, sizeof(DDPrivateDriverCaps)); DDPrivateDriverCaps.dwSize=sizeof(DDPrivateDriverCaps);
// we want the kernel to call us when a primary surface is created
// so that we can store some private information in the
// lpGbl->dwReserved1 field
DDPrivateDriverCaps.dwPrivateCaps=DDHAL_PRIVATECAP_NOTIFYPRIMARYCREATION;
lpData->dwActualSize =sizeof(DDPrivateDriverCaps);
dwSize = min(sizeof(DDPrivateDriverCaps),lpData->dwExpectedSize); memcpy(lpData->lpvData, &DDPrivateDriverCaps, dwSize); lpData->ddRVal = DD_OK; } #if DX7_STEREO
else if (IsEqualIID(&(lpData->guidInfo), &GUID_DDMoreSurfaceCaps) ) { DD_MORESURFACECAPS DDMoreSurfaceCaps; DDSCAPSEX ddsCapsEx, ddsCapsExAlt; ULONG ulCopyPointer;
DBG_DD((3," GUID_DDMoreSurfaceCaps"));
// fill in everything until expectedsize...
memset(&DDMoreSurfaceCaps, 0, sizeof(DDMoreSurfaceCaps));
// Caps for heaps 2..n
memset(&ddsCapsEx, 0, sizeof(ddsCapsEx)); memset(&ddsCapsExAlt, 0, sizeof(ddsCapsEx));
DDMoreSurfaceCaps.dwSize=lpData->dwExpectedSize;
DBG_DD((3," stereo support: %ld", ppdev->bCanDoStereo)); if (ppdev->bCanDoStereo) { DDMoreSurfaceCaps.ddsCapsMore.dwCaps2 = DDSCAPS2_STEREOSURFACELEFT; } lpData->dwActualSize = lpData->dwExpectedSize;
dwSize = min(sizeof(DDMoreSurfaceCaps),lpData->dwExpectedSize); memcpy(lpData->lpvData, &DDMoreSurfaceCaps, dwSize);
// now fill in other heaps...
while (dwSize < lpData->dwExpectedSize) { memcpy( (PBYTE)lpData->lpvData+dwSize, &ddsCapsEx, sizeof(DDSCAPSEX)); dwSize += sizeof(DDSCAPSEX); memcpy( (PBYTE)lpData->lpvData+dwSize, &ddsCapsExAlt, sizeof(DDSCAPSEX)); dwSize += sizeof(DDSCAPSEX); }
lpData->ddRVal = DD_OK; } else if (IsEqualIID(&(lpData->guidInfo), &GUID_DDStereoMode) ) { PDD_STEREOMODE pDDStereoMode;
// Permedia supports all modes as stereo modes.
// for test purposes, we restrict them to something
// larger than 320x240
//
// note: this GUID_DDStereoMode is only used on NT to
// report stereo modes. There is no need to implement
// it in win9x drivers. Win9x drivers report stereo
// modes by setting the DDMODEINFO_STEREO bit in the
// dwFlags member of the DDHALMODEINFO structure.
// It is also recommended to report DDMODEINFO_MAXREFRESH
// for stereo modes when running under a runtime >= DX7 to
// allow applications to select higher refresh rates for
// stereo modes.
//
if (lpData->dwExpectedSize >= sizeof(PDD_STEREOMODE)) { pDDStereoMode = (PDD_STEREOMODE) lpData->lpvData;
bIsStereoMode( ppdev, pDDStereoMode);
DBG_DD((3," GUID_DDStereoMode(%d,%d,%d,%d=%d)", pDDStereoMode->dwWidth, pDDStereoMode->dwHeight, pDDStereoMode->dwBpp, pDDStereoMode->dwRefreshRate, pDDStereoMode->bSupported));
lpData->dwActualSize = sizeof(DD_STEREOMODE); lpData->ddRVal = DD_OK; } } #endif
else if (IsEqualIID(&(lpData->guidInfo), &GUID_NonLocalVidMemCaps) ) { DD_NONLOCALVIDMEMCAPS DDNonLocalVidMemCaps;
DBG_DD((3," GUID_DDNonLocalVidMemCaps"));
memset(&DDNonLocalVidMemCaps, 0, sizeof(DDNonLocalVidMemCaps)); DDNonLocalVidMemCaps.dwSize=sizeof(DDNonLocalVidMemCaps);
//fill in all supported nonlocal to videomemory blts
//
DDNonLocalVidMemCaps.dwNLVBCaps = DDCAPS_BLT | DDCAPS_BLTSTRETCH | DDCAPS_BLTQUEUE | DDCAPS_COLORKEY | DDCAPS_ALPHA | DDCAPS_CANBLTSYSMEM;
DDNonLocalVidMemCaps.dwNLVBCaps2 = 0;
DDNonLocalVidMemCaps.dwNLVBCKeyCaps=DDCKEYCAPS_SRCBLT | DDCKEYCAPS_SRCBLTCLRSPACE;
DDNonLocalVidMemCaps.dwNLVBFXCaps = DDFXCAPS_BLTALPHA | DDFXCAPS_BLTFILTER | DDFXCAPS_BLTSTRETCHY | DDFXCAPS_BLTSTRETCHX | DDFXCAPS_BLTSTRETCHYN | DDFXCAPS_BLTSTRETCHXN | DDFXCAPS_BLTSHRINKY | DDFXCAPS_BLTSHRINKX | DDFXCAPS_BLTSHRINKYN | DDFXCAPS_BLTSHRINKXN | DDFXCAPS_BLTMIRRORUPDOWN | DDFXCAPS_BLTMIRRORLEFTRIGHT;
if (ppdev->iBitmapFormat != BMF_8BPP) { DDNonLocalVidMemCaps.dwNLVBCaps |= DDCAPS_BLTFOURCC; DDNonLocalVidMemCaps.dwNLVBCKeyCaps|=DDCKEYCAPS_SRCBLTCLRSPACEYUV; }
for(INT i = 0; i < DD_ROP_SPACE; i++ ) DDNonLocalVidMemCaps.dwNLVBRops[i] = rops[i];
lpData->dwActualSize =sizeof(DDNonLocalVidMemCaps);
dwSize = min(sizeof(DDNonLocalVidMemCaps),lpData->dwExpectedSize); memcpy(lpData->lpvData, &DDNonLocalVidMemCaps, dwSize); lpData->ddRVal = DD_OK; } else if (IsEqualIID(&lpData->guidInfo, &GUID_NTCallbacks)) { DD_NTCALLBACKS NtCallbacks;
memset(&NtCallbacks, 0, sizeof(NtCallbacks));
dwSize = min(lpData->dwExpectedSize, sizeof(DD_NTCALLBACKS));
NtCallbacks.dwSize = dwSize; NtCallbacks.dwFlags = DDHAL_NTCB32_FREEDRIVERMEMORY | DDHAL_NTCB32_SETEXCLUSIVEMODE | DDHAL_NTCB32_FLIPTOGDISURFACE ; //@@BEGIN_DDKSPLIT
#if MULTITHREADED
NtCallbacks.FreeDriverMemory = DdFreeDriverMemory; // Internally protected
NtCallbacks.SetExclusiveMode = MtDdSetExclusiveMode; NtCallbacks.FlipToGDISurface = MtDdFlipToGDISurface; #else
//@@END_DDKSPLIT
NtCallbacks.FreeDriverMemory = DdFreeDriverMemory; NtCallbacks.SetExclusiveMode = DdSetExclusiveMode; NtCallbacks.FlipToGDISurface = DdFlipToGDISurface; //@@BEGIN_DDKSPLIT
#endif MULTITHREADED
//@@END_DDKSPLIT
memcpy(lpData->lpvData, &NtCallbacks, dwSize);
lpData->ddRVal = DD_OK; }
// We always handled it.
return DDHAL_DRIVER_HANDLED;
} // GetDriverInfo
//-----------------------------------------------------------------------------
//
// updateFlipStatus
//
// return DD_OK when last flip has occured.
//
//-----------------------------------------------------------------------------
HRESULT updateFlipStatus( PPDev ppdev ) { PERMEDIA_DEFS(ppdev); DBG_DD((6, "DDraw:updateFlipStatus"));
// we assume that we are already in the DDraw/D3D context.
// read Permedia register which tells us if there is a flip pending
if (ppdev->dwNewDDSurfaceOffset!=0xffffffff) { ULONG ulScreenBase=READ_PERMEDIA_REG(PREG_SCREENBASE);
if (ulScreenBase!= ppdev->dwNewDDSurfaceOffset) {
DBG_DD((7," SurfaceOffset %08lx instead of %08lx", ulScreenBase, ppdev->dwNewDDSurfaceOffset));
//
// make sure all pending data was flushed!
//
FLUSHDMA();
//
// if we are busy, return
// otherwise the pipeline is empty and we can
// fall through and to check if the chip already flipped.
//
if (DRAW_ENGINE_BUSY) return DDERR_WASSTILLDRAWING;
} }
DWORD dwVideoControl=READ_PERMEDIA_REG(PREG_VIDEOCONTROL);
if (dwVideoControl & PREG_VC_SCREENBASEPENDING) { DBG_DD((7," VideoControl still pending (%08lx)",dwVideoControl)); return DDERR_WASSTILLDRAWING; }
return DD_OK;
} // updateFlipStatus
//@@BEGIN_DDKSPLIT
#if MULTITHREADED
//-----------------------------------------------------------------------------
//
// Multithread support wrappers for Dx callback functions
//
//-----------------------------------------------------------------------------
//DWORD CALLBACK MtDdBlt( LPDDHAL_BLTDATA lpBlt );
WRAPMTDXCALLBACK(DD, DdBlt, LPDDHAL_BLTDATA, lpBlt, lpBlt->lpDD->dhpdev);
//DWORD CALLBACK MtDdCreateSurface( LPDDHAL_CREATESURFACEDATA pcsd);
WRAPMTDXCALLBACK(DD, DdCreateSurface, LPDDHAL_CREATESURFACEDATA, pcsd, pcsd->lpDD->dhpdev);
//DWORD CALLBACK MtDdDestroySurface( LPDDHAL_DESTROYSURFACEDATA psdd);
WRAPMTDXCALLBACK(DD, DdDestroySurface, LPDDHAL_DESTROYSURFACEDATA, psdd, psdd->lpDD->dhpdev);
//DWORD CALLBACK MtDdFlip( LPDDHAL_FLIPDATA lpFlipData);
WRAPMTDXCALLBACK(DD, DdFlip, LPDDHAL_FLIPDATA, lpFlipData, lpFlipData->lpDD->dhpdev);
//DWORD CALLBACK MtDdFlipToGDISurface(PDD_FLIPTOGDISURFACEDATA lpFlipToGDISurface);
WRAPMTDXCALLBACK(DD, DdFlipToGDISurface, PDD_FLIPTOGDISURFACEDATA, lpFlipToGDISurface, lpFlipToGDISurface->lpDD->dhpdev);
//DWORD CALLBACK MtDdGetFlipStatus(LPDDHAL_GETFLIPSTATUSDATA lpGetFlipStatus);
WRAPMTDXCALLBACK(DD, DdGetFlipStatus, LPDDHAL_GETFLIPSTATUSDATA, lpGetFlipStatus, lpGetFlipStatus->lpDD->dhpdev);
//DWORD CALLBACK MtDdLock( LPDDHAL_LOCKDATA lpLockData );
WRAPMTDXCALLBACK(DD, DdLock, LPDDHAL_LOCKDATA, lpLockData, lpLockData->lpDD->dhpdev);
//DWORD CALLBACK MtDdSetExclusiveMode(PDD_SETEXCLUSIVEMODEDATA lpSetExclusiveMode);
WRAPMTDXCALLBACK(DD, DdSetExclusiveMode, PDD_SETEXCLUSIVEMODEDATA, lpSetExclusiveMode, lpSetExclusiveMode->lpDD->dhpdev);
#endif MULTITHREADED
//@@END_DDKSPLIT
|