/*========================================================================== * * Copyright (C) 1994-1995 Microsoft Corporation. All Rights Reserved. * * File: ddmode.c * Content: DirectDraw mode support * History: * Date By Reason * ==== == ====== * 31-jan-95 craige split out of ddraw.c and enhanced * 27-feb-95 craige new sync. macros * 01-mar-95 craige Win95 mode stuff * 19-mar-95 craige use HRESULTs * 28-mar-95 craige made modeset work again * 01-apr-95 craige happy fun joy updated header file * 19-apr-95 craige check for invalid callback in EnumDisplayModes * 14-may-95 craige allow BPP change; validate EnumDisplayModes modes * 15-may-95 craige keep track of who changes the mode * 02-jun-95 craige keep track of the mode set by a process * 06-jun-95 craige added internal fn RestoreDisplayMode * 11-jun-95 craige don't allow mode switch if surfaces locked * 12-jun-95 craige new process list stuff * 25-jun-95 craige one ddraw mutex * 28-jun-95 craige ENTER_DDRAW at very start of fns * 30-jun-95 craige turned off > 16bpp * 01-jul-95 craige bug 106 - always went to last mode if mode not found * 02-jul-95 craige RestoreDisplayMode needs to call HEL too * 04-jul-95 craige YEEHAW: new driver struct; SEH * 05-jul-95 craige crank up priority during mode change * 13-jul-95 craige first step in mode set fix; made it work * 19-jul-95 craige bug 189 - graphics mode change being ignored sometimes * 20-jul-95 craige internal reorg to prevent thunking during modeset * 22-jul-95 craige bug 216 - random hang switching bpp - fixed by * using apps hwnd to hide things. * bug 230 - unsupported starting modes * 29-jul-95 toddla allways call HEL for SetMode for display driver * 10-aug-95 toddla EnumDisplayModes changed to take a lp not a lplp * 02-sep-95 craige bug 854: disable > 640x480 modes for rel 1 * 04-sep-95 craige bug 894: allow forcing of mode set * 08-sep-95 craige bug 932: set preferred mode after RestoreDisplayMode * 05-jan-96 kylej add interface structures * 09-jan-96 kylej enable >640x480 modes for rel 2 * 27-feb-96 colinmc ensured that bits-per-pixel is always tested for * when enumerating display modes and that enumeration * always assumes you will be in exclusive mode when * you actually do the mode switch * 11-mar-96 jeffno Dynamic mode switch stuff for NT * 24-mar-96 kylej Check modes with monitor profile * 26-mar-96 jeffno Added ModeChangedOnENTERDDRAW * ***************************************************************************/ #include "ddrawpr.h" #ifdef WINNT #include "ddrawgdi.h" #endif static DDHALMODEINFO ddmiModeXModes[] = { { 320, // width (in pixels) of mode 200, // height (in pixels) of mode 320, // pitch (in bytes) of mode 8, // bits per pixel (WORD)(DDMODEINFO_PALETTIZED | DDMODEINFO_MODEX), // flags 0, // refresh rate 0, // red bit mask 0, // green bit mask 0, // blue bit mask 0 // alpha bit mask }, { 320, // width (in pixels) of mode 240, // height (in pixels) of mode 320, // pitch (in bytes) of mode 8, // bits per pixel (WORD)(DDMODEINFO_PALETTIZED | DDMODEINFO_MODEX), // flags 0, // refresh rate 0, // red bit mask 0, // green bit mask 0, // blue bit mask 0 // alpha bit mask } }; #define NUM_MODEX_MODES (sizeof( ddmiModeXModes ) / sizeof( ddmiModeXModes[0] ) ) /* * makeDEVMODE * * create a DEVMODE struct (and flags) from mode info * * NOTE: We now always set the exclusive bit here and * we always set the bpp. This is because we were * previously not setting the bpp when not exclusive * so the checking code was always passing the surface * if it could do a mode of that size regardless of * color depth. * * The new semantics of EnumDisplayModes is that it * gives you a list of all display modes you could * switch into if you were exclusive. */ static void makeDEVMODE( LPDDRAWI_DIRECTDRAW_GBL this, LPDDHALMODEINFO pmi, BOOL inexcl, BOOL useRefreshRate, LPDWORD pcds_flags, LPDEVMODE pdm ) { pdm->dmSize = sizeof( *pdm ); pdm->dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL; if( useRefreshRate & (pmi->wRefreshRate != 0)) pdm->dmFields |= DM_DISPLAYFREQUENCY; pdm->dmPelsWidth = pmi->dwWidth; pdm->dmPelsHeight = pmi->dwHeight; pdm->dmBitsPerPel = pmi->dwBPP; pdm->dmDisplayFrequency = pmi->wRefreshRate; *pcds_flags = ( #ifdef WIN95 CDS_EXCLUSIVE | #endif CDS_FULLSCREEN ); } /* makeDEVMODE */ /* * AddModeXModes */ void AddModeXModes( LPDDRAWI_DIRECTDRAW_GBL pdrv ) { DWORD i; DWORD j; LPDDHALMODEINFO pmi_i; LPDDHALMODEINFO pmi_j; BOOL hasmode[NUM_MODEX_MODES]; DWORD newmodecnt; LPDDHALMODEINFO pmi; for( j=0;jdwNumModes;i++ ) { pmi_i = &pdrv->lpModeInfo[i]; for( j=0;jdwWidth == pmi_j->dwWidth) && (pmi_i->dwHeight == pmi_j->dwHeight) && (pmi_i->dwBPP == pmi_j->dwBPP) && ((pmi_i->wFlags & pmi_j->wFlags) & DDMODEINFO_PALETTIZED ) ) { // There is a mode already in the mode table the same as the modeX mode. // check to make sure that the driver really supports it DWORD cds_flags; DEVMODE dm; int cds_rc; makeDEVMODE( pdrv, pmi_i, TRUE, FALSE, &cds_flags, &dm ); cds_flags |= CDS_TEST; cds_rc = ChangeDisplaySettings( &dm, cds_flags ); if( cds_rc != 0) { // The driver does not support this mode even though it is in the mode table. // Mark the mode as unsupported and go ahead and add the ModeX mode. DPF( 3, "Mode %d not supported (%dx%dx%d), rc = %d, marking invalid", i, pmi_i->dwWidth, pmi_i->dwHeight, pmi_i->dwBPP, cds_rc ); pmi_i->wFlags |= DDMODEINFO_UNSUPPORTED; } else { // Don't add the ModeX mode, the driver supports a linear mode. hasmode[j] = TRUE; } } } } /* * count how many new modes we need */ newmodecnt = 0; for( j=0;j 0 ) { pmi = MemAlloc( (newmodecnt + pdrv->dwNumModes) * sizeof( DDHALMODEINFO ) ); if( pmi != NULL ) { memcpy( pmi, pdrv->lpModeInfo, pdrv->dwNumModes * sizeof( DDHALMODEINFO ) ); for( j=0;jdwNumModes ] = ddmiModeXModes[j]; pdrv->dwNumModes++; } } MemFree( pdrv->lpModeInfo ); pdrv->lpModeInfo = pmi; } } } /* AddModeXModes */ #ifdef WIN95 BOOL MonitorCanHandleMode( DWORD width, DWORD height, WORD refreshRate ) { DWORD max_monitor_x; DWORD min_refresh; DWORD max_refresh; max_monitor_x = (DWORD)DD16_GetMonitorMaxSize(1); if( ( max_monitor_x != 0 ) && ( width > max_monitor_x ) ) { DPF(3, "Mode's width greater than monitor maximum width (%d)", max_monitor_x); return FALSE; } if( refreshRate == 0 ) { // default refresh rate specified, no need to verify it return TRUE; } // a refresh rate was specified, we'd better make sure the monitor can handle it if(DD16_GetMonitorRefreshRateRanges(1, (int)width, (int) height, &min_refresh, &max_refresh)) { if( (min_refresh != 0) && (refreshRate < min_refresh) ) { DPF(3, "Requested refresh rate < monitor's minimum refresh rate (%d)", min_refresh); return FALSE; } if( (max_refresh != 0) && (refreshRate > max_refresh) ) { DPF(3, "Requested refresh rate > monitor's maximum refresh rate (%d)", max_refresh); return FALSE; } } // The monitor likes it. return TRUE; } #else BOOL MonitorCanHandleMode( DWORD width, DWORD height, WORD refreshRate ) { return TRUE; } #endif /* * setSurfaceDescFromMode */ static void setSurfaceDescFromMode( LPDDHALMODEINFO pmi, LPDDSURFACEDESC pddsd ) { memset( pddsd, 0, sizeof( DDSURFACEDESC ) ); pddsd->dwSize = sizeof( DDSURFACEDESC ); pddsd->dwFlags = DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT | DDSD_PITCH | DDSD_REFRESHRATE; pddsd->dwHeight = pmi->dwHeight; pddsd->dwWidth = pmi->dwWidth; pddsd->lPitch = pmi->lPitch; pddsd->dwRefreshRate = (DWORD)pmi->wRefreshRate; #ifdef WINNT // on NT, a refresh rate of 1 means adapter default. We expose // this to the application as a refresh rate of 0 which just means // pick a default refresh rate. if( pddsd->dwRefreshRate == 1 ) { pddsd->dwRefreshRate = 0; } #endif pddsd->ddpfPixelFormat.dwSize = sizeof( DDPIXELFORMAT ); pddsd->ddpfPixelFormat.dwFlags = DDPF_RGB; pddsd->ddpfPixelFormat.dwRGBBitCount = (DWORD)pmi->dwBPP; if( pmi->wFlags & DDMODEINFO_PALETTIZED ) { pddsd->ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED8; } else { pddsd->ddpfPixelFormat.dwRBitMask = pmi->dwRBitMask; pddsd->ddpfPixelFormat.dwGBitMask = pmi->dwGBitMask; pddsd->ddpfPixelFormat.dwBBitMask = pmi->dwBBitMask; pddsd->ddpfPixelFormat.dwRGBAlphaBitMask = pmi->dwAlphaBitMask; } } /* setSurfaceDescFromMode */ #ifdef WINNT /* * ModeChanged * * This function always calls FetchDirectDrawData. It's necessary in those cases' * where the focus changed but was handled by calling NT's DdDisableAllSurfaces * which doesn't bump the display uniqueness value, which makes ModeChangedOnENTERDDRAW * return without doing anything, so we'd never restore the ddraw object. */ BOOL NTModeChanged(LPDDRAWI_DIRECTDRAW_GBL pdrv) { DWORD oldorig=pdrv->dwModeIndexOrig; DPF(4,"NTModeChanged called"); uDisplaySettingsUnique=DdQueryDisplaySettingsUniqueness(); if (NULL == FetchDirectDrawData( pdrv, TRUE, 0 )) return FALSE; pdrv->dwModeIndexOrig=oldorig; return TRUE; } /* * ModeChangedOnENTERDDRAW * * This function is called via the ENTERDDRAW macro to check whether the mode * has changed. If it has, we update the driver object and the mode uniqueness. */ void ModeChangedOnENTERDDRAW(void) { LPDDRAWI_DIRECTDRAW_INT pdrv_int; LPDDRAWI_DIRECTDRAW_GBL pdrv; if ( DdQueryDisplaySettingsUniqueness() == uDisplaySettingsUnique ) return; /* * we don't want the helper coming and resetting a driver object which it doesn't * own and getting registered with the Kernel and all that other crap that could * happen */ if (dwHelperPid==GetCurrentProcessId()) { DPF(4,"Ignoring a mode change in ddhelp's process"); return; } DPF(4,"ModeChangedOnENTERDDRAW uniqueness changed"); pdrv_int = lpDriverObjectList; if (pdrv_int) { if (pdrv_int->lpLcl->lpGbl) { NTModeChanged(pdrv_int->lpLcl->lpGbl); return; } } } #endif //winnt #undef DPF_MODNAME #define DPF_MODNAME "GetDisplayMode" /* * DD_GetDisplayMode */ HRESULT DDAPI DD_GetDisplayMode( LPDIRECTDRAW lpDD, LPDDSURFACEDESC lpSurfaceDesc ) { LPDDRAWI_DIRECTDRAW_INT this_int; LPDDRAWI_DIRECTDRAW_LCL this_lcl; LPDDRAWI_DIRECTDRAW_GBL this; LPDDHALMODEINFO pmi; ENTER_DDRAW(); TRY { this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD; if( !VALID_DIRECTDRAW_PTR( this_int ) ) { LEAVE_DDRAW(); return DDERR_INVALIDOBJECT; } this_lcl = this_int->lpLcl; this = this_lcl->lpGbl; if( !VALIDEX_DDSURFACEDESC_PTR( lpSurfaceDesc ) ) { LEAVE_DDRAW(); return DDERR_INVALIDPARAMS; } if( this->dwModeIndex == DDUNSUPPORTEDMODE) { DPF_ERR( "Driver is in an unsupported mode" ); LEAVE_DDRAW(); return DDERR_UNSUPPORTEDMODE; } pmi = &this->lpModeInfo[ this->dwModeIndex ]; setSurfaceDescFromMode( pmi, lpSurfaceDesc ); } EXCEPT( EXCEPTION_EXECUTE_HANDLER ) { DPF_ERR( "Exception encountered validating parameters" ); LEAVE_DDRAW(); return DDERR_INVALIDPARAMS; } LEAVE_DDRAW(); return DD_OK; } /* DD_GetDisplayMode */ #undef DPF_MODNAME #define DPF_MODNAME "SetDisplayMode" /* * bumpPriority */ static DWORD bumpPriority( void ) { DWORD oldclass; HANDLE hprocess; hprocess = GetCurrentProcess(); oldclass = GetPriorityClass( hprocess ); SetPriorityClass( hprocess, HIGH_PRIORITY_CLASS ); return oldclass; } /* bumpPriority */ /* * restorePriority */ static void restorePriority( DWORD oldclass ) { HANDLE hprocess; hprocess = GetCurrentProcess(); SetPriorityClass( hprocess, oldclass ); } /* restorePriority */ #if 0 static char szClassName[] = "DirectDrawFullscreenWindow"; static HWND hWndTmp; static HCURSOR hSaveClassCursor; static HCURSOR hSaveCursor; static LONG lWindowLong; static RECT rWnd; #define OCR_WAIT_DEFAULT 102 /* * curtainsUp */ void curtainsUp( LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl ) { HCURSOR hcursor= (HCURSOR)LoadImage(NULL,MAKEINTRESOURCE(OCR_WAIT_DEFAULT),IMAGE_CURSOR,0,0,0); if( (pdrv_lcl->hWnd != 0) && IsWindow( (HWND) pdrv_lcl->hWnd ) ) { lWindowLong = GetWindowLong( (HWND) pdrv_lcl->hWnd, GWL_EXSTYLE ); SetWindowLong( (HWND) pdrv_lcl->hWnd, GWL_EXSTYLE, lWindowLong | (WS_EX_TOOLWINDOW) ); hSaveClassCursor = (HCURSOR) GetClassLong( (HWND) pdrv_lcl->hWnd, GCL_HCURSOR ); SetClassLong( (HWND) pdrv_lcl->hWnd, GCL_HCURSOR, (LONG) hcursor ); GetWindowRect( (HWND) pdrv_lcl->hWnd, (LPRECT) &rWnd ); SetWindowPos( (HWND) pdrv_lcl->hWnd, NULL, 0, 0, 10000, 10000, SWP_NOZORDER | SWP_NOACTIVATE ); SetForegroundWindow( (HWND) pdrv_lcl->hWnd ); } else { WNDCLASS cls; pdrv_lcl->hWnd = 0; cls.lpszClassName = szClassName; cls.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); cls.hInstance = hModule; cls.hIcon = NULL; cls.hCursor = hcursor; cls.lpszMenuName = NULL; cls.style = CS_BYTEALIGNCLIENT | CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS; cls.lpfnWndProc = (WNDPROC)DefWindowProc; cls.cbWndExtra = 0; cls.cbClsExtra = 0; RegisterClass(&cls); DPF( 3, "*** CREATEWINDOW" ); hWndTmp = CreateWindowEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW, szClassName, szClassName, WS_POPUP|WS_VISIBLE, 0, 0, 10000, 10000, NULL, NULL, hModule, NULL); DPF( 3, "*** BACK FROM CREATEWINDOW, hwnd=%08lx", hWndTmp ); if( hWndTmp != NULL) { SetForegroundWindow( hWndTmp ); } } hSaveCursor = SetCursor( hcursor ); } /* curtainsUp */ /* * curtainsDown */ void curtainsDown( LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl ) { if( (pdrv_lcl->hWnd != 0) && IsWindow( (HWND) pdrv_lcl->hWnd ) ) { SetWindowLong( (HWND) pdrv_lcl->hWnd, GWL_EXSTYLE, lWindowLong ); SetClassLong( (HWND) pdrv_lcl->hWnd, GCL_HCURSOR, (LONG) hSaveClassCursor ); SetCursor( hSaveCursor ); SetWindowPos( (HWND) pdrv_lcl->hWnd, NULL, rWnd.left, rWnd.top, rWnd.right-rWnd.left, rWnd.bottom-rWnd.top, SWP_NOZORDER | SWP_NOACTIVATE ); } else { SetCursor( hSaveCursor ); pdrv_lcl->hWnd = 0; if( hWndTmp != NULL ) { DestroyWindow( hWndTmp ); UnregisterClass( szClassName, hModule ); } } hWndTmp = NULL; } /* curtainsDown */ #endif /* * fetchModeXData */ static LPDDRAWI_DIRECTDRAW_GBL fetchModeXData( LPDDRAWI_DIRECTDRAW_GBL pdrv, LPDDHALMODEINFO pmi ) { DDHALINFO ddhi; LPDDRAWI_DIRECTDRAW_GBL new_pdrv; DDPIXELFORMAT dpf; extern dwFakeFlags; /* * initialize the DDHALINFO struct */ memset( &ddhi, 0, sizeof( ddhi ) ); ddhi.dwSize = sizeof( ddhi ); /* * capabilities supported (none) */ ddhi.ddCaps.dwCaps = 0; ddhi.ddCaps.dwFXCaps = 0; ddhi.ddCaps.dwCKeyCaps = 0; ddhi.ddCaps.ddsCaps.dwCaps = 0; /* * pointer to primary surface */ ddhi.vmiData.fpPrimary = 0xbad00bad; /* * build mode and pixel format info */ ddhi.vmiData.dwDisplayHeight = pmi->dwHeight; ddhi.vmiData.dwDisplayWidth = pmi->dwWidth; ddhi.vmiData.lDisplayPitch = pmi->lPitch; BuildPixelFormat( pmi, &dpf ); ddhi.vmiData.ddpfDisplay = dpf; /* * fourcc code information */ ddhi.ddCaps.dwNumFourCCCodes = 0; ddhi.lpdwFourCC = NULL; /* * Fill in heap info */ ddhi.vmiData.dwNumHeaps = 0; ddhi.vmiData.pvmList = NULL; /* * required alignments of the scanlines of each kind of memory * (DWORD is the MINIMUM) */ ddhi.vmiData.dwOffscreenAlign = sizeof( DWORD ); ddhi.vmiData.dwTextureAlign = sizeof( DWORD ); ddhi.vmiData.dwZBufferAlign = sizeof( DWORD ); /* * callback functions */ ddhi.lpDDCallbacks = NULL; ddhi.lpDDSurfaceCallbacks = NULL; ddhi.lpDDPaletteCallbacks = NULL; /* * create the driver object */ new_pdrv = DirectDrawObjectCreate( &ddhi, TRUE, pdrv ); DPF(6,"MODEX driver object's display is %dx%d, pitch is %d", ddhi.vmiData.dwDisplayHeight,ddhi.vmiData.dwDisplayWidth,ddhi.vmiData.lDisplayPitch); if( new_pdrv != NULL ) { new_pdrv->dwFlags |= DDRAWI_MODEX; if( new_pdrv->dwPDevice != 0 ) { new_pdrv->dwPDevice = 0; new_pdrv->lpwPDeviceFlags = (WORD *)&dwFakeFlags; } } DPF( 3, "ModeX DirectDraw object created" ); DPF( 3, " width=%ld, height=%ld, %ld bpp", new_pdrv->vmiData.dwDisplayWidth, new_pdrv->vmiData.dwDisplayHeight, new_pdrv->vmiData.ddpfDisplay.dwRGBBitCount ); DPF( 3, " lDisplayPitch = %ld", new_pdrv->vmiData.lDisplayPitch ); return new_pdrv; } /* fetchModeXData */ /* * stopModeX */ static void stopModeX( LPDDRAWI_DIRECTDRAW_GBL pdrv ) { DPF( 5, "***************** Turning off ModeX *****************" ); #ifdef WIN95 ModeX_RestoreMode(); #else DdSetModeX(pdrv,0); #endif pdrv->dwFlags &= ~DDRAWI_MODEX; DPF( 5, "**************** DONE Turning off ModeX **************" ); } /* stopModeX */ /* * SetDisplayMode */ HRESULT SetDisplayMode( LPDDRAWI_DIRECTDRAW_LCL this_lcl, DWORD modeidx, BOOL force, BOOL useRefreshRate) { DWORD rc; DDHAL_SETMODEDATA smd; LPDDHAL_SETMODE smfn; LPDDHAL_SETMODE smhalfn; LPDDHALMODEINFO pmi; BOOL inexcl; BOOL emulation; LPDDRAWI_DIRECTDRAW_GBL this; DWORD oldclass; BOOL use_modex; BOOL was_modex; DWORD real_modeidx; /* * Signify that the app at least tried to set a mode. * Redrawing of the desktop will only happen if this flag is set. */ this_lcl->dwLocalFlags |= DDRAWILCL_MODEHASBEENCHANGED; this = this_lcl->lpGbl; /* * don't allow if surfaces open */ if( !force ) { if( this->dwSurfaceLockCount > 0 ) { DPF_ERR( "Can't switch modes with locked surfaces!" ); return DDERR_SURFACEBUSY; } } if( modeidx == DDUNSUPPORTEDMODE ) { DPF_ERR( "Trying to set to an unsupported mode" ); return DDERR_UNSUPPORTEDMODE; } /* * is our current mode a disp dib mode? */ was_modex = FALSE; if( this->dwModeIndex != DDUNSUPPORTEDMODE ) { if( this->lpModeInfo[ this->dwModeIndex ].wFlags & DDMODEINFO_MODEX ) { was_modex = TRUE; } } /* * is the new mode a mode x mode */ pmi = &this->lpModeInfo[ modeidx ]; if( pmi->wFlags & DDMODEINFO_MODEX ) { DPF( 1, "Mode %ld is a ModeX mode", modeidx); use_modex = TRUE; } else { use_modex = FALSE; } /* * don't re-set the mode to the same one... * NOTE: we ALWAYS set the mode in emulation on Win95 since our index could be wrong */ #ifdef WINNT if( modeidx == this->dwModeIndex ) { DPF( 2, "%08lx: Current Mode match: %ldx%ld, %dbpp", GetCurrentProcessId(), pmi->dwWidth, pmi->dwHeight, pmi->dwBPP ); if( this->dwFlags & DDRAWI_DISPLAYDRV ) { RedrawWindow( NULL, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN ); } return DD_OK; } #else if( modeidx == this->dwModeIndex && !(this->dwFlags & DDRAWI_NOHARDWARE) ) { DPF( 2, "%08lx: Current Mode match: %ldx%ld, %dbpp", GetCurrentProcessId(), pmi->dwWidth, pmi->dwHeight, pmi->dwBPP ); return DD_OK; } #endif DPF( 5, "***********************************************" ); DPF( 5, "*** SETDISPLAYMODE: %ldx%ld, %dbpp", pmi->dwWidth, pmi->dwHeight, pmi->dwBPP ); DPF( 5, "*** dwModeIndex (current) = %ld", this->dwModeIndex ); DPF( 5, "*** modeidx (new) = %ld", modeidx ); DPF( 5, "*** use_modex = %ld", use_modex ); DPF( 5, "*** was_modex = %ld", was_modex ); DPF( 5, "***********************************************" ); /* * check if in exclusive mode */ inexcl = (this->lpExclusiveOwner == this_lcl); /* * check bpp */ if( (this->dwFlags & DDRAWI_DISPLAYDRV) && !force ) { if( (this->lpModeInfo[this->dwModeIndex].dwBPP != this->lpModeInfo[modeidx].dwBPP) || ((this->lpModeInfo[this->dwModeIndex].dwBPP == this->lpModeInfo[modeidx].dwBPP) && use_modex ) ) { if( !inexcl || !(this->dwFlags & DDRAWI_FULLSCREEN) ) { DPF_ERR( "Can't change BPP if not in exclusive fullscreen mode" ); return DDERR_NOEXCLUSIVEMODE; } } } /* * see if we need to shutdown modex mode */ if( was_modex ) { stopModeX( this ); } /* * see if we need to set a modex mode */ if( use_modex ) { DWORD i; LPDDHALMODEINFO tmp_pmi; real_modeidx = modeidx; for( i=0;idwNumModes;i++ ) { tmp_pmi = &this->lpModeInfo[ i ]; if( (tmp_pmi->dwWidth == 640) && (tmp_pmi->dwHeight == 480) && (tmp_pmi->dwBPP == 8) && (tmp_pmi->wFlags & DDMODEINFO_PALETTIZED) ) { DPF( 5, "MODEX: Setting to 640x480x8 first (index=%ld)", i ); modeidx = i; break; } } if( i == this->dwNumModes ) { DPF( 1, "Mode not supported" ); return DDERR_GENERIC; } } /* * get the driver to set the new mode... */ #ifdef WIN95 if( ( this->dwFlags & DDRAWI_DISPLAYDRV ) || ( this->dwFlags & DDRAWI_NOHARDWARE ) || ( this_lcl->lpDDCB->cbDDCallbacks.SetMode == NULL ) ) #else if (1) //always use mySetDisplayMode for NT #endif { smfn = this_lcl->lpDDCB->HELDD.SetMode; smhalfn = smfn; emulation = TRUE; DPF( 3, "Calling HEL SetMode" ); } else { smhalfn = this_lcl->lpDDCB->cbDDCallbacks.SetMode; smfn = this_lcl->lpDDCB->HALDD.SetMode; emulation = FALSE; } if( smhalfn != NULL ) { DWORD oldmode; BOOL didsetmode; /* * set the mode if this isn't a modex mode, or if it is a modex * mode but wasn't one before */ if( !use_modex || (use_modex && !was_modex) ) { smd.SetMode = smhalfn; smd.lpDD = this; smd.dwModeIndex = modeidx; smd.inexcl = inexcl; smd.useRefreshRate = useRefreshRate; oldclass = bumpPriority(); DOHALCALL( SetMode, smfn, smd, rc, emulation ); restorePriority( oldclass ); didsetmode = TRUE; } else { rc = DDHAL_DRIVER_HANDLED; smd.ddRVal = DD_OK; didsetmode = FALSE; } if( rc == DDHAL_DRIVER_HANDLED ) { if( smd.ddRVal == DD_OK ) { oldmode = this->dwModeIndexOrig; // save original mode index if( didsetmode ) { #ifdef WINNT uDisplaySettingsUnique=DdQueryDisplaySettingsUniqueness(); #endif FetchDirectDrawData( this, TRUE, 0 ); #ifndef WINNT this->dwModeIndex = modeidx; this_lcl->dwPreferredMode = modeidx; #else this_lcl->dwPreferredMode = this->dwModeIndex; #endif DPF(9,"Preferred mode index is %d, desired mode is %d",this_lcl->dwPreferredMode,modeidx); this->dwModeIndexOrig = oldmode; } /* * now set modex mode */ if( use_modex ) { extern void HELStopDCI( void ); DPF( 5, "********************** Setting MODEX MODE **********************" ); HELStopDCI(); #ifdef WIN95 ModeX_SetMode( (UINT)pmi->dwWidth, (UINT)pmi->dwHeight); #else DdSetModeX(this,(ULONG) pmi->dwHeight); //DPF(6,"HAL CreateSurface is %08x after DdSetModeX"); { BOOL bNewMode; if (!DdReenableDirectDrawObject(this,&bNewMode)) { DPF_ERR("After MODEX, call to DdReenableDirectDrawObject failed!"); return DDERR_UNSUPPORTED; } } #endif /* * ModeX now active, program our driver object and return */ #ifdef WINNT uDisplaySettingsUnique=DdQueryDisplaySettingsUniqueness(); fetchModeXData( this, pmi ); this_lcl->lpDDCB = this->lpDDCBtmp; #else fetchModeXData( this, pmi ); #endif this->dwModeIndex = real_modeidx; this_lcl->dwPreferredMode = real_modeidx; this->dwModeIndexOrig = oldmode; DPF( 5, "********************** Done Setting MODEX MODE **********************" ); return DD_OK; } } return smd.ddRVal; } } return DDERR_UNSUPPORTED; } /* SetDisplayMode */ /* * DD_SetDisplayMode */ HRESULT DDAPI DD_SetDisplayMode( LPDIRECTDRAW lpDD, DWORD dwWidth, DWORD dwHeight, DWORD dwBPP ) { DPF(9,"DD1 setdisplay mode called"); return DD_SetDisplayMode2(lpDD,dwWidth,dwHeight,dwBPP,0,0); } /* DD_SetDisplayMode */ /* * DD_SetDisplayMode2 */ HRESULT DDAPI DD_SetDisplayMode2( LPDIRECTDRAW lpDD, DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwRefreshRate, DWORD dwFlags) { LPDDRAWI_DIRECTDRAW_INT this_int; LPDDRAWI_DIRECTDRAW_LCL this_lcl; LPDDRAWI_DIRECTDRAW_GBL this; int i; int j; LPDDHALMODEINFO pmi; HRESULT ddrval; int iChosenMode; WORD wChosenRefresh; DWORD dwNumberOfTempModes; #ifdef WINNT WORD wCurrentRefresh=0; DWORD dwCurrentWidth=0; #endif typedef struct { DDHALMODEINFO mi; int iIndex; }TEMP_MODE_LIST; TEMP_MODE_LIST * pTempList=0; ENTER_DDRAW(); TRY { this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD; if( !VALID_DIRECTDRAW_PTR( this_int ) ) { LEAVE_DDRAW(); return DDERR_INVALIDOBJECT; } this_lcl = this_int->lpLcl; this = this_lcl->lpGbl; /* * no flags defined right now */ if( dwFlags ) { DPF_ERR( "Invalid flags specified" ); LEAVE_DDRAW(); return DDERR_INVALIDPARAMS; } /* * don't allow change if surfaces are locked */ if( this->dwSurfaceLockCount ) { DPF_ERR( "Surfaces are locked, can't switch the mode" ); LEAVE_DDRAW(); return DDERR_SURFACEBUSY; } /* * don't allow change if some other process has exclusive mode */ if( (this->lpExclusiveOwner != NULL) && (this->lpExclusiveOwner != this_lcl ) ) { DPF_ERR( "Can't change mode; exclusive mode not owned" ); LEAVE_DDRAW(); return DDERR_NOEXCLUSIVEMODE; } #ifdef WINNT /* * Get the current refresh rate, if we have one. */ if( 0xFFFFFFFFUL != this->dwModeIndex ) { wCurrentRefresh = this->lpModeInfo[ this->dwModeIndex ].wRefreshRate; dwCurrentWidth = this->lpModeInfo[ this->dwModeIndex ].dwWidth; } #endif /* * Modes are now chosen in a brain-dead 3-step process: * -Build a temporary list of modes which match the desired spatial and color resolutions * -Sort this list into ascending refresh rate order. * -Select from this list the rate which best matches what we want. */ /* * Step 1. Build a list of modes which match the desired spatial and color resolutions */ pTempList = (TEMP_MODE_LIST*) MemAlloc(this->dwNumModes * sizeof(TEMP_MODE_LIST)); if (0 == pTempList) { LEAVE_DDRAW(); return DDERR_OUTOFMEMORY; } /* * On NT, some cards will enumerate only one refresh rate choice for each * resolution, and that choice will be the hardware default rate. */ dwNumberOfTempModes=0; for(i = 0;i <(int) (this->dwNumModes);i++) { pmi = &this->lpModeInfo[i]; if( (pmi->dwWidth == dwWidth) && (pmi->dwHeight == dwHeight) && ((DWORD)pmi->dwBPP == dwBPP) && ((pmi->wFlags & DDMODEINFO_UNSUPPORTED) == 0)) { pTempList[dwNumberOfTempModes].mi = *pmi; pTempList[dwNumberOfTempModes].iIndex = i; #ifdef WINNT /* * The app can specify a refresh rate of zero for "don't care", * Since on NT default refresh rates are specified by '1' in the * mode list, we'll translate 1 to 0 in the temporary list. */ if (pmi->wRefreshRate <= 1) { pTempList[dwNumberOfTempModes].mi.wRefreshRate = 0; } #endif dwNumberOfTempModes++; } } if (0 == dwNumberOfTempModes) { MemFree(pTempList); LEAVE_DDRAW(); DPF( 0,"Mode not found... No match amongst available spatial and color resolutions (wanted %dx%dx%d)",dwWidth,dwHeight,dwBPP ); return DDERR_INVALIDMODE; } for(i=0;i<(int)dwNumberOfTempModes;i++) DPF(9,"Copied mode list element %d:%dx%dx%d@%d",i, pTempList[i].mi.dwWidth, pTempList[i].mi.dwHeight, pTempList[i].mi.dwBPP, pTempList[i].mi.wRefreshRate); /* * Step 2. Sort list into ascending refresh order * Bubble sort * Note this does nothing if there's only one surviving mode. */ for (i=0;i<(int)dwNumberOfTempModes;i++) { for (j=(int)dwNumberOfTempModes-1;j>i;j--) { if (pTempList[i].mi.wRefreshRate > pTempList[j].mi.wRefreshRate) { TEMP_MODE_LIST temp = pTempList[i]; pTempList[i] = pTempList[j]; pTempList[j] = temp; } } } for(i=0;i<(int)dwNumberOfTempModes;i++) DPF(9,"Sorted mode list element %d:%dx%dx%d@%d",i, pTempList[i].mi.dwWidth, pTempList[i].mi.dwHeight, pTempList[i].mi.dwBPP, pTempList[i].mi.wRefreshRate); /* * Step 3. Find the rate we're looking for. * There are three cases. * 1:Looking for a specific refresh * 2a:Not looking for a specific refresh and stepping down in spatial resolution * 2a:Not looking for a specific refresh and stepping up in spatial resolution */ iChosenMode = -1; if (dwRefreshRate) { /* case 1 */ DPF(9,"App wants rate of %d",dwRefreshRate); for (i=0;i<(int)dwNumberOfTempModes;i++) { /* * We'll never match a zero (hardware default) rate here, * but if there's only one rate which has refresh=0 * the app will never ask for a non-zero rate, because it will * never have seen one at enumerate time. */ if ( (DWORD) (pTempList[i].mi.wRefreshRate) == dwRefreshRate ) { iChosenMode=pTempList[i].iIndex; break; } } } else { #if 0 //def WINNT /* case 2. a or b? */ if (dwWidth <= dwCurrentWidth) { /* * Case 2a: Going down in spatial resolution, so ascend the rates, looking for the highest * rate which does not exceed the current rate. If there's no such rate, grab the lowest * of all the rates (all of which are greater than the current rate). * Start with the first (lowest rate possible): */ iChosenMode = pTempList[0].iIndex; for (i=0;i< (int) dwNumberOfTempModes;i++) { if ( pTempList[i].mi.wRefreshRate > wCurrentRefresh ) { /* * Found a rate greater than the current. This and all later rates are not wanted * (unless we already chose it by default by assigning iChosenMode to the first in the list). */ if ( 0 != this->lpModeInfo[iChosenMode].wRefreshRate ) { /* * If the last mode we found was a hardware default, then * we need to choose the next one. If we got here, then * the last mode was _not_ a HDR, and we can safely choose it. */ break; } } iChosenMode = pTempList[i].iIndex; } } else #endif { /* * Case 2b: Going up in spatial resolution, so just pick the lowest rate (earliest in list) * which isn't a hardware default, unless no such rate exists. */ iChosenMode=pTempList[0].iIndex; #if 0 for (i=0;i< (int) dwNumberOfTempModes;i++) { if ( pTempList[i].mi.wRefreshRate != 0 ) { break; } iChosenMode = pTempList[i].iIndex; } #endif } } if (-1 == iChosenMode) { MemFree(pTempList); LEAVE_DDRAW(); DPF( 0,"Mode not found... No match amongst available refresh rates (wanted %dx%dx%d@%d)",dwWidth,dwHeight,dwBPP,dwRefreshRate); return DDERR_INVALIDMODE; } MemFree(pTempList); pmi = &this->lpModeInfo[iChosenMode]; DPF(9,"Desired width:%d, current width:%d. Current refresh:%d, chosen refresh %d", dwWidth, dwCurrentWidth, wCurrentRefresh, this->lpModeInfo[iChosenMode].wRefreshRate); /* * only allow ModeX modes if the cooplevel is ok */ if( (pmi->wFlags & DDMODEINFO_MODEX) && !(this_lcl->dwLocalFlags & DDRAWILCL_ALLOWMODEX) ) { LEAVE_DDRAW(); DPF( 0,"must set DDSCL_ALLOWMODEX to use ModeX modes" ); return DDERR_INVALIDMODE; } } EXCEPT( EXCEPTION_EXECUTE_HANDLER ) { DPF_ERR( "Exception encountered validating parameters" ); LEAVE_DDRAW(); return DDERR_INVALIDPARAMS; } // see if the monitor likes it if( !(pmi->wFlags & DDMODEINFO_MODEX) && !MonitorCanHandleMode(pmi->dwWidth, pmi->dwHeight, pmi->wRefreshRate) ) { // Monitor doesn't like it DPF_ERR("Mode not compatible with monitor"); return DDERR_INVALIDMODE; } /* * set the display mode, and pay attention to refresh rate if we were asked to. * Always pay attention to rate on NT. * NOTE!!! This is a very slight change from what we did in released DX2!!! * - This function is now called from DD_SetDisplayMode with a refresh rate of 0, * so we check for that circumstance and use it to say to the driver wether * or not to pay attention to the refresh rate. Fine. However, now when * someone calls DD_SetDisplayMode2 with a refresh rate of 0, we tell * the driver to ignore the rate, when before we were telling the driver * to force to some rate we found in the mode table (which would have been * the first mode which matched resolution in the list... probably the lowest * refresh rate). */ #if 1 //def WIN95 if (0 == dwRefreshRate) ddrval = SetDisplayMode( this_lcl, iChosenMode, FALSE, FALSE ); else #endif ddrval = SetDisplayMode( this_lcl, iChosenMode, FALSE, TRUE ); LEAVE_DDRAW(); return ddrval; } /* DD_SetDisplayMode2 */ #undef DPF_MODNAME #define DPF_MODNAME "RestoreDisplayMode" /* * RestoreDisplayMode * * For use by DD_RestoreDisplayMode & internally. * Must be called with driver lock taken */ HRESULT RestoreDisplayMode( LPDDRAWI_DIRECTDRAW_LCL this_lcl, BOOL force ) { DWORD rc; DDHAL_SETMODEDATA smd; BOOL inexcl; DWORD pid; LPDDHAL_SETMODE smfn; LPDDHAL_SETMODE smhalfn; BOOL emulation; LPDDRAWI_DIRECTDRAW_GBL this; DWORD oldclass; BOOL was_modex; this = this_lcl->lpGbl; DPF(9,"Restoring Display mode to index %d, %dx%dx%d@%d",this->dwModeIndexOrig, this->lpModeInfo[this->dwModeIndexOrig].dwWidth, this->lpModeInfo[this->dwModeIndexOrig].dwHeight, this->lpModeInfo[this->dwModeIndexOrig].dwBPP, this->lpModeInfo[this->dwModeIndexOrig].wRefreshRate); if (0 == (this_lcl->dwLocalFlags & DDRAWILCL_MODEHASBEENCHANGED) ) { /* * This app never made a mode change, so we ignore the restore, in case someone switch desktop * modes while playing a movie in a window, for instance. We do it before the redraw window * so that we don't flash icons when a windowed app exits. */ DPF( 2, "Mode was never changed by this app" ); return DD_OK; } /* * we ALWAYS set the mode in emulation on Win95 since our index could be wrong */ #ifdef WINNT if (this->dwModeIndex == this->dwModeIndexOrig) { DPF( 2, "Mode wasn't changed" ); RedrawWindow( NULL, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN ); return DD_OK; } #else if( ( (this->dwModeIndex == this->dwModeIndexOrig) && !(this->dwFlags & DDRAWI_NOHARDWARE) ) || (this->lpModeInfo==NULL) ) { DPF( 2, "Mode wasn't changed" ); RedrawWindow( NULL, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN ); return DD_OK; } #endif DPF( 1, "In RestoreDisplayMode" ); pid = GetCurrentProcessId(); /* * don't allow mode change if surfaces are locked */ if( !force ) { if( this->dwSurfaceLockCount > 0 ) { DPF( 0, "Can't switch modes with locked surfaces!" ); return DDERR_SURFACEBUSY; } } /* * see if we're in exclusive mode */ if( force ) { inexcl = TRUE; } else { inexcl = (this->lpExclusiveOwner == this_lcl); } /* * check bpp */ if( this->lpModeInfo[ this->dwModeIndex ].wFlags & DDMODEINFO_MODEX ) { was_modex = TRUE; } else { was_modex = FALSE; } /* * turn off modex first... */ if( was_modex ) { stopModeX( this ); } /* * get the driver to restore the mode... */ #ifdef WIN95 if( ( this->dwFlags & DDRAWI_DISPLAYDRV ) || ( this->dwFlags & DDRAWI_NOHARDWARE ) || ( this_lcl->lpDDCB->cbDDCallbacks.SetMode == NULL ) ) #else if (1) //always use hel for nt #endif { smfn = this_lcl->lpDDCB->HELDD.SetMode; smhalfn = smfn; emulation = TRUE; } else { smhalfn = this_lcl->lpDDCB->cbDDCallbacks.SetMode; smfn = this_lcl->lpDDCB->HALDD.SetMode; emulation = FALSE; } if( smhalfn != NULL ) { smd.SetMode = smhalfn; smd.lpDD = this; #ifdef WIN95 smd.dwModeIndex = (DWORD) -1; #else /* * If we allow the HEL to set the desktop to what's in the registry, * we'll possibly end up with a mode index that was different to what * we originally thought it was, so we force a return to the mode we * were in when the direct draw object was created, which has to match * the GDI desktop. */ smd.dwModeIndex = this->dwModeIndexOrig; #endif smd.inexcl = inexcl; smd.useRefreshRate = TRUE; oldclass = bumpPriority(); DOHALCALL( SetMode, smfn, smd, rc, emulation ); restorePriority( oldclass ); if( rc == DDHAL_DRIVER_HANDLED ) { if( smd.ddRVal == DD_OK ) { DPF( 3, "RestoreDisplayMode: Process %08lx Mode = %ld", GETCURRPID(), this->dwModeIndex ); #ifdef WINNT uDisplaySettingsUnique=DdQueryDisplaySettingsUniqueness(); #endif FetchDirectDrawData( this, TRUE, 0 ); if( this->dwFlags & DDRAWI_DISPLAYDRV ) { DPF(4,"Redrawing all windows"); RedrawWindow( NULL, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN ); } } return smd.ddRVal; } } return DDERR_UNSUPPORTED; } /* RestoreDisplayMode */ /* * DD_RestoreDisplayMode * * restore mode */ HRESULT DDAPI DD_RestoreDisplayMode( LPDIRECTDRAW lpDD ) { LPDDRAWI_DIRECTDRAW_INT this_int; LPDDRAWI_DIRECTDRAW_LCL this_lcl; LPDDRAWI_DIRECTDRAW_GBL this; HRESULT ddrval; ENTER_DDRAW(); TRY { this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD; if( !VALID_DIRECTDRAW_PTR( this_int ) ) { LEAVE_DDRAW(); return DDERR_INVALIDOBJECT; } this_lcl = this_int->lpLcl; this = this_lcl->lpGbl; /* * switching to the same mode? */ if( this->dwModeIndex == this->dwModeIndexOrig ) { LEAVE_DDRAW(); return DD_OK; } /* * don't allow change if some other process has exclusive mode */ if( (this->lpExclusiveOwner != NULL) && (this->lpExclusiveOwner != this_lcl ) ) { DPF_ERR( "Can't change mode; exclusive mode owned" ); LEAVE_DDRAW(); return DDERR_NOEXCLUSIVEMODE; } /* * don't allow change if surfaces are locked */ if( this->dwSurfaceLockCount ) { DPF_ERR( "Surfaces are locked, can't switch the mode" ); LEAVE_DDRAW(); return DDERR_SURFACEBUSY; } } EXCEPT( EXCEPTION_EXECUTE_HANDLER ) { DPF_ERR( "Exception encountered validating parameters" ); LEAVE_DDRAW(); return DDERR_INVALIDPARAMS; } ddrval = RestoreDisplayMode( this_lcl, FALSE ); if( ddrval == DD_OK ) { this_lcl->dwPreferredMode = this->dwModeIndex; DPF( 1, "Preferred mode is now %ld", this_lcl->dwPreferredMode ); } LEAVE_DDRAW(); return ddrval; } /* DD_RestoreDisplayMode */ #undef DPF_MODNAME #define DPF_MODNAME "EnumDisplayModes" /* * DD_EnumDisplayModes */ HRESULT DDAPI DD_EnumDisplayModes( LPDIRECTDRAW lpDD, DWORD dwFlags, LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext, LPDDENUMMODESCALLBACK lpEnumCallback ) { LPDDRAWI_DIRECTDRAW_INT this_int; LPDDRAWI_DIRECTDRAW_LCL this_lcl; LPDDRAWI_DIRECTDRAW_GBL this; DWORD rc; DDSURFACEDESC ddsd; LPDDHALMODEINFO pmi; int i, j; BOOL inexcl; BOOL bUseRefreshRate; ENTER_DDRAW(); TRY { this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD; if( !VALID_DIRECTDRAW_PTR( this_int ) ) { LEAVE_DDRAW(); return DDERR_INVALIDOBJECT; } this_lcl = this_int->lpLcl; this = this_lcl->lpGbl; if( lpDDSurfaceDesc != NULL ) { if( !VALID_DDSURFACEDESC_PTR(lpDDSurfaceDesc) ) { DPF_ERR( "Invalid surface description" ); LEAVE_DDRAW(); return DDERR_INVALIDPARAMS; } } if ( dwFlags & ~DDEDM_VALID) { DPF_ERR( "Invalid flags") ; LEAVE_DDRAW(); return DDERR_INVALIDPARAMS; } if( !VALIDEX_CODE_PTR( lpEnumCallback ) ) { DPF_ERR( "Invalid enum. callback routine" ); LEAVE_DDRAW(); return DDERR_INVALIDPARAMS; } } EXCEPT( EXCEPTION_EXECUTE_HANDLER ) { DPF_ERR( "Exception encountered validating parameters" ); LEAVE_DDRAW(); return DDERR_INVALIDPARAMS; } /* * see if we're in exclusive mode */ inexcl = (this->lpExclusiveOwner == this_lcl); /* * go through all possible modes... */ for( i=0;i<(int)this->dwNumModes;i++ ) { pmi = &this->lpModeInfo[i]; /* * check to see if this is a duplicate mode */ for (j=0; jlpModeInfo[j].dwHeight == pmi->dwHeight) && (this->lpModeInfo[j].dwWidth == pmi->dwWidth) && (this->lpModeInfo[j].dwBPP == pmi->dwBPP) ) { // basic mode matches, what about refresh rate? if( dwFlags & DDEDM_REFRESHRATES ) { // if refresh rate is not unique then the modes match if( this->lpModeInfo[j].wRefreshRate == pmi->wRefreshRate ) { DPF(1, "matched: %d %d", this->lpModeInfo[j].wRefreshRate, pmi->wRefreshRate); break; } // unique refresh rate and the app cares, the modes don't match } else { // the app doesn't care about refresh rates break; } } } if( j != i) { // broke out early, mode i is not unique, move on to the next one. continue; } /* * check if surface description matches mode */ if ( lpDDSurfaceDesc ) { if( lpDDSurfaceDesc->dwFlags & DDSD_HEIGHT ) { if( lpDDSurfaceDesc->dwHeight != pmi->dwHeight ) { continue; } } if( lpDDSurfaceDesc->dwFlags & DDSD_WIDTH ) { if( lpDDSurfaceDesc->dwWidth != pmi->dwWidth ) { continue; } } if( lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT ) { if( lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount != pmi->dwBPP ) { continue; } } if( lpDDSurfaceDesc->dwFlags & DDSD_REFRESHRATE ) { bUseRefreshRate = TRUE; if( lpDDSurfaceDesc->dwRefreshRate != (DWORD)pmi->wRefreshRate ) { continue; } } else { bUseRefreshRate = FALSE; } } #ifdef WIN95 /* * see if driver will allow this */ if( (this->dwFlags & DDRAWI_DISPLAYDRV) && !(pmi->wFlags & DDMODEINFO_MODEX) ) { DWORD cds_flags; DEVMODE dm; int cds_rc; makeDEVMODE( this, pmi, inexcl, bUseRefreshRate, &cds_flags, &dm ); cds_flags |= CDS_TEST; cds_rc = ChangeDisplaySettings( &dm, cds_flags ); if( cds_rc != 0 ) { if( bUseRefreshRate ) { DPF( 3, "Mode %d not supported (%ldx%ldx%ld rr=%d), rc = %d", i, pmi->dwWidth, pmi->dwHeight, pmi->dwBPP, pmi->wRefreshRate, cds_rc ); } else { DPF( 3, "Mode %d not supported (%ldx%ldx%ld), rc = %d", i, pmi->dwWidth, pmi->dwHeight, pmi->dwBPP, cds_rc ); } continue; } if( !MonitorCanHandleMode( pmi->dwWidth, pmi->dwHeight, pmi->wRefreshRate ) ) { DPF( 3, "Monitor can't handle mode %d: (%ldx%ld rr=%d)", i, pmi->dwWidth, pmi->dwHeight, pmi->wRefreshRate); continue; } } if( (this->dwFlags & DDRAWI_DISPLAYDRV) && (pmi->wFlags & DDMODEINFO_MODEX) && !(this_lcl->dwLocalFlags & DDRAWILCL_ALLOWMODEX) ) { DPF( 3, "skipping ModeX mode" ); continue; } #endif /* * invoke callback with surface desc. */ setSurfaceDescFromMode( pmi, &ddsd ); /* * Hardware default rates on NT are signified as 1Hz. We translate this to * 0Hz for DDraw apps. At SetDisplayMode time, 0Hz is translated back to 1Hz. */ if(0==(dwFlags & DDEDM_REFRESHRATES)) { ddsd.dwRefreshRate = 0; } rc = lpEnumCallback( &ddsd, lpContext ); if( rc == 0 ) { break; } } LEAVE_DDRAW(); return DD_OK; } /* DD_EnumDisplayModes */