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.

420 lines
13 KiB

  1. /******************************Module*Header**********************************\
  2. *
  3. * *******************
  4. * * D3D SAMPLE CODE *
  5. * *******************
  6. *
  7. * Module Name: d3dstrct.c
  8. *
  9. * Content: Internal D3D structure management.
  10. *
  11. * Copyright (c) 1994-1999 3Dlabs Inc. Ltd. All rights reserved.
  12. * Copyright (c) 1995-2003 Microsoft Corporation. All rights reserved.
  13. \*****************************************************************************/
  14. #include "glint.h"
  15. #include "d3dstrct.h"
  16. //----------------------------------------------------------------------------
  17. // This file provides a centralized place where we manage ans use internal
  18. // data structures for the driver. This way, we can change the data structure
  19. // or its management without affecting the rest of the code.
  20. //----------------------------------------------------------------------------
  21. //----------------------------------------------------------------------------
  22. //********************** A R R A Y S T R U C T U R E *********************
  23. //----------------------------------------------------------------------------
  24. //-----------------------------------------------------------------------------
  25. //
  26. // PA_CreateArray
  27. //
  28. // Creates an array of pointers.
  29. //
  30. //-----------------------------------------------------------------------------
  31. PointerArray*
  32. PA_CreateArray()
  33. {
  34. PointerArray* pNewArray;
  35. pNewArray = HEAP_ALLOC(HEAP_ZERO_MEMORY,
  36. sizeof(PointerArray),
  37. ALLOC_TAG_DX(5));
  38. if (!pNewArray)
  39. {
  40. DISPDBG((ERRLVL,"ERROR: PointerArray allocation failed"));
  41. return NULL;
  42. }
  43. // Explicit initialization
  44. pNewArray->pPointers = NULL;
  45. pNewArray->dwNumPointers = 0;
  46. pNewArray->pfnDestroyCallback = NULL;
  47. return pNewArray;
  48. } // PA_CreateArray
  49. //-----------------------------------------------------------------------------
  50. //
  51. // PA_SetDataDestroyCallback
  52. //
  53. // Records the data pointer destroy callback.
  54. //
  55. //-----------------------------------------------------------------------------
  56. void
  57. PA_SetDataDestroyCallback(
  58. PointerArray* pArray,
  59. PA_DestroyCB DestroyCallback)
  60. {
  61. pArray->pfnDestroyCallback = DestroyCallback;
  62. } // PA_SetDataDestroyCallback
  63. //-----------------------------------------------------------------------------
  64. //
  65. // PA_DestroyArray
  66. //
  67. // Destroys all the pointers in the array. Optionally calls a callback with
  68. // each pointer to allow clients to free objects associated with the pointer
  69. //-----------------------------------------------------------------------------
  70. BOOL
  71. PA_DestroyArray(PointerArray* pArray, VOID *pExtra)
  72. {
  73. if (pArray != NULL)
  74. {
  75. if (pArray->pPointers != NULL)
  76. {
  77. DWORD dwCount;
  78. // If there is a registered destroy callback, call it for every
  79. // non-null data pointer
  80. if (pArray->pfnDestroyCallback != NULL)
  81. {
  82. for (dwCount = 0; dwCount < pArray->dwNumPointers; dwCount++)
  83. {
  84. if (pArray->pPointers[dwCount] != 0)
  85. {
  86. // Call the data destroy callback
  87. pArray->pfnDestroyCallback(
  88. pArray,
  89. (void*)pArray->pPointers[dwCount],
  90. pExtra);
  91. }
  92. }
  93. }
  94. // Free the Array of Pointers
  95. HEAP_FREE(pArray->pPointers);
  96. pArray->pPointers = NULL;
  97. }
  98. // Free the pointer array
  99. HEAP_FREE(pArray);
  100. }
  101. return TRUE;
  102. } // PA_DestroyArray
  103. //-----------------------------------------------------------------------------
  104. //
  105. // PA_GetEntry
  106. //
  107. // Look up the Pointer in the array an return it
  108. //
  109. //-----------------------------------------------------------------------------
  110. void*
  111. PA_GetEntry(PointerArray* pArray, DWORD dwNum)
  112. {
  113. ASSERTDD((pArray != NULL), "ERROR: Bad Pointer array!");
  114. if ((pArray->dwNumPointers == 0) ||
  115. (dwNum > (pArray->dwNumPointers - 1)) )
  116. {
  117. // We will be getting called frequently by D3DCreateSurfaceEx for
  118. // handles which might not be initialized so this will be hit often
  119. DISPDBG((DBGLVL,"PA_GetEntry: Ptr outside of range (usually OK)"));
  120. return NULL;
  121. }
  122. return (void*)pArray->pPointers[dwNum];
  123. } // PA_GetEntry
  124. //-----------------------------------------------------------------------------
  125. //
  126. // PA_SetEntry
  127. //
  128. // Sets an entry in the array of pointers. If the entry is larger than
  129. // the array, the array is grown to accomodate it. Returns FALSE if we
  130. // fail to set the data for any reason (mainly out of memory).
  131. //
  132. //-----------------------------------------------------------------------------
  133. BOOL
  134. PA_SetEntry(
  135. PointerArray* pArray,
  136. DWORD dwNum,
  137. void* pData)
  138. {
  139. ASSERTDD(pArray != NULL, "Bad pointer array");
  140. if ( (dwNum + 1 ) > pArray->dwNumPointers )
  141. {
  142. ULONG_PTR* pNewArray;
  143. DWORD dwNewArrayLength, dwNewArraySize;
  144. //
  145. // The array either already exists and has to be grown in size
  146. // or doesnt exist at all
  147. //
  148. DISPDBG((DBGLVL, "Expanding/creating pointer array"));
  149. dwNewArrayLength = (dwNum * 2) + 1; // Tunable heuristic
  150. // ask for double of the space
  151. // needed for the new element
  152. dwNewArraySize = dwNewArrayLength * sizeof(ULONG_PTR);
  153. pNewArray = (ULONG_PTR*)HEAP_ALLOC(HEAP_ZERO_MEMORY,
  154. dwNewArraySize,
  155. ALLOC_TAG_DX(7));
  156. if (pNewArray == NULL)
  157. {
  158. DISPDBG((DBGLVL,"ERROR: Failed to allocate new Pointer array!!"));
  159. return FALSE;
  160. }
  161. if (pArray->pPointers != NULL)
  162. {
  163. // We had an old valid array before this, so we need to transfer
  164. // old array elements into the new array and destroy the old array
  165. memcpy( pNewArray,
  166. pArray->pPointers,
  167. (pArray->dwNumPointers * sizeof(ULONG_PTR)) );
  168. HEAP_FREE(pArray->pPointers);
  169. }
  170. // Update our pointer to the array and its size info
  171. pArray->pPointers = pNewArray;
  172. pArray->dwNumPointers = dwNewArrayLength;
  173. }
  174. pArray->pPointers[dwNum] = (ULONG_PTR)pData;
  175. return TRUE;
  176. } // PA_SetEntry
  177. //----------------------------------------------------------------------------
  178. //********************** H A S H S T R U C T U R E *********************
  179. //----------------------------------------------------------------------------
  180. // Manages a hash table
  181. // Each slot contains front and back pointers, a handle, and an app-specific
  182. // data pointer. Entries are the things that the clients add/remove
  183. // Slots are the internal data chunks that are managed as part of the hash table
  184. //-----------------------------------------------------------------------------
  185. //
  186. // HT_CreateHashTable
  187. //
  188. //-----------------------------------------------------------------------------
  189. HashTable*
  190. HT_CreateHashTable()
  191. {
  192. HashTable* pHashTable;
  193. DISPDBG((DBGLVL,"In HT_CreateHashTable"));
  194. pHashTable = (HashTable*)HEAP_ALLOC(HEAP_ZERO_MEMORY,
  195. sizeof(HashTable),
  196. ALLOC_TAG_DX(8));
  197. if (pHashTable == NULL)
  198. {
  199. DISPDBG((DBGLVL,"Hash table alloc failed!"));
  200. return NULL;
  201. }
  202. return pHashTable;
  203. } // HT_CreateHashTable
  204. //-----------------------------------------------------------------------------
  205. //
  206. // HT_SetDataDestroyCallback
  207. //
  208. //-----------------------------------------------------------------------------
  209. void
  210. HT_SetDataDestroyCallback(
  211. HashTable* pHashTable,
  212. DataDestroyCB DestroyCallback)
  213. {
  214. DISPDBG((DBGLVL,"In HT_SetDataDestroyCallback"));
  215. ASSERTDD(pHashTable != NULL,"ERROR: HashTable passed in is not valid!");
  216. pHashTable->pfnDestroyCallback = DestroyCallback;
  217. } // HT_SetDataDestroyCallback
  218. //-----------------------------------------------------------------------------
  219. //
  220. // HT_ClearEntriesHashTable
  221. //
  222. //-----------------------------------------------------------------------------
  223. void
  224. HT_ClearEntriesHashTable(HashTable* pHashTable, VOID* pExtra)
  225. {
  226. int i;
  227. HashSlot* pHashSlot = NULL;
  228. DISPDBG((DBGLVL,"In HT_ClearEntriesHashTable"));
  229. ASSERTDD(pHashTable != NULL,"ERROR: HashTable passed in is not valid!");
  230. for (i = 0; i < HASH_SIZE; i++)
  231. {
  232. while (pHashSlot = pHashTable->Slots[i])
  233. {
  234. HT_RemoveEntry(pHashTable, pHashSlot->dwHandle, pExtra);
  235. }
  236. pHashTable->Slots[i] = NULL;
  237. }
  238. } // HT_ClearEntriesHashTable
  239. //-----------------------------------------------------------------------------
  240. //
  241. // HT_DestroyHashTable
  242. //
  243. //-----------------------------------------------------------------------------
  244. void
  245. HT_DestroyHashTable(HashTable* pHashTable, VOID* pExtra)
  246. {
  247. HT_ClearEntriesHashTable(pHashTable, pExtra);
  248. HEAP_FREE(pHashTable);
  249. } // HT_DestroyHashTable
  250. //-----------------------------------------------------------------------------
  251. //
  252. // vBOOL HT_AddEntry
  253. //
  254. //-----------------------------------------------------------------------------
  255. BOOL HT_AddEntry(HashTable* pTable, ULONG_PTR dwHandle, void* pData)
  256. {
  257. HashSlot* pHashSlot = NULL;
  258. DISPDBG((DBGLVL,"In HT_AddEntry"));
  259. ASSERTDD(pTable != NULL,"ERROR: HashTable passed in is not valid!");
  260. pHashSlot = HEAP_ALLOC(HEAP_ZERO_MEMORY,
  261. sizeof(HashSlot),
  262. ALLOC_TAG_DX(9));
  263. if (pHashSlot == NULL)
  264. {
  265. DISPDBG((ERRLVL,"Hash entry alloc failed!"));
  266. return FALSE;
  267. }
  268. // Sew this new entry into the hash table
  269. if (pTable->Slots[HT_HASH_OF(dwHandle)])
  270. {
  271. pTable->Slots[HT_HASH_OF(dwHandle)]->pPrev = pHashSlot;
  272. }
  273. // Carry on a next pointer
  274. pHashSlot->pNext = pTable->Slots[HT_HASH_OF(dwHandle)];
  275. pHashSlot->pPrev = NULL;
  276. // Remember the app-supplied data and the handle
  277. pHashSlot->pData = pData;
  278. pHashSlot->dwHandle = dwHandle;
  279. // hash table refers to this one now.
  280. pTable->Slots[HT_HASH_OF(dwHandle)] = pHashSlot;
  281. return TRUE;
  282. } // HT_AddEntry
  283. //-----------------------------------------------------------------------------
  284. //
  285. // BOOL HT_RemoveEntry
  286. //
  287. //-----------------------------------------------------------------------------
  288. BOOL HT_RemoveEntry(HashTable* pTable, ULONG_PTR dwHandle, VOID *pExtra)
  289. {
  290. HashSlot* pSlot = HT_GetSlotFromHandle(pTable, dwHandle);
  291. DISPDBG((DBGLVL,"In HT_RemoveEntry"));
  292. ASSERTDD(pTable != NULL,"ERROR: HashTable passed in is not valid!");
  293. if (pSlot == NULL)
  294. {
  295. DISPDBG((WRNLVL,"WARNING: Hash entry does not exist"));
  296. return FALSE;
  297. }
  298. // Mark the entry as gone from the hash table if it is at the front
  299. if (pTable->Slots[HT_HASH_OF(dwHandle)]->dwHandle == pSlot->dwHandle)
  300. {
  301. pTable->Slots[HT_HASH_OF(dwHandle)] =
  302. pTable->Slots[HT_HASH_OF(dwHandle)]->pNext;
  303. }
  304. // and sew the list back together.
  305. if (pSlot->pPrev)
  306. {
  307. pSlot->pPrev->pNext = pSlot->pNext;
  308. }
  309. if (pSlot->pNext)
  310. {
  311. pSlot->pNext->pPrev = pSlot->pPrev;
  312. }
  313. // If the destroy data callback is setup, call it.
  314. if ((pSlot->pData != NULL) && (pTable->pfnDestroyCallback))
  315. {
  316. DISPDBG((WRNLVL,"Calling DestroyCallback for undestroyed data"));
  317. pTable->pfnDestroyCallback(pTable, pSlot->pData, pExtra);
  318. }
  319. // Free the memory associated with the slot
  320. HEAP_FREE(pSlot);
  321. return TRUE;
  322. } // HT_RemoveEntry
  323. //-----------------------------------------------------------------------------
  324. //
  325. // BOOL HT_SwapEntries
  326. //
  327. //-----------------------------------------------------------------------------
  328. BOOL HT_SwapEntries(HashTable* pTable, DWORD dwHandle1, DWORD dwHandle2)
  329. {
  330. HashSlot* pEntry1;
  331. HashSlot* pEntry2;
  332. void* pDataTemp;
  333. ASSERTDD(pTable != NULL,"ERROR: HashTable passed in is not valid!");
  334. pEntry1 = HT_GetSlotFromHandle(pTable, dwHandle1);
  335. pEntry2 = HT_GetSlotFromHandle(pTable, dwHandle2);
  336. // The handle remains the same, the pointers to the actual data are swapped
  337. if (pEntry1 && pEntry2)
  338. {
  339. pDataTemp = pEntry1->pData;
  340. pEntry1->pData = pEntry2->pData;
  341. pEntry2->pData = pDataTemp;
  342. return TRUE;
  343. }
  344. DISPDBG((ERRLVL,"ERROR: Swapped entries are invalid!"));
  345. return FALSE;
  346. } // HT_SwapEntries