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