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