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.

1003 lines
28 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1994-1998 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: ddheap.c
  6. * Content: Top-level heap routines.
  7. * History:
  8. * Date By Reason
  9. * ==== == ======
  10. * 06-dec-94 craige initial implementation
  11. * 06-jan-95 craige integrated into DDRAW
  12. * 20-mar-95 craige prepare for rectangular memory manager
  13. * 27-mar-95 craige linear or rectangular vidmem
  14. * 01-apr-95 craige happy fun joy updated header file
  15. * 06-apr-95 craige fill in free video memory
  16. * 15-may-95 craige made separate VMEM struct for rect & linear
  17. * 10-jun-95 craige exported fns
  18. * 02-jul-95 craige fail if VidMemInit if linear or rect. fail;
  19. * removed linFindMemBlock
  20. * 17-jul-95 craige added VidMemLargestFree
  21. * 01-dec-95 colinmc added VidMemAmountAllocated
  22. * 11-dec-95 kylej added VidMemGetRectStride
  23. * 05-jul-96 colinmc Work Item: Removing the restriction on taking Win16
  24. * lock on VRAM surfaces (not including the primary)
  25. * 03-mar-97 jeffno Work item: Extended surface memory alignment
  26. * 13-mar-97 colinmc Bug 6533: Pass uncached flag to VMM correctly
  27. * 03-Feb-98 DrewB Made portable between user and kernel.
  28. *
  29. ***************************************************************************/
  30. #include "ddrawpr.h"
  31. /*
  32. * IsDifferentPixelFormat
  33. *
  34. * determine if two pixel formats are the same or not
  35. *
  36. * (CMcC) 12/14/95 Really useful - so no longer static
  37. *
  38. * This function really shouldn't be in a heap file but it's
  39. * needed by both the user and kernel code so this is a convenient
  40. * place to put it to have it shared.
  41. */
  42. BOOL IsDifferentPixelFormat( LPDDPIXELFORMAT pdpf1, LPDDPIXELFORMAT pdpf2 )
  43. {
  44. /*
  45. * same flags?
  46. */
  47. if( pdpf1->dwFlags != pdpf2->dwFlags )
  48. {
  49. VDPF(( 4, S, "Flags differ!" ));
  50. return TRUE;
  51. }
  52. /*
  53. * same bitcount for non-YUV surfaces?
  54. */
  55. if( !(pdpf1->dwFlags & (DDPF_YUV | DDPF_FOURCC)) )
  56. {
  57. if( pdpf1->dwRGBBitCount != pdpf2->dwRGBBitCount )
  58. {
  59. VDPF(( 4, S, "RGB Bitcount differs!" ));
  60. return TRUE;
  61. }
  62. }
  63. /*
  64. * same RGB properties?
  65. */
  66. if( pdpf1->dwFlags & DDPF_RGB )
  67. {
  68. if( pdpf1->dwRBitMask != pdpf2->dwRBitMask )
  69. {
  70. VDPF(( 4, S, "RBitMask differs!" ));
  71. return TRUE;
  72. }
  73. if( pdpf1->dwGBitMask != pdpf2->dwGBitMask )
  74. {
  75. VDPF(( 4, S, "GBitMask differs!" ));
  76. return TRUE;
  77. }
  78. if( pdpf1->dwBBitMask != pdpf2->dwBBitMask )
  79. {
  80. VDPF(( 4, S, "BBitMask differs!" ));
  81. return TRUE;
  82. }
  83. if( ( pdpf1->dwFlags & DDPF_ALPHAPIXELS ) &&
  84. ( pdpf1->dwRGBAlphaBitMask != pdpf2->dwRGBAlphaBitMask )
  85. )
  86. {
  87. VDPF(( 4, S, "RGBAlphaBitMask differs!" ));
  88. return TRUE;
  89. }
  90. }
  91. /*
  92. * same YUV properties?
  93. */
  94. if( pdpf1->dwFlags & DDPF_YUV )
  95. {
  96. VDPF(( 5, S, "YUV???" ));
  97. if( pdpf1->dwFourCC != pdpf2->dwFourCC )
  98. {
  99. return TRUE;
  100. }
  101. if( pdpf1->dwYUVBitCount != pdpf2->dwYUVBitCount )
  102. {
  103. return TRUE;
  104. }
  105. if( pdpf1->dwYBitMask != pdpf2->dwYBitMask )
  106. {
  107. return TRUE;
  108. }
  109. if( pdpf1->dwUBitMask != pdpf2->dwUBitMask )
  110. {
  111. return TRUE;
  112. }
  113. if( pdpf1->dwVBitMask != pdpf2->dwVBitMask )
  114. {
  115. return TRUE;
  116. }
  117. if( ( pdpf1->dwFlags & DDPF_ALPHAPIXELS ) &&
  118. (pdpf1->dwYUVAlphaBitMask != pdpf2->dwYUVAlphaBitMask )
  119. )
  120. {
  121. return TRUE;
  122. }
  123. }
  124. /*
  125. * Possible to use FOURCCs w/o setting the DDPF_YUV flag
  126. * ScottM 7/11/96
  127. */
  128. else if( pdpf1->dwFlags & DDPF_FOURCC )
  129. {
  130. VDPF(( 5, S, "FOURCC???" ));
  131. if( pdpf1->dwFourCC != pdpf2->dwFourCC )
  132. {
  133. return TRUE;
  134. }
  135. }
  136. /*
  137. * If Interleaved Z then check Z bit masks are the same
  138. */
  139. if( pdpf1->dwFlags & DDPF_ZPIXELS )
  140. {
  141. VDPF(( 5, S, "ZPIXELS???" ));
  142. if( pdpf1->dwRGBZBitMask != pdpf2->dwRGBZBitMask )
  143. return TRUE;
  144. }
  145. return FALSE;
  146. } /* IsDifferentPixelFormat */
  147. /*
  148. * VidMemInit - initialize video memory manager heap
  149. */
  150. LPVMEMHEAP WINAPI VidMemInit(
  151. DWORD flags,
  152. FLATPTR start,
  153. FLATPTR width_or_end,
  154. DWORD height,
  155. DWORD pitch )
  156. {
  157. LPVMEMHEAP pvmh;
  158. pvmh = (LPVMEMHEAP)MemAlloc( sizeof( VMEMHEAP ) );
  159. if( pvmh == NULL )
  160. {
  161. return NULL;
  162. }
  163. pvmh->dwFlags = flags;
  164. ZeroMemory( & pvmh->Alignment.ddsCaps, sizeof(pvmh->Alignment.ddsCaps) );
  165. if( pvmh->dwFlags & VMEMHEAP_LINEAR )
  166. {
  167. if( !linVidMemInit( pvmh, start, width_or_end ) )
  168. {
  169. MemFree( pvmh );
  170. return NULL;
  171. }
  172. }
  173. else
  174. {
  175. if( !rectVidMemInit( pvmh, start, (DWORD) width_or_end, height,
  176. pitch ) )
  177. {
  178. MemFree( pvmh );
  179. return NULL;
  180. }
  181. }
  182. return pvmh;
  183. } /* VidMemInit */
  184. /*
  185. * VidMemFini - done with video memory manager
  186. */
  187. void WINAPI VidMemFini( LPVMEMHEAP pvmh )
  188. {
  189. if( pvmh->dwFlags & VMEMHEAP_LINEAR )
  190. {
  191. linVidMemFini( pvmh );
  192. }
  193. else
  194. {
  195. rectVidMemFini( pvmh );
  196. }
  197. } /* VidMemFini */
  198. /*
  199. * InternalVidMemAlloc - alloc some flat video memory and give us back the size
  200. * we allocated
  201. */
  202. FLATPTR WINAPI InternalVidMemAlloc( LPVMEMHEAP pvmh, DWORD x, DWORD y,
  203. LPDWORD lpdwSize,
  204. LPSURFACEALIGNMENT lpAlignment,
  205. LPLONG lpNewPitch )
  206. {
  207. if( pvmh->dwFlags & VMEMHEAP_LINEAR )
  208. {
  209. return linVidMemAlloc( pvmh, x, y, lpdwSize, lpAlignment, lpNewPitch );
  210. }
  211. else
  212. {
  213. FLATPTR lp = rectVidMemAlloc( pvmh, x, y, lpdwSize, lpAlignment );
  214. if (lp && lpNewPitch )
  215. {
  216. *lpNewPitch = (LONG) pvmh->stride;
  217. }
  218. return lp;
  219. }
  220. return (FLATPTR) NULL;
  221. } /* InternalVidMemAlloc */
  222. /*
  223. * VidMemAlloc - alloc some flat video memory
  224. */
  225. FLATPTR WINAPI VidMemAlloc( LPVMEMHEAP pvmh, DWORD x, DWORD y )
  226. {
  227. DWORD dwSize;
  228. /*
  229. * We are not interested in the size here.
  230. */
  231. return InternalVidMemAlloc( pvmh, x, y, &dwSize , NULL , NULL );
  232. } /* VidMemAlloc */
  233. /*
  234. * VidMemFree = free some flat video memory
  235. */
  236. void WINAPI VidMemFree( LPVMEMHEAP pvmh, FLATPTR ptr )
  237. {
  238. if( pvmh->dwFlags & VMEMHEAP_LINEAR )
  239. {
  240. linVidMemFree( pvmh, ptr );
  241. }
  242. else
  243. {
  244. rectVidMemFree( pvmh, ptr );
  245. }
  246. } /* VidMemFree */
  247. /*
  248. * VidMemAmountAllocated
  249. */
  250. DWORD WINAPI VidMemAmountAllocated( LPVMEMHEAP pvmh )
  251. {
  252. if( pvmh->dwFlags & VMEMHEAP_LINEAR )
  253. {
  254. return linVidMemAmountAllocated( pvmh );
  255. }
  256. else
  257. {
  258. return rectVidMemAmountAllocated( pvmh );
  259. }
  260. } /* VidMemAmountAllocated */
  261. /*
  262. * VidMemAmountFree
  263. */
  264. DWORD WINAPI VidMemAmountFree( LPVMEMHEAP pvmh )
  265. {
  266. if( pvmh->dwFlags & VMEMHEAP_LINEAR )
  267. {
  268. return linVidMemAmountFree( pvmh );
  269. }
  270. else
  271. {
  272. return rectVidMemAmountFree( pvmh );
  273. }
  274. } /* VidMemAmountFree */
  275. /*
  276. * VidMemLargestFree
  277. */
  278. DWORD WINAPI VidMemLargestFree( LPVMEMHEAP pvmh )
  279. {
  280. if( pvmh->dwFlags & VMEMHEAP_LINEAR )
  281. {
  282. return linVidMemLargestFree( pvmh );
  283. }
  284. else
  285. {
  286. return 0;
  287. }
  288. } /* VidMemLargestFree */
  289. /*
  290. * HeapVidMemInit
  291. *
  292. * Top level heap initialization code which handles AGP stuff.
  293. */
  294. LPVMEMHEAP WINAPI HeapVidMemInit( LPVIDMEM lpVidMem,
  295. DWORD pitch,
  296. HANDLE hdev,
  297. LPHEAPALIGNMENT pgad)
  298. {
  299. DWORD dwSize;
  300. FLATPTR fpLinStart;
  301. LARGE_INTEGER liDevStart;
  302. PVOID pvReservation;
  303. DDASSERT( NULL != lpVidMem );
  304. if( lpVidMem->dwFlags & VIDMEM_ISNONLOCAL )
  305. {
  306. BOOL fIsUC;
  307. BOOL fIsWC;
  308. DWORD dwSizeReserved = 0;
  309. /*
  310. * Its a non-local heap so the first thing we need to do
  311. * is to reserved the heap address range.
  312. */
  313. /*
  314. * Compute the size of the heap.
  315. */
  316. if( lpVidMem->dwFlags & VIDMEM_ISLINEAR )
  317. {
  318. dwSize = (DWORD)(lpVidMem->fpEnd - lpVidMem->fpStart) + 1UL;
  319. if (dwSize & 1)
  320. {
  321. DPF_ERR("Driver error: fpEnd of non-local heap should be inclusive");
  322. }
  323. }
  324. else
  325. {
  326. DDASSERT( lpVidMem->dwFlags & VIDMEM_ISRECTANGULAR );
  327. dwSize = (pitch * lpVidMem->dwHeight);
  328. }
  329. DDASSERT( 0UL != dwSize );
  330. if( lpVidMem->dwFlags & VIDMEM_ISWC )
  331. {
  332. fIsUC = FALSE;
  333. fIsWC = TRUE;
  334. }
  335. else
  336. {
  337. fIsUC = TRUE;
  338. fIsWC = FALSE;
  339. }
  340. if( !(dwSizeReserved = AGPReserve( hdev, dwSize, fIsUC, fIsWC,
  341. &fpLinStart, &liDevStart,
  342. &pvReservation )) )
  343. {
  344. VDPF(( 0, V, "Could not reserve a GART address range for a "
  345. "linear heap of size 0x%08x", dwSize ));
  346. return 0UL;
  347. }
  348. else
  349. {
  350. VDPF((4,V, "Allocated a GART address range starting at "
  351. "0x%08x (linear) 0x%08x:0x%08x (physical) of size %d",
  352. fpLinStart, liDevStart.HighPart, liDevStart.LowPart,
  353. dwSizeReserved ));
  354. }
  355. if (dwSizeReserved != dwSize)
  356. {
  357. VDPF((1,V,"WARNING! This system required that the full "
  358. "nonlocal aperture could not be reserved!"));
  359. VDPF((1,V," Requested aperture:%08x, "
  360. "Reserved aperture:%08x", dwSize, dwSizeReserved));
  361. }
  362. /*
  363. * Update the heap for the new start address
  364. * (and end address for a linear heap).
  365. */
  366. lpVidMem->fpStart = fpLinStart;
  367. if( lpVidMem->dwFlags & VIDMEM_ISLINEAR )
  368. {
  369. lpVidMem->fpEnd = ( fpLinStart + dwSizeReserved ) - 1UL;
  370. }
  371. else
  372. {
  373. DDASSERT( lpVidMem->dwFlags & VIDMEM_ISRECTANGULAR );
  374. DDASSERT( pitch );
  375. lpVidMem->dwHeight = dwSizeReserved / pitch;
  376. }
  377. }
  378. if( lpVidMem->dwFlags & VIDMEM_ISLINEAR )
  379. {
  380. VDPF(( 4,V, "VidMemInit: Linear: fpStart = 0x%08x fpEnd = 0x%08x",
  381. lpVidMem->fpStart, lpVidMem->fpEnd ));
  382. lpVidMem->lpHeap = VidMemInit( VMEMHEAP_LINEAR, lpVidMem->fpStart,
  383. lpVidMem->fpEnd, 0, 0 );
  384. }
  385. else
  386. {
  387. VDPF(( 4,V, "VidMemInit: Rectangular: fpStart = 0x%08x "
  388. "dwWidth = %ld dwHeight = %ld, pitch = %ld",
  389. lpVidMem->fpStart, lpVidMem->dwWidth, lpVidMem->dwHeight,
  390. pitch ));
  391. lpVidMem->lpHeap = VidMemInit( VMEMHEAP_RECTANGULAR, lpVidMem->fpStart,
  392. lpVidMem->dwWidth, lpVidMem->dwHeight,
  393. pitch );
  394. }
  395. /*
  396. * Modify the caps and alt-caps so that you don't allocate local
  397. * video memory surfaces out of AGP memory and vice-verse.
  398. */
  399. if( lpVidMem->dwFlags & VIDMEM_ISNONLOCAL )
  400. {
  401. /*
  402. * Its an AGP heap. So don't let explict LOCAL video memory
  403. * be allocated out of this heap.
  404. */
  405. lpVidMem->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM;
  406. lpVidMem->ddsCapsAlt.dwCaps |= DDSCAPS_LOCALVIDMEM;
  407. }
  408. else
  409. {
  410. /*
  411. * Its a local video memory heap. So don't let explicity NON-LOCAL
  412. * video memory be allocated out of this heap.
  413. */
  414. lpVidMem->ddsCaps.dwCaps |= DDSCAPS_NONLOCALVIDMEM;
  415. lpVidMem->ddsCapsAlt.dwCaps |= DDSCAPS_NONLOCALVIDMEM;
  416. }
  417. if( lpVidMem->dwFlags & VIDMEM_ISNONLOCAL )
  418. {
  419. if (lpVidMem->lpHeap != NULL)
  420. {
  421. /*
  422. * We start out with no committed memory.
  423. */
  424. lpVidMem->lpHeap->fpGARTLin = fpLinStart;
  425. // Fill in partial physical address for Win9x.
  426. lpVidMem->lpHeap->fpGARTDev = liDevStart.LowPart;
  427. // Fill in complete physical address for NT.
  428. lpVidMem->lpHeap->liPhysAGPBase = liDevStart;
  429. lpVidMem->lpHeap->pvPhysRsrv = pvReservation;
  430. lpVidMem->lpHeap->dwCommitedSize = 0UL;
  431. }
  432. else if (pvReservation != NULL)
  433. {
  434. AGPFree( hdev, pvReservation );
  435. }
  436. }
  437. /*
  438. * Copy any extended alignment data into the private heap structure
  439. */
  440. if ( lpVidMem->lpHeap )
  441. {
  442. if ( pgad )
  443. {
  444. lpVidMem->lpHeap->dwFlags |= VMEMHEAP_ALIGNMENT;
  445. lpVidMem->lpHeap->Alignment = *pgad;
  446. VDPF((4,V,"Extended alignment turned on for this heap."));
  447. VDPF((4,V,"Alignments are turned on for:"));
  448. VDPF((4,V," %08X",pgad->ddsCaps));
  449. }
  450. else
  451. {
  452. /*
  453. * This means the allocation routines will do no alignment modifications
  454. */
  455. VDPF((4,V,"Extended alignment turned OFF for this heap."));
  456. lpVidMem->lpHeap->dwFlags &= ~VMEMHEAP_ALIGNMENT;
  457. }
  458. }
  459. return lpVidMem->lpHeap;
  460. } /* HeapVidMemInit */
  461. /*
  462. * HeapVidMemFini
  463. *
  464. * Top level heap release code. Handle AGP stuff
  465. */
  466. void WINAPI HeapVidMemFini( LPVIDMEM lpVidMem, HANDLE hdev )
  467. {
  468. DWORD dwCommittedSize = 0UL;
  469. PVOID pvReservation;
  470. /*
  471. * Remember how much memory we committed to the AGP heap.
  472. */
  473. DDASSERT( NULL != lpVidMem->lpHeap );
  474. if( lpVidMem->dwFlags & VIDMEM_ISNONLOCAL )
  475. {
  476. dwCommittedSize = lpVidMem->lpHeap->dwCommitedSize;
  477. pvReservation = lpVidMem->lpHeap->pvPhysRsrv;
  478. }
  479. /*
  480. * Free the memory manager
  481. */
  482. VidMemFini( lpVidMem->lpHeap );
  483. lpVidMem->lpHeap = NULL;
  484. if( lpVidMem->dwFlags & VIDMEM_ISNONLOCAL )
  485. {
  486. BOOL fSuccess;
  487. /*
  488. * If this is a non-local (AGP) heap then decommit and
  489. * free the GART memory now.
  490. */
  491. if( 0UL != dwCommittedSize )
  492. {
  493. /*
  494. * Only decommit if we actually bothered to commit something
  495. * in the first place.
  496. */
  497. fSuccess = AGPDecommitAll( hdev, pvReservation, dwCommittedSize );
  498. /*
  499. * Should never fail and not much we can do if it does apart
  500. * from assert that something bad is happening.
  501. */
  502. DDASSERT( fSuccess );
  503. }
  504. fSuccess = AGPFree( hdev, pvReservation );
  505. /*
  506. * Again this should only fail if the OS is in an unstable state
  507. * or if I have messed up (sadly the later is all too likely)
  508. * so assert.
  509. */
  510. DDASSERT( fSuccess );
  511. }
  512. } /* HeapVidMemFini */
  513. /*
  514. * This is an external entry point which can be used by drivers to allocate
  515. * aligned surfaces.
  516. */
  517. FLATPTR WINAPI HeapVidMemAllocAligned(
  518. LPVIDMEM lpVidMem,
  519. DWORD dwWidth,
  520. DWORD dwHeight,
  521. LPSURFACEALIGNMENT lpAlignment ,
  522. LPLONG lpNewPitch )
  523. {
  524. HANDLE hdev;
  525. FLATPTR ptr;
  526. DWORD dwSize;
  527. if ( lpVidMem == NULL ||
  528. lpVidMem->lpHeap == NULL ||
  529. (lpVidMem->dwFlags & VIDMEM_HEAPDISABLED) )
  530. {
  531. return (FLATPTR) NULL;
  532. }
  533. /*
  534. * As we may need to commit AGP memory we need a device handle
  535. * to communicate with the AGP controller. Rather than hunting
  536. * through the driver object list hoping we will find a
  537. * local object for this process we just create a handle
  538. * and discard it after the allocation. This should not be
  539. * performance critical code to start with.
  540. */
  541. hdev = OsGetAGPDeviceHandle(lpVidMem->lpHeap);
  542. if (hdev == NULL)
  543. {
  544. return 0;
  545. }
  546. /* Pass NULL Alignment and new pitch pointer */
  547. ptr = HeapVidMemAlloc( lpVidMem, dwWidth, dwHeight,
  548. hdev, lpAlignment, lpNewPitch, &dwSize );
  549. OsCloseAGPDeviceHandle( hdev );
  550. return ptr;
  551. }
  552. /*
  553. * HeapVidMemAlloc
  554. *
  555. * Top level video memory allocation function. Handles AGP stuff
  556. */
  557. FLATPTR WINAPI HeapVidMemAlloc( LPVIDMEM lpVidMem, DWORD x, DWORD y,
  558. HANDLE hdev, LPSURFACEALIGNMENT lpAlignment,
  559. LPLONG lpNewPitch, LPDWORD pdwSize )
  560. {
  561. FLATPTR fpMem;
  562. DWORD dwSize;
  563. DDASSERT( NULL != lpVidMem );
  564. DDASSERT( NULL != lpVidMem->lpHeap );
  565. fpMem = InternalVidMemAlloc( lpVidMem->lpHeap, x, y, &dwSize,
  566. lpAlignment, lpNewPitch );
  567. if( 0UL == fpMem )
  568. {
  569. return fpMem;
  570. }
  571. if( lpVidMem->dwFlags & VIDMEM_ISNONLOCAL )
  572. {
  573. DWORD dwCommittedSize;
  574. /*
  575. * If this is a non-local heap then we may not have actually
  576. * committed the memory that has just been allocated. We can
  577. * determine this by seeing if the highest address so far
  578. * committed is less than the last address in the surface.
  579. */
  580. dwCommittedSize = lpVidMem->lpHeap->dwCommitedSize;
  581. if( (fpMem + dwSize) > (lpVidMem->fpStart + dwCommittedSize) )
  582. {
  583. DWORD dwSizeToCommit;
  584. BOOL fSuccess;
  585. /*
  586. * We have not yet committed sufficient memory from this heap for
  587. * this surface so commit now. We don't want to recommit for every
  588. * surface creation so we have a minimum commit size
  589. * (dwAGPPolicyCommitDelta). We also need to ensure that by forcing
  590. * the granularity we don't go over the total size of the heap. So
  591. * clamp to that also.
  592. */
  593. dwSizeToCommit = (DWORD)((fpMem + dwSize) -
  594. (lpVidMem->fpStart + dwCommittedSize));
  595. if( dwSizeToCommit < dwAGPPolicyCommitDelta )
  596. dwSizeToCommit = min(dwAGPPolicyCommitDelta,
  597. lpVidMem->lpHeap->dwTotalSize -
  598. dwCommittedSize);
  599. /*
  600. * Okay, we have the offset and the size we need to commit. So ask
  601. * the OS to commit memory to that portion of this previously
  602. * reserved GART range.
  603. *
  604. * NOTE: We start commiting from the start of the currently
  605. * uncommitted area.
  606. */
  607. fSuccess = AGPCommit( hdev, lpVidMem->lpHeap->pvPhysRsrv,
  608. dwCommittedSize, dwSizeToCommit );
  609. if( !fSuccess )
  610. {
  611. /*
  612. * Couldn't commit. Must be out of memory.
  613. * Put the allocated memory back and fail.
  614. */
  615. VidMemFree( lpVidMem->lpHeap, fpMem );
  616. return (FLATPTR) NULL;
  617. }
  618. lpVidMem->lpHeap->dwCommitedSize += dwSizeToCommit;
  619. }
  620. }
  621. if (pdwSize != NULL)
  622. {
  623. *pdwSize = dwSize;
  624. }
  625. return fpMem;
  626. } /* HeapVidMemAlloc */
  627. /*
  628. * SurfaceCapsToAlignment
  629. *
  630. * Return a pointer to the appropriate alignment element in a VMEMHEAP
  631. * structure given surface caps.
  632. *
  633. */
  634. LPSURFACEALIGNMENT SurfaceCapsToAlignment(
  635. LPVIDMEM lpVidmem ,
  636. LPDDRAWI_DDRAWSURFACE_LCL lpSurfaceLcl,
  637. LPVIDMEMINFO lpVidMemInfo)
  638. {
  639. LPVMEMHEAP lpHeap;
  640. LPDDSCAPS lpCaps;
  641. LPDDRAWI_DDRAWSURFACE_GBL lpSurfaceGbl;
  642. DDASSERT( lpVidmem );
  643. DDASSERT( lpSurfaceLcl );
  644. DDASSERT( lpVidMemInfo );
  645. DDASSERT( lpVidmem->lpHeap );
  646. if ( !lpVidmem->lpHeap )
  647. return NULL;
  648. lpCaps = &lpSurfaceLcl->ddsCaps;
  649. lpHeap = lpVidmem->lpHeap;
  650. lpSurfaceGbl = lpSurfaceLcl->lpGbl;
  651. if ( (lpHeap->dwFlags & VMEMHEAP_ALIGNMENT) == 0 )
  652. return NULL;
  653. if ( lpCaps->dwCaps & DDSCAPS_EXECUTEBUFFER )
  654. {
  655. if ( lpHeap->Alignment.ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
  656. {
  657. VDPF((4,V,"Aligning surface as execute buffer"));
  658. return & lpHeap->Alignment.ExecuteBuffer;
  659. }
  660. /*
  661. * If the surface is an execute buffer, then no other
  662. * alignment can apply
  663. */
  664. return NULL;
  665. }
  666. if ( lpCaps->dwCaps & DDSCAPS_OVERLAY )
  667. {
  668. if ( lpHeap->Alignment.ddsCaps.dwCaps & DDSCAPS_OVERLAY )
  669. {
  670. VDPF((4,V,"Aligning surface as overlay"));
  671. return & lpHeap->Alignment.Overlay;
  672. }
  673. /*
  674. * If the surface is an overlay, then no other alignment can apply
  675. */
  676. return NULL;
  677. }
  678. if ( lpCaps->dwCaps & DDSCAPS_TEXTURE )
  679. {
  680. if ( lpHeap->Alignment.ddsCaps.dwCaps & DDSCAPS_TEXTURE )
  681. {
  682. VDPF((4,V,"Aligning surface as texture"));
  683. return & lpHeap->Alignment.Texture;
  684. }
  685. /*
  686. * If it's a texture, it can't be an offscreen or any of the others
  687. */
  688. return NULL;
  689. }
  690. if ( lpCaps->dwCaps & DDSCAPS_ZBUFFER )
  691. {
  692. if ( lpHeap->Alignment.ddsCaps.dwCaps & DDSCAPS_ZBUFFER )
  693. {
  694. VDPF((4,V,"Aligning surface as Z buffer"));
  695. return & lpHeap->Alignment.ZBuffer;
  696. }
  697. return NULL;
  698. }
  699. if ( lpCaps->dwCaps & DDSCAPS_ALPHA )
  700. {
  701. if ( lpHeap->Alignment.ddsCaps.dwCaps & DDSCAPS_ALPHA )
  702. {
  703. VDPF((4,V,"Aligning surface as alpha buffer"));
  704. return & lpHeap->Alignment.AlphaBuffer;
  705. }
  706. return NULL;
  707. }
  708. /*
  709. * We need to give a surface which may potentially become a back buffer
  710. * the alignment which is reserved for potentially visible back buffers.
  711. * This includes any surface which has made it through the above checks
  712. * and has the same dimensions as the primary.
  713. * Note we check only the dimensions of the primary. There's an outside
  714. * chance that an app could create its back buffer before it creates
  715. * the primary
  716. */
  717. do
  718. {
  719. if ( lpSurfaceLcl->dwFlags & DDRAWISURF_HASPIXELFORMAT )
  720. {
  721. if (IsDifferentPixelFormat( &lpVidMemInfo->ddpfDisplay,
  722. &lpSurfaceGbl->ddpfSurface ))
  723. {
  724. /*
  725. * Different pixel format from primary means this surface
  726. * cannot be part of primary chain
  727. */
  728. break;
  729. }
  730. }
  731. if ( (DWORD)lpSurfaceGbl->wWidth != lpVidMemInfo->dwDisplayWidth )
  732. break;
  733. if ( (DWORD)lpSurfaceGbl->wHeight != lpVidMemInfo->dwDisplayHeight )
  734. break;
  735. /*
  736. * This surface could potentially be part of primary chain.
  737. * It has the same
  738. * pixel format as the primary and the same dimensions.
  739. */
  740. if ( lpHeap->Alignment.ddsCaps.dwCaps & DDSCAPS_FLIP )
  741. {
  742. VDPF((4,V,"Aligning surface as potential primary surface"));
  743. return & lpHeap->Alignment.FlipTarget;
  744. }
  745. /*
  746. * Drop through and check for offscreen if driver specified no
  747. * part-of-primary-chain alignment
  748. */
  749. break;
  750. } while (0);
  751. if ( lpCaps->dwCaps & DDSCAPS_OFFSCREENPLAIN )
  752. {
  753. if ( lpHeap->Alignment.ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN )
  754. {
  755. VDPF((4,V,"Aligning surface as offscreen plain"));
  756. return & lpHeap->Alignment.Offscreen;
  757. }
  758. }
  759. VDPF((4,V,"No extended alignment for surface"));
  760. return NULL;
  761. }
  762. /*
  763. * DdHeapAlloc
  764. *
  765. * Search all heaps for one that has space and the appropriate
  766. * caps for the requested surface type and size.
  767. *
  768. * We AND the caps bits required and the caps bits not allowed
  769. * by the video memory. If the result is zero, it is OK.
  770. *
  771. * This is called in 2 passes. Pass1 is the preferred memory state,
  772. * pass2 is the "oh no no memory" state.
  773. *
  774. * On pass1, we use ddsCaps in the VIDMEM struct.
  775. * On pass2, we use ddsCapsAlt in the VIDMEM struct.
  776. *
  777. */
  778. FLATPTR DdHeapAlloc( DWORD dwNumHeaps,
  779. LPVIDMEM pvmHeaps,
  780. HANDLE hdev,
  781. LPVIDMEMINFO lpVidMemInfo,
  782. DWORD dwWidth,
  783. DWORD dwHeight,
  784. LPDDRAWI_DDRAWSURFACE_LCL lpSurfaceLcl,
  785. DWORD dwFlags,
  786. LPVIDMEM *ppvmHeap,
  787. LPLONG plNewPitch,
  788. LPDWORD pdwNewCaps,
  789. LPDWORD pdwSize)
  790. {
  791. LPVIDMEM pvm;
  792. DWORD vm_caps;
  793. int i;
  794. FLATPTR pvidmem;
  795. HANDLE hvxd;
  796. LPDDSCAPS lpCaps;
  797. LPDDSCAPSEX lpExtendedRestrictions;
  798. LPDDSCAPSEX lpExtendedCaps;
  799. DDASSERT( NULL != pdwNewCaps );
  800. DDASSERT( NULL != lpSurfaceLcl );
  801. lpCaps = &lpSurfaceLcl->ddsCaps;
  802. lpExtendedCaps = &lpSurfaceLcl->lpSurfMore->ddsCapsEx;
  803. for( i = 0 ; i < (int)dwNumHeaps ; i++ )
  804. {
  805. pvm = &pvmHeaps[i];
  806. // Skip disabled heaps.
  807. if (pvm->dwFlags & VIDMEM_HEAPDISABLED)
  808. {
  809. continue;
  810. }
  811. /*
  812. * Skip rectangular heaps if we were told to.
  813. */
  814. if (dwFlags & DDHA_SKIPRECTANGULARHEAPS)
  815. {
  816. if (pvm->dwFlags & VIDMEM_ISRECTANGULAR)
  817. {
  818. continue;
  819. }
  820. }
  821. /*
  822. * If local or non-local video memory has been explicity
  823. * specified then ignore heaps which don't match the required
  824. * memory type.
  825. */
  826. if( ( lpCaps->dwCaps & DDSCAPS_LOCALVIDMEM ) &&
  827. ( pvm->dwFlags & VIDMEM_ISNONLOCAL ) )
  828. {
  829. VDPF(( 4, V, "Local video memory was requested but heap is "
  830. "non local. Ignoring heap %d", i ));
  831. continue;
  832. }
  833. if( ( lpCaps->dwCaps & DDSCAPS_NONLOCALVIDMEM ) &&
  834. !( pvm->dwFlags & VIDMEM_ISNONLOCAL ) )
  835. {
  836. VDPF(( 4, V, "Non-local video memory was requested but "
  837. "heap is local. Ignoring heap %d", i ));
  838. continue;
  839. }
  840. if( !( lpCaps->dwCaps & DDSCAPS_NONLOCALVIDMEM ) &&
  841. ( pvm->dwFlags & VIDMEM_ISNONLOCAL ) &&
  842. ( dwFlags & DDHA_ALLOWNONLOCALMEMORY ) )
  843. {
  844. /*
  845. * We can allow textures to fail over to DMA model cards
  846. * if the card exposes an appropriate heap. This won't
  847. * affect cards which can't texture from nonlocal, because
  848. * they won't expose such a heap. This mod doesn't affect
  849. * execute model because all surfaces fail over to nonlocal
  850. * for them.
  851. * Note that we should only fail over to nonlocal if the
  852. * surface wasn't explicitly requested in local. There is a
  853. * clause a few lines up which guarantees this.
  854. */
  855. if ( !(lpCaps->dwCaps & DDSCAPS_TEXTURE) )
  856. {
  857. VDPF(( 4, V, "Non-local memory not explicitly requested "
  858. "for non-texture surface. Ignoring non-local heap %d",
  859. i ));
  860. continue;
  861. }
  862. /*
  863. * If the device can't texture out of AGP, we need to fail this
  864. * heap, since the app is probably expecting to texture out of
  865. * this surface.
  866. */
  867. if ( !(dwFlags & DDHA_ALLOWNONLOCALTEXTURES) )
  868. {
  869. continue;
  870. }
  871. }
  872. if( dwFlags & DDHA_USEALTCAPS )
  873. {
  874. vm_caps = pvm->ddsCapsAlt.dwCaps;
  875. lpExtendedRestrictions = &(pvm->lpHeap->ddsCapsExAlt);
  876. }
  877. else
  878. {
  879. vm_caps = pvm->ddsCaps.dwCaps;
  880. lpExtendedRestrictions = &(pvm->lpHeap->ddsCapsEx);
  881. }
  882. if( ((lpCaps->dwCaps & vm_caps) == 0) &&
  883. ((lpExtendedRestrictions->dwCaps2 & lpExtendedCaps->dwCaps2) == 0) &&
  884. ((lpExtendedRestrictions->dwCaps3 & lpExtendedCaps->dwCaps3) == 0) &&
  885. ((lpExtendedRestrictions->dwCaps4 & lpExtendedCaps->dwCaps4) == 0))
  886. {
  887. pvidmem = HeapVidMemAlloc(
  888. pvm,
  889. dwWidth,
  890. dwHeight,
  891. hdev,
  892. SurfaceCapsToAlignment(pvm, lpSurfaceLcl, lpVidMemInfo),
  893. plNewPitch,
  894. pdwSize);
  895. if( pvidmem != (FLATPTR) NULL )
  896. {
  897. *ppvmHeap = pvm;
  898. if( pvm->dwFlags & VIDMEM_ISNONLOCAL )
  899. *pdwNewCaps |= DDSCAPS_NONLOCALVIDMEM;
  900. else
  901. *pdwNewCaps |= DDSCAPS_LOCALVIDMEM;
  902. return pvidmem;
  903. }
  904. }
  905. }
  906. return (FLATPTR) NULL;
  907. } /* DdHeapAlloc */