You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2136 lines
74 KiB
2136 lines
74 KiB
/******************************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
|