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

1369 lines
40 KiB

  1. //=============================================================================
  2. //
  3. // Copyright (C) 1998 Microsoft Corporation. All rights reserved.
  4. //
  5. // File: ddmodent.c
  6. // Content: DirectDraw display mode code for NT
  7. //
  8. // Date By Reason
  9. // ---------- -------- -----------------------------------------------------
  10. // 02/20/1998 johnstep Initialial implementation, replaces ddmode.c on NT
  11. // 05/29/1998 jeffno ModeX emulation
  12. //
  13. //=============================================================================
  14. #include "ddrawpr.h"
  15. #include "ddrawgdi.h"
  16. #define MODEX_WIDTH 320
  17. #define MODEX_HEIGHT1 200
  18. #define MODEX_HEIGHT2 240
  19. #define MODEX_BPP 8
  20. //=============================================================================
  21. //
  22. // Function: GetNumberOfMonitorAttachedToDesktop
  23. //
  24. // Count number of monitors attached to current desktop.
  25. //
  26. //=============================================================================
  27. DWORD GetNumberOfMonitorAttachedToDesktop()
  28. {
  29. DWORD dwNumberOfMonitor = 0;
  30. DWORD iDevNum = 0;
  31. DISPLAY_DEVICE DisplayDevice;
  32. ZeroMemory(&DisplayDevice,sizeof(DISPLAY_DEVICE));
  33. DisplayDevice.cb = sizeof(DISPLAY_DEVICE);
  34. while (EnumDisplayDevices(NULL,iDevNum,&DisplayDevice,0))
  35. {
  36. if (DisplayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)
  37. {
  38. dwNumberOfMonitor++;
  39. }
  40. ZeroMemory(&DisplayDevice,sizeof(DISPLAY_DEVICE));
  41. DisplayDevice.cb = sizeof(DISPLAY_DEVICE);
  42. iDevNum++;
  43. }
  44. return dwNumberOfMonitor;
  45. }
  46. //=============================================================================
  47. //
  48. // Function: resetAllDirectDrawObjects
  49. //
  50. // On NT we have to reenable all the DirectDraw objects on any mode change
  51. // because a mode change disables all the kernel mode DirectDraw objects due
  52. // to desktop changes, etc.
  53. //
  54. //=============================================================================
  55. void resetAllDirectDrawObjects()
  56. {
  57. LPDDRAWI_DIRECTDRAW_LCL pdd_lcl;
  58. LPDDRAWI_DIRECTDRAW_GBL pdd_gbl;
  59. BOOL bRestoreGamma;
  60. HDC hdc;
  61. WORD wMonitorsAttachedToDesktop = (WORD) GetNumberOfMonitorAttachedToDesktop();
  62. // First mark all DirectDraw global objects as having not changed.
  63. for (pdd_lcl = lpDriverLocalList; pdd_lcl;)
  64. {
  65. if (pdd_lcl->lpGbl)
  66. {
  67. pdd_lcl->lpGbl->dwFlags |= DDRAWI_DDRAWDATANOTFETCHED;
  68. }
  69. pdd_lcl = pdd_lcl->lpLink;
  70. }
  71. // Now reset all drivers unmarking them as we go. We may need to create
  72. // temporary kernel mode DirectDraw objects in order to pass down a valid
  73. // handle to the kernel.
  74. for (pdd_lcl = lpDriverLocalList; pdd_lcl;)
  75. {
  76. pdd_gbl = pdd_lcl->lpGbl;
  77. if (pdd_gbl && (pdd_gbl->dwFlags & DDRAWI_DDRAWDATANOTFETCHED))
  78. {
  79. // Determine if the gamma ramp needs to be restored
  80. bRestoreGamma = ( pdd_lcl->lpPrimary != NULL ) &&
  81. ( pdd_lcl->lpPrimary->lpLcl->lpSurfMore->lpGammaRamp != NULL ) &&
  82. ( pdd_lcl->lpPrimary->lpLcl->dwFlags & DDRAWISURF_SETGAMMA );
  83. pdd_gbl->dwFlags &= ~DDRAWI_DDRAWDATANOTFETCHED;
  84. if (!(pdd_gbl->dwFlags & DDRAWI_MODEX))
  85. {
  86. // If we find a local for this process/driver pair, we will use
  87. // its hDD to pass to the kernel. If not, we must create a
  88. // temproary kernel mode DirectDraw object, and delete it after
  89. // resetting the driver.
  90. FetchDirectDrawData(pdd_gbl, TRUE, 0, NULL, NULL, 0, pdd_lcl);
  91. }
  92. else
  93. {
  94. DDHALMODEINFO mi =
  95. {
  96. MODEX_WIDTH, // width (in pixels) of mode
  97. MODEX_HEIGHT1, // height (in pixels) of mode
  98. MODEX_WIDTH, // pitch (in bytes) of mode
  99. MODEX_BPP, // bits per pixel
  100. (WORD)(DDMODEINFO_PALETTIZED | DDMODEINFO_MODEX), // flags
  101. 0, // refresh rate
  102. 0, // red bit mask
  103. 0, // green bit mask
  104. 0, // blue bit mask
  105. 0 // alpha bit mask
  106. };
  107. //fixup the height to the actual height:
  108. mi.dwHeight = pdd_lcl->dmiPreferred.wHeight;
  109. fetchModeXData( pdd_gbl, &mi, INVALID_HANDLE_VALUE );
  110. }
  111. pdd_gbl->dmiCurrent.wMonitorsAttachedToDesktop = (BYTE)wMonitorsAttachedToDesktop;
  112. hdc = DD_CreateDC(pdd_gbl->cDriverName);
  113. if ( pdd_gbl->dwFlags & DDRAWI_NOHARDWARE )
  114. {
  115. // The HEL will wipe out our hard-earned modex data otherwise
  116. if (0 == (pdd_gbl->dwFlags & DDRAWI_MODEX) )
  117. {
  118. extern void UpdateDirectDrawMode(LPDDRAWI_DIRECTDRAW_GBL);
  119. UpdateDirectDrawMode(pdd_gbl);
  120. }
  121. }
  122. else
  123. {
  124. if( bRestoreGamma )
  125. {
  126. SetGamma( pdd_lcl->lpPrimary->lpLcl, pdd_lcl );
  127. }
  128. InitDIB(hdc, pdd_gbl->gpbmiSrc);
  129. InitDIB(hdc, pdd_gbl->gpbmiDest);
  130. }
  131. DD_DoneDC(hdc);
  132. }
  133. pdd_lcl = pdd_lcl->lpLink;
  134. }
  135. CheckAliasedLocksOnModeChange();
  136. }
  137. //=============================================================================
  138. //
  139. // Function: ModeChangedOnENTERDDRAW
  140. //
  141. //=============================================================================
  142. void ModeChangedOnENTERDDRAW(void)
  143. {
  144. resetAllDirectDrawObjects();
  145. }
  146. //=============================================================================
  147. //
  148. // Function: FillBitMasks
  149. //
  150. //=============================================================================
  151. void FillBitMasks(LPDDPIXELFORMAT pddpf, HDC hdc)
  152. {
  153. if (hdc)
  154. {
  155. HBITMAP hbm;
  156. BITMAPINFO *pbmi;
  157. DWORD *pdwColors;
  158. if (pbmi = LocalAlloc(LPTR, 3 * sizeof (RGBQUAD) + sizeof (BITMAPINFO)))
  159. {
  160. if (hbm = CreateCompatibleBitmap(hdc, 1, 1))
  161. {
  162. pbmi->bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
  163. if (GetDIBits(hdc, hbm, 0, 0, NULL, pbmi, DIB_RGB_COLORS))
  164. {
  165. if (pbmi->bmiHeader.biCompression == BI_BITFIELDS)
  166. {
  167. GetDIBits(hdc, hbm, 0, pbmi->bmiHeader.biHeight,
  168. NULL, pbmi, DIB_RGB_COLORS);
  169. pdwColors = (DWORD *) &pbmi->bmiColors[0];
  170. pddpf->dwRBitMask = pdwColors[0];
  171. pddpf->dwGBitMask = pdwColors[1];
  172. pddpf->dwBBitMask = pdwColors[2];
  173. pddpf->dwRGBAlphaBitMask = 0;
  174. }
  175. }
  176. DeleteObject(hbm);
  177. }
  178. LocalFree(pbmi);
  179. }
  180. }
  181. else
  182. {
  183. switch (pddpf->dwRGBBitCount)
  184. {
  185. case 15:
  186. pddpf->dwRBitMask = 0x7C00;
  187. pddpf->dwGBitMask = 0x03E0;
  188. pddpf->dwBBitMask = 0x001F;
  189. pddpf->dwRGBAlphaBitMask = 0;
  190. break;
  191. case 16:
  192. pddpf->dwRBitMask = 0xF800;
  193. pddpf->dwGBitMask = 0x07E0;
  194. pddpf->dwBBitMask = 0x001F;
  195. pddpf->dwRGBAlphaBitMask = 0;
  196. break;
  197. case 32:
  198. pddpf->dwRBitMask = 0x00FF0000;
  199. pddpf->dwGBitMask = 0x0000FF00;
  200. pddpf->dwBBitMask = 0x000000FF;
  201. pddpf->dwRGBAlphaBitMask = 0x00000000;
  202. break;
  203. default:
  204. pddpf->dwRBitMask = 0;
  205. pddpf->dwGBitMask = 0;
  206. pddpf->dwBBitMask = 0;
  207. pddpf->dwRGBAlphaBitMask = 0;
  208. }
  209. }
  210. }
  211. //=============================================================================
  212. //
  213. // Function: setPixelFormat
  214. //
  215. //=============================================================================
  216. static void setPixelFormat(LPDDPIXELFORMAT pddpf, HDC hdc, DWORD bpp)
  217. {
  218. pddpf->dwSize = sizeof (DDPIXELFORMAT);
  219. pddpf->dwFlags = DDPF_RGB;
  220. pddpf->dwRGBBitCount = hdc ? GetDeviceCaps(hdc, BITSPIXEL) : bpp;
  221. switch (pddpf->dwRGBBitCount)
  222. {
  223. case 8:
  224. pddpf->dwFlags |= DDPF_PALETTEINDEXED8;
  225. pddpf->dwRBitMask = 0;
  226. pddpf->dwGBitMask = 0;
  227. pddpf->dwBBitMask = 0;
  228. pddpf->dwRGBAlphaBitMask = 0;
  229. break;
  230. case 24:
  231. pddpf->dwRBitMask = 0x00FF0000;
  232. pddpf->dwGBitMask = 0x0000FF00;
  233. pddpf->dwBBitMask = 0x000000FF;
  234. pddpf->dwRGBAlphaBitMask = 0x00000000;
  235. break;
  236. default:
  237. FillBitMasks(pddpf, hdc);
  238. break;
  239. }
  240. }
  241. //=============================================================================
  242. //
  243. // Function: DD_GetDisplayMode
  244. //
  245. //=============================================================================
  246. HRESULT DDAPI DD_GetDisplayMode(LPDIRECTDRAW pdd, LPDDSURFACEDESC pddsd)
  247. {
  248. LPDDRAWI_DIRECTDRAW_INT pdd_int;
  249. LPDDRAWI_DIRECTDRAW_LCL pdd_lcl;
  250. LPDDRAWI_DIRECTDRAW_GBL pdd_gbl;
  251. HDC hdc;
  252. ENTER_DDRAW();
  253. DPF(2,A,"ENTERAPI: DD_GetDisplayMode");
  254. TRY
  255. {
  256. pdd_int = (LPDDRAWI_DIRECTDRAW_INT) pdd;
  257. if (!VALID_DIRECTDRAW_PTR(pdd_int))
  258. {
  259. DPF(0, "Invalid object");
  260. LEAVE_DDRAW();
  261. return DDERR_INVALIDOBJECT;
  262. }
  263. pdd_lcl = pdd_int->lpLcl;
  264. pdd_gbl = pdd_lcl->lpGbl;
  265. if (!VALIDEX_DDSURFACEDESC2_PTR(pddsd) &&
  266. !VALIDEX_DDSURFACEDESC_PTR(pddsd))
  267. {
  268. DPF(0, "Invalid params");
  269. LEAVE_DDRAW();
  270. return DDERR_INVALIDPARAMS;
  271. }
  272. }
  273. EXCEPT(EXCEPTION_EXECUTE_HANDLER)
  274. {
  275. DPF_ERR("DD_GetDisplayMode: Exception encountered validating parameters");
  276. LEAVE_DDRAW();
  277. return DDERR_INVALIDPARAMS;
  278. }
  279. ZeroMemory(pddsd, pddsd->dwSize);
  280. if (LOWERTHANDDRAW4(pdd_int))
  281. {
  282. pddsd->dwSize = sizeof (DDSURFACEDESC);
  283. }
  284. else
  285. {
  286. pddsd->dwSize = sizeof (DDSURFACEDESC2);
  287. }
  288. pddsd->dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_PIXELFORMAT | DDSD_REFRESHRATE;
  289. hdc = DD_CreateDC(pdd_gbl->cDriverName);
  290. pddsd->dwWidth = pdd_gbl->lpModeInfo->dwWidth;
  291. pddsd->dwHeight = pdd_gbl->lpModeInfo->dwHeight;
  292. pddsd->dwRefreshRate = pdd_gbl->lpModeInfo->wRefreshRate;
  293. setPixelFormat(&(pddsd->ddpfPixelFormat), hdc, 0);
  294. pddsd->lPitch = (pddsd->dwWidth * pddsd->ddpfPixelFormat.dwRGBBitCount) >> 3; // hack
  295. // set stereo surface caps bits if driver marks mode as stereo mode
  296. if (GetDDStereoMode(pdd_gbl,
  297. pddsd->dwWidth,
  298. pddsd->dwHeight,
  299. pddsd->ddpfPixelFormat.dwRGBBitCount,
  300. pddsd->dwRefreshRate) &&
  301. !LOWERTHANDDRAW7(pdd_int) &&
  302. VALIDEX_DDSURFACEDESC2_PTR(pddsd))
  303. {
  304. LPDDSURFACEDESC2 pddsd2 = (LPDDSURFACEDESC2)pddsd;
  305. pddsd2->ddsCaps.dwCaps2 |= DDSCAPS2_STEREOSURFACELEFT;
  306. }
  307. DD_DoneDC(hdc);
  308. LEAVE_DDRAW();
  309. return DD_OK;
  310. }
  311. //=============================================================================
  312. //
  313. // Function: SetDisplayMode
  314. //
  315. //=============================================================================
  316. /*
  317. * IsRefreshRateSupported
  318. */
  319. BOOL IsRefreshRateSupported(LPDDRAWI_DIRECTDRAW_GBL pdrv,
  320. DWORD Width,
  321. DWORD Height,
  322. DWORD BitsPerPixel,
  323. DWORD RefreshRate)
  324. {
  325. DEVMODE dm;
  326. LPSTR pDeviceName;
  327. int i;
  328. pDeviceName = (_stricmp(pdrv->cDriverName, "display") == 0) ?
  329. g_szPrimaryDisplay : pdrv->cDriverName;
  330. for (i = 0;; i++)
  331. {
  332. ZeroMemory(&dm, sizeof dm);
  333. dm.dmSize = sizeof dm;
  334. if (EnumDisplaySettings(pDeviceName, i, &dm))
  335. {
  336. if ((dm.dmPelsWidth == Width) &&
  337. (dm.dmPelsHeight == Height) &&
  338. (dm.dmBitsPerPel == BitsPerPixel) &&
  339. (dm.dmDisplayFrequency == RefreshRate))
  340. {
  341. return TRUE;
  342. }
  343. }
  344. else
  345. {
  346. break;
  347. }
  348. }
  349. return FALSE;
  350. }
  351. /*
  352. * PickRefreshRate
  353. *
  354. * On NT, we want to pick a high reffresh rate, but we don't want to pick one
  355. * too high. In theory, mode pruning would be 100% safe and we can always pick
  356. * a high one, but we don't trust it 100%.
  357. */
  358. DWORD PickRefreshRate(LPDDRAWI_DIRECTDRAW_GBL pdrv,
  359. DWORD Width,
  360. DWORD Height,
  361. DWORD RefreshRate,
  362. DWORD BitsPerPixel)
  363. {
  364. DEVMODE dm;
  365. LPSTR pDeviceName;
  366. pDeviceName = (_stricmp(pdrv->cDriverName, "display") == 0) ?
  367. g_szPrimaryDisplay : pdrv->cDriverName;
  368. if (dwRegFlags & DDRAW_REGFLAGS_FORCEREFRESHRATE)
  369. {
  370. if (IsRefreshRateSupported(pdrv,
  371. Width,
  372. Height,
  373. BitsPerPixel,
  374. dwForceRefreshRate))
  375. {
  376. return dwForceRefreshRate;
  377. }
  378. }
  379. // If the app specified the refresh rate, we will use it; otherwise, we'll
  380. // pick one ourselves.
  381. if (RefreshRate == 0)
  382. {
  383. // If the mode requires no more bandwidth than the desktop mode from which
  384. // the app was launched, we will go ahead and try that mode.
  385. ZeroMemory(&dm, sizeof dm);
  386. dm.dmSize = sizeof dm;
  387. EnumDisplaySettings(pDeviceName, ENUM_REGISTRY_SETTINGS, &dm);
  388. if ((Width <= dm.dmPelsWidth) &&
  389. (Height <= dm.dmPelsHeight))
  390. {
  391. if (IsRefreshRateSupported(pdrv,
  392. Width,
  393. Height,
  394. BitsPerPixel,
  395. dm.dmDisplayFrequency))
  396. {
  397. RefreshRate = dm.dmDisplayFrequency;
  398. }
  399. }
  400. // If we still don't have a refresh rate, try 75hz
  401. if (RefreshRate == 0)
  402. {
  403. if (IsRefreshRateSupported(pdrv,
  404. Width,
  405. Height,
  406. BitsPerPixel,
  407. 75))
  408. {
  409. RefreshRate = 75;
  410. }
  411. }
  412. // If we still don't have a refresh rate, use 60hz
  413. if (RefreshRate == 0)
  414. {
  415. if (IsRefreshRateSupported(pdrv,
  416. Width,
  417. Height,
  418. BitsPerPixel,
  419. 60))
  420. {
  421. RefreshRate = 60;
  422. }
  423. }
  424. }
  425. return RefreshRate;
  426. }
  427. HRESULT SetDisplayMode(
  428. LPDDRAWI_DIRECTDRAW_LCL pdd_lcl,
  429. DWORD index,
  430. BOOL force,
  431. BOOL useRefreshRate)
  432. {
  433. LPDDRAWI_DIRECTDRAW_GBL pdd_gbl;
  434. DEVMODE dm;
  435. LONG result;
  436. BOOL bNewMode;
  437. DDHALINFO ddhi;
  438. LPCTSTR pszDevice;
  439. DWORD refreshRate;
  440. BOOL forceRefresh;
  441. pdd_lcl->dwLocalFlags |= DDRAWILCL_MODEHASBEENCHANGED;
  442. pdd_gbl = pdd_lcl->lpGbl;
  443. //
  444. // If not forcing, do not change mode with surface locks.
  445. //
  446. if (!force)
  447. {
  448. if (pdd_gbl->dwSurfaceLockCount > 0)
  449. {
  450. LPDDRAWI_DDRAWSURFACE_INT pTemp;
  451. // When we enabled vidmem vertex buffers in DX8, we found that some
  452. // apps do not unlock them before the mode change, but we don't want
  453. // to break them now, so we will hack around this by allowing the
  454. // mode switch to occur if all that's locked are vidmem VBs.
  455. pTemp = pdd_gbl->dsList;
  456. while (pTemp != NULL)
  457. {
  458. if (pTemp->lpLcl->lpGbl->dwUsageCount > 0)
  459. {
  460. if ((pTemp->lpLcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) &&
  461. !(pTemp->lpLcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER))
  462. {
  463. break;
  464. }
  465. }
  466. pTemp = pTemp->lpLink;
  467. }
  468. if (pTemp != NULL)
  469. {
  470. return DDERR_SURFACEBUSY;
  471. }
  472. }
  473. }
  474. //
  475. // Add code here to not set mode if it didn't change?
  476. //
  477. ZeroMemory(&dm, sizeof dm);
  478. dm.dmSize = sizeof dm;
  479. dm.dmBitsPerPel = pdd_lcl->dmiPreferred.wBPP;
  480. dm.dmPelsWidth = pdd_lcl->dmiPreferred.wWidth;
  481. dm.dmPelsHeight = pdd_lcl->dmiPreferred.wHeight;
  482. if (dm.dmBitsPerPel == 16)
  483. {
  484. if (pdd_gbl->lpModeInfo->wFlags & DDMODEINFO_555MODE)
  485. {
  486. dm.dmBitsPerPel = 15;
  487. }
  488. }
  489. dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
  490. if (useRefreshRate)
  491. {
  492. dm.dmDisplayFrequency = PickRefreshRate(pdd_lcl->lpGbl,
  493. dm.dmPelsWidth,
  494. dm.dmPelsHeight,
  495. pdd_lcl->dmiPreferred.wRefreshRate,
  496. dm.dmBitsPerPel);
  497. dm.dmFields |= DM_DISPLAYFREQUENCY;
  498. }
  499. else
  500. {
  501. dm.dmDisplayFrequency = PickRefreshRate(pdd_lcl->lpGbl,
  502. dm.dmPelsWidth,
  503. dm.dmPelsHeight,
  504. 0,
  505. dm.dmBitsPerPel);
  506. if (dm.dmDisplayFrequency > 0)
  507. {
  508. dm.dmFields |= DM_DISPLAYFREQUENCY;
  509. pdd_lcl->dmiPreferred.wRefreshRate = (WORD) dm.dmDisplayFrequency;
  510. }
  511. }
  512. if (_stricmp(pdd_gbl->cDriverName, "DISPLAY"))
  513. {
  514. pszDevice = pdd_gbl->cDriverName;
  515. }
  516. else
  517. {
  518. pszDevice = NULL;
  519. }
  520. // clean up any previous modex stuff:
  521. pdd_gbl->dwFlags &= ~DDRAWI_MODEX;
  522. NotifyDriverToDeferFrees();
  523. pdd_gbl->dwFlags |= DDRAWI_CHANGINGMODE;
  524. result = ChangeDisplaySettingsEx(pszDevice, &dm, NULL, CDS_FULLSCREEN, 0);
  525. pdd_gbl->dwFlags &= ~DDRAWI_CHANGINGMODE;
  526. DPF(5, "ChangeDisplaySettings: %d", result);
  527. if (result != DISP_CHANGE_SUCCESSFUL)
  528. {
  529. //
  530. // Check if it's a potentially emulated ModeX mode
  531. //
  532. if (pdd_lcl->dwLocalFlags & DDRAWILCL_ALLOWMODEX)
  533. {
  534. if (pdd_lcl->dmiPreferred.wBPP == MODEX_BPP &&
  535. pdd_lcl->dmiPreferred.wWidth == MODEX_WIDTH)
  536. {
  537. if (pdd_lcl->dmiPreferred.wHeight == MODEX_HEIGHT2 || pdd_lcl->dmiPreferred.wHeight == MODEX_HEIGHT1)
  538. {
  539. // Set 640x480x8 for consistency with win9x and reliable mouse pos messages.
  540. dm.dmFields &= ~DM_DISPLAYFREQUENCY;
  541. dm.dmPelsWidth = 640;
  542. dm.dmPelsHeight = 480;
  543. pdd_gbl->dwFlags |= DDRAWI_CHANGINGMODE;
  544. result = ChangeDisplaySettingsEx(pszDevice, &dm, NULL, CDS_FULLSCREEN, 0);
  545. pdd_gbl->dwFlags &= ~DDRAWI_CHANGINGMODE;
  546. }
  547. }
  548. }
  549. if (result == DISP_CHANGE_SUCCESSFUL)
  550. {
  551. //now we are in 640x480, we need to mark the ddraw local that it's in emulated modex
  552. pdd_gbl->dwFlags |= DDRAWI_MODEX;
  553. }
  554. else
  555. {
  556. //failed to set 640x480
  557. NotifyDriverOfFreeAliasedLocks();
  558. return DDERR_UNSUPPORTED;
  559. }
  560. }
  561. uDisplaySettingsUnique = DdQueryDisplaySettingsUniqueness();
  562. resetAllDirectDrawObjects();
  563. pdd_lcl->dwLocalFlags |= DDRAWILCL_MODEHASBEENCHANGED | DDRAWILCL_DIRTYDC;
  564. return DD_OK;
  565. }
  566. //=============================================================================
  567. //
  568. // Function: DD_SetDisplayMode
  569. //
  570. //=============================================================================
  571. HRESULT DDAPI DD_SetDisplayMode(
  572. LPDIRECTDRAW pdd,
  573. DWORD dwWidth,
  574. DWORD dwHeight,
  575. DWORD dwBPP)
  576. {
  577. DPF(2,A,"ENTERAPI: DD_SetDisplayMode");
  578. return DD_SetDisplayMode2(pdd, dwWidth, dwHeight, dwBPP, 0, 0);
  579. }
  580. //=============================================================================
  581. //
  582. // Function: DD_SetDisplayMode2
  583. //
  584. //=============================================================================
  585. HRESULT DDAPI DD_SetDisplayMode2(
  586. LPDIRECTDRAW pdd,
  587. DWORD dwWidth,
  588. DWORD dwHeight,
  589. DWORD dwBPP,
  590. DWORD dwRefreshRate,
  591. DWORD dwFlags)
  592. {
  593. LPDDRAWI_DIRECTDRAW_INT pdd_int;
  594. LPDDRAWI_DIRECTDRAW_LCL pdd_lcl;
  595. LPDDRAWI_DIRECTDRAW_GBL pdd_gbl;
  596. HRESULT hr;
  597. DISPLAYMODEINFO dmiSave;
  598. BOOL excl_exists,has_excl;
  599. ENTER_DDRAW();
  600. DPF(2,A,"ENTERAPI: DD_SetDisplayMode2");
  601. TRY
  602. {
  603. pdd_int = (LPDDRAWI_DIRECTDRAW_INT) pdd;
  604. if (!VALID_DIRECTDRAW_PTR(pdd_int))
  605. {
  606. DPF(0, "Invalid object");
  607. LEAVE_DDRAW();
  608. return DDERR_INVALIDOBJECT;
  609. }
  610. if (dwFlags & ~DDSDM_VALID)
  611. {
  612. DPF_ERR("Invalid flags");
  613. LEAVE_DDRAW();
  614. return DDERR_INVALIDPARAMS;
  615. }
  616. pdd_lcl = pdd_int->lpLcl;
  617. pdd_gbl = pdd_lcl->lpGbl;
  618. if (pdd_gbl->dwSurfaceLockCount > 0)
  619. {
  620. LPDDRAWI_DDRAWSURFACE_INT pTemp;
  621. // When we enabled vidmem vertex buffers in DX8, we found that some
  622. // apps do not unlock them before the mode change, but we don't want
  623. // to break them now, so we will hack around this by allowing the
  624. // mode switch to occur if all that's locked are vidmem VBs.
  625. pTemp = pdd_gbl->dsList;
  626. while (pTemp != NULL)
  627. {
  628. if (pTemp->lpLcl->lpGbl->dwUsageCount > 0)
  629. {
  630. if ((pTemp->lpLcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) &&
  631. !(pTemp->lpLcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER))
  632. {
  633. break;
  634. }
  635. }
  636. pTemp = pTemp->lpLink;
  637. }
  638. if (pTemp != NULL)
  639. {
  640. DPF_ERR("Surfaces are locked, can't switch the mode");
  641. LEAVE_DDRAW();
  642. return DDERR_SURFACEBUSY;
  643. }
  644. }
  645. CheckExclusiveMode(pdd_lcl, &excl_exists, &has_excl, FALSE, NULL, FALSE);
  646. if (excl_exists &&
  647. (!has_excl))
  648. {
  649. DPF_ERR("Can't change mode; exclusive mode not owned");
  650. LEAVE_DDRAW();
  651. return DDERR_NOEXCLUSIVEMODE;
  652. }
  653. dmiSave = pdd_lcl->dmiPreferred;
  654. pdd_lcl->dmiPreferred.wWidth = (WORD) dwWidth;
  655. pdd_lcl->dmiPreferred.wHeight = (WORD) dwHeight;
  656. pdd_lcl->dmiPreferred.wBPP = (BYTE) dwBPP;
  657. pdd_lcl->dmiPreferred.wRefreshRate = (WORD) dwRefreshRate;
  658. }
  659. EXCEPT(EXCEPTION_EXECUTE_HANDLER)
  660. {
  661. DPF_ERR("DD_SetDisplayMode2: Exception encountered validating parameters");
  662. LEAVE_DDRAW();
  663. return DDERR_INVALIDPARAMS;
  664. }
  665. hr = SetDisplayMode(pdd_lcl, 0, FALSE, dwRefreshRate ? TRUE : FALSE);
  666. if (FAILED(hr))
  667. {
  668. pdd_lcl->dmiPreferred = dmiSave;
  669. }
  670. else
  671. {
  672. pdd_lcl->dmiPreferred = pdd_gbl->dmiCurrent;
  673. }
  674. LEAVE_DDRAW();
  675. return hr;
  676. }
  677. //=============================================================================
  678. //
  679. // Function: RestoreDisplayMode
  680. //
  681. //=============================================================================
  682. HRESULT RestoreDisplayMode(LPDDRAWI_DIRECTDRAW_LCL pdd_lcl, BOOL force)
  683. {
  684. LPDDRAWI_DIRECTDRAW_GBL pdd_gbl;
  685. LPCTSTR pszDevice;
  686. LONG result;
  687. pdd_gbl = pdd_lcl->lpGbl;
  688. pdd_gbl->dwFlags &= ~DDRAWI_MODEX;
  689. if (!(pdd_lcl->dwLocalFlags & DDRAWILCL_MODEHASBEENCHANGED))
  690. {
  691. DPF(2, "Mode was never changed by this app");
  692. return DD_OK;
  693. }
  694. if (!force)
  695. {
  696. if (pdd_gbl->dwSurfaceLockCount > 0)
  697. {
  698. LPDDRAWI_DDRAWSURFACE_INT pTemp;
  699. // When we enabled vidmem vertex buffers in DX8, we found that some
  700. // apps do not unlock them before the mode change, but we don't want
  701. // to break them now, so we will hack around this by allowing the
  702. // mode switch to occur if all that's locked are vidmem VBs.
  703. pTemp = pdd_gbl->dsList;
  704. while (pTemp != NULL)
  705. {
  706. if (pTemp->lpLcl->lpGbl->dwUsageCount > 0)
  707. {
  708. if ((pTemp->lpLcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) &&
  709. !(pTemp->lpLcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER))
  710. {
  711. break;
  712. }
  713. }
  714. pTemp = pTemp->lpLink;
  715. }
  716. if (pTemp != NULL)
  717. {
  718. return DDERR_SURFACEBUSY;
  719. }
  720. }
  721. }
  722. if (_stricmp(pdd_gbl->cDriverName, "DISPLAY"))
  723. {
  724. pszDevice = pdd_gbl->cDriverName;
  725. }
  726. else
  727. {
  728. pszDevice = NULL;
  729. }
  730. NotifyDriverToDeferFrees();
  731. pdd_gbl->dwFlags |= DDRAWI_CHANGINGMODE;
  732. result = ChangeDisplaySettingsEx(pszDevice, NULL, NULL, CDS_FULLSCREEN, 0);
  733. pdd_gbl->dwFlags &= ~DDRAWI_CHANGINGMODE;
  734. if (result != DISP_CHANGE_SUCCESSFUL)
  735. {
  736. NotifyDriverOfFreeAliasedLocks();
  737. return DDERR_UNSUPPORTED;
  738. }
  739. //
  740. // FetchDirectDrawData here, which will update the global object with
  741. // the new mode information.
  742. //
  743. uDisplaySettingsUnique = DdQueryDisplaySettingsUniqueness();
  744. resetAllDirectDrawObjects();
  745. pdd_lcl->dwLocalFlags &= ~DDRAWILCL_MODEHASBEENCHANGED;
  746. pdd_lcl->dwLocalFlags |= DDRAWILCL_DIRTYDC;
  747. RedrawWindow(NULL, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);
  748. return DD_OK;
  749. }
  750. //=============================================================================
  751. //
  752. // Function: DD_RestoreDisplayMode
  753. //
  754. //=============================================================================
  755. HRESULT DDAPI DD_RestoreDisplayMode(LPDIRECTDRAW pdd)
  756. {
  757. LPDDRAWI_DIRECTDRAW_INT pdd_int;
  758. LPDDRAWI_DIRECTDRAW_LCL pdd_lcl;
  759. LPDDRAWI_DIRECTDRAW_GBL pdd_gbl;
  760. BOOL excl_exists,has_excl;
  761. HRESULT hr;
  762. ENTER_DDRAW();
  763. DPF(2,A,"ENTERAPI: DD_RestoreDisplayMode");
  764. TRY
  765. {
  766. pdd_int = (LPDDRAWI_DIRECTDRAW_INT) pdd;
  767. if (!VALID_DIRECTDRAW_PTR(pdd_int))
  768. {
  769. DPF(0, "Invalid object");
  770. LEAVE_DDRAW();
  771. return DDERR_INVALIDOBJECT;
  772. }
  773. pdd_lcl = pdd_int->lpLcl;
  774. pdd_gbl = pdd_lcl->lpGbl;
  775. CheckExclusiveMode(pdd_lcl, &excl_exists, &has_excl, FALSE, NULL, FALSE);
  776. if (excl_exists &&
  777. (!has_excl))
  778. {
  779. DPF_ERR("Can't change mode; exclusive mode owned");
  780. LEAVE_DDRAW();
  781. return DDERR_NOEXCLUSIVEMODE;
  782. }
  783. if (pdd_gbl->dwSurfaceLockCount > 0)
  784. {
  785. LPDDRAWI_DDRAWSURFACE_INT pTemp;
  786. // When we enabled vidmem vertex buffers in DX8, we found that some
  787. // apps do not unlock them before the mode change, but we don't want
  788. // to break them now, so we will hack around this by allowing the
  789. // mode switch to occur if all that's locked are vidmem VBs.
  790. pTemp = pdd_gbl->dsList;
  791. while (pTemp != NULL)
  792. {
  793. if (pTemp->lpLcl->lpGbl->dwUsageCount > 0)
  794. {
  795. if ((pTemp->lpLcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) &&
  796. !(pTemp->lpLcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER))
  797. {
  798. break;
  799. }
  800. }
  801. pTemp = pTemp->lpLink;
  802. }
  803. if (pTemp != NULL)
  804. {
  805. DPF_ERR("Surfaces are locked, can't switch the mode");
  806. LEAVE_DDRAW();
  807. return DDERR_SURFACEBUSY;
  808. }
  809. }
  810. }
  811. EXCEPT(EXCEPTION_EXECUTE_HANDLER)
  812. {
  813. DPF_ERR("DD_RestoreDisplayMode: Exception encountered validating parameters");
  814. LEAVE_DDRAW();
  815. return DDERR_INVALIDPARAMS;
  816. }
  817. hr = RestoreDisplayMode(pdd_lcl, TRUE);
  818. LEAVE_DDRAW();
  819. return hr;
  820. }
  821. //=============================================================================
  822. //
  823. // Function: DD_EnumDisplayModes
  824. //
  825. //=============================================================================
  826. HRESULT DDAPI DD_EnumDisplayModes(
  827. LPDIRECTDRAW pdd,
  828. DWORD dwFlags,
  829. LPDDSURFACEDESC pddsd,
  830. LPVOID pContext,
  831. LPDDENUMMODESCALLBACK pEnumCallback)
  832. {
  833. DPF(2,A,"ENTERAPI: DD_EnumDisplayModes");
  834. if (pddsd)
  835. {
  836. DDSURFACEDESC2 ddsd2;
  837. TRY
  838. {
  839. if(!VALID_DIRECTDRAW_PTR(((LPDDRAWI_DIRECTDRAW_INT) pdd)))
  840. {
  841. return DDERR_INVALIDOBJECT;
  842. }
  843. if(!VALID_DDSURFACEDESC_PTR(pddsd))
  844. {
  845. DPF_ERR("Invalid surface description. Did you set the dwSize member?");
  846. DPF_APIRETURNS(DDERR_INVALIDPARAMS);
  847. return DDERR_INVALIDPARAMS;
  848. }
  849. CopyMemory(&ddsd2, pddsd, sizeof *pddsd);
  850. }
  851. EXCEPT(EXCEPTION_EXECUTE_HANDLER)
  852. {
  853. DPF_ERR("Exception encountered validating parameters: Bad LPDDSURFACEDESC");
  854. DPF_APIRETURNS(DDERR_INVALIDPARAMS);
  855. return DDERR_INVALIDPARAMS;
  856. }
  857. ddsd2.dwSize = sizeof ddsd2;
  858. ZeroMemory(((LPBYTE)&ddsd2 + sizeof *pddsd), (sizeof ddsd2) - (sizeof *pddsd));
  859. return DD_EnumDisplayModes4(pdd, dwFlags, &ddsd2, pContext, (LPDDENUMMODESCALLBACK2) pEnumCallback);
  860. }
  861. return DD_EnumDisplayModes4(pdd, dwFlags, NULL, pContext, (LPDDENUMMODESCALLBACK2) pEnumCallback);
  862. }
  863. BOOL EnumerateMode(
  864. LPDDRAWI_DIRECTDRAW_INT pdd_int,
  865. LPDDENUMMODESCALLBACK2 pEnumCallback,
  866. LPVOID pContext,
  867. WORD wWidth,
  868. WORD wHeight,
  869. WORD wBPP,
  870. WORD wRefreshRate,
  871. DWORD dwFlags,
  872. BOOL bIsEmulatedModex )
  873. {
  874. DDSURFACEDESC2 ddsd;
  875. ZeroMemory(&ddsd, sizeof ddsd);
  876. if (LOWERTHANDDRAW4(pdd_int))
  877. {
  878. ddsd.dwSize = sizeof (DDSURFACEDESC);
  879. }
  880. else
  881. {
  882. ddsd.dwSize = sizeof (DDSURFACEDESC2);
  883. }
  884. ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_PITCH | DDSD_REFRESHRATE;
  885. ddsd.dwWidth = wWidth;
  886. ddsd.dwHeight = wHeight;
  887. ddsd.lPitch = (ddsd.dwWidth * wBPP) >> 3; // hack
  888. setPixelFormat(&(ddsd.ddpfPixelFormat), NULL, wBPP);
  889. if (dwFlags & DDEDM_REFRESHRATES)
  890. {
  891. ddsd.dwRefreshRate = wRefreshRate;
  892. }
  893. else
  894. {
  895. ddsd.dwRefreshRate = 0;
  896. }
  897. if ( bIsEmulatedModex )
  898. {
  899. ddsd.ddsCaps.dwCaps |= DDSCAPS_MODEX;
  900. } else
  901. {
  902. // call driver here if this is a stereo mode!!!
  903. if (!LOWERTHANDDRAW7(pdd_int) &&
  904. GetDDStereoMode(pdd_int->lpLcl->lpGbl,
  905. wWidth,
  906. wHeight,
  907. wBPP,
  908. ddsd.dwRefreshRate))
  909. {
  910. ddsd.ddsCaps.dwCaps2 |= DDSCAPS2_STEREOSURFACELEFT;
  911. }
  912. }
  913. return pEnumCallback(&ddsd, pContext);
  914. }
  915. //=============================================================================
  916. //
  917. // Function: DD_EnumDisplayModes4
  918. //
  919. //=============================================================================
  920. HRESULT DDAPI DD_EnumDisplayModes4(
  921. LPDIRECTDRAW pdd,
  922. DWORD dwFlags,
  923. LPDDSURFACEDESC2 pddsd,
  924. LPVOID pContext,
  925. LPDDENUMMODESCALLBACK2 pEnumCallback)
  926. {
  927. LPDDRAWI_DIRECTDRAW_INT pdd_int;
  928. LPDDRAWI_DIRECTDRAW_LCL pdd_lcl;
  929. LPDDRAWI_DIRECTDRAW_GBL pdd_gbl;
  930. HRESULT hr;
  931. DEVMODE dm;
  932. int i, j;
  933. DWORD dwResult;
  934. DISPLAYMODEINFO *pdmi;
  935. DISPLAYMODEINFO *pdmiTemp;
  936. int numModes;
  937. int maxModes;
  938. LPCTSTR pszDevice;
  939. BOOL bFound320x240x8 = FALSE;
  940. BOOL bFound320x200x8 = FALSE;
  941. BOOL bFound640x480x8 = FALSE;
  942. ENTER_DDRAW();
  943. DPF(2,A,"ENTERAPI: DD_EnumDisplayModes4");
  944. TRY
  945. {
  946. pdd_int = (LPDDRAWI_DIRECTDRAW_INT) pdd;
  947. if (!VALID_DIRECTDRAW_PTR(pdd_int))
  948. {
  949. DPF(0, "Invalid object");
  950. LEAVE_DDRAW();
  951. return DDERR_INVALIDOBJECT;
  952. }
  953. pdd_lcl = pdd_int->lpLcl;
  954. pdd_gbl = pdd_lcl->lpGbl;
  955. if (pddsd && !VALID_DDSURFACEDESC2_PTR(pddsd))
  956. {
  957. DPF_ERR("Invalid surface description");
  958. LEAVE_DDRAW();
  959. return DDERR_INVALIDPARAMS;
  960. }
  961. if (dwFlags & ~DDEDM_VALID)
  962. {
  963. DPF_ERR("Invalid flags");
  964. LEAVE_DDRAW();
  965. return DDERR_INVALIDPARAMS;
  966. }
  967. if (!VALIDEX_CODE_PTR(pEnumCallback))
  968. {
  969. DPF_ERR("Invalid enumerate callback pointer");
  970. LEAVE_DDRAW();
  971. return DDERR_INVALIDPARAMS;
  972. }
  973. }
  974. EXCEPT(EXCEPTION_EXECUTE_HANDLER)
  975. {
  976. DPF_ERR("Exception encountered validating parameters: Bad LPDDSURFACEDESC");
  977. LEAVE_DDRAW();
  978. return DDERR_INVALIDPARAMS;
  979. }
  980. maxModes = 256; // enough to handle most drivers
  981. pdmi = LocalAlloc(LMEM_FIXED, maxModes * sizeof (DISPLAYMODEINFO));
  982. if (!pdmi)
  983. {
  984. DPF_ERR("Out of memory building mode list");
  985. LEAVE_DDRAW();
  986. return DDERR_GENERIC;
  987. }
  988. if (_stricmp(pdd_gbl->cDriverName, "DISPLAY"))
  989. {
  990. pszDevice = pdd_gbl->cDriverName;
  991. }
  992. else
  993. {
  994. pszDevice = NULL;
  995. }
  996. dm.dmSize = sizeof(dm);
  997. for (numModes = 0, j = 0; EnumDisplaySettings(pszDevice, j, &dm); ++j)
  998. {
  999. //Filter MODEX driver modes
  1000. if ( (_stricmp(dm.dmDeviceName,"MODEX") == 0) || (_stricmp(dm.dmDeviceName,"VGA") == 0) )
  1001. {
  1002. DPF(5,"Filtered mode %dx%dx%d from %s",dm.dmPelsWidth,dm.dmPelsHeight,dm.dmBitsPerPel,dm.dmDeviceName);
  1003. continue;
  1004. }
  1005. if (dm.dmBitsPerPel == MODEX_BPP)
  1006. {
  1007. if (dm.dmPelsWidth == MODEX_WIDTH)
  1008. {
  1009. if (dm.dmPelsHeight == MODEX_HEIGHT1)
  1010. bFound320x200x8 = TRUE;
  1011. if (dm.dmPelsHeight == MODEX_HEIGHT2)
  1012. bFound320x240x8 = TRUE;
  1013. }
  1014. if (dm.dmPelsWidth == 640 && dm.dmPelsHeight == 480)
  1015. bFound640x480x8 = TRUE;
  1016. }
  1017. //Filter less than 256 color modes
  1018. if (dm.dmBitsPerPel < 8)
  1019. {
  1020. continue;
  1021. }
  1022. //
  1023. // NOTE: If the driver supports 15 bpp but not 16, then
  1024. // EnumDisplaySettings will return 16 for compatibility reasons. The
  1025. // bitmasks we fill in will be for 16 bpp (since we can't determine
  1026. // which mode it really is), so they may be incorrect.
  1027. //
  1028. // There should never be a case where we got only 15 bpp. If a driver
  1029. // only supports 555, it should be reported as 16 bpp.
  1030. //
  1031. if (dm.dmBitsPerPel == 15)
  1032. {
  1033. dm.dmBitsPerPel = 16;
  1034. }
  1035. //
  1036. // If the caller supplied a DDSURFACEDESC, check for width,
  1037. // height, bpp, and refresh rate for a match.
  1038. //
  1039. if (pddsd &&
  1040. (((pddsd->dwFlags & DDSD_WIDTH) &&
  1041. (dm.dmPelsWidth != pddsd->dwWidth)) ||
  1042. ((pddsd->dwFlags & DDSD_HEIGHT) &&
  1043. (dm.dmPelsHeight != pddsd->dwHeight)) ||
  1044. ((pddsd->dwFlags & DDSD_PIXELFORMAT) &&
  1045. (dm.dmBitsPerPel != pddsd->ddpfPixelFormat.dwRGBBitCount)) ||
  1046. ((pddsd->dwFlags & DDSD_REFRESHRATE) &&
  1047. (dm.dmDisplayFrequency != pddsd->dwRefreshRate))))
  1048. {
  1049. continue; // current mode does not match criteria
  1050. }
  1051. //
  1052. // Check to see if mode is already in the list. The flag which
  1053. // affects this is DDEDM_REFRESHRATES.
  1054. //
  1055. for (i = 0; i < numModes; ++i)
  1056. {
  1057. if ((dm.dmPelsWidth == pdmi[i].wWidth) &&
  1058. (dm.dmPelsHeight == pdmi[i].wHeight) &&
  1059. (dm.dmBitsPerPel == pdmi[i].wBPP))
  1060. {
  1061. if (dwFlags & DDEDM_REFRESHRATES)
  1062. {
  1063. if (dm.dmDisplayFrequency == pdmi[i].wRefreshRate)
  1064. {
  1065. break; // found a match
  1066. }
  1067. }
  1068. else
  1069. {
  1070. break; // found a match
  1071. }
  1072. }
  1073. }
  1074. if (i < numModes)
  1075. {
  1076. continue; // mode already in list
  1077. }
  1078. pdmi[numModes].wWidth = (WORD) dm.dmPelsWidth;
  1079. pdmi[numModes].wHeight = (WORD) dm.dmPelsHeight;
  1080. pdmi[numModes].wBPP = (BYTE) dm.dmBitsPerPel;
  1081. pdmi[numModes].wRefreshRate = (dwFlags & DDEDM_REFRESHRATES) ?
  1082. (WORD) dm.dmDisplayFrequency : 0;
  1083. if (++numModes >= maxModes)
  1084. {
  1085. if (maxModes < 8192)
  1086. {
  1087. maxModes <<= 1;
  1088. pdmiTemp = LocalAlloc(LMEM_FIXED, maxModes * sizeof (DISPLAYMODEINFO));
  1089. if (pdmiTemp)
  1090. {
  1091. CopyMemory(pdmiTemp, pdmi, numModes * sizeof (DISPLAYMODEINFO));
  1092. LocalFree(pdmi);
  1093. pdmi = pdmiTemp;
  1094. }
  1095. else
  1096. {
  1097. LocalFree(pdmi);
  1098. DPF_ERR("Out of memory expanding mode list");
  1099. LEAVE_DDRAW();
  1100. return DDERR_GENERIC;
  1101. }
  1102. }
  1103. else
  1104. {
  1105. LocalFree(pdmi);
  1106. DPF_ERR("Too many display modes");
  1107. LEAVE_DDRAW();
  1108. return DDERR_GENERIC;
  1109. }
  1110. }
  1111. }
  1112. //
  1113. // Should we sort modes here? Probably not.
  1114. //
  1115. for (i = 0; i < numModes; ++i)
  1116. {
  1117. if (!EnumerateMode(
  1118. pdd_int,
  1119. pEnumCallback, pContext,
  1120. pdmi[i].wWidth,
  1121. pdmi[i].wHeight,
  1122. pdmi[i].wBPP,
  1123. pdmi[i].wRefreshRate,
  1124. dwFlags,
  1125. FALSE )) //not a modex mode
  1126. {
  1127. break;
  1128. }
  1129. }
  1130. //
  1131. // Enumerate emulated modex modes if required
  1132. //
  1133. while (1)
  1134. {
  1135. if (pdd_lcl->dwLocalFlags & DDRAWILCL_ALLOWMODEX)
  1136. {
  1137. //640x480 is necessary to turn on emulation
  1138. if ( bFound640x480x8 )
  1139. {
  1140. if ( !bFound320x200x8 )
  1141. {
  1142. if (!EnumerateMode(
  1143. pdd_int,
  1144. pEnumCallback, pContext,
  1145. MODEX_WIDTH,MODEX_HEIGHT1,MODEX_BPP,60,
  1146. dwFlags,
  1147. TRUE )) //not a modex mode
  1148. {
  1149. break;
  1150. }
  1151. }
  1152. if ( !bFound320x240x8 )
  1153. {
  1154. if (!EnumerateMode(
  1155. pdd_int,
  1156. pEnumCallback, pContext,
  1157. MODEX_WIDTH,MODEX_HEIGHT2,MODEX_BPP,60,
  1158. dwFlags,
  1159. TRUE )) //not a modex mode
  1160. {
  1161. break;
  1162. }
  1163. }
  1164. }
  1165. }
  1166. break;
  1167. }
  1168. LocalFree(pdmi);
  1169. LEAVE_DDRAW();
  1170. return DD_OK;
  1171. }