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.
 
 
 
 
 
 

1376 lines
42 KiB

/***************************************************************************
*
* ******************************************
* * Copyright (c) 1996, Cirrus Logic, Inc. *
* * All Rights Reserved *
* ******************************************
*
* PROJECT: Laguna I (CL-GD546x) -
*
* FILE: ddsurf.c
*
* AUTHOR: Benny Ng
*
* DESCRIPTION:
* This module implements the DirectDraw SURFACE
* components for the Laguna NT driver.
*
* MODULES:
* DdLock()
* DdUnlock()
* CanCreateSurface()
* CreateSurface()
* DestroySurface()
*
* REVISION HISTORY:
* 7/12/96 Benny Ng Initial version
*
* $Log: X:/log/laguna/nt35/displays/cl546x/ddsurf.c $
*
* Rev 1.25 May 01 1998 11:33:02 frido
* Added one more check for PC98.
*
* Rev 1.24 May 01 1998 11:07:24 frido
* Finally the programmable blitter stride works.
*
* Rev 1.23 Mar 30 1998 13:04:38 frido
* Added one more call to Set256ByteFetch if an overlay failed to be created.
*
* Rev 1.22 Mar 25 1998 18:09:44 frido
* PDR#11184. Finally. When overlays are turned on, 256-byte fetch
* should be turned off. And when overlays are turned off again, 256-byte
* fetch should be restored.
*
* Rev 1.21 17 Oct 1997 11:29:48 bennyn
* Clear dwReserved1 after DestroySurface.
*
* Rev 1.20 16 Oct 1997 09:52:56 bennyn
*
* Fixed the FlipCube FPS exceed refresh rate problem
*
* Rev 1.19 08 Oct 1997 11:29:38 RUSSL
* Fix so this file can be compiled without OVERLAY defined
*
* Rev 1.18 26 Sep 1997 11:01:14 bennyn
* Fixed PDR 10563
*
* Rev 1.17 16 Sep 1997 15:13:46 bennyn
* Added DD overlay support.
*
* Rev 1.16 03 Sep 1997 17:00:48 bennyn
* In CreateSurface() punts the request if at 320x240x8 or 320x200x8
*
****************************************************************************
****************************************************************************/
/*----------------------------- INCLUDES ----------------------------------*/
#include "precomp.h"
#include <clioctl.h>
//
// This file isn't used in NT 3.51
//
#ifndef WINNT_VER35
/*----------------------------- DEFINES -----------------------------------*/
//#define DBGBRK
#define DBGLVL 1
/*--------------------- STATIC FUNCTION PROTOTYPES ------------------------*/
#if DRIVER_5465 && defined(OVERLAY)
VOID GetFormatInfo (LPDDPIXELFORMAT lpFormat, LPDWORD lpFourcc, LPDWORD lpBitCount);
#endif
/*--------------------------- ENUMERATIONS --------------------------------*/
/*----------------------------- TYPEDEFS ----------------------------------*/
/*-------------------------- STATIC VARIABLES -----------------------------*/
/*-------------------------- GLOBAL FUNCTIONS -----------------------------*/
#if DRIVER_5465 // PDR#11184
VOID Set256ByteFetch(PPDEV ppdev, BOOL fEnable)
{
ULONG ulStall = 50 * 1000;
ULONG ulReturn;
while (LLDR_SZ(grSTATUS) != 0) ; // Wait for idle chip.
while (LLDR_SZ(grQFREE) != 25) ; // Wait for empty FIFO queue.
if (!DEVICE_IO_CTRL(ppdev->hDriver, // Wait for 50 ms.
IOCTL_STALL,
&ulStall, sizeof(ulStall),
NULL, 0,
&ulReturn,
NULL))
{
RIP(_DISP_ "Set256ByteFetch - IOCTL_STALL failed!\n");
}
if (fEnable)
{
// Restore the CONTROL2 register value.
LL16(grCONTROL2, ppdev->DriverData.dwCONTROL2Save);
}
else
{
// Disable 256-byte fetch after storing the current value.
ppdev->DriverData.dwCONTROL2Save = LLDR_SZ(grCONTROL2);
LL16(grCONTROL2, ppdev->DriverData.dwCONTROL2Save & ~0x0010);
}
}
#endif
/****************************************************************************
* FUNCTION NAME: DdLock
*
* DESCRIPTION: This callback is invoked whenever a surface is about
* to be directly accessed by the user. This is where you
* need to make sure that a surface can be safely accessed
* by the user.
* If your memory cannot be accessed while in accelerator
* mode, you should take either take the card out of
* accelerator mode or else return DDERR_SURFACEBUSY
* If someone is accessing a surface that was just flipped
* away from, make sure that the old surface (what was the
* primary) has finished being displayed.
* (Based on Laguna Win95 DirectDraw code)
****************************************************************************/
DWORD DdLock(PDD_LOCKDATA lpLock)
{
#ifdef RDRAM_8BIT
RECTL SrcRectl;
#endif
DRIVERDATA* pDriverData;
PDEV* ppdev;
HRESULT ddrval;
DWORD tmp;
DISPDBG((DBGLVL, "DDraw - DdLock\n"));
#ifdef DBGBRK
DBGBREAKPOINT();
#endif
ppdev = (PDEV*) lpLock->lpDD->dhpdev;
pDriverData = (DRIVERDATA*) &ppdev->DriverData;
SYNC_W_3D(ppdev);
#if DRIVER_5465 && defined(OVERLAY)
if (DDSCAPS_OVERLAY & lpLock->lpDDSurface->ddsCaps.dwCaps)
{
ppdev->dwDDLinearCnt++;
return pDriverData->OverlayTable.pfnLock(ppdev, lpLock);
}
#endif
#ifdef RDRAM_8BIT
if (lpLock->lpDDSurface->lpGbl->ddpfSurface.dwFlags & DDPF_FOURCC)
{
if (lpLock->bHasRect)
SrcRectl = lpLock->rArea;
else
{
tmp = lpLock->lpDDSurface->lpGbl->fpVidMem;
SrcRectl.top = cvlxy(ppdev->lDeltaScreen, tmp, BYTESPERPIXEL);
SrcRectl.left = SrcRectl.top & 0xFFFF;
SrcRectl.top = (SrcRectl.top >> 16) & 0xFFFF;
SrcRectl.bottom = SrcRectl.top + lpLock->lpDDSurface->lpGbl->wHeight;
SrcRectl.right = SrcRectl.left + lpLock->lpDDSurface->lpGbl->wWidth;
};
ppdev->offscr_YUV.nInUse = TRUE;
ppdev->offscr_YUV.SrcRect = SrcRectl;
ppdev->offscr_YUV.ratio = 0;
lpLock->lpDDSurface->lpGbl->dwReserved1 = 0;
};
#endif
// get the monitor frequency after a mode reset
if (pDriverData->fReset)
{
vGetDisplayDuration(&ppdev->flipRecord);
pDriverData->fReset = FALSE;
};
// Check to see if any pending physical flip has occurred.
// Don't allow a lock if a blt is in progress:
ddrval = vUpdateFlipStatus(&ppdev->flipRecord,
lpLock->lpDDSurface->lpGbl->fpVidMem);
if (ddrval != DD_OK)
{
lpLock->ddRVal = DDERR_WASSTILLDRAWING;
return(DDHAL_DRIVER_HANDLED);
};
// don't allow a lock if a blt is in progress
// (only do this if your hardware requires it)
// Note: GD5462 requires it. Blitter and screen
// access are not otherwise synchronized.
if ((ppdev->dwDDLinearCnt == 0) && (DrawEngineBusy(pDriverData)))
{
lpLock->ddRVal = DDERR_WASSTILLDRAWING;
return DDHAL_DRIVER_HANDLED;
};
// Reference count it, just for the heck of it:
ppdev->dwDDLinearCnt++;
return(DDHAL_DRIVER_NOTHANDLED);
} // Lock
/****************************************************************************
* FUNCTION NAME: DdUnlock
*
* DESCRIPTION:
****************************************************************************/
DWORD DdUnlock(PDD_UNLOCKDATA lpUnlock)
{
PDEV* ppdev = (PDEV*) lpUnlock->lpDD->dhpdev;
DISPDBG((DBGLVL, "DDraw - DdUnlock\n"));
#if DRIVER_5465 && defined(OVERLAY)
if (DDSCAPS_OVERLAY & lpUnlock->lpDDSurface->ddsCaps.dwCaps)
ppdev->DriverData.OverlayTable.pfnUnlock(ppdev,lpUnlock);
#endif
#ifdef DBGBRK
DBGBREAKPOINT();
#endif
ppdev->dwDDLinearCnt--;
return DDHAL_DRIVER_NOTHANDLED;
} // Unlock
/****************************************************************************
* FUNCTION NAME: CanCreateSurface
*
* DESCRIPTION:
* (Based on Laguna Win95 DirectDraw code)
****************************************************************************/
DWORD CanCreateSurface (PDD_CANCREATESURFACEDATA lpInput)
{
DRIVERDATA* pDriverData;
PDEV* ppdev;
DISPDBG((DBGLVL, "DDraw - CanCreateSurface\n"));
#ifdef DBGBRK
DBGBREAKPOINT();
#endif
ppdev = (PDEV*) lpInput->lpDD->dhpdev;
pDriverData = (DRIVERDATA*) &ppdev->DriverData;
// First check for overlay surfaces
if (lpInput->lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_OVERLAY)
{
#if DRIVER_5465 && defined(OVERLAY)
if (DDSCAPS_OVERLAY & lpInput->lpDDSurfaceDesc->ddsCaps.dwCaps)
{
DWORD dwFourCC;
DWORD dwBitCount;
HRESULT hr;
if (lpInput->bIsDifferentPixelFormat)
{
GetFormatInfo(&(lpInput->lpDDSurfaceDesc->ddpfPixelFormat),
&dwFourCC, &dwBitCount);
}
else
{
dwBitCount = BITSPERPIXEL;
if (16 == dwBitCount)
dwFourCC = BI_BITFIELDS;
else
dwFourCC = BI_RGB;
}
hr = pDriverData->OverlayTable.pfnCanCreateSurface(ppdev,dwFourCC,dwBitCount);
if (DD_OK != hr)
{
lpInput->ddRVal = hr;
return DDHAL_DRIVER_HANDLED;
}
}
#else
lpInput->ddRVal = DDERR_NOOVERLAYHW;;
return (DDHAL_DRIVER_HANDLED);
#endif
}
else if (lpInput->bIsDifferentPixelFormat)
{
// Next check for formats that don't match the primary surface.
LPDDPIXELFORMAT lpFormat = &lpInput->lpDDSurfaceDesc->ddpfPixelFormat;
if (lpFormat->dwFlags & DDPF_FOURCC)
{
// YUV422 surface
if (lpFormat->dwFourCC == FOURCC_UYVY)
{
#if DRIVER_5465
if (ppdev->iBitmapFormat == BMF_8BPP)
lpInput->ddRVal = DDERR_INVALIDPIXELFORMAT;
else
lpInput->ddRVal = DD_OK;
return (DDHAL_DRIVER_HANDLED);
#else // 5462 and 5464 driver
#if _WIN32_WINNT >= 0x0500
// For NT5 do not allow any YUV surfaces that are not
// overlays.
;
#else // NT4
// if we have nine bit RDRAMs then surface creation is okay
if (TRUE == pDriverData->fNineBitRDRAMS)
{
lpInput->ddRVal = DD_OK;
return (DDHAL_DRIVER_HANDLED);
}
// if we have eight bit RDRAMs then see if already
// have a YUV422 surface
else if (FALSE == ppdev->offscr_YUV.nInUse)
{
lpInput->ddRVal = DD_OK;
return (DDHAL_DRIVER_HANDLED);
};
#endif
#endif // DRIVER_5465
}; // endif (lpFormat->dwFourCC == FOURCC_UYVY)
}
else
{
// support RGB565 with RGB8 primary surface !!!
}; // endif (lpFormat->dwFlags & DDPF_FOURCC)
lpInput->ddRVal = DDERR_INVALIDPIXELFORMAT;
return (DDHAL_DRIVER_HANDLED);
}; // endif (lpInput->lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_OVERLAY)
lpInput->ddRVal = DD_OK;
return (DDHAL_DRIVER_HANDLED);
} // CanCreateSurface
/****************************************************************************
* FUNCTION NAME: InsertInDDOFSQ()
*
* DESCRIPTION: Insert the handle into the DD Offscreen memory queue.
****************************************************************************/
void InsertInDDOFSQ(PPDEV ppdev, DDOFM *hdl)
{
hdl->prevhdl = NULL;
if (ppdev->DDOffScnMemQ == NULL)
{
hdl->nexthdl = NULL;
ppdev->DDOffScnMemQ = hdl;
}
else
{
ppdev->DDOffScnMemQ->prevhdl = hdl;
hdl->nexthdl = ppdev->DDOffScnMemQ;
ppdev->DDOffScnMemQ = hdl;
};
} // InsertInDDOFSQ()
/****************************************************************************
* FUNCTION NAME: RemoveFrmDDOFSQ()
*
* DESCRIPTION: Remove the handle from the DD Offscreen memory queue.
****************************************************************************/
BOOL RemoveFrmDDOFSQ(PPDEV ppdev, DDOFM *hdl)
{
DDOFM *prvpds, *nxtpds;
DDOFM *pds;
BOOL fndflg;
// Validate the release block
fndflg = FALSE;
pds = ppdev->DDOffScnMemQ;
while (pds != 0)
{
if (hdl == pds)
{
fndflg = TRUE;
break;
};
// Next free block
pds = pds->nexthdl;
}; // end while
// Return if it is an invalid handle
if (!fndflg)
return (FALSE);
prvpds = hdl->prevhdl;
nxtpds = hdl->nexthdl;
if (hdl == ppdev->DDOffScnMemQ)
{
ppdev->DDOffScnMemQ = nxtpds;
if (nxtpds != 0)
nxtpds->prevhdl = NULL;
}
else
{
if (nxtpds != NULL)
nxtpds->prevhdl = prvpds;
if (prvpds != NULL)
prvpds->nexthdl = nxtpds;
};
// Free allocated DDOFM structure from host memory
MEMORY_FREE(hdl);
return (TRUE);
} // RemoveFrmDDOFSQ()
/****************************************************************************
* FUNCTION NAME: CreateSurface
*
* DESCRIPTION:
* (Based on Laguna Win95 DirectDraw code)
****************************************************************************/
DWORD CreateSurface (PDD_CREATESURFACEDATA lpInput)
{
BOOL puntflag = FALSE;
BOOL bYUVsurf;
#if DRIVER_5465 && defined(OVERLAY)
BOOL bOverlaySurf;
#endif // #if DRIVER_5465 && defined(OVERLAY)
DRIVERDATA* pDriverData;
PDEV* ppdev;
LPDDSURFACEDESC lpDDSurfaceDesc = lpInput->lpDDSurfaceDesc;
LPDDPIXELFORMAT lpFormat = &lpInput->lpDDSurfaceDesc->ddpfPixelFormat;
DWORD dwPitch = 0;
DISPDBG((DBGLVL, "DDraw - CreateSurface\n"));
#ifdef DBGBRK
DBGBREAKPOINT();
#endif
ppdev = (PDEV*) lpInput->lpDD->dhpdev;
pDriverData = (DRIVERDATA*) &ppdev->DriverData;
bYUVsurf = FALSE;
#if DRIVER_5465 && defined(OVERLAY)
bOverlaySurf = FALSE;
#endif // #if DRIVER_5465 && defined(OVERLAY)
#if DRIVER_5465
#ifdef ALLOC_IN_CREATESURFACE
{ // Support for 5465
PDD_SURFACE_LOCAL *lplpSurface;
SIZEL sizl;
OFMHDL *hdl;
DDOFM *pds;
DWORD i;
#if DRIVER_5465 && defined(OVERLAY)
DWORD dwBitCount;
DWORD dwFourCC;
// check for overlay surface
if (lpDDSurfaceDesc->ddsCaps.dwCaps & ( DDSCAPS_OVERLAY
#if DDRAW_COMPAT >= 50
| DDSCAPS_VIDEOPORT
#endif
))
{
if (lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT)
{
GetFormatInfo(&(lpInput->lpDDSurfaceDesc->ddpfPixelFormat),
&dwFourCC, &dwBitCount);
}
else
{
dwFourCC = 0;
dwBitCount = BITSPERPIXEL;
}
#if DDRAW_COMPAT >= 50
if((CL_GD5465 == pDriverData->dwLgVenDevID)
&& (DDSCAPS_VIDEOPORT & lpDDSurfaceDesc->ddsCaps.dwCaps))
{
if((lpDDSurfaceDesc->dwWidth * dwBitCount >> 3) >= 2048 )
{
//Surface is too wide for video port
lpInput->ddRVal = DDERR_TOOBIGWIDTH;
return DDHAL_DRIVER_HANDLED;
}
}
#endif
bOverlaySurf = TRUE;
} // end overlay surface handler
else
#endif // #if DRIVER_5465 && defined(OVERLAY)
if (lpInput->lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT)
{
// Specify the block size for non-RGB surfaces
if (lpFormat->dwFlags & DDPF_FOURCC)
{
// YUV422 surface
if (lpFormat->dwFourCC == FOURCC_UYVY)
{
bYUVsurf = TRUE;
}; // endif (lpFormat->dwFourCC == FOURCC_UYVY)
}; // endif (lpFormat->dwFlags & DDPF_FOURCC)
} // endif (lpInput->lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT)
// Not support 8BPP YUV surface
if (
#if DRIVER_5465 && defined(OVERLAY)
(!bOverlaySurf) &&
#endif // #if DRIVER_5465 && defined(OVERLAY)
((bYUVsurf) && (8 == BITSPERPIXEL)))
{
lpInput->ddRVal = DDERR_INVALIDPIXELFORMAT;
return DDHAL_DRIVER_HANDLED;
}; // endif (8 == BITSPERPIXEL)
lplpSurface = lpInput->lplpSList;
for (i = 0; i < lpInput->dwSCnt; i++)
{
PDD_SURFACE_LOCAL lpSurface = *lplpSurface;
sizl.cx = lpSurface->lpGbl->wWidth;
sizl.cy = lpSurface->lpGbl->wHeight;
#if 1 // PC98
if ( (lpDDSurfaceDesc->dwFlags == (DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH))
&& (lpDDSurfaceDesc->ddsCaps.dwCaps == DDSCAPS_VIDEOMEMORY)
&& (lpDDSurfaceDesc->dwHeight == 32 && lpDDSurfaceDesc->dwWidth == 32)
&& (sizl.cx == 32 && sizl.cy == 32)
&& (lpInput->dwSCnt == 1)
)
{
sizl.cx = min(32 * 32, ppdev->lDeltaScreen / ppdev->iBytesPerPixel);
sizl.cy = (32 * 32) / sizl.cx;
if ( (sizl.cx * sizl.cy) < (32 * 32) )
{
sizl.cy++;
}
dwPitch = 32 * ppdev->iBytesPerPixel;
}
#endif
#if DRIVER_5465 && defined(OVERLAY)
// Adjust the overlay surface request size with pixel format
if (bOverlaySurf)
{
unsigned long OvlyBPP;
if (bYUVsurf)
OvlyBPP = lpSurface->lpGbl->ddpfSurface.dwYUVBitCount/8;
else
OvlyBPP = lpSurface->lpGbl->ddpfSurface.dwRGBBitCount/8;
if (OvlyBPP > BYTESPERPIXEL)
sizl.cx = (sizl.cx * OvlyBPP) / BYTESPERPIXEL;
};
#endif // #if DRIVER_5465 && defined(OVERLAY)
// At certain modes (eg 1280x1024x24), When you runs MOV or AVI from
// desktop, the DD CreateSurface has to punt the request back to DD
// due to no offscreen memmory available. When you hit ALT-ENTER to
// go full screen, the appl swithces to mode (320x240x8 or 320x200x8),
// create DD surfaces and then directly write to the DD surfaces.
// Unfortunely, in those modes the pitch is 640 but the appl assumes
// the pitch is 320 and we got half screen of the imagine.
//
// To fix the problem, just fails the create surface for those
// particule request.
//
puntflag = FALSE;
if (ppdev->iBytesPerPixel == 1)
{
if ((ppdev->cxScreen == 320) && (sizl.cx == 320))
{
if (((ppdev->cyScreen == 240) && (sizl.cy == 240)) ||
((ppdev->cyScreen == 200) && (sizl.cy == 200)))
{
// Punt the create surface cause FlipCube FPS exceeds the
// refresh rate.
// So in order to bypass the above problem, it is looking for
// bPrevModeDDOutOfVideoMem to be set when create surface fails
// due to out of video memory in the previous mode before
// punting the request.
if (ppdev->bPrevModeDDOutOfVideoMem)
puntflag = TRUE;
};
};
};
if (!puntflag)
{
#if DRIVER_5465 && defined(OVERLAY)
if (bOverlaySurf)
{
hdl = AllocOffScnMem(ppdev, &sizl, EIGHT_BYTES_ALIGN, NULL);
}
else
#endif // #if DRIVER_5465 && defined(OVERLAY)
hdl = AllocOffScnMem(ppdev, &sizl, PIXEL_AlIGN, NULL);
#if 1 // PC98
if (!bOverlaySurf)
#endif
// Somehow when allocate the bottom of the offscreen memory to
// DirectDraw, it hangs the DirectDraw.
// The following is temporary patch fix for the problem
{
BOOL gotit;
ULONG val;
ULONG fpvidmem;
val = ppdev->lTotalMem - 0x20000;
gotit = FALSE;
while ((!gotit) && (hdl != NULL))
{
fpvidmem = (hdl->aligned_y * ppdev->lDeltaScreen) + hdl->aligned_x;
if (fpvidmem > val)
{
pds = (DDOFM *) MEM_ALLOC (FL_ZERO_MEMORY, sizeof(DDOFM), ALLOC_TAG);
if (pds==NULL)
{
FreeOffScnMem(ppdev, hdl);
lpInput->ddRVal = DDERR_OUTOFMEMORY;
return DDHAL_DRIVER_NOTHANDLED;
}
pds->prevhdl = 0;
pds->nexthdl = 0;
pds->phdl = hdl;
InsertInDDOFSQ(ppdev, pds);
hdl = AllocOffScnMem(ppdev, &sizl, PIXEL_AlIGN, NULL);
}
else
{
gotit = TRUE;
};
}; // endwhile
}
lpSurface->dwReserved1 = 0;
if (hdl != NULL)
{
#ifdef WINNT_VER40
if ((pds = (DDOFM *) MEM_ALLOC (FL_ZERO_MEMORY, sizeof(DDOFM), ALLOC_TAG)) != NULL)
#else
if ((pds = (DDOFM *) MEM_ALLOC (LPTR, sizeof(DDOFM))) != NULL)
#endif
{
ppdev->bPrevModeDDOutOfVideoMem = FALSE;
// If pixel format is difference from FB, set the flag
if (lpInput->lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT)
{
lpSurface->dwFlags |= DDRAWISURF_HASPIXELFORMAT;
};
// lpSurface->lpGbl->fpVidMem = DDHAL_PLEASEALLOC_BLOCKSIZE;
if (bYUVsurf)
{
lpSurface->lpGbl->ddpfSurface.dwYUVBitCount = 16;
lpSurface->lpGbl->ddpfSurface.dwYBitMask = (DWORD) -1;
lpSurface->lpGbl->ddpfSurface.dwUBitMask = (DWORD) -1;
lpSurface->lpGbl->ddpfSurface.dwVBitMask = (DWORD) -1;
lpSurface->lpGbl->dwBlockSizeX = lpSurface->lpGbl->wWidth;
lpSurface->lpGbl->dwBlockSizeY = lpSurface->lpGbl->wHeight;
lpSurface->dwFlags |= DDRAWISURF_HASPIXELFORMAT;
}; // endif (bYUVsurf)
#if DRIVER_5465 && defined(OVERLAY)
if (bOverlaySurf)
{
#if DDRAW_COMPAT >= 50
if (lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_OVERLAY)
#endif
{
HRESULT hResult;
#if 1 // PDR#11184
// Finally... When overlays are turned on, 256-byte fetch should be turned off.
if (pDriverData->dwOverlayCount++ == 0)
{
Set256ByteFetch(ppdev, FALSE);
}
#endif
lpSurface->dwReserved1 = (DWORD) pds;
hResult = pDriverData->OverlayTable.pfnCreateSurface(ppdev,
lpSurface,
dwFourCC);
if (DD_OK != hResult)
{
#if 1 // PDR#11184
// Decrement overlay counter and maybe turn 256-byte fetch
// back on.
if (--pDriverData->dwOverlayCount == 0)
{
Set256ByteFetch(ppdev, TRUE);
}
#endif
// Free the allocated offscreen memory
FreeOffScnMem(ppdev, hdl);
// Free allocated DDOFM structure from host memory
MEMORY_FREE(pds);
lpSurface->dwReserved1 = 0;
lpInput->ddRVal = hResult;
return DDHAL_DRIVER_HANDLED;
}
}
// don't need this for NT yet
#if 0
// if the surface width is larger than the display pitch, or
// its a 5465, and a videoport surface wider than 2048 bytes or
// its a CLPL surface
// then convert to a linear allocation
//
// prior to DX5 we never even get called for surfaces wider than
// the display pitch
if ( (FOURCC_YUVPLANAR == dwFourCC)
#if DDRAW_COMPAT >= 50
|| (lpSurface->lpGbl->dwBlockSizeX > pDriverData->ScreenPitch)
|| ( (CL_GD5465 == pDriverData->dwLgVenDevID)
&& (DDSCAPS_VIDEOPORT & lpDDSurfaceDesc->ddsCaps.dwCaps)
&& (2048 <= pDriverData->ScreenPitch)
)
#endif
)
{
// fake a linear space in rectangular memory
LP_SURFACE_DATA lpSurfaceData = (LP_SURFACE_DATA)(lpSurface->dwReserved1);
DWORD dwTotalBytes;
DWORD dwNumScanLines;
lpSurfaceData->dwOverlayFlags |= FLG_LINEAR;
// CLPL surfaces need 3/4 of the space an equivalent size
// YUV422 surface would need, the space allocated for the
// Y values is the width * height and the space for the UV
// interleaved values is half again as much. Pad the Y
// region so the UV interleaved data is on a qword boundary
// in aperture 0
if (FOURCC_YUVPLANAR == dwFourCC)
{
// compute space needed for Y values
dwTotalBytes = ((lpSurface->lpGbl->wHeight * lpSurface->lpGbl->wWidth) + 7) & ~7;
// add on space for UV interleaved values
dwTotalBytes += dwTotalBytes / 2;
// CLPL surfaces have pitch same as width
lpSurface->lpGbl->lPitch = lpSurface->lpGbl->wWidth;
}
// the normal case
else
{
dwTotalBytes = lpSurface->lpGbl->dwBlockSizeY *
lpSurface->lpGbl->dwBlockSizeX;
lpSurface->lpGbl->lPitch = lpSurface->lpGbl->dwBlockSizeX;
}
dwNumScanLines = (dwTotalBytes + pDriverData->ScreenPitch - 1) /
pDriverData->ScreenPitch;
lpSurface->lpGbl->dwBlockSizeY = dwNumScanLines;
lpSurface->lpGbl->dwBlockSizeX = pDriverData->ScreenPitch;
if (! pDriverData->fWeAllocDDSurfaces)
{
LOAD_THE_STILL(lpSurface->lpGbl->dwBlockSizeX,
lpSurface->lpGbl->dwBlockSizeY);
}
lpSurface->lpGbl->fpVidMem = DDHAL_PLEASEALLOC_BLOCKSIZE;
}
#endif // if 0
}; // endif (bOverlaySurf)
#endif // #if DRIVER_5465 && defined(OVERLAY)
pds->prevhdl = 0;
pds->nexthdl = 0;
pds->phdl = hdl;
InsertInDDOFSQ(ppdev, pds);
lpSurface->lpGbl->fpVidMem = (hdl->aligned_y * ppdev->lDeltaScreen) +
hdl->aligned_x;
lpSurface->dwReserved1 = (DWORD) pds ;
lpSurface->lpGbl->xHint = hdl->aligned_x/ppdev->iBytesPerPixel;
lpSurface->lpGbl->yHint = hdl->aligned_y;
#if 1 // PC98
if (dwPitch)
{
lpSurface->lpGbl->lPitch = dwPitch;
}
else
#endif
lpSurface->lpGbl->lPitch = ppdev->lDeltaScreen;
#if 1 // PC98
if (dwPitch)
{
lpDDSurfaceDesc->lPitch = dwPitch;
}
else
#endif
lpDDSurfaceDesc->lPitch = ppdev->lDeltaScreen;
lpDDSurfaceDesc->dwFlags |= DDSD_PITCH;
// We handled the creation entirely ourselves, so we have to
// set the return code and return DDHAL_DRIVER_HANDLED:
lpInput->ddRVal = DD_OK;
}
else
{
FreeOffScnMem(ppdev, hdl);
lpInput->ddRVal = DDERR_OUTOFMEMORY;
return DDHAL_DRIVER_NOTHANDLED;
};
}
else
{
ppdev->bPrevModeDDOutOfVideoMem = TRUE;
lpInput->ddRVal = DDERR_OUTOFVIDEOMEMORY;
return DDHAL_DRIVER_NOTHANDLED;
// lpSurface->lpGbl->lPitch = (ppdev->iBytesPerPixel * sizl.cx + 3) & ~3;
// lpSurface->lpGbl->dwUserMemSize = lpSurface->lpGbl->lPitch * sizl.cy;
// if (bYUVsurf)
// lpSurface->lpGbl->fpVidMem |= DDHAL_PLEASEALLOC_USERMEM;
}; // if (hdl != NULL)
} // endif (puntflag)
lplpSurface++;
}; // endfor
if (puntflag)
{
lpInput->ddRVal = DDERR_GENERIC;
return DDHAL_DRIVER_HANDLED;
};
if (hdl != NULL)
{
lpInput->ddRVal = DD_OK;
return DDHAL_DRIVER_HANDLED;
}
else
{
return DDHAL_DRIVER_NOTHANDLED;
};
}; // // Support for 5465
#endif // ALLOC_IN_CREATESURFACE
#else
{ // Support for 5462 or 5464
// Do nothing except fill in the block size for YUV surfaces.
// We tag and count the video surfaces in Blt32.
if (lpInput->lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT)
{
// only support alternate pixel format in 8 & 16 bpp frame buffers
if ((8 != BITSPERPIXEL) && (16 != BITSPERPIXEL))
{
lpInput->ddRVal = DDERR_INVALIDPIXELFORMAT;
return DDHAL_DRIVER_HANDLED;
};
// Specify the block size for non-RGB surfaces
if (lpFormat->dwFlags & DDPF_FOURCC)
{
#if _WIN32_WINNT >= 0x0500
// For NT5, do not allow any YUV surfaces for 5462 and 5464
lpInput->ddRVal = DDERR_INVALIDPIXELFORMAT;
return DDHAL_DRIVER_HANDLED;
#endif
// YUV422 surface
if (lpFormat->dwFourCC == FOURCC_UYVY)
{
PDD_SURFACE_LOCAL *lplpSurface;
unsigned int i;
GRAB_VIDEO_FORMAT_SEMAPHORE(&(pDriverData->VideoSemaphore));
if (0 == pDriverData->NumVideoSurfaces)
{
// no video surfaces so we can create anu format we want
pDriverData->NumVideoSurfaces += (WORD)lpInput->dwSCnt;
pDriverData->CurrentVideoFormat &= 0xFF00;
pDriverData->CurrentVideoFormat |= FMT_VID_16BPP | FMT_VID_YUV422;
if (2 == BYTESPERPIXEL)
{
pDriverData->CurrentVideoFormat |= FMT_VID_GAMMA;
SetGamma(ppdev, pDriverData);
};
ppdev->grFORMAT = (ppdev->grFORMAT & 0xFF00) |
(pDriverData->CurrentVideoFormat & 0x00FF);
LL16(grFormat, ppdev->grFORMAT);
if (TRUE == pDriverData->fNineBitRDRAMS)
{
LL8(grStop_BLT_2, ENABLE_VIDEO_FORMAT);
LL8(grExternal_Overlay, ENABLE_RAMBUS_9TH_BIT);
}
else // 8 bit RDRAMs
{
LL8(grStart_BLT_2, ENABLE_VIDEO_FORMAT | ENABLE_VIDEO_WINDOW);
LL8(grStop_BLT_2, ENABLE_VIDEO_FORMAT | ENABLE_VIDEO_WINDOW);
};
}
else
{
if ((FMT_VID_16BPP | FMT_VID_YUV422) == pDriverData->CurrentVideoFormat)
{
pDriverData->NumVideoSurfaces += (WORD)lpInput->dwSCnt;
}
else
{
UNGRAB_VIDEO_FORMAT_SEMAPHORE(&(pDriverData->VideoSemaphore));
lpInput->ddRVal = DDERR_CURRENTLYNOTAVAIL;
return DDHAL_DRIVER_HANDLED;
};
}; // endif (0 == pDriverData->NumVideoSurfaces)
UNGRAB_VIDEO_FORMAT_SEMAPHORE(&(pDriverData->VideoSemaphore));
SET_DRVSEM_YUV();
ppdev->bYUVSurfaceOn = TRUE;
bYUVsurf = TRUE;
// They may have specified multiple surfaces
lplpSurface = lpInput->lplpSList;
for (i = 0; i < lpInput->dwSCnt; i++)
{
PDD_SURFACE_LOCAL lpSurface = *lplpSurface;
lpSurface->lpGbl->ddpfSurface.dwYUVBitCount = 16;
lpSurface->lpGbl->ddpfSurface.dwYBitMask = (DWORD) -1;
lpSurface->lpGbl->ddpfSurface.dwUBitMask = (DWORD) -1;
lpSurface->lpGbl->ddpfSurface.dwVBitMask = (DWORD) -1;
lpSurface->lpGbl->lPitch = ppdev->lDeltaScreen;
if (CL_GD5462 == ppdev->dwLgDevID)
lpSurface->lpGbl->dwBlockSizeX = lpSurface->lpGbl->wWidth << 1;
else
lpSurface->lpGbl->dwBlockSizeX = lpSurface->lpGbl->wWidth * 3;
lpSurface->lpGbl->dwBlockSizeY = lpSurface->lpGbl->wHeight;
lpSurface->lpGbl->fpVidMem = DDHAL_PLEASEALLOC_BLOCKSIZE;
lplpSurface++;
}; // endfor
}; // endif (lpFormat->dwFourCC == FOURCC_UYVY)
}; // endif (lpFormat->dwFlags & DDPF_FOURCC)
} // endif (lpInput->lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT)
#ifdef ALLOC_IN_CREATESURFACE
{
PDD_SURFACE_LOCAL *lplpSurface;
SIZEL sizl;
OFMHDL *hdl;
DDOFM *pds;
DWORD i;
hdl = NULL;
lplpSurface = lpInput->lplpSList;
for (i = 0; i < lpInput->dwSCnt; i++)
{
PDD_SURFACE_LOCAL lpSurface = *lplpSurface;
if (bYUVsurf)
{
sizl.cx = lpSurface->lpGbl->dwBlockSizeX/ppdev->iBytesPerPixel;
sizl.cy = lpSurface->lpGbl->dwBlockSizeY;
lpSurface->dwFlags |= DDRAWISURF_HASPIXELFORMAT;
}
else
{
sizl.cx = lpSurface->lpGbl->wWidth;
sizl.cy = lpSurface->lpGbl->wHeight;
};
hdl = AllocOffScnMem(ppdev, &sizl, PIXEL_AlIGN, NULL);
// Somehow when allocate the bottom of the offscreen memory to
// DirectDraw, it hangs the DirectDraw.
// The following is temporary patch fix for the problem
{
BOOL gotit;
ULONG val;
ULONG fpvidmem;
val = ppdev->lTotalMem - 0x20000;
gotit = FALSE;
while ((!gotit) && (hdl != NULL))
{
fpvidmem = (hdl->aligned_y * ppdev->lDeltaScreen) + hdl->aligned_x;
if (fpvidmem > val)
{
pds = (DDOFM *) MEM_ALLOC (FL_ZERO_MEMORY, sizeof(DDOFM), ALLOC_TAG);
if (pds==NULL)
{
FreeOffScnMem(ppdev, hdl);
lpInput->ddRVal = DDERR_OUTOFMEMORY;
return DDHAL_DRIVER_NOTHANDLED;
}
pds->prevhdl = 0;
pds->nexthdl = 0;
pds->phdl = hdl;
InsertInDDOFSQ(ppdev, pds);
hdl = AllocOffScnMem(ppdev, &sizl, PIXEL_AlIGN, NULL);
}
else
{
gotit = TRUE;
};
}; // endwhile
}
lpSurface->dwReserved1 = 0;
if (hdl != NULL)
{
#ifdef WINNT_VER40
if ((pds = (DDOFM *) MEM_ALLOC (FL_ZERO_MEMORY, sizeof(DDOFM), ALLOC_TAG)) != NULL)
#else
if ((pds = (DDOFM *) MEM_ALLOC (LPTR, sizeof(DDOFM))) != NULL)
#endif
{
pds->prevhdl = 0;
pds->nexthdl = 0;
pds->phdl = hdl;
InsertInDDOFSQ(ppdev, pds);
lpSurface->lpGbl->fpVidMem = (hdl->aligned_y * ppdev->lDeltaScreen) +
hdl->aligned_x;
lpSurface->dwReserved1 = (DWORD) pds ;
lpSurface->lpGbl->xHint = hdl->aligned_x/ppdev->iBytesPerPixel;
lpSurface->lpGbl->yHint = hdl->aligned_y;
lpSurface->lpGbl->lPitch = ppdev->lDeltaScreen;
lpDDSurfaceDesc->lPitch = ppdev->lDeltaScreen;
lpDDSurfaceDesc->dwFlags |= DDSD_PITCH;
// We handled the creation entirely ourselves, so we have to
// set the return code and return DDHAL_DRIVER_HANDLED:
lpInput->ddRVal = DD_OK;
}
else
{
FreeOffScnMem(ppdev, hdl);
};
}; // if (hdl != NULL)
lplpSurface++;
}; // endfor
if (hdl != NULL)
return DDHAL_DRIVER_HANDLED;
else
return DDHAL_DRIVER_NOTHANDLED;
};
#endif // ALLOC_IN_CREATESURFACE
} // Support for 5462 or 5464
#endif // DRIVER_5465
return DDHAL_DRIVER_NOTHANDLED;
} // CreateSurface
/****************************************************************************
* FUNCTION NAME: DestroySurface
*
* DESCRIPTION:
* (Based on Laguna Win95 DirectDraw code)
****************************************************************************/
DWORD DestroySurface (PDD_DESTROYSURFACEDATA lpInput)
{
PDD_SURFACE_LOCAL lpLocalSurface;
DRIVERDATA* pDriverData;
PDEV* ppdev;
DDOFM *hdl;
DISPDBG((DBGLVL, "DDraw - DestroySurface\n"));
#ifdef DBGBRK
DBGBREAKPOINT();
#endif
ppdev = (PDEV*) lpInput->lpDD->dhpdev;
pDriverData = (DRIVERDATA*) &ppdev->DriverData;
lpLocalSurface = lpInput->lpDDSurface;
#if DRIVER_5465
{ // Support for 5465
#if DRIVER_5465 && defined(OVERLAY)
// check for overlay surface
if (lpInput->lpDDSurface->ddsCaps.dwCaps & DDSCAPS_OVERLAY)
{
pDriverData->OverlayTable.pfnDestroySurface(ppdev,lpInput);
#if 1 // PDR#11184
// Enable 256-byte fetch if the last overlay surface has been destroyed.
if (--pDriverData->dwOverlayCount == 0)
{
Set256ByteFetch(ppdev, TRUE);
}
#endif
}
#endif
} // Support for 5465
#else
{ // Support for 5462 or 5464
if (DDRAWISURF_HASPIXELFORMAT & lpInput->lpDDSurface->dwFlags)
{
LPDDPIXELFORMAT lpFormat = &lpInput->lpDDSurface->lpGbl->ddpfSurface;
if (DDPF_FOURCC & lpFormat->dwFlags)
{
if (FOURCC_UYVY == lpFormat->dwFourCC)
{
GRAB_VIDEO_FORMAT_SEMAPHORE(&(pDriverData->VideoSemaphore));
if (0 == --pDriverData->NumVideoSurfaces)
{
CLR_DRVSEM_YUV();
// disable stuff if there's no more video windows
pDriverData->CurrentVideoFormat = pDriverData->CurrentVideoFormat & 0xFF00;
// These trash the video window left on screen
//pDriverData->grFormat = pREG->grFormat & 0xFF00;
//pDriverData->grStop_BLT_2 &= ~ENABLE_VIDEO_FORMAT;
//pDriverData->grExternal_Overlay &= ~ENABLE_RAMBUS_9TH_BIT;
}; // endif (0 == --pDriverData->NumVideoSurfaces)
UNGRAB_VIDEO_FORMAT_SEMAPHORE(&(pDriverData->VideoSemaphore));
#ifdef RDRAM_8BIT
if (FALSE == pDriverData->fNineBitRDRAMS)
{
// Need to Delete Rectangle and Clear Window
ppdev->offscr_YUV.nInUse = FALSE;
LL16(grX_Start_2, 0);
LL16(grY_Start_2, 0);
LL16(grX_End_2, 0);
LL16(grY_End_2, 0);
};
#endif
}; // endif (FOURCC_UYVY == lpFormat->dwFourCC)
}; // endif (DDPF_FOURCC & lpFormat->dwFlags)
}; // endif (DDRAWISURF_HASPIXELFORMAT & lpInput->lpDDSurface->dwFlags)
} // Support for 5462 or 5464
#endif // #endif DRIVER_5465
#ifdef ALLOC_IN_CREATESURFACE
if (lpLocalSurface->dwReserved1 != 0)
{
hdl = (DDOFM *) lpLocalSurface->dwReserved1;
FreeOffScnMem(ppdev, hdl->phdl);
RemoveFrmDDOFSQ(ppdev, hdl);
lpLocalSurface->dwReserved1 = 0;
};
lpInput->ddRVal = DD_OK;
return DDHAL_DRIVER_HANDLED;
#endif // ALLOC_IN_CREATESURFACE
return DDHAL_DRIVER_NOTHANDLED;
} // DestroySurface
#if DRIVER_5465 && defined(OVERLAY)
/***************************************************************************
*
* FUNCTION: GetFormatInfo()
*
* DESCRIPTION: This returns the FOURCC and the bit depth of the specified
* format. This is useful since DirectDraw has so many
* different ways to determine the format.
*
****************************************************************************/
VOID
GetFormatInfo (LPDDPIXELFORMAT lpFormat, LPDWORD lpFourcc, LPDWORD lpBitCount)
{
if (lpFormat->dwFlags & DDPF_FOURCC)
{
*lpFourcc = lpFormat->dwFourCC;
if (lpFormat->dwFourCC == BI_RGB)
{
*lpBitCount = lpFormat->dwRGBBitCount;
#ifdef DEBUG
if (lpFormat->dwRGBBitCount == 8)
{
DBG_MESSAGE(("Format: RGB 8"));
}
else if (lpFormat->dwRGBBitCount == 16)
{
DBG_MESSAGE(("Format: RGB 5:5:5"));
}
#endif
}
else if (lpFormat->dwFourCC == BI_BITFIELDS)
{
if ((lpFormat->dwRGBBitCount != 16) ||
(lpFormat->dwRBitMask != 0xf800) ||
(lpFormat->dwGBitMask != 0x07e0) ||
(lpFormat->dwBBitMask != 0x001f))
{
*lpFourcc = (DWORD) -1;
}
else
{
*lpBitCount = 16;
DBG_MESSAGE(("Format: RGB 5:6:5"));
}
}
else
{
lpFormat->dwRBitMask = (DWORD) -1;
lpFormat->dwGBitMask = (DWORD) -1;
lpFormat->dwBBitMask = (DWORD) -1;
if (FOURCC_YUVPLANAR == lpFormat->dwFourCC)
{
*lpBitCount = 8;
DBG_MESSAGE(("Format: CLPL"));
}
else
{
*lpBitCount = 16;
DBG_MESSAGE(("Format: UYVY"));
}
}
}
else if (lpFormat->dwFlags & DDPF_RGB)
{
if (lpFormat->dwRGBBitCount == 8)
{
*lpFourcc = BI_RGB;
DBG_MESSAGE(("Format: RGB 8"));
}
else if ((lpFormat->dwRGBBitCount == 16) &&
(lpFormat->dwRBitMask == 0xf800) &&
(lpFormat->dwGBitMask == 0x07e0) &&
(lpFormat->dwBBitMask == 0x001f))
{
*lpFourcc = BI_BITFIELDS;
DBG_MESSAGE(("Format: RGB 5:6:5"));
}
else if ((lpFormat->dwRGBBitCount == 16) &&
(lpFormat->dwRBitMask == 0x7C00) &&
(lpFormat->dwGBitMask == 0x03e0) &&
(lpFormat->dwBBitMask == 0x001f))
{
*lpFourcc = BI_RGB;
DBG_MESSAGE(("Format: RGB 5:5:5"));
}
else if (((lpFormat->dwRGBBitCount == 24) ||
(lpFormat->dwRGBBitCount == 32)) &&
(lpFormat->dwRBitMask == 0xff0000) &&
(lpFormat->dwGBitMask == 0x00ff00) &&
(lpFormat->dwBBitMask == 0x0000ff))
{
*lpFourcc = BI_RGB;
DBG_MESSAGE(("Format: RGB 8:8:8"));
}
else
{
*lpFourcc = (DWORD) -1;
}
*lpBitCount = lpFormat->dwRGBBitCount;
}
else if (DDPF_PALETTEINDEXED4 & lpFormat->dwFlags)
{
*lpFourcc = (DWORD)-1;
*lpBitCount = 4;
}
else if (DDPF_PALETTEINDEXED8 & lpFormat->dwFlags)
{
*lpFourcc = (DWORD)-1;
*lpBitCount = 8;
}
else if (lpFormat->dwRGBBitCount == 16)
{
*lpFourcc = BI_RGB;
*lpBitCount = lpFormat->dwRGBBitCount; // always 16 for now.
}
else
{
*lpFourcc = (DWORD) -1;
*lpBitCount = 0;
}
}
#endif // DRIVER_5465 && OVERLAY
#endif // ! ver 3.51