/************************************************************************** *************************************************************************** * * Copyright (c) 1997, Cirrus Logic, Inc. * All Rights Reserved * * FILE: 5465over.c * * DESCRIPTION: * * REVISION HISTORY: * * $Log: \\uinac\log\log\laguna\ddraw\src\5465over.c $ * * Rev 1.75 19 May 1998 09:54:36 xcong * Assign GfVdFormat in ChipIOReadBWRegs() for TV-Out support. * * Rev 1.74 07 Apr 1998 17:28:58 xcong * Get CR1 and CR1E in ChipIOBWRead() * * Rev 1.73 Mar 30 1998 13:06:52 frido * Changed some parenthesis so the Codewright source parser can find the * functions. * * Rev 1.72 08 Jan 1998 10:45:28 xcong * Don't pass lpDDHALData in ComputeVWPositionData() for NT. * * Rev 1.71 07 Jan 1998 17:55:32 xcong * Delete *lpDDHALData in SetPostion() for NT only. *  * * Rev 1.70 06 Jan 1998 14:43:54 xcong * Pass lpDDHALData in CurrentVLine(). * * Rev 1.69 06 Jan 1998 11:42:06 xcong * Change pDriverData into local lpDDHALData for multi-monitor support. * * Rev 1.68 Dec 11 1997 14:03:28 frido * PDR#11011: A workaround has been added to convert a "dummy" * update into a SHOW update when certain criteria are met. * * Rev 1.67 Dec 10 1997 13:41:32 frido * Merged from 1.62 branch. * * Rev 1.63.2.0 Dec 03 1997 14:44:54 frido * PDR#11017. The hardware is broken when shrinking videos horizontally with * RGB32 format. A software workaround has been added to disable overlay in * this case. * * Rev 1.66 Dec 10 1997 13:32:08 frido * Merged from 1.62 branch. * * Rev 1.65 14 Nov 1997 13:04:18 XCONG * Undo the modification for dwOverlayOffset for NT. * * Rev 1.64 06 Nov 1997 15:46:14 XCONG * When update dwOverlayOffset, update this variable for all the attached surf * too. * * Rev 1.63.2.0 Dec 03 1997 14:44:54 frido * PDR#11017. The hardware is broken when shrinking videos horizontally with * RGB32 format. A software workaround has been added to disable overlay in * this case. * * Rev 1.63 04 Nov 1997 13:41:34 RUSSL * Fix for PDR #10815 * * Rev 1.62 04 Nov 1997 12:57:02 RUSSL * Removed forcing of min stretch in 24bpp to start at 1000 (for new bweq code) * * Rev 1.61 30 Oct 1997 14:34:18 RUSSL * Mods to support new interface to bweqn code * Moved KillOverlay function here from 5465bw.c * ChipIOReadBWRegs reads additional regs that are new to the BWREGS struct * Added code in ChipIOReadBWRegs to clear bits 4 & 7 (the 256 byte fetch * related bits) of the BWREGS Control2 value. The bweqn should use * 256 byte fetch off values, since we are disabling 256 byte fetch * when overlay or videoport surfaces are created. * * Rev 1.60 08 Oct 1997 11:15:02 RUSSL * Fix for NT40 build without overlay support * * Rev 1.59 25 Sep 1997 17:33:40 RUSSL * Modified HeapAlloc calls to use HEAP_ALLOC macro * and HeapFree calls to use HEAP_FREE macro * * Rev 1.58 19 Sep 1997 14:35:04 bennyn * Fixed NT4.0 5462/64 build problem * * Rev 1.57 17 Sep 1997 16:27:20 RUSSL * Looks like setting the HardwareOwner is FlipOverlayStatus is an NT only * thing. * * Rev 1.56 16 Sep 1997 15:28:38 bennyn * Modified for NT DD overlay * * Rev 1.55 04 Sep 1997 09:43:26 RUSSL * Fixed up Xing's changes so they compile for NT * * Rev 1.54 04 Sep 1997 10:07:52 XCONG * Delete f256Fetch, since the code to disable 256 byte fetch is moved to * surface.c, nobody use this variable anymore. * * Rev 1.53 03 Sep 1997 18:40:12 XCONG * Disable overlay in 640*480*32 at 85Hz by calling KillOverlay(). * This is temporary fix for PDR#10381. * * Rev 1.52 03 Sep 1997 16:35:02 RUSSL * * Rev 1.51 02 Sep 1997 12:35:48 RUSSL * Added GET_SURFACE_DATA_PTR macro and modified relevant code to get ptr * using macro. This will minimize the remaining changes needed for NT. * * Rev 1.50 29 Aug 1997 16:47:26 RUSSL * Added support for NT * It's not quite complete, we need to allocate a LP_SURFACE_DATA structure * for each overlay surface and store it somewhere in the DD_SURFACE_LOCAL * structure (this needs to be done by CreateSurface). And then add code * in here to get access to that struct when necessary. #pragma message's * indicate where. * Removed code to disable 256 byte fetch, its done by CreateSurface32 * * Rev 1.49 15 Aug 1997 16:38:30 XCONG * Put overlay source alignment back to 1. This is screen alignment instead o * * Rev 1.48 14 Aug 1997 16:47:42 XCONG * If overlay window is created, disable 256 byte fetch. * Move gwNormalDTTR initialization into CreateSurface function. * * Rev 1.47 29 Jul 1997 15:29:14 XCONG * For autoflip overlay make sure dwNumAutoFlip == 2 * * Rev 1.46 28 Jul 1997 09:19:46 RUSSL * Modified GetOverlayFlipStatus to check arm bit in hw rather than determine * elapsed time since previous flip * Added video window index argument to GetOverlayFlipStatus function * Made dwNumVideoWindows a global var rather than static * Moved GetVideoWindowIndex inline function to overlay.h * * Rev 1.45 24 Jul 1997 17:50:14 RUSSL * modified src alignment values reported in ddhalinfo * fixed error with disabling dst colorkey at 24bpp, I was turning off * src colorkey related caps bits * * Rev 1.44 16 Jul 1997 17:15:32 XCONG * Add and use dwOverlayOffset and more in SURFACE_DATA structure in order * to eliminate global variables. * * Rev 1.43 14 Jul 1997 13:11:50 RUSSL * added ChipIOReadBWRegs (moved here from 5465bw.c) * * Rev 1.42 11 Jul 1997 11:57:26 XCONG * Fix ptich problem in FlipOverlay for interleaved surface. * * Rev 1.41 11 Jul 1997 08:57:02 RUSSL * Fixed y clipping of CLPL surfaces in FlipOverlaySurface and * ComputeVWPositionData * * Rev 1.40 09 Jul 1997 15:27:44 RUSSL * Implemented CLPL lobotomy mode * allocates a block of system memory for the app to write the UV data to, * when the app locks the surface the system memory addresses are returned * so the app writes to system memory, and when the app unlocks the surface, * the data is copied into the frame buffer. The copy is done from left to * right a scanline at a time. There appears to be a hw bug when writing * to aperture 3 from right to left. Roughly every other 4 dwords is * dropped. This bug showed up when allowing the Compcore MPEG player to * write directly to aperture 3. (also see comments in SysToFBCopy) * Added GetUserSettings to read user controllable options from registry * Current user controllable settings are: * OverlayBW - enables/disables use of bandwidth equation (default=enabled) * OverlayCLPL - enables/disables support for CLPL format (default=enabled) * OverlayCLPLLobotomyMode - enables/disables above described CLPL * lobotomy mode (default=enabled) * For forward compatibility, assume future chips have one video window * * Rev 1.39 30 Jun 1997 10:37:20 RUSSL * Added global var to control whether or not CLPL is supported * CLPL support is based on a registry key "OverlayCLPL", set to "on" to * enable CLPL, default is "off" * * Rev 1.38 23 Jun 1997 10:50:10 RUSSL * Modified for reduced size of CLPL surfaces * * Rev 1.37 20 Jun 1997 13:47:44 RUSSL * Enabled CLPL overlay surface support (aka YUV420 & YUVPLANAR) * Enabled 32 bit overlay surface support * Removed REQUIREs and HW_(UN)LOCK_SEMAPHOREs (they didn't do anything anyway) * CreateSurface now returns an HRESULT * * Rev 1.36 09 Jun 1997 13:46:22 XCONG * In FlipOverlaySurface(), Update VW_CONTROL0 too for DDFLIP_EVEN. * * Rev 1.35 03 Jun 1997 09:52:50 RUSSL * Added setting of VWEnable bit in CONTROL0 register in SetPosition and * FlipOverlaySurface functions * * Rev 1.34 22 May 1997 16:27:46 RUSSL * Disable overlay shrink at 24bpp * * Rev 1.33 15 May 1997 17:36:38 RUSSL * Set ddCaps.dwAlignStrideAlign to bytes per pixel in Init5465Overlay * Set bNoOverlayInThisMode to TRUE if in interlaced mode * * Rev 1.32 15 May 1997 15:48:20 XCONG * Change all the BWE flags back (in bw.h). * * Rev 1.31 15 May 1997 10:56:54 RUSSL * Changed IsFormatValid to return an HRESULT rather than a BOOL so * CanCreateSurface32 can return a reasonable error code if the surface * can't be created * * Rev 1.30 13 May 1997 09:53:04 RUSSL * Removed code in Init5465Info that was initializing the VW0_TEST0 register * * Rev 1.29 12 May 1997 17:22:32 XCONG * Change wVPortCreated in VideoPortEx into wNotify * * Rev 1.28 10 May 1997 12:51:02 EDWINW * Fix PDR 9574. DestroySurface trashes tile size when trying to restore the * DTTR's FIFO threshold. * * Rev 1.27 09 May 1997 16:26:36 XCONG * Only check VPE_ON and OVERLAY_ON flags in DX5 * * Rev 1.26 09 May 1997 11:10:22 XCONG * Uses the flags in overlay.h for BWE flags. Befor save and restore * gwNormIDTTR check VPE is still running or not, because VPE will do the same * thing. * * Rev 1.25 08 May 1997 17:57:40 XCONG * Make the BWE variables global. Set uDispDepth as the same as * sourc depth instead of graphic depth. * * Rev 1.24 24 Apr 1997 14:36:46 XCONG * For SW playback only use smooth-interlaced mode when BOB and INTERLEAVE * flags are both set. * * Rev 1.23 24 Apr 1997 12:02:54 RUSSL * Reenabled writing 0x52 to TEST0 reg on 5465AC if bw eqn is in use. * 800x600x16 @ 85Hz looks like it's running on the hairy edge of * stability with this. All other modes (at all resolutions, colordepths * and refresh rates) with sufficient bandwidth to use overlay looked * stable although there is still some static in some modes. * * Rev 1.22 17 Apr 1997 09:38:22 RUSSL * Fix for PDR #9339, disable destination colorkeying support at 24bpp. * This looks like its a HWBUG. This code can be disabled by defining * HWBUG_24BPP_DST_COLORKEY as zero. * Write DTTR FIFO value returned by ChipIsEnoughBandwidth, original DTTR * setting is saved in a global var which is restored when final overlay * surface is destroyed * * Rev 1.21 16 Apr 1997 10:19:28 RUSSL * Had to update list of parms passed to GetBooleanSetting * * Rev 1.20 15 Apr 1997 17:46:46 RUSSL * Added use of PDC's bandwidth equation * Added use of registry key/system.ini entry to disable use of BWEqn * Removed IsSufficientBandwidth functions * Modified Init5465Info to determine min & max zoom factors in current * mode by calling BWEqn * ComputeVWFifoThreshold sets VW fifo threshold to value returned previously * by bandwidth equation (or it uses 8 if use of BWEqn is disabled) * * Rev 1.19 04 Apr 1997 16:11:56 XCONG * Add support for SW double-buffer and BOB palyback. Change the way to * calculate VACCUM_STP for interleaved BOB. * * Rev 1.18 03 Apr 1997 09:58:42 RUSSL * Disable writing 0x42 or 0x52 to TEST0 reg, it's more grief than it's worth * Wait until we get a real bandwidth equation * Made IsFormatValid always return FALSE when we're in an interlaced mode, * this essentially disables use of overlay in interlaced modes * * Rev 1.17 28 Mar 1997 14:57:26 RUSSL * Need to write 0x42 to TEST0 in 24bpp modes * Display driver now puts 32bit linear address of pDevice in * pDriverData->lpPDevice, so don't need to call MapSLFix * * Rev 1.16 24 Mar 1997 22:54:58 XCONG * Add auto-flip overlay support. Include SSD_STRT_ADDR in tagVWDATA for * all the version of DDRAW. * * Rev 1.15 24 Mar 1997 16:44:56 RUSSL * Changed CreateSurface so that CreateSurface32 fills in the blocksize, etc. * * Rev 1.14 24 Mar 1997 12:12:40 RUSSL * Added write of 0x52 to TEST0 reg on 5465AC, this enables some hw fixes * * Rev 1.13 19 Mar 1997 11:47:40 cjl * Simply added line to include new ddshared.h file. * * Rev 1.12 12 Mar 1997 14:59:00 RUSSL * replaced a block of includes with include of precomp.h for * precompiled headers * Removed unneeded pragma message related to mapping in YUY2 aperture * * Rev 1.11 07 Mar 1997 12:43:22 RUSSL * Modified DDRAW_COMPAT usage * Merged in PDC's VPE code for DX5 * Made IsSufficientBandwidth5465 global rather than static * * Rev 1.10 24 Feb 1997 13:49:52 RUSSL * Enabled YUY2 format * Added RBGtoYCbCr function * Modified DetermineVWColorKeyData to handle source color keying of UYVY * and YUY2 surfaces * * Rev 1.9 14 Feb 1997 10:01:14 RUSSL * Added more conditional compilation flags to enable/disable horizontal * mirroring, use of REQUIRE for qfree checking and use of HW_IN_USE * driver semaphore. * If building debug version, change inline functions to not be inline. * WINICE can't deal with inline functions, so source code doesn't line * up correctly. * Added ASSERT to make sure post immediately bit is clear in TEST0 reg * before updating video window registers * Ignore DDOVER_DDFX flag in UpdateSurface because Microsoft's WHQL Overfly * test program sets this flag but fills overlayFX.dwDDFX with junk. * In some cases they set the DDOVERFX_MIRRORLEFTRIGHT bit even though * we don't even say we support that capability! In order to get Overfly * to work, we need to ignore the overlayFX.dwDDFX flags that we don't * support (which is currently all of them) This fixes BPR #8528 * * Rev 1.8 04 Feb 1997 14:15:48 RUSSL * Added check in IsFormatValid to see if VPM is using the hardware * Added SaveRectangles to reduce duplicate code in UpdateSurface * Adjusted zoom code calculation for x shrink so don't go past end of src * * Rev 1.7 31 Jan 1997 08:59:30 RUSSL * Added better video window support checking based on chip id in * Init5465Overlay * Adjusted init code alignment requirements reported to ddraw * Addressed most of pragma message statements * Fixed bug in FlipOverlaySurface when surface is clipped * Enabled overlay shrink caps and added shrink zoom code calculations * * Rev 1.6 29 Jan 1997 18:00:30 RUSSL * Added use of require macro before register writes * Modified zoom code calculations * * Rev 1.5 28 Jan 1997 17:34:58 RUSSL * VEND is the last line shown by the overlay * Karl and I figured out how to make source color key work (at least at 16bpp) * hopefully the code matches what we did manually. We need an app * that uses source color keying to really test it. * * Rev 1.4 28 Jan 1997 15:29:42 RUSSL * destination color keying is actually done using the hardware CLRKEY * registers and setting OCCLUDE in CONTROL0 to 1 (the documentation * appears to have the source color key settings & the destination color * key settings swapped) * source color keying doesn't appear to work * * Rev 1.3 27 Jan 1997 19:10:26 RUSSL * Use a variable dwNumVideoWindows rather than a hardcoded define * Added WaitForArmToClear, Set5465FlipDuration & PanOverlay1_Init * Made IsFormatValid return TRUE only for UYVY overlay surfaces for now * Made CreateSurface use rectangular allocation, specify block size for * rgb surfaces if we are managing surface creation, let CreateSurface * return NOTHANDLED so DDraw will fill in the surface ptr * Added error checking for dwReserved1 of local surface struct in case * it's NULL * Added additional debug output * Put code in ComputeVWZoomCodes, ComputeVWPosData, DetermineColorKeyData, * ComputeVWFifoThreshold * Added programming of the hw registers in RegInitVideoVW & RegMoveVideoVW * * Rev 1.2 21 Jan 1997 15:44:40 RUSSL * Okay this didn't compile and link last time * * Rev 1.1 21 Jan 1997 14:55:14 RUSSL * Port of 5480 overlay code from CirrusMM driver to 5465 * * Rev 1.0 15 Jan 1997 10:36:22 RUSSL * Initial revision. * *************************************************************************** ***************************************************************************/ /*************************************************************************** * I N C L U D E S ****************************************************************************/ #include "precomp.h" #if defined WINNT_VER35 // WINNT_VER35 // If WinNT 3.5 skip all the source code #elif defined (NTDRIVER_546x) // If WinNT 4.0 and 5462/64 build skip all the source code #elif defined(WINNT_VER40) && !defined(OVERLAY) // if nt40 without overlay, skip all the source code #else #ifndef WINNT_VER40 #include "ddshared.h" #include "flip.h" #include "surface.h" #include "blt.h" #include "overlay.h" #if DDRAW_COMPAT >= 50 #include "vp.h" #endif #include "settings.h" #include "5465bw.h" #include "swat.inc" #endif /*************************************************************************** * D E F I N E S ****************************************************************************/ #ifdef WINNT_VER40 #define ENABLE_YUY2 0 #define ENABLE_YUVPLANAR 0 #define DISABLE_MOST_MODES 0 #else #define ENABLE_YUY2 1 #define ENABLE_YUVPLANAR 1 #define DISABLE_MOST_MODES 0 #endif #define ENABLE_SD_RGB32 1 #define ENABLE_MIRRORING 0 #define HWBUG_24BPP_DST_COLORKEY 1 #ifdef DEBUG #define INLINE #else #define INLINE __inline #endif // VW_CAP0 bits #define VWCAP_VW_PRESENT 0x00000001 // VW_CONTROL1 bits #define VW_ByPassClrSpc 0x00000002 #define VW_YShrinkEn 0x00000001 // VW_CONTROL0 bits #define VW_XShrinkBy2 0x80000000 #define VW_ClkMode2x 0x40000000 #define VW_FIFO_THRSH_EN 0x20000000 #define VW_ALPHA_KEYCMP_EN 0x10000000 #define VW_DB_VPORT_ID_MASK 0x0F000000 #define VW_DB_VSM_ID_MASK 0x00F00000 #define VW_DB_CTL_MASK 0x000F0000 #define VW_SD_FRMT_MASK 0x0000FF00 #define VW_OCCLUDE_MASK 0x000000F0 #define VW_SMTH_INT 0x00000008 #define VW_HMIRR_EN 0x00000004 #define VW_VWE 0x00000002 #define VW_ARM 0x00000001 // Source Data Formats for SD_FRMT #define SD_YUV422 0x00 // ITU 601 compliant YUV data #define SD_YUV420 0x03 // ITU 601 compliant YUV data #define SD_YUV422_FS 0x04 // Full Scale YUV data #define SD_YVU420_FS 0x07 // Full Scale YUV data #define SD_RGB16_555 0x08 // 5:5:5 #define SD_RGB16_565 0x09 // 5:6:5 #define SD_RGB32 0x0B // ARGB #define SD_FRMT_SHIFT 8 // Occlude types for OCCLUDE #define NO_OCCLUSION 0 // video window always displayed #define COLOR_KEY 1 // destination color keying #define CHROMA_KEY 2 // source color keying #define OCCLUDE_SHIFT 4 // VW_TEST0 bits #define VW_PostImed 1 #define VWVRepEnable 0x4 // defines used in Init5465Info() #define SRC_WIDTH 160 #define SRC_HEIGHT 120 #define MAX_ZOOM 8000 #define MIN_ZOOM 500 #define ZOOM_STEP 100 #ifdef WINNT_VER40 #define lpDDHALData ((DRIVERDATA *)(&(ppdev->DriverData))) #define ASSERT(x) #define DRAW_ENGINE_BUSY DrawEngineBusy(lpDDHALData) #endif #ifdef WINNT_VER40 #define GET_SURFACE_DATA_PTR(lpSurface) (LP_SURFACE_DATA)((lpSurface)->dwReserved1) #else #define GET_SURFACE_DATA_PTR(lpSurface) (LP_SURFACE_DATA)((lpSurface)->dwReserved1) #endif #if ENABLE_256_BYTE_FETCH // bit defs for PERFORMANCE register #define ECO_256_BYTES_FIX_EN 0x4000 // bit defs for CONTROL2 register #define MONO_SAFETY_256 0x0080 #define BYTE_REQ_256 0x0010 #endif /*************************************************************************** * T Y P E D E F S ****************************************************************************/ typedef struct tagVWDATA { WORD HSTRT; WORD HSDSZ; WORD HEND; DWORD HACCUM_STP; DWORD HACCUM_SD; WORD VSTRT; WORD VEND; DWORD VACCUM_STP; DWORD VACCUM_SDA; DWORD VACCUM_SDB; DWORD PSD_STRT_ADDR; DWORD SSD_STRT_ADDR; #if ENABLE_YUVPLANAR DWORD PSD_UVSTRT_ADDR; DWORD SSD_UVSTRT_ADDR; #endif WORD SD_PITCH; DWORD CLRKEY_MIN; DWORD CLRKEY_MAX; DWORD CHRMKEY_MIN; DWORD CHRMKEY_MAX; // WORD BRIGHT_ADJ; // BYTE Z_ORDER; WORD FIFO_THRSH; DWORD CONTROL1; DWORD CONTROL0; // DWORD CAP1; // DWORD CAP0; // DWORD TEST0; } VWDATA; typedef struct tagUSERSETTINGS { BOOL *pVar; char *pRegKey; BOOL defaultVal; } USERSETTINGS; #if ENABLE_YUVPLANAR // structure for CLPL (YUV planar) surface typedef struct tagCLPLInfo { LPVOID fpYSurface; // Y data in first aperture LPVOID fpUSurface; // U data in 0-2M of fourth aperture LPVOID fpVSurface; // V data in 2-4M of fourth aperture // pointers for CLPLLobotomyMode LPVOID fpUSystemSurface; LPVOID fpVSystemSurface; LPVOID fpRealUSurface; // U data in 0-2M of fourth aperture LPVOID fpRealVSurface; // V data in 2-4M of fourth aperture } CLPLInfo; typedef CLPLInfo *LPCLPLSURFACE; #endif /*************************************************************************** * E X T E R N A L V A R I A B L E S ****************************************************************************/ #ifndef WINNT_VER40 #if DDRAW_COMPAT >= 50 extern WORD gwNotify; //#xc #endif #endif /*************************************************************************** * S T A T I C V A R I A B L E S ****************************************************************************/ #ifdef WINNT_VER40 // For NT these are in ppdev->DriverData #define bUseBWEqn ppdev->DriverData.bUseBWEqn #define bNoOverlayInThisMode ppdev->DriverData.bNoOverlayInThisMode #define lpHardwareOwner ppdev->DriverData.lpHardwareOwner #define lpColorSurfaceVW ppdev->DriverData.lpColorSurfaceVW #define lpSrcColorSurfaceVW ppdev->DriverData.lpSrcColorSurfaceVW #define grOverlaySrc ppdev->DriverData.grOverlaySrc #define grOverlayDest ppdev->DriverData.grOverlayDest #define gdwFourccVW ppdev->DriverData.gdwFourccVW #if ENABLE_MIRRORING #define bIsVWMirrored ppdev->DriverData.bIsVWMirrored #endif #define gdwAvailVW ppdev->DriverData.gdwAvailVW // Next available video window //#define gwZOrder ppdev->DriverData.gwZOrder // default primary on top. #define gdwColorKey ppdev->DriverData.gdwColorKey #define gdwSrcColorKeyLow ppdev->DriverData.gdwSrcColorKeyLow #define gdwSrcColorKeyHigh ppdev->DriverData.gdwSrcColorKeyHigh #define gdwDestColorKeyOwnerVW ppdev->DriverData.gdwDestColorKeyOwnerVW // DstColorKey owner (NULL or FLG_VWX) #define gdwSrcColorKeyOwnerVW ppdev->DriverData.gdwSrcColorKeyOwnerVW // SrcColorKey owner (NULL or FLG_VWX) #define giOvlyCnt ppdev->DriverData.giOvlyCnt #if ENABLE_YUVPLANAR // YUV Planar surfaces cannot exist #define giPlanarCnt ppdev->DriverData.giPlanarCnt // with other overlay surfaces #define bCLPLLobotomyMode ppdev->DriverData.bCLPLLobotomyMode #endif //#define gbDoubleClock ppdev->DriverData.gbDoubleClock #if DISABLE_MOST_MODES #define bDisableMostModes ppdev->DriverData.bDisableMostModes #endif #else // Win95 ASSERTFILE("5465over.c"); STATIC DIBENGINE *pPDevice; STATIC BOOL bUseBWEqn; STATIC BOOL bNoOverlayInThisMode; STATIC LPDDRAWI_DDRAWSURFACE_LCL lpHardwareOwner[MAX_VIDEO_WINDOWS]; STATIC LPDDRAWI_DDRAWSURFACE_LCL lpColorSurfaceVW[MAX_VIDEO_WINDOWS]; STATIC LPDDRAWI_DDRAWSURFACE_LCL lpSrcColorSurfaceVW[MAX_VIDEO_WINDOWS]; STATIC RECTL grOverlaySrc[MAX_VIDEO_WINDOWS]; STATIC RECTL grOverlayDest[MAX_VIDEO_WINDOWS]; STATIC DWORD gdwFourccVW[MAX_VIDEO_WINDOWS]; #if ENABLE_MIRRORING STATIC BOOL bIsVWMirrored[MAX_VIDEO_WINDOWS]; #endif STATIC DWORD gdwAvailVW; // Next available video window //STATIC WORD gwZOrder = OVERLAYZ_PRIMARY_ON_TOP; // default primary on top. STATIC DWORD gdwColorKey; STATIC DWORD gdwSrcColorKeyLow; STATIC DWORD gdwSrcColorKeyHigh; STATIC DWORD gdwDestColorKeyOwnerVW = 0; // DstColorKey owner (NULL or FLG_VWX) STATIC DWORD gdwSrcColorKeyOwnerVW = 0; // SrcColorKey owner (NULL or FLG_VWX) STATIC int giOvlyCnt[MAX_VIDEO_WINDOWS]; #if ENABLE_YUVPLANAR // YUV Planar surfaces cannot exist STATIC int giPlanarCnt = 0; // with other overlay surfaces STATIC BOOL bCLPLLobotomyMode; #endif //STATIC BOOL gbDoubleClock; #if DISABLE_MOST_MODES STATIC BOOL bDisableMostModes; #endif #endif /*************************************************************************** * G L O B A L V A R I A B L E S ****************************************************************************/ #ifdef WINNT_VER40 // For NT these are in ppdev->DriverData #define gsOverlayFlip ppdev->DriverData.gsOverlayFlip #define gsProgRegs ppdev->DriverData.gsProgRegs #define gvidConfig ppdev->DriverData.gvidConfig #define gwNormalDTTR ppdev->DriverData.gwNormalDTTR #define dwNumVideoWindows ppdev->DriverData.dwNumVideoWindows #if ENABLE_YUVPLANAR #define bEnableCLPL ppdev->DriverData.bEnableCLPL #endif #else OVERLAYFLIPRECORD gsOverlayFlip; PROGREGS gsProgRegs = {0}; //Make them global so VPE can use the same ones VIDCONFIG gvidConfig = {0}; WORD gwNormalDTTR; DWORD dwNumVideoWindows; #if ENABLE_YUVPLANAR BOOL bEnableCLPL; #endif #endif /*************************************************************************** * S T A T I C F U N C T I O N P R O T O T Y P E S ****************************************************************************/ #ifdef WINNT_VER40 static void GetUserSettings ( PDEV * ); STATIC HRESULT IsFormatValid ( PDEV*, DWORD, DWORD ); STATIC HRESULT CreateOverlaySurface ( PDEV*, PDD_SURFACE_LOCAL, DWORD ); STATIC VOID DestroyOverlaySurface( PDEV*, PDD_DESTROYSURFACEDATA ); STATIC DWORD FlipOverlaySurface ( PDEV*, PDD_FLIPDATA ); STATIC DWORD LockSurface ( PDEV*, PDD_LOCKDATA ); STATIC VOID UnlockSurface ( PDEV*, PDD_UNLOCKDATA ); STATIC VOID SetColorKey ( PDEV*, PDD_SETCOLORKEYDATA ); STATIC DWORD UpdateSurface ( PDEV*, PDD_UPDATEOVERLAYDATA ); STATIC DWORD SetPosition ( PDEV*, PDD_SETOVERLAYPOSITIONDATA ); STATIC DWORD GetOverlayFlipStatus ( PDEV*, FLATPTR, DWORD ); STATIC BOOL RegInitVideoVW ( PDEV*, DWORD, PDD_SURFACE_LOCAL ); STATIC VOID RegMoveVideoVW ( PDEV*, DWORD, PDD_SURFACE_LOCAL ); #else static void GetUserSettings ( void ); STATIC HRESULT IsFormatValid ( LPGLOBALDATA, DWORD, DWORD ); STATIC HRESULT CreateSurface ( LPDDRAWI_DDRAWSURFACE_LCL, DWORD,LPGLOBALDATA ); STATIC VOID DestroySurface ( LPDDHAL_DESTROYSURFACEDATA ); STATIC DWORD FlipOverlaySurface ( LPDDHAL_FLIPDATA ); STATIC DWORD LockSurface ( LPDDHAL_LOCKDATA ); STATIC VOID UnlockSurface ( LPDDHAL_UNLOCKDATA ); STATIC VOID SetColorKey ( LPDDHAL_SETCOLORKEYDATA); STATIC DWORD UpdateSurface ( LPDDHAL_UPDATEOVERLAYDATA ); STATIC DWORD SetPosition ( LPDDHAL_SETOVERLAYPOSITIONDATA ); STATIC DWORD GetOverlayFlipStatus (LPGLOBALDATA, FLATPTR, DWORD ); STATIC BOOL RegInitVideoVW ( DWORD, LPDDRAWI_DDRAWSURFACE_LCL,LPGLOBALDATA ); STATIC VOID RegMoveVideoVW ( DWORD, LPDDRAWI_DDRAWSURFACE_LCL,LPGLOBALDATA ); #endif /*************************************************************************** * E X T E R N A L F U N C T I O N P R O T O T Y P E S ****************************************************************************/ #if WINNT_VER40 extern int CurrentVLine (PDEV *); extern VOID GetFormatInfo (LPDDPIXELFORMAT, LPDWORD, LPDWORD); #endif #ifdef USE_OLD_BWEQ extern BOOL KillOverlay ( #ifdef WINNT_VER40 PDEV *ppdev, #endif WORD wScreenX, UINT uScreenDepth ); //fix PDR#10381 #endif BOOL ChipIOReadBWRegs ( #ifdef WINNT_VER40 PDEV *ppdev, #else LPGLOBALDATA lpDDHALData, #endif LPBWREGS pBWRegs ); /*************************************************************************** * * FUNCTION: MakeVideoWindowFlag * * DESCRIPTION: * ****************************************************************************/ static INLINE DWORD MakeVideoWindowFlag ( DWORD dwVWIndex ) { ASSERT(dwNumVideoWindows > dwVWIndex); return ((1 << dwVWIndex) << FLG_VW_SHIFT); } #if 0 /*************************************************************************** * * FUNCTION: GetDoubleClockStatus * * DESCRIPTION: * ****************************************************************************/ static INLINE DWORD GetDoubleClockStatus ( VOID ) { #pragma message("GetDoubleClockStatus not implemented!") return FALSE; } #endif /*************************************************************************** * * FUNCTION: GetDDHALContext * * DESCRIPTION: * Get shared data structure (SDATA) pointer ****************************************************************************/ #ifndef WINNT_VER40 INLINE LPGLOBALDATA GetDDHALContext( LPDDRAWI_DIRECTDRAW_GBL lpGb ) { #if (DDRAW_COMPAT >= 50) if(lpGb->dwReserved3) //the SDATA pointer is passed by dwReserved3 //for DX50 return (LPGLOBALDATA)lpGb->dwReserved3; else #endif return pDriverData; } #endif /*************************************************************************** * * FUNCTION: IsHardwareInUseVW * * DESCRIPTION: * ****************************************************************************/ static INLINE BOOL IsVWHardwareInUse ( #ifdef WINNT_VER40 PDEV *ppdev, #else LPGLOBALDATA lpDDHALData, #endif DWORD dwVWIndex ) { ASSERT(dwNumVideoWindows > dwVWIndex); if (VW_VWE & ((PVGAR)lpDDHALData->RegsAddress)->VideoWindow[dwVWIndex].grVW_CONTROL0) return TRUE; return FALSE; } /*************************************************************************** * * FUNCTION: WaitForArmToClear * * DESCRIPTION: * ****************************************************************************/ static INLINE VOID WaitForVWArmToClear ( #ifdef WINNT_VER40 PDEV *ppdev, #else LPGLOBALDATA lpDDHALData, #endif DWORD dwVWIndex ) { // wait for previous register writes to post // the hardware clears the ARM bit at that time ASSERT(dwNumVideoWindows > dwVWIndex); while (((PVGAR)lpDDHALData->RegsAddress)->VideoWindow[dwVWIndex].grVW_CONTROL0 & VW_ARM) ; } /*************************************************************************** * * FUNCTION: EnableOverlay * * DESCRIPTION: * ****************************************************************************/ static INLINE VOID EnableOverlay ( #ifdef WINNT_VER40 PDEV *ppdev, #else LPGLOBALDATA lpDDHALData, #endif DWORD dwVWIndex ) { ASSERT(dwNumVideoWindows > dwVWIndex); #ifdef WINNT_VER40 WaitForVWArmToClear(ppdev,dwVWIndex); #else WaitForVWArmToClear(lpDDHALData,dwVWIndex); #endif ((PVGAR)lpDDHALData->RegsAddress)->VideoWindow[dwVWIndex].grVW_CONTROL0 |= (VW_VWE | VW_ARM); } /*************************************************************************** * * FUNCTION: DisableOverlay * * DESCRIPTION: * ****************************************************************************/ static INLINE VOID DisableOverlay ( #ifdef WINNT_VER40 PDEV *ppdev, #else LPGLOBALDATA lpDDHALData, #endif DWORD dwVWIndex ) { ASSERT(dwNumVideoWindows > dwVWIndex); #ifdef WINNT_VER40 WaitForVWArmToClear(ppdev,dwVWIndex); #else WaitForVWArmToClear(lpDDHALData,dwVWIndex); #endif ((PVGAR)lpDDHALData->RegsAddress)->VideoWindow[dwVWIndex].grVW_CONTROL0 &= ~(VW_FIFO_THRSH_EN | VW_VWE); ((PVGAR)lpDDHALData->RegsAddress)->VideoWindow[dwVWIndex].grVW_CONTROL0 |= VW_ARM; } /*************************************************************************** * * FUNCTION: Set5465FlipDuration * * DESCRIPTION: * ****************************************************************************/ VOID Set5465FlipDuration ( #ifdef WINNT_VER40 PDEV *ppdev, #endif DWORD dwFlipDuration ) { gsOverlayFlip.dwFlipDuration = dwFlipDuration; } /*************************************************************************** * * FUNCTION: GetUserSettings * * DESCRIPTION: * ****************************************************************************/ VOID GetUserSettings ( #ifdef WINNT_VER40 PDEV *ppdev #else VOID #endif ) { #ifdef WINNT_VER40 #pragma message("GetUserSettings: Where are laguna settings stored in the NT registry?") bUseBWEqn = TRUE; #if ENABLE_YUVPLANAR bEnableCLPL = TRUE; bCLPLLobotomyMode = TRUE; #endif #else // else Win95 static const USERSETTINGS UserSettings[] = { { &bUseBWEqn, "OverlayBW", TRUE }, #if ENABLE_YUVPLANAR { &bEnableCLPL, "OverlayCLPL", TRUE }, { &bCLPLLobotomyMode, "OverlayCLPLLobotomyMode", TRUE }, #endif #if DISABLE_MOST_MODES { &bDisableMostModes, "OverlayBWHack", TRUE }, #endif }; const USERSETTINGS *pUserSetting; for (pUserSetting = &UserSettings[0]; pUserSetting < &UserSettings[sizeof(UserSettings)/sizeof(UserSettings[0])]; pUserSetting++) { *(pUserSetting->pVar) = pUserSetting->defaultVal; GetBooleanSetting(pUserSetting->pRegKey, pUserSetting->pVar, LOCATION_OF_3D_PERFORMANCE); } #endif } /*************************************************************************** * * FUNCTION: Init5465Overlay * * DESCRIPTION: * ****************************************************************************/ VOID Init5465Overlay ( #ifdef WINNT_VER40 PDEV *ppdev, DWORD dwChipType, PDD_HALINFO pDDHALInfo, LPOVERLAYTABLE pOverlayTable #else DWORD dwChipType, LPDDHALINFO pDDHALInfo, LPOVERLAYTABLE pOverlayTable, LPGLOBALDATA lpDDHALData #endif ) { DWORD dwNumFourCCs; #ifdef WINNT_VER40 GetUserSettings(ppdev); #else GetUserSettings(); #endif if (! bUseBWEqn) gsProgRegs.VW0_FIFO_THRSH = 8; // We should check the capabilities register on the chip // but it's busted #ifdef WINNT_VER40 if (CL_GD5465 == dwChipType) #else if (GD5465_PCI_DEVICE_ID == dwChipType) #endif dwNumVideoWindows = 1; else { #if 1 dwNumVideoWindows = 1; #else int i; PVGAR pREG = (PVGAR)lpDDHALData->RegsAddress; dwNumVideoWindows = 0; for (i = 0; i < MAX_VIDEO_WINDOWS; i++) { if (VWCAP_VW_PRESENT & pREG->VideoWindow[i].grVW_CAP0) dwNumVideoWindows++; } #endif } #ifdef WINNT_VER40 if (NULL != pDDHALInfo) #endif { pDDHALInfo->ddCaps.dwMaxVisibleOverlays = dwNumVideoWindows; pDDHALInfo->ddCaps.dwCurrVisibleOverlays = 0; #ifndef WINNT_VER40 pPDevice = (DIBENGINE *)lpDDHALData->lpPDevice; #endif // Fill in the caps pDDHALInfo->ddCaps.dwCaps |= DDCAPS_OVERLAY | DDCAPS_OVERLAYFOURCC | DDCAPS_OVERLAYSTRETCH | DDCAPS_ALIGNSTRIDE | DDCAPS_OVERLAYCANTCLIP ; pDDHALInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_OVERLAY ; pDDHALInfo->ddCaps.dwFXCaps |= DDFXCAPS_OVERLAYARITHSTRETCHY | DDFXCAPS_OVERLAYSTRETCHX | DDFXCAPS_OVERLAYSTRETCHY | DDFXCAPS_OVERLAYSHRINKX | DDFXCAPS_OVERLAYSHRINKY #if ENABLE_MIRRORING | DDFXCAPS_OVERLAYMIRRORLEFTRIGHT #endif ; } /* FOURCCs supported */ #if (MAX_FOURCCS < 3) #error dwFourCC array too small #endif dwNumFourCCs = 0; lpDDHALData->dwFourCC[dwNumFourCCs++] = FOURCC_UYVY; #if ENABLE_YUY2 lpDDHALData->dwFourCC[dwNumFourCCs++] = FOURCC_YUY2; #endif #if ENABLE_YUVPLANAR // add CLPL fourcc if registry key set to "on" if (bEnableCLPL) lpDDHALData->dwFourCC[dwNumFourCCs++] = FOURCC_YUVPLANAR; #endif #ifdef WINNT_VER40 if (NULL != pDDHALInfo) #endif { pDDHALInfo->ddCaps.dwNumFourCCCodes = dwNumFourCCs; // say we can handle byte alignment and any byte width pDDHALInfo->ddCaps.dwAlignBoundarySrc = 1; // src rect x byte alignment pDDHALInfo->ddCaps.dwAlignSizeSrc = 1; // src rect x byte size pDDHALInfo->ddCaps.dwAlignBoundaryDest = 1; // dst rect x byte alignment pDDHALInfo->ddCaps.dwAlignSizeDest = 1; // dst rect x byte size // stride alignment #ifdef WINNT_VER40 pDDHALInfo->ddCaps.dwAlignStrideAlign = ppdev->cxMemory; #else pDDHALInfo->ddCaps.dwAlignStrideAlign = pPDevice->deWidthBytes; #endif pDDHALInfo->ddCaps.dwMinOverlayStretch = 500; // min stretch is 0.5:1 pDDHALInfo->ddCaps.dwMaxOverlayStretch = 8000; // max stretch is 8:1 #ifdef WINNT_VER40 ppdev->DriverData.dwMinOverlayStretch = 500; ppdev->DriverData.dwMaxOverlayStretch = 8000; #endif pDDHALInfo->vmiData.dwOverlayAlign = 8 * 8; // qword alignment in bits } // Initialize OverlayTable function pointers pOverlayTable->pfnCanCreateSurface = IsFormatValid; #ifdef WINNT_VER40 pOverlayTable->pfnCreateSurface = CreateOverlaySurface; pOverlayTable->pfnDestroySurface = DestroyOverlaySurface; #else pOverlayTable->pfnCreateSurface = CreateSurface; pOverlayTable->pfnDestroySurface = DestroySurface; #endif pOverlayTable->pfnLock = LockSurface; pOverlayTable->pfnUnlock = UnlockSurface; pOverlayTable->pfnSetColorKey = SetColorKey; pOverlayTable->pfnFlip = FlipOverlaySurface; pOverlayTable->pfnUpdateOverlay = UpdateSurface; pOverlayTable->pfnSetOverlayPos = SetPosition; pOverlayTable->pfnGetFlipStatus = GetOverlayFlipStatus; // do mode specific initialization #ifdef WINNT_VER40 if (NULL != pDDHALInfo) Init5465Info(ppdev, pDDHALInfo); #else Init5465Info(pDDHALInfo, lpDDHALData); #endif } /*************************************************************************** * * FUNCTION: Init5465Info * * DESCRIPTION: * ****************************************************************************/ VOID Init5465Info ( #ifdef WINNT_VER40 PDEV *ppdev, PDD_HALINFO pDDHALInfo #else LPDDHALINFO pDDHALInfo, LPGLOBALDATA lpDDHALData #endif ) { // assume we can use overlay in this mode bNoOverlayInThisMode = FALSE; if (! bUseBWEqn) gsProgRegs.DispThrsTiming = ((PVGAR)lpDDHALData->RegsAddress)->grDisplay_Threshold_and_Tiling & 0x3F; // Are we double clocked? // gbDoubleClock = GetDoubleClockStatus(); // re-init these on mode change, we might tweak them below pDDHALInfo->ddCaps.dwAlignBoundaryDest = 1; pDDHALInfo->ddCaps.dwAlignSizeDest = 1; pDDHALInfo->ddCaps.dwMinOverlayStretch = 500; pDDHALInfo->ddCaps.dwMaxOverlayStretch = 8000; #ifdef WINNT_VER40 ppdev->DriverData.dwMinOverlayStretch = 500; ppdev->DriverData.dwMaxOverlayStretch = 8000; #endif // tell ddraw we can do colorkeying // we might undo this below pDDHALInfo->ddCaps.dwCKeyCaps |= DDCKEYCAPS_DESTOVERLAY | DDCKEYCAPS_DESTOVERLAYYUV | DDCKEYCAPS_DESTOVERLAYONEACTIVE | DDCKEYCAPS_SRCOVERLAY | DDCKEYCAPS_SRCOVERLAYYUV | DDCKEYCAPS_SRCOVERLAYONEACTIVE | DDCKEYCAPS_SRCOVERLAYCLRSPACE | DDCKEYCAPS_SRCOVERLAYCLRSPACEYUV ; if (bUseBWEqn) { DWORD dwZoom; VIDCONFIG vidConfig; BWREGS bwregs; // initialize vidConfig memset(&vidConfig, 0, sizeof(vidConfig)); vidConfig.uSrcDepth = 16; #ifdef WINNT_VER40 vidConfig.uDispDepth = ppdev->ulBitCount; vidConfig.uGfxDepth = ppdev->ulBitCount; #else vidConfig.uDispDepth = pPDevice->deBitsPixel; vidConfig.uGfxDepth = pPDevice->deBitsPixel; #endif vidConfig.dwFlags = VCFLG_COLORKEY | VCFLG_DISP; vidConfig.sizSrc.cx = SRC_WIDTH; vidConfig.sizSrc.cy = SRC_HEIGHT; if(gvidConfig.dwFlags & VCFLG_CAP) { //if video port is on, includes it for BWE vidConfig.dwFlags |= VCFLG_CAP; vidConfig.sizXfer = gvidConfig.sizXfer; vidConfig.sizCap = gvidConfig.sizCap; vidConfig.sizXfer = gvidConfig.sizXfer; vidConfig.dwXferRate = gvidConfig.dwXferRate; vidConfig.uXferDepth = gvidConfig.uXferDepth; vidConfig.uCapDepth = gvidConfig.uCapDepth; vidConfig.uSrcDepth = gvidConfig.uSrcDepth; } #ifdef WINNT_VER40 ChipIOReadBWRegs(ppdev, &bwregs); #else ChipIOReadBWRegs(lpDDHALData, &bwregs); #endif #ifdef USE_OLD_BWEQ //Kill overlay for some modes #ifdef WINNT_VER40 if(KillOverlay(ppdev, (WORD)ppdev->cxScreen, (UINT)ppdev->ulBitCount)) #else if(KillOverlay( pPDevice->deWidth,pPDevice->deBitsPixel)) #endif bNoOverlayInThisMode = TRUE; else #endif { // stupid linear search for min & max zoom factors // Check bandwidth to find the maximum zoom factor of 16 bit data // with colorkey dwZoom = MAX_ZOOM; do { vidConfig.sizDisp.cx = (SRC_WIDTH * dwZoom) / 1000; vidConfig.sizDisp.cy = (SRC_HEIGHT * dwZoom) / 1000; if (ChipIsEnoughBandwidth(&gsProgRegs, &vidConfig, &bwregs)) { #ifndef WINNT_VER40 DBG_MESSAGE(("Maximum zoom factor: %d", dwZoom)); #endif pDDHALInfo->ddCaps.dwMaxOverlayStretch = dwZoom; #ifdef WINNT_VER40 ppdev->DriverData.dwMaxOverlayStretch = dwZoom; #endif break; } dwZoom -= ZOOM_STEP; } while (dwZoom > 4000); if (dwZoom != pDDHALInfo->ddCaps.dwMaxOverlayStretch) bNoOverlayInThisMode = TRUE; // Check bandwidth to find the minimum zoom factor of 16 bit data // with colorkey dwZoom = MIN_ZOOM; #ifdef USE_OLD_BWEQ // disable overlay shrink in 24bpp modes #ifdef WINNT_VER40 if (24 == ppdev->ulBitCount) #else if (24 == pPDevice->deBitsPixel) #endif dwZoom = 1000; #endif do { vidConfig.sizDisp.cx = (SRC_WIDTH * dwZoom) / 1000; vidConfig.sizDisp.cy = (SRC_HEIGHT * dwZoom) / 1000; if (ChipIsEnoughBandwidth(&gsProgRegs, &vidConfig, &bwregs)) { #ifndef WINNT_VER40 DBG_MESSAGE(("Minimum zoom factor: %d", dwZoom)); #endif pDDHALInfo->ddCaps.dwMinOverlayStretch = dwZoom; #ifdef WINNT_VER40 ppdev->DriverData.dwMinOverlayStretch = dwZoom; #endif break; } dwZoom += ZOOM_STEP; } while (dwZoom < 4000); if (dwZoom != pDDHALInfo->ddCaps.dwMinOverlayStretch) bNoOverlayInThisMode = TRUE; } // I'll leave this code in here but so far I have only seen that if // we don't have enough bandwidth to use overlay with colorkey then // we don't have enough bandwidth period // try to see if there's enough bandwidth to use overlay without colorkey if (TRUE == bNoOverlayInThisMode) { // reset this in case we find enough bandwidth to use overlay // without colorkey bNoOverlayInThisMode = FALSE; // retry without colorkey available // tell ddraw we don't do colorkeying pDDHALInfo->ddCaps.dwCKeyCaps &= ~(DDCKEYCAPS_DESTOVERLAY | DDCKEYCAPS_DESTOVERLAYYUV | DDCKEYCAPS_DESTOVERLAYONEACTIVE | DDCKEYCAPS_SRCOVERLAY | DDCKEYCAPS_SRCOVERLAYYUV | DDCKEYCAPS_SRCOVERLAYONEACTIVE | DDCKEYCAPS_SRCOVERLAYCLRSPACE | DDCKEYCAPS_SRCOVERLAYCLRSPACEYUV) ; #ifdef USE_OLD_BWEQ #ifdef WINNT_VER40 if(KillOverlay(ppdev, (WORD)ppdev->cxScreen, (UINT)ppdev->ulBitCount)) #else if(KillOverlay( pPDevice->deWidth,pPDevice->deBitsPixel)) #endif bNoOverlayInThisMode = TRUE; else #endif { // Check bandwidth to find the maximum zoom factor of 16 bit data dwZoom = MAX_ZOOM; do { vidConfig.sizDisp.cx = (SRC_WIDTH * dwZoom) / 1000; vidConfig.sizDisp.cy = (SRC_HEIGHT * dwZoom) / 1000; if (ChipIsEnoughBandwidth(&gsProgRegs, &vidConfig, &bwregs)) { #ifndef WINNT_VER40 DBG_MESSAGE(("Maximum zoom factor: %d", dwZoom)); #endif pDDHALInfo->ddCaps.dwMaxOverlayStretch = dwZoom; #ifdef WINNT_VER40 ppdev->DriverData.dwMaxOverlayStretch = dwZoom; #endif break; } dwZoom -= ZOOM_STEP; } while (dwZoom > 4000); if (dwZoom != pDDHALInfo->ddCaps.dwMaxOverlayStretch) bNoOverlayInThisMode = TRUE; // Check bandwidth to find the minimum zoom factor of 16 bit data dwZoom = MIN_ZOOM; // disable overlay shrink in 24bpp modes #ifdef WINNT_VER40 if (24 == ppdev->ulBitCount) #else if (24 == pPDevice->deBitsPixel) #endif dwZoom = 1000; do { vidConfig.sizDisp.cx = (SRC_WIDTH * dwZoom) / 1000; vidConfig.sizDisp.cy = (SRC_HEIGHT * dwZoom) / 1000; if (ChipIsEnoughBandwidth(&gsProgRegs, &vidConfig, &bwregs)) { #ifndef WINNT_VER40 DBG_MESSAGE(("Minimum zoom factor: %d", dwZoom)); #endif pDDHALInfo->ddCaps.dwMinOverlayStretch = dwZoom; #ifdef WINNT_VER40 ppdev->DriverData.dwMinOverlayStretch = dwZoom; #endif break; } dwZoom += ZOOM_STEP; } while (dwZoom < 4000); if (dwZoom != pDDHALInfo->ddCaps.dwMinOverlayStretch) bNoOverlayInThisMode = TRUE; } #ifdef DEBUG if (bNoOverlayInThisMode) { ERRORLOG((" overlay disabled in %ldx%ldx%ld", (DWORD)pPDevice->deWidth, (DWORD)pPDevice->deHeight, (DWORD)pPDevice->deBitsPixel)); } else { ERRORLOG((" overlay colorkey not supported in %ldx%ldx%ld", (DWORD)pPDevice->deWidth, (DWORD)pPDevice->deHeight, (DWORD)pPDevice->deBitsPixel)); } #endif } // see if we're in interlaced mode, if so disable overlay if (1 & ((PVGAR)lpDDHALData->RegsAddress)->grCR1A) bNoOverlayInThisMode = TRUE; #if DISABLE_MOST_MODES if (bDisableMostModes) { PVGAR pREG = (PVGAR)lpDDHALData->RegsAddress; // disable overlay support for 1024x768 and above if ((1024 <= pPDevice->deWidth) && ( 768 <= pPDevice->deHeight)) bNoOverlayInThisMode = TRUE; // disable overlay support for 640x480x32@85Hz if ((640 == pPDevice->deWidth) && (480 == pPDevice->deHeight) && ( 32 == pPDevice->deBitsPixel) && (0x33 == pREG->grSRE) && (0x7E == pREG->grSR1E)) bNoOverlayInThisMode = TRUE; // disable overlay support for 800x600x32@85Hz if ((800 == pPDevice->deWidth) && (600 == pPDevice->deHeight) && ( 32 == pPDevice->deBitsPixel) && (0x1C == pREG->grSRE) && (0x37 == pREG->grSR1E)) bNoOverlayInThisMode = TRUE; } #endif #if 0 // TDDRAW.EXE error return from UpdateOverlay in to following cases if (ppdev->ulBitCount == 8 && ppdev->cxScreen == 1280) { if ( (ppdev->cyScreen == 1024 && ppdev->ulFreq >= 72) || (ppdev->cyScreen == 960 && ppdev->ulFreq >= 85) ) bNoOverlayInThisMode = TRUE; } if ( ppdev->cxScreen == 640 && ppdev->cyScreen == 350 ) bNoOverlayInThisMode = TRUE; #endif// 0 // if no overlay in this mode set min & max overlay stretch to 0 if (TRUE == bNoOverlayInThisMode) { pDDHALInfo->ddCaps.dwMinOverlayStretch = 0; pDDHALInfo->ddCaps.dwMaxOverlayStretch = 0; #ifdef WINNT_VER40 ppdev->DriverData.dwMinOverlayStretch = 0; ppdev->DriverData.dwMaxOverlayStretch = 0; #endif } } #if HWBUG_24BPP_DST_COLORKEY #ifdef WINNT_VER40 if (24 == ppdev->ulBitCount) #else if (24 == pPDevice->deBitsPixel) #endif { // disable destination colorkey support at 24bpp // the hardware appears to be busted pDDHALInfo->ddCaps.dwCKeyCaps &= ~( DDCKEYCAPS_DESTOVERLAY | DDCKEYCAPS_DESTOVERLAYYUV | DDCKEYCAPS_DESTOVERLAYONEACTIVE); } #endif #if 0 // When double clocking (i.e. 1280x1024), the minimum // zoom is 2X. if ((gbDoubleClock) && (pDDHALInfo->ddCaps.dwMinOverlayStretch < 2000)) { pDDHALInfo->ddCaps.dwMinOverlayStretch = 2000; } // don't use overlay in the 1X case. if (pDDHALInfo->ddCaps.dwMinOverlayStretch < 1500) { pDDHALInfo->ddCaps.dwMinOverlayStretch = 1500; } // Specify destination requirements. if ((BITSPERPIXEL == 24) || gbDoubleClock) { pDDHALInfo->ddCaps.dwCaps |= DDCAPS_ALIGNBOUNDARYDEST | DDCAPS_ALIGNSIZEDEST ; pDDHALInfo->ddCaps.dwAlignBoundaryDest = 4; pDDHALInfo->ddCaps.dwAlignSizeDest = 4; } #endif } /*************************************************************************** * * FUNCTION: IsFormatValid * * DESCRIPTION: This function verifies that the overlay hardware can * support the specified format. * ****************************************************************************/ STATIC HRESULT IsFormatValid ( #ifdef WINNT_VER40 PDEV *ppdev, #else LPGLOBALDATA lpDDHALData, #endif DWORD dwFourcc, DWORD dwBitCount ) { DWORD i; #ifndef WINNT_VER40 DBG_MESSAGE(("IsFormatValid (dwFourcc = 0x%08lX, dwBitCount = 0x%08lX)", dwFourcc, dwBitCount)); #endif // see if we're in interlaced mode // if so then don't allow overlay surface to be created // also if there isn't enough bandwidth then fail all // overlay surface CanCreate requests if (bNoOverlayInThisMode || (1 & ((PVGAR)lpDDHALData->RegsAddress)->grCR1A)) return DDERR_CURRENTLYNOTAVAIL; for (i = 0; i < dwNumVideoWindows; i++) { // see if ddraw thinks the video window is available // and make sure VPM isn't using it if ((0 == giOvlyCnt[i]) && #ifdef WINNT_VER40 (! IsVWHardwareInUse(ppdev,i)) #else (! IsVWHardwareInUse(lpDDHALData,i)) #endif ) { #ifndef WINNT_VER40 DBG_MESSAGE(("Video Window %d available", i)); #endif // I'll say YUCK again! // I hate this, what if VPM sneaks in between a CanCreateSurface // call and a CreateSurface call and grabs this video window // Guess we'll just say the creation succeeded but then fail all use // of the video window gdwAvailVW = MakeVideoWindowFlag(i); break; } } if (dwNumVideoWindows == i) { DBG_MESSAGE(("All video windows in use, returning FALSE")); return DDERR_CURRENTLYNOTAVAIL; } // only support 5:5:5, 5:6:5 and UYVY overlay surfaces if ( ((dwFourcc != BI_RGB) || (dwBitCount != 16)) #if ENABLE_SD_RGB32 && ((dwFourcc != BI_RGB) || (dwBitCount != 32)) #endif && (dwFourcc != BI_BITFIELDS) && (dwFourcc != FOURCC_UYVY) #if ENABLE_YUY2 && (dwFourcc != FOURCC_YUY2) #endif #if ENABLE_YUVPLANAR && (dwFourcc != FOURCC_YUVPLANAR) #endif ) { #ifndef WINNT_VER40 DBG_MESSAGE(("IsFormatValid5465: returning FALSE, FourCC = %08lX", dwFourcc)); #endif return DDERR_INVALIDPIXELFORMAT; } #ifndef WINNT_VER40 DBG_MESSAGE(("IsFormatValid5465: returning TRUE, FourCC = %08lX", dwFourcc)); #endif return DD_OK; } /*************************************************************************** * * FUNCTION: CreateSurface * * DESCRIPTION: This function sets various flags depending on what * is happening. * ****************************************************************************/ #ifdef WINNT_VER40 STATIC HRESULT CreateOverlaySurface( #else STATIC HRESULT CreateSurface( #endif #ifdef WINNT_VER40 PDEV *ppdev, PDD_SURFACE_LOCAL lpSurface, DWORD dwFourcc #else LPDDRAWI_DDRAWSURFACE_LCL lpSurface, DWORD dwFourcc, LPGLOBALDATA lpDDHALData #endif ) { LP_SURFACE_DATA lpSurfaceData = GET_SURFACE_DATA_PTR(lpSurface); DWORD dwVWIndex; // For non-RGB surfaces, we must always specify the block size. #ifndef WINNT_VER40 DBG_MESSAGE(("Overlay CreateSurface (lpSurface = %08lX, dwFourcc = %08lX)", lpSurface, dwFourcc)); #endif lpSurfaceData->dwOverlayFlags |= FLG_OVERLAY; #ifdef WINNT_VER40 if (gdwAvailVW == 0) { UINT i; for (i = 0; i < dwNumVideoWindows; i++) { // see if ddraw thinks the video window is available // and make sure VPM isn't using it if ( (giOvlyCnt[i] == 0) && ! IsVWHardwareInUse(ppdev,i) ) { gdwAvailVW = MakeVideoWindowFlag(i); break; } } if (i == dwNumVideoWindows) { DBG_MESSAGE(("All video windows in use, returning FALSE")); return DDERR_CURRENTLYNOTAVAIL; } } #endif dwVWIndex = GetVideoWindowIndex(gdwAvailVW); ASSERT(dwNumVideoWindows > dwVWIndex); lpSurfaceData->dwOverlayFlags |= gdwAvailVW; gdwFourccVW[dwVWIndex] = dwFourcc; if ( (dwFourcc == FOURCC_UYVY) #if ENABLE_YUY2 || (dwFourcc == FOURCC_YUY2) #endif #if ENABLE_YUVPLANAR || (dwFourcc == FOURCC_YUVPLANAR) #endif ) { lpSurface->lpGbl->ddpfSurface.dwYUVBitCount = 16; lpSurface->lpGbl->ddpfSurface.dwYBitMask = (DWORD) -1; lpSurface->lpGbl->ddpfSurface.dwUBitMask = (DWORD) -1; lpSurface->lpGbl->ddpfSurface.dwVBitMask = (DWORD) -1; if (dwFourcc == FOURCC_UYVY) { lpSurfaceData->dwOverlayFlags |= FLG_UYVY; } #if ENABLE_YUY2 else if (dwFourcc == FOURCC_YUY2) { lpSurfaceData->dwOverlayFlags |= FLG_YUY2; } #endif #if ENABLE_YUVPLANAR else // if (dwFourcc == FOURCC_YUVPLANAR) { lpSurfaceData->dwOverlayFlags |= FLG_YUVPLANAR; giPlanarCnt++; lpSurface->lpGbl->ddpfSurface.dwYUVBitCount = 12; //allocate a CLPLInfo structure lpSurfaceData->lpCLPLData = HEAP_ALLOC(hSharedHeap, HEAP_ZERO_MEMORY, sizeof(CLPLInfo), OWNER_OVERLAY, (DWORD)lpSurface); if (0 == lpSurfaceData->lpCLPLData) { return DDERR_OUTOFMEMORY; } if (bCLPLLobotomyMode) { LPCLPLSURFACE lpCLPL = lpSurfaceData->lpCLPLData; DWORD dwSize; dwSize = (lpSurface->lpGbl->wWidth * lpSurface->lpGbl->wHeight) / 2; lpCLPL->fpUSystemSurface = HEAP_ALLOC(hSharedHeap, HEAP_ZERO_MEMORY, dwSize, OWNER_OVERLAY, (DWORD)lpSurface); if (0 == lpCLPL->fpUSystemSurface) { HEAP_FREE(hSharedHeap, 0, (LPVOID)lpSurfaceData->lpCLPLData); lpSurfaceData->lpCLPLData = NULL; return DDERR_OUTOFMEMORY; } lpCLPL->fpVSystemSurface = (LPVOID)((DWORD)(lpCLPL->fpUSystemSurface) + dwSize / 2); DBG_MESSAGE(("CLPL lobotomy mode addrs: USys=%08lX, VSys=%08lX, size=%08lX", lpCLPL->fpUSystemSurface, lpCLPL->fpVSystemSurface, dwSize)); } } #endif } if(giOvlyCnt[dwVWIndex] == 0 ) { // save copy of current DTTR value #if DDRAW_COMPAT >= 50 gwNotify |= OVERLAY_ON; //if VPE is created this variable is already initialized if(!(gwNotify & VPE_ON)) #endif { gwNormalDTTR = ((PVGAR)lpDDHALData->RegsAddress)->grDisplay_Threshold_and_Tiling; } } giOvlyCnt[dwVWIndex]++; // CreateSurface32 fills in block size return DD_OK; } /*************************************************************************** * * FUNCTION: DestroySurface * * DESCRIPTION: This does misc things when an overlay surface is * destroyed. * ****************************************************************************/ #ifdef WINNT_VER40 STATIC VOID DestroyOverlaySurface( #else STATIC VOID DestroySurface( #endif #ifdef WINNT_VER40 PDEV *ppdev, PDD_DESTROYSURFACEDATA lpInput #else LPDDHAL_DESTROYSURFACEDATA lpInput #endif ) { #ifndef WINNT_VER40 LPGLOBALDATA lpDDHALData = GetDDHALContext( lpInput->lpDD); #endif LP_SURFACE_DATA lpSurfaceData; PVGAR pREG = (PVGAR)lpDDHALData->RegsAddress; DWORD dwVWIndex; #ifndef WINNT_VER40 DBG_MESSAGE(("Overlay DestroySurface (lpInput = 0x%08lX)", lpInput)); #endif if (0 == lpInput->lpDDSurface->dwReserved1) { lpInput->ddRVal = DDERR_NOTAOVERLAYSURFACE; return; } lpSurfaceData = GET_SURFACE_DATA_PTR(lpInput->lpDDSurface); dwVWIndex = GetVideoWindowIndex(lpSurfaceData->dwOverlayFlags); ASSERT(dwNumVideoWindows > dwVWIndex); if (lpSurfaceData->dwOverlayFlags & FLG_ENABLED) { // Turn the video off #ifndef WINNT_VER40 DBG_MESSAGE(("Turning off VW %ld in DestroySurface", dwVWIndex)); #endif #ifdef WINNT_VER40 DisableOverlay(ppdev, dwVWIndex); #else DisableOverlay(lpDDHALData, dwVWIndex); #endif lpHardwareOwner[dwVWIndex] = NULL; // clear show bit if panning of desktop enabled } #if ENABLE_YUVPLANAR if (lpSurfaceData->dwOverlayFlags & FLG_YUVPLANAR) { if (giPlanarCnt > 0) { LPCLPLSURFACE lpCLPL = lpSurfaceData->lpCLPLData; giPlanarCnt--; if (0 != lpCLPL) { if ((bCLPLLobotomyMode) && (0 != lpCLPL->fpUSystemSurface)) HEAP_FREE(hSharedHeap, 0, (LPVOID)lpCLPL->fpUSystemSurface); // Free up the memory for the CLPLInfo structure HEAP_FREE(hSharedHeap, 0, (LPVOID)lpCLPL); } } } #endif if (lpSurfaceData->dwOverlayFlags & FLG_VW_MASK) { if (giOvlyCnt[dwVWIndex] > 0) { if (0 == --giOvlyCnt[dwVWIndex]) { // get current DTTR, mask off FIFO threshold WORD CurrentDTTR = pREG->grDisplay_Threshold_and_Tiling & 0xFFC0; #if DDRAW_COMPAT >= 50 gvidConfig.dwFlags &= ~(VCFLG_COLORKEY | VCFLG_CHROMAKEY | VCFLG_DISP | VCFLG_420); gwNotify &= ~OVERLAY_ON; if(!(gwNotify & VPE_ON)) #endif { // Fix PDR 9574: Restore FIFO threshold value when overlay surface // is destroyed, do not restore the tile size. // If tile size has changed, we are likely in the middle of changing // video mode. No need to resotre FIFO in this case. if ( CurrentDTTR == (gwNormalDTTR & 0xFFC0) ) { // check tile size pREG->grDisplay_Threshold_and_Tiling = CurrentDTTR | (gwNormalDTTR & 0x003F); // reset FIFO Threshold } } } } } // Clear up the ownership of Dest ColorKey. gdwDestColorKeyOwnerVW &= ~(lpSurfaceData->dwOverlayFlags & FLG_VW_MASK); // Clear up the ownership of Src ColorKey. gdwSrcColorKeyOwnerVW &= ~(lpSurfaceData->dwOverlayFlags & FLG_VW_MASK); #if 0 if (lpInput->lpDDSurface->ddsCaps.dwCaps & DDSCAPS_LIVEVIDEO) { // Disable Video Capture. #pragma message("Destroy Surface") #pragma message(" Who turned on video capture?") #pragma message(" Shouldn't they shut it off?") #pragma message(" How do I disable video capture on this fraggin' thing?") } #endif } /*************************************************************************** * * FUNCTION: FlipOverlaySurface * * DESCRIPTION: This function is called by DDDRV when it wants to flip the * overlay surface. * ****************************************************************************/ STATIC DWORD FlipOverlaySurface ( #ifdef WINNT_VER40 PDEV *ppdev, PDD_FLIPDATA lpFlipData #else LPDDHAL_FLIPDATA lpFlipData #endif ) { #ifndef WINNT_VER40 LPGLOBALDATA lpDDHALData = GetDDHALContext( lpFlipData->lpDD); #endif DWORD dwOffset,dwOffset2; LP_SURFACE_DATA lpSurfaceData; DWORD dwFourcc; DWORD dwBitCount; PVGAR pREG = (PVGAR)lpDDHALData->RegsAddress; DWORD dwVWIndex; #if DDRAW_COMPAT >= 50 DWORD dwControl0; DWORD dwSrfFlags = FALSE; #endif DWORD dwSurfBase, dwSurfOffset; #ifndef WINNT_VER40 DBG_MESSAGE(("FlipOverlaySurface (lpFlipData = 0x%08lX)", lpFlipData)); #endif if (0 == lpFlipData->lpSurfCurr->dwReserved1) { lpFlipData->ddRVal = DDERR_NOTAOVERLAYSURFACE; return DDHAL_DRIVER_HANDLED; } lpSurfaceData = GET_SURFACE_DATA_PTR(lpFlipData->lpSurfCurr); dwVWIndex = GetVideoWindowIndex(lpSurfaceData->dwOverlayFlags); ASSERT(dwNumVideoWindows > dwVWIndex); // When TVTap/VPM is used with DirectDraw, things got more twisted. // VPM doesn't call UpdateSurface, so lpHardwareOwner // won't be set, nevertheless, the HW is grabbed by VPM. // In that case, should fail the Flip call to prevent bad VPM. // YUCK!!! // The VWE bit in the hardware seems to be the semaphore for sharing the // overlay with VPM if ((lpHardwareOwner[dwVWIndex] == NULL) && #ifdef WINNT_VER40 IsVWHardwareInUse(ppdev, dwVWIndex) #else IsVWHardwareInUse(lpDDHALData,dwVWIndex) #endif ) { #ifndef WINNT_VER40 DBG_MESSAGE(("VW %ld already in use, Out of Caps!", dwVWIndex)); #endif lpFlipData->ddRVal = DDERR_OUTOFCAPS; return (DDHAL_DRIVER_HANDLED); } #ifdef WINNT_VER40 if(GetOverlayFlipStatus(ppdev, 0, dwVWIndex) != DD_OK || DRAW_ENGINE_BUSY || IN_VBLANK) #else if(GetOverlayFlipStatus(lpDDHALData,0, dwVWIndex) != DD_OK || DRAW_ENGINE_BUSY || IN_VBLANK) #endif { lpFlipData->ddRVal = DDERR_WASSTILLDRAWING; return DDHAL_DRIVER_HANDLED; } // Determine the format of the video data if (lpFlipData->lpSurfTarg->dwFlags & DDRAWISURF_HASPIXELFORMAT) { GetFormatInfo (&(lpFlipData->lpSurfTarg->lpGbl->ddpfSurface), &dwFourcc, &dwBitCount); } else { dwBitCount = BITSPERPIXEL; } // Determine the offset to the new area. #ifdef WINNT_VER40 dwSurfBase = lpFlipData->lpSurfTarg->lpGbl->fpVidMem; #else dwSurfBase = (lpFlipData->lpSurfTarg->lpGbl->fpVidMem - lpDDHALData->ScreenAddress); #endif dwSurfOffset = lpSurfaceData->dwOverlayOffset; dwOffset = dwSurfBase + dwSurfOffset; #if ENABLE_MIRRORING // Flip the overlay surface by changing PSD_STRT_ADDR if (bIsVWMirrored[dwVWIndex]) { // for mirroring // point to the last byte of the last pixel on the right edge of the source dwOffset += (DWORD)(grOverlaySrc[dwVWIndex].right - grOverlaySrc[dwVWIndex].left - 1); } #endif dwOffset2 = 0; #if DDRAW_COMPAT >= 50 dwControl0 = pREG->VideoWindow[dwVWIndex].grVW_CONTROL0; if(lpFlipData->lpSurfTarg->lpSurfMore->lpVideoPort != NULL) { if(( lpFlipData->lpSurfTarg->lpSurfMore->dwOverlayFlags & DDOVER_AUTOFLIP) &&(lpFlipData->lpSurfTarg->lpSurfMore->lpVideoPort->ddvpInfo.dwVPFlags &DDVP_AUTOFLIP) && (lpFlipData->lpSurfTarg->lpAttachListFrom != NULL) && (lpFlipData->lpSurfTarg->lpAttachListFrom->lpAttached != NULL)) { dwSrfFlags = DDOVER_AUTOFLIP; } else if(( lpFlipData->lpSurfTarg->lpSurfMore->dwOverlayFlags & DDOVER_BOB) &&(lpFlipData->lpSurfTarg->lpSurfMore->lpVideoPort->ddvpInfo.dwVPFlags & DDVP_INTERLEAVE)) { dwSrfFlags = DDOVER_BOB; //Smooth interlace dwOffset2 = dwOffset + lpFlipData->lpSurfTarg->lpGbl->lPitch; //point to the next line } } if(dwSrfFlags & DDOVER_BOB) { //Smooth interlace dwOffset2 = dwOffset + lpFlipData->lpSurfTarg->lpGbl->lPitch; //point to the next line } else if(dwSrfFlags & DDOVER_AUTOFLIP) { //Auto Flip Overlay dwOffset2 = lpSurfaceData->dwAutoBaseAddr2 + dwSurfOffset; if(dwOffset2 == dwOffset) { dwOffset = lpSurfaceData->dwAutoBaseAddr1 + dwSurfOffset; } //For non-smooth-interlaced auto-flip these two address need // to be switched. HW BUG if(!(lpFlipData->lpSurfTarg->lpSurfMore->dwOverlayFlags & DDOVER_BOB)) { DWORD dwTmp = dwOffset; dwOffset = dwOffset2; dwOffset2 = dwTmp; } } else if( lpFlipData->lpSurfTarg->lpSurfMore->dwOverlayFlags & DDOVER_INTERLEAVED) { dwControl0 &= ~0x30000; if(lpFlipData->dwFlags & DDFLIP_ODD) //SW flip { dwOffset2 = dwOffset + lpFlipData->lpSurfTarg->lpGbl->lPitch ; //point to the next line dwControl0 |= 0x10000; //use VW_SDD } } else if(lpFlipData->dwFlags & DDFLIP_ODD) //SW flip { dwOffset2 = dwOffset; dwControl0 &= ~0x30000; dwControl0 |= 0x10000; //use VW_SDD } #endif // write new start address to hardware #ifdef WINNT_VER40 WaitForVWArmToClear(ppdev,dwVWIndex); #else WaitForVWArmToClear(lpDDHALData,dwVWIndex); #endif ASSERT(! (pREG->VideoWindow[dwVWIndex].grVW_TEST0 & VW_PostImed)); LL32(VideoWindow[dwVWIndex].grVW_PSD_STRT_ADDR, dwOffset); LL32(VideoWindow[dwVWIndex].grVW_SSD_STRT_ADDR, dwOffset2); #if ENABLE_YUVPLANAR if (lpSurfaceData->dwOverlayFlags & FLG_YUVPLANAR) { // PSD_STRT_ADDR has been set to the start of the Y data in aperture0 // set PSD_UVSTRT_ADDR to start of UV interleaved data in aperture 0 // UV data is only half the height of Y data LL32(VideoWindow[dwVWIndex].grVW_PSD_UVSTRT_ADDR, dwSurfBase + (((lpFlipData->lpSurfTarg->lpGbl->wHeight * lpFlipData->lpSurfTarg->lpGbl->lPitch) + 7) & ~7) + (dwSurfOffset / 2)); LL32(VideoWindow[dwVWIndex].grVW_SSD_UVSTRT_ADDR, dwOffset2); } #endif #if DDRAW_COMPAT >= 50 if (lpSurfaceData->dwOverlayFlags & FLG_ENABLED) pREG->VideoWindow[dwVWIndex].grVW_CONTROL0 = (dwControl0 |VW_VWE | VW_ARM); else pREG->VideoWindow[dwVWIndex].grVW_CONTROL0 = dwControl0 | VW_ARM; #else if (lpSurfaceData->dwOverlayFlags & FLG_ENABLED) pREG->VideoWindow[dwVWIndex].grVW_CONTROL0 |= (VW_VWE | VW_ARM); else pREG->VideoWindow[dwVWIndex].grVW_CONTROL0 |= VW_ARM; #endif #ifdef WINNT_VER40 // Update the hardware owner lpHardwareOwner[dwVWIndex] = lpFlipData->lpSurfTarg; #endif // remember where/when we were when we did the flip #ifdef WINNT_VER40 EngQueryPerformanceCounter(&gsOverlayFlip.liFlipTime); #else QueryPerformanceCounter((LARGE_INTEGER *)&gsOverlayFlip.liFlipTime); #endif #ifdef WINNT_VER40 gsOverlayFlip.dwFlipScanline = CurrentVLine(ppdev); #else gsOverlayFlip.dwFlipScanline = CurrentVLine(lpDDHALData); #endif gsOverlayFlip.bFlipFlag = TRUE; gsOverlayFlip.fpFlipFrom = lpFlipData->lpSurfCurr->lpGbl->fpVidMem; gsOverlayFlip.bHaveEverCrossedVBlank = FALSE; if (IN_VBLANK) { gsOverlayFlip.bWasEverInDisplay = FALSE; } else { gsOverlayFlip.bWasEverInDisplay = TRUE; } lpFlipData->ddRVal = DD_OK; return DDHAL_DRIVER_HANDLED; } /*************************************************************************** * * FUNCTION: LockSurface * * DESCRIPTION: Checks for flipping before allowing access to the surface. * ****************************************************************************/ STATIC DWORD LockSurface ( #ifdef WINNT_VER40 PDEV *ppdev, PDD_LOCKDATA lpInput #else LPDDHAL_LOCKDATA lpInput #endif ) { #if ENABLE_YUVPLANAR LPCLPLSURFACE lpCLPL; // pointer to our YUV planar DWORD dwUVOffset; #endif LP_SURFACE_DATA lpSurfaceData; DWORD dwVWIndex; #ifndef WINNT_VER40 LPGLOBALDATA lpDDHALData = GetDDHALContext( lpInput->lpDD); #endif #ifndef WINNT_VER40 DBG_MESSAGE(("Overlay LockSurface (lpInput = 0x%08lX)", lpInput)); #endif if (0 == lpInput->lpDDSurface->dwReserved1) { lpInput->ddRVal = DDERR_NOTAOVERLAYSURFACE; return DDHAL_DRIVER_HANDLED; } lpSurfaceData = GET_SURFACE_DATA_PTR(lpInput->lpDDSurface); dwVWIndex = GetVideoWindowIndex(lpSurfaceData->dwOverlayFlags); ASSERT(dwNumVideoWindows > dwVWIndex); // Check for flipping if ((gsOverlayFlip.bFlipFlag) && ( #ifdef WINNT_VER40 GetOverlayFlipStatus(ppdev, lpInput->lpDDSurface->lpGbl->fpVidMem, dwVWIndex) #else GetOverlayFlipStatus(lpDDHALData,lpInput->lpDDSurface->lpGbl->fpVidMem, dwVWIndex) #endif == DDERR_WASSTILLDRAWING)) { lpInput->ddRVal = DDERR_WASSTILLDRAWING; return DDHAL_DRIVER_HANDLED; } #if ENABLE_YUVPLANAR if (lpSurfaceData->dwOverlayFlags & FLG_YUVPLANAR) { // make sure CLPL aperture is mapped in if (! lpDDHALData->dwCLPLAperture) { lpInput->ddRVal = DD_OK; return DDHAL_DRIVER_NOTHANDLED; } // here's how this YUV420/YUVPLANAR/CLPL stuff works: // the CLPL surface consists of all the Y data followed by a region of // UV interleaved data. We are currently supporting only linear surfaces // for CLPL so there will be wHeight lines of Y data followed by wHeight/2 // lines of UV interleaved data. CreateSurface32 has padded the surface // allocation such that the UV interleaved data will start on the first // quadword boundary following the Y data. // // We pass back a pointer to a structure containing the address of a Y // region, a U region and a V region to the app. The app writes to the // U and V regions as if they are linear and the hardware converts this // data into the UV interleaved data in aperture 0. // // For the U ptr we give the app an address pointing somewhere in the // first four meg of aperture 3 and for the V ptr we give the app an // address pointing to the same somewhere but in the second four meg // of aperture 3. When the app writes to these addresses, the data // shows up in aperture 0 such that: // the U data is at ap0_offset = ap3_offset * 2 // the V data is at ap0_offset = (ap3_offset - 4MB) * 2 + 1 // // what we need to do then is give the app the folloing ptrs: // Y ptr = ap0_offset of the Y region (the beginning of the surface) // U ptr = ap3_offset for U data = U_ap0_offset / 2 // V ptr = ap3_offset for V data = (V_ap0_offset - 1) / 2 + 4MB // where U_ap0_offset = offset we want the U data to start // and V_ap0_offset = offset we want the V data to start // we also need V_ap0_offset = U_ap0_offset + 1 // Compute Y and UV aperture in frame buffer lpCLPL = (LPCLPLSURFACE)lpSurfaceData->lpCLPLData; lpInput->lpSurfData = (LPVOID)lpCLPL; // Y data starts at beginning of surface in aperture0 lpCLPL->fpYSurface = (LPVOID)lpInput->lpDDSurface->lpGbl->fpVidMem; DBG_MESSAGE(("Aperture0 Y offset = %08lX", (lpInput->lpDDSurface->lpGbl->fpVidMem - lpDDHALData->ScreenAddress))); DBG_MESSAGE((" surface height = %08lX, pitch = %08lX", lpInput->lpDDSurface->lpGbl->wHeight, lpInput->lpDDSurface->lpGbl->lPitch)); // determine offset of UV data in aperture 0 (and make it qword aligned) dwUVOffset = (lpInput->lpDDSurface->lpGbl->fpVidMem - lpDDHALData->ScreenAddress) + (((lpInput->lpDDSurface->lpGbl->wHeight * lpInput->lpDDSurface->lpGbl->lPitch) + 7) & ~7); DBG_MESSAGE(("Aperture0 UV offset = %08lX", dwUVOffset)); // convert UV aperture0 offset to aperture3 offset DBG_MESSAGE(("Aperture3 UV offset = %08lX", dwUVOffset / 2)); dwUVOffset = lpDDHALData->dwCLPLAperture + dwUVOffset / 2; if (bCLPLLobotomyMode) { lpCLPL->fpRealUSurface = (LPVOID)(dwUVOffset); lpCLPL->fpRealVSurface = (LPVOID)(dwUVOffset + 0x400000); DBG_MESSAGE(("CLPL lobotomy mode addrs: RealU=%08lX, RealV=%08lX", lpCLPL->fpRealUSurface, lpCLPL->fpRealVSurface)); lpCLPL->fpUSurface = lpCLPL->fpUSystemSurface; lpCLPL->fpVSurface = lpCLPL->fpVSystemSurface; } else { lpCLPL->fpUSurface = (LPVOID)(dwUVOffset); lpCLPL->fpVSurface = (LPVOID)(dwUVOffset + 0x400000); } DBG_MESSAGE(("CLPL addrs: Y=%08lX, U=%08lX, V=%08lX", lpCLPL->fpYSurface, lpCLPL->fpUSurface, lpCLPL->fpVSurface)); lpInput->ddRVal = DD_OK; return DDHAL_DRIVER_HANDLED; } #endif #if ENABLE_YUY2 // Force them to use the byte swap aperture if (lpSurfaceData->dwOverlayFlags & FLG_YUY2) { // make sure the YUY2 aperture is mapped in if (! lpDDHALData->dwYUY2Aperture) { lpInput->ddRVal = DD_OK; return DDHAL_DRIVER_NOTHANDLED; } lpInput->lpSurfData = (LPVOID) ((lpInput->lpDDSurface->lpGbl->fpVidMem - lpDDHALData->ScreenAddress) + lpDDHALData->dwYUY2Aperture); lpInput->ddRVal = DD_OK; return DDHAL_DRIVER_HANDLED; } #endif lpInput->ddRVal = DD_OK; return DDHAL_DRIVER_NOTHANDLED; } #if ENABLE_YUVPLANAR /*************************************************************************** * * FUNCTION: SysToFBCopy() * * DESCRIPTION: * ****************************************************************************/ #if 1 static INLINE VOID SysToFBCopy ( BYTE *dst, LONG dstPitch, BYTE *src, LONG srcPitch, REG32 ext, LONG bpp ) { int yext = ext.pt.Y; int xext = ext.pt.X * bpp; while (0 < yext--) { memcpy(dst,src,xext); dst += dstPitch; src += srcPitch; } } #else // writing the scanline from right to left shows the hwbug where roughly // every other 4 dwords written to aperture3 is dropped // and the video is generally display with a lovely flourescent green // checkerboard pattern // // This duplicates the problem seen by allowing the Compcore MPEG player // write directly to aperture3 #pragma optimize("", off) // the compiler ignores __inline because of the inline assembly static INLINE VOID SysToFBCopy ( BYTE *dst, LONG dstPitch, BYTE *src, LONG srcPitch, REG32 ext, LONG bpp ) { int yext = ext.pt.Y; int xext = ext.pt.X * bpp; _asm std dst += dstPitch - sizeof(DWORD); src += srcPitch - sizeof(DWORD); while (0 < yext--) { _asm { mov eax,xext mov edi,dst mov esi,src mov ecx,eax shr ecx,2 rep movsd mov ecx,eax and ecx,3 rep movsb } dst += dstPitch; src += srcPitch; } _asm cld } #pragma optimize("", on) #endif #endif /*************************************************************************** * * FUNCTION: UnlockSurface * * DESCRIPTION: This function is called by DDHAL when it is finished accessing * the frame buffer. * ****************************************************************************/ STATIC VOID UnlockSurface ( #ifdef WINNT_VER40 PDEV *ppdev, PDD_UNLOCKDATA lpInput #else LPDDHAL_UNLOCKDATA lpInput #endif ) { #if ENABLE_YUVPLANAR LPCLPLSURFACE lpCLPL; // pointer to our YUV planar #endif LP_SURFACE_DATA lpSurfaceData; #ifndef WINNT_VER40 DBG_MESSAGE(("Overlay UnlockSurface (lpInput = 0x%08lX)", lpInput)); #endif if (0 == lpInput->lpDDSurface->dwReserved1) { lpInput->ddRVal = DDERR_NOTAOVERLAYSURFACE; return; } lpSurfaceData = GET_SURFACE_DATA_PTR(lpInput->lpDDSurface); #if ENABLE_YUVPLANAR if ((lpSurfaceData->dwOverlayFlags & FLG_YUVPLANAR) && bCLPLLobotomyMode) { REG32 ext; LONG pitch; lpCLPL = (LPCLPLSURFACE)lpSurfaceData->lpCLPLData; ext.pt.X = lpInput->lpDDSurface->lpGbl->wWidth / 2; ext.pt.Y = lpInput->lpDDSurface->lpGbl->wHeight / 2; pitch = lpInput->lpDDSurface->lpGbl->lPitch / 2; SysToFBCopy(lpCLPL->fpRealUSurface, pitch, lpCLPL->fpUSystemSurface, pitch, ext, 1); SysToFBCopy(lpCLPL->fpRealVSurface, pitch, lpCLPL->fpVSystemSurface, pitch, ext, 1); } #endif } /*************************************************************************** * * FUNCTION: SetColorKey * * DESCRIPTION: Looks at the color key for changes in the while * overlay is active. * ****************************************************************************/ STATIC VOID SetColorKey ( #ifdef WINNT_VER40 PDEV *ppdev, PDD_SETCOLORKEYDATA lpInput #else LPDDHAL_SETCOLORKEYDATA lpInput #endif ) { LP_SURFACE_DATA lpSurfaceData; LP_SURFACE_DATA lpHWOwnerData; DWORD dwVWIndex; #ifndef WINNT_VER40 LPGLOBALDATA lpDDHALData = GetDDHALContext( lpInput->lpDD); #endif #ifndef WINNT_VER40 DBG_MESSAGE(("Overlay SetColorKey (lpInput = 0x%08lX)", lpInput)); #endif if (0 == lpInput->lpDDSurface->dwReserved1) { lpInput->ddRVal = DDERR_NOTAOVERLAYSURFACE; return; } lpSurfaceData = GET_SURFACE_DATA_PTR(lpInput->lpDDSurface); dwVWIndex = GetVideoWindowIndex(lpSurfaceData->dwOverlayFlags); ASSERT(dwNumVideoWindows > dwVWIndex); if ((lpInput->dwFlags & DDCKEY_DESTOVERLAY) && (lpInput->lpDDSurface == lpColorSurfaceVW[dwVWIndex])) { // See if someone else is already using the colorkey. if ((gdwDestColorKeyOwnerVW & FLG_VW_MASK) && (lpInput->lpDDSurface != lpColorSurfaceVW[dwVWIndex])) { // ColorKey already being used. lpInput->ddRVal = DDERR_OUTOFCAPS; return; } // You get here only when the call is issued AFTER UpdateOverlay. gdwColorKey = lpInput->ckNew.dwColorSpaceLowValue; if (0 == lpHardwareOwner[dwVWIndex]->dwReserved1) { lpInput->ddRVal = DDERR_NOTAOVERLAYSURFACE; return; } lpHWOwnerData = GET_SURFACE_DATA_PTR(lpHardwareOwner[dwVWIndex]); if ((lpInput->lpDDSurface == lpColorSurfaceVW[dwVWIndex]) && (lpHardwareOwner[dwVWIndex]) && (lpHWOwnerData->dwOverlayFlags & FLG_ENABLED)) { gdwDestColorKeyOwnerVW = MakeVideoWindowFlag(dwVWIndex); lpHWOwnerData->dwOverlayFlags |= FLG_COLOR_KEY; #ifdef WINNT_VER40 RegInitVideoVW(ppdev, dwVWIndex, lpHardwareOwner[dwVWIndex]); #else RegInitVideoVW(dwVWIndex, lpHardwareOwner[dwVWIndex],lpDDHALData); #endif } } else if ((lpInput->dwFlags & DDCKEY_SRCOVERLAY) && (lpInput->lpDDSurface == lpSrcColorSurfaceVW[dwVWIndex])) { // See if someone else already uses the colorkey. if ((gdwSrcColorKeyOwnerVW != 0 ) && !(gdwSrcColorKeyOwnerVW & lpSurfaceData->dwOverlayFlags)) { // ColorKey already been used. lpInput->ddRVal = DDERR_OUTOFCAPS; return; } gdwSrcColorKeyLow = lpInput->ckNew.dwColorSpaceLowValue; gdwSrcColorKeyHigh = lpInput->ckNew.dwColorSpaceHighValue; if (gdwSrcColorKeyLow > gdwSrcColorKeyHigh) { gdwSrcColorKeyHigh = gdwSrcColorKeyLow; } if (0 == lpHardwareOwner[dwVWIndex]->dwReserved1) { lpInput->ddRVal = DDERR_NOTAOVERLAYSURFACE; return; } lpHWOwnerData = GET_SURFACE_DATA_PTR(lpHardwareOwner[dwVWIndex]); if ((lpSurfaceData->dwOverlayFlags & FLG_VW_MASK) && (lpHardwareOwner[dwVWIndex]) && (lpHWOwnerData->dwOverlayFlags & FLG_ENABLED)) { gdwSrcColorKeyOwnerVW = MakeVideoWindowFlag(dwVWIndex); lpHWOwnerData->dwOverlayFlags |= FLG_SRC_COLOR_KEY; #ifdef WINNT_VER40 RegInitVideoVW(ppdev, dwVWIndex, lpHardwareOwner[dwVWIndex]); #else RegInitVideoVW(dwVWIndex, lpHardwareOwner[dwVWIndex],lpDDHALData); #endif } } } /*************************************************************************** * * FUNCTION: SaveRectangles * * DESCRIPTION: * ****************************************************************************/ static INLINE BOOL SaveRectangles ( #ifdef WINNT_VER40 PDEV *ppdev, #endif DWORD dwVWIndex, BOOL bCheckBandwidth, DWORD dwBitCount, #ifdef WINNT_VER40 PDD_UPDATEOVERLAYDATA lpInput #else LPDDHAL_UPDATEOVERLAYDATA lpInput, LPGLOBALDATA lpDDHALData #endif ) { SIZEL Dst; SIZEL Src; BWREGS bwregs; // Is there sufficient bandwidth to work? gvidConfig.sizSrc.cx = lpInput->rSrc.right - lpInput->rSrc.left; gvidConfig.sizSrc.cy = lpInput->rSrc.bottom - lpInput->rSrc.top; gvidConfig.sizDisp.cx = lpInput->rDest.right - lpInput->rDest.left; gvidConfig.sizDisp.cy = lpInput->rDest.bottom - lpInput->rDest.top; gvidConfig.uSrcDepth = dwBitCount; gvidConfig.uDispDepth = dwBitCount; //video window has the same as source gvidConfig.uGfxDepth = BITSPERPIXEL; gvidConfig.dwFlags |= VCFLG_DISP; #ifdef WINNT_VER40 ChipIOReadBWRegs(ppdev, &bwregs); #else ChipIOReadBWRegs(lpDDHALData, &bwregs); #endif if (bCheckBandwidth && bUseBWEqn && !ChipIsEnoughBandwidth(&gsProgRegs, &gvidConfig, &bwregs) ) { gvidConfig.dwFlags &= ~VCFLG_DISP; lpInput->ddRVal = DDERR_OUTOFCAPS; return FALSE; } // Save the rectangles #ifndef WINNT_VER40 DBG_MESSAGE(("rSrc = %lX,%lX %lX,%lX", lpInput->rSrc.left,lpInput->rSrc.top, lpInput->rSrc.right,lpInput->rSrc.bottom)); DBG_MESSAGE(("rcOverlaySrc = %lX,%lX %lX,%lX", lpInput->lpDDSrcSurface->rcOverlaySrc.left, lpInput->lpDDSrcSurface->rcOverlaySrc.top, lpInput->lpDDSrcSurface->rcOverlaySrc.right, lpInput->lpDDSrcSurface->rcOverlaySrc.bottom)); #endif grOverlaySrc[dwVWIndex].left = (int)lpInput->rSrc.left; grOverlaySrc[dwVWIndex].right = (int)lpInput->rSrc.right; grOverlaySrc[dwVWIndex].top = (int)lpInput->rSrc.top; grOverlaySrc[dwVWIndex].bottom = (int)lpInput->rSrc.bottom; #ifndef WINNT_VER40 DBG_MESSAGE(("rDest = %lX,%lX %lX,%lX", lpInput->rDest.left,lpInput->rDest.top, lpInput->rDest.right,lpInput->rDest.bottom)); DBG_MESSAGE(("rcOverlayDest = %lX,%lX %lX,%lX", lpInput->lpDDSrcSurface->rcOverlayDest.left, lpInput->lpDDSrcSurface->rcOverlayDest.top, lpInput->lpDDSrcSurface->rcOverlayDest.right, lpInput->lpDDSrcSurface->rcOverlayDest.bottom)); #endif grOverlayDest[dwVWIndex].left = (int)lpInput->rDest.left; grOverlayDest[dwVWIndex].right = (int)lpInput->rDest.right; grOverlayDest[dwVWIndex].top = (int)lpInput->rDest.top; grOverlayDest[dwVWIndex].bottom = (int)lpInput->rDest.bottom; // make sure resize is within hw capabilities // x can shrink down to 1/2 and stretch up to 8x // y can stretch up to 8x Dst.cx = grOverlayDest[dwVWIndex].right - grOverlayDest[dwVWIndex].left; Dst.cy = grOverlayDest[dwVWIndex].bottom - grOverlayDest[dwVWIndex].top; Src.cx = grOverlaySrc[dwVWIndex].right - grOverlaySrc[dwVWIndex].left; Src.cy = grOverlaySrc[dwVWIndex].bottom - grOverlaySrc[dwVWIndex].top; #ifdef WINNT_VER40 if (Dst.cx > (LONG)(lpDDHALData->dwMaxOverlayStretch * Src.cx / 1000)) #else if (Dst.cx > (LONG)(lpDDHALData->HALInfo.ddCaps.dwMaxOverlayStretch * Src.cx / 1000)) #endif { lpInput->ddRVal = DDERR_TOOBIGWIDTH; return FALSE; } #ifdef WINNT_VER40 else if (Dst.cy > (LONG)(lpDDHALData->dwMaxOverlayStretch * Src.cy / 1000)) #else else if (Dst.cy > (LONG)(lpDDHALData->HALInfo.ddCaps.dwMaxOverlayStretch * Src.cy / 1000)) #endif { lpInput->ddRVal = DDERR_TOOBIGHEIGHT; return FALSE; } #ifdef WINNT_VER40 else if (Dst.cx < (LONG)(lpDDHALData->dwMinOverlayStretch * Src.cx / 1000)) #else else if (Dst.cx < (LONG)(lpDDHALData->HALInfo.ddCaps.dwMinOverlayStretch * Src.cx / 1000)) #endif { lpInput->ddRVal = DDERR_UNSUPPORTED; // too small width return FALSE; } if (MIN_OLAY_WIDTH >= Src.cx) { lpInput->ddRVal = DDERR_OUTOFCAPS; return FALSE; } return TRUE; } /*************************************************************************** * * FUNCTION: UpdateSurface * * DESCRIPTION: * ****************************************************************************/ STATIC DWORD UpdateSurface ( #ifdef WINNT_VER40 PDEV *ppdev, PDD_UPDATEOVERLAYDATA lpInput #else LPDDHAL_UPDATEOVERLAYDATA lpInput #endif ) { DWORD dwOldStatus; DWORD dwFourcc; BOOL bCheckBandwidth; DWORD dwBitCount; DWORD dwDestColorKey; LP_SURFACE_DATA lpSrcSurfaceData; DWORD dwVWIndex; DWORD dwVWFlag; BWREGS bwregs; BOOL bShowOverlay = FALSE; #ifndef WINNT_VER40 LPGLOBALDATA lpDDHALData = GetDDHALContext( lpInput->lpDD); #endif #ifndef WINNT_VER40 DBG_MESSAGE(("Overlay UpdateSurface (lpInput = 0x%08lX)", lpInput)); #endif if (0 == lpInput->lpDDSrcSurface->dwReserved1) { lpInput->ddRVal = DDERR_NOTAOVERLAYSURFACE; return DDHAL_DRIVER_HANDLED; } lpSrcSurfaceData = GET_SURFACE_DATA_PTR(lpInput->lpDDSrcSurface); if (lpInput->lpDDSrcSurface->dwFlags & DDRAWISURF_HASPIXELFORMAT) { GetFormatInfo(&(lpInput->lpDDSrcSurface->lpGbl->ddpfSurface), &dwFourcc, &dwBitCount); } else { dwBitCount = BITSPERPIXEL; if (16 == dwBitCount) dwFourcc = BI_BITFIELDS; // 5:6:5 else dwFourcc = BI_RGB; // 8bpp, 5:5:5, 24bpp & 32bpp } gvidConfig.dwFlags &= ~(VCFLG_COLORKEY | VCFLG_CHROMAKEY | VCFLG_DISP | VCFLG_420); #if ENABLE_YUVPLANAR if (lpSrcSurfaceData->dwOverlayFlags & FLG_YUVPLANAR) gvidConfig.dwFlags |= VCFLG_420; #endif // Are we color keying? bCheckBandwidth = TRUE; dwOldStatus = lpSrcSurfaceData->dwOverlayFlags; dwVWIndex = GetVideoWindowIndex(dwOldStatus); ASSERT(dwNumVideoWindows > dwVWIndex); dwVWFlag = MakeVideoWindowFlag(dwVWIndex); lpColorSurfaceVW[dwVWIndex] = lpSrcColorSurfaceVW[dwVWIndex] = NULL; #if ENABLE_MIRRORING bIsVWMirrored[dwVWIndex] = FALSE; #endif if ((lpInput->dwFlags & (DDOVER_KEYDEST | DDOVER_KEYDESTOVERRIDE)) && (lpInput->dwFlags & (DDOVER_KEYSRC | DDOVER_KEYSRCOVERRIDE))) { // Cannot perform src colorkey and dest colorkey at the same time lpInput->ddRVal = DDERR_NOCOLORKEYHW; return DDHAL_DRIVER_HANDLED; } #if HWBUG_24BPP_DST_COLORKEY if ( #ifdef WINNT_VER40 (24 == ppdev->ulBitCount) && #else (24 == pPDevice->deBitsPixel) && #endif (lpInput->dwFlags & (DDOVER_KEYDEST | DDOVER_KEYDESTOVERRIDE))) { // destination colorkeying at 24bpp is busted in hardware lpInput->ddRVal = DDERR_NOCOLORKEYHW; return DDHAL_DRIVER_HANDLED; } #endif #ifdef WINNT_VER40 ChipIOReadBWRegs(ppdev, &bwregs); #else ChipIOReadBWRegs(lpDDHALData, &bwregs); #endif lpSrcSurfaceData->dwOverlayFlags &= ~(FLG_COLOR_KEY|FLG_SRC_COLOR_KEY); #ifndef WINNT_VER40 if ( (lpInput->dwFlags == 0) && (lpHardwareOwner[dwVWIndex] == NULL) && (lpSrcSurfaceData->dwOverlayFlags & FLG_OVERLAY) ) { bShowOverlay = TRUE; } #endif if (lpInput->dwFlags & (DDOVER_KEYDEST | DDOVER_KEYDESTOVERRIDE)) { dwDestColorKey = (lpInput->dwFlags & DDOVER_KEYDEST) ? lpInput->lpDDDestSurface->ddckCKDestOverlay.dwColorSpaceLowValue : lpInput->overlayFX.dckDestColorkey.dwColorSpaceLowValue; // Allow colorkey override only when it's the original // colorkey owner, or no one owns the colorkey so far. if (gdwDestColorKeyOwnerVW == 0) { gdwDestColorKeyOwnerVW = dwVWFlag; } else if ((dwDestColorKey != gdwColorKey) && (dwOldStatus & dwVWFlag) && !(gdwDestColorKeyOwnerVW & dwVWFlag)) { // ColorKey already been used by someone else. // It's not the original colorkey owner, // and the key color is not the same as the other one. lpInput->ddRVal = DDERR_OUTOFCAPS; return DDHAL_DRIVER_HANDLED; } // Is there sufficient bandwidth to work? gvidConfig.sizSrc.cx = lpInput->rSrc.right - lpInput->rSrc.left; gvidConfig.sizSrc.cy = lpInput->rSrc.bottom - lpInput->rSrc.top; gvidConfig.sizDisp.cx = lpInput->rDest.right - lpInput->rDest.left; gvidConfig.sizDisp.cy = lpInput->rDest.bottom - lpInput->rDest.top; gvidConfig.uSrcDepth = dwBitCount; gvidConfig.uDispDepth = dwBitCount; //video window has the same depth as //the source gvidConfig.uGfxDepth = BITSPERPIXEL; gvidConfig.dwFlags |= VCFLG_COLORKEY | VCFLG_DISP; if (!bUseBWEqn || ChipIsEnoughBandwidth(&gsProgRegs, &gvidConfig, &bwregs) ) { bCheckBandwidth = FALSE; lpSrcSurfaceData->dwOverlayFlags |= FLG_COLOR_KEY; if (lpInput->dwFlags & DDOVER_KEYDEST) { gdwColorKey = lpInput->lpDDDestSurface->ddckCKDestOverlay.dwColorSpaceLowValue; lpColorSurfaceVW[dwVWIndex] = lpInput->lpDDDestSurface; } else { gdwColorKey = lpInput->overlayFX.dckDestColorkey.dwColorSpaceLowValue; } } else { gvidConfig.dwFlags &= ~(VCFLG_COLORKEY | VCFLG_DISP); lpInput->ddRVal = DDERR_NOCOLORKEYHW; return DDHAL_DRIVER_HANDLED; } } else if (lpInput->dwFlags & (DDOVER_KEYSRC | DDOVER_KEYSRCOVERRIDE)) { // Allow SrcColorKey override only when it's the original // colorkey owner, or no one owns the colorkey so far. if (gdwSrcColorKeyOwnerVW == 0) { gdwSrcColorKeyOwnerVW = dwVWFlag; } else if (!(dwOldStatus & gdwSrcColorKeyOwnerVW)) { // It's not the original colorkey owner lpInput->ddRVal = DDERR_OUTOFCAPS; return DDHAL_DRIVER_HANDLED; } // Is there sufficient bandwidth to work? gvidConfig.sizSrc.cx = lpInput->rSrc.right - lpInput->rSrc.left; gvidConfig.sizSrc.cy = lpInput->rSrc.bottom - lpInput->rSrc.top; gvidConfig.sizDisp.cx = lpInput->rDest.right - lpInput->rDest.left; gvidConfig.sizDisp.cy = lpInput->rDest.bottom - lpInput->rDest.top; gvidConfig.uSrcDepth = dwBitCount; gvidConfig.uDispDepth = dwBitCount; //video window has the same as source gvidConfig.uGfxDepth = BITSPERPIXEL; gvidConfig.dwFlags |= VCFLG_CHROMAKEY | VCFLG_DISP; if (!bUseBWEqn || ChipIsEnoughBandwidth(&gsProgRegs, &gvidConfig, &bwregs) ) { bCheckBandwidth = FALSE; lpSrcSurfaceData->dwOverlayFlags |= FLG_SRC_COLOR_KEY; lpSrcColorSurfaceVW[dwVWIndex] = lpInput->lpDDSrcSurface; if (lpInput->dwFlags & DDOVER_KEYSRC) { gdwSrcColorKeyLow = lpInput->lpDDSrcSurface->ddckCKSrcOverlay.dwColorSpaceLowValue; gdwSrcColorKeyHigh = lpInput->lpDDSrcSurface->ddckCKSrcOverlay.dwColorSpaceHighValue; } else { gdwSrcColorKeyLow = lpInput->overlayFX.dckSrcColorkey.dwColorSpaceLowValue; gdwSrcColorKeyHigh = lpInput->overlayFX.dckSrcColorkey.dwColorSpaceHighValue; } if (gdwSrcColorKeyHigh < gdwSrcColorKeyHigh) { gdwSrcColorKeyHigh = gdwSrcColorKeyLow; } } else { gvidConfig.dwFlags &= ~(VCFLG_CHROMAKEY | VCFLG_DISP); lpInput->ddRVal = DDERR_NOCOLORKEYHW; return DDHAL_DRIVER_HANDLED; } } #ifdef WINNT_VER40 #if 0 // The hardware is broken when using RGB32 data and ShrinkXBy2. if ( (dwFourcc == BI_RGB) && (dwBitCount == 32) && (gvidConfig.sizSrc.cx > gvidConfig.sizDisp.cx) && (lpSrcSurfaceData->dwOverlayFlags & (FLG_ENABLED | 0x02000000)) ) { if (lpSrcSurfaceData->dwOverlayFlags & FLG_ENABLED) { // Turn the video off. DisableOverlay(ppdev, dwVWIndex); lpHardwareOwner[dwVWIndex] = NULL; lpSrcSurfaceData->dwOverlayFlags &= ~FLG_ENABLED; lpSrcSurfaceData->dwOverlayFlags |= 0x02000000; } if (lpSrcSurfaceData->dwOverlayFlags & FLG_VW_MASK) { PVGAR pREG = (PVGAR) lpDDHALData->RegsAddress; if (giOvlyCnt[dwVWIndex] > 0) { if (--giOvlyCnt[dwVWIndex] == 0) { // Get current DTTR, mask off FIFO threshold. WORD CurrentDTTR = pREG->grDisplay_Threshold_and_Tiling & 0xFFC0; // Fix PDR 9574: Restore FIFO threshold value when overlay // surface is destroyed, do not restore the tile size. If // tile size has changed, we are likely in the middle of // changing video mode. No need to restore FIFO in this // case. if ( CurrentDTTR == (gwNormalDTTR & 0xFFC0) ) { pREG->grDisplay_Threshold_and_Tiling = CurrentDTTR | (gwNormalDTTR & 0x003F); } } } } else if (giOvlyCnt[dwVWIndex] > 0) { giOvlyCnt[dwVWIndex]--; } // Clear up the ownership of Dest ColorKey. gdwDestColorKeyOwnerVW &= ~(lpSrcSurfaceData->dwOverlayFlags & FLG_VW_MASK); // Clear up the ownership of Src ColorKey. gdwSrcColorKeyOwnerVW &= ~(lpSrcSurfaceData->dwOverlayFlags & FLG_VW_MASK); lpInput->ddRVal = DDERR_OUTOFCAPS; return(DDHAL_DRIVER_HANDLED); } #else // The hardware is broken when using RGB32 data and ShrinkXBy2. if ( (dwFourcc == BI_RGB) && (dwBitCount == 32) && (gvidConfig.sizSrc.cx > gvidConfig.sizDisp.cx) && (lpSrcSurfaceData->dwOverlayFlags & FLG_ENABLED) ) { // Turn the video off. DisableOverlay(ppdev, dwVWIndex); lpHardwareOwner[dwVWIndex] = NULL; lpSrcSurfaceData->dwOverlayFlags &= ~FLG_ENABLED; lpSrcSurfaceData->dwOverlayFlags |= 0x02000000; if (lpSrcSurfaceData->dwOverlayFlags & FLG_VW_MASK) { PVGAR pREG = (PVGAR) lpDDHALData->RegsAddress; if (giOvlyCnt[dwVWIndex] > 0) { if (--giOvlyCnt[dwVWIndex] == 0) { // Get current DTTR, mask off FIFO threshold. WORD CurrentDTTR = pREG->grDisplay_Threshold_and_Tiling & 0xFFC0; // Fix PDR 9574: Restore FIFO threshold value when overlay // surface is destroyed, do not restore the tile size. If // tile size has changed, we are likely in the middle of // changing video mode. No need to restore FIFO in this // case. if ( CurrentDTTR == (gwNormalDTTR & 0xFFC0) ) { pREG->grDisplay_Threshold_and_Tiling = CurrentDTTR | (gwNormalDTTR & 0x003F); } } } } else if (giOvlyCnt[dwVWIndex] > 0) { giOvlyCnt[dwVWIndex]--; } // Clear up the ownership of Dest ColorKey. gdwDestColorKeyOwnerVW &= ~(lpSrcSurfaceData->dwOverlayFlags & FLG_VW_MASK); // Clear up the ownership of Src ColorKey. gdwSrcColorKeyOwnerVW &= ~(lpSrcSurfaceData->dwOverlayFlags & FLG_VW_MASK); lpInput->ddRVal = DDERR_OUTOFCAPS; return(DDHAL_DRIVER_HANDLED); } else if (lpSrcSurfaceData->dwOverlayFlags & 0x02000000) { if (gvidConfig.sizSrc.cx > gvidConfig.sizDisp.cx) { lpInput->ddRVal = DDERR_OUTOFCAPS; return(DDHAL_DRIVER_HANDLED); } lpSrcSurfaceData->dwOverlayFlags &= ~0x02000000; } #endif #endif /* WINNT_VER40 */ // Because of Microsoft's Overfly bug we must ignore DDOVER_DDFX completely // or Overfly reports DDERR_UNSUPPORTED at least in 1024x768x16 // So these guys can't even write a test app for WHQL that abides by their // own rules? if (lpInput->dwFlags & DDOVER_DDFX) { #ifndef WINNT_VER40 DBG_MESSAGE((" overlayFX.dwFlags = %08lX", lpInput->overlayFX.dwFlags)); DBG_MESSAGE((" overlayFX.dwDDFX = %08lX", lpInput->overlayFX.dwDDFX)); #endif #if ENABLE_MIRRORING if (lpInput->overlayFX.dwDDFX & DDOVERFX_MIRRORLEFTRIGHT) { bIsVWMirrored[dwVWIndex] = TRUE; } // For some bizarre reason, Microsoft's WHQL Overfly app sets the // DDOVER_DDFX flag but sets overlayFX.dwDDFX with complete junk // overlayFX.dwFlags also has junk // so we must ignore dwDDFX flags we don't support rather than return an // error. Gee that sound like good practice! #if 0 else { lpInput->ddRVal = DDERR_UNSUPPORTED; return DDHAL_DRIVER_HANDLED; } #endif #endif } #if DDRAW_COMPAT >= 50 if( lpInput->dwFlags & DDOVER_AUTOFLIP) { if(lpInput->lpDDSrcSurface->lpSurfMore->lpVideoPort) { if(lpInput->lpDDSrcSurface->lpSurfMore->lpVideoPort->dwNumAutoflip != 2) { //Hardware only support autoflip between 2 surfaces lpInput->ddRVal = DDERR_GENERIC; return (DDHAL_DRIVER_HANDLED); } } else { //Autoflip must use vport lpInput->ddRVal = DDERR_INVALIDPARAMS; return (DDHAL_DRIVER_HANDLED); } } #endif if ( (lpInput->dwFlags & DDOVER_SHOW) || bShowOverlay) { // Is somebody else using our hardware? if (((lpHardwareOwner[dwVWIndex] != NULL) && (lpHardwareOwner[dwVWIndex] != lpInput->lpDDSrcSurface)) || ((lpHardwareOwner[dwVWIndex] == NULL) && #ifdef WINNT_VER40 IsVWHardwareInUse(ppdev, dwVWIndex) #else IsVWHardwareInUse(lpDDHALData,dwVWIndex) #endif )) { lpInput->ddRVal = DDERR_OUTOFCAPS; return DDHAL_DRIVER_HANDLED; } // Is a valid destination surface specified? if (!(lpInput->lpDDDestSurface->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) { lpInput->ddRVal = DDERR_INVALIDPARAMS; return DDHAL_DRIVER_HANDLED; } // Save the rectangles #ifdef WINNT_VER40 if (! SaveRectangles(ppdev, dwVWIndex, bCheckBandwidth, dwBitCount, lpInput)) #else if (! SaveRectangles(dwVWIndex, bCheckBandwidth, dwBitCount,lpInput,lpDDHALData)) #endif { // SaveRectangles sets lpInput->ddRVal on error return DDHAL_DRIVER_HANDLED; } #if DDRAW_COMPAT >= 50 lpInput->lpDDSrcSurface->lpSurfMore->dwOverlayFlags = lpInput->dwFlags; #endif lpHardwareOwner[dwVWIndex] = lpInput->lpDDSrcSurface; lpSrcSurfaceData->dwOverlayFlags |= FLG_ENABLED; #ifdef WINNT_VER40 RegInitVideoVW(ppdev, dwVWIndex, lpInput->lpDDSrcSurface); #else RegInitVideoVW(dwVWIndex, lpInput->lpDDSrcSurface, lpDDHALData); #endif } else if (lpInput->dwFlags & DDOVER_HIDE) { if (lpHardwareOwner[dwVWIndex] == lpInput->lpDDSrcSurface) { lpHardwareOwner[dwVWIndex] = NULL; // clear panning show bit here // Turn the video off lpSrcSurfaceData->dwOverlayFlags &= ~FLG_ENABLED; #ifdef WINNT_VER40 DisableOverlay(ppdev, dwVWIndex); #else DisableOverlay(lpDDHALData, dwVWIndex); #endif } } else if (lpHardwareOwner[dwVWIndex] == lpInput->lpDDSrcSurface) { //Save the rectangles #ifdef WINNT_VER40 if (! SaveRectangles(ppdev, dwVWIndex, bCheckBandwidth, dwBitCount, lpInput)) #else if (! SaveRectangles(dwVWIndex, bCheckBandwidth, dwBitCount,lpInput,lpDDHALData)) #endif { // SaveRectangles sets lpInput->ddRVal on error return DDHAL_DRIVER_HANDLED; } #if DDRAW_COMPAT >= 50 lpInput->lpDDSrcSurface->lpSurfMore->dwOverlayFlags = lpInput->dwFlags; #endif #ifdef WINNT_VER40 RegInitVideoVW(ppdev, dwVWIndex, lpInput->lpDDSrcSurface); #else RegInitVideoVW(dwVWIndex, lpInput->lpDDSrcSurface, lpDDHALData); #endif } lpInput->ddRVal = DD_OK; return DDHAL_DRIVER_HANDLED; } /*************************************************************************** * * FUNCTION: SetPosition * * DESCRIPTION: * ****************************************************************************/ STATIC DWORD SetPosition ( #ifdef WINNT_VER40 PDEV *ppdev, PDD_SETOVERLAYPOSITIONDATA lpInput #else LPDDHAL_SETOVERLAYPOSITIONDATA lpInput #endif ) { LP_SURFACE_DATA lpSrcSurfaceData; DWORD dwVWIndex; #ifndef WINNT_VER40 LPGLOBALDATA lpDDHALData = GetDDHALContext( lpInput->lpDD); #endif #ifndef WINNT_VER40 DBG_MESSAGE(("Overlay SetPosition (lpInput = 0x%08lX)", lpInput)); #endif if (0 == lpInput->lpDDSrcSurface->dwReserved1) { lpInput->ddRVal = DDERR_NOTAOVERLAYSURFACE; return DDHAL_DRIVER_HANDLED; } lpSrcSurfaceData = GET_SURFACE_DATA_PTR(lpInput->lpDDSrcSurface); dwVWIndex = GetVideoWindowIndex(lpSrcSurfaceData->dwOverlayFlags); ASSERT(dwNumVideoWindows > dwVWIndex); if (lpHardwareOwner[dwVWIndex] == lpInput->lpDDSrcSurface) { // Update the rectangles grOverlayDest[dwVWIndex].right = (int)(grOverlayDest[dwVWIndex].right - grOverlayDest[dwVWIndex].left) + (int)lpInput->lXPos; grOverlayDest[dwVWIndex].left = (int) lpInput->lXPos; grOverlayDest[dwVWIndex].bottom = (int)(grOverlayDest[dwVWIndex].bottom - grOverlayDest[dwVWIndex].top) + (int)lpInput->lYPos; grOverlayDest[dwVWIndex].top = (int) lpInput->lYPos; #ifdef WINNT_VER40 RegMoveVideoVW(ppdev, dwVWIndex, lpInput->lpDDSrcSurface); #else RegMoveVideoVW(dwVWIndex, lpInput->lpDDSrcSurface, lpDDHALData); #endif } lpInput->ddRVal = DD_OK; return DDHAL_DRIVER_HANDLED; } /*************************************************************************** * * FUNCTION: GetOverlayFlipStatus * * DESCRIPTION: * ****************************************************************************/ STATIC DWORD GetOverlayFlipStatus ( #ifdef WINNT_VER40 PDEV *ppdev, #else LPGLOBALDATA lpDDHALData, #endif FLATPTR fpVidMem, DWORD dwVWIndex ) { if (gsOverlayFlip.bFlipFlag && ((fpVidMem == 0) || (fpVidMem == gsOverlayFlip.fpFlipFrom))) { #if 1 // if arm bit is set then some action is still pending // so fail ASSERT(dwNumVideoWindows > dwVWIndex); if (VW_ARM & ((PVGAR)lpDDHALData->RegsAddress)->VideoWindow[dwVWIndex].grVW_CONTROL0) return (DWORD)DDERR_WASSTILLDRAWING; #else __int64 ttime; int iTemp; DBG_MESSAGE(("GetOverlayFlipStatus (fpVidMem = 0x%08lX)", fpVidMem)); // If the current scanline is less than the flip scan line, // we know that a VSYNC has occurred. iTemp = CurrentVLine(lpDDHALData); if (gsOverlayFlip.dwFlipScanline > (DWORD) iTemp) { // Don't allow access during the vertical retrace if (iTemp == 0) { if (gsOverlayFlip.bWasEverInDisplay) { gsOverlayFlip.bHaveEverCrossedVBlank = TRUE; } return (DWORD)DDERR_WASSTILLDRAWING; } } // Otherwise, we can check to see if 1) we have ever // been in a vertical retrace or 2) if a fixed amount of time // has expired. else if (gsOverlayFlip.bHaveEverCrossedVBlank == FALSE) { gsOverlayFlip.bWasEverInDisplay = TRUE; QueryPerformanceCounter((LARGE_INTEGER *)&ttime); if ((ttime-gsOverlayFlip.liFlipTime) <= gsOverlayFlip.dwFlipDuration) { return (DWORD)DDERR_WASSTILLDRAWING; } } #endif gsOverlayFlip.bFlipFlag = FALSE; } return DD_OK; } /*************************************************************************** * * FUNCTION: ComputeVWZoomCodes * * DESCRIPTION: Computes HACCUM_STP, HACCUM_SD, * VACCUM_STP, VACCUM_SDA and VACCUM_SDB * ****************************************************************************/ STATIC VOID ComputeVWZoomCodes ( #ifdef WINNT_VER40 PDEV *ppdev, #endif DWORD dwVWIndex, VWDATA *pVWData ) { SIZEL Dst; SIZEL Src; Dst.cx = grOverlayDest[dwVWIndex].right - grOverlayDest[dwVWIndex].left; Src.cx = grOverlaySrc[dwVWIndex].right - grOverlaySrc[dwVWIndex].left; if (Dst.cx == Src.cx) { // no horizontal resize pVWData->HACCUM_STP = 0x00010000; } else if (Dst.cx > Src.cx) { // make sure we aren't going beyond hw capabilities ASSERT(Dst.cx <= 8 * Src.cx); // horizontal stretch // // ideally zoom code = 256 * (256 * Src.cx / Dst.cx) // we always want to truncate (256 * Src.cy / Dst.cx) // because truncating will give us back a Src.cx which is less than or // equal to the actual width of the source and we will never overrun the // source extent (and won't get the green stripe) pVWData->HACCUM_STP = (256 * 256 * Src.cx) / Dst.cx; } else { // make sure we aren't going beyond hw capabilities ASSERT(2 * Dst.cx >= Src.cx); // horizontal shrink // // this is the zoom code for Src.cx/2 be stretched to Dst.cx // using 128 seems to give a zoom code one too high // then we get the green stripe on the right edge of the video pVWData->HACCUM_STP = (256 * 127 * Src.cx) / Dst.cx; pVWData->CONTROL0 |= VW_XShrinkBy2; } // Just set horizontal seeds to zero for now pVWData->HACCUM_SD = 0; Dst.cy = grOverlayDest[dwVWIndex].bottom - grOverlayDest[dwVWIndex].top; Src.cy = grOverlaySrc[dwVWIndex].bottom - grOverlaySrc[dwVWIndex].top; if (Dst.cy == Src.cy) { pVWData->VACCUM_STP = 0x00010000; } else if (Dst.cy > Src.cy) { // make sure we aren't going beyond hw capabilities ASSERT(Dst.cy <= 8 * Src.cy); // vertical stretch // // ideally zoom code = 256 * (256 * Src.cy / Dst.cy) // we always want to truncate (256 * Src.cy / Dst.cy) // because truncating will give us back a Src.cy which is less than or // equal to the actual size of the source and we will never overrun the // source extent (and won't get the green stripe) // using 256 seems to give a zoom code one too high for full screen // then we get garbage on the bottom of the screen pVWData->VACCUM_STP = (256 * 255 * Src.cy) / Dst.cy; } else { // vertical shrink // // ideally zoom code = 256 * (256 * Dst.cy / Src.cy) // we always want to round up (256 * Dst.cy / Src.cy) // because rounding up will give us back a Src.cy which is less than or // equal to the actual size of the source and we will never overrun the // source extent (and won't get the green stripe) pVWData->VACCUM_STP = (256 * 256 * Dst.cy + 256 * (Src.cy - 1)) / Src.cy; pVWData->CONTROL1 |= VW_YShrinkEn; } // Just set vertical seeds to zero for now pVWData->VACCUM_SDA = 0; pVWData->VACCUM_SDB = 0; } /*************************************************************************** * * FUNCTION: ComputeVWPositionData * * DESCRIPTION: Computes HSTRT, HEND, HSDSZ, VSTRT, VEND, * PD_STRT_ADDR and SD_PITCH * ****************************************************************************/ STATIC VOID ComputeVWPositionData ( PRECTL pVideoRect, PRECTL pOverlaySrc, PRECTL pOverlayDest, #ifdef WINNT_VER40 PDD_SURFACE_GLOBAL pGbl, #else LPDDRAWI_DDRAWSURFACE_GBL pGbl, LPGLOBALDATA lpDDHALData, #endif DWORD dwBitCount, VWDATA *pVWData, BOOL bCLPL ) { DWORD dwSurfBase,dwSurfOffset; pVWData->HSTRT = LOWORD(pVideoRect->left); pVWData->HEND = LOWORD(pVideoRect->right) - 1; pVWData->HSDSZ = (WORD)(pOverlaySrc->right - pOverlaySrc->left); pVWData->VSTRT = LOWORD(pVideoRect->top); pVWData->VEND = LOWORD(pVideoRect->bottom) - 1; #ifdef WINNT_VER40 dwSurfBase = pGbl->fpVidMem; #else dwSurfBase = (pGbl->fpVidMem - lpDDHALData->ScreenAddress); #endif dwSurfOffset = pOverlaySrc->top * pGbl->lPitch + pOverlaySrc->left * (dwBitCount / 8); pVWData->PSD_STRT_ADDR = dwSurfBase + dwSurfOffset; #if ENABLE_YUVPLANAR if (bCLPL) { // qword aligned offset of UV interleaved data in aperture 0 // need same offset into UV data as offset into Y data // so it's just PSD_STRT_ADDR plus area of Y data pVWData->PSD_UVSTRT_ADDR = dwSurfBase + (((pGbl->wHeight * pGbl->lPitch) + 7) & ~7) + (dwSurfOffset / 2); } else pVWData->PSD_UVSTRT_ADDR = 0; #endif #if ENABLE_MIRRORING if (bIsVWMirrored[dwVWIndex]) { // for mirroring // point to the last byte of the last pixel on the right edge of the source pVWData->PSD_STRT_ADDR += (DWORD)(pOverlaySrc->right - pOverlaySrc->left - 1); } #endif pVWData->SD_PITCH = (WORD)(pGbl->lPitch); } /*************************************************************************** * * FUNCTION: RGBtoYCrCb * * DESCRIPTION: Conversion equations are from page 42 of the second edition * of "Video Demystified" by Keith Jack * ****************************************************************************/ STATIC DWORD INLINE RGBtoYCbCr ( DWORD dwRGB ) { long Y, Cr, Cb; long r, g, b; r = (dwRGB & 0xF800) >> 8; g = (dwRGB & 0x07E0) >> 3; b = (dwRGB & 0x001F) << 3; Y = ( 77 * r + 150 * g + 29 * b) / 256; // max value of Y from this is if r, g & b are all 255 then Y = 255 // min value of Y from this is if r, g & b are all 0 then Y = 0 // so don't need to clamp Y Cb = (-44 * r - 87 * g + 131 * b) / 256 + 128; // max value of Cb is if r & g are 0 and b is 255 then Cb = 258 // min value of Cb is if r & g are 255 and b is 0 then Cb = -2 // so need to clamp Cb between 0 and 255 if (255 < Cb) Cb = 255; else if (0 > Cb) Cb = 0; Cr = (131 * r - 110 * g - 21 * b) / 256 + 128; // max value of Cr is if r is 255 and g & b are 0 then Cr = 258 // min value of Cr is if r is 0 and g & b are 255 then Cr = -2 // so need to clamp Cr between 0 and 255 if (255 < Cr) Cr = 255; else if (0 > Cr) Cr = 0; return (((Y & 0xFF) << 16) | ((Cb & 0xFF) << 8) | ((Cr & 0xFF))); } /*************************************************************************** * * FUNCTION: DetermineVWColorKeyData * * DESCRIPTION: Determines CLRKEY_MIN & CLRKEY_MAX or * CHRMKEY_MIN & CHRMKEY_MAX * ****************************************************************************/ STATIC VOID DetermineVWColorKeyData ( #ifdef WINNT_VER40 PDEV *ppdev, #else LPGLOBALDATA lpDDHALData, #endif DWORD dwOverlayFlags, DWORD dwBitCount, VWDATA *pVWData ) { if (FLG_COLOR_KEY & dwOverlayFlags) { // destination color key, uses color key on 5465 pVWData->CLRKEY_MIN = gdwColorKey; pVWData->CLRKEY_MAX = gdwColorKey; pVWData->CONTROL0 &= ~VW_OCCLUDE_MASK; pVWData->CONTROL0 |= (COLOR_KEY << OCCLUDE_SHIFT); } else if (FLG_SRC_COLOR_KEY & dwOverlayFlags) { PVGAR pREG = (PVGAR)lpDDHALData->RegsAddress; BYTE r,g,b; // source color key, uses chroma key on 5465 switch (dwBitCount) { case 8: // read colors from the DAC LL8(grPalette_Read_Address,(BYTE)(gdwSrcColorKeyLow & 0xFF)); r = pREG->grPalette_Data; g = pREG->grPalette_Data; b = pREG->grPalette_Data; pVWData->CHRMKEY_MIN = ((DWORD)(r) << 16) | ((DWORD)(g) << 8) | ((DWORD)(b)); LL8(grPalette_Read_Address,(BYTE)(gdwSrcColorKeyHigh & 0xFF)); r = pREG->grPalette_Data; g = pREG->grPalette_Data; b = pREG->grPalette_Data; pVWData->CHRMKEY_MAX = ((DWORD)(r) << 16) | ((DWORD)(g) << 8) | ((DWORD)(b)); break; case 16: if ((FLG_UYVY | FLG_YUY2) & dwOverlayFlags) { // Since we are currently using ITU 601 compliant YUV data // convert color key to YCrCb pVWData->CHRMKEY_MIN = RGBtoYCbCr(gdwSrcColorKeyLow); pVWData->CHRMKEY_MAX = RGBtoYCbCr(gdwSrcColorKeyHigh); } else { // convert 5:6:5 to true color pVWData->CHRMKEY_MIN = ((gdwSrcColorKeyLow & 0xF800) << 8) | // red ((gdwSrcColorKeyLow & 0x07E0) << 5) | // green ((gdwSrcColorKeyLow & 0x001F) << 3); // blue pVWData->CHRMKEY_MAX = ((gdwSrcColorKeyHigh & 0xF800) << 8) | // red ((gdwSrcColorKeyHigh & 0x07E0) << 5) | // green ((gdwSrcColorKeyHigh & 0x001F) << 3); // blue } break; case 24: case 32: pVWData->CHRMKEY_MIN = (gdwSrcColorKeyLow & 0x00FFFFFF); pVWData->CHRMKEY_MAX = (gdwSrcColorKeyHigh & 0x00FFFFFF); break; } pVWData->CONTROL0 &= ~VW_OCCLUDE_MASK; pVWData->CONTROL0 |= (CHROMA_KEY << OCCLUDE_SHIFT); } else { pVWData->CONTROL0 &= ~VW_OCCLUDE_MASK; pVWData->CONTROL0 |= (NO_OCCLUSION << OCCLUDE_SHIFT); } } /*************************************************************************** * * FUNCTION: ComputeVWFifoThreshold * * DESCRIPTION: * ****************************************************************************/ static INLINE VOID ComputeVWFifoThreshold ( #ifdef WINNT_VER40 PDEV *ppdev, #else LPGLOBALDATA lpDDHALData, #endif VWDATA *pVWData ) { PVGAR pREG = (PVGAR)lpDDHALData->RegsAddress; pREG->grDisplay_Threshold_and_Tiling = (pREG->grDisplay_Threshold_and_Tiling & 0xFFC0) | (gsProgRegs.DispThrsTiming & 0x003F); pVWData->FIFO_THRSH = gsProgRegs.VW0_FIFO_THRSH; } /*************************************************************************** * * FUNCTION: PanOverlay1_Init * * DESCRIPTION: Save data for panning overlay window one. * Clip lpVideoRect to panning viewport. * ****************************************************************************/ static INLINE VOID PanOverlay1_Init ( #ifdef WINNT_VER40 PDEV *ppdev, #endif LPRECTL lpVideoRect, LPRECTL lpOverlaySrc, LPRECTL lpOverlayDest ) { // This is not necessary on Laguna since we can't pan the screen // clip left edge of destination if (0 > (lpVideoRect->left = lpOverlayDest->left)) lpVideoRect->left = 0; // clip right edge of destination #ifdef WINNT_VER40 if ((LONG)ppdev->cxScreen < (lpVideoRect->right = lpOverlayDest->right)) lpVideoRect->right = (LONG)ppdev->cxScreen; #else if ((LONG)pPDevice->deWidth < (lpVideoRect->right = lpOverlayDest->right)) lpVideoRect->right = (LONG)pPDevice->deWidth; #endif // clip top edge of destination if (0 > (lpVideoRect->top = lpOverlayDest->top)) lpVideoRect->top = 0; // clip bottom edge of destination #ifdef WINNT_VER40 if ((LONG)ppdev->cyScreen < (lpVideoRect->bottom = lpOverlayDest->bottom)) lpVideoRect->bottom = (LONG)ppdev->cyScreen; #else if ((LONG)pPDevice->deHeight < (lpVideoRect->bottom = lpOverlayDest->bottom)) lpVideoRect->bottom = (LONG)pPDevice->deHeight; #endif } /*************************************************************************** * * FUNCTION: RegInitVideoVW * * DESCRIPTION: This function is called to program the video format and * the physical offset of the Video Window video data * in the frame buffer. * ****************************************************************************/ STATIC BOOL RegInitVideoVW ( #ifdef WINNT_VER40 PDEV *ppdev, DWORD dwVWIndex, PDD_SURFACE_LOCAL lpSurface #else DWORD dwVWIndex, LPDDRAWI_DDRAWSURFACE_LCL lpSurface, LPGLOBALDATA lpDDHALData #endif ) { LP_SURFACE_DATA lpSurfaceData = GET_SURFACE_DATA_PTR(lpSurface); VWDATA VWData; BOOL bOverlayTooSmall = FALSE; DWORD dwFourcc; LONG lPitch; DWORD dwBitCount; RECTL rVideoRect; PVGAR pREG = (PVGAR)lpDDHALData->RegsAddress; #if DDRAW_COMPAT >= 50 DWORD dwSrfFlags = FALSE; #endif DWORD width; //////#ifndef WINNT_VER40 PDD_ATTACHLIST lpSurfaceAttached; LP_SURFACE_DATA lpSurfaceDataTmp; //////#endif ASSERT(dwNumVideoWindows > dwVWIndex); // Determine the format of the video data if (lpSurface->dwFlags & DDRAWISURF_HASPIXELFORMAT) { GetFormatInfo(&(lpSurface->lpGbl->ddpfSurface), &dwFourcc, &dwBitCount); } else { dwBitCount = BITSPERPIXEL; if (16 == dwBitCount) dwFourcc = BI_BITFIELDS; // 5:6:5 else dwFourcc = BI_RGB; // 8bpp, 5:5:5, 24bpp & 32bpp } #ifdef WINNT_VER40 PanOverlay1_Init(ppdev,&rVideoRect,&grOverlaySrc[dwVWIndex],&grOverlayDest[dwVWIndex]); #else PanOverlay1_Init(&rVideoRect,&grOverlaySrc[dwVWIndex],&grOverlayDest[dwVWIndex]); #endif // rVideoRect is now adjusted and clipped to the panning viewport. // Disable overlay if totally clipped by viewport. if (((rVideoRect.right - rVideoRect.left) <= 0) || ((rVideoRect.bottom- rVideoRect.top ) <= 0)) { #ifdef WINNT_VER40 DisableOverlay(ppdev, dwVWIndex); #else DisableOverlay(lpDDHALData,dwVWIndex); #endif return TRUE; } memset(&VWData, 0, sizeof(VWData)); lPitch = lpSurface->lpGbl->lPitch; #ifdef WINNT_VER40 ComputeVWZoomCodes(ppdev, dwVWIndex, &VWData); #else ComputeVWZoomCodes(dwVWIndex, &VWData); #endif ComputeVWPositionData(&rVideoRect, &grOverlaySrc[dwVWIndex], &grOverlayDest[dwVWIndex], lpSurface->lpGbl, #ifndef WINNT_VER40 lpDDHALData, #endif dwBitCount, &VWData, FOURCC_YUVPLANAR == dwFourcc); lpSurfaceData->dwOverlayOffset = //This offset will be used in FlipOverlay VWData.PSD_STRT_ADDR - // and VPE lpSurface->lpGbl->fpVidMem #ifndef WINNT_VER40 + lpDDHALData->ScreenAddress #endif ; /////////#ifndef WINNT_VER40 //Update all the attached surfaces lpSurfaceAttached = lpSurface->lpAttachListFrom; while( lpSurfaceAttached) { if(lpSurfaceAttached->lpAttached) { lpSurfaceDataTmp = GET_SURFACE_DATA_PTR(lpSurfaceAttached->lpAttached); lpSurfaceDataTmp->dwOverlayOffset = lpSurfaceData->dwOverlayOffset; lpSurfaceAttached = lpSurfaceAttached->lpAttached->lpAttachListFrom; } else break; } lpSurfaceAttached = lpSurface->lpAttachList; while( lpSurfaceAttached) { if(lpSurfaceAttached->lpAttached) { lpSurfaceDataTmp = GET_SURFACE_DATA_PTR(lpSurfaceAttached->lpAttached); lpSurfaceDataTmp->dwOverlayOffset = lpSurfaceData->dwOverlayOffset; lpSurfaceAttached = lpSurfaceAttached->lpAttached->lpAttachList; } else break; } //////////#endif #if ENABLE_MIRRORING // Mirror Video Windows support. if (bIsVWMirrored[dwVWIndex]) VWData.CONTROL0 |= VW_HMIRR_EN; #endif // Xing, isn't the memset above enough? VWData.SSD_STRT_ADDR = 0L; #if DDRAW_COMPAT >= 50 if (gwNotify & VPE_ON) { if((lpSurface->lpSurfMore->lpVideoPort != NULL)&& (lpSurface->ddsCaps.dwCaps & DDSCAPS_VIDEOPORT)) { if((lpSurface->lpSurfMore->dwOverlayFlags & DDOVER_BOB) &&(lpSurface->lpSurfMore->lpVideoPort->ddvpInfo.dwVPFlags & DDVP_INTERLEAVE)) { dwSrfFlags = DDOVER_BOB; } else if((lpSurface->lpSurfMore->lpVideoPort->ddvpInfo.dwVPFlags &DDVP_AUTOFLIP) &&(lpSurface->lpSurfMore->dwOverlayFlags & DDOVER_AUTOFLIP) && (lpSurface->lpAttachListFrom != NULL) && (lpSurface->lpAttachListFrom->lpAttached != NULL)) { dwSrfFlags = DDOVER_AUTOFLIP; } } } if((dwSrfFlags & DDOVER_BOB) ||(!dwSrfFlags &&(lpSurface->lpSurfMore->dwOverlayFlags & DDOVER_INTERLEAVED))) { RECTL rcTemp; rcTemp = grOverlaySrc[dwVWIndex]; grOverlaySrc[dwVWIndex].top >>=1; grOverlaySrc[dwVWIndex].bottom >>=1; //use half source size to VWData.CONTROL1 &= ~VW_YShrinkEn; //find zoom factor ComputeVWZoomCodes(dwVWIndex, &VWData); grOverlaySrc[dwVWIndex] = rcTemp; VWData.SD_PITCH <<= 1; VWData.CONTROL0 &= ~0x30000ul; if(dwSrfFlags & DDOVER_BOB) { VWData.SSD_STRT_ADDR = VWData.PSD_STRT_ADDR + lPitch; VWData.CONTROL0 |= 0x20000ul; //enable buffer two } } else if(dwSrfFlags & DDOVER_AUTOFLIP) { VWData.SSD_STRT_ADDR = lpSurfaceData->dwAutoBaseAddr2 + lpSurfaceData->dwOverlayOffset; if( VWData.PSD_STRT_ADDR == VWData.SSD_STRT_ADDR ) { VWData.PSD_STRT_ADDR = lpSurfaceData->dwAutoBaseAddr1 + lpSurfaceData->dwOverlayOffset; } VWData.CONTROL0 &= ~0x30000ul; VWData.CONTROL0 |= 0x20000ul; //enable the second buffer if(!(lpSurface->lpSurfMore->dwOverlayFlags & DDOVER_BOB)) { //For non-smooth-interlaced auto-flip these two address need // to be switched. HW BUG DWORD dwTmp = VWData.PSD_STRT_ADDR; VWData.PSD_STRT_ADDR = VWData.SSD_STRT_ADDR; VWData.SSD_STRT_ADDR = dwTmp; } } if(lpSurface->lpSurfMore->dwOverlayFlags & DDOVER_BOB) { BOOL fSDAHalf = TRUE; #if ENABLE_MIRRORING if (lpInput->overlayFX.dwDDFX & DDOVERFX_MIRRORLEFTRIGHT) fSDAHalf = !fSDAHalf; #endif if(VWData.VACCUM_STP >= 0x8000ul) fSDAHalf = !fSDAHalf; if(fSDAHalf) { VWData.VACCUM_SDA = 0x8000ul; VWData.VACCUM_SDB = 0ul; } else { VWData.VACCUM_SDA = 0ul; VWData.VACCUM_SDB = 0x8000ul; } VWData.CONTROL0 |= 0x8ul; } #endif if (lpSurfaceData->dwOverlayFlags & FLG_ENABLED) VWData.CONTROL0 |= (VW_VWE | VW_ARM); // set source data format if (dwFourcc == BI_RGB) { if (dwBitCount == 16) { VWData.CONTROL0 |= (SD_RGB16_555 << SD_FRMT_SHIFT); } #if ENABLE_SD_RGB32 else if (dwBitCount == 32) { VWData.CONTROL0 |= (SD_RGB32 << SD_FRMT_SHIFT); } #endif } else if (dwFourcc == BI_BITFIELDS) { VWData.CONTROL0 |= (SD_RGB16_565 << SD_FRMT_SHIFT); } #if ENABLE_YUVPLANAR else if (dwFourcc == FOURCC_YUVPLANAR) { VWData.CONTROL0 |= (SD_YUV420 << SD_FRMT_SHIFT); } #endif else if (FOURCC_UYVY == dwFourcc) { VWData.CONTROL0 |= (SD_YUV422 << SD_FRMT_SHIFT); } #ifdef WINNT_VER40 DetermineVWColorKeyData(ppdev, lpSurfaceData->dwOverlayFlags, dwBitCount, &VWData); #else DetermineVWColorKeyData(lpDDHALData,lpSurfaceData->dwOverlayFlags, dwBitCount, &VWData); #endif #ifdef WINNT_VER40 ComputeVWFifoThreshold(ppdev, &VWData); #else ComputeVWFifoThreshold(lpDDHALData,&VWData); #endif // Now start programming the registers #ifdef WINNT_VER40 WaitForVWArmToClear(ppdev, dwVWIndex); #else WaitForVWArmToClear(lpDDHALData, dwVWIndex); #endif ASSERT(! (pREG->VideoWindow[dwVWIndex].grVW_TEST0 & VW_PostImed)); LL16(VideoWindow[dwVWIndex].grVW_HSTRT, VWData.HSTRT); LL16(VideoWindow[dwVWIndex].grVW_HEND, VWData.HEND); LL16(VideoWindow[dwVWIndex].grVW_HSDSZ, VWData.HSDSZ); LL32(VideoWindow[dwVWIndex].grVW_HACCUM_STP, VWData.HACCUM_STP); LL32(VideoWindow[dwVWIndex].grVW_HACCUM_SD, VWData.HACCUM_SD); LL16(VideoWindow[dwVWIndex].grVW_VSTRT, VWData.VSTRT); LL16(VideoWindow[dwVWIndex].grVW_VEND, VWData.VEND); LL32(VideoWindow[dwVWIndex].grVW_VACCUM_STP, VWData.VACCUM_STP); LL32(VideoWindow[dwVWIndex].grVW_VACCUM_SDA, VWData.VACCUM_SDA); LL32(VideoWindow[dwVWIndex].grVW_VACCUM_SDB, VWData.VACCUM_SDB); LL32(VideoWindow[dwVWIndex].grVW_PSD_STRT_ADDR, VWData.PSD_STRT_ADDR); LL32(VideoWindow[dwVWIndex].grVW_SSD_STRT_ADDR, VWData.SSD_STRT_ADDR); #if ENABLE_YUVPLANAR if (dwFourcc == FOURCC_YUVPLANAR) { LL32(VideoWindow[dwVWIndex].grVW_PSD_UVSTRT_ADDR, VWData.PSD_UVSTRT_ADDR); LL32(VideoWindow[dwVWIndex].grVW_SSD_UVSTRT_ADDR, VWData.SSD_UVSTRT_ADDR); } #endif LL16(VideoWindow[dwVWIndex].grVW_SD_PITCH, VWData.SD_PITCH); if (FLG_SRC_COLOR_KEY & lpSurfaceData->dwOverlayFlags) { LL32(VideoWindow[dwVWIndex].grVW_CHRMKEY_MIN, VWData.CHRMKEY_MIN); LL32(VideoWindow[dwVWIndex].grVW_CHRMKEY_MAX, VWData.CHRMKEY_MAX); } else if (FLG_COLOR_KEY & lpSurfaceData->dwOverlayFlags) { LL32(VideoWindow[dwVWIndex].grVW_CLRKEY_MIN, VWData.CLRKEY_MIN); LL32(VideoWindow[dwVWIndex].grVW_CLRKEY_MAX, VWData.CLRKEY_MAX); } LL16(VideoWindow[dwVWIndex].grVW_FIFO_THRSH, VWData.FIFO_THRSH); LL32(VideoWindow[dwVWIndex].grVW_CONTROL1, VWData.CONTROL1); // fix for PDR #10815 // if src width >= 1536 bytes (or 3072 bytes for shrink) // disable vertical interpolation width = (grOverlaySrc[dwVWIndex].right - grOverlaySrc[dwVWIndex].left) * (dwBitCount / 8); if (VW_YShrinkEn & VWData.CONTROL1) width /= 2; if (width >= 1536) { // set replication bit in TEST0 reg pREG->VideoWindow[dwVWIndex].grVW_TEST0 |= VWVRepEnable; } else { // clear replication bit in TEST0 reg pREG->VideoWindow[dwVWIndex].grVW_TEST0 &= ~VWVRepEnable; } // write last to arm LL32(VideoWindow[dwVWIndex].grVW_CONTROL0, VWData.CONTROL0); return TRUE; } /*************************************************************************** * * FUNCTION: RegMoveVideoVW * * DESCRIPTION: This function is called to move the video window that has * already been programed. * ****************************************************************************/ STATIC VOID RegMoveVideoVW ( #ifdef WINNT_VER40 PDEV *ppdev, DWORD dwVWIndex, PDD_SURFACE_LOCAL lpSurface #else DWORD dwVWIndex, LPDDRAWI_DDRAWSURFACE_LCL lpSurface, LPGLOBALDATA lpDDHALData #endif ) { LP_SURFACE_DATA lpSurfaceData = GET_SURFACE_DATA_PTR(lpSurface); VWDATA VWData; DWORD dwFourcc; LONG lPitch; DWORD dwBitCount; RECTL rVideoRect; PVGAR pREG = (PVGAR)lpDDHALData->RegsAddress; ASSERT(dwNumVideoWindows > dwVWIndex); // Determine the format of the video data if (lpSurface->dwFlags & DDRAWISURF_HASPIXELFORMAT) { GetFormatInfo (&(lpSurface->lpGbl->ddpfSurface), &dwFourcc, &dwBitCount); } else { dwBitCount = BITSPERPIXEL; if (16 == dwBitCount) dwFourcc = BI_BITFIELDS; // 5:6:5 else dwFourcc = BI_RGB; // 8bpp, 5:5:5, 24bpp & 32bpp } #ifdef WINNT_VER40 PanOverlay1_Init(ppdev,&rVideoRect,&grOverlaySrc[dwVWIndex],&grOverlayDest[dwVWIndex]); #else PanOverlay1_Init(&rVideoRect,&grOverlaySrc[dwVWIndex],&grOverlayDest[dwVWIndex]); #endif // rVideoRect is now adjusted and clipped to the panning viewport. // Disable overlay if totally clipped by viewport. if (((rVideoRect.right - rVideoRect.left) <= 0) || ((rVideoRect.bottom- rVideoRect.top ) <= 0)) { #ifdef WINNT_VER40 DisableOverlay(ppdev, dwVWIndex); #else DisableOverlay(lpDDHALData, dwVWIndex); #endif return; } memset(&VWData, 0, sizeof(VWData)); VWData.CONTROL0 = pREG->VideoWindow[dwVWIndex].grVW_CONTROL0; if (lpSurfaceData->dwOverlayFlags & FLG_ENABLED) VWData.CONTROL0 |= VW_VWE; VWData.CONTROL0 |= VW_ARM; lPitch = lpSurface->lpGbl->lPitch; // if shrink in x, set shrink x by 2 bit in CONTROL0 // shrink in y is okay, because that bit is in CONTROL1 and // we aren't touching CONTROL1 here if ((grOverlayDest[dwVWIndex].right - grOverlayDest[dwVWIndex].left) < (grOverlaySrc[dwVWIndex].right - grOverlaySrc[dwVWIndex].left)) { VWData.CONTROL0 |= VW_XShrinkBy2; } ComputeVWPositionData(&rVideoRect, &grOverlaySrc[dwVWIndex], &grOverlayDest[dwVWIndex], lpSurface->lpGbl, #ifndef WINNT_VER40 lpDDHALData, #endif dwBitCount, &VWData, FOURCC_YUVPLANAR == dwFourcc); #if ENABLE_MIRRORING if (bIsVWMirrored[dwVWIndex]) VWData.CONTROL0 |= VW_HMIRR_EN; #endif // Xing, isn't the memset above enough? VWData.SSD_STRT_ADDR = 0; #if DDRAW_COMPAT >= 50 if( gwNotify & VPE_ON) { if(lpSurface->lpSurfMore->lpVideoPort != NULL) { if((lpSurface->lpSurfMore->lpVideoPort->ddvpInfo.dwVPFlags &DDVP_AUTOFLIP) && (lpSurface->lpSurfMore->dwOverlayFlags & DDOVER_AUTOFLIP) && (lpSurface->lpAttachListFrom != NULL) && (lpSurface->lpAttachListFrom->lpAttached != NULL)) { VWData.SSD_STRT_ADDR = lpSurfaceData->dwAutoBaseAddr2 + lpSurfaceData->dwOverlayOffset; if( VWData.PSD_STRT_ADDR == VWData.SSD_STRT_ADDR ) { VWData.PSD_STRT_ADDR = lpSurfaceData->dwAutoBaseAddr1 + lpSurfaceData->dwOverlayOffset; } VWData.CONTROL0 &= ~0x30000ul; VWData.CONTROL0 |= 0x20000ul; //enable the second buffer if(!(lpSurface->lpSurfMore->dwOverlayFlags & DDOVER_BOB)) { //For non-smooth-interlaced auto-flip these two address need // to be switched. HW BUG DWORD dwTmp = VWData.PSD_STRT_ADDR; VWData.PSD_STRT_ADDR = VWData.SSD_STRT_ADDR; VWData.SSD_STRT_ADDR = dwTmp; } } else if((lpSurface->lpSurfMore->dwOverlayFlags & DDOVER_BOB) &&(lpSurface->lpSurfMore->lpVideoPort->ddvpInfo.dwVPFlags & DDVP_INTERLEAVE)) { VWData.SSD_STRT_ADDR = VWData.PSD_STRT_ADDR + lPitch; } } } #endif // Now start programming the registers ASSERT(! (pREG->VideoWindow[dwVWIndex].grVW_TEST0 & VW_PostImed)); #ifdef WINNT_VER40 WaitForVWArmToClear(ppdev, dwVWIndex); #else WaitForVWArmToClear(lpDDHALData, dwVWIndex); #endif LL16(VideoWindow[dwVWIndex].grVW_HSTRT, VWData.HSTRT); LL16(VideoWindow[dwVWIndex].grVW_HEND, VWData.HEND); LL16(VideoWindow[dwVWIndex].grVW_HSDSZ, VWData.HSDSZ); LL16(VideoWindow[dwVWIndex].grVW_VSTRT, VWData.VSTRT); LL16(VideoWindow[dwVWIndex].grVW_VEND, VWData.VEND); LL32(VideoWindow[dwVWIndex].grVW_PSD_STRT_ADDR, VWData.PSD_STRT_ADDR); LL32(VideoWindow[dwVWIndex].grVW_SSD_STRT_ADDR, VWData.SSD_STRT_ADDR); #if ENABLE_YUVPLANAR if (dwFourcc == FOURCC_YUVPLANAR) { LL32(VideoWindow[dwVWIndex].grVW_PSD_UVSTRT_ADDR, VWData.PSD_UVSTRT_ADDR); LL32(VideoWindow[dwVWIndex].grVW_SSD_UVSTRT_ADDR, VWData.SSD_UVSTRT_ADDR); } #endif LL16(VideoWindow[dwVWIndex].grVW_SD_PITCH, VWData.SD_PITCH); LL32(VideoWindow[dwVWIndex].grVW_CONTROL0, VWData.CONTROL0); } /*************************************************************************** * * FUNCTION: ChipIOReadBWRegs * * DESCRIPTION: * ****************************************************************************/ BOOL ChipIOReadBWRegs ( #ifdef WINNT_VER40 PDEV *ppdev, #else LPGLOBALDATA lpDDHALData, #endif LPBWREGS pBWRegs ) { PVGAR pREG = (PVGAR)lpDDHALData->RegsAddress; #ifdef WINNT_VER40 pBWRegs->BCLK_Mult = pREG->grBCLK_Multiplier; #else pBWRegs->BCLK_Mult = pREG->grBCLK_numerator; #endif pBWRegs->MISCOutput = pREG->grMISC; pBWRegs->VCLK3Denom = pREG->grSRE; pBWRegs->VCLK3Num = pREG->grSR1E; pBWRegs->DispThrsTiming = pREG->grDisplay_Threshold_and_Tiling; pBWRegs->RIFControl = pREG->grRIF_CONTROL; pBWRegs->GfVdFormat = pREG->grFormat; #ifdef WINNT_VER40 pBWRegs->BCLK_Denom = pREG->grBCLK_Denominator; #else pBWRegs->BCLK_Denom = pREG->grBCLK_denom; #endif pBWRegs->Control2 = pREG->grCONTROL2; pBWRegs->CR1 = pREG->grCR1; pBWRegs->CR1E = pREG->grCR1E; #if ENABLE_256_BYTE_FETCH // if we are disabling 256 byte fetch when overlay or videoport // surfaces are created, then wipe out the 256 byte fetch related // bits in CONTROL2 // clear MONO_SAFETY_256 & BYTE_REQ_256 bits of CONTROL2 register pBWRegs->Control2 &= ~(MONO_SAFETY_256 | BYTE_REQ_256); #endif return TRUE; } #ifdef USE_OLD_BWEQ /*************************************************************************** * * FUNCTION: KillOverlay * * DESCRIPTION: Disable overlay in the following cases * ****************************************************************************/ BOOL KillOverlay ( #ifdef WINNT_VER40 PDEV *ppdev, #endif WORD wScreenX, UINT uScreenDepth ) { BWREGS bwregs; DWORD dwMCLK, dwVCLK; #ifdef WINNT_VER40 if(!ChipIOReadBWRegs(ppdev, &bwregs)) #else if(!ChipIOReadBWRegs(&bwregs)) #endif { return TRUE; } if(!ChipCalcMCLK(&bwregs, &dwMCLK)) { return TRUE; } if(!ChipCalcVCLK(&bwregs, &dwVCLK)) { return TRUE; } if(dwMCLK < 75000000) { if(uScreenDepth == 32 ) { if(wScreenX == 640 ) { if(dwVCLK > 32000000) return TRUE; } } } return FALSE; } #endif // USE_OLD_BWEQ #endif // WINNT_VER35