Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

3790 lines
144 KiB

/******************************Module*Header**********************************\
*
* **************************
* * DirectDraw SAMPLE CODE *
* **************************
*
* Module Name: dd.c
*
* Content: Main DirectDraw callbacks
*
* Copyright (c) 1994-1999 3Dlabs Inc. Ltd. All rights reserved.
* Copyright (c) 1995-2003 Microsoft Corporation. All rights reserved.
\*****************************************************************************/
#define INITGUID
#include "glint.h"
#if W95_DDRAW
#include "ddkmmini.h"
#include <mmsystem.h>
#endif
#include "dma.h"
#include "tag.h"
void __GetDDHALInfo(P3_THUNKEDDATA* pThisDisplay, DDHALINFO* pHALInfo);
#if W95_DDRAW
// These variables MUST be initialised, therby forcing them into DATA.
// This segment is shared.
P3_THUNKEDDATA* g_pDriverData = NULL;
//-----------------------------------------------------------------------------
//
// ***************************WIN9x ONLY**********************************
//
// DllMain
//
// DLL Entry point.
//
//-----------------------------------------------------------------------------
BOOL WINAPI
DllMain(
HINSTANCE hModule,
DWORD dwReason,
LPVOID lpvReserved)
{
// The 16 bit side requires an HINSTANCE
g_DXGlobals.hInstance = hModule;
switch( dwReason )
{
case DLL_PROCESS_ATTACH:
// We don't care about thread attach messages.
DisableThreadLibraryCalls( hModule );
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
default:
break;
}
return TRUE;
} // DllMain
//-----------------------------Public Routine----------------------------------
//
// ***************************WIN9x ONLY**********************************
//
// DdDestroyDriver
//
// Destroys a DirectDraw driver.
//
// Parameters
// pddd
// Address of a DDHAL_DESTROYDRIVERDATA structure that contains
// information necessary to destroy the driver.
// Members
//
// LPDDRAWI_DIRECTDRAW_GBL
// lpDD
// Address of the DirectDraw structure representing
// the DirectDraw object.
// HRESULT
// ddRVal
// Passes the DirectDraw return values.
// LPDDHAL_DESTROYDRIVER
// DestroyDriver
// This member is used by the DirectDraw API and should
// not be filled in by the driver.
//
// Return Value
// Returns one of the following values:
//
// DDHAL_DRIVER_HANDLED
// DDHAL_DRIVER_NOTHANDLED
//-----------------------------------------------------------------------------
//
// (!!!) Temp patch, move to Win9x header later, this CB is currently not used.
//
#define DIRECTX_DESTROYDRIVER_ESCAPE 0xbadbadee
DWORD CALLBACK
DdDestroyDriver(
LPDDHAL_DESTROYDRIVERDATA pddd)
{
HDC hDC;
P3_THUNKEDDATA* pThisDisplay;
LPGLINTINFO pGLInfo;
DISPDBG((DBGLVL,"*** In DdDestroyDriver"));
GET_THUNKEDDATA(pThisDisplay, pddd->lpDD);
pGLInfo = pThisDisplay->pGLInfo;
// Destroy the hash table
HT_DestroyHashTable(pThisDisplay->pDirectDrawLocalsHashTable, pThisDisplay);
DISPDBG((DBGLVL,"Calling Display Driver's DestroyDriver16"));
hDC = CREATE_DRIVER_DC ( pThisDisplay->pGLInfo );
if ( hDC != NULL )
{
DISPDBG((DBGLVL,"HDC: 0x%x", hDC));
ExtEscape ( hDC,
DIRECTX_DESTROYDRIVER_ESCAPE,
sizeof(DDHAL_DESTROYDRIVERDATA),
(LPCSTR)pddd,
0,
NULL );
DELETE_DRIVER_DC ( hDC );
}
pddd->ddRVal = DD_OK;
return DDHAL_DRIVER_HANDLED;
} // DdDestroyDriver
//-----------------------------Public Routine----------------------------------
//
// ***************************WIN9x ONLY**********************************
//
// DriverInit
//
// The entry point called by DirectDraw to initialize the 32-bit driver.
//
// DriverInit is called after the control function receives QUERYESCAPESUPPORT
// with DDGET32BITDRIVERNAME escapes and returns the entry point (szEntryPoint).
// DriverInit is only called once during driver initialization; it is not
// called on mode changes.
//
// The dwDriverData parameter points to a region of shared data between the
// 16- and 32-bit address space. It must be aliased through MapSLFix (a
// standard Windows driver routine), which converts it to a 32-bit pointer,
// g_pDriverData. MapSLFix creates a 16-bit selector for a 32-bit pointer, so
// you can use what it returns from the 16-bit side. A 16:16 pointer is created
// to point to the needed 32-bit objects, so a 64K piece of memory is shared
// between 16- and 32-bit sides. Since only 64K of linear address space is
// accessible with a 16:16 pointer, any objects larger than 64K will require
// two 16:16 pointers tiled together (most objects should be smaller than 64K).
// The pointer is used to set the fReset flag to TRUE because the display
// parameters are being reset. The buildDDHALInfo32 function is called from
// this function to fill out all of the 32-bit function names and driver
// information.
//
// Returns 1.
//
// Parameters
// DWORD
// dwDriverData
// Doubleword pointer that points to a shared memory region
// between 16- and 32-bit address space.
//-----------------------------------------------------------------------------
DWORD CALLBACK
DriverInit(
DWORD dwDriverData )
{
P3_THUNKEDDATA* pThisDisplay;
DWORD DataPointer = 0;
HANDLE hDevice = NULL;
DWORD InPtr = dwDriverData;
DWORD dwSizeRet;
DWORD bResult;
// The g_pThisTemp may have been hosed, so we must reset
// it to continue
#if DBG
g_pThisTemp = NULL;
#endif
//extern LPVOID _stdcall MapSL( DWORD ); // 16:16 -> 0:32
//DataPointer = (DWORD)MapSL(dwDriverData);
//!! Don't laugh at this... I tried calling the MapSL function
//to fix up the pointer, but couldn't get it to work all of the time
//(When the display was running the second instance of itself).
hDevice = CreateFile("\\\\.\\perm3mvd",
GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
(LPSECURITY_ATTRIBUTES) NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);
if (hDevice == (HANDLE) INVALID_HANDLE_VALUE)
{
DISPDBG((ERRLVL, "ERROR: Invalid Handle"));
return 0;
}
else
{
DISPDBG((DBGLVL, "Got handle"));
bResult = DeviceIoControl(hDevice,
GLINT_16TO32_POINTER,
&InPtr,
sizeof(DWORD),
&DataPointer,
sizeof(DWORD),
&dwSizeRet,
0);
if (!bResult || (DataPointer == 0))
{
DISPDBG((ERRLVL,"ERROR: Pointer conversion failed!"));
CloseHandle(hDevice);
return 0;
}
}
CloseHandle(hDevice);
#if DBG
g_pThisTemp = (P3_THUNKEDDATA*)DataPointer;
#endif
//
// Sanity check
//
if (! (((P3_THUNKEDDATA*)DataPointer)->pGLInfo)) {
return 0;
}
if (((P3_THUNKEDDATA*)DataPointer)->pGLInfo->dwDeviceHandle == 1)
{
g_pDriverData = (P3_THUNKEDDATA*)DataPointer;
DISPDBG((ERRLVL, "Device is the Primary, Setting sData: 0x%x",
g_pDriverData));
}
else
{
DISPDBG((ERRLVL, "Device NOT Primary Display, "
"Setting dwReturn: 0x%x",
DataPointer));
}
pThisDisplay = (P3_THUNKEDDATA*)DataPointer;
if (pThisDisplay->dwSetupThisDisplay == 0)
{
// Pass the current pointer to the init function
if (! _DD_InitDDHAL32Bit((P3_THUNKEDDATA*)DataPointer))
{
DISPDBG((ERRLVL,"ERROR: DriverInit Failed!"));
return 0;
}
else
{
//
// Initialize the heap manager data structure
//
_DX_LIN_UnInitialiseHeapManager(&pThisDisplay->LocalVideoHeap0Info);
if (!_DX_LIN_InitialiseHeapManager(
&pThisDisplay->LocalVideoHeap0Info,
pThisDisplay->LocalVideoHeap0Info.dwMemStart,
pThisDisplay->LocalVideoHeap0Info.dwMemEnd))
{
DISPDBG((ERRLVL, "ERROR: Heap0 initialization failed!"));
}
DISPDBG((ERRLVL,"Returned g_pDriverData"));
}
}
// Increase the reference count on the display object.
pThisDisplay->dwSetupThisDisplay++;
// Set up the size of the ddCaps
pThisDisplay->ddhi32.ddCaps.dwSize = sizeof(DDCORECAPS);
// Set the flag that says we have to handle a mode change.
// This will cause the chip to be initialised properly at the
// right time (whilst in a Win16Lock)
((P3_THUNKEDDATA*)DataPointer)->bResetMode = TRUE;
((P3_THUNKEDDATA*)DataPointer)->bStartOfDay = TRUE;
((P3_THUNKEDDATA*)DataPointer)->pGLInfo->dwDirectXState =
DIRECTX_LASTOP_UNKNOWN;
return (DWORD)DataPointer;
} // DriverInit
//-----------------------------Public Routine----------------------------------
//
// ***************************WIN9x ONLY**********************************
//
// DdControlColor
//
// Controls the luminance and brightness controls of an overlay surface
// or a primary surface. This callback is optional.
//
// Parameters
// lpColorControl
// Points to a DD_COLORCONTROLDATA structure that contains
// the color control information for a specified overlay
// surface.
//
// Members
//
// PDD_DIRECTDRAW_GLOBAL
// lpDD
// Points to a DD_DIRECTDRAW_GLOBAL structure that
// describes the driver.
// PDD_SURFACE_LOCAL
// lpDDSurface
// Points to the DD_SURFACE_LOCAL structure
// representing the overlay surface.
// DDCOLORCONTROL
// ColorData
// Is a DDCOLORCONTROL structure. See dwFlags to
// determine how to use this member. The
// DDCOLORCONTROL structure is defined in ddraw.h.
// DWORD
// dwFlags
// Is the color control flags. This member can be
// one of the following values:
//
// DDRAWI_GETCOLOR The driver should return the color
// controls it supports for the
// specified overlay in ColorData.
// The driver should set the appropriate
// flags in the dwFlags member of the
// DDCOLORCONTROL structure to indicate
// which other members the driver has
// returned valid data in.
// DDRAWI_SETCOLOR
// The driver should set the current color
// controls for the specified overlay
// using the values specified in ColorData.
// HRESULT
// ddRVal
// Is the location in which the driver writes the
// return value of the DdControlColor callback. A
// return code of DD_OK indicates success.
// VOID*
// ColorControl
// Is unused on Windows 2000.
//
// Return Value
// DdControlColor returns one of the following callback codes:
//
// DDHAL_DRIVER_HANDLED
// DDHAL_DRIVER_NOTHANDLED
// Comments
//
// DdControlColor can be optionally implemented in a DirectDraw driver.
//-----------------------------------------------------------------------------
// Set this to 1 to support gamma correction, or zero to disable.
#define COLCON_SUPPORTS_GAMMA 1
DWORD CALLBACK
DdControlColor(
LPDDHAL_COLORCONTROLDATA lpColConData )
{
P3_THUNKEDDATA* pThisDisplay;
P3_SURF_FORMAT* pFormatSurface;
GET_THUNKEDDATA(pThisDisplay, lpColConData->lpDD);
DISPDBG((DBGLVL,"DdControlColor"));
//
// What the DDCOLORCONTROL structure looks like:
// {
// DWORD dwSize;
// DWORD dwFlags;
// LONG lBrightness;
// LONG lContrast;
// LONG lHue;
// LONG lSaturation;
// LONG lSharpness;
// LONG lGamma;
// LONG lColorEnable;
// DWORD dwReserved1;
// } DDCOLORCONTROL;
//
pFormatSurface = _DD_SUR_GetSurfaceFormat(lpColConData->lpDDSurface);
if ( pFormatSurface->dwBitsPerPixel <= 8 )
{
// Can't do colour control on this format screen.
// Only works on true-colour screens (and we don't
// support 332 as a primary).
lpColConData->lpColorData->dwFlags = 0;
lpColConData->ddRVal = DD_OK;
return ( DDHAL_DRIVER_HANDLED );
}
// See what they want.
if ( lpColConData->dwFlags == DDRAWI_GETCOLOR )
{
// Get the colour info.
lpColConData->lpColorData->lBrightness =
pThisDisplay->ColConBrightness;
lpColConData->lpColorData->lContrast =
pThisDisplay->ColConContrast;
#if COLCON_SUPPORTS_GAMMA
lpColConData->lpColorData->lGamma =
pThisDisplay->ColConGamma;
lpColConData->lpColorData->dwFlags =
DDCOLOR_BRIGHTNESS |
DDCOLOR_CONTRAST |
DDCOLOR_GAMMA;
#else
// We don't support gamma values.
lpColConData->lpColorData->lGamma = 0;
lpColConData->lpColorData->dwFlags =
DDCOLOR_BRIGHTNESS |
DDCOLOR_CONTRAST;
#endif
}
else if ( lpColConData->dwFlags == DDRAWI_SETCOLOR )
{
WORD wRamp[256*3];
WORD *pwRampR, *pwRampG, *pwRampB;
BOOL bRes;
HDC hDC;
float fCol1, fCol2, fCol3, fCol4;
float fBrightGrad, fBrightBase;
float fContGrad1, fContBase1;
float fContGrad2, fContBase2;
float fContGrad3, fContBase3;
float fContCutoff12, fContCutoff23;
float fGammaGrad1, fGammaBase1;
float fGammaGrad2, fGammaBase2;
float fGammaCutoff12;
float fTemp;
int iTemp, iCount;
// Set some new colour info.
if ( ( lpColConData->lpColorData->dwFlags & DDCOLOR_BRIGHTNESS ) != 0 )
{
pThisDisplay->ColConBrightness =
lpColConData->lpColorData->lBrightness;
}
if ( ( lpColConData->lpColorData->dwFlags & DDCOLOR_CONTRAST ) != 0 )
{
pThisDisplay->ColConContrast =
lpColConData->lpColorData->lContrast;
}
#if COLCON_SUPPORTS_GAMMA
if ( ( lpColConData->lpColorData->dwFlags & DDCOLOR_GAMMA ) != 0 )
{
pThisDisplay->ColConGamma =
lpColConData->lpColorData->lGamma;
}
#endif
// Set up the constants.
// Brightness.
// 0->10000 maps to 0.0->1.0. Default is 0
fCol1 = (float)(pThisDisplay->ColConBrightness) / 10000.0f;
fBrightGrad = 1.0f - fCol1;
fBrightBase = fCol1;
// Contrast
// 0->20000 maps to 0.0->1.0. Default 10000 maps to 0.5
fCol1 = (float)(pThisDisplay->ColConContrast) / 20000.0f;
fContCutoff12 = fCol1 / 2.0f;
fContCutoff23 = 1.0f - ( fCol1 / 2.0f );
fContGrad1 = ( 1.0f - fCol1 ) / fCol1;
fContBase1 = 0.0f;
fContGrad2 = fCol1 / ( 1.0f - fCol1 );
fContBase2 = ( 0.5f - fCol1 ) / ( 1.0f - fCol1 );
fContGrad3 = ( 1.0f - fCol1 ) / fCol1;
fContBase3 = ( ( 2.0f * fCol1 ) - 1.0f ) / fCol1;
// Gamma
// 1->500 maps to 0.01->5.0, default of 100 maps to 1.0
// But then map to 0.0->0.5->1.0 non-linearly.
if ( pThisDisplay->ColConGamma <= 2 )
{
// App is probably using the old docs that forgot to point
// out the *100
ASSERTDD ( FALSE, "** Colorcontrol32: App set gamma value of 2"
" or less - probably using old DX docs" );
fTemp = (float)(pThisDisplay->ColConGamma);
}
else
{
fTemp = (float)(pThisDisplay->ColConGamma) / 100.0f;
}
fTemp = 1.0f - ( 1.0f / ( 1.0f + fTemp ) );
fGammaCutoff12 = 1.0f - fTemp;
fGammaGrad1 = fTemp / ( 1.0f - fTemp );
fGammaBase1 = 0.0f;
fGammaGrad2 = ( 1.0f - fTemp ) / fTemp;
fGammaBase2 = ( 2.0f * fTemp - 1.0f ) / fTemp;
// Now set up the table.
fCol1 = 0.0f;
pwRampR = &(wRamp[0]);
pwRampG = &(wRamp[256]);
pwRampB = &(wRamp[512]);
for ( iCount = 256; iCount > 0; iCount-- )
{
fCol1 += 1.0f / 256.0f;
// Apply linear approximation gamma.
if ( fCol1 < fGammaCutoff12 )
{
fCol2 = fGammaBase1 + fGammaGrad1 * fCol1;
}
else
{
fCol2 = fGammaBase2 + fGammaGrad2 * fCol1;
}
// Apply contrast
if ( fCol2 < fContCutoff12 )
{
fCol3 = fContBase1 + fContGrad1 * fCol2;
}
else if ( fCol2 < fContCutoff23 )
{
fCol3 = fContBase2 + fContGrad2 * fCol2;
}
else
{
fCol3 = fContBase3 + fContGrad3 * fCol2;
}
// Apply brightness
fCol4 = fBrightBase + fBrightGrad * fCol3;
// Convert 0.0->1.0 to 0->65535
fTemp = ( fCol4 * 65536.0f );
myFtoi ( &iTemp, fTemp );
if ( iTemp < 0 )
{
iTemp = 0;
}
else if ( iTemp > 65535 )
{
iTemp = 65535;
}
*pwRampR = (WORD)iTemp;
*pwRampG = (WORD)iTemp;
*pwRampB = (WORD)iTemp;
pwRampR++;
pwRampG++;
pwRampB++;
}
// And do the hardware itself.
hDC = CREATE_DRIVER_DC ( pThisDisplay->pGLInfo );
if ( hDC != NULL )
{
bRes = SetDeviceGammaRamp ( hDC, wRamp );
DELETE_DRIVER_DC ( hDC );
ASSERTDD ( bRes, "DdControlColor - SetDeviceGammaRamp failed" );
}
else
{
ASSERTDD ( FALSE, "DdControlColor - CREATE_DRIVER_DC failed" );
}
}
else
{
// Don't know what they want to do. Panic.
ASSERTDD ( FALSE, "DdControlColor - don't know what to do." );
lpColConData->ddRVal = DDERR_INVALIDPARAMS;
return ( DDHAL_DRIVER_HANDLED );
}
lpColConData->ddRVal = DD_OK;
return ( DDHAL_DRIVER_HANDLED );
} // DdControlColor
#endif // W95_DDRAW
DirectXGlobals g_DXGlobals = { 0 };
#if WNT_DDRAW
//-----------------------------Public Routine----------------------------------
//
// ***************************WIN NT ONLY**********************************
//
// DdMapMemory
//
// Maps application-modifiable portions of the frame buffer into the
// user-mode address space of the specified process, or unmaps memory.
//
// DdMapMemory is called to perform memory mapping before the first call to
// DdLock. The handle returned by the driver in fpProcess will be passed to
// every DdLock call made on the driver.
//
// DdMapMemory is also called to unmap memory after the last DdUnLock call is
// made.
//
// To prevent driver crashes, the driver must not map any portion of the frame
// buffer that must not be modified by an application.
//
// Parameters
// lpMapMemory
// Points to a DD_MAPMEMORYDATA structure that contains details for
// the memory mapping or unmapping operation.
//
// .lpDD
// Points to a DD_DIRECTDRAW_GLOBAL structure that represents
// the driver.
// .bMap
// Specifies the memory operation that the driver should perform.
// A value of TRUE indicates that the driver should map memory;
// FALSE means that the driver should unmap memory.
// .hProcess
// Specifies a handle to the process whose address space is
// affected.
// .fpProcess
// Specifies the location in which the driver should return the
// base address of the process's memory mapped space when bMap
// is TRUE. When bMap is FALSE, fpProcess contains the base
// address of the memory to be unmapped by the driver.
// .ddRVal
// Specifies the location in which the driver writes the return
// value of the DdMapMemory callback. A return code of DD_OK
// indicates success.
//
//-----------------------------------------------------------------------------
DWORD CALLBACK
DdMapMemory(
PDD_MAPMEMORYDATA lpMapMemory)
{
PDEV* ppdev;
VIDEO_SHARE_MEMORY ShareMemory;
VIDEO_SHARE_MEMORY_INFORMATION ShareMemoryInformation;
DWORD ReturnedDataLength;
DBG_CB_ENTRY(DdMapMemory);
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))
{
DISPDBG((ERRLVL, "Failed IOCTL_VIDEO_SHARE_MEMORY"));
lpMapMemory->ddRVal = DDERR_GENERIC;
DISPDBG((ERRLVL, "DdMapMemory: Exit GEN, DDHAL_DRIVER_HANDLED"));
DBG_CB_EXIT(DdMapMemory, 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;
DBG_CB_EXIT(DdMapMemory, DD_OK);
return(DDHAL_DRIVER_HANDLED);
} // DdMapMemory
//-----------------------------Public Routine----------------------------------
//
// ***************************WIN NT ONLY**********************************
//
// 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;
PDEV* ppdev;
LONGLONG li;
DWORD Unused = 0;
P3_THUNKEDDATA* pThisDisplay;
DWORD dwChipConfig;
DWORD cHeaps;
static DWORD fourCC[] = { FOURCC_YUV422 }; // The FourCC's we support
ppdev = (PDEV*) dhpdev;
pThisDisplay = (P3_THUNKEDDATA*) ppdev->thunkData;
DBG_CB_ENTRY(DrvGetDirectDrawInfo);
*pdwNumFourCC = 0;
// We may not support DirectDraw on this card:
if (!(ppdev->flStatus & STAT_DIRECTDRAW))
{
DISPDBG((ERRLVL, "DrvGetDirectDrawInfo: exit, not enabled"));
DBG_CB_EXIT(DrvGetDirectDrawInfo,FALSE);
return(FALSE);
}
// Need a pointer to the registers to read config info
pThisDisplay->pGLInfo->pRegs = (ULONG_PTR) ppdev->pulCtrlBase[0];
//@@BEGIN_DDKSPLIT
//azn - loss of bits 64->32
//@@END_DDKSPLIT
pThisDisplay->control = (FLATPTR)pThisDisplay->pGLInfo->pRegs;
pThisDisplay->pGlint = (FPGLREG)pThisDisplay->control;
#if DBG
// We can only initialise g_pThisTemp after
// the registers have been mapped in.
g_pThisTemp = pThisDisplay;
#endif
// Decide if we can use AGP or not
dwChipConfig =
(DWORD)((PREGISTERS)pThisDisplay->pGLInfo->pRegs)->Glint.ChipConfig;
// Make the AGP decision (NT Only!)
if ( ((dwChipConfig & PM_CHIPCONFIG_AGP1XCAPABLE) ||
(dwChipConfig & PM_CHIPCONFIG_AGP2XCAPABLE) ||
(dwChipConfig & PM_CHIPCONFIG_AGP4XCAPABLE)) )
{
DISPDBG((WRNLVL,"AGP Permedia3 Board detected!"));
pThisDisplay->bCanAGP = TRUE;
}
else
{
DISPDBG((WRNLVL,"Permedia3 Board is NOT AGP"));
pThisDisplay->bCanAGP = FALSE;
}
// Fill in the DDHAL Informational caps that Win95 has setup.
__GetDDHALInfo(pThisDisplay, pHalInfo);
// On Win2K we need to return the D3D callbacks
DISPDBG((DBGLVL ,"Creating Direct3D info"));
_D3DHALCreateDriver(pThisDisplay);
// Record the pointers that were created. Note that the above call
// may not have recreated a previous set of data.
pHalInfo->lpD3DGlobalDriverData = (void*)pThisDisplay->lpD3DGlobalDriverData;
pHalInfo->lpD3DHALCallbacks = (void*)pThisDisplay->lpD3DHALCallbacks;
pHalInfo->lpD3DBufCallbacks = (void *)pThisDisplay->lpD3DBufCallbacks;
if ( (pHalInfo->lpD3DBufCallbacks) &&
(pHalInfo->lpD3DBufCallbacks->dwSize != 0))
{
pHalInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_EXECUTEBUFFER;
}
// Fill in any DDHAL caps that are specific to Windows NT.
// 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)
{
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;
//@@BEGIN_DDKSPLIT
// Free up as much off-screen memory as possible:
//TMM ?? bMoveAllDfbsFromOffscreenToDibs(ppdev);
//@@END_DDKSPLIT
// We have to tell DirectDraw our preferred off-screen alignment, even
// if we're doing our own off-screen memory management:
pHalInfo->vmiData.dwOffscreenAlign = 4;
pHalInfo->vmiData.dwZBufferAlign = 4;
pHalInfo->vmiData.dwTextureAlign = 4;
pHalInfo->vmiData.dwOverlayAlign = 4;
// Since we do our own memory allocation, we have to set dwVidMemTotal
// ourselves. Note that this represents the amount of available off-
// screen memory, not all of video memory:
pHalInfo->ddCaps.dwVidMemTotal =
ppdev->heap.cxMax * ppdev->heap.cyMax * ppdev->cjPelSize;
// If we are on Permedia, then setup the YUV modes for Video playback
// acceleration. We can do YUV conversions at any depth except 8 bits...
// On Win95 this information is setup in the Mini Display Driver.
if (ppdev->iBitmapFormat != BMF_8BPP)
{
*pdwNumFourCC = sizeof( fourCC ) / sizeof( fourCC[0] );
if (pdwFourCC)
{
memcpy(pdwFourCC, fourCC, sizeof(fourCC));
}
}
cHeaps = 0;
if(pThisDisplay->bCanAGP)
{
++cHeaps; // agp memory heap
}
// Report the heaps we want DD to manage.
// Currently this is needed in this sample for the AGP heap.
if(pvmList)
{
VIDEOMEMORY *pVm = pvmList;
// If we support AGP , then define the AGP heap
if(pThisDisplay->bCanAGP)
{
DWORD dwAGPMemBytes;
//@@BEGIN_DDKSPLIT
// azn This business of hard-allocating 32MB is not right.
// We need to fix it and verify with JeffN what's the best
// policy to show in the sample
// Request a suitably sized AGP heap, don't ask for a heap
// larger than the available memory
// This is taken care of by the W2000 runtime policy, so I don't
// think we need to do this for W2k. CTM.
//@@END_DDKSPLIT
// Default to 32Mb of AGP memory
dwAGPMemBytes = 32*1024*1024;
// Report the AGP heap
// 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).
// DDraw ignores our start address so just set to zero
pVm->fpStart = 0;
// Fetch the last byte of AGP memory
pVm->fpEnd = dwAGPMemBytes - 1;
pVm->dwFlags = VIDMEM_ISNONLOCAL |
VIDMEM_ISLINEAR |
VIDMEM_ISWC;
// Only use AGP memory for texture surfaces
pVm->ddsCaps.dwCaps = DDSCAPS_OVERLAY |
DDSCAPS_OFFSCREENPLAIN |
DDSCAPS_FRONTBUFFER |
DDSCAPS_BACKBUFFER |
DDSCAPS_ZBUFFER |
DDSCAPS_3DDEVICE;
pVm->ddsCapsAlt.dwCaps = DDSCAPS_OVERLAY |
DDSCAPS_OFFSCREENPLAIN |
DDSCAPS_FRONTBUFFER |
DDSCAPS_BACKBUFFER |
DDSCAPS_ZBUFFER |
DDSCAPS_3DDEVICE;
DISPDBG((DBGLVL, "Initialised AGP Heap for P2, Start:0x%x, End:0x%x",
pVm->fpStart, pVm->fpEnd));
++pVm;
}
else
{
DISPDBG((WRNLVL, "NOT reporting AGP heap"));
}
}
else
{
DISPDBG((DBGLVL, "Heap info NOT requested"));
}
// Report the number of heaps we support
if (pdwNumHeaps)
{
*pdwNumHeaps = cHeaps;
}
DBG_CB_EXIT(DrvGetDirectDrawInfo,TRUE);
return(TRUE);
} // DrvGetDirectDrawInfo
#endif // WNT_DDRAW
#if USE_FLIP_BACKOFF
//-----------------------------------------------------------------------------
//
// __WaitTimeDelay
//
//-----------------------------------------------------------------------------
#define WAIT_TIME_DELAY 2
void __WaitTimeDelay(void)
{
static DWORD dwLastTime; // Doesn't matter what the
// start value is (honest!)
DWORD dwCurTime, iTimeDiff;
// Make sure that we don't start hammering on the chip.
// If someone uses the WAIT flag, or they do a loop
// themselves, we will constantly be reading the chip,
// which will disrupt the DMA stream. Therefore,
// make sure we don't start reading it too often.
// This #define will need tweaking, of course.
do
{
dwCurTime = timeGetTime();
// Be careful about wraparound conditions.
iTimeDiff = (signed int)( dwCurTime - dwLastTime );
} while ( ( iTimeDiff > 0 ) && ( iTimeDiff < WAIT_TIME_DELAY ) );
// And store the new "last" time.
dwLastTime = dwCurTime;
} // __WaitTimeDelay
#endif //#if USE_FLIP_BACKOFF
//-----------------------------------------------------------------------------
//
// __QueryRenderIDStatus
//
// Checks to see if the given two RenderIDs have been finished yet.
//
// If there is a problem, the pipeline will be flushed and the
// RenderIDs set to the newest ID.
//
// If bAllowDMAFlush is TRUE, then if either RenderID is still in the
// pipe, the current DMA buffer is flushed. Otherwise there is a
// fairly good chance that the command with that RenderID may simply
// sit in the DMA buffer and never be executed. To disable this,
// pass in FALSE. This may be needed because the routine has already
// grabbed the DMA buffer, etc. and in that case it needs to do the flush
// itself when it gets DDERR_WASSTILLDRAWING.
//
// The return value is either DD_OK (both RenderIDs have been finished),
// or DDERR_WASSTILLDRAWING.
//
//-----------------------------------------------------------------------------
HRESULT
__QueryRenderIDStatus(
P3_THUNKEDDATA* pThisDisplay,
BOOL bAllowDMAFlush )
{
P3_DMA_DEFS();
ASSERTDD ( CHIP_RENDER_ID_IS_VALID(),
"** __QueryRenderIDStatus:Chip RenderID was invalid - fix it!");
if ( RENDER_ID_HAS_COMPLETED ( pThisDisplay->dwLastFlipRenderID ))
{
// OK, the RenderID has cleared the pipe, so we can carry on.
return ( DD_OK );
}
else
{
// Can't flip yet - one surface is still pending.
if (!NEED_TO_RESYNC_CHIP_AND_SURFACE (pThisDisplay->dwLastFlipRenderID))
{
// No error - we just need to wait. We'll flush the buffer and
// return DDERR_WASSTILLDRAWING
if ( bAllowDMAFlush )
{
DDRAW_OPERATION(pContext, pThisDisplay);
P3_DMA_GET_BUFFER();
P3_DMA_FLUSH_BUFFER();
}
#if USE_FLIP_BACKOFF
__WaitTimeDelay();
#endif
return ( DDERR_WASSTILLDRAWING );
}
else
{
// Something went wrong - need to do a safety-net resync.
DISPDBG((ERRLVL,"__QueryRenderIDStatus: "
"RenderID failure - need a resync"));
SYNC_WITH_GLINT;
pThisDisplay->dwLastFlipRenderID = GET_HOST_RENDER_ID();
// And continue with the operation.
return ( DD_OK );
}
}
} // __QueryRenderIDStatus
//-----------------------------------------------------------------------------
//
// _DX_QueryFlipStatus
//
// Checks and sees if the most recent flip has occurred. If so returns DD_OK.
//
//-----------------------------------------------------------------------------
HRESULT
_DX_QueryFlipStatus(
P3_THUNKEDDATA* pThisDisplay,
FLATPTR fpVidMem,
BOOL bAllowDMAFlush )
{
// If fpVidMem == 0, the Query is asking for the 'general flip status'.
// The question is "Am I safe to add another flip, independent of surfaces".
// If fpVidmem != 0, the Query is asking if it is safe to 'use' the current
// fpvidmem surface. It will only be safe to use unconditionally if that
// surface has been succesfully flipped away from, OR it was not the last
// surface flipped away from.
// The answers will be yes, iff the RenderID of the flip travelling down
// the core has been sent to the MemoryController and put in the scratch ID,
// and iff the bypass pending bit has been cleared. These two checks
// effectively guarantee that the previously queue'd flip has taken place.
// The fpFlipFrom is a record of the last surface that was flipped away from
if((fpVidMem == 0) || (fpVidMem == pThisDisplay->flipRecord.fpFlipFrom))
{
DWORD dwVidControl;
HRESULT hres;
// Check if the pThisDisplay->dwLastFlipRenderID has completed
hres = __QueryRenderIDStatus ( pThisDisplay, bAllowDMAFlush );
if ( SUCCEEDED(hres) )
{
BOOL bFlipHasFinished;
// OK, the previous flip has got to the end of the pipe,
// but it may not actually have happened yet.
// Read the Bypass pending bit. If it's clear then
// we proceed.
#if W95_DDRAW
if ( ( ( pThisDisplay->pGLInfo->dwFlags & GMVF_DFP_DISPLAY ) != 0 ) &&
( ( pThisDisplay->pGLInfo->dwScreenWidth !=
pThisDisplay->pGLInfo->dwVideoWidth ) ||
( pThisDisplay->pGLInfo->dwScreenHeight !=
pThisDisplay->pGLInfo->dwVideoHeight ) ) )
{
// Display driver is using the overlay on a DFP, so we need to
// check the overlay pending bit, not the screen pending bit.
if ( ( ( READ_GLINT_CTRL_REG(VideoOverlayUpdate) ) & 0x1 ) == 0 )
{
bFlipHasFinished = TRUE;
}
else
{
bFlipHasFinished = FALSE;
}
}
else
#endif // W95_DDRAW
{
dwVidControl = READ_GLINT_CTRL_REG(VideoControl);
if (dwVidControl & (0x1 << 7))
{
bFlipHasFinished = FALSE;
}
else
{
bFlipHasFinished = TRUE;
}
}
if ( bFlipHasFinished )
{
// This flip has actually completed.
return ( DD_OK );
}
else
{
#if USE_FLIP_BACKOFF
__WaitTimeDelay();
#endif //#if USE_FLIP_BACKOFF
return ( DDERR_WASSTILLDRAWING );
}
}
else
{
// No, still waiting for the flip command to exit the pipe.
return ( DDERR_WASSTILLDRAWING );
}
}
else
{
return ( DD_OK );
}
} // _DX_QueryFlipStatus
//-----------------------------Public Routine----------------------------------
//
// DdFlip
//
// Causes the surface memory associated with the target surface to become
// the primary surface, and the current surface to become the nonprimary
// surface.
//
// DdFlip allows a display driver to perform multi-buffering. DirectDraw drivers
// must implement this function.
//
// The driver should update its surface pointers so that the next frame will be
// written to the surface to which lpSurfTarg points. If a previous flip request
// is still pending, the driver should fail the call and return
// DDERR_WASSTILLDRAWING. The driver should ensure that the scan line is not in
// the vertical blank before performing the flip. DdFlip does not affect the
// actual display of the video data.
//
// If the driver's hardware supports overlays or textures, DdFlip should make
// any necessary checks based on the surface type before performing the flip.
//
// Parameters
//
// lpFlipData
// Points to a DD_FLIPDATA structure that contains the information
// required to perform the flip.
//
// .lpDD
// Points to the DD_DIRECTDRAW_GLOBAL structure that describes
// the driver.
// .lpSurfCurr
// Points to the DD_SURFACE_LOCAL structure describing the
// current surface.
// .lpSurfTarg
// Points to the DD_SURFACE_LOCAL structure describing the
// target surface; that is, the surface to which the driver
// should flip.
// .dwFlags
// This is a set of flags that provide the driver with details
// for the flip. This member can be a bit-wise OR of the
// following flags:
//
// DDFLIP_EVEN
// The surface to which lpSurfTarg points contains only
// the even field of video data. This flag is valid only when
// the surface is an overlay, and is mutually exclusive of
// DDFLIP_ODD.
// DDFLIP_ODD
// The surface to which lpSurfTarg points contains only the
// odd field of video data. This flag is valid only when the
// surface is an overlay, and is mutually exclusive of
// DDFLIP_EVEN.
// DDFLIP_NOVSYNC
// The driver should perform the flip and return immediately.
// Typically, the now current back buffer (which used to be
// the front buffer) is still visible until the next vertical
// retrace. Subsequent operations involving the surfaces
// to which lpSurfCurr and lpSurfTarg point will not check
// to see if the physical flip has finished. This allows an
// application to perform flips at a higher frequency than
// the monitor refresh rate, although it might introduce
// visible artifacts.
// DDFLIP_INTERVAL2
// The driver should perform the flip on every other vertical
// sync. It should return DDERR_WASSTILLDRAWING until the
// second vertical retrace has occurred. This flag is mutually
// exclusive of DDFLIP_INTERVAL3 and DDFLIP_INTERVAL4.
// DDFLIP_INTERVAL3
// The driver should perform the flip on every third vertical
// sync. It should return DDERR_WASSTILLDRAWING until the
// third vertical retrace has occurred. This flag is mutually
// exclusive of DDFLIP_INTERVAL2 and DDFLIP_INTERVAL4.
// DDFLIP_INTERVAL4
// The driver should perform the flip on every fourth vertical
// sync. It should return DDERR_WASSTILLDRAWING until the
// fourth vertical retrace has occurred. This flag is mutually
// exclusive of DDFLIP_INTERVAL2 and DDFLIP_INTERVAL3.
//
// .ddRVal
// Specifies the location in which the driver writes the return
// value of the DdFlip callback. A return code of DD_OK indicates
// success.
// .Flip
// This is unused on Windows 2000.
// .lpSurfCurrLeft
// Points to the DD_SURFACE_LOCAL structure describing the current
// left surface.
// .lpSurfTargLeft
// Points to the DD_SURFACE_LOCAL structure describing the left
// target surface to flip to.
//
//-----------------------------------------------------------------------------
DWORD CALLBACK
DdFlip(
LPDDHAL_FLIPDATA lpFlipData)
{
DWORD dwDDSurfaceOffset;
P3_THUNKEDDATA* pThisDisplay;
HRESULT ddrval;
GET_THUNKEDDATA(pThisDisplay, lpFlipData->lpDD);
DBG_CB_ENTRY(DdFlip);
VALIDATE_MODE_AND_STATE(pThisDisplay);
STOP_SOFTWARE_CURSOR(pThisDisplay);
// Is the previous Flip already done? Check if the current surface is
// already displayed and don't allow a new flip (unless the DDFLIP_NOVSYNC
// is set) to queue if the old one isn't finished.
ddrval = _DX_QueryFlipStatus(pThisDisplay, 0, TRUE);
if((FAILED(ddrval)) &&
!(lpFlipData->dwFlags & DDFLIP_NOVSYNC))
{
lpFlipData->ddRVal = DDERR_WASSTILLDRAWING;
START_SOFTWARE_CURSOR(pThisDisplay);
DBG_CB_EXIT(DdFlip,DDERR_WASSTILLDRAWING);
return DDHAL_DRIVER_HANDLED;
}
// Set the flipped flag so that the D3D side does any necessary
// setup updates before starting to render the next frame
pThisDisplay->bFlippedSurface = TRUE;
// Do the flip
{
P3_DMA_DEFS();
DWORD dwNewRenderID;
DDRAW_OPERATION(pContext, pThisDisplay);
P3_DMA_GET_BUFFER_ENTRIES(12);
// Make sure all the rendering is finished
SYNC_WITH_GLINT;
// Check the surface type (overlay or not overlay)
// Update the overlay
if ((((pThisDisplay->pGLInfo->dwFlags & GMVF_DFP_DISPLAY) != 0) &&
((pThisDisplay->pGLInfo->dwScreenWidth !=
pThisDisplay->pGLInfo->dwVideoWidth) ||
(pThisDisplay->pGLInfo->dwScreenHeight !=
pThisDisplay->pGLInfo->dwVideoHeight))) ||
(lpFlipData->lpSurfTarg->ddsCaps.dwCaps & DDSCAPS_OVERLAY))
{
DWORD dwVideoOverlayUpdate;
do
{
dwVideoOverlayUpdate = READ_GLINT_CTRL_REG(VideoOverlayUpdate);
} while ((dwVideoOverlayUpdate & 0x1) != 0);
// Just let the overlay routine do the hard work.
// Tell it that this is a screen emulation.
_DD_OV_UpdateSource(pThisDisplay,
lpFlipData->lpSurfTarg);
UPDATE_OVERLAY(pThisDisplay,
!(lpFlipData->dwFlags & DDFLIP_NOVSYNC),
FALSE);
}
else // Normal mode - flip the screen address.
{
ULONG ulVControl;
#if W95_DDRAW
// Apps should use the DDFLIP_NOVSYNC to take advantage of
// the new capability of the Perm3
if (! (lpFlipData->dwFlags & DDFLIP_NOVSYNC))
{
if (READ_GLINT_CTRL_REG(VideoControl) & __GP_VIDEO_ENABLE)
{
LOAD_GLINT_CTRL_REG(IntFlags, INTR_VBLANK_SET);
while (((READ_GLINT_CTRL_REG(IntFlags)) & INTR_VBLANK_SET) == 0);
}
}
#endif
#if DX7_STEREO
if (lpFlipData->dwFlags & DDFLIP_STEREO ) // will be stereo
{
if (lpFlipData->lpSurfTargLeft)
{
dwDDSurfaceOffset =
(DWORD)(lpFlipData->lpSurfTargLeft->lpGbl->fpVidMem -
pThisDisplay->dwScreenFlatAddr);
// Update the screenbase address using the DownloadAddress
// & Data mechanism (therefore through the core)
SEND_P3_DATA(VTGAddress,
VTG_VIDEO_ADDRESS(VID_SCREENBASERIGHT));
SEND_P3_DATA(VTGData, (dwDDSurfaceOffset >> 4) );
}
ulVControl = READ_GLINT_CTRL_REG(VideoControl);
LOAD_GLINT_CTRL_REG(VideoControl,
ulVControl | __VIDEO_STEREOENABLE);
}
else
{
ulVControl = READ_GLINT_CTRL_REG(VideoControl);
LOAD_GLINT_CTRL_REG(VideoControl,
ulVControl & (~__VIDEO_STEREOENABLE));
}
#endif
// Get the surface offset from the start of memory
dwDDSurfaceOffset =
(DWORD)(lpFlipData->lpSurfTarg->lpGbl->fpVidMem -
pThisDisplay->dwScreenFlatAddr);
// Update the screenbase address using the DownloadAddress/data
// mechanism (therefore through the core)
// Setup so that DownloadData will update the ScreenBase Address.
SEND_P3_DATA(VTGAddress, VTG_VIDEO_ADDRESS(VID_SCREENBASE));
SEND_P3_DATA(VTGData, (dwDDSurfaceOffset >> 4) );
}
// Send a new RenderID to the chip.
dwNewRenderID = GET_NEW_HOST_RENDER_ID();
SEND_HOST_RENDER_ID ( dwNewRenderID );
pThisDisplay->dwLastFlipRenderID = dwNewRenderID;
// Flush the P3 Data
P3_DMA_COMMIT_BUFFER();
P3_DMA_FLUSH_BUFFER();
}
// Remember where we flipped from
pThisDisplay->flipRecord.fpFlipFrom =
lpFlipData->lpSurfCurr->lpGbl->fpVidMem;
lpFlipData->ddRVal = DD_OK;
START_SOFTWARE_CURSOR(pThisDisplay);
DBG_CB_EXIT(DdFlip,DD_OK);
return DDHAL_DRIVER_HANDLED;
} // DdFlip
//-----------------------------Public Routine----------------------------------
//
// DdWaitForVerticalBlank
//
// Returns the vertical blank status of the device.
//
// Parameters
//
// lpWaitForVerticalBlank
// Points to a DD_WAITFORVERTICALBLANKDATA structure that
// contains the information required to obtain the vertical
// blank status.
//
// PDD_DIRECTDRAW_GLOBAL
// lpDD
// Points to the DirectDraw structure representing
// the DirectDraw object.
// DWORD
// dwFlags
// Specifies how the driver should wait for the vertical blank.
// This member can be one of the following values:
//
// DDWAITVB_I_TESTVB The driver should determine whether
// a vertical blank is currently
// occurring and return the status in
// bIsInVB.
// DDWAITVB_BLOCKBEGIN The driver should return when it
// detects the beginning of the vertical
// blank interval.
// DDWAITVB_BLOCKBEGINEVENT Is currently unsupported on Windows
// 2000 and should be ignored by the
// driver.
// DDWAITVB_BLOCKEND The driver should return when it
// detects the end of the vertical
// blank interval and display begins.
// DWORD
// bIsInVB
// Indicates the status of the vertical blank. A value of
// TRUE indicates that the device is in a vertical blank;
// FALSE means that it is not. The driver should return the
// current vertical blanking status in this member when
// dwFlags is DDWAITVB_I_TESTVB.
// DWORD
// hEvent
// Is currently unsupported on Windows 2000 and should be ignored
// by the driver.
// HRESULT
// ddRVal
// Is the location in which the driver writes the return value of
// the DdWaitForVerticalBlank callback. A return code of DD_OK
// indicates success.
// VOID*
// WaitForVerticalBlank
// Is unused on Windows 2000.
//
// Return Value
// DdWaitForVerticalBlank returns one of the following callback codes:
//
// DDHAL_DRIVER_HANDLED
// DDHAL_DRIVER_NOTHANDLED
//
// Comments
// Depending on the value of dwFlags, the driver should do the following:
//
// If dwFlags is DDWAITVB_I_TESTVB, the driver should query the current
// vertical blanking status. The driver should set bIsInVB to TRUE if the
// monitor is currently in a vertical blank; otherwise it should set it
// to FALSE.
//
// If dwFlags is DDWAITVB_BLOCKBEGIN, the driver should block and wait
// until a vertical blank begins. If a vertical blank is in progress when
// the driver begins the block, the driver should wait until the next
// vertical blank begins before returning.
//
// If dwFlags is DDWAITVB_BLOCKEND, the driver should block and wait
// until a vertical blank ends.
//
// When the driver successfully handles the action specified in dwFlags,
// it should set DD_OK in ddRVal and return DDHAL_DRIVER_HANDLED. The
// driver should return DDHAL_DRIVER_NOTHANDLED for those flags that it
// is incapable of handling.
//
// DdWaitForVerticalBlank allows an application to synchronize itself
// with the vertical blanking interval (VBI).
//
//-----------------------------------------------------------------------------
// bit in VideoControl Register
#define __GP_VIDEO_ENABLE 0x0001
DWORD CALLBACK
DdWaitForVerticalBlank(
LPDDHAL_WAITFORVERTICALBLANKDATA lpWaitForVerticalBlank)
{
static BOOL bBlankReturn = TRUE;
P3_THUNKEDDATA* pThisDisplay;
GET_THUNKEDDATA(pThisDisplay, lpWaitForVerticalBlank->lpDD);
DBG_CB_ENTRY(DdWaitForVerticalBlank);
switch(lpWaitForVerticalBlank->dwFlags)
{
case DDWAITVB_I_TESTVB:
//
// just toggle the return bit when monitor is powered off
//
if( ! ( READ_GLINT_CTRL_REG(VideoControl) & __GP_VIDEO_ENABLE ) )
{
lpWaitForVerticalBlank->bIsInVB = bBlankReturn;
bBlankReturn = !bBlankReturn;
}
else
{
// Just a request for current VBLANK status
lpWaitForVerticalBlank->bIsInVB = IN_VBLANK;
}
lpWaitForVerticalBlank->ddRVal = DD_OK;
DBG_CB_EXIT(DdWaitForVerticalBlank,DD_OK);
return DDHAL_DRIVER_HANDLED;
case DDWAITVB_BLOCKBEGIN:
//
// only wait when the monitor is on
//
if( READ_GLINT_CTRL_REG(VideoControl) & __GP_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_VBLANK)
NULL;
while(!IN_VBLANK)
NULL;
}
lpWaitForVerticalBlank->ddRVal = DD_OK;
DBG_CB_EXIT(DdWaitForVerticalBlank,DD_OK);
return DDHAL_DRIVER_HANDLED;
case DDWAITVB_BLOCKEND:
//
// only wait when the monitor is on
//
if( READ_GLINT_CTRL_REG(VideoControl) & __GP_VIDEO_ENABLE )
{
// if blockend is requested we wait for the vblank interval to end.
if( IN_VBLANK )
{
while( IN_VBLANK )
NULL;
}
else
{
while(IN_DISPLAY)
NULL;
while(IN_VBLANK)
NULL;
}
}
lpWaitForVerticalBlank->ddRVal = DD_OK;
DBG_CB_EXIT(DdWaitForVerticalBlank,DD_OK);
return DDHAL_DRIVER_HANDLED;
}
DBG_CB_EXIT(DdWaitForVerticalBlank,0);
return DDHAL_DRIVER_NOTHANDLED;
} // DdWaitForVerticalBlank
//-----------------------------Public Routine----------------------------------
//
// DdLock
//
// Locks a specified area of surface memory and provides a valid pointer to a
// block of memory associated with a surface.
//
// Parameters
// lpLock
// Points to a DD_LOCKDATA structure that contains the information
// required to perform the lockdown.
//
// Members
//
// PDD_DIRECTDRAW_GLOBAL
// lpDD
// Points to a DD_DIRECTDRAW_GLOBAL structure that
// describes the driver.
// PDD_SURFACE_LOCAL
// lpDDSurface
// Points to a DD_SURFACE_LOCAL structure that describes the
// surface associated with the memory region to be locked down.
// DWORD
// bHasRect
// Specifies whether the area in rArea is valid.
// RECTL
// rArea
// Is a RECTL structure that defines the area on the
// surface to lock down.
// LPVOID
// lpSurfData
// Is the location in which the driver can return a pointer
// to the memory region that it locked down.
// HRESULT
// ddRVal
// Is the location in which the driver writes the return value
// of the DdLock callback. A return code of DD_OK
// indicates success.
// VOID*
// Lock
// Is unused on Windows 2000.
// DWORD
// dwFlags
// Is a bitmask that tells the driver how to perform the
// memory lockdown. This member is a bitwise-OR of any
// of the following values:
//
// DDLOCK_SURFACEMEMORYPTR The driver should return a valid
// memory pointer to the top of the
// rectangle specified in rArea. If
// no rectangle is specified, the
// driver should return a pointer to
// the top of the surface.
// DDLOCK_WAIT This flag is reserved for system
// use and should be ignored by the
// driver. Otherwise performance may
// be adversely hurt.
// DDLOCK_READONLY The surface being locked will only
// be read from. On Windows 2000,
// this flag is currently never set.
// DDLOCK_WRITEONLY The surface being locked will only
// be written to. On Windows 2000,
// this flag is currently never set.
// DDLOCK_EVENT This flag is reserved for system
// use and should be ignored by the
// driver.
// FLATPTR
// fpProcess
// Is a pointer to a user-mode mapping of the driver's memory.
// The driver performs this mapping in DdMapMemory.
// Return Value
// DdLock returns one of the following callback codes:
//
// DDHAL_DRIVER_HANDLED
// DDHAL_DRIVER_NOTHANDLED
// Comments
//
// DdLock should set ddRVal to DDERR_WASSTILLDRAWING and return
// DDHAL_DRIVER_HANDLED if a blt or flip is in progress.
//
// Unless otherwise specified by dwFlags, the driver can return a memory
// pointer to the top of the surface in lpSurfData. If the driver needs
// to calculate its own address for the surface, it can rely on the
// pointer passed in fpProcess as being a per-process pointer to the
// user-mode mapping of its DirectDraw-accessible frame buffer.
//
// A lock does not provide exclusive access to the requested memory block;
// that is, multiple threads can lock the same surface at the same time.
// It is the application's responsibility to synchronize access to the
// memory block whose pointer is being obtained.
//
//-----------------------------------------------------------------------------
DWORD CALLBACK
DdLock(
LPDDHAL_LOCKDATA lpLockData )
{
HRESULT ddrval;
P3_THUNKEDDATA* pThisDisplay;
GET_THUNKEDDATA(pThisDisplay, lpLockData->lpDD);
DBG_CB_ENTRY(DdLock);
VALIDATE_MODE_AND_STATE(pThisDisplay);
DBGDUMP_DDRAWSURFACE_LCL(DBGLVL, lpLockData->lpDDSurface);
// 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.
STOP_SOFTWARE_CURSOR(pThisDisplay);
// Check to see if any pending physical flip has occurred.
ddrval = _DX_QueryFlipStatus(pThisDisplay,
lpLockData->lpDDSurface->lpGbl->fpVidMem,
TRUE);
if( FAILED(ddrval) )
{
lpLockData->ddRVal = DDERR_WASSTILLDRAWING;
START_SOFTWARE_CURSOR(pThisDisplay);
DBG_CB_EXIT(DdLock,DDERR_WASSTILLDRAWING);
return DDHAL_DRIVER_HANDLED;
}
// don't allow a lock if a blt is in progress
if(DRAW_ENGINE_BUSY(pThisDisplay))
{
lpLockData->ddRVal = DDERR_WASSTILLDRAWING;
START_SOFTWARE_CURSOR(pThisDisplay);
DBG_CB_EXIT(DdLock, lpLockData->ddRVal);
return DDHAL_DRIVER_HANDLED;
}
#if DX7_TEXMANAGEMENT
//
// If the user attempts to lock a driver managed surface,
// mark it as dirty and return. This way next time we attempt
// to use the surface we will reload it from the sysmem copy
//
if (lpLockData->lpDDSurface->lpSurfMore->ddsCapsEx.dwCaps2 &
DDSCAPS2_TEXTUREMANAGE)
{
DISPDBG((DBGLVL, "DDraw:Lock %08lx %08lx",
lpLockData->lpDDSurface->lpSurfMore->dwSurfaceHandle,
lpLockData->lpDDSurface->lpGbl->fpVidMem));
_D3D_TM_MarkDDSurfaceAsDirty(pThisDisplay,
lpLockData->lpDDSurface,
TRUE);
if (lpLockData->bHasRect)
{
#if DX8_3DTEXTURES
if (lpLockData->dwFlags & DDLOCK_HASVOLUMETEXTUREBOXRECT)
{
DWORD left, right, front, back;
// Sub Volume Lock suppport (DX8.1 feature)
// Check if we are able to lock just a subvolume instead of
// the whole volume texture and therefore potentially increase
// performance.
// left and .right subfields of the rArea field have to be
// reinterpreted as also containing respectively the Front and
// Back coordinates of the locked volume in their higher 16 bits
front = lpLockData->rArea.left >> 16;
back = lpLockData->rArea.right >> 16;
left = lpLockData->rArea.left && 0xFFFF;
right = lpLockData->rArea.right && 0xFFFF;
lpLockData->lpSurfData = (LPVOID)
(lpLockData->lpDDSurface->lpGbl->fpVidMem +
(front * lpLockData->lpDDSurface->lpGbl->dwBlockSizeY ) +
(lpLockData->lpDDSurface->lpGbl->lPitch *
lpLockData->rArea.top) +
(lpLockData->rArea.left <<
DDSurf_GetPixelShift(lpLockData->lpDDSurface)));
}
else
#endif // DX8_3DTEXTURES
{
lpLockData->lpSurfData = (LPVOID)
(lpLockData->lpDDSurface->lpGbl->fpVidMem +
(lpLockData->lpDDSurface->lpGbl->lPitch *
lpLockData->rArea.top) +
(lpLockData->rArea.left <<
DDSurf_GetPixelShift(lpLockData->lpDDSurface)));
}
}
else
{
lpLockData->lpSurfData = (LPVOID)
(lpLockData->lpDDSurface->lpGbl->fpVidMem);
}
lpLockData->ddRVal = DD_OK;
START_SOFTWARE_CURSOR(pThisDisplay);
DBG_CB_EXIT(DdLock, lpLockData->ddRVal);
return DDHAL_DRIVER_HANDLED;
}
#endif // DX7_TEXMANAGEMENT
// Switch to DirectDraw context
DDRAW_OPERATION(pContext, pThisDisplay);
// send a flush and wait for outstanding operations
// before allowing surfaces to be locked.
{P3_DMA_DEFS();
P3_DMA_GET_BUFFER();
P3_DMA_FLUSH_BUFFER();
}
// Wait for outstanding operations before allowing surfaces to be locked
SYNC_WITH_GLINT;
// Since all our surfaces are linear we don't need to do
// a patch->unpatch conversion here.
START_SOFTWARE_CURSOR(pThisDisplay);
lpLockData->ddRVal = DD_OK;
DBG_CB_EXIT(DdLock,lpLockData->ddRVal);
// 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
//-----------------------------Public Routine----------------------------------
//
// DdUnlock
//
// Releases the lock held on the specified surface.
//
// Parameters
//
// lpUnlock
// Points to a DD_UNLOCKDATA structure that contains the
// information required to perform the lock release.
//
// Members
//
// PDD_DIRECTDRAW_GLOBAL
// lpDD
// Points to a DD_DIRECTDRAW_GLOBAL structure that
// describes the driver.
// PDD_SURFACE_LOCAL
// lpDDSurface
// Points to a DD_SURFACE_LOCAL structure that describes the
// surface to be unlocked.
// HRESULT
// ddRVal
// Is the location in which the driver writes the return value
// of the DdUnlock callback. A return code of DD_OK indicates
// success.
// VOID*
// Unlock
// Is unused on Windows 2000.
//
// Return Value
// DdUnlock returns one of the following callback codes:
//
// DDHAL_DRIVER_HANDLED
// DDHAL_DRIVER_NOTHANDLED
//
// Comments
// The driver does not need to verify that the memory was previously
// locked down by DdLock, because DirectDraw does parameter validation
// before calling this routine.
//-----------------------------------------------------------------------------
DWORD CALLBACK
DdUnlock(
LPDDHAL_UNLOCKDATA lpUnlockData )
{
P3_THUNKEDDATA* pThisDisplay;
DBG_CB_ENTRY(DdUnlock);
lpUnlockData->ddRVal = DD_OK;
DBG_CB_EXIT(DdUnlock,lpUnlockData->ddRVal);
return ( DDHAL_DRIVER_HANDLED );
} // DdUnlock
//-----------------------------Public Routine----------------------------------
// DdGetScanLine
//
// Returns the number of the current physical scan line.
//
// Parameters
// pGetScanLine
// Points to a DD_GETSCANLINEDATA structure in which the
// driver returns the number of the current scan line.
// Members
//
// PDD_DIRECTDRAW_GLOBAL
// lpDD
// Points to a DD_DIRECTDRAW_GLOBAL structure that
// represents the driver.
// DWORD
// dwScanLine
// Is the location in which the driver returns the number
// of the current scan line.
// HRESULT
// ddRVal
// Is the location in which the driver writes the return
// value of the DdGetScanLine callback. A return code of
// DD_OK indicates success.
// VOID *
// GetScanLine
// Is unused on Windows 2000.
// Return Value
// DdGetScanLine returns one of the following callback codes:
//
// DDHAL_DRIVER_HANDLED
// DDHAL_DRIVER_NOTHANDLED
//
// Comments
// If the monitor is not in vertical blank, the driver should write
// the scan line value in dwScanLine. The number must be between zero
// and n, where scan line 0 is the first visible scan line and n is
// the last visible scan line on the screen. The driver should then
// set DD_OK in ddRVal and return DDHAL_DRIVER_HANDLED.
//
// The scan line is indeterminate if a vertical blank is in progress.
// In this situation, the driver should set ddRVal to
// DDERR_VERTICALBLANKINPROGRESS and return DDHAL_DRIVER_HANDLED.
//
//-----------------------------------------------------------------------------
DWORD CALLBACK
DdGetScanLine(
LPDDHAL_GETSCANLINEDATA lpGetScanLine)
{
P3_THUNKEDDATA* pThisDisplay;
GET_THUNKEDDATA(pThisDisplay, lpGetScanLine->lpDD);
DBG_CB_ENTRY(DdGetScanLine);
VALIDATE_MODE_AND_STATE(pThisDisplay);
//
// If a vertical blank is in progress the scan line is in
// 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_VBLANK )
{
lpGetScanLine->ddRVal = DDERR_VERTICALBLANKINPROGRESS;
lpGetScanLine->dwScanLine = 0;
}
else
{
LONG lVBEnd = READ_GLINT_CTRL_REG(VbEnd);
LONG lScanline = READ_GLINT_CTRL_REG(LineCount);
// Need to return a number from 0 -> (ScreenHeight + VBlank Size)
lScanline = lScanline - lVBEnd;
if (lScanline < 0)
{
lScanline = pThisDisplay->dwScreenHeight + (lVBEnd + lScanline);
}
// Modes less than 400 high are line-doubled.
if (pThisDisplay->dwScreenHeight < 400)
{
lScanline >>= 1;
}
DISPDBG((DBGLVL,"Scanline: %d", lScanline));
lpGetScanLine->dwScanLine = (DWORD)lScanline;
lpGetScanLine->ddRVal = DD_OK;
}
DBG_CB_EXIT(DdGetScanLine,lpGetScanLine->ddRVal);
return DDHAL_DRIVER_HANDLED;
} // DdGetScanLine
//-----------------------------Public Routine----------------------------------
// DdGetBltStatus
//
// Queries the blt status of the specified surface.
//
// Parameters
// lpGetBltStatus
// Points to a DD_GETBLTSTATUSDATA structure that contains the
// information required to perform the blt status query.
//
// Members
//
// PDD_DIRECTDRAW_GLOBAL
// lpDD
// Points to a DD_DIRECTDRAW_GLOBAL structure that
// describes the driver.
// PDD_SURFACE_LOCAL
// lpDDSurface
// Points to a DD_SURFACE_LOCAL structure
// representing the surface whose blt status is
// being queried.
// DWORD
// dwFlags
// Specifies the blt status being requested. This
// member can be one of the following values which
// are defined in ddraw.h:
//
// DDGBS_CANBLT Queries whether the driver
// can currently perform a blit.
// DDGBS_ISBLTDONE Queries whether the driver
// has completed the last blit.
// HRESULT
// ddRVal
// Is the location in which the driver writes the
// return value of the DdGetBltStatus callback.
// A return code of DD_OK indicates success.
// VOID*
// GetBltStatus
// Is unused on Windows 2000.
// Return Value
// DdGetBltStatus returns one of the following callback codes:
//
// DDHAL_DRIVER_HANDLED
// DDHAL_DRIVER_NOTHANDLED
//
// Comments
// The blt status that the driver returns is based on the dwFlags
// member of the structure that lpGetBltStatus points to as follows:
//
// If the flag is DDGBS_CANBLT, the driver should determine whether
// the surface is currently involved in a flip. If a flip is not in
// progress and if the hardware is otherwise capable of currently
// accepting a blt request, the driver should return DD_OK in ddRVal.
// If a flip is in progress or if the hardware cannot currently
// accept another blt request, the driver should set ddRVal to
// DDERR_WASSTILLDRAWING.
//
// If the flag is DDGBS_ISBLTDONE, the driver should set ddRVal to
// DDERR_WASSTILLDRAWING if a blt is currently in progress; otherwise
// it should return DD_OK.
//
//
//-----------------------------------------------------------------------------
DWORD CALLBACK DdGetBltStatus(
LPDDHAL_GETBLTSTATUSDATA lpGetBltStatus )
{
P3_THUNKEDDATA* pThisDisplay;
GET_THUNKEDDATA(pThisDisplay, lpGetBltStatus->lpDD);
DBG_CB_ENTRY(DdGetBltStatus);
STOP_SOFTWARE_CURSOR(pThisDisplay);
// Notice that your implementation could be optimized to check for the
// particular surface specified. Here we are just querying the general
// blt status of the engine.
// Driver is being queried whether it can add a blt
if( lpGetBltStatus->dwFlags == DDGBS_CANBLT )
{
// Must explicitely wait for the flip
lpGetBltStatus->ddRVal =
_DX_QueryFlipStatus(pThisDisplay,
lpGetBltStatus->lpDDSurface->lpGbl->fpVidMem,
TRUE);
if( SUCCEEDED( lpGetBltStatus->ddRVal ) )
{
// so there was no flip going on, is the engine idle to add a blt?
if( DRAW_ENGINE_BUSY(pThisDisplay) )
{
lpGetBltStatus->ddRVal = DDERR_WASSTILLDRAWING;
}
else
{
lpGetBltStatus->ddRVal = DD_OK;
}
}
}
else if ( lpGetBltStatus->dwFlags == DDGBS_ISBLTDONE )
{
if ( DRAW_ENGINE_BUSY(pThisDisplay) )
{
lpGetBltStatus->ddRVal = DDERR_WASSTILLDRAWING;
}
else
{
lpGetBltStatus->ddRVal = DD_OK;
}
}
START_SOFTWARE_CURSOR(pThisDisplay);
DBG_CB_EXIT(DdGetBltStatus, lpGetBltStatus->ddRVal);
return DDHAL_DRIVER_HANDLED;
} // DdGetBltStatus
//-----------------------------Public Routine----------------------------------
//
// DdGetFlipStatus
//
// Determines whether the most recently requested flip
// on a surface has occurred.
//
// Parameters
// lpGetFlipStatus
// Points to a DD_GETFLIPSTATUSDATA structure that contains
// the information required to perform the flip status query.
//
// Members
//
// PDD_DIRECTDRAW_GLOBAL
// lpDD
// Points to a DD_DIRECTDRAW_GLOBAL structure
// representing the driver.
// PDD_SURFACE_LOCAL
// lpDDSurface
// Points to a DD_SURFACE_LOCAL structure that
// describes the surface whose flip status is
// being queried.
// DWORD
// dwFlags
// Specifies the flip status being requested. This
// member can be one of the following values which
// are defined in ddraw.h:
//
// DDGFS_CANFLIP Queries whether the driver can
// currently perform a flip.
// DDGFS_ISFLIPDONE Queries whether the driver has
// finished the last flip.
// HRESULT
// ddRVal
// Is the location in which the driver writes the
// return value of the DdGetFlipStatus callback.
// A return code of DD_OK indicates success.
// VOID*
// GetFlipStatus
// Is unused on Windows 2000.
//
// Return Value
// DdGetFlipStatus returns one of the following callback codes:
//
// DDHAL_DRIVER_HANDLED
// DDHAL_DRIVER_NOTHANDLED
//
// Comments
//
// The driver should report its flip status based on the flag set in
// the dwFlags member of the structure that lpGetFlipStatus points
// to as follows:
//
// If the flag is DDGFS_CANFLIP, the driver should determine whether
// the surface is currently involved in a flip. If a flip or a blt is
// not in progress and if the hardware is otherwise capable of
// currently accepting a flip request, the driver should return DD_OK
// in ddRVal. If a flip is in progress or if the hardware cannot
// currently accept a flip request, the driver should set ddRVal to
// DDERR_WASSTILLDRAWING.
//
// If the flag is DDGFS_ISFLIPDONE, the driver should set ddRVal to
// DDERR_WASSTILLDRAWING if a flip is currently in progress; otherwise
// it should return DD_OK.
//
// Notes:
//
// 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
//
// On the Permedia, flips are done using SuspendUntilFrameBlank,
// so no syncs ever need to be done in software, so this always
// returns DD_OK.
//
//-----------------------------------------------------------------------------
DWORD CALLBACK
DdGetFlipStatus(
LPDDHAL_GETFLIPSTATUSDATA lpGetFlipStatus )
{
P3_THUNKEDDATA* pThisDisplay;
GET_THUNKEDDATA(pThisDisplay, lpGetFlipStatus->lpDD);
DBG_CB_ENTRY(DdGetFlipStatus);
STOP_SOFTWARE_CURSOR(pThisDisplay);
//
// 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 = _DX_QueryFlipStatus(pThisDisplay, 0, TRUE);
//
// check if the bltter busy if someone wants to know if they can flip
//
if( lpGetFlipStatus->dwFlags == DDGFS_CANFLIP )
{
if( ( SUCCEEDED( lpGetFlipStatus->ddRVal ) ) &&
( DRAW_ENGINE_BUSY(pThisDisplay) ) )
{
lpGetFlipStatus->ddRVal = DDERR_WASSTILLDRAWING;
}
}
START_SOFTWARE_CURSOR(pThisDisplay);
DBG_CB_EXIT(DdGetFlipStatus,lpGetFlipStatus->ddRVal);
return DDHAL_DRIVER_HANDLED;
} // DdGetFlipStatus
//-----------------------------------------------------------------------------
// __SetupRops
//
// Build array for supported ROPS
//-----------------------------------------------------------------------------
static 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
//-----------------------------------------------------------------------------
//
// ChangeDDHAL32Mode
//
// CALLED PER MODE CHANGE - NEVER AT START OF DAY (NO LOCK)
// Sets up Chip registers for this mode.
//
//-----------------------------------------------------------------------------
void
ChangeDDHAL32Mode(
P3_THUNKEDDATA* pThisDisplay)
{
DISPDBG((DBGLVL,"New Screen Width: %d",pThisDisplay->dwScreenWidth));
//@@BEGIN_DDKSPLIT
#if AZN
// If the driver has just started, reset the DMA Buffers to a known state.
if (pThisDisplay->bStartOfDay)
{
#if 0
unsigned long i;
for (i = 0; i < pThisDisplay->pGLInfo->NumberOfSubBuffers; i++)
{
pThisDisplay->pGLInfo->DMAPartition[i].bStampedDMA = TRUE;
pThisDisplay->pGLInfo->DMAPartition[i].Locked = FALSE;
//azn - this is hard to say in 64 bits!
memset((void*)pThisDisplay->pGLInfo->DMAPartition[i].VirtAddr,
0x4D,
(pThisDisplay->pGLInfo->DMAPartition[i].MaxAddress -
pThisDisplay->pGLInfo->DMAPartition[i].VirtAddr));
}
#endif
// We don't need start of day setup anymore
pThisDisplay->bStartOfDay = FALSE;
}
#endif
//@@END_DDKSPLIT
STOP_SOFTWARE_CURSOR(pThisDisplay);
// Switch to DirectDraw context
DDRAW_OPERATION(pContext, pThisDisplay);
// Set up video Control
#if WNT_DDRAW
{
ULONG vidCon;
vidCon = READ_GLINT_CTRL_REG(VideoControl);
vidCon &= ~(3 << 9);
vidCon |= (0 << 9); // P3/P2 Limit to frame rate
LOAD_GLINT_CTRL_REG(VideoControl, vidCon);
}
#endif // WNT_DDRAW
// We have handled the display mode change
pThisDisplay->bResetMode = 0;
pThisDisplay->ModeChangeCount++;
START_SOFTWARE_CURSOR(pThisDisplay);
} // ChangeDDHAL32Mode
//-----------------------------------------------------------------------------
//
// Function: __GetDDHALInfo
//
// Returns: void
//
// Description:
//
// Takes a pointer to a partially or fully filled in pThisDisplay and a pointer
// to an empty DDHALINFO and fills in the DDHALINFO. This eases porting to NT
// and means that caps changes are done in only one place. The pThisDisplay
// may not be fully constructed here, so you should only:
// a) Query the registry
// b) DISPDBG
// If you need to add anything to pThisDisplay for NT, you should fill it in
// during the DrvGetDirectDraw call.
//
// The problem here is when the code is run on NT. If there was any other way...
//
// The following caps have been found to cause NT to bail....
// DDCAPS_GDI, DDFXCAPS_BLTMIRRORUPDOWN, DDFXCAPS_BLTMIRRORLEFTRIGHT
//
//
//-----------------------------------------------------------------------------
//
// use bits to indicate which ROPs you support.
//
// DWORD 0, bit 0 == ROP 0
// DWORD 8, bit 31 == ROP 255
//
static DWORD ropsAGP[DD_ROP_SPACE] = { 0 };
void
__GetDDHALInfo(
P3_THUNKEDDATA* pThisDisplay,
DDHALINFO* pHALInfo)
{
DWORD dwResult;
BOOL bRet;
int i;
static BYTE ropList95[] =
{
SRCCOPY >> 16,
WHITENESS >> 16,
BLACKNESS >> 16
};
static BYTE ropListNT[] =
{
SRCCOPY >> 16
};
static BYTE ropListAGP[] =
{
SRCCOPY >> 16,
WHITENESS >> 16,
BLACKNESS >> 16
};
static DWORD rops[DD_ROP_SPACE] = { 0 };
// Setup the HAL driver caps.
memset( pHALInfo, 0, sizeof(DDHALINFO) );
pHALInfo->dwSize = sizeof(DDHALINFO);
// Setup the ROPS we do.
#ifdef WNT_DDRAW
__SetupRops( ropListNT,
rops,
sizeof(ropListNT)/sizeof(ropListNT[0]));
#else
__SetupRops( ropList95,
rops,
sizeof(ropList95)/sizeof(ropList95[0]));
#endif
__SetupRops( ropListAGP,
ropsAGP,
sizeof(ropListAGP)/sizeof(ropListAGP[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;
// More caps on Win95 than on NT (mainly for D3D)
#ifdef WNT_DDRAW
pHALInfo->ddCaps.dwCaps |= DDCAPS_3D |
DDCAPS_BLTDEPTHFILL;
pHALInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_3DDEVICE |
DDSCAPS_ZBUFFER |
DDSCAPS_ALPHA;
pHALInfo->ddCaps.dwCaps2 = 0;
#else
pHALInfo->ddCaps.dwCaps |= DDCAPS_3D |
DDCAPS_GDI |
DDCAPS_ALPHA |
DDCAPS_BLTDEPTHFILL;
pHALInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_ALPHA |
DDSCAPS_3DDEVICE |
DDSCAPS_ZBUFFER;
pHALInfo->ddCaps.dwCaps2 = DDCAPS2_NOPAGELOCKREQUIRED | DDCAPS2_FLIPNOVSYNC;
#endif // WNT_DDRAW
#if DX7_TEXMANAGEMENT
// We need to set this bit up in order to be able to do
// out own texture management
pHALInfo->ddCaps.dwCaps2 |= DDCAPS2_CANMANAGETEXTURE;
#if DX8_DDI
pHALInfo->ddCaps.dwCaps2 |= DDCAPS2_CANMANAGERESOURCE;
#endif
#endif
#if DX8_DDI
// We need to flag we can run in windowed mode, otherwise we
// might get restricted by apps to run in fullscreen only
pHALInfo->ddCaps.dwCaps2 |= DDCAPS2_CANRENDERWINDOWED;
#endif
pHALInfo->ddCaps.dwFXCaps = 0;
// P3RX can do:
// 1. Stretching/Shrinking
// 2. YUV->RGB conversion
// 3. Mirroring in X and Y
// 4. ColorKeying from a source color and a source color space
pHALInfo->ddCaps.dwCaps |= DDCAPS_BLTSTRETCH |
DDCAPS_BLTFOURCC |
DDCAPS_COLORKEY |
DDCAPS_CANBLTSYSMEM;
// Special effects caps
pHALInfo->ddCaps.dwFXCaps = DDFXCAPS_BLTSTRETCHY |
DDFXCAPS_BLTSTRETCHX |
DDFXCAPS_BLTSTRETCHYN |
DDFXCAPS_BLTSTRETCHXN |
DDFXCAPS_BLTSHRINKY |
DDFXCAPS_BLTSHRINKX |
DDFXCAPS_BLTSHRINKYN |
DDFXCAPS_BLTSHRINKXN;
// ColorKey caps
pHALInfo->ddCaps.dwCKeyCaps = DDCKEYCAPS_SRCBLT |
DDCKEYCAPS_SRCBLTCLRSPACE |
DDCKEYCAPS_DESTBLT |
DDCKEYCAPS_DESTBLTCLRSPACE;
pHALInfo->ddCaps.dwSVBCaps = DDCAPS_BLT;
// We can do a texture from sysmem to video mem.
pHALInfo->ddCaps.dwSVBCKeyCaps = DDCKEYCAPS_DESTBLT |
DDCKEYCAPS_DESTBLTCLRSPACE;
pHALInfo->ddCaps.dwSVBFXCaps = 0;
// Fill in the sysmem->vidmem rops (only can copy);
for( i=0;i<DD_ROP_SPACE;i++ )
{
pHALInfo->ddCaps.dwSVBRops[i] = rops[i];
}
pHALInfo->ddCaps.dwFXCaps |= DDFXCAPS_BLTMIRRORUPDOWN |
DDFXCAPS_BLTMIRRORLEFTRIGHT;
pHALInfo->ddCaps.dwCKeyCaps |= DDCKEYCAPS_SRCBLTCLRSPACEYUV;
pHALInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_TEXTURE;
#if DX7_STEREO
// Report the stereo capability back to runtime
pHALInfo->ddCaps.dwCaps2 |= DDCAPS2_STEREO;
pHALInfo->ddCaps.dwSVCaps = DDSVCAPS_STEREOSEQUENTIAL;
#endif
// Z Buffer is only 16 Bits
pHALInfo->ddCaps.dwZBufferBitDepths = DDBD_16;
pHALInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_MIPMAP;
if (pThisDisplay->bCanAGP && (pThisDisplay->dwDXVersion > DX5_RUNTIME))
{
pHALInfo->ddCaps.dwCaps2 |= DDCAPS2_NONLOCALVIDMEM;
pHALInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM |
DDSCAPS_NONLOCALVIDMEM;
// We support the hybrid AGP model. This means we have
// specific things we can do from AGP->Video memory, but
// we can also texture directly from AGP memory
pHALInfo->ddCaps.dwCaps2 |= DDCAPS2_NONLOCALVIDMEMCAPS;
}
else
{
DISPDBG((WRNLVL,"P3 Board is NOT AGP"));
}
// If we are a P3 we can do videoports
if (RENDERCHIP_PERMEDIAP3)
{
#ifdef SUPPORT_VIDEOPORT
// We support 1 video port. Must set CurrVideoPorts to 0
// We can't do interleaved bobbing yet - maybe in the future.
pHALInfo->ddCaps.dwCaps2 |= DDCAPS2_VIDEOPORT |
DDCAPS2_CANBOBNONINTERLEAVED;
pHALInfo->ddCaps.dwMaxVideoPorts = 1;
pHALInfo->ddCaps.dwCurrVideoPorts = 0;
#if W95_DDRAW
pHALInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_VIDEOPORT;
#endif // W95_DDRAW
#endif // SUPPORT_VIDEOPORT
if ( ( ( pThisDisplay->pGLInfo->dwFlags & GMVF_DFP_DISPLAY ) != 0 ) &&
( ( pThisDisplay->pGLInfo->dwScreenWidth !=
pThisDisplay->pGLInfo->dwVideoWidth ) ||
( pThisDisplay->pGLInfo->dwScreenHeight !=
pThisDisplay->pGLInfo->dwVideoHeight ) ) )
{
// Display driver is using the overlay to show the
// picture - disable the overlay.
pHALInfo->ddCaps.dwMaxVisibleOverlays = 0;
pHALInfo->ddCaps.dwCurrVisibleOverlays = 0;
}
#if WNT_DDRAW
else if (pThisDisplay->ppdev->flCaps & CAPS_DISABLE_OVERLAY)
#else
else if (pThisDisplay->pGLInfo->dwFlags & GMVF_DISABLE_OVERLAY)
#endif
{
// Overlays not supported in hw
pHALInfo->ddCaps.dwMaxVisibleOverlays = 0;
pHALInfo->ddCaps.dwCurrVisibleOverlays = 0;
}
else
{
// Overlay is free to use.
pHALInfo->ddCaps.dwMaxVisibleOverlays = 1;
pHALInfo->ddCaps.dwCurrVisibleOverlays = 0;
pHALInfo->ddCaps.dwCaps |= DDCAPS_OVERLAY |
DDCAPS_OVERLAYFOURCC |
DDCAPS_OVERLAYSTRETCH |
DDCAPS_COLORKEYHWASSIST |
DDCAPS_OVERLAYCANTCLIP;
pHALInfo->ddCaps.dwCKeyCaps |= DDCKEYCAPS_SRCOVERLAY |
DDCKEYCAPS_SRCOVERLAYONEACTIVE |
DDCKEYCAPS_SRCOVERLAYYUV |
DDCKEYCAPS_DESTOVERLAY |
DDCKEYCAPS_DESTOVERLAYONEACTIVE |
DDCKEYCAPS_DESTOVERLAYYUV;
pHALInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_OVERLAY;
pHALInfo->ddCaps.dwFXCaps |= DDFXCAPS_OVERLAYSHRINKX |
DDFXCAPS_OVERLAYSHRINKXN |
DDFXCAPS_OVERLAYSHRINKY |
DDFXCAPS_OVERLAYSHRINKYN |
DDFXCAPS_OVERLAYSTRETCHX |
DDFXCAPS_OVERLAYSTRETCHXN |
DDFXCAPS_OVERLAYSTRETCHY |
DDFXCAPS_OVERLAYSTRETCHYN;
// Indicates that Perm3 has no stretch ratio limitation
pHALInfo->ddCaps.dwMinOverlayStretch = 1;
pHALInfo->ddCaps.dwMaxOverlayStretch = 32000;
}
}
#ifdef W95_DDRAW
// Enable colour control asc brightness, contrast, gamma.
pHALInfo->ddCaps.dwCaps2 |= DDCAPS2_COLORCONTROLPRIMARY;
#endif
// Also permit surfaces wider than the display buffer.
pHALInfo->ddCaps.dwCaps2 |= DDCAPS2_WIDESURFACES;
// Enable copy blts betweemn Four CC formats for DShow acceleration
pHALInfo->ddCaps.dwCaps2 |= DDCAPS2_COPYFOURCC;
// 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;
// No alpha blending for overlays, so I'm not sure what these should be.
// Because we support 32bpp overlays, it's just that you can't use the
// alpha bits for blending. Pass.
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;
//
// ROPS supported
//
for( i=0;i<DD_ROP_SPACE;i++ )
{
pHALInfo->ddCaps.dwRops[i] = rops[i];
}
#if W95_DDRAW
// Reset to NULL for debugging
pThisDisplay->lpD3DGlobalDriverData = 0;
ZeroMemory(&pThisDisplay->DDExeBufCallbacks,
sizeof(DDHAL_DDEXEBUFCALLBACKS));
// Note that the NT code does this elsewhere
_D3DHALCreateDriver(
pThisDisplay);
// (LPD3DHAL_GLOBALDRIVERDATA*)&pThisDisplay->lpD3DGlobalDriverData,
// (LPD3DHAL_CALLBACKS*) &pThisDisplay->lpD3DHALCallbacks,
// &pThisDisplay->DDExeBufCallbacks);
// If we filled in the execute buffer callbacks, set the cap bit
if (pThisDisplay->DDExeBufCallbacks.dwSize != 0)
{
pHALInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_EXECUTEBUFFER;
}
#endif
// For DX5 and beyond we support this new informational callback.
pHALInfo->GetDriverInfo = DdGetDriverInfo;
pHALInfo->dwFlags |= DDHALINFO_GETDRIVERINFOSET;
#if DX8_DDI
// Flag our support for a new class of GUIDs that may come through
// GetDriverInfo for DX8 drivers. (This support will be compulsory)
pHALInfo->dwFlags |= DDHALINFO_GETDRIVERINFO2;
#endif DX8_DDI
} // __GetDDHALInfo
static HashTable* g_pDirectDrawLocalsHashTable = NULL; // azn
//-----------------------------------------------------------------------------
//
// _DD_InitDDHAL32Bit
//
// CALLED ONCE AT START OF DAY
// No Chip register setup is done here - it is all handled in the mode
// change code. DO NOT DO IT HERE - THERE IS NO WIN16LOCK AT THIS TIME!!!
//
//-----------------------------------------------------------------------------
BOOL
_DD_InitDDHAL32Bit(
P3_THUNKEDDATA* pThisDisplay)
{
BOOL bRet;
DWORD Result;
LPGLINTINFO pGLInfo = pThisDisplay->pGLInfo;
ASSERTDD(pGLInfo != NULL, "ERROR: pGLInfo not valid!");
// Note: Can't use P3_DMA_DEFS macro here, as pGlint isn't initialised yet.
DISPDBG((DBGLVL, "** In _DD_InitDDHAL32Bit, pGlint 0x%x",
pThisDisplay->control));
DISPDBG((DBGLVL, "Sizeof DDHALINFO: %d", (int) sizeof(DDHALINFO)));
// Force D3D to setup surface offsets as if a flip had happened
pThisDisplay->bFlippedSurface = TRUE;
// A flag to say that the driver is essentially at the start of day. This
// is set to let later calls in the driver know that they have work to do.
pThisDisplay->bStartOfDay = TRUE;
#if W95_DDRAW
// At start of day the videoport is dead to the world
pThisDisplay->VidPort.bActive = FALSE;
#endif // W95_DDRAW
// Reset the GART copies.
pThisDisplay->dwGARTLin = 0;
pThisDisplay->dwGARTDev = 0;
pThisDisplay->dwGARTLinBase = 0;
pThisDisplay->dwGARTDevBase = 0;
pThisDisplay->pGlint = (FPGLREG)pThisDisplay->control;
// Set up the global overlay data
pThisDisplay->bOverlayVisible = (DWORD)FALSE;
pThisDisplay->OverlayDstRectL = 0;
pThisDisplay->OverlayDstRectR = 0;
pThisDisplay->OverlayDstRectT = 0;
pThisDisplay->OverlayDstRectB = 0;
pThisDisplay->OverlaySrcRectL = 0;
pThisDisplay->OverlaySrcRectR = 0;
pThisDisplay->OverlaySrcRectT = 0;
pThisDisplay->OverlaySrcRectB = 0;
pThisDisplay->OverlayDstSurfLcl = (ULONG_PTR)NULL;
pThisDisplay->OverlaySrcSurfLcl = (ULONG_PTR)NULL;
pThisDisplay->OverlayDstColourKey = CLR_INVALID;
pThisDisplay->OverlaySrcColourKey = CLR_INVALID;
pThisDisplay->OverlayClipRgnMem = (ULONG_PTR)NULL;
pThisDisplay->OverlayClipRgnMemSize = 0;
pThisDisplay->OverlayUpdateCountdown = 0;
pThisDisplay->bOverlayFlippedThisVbl = (DWORD)FALSE;
pThisDisplay->bOverlayUpdatedThisVbl = (DWORD)FALSE;
pThisDisplay->OverlayTempSurf.VidMem = (ULONG_PTR)NULL;
pThisDisplay->OverlayTempSurf.Pitch = (DWORD)0;
#if W95_DDRAW
// Set up colour control data.
pThisDisplay->ColConBrightness = 0;
pThisDisplay->ColConContrast = 10000;
pThisDisplay->ColConGamma = 100;
#endif // W95_DDRAW
#if DX7_VIDMEM_VB
// Set up DrawPrim temporary index buffer.
pThisDisplay->DrawPrimIndexBufferMem = (ULONG_PTR)NULL;
pThisDisplay->DrawPrimIndexBufferMemSize = 0;
pThisDisplay->DrawPrimVertexBufferMem = (ULONG_PTR)NULL;
pThisDisplay->DrawPrimVertexBufferMemSize = 0;
#endif // DX7_VIDMEM_VB
// Set up current RenderID to be as far away from a "sensible"
// value as possible. Hopefully, if the context switch fails and
// someone starts using it for something else, these values and
// the ones they use will be very different, and various asserts
// will scream immediately.
// Also, say that the RenderID is invalid, because we have not actually
// set up the chip. The context switch should set up & flush the
// chip, and then it will set bRenderIDValid to TRUE.
// Loads of asserts throughout the code will scream if something
// doesn't do the setup & flush for some reason.
pThisDisplay->dwRenderID = 0x8eaddead | RENDER_ID_KNACKERED_BITS;
pThisDisplay->dwLastFlipRenderID = 0x8eaddead | RENDER_ID_KNACKERED_BITS;
pThisDisplay->bRenderIDValid = (DWORD)FALSE;
#if W95_DDRAW
// Create a shared heap
if (g_DXGlobals.hHeap32 == 0)
g_DXGlobals.hHeap32 = (DWORD)HeapCreate( HEAP_SHARED, 2500, 0);
#endif // W95_DDRAW
// Make sure we're running the right chip. If not, STOP.
ASSERTDD((RENDERCHIP_P3RXFAMILY),"ERROR: Invalid RENDERFAMILY!!");
// Dump some debugging information
DISPDBG((DBGLVL, "************* _DD_InitDDHAL32Bit *************************************" ));
DISPDBG((DBGLVL, " dwScreenFlatAddr=%08lx", pThisDisplay->dwScreenFlatAddr ));
DISPDBG((DBGLVL, " dwScreenStart =%08lx", pThisDisplay->dwScreenStart));
DISPDBG((DBGLVL, " dwLocalBuffer=%08lx", pThisDisplay->dwLocalBuffer ));
DISPDBG((DBGLVL, " dwScreenWidth=%08lx", pThisDisplay->dwScreenWidth ));
DISPDBG((DBGLVL, " dwScreenHeight=%08lx", pThisDisplay->dwScreenHeight ));
DISPDBG((DBGLVL, " bReset=%08lx", pThisDisplay->bResetMode ));
DISPDBG((DBGLVL, " dwRGBBitCount=%ld", pThisDisplay->ddpfDisplay.dwRGBBitCount ));
DISPDBG((DBGLVL, " pGLInfo=%08lp", pGLInfo ));
DISPDBG((DBGLVL, " Render: 0x%x, Rev:0x%x", pGLInfo->dwRenderChipID, pGLInfo->dwRenderChipRev));
#if W95_DDRAW
DISPDBG((DBGLVL, " Support: 0x%x, Rev:0x%x", pGLInfo->dwSupportChipID, pGLInfo->dwSupportChipRev));
DISPDBG((DBGLVL, " Board: 0x%x, Rev:0x%x", pGLInfo->dwBoardID, pGLInfo->dwBoardRev));
// DISPDBG((DBGLVL, " BF Size: 0x%x, LB Depth:0x%x", pGLInfo->cBlockFillSize, pGLInfo->cLBDepth));
#endif // W95_DDRAW
DISPDBG((DBGLVL, " FB Size: 0x%x", pGLInfo->ddFBSize));
DISPDBG((DBGLVL, " RMask: 0x%x", pThisDisplay->ddpfDisplay.dwRBitMask ));
DISPDBG((DBGLVL, " GMask: 0x%x", pThisDisplay->ddpfDisplay.dwGBitMask ));
DISPDBG((DBGLVL, " BMask: 0x%x", pThisDisplay->ddpfDisplay.dwBBitMask ));
DISPDBG((DBGLVL, "******************************************************************" ));
// Allocate a DMA buffer for the DX driver
HWC_AllocDMABuffer(pThisDisplay);
#define SURFCB pThisDisplay->DDSurfCallbacks
#define HALCB pThisDisplay->DDHALCallbacks
// Fill in the HAL Callback pointers
memset(&HALCB, 0, sizeof(DDHAL_DDCALLBACKS));
HALCB.dwSize = sizeof(DDHAL_DDCALLBACKS);
// Field the HAL DDraw callbacks we support
HALCB.CanCreateSurface = DdCanCreateSurface;
HALCB.CreateSurface = DdCreateSurface;
HALCB.WaitForVerticalBlank = DdWaitForVerticalBlank;
HALCB.GetScanLine = DdGetScanLine;
#if WNT_DDRAW
HALCB.MapMemory = DdMapMemory;
#else
HALCB.DestroyDriver = DdDestroyDriver; // Only on Win95.
#endif // WNT_DDRAW
HALCB.dwFlags = DDHAL_CB32_WAITFORVERTICALBLANK |
#if WNT_DDRAW
DDHAL_CB32_MAPMEMORY |
#else // WNT_DDRAW
DDHAL_CB32_DESTROYDRIVER |
#endif
DDHAL_CB32_GETSCANLINE |
DDHAL_CB32_CANCREATESURFACE |
DDHAL_CB32_CREATESURFACE;
// Fill in the Surface Callback pointers
memset(&SURFCB, 0, sizeof(DDHAL_DDSURFACECALLBACKS));
SURFCB.dwSize = sizeof(DDHAL_DDSURFACECALLBACKS);
// Field the Ddraw Surface callbacks we support
SURFCB.DestroySurface = DdDestroySurface;
SURFCB.Lock = DdLock;
SURFCB.Unlock = DdUnlock;
SURFCB.GetBltStatus = DdGetBltStatus;
SURFCB.GetFlipStatus = DdGetFlipStatus;
SURFCB.SetColorKey = DdSetColorKey;
SURFCB.Flip = DdFlip;
SURFCB.Blt = DdBlt;
SURFCB.dwFlags = DDHAL_SURFCB32_DESTROYSURFACE |
DDHAL_SURFCB32_FLIP |
DDHAL_SURFCB32_LOCK |
DDHAL_SURFCB32_BLT |
DDHAL_SURFCB32_GETBLTSTATUS |
DDHAL_SURFCB32_GETFLIPSTATUS |
DDHAL_SURFCB32_SETCOLORKEY |
DDHAL_SURFCB32_UNLOCK;
pThisDisplay->hInstance = g_DXGlobals.hInstance;
#if WNT_DDRAW
if (0 == (pThisDisplay->ppdev->flCaps & CAPS_DISABLE_OVERLAY))
#else
if (0 == (pThisDisplay->pGLInfo->dwFlags & GMVF_DISABLE_OVERLAY))
#endif
{
SURFCB.UpdateOverlay = DdUpdateOverlay; // Now supporting overlays.
SURFCB.SetOverlayPosition = DdSetOverlayPosition;
SURFCB.dwFlags |=
DDHAL_SURFCB32_UPDATEOVERLAY | // Now supporting
DDHAL_SURFCB32_SETOVERLAYPOSITION ; // overlays.
}
// Fill in the DDHAL Informational caps
__GetDDHALInfo(pThisDisplay, &pThisDisplay->ddhi32);
// Create/get DD locals hash table to store our DX surface handles
//@@BEGIN_DDKSPLIT
// azn
// We need to move this creation/destruction of g_pDirectDrawLocalsHashTable
// into DrvEnableDriver and DrvDisableDriver and maybe maintain a Ref count
// as we might be running on a multi-Perm3 machine.
//@@END_DDKSPLIT
if (g_pDirectDrawLocalsHashTable == NULL)
{
DISPDBG((DBGLVL,"pDirectDrawLocalsHashTable CREATED"));
g_pDirectDrawLocalsHashTable =
pThisDisplay->pDirectDrawLocalsHashTable = HT_CreateHashTable();
}
else
{
DISPDBG((DBGLVL,"Hash table for DirectDraw locals already exists"));
pThisDisplay->pDirectDrawLocalsHashTable =
g_pDirectDrawLocalsHashTable;
}
if (pThisDisplay->pDirectDrawLocalsHashTable == NULL)
{
return (FALSE);
}
HT_SetDataDestroyCallback(pThisDisplay->pDirectDrawLocalsHashTable,
_D3D_SU_DirectDrawLocalDestroyCallback);
#if W95_DDRAW
if ( g_DXGlobals.hHeap32 == 0 )
{
return ( FALSE );
}
else
{
return ( TRUE );
}
#endif
return (TRUE);
} // _DD_InitDDHAL32Bit
#if DX7_STEREO
//-----------------------------------------------------------------------------
//
// _DD_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
_DD_bIsStereoMode(
P3_THUNKEDDATA* pThisDisplay,
DWORD dwWidth,
DWORD dwHeight,
DWORD dwBpp)
{
DWORD dwLines;
// we need to check dwBpp for a valid value as PDD_STEREOMODE.dwBpp is a
// parameter passed on from the user mode API call and which is expected
// to have the values 8,16,24,32 (though we don't really support 24bpp)
if ((dwWidth >= 320) && (dwHeight >= 240) &&
((dwBpp == 8) || (dwBpp == 16) || (dwBpp == 24) || (dwBpp ==32) ) )
{
// This the total number of "lines" that fit in our available vidmem
// at the given width and pixel format
dwLines = pThisDisplay->pGLInfo->ddFBSize / (dwWidth*dwBpp/8);
// Here we limit stereo modes so that two front and two backbuffers
// can be created for rendering.
if (dwLines > (dwHeight*4))
{
return TRUE;
}
}
return FALSE;
}
#endif // DX7_STEREO
#ifdef WNT_DDRAW
typedef DD_NONLOCALVIDMEMCAPS DDNONLOCALVIDMEMCAPS;
#else
#define DD_MISCELLANEOUSCALLBACKS DDHAL_DDMISCELLANEOUSCALLBACKS
#endif
//-----------------------------Public Routine----------------------------------
//
// DdGetDriverInfo
//
// Queries the driver for additional information about itself.
//
// Parameters
// lpGetDriverInfo
// Points to a DD_GETDRIVERINFODATA structure that contains the
// information required to perform the query.
//
// Members
//
// VOID *
// dphdev
// Is a handle to the driver's PDEV.
// DWORD
// dwSize
// Specifies the size in bytes of this
// DD_GETDRIVERINFODATA structure.
// DWORD
// dwFlags
// Is currently unused and is set to zero.
// GUID
// guidInfo
// Specifies the GUID of the DirectX support for which the
// driver is being queried. In a Windows 2000 DirectDraw
// driver, this member can be one of the following values
// (in alphabetic order):
//
// GUID_ColorControlCallbacks Queries whether the driver supports
// DdControlColor. If the driver does
// support it, the driver should
// initialize and return a
// DD_COLORCONTROLCALLBACKS structure
// in the buffer to which lpvData
// points.
// GUID_D3DCallbacks Queries whether the driver supports
// any of the functionality specified
// through the D3DNTHAL_CALLBACKS
// structure. If the driver does not
// provide any of this support, it
// should initialize and return a
// D3DNTHAL_CALLBACKS structure in
// the buffer to which lpvData points
// GUID_D3DCallbacks2 Obsolete.
// GUID_D3DCallbacks3 Queries whether the driver supports
// any of the functionality specified
// through the D3DNTHAL_CALLBACKS3
// structure. If the driver does provide
// any of this support, it should
// initialize and return a
// D3DNTHAL_CALLBACKS3 structure in
// the buffer to which lpvData points.
// GUID_D3DCaps Obsolete.
// GUID_D3DExtendedCaps Queries whether the driver supports
// any of the Direct3D functionality
// specified through the
// D3DNTHAL_D3DEXTENDEDCAPS structure.
// If the driver does provide any of
// this support, it should initialize
// and return a
// D3DNTHAL_D3DEXTENDEDCAPS structure
// in the buffer to which lpvData
// points.
// GUID_D3DParseUnknownCommandCallback Provides the Direct3D
// portion of the driver with the
// Direct3D runtime's
// D3dParseUnknownCommandCallback.
// The driver's D3dDrawPrimitives2
// callback calls
// D3dParseUnknownCommandCallback
// to parse commands from the
// command buffer that the driver
// doesn't understand.
// DirectDraw passes a pointer to this
// function in the buffer to which
// lpvData points. If the driver
// supports this aspect of Direct3D,
// it should store the pointer.
// GUID_GetHeapAlignment Queries whether the driver supports
// surface alignment requirements on a
// per-heap basis. If the driver does
// provide this support, it should
// initialize and return a
// DD_GETHEAPALIGNMENTDATA structure
// in the buffer to which lpvData
// points.
// GUID_KernelCallbacks Queries whether the driver supports
// any of the functionality specified
// through the DD_KERNELCALLBACKS
// structure. If the driver does
// provide any of this support, it
// should initialize and return a
// DD_KERNELCALLBACKS structure in the
// buffer to which lpvData points.
// GUID_KernelCaps Queries whether the driver supports
// any of the kernel-mode capabilities
// specified through the DDKERNELCAPS
// structure. If the driver does
// provide any of this support, it
// should initialize and return a
// DDKERNELCAPS structure in the buffer
// to which lpvData points.
// GUID_MiscellaneousCallbacks Queries whether the driver supports
// DdGetAvailDriverMemory. If the
// driver does support it, the driver
// should initialize and return a
// DD_MISCELLANEOUSCALLBACKS structure
// in the buffer to which lpvData
// points.
// GUID_Miscellaneous2Callbacks Queries whether the driver
// supports the additional miscellaneous
// functionality specified in the
// DD_MISCELLANEOUS2CALLBACKS structure.
// If the driver does support any of
// this support, the driver should
// initialize and return a
// DD_MISCELLANEOUS2CALLBACKS structure
// in the buffer to which lpvData
// points.
// GUID_MotionCompCallbacks Queries whether the driver supports
// the motion compensation
// functionality specified through the
// DD_MOTIONCOMPCALLBACKS structure.
// If the driver does provide any of
// this support, is should initialize
// and return a DD_MOTIONCOMPCALLBACKS
// structure in the buffer to which
// lpvData points.
// GUID_NonLocalVidMemCaps Queries whether the driver supports
// any of the nonlocal display memory
// capabilities specified through the
// DD_NONLOCALVIDMEMCAPS structure.
// If the driver does provide any of
// this support, it should initialize
// and return a DD_NONLOCALVIDMEMCAPS
// structure in the buffer to which
// lpvData points.
// GUID_NTCallbacks Queries whether the driver supports
// any of the functionality specified
// through the DD_NTCALLBACKS structure.
// If the driver does provide any of
// this support, it should initialize
// and return a DD_NTCALLBACKS
// structure in the buffer to which
// lpvData points.
// GUID_NTPrivateDriverCaps Queries whether the driver supports
// the Windows 95/ Windows 98-style
// surface creation techniques
// specified through the
// DD_NTPRIVATEDRIVERCAPS structure.
// If the driver does provide any of
// this support, it should initialize
// and return a DD_NTPRIVATEDRIVERCAPS
// structure in the buffer to which
// lpvData points.
// GUID_UpdateNonLocalHeap Queries whether the driver supports
// retrieval of the base addresses of
// each nonlocal heap in turn. If the
// driver does provide this support,
// it should initialize and return a
// DD_UPDATENONLOCALHEAPDATA structure
// in the buffer to which lpvData
// points.
// GUID_VideoPortCallbacks Queries whether the driver supports
// the video port extensions (VPE). If
// the driver does support VPE, it
// should initialize and return a
// DD_VIDEOPORTCALLBACKS structure in
// the buffer to which lpvData points.
// GUID_VideoPortCaps Queries whether the driver supports
// any of the VPE object capabilities
// specified through the DDVIDEOPORTCAPS
// structure. If the driver does provide
// any of this support, it should
// initialize and return a
// DDVIDEOPORTCAPS structure in the
// buffer to which lpvData points.
// GUID_ZPixelFormats Queries the pixel formats supported
// by the depth buffer. If the driver
// supports Direct3D, it should allocate
// and initialize the appropriate
// members of a DDPIXELFORMAT structure
// for every z-buffer format that it
// supports and return these in the
// buffer to which lpvData points.
//
// DWORD
// dwExpectedSize
// Specifies the number of bytes of data that DirectDraw
// expects the driver to pass back in the buffer to which
// lpvData points.
// PVOID
// lpvData
// Points to a DirectDraw-allocated buffer into which the
// driver copies the requested data. This buffer is
// typically dwExpectedSize bytes in size. The driver must
// not write more than dwExpectedSize bytes of data in it.
// DWORD
// dwActualSize
// Is the location in which the driver returns the number
// of bytes of data it writes in lpvData.
// HRESULT
// ddRVal
// Specifies the driver's return value.
//
// Return Value
// DdGetDriverInfo must return DDHAL_DRIVER_HANDLED.
//
// Comments
//
// Drivers must implement DdGetDriverInfo to expose driver-supported
// DirectDraw functionality that is not returnable through
// DrvEnableDirectDraw.
//
// The driver's DrvGetDirectDrawInfo function returns a pointer to
// DdGetDriverInfo in the GetDriverInfo member of the DD_HALINFO structure.
//
// To inform DirectDraw that the DdGetDriverInfo member has been set
// correctly, the driver must also set the DDHALINFO_GETDRIVERINFOSET bit
// of dwFlags in the DD_HALINFO structure.
//
// DdGetDriverInfo should determine whether the driver and its hardware
// support the callbacks or capabilities requested by the specified GUID.
// For all GUIDs except GUID_D3DParseUnknownCommandCallback, if the driver
// does provide the requested support, it should set the following members
// of the DD_GETDRIVERINFODATA structure:
//
// Set dwActualSize to be the size in bytes of the callback or capability
// structure being returned by the driver.
//
// In the memory that lpvData points to, initialize the members of the
// callback or capability structure that corresponds with the requested
// feature as follows:
//
// Set the dwSize member to be the size in bytes of the structure.
//
// For callbacks, set the function pointers to point to those callbacks
// implemented by the driver, and set the bits in the dwFlags member to
// indicate which functions the driver supports.
//
// For capabilities, set the appropriate members of the capability
// structure with values supported by the driver/device.
//
// Return DD_OK in ddRVal.
// If the driver does not support the feature, it should set ddRVal
// to DDERR_CURRENTLYNOTAVAIL and return.
//
// DirectDraw informs the driver of the expected amount of data in the
// dwExpectedSize member of the DD_GETDRIVERINFODATA structure. The
// driver must not fill in more data than dwExpectedSize bytes.
//
// To avoid problems using DdGetDriverInfo:
//
// Do not implement dependencies based on the order in which DdGetDriverInfo
// is called. For example, avoid hooking driver initialization steps into
// DdGetDriverInfo.
//
// Do not try to ascertain the DirectDraw version based on the calls to
// DdGetDriverInfo.
//
// Do not assume anything about the number of times DirectDraw will call the
// driver, or the number of times DirectDraw will query a given GUID. It is
// possible that DirectDraw will probe the driver repeatedly with the same
// GUID. Implementing assumptions about this in the driver hampers its
// compatibility with future runtimes.
//
//-----------------------------------------------------------------------------
DWORD CALLBACK
DdGetDriverInfo(
LPDDHAL_GETDRIVERINFODATA lpData)
{
DWORD dwSize;
P3_THUNKEDDATA* pThisDisplay;
#if WNT_DDRAW
pThisDisplay = (P3_THUNKEDDATA*)(((PPDEV)(lpData->dhpdev))->thunkData);
#else
pThisDisplay = (P3_THUNKEDDATA*)lpData->dwContext;
if (! pThisDisplay)
{
pThisDisplay = g_pDriverData;
}
#endif
DBG_CB_ENTRY(DdGetDriverInfo);
// Default to 'not supported'
lpData->ddRVal = DDERR_CURRENTLYNOTAVAIL;
//------------------------------------
// Process any D3D related GUIDs here
//------------------------------------
_D3DGetDriverInfo(lpData);
//------------------------------------
// any other GUIDS are handled here
//------------------------------------
if (MATCH_GUID((lpData->guidInfo), GUID_MiscellaneousCallbacks) )
{
DD_MISCELLANEOUSCALLBACKS MISC_CB;
DISPDBG((DBGLVL," GUID_MiscellaneousCallbacks"));
memset(&MISC_CB, 0, sizeof(DD_MISCELLANEOUSCALLBACKS));
MISC_CB.dwSize = sizeof(DD_MISCELLANEOUSCALLBACKS);
#if W95_DDRAW
MISC_CB.GetHeapAlignment = DdGetHeapAlignment;
MISC_CB.dwFlags = DDHAL_MISCCB32_GETHEAPALIGNMENT;
// Setup the AGP callback if running on an AGP board.
if ((pThisDisplay->dwDXVersion > DX5_RUNTIME) &&
pThisDisplay->bCanAGP)
{
MISC_CB.dwFlags |= DDHAL_MISCCB32_UPDATENONLOCALHEAP;
MISC_CB.UpdateNonLocalHeap = DdUpdateNonLocalHeap;
}
#endif // W95_DDRAW
MISC_CB.dwFlags |= DDHAL_MISCCB32_GETAVAILDRIVERMEMORY;
MISC_CB.GetAvailDriverMemory = DdGetAvailDriverMemory;
// Copy the filled in structure into the passed data area
dwSize = min(lpData->dwExpectedSize , sizeof(MISC_CB));
lpData->dwActualSize = sizeof(MISC_CB);
memcpy(lpData->lpvData, &MISC_CB, dwSize );
lpData->ddRVal = DD_OK;
}
#if WNT_DDRAW
if (MATCH_GUID((lpData->guidInfo), GUID_UpdateNonLocalHeap))
{
// On NT kernels the AGP heap details are passed into the driver
// here, rather than through a seperate callback.
if (pThisDisplay->bCanAGP)
{
DDHAL_UPDATENONLOCALHEAPDATA* plhd;
DISPDBG((DBGLVL, " GUID_UpdateNonLocalHeap"));
plhd = (DDHAL_UPDATENONLOCALHEAPDATA*)lpData->lpvData;
// Fill in the base pointers
pThisDisplay->dwGARTDevBase = (DWORD)plhd->fpGARTDev;
pThisDisplay->dwGARTLinBase = (DWORD)plhd->fpGARTLin;
// Fill in the changeable base pointers.
pThisDisplay->dwGARTDev = pThisDisplay->dwGARTDevBase;
pThisDisplay->dwGARTLin = pThisDisplay->dwGARTLinBase;
lpData->ddRVal = DD_OK;
}
}
#endif // WNT_DDRAW
if (MATCH_GUID((lpData->guidInfo), GUID_NonLocalVidMemCaps) &&
(pThisDisplay->bCanAGP))
{
int i;
DDNONLOCALVIDMEMCAPS NLVCAPS;
DISPDBG((DBGLVL," GUID_NonLocalVidMemCaps"));
if (lpData->dwExpectedSize != sizeof(DDNONLOCALVIDMEMCAPS) )
{
DISPDBG((ERRLVL,"ERROR: NON-Local vidmem caps size incorrect!"));
DBG_CB_EXIT(DdGetDriverInfo, lpData->ddRVal );
return DDHAL_DRIVER_HANDLED;
}
// The flag D3DDEVCAPS_TEXTURENONLOCALVIDMEM in the D3D caps
// indicates that although we are exposing DMA-Model AGP, we
// can still texture directly from AGP memory.
memset(&NLVCAPS, 0, sizeof(DDNONLOCALVIDMEMCAPS));
NLVCAPS.dwSize = sizeof(DDNONLOCALVIDMEMCAPS);
NLVCAPS.dwNLVBCaps = DDCAPS_BLT |
DDCAPS_ALPHA |
DDCAPS_BLTSTRETCH |
DDCAPS_BLTQUEUE |
DDCAPS_BLTFOURCC |
DDCAPS_COLORKEY |
DDCAPS_CANBLTSYSMEM;
NLVCAPS.dwNLVBCaps2 = DDCAPS2_WIDESURFACES;
NLVCAPS.dwNLVBCKeyCaps = DDCKEYCAPS_SRCBLT |
DDCKEYCAPS_SRCBLTCLRSPACE |
DDCKEYCAPS_DESTBLT |
DDCKEYCAPS_DESTBLTCLRSPACE;
NLVCAPS.dwNLVBFXCaps = DDFXCAPS_BLTSTRETCHY |
DDFXCAPS_BLTSTRETCHX |
DDFXCAPS_BLTSTRETCHYN |
DDFXCAPS_BLTSTRETCHXN |
DDFXCAPS_BLTSHRINKY |
DDFXCAPS_BLTSHRINKX |
DDFXCAPS_BLTSHRINKYN |
DDFXCAPS_BLTSHRINKXN;
for( i=0;i<DD_ROP_SPACE;i++ )
{
NLVCAPS.dwNLVBRops[i] = ropsAGP[i];
}
// Copy the filled in structure into the passed data area
dwSize = min( lpData->dwExpectedSize, sizeof(DDNONLOCALVIDMEMCAPS));
lpData->dwActualSize = sizeof(DDNONLOCALVIDMEMCAPS);
memcpy(lpData->lpvData, &NLVCAPS, dwSize );
lpData->ddRVal = DD_OK;
}
//@@BEGIN_DDKSPLIT
#ifdef SUPPORT_VIDEOPORT
#if W95_DDRAW
// Fill in the VideoPort callbacks
if (MATCH_GUID((lpData->guidInfo), GUID_VideoPortCallbacks) )
{
DDHAL_DDVIDEOPORTCALLBACKS VIDCB;
DISPDBG((DBGLVL," GUID_VideoPortCallbacks"));
memset(&VIDCB, 0, sizeof(DDHAL_DDVIDEOPORTCALLBACKS));
VIDCB.dwSize = sizeof(DDHAL_DDVIDEOPORTCALLBACKS);
VIDCB.CanCreateVideoPort = DdCanCreateVideoPort;
VIDCB.CreateVideoPort = DdCreateVideoPort;
VIDCB.FlipVideoPort = DdFlipVideoPort;
VIDCB.GetVideoPortBandwidth = DdGetVideoPortBandwidth;
VIDCB.GetVideoPortInputFormats = DdGetVideoPortInputFormats;
VIDCB.GetVideoPortOutputFormats = DdGetVideoPortOutputFormats;
VIDCB.GetVideoPortField = DdGetVideoPortField;
VIDCB.GetVideoPortLine = DdGetVideoPortLine;
VIDCB.GetVideoPortConnectInfo = DDGetVideoPortConnectInfo;
VIDCB.DestroyVideoPort = DdDestroyVideoPort;
VIDCB.GetVideoPortFlipStatus = DdGetVideoPortFlipStatus;
VIDCB.UpdateVideoPort = DdUpdateVideoPort;
VIDCB.WaitForVideoPortSync = DdWaitForVideoPortSync;
VIDCB.GetVideoSignalStatus = DdGetVideoSignalStatus;
VIDCB.dwFlags = DDHAL_VPORT32_CANCREATEVIDEOPORT |
DDHAL_VPORT32_CREATEVIDEOPORT |
DDHAL_VPORT32_DESTROY |
DDHAL_VPORT32_FLIP |
DDHAL_VPORT32_GETBANDWIDTH |
DDHAL_VPORT32_GETINPUTFORMATS |
DDHAL_VPORT32_GETOUTPUTFORMATS |
DDHAL_VPORT32_GETFIELD |
DDHAL_VPORT32_GETLINE |
DDHAL_VPORT32_GETFLIPSTATUS |
DDHAL_VPORT32_UPDATE |
DDHAL_VPORT32_WAITFORSYNC |
DDHAL_VPORT32_GETCONNECT |
DDHAL_VPORT32_GETSIGNALSTATUS;
// Copy the filled in structure into the
// passed data area
dwSize = lpData->dwExpectedSize;
if ( sizeof(VIDCB) < dwSize )
{
dwSize = sizeof(VIDCB);
}
lpData->dwActualSize = sizeof(VIDCB);
memcpy(lpData->lpvData, &VIDCB, dwSize );
lpData->ddRVal = DD_OK;
}
// Fill in the VideoPortCaps
if (MATCH_GUID((lpData->guidInfo), GUID_VideoPortCaps) )
{
DDVIDEOPORTCAPS VIDCAPS;
DISPDBG((DBGLVL," GUID_VideoPortCaps"));
if (lpData->dwExpectedSize != sizeof(VIDCAPS) )
{
DISPDBG((ERRLVL,"ERROR: VIDCAPS size incorrect"));
DBG_CB_EXIT(DdGetDriverInfo, lpData->ddRVal );
return DDHAL_DRIVER_HANDLED;
}
// Now fill in the videoport description (it's easier if it's on
// the 32 bit side..)
VIDCAPS.dwSize = sizeof(DDVIDEOPORTCAPS);
VIDCAPS.dwFlags = DDVPD_ALIGN |
DDVPD_AUTOFLIP |
DDVPD_WIDTH |
DDVPD_HEIGHT |
DDVPD_FX |
DDVPD_CAPS;
VIDCAPS.dwMaxWidth = 2048;
VIDCAPS.dwMaxVBIWidth = 2048;
VIDCAPS.dwMaxHeight = 2048;
VIDCAPS.dwVideoPortID = 0;
VIDCAPS.dwCaps = DDVPCAPS_AUTOFLIP |
DDVPCAPS_NONINTERLACED |
DDVPCAPS_INTERLACED |
DDVPCAPS_READBACKFIELD |
DDVPCAPS_READBACKLINE |
DDVPCAPS_SKIPEVENFIELDS |
DDVPCAPS_SKIPODDFIELDS |
DDVPCAPS_VBISURFACE |
DDVPCAPS_OVERSAMPLEDVBI;
VIDCAPS.dwFX = DDVPFX_CROPX |
DDVPFX_CROPY |
DDVPFX_INTERLEAVE |
DDVPFX_MIRRORLEFTRIGHT |
DDVPFX_MIRRORUPDOWN |
DDVPFX_PRESHRINKXB |
DDVPFX_VBICONVERT |
DDVPFX_VBINOSCALE |
DDVPFX_PRESHRINKYB |
DDVPFX_IGNOREVBIXCROP;
VIDCAPS.dwNumAutoFlipSurfaces = 2;
VIDCAPS.dwAlignVideoPortBoundary = 4;
VIDCAPS.dwAlignVideoPortPrescaleWidth = 4;
VIDCAPS.dwAlignVideoPortCropBoundary = 4;
VIDCAPS.dwAlignVideoPortCropWidth = 4;
VIDCAPS.dwPreshrinkXStep = 1;
VIDCAPS.dwPreshrinkYStep = 1;
lpData->dwActualSize = sizeof(VIDCAPS);
memcpy(lpData->lpvData, &VIDCAPS, sizeof(VIDCAPS) );
lpData->ddRVal = DD_OK;
}
// Fill in the kernel Callbacks
if (MATCH_GUID((lpData->guidInfo), GUID_KernelCallbacks) )
{
DDHAL_DDKERNELCALLBACKS KERNCB;
DISPDBG((DBGLVL," GUID_KernelCallbacks"));
memset(&KERNCB, 0, sizeof(DDHAL_DDKERNELCALLBACKS));
KERNCB.dwSize = sizeof(KERNCB);
KERNCB.SyncSurfaceData = DdSyncSurfaceData;
KERNCB.SyncVideoPortData = DdSyncVideoPortData;
KERNCB.dwFlags = DDHAL_KERNEL_SYNCSURFACEDATA |
DDHAL_KERNEL_SYNCVIDEOPORTDATA;
dwSize = lpData->dwExpectedSize;
if ( sizeof(KERNCB) < dwSize )
{
dwSize = sizeof(KERNCB);
}
lpData->dwActualSize = sizeof(KERNCB);
memcpy(lpData->lpvData, &KERNCB, dwSize );
lpData->ddRVal = DD_OK;
}
// Fill in the kernel caps
if (MATCH_GUID((lpData->guidInfo), GUID_KernelCaps) )
{
DDKERNELCAPS KERNCAPS;
DISPDBG((DBGLVL," GUID_KernelCaps"));
if (lpData->dwExpectedSize != sizeof(DDKERNELCAPS) )
{
DISPDBG((ERRLVL,"ERROR: Kernel caps structure invalid size!"));
return DDHAL_DRIVER_HANDLED;
}
ZeroMemory(&KERNCAPS, sizeof(KERNCAPS));
KERNCAPS.dwSize = sizeof(KERNCAPS);
KERNCAPS.dwCaps = DDKERNELCAPS_LOCK |
DDKERNELCAPS_FLIPOVERLAY |
DDKERNELCAPS_SETSTATE;
if (!(pThisDisplay->pGLInfo->dwFlags & GMVF_NOIRQ))
{
KERNCAPS.dwCaps |= DDKERNELCAPS_CAPTURE_SYSMEM |
DDKERNELCAPS_FIELDPOLARITY |
DDKERNELCAPS_SKIPFIELDS |
DDKERNELCAPS_FLIPVIDEOPORT |
DDKERNELCAPS_AUTOFLIP;
KERNCAPS.dwIRQCaps = DDIRQ_VPORT0_VSYNC |
DDIRQ_DISPLAY_VSYNC |
DDIRQ_BUSMASTER;
}
lpData->dwActualSize = sizeof(DDKERNELCAPS);
memcpy(lpData->lpvData, &KERNCAPS, sizeof(DDKERNELCAPS) );
lpData->ddRVal = DD_OK;
}
#endif // W95_DDRAW
#endif // SUPPORT_VIDEOPORT
//@@END_DDKSPLIT
#ifdef W95_DDRAW
#ifdef USE_DD_CONTROL_COLOR
// Fill in the colour control callbacks.
if (MATCH_GUID((lpData->guidInfo), GUID_ColorControlCallbacks) )
{
DDHAL_DDCOLORCONTROLCALLBACKS ColConCB;
DISPDBG((DBGLVL," GUID_ColorControlCallbacks"));
memset(&ColConCB, 0, sizeof(ColConCB));
ColConCB.dwSize = sizeof(ColConCB);
ColConCB.dwFlags = DDHAL_COLOR_COLORCONTROL;
ColConCB.ColorControl = DdControlColor;
dwSize = min( lpData->dwExpectedSize, sizeof(ColConCB));
lpData->dwActualSize = sizeof(ColConCB);
memcpy(lpData->lpvData, &ColConCB, dwSize);
lpData->ddRVal = DD_OK;
}
#endif
#endif
#if !defined(_WIN64) && WNT_DDRAW
// Fill in the NT specific callbacks
if (MATCH_GUID((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;
NtCallbacks.FreeDriverMemory = DdFreeDriverMemory;
NtCallbacks.SetExclusiveMode = DdSetExclusiveMode;
NtCallbacks.FlipToGDISurface = DdFlipToGDISurface;
memcpy(lpData->lpvData, &NtCallbacks, dwSize);
lpData->ddRVal = DD_OK;
}
#endif
#if DX7_STEREO
if (MATCH_GUID((lpData->guidInfo), GUID_DDMoreSurfaceCaps) )
{
#if WNT_DDRAW
DD_MORESURFACECAPS DDMoreSurfaceCaps;
#else
DDMORESURFACECAPS DDMoreSurfaceCaps;
#endif
DDSCAPSEX ddsCapsEx, ddsCapsExAlt;
ULONG ulCopyPointer;
DISPDBG((DBGLVL," 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;
if (_DD_bIsStereoMode(pThisDisplay,
pThisDisplay->dwScreenWidth,
pThisDisplay->dwScreenHeight,
pThisDisplay->ddpfDisplay.dwRGBBitCount))
{
DDMoreSurfaceCaps.ddsCapsMore.dwCaps2 =
DDSCAPS2_STEREOSURFACELEFT;
}
lpData->dwActualSize = lpData->dwExpectedSize;
dwSize = min(sizeof(DDMoreSurfaceCaps),lpData->dwExpectedSize);
memcpy(lpData->lpvData, &DDMoreSurfaceCaps, dwSize);
// Now fill in ddsCapsEx and ddsCapsExAlt heaps
// Hardware with different restrictions for different heaps
// should prepare ddsCapsEx and ddsCapsExAlt carefully and
// fill them into lpvData in proper order
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;
}
#endif // DX7_STEREO
// We always handled it.
DBG_CB_EXIT(DdGetDriverInfo, lpData->ddRVal );
return DDHAL_DRIVER_HANDLED;
} // DdGetDriverInfo