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

4313 lines
134 KiB

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