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.

411 lines
15 KiB

  1. /******************************Module*Header**********************************\
  2. *
  3. * *******************
  4. * * D3D SAMPLE CODE *
  5. * *******************
  6. *
  7. * Module Name: d3dtxman.c
  8. *
  9. * Content: D3D Texture manager
  10. *
  11. * Copyright (c) 1995-1999 Microsoft Corporation. All rights Reserved.
  12. \*****************************************************************************/
  13. #include "precomp.h"
  14. #include "d3dtxman.h"
  15. #include "dd.h"
  16. #include "heap.h"
  17. #define ALLOC_TAG ALLOC_TAG_TD2P
  18. //-----------------------------------------------------------------------------
  19. //
  20. // void TextureHeapHeapify
  21. //
  22. //-----------------------------------------------------------------------------
  23. void TextureHeapHeapify(PTextureHeap pTextureHeap, DWORD k)
  24. {
  25. while(true)
  26. {
  27. DWORD smallest;
  28. DWORD l = lchild(k);
  29. DWORD r = rchild(k);
  30. if(l < pTextureHeap->m_next)
  31. if(TextureCost(pTextureHeap->m_data_p[l]) <
  32. TextureCost(pTextureHeap->m_data_p[k]))
  33. smallest = l;
  34. else
  35. smallest = k;
  36. else
  37. smallest = k;
  38. if(r < pTextureHeap->m_next)
  39. if(TextureCost(pTextureHeap->m_data_p[r]) <
  40. TextureCost(pTextureHeap->m_data_p[smallest]))
  41. smallest = r;
  42. if(smallest != k)
  43. {
  44. PPERMEDIA_D3DTEXTURE t = pTextureHeap->m_data_p[k];
  45. pTextureHeap->m_data_p[k] = pTextureHeap->m_data_p[smallest];
  46. pTextureHeap->m_data_p[k]->m_dwHeapIndex = k;
  47. pTextureHeap->m_data_p[smallest] = t;
  48. t->m_dwHeapIndex = smallest;
  49. k = smallest;
  50. }
  51. else
  52. break;
  53. }
  54. }
  55. //-----------------------------------------------------------------------------
  56. //
  57. // bool TextureHeapAdd
  58. //
  59. //-----------------------------------------------------------------------------
  60. bool TextureHeapAdd(PTextureHeap pTextureHeap, PPERMEDIA_D3DTEXTURE lpD3DTexI)
  61. {
  62. if(pTextureHeap->m_next == pTextureHeap->m_size)
  63. {
  64. pTextureHeap->m_size = pTextureHeap->m_size * 2 - 1;
  65. PPERMEDIA_D3DTEXTURE *p = (PPERMEDIA_D3DTEXTURE *)
  66. ENGALLOCMEM( FL_ZERO_MEMORY,
  67. sizeof(PPERMEDIA_D3DTEXTURE)*pTextureHeap->m_size,ALLOC_TAG);
  68. if(p == 0)
  69. {
  70. DBG_D3D((0,"Failed to allocate memory to grow heap."));
  71. pTextureHeap->m_size = (pTextureHeap->m_size + 1) / 2; // restore size
  72. return false;
  73. }
  74. memcpy(p + 1, pTextureHeap->m_data_p + 1,
  75. sizeof(PPERMEDIA_D3DTEXTURE) * (pTextureHeap->m_next - 1));
  76. ENGFREEMEM( pTextureHeap->m_data_p);
  77. pTextureHeap->m_data_p = p;
  78. }
  79. ULONGLONG Cost = TextureCost(lpD3DTexI);
  80. for(DWORD k = pTextureHeap->m_next; k > 1; k = parent(k))
  81. if(Cost < TextureCost(pTextureHeap->m_data_p[parent(k)]))
  82. {
  83. pTextureHeap->m_data_p[k] = pTextureHeap->m_data_p[parent(k)];
  84. pTextureHeap->m_data_p[k]->m_dwHeapIndex = k;
  85. }
  86. else
  87. break;
  88. pTextureHeap->m_data_p[k] = lpD3DTexI;
  89. lpD3DTexI->m_dwHeapIndex = k;
  90. ++pTextureHeap->m_next;
  91. return true;
  92. }
  93. //-----------------------------------------------------------------------------
  94. //
  95. // PPERMEDIA_D3DTEXTURE TextureHeapExtractMin
  96. //
  97. //-----------------------------------------------------------------------------
  98. PPERMEDIA_D3DTEXTURE TextureHeapExtractMin(PTextureHeap pTextureHeap)
  99. {
  100. PPERMEDIA_D3DTEXTURE lpD3DTexI = pTextureHeap->m_data_p[1];
  101. --pTextureHeap->m_next;
  102. pTextureHeap->m_data_p[1] = pTextureHeap->m_data_p[pTextureHeap->m_next];
  103. pTextureHeap->m_data_p[1]->m_dwHeapIndex = 1;
  104. TextureHeapHeapify(pTextureHeap,1);
  105. lpD3DTexI->m_dwHeapIndex = 0;
  106. return lpD3DTexI;
  107. }
  108. //-----------------------------------------------------------------------------
  109. //
  110. // PPERMEDIA_D3DTEXTURE TextureHeapExtractMax
  111. //
  112. //-----------------------------------------------------------------------------
  113. PPERMEDIA_D3DTEXTURE TextureHeapExtractMax(PTextureHeap pTextureHeap)
  114. {
  115. // When extracting the max element from the heap, we don't need to
  116. // search the entire heap, but just the leafnodes. This is because
  117. // it is guaranteed that parent nodes are cheaper than the leaf nodes
  118. // so once you have looked through the leaves, you won't find anything
  119. // cheaper.
  120. // NOTE: (lchild(i) >= m_next) is true only for leaf nodes.
  121. // ALSO NOTE: You cannot have a rchild without a lchild, so simply
  122. // checking for lchild is sufficient.
  123. unsigned max = pTextureHeap->m_next - 1;
  124. ULONGLONG maxcost = 0;
  125. for(unsigned i = max; lchild(i) >= pTextureHeap->m_next; --i)
  126. {
  127. ULONGLONG Cost = TextureCost(pTextureHeap->m_data_p[i]);
  128. if(maxcost < Cost)
  129. {
  130. maxcost = Cost;
  131. max = i;
  132. }
  133. }
  134. PPERMEDIA_D3DTEXTURE lpD3DTexI = pTextureHeap->m_data_p[max];
  135. TextureHeapDel(pTextureHeap,max);
  136. return lpD3DTexI;
  137. }
  138. //-----------------------------------------------------------------------------
  139. //
  140. // void TextureHeapDel
  141. //
  142. //-----------------------------------------------------------------------------
  143. void TextureHeapDel(PTextureHeap pTextureHeap, DWORD k)
  144. {
  145. PPERMEDIA_D3DTEXTURE lpD3DTexI = pTextureHeap->m_data_p[k];
  146. --pTextureHeap->m_next;
  147. ULONGLONG Cost = TextureCost(pTextureHeap->m_data_p[pTextureHeap->m_next]);
  148. if(Cost < TextureCost(lpD3DTexI))
  149. {
  150. while(k > 1)
  151. {
  152. if(Cost < TextureCost(pTextureHeap->m_data_p[parent(k)]))
  153. {
  154. pTextureHeap->m_data_p[k] = pTextureHeap->m_data_p[parent(k)];
  155. pTextureHeap->m_data_p[k]->m_dwHeapIndex = k;
  156. }
  157. else
  158. break;
  159. k = parent(k);
  160. }
  161. pTextureHeap->m_data_p[k] = pTextureHeap->m_data_p[pTextureHeap->m_next];
  162. pTextureHeap->m_data_p[k]->m_dwHeapIndex = k;
  163. }
  164. else
  165. {
  166. pTextureHeap->m_data_p[k] = pTextureHeap->m_data_p[pTextureHeap->m_next];
  167. pTextureHeap->m_data_p[k]->m_dwHeapIndex = k;
  168. TextureHeapHeapify(pTextureHeap,k);
  169. }
  170. lpD3DTexI->m_dwHeapIndex = 0;
  171. }
  172. //-----------------------------------------------------------------------------
  173. //
  174. // void TextureHeapUpdate
  175. //
  176. //-----------------------------------------------------------------------------
  177. void TextureHeapUpdate(PTextureHeap pTextureHeap, DWORD k,
  178. DWORD priority, DWORD ticks)
  179. {
  180. PPERMEDIA_D3DTEXTURE lpD3DTexI = pTextureHeap->m_data_p[k];
  181. ULONGLONG Cost = 0;
  182. #ifdef _X86_
  183. _asm
  184. {
  185. mov edx, 0;
  186. shl edx, 31;
  187. mov eax, priority;
  188. mov ecx, eax;
  189. shr eax, 1;
  190. or edx, eax;
  191. mov DWORD PTR Cost + 4, edx;
  192. shl ecx, 31;
  193. mov eax, ticks;
  194. shr eax, 1;
  195. or eax, ecx;
  196. mov DWORD PTR Cost, eax;
  197. }
  198. #else
  199. Cost = ((ULONGLONG)priority << 31) + ((ULONGLONG)(ticks >> 1));
  200. #endif
  201. if(Cost < TextureCost(lpD3DTexI))
  202. {
  203. while(k > 1)
  204. {
  205. if(Cost < TextureCost(pTextureHeap->m_data_p[parent(k)]))
  206. {
  207. pTextureHeap->m_data_p[k] = pTextureHeap->m_data_p[parent(k)];
  208. pTextureHeap->m_data_p[k]->m_dwHeapIndex = k;
  209. }
  210. else
  211. break;
  212. k = parent(k);
  213. }
  214. lpD3DTexI->m_dwPriority = priority;
  215. lpD3DTexI->m_dwTicks = ticks;
  216. lpD3DTexI->m_dwHeapIndex = k;
  217. pTextureHeap->m_data_p[k] = lpD3DTexI;
  218. }
  219. else
  220. {
  221. lpD3DTexI->m_dwPriority = priority;
  222. lpD3DTexI->m_dwTicks = ticks;
  223. TextureHeapHeapify(pTextureHeap,k);
  224. }
  225. }
  226. //-----------------------------------------------------------------------------
  227. //
  228. // HRESULT TextureCacheManagerInitialize
  229. //
  230. //-----------------------------------------------------------------------------
  231. HRESULT TextureCacheManagerInitialize(
  232. PTextureCacheManager pTextureCacheManager)
  233. {
  234. pTextureCacheManager->tcm_ticks = 0;
  235. pTextureCacheManager->m_heap.m_next = 1;
  236. pTextureCacheManager->m_heap.m_size = 1024;
  237. pTextureCacheManager->m_heap.m_data_p = (PPERMEDIA_D3DTEXTURE *)
  238. ENGALLOCMEM( FL_ZERO_MEMORY,
  239. sizeof(PPERMEDIA_D3DTEXTURE)*pTextureCacheManager->m_heap.m_size,
  240. ALLOC_TAG);
  241. if(pTextureCacheManager->m_heap.m_data_p == 0)
  242. {
  243. DBG_D3D((0,"Failed to allocate texture heap."));
  244. return E_OUTOFMEMORY;
  245. }
  246. memset(pTextureCacheManager->m_heap.m_data_p, 0,
  247. sizeof(PPERMEDIA_D3DTEXTURE) * pTextureCacheManager->m_heap.m_size);
  248. return D3D_OK;
  249. }
  250. //-----------------------------------------------------------------------------
  251. //
  252. // BOOL TextureCacheManagerFreeTextures
  253. //
  254. //-----------------------------------------------------------------------------
  255. BOOL TextureCacheManagerFreeTextures(
  256. PTextureCacheManager pTextureCacheManager,DWORD dwStage, DWORD dwBytes)
  257. {
  258. if(pTextureCacheManager->m_heap.m_next <= 1)
  259. return false;
  260. PPERMEDIA_D3DTEXTURE rc;
  261. for(unsigned i = 0;
  262. pTextureCacheManager->m_heap.m_next > 1 && i < dwBytes;
  263. i += rc->m_dwBytes)
  264. {
  265. // Find the LRU texture and remove it.
  266. rc = TextureHeapExtractMin(&pTextureCacheManager->m_heap);
  267. TextureCacheManagerRemove(pTextureCacheManager,rc);
  268. pTextureCacheManager->m_stats.dwLastPri = rc->m_dwPriority;
  269. ++pTextureCacheManager->m_stats.dwNumEvicts;
  270. DBG_D3D((2, "Removed texture with timestamp %u,%u (current = %u).",
  271. rc->m_dwPriority, rc->m_dwTicks, pTextureCacheManager->tcm_ticks));
  272. }
  273. return true;
  274. }
  275. //-----------------------------------------------------------------------------
  276. //
  277. // HRESULT TextureCacheManagerAllocNode
  278. //
  279. //-----------------------------------------------------------------------------
  280. HRESULT TextureCacheManagerAllocNode(
  281. PERMEDIA_D3DCONTEXT* pContext,
  282. PPERMEDIA_D3DTEXTURE pTexture)
  283. {
  284. DWORD trycount = 0, bytecount = pTexture->m_dwBytes;
  285. PermediaSurfaceData* pPrivateData=pTexture->pTextureSurface;
  286. PTextureCacheManager pTextureCacheManager=pContext->pTextureManager;
  287. if (NULL == pPrivateData)
  288. {
  289. DBG_D3D((0,"pTextureSurface==NULL invalid texture"));
  290. return D3D_OK; //we already have the video memory allocated
  291. }
  292. // Attempt to allocate a texture.
  293. while(NULL == pPrivateData->fpVidMem)
  294. {
  295. LONG lScratchDelta;
  296. DWORD PackedPP;
  297. ++trycount;
  298. pPrivateData->fpVidMem=(FLATPTR)
  299. ulVidMemAllocate( pContext->ppdev,
  300. pTexture->wWidth,
  301. pTexture->wHeight,
  302. ShiftLookup[pTexture->dwRGBBitCount>>3],
  303. &lScratchDelta,
  304. &pPrivateData->pvmHeap,
  305. &PackedPP,
  306. FALSE);
  307. DBG_D3D((8,"Got fpVidMem=%08lx",pPrivateData->fpVidMem));
  308. if (NULL != pPrivateData->fpVidMem)
  309. { // No problem, there is enough memory.
  310. pTexture->m_dwTicks = pTextureCacheManager->tcm_ticks;
  311. if(!TextureHeapAdd(&pTextureCacheManager->m_heap,pTexture))
  312. {
  313. VidMemFree(pPrivateData->pvmHeap->lpHeap,
  314. pPrivateData->fpVidMem);
  315. pPrivateData->fpVidMem=NULL;
  316. DBG_D3D((0,"Out of memory"));
  317. return DDERR_OUTOFMEMORY;
  318. }
  319. pPrivateData->dwFlags |= P2_SURFACE_NEEDUPDATE;
  320. break;
  321. }
  322. else
  323. {
  324. if (!TextureCacheManagerFreeTextures(
  325. pTextureCacheManager,0, bytecount))
  326. {
  327. DBG_D3D((0,"all Freed no further video memory available"));
  328. return DDERR_OUTOFVIDEOMEMORY; //nothing left
  329. }
  330. bytecount <<= 1;
  331. }
  332. }
  333. if(trycount > 1)
  334. {
  335. DBG_D3D((8, "Allocated texture after %u tries.", trycount));
  336. }
  337. TextureCacheManagerIncTotSz(pTextureCacheManager,
  338. pTexture->m_dwBytes);
  339. ++pTextureCacheManager->m_stats.dwWorkingSet;
  340. pTextureCacheManager->m_stats.dwWorkingSetBytes
  341. += (pTexture->m_dwBytes);
  342. ++pTextureCacheManager->m_stats.dwNumVidCreates;
  343. return D3D_OK;
  344. }
  345. //-----------------------------------------------------------------------------
  346. //
  347. // void TextureCacheManagerRemove
  348. //
  349. // remove all HW handles and release surface
  350. //
  351. //-----------------------------------------------------------------------------
  352. void TextureCacheManagerRemove(
  353. PTextureCacheManager pTextureCacheManager,
  354. PPERMEDIA_D3DTEXTURE pTexture)
  355. {
  356. PermediaSurfaceData* pPrivateData=pTexture->pTextureSurface;
  357. if (CHECK_P2_SURFACEDATA_VALIDITY(pPrivateData) && pPrivateData->fpVidMem)
  358. {
  359. VidMemFree(pPrivateData->pvmHeap->lpHeap,pPrivateData->fpVidMem);
  360. pPrivateData->fpVidMem=NULL;
  361. TextureCacheManagerDecTotSz(pTextureCacheManager,
  362. pTexture->m_dwBytes);
  363. --pTextureCacheManager->m_stats.dwWorkingSet;
  364. pTextureCacheManager->m_stats.dwWorkingSetBytes -=
  365. (pTexture->m_dwBytes);
  366. }
  367. if (pTexture->m_dwHeapIndex && pTextureCacheManager->m_heap.m_data_p)
  368. TextureHeapDel(&pTextureCacheManager->m_heap,
  369. pTexture->m_dwHeapIndex);
  370. }
  371. //-----------------------------------------------------------------------------
  372. //
  373. // void TextureCacheManagerEvictTextures
  374. //
  375. //-----------------------------------------------------------------------------
  376. void TextureCacheManagerEvictTextures(
  377. PTextureCacheManager pTextureCacheManager)
  378. {
  379. while(pTextureCacheManager->m_heap.m_next > 1)
  380. {
  381. PPERMEDIA_D3DTEXTURE lpD3DTexI =
  382. TextureHeapExtractMin(&pTextureCacheManager->m_heap);
  383. TextureCacheManagerRemove(pTextureCacheManager,lpD3DTexI);
  384. }
  385. pTextureCacheManager->tcm_ticks = 0;
  386. }
  387. //-----------------------------------------------------------------------------
  388. //
  389. // void TextureCacheManagerTimeStamp
  390. //
  391. //-----------------------------------------------------------------------------
  392. void TextureCacheManagerTimeStamp(
  393. PTextureCacheManager pTextureCacheManager,PPERMEDIA_D3DTEXTURE lpD3DTexI)
  394. {
  395. TextureHeapUpdate(&pTextureCacheManager->m_heap,
  396. lpD3DTexI->m_dwHeapIndex, lpD3DTexI->m_dwPriority,
  397. pTextureCacheManager->tcm_ticks);
  398. pTextureCacheManager->tcm_ticks += 2;
  399. }