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.

2924 lines
79 KiB

  1. /****************************************************************************
  2. *****************************************************************************
  3. *
  4. * ******************************************
  5. * * Copyright (c) 1995, Cirrus Logic, Inc. *
  6. * * All Rights Reserved *
  7. * ******************************************
  8. *
  9. * PROJECT: Laguna I (CL-GD5462) -
  10. *
  11. * FILE: memmgr.c
  12. *
  13. * AUTHOR: Benny Ng
  14. *
  15. * DESCRIPTION:
  16. * This program provides the off screen memory management
  17. * using (X,Y) coordinate as memory reference instead of
  18. * linear memory.
  19. *
  20. * MODULES:
  21. * SaveOffscnToHost()
  22. * RestoreHostToOffscn()
  23. * DDOffScnMemAlloc()
  24. * DDOffScnMemRestore()
  25. * InitOffScnMem()
  26. * AllocOffScnMem()
  27. * FreeOffScnMem()
  28. * CloseOffScnMem()
  29. * ConvertToVideoBufferAddr()
  30. * OFS_AllocHdl()
  31. * OFS_InitMem()
  32. * OFS_PackMem()
  33. * OFS_InsertInFreeQ()
  34. * OFS_RemoveFrmFreeQ()
  35. * OFS_InsertInUsedQ()
  36. * OFS_RemoveFrmUsedQ()
  37. *
  38. * REVISION HISTORY:
  39. * 6/12/95 Benny Ng Initial version
  40. *
  41. * $Log: X:/log/laguna/nt35/displays/cl546x/MEMMGR.C $
  42. *
  43. * Rev 1.48 Mar 04 1998 15:28:50 frido
  44. * Added new shadow macros.
  45. *
  46. * Rev 1.47 Jan 22 1998 16:21:16 frido
  47. * PDR#11132. The CopyBitmaps function is using byte aligned striping
  48. * but was using the normal BLTEXT register instead of MBLTEXT.
  49. *
  50. * Rev 1.46 Dec 10 1997 13:32:16 frido
  51. * Merged from 1.62 branch.
  52. *
  53. * Rev 1.45.1.2 Dec 04 1997 13:40:22 frido
  54. * PDR#11039: Removed memory mover in 24-bpp as well.
  55. *
  56. * Rev 1.45.1.1 Dec 03 1997 18:11:10 frido
  57. * PDR#11039. Disabled the memory mover in 32-bpp. It seems to cause
  58. * corruption. This needs to be investigated after WHQL!
  59. *
  60. * Rev 1.45.1.0 Nov 13 1997 16:40:52 frido
  61. * Added striping code inside the CopyBitmap routine which is used by the
  62. * memory manager mmMove routine. This fixes the drop in speed in the
  63. * High-End Graphics.
  64. *
  65. * Rev 1.45 Nov 03 1997 15:48:10 frido
  66. * Added REQUIRE macros.
  67. *
  68. * Rev 1.44 Oct 28 1997 09:44:00 frido
  69. * Fixed a compile problem with the updated mmCore.c
  70. *
  71. * Rev 1.43 02 Oct 1997 17:13:36 frido
  72. * I have removed the extra rectangle in 1280x1024x8.
  73. *
  74. * Rev 1.42 24 Sep 1997 13:46:14 frido
  75. * PDR#10526: Immortal Klowns needs its surfaces to be DWORD aligned in size.
  76. *
  77. * Rev 1.41 16 Sep 1997 15:07:28 bennyn
  78. *
  79. * Added eight bytes alignment option
  80. *
  81. * Rev 1.40 29 Aug 1997 14:05:12 noelv
  82. * Added MINSZY define.
  83. *
  84. * Rev 1.39 29 Aug 1997 08:54:58 FRIDO
  85. * The old AllocOffScnMem routine had various bugs in there causing
  86. * overlapping rectangles. The entire algoritm has been changed.
  87. *
  88. * Rev 1.38 25 Aug 1997 16:05:46 FRIDO
  89. *
  90. * Added invalidation of brush cache in DDOffScnMemRestore.
  91. *
  92. * Rev 1.37 18 Aug 1997 09:21:22 FRIDO
  93. *
  94. * Added initialization of bitmap filter.
  95. *
  96. * Rev 1.36 13 Aug 1997 12:16:24 bennyn
  97. * Changed the PREALLOC_Y to 17 & Fixed the free rectange initialization bug
  98. *
  99. * Rev 1.35 08 Aug 1997 17:24:16 FRIDO
  100. * Added support for new memory manager.
  101. *
  102. * Rev 1.34 07 Aug 1997 12:31:30 bennyn
  103. * Undo Shuhua's fix and eliminated the extra rectangle for 1600x1200x16 and x
  104. *
  105. * Rev 1.33 06 Aug 1997 12:47:52 noelv
  106. * Shuhua's fix for DXView no-memory bug. # 10227
  107. *
  108. * Rev 1.32 01 Jul 1997 09:53:30 einkauf
  109. * init pdsurf to NULL in OFS_InsertInFreeQ (fix PDR 9385)
  110. * change x tile size to 64 instead of 32 for 3D draw buffers
  111. *
  112. * Rev 1.31 29 Apr 1997 16:28:46 noelv
  113. *
  114. * Merged in new SWAT code.
  115. * SWAT:
  116. * SWAT: Rev 1.6 24 Apr 1997 11:56:40 frido
  117. * SWAT: NT140b09 merge.
  118. * SWAT:
  119. * SWAT: Rev 1.5 24 Apr 1997 11:49:56 frido
  120. * SWAT: Removed all memory manager changes.
  121. * SWAT:
  122. * SWAT: Rev 1.4 19 Apr 1997 16:41:56 frido
  123. * SWAT: Fixed minor bugs.
  124. * SWAT: Added SWAT.h include file.
  125. * SWAT:
  126. * SWAT: Rev 1.3 15 Apr 1997 19:12:56 frido
  127. * SWAT: Added more SWAT5 code (still disabled).
  128. * SWAT:
  129. * SWAT: Rev 1.2 10 Apr 1997 17:36:56 frido
  130. * SWAT: Started work on SWAT5 optmizations.
  131. * SWAT:
  132. * SWAT: Rev 1.1 09 Apr 1997 17:33:16 frido
  133. * SWAT: Called vAssertModeText to enable/disable font cache for DirectDraw.
  134. *
  135. * Rev 1.30 17 Apr 1997 15:31:28 noelv
  136. * Dont' use the extra rectangle on an 8 meg board.
  137. *
  138. * Rev 1.29 17 Apr 1997 12:03:44 bennyn
  139. * Fixed init offscn mem allocation problem for 1280x1024x24.
  140. *
  141. * Rev 1.28 26 Feb 1997 09:23:40 noelv
  142. *
  143. * Added MCD support from ADC
  144. *
  145. * Rev 1.27 23 Jan 1997 10:57:32 noelv
  146. * Added debugging option to erase memory blocks when freed.
  147. *
  148. * Rev 1.26 27 Nov 1996 11:32:42 noelv
  149. * Disabled Magic Bitmap. Yeah!!!
  150. *
  151. * Rev 1.25 26 Nov 1996 09:58:52 noelv
  152. *
  153. * Added DBG prints.
  154. *
  155. * Rev 1.24 12 Nov 1996 15:21:58 bennyn
  156. *
  157. * Fixed ALT-ENTER problem with DD appl
  158. *
  159. * Rev 1.23 07 Nov 1996 16:01:38 bennyn
  160. * Alloc offscn mem in DD createsurface
  161. *
  162. * Rev 1.22 23 Oct 1996 14:42:42 BENNYN
  163. *
  164. * CLeanup not use code for DirectDraw cursor
  165. *
  166. * Rev 1.21 18 Sep 1996 13:58:48 bennyn
  167. *
  168. * Put the cursor mask and brush cache at the bottom of offscn mem
  169. *
  170. * Rev 1.20 27 Aug 1996 09:41:48 bennyn
  171. * Restore the changes from the missing version
  172. *
  173. * Rev 1.19 26 Aug 1996 17:33:40 bennyn
  174. * Restore the changes for the losed version
  175. *
  176. * Rev 1.18 23 Aug 1996 09:10:28 noelv
  177. * Save unders are now discardable.
  178. *
  179. * Rev 1.7 22 Aug 1996 18:09:30 frido
  180. * #ss -Added removing of DrvSaveScreenBits areas when DirectDraw gets
  181. * initialized.
  182. *
  183. * Rev 1.6 20 Aug 1996 11:07:56 frido
  184. * #ddl - Fixed DirectDraw lockup problem (compiler optimization bug).
  185. *
  186. * Rev 1.5 17 Aug 1996 19:39:16 frido
  187. * Fixed DirectDraw cursor problem.
  188. *
  189. * Rev 1.4 17 Aug 1996 14:03:42 frido
  190. * Added pre-compiled header.
  191. *
  192. * Rev 1.3 17 Aug 1996 13:25:28 frido
  193. * New release from Bellevue.
  194. *
  195. * Rev 1.14 16 Aug 1996 09:04:22 bennyn
  196. *
  197. * Modified to fix DirectDraw cursor problem
  198. *
  199. * Rev 1.13 07 Aug 1996 13:52:32 noelv
  200. *
  201. * Cleaned up my hack job init code.
  202. *
  203. * Rev 1.12 25 Jul 1996 15:59:14 bennyn
  204. *
  205. * Free more offscreen mem for DirectDraw
  206. *
  207. * Rev 1.11 11 Jul 1996 15:54:18 bennyn
  208. *
  209. * Added DirectDraw support
  210. *
  211. * Rev 1.10 05 Jun 1996 09:03:10 noelv
  212. *
  213. * Added the "extra rectangle".
  214. *
  215. * Rev 1.9 27 May 1996 14:53:12 BENNYN
  216. * Use 2 free queues search instead of one
  217. *
  218. * Rev 1.8 21 May 1996 14:43:24 BENNYN
  219. * Cleanup and code optimize.
  220. *
  221. * Rev 1.7 01 May 1996 11:00:06 bennyn
  222. *
  223. * Modified for NT4.0
  224. *
  225. * Rev 1.6 25 Apr 1996 22:40:34 noelv
  226. * Cleaned up frame buffer initialization some. All of main rectangle is mana
  227. *
  228. * Rev 1.5 10 Apr 1996 14:14:34 NOELV
  229. *
  230. * Hacked to ignore the 'extra' rectangle.
  231. *
  232. * Rev 1.4 04 Apr 1996 13:20:18 noelv
  233. * Frido release 26
  234. *
  235. * Rev 1.2 28 Mar 1996 20:03:16 frido
  236. * Added comments around changes.
  237. *
  238. * Rev 1.1 25 Mar 1996 11:56:26 frido
  239. * Removed warning message.
  240. *
  241. * Rev 1.0 17 Jan 1996 12:53:26 frido
  242. * Checked in from initial workfile by PVCS Version Manager Project Assistant.
  243. *
  244. * Rev 1.0 25 Jul 1995 11:23:18 NOELV
  245. * Initial revision.
  246. *
  247. * Rev 1.4 20 Jun 1995 16:09:46 BENNYN
  248. *
  249. *
  250. * Rev 1.3 09 Jun 1995 16:03:38 BENNYN
  251. *
  252. * Rev 1.2 09 Jun 1995 09:48:54 BENNYN
  253. * Modified the linear address offset calculation
  254. *
  255. * Rev 1.1 08 Jun 1995 15:20:08 BENNYN
  256. *
  257. * Rev 1.0 08 Jun 1995 14:54:16 BENNYN
  258. * Initial revision.
  259. *
  260. ****************************************************************************
  261. ****************************************************************************/
  262. /*----------------------------- INCLUDES ----------------------------------*/
  263. #include "precomp.h"
  264. #include "SWAT.h" // SWAT optimizations.
  265. #define DISPLVL 1
  266. #if !MEMMGR
  267. /******************************************************************************\
  268. * *
  269. * O L D M E M O R Y M A N A G E R *
  270. * *
  271. \******************************************************************************/
  272. /*----------------------------- DEFINES -----------------------------------*/
  273. // Definition of FLAG in OFMHDL structure
  274. #define IN_USE 1
  275. #define FREE 2
  276. #define UNKNOWN 3
  277. #define MEMSZY 64
  278. #define MINSZX 16
  279. #define MINSZY 1
  280. //#define DBGBRK
  281. #define PREALLOC_Y 17
  282. //
  283. // This is a debugging option.
  284. // We will erase (paint white) offscreen memory when it is freed.
  285. //
  286. #define CLEAR_WHEN_FREE 0
  287. /*--------------------- STATIC FUNCTION PROTOTYPES ------------------------*/
  288. /*--------------------------- ENUMERATIONS --------------------------------*/
  289. /*----------------------------- TYPEDEFS ----------------------------------*/
  290. typedef union _HOST_DATA {
  291. BYTE bData[8];
  292. DWORD dwData[2];
  293. } HOST_DATA;
  294. /*-------------------------- STATIC VARIABLES -----------------------------*/
  295. /*-------------------------- GLOBAL FUNCTIONS -----------------------------*/
  296. // Function prototypes
  297. POFMHDL OFS_AllocHdl();
  298. BOOL OFS_InitMem (PPDEV ppdev, PRECTL surf);
  299. POFMHDL OFS_FindBestFitFreeBlock(PPDEV ppdev, OFMHDL *pFreeQ,
  300. PLONG reqszx, PLONG reqszy,
  301. ULONG alignflag);
  302. void OFS_PackMem (PPDEV ppdev, OFMHDL *hdl);
  303. void OFS_InsertInFreeQ (PPDEV ppdev, OFMHDL *hdl);
  304. void OFS_RemoveFrmFreeQ (PPDEV ppdev, OFMHDL *hdl);
  305. void OFS_InsertInUsedQ (PPDEV ppdev, OFMHDL *hdl);
  306. void OFS_RemoveFrmUsedQ (PPDEV ppdev, OFMHDL *hdl);
  307. BOOL OFS_DiscardMem(PPDEV ppdev, LONG reqszx, LONG reqszy);
  308. #ifndef WINNT_VER35
  309. #if 0 // Save the code as sample screen to host and host to screen BLT
  310. // ppdev->pPtrMaskHost = SaveOffscnToHost(ppdev, ppdev->PtrMaskHandle);
  311. // RestoreHostToOffscn(ppdev, ppdev->PtrMaskHandle, ppdev->pPtrMaskHost);
  312. /****************************************************************************
  313. * FUNCTION NAME: SaveOffscnToHost
  314. *
  315. * DESCRIPTION: Save the off-screen memory to host.
  316. *
  317. * Output: Pointer to host address
  318. * NULL = failed.
  319. ****************************************************************************/
  320. PBYTE SaveOffscnToHost(PPDEV ppdev, POFMHDL pdh)
  321. {
  322. BYTE *pvHost = NULL;
  323. BYTE *pvHostScan0;
  324. HOST_DATA rddata;
  325. ULONG ultmp;
  326. LONG i, j, k;
  327. LONG xsize, ysize, tsize;
  328. if (pdh == NULL)
  329. return NULL;
  330. // Calculate the host size
  331. tsize = pdh->sizex * pdh->sizey;
  332. pvHostScan0 = (BYTE *) MEM_ALLOC (FL_ZERO_MEMORY, tsize, ALLOC_TAG);
  333. if (pvHostScan0 == NULL)
  334. return NULL;
  335. DISPDBG((DISPLVL, "SaveOffscnToHost\n"));
  336. // Do a Screen to Host BLT
  337. // Wait for BLT engine not busy
  338. while (((ultmp = LLDR_SZ (grSTATUS)) & 0x7) != 0)
  339. ;
  340. // Save the host address in PDEV
  341. pvHost = pvHostScan0;
  342. // Setup the laguna registers for byte to byte BLT extents
  343. REQUIRE(9);
  344. LL_DRAWBLTDEF(0x201000CC, 0);
  345. // LL16 (grOP1_opRDRAM.pt.X, 0);
  346. LL_OP1_MONO (pdh->x, pdh->y);
  347. LL32 (grOP0_opMRDRAM.dw, 0);
  348. // LL16 (grMBLTEXT_EX.pt.X, (WORD)lSrcDelta);
  349. // LL16 (grMBLTEXT_EX.pt.Y, cy);
  350. xsize = pdh->sizex;
  351. ysize = pdh->sizey;
  352. LL_MBLTEXT (xsize, ysize);
  353. // Copy the offscreen memory data to host space
  354. for (i=0; i < ysize; i++)
  355. {
  356. // Copy one screen line data from source to destination
  357. k = 8;
  358. for (j=0; j < xsize; j++)
  359. {
  360. if (k > 7)
  361. {
  362. k = 0;
  363. // Read the offscreen data
  364. rddata.dwData[0] = LLDR_SZ(grHOSTDATA[0]);
  365. rddata.dwData[1] = LLDR_SZ(grHOSTDATA[1]);
  366. };
  367. *pvHostScan0 = rddata.bData[k++];
  368. pvHostScan0++;
  369. }; // end for j
  370. }; // end for i
  371. return (pvHost);
  372. }
  373. /****************************************************************************
  374. * FUNCTION NAME: RestoreHostToOffscn
  375. *
  376. * DESCRIPTION: Restore host data to the off-screen memory.
  377. *
  378. * Output: TRUE = success,
  379. * FALSE = failed.
  380. ****************************************************************************/
  381. BOOL RestoreHostToOffscn(PPDEV ppdev, POFMHDL pdh, PBYTE pHostAddr)
  382. {
  383. BYTE *pvScan0;
  384. ULONG ultmp;
  385. LONG cx, cy;
  386. LONG i, j, k;
  387. ULONG XYcord;
  388. PDWORD pPattern;
  389. HOST_DATA datapattern;
  390. LONG xsize, ysize;
  391. if ((pdh == NULL) || (pHostAddr == NULL))
  392. return FALSE;
  393. DISPDBG((DISPLVL, "RestoreHostToOffscn\n"));
  394. // Do the host to screen blt
  395. // Wait for BLT engine not busy
  396. while (((ultmp = LLDR_SZ (grSTATUS)) & 0x7) != 0)
  397. ;
  398. pPattern = &datapattern.dwData[0];
  399. pvScan0 = pHostAddr;
  400. // Get dimensions of the bitmap
  401. cx = pdh->sizex;
  402. cy = pdh->sizey;
  403. // Setup the laguna registers for byte to byte BLT extents
  404. REQUIRE(9);
  405. LL_DRAWBLTDEF(0x102000CC, 0);
  406. // LL16 (grOP1_opRDRAM.pt.X, 0);
  407. LL_OP1 (0,0);
  408. XYcord = (pdh->y << 16) | (pdh->x);
  409. LL32 (grOP0_opMRDRAM.dw, XYcord);
  410. // LL16 (grMBLTEXT_EX.pt.X, (WORD)lSrcDelta);
  411. // LL16 (grMBLTEXT_EX.pt.Y, cy);
  412. LL_MBLTEXT (cx, cy);
  413. // Copy the host bitmap data into the space in offscreen memory
  414. k = 0;
  415. for (i=0; i < cy; i++)
  416. {
  417. datapattern.dwData[0] = 0;
  418. // Copy one screen line data from source to destination
  419. for (j=0; j < cx; j++)
  420. {
  421. datapattern.bData[k++] = *pvScan0;
  422. pvScan0++;
  423. if (k > 3)
  424. {
  425. REQUIRE(1);
  426. LL32 (grHOSTDATA[0], *pPattern);
  427. k = 0;
  428. }; // endif (k > 3)
  429. }; // endfor j
  430. }; // end for i
  431. return TRUE;
  432. }
  433. #endif
  434. #if 0 // SWAT3 - the "inifinite" loop has gone
  435. #if 1 //#ddl
  436. #pragma optimize("", off)
  437. #endif
  438. #endif
  439. /****************************************************************************
  440. * FUNCTION NAME: DDOffScnMemAlloc()
  441. *
  442. * DESCRIPTION: Free up as much off-screen memory as possible, and
  443. * reserve the biggest chunk for use by DirectDraw.
  444. *
  445. * Output: Pointer to the OFMHDL structure or.
  446. * NULL means not enough memory for allocation.
  447. ****************************************************************************/
  448. POFMHDL DDOffScnMemAlloc(PPDEV ppdev)
  449. {
  450. LONG lg_szx, lg_szy;
  451. OFMHDL *pds, *pallochdl;
  452. POFMHDL pofm, pofmNext;
  453. ULONG ultmp;
  454. DISPDBG((DISPLVL, "DDOffScnMemAlloc\n"));
  455. #ifdef DBGBRK
  456. DBGBREAKPOINT();
  457. #endif
  458. #if WINBENCH96
  459. // Free the pre-allocate magic block
  460. if (ppdev->pofmMagic != NULL)
  461. {
  462. FreeOffScnMem(ppdev, ppdev->pofmMagic);
  463. ppdev->pofmMagic = NULL;
  464. ppdev->bMagicUsed = 0;
  465. };
  466. #endif
  467. #if 0 // Not free the brush cache
  468. // Free the brush cache
  469. if (ppdev->Bcache != NULL)
  470. {
  471. FreeOffScnMem(ppdev, ppdev->Bcache);
  472. ppdev->Bcache = NULL;
  473. };
  474. #endif // Not free the brush cache
  475. // We have to move all off-screen device bitmaps to memory.
  476. for (pofm = ppdev->OFM_UsedQ; pofm; pofm = pofmNext)
  477. {
  478. pofmNext = pofm->nexthdl;
  479. if ( (pofm->pdsurf) && (pofm->pdsurf->pofm) )
  480. {
  481. if (!bCreateDibFromScreen(ppdev, pofm->pdsurf))
  482. {
  483. DISPDBG((DISPLVL, "DD: Error moving off-screen bitmap to DIB"));
  484. break;
  485. }
  486. }
  487. #if 1 //#ss
  488. else if (pofm->alignflag & SAVESCREEN_FLAG)
  489. {
  490. // Free the DrvSaveScreenBits rectangle.
  491. FreeOffScnMem(ppdev, pofm);
  492. }
  493. #endif
  494. }
  495. // Free the Font cache.
  496. #if 1 // SWAT3 - Font cache release has moved to vAssertModeText.
  497. vAssertModeText(ppdev, FALSE);
  498. #else
  499. while (ppdev->pfcChain != NULL)
  500. {
  501. DrvDestroyFont(ppdev->pfcChain->pfo);
  502. }
  503. #endif
  504. // Find the biggest chunk of free memory for use by DirectDraw.
  505. #ifndef ALLOC_IN_CREATESURFACE
  506. if ((pds = ppdev->OFM_SubFreeQ2) == NULL)
  507. pds = ppdev->OFM_SubFreeQ1;
  508. #endif
  509. pallochdl = NULL;
  510. #ifndef ALLOC_IN_CREATESURFACE
  511. lg_szx = 0;
  512. lg_szy = 0;
  513. while (pds != NULL)
  514. {
  515. if (pds->flag == FREE)
  516. {
  517. if ((pds->sizex > lg_szx) || (pds->sizey > lg_szy))
  518. {
  519. lg_szx = pds->sizex;
  520. lg_szy = pds->sizey;
  521. pallochdl = pds;
  522. }; // if ((pds->sizex > lg_szx) || (pds->sizex > lg_szy))
  523. }; // if (pds->flag == FREE)
  524. // Next free block
  525. pds = pds->subnxthdl;
  526. } /* end while */
  527. // Remove the free block from Free Queue and insert into the Used Queue
  528. if (pallochdl != NULL)
  529. {
  530. OFS_RemoveFrmFreeQ(ppdev, pallochdl);
  531. OFS_InsertInUsedQ(ppdev, pallochdl);
  532. };
  533. #endif
  534. return(pallochdl);
  535. } // DDOffScnMemAlloc()
  536. #if 0 // SWAT3
  537. #if 1 //#ddl
  538. #pragma optimize("", on)
  539. #endif
  540. #endif
  541. /****************************************************************************
  542. * FUNCTION NAME: DDOffScnMemRestore()
  543. *
  544. * DESCRIPTION: Restore the offscreen memory allocation after DirectDraw
  545. * use.
  546. ****************************************************************************/
  547. void DDOffScnMemRestore(PPDEV ppdev)
  548. {
  549. SIZEL sizl;
  550. int i;
  551. ULONG curloc;
  552. ULONG ultmp;
  553. DDOFM *pds;
  554. DDOFM *nxtpds;
  555. DISPDBG((DISPLVL, "DDOffScnMemRestore\n"));
  556. #ifdef DBGBRK
  557. DBGBREAKPOINT();
  558. #endif
  559. // Free all the DD allocate offsreen memory
  560. pds = ppdev->DDOffScnMemQ;
  561. while (pds != NULL)
  562. {
  563. nxtpds = pds->nexthdl;
  564. FreeOffScnMem(ppdev, pds->phdl);
  565. MEMORY_FREE(pds);
  566. pds = nxtpds;
  567. };
  568. ppdev->DDOffScnMemQ = NULL;
  569. // Free the allocated DirectDraw off-screen memory
  570. if (ppdev->DirectDrawHandle != NULL)
  571. {
  572. FreeOffScnMem(ppdev, ppdev->DirectDrawHandle);
  573. ppdev->DirectDrawHandle = NULL;
  574. };
  575. #if 0 // Not free the brush cache
  576. // Allocate brush cache
  577. vInvalidateBrushCache(ppdev);
  578. // Invalidate the entire monochrome brush cache.
  579. for (i = 0; i < NUM_MONO_BRUSHES; i++)
  580. {
  581. ppdev->Mtable[i].iUniq = 0;
  582. memset(ppdev->Mtable[i].ajPattern, 0, sizeof(ppdev->Mtable[i].ajPattern));
  583. }
  584. ppdev->MNext = 0;
  585. // Invalidate the entire 4-bpp brush cache.
  586. for (i = 0; i < NUM_4BPP_BRUSHES; i++)
  587. {
  588. ppdev->Xtable[i].iUniq = 0;
  589. memset(ppdev->Xtable[i].ajPattern, 0, sizeof(ppdev->Xtable[i].ajPattern));
  590. }
  591. ppdev->XNext = 0;
  592. // Invalidate the entire dither brush cache.
  593. for (i = 0; i < NUM_DITHER_BRUSHES; i++)
  594. {
  595. ppdev->Dtable[i].ulColor = (ULONG) -1;
  596. }
  597. ppdev->DNext = 0;
  598. // Invalidate the entire color brush cache.
  599. for (i = 0; i < (int) ppdev->CLast; i++)
  600. {
  601. ppdev->Ctable[i].brushID = 0;
  602. }
  603. ppdev->CNext = 0;
  604. #else
  605. // Invalidate the entire brush cache now.
  606. vInvalidateBrushCache(ppdev);
  607. #endif // Not free the brush cache
  608. #if WINBENCH96
  609. // Allocate the magic block
  610. sizl.cx = MAGIC_SIZEX;
  611. sizl.cy = MAGIC_SIZEY;
  612. ppdev->pofmMagic = AllocOffScnMem(ppdev, &sizl, PIXEL_AlIGN, NULL);
  613. ppdev->bMagicUsed = 0;
  614. #endif
  615. // Invalidate all cached fonts.
  616. #if SWAT3
  617. vAssertModeText(ppdev, TRUE);
  618. #endif
  619. ppdev->ulFontCount++;
  620. } // DDOffScnMemRestore()
  621. #endif // ! ver3.51
  622. /****************************************************************************
  623. * FUNCTION NAME: InitOffScnMem()
  624. *
  625. * DESCRIPTION: Initialize the offscreen memory. This module uses
  626. * the screen size, screen pitch and bits per pixel to
  627. * calculate the amount of off screen available and performs
  628. * the off screen memory management initialization.
  629. *
  630. * When this routine is called, the following member in
  631. * the PDEV structure is assumed being setup for the current
  632. * mode.
  633. * lOffset_2D,
  634. * lTotalMem,
  635. * lTileSize,
  636. * lDeltaScreen,
  637. * ulBitCount
  638. * cxScreen,
  639. * cyScreen.
  640. *
  641. * This routine needs to be called whenever there is a
  642. * mode change.
  643. *
  644. * Output: TRUE = Ok,
  645. * FALSE = failed.
  646. ****************************************************************************/
  647. BOOL InitOffScnMem(PPDEV ppdev)
  648. {
  649. BOOL bAllocCursorMaskBuf;
  650. RECTL surf;
  651. SIZEL rctsize;
  652. ULONG AvailMem;
  653. ULONG ulTemp;
  654. ULONG alignflag;
  655. LONG ScnPitch;
  656. ULONG BytesInExtraRect, BytesInMainRect, Interleave, WidthInTiles,
  657. TileHeight, ExtraHeight, ExtraWidth, NumScanLines;
  658. ULONG ulLastLinearScan = ppdev->lTotalMem / ppdev->lDeltaScreen;
  659. BYTE TileCntl;
  660. DISPDBG((DISPLVL, "InitOffScnMem\n"));
  661. #ifdef DBGBRK
  662. DBGBREAKPOINT();
  663. #endif
  664. // If invalid argument or offscreen manager already initialized,
  665. // return FALSE
  666. if ((ppdev == NULL) || (ppdev->OFM_init == TRUE))
  667. return (FALSE);
  668. // Create Mutex
  669. #ifdef WINNT_VER40
  670. if ((ppdev->MMhsem = EngCreateSemaphore()) == NULL)
  671. #else
  672. if ((ppdev->MutexHdl = CreateMutex(NULL, FALSE, NULL)) == NULL)
  673. #endif
  674. return (FALSE);
  675. // Wait for Mutex is released
  676. #ifdef WINNT_VER40
  677. EngAcquireSemaphore(ppdev->MMhsem);
  678. #else
  679. WaitForSingleObject(ppdev->MutexHdl, INFINITE);
  680. #endif
  681. ppdev->bDirectDrawInUse = FALSE;
  682. ppdev->OFM_init = TRUE;
  683. ppdev->OFM_SubFreeQ1 = NULL;
  684. ppdev->OFM_SubFreeQ2 = NULL;
  685. ppdev->OFM_UsedQ = NULL;
  686. ppdev->OFM_FreeQ = NULL;
  687. ppdev->DDOffScnMemQ = NULL;
  688. #ifdef WINNT_VER40
  689. ppdev->DirectDrawHandle = NULL;
  690. #endif
  691. // Release the Mutex
  692. #ifdef WINNT_VER40
  693. EngReleaseSemaphore(ppdev->MMhsem);
  694. #else
  695. ReleaseMutex(ppdev->MutexHdl);
  696. #endif
  697. //
  698. // Get the whole frame buffer as off screen memory.
  699. // The frame buffer is composed of 2 rectangles. A main rectangle
  700. // whose width is the same as the memory pitch, and an "extra" rectangle
  701. // which is narrower and hangs off the lower left corner of the main
  702. // rectangle.
  703. //
  704. // The tiling interleave factor.
  705. TileCntl = LLDR_SZ(grTILE_CTRL);
  706. DISPDBG((DISPLVL, "InitOffScnMem - TileCntl = %d\n", TileCntl));
  707. TileCntl = (TileCntl >> 6) & 0x3;
  708. Interleave = 1 << TileCntl;
  709. DISPDBG((DISPLVL, "InitOffScnMem - Interleave = %d\n", Interleave));
  710. // Width of the frame buffer in tiles. Each tile may be 128x16 bytes
  711. // or 256x8 bytes.
  712. WidthInTiles = ppdev->lDeltaScreen / ppdev->lTileSize;
  713. DISPDBG((DISPLVL, "InitOffScnMem - WidthInTiles = %d\n", WidthInTiles));
  714. // Get the size in bytes of the Extra rectangle.
  715. BytesInExtraRect = ppdev->lTotalMem % (WidthInTiles * 2048 * Interleave);
  716. DISPDBG((DISPLVL, "InitOffScnMem - BytesInExtraRect = %d\n",
  717. BytesInExtraRect));
  718. // Get the size in bytes of the Main rectangle
  719. BytesInMainRect = ppdev->lTotalMem - BytesInExtraRect;
  720. DISPDBG((DISPLVL, "InitOffScnMem - BytesInMain = %d\n", BytesInMainRect));
  721. // Get the number of scan lines in the main rectangle.
  722. NumScanLines = BytesInMainRect / ppdev->lDeltaScreen;
  723. DISPDBG((DISPLVL, "InitOffScnMem - NumScanLines = %d\n", NumScanLines));
  724. // v-normmi
  725. ppdev->cyMemoryReal = NumScanLines; // without extra rectangle which will be
  726. // added below
  727. // Manage main rectangle
  728. if (NumScanLines > (ppdev->cyScreen + PREALLOC_Y))
  729. {
  730. surf.left = 0;
  731. surf.top = 0;
  732. surf.right = ppdev->lDeltaScreen;
  733. surf.bottom = NumScanLines - PREALLOC_Y;
  734. }
  735. else if (NumScanLines > ppdev->cyScreen)
  736. {
  737. surf.left = 0;
  738. surf.top = 0;
  739. surf.right = ppdev->lDeltaScreen;
  740. surf.bottom = ppdev->cyScreen;
  741. }
  742. // v-normmi
  743. // else if ((ULONG) ppdev->lDeltaScreen != ppdev->cxScreen)
  744. else if ((ULONG) ppdev->lDeltaScreen != (ppdev->cxScreen * ppdev->iBytesPerPixel))
  745. {
  746. surf.left = ppdev->cxScreen * ppdev->iBytesPerPixel;
  747. surf.top = 0;
  748. surf.right = ppdev->lDeltaScreen;
  749. surf.bottom = NumScanLines - PREALLOC_Y;
  750. if (!OFS_InitMem(ppdev, &surf))
  751. {
  752. DISPDBG((DISPLVL, "InitOffScnMem - InitMem1-1 failed\n"));
  753. return(FALSE);
  754. }
  755. surf.left = 0;
  756. surf.top = 0;
  757. surf.right = ppdev->cxScreen * ppdev->iBytesPerPixel;
  758. surf.bottom = NumScanLines;
  759. }
  760. else
  761. {
  762. surf.left = 0;
  763. surf.top = 0;
  764. surf.right = ppdev->lDeltaScreen;
  765. surf.bottom = NumScanLines;
  766. };
  767. DISPDBG((DISPLVL, "Initializing surface (x=%d,y=%d) to (x=%d,y=%d)....\n",
  768. surf.left, surf.top, surf.right, surf.bottom));
  769. if (!OFS_InitMem(ppdev, &surf))
  770. {
  771. DISPDBG((DISPLVL, "InitOffScnMem - InitMem1 failed\n"));
  772. return(FALSE);
  773. }
  774. // Mark a (PREALLOC_Y x Screen pitch) free block at the buttom
  775. // of the offscreen memory.
  776. // The purpose for that is to force the cursor mask and brush cache
  777. // to be allocated at that area.
  778. bAllocCursorMaskBuf = FALSE;
  779. if (NumScanLines > (ppdev->cyScreen + PREALLOC_Y))
  780. {
  781. bAllocCursorMaskBuf = TRUE;
  782. surf.left = 0;
  783. surf.top = NumScanLines - PREALLOC_Y;
  784. surf.right = ppdev->lDeltaScreen;
  785. surf.bottom = NumScanLines;
  786. }
  787. else if (NumScanLines > ppdev->cyScreen)
  788. {
  789. bAllocCursorMaskBuf = TRUE;
  790. surf.left = 0;
  791. surf.top = ppdev->cyScreen;
  792. surf.right = ppdev->lDeltaScreen;
  793. surf.bottom = NumScanLines;
  794. }
  795. // v-normmi
  796. // else if ((ULONG) ppdev->lDeltaScreen != ppdev->cxScreen)
  797. else if ((ULONG) ppdev->lDeltaScreen != (ppdev->cxScreen * ppdev->iBytesPerPixel))
  798. {
  799. bAllocCursorMaskBuf = TRUE;
  800. surf.left = ppdev->cxScreen * ppdev->iBytesPerPixel;
  801. surf.top = NumScanLines - PREALLOC_Y;
  802. surf.right = ppdev->lDeltaScreen;
  803. surf.bottom = NumScanLines;
  804. };
  805. if (bAllocCursorMaskBuf)
  806. {
  807. if (!OFS_InitMem(ppdev, &surf))
  808. {
  809. DISPDBG((DISPLVL, "InitOffScnMem - InitMem2 failed\n"));
  810. return(FALSE);
  811. }
  812. };
  813. //
  814. // BTN - For some reason, this extra rectange cause the WHQL PC97
  815. // Rand Create/Release 100x test fails on 1600x1200x16 and 1600x1200x8
  816. //
  817. if ((ppdev->cxScreen == 1600) &&
  818. (ppdev->cyScreen == 1200) &&
  819. ((ppdev->iBytesPerPixel == 2) || (ppdev->iBytesPerPixel == 1)))
  820. BytesInExtraRect = 0;
  821. //
  822. // Manage the extra rectangle.
  823. // NVH - Skip for 8 meg boards.
  824. //
  825. if (ppdev->lTotalMem < 8*1024*1024)
  826. if (BytesInExtraRect)
  827. {
  828. // get Tile Height
  829. TileHeight = 2048 / ppdev->lTileSize;
  830. DISPDBG((DISPLVL, "InitOffScnMem - TileHeight = %d\n", TileHeight));
  831. // Get height of extra rectangle
  832. ExtraHeight = Interleave * TileHeight;
  833. DISPDBG((DISPLVL, "InitOffScnMem - ExtraHeight = %d\n", ExtraHeight));
  834. // v-normmi
  835. ppdev->cyMemoryReal += ExtraHeight; // account for extra rectangle
  836. // Get the width of the extra rectangle
  837. ExtraWidth = BytesInExtraRect / ExtraHeight;
  838. DISPDBG((DISPLVL, "InitOffScnMem - ExtraWidth = %d\n", ExtraWidth));
  839. ulLastLinearScan = (ExtraHeight + NumScanLines);
  840. surf.left = 0;
  841. surf.top = NumScanLines;
  842. surf.right = ExtraWidth;
  843. surf.bottom = MIN ((LONG) ulLastLinearScan,
  844. (LONG) (ExtraHeight+NumScanLines));
  845. DISPDBG((DISPLVL, "Initializing surface (x=%d,y=%d) to (x=%d,y=%d).\n",
  846. surf.left, surf.top, surf.right, surf.bottom));
  847. if (!OFS_InitMem(ppdev, &surf))
  848. {
  849. DISPDBG((DISPLVL, "InitOffScnMem - InitMem1 failed\n"));
  850. return(FALSE);
  851. }
  852. }
  853. else
  854. {
  855. DISPDBG((DISPLVL, " **** No extra rectangle.\n"));
  856. }
  857. #ifdef DBGBRK
  858. DBGBREAKPOINT();
  859. #endif
  860. // Allocate the active video buffer space from the off screen memory
  861. rctsize.cx = ppdev->cxScreen;
  862. rctsize.cy = ppdev->cyScreen;
  863. if ((ppdev->lTileSize == (LONG) 128) || (ppdev->lTileSize == (LONG) 256))
  864. alignflag = 0;
  865. else
  866. alignflag = NO_X_TILE_AlIGN | NO_Y_TILE_AlIGN;
  867. if ((ppdev->ScrnHandle = AllocOffScnMem(ppdev, &rctsize, alignflag, NULL)) == NULL)
  868. {
  869. DISPDBG((DISPLVL, "InitOffScnMem - AllocOffScnMem failed\n"));
  870. return(FALSE);
  871. };
  872. DISPDBG((DISPLVL, "InitOffScnMem Completed\n"));
  873. #ifdef DBGBRK
  874. DBGBREAKPOINT();
  875. #endif
  876. return (TRUE);
  877. } // InitOffScnMem()
  878. /****************************************************************************
  879. * FUNCTION NAME: AllocOffScnMem()
  880. *
  881. * DESCRIPTION: Allocate a rectange space from the offscreen memory.
  882. * This routine do a search of the Free Queue to find a
  883. * best fit free memory block. It the free block is bigger
  884. * than the request size, it will split the unused memory
  885. * into smaller rectange blocks and insert them back to
  886. * the Free Queue for future use. It will also do a tile
  887. * or pixel alignment if requested.
  888. *
  889. * If no more enough free memory for the current request,
  890. * This routine will search Used Queue for any discardable
  891. * allocated block. Releases those blocks to satisfy
  892. * the current request.
  893. *
  894. * An user-supplied callback function will be call before
  895. * the discardable block is released.
  896. *
  897. * Input: surf: Request of the offscreen memory size (in Pixel).
  898. *
  899. * alignflag: Alignment flag.
  900. *
  901. * pcallback: Callback function pointer.
  902. * (Only apply if the flag is set to DISCARDABLE_FLAG).
  903. *
  904. * Output: Pointer to the OFMHDL structure or.
  905. * NULL means not enough memory for allocation.
  906. ****************************************************************************/
  907. POFMHDL AllocOffScnMem(PPDEV ppdev,
  908. PSIZEL surf,
  909. ULONG alignflag,
  910. POFM_CALLBACK pcallback)
  911. {
  912. // Convert the pixel into bytes requirement
  913. LONG bpp;
  914. LONG reqszx;
  915. LONG reqszy;
  916. LONG orgreqszx;
  917. OFMHDL *pds, *pallochdl;
  918. BOOL findflg, alignblkflg;
  919. LONG szx, szy;
  920. LONG tmpx, tmpy;
  921. DISPDBG((DISPLVL, "AllocOffScnMem\n"));
  922. #ifdef DBGBRK
  923. DBGBREAKPOINT();
  924. #endif
  925. if (alignflag & MCD_Z_BUFFER_ALLOCATE)
  926. {
  927. // special memory region -> z buffer: always 16bit/pix
  928. bpp = 2;
  929. }
  930. else if (alignflag & MCD_TEXTURE_ALLOCATE)
  931. {
  932. // special memory region -> texture map: depth varies and is coded in alignflag
  933. bpp = (alignflag & MCD_TEXTURE_ALLOCATE) >> MCD_TEXTURE_ALLOC_SHIFT;
  934. }
  935. else
  936. {
  937. // normal memory region -> allocate at depth of frame buffer
  938. bpp = ppdev->ulBitCount/8;
  939. }
  940. reqszx = surf->cx * bpp;
  941. reqszy = surf->cy;
  942. orgreqszx = reqszx;
  943. // If no more free memory or invalid arguments, return NULL
  944. // if ((ppdev == NULL) || (surf == NULL) || (ppdev->OFM_FreeQ == NULL) || (!ppdev->OFM_init))
  945. if (ppdev->OFM_FreeQ == NULL)
  946. return (NULL);
  947. #ifndef ALLOC_IN_CREATESURFACE
  948. if (ppdev->bDirectDrawInUse)
  949. return (NULL);
  950. #endif
  951. // Wait for Mutex is released
  952. #ifdef WINNT_VER40
  953. EngAcquireSemaphore(ppdev->MMhsem);
  954. #else
  955. WaitForSingleObject(ppdev->MutexHdl, INFINITE);
  956. #endif
  957. // Search for the free memory block
  958. findflg = FALSE;
  959. pallochdl = NULL;
  960. while (!findflg)
  961. {
  962. // Search for the best fit block for the request and
  963. // Check whether any free block satisfy the requirement
  964. if (reqszy < MEMSZY)
  965. {
  966. pallochdl = OFS_FindBestFitFreeBlock(ppdev,
  967. ppdev->OFM_SubFreeQ1,
  968. &reqszx, &reqszy,
  969. alignflag);
  970. };
  971. if (pallochdl == NULL)
  972. {
  973. pallochdl = OFS_FindBestFitFreeBlock(ppdev,
  974. ppdev->OFM_SubFreeQ2,
  975. &reqszx, &reqszy,
  976. alignflag);
  977. };
  978. if (pallochdl != NULL)
  979. {
  980. // Remove the free block from Free Queue
  981. OFS_RemoveFrmFreeQ(ppdev, pallochdl);
  982. alignblkflg = FALSE;
  983. #if 0 // Frido 08/29/97: a new algorithm is in place now, see below.
  984. // If tilt aligned, create the free block for the align adjusted
  985. // memory
  986. if (!(alignflag & PIXEL_AlIGN))
  987. {
  988. if ((tmpx = pallochdl->aligned_x - pallochdl->x) > MINSZX)
  989. {
  990. if ((pds = OFS_AllocHdl()) != NULL)
  991. {
  992. pds->x = pallochdl->x;
  993. pds->y = pallochdl->y;
  994. pds->sizex = tmpx;
  995. pds->sizey = reqszy;
  996. OFS_InsertInFreeQ(ppdev, pds);
  997. alignblkflg = TRUE;
  998. };
  999. };
  1000. };
  1001. szx = pallochdl->sizex;
  1002. szy = pallochdl->sizey;
  1003. // If the block is larger than the request size, create the
  1004. // free blocks for excess size
  1005. if ((szx > reqszx) && (szy > reqszy))
  1006. {
  1007. if ((szx - reqszx) > (szy - reqszy))
  1008. {
  1009. tmpx = reqszx;
  1010. tmpy = szy;
  1011. }
  1012. else
  1013. {
  1014. tmpx = szx;
  1015. tmpy = reqszy;
  1016. };
  1017. }
  1018. else
  1019. {
  1020. tmpx = reqszx;
  1021. tmpy = reqszy;
  1022. }; // endif ((szx > reqszx) && (szy > reqszy))
  1023. if (szx > reqszx)
  1024. {
  1025. if ((pds = OFS_AllocHdl()) != NULL)
  1026. {
  1027. pds->x = pallochdl->x + reqszx;
  1028. pds->y = pallochdl->y;
  1029. pds->sizex = szx - reqszx;
  1030. pds->sizey = tmpy;
  1031. OFS_InsertInFreeQ(ppdev, pds);
  1032. };
  1033. }
  1034. else
  1035. {
  1036. reqszx = szx;
  1037. };
  1038. if (szy > reqszy)
  1039. {
  1040. if ((pds = OFS_AllocHdl()) != NULL)
  1041. {
  1042. pds->x = pallochdl->x;
  1043. pds->y = pallochdl->y + reqszy;
  1044. pds->sizex = tmpx;
  1045. pds->sizey = szy - reqszy;
  1046. OFS_InsertInFreeQ(ppdev, pds);
  1047. };
  1048. }
  1049. else
  1050. {
  1051. reqszy = szy;
  1052. };
  1053. // If this is discardable block, save the callback function pointer
  1054. if ((alignflag & DISCARDABLE_FLAG) != 0)
  1055. pallochdl->pcallback = pcallback;
  1056. else
  1057. pallochdl->pcallback = NULL;
  1058. // Insert allocate block into the Used Queue
  1059. if (alignblkflg)
  1060. {
  1061. pallochdl->x = pallochdl->aligned_x;
  1062. pallochdl->y = pallochdl->aligned_y;
  1063. pallochdl->sizex = orgreqszx;
  1064. }
  1065. else
  1066. {
  1067. pallochdl->sizex = reqszx;
  1068. };
  1069. pallochdl->sizey = reqszy;
  1070. #else
  1071. tmpx = pallochdl->aligned_x + reqszx;
  1072. tmpy = pallochdl->aligned_y + reqszy;
  1073. // Do we have extra space at the top?
  1074. szy = pallochdl->aligned_y - pallochdl->y;
  1075. if (szy >= MINSZY)
  1076. {
  1077. pds = OFS_AllocHdl();
  1078. if (pds != NULL)
  1079. {
  1080. pds->x = pallochdl->x;
  1081. pds->y = pallochdl->y;
  1082. pds->sizex = pallochdl->sizex;
  1083. pds->sizey = szy;
  1084. OFS_InsertInFreeQ(ppdev, pds);
  1085. pallochdl->y += szy;
  1086. pallochdl->sizey -= szy;
  1087. }
  1088. }
  1089. // Do we have extra space at the bottom?
  1090. szy = pallochdl->y + pallochdl->sizey - tmpy;
  1091. if (szy >= MINSZY)
  1092. {
  1093. pds = OFS_AllocHdl();
  1094. if (pds != NULL)
  1095. {
  1096. pds->x = pallochdl->x;
  1097. pds->y = tmpy;
  1098. pds->sizex = pallochdl->sizex;
  1099. pds->sizey = szy;
  1100. OFS_InsertInFreeQ(ppdev, pds);
  1101. pallochdl->sizey -= szy;
  1102. }
  1103. }
  1104. // Do we have extra space at the top?
  1105. szx = pallochdl->aligned_x - pallochdl->x;
  1106. if (szx >= MINSZX)
  1107. {
  1108. pds = OFS_AllocHdl();
  1109. if (pds != NULL)
  1110. {
  1111. pds->x = pallochdl->x;
  1112. pds->y = pallochdl->y;
  1113. pds->sizex = szx;
  1114. pds->sizey = pallochdl->sizey;
  1115. OFS_InsertInFreeQ(ppdev, pds);
  1116. pallochdl->x += szx;
  1117. pallochdl->sizex -= szx;
  1118. }
  1119. }
  1120. // Do we have extra space at the right?
  1121. szx = pallochdl->x + pallochdl->sizex - tmpx;
  1122. if (szx >= MINSZX)
  1123. {
  1124. pds = OFS_AllocHdl();
  1125. if (pds != NULL)
  1126. {
  1127. pds->x = tmpx;
  1128. pds->y = pallochdl->y;
  1129. pds->sizex = szx;
  1130. pds->sizey = pallochdl->sizey;
  1131. OFS_InsertInFreeQ(ppdev, pds);
  1132. pallochdl->sizex -= szx;
  1133. }
  1134. }
  1135. #endif
  1136. pallochdl->alignflag = alignflag;
  1137. OFS_InsertInUsedQ(ppdev, pallochdl);
  1138. // Set Find flag to indicate a free block is found
  1139. findflg = TRUE;
  1140. }
  1141. else
  1142. {
  1143. // Free block not found, try to discard any discardable memory
  1144. // to satisfy the request
  1145. if (!OFS_DiscardMem(ppdev, reqszx, reqszy))
  1146. {
  1147. DISPDBG((DISPLVL, "AllocOffScnMem failed\n"));
  1148. // Allocation fail not enough memory
  1149. break;
  1150. };
  1151. }; // endif pallochdl != NULL
  1152. }; // endwhile
  1153. // Release the Mutex
  1154. #ifdef WINNT_VER40
  1155. EngReleaseSemaphore(ppdev->MMhsem);
  1156. #else
  1157. ReleaseMutex(ppdev->MutexHdl);
  1158. #endif
  1159. DISPDBG((DISPLVL, "AllocOffScnMem Completed\n"));
  1160. #ifdef DBGBRK
  1161. DBGBREAKPOINT();
  1162. #endif
  1163. if (pallochdl)
  1164. {
  1165. DISPDBG((DISPLVL,
  1166. "AllocOffScnMem: from (x=%d,y=%d) to (x=%d,y=%d).\n",
  1167. pallochdl->x,
  1168. pallochdl->y,
  1169. (pallochdl->x + pallochdl->sizex),
  1170. (pallochdl->y + pallochdl->sizey) ));
  1171. }
  1172. return(pallochdl);
  1173. } // AllocOffScnMem()
  1174. /****************************************************************************
  1175. * FUNCTION NAME: FreeOffScnMem()
  1176. *
  1177. * DESCRIPTION: Free the allocated offscreen memory.
  1178. *
  1179. * Input: Pointer to the OFMHDL structure.
  1180. *
  1181. * Output: TRUE = Ok,
  1182. * FALSE = failed.
  1183. ****************************************************************************/
  1184. BOOL FreeOffScnMem(PPDEV ppdev,
  1185. OFMHDL *hdl)
  1186. {
  1187. OFMHDL *pds;
  1188. BOOL fndflg;
  1189. DISPDBG((DISPLVL, "FreeOffScnMem\n"));
  1190. #ifdef DBGBRK
  1191. DBGBREAKPOINT();
  1192. #endif
  1193. // if ((!ppdev->OFM_init) || (ppdev == NULL) || (hdl == NULL))
  1194. if (ppdev == NULL)
  1195. return (FALSE);
  1196. #if CLEAR_WHEN_FREE
  1197. REQUIRE(7);
  1198. LL16(grBLTDEF, 0x1101); // solid color fill
  1199. LL16(grDRAWDEF, 0x00FF); // whiteness
  1200. LL_OP0(hdl->x, hdl->y);
  1201. LL_BLTEXT( (hdl->sizex/ppdev->iBytesPerPixel), hdl->sizey );
  1202. #endif
  1203. // Wait for Mutex is released
  1204. #ifdef WINNT_VER40
  1205. EngAcquireSemaphore(ppdev->MMhsem);
  1206. #else
  1207. WaitForSingleObject(ppdev->MutexHdl, INFINITE);
  1208. #endif
  1209. // Validate the release block
  1210. fndflg = FALSE;
  1211. pds = ppdev->OFM_UsedQ;
  1212. while (pds != 0)
  1213. {
  1214. if ((hdl == pds) && (pds->flag == IN_USE))
  1215. {
  1216. fndflg = TRUE;
  1217. break;
  1218. };
  1219. // Next free block
  1220. pds = pds->nexthdl;
  1221. }; // end while
  1222. // Return if it is an invalid handle
  1223. if (!fndflg)
  1224. return (FALSE);
  1225. DISPDBG((DISPLVL,
  1226. "FreeOffScnMem: from (x=%d,y=%d) to (x=%d,y=%d).\n",
  1227. hdl->x,
  1228. hdl->y,
  1229. (hdl->x + hdl->sizex),
  1230. (hdl->y + hdl->sizey) ));
  1231. // Remove the block from the Used queue
  1232. OFS_RemoveFrmUsedQ(ppdev, hdl);
  1233. // Unfragment the memory
  1234. OFS_PackMem(ppdev, hdl);
  1235. // Insert the block into the Free queue
  1236. OFS_InsertInFreeQ(ppdev, hdl);
  1237. // Release the Mutex
  1238. #ifdef WINNT_VER40
  1239. EngReleaseSemaphore(ppdev->MMhsem);
  1240. #else
  1241. ReleaseMutex(ppdev->MutexHdl);
  1242. #endif
  1243. DISPDBG((DISPLVL, "FreeOffScnMem Completed\n"));
  1244. #ifdef DBGBRK
  1245. DBGBREAKPOINT();
  1246. #endif
  1247. return (TRUE);
  1248. } // FreeOffScnMem()
  1249. /****************************************************************************
  1250. * FUNCTION NAME: CloseOffScnMem()
  1251. *
  1252. * DESCRIPTION: Close the offscreen memory manager. This function
  1253. * will release all allocated offscreen memories and the
  1254. * memories used by the Offscreen manager back to Windows.
  1255. ****************************************************************************/
  1256. void CloseOffScnMem(PPDEV ppdev)
  1257. {
  1258. OFMHDL *pds;
  1259. OFMHDL *nxtpds;
  1260. DISPDBG((DISPLVL, "CloseOffScnMem\n"));
  1261. #ifdef DBGBRK
  1262. DBGBREAKPOINT();
  1263. #endif
  1264. // If invalid arguments, return NULL
  1265. if ((!ppdev->OFM_init) || (ppdev == NULL))
  1266. return;
  1267. // Wait for Mutex is released
  1268. #ifdef WINNT_VER40
  1269. EngAcquireSemaphore(ppdev->MMhsem);
  1270. #else
  1271. WaitForSingleObject(ppdev->MutexHdl, INFINITE);
  1272. #endif
  1273. pds = ppdev->OFM_UsedQ;
  1274. while (pds != NULL)
  1275. {
  1276. nxtpds = pds->nexthdl;
  1277. MEMORY_FREE(pds);
  1278. pds = nxtpds;
  1279. };
  1280. pds = ppdev->OFM_FreeQ;
  1281. while (pds != NULL)
  1282. {
  1283. nxtpds = pds->nexthdl;
  1284. MEMORY_FREE(pds);
  1285. pds = nxtpds;
  1286. };
  1287. ppdev->OFM_UsedQ = NULL;
  1288. ppdev->OFM_FreeQ = NULL;
  1289. ppdev->OFM_SubFreeQ1 = NULL;
  1290. ppdev->OFM_SubFreeQ2 = NULL;
  1291. ppdev->DDOffScnMemQ = NULL;
  1292. ppdev->OFM_init = FALSE;
  1293. // Release the Mutex
  1294. #ifdef WINNT_VER40
  1295. EngReleaseSemaphore(ppdev->MMhsem);
  1296. #else
  1297. ReleaseMutex(ppdev->MutexHdl);
  1298. #endif
  1299. // Close the Mutex
  1300. #ifdef WINNT_VER40
  1301. EngDeleteSemaphore(ppdev->MMhsem);
  1302. #else
  1303. CloseHandle(ppdev->MutexHdl);
  1304. #endif
  1305. DISPDBG((DISPLVL, "CloseOffScnMem Completed\n"));
  1306. #ifdef DBGBRK
  1307. DBGBREAKPOINT();
  1308. #endif
  1309. } // CloseOffScnMem()
  1310. /****************************************************************************
  1311. * FUNCTION NAME: ConvertToVideoBufferAddr()
  1312. *
  1313. * DESCRIPTION: Convert the X, Y rectange cordinate into Linear address
  1314. * in video buffer.
  1315. *
  1316. * Input: Pointer to the OFMHDL structure.
  1317. *
  1318. * Output: 32-bits Linear address pointer.
  1319. ****************************************************************************/
  1320. PVOID ConvertToVideoBufferAddr(PPDEV ppdev, POFMHDL psurf)
  1321. {
  1322. ULONG retaddr;
  1323. DISPDBG((DISPLVL, "ConvertToVideoBufferAddr\n"));
  1324. // If invalid arguments, return NULL
  1325. //v-normmi
  1326. //if ((!ppdev->OFM_init) || (ppdev == NULL) || (psurf == NULL))
  1327. if (( ppdev == NULL) || (!ppdev->OFM_init) || (psurf == NULL))
  1328. return (NULL);
  1329. // Wait for Mutex is released
  1330. #ifdef WINNT_VER40
  1331. EngAcquireSemaphore(ppdev->MMhsem);
  1332. #else
  1333. WaitForSingleObject(ppdev->MutexHdl, INFINITE);
  1334. #endif
  1335. // Calculate the linear address from the X & Y coordinate
  1336. retaddr = ((ULONG) (psurf->x + (ppdev->lDeltaScreen * psurf->y))) +
  1337. ((ULONG) ppdev->pjScreen);
  1338. DISPDBG((DISPLVL, "ConvertToVideoBufferAddr Completed\n"));
  1339. #ifdef DBGBRK
  1340. DBGBREAKPOINT();
  1341. #endif
  1342. // Release the Mutex
  1343. #ifdef WINNT_VER40
  1344. EngReleaseSemaphore(ppdev->MMhsem);
  1345. #else
  1346. ReleaseMutex(ppdev->MutexHdl);
  1347. #endif
  1348. return ((PVOID)retaddr);
  1349. } // ConvertToVideoBufAddr()
  1350. /****************************************************************************
  1351. * FUNCTION NAME: OFS_AllocHdl()
  1352. *
  1353. * DESCRIPTION: Alocate offscreen memoru handler from the windows heap.
  1354. *
  1355. * Input: None
  1356. *
  1357. * Output: Pointer to OFMHDL structre
  1358. ****************************************************************************/
  1359. POFMHDL OFS_AllocHdl()
  1360. {
  1361. OFMHDL *pds;
  1362. #ifdef WINNT_VER40
  1363. if ((pds = (POFMHDL) MEM_ALLOC (FL_ZERO_MEMORY, sizeof(OFMHDL), ALLOC_TAG)) != NULL)
  1364. #else
  1365. if ((pds = (POFMHDL) MEM_ALLOC (LPTR, sizeof(OFMHDL))) != NULL)
  1366. #endif
  1367. {
  1368. pds->x = 0;
  1369. pds->y = 0;
  1370. pds->aligned_x = 0;
  1371. pds->aligned_y = 0;
  1372. pds->sizex = 0;
  1373. pds->sizey = 0;
  1374. pds->alignflag = 0;
  1375. pds->flag = 0;
  1376. pds->pcallback = 0;
  1377. pds->prevhdl = 0;
  1378. pds->nexthdl = 0;
  1379. pds->subprvhdl = 0;
  1380. pds->subnxthdl = 0;
  1381. pds->prvFonthdl = 0;
  1382. pds->nxtFonthdl = 0;
  1383. pds->pdsurf = 0;
  1384. };
  1385. return (pds);
  1386. } // OFS_AllocHdl()
  1387. /****************************************************************************
  1388. * FUNCTION NAME: OFS_InitMem()
  1389. *
  1390. * DESCRIPTION: Initialize the offscreen memory.
  1391. *
  1392. * Input: Coordinate and size of the offscreen memory.
  1393. *
  1394. * Output: TRUE = Ok,
  1395. * FALSE = failed.
  1396. ****************************************************************************/
  1397. BOOL OFS_InitMem(PPDEV ppdev,
  1398. PRECTL surf)
  1399. {
  1400. OFMHDL *pds;
  1401. // Allocate the control block handle from local windows memory pool
  1402. #ifdef WINNT_VER40
  1403. if ((pds = (POFMHDL) MEM_ALLOC(FL_ZERO_MEMORY, sizeof(OFMHDL), ALLOC_TAG)) == NULL)
  1404. #else
  1405. if ((pds = (POFMHDL) MEM_ALLOC(LPTR, sizeof(OFMHDL))) == NULL)
  1406. #endif
  1407. return (FALSE);
  1408. // Wait for Mutex is released
  1409. #ifdef WINNT_VER40
  1410. EngAcquireSemaphore(ppdev->MMhsem);
  1411. #else
  1412. WaitForSingleObject(ppdev->MutexHdl, INFINITE);
  1413. #endif
  1414. // Insert the free memory block into the queue
  1415. pds->x = surf->left;
  1416. pds->y = surf->top;
  1417. pds->sizex = surf->right - surf->left;
  1418. pds->sizey = surf->bottom - surf->top;
  1419. OFS_InsertInFreeQ(ppdev, pds);
  1420. // Release the Mutex
  1421. #ifdef WINNT_VER40
  1422. EngReleaseSemaphore(ppdev->MMhsem);
  1423. #else
  1424. ReleaseMutex(ppdev->MutexHdl);
  1425. #endif
  1426. return (TRUE);
  1427. } // OFS_InitMem()
  1428. /****************************************************************************
  1429. * FUNCTION NAME: OFS_FindBestFitFreeBlock()
  1430. *
  1431. * DESCRIPTION: Find the best fit free block.
  1432. *
  1433. * Input: Request offscreen memory size (in bytes).
  1434. *
  1435. * Output: Pointer to the OFMHDL structure or.
  1436. * NULL means not enough memory for allocation.
  1437. ****************************************************************************/
  1438. POFMHDL OFS_FindBestFitFreeBlock(PPDEV ppdev,
  1439. OFMHDL *pFreeQ,
  1440. PLONG preqszx,
  1441. PLONG preqszy,
  1442. ULONG alignflag)
  1443. {
  1444. OFMHDL *pds = pFreeQ;
  1445. LONG reqszx = *preqszx;
  1446. LONG reqszy = *preqszy;
  1447. OFMHDL *pbestfit_hdl = NULL;
  1448. LONG bestfitx = 0x7FFFFFF;
  1449. LONG bestfity = 0x7FFFFFF;
  1450. LONG bpp;
  1451. LONG tileszx = 0;
  1452. LONG tileszy = 0;
  1453. LONG maskx = 0;
  1454. LONG masky = 0;
  1455. BOOL Findit = FALSE;
  1456. ULONG bestfit_aligned_x, bestfit_aligned_y;
  1457. LONG bestfit_Reqszx, bestfit_Reqszy;
  1458. ULONG aligned_x, aligned_y;
  1459. LONG szx, szy;
  1460. LONG NewReqszx, NewReqszy;
  1461. BOOL adjxflg, adjyflg;
  1462. if (alignflag & MCD_Z_BUFFER_ALLOCATE)
  1463. {
  1464. // special memory region -> z buffer: always 16bit/pix
  1465. bpp = 2;
  1466. }
  1467. else if (alignflag & MCD_TEXTURE_ALLOCATE)
  1468. {
  1469. // special memory region -> texture map: depth varies and is coded in alignflag
  1470. bpp = (alignflag & MCD_TEXTURE_ALLOCATE) >> MCD_TEXTURE_ALLOC_SHIFT;
  1471. }
  1472. else
  1473. {
  1474. // normal memory region -> allocate at depth of frame buffer
  1475. bpp = ppdev->ulBitCount/8;
  1476. }
  1477. // Check the alignment flag and adjust the request size accordingly.
  1478. if (alignflag & EIGHT_BYTES_ALIGN)
  1479. { // 8 bytes alignment.
  1480. tileszx = 8;
  1481. tileszy = 1;
  1482. maskx = tileszx - 0x1;
  1483. masky = 0;
  1484. }
  1485. else if (alignflag & PIXEL_AlIGN)
  1486. {
  1487. tileszx = bpp;
  1488. tileszy = 1;
  1489. maskx = tileszx - 0x1;
  1490. masky = 0;
  1491. if (bpp == 3)
  1492. {
  1493. maskx += 1;
  1494. masky += 1;
  1495. };
  1496. }
  1497. else if (alignflag & (MCD_DRAW_BUFFER_ALLOCATE|MCD_Z_BUFFER_ALLOCATE|MCD_TEXTURE_ALLOCATE))
  1498. {
  1499. // Determine tile size
  1500. if (alignflag & MCD_DRAW_BUFFER_ALLOCATE)
  1501. tileszx = 64; // rgb buffer on 64 byte boundary (z always at x=0, so tile doesn't matter)
  1502. else
  1503. tileszx = 32; // texture on 32 byte boundary
  1504. if (alignflag & MCD_TEXTURE_ALLOCATE)
  1505. tileszy = 16; // textures must be on 16 scanline boundary
  1506. else
  1507. tileszy = 32; // z,backbuf must be on 32 scanline boundary
  1508. maskx = tileszx - 1;
  1509. masky = tileszy - 1;
  1510. }
  1511. else
  1512. {
  1513. // Determine tile size
  1514. tileszx = ppdev->lTileSize;
  1515. tileszy = (LONG) 2048/ppdev->lTileSize;
  1516. maskx = tileszx - 1;
  1517. masky = tileszy - 1;
  1518. };
  1519. // Search for the best fit block for the request
  1520. while (pds != NULL)
  1521. {
  1522. if (pds->flag == FREE)
  1523. {
  1524. szx = pds->sizex;
  1525. szy = pds->sizey;
  1526. // MCD z buffer, and possibly color buffer need to start at x=0
  1527. if ((szx >= reqszx) && (szy >= reqszy) && (!(alignflag & MCD_NO_X_OFFSET) || (pds->x==0)))
  1528. {
  1529. // If yes, calculate the aligned rectange starting positions
  1530. aligned_x = pds->x;
  1531. aligned_y = pds->y;
  1532. adjxflg = FALSE;
  1533. adjyflg = FALSE;
  1534. if (alignflag & PIXEL_AlIGN)
  1535. {
  1536. if ((pds->x % bpp) != 0)
  1537. adjxflg = TRUE;
  1538. if ((pds->y % bpp) != 0)
  1539. adjyflg = TRUE;
  1540. }
  1541. else
  1542. {
  1543. if ((!(alignflag & NO_X_TILE_AlIGN)) && ((pds->x % tileszx) != 0))
  1544. adjxflg = TRUE;
  1545. if ((!(alignflag & NO_Y_TILE_AlIGN)) && ((pds->y % tileszy) != 0))
  1546. adjyflg = TRUE;
  1547. };
  1548. if (adjxflg)
  1549. aligned_x = (pds->x & (~maskx)) + tileszx;
  1550. if (adjyflg)
  1551. aligned_y = (pds->y & (~masky)) + tileszy;
  1552. // Adjust the request size again to fit the required alignment
  1553. NewReqszx = reqszx + (aligned_x - pds->x);
  1554. NewReqszy = reqszy + (aligned_y - pds->y);
  1555. // Check the allocate block is large enough to hold the adjusted
  1556. // request size
  1557. if ((szx >= NewReqszx) && (szy >= NewReqszy))
  1558. {
  1559. if ((szx == NewReqszx) && (szy == NewReqszy))
  1560. {
  1561. Findit = TRUE;
  1562. bestfit_Reqszx = NewReqszx;
  1563. bestfit_Reqszy = NewReqszy;
  1564. bestfit_aligned_x = aligned_x;
  1565. bestfit_aligned_y = aligned_y;
  1566. pbestfit_hdl = pds;
  1567. }
  1568. else if ((bestfitx > szx) || (bestfity > szy))
  1569. {
  1570. bestfit_Reqszx = NewReqszx;
  1571. bestfit_Reqszy = NewReqszy;
  1572. bestfit_aligned_x = aligned_x;
  1573. bestfit_aligned_y = aligned_y;
  1574. bestfitx = szx;
  1575. bestfity = szy;
  1576. pbestfit_hdl = pds;
  1577. }; // if ((bestfitx > szx) || (bestfity > szy))
  1578. }; // if ((szx >= NewReqszx) && (szy >= NewReqszy))
  1579. }; // if ((szx >= reqszx) && (szy >= reqszy))
  1580. }; // if (pds->flag == FREE)
  1581. // Next free block
  1582. if (Findit)
  1583. pds = NULL;
  1584. else
  1585. pds = pds->subnxthdl;
  1586. } /* end while */
  1587. if (pbestfit_hdl != NULL)
  1588. {
  1589. *preqszx = bestfit_Reqszx;
  1590. *preqszy = bestfit_Reqszy;
  1591. pbestfit_hdl->aligned_x = bestfit_aligned_x;
  1592. pbestfit_hdl->aligned_y = bestfit_aligned_y;
  1593. };
  1594. return(pbestfit_hdl);
  1595. } // OFS_FindBestFitFreeBlock()
  1596. /****************************************************************************
  1597. * FUNCTION NAME: OFS_PackMem()
  1598. *
  1599. * DESCRIPTION: Unfragment the memory.
  1600. * This routine combines current release memory block
  1601. * with the adjacent free blocks of same X or Y dimension into
  1602. * one big free block.
  1603. ****************************************************************************/
  1604. void OFS_PackMem(PPDEV ppdev,
  1605. OFMHDL *hdl)
  1606. {
  1607. BOOL cmbflg;
  1608. OFMHDL *pds;
  1609. ULONG pdsxdim, pdsydim;
  1610. pds = ppdev->OFM_FreeQ;
  1611. while (pds != NULL)
  1612. {
  1613. // Check for any free block (aliasing in either X or Y direction)
  1614. // before or after the current release block.
  1615. // If yes, combine the two into one big free block
  1616. pdsxdim = pds->x + pds->sizex;
  1617. pdsydim = pds->y + pds->sizey;
  1618. cmbflg = FALSE;
  1619. // Check for X-axis
  1620. if ((hdl->x == pds->x) && ((hdl->x + hdl->sizex) == pdsxdim))
  1621. {
  1622. if ((hdl->y == pdsydim) || (hdl->y == (pds->y - hdl->sizey)))
  1623. {
  1624. cmbflg = TRUE;
  1625. hdl->sizey += pds->sizey;
  1626. if (hdl->y == pdsydim)
  1627. hdl->y = pds->y;
  1628. };
  1629. };
  1630. // Check for Y-axis
  1631. if ((hdl->y == pds->y) && ((hdl->y + hdl->sizey) == pdsydim))
  1632. {
  1633. if ((hdl->x == pdsxdim) || (hdl->x == (pds->x - hdl->sizex)))
  1634. {
  1635. cmbflg = TRUE;
  1636. hdl->sizex += pds->sizex;
  1637. if (hdl->x == pdsxdim)
  1638. hdl->x = pds->x;
  1639. };
  1640. };
  1641. if (cmbflg)
  1642. {
  1643. OFS_RemoveFrmFreeQ(ppdev, pds);
  1644. // Release control block to Windows
  1645. MEMORY_FREE(pds);
  1646. // Restart the unfragment memory processing
  1647. pds = ppdev->OFM_FreeQ;
  1648. }
  1649. else
  1650. {
  1651. // Next free block
  1652. pds = pds->nexthdl;
  1653. };
  1654. }; // end while
  1655. } // OFS_PackMem
  1656. /****************************************************************************
  1657. * FUNCTION NAME: OFS_InsertInFreeQ()
  1658. *
  1659. * DESCRIPTION: Insert the handle into the Free queue.
  1660. *
  1661. * Input: Pointer to the OFMHDL structure.
  1662. *
  1663. * Output: None
  1664. ****************************************************************************/
  1665. void OFS_InsertInFreeQ(PPDEV ppdev,
  1666. OFMHDL *hdl)
  1667. {
  1668. hdl->flag = FREE;
  1669. hdl->prevhdl = NULL;
  1670. hdl->subprvhdl = NULL;
  1671. hdl->aligned_x = 0;
  1672. hdl->aligned_y = 0;
  1673. hdl->alignflag = 0;
  1674. hdl->pcallback = NULL;
  1675. // Fix for PDR9385 - added by Mark Einkauf
  1676. // if pdsurf non-zero, when this block reused later, various DIB functions can misbehave
  1677. // Exact scenario in 9385 was...
  1678. // first app exit:
  1679. // DrvDisableDirectDraw freed all OFM blocks (leaving pdsurf field non-0 in some cases)
  1680. // next app startup:
  1681. // DrvGetDirectDrawInfo, calls...
  1682. // DDOffScnMemAlloc
  1683. // - loops through all OFM_UsedQ blocks, searching for
  1684. // off screen bit maps it can convert to DIB (and then free the offscreen memory)
  1685. // - Finds UsedQ block with non-zero pdsurf, pointing to non-existent pdsurf,
  1686. // which then had non-zero pofm field, causing it to appear as a valid
  1687. // off-screen bitmap
  1688. // - does memcpy with garbage x,y,sizex,sizey, wreaking havoc on system memory
  1689. // in a random sort of way
  1690. hdl->pdsurf = NULL;
  1691. // Insert into the SubFreeQs
  1692. if (hdl->sizey < MEMSZY)
  1693. {
  1694. if (ppdev->OFM_SubFreeQ1 == NULL)
  1695. {
  1696. hdl->subnxthdl = NULL;
  1697. ppdev->OFM_SubFreeQ1 = hdl;
  1698. }
  1699. else
  1700. {
  1701. ppdev->OFM_SubFreeQ1->subprvhdl = hdl;
  1702. hdl->subnxthdl = ppdev->OFM_SubFreeQ1;
  1703. ppdev->OFM_SubFreeQ1 = hdl;
  1704. };
  1705. }
  1706. else
  1707. {
  1708. if (ppdev->OFM_SubFreeQ2 == NULL)
  1709. {
  1710. hdl->subnxthdl = NULL;
  1711. ppdev->OFM_SubFreeQ2 = hdl;
  1712. }
  1713. else
  1714. {
  1715. ppdev->OFM_SubFreeQ2->subprvhdl = hdl;
  1716. hdl->subnxthdl = ppdev->OFM_SubFreeQ2;
  1717. ppdev->OFM_SubFreeQ2 = hdl;
  1718. };
  1719. };
  1720. // Insert into the Main FreeQ
  1721. if (ppdev->OFM_FreeQ == NULL)
  1722. {
  1723. hdl->nexthdl = NULL;
  1724. ppdev->OFM_FreeQ = hdl;
  1725. }
  1726. else
  1727. {
  1728. ppdev->OFM_FreeQ->prevhdl = hdl;
  1729. hdl->nexthdl = ppdev->OFM_FreeQ;
  1730. ppdev->OFM_FreeQ = hdl;
  1731. };
  1732. } // OFS_InsertInFreeQ()
  1733. /****************************************************************************
  1734. * FUNCTION NAME: OFS_RemoveFrmFreeQ()
  1735. *
  1736. * DESCRIPTION: Remove the handle from the Free queue.
  1737. ****************************************************************************/
  1738. void OFS_RemoveFrmFreeQ(PPDEV ppdev,
  1739. OFMHDL *hdl)
  1740. {
  1741. OFMHDL *prvpds, *nxtpds;
  1742. OFMHDL *subprvpds, *subnxtpds;
  1743. hdl->flag = UNKNOWN;
  1744. prvpds = hdl->prevhdl;
  1745. nxtpds = hdl->nexthdl;
  1746. subprvpds = hdl->subprvhdl;
  1747. subnxtpds = hdl->subnxthdl;
  1748. // Remove from the SubFreeQs
  1749. if (hdl->sizey < MEMSZY)
  1750. {
  1751. if (hdl == ppdev->OFM_SubFreeQ1)
  1752. {
  1753. ppdev->OFM_SubFreeQ1 = subnxtpds;
  1754. if (subnxtpds != 0)
  1755. subnxtpds->subprvhdl = NULL;
  1756. }
  1757. else
  1758. {
  1759. if (subnxtpds != NULL)
  1760. subnxtpds->subprvhdl = subprvpds;
  1761. if (subprvpds != NULL)
  1762. subprvpds->subnxthdl = subnxtpds;
  1763. };
  1764. }
  1765. else
  1766. {
  1767. if (hdl == ppdev->OFM_SubFreeQ2)
  1768. {
  1769. ppdev->OFM_SubFreeQ2 = subnxtpds;
  1770. if (subnxtpds != 0)
  1771. subnxtpds->subprvhdl = NULL;
  1772. }
  1773. else
  1774. {
  1775. if (subnxtpds != NULL)
  1776. subnxtpds->subprvhdl = subprvpds;
  1777. if (subprvpds != NULL)
  1778. subprvpds->subnxthdl = subnxtpds;
  1779. };
  1780. };
  1781. // Remove from the Main FreeQ
  1782. if (hdl == ppdev->OFM_FreeQ)
  1783. {
  1784. ppdev->OFM_FreeQ = nxtpds;
  1785. if (nxtpds != 0)
  1786. nxtpds->prevhdl = NULL;
  1787. }
  1788. else
  1789. {
  1790. if (nxtpds != NULL)
  1791. nxtpds->prevhdl = prvpds;
  1792. if (prvpds != NULL)
  1793. prvpds->nexthdl = nxtpds;
  1794. };
  1795. } // OFS_RemoveFrmFreeQ
  1796. /****************************************************************************
  1797. * FUNCTION NAME: OFS_InsertInUsedQ()
  1798. *
  1799. * DESCRIPTION: Insert the handle into the Used queue.
  1800. ****************************************************************************/
  1801. void OFS_InsertInUsedQ(PPDEV ppdev,
  1802. OFMHDL *hdl)
  1803. {
  1804. hdl->flag = IN_USE;
  1805. hdl->prevhdl = NULL;
  1806. if (ppdev->OFM_UsedQ == NULL)
  1807. {
  1808. hdl->nexthdl = NULL;
  1809. ppdev->OFM_UsedQ = hdl;
  1810. }
  1811. else
  1812. {
  1813. ppdev->OFM_UsedQ->prevhdl = hdl;
  1814. hdl->nexthdl = ppdev->OFM_UsedQ;
  1815. ppdev->OFM_UsedQ = hdl;
  1816. };
  1817. } // OFS_InsertInUsedQ()
  1818. /****************************************************************************
  1819. * FUNCTION NAME: OFS_RemoveFrmUsedQ()
  1820. *
  1821. * DESCRIPTION: Remove the handle from the Used queue.
  1822. ****************************************************************************/
  1823. void OFS_RemoveFrmUsedQ(PPDEV ppdev,
  1824. OFMHDL *hdl)
  1825. {
  1826. OFMHDL *prvpds, *nxtpds;
  1827. hdl->flag = UNKNOWN;
  1828. prvpds = hdl->prevhdl;
  1829. nxtpds = hdl->nexthdl;
  1830. if (hdl == ppdev->OFM_UsedQ)
  1831. {
  1832. ppdev->OFM_UsedQ = nxtpds;
  1833. if (nxtpds != 0)
  1834. nxtpds->prevhdl = NULL;
  1835. }
  1836. else
  1837. {
  1838. if (nxtpds != NULL)
  1839. nxtpds->prevhdl = prvpds;
  1840. if (prvpds != NULL)
  1841. prvpds->nexthdl = nxtpds;
  1842. };
  1843. } // OFS_RemoveFrmUsedQ()
  1844. /****************************************************************************
  1845. * FUNCTION NAME: OFS_DiscardMem()
  1846. *
  1847. * DESCRIPTION: This routine search Used Queue to find any discardable
  1848. * allocated block. Releases those blocks to satisfy
  1849. * the current request.
  1850. *
  1851. * Input: Request offscreen memory size (in bytes).
  1852. *
  1853. * Output: TRUE: Find a free block.
  1854. * FALSE: No free block available.
  1855. ****************************************************************************/
  1856. BOOL OFS_DiscardMem(PPDEV ppdev,
  1857. LONG reqszx,
  1858. LONG reqszy)
  1859. {
  1860. OFMHDL *hdl, *pds;
  1861. hdl = ppdev->OFM_UsedQ;
  1862. while (hdl != NULL)
  1863. {
  1864. if ((hdl->alignflag & DISCARDABLE_FLAG) != 0)
  1865. {
  1866. // Save the handle
  1867. pds = hdl;
  1868. // Get next free block handle
  1869. hdl = hdl->nexthdl;
  1870. // Call the callback function
  1871. if (pds->pcallback != NULL)
  1872. pds->pcallback();
  1873. // Remove this discardable block from the Used queue
  1874. OFS_RemoveFrmUsedQ(ppdev, pds);
  1875. // Unfragment the memory
  1876. OFS_PackMem(ppdev, pds);
  1877. // Insert the block into the Free queue
  1878. OFS_InsertInFreeQ(ppdev, pds);
  1879. // Return TRUE, if the combined block is satisfy the request.
  1880. // Otherwise continues search for next discardable block.
  1881. if ((pds->sizex >= reqszx) && (pds->sizey >= reqszy))
  1882. return TRUE;
  1883. }
  1884. else
  1885. {
  1886. // Next free block
  1887. hdl = hdl->nexthdl;
  1888. }; // endif ((hdl->alignflag & DISCARDABLE_FLAG) != 0)
  1889. }; // endwhile (hdl != NULL)
  1890. // Return FALSE, no more discardable block to release and still
  1891. // no free block large enough for the request.
  1892. return FALSE;
  1893. } // OFS_DiscardMem
  1894. #else /* MEMMGR */
  1895. /******************************************************************************\
  1896. * *
  1897. * N E W M E M O R Y M A N A G E R *
  1898. * *
  1899. \******************************************************************************/
  1900. #ifdef WINNT_VER40
  1901. #define CREATE_MUTEX(ppdev) ppdev->MMhsem = EngCreateSemaphore()
  1902. #define DELETE_MUTEX(ppdev) EngDeleteSemaphore(ppdev->MMhsem)
  1903. #define BEGIN_MUTEX(ppdev) EngAcquireSemaphore(ppdev->MMhsem);
  1904. #define END_MUTEX(ppdev) EngReleaseSemaphore(ppdev->MMhsem)
  1905. #else
  1906. #define CREATE_MUTEX(ppdev) ppdev->MutexHdl = CreateMutex(NULL, FALSE, NULL)
  1907. #define DELETE_MUTEX(ppdev) CloseHandle(ppdev->MutexHdl)
  1908. #define BEGIN_MUTEX(ppdev) WaitForSingleObject(ppdev->MutexHdl, INFINITE);
  1909. #define END_MUTEX(ppdev) ReleaseMutex(ppdev->MutexHdl)
  1910. #endif
  1911. /******************************************************************************\
  1912. * Function: HostifyBitmap
  1913. *
  1914. * Purpose: Move a device bitmap from off-screen memory to host memory.
  1915. *
  1916. * On entry: pdm Pointer to node to hostify.
  1917. *
  1918. * Returns: TRUE if successful, FALSE if there is an error.
  1919. \******************************************************************************/
  1920. BOOL HostifyBitmap(PDEVMEM pdm)
  1921. {
  1922. if (pdm->ofm.pdsurf != NULL)
  1923. {
  1924. // Hostify the bitmap.
  1925. if (!bCreateDibFromScreen(pdm->ofm.pdsurf->ppdev, pdm->ofm.pdsurf))
  1926. {
  1927. // There was an error.
  1928. return FALSE;
  1929. }
  1930. }
  1931. return TRUE;
  1932. }
  1933. /******************************************************************************\
  1934. * Function: HostifyAllBitmaps
  1935. *
  1936. * Purpose: Move all device bitmaps from off-screen memory to host memory.
  1937. *
  1938. * On entry: ppdev Pointer to physical device.
  1939. *
  1940. * Returns: Nothing.
  1941. \******************************************************************************/
  1942. void HostifyAllBitmaps(PPDEV ppdev)
  1943. {
  1944. PDEVMEM pdm, pdmNext;
  1945. // Walk through all used nodes.
  1946. for (pdm = ppdev->mmMemMgr.pdmUsed; pdm != NULL; pdm = pdmNext)
  1947. {
  1948. // Save pointer to next node.
  1949. pdmNext = pdm->next;
  1950. // If this is a device bitmap, hostify it.
  1951. if (pdm->ofm.pdsurf != NULL)
  1952. {
  1953. if (bCreateDibFromScreen(ppdev, pdm->ofm.pdsurf))
  1954. {
  1955. // After successful hostification, free the node.
  1956. mmFree(&ppdev->mmMemMgr, pdm);
  1957. }
  1958. }
  1959. // If this is a SaveScreen bitmap, just remove it.
  1960. else if (pdm->ofm.alignflag & SAVESCREEN_FLAG)
  1961. {
  1962. mmFree(&ppdev->mmMemMgr, pdm);
  1963. }
  1964. }
  1965. }
  1966. /******************************************************************************\
  1967. * Function: CopyBitmap
  1968. *
  1969. * Purpose: Move a device bitmap in off-screen memory.
  1970. *
  1971. * On entry: pdmNew Pointer to new node for device bitmap.
  1972. * pdmOld Pointer to old node of device bitmap.
  1973. *
  1974. * Returns: Nothing.
  1975. \******************************************************************************/
  1976. void CopyBitmap(PDEVMEM pdmNew, PDEVMEM pdmOld)
  1977. {
  1978. PPDEV ppdev;
  1979. PDSURF pdsurf;
  1980. ULONG xSrc, xDest, xExt, cx;
  1981. BOOL fFirst = TRUE;
  1982. // Set the pointers to the device bitmap and physical device.
  1983. pdsurf = pdmOld->ofm.pdsurf;
  1984. ppdev = pdsurf->ppdev;
  1985. // Setup the values in the old NT structure.
  1986. pdmNew->ofm.x = pdmNew->ofm.aligned_x = pdmNew->cbAddr.pt.x;
  1987. pdmNew->ofm.y = pdmNew->ofm.aligned_y = pdmNew->cbAddr.pt.y;
  1988. pdmNew->ofm.sizex = pdmNew->cbSize.pt.x;
  1989. pdmNew->ofm.sizey = pdmNew->cbSize.pt.y;
  1990. // Copy the information from the old node.
  1991. pdmNew->ofm.alignflag = pdmOld->ofm.alignflag;
  1992. pdmNew->ofm.pcallback = pdmOld->ofm.pcallback;
  1993. pdmNew->ofm.pdsurf = pdsurf;
  1994. // Update the device bitmap structure.
  1995. pdsurf->pofm = (POFMHDL) pdmNew;
  1996. pdsurf->ptl.x = pdmNew->cbAddr.pt.x / ppdev->iBytesPerPixel;
  1997. pdsurf->ptl.y = pdmNew->cbAddr.pt.y;
  1998. pdsurf->packedXY = (pdsurf->ptl.y << 16) | pdsurf->ptl.x;
  1999. // Copy the device bitmap to a new location.
  2000. xSrc = pdmOld->cbAddr.pt.x;
  2001. xDest = pdmNew->cbAddr.pt.x;
  2002. xExt = pdmNew->cbSize.pt.x;
  2003. // We do striping.
  2004. while (xExt > 0)
  2005. {
  2006. cx = min( xExt, ppdev->lTileSize - (xSrc % ppdev->lTileSize) );
  2007. cx = min( cx, ppdev->lTileSize - (xDest % ppdev->lTileSize) );
  2008. if (fFirst)
  2009. {
  2010. fFirst = FALSE;
  2011. REQUIRE(9);
  2012. LL_DRAWBLTDEF(0x101000CC, 0);
  2013. LL_OP1_MONO(xSrc, pdmOld->cbAddr.pt.y);
  2014. LL_OP0_MONO(xDest, pdmNew->cbAddr.pt.y);
  2015. LL_MBLTEXT(cx, pdmNew->cbSize.pt.y);
  2016. }
  2017. else
  2018. {
  2019. REQUIRE(4);
  2020. LL16(grOP1_opMRDRAM.PT.X, xSrc);
  2021. LL16(grOP0_opMRDRAM.PT.X, xDest);
  2022. LL16(grMBLTEXT_XEX.PT.X, cx);
  2023. }
  2024. xSrc += cx;
  2025. xDest += cx;
  2026. xExt -= cx;
  2027. }
  2028. }
  2029. /******************************************************************************\
  2030. * Function: InitOffScnMem
  2031. *
  2032. * Purpose: Initialize the off-screen memory manager.
  2033. *
  2034. * On entry: ppdev Pointer to physical device.
  2035. *
  2036. * Returns: TRUE if successful, FALSE if there is an error.
  2037. \******************************************************************************/
  2038. BOOL InitOffScnMem(PPDEV ppdev)
  2039. {
  2040. UINT Interleave, WidthInTiles, ExtraWidth, ExtraHeight;
  2041. ULONG BytesInMainRect, BytesInExtraRect;
  2042. GXRECT rect;
  2043. SIZEL size;
  2044. GXPOINT align;
  2045. PDEVMEM pdm;
  2046. DISPDBG((DISPLVL, "InitOffScnMem\n"));
  2047. // Already initialized?
  2048. if (ppdev == NULL || ppdev->OFM_init == TRUE)
  2049. {
  2050. DISPDBG((DISPLVL, "InitOffScnMem: already initialized\n"));
  2051. return FALSE;
  2052. }
  2053. // Create the semaphore.
  2054. if ((CREATE_MUTEX(ppdev)) == NULL)
  2055. {
  2056. DISPDBG((DISPLVL, "InitOffScnMem: CREATE_MUTEX failed\n"));
  2057. return FALSE;
  2058. }
  2059. // Setup the maximum width for a device bitmap for which we will move and
  2060. // hostify other devcie bitmaps.
  2061. if ( (ppdev->iBytesPerPixel == 3) || (ppdev->iBytesPerPixel == 4) )
  2062. {
  2063. ppdev->must_have_width = 0;
  2064. }
  2065. else
  2066. {
  2067. ppdev->must_have_width = ppdev->cxScreen * 98 / 100;
  2068. }
  2069. // Calculate memory stuff.
  2070. Interleave = 1 << ((LLDR_SZ(grTILE_CTRL) & 0xC0) >> 6);
  2071. WidthInTiles = ppdev->lDeltaScreen / ppdev->lTileSize;
  2072. BytesInExtraRect = ppdev->lTotalMem % (WidthInTiles * 2048 * Interleave);
  2073. BytesInMainRect = ppdev->lTotalMem - BytesInExtraRect;
  2074. //
  2075. // BTN - For some reason, this extra rectange cause the WHQL PC97
  2076. // Rand Create/Release 100x test fails on 1600x1200x16 and 1600x1200x8
  2077. //
  2078. if ((ppdev->cxScreen == 1600) &&
  2079. (ppdev->cyScreen == 1200) &&
  2080. ((ppdev->iBytesPerPixel == 2) || (ppdev->iBytesPerPixel == 1)))
  2081. BytesInExtraRect = 0;
  2082. //
  2083. // I have removed the extra rectangle at 1280x1024x8. Somehow it messes up
  2084. // FoxBear.
  2085. //
  2086. if ( (ppdev->cxScreen == 1280)
  2087. && (ppdev->cyScreen == 1024)
  2088. && (ppdev->iBytesPerPixel == 1)
  2089. )
  2090. {
  2091. BytesInExtraRect = 0;
  2092. }
  2093. // Setup the main rectangle.
  2094. rect.left = 0;
  2095. rect.top = 0;
  2096. rect.right = ppdev->lDeltaScreen;
  2097. rect.bottom = BytesInMainRect / ppdev->lDeltaScreen;
  2098. // Setup the extra rectangle.
  2099. if (BytesInExtraRect && ppdev->lTotalMem < 8 * 1024 * 1024)
  2100. {
  2101. ExtraHeight = Interleave * 2048 / ppdev->lTileSize;
  2102. ExtraWidth = BytesInExtraRect / ExtraHeight;
  2103. }
  2104. else
  2105. {
  2106. ExtraWidth = ExtraHeight = 0;
  2107. }
  2108. // v-normmi effective height of direct frame buffer access region
  2109. // not all of it is populated with memory
  2110. ppdev->cyMemoryReal = rect.bottom + ExtraHeight;
  2111. BEGIN_MUTEX(ppdev)
  2112. {
  2113. // Initialize the mmemory manager core.
  2114. ppdev->mmMemMgr.mmTileWidth = ppdev->lTileSize;
  2115. ppdev->mmMemMgr.mmHeapWidth = rect.right;
  2116. ppdev->mmMemMgr.mmHeapHeight = rect.bottom + ExtraHeight;
  2117. mmInit(&ppdev->mmMemMgr);
  2118. // Initialize flags and queues.
  2119. ppdev->OFM_init = TRUE;
  2120. ppdev->bDirectDrawInUse = FALSE;
  2121. ppdev->DDOffScnMemQ = FALSE;
  2122. ppdev->DirectDrawHandle = NULL;
  2123. }
  2124. END_MUTEX(ppdev);
  2125. // Add the main rectangle to the heap.
  2126. if (!mmAddRectToList(&ppdev->mmMemMgr, &ppdev->mmMemMgr.pdmHeap, &rect,
  2127. FALSE))
  2128. {
  2129. DISPDBG((DISPLVL, "InitOffScnMem: mmAddRectToList failed\n"));
  2130. return FALSE;
  2131. }
  2132. DISPDBG((DISPLVL, "InitOffScnMem: main rectangle from (%d,%d) to (%d,%d)\n",
  2133. rect.left, rect.top, rect.right, rect.bottom));
  2134. // Add the extra rectangle to the heap.
  2135. if (ExtraWidth > 0 && ExtraHeight > 0)
  2136. {
  2137. rect.left = 0;
  2138. rect.top = rect.bottom;
  2139. rect.right = ExtraWidth;
  2140. rect.bottom += ExtraHeight;
  2141. if (mmAddRectToList(&ppdev->mmMemMgr, &ppdev->mmMemMgr.pdmHeap, &rect,
  2142. FALSE))
  2143. {
  2144. DISPDBG((DISPLVL, "InitOffScnMem: "
  2145. "extra rectangle from (%d,%d) to (%d,%d)\n", rect.left,
  2146. rect.top, rect.right, rect.bottom));
  2147. }
  2148. }
  2149. // Allocate a node for the screen.
  2150. size.cx = ppdev->cxScreen;
  2151. size.cy = ppdev->cyScreen;
  2152. ppdev->ScrnHandle = AllocOffScnMem(ppdev, &size, SCREEN_ALLOCATE, NULL);
  2153. if (ppdev->ScrnHandle == NULL)
  2154. {
  2155. DISPDBG((DISPLVL, "InitOffScnMem: AllocOffScnMem failed\n"));
  2156. return FALSE;
  2157. }
  2158. // Determine if bitmap filter should be turned on.
  2159. align.pt.x = align.pt.y = 1;
  2160. pdm = mmAllocLargest(&ppdev->mmMemMgr, align);
  2161. if (pdm == NULL)
  2162. {
  2163. DISPDBG((DISPLVL, "InitOffScnMem: mmAllocLargest faled\n"));
  2164. return FALSE;
  2165. }
  2166. size.cx = pdm->cbSize.pt.x / ppdev->iBytesPerPixel;
  2167. size.cy = pdm->cbSize.pt.y;
  2168. mmFree(&ppdev->mmMemMgr, pdm);
  2169. if ((ULONG) size.cx < ppdev->cxScreen || (ULONG) size.cy < ppdev->cyScreen)
  2170. {
  2171. ppdev->fBitmapFilter = TRUE;
  2172. ppdev->szlBitmapMin.cx = 64;
  2173. ppdev->szlBitmapMin.cy = 64;
  2174. ppdev->szlBitmapMax.cx = size.cx;
  2175. ppdev->szlBitmapMax.cy = size.cy;
  2176. }
  2177. else
  2178. {
  2179. ppdev->fBitmapFilter = FALSE;
  2180. }
  2181. // Return success.
  2182. DISPDBG((DISPLVL, "InitOffScnMem: completed\n"));
  2183. return TRUE;
  2184. }
  2185. /******************************************************************************\
  2186. * Function: CloseOffScnMem
  2187. *
  2188. * Purpose: Free all memory allocated for the off-screen memory manager.
  2189. *
  2190. * On entry: ppdev Pointer to physical device.
  2191. *
  2192. * Returns: Nothing.
  2193. \******************************************************************************/
  2194. void CloseOffScnMem(PPDEV ppdev)
  2195. {
  2196. PHANDLES ph, phNext;
  2197. DISPDBG((DISPLVL, "CloseOffScnMem\n"));
  2198. // Already closed?
  2199. if (ppdev == NULL || !ppdev->OFM_init)
  2200. {
  2201. DISPDBG((DISPLVL, "CloseOffScnMem: already closed\n"));
  2202. return;
  2203. }
  2204. BEGIN_MUTEX(ppdev)
  2205. {
  2206. // Delete all allocated arrays.
  2207. for (ph = ppdev->mmMemMgr.phArray; ph != NULL; ph = phNext)
  2208. {
  2209. phNext = ph->pNext;
  2210. MEMORY_FREE(ph);
  2211. }
  2212. ppdev->mmMemMgr.phArray = NULL;
  2213. ppdev->mmMemMgr.pdmUsed = NULL;
  2214. ppdev->mmMemMgr.pdmFree = NULL;
  2215. ppdev->mmMemMgr.pdmHeap = NULL;
  2216. ppdev->mmMemMgr.pdmHandles = NULL;
  2217. ppdev->OFM_init = FALSE;
  2218. }
  2219. END_MUTEX(ppdev);
  2220. // Delete the semaphore.
  2221. DELETE_MUTEX(ppdev);
  2222. DISPDBG((DISPLVL, "CloseOffScnMem: completed\n"));
  2223. }
  2224. /******************************************************************************\
  2225. * Function: AllocOffScnMem
  2226. *
  2227. * Purpose: Allocate a node in off-screen memory.
  2228. *
  2229. * On entry: ppdev Pointer to physical device.
  2230. * psize Pointer to the size of the requested node. The size
  2231. * is specified in pixels or bytes, depending on the
  2232. * alignment flags.
  2233. * alignflag Alignment flags.
  2234. * pcallback Pointer to callback routine if DISCARDABLE_FLAG is
  2235. * set.
  2236. *
  2237. * Returns: Pointer to the node if successful, or NULL if there is not
  2238. * enough memory to allocate the node.
  2239. \******************************************************************************/
  2240. POFMHDL AllocOffScnMem(PPDEV ppdev, PSIZEL psize, ULONG alignflag,
  2241. POFM_CALLBACK pcallback)
  2242. {
  2243. GXPOINT size, align;
  2244. UINT bpp;
  2245. PDEVMEM pdm;
  2246. DISPDBG((DISPLVL, "AllocOffScnMem\n"));
  2247. // If the memory manager active?
  2248. if (ppdev == NULL || !ppdev->OFM_init || psize == NULL)
  2249. {
  2250. DISPDBG((DISPLVL, "AllocOffScnMem: not initialized\n"));
  2251. return NULL;
  2252. }
  2253. #ifndef ALLOC_IN_CREATESURFACE
  2254. // Return in case DirectDraw is active.
  2255. if (pdpev->bDirectDrawInUse)
  2256. {
  2257. DISPDBG((DISPLVL, "AllocOffScnMem: DirectDraw is active\n"));
  2258. return NULL;
  2259. }
  2260. #endif
  2261. // Z-buffer alignment.
  2262. if (alignflag & MCD_Z_BUFFER_ALLOCATE)
  2263. {
  2264. bpp = 2;
  2265. align.pt.x = 32;
  2266. align.pt.y = 32;
  2267. }
  2268. // Texture alignment.
  2269. else if (alignflag & MCD_TEXTURE_ALLOCATE)
  2270. {
  2271. bpp = (alignflag & MCD_TEXTURE_ALLOCATE) >> MCD_TEXTURE_ALLOC_SHIFT;
  2272. align.pt.x = 32;
  2273. align.pt.y = 16;
  2274. }
  2275. // DirectDraw buffer alignment.
  2276. else if (alignflag & MCD_DRAW_BUFFER_ALLOCATE)
  2277. {
  2278. bpp = ppdev->iBytesPerPixel;
  2279. align.pt.x = 64;
  2280. align.pt.y = 32;
  2281. }
  2282. // 8 bytes alignment.
  2283. else if (alignflag & EIGHT_BYTES_ALIGN)
  2284. {
  2285. bpp = ppdev->iBytesPerPixel;
  2286. align.pt.x = 8;
  2287. align.pt.y = 1;
  2288. }
  2289. // Pixel alignment.
  2290. else if (alignflag & PIXEL_AlIGN)
  2291. {
  2292. bpp = ppdev->iBytesPerPixel;
  2293. align.pt.x = ppdev->iBytesPerPixel;
  2294. align.pt.y = 1;
  2295. }
  2296. // Screen alignment.
  2297. else if (alignflag & SCREEN_ALLOCATE)
  2298. {
  2299. bpp = ppdev->iBytesPerPixel;
  2300. align.pt.x = ppdev->lDeltaScreen;
  2301. align.pt.y = ppdev->cyMemory;
  2302. }
  2303. // Tile alignment.
  2304. else
  2305. {
  2306. bpp = 1;
  2307. align.pt.x = ppdev->lTileSize;
  2308. align.pt.y = 2048 / ppdev->lTileSize;
  2309. if (alignflag & NO_X_TILE_AlIGN)
  2310. {
  2311. align.pt.x = 1;
  2312. }
  2313. if (alignflag & NO_Y_TILE_AlIGN)
  2314. {
  2315. align.pt.y = 1;
  2316. }
  2317. }
  2318. // The Z-buffer needs to be allocated at x=0.
  2319. if (alignflag & MCD_NO_X_OFFSET)
  2320. {
  2321. align.pt.x = ppdev->lDeltaScreen;
  2322. }
  2323. #if TILE_ALIGNMENT
  2324. // If this is a call from DrvCreateDeviceBitmap, set tile alignment.
  2325. if (alignflag & MUST_HAVE)
  2326. {
  2327. align.pt.x |= 0x8000;
  2328. }
  2329. #endif
  2330. // Set the size of the node.
  2331. size.pt.x = psize->cx * bpp;
  2332. size.pt.y = psize->cy;
  2333. #if 1 // PDR#10526
  2334. // Immortal Klowns copies a few bytes too much to the screen if the size of
  2335. // a DirectDraw surface is not DWORD aligned. So for DirectDraw and pixel
  2336. // aligned allocations we align the size to DWORDs.
  2337. if (ppdev->bDirectDrawInUse && (alignflag & PIXEL_AlIGN))
  2338. {
  2339. size.pt.x = (size.pt.x + 3) & ~3;
  2340. }
  2341. #endif
  2342. BEGIN_MUTEX(ppdev)
  2343. {
  2344. // 1st pass, allocate the node.
  2345. pdm = mmAlloc(&ppdev->mmMemMgr, size, align);
  2346. if (pdm == NULL && (alignflag & MUST_HAVE))
  2347. {
  2348. // 2nd pass, move stuff away and allocate the node.
  2349. pdm = mmMove(&ppdev->mmMemMgr, size, align, CopyBitmap);
  2350. }
  2351. }
  2352. END_MUTEX(ppdev);
  2353. if (pdm == NULL)
  2354. {
  2355. // Oops, no room for the node.
  2356. DISPDBG((DISPLVL, "AllocOffScnMem: failed for (%dx%d)\n", size.pt.x,
  2357. size.pt.y));
  2358. return NULL;
  2359. }
  2360. // Setup the values in the old NT structure.
  2361. pdm->ofm.x = pdm->ofm.aligned_x = pdm->cbAddr.pt.x;
  2362. pdm->ofm.y = pdm->ofm.aligned_y = pdm->cbAddr.pt.y;
  2363. pdm->ofm.sizex = pdm->cbSize.pt.x;
  2364. pdm->ofm.sizey = pdm->cbSize.pt.y;
  2365. pdm->ofm.alignflag = alignflag;
  2366. pdm->ofm.pdsurf = NULL;
  2367. // Set the address of the callback function.
  2368. if (alignflag & DISCARDABLE_FLAG)
  2369. {
  2370. pdm->ofm.pcallback = pcallback;
  2371. }
  2372. else if (alignflag & MUST_HAVE)
  2373. {
  2374. // This is a device bitmap.
  2375. pdm->ofm.pcallback = (POFM_CALLBACK) HostifyBitmap;
  2376. }
  2377. else
  2378. {
  2379. // No callback function.
  2380. pdm->ofm.pcallback = NULL;
  2381. }
  2382. // Return node.
  2383. DISPDBG((DISPLVL, "AllocOffScnMem: completed from (%d,%d) to (%d,%d)\n",
  2384. pdm->cbAddr.pt.x, pdm->cbAddr.pt.y, pdm->cbAddr.pt.x +
  2385. pdm->cbSize.pt.x, pdm->cbAddr.pt.y + pdm->cbSize.pt.y));
  2386. return (POFMHDL) pdm;
  2387. }
  2388. /******************************************************************************\
  2389. * Function: FreeOffScnMem
  2390. *
  2391. * Purpose: Free a node allocated from off-screen memory.
  2392. *
  2393. * On entry: ppdev Pointer to physical device.
  2394. * hdl Handle of node to free.
  2395. *
  2396. * Returns: TRUE if successful, FALSE if there is an error.
  2397. \******************************************************************************/
  2398. BOOL FreeOffScnMem(PPDEV ppdev, POFMHDL hdl)
  2399. {
  2400. DISPDBG((DISPLVL, "FreeOffScnMem\n"));
  2401. // If the memory manager enabled?
  2402. if (ppdev == NULL || !ppdev->OFM_init || hdl == NULL)
  2403. {
  2404. DISPDBG((DISPLVL, "FreeOffScnMem: not initialized\n"));
  2405. return FALSE;
  2406. }
  2407. // Free the node.
  2408. DISPDBG((DISPLVL, "FreeOffScnMem: from (%d,%d) to (%d,%d)\n", hdl->x,
  2409. hdl->y, hdl->x + hdl->sizex, hdl->y + hdl->sizey));
  2410. mmFree(&ppdev->mmMemMgr, (PDEVMEM) hdl);
  2411. // Return success.
  2412. DISPDBG((DISPLVL, "FreeOffScnMem: completed\n"));
  2413. return TRUE;
  2414. }
  2415. /******************************************************************************\
  2416. * Function: ConvertToVideoBufferAddr
  2417. *
  2418. * Purpose: Convert the location of a node in off-screen memory to a linear
  2419. * address.
  2420. *
  2421. * On entry: ppdev Pointer to physical device.
  2422. * hdl Handle of node.
  2423. *
  2424. * Returns: Linear address of node.
  2425. \******************************************************************************/
  2426. PVOID ConvertToVideoBufferAddr(PPDEV ppdev, POFMHDL hdl)
  2427. {
  2428. PBYTE retaddr;
  2429. BEGIN_MUTEX(ppdev)
  2430. {
  2431. // Calculate the address.
  2432. retaddr = ppdev->pjScreen + hdl->x + hdl->y * ppdev->lDeltaScreen;
  2433. }
  2434. END_MUTEX(ppdev);
  2435. return (PVOID) retaddr;
  2436. }
  2437. /******************************************************************************\
  2438. * Function: DDOffScnMemAlloc
  2439. *
  2440. * Purpose: Free all non-essential memory to make room for DirectDraw.
  2441. *
  2442. * On entry: ppdev Pointer to physical device.
  2443. *
  2444. * Returns: Pointer to biggest node for DirectDraw or NULL if the memory
  2445. * manager handles DirectDraw surfaces.
  2446. \******************************************************************************/
  2447. POFMHDL DDOffScnMemAlloc(PPDEV ppdev)
  2448. {
  2449. PDEVMEM pdm;
  2450. GXPOINT align;
  2451. DISPDBG((DISPLVL, "DDOffScnMemAlloc\n"));
  2452. // Hostify all device bitmaps.
  2453. HostifyAllBitmaps(ppdev);
  2454. // SWAT3: Font cache release has moved to vAssertModeText.
  2455. vAssertModeText(ppdev, FALSE);
  2456. #ifdef ALLOC_IN_CREATESURFACE
  2457. // We handle DirectDraw surfaces ourselfs.
  2458. pdm = NULL;
  2459. #else
  2460. // Allocate the biggest chunk of memory for DirectDraw.
  2461. align.pt.x = align.pt.y = 1;
  2462. pdm = mmAllocLargest(&ppdev->mmMemMgr, align);
  2463. #endif
  2464. DISPDBG((DISPLVL, "DDOffScnMemAlloc: completed\n"));
  2465. return (POFMHDL) pdm;
  2466. }
  2467. /******************************************************************************\
  2468. * Function: DDOffScnMemRestore
  2469. *
  2470. * Purpose: Release the memory allocated by DirectDraw.
  2471. *
  2472. * On entry: ppdev Pointer to physical device.
  2473. *
  2474. * Returns: Nothing.
  2475. \******************************************************************************/
  2476. void DDOffScnMemRestore(PPDEV ppdev)
  2477. {
  2478. PDDOFM pdd, pddNext;
  2479. DISPDBG((DISPLVL, "DDOffScnMemRestore\n"));
  2480. // Release all DirectDraw nodes.
  2481. for (pdd = ppdev->DDOffScnMemQ; pdd != NULL; pdd = pddNext)
  2482. {
  2483. pddNext = pdd->nexthdl;
  2484. mmFree(&ppdev->mmMemMgr, (PDEVMEM) pdd->phdl);
  2485. MEMORY_FREE(pdd);
  2486. }
  2487. ppdev->DDOffScnMemQ = NULL;
  2488. // Release DirectDraw memory.
  2489. if (ppdev->DirectDrawHandle != NULL)
  2490. {
  2491. mmFree(&ppdev->mmMemMgr, (PDEVMEM) ppdev->DirectDrawHandle);
  2492. ppdev->DirectDrawHandle = NULL;
  2493. }
  2494. // Invalidate the entire brush cache now.
  2495. vInvalidateBrushCache(ppdev);
  2496. // Invalidate all cached fonts.
  2497. #if SWAT3
  2498. vAssertModeText(ppdev, TRUE);
  2499. #endif
  2500. ppdev->ulFontCount++;
  2501. DISPDBG((DISPLVL, "DDOffScnMemRestore: completed\n"));
  2502. }
  2503. /******************************************************************************\
  2504. * Function: FindHandle
  2505. *
  2506. * Purpose: Find a specific node int the used list.
  2507. *
  2508. * On entry: ppdev Pointer to physical device.
  2509. * hdl Handle of node to find.
  2510. *
  2511. * Returns: A pointer to the specified handle if it is found in the used
  2512. * list, otherwise NULL will be returned.
  2513. \******************************************************************************/
  2514. POFMHDL FindHandle(PPDEV ppdev, POFMHDL hdl)
  2515. {
  2516. PDEVMEM pdm;
  2517. // Walk through the used list.
  2518. for (pdm = ppdev->mmMemMgr.pdmUsed; pdm != NULL; pdm = pdm->next)
  2519. {
  2520. if ((POFMHDL) pdm == hdl)
  2521. {
  2522. // We have a match!
  2523. return hdl;
  2524. }
  2525. }
  2526. return NULL;
  2527. }
  2528. #endif /* MEMMGR */
  2529.