/drivers/gpu/pvr/handle.c

https://bitbucket.org/wisechild/galaxy-nexus · C · 1873 lines · 1391 code · 457 blank · 25 comment · 287 complexity · b19747385e728bc71f9a33a3ac83ecdf MD5 · raw file

  1. /**********************************************************************
  2. *
  3. * Copyright (C) Imagination Technologies Ltd. All rights reserved.
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms and conditions of the GNU General Public License,
  7. * version 2, as published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope it will be useful but, except
  10. * as otherwise stated in writing, without any warranty; without even the
  11. * implied warranty of merchantability or fitness for a particular purpose.
  12. * See the GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along with
  15. * this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  17. *
  18. * The full GNU General Public License is included in this distribution in
  19. * the file called "COPYING".
  20. *
  21. * Contact Information:
  22. * Imagination Technologies Ltd. <gpl-support@imgtec.com>
  23. * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
  24. *
  25. ******************************************************************************/
  26. #if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
  27. #include <stddef.h>
  28. #include "services_headers.h"
  29. #include "handle.h"
  30. #ifdef DEBUG
  31. #define HANDLE_BLOCK_SHIFT 2
  32. #else
  33. #define HANDLE_BLOCK_SHIFT 8
  34. #endif
  35. #define DIVIDE_BY_BLOCK_SIZE(i) (((IMG_UINT32)(i)) >> HANDLE_BLOCK_SHIFT)
  36. #define MULTIPLY_BY_BLOCK_SIZE(i) (((IMG_UINT32)(i)) << HANDLE_BLOCK_SHIFT)
  37. #define HANDLE_BLOCK_SIZE MULTIPLY_BY_BLOCK_SIZE(1)
  38. #define HANDLE_SUB_BLOCK_MASK (HANDLE_BLOCK_SIZE - 1)
  39. #define HANDLE_BLOCK_MASK (~(HANDLE_SUB_BLOCK_MASK))
  40. #define HANDLE_HASH_TAB_INIT_SIZE 32
  41. #define INDEX_IS_VALID(psBase, i) ((i) < (psBase)->ui32TotalHandCount)
  42. #if defined (SUPPORT_SID_INTERFACE)
  43. #define INDEX_TO_HANDLE(i) ((IMG_SID)((i) + 1))
  44. #define HANDLE_TO_INDEX(h) ((IMG_UINT32)(h) - 1)
  45. #else
  46. #define INDEX_TO_HANDLE(i) ((IMG_HANDLE)((IMG_UINTPTR_T)(i) + 1))
  47. #define HANDLE_TO_INDEX(h) ((IMG_UINT32)(IMG_UINTPTR_T)(h) - 1)
  48. #endif
  49. #define INDEX_TO_BLOCK_INDEX(i) DIVIDE_BY_BLOCK_SIZE(i)
  50. #define BLOCK_INDEX_TO_INDEX(i) MULTIPLY_BY_BLOCK_SIZE(i)
  51. #define INDEX_TO_SUB_BLOCK_INDEX(i) ((i) & HANDLE_SUB_BLOCK_MASK)
  52. #define INDEX_TO_INDEX_STRUCT_PTR(psArray, i) (&((psArray)[INDEX_TO_BLOCK_INDEX(i)]))
  53. #define BASE_AND_INDEX_TO_INDEX_STRUCT_PTR(psBase, i) INDEX_TO_INDEX_STRUCT_PTR((psBase)->psHandleArray, i)
  54. #define INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, i) (BASE_AND_INDEX_TO_INDEX_STRUCT_PTR(psBase, i)->ui32FreeHandBlockCount)
  55. #define INDEX_TO_HANDLE_STRUCT_PTR(psBase, i) (BASE_AND_INDEX_TO_INDEX_STRUCT_PTR(psBase, i)->psHandle + INDEX_TO_SUB_BLOCK_INDEX(i))
  56. #define HANDLE_TO_HANDLE_STRUCT_PTR(psBase, h) (INDEX_TO_HANDLE_STRUCT_PTR(psBase, HANDLE_TO_INDEX(h)))
  57. #define HANDLE_PTR_TO_INDEX(psHandle) ((psHandle)->ui32Index)
  58. #define HANDLE_PTR_TO_HANDLE(psHandle) INDEX_TO_HANDLE(HANDLE_PTR_TO_INDEX(psHandle))
  59. #define ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(a) (HANDLE_BLOCK_MASK & (a))
  60. #define ROUND_UP_TO_MULTIPLE_OF_BLOCK_SIZE(a) ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE((a) + HANDLE_BLOCK_SIZE - 1)
  61. #define DEFAULT_MAX_HANDLE 0x7fffffffu
  62. #define DEFAULT_MAX_INDEX_PLUS_ONE ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(DEFAULT_MAX_HANDLE)
  63. #define HANDLES_BATCHED(psBase) ((psBase)->ui32HandBatchSize != 0)
  64. #define HANDLE_ARRAY_SIZE(handleCount) DIVIDE_BY_BLOCK_SIZE(ROUND_UP_TO_MULTIPLE_OF_BLOCK_SIZE(handleCount))
  65. #define SET_FLAG(v, f) ((IMG_VOID)((v) |= (f)))
  66. #define CLEAR_FLAG(v, f) ((IMG_VOID)((v) &= ~(f)))
  67. #define TEST_FLAG(v, f) ((IMG_BOOL)(((v) & (f)) != 0))
  68. #define TEST_ALLOC_FLAG(psHandle, f) TEST_FLAG((psHandle)->eFlag, f)
  69. #define SET_INTERNAL_FLAG(psHandle, f) SET_FLAG((psHandle)->eInternalFlag, f)
  70. #define CLEAR_INTERNAL_FLAG(psHandle, f) CLEAR_FLAG((psHandle)->eInternalFlag, f)
  71. #define TEST_INTERNAL_FLAG(psHandle, f) TEST_FLAG((psHandle)->eInternalFlag, f)
  72. #define BATCHED_HANDLE(psHandle) TEST_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
  73. #define SET_BATCHED_HANDLE(psHandle) SET_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
  74. #define SET_UNBATCHED_HANDLE(psHandle) CLEAR_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
  75. #define BATCHED_HANDLE_PARTIALLY_FREE(psHandle) TEST_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE)
  76. #define SET_BATCHED_HANDLE_PARTIALLY_FREE(psHandle) SET_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE)
  77. #define HANDLE_STRUCT_IS_FREE(psHandle) ((psHandle)->eType == PVRSRV_HANDLE_TYPE_NONE && (psHandle)->eInternalFlag == INTERNAL_HANDLE_FLAG_NONE)
  78. #ifdef MIN
  79. #undef MIN
  80. #endif
  81. #define MIN(x, y) (((x) < (y)) ? (x) : (y))
  82. struct sHandleList
  83. {
  84. IMG_UINT32 ui32Prev;
  85. IMG_UINT32 ui32Next;
  86. #if defined (SUPPORT_SID_INTERFACE)
  87. IMG_SID hParent;
  88. #else
  89. IMG_HANDLE hParent;
  90. #endif
  91. };
  92. enum ePVRSRVInternalHandleFlag
  93. {
  94. INTERNAL_HANDLE_FLAG_NONE = 0x00,
  95. INTERNAL_HANDLE_FLAG_BATCHED = 0x01,
  96. INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE = 0x02,
  97. };
  98. struct sHandle
  99. {
  100. PVRSRV_HANDLE_TYPE eType;
  101. IMG_VOID *pvData;
  102. IMG_UINT32 ui32NextIndexPlusOne;
  103. enum ePVRSRVInternalHandleFlag eInternalFlag;
  104. PVRSRV_HANDLE_ALLOC_FLAG eFlag;
  105. IMG_UINT32 ui32Index;
  106. struct sHandleList sChildren;
  107. struct sHandleList sSiblings;
  108. };
  109. struct sHandleIndex
  110. {
  111. struct sHandle *psHandle;
  112. IMG_HANDLE hBlockAlloc;
  113. IMG_UINT32 ui32FreeHandBlockCount;
  114. };
  115. struct _PVRSRV_HANDLE_BASE_
  116. {
  117. IMG_HANDLE hBaseBlockAlloc;
  118. IMG_HANDLE hArrayBlockAlloc;
  119. struct sHandleIndex *psHandleArray;
  120. HASH_TABLE *psHashTab;
  121. IMG_UINT32 ui32FreeHandCount;
  122. IMG_UINT32 ui32FirstFreeIndex;
  123. IMG_UINT32 ui32MaxIndexPlusOne;
  124. IMG_UINT32 ui32TotalHandCount;
  125. IMG_UINT32 ui32LastFreeIndexPlusOne;
  126. IMG_UINT32 ui32HandBatchSize;
  127. IMG_UINT32 ui32TotalHandCountPreBatch;
  128. IMG_UINT32 ui32FirstBatchIndexPlusOne;
  129. IMG_UINT32 ui32BatchHandAllocFailures;
  130. IMG_BOOL bPurgingEnabled;
  131. };
  132. enum eHandKey {
  133. HAND_KEY_DATA = 0,
  134. HAND_KEY_TYPE,
  135. HAND_KEY_PARENT,
  136. HAND_KEY_LEN
  137. };
  138. PVRSRV_HANDLE_BASE *gpsKernelHandleBase = IMG_NULL;
  139. typedef IMG_UINTPTR_T HAND_KEY[HAND_KEY_LEN];
  140. #ifdef INLINE_IS_PRAGMA
  141. #pragma inline(HandleListInit)
  142. #endif
  143. static INLINE
  144. #if defined (SUPPORT_SID_INTERFACE)
  145. IMG_VOID HandleListInit(IMG_UINT32 ui32Index, struct sHandleList *psList, IMG_SID hParent)
  146. #else
  147. IMG_VOID HandleListInit(IMG_UINT32 ui32Index, struct sHandleList *psList, IMG_HANDLE hParent)
  148. #endif
  149. {
  150. psList->ui32Next = ui32Index;
  151. psList->ui32Prev = ui32Index;
  152. psList->hParent = hParent;
  153. }
  154. #ifdef INLINE_IS_PRAGMA
  155. #pragma inline(InitParentList)
  156. #endif
  157. static INLINE
  158. IMG_VOID InitParentList(struct sHandle *psHandle)
  159. {
  160. IMG_UINT32 ui32Parent = HANDLE_PTR_TO_INDEX(psHandle);
  161. HandleListInit(ui32Parent, &psHandle->sChildren, INDEX_TO_HANDLE(ui32Parent));
  162. }
  163. #ifdef INLINE_IS_PRAGMA
  164. #pragma inline(InitChildEntry)
  165. #endif
  166. static INLINE
  167. IMG_VOID InitChildEntry(struct sHandle *psHandle)
  168. {
  169. HandleListInit(HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sSiblings, IMG_NULL);
  170. }
  171. #ifdef INLINE_IS_PRAGMA
  172. #pragma inline(HandleListIsEmpty)
  173. #endif
  174. static INLINE
  175. IMG_BOOL HandleListIsEmpty(IMG_UINT32 ui32Index, struct sHandleList *psList)
  176. {
  177. IMG_BOOL bIsEmpty;
  178. bIsEmpty = (IMG_BOOL)(psList->ui32Next == ui32Index);
  179. #ifdef DEBUG
  180. {
  181. IMG_BOOL bIsEmpty2;
  182. bIsEmpty2 = (IMG_BOOL)(psList->ui32Prev == ui32Index);
  183. PVR_ASSERT(bIsEmpty == bIsEmpty2)
  184. }
  185. #endif
  186. return bIsEmpty;
  187. }
  188. #ifdef DEBUG
  189. #ifdef INLINE_IS_PRAGMA
  190. #pragma inline(NoChildren)
  191. #endif
  192. static INLINE
  193. IMG_BOOL NoChildren(struct sHandle *psHandle)
  194. {
  195. PVR_ASSERT(psHandle->sChildren.hParent == HANDLE_PTR_TO_HANDLE(psHandle))
  196. return HandleListIsEmpty(HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sChildren);
  197. }
  198. #ifdef INLINE_IS_PRAGMA
  199. #pragma inline(NoParent)
  200. #endif
  201. static INLINE
  202. IMG_BOOL NoParent(struct sHandle *psHandle)
  203. {
  204. if (HandleListIsEmpty(HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sSiblings))
  205. {
  206. PVR_ASSERT(psHandle->sSiblings.hParent == IMG_NULL)
  207. return IMG_TRUE;
  208. }
  209. else
  210. {
  211. PVR_ASSERT(psHandle->sSiblings.hParent != IMG_NULL)
  212. }
  213. return IMG_FALSE;
  214. }
  215. #endif
  216. #ifdef INLINE_IS_PRAGMA
  217. #pragma inline(ParentHandle)
  218. #endif
  219. static INLINE
  220. #if defined (SUPPORT_SID_INTERFACE)
  221. IMG_SID ParentHandle(struct sHandle *psHandle)
  222. #else
  223. IMG_HANDLE ParentHandle(struct sHandle *psHandle)
  224. #endif
  225. {
  226. return psHandle->sSiblings.hParent;
  227. }
  228. #define LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, i, p, po, eo) \
  229. ((struct sHandleList *)((IMG_CHAR *)(INDEX_TO_HANDLE_STRUCT_PTR(psBase, i)) + (((i) == (p)) ? (po) : (eo))))
  230. #ifdef INLINE_IS_PRAGMA
  231. #pragma inline(HandleListInsertBefore)
  232. #endif
  233. static INLINE
  234. IMG_VOID HandleListInsertBefore(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32InsIndex, struct sHandleList *psIns, IMG_SIZE_T uiParentOffset, IMG_UINT32 ui32EntryIndex, struct sHandleList *psEntry, IMG_SIZE_T uiEntryOffset, IMG_UINT32 ui32ParentIndex)
  235. {
  236. struct sHandleList *psPrevIns = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psIns->ui32Prev, ui32ParentIndex, uiParentOffset, uiEntryOffset);
  237. PVR_ASSERT(psEntry->hParent == IMG_NULL)
  238. PVR_ASSERT(ui32InsIndex == psPrevIns->ui32Next)
  239. PVR_ASSERT(LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32ParentIndex, ui32ParentIndex, uiParentOffset, uiParentOffset)->hParent == INDEX_TO_HANDLE(ui32ParentIndex))
  240. psEntry->ui32Prev = psIns->ui32Prev;
  241. psIns->ui32Prev = ui32EntryIndex;
  242. psEntry->ui32Next = ui32InsIndex;
  243. psPrevIns->ui32Next = ui32EntryIndex;
  244. psEntry->hParent = INDEX_TO_HANDLE(ui32ParentIndex);
  245. }
  246. #ifdef INLINE_IS_PRAGMA
  247. #pragma inline(AdoptChild)
  248. #endif
  249. static INLINE
  250. IMG_VOID AdoptChild(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psParent, struct sHandle *psChild)
  251. {
  252. IMG_UINT32 ui32Parent = HANDLE_TO_INDEX(psParent->sChildren.hParent);
  253. PVR_ASSERT(ui32Parent == HANDLE_PTR_TO_INDEX(psParent))
  254. HandleListInsertBefore(psBase, ui32Parent, &psParent->sChildren, offsetof(struct sHandle, sChildren), HANDLE_PTR_TO_INDEX(psChild), &psChild->sSiblings, offsetof(struct sHandle, sSiblings), ui32Parent);
  255. }
  256. #ifdef INLINE_IS_PRAGMA
  257. #pragma inline(HandleListRemove)
  258. #endif
  259. static INLINE
  260. IMG_VOID HandleListRemove(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32EntryIndex, struct sHandleList *psEntry, IMG_SIZE_T uiEntryOffset, IMG_SIZE_T uiParentOffset)
  261. {
  262. if (!HandleListIsEmpty(ui32EntryIndex, psEntry))
  263. {
  264. struct sHandleList *psPrev = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Prev, HANDLE_TO_INDEX(psEntry->hParent), uiParentOffset, uiEntryOffset);
  265. struct sHandleList *psNext = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Next, HANDLE_TO_INDEX(psEntry->hParent), uiParentOffset, uiEntryOffset);
  266. PVR_ASSERT(psEntry->hParent != IMG_NULL)
  267. psPrev->ui32Next = psEntry->ui32Next;
  268. psNext->ui32Prev = psEntry->ui32Prev;
  269. HandleListInit(ui32EntryIndex, psEntry, IMG_NULL);
  270. }
  271. }
  272. #ifdef INLINE_IS_PRAGMA
  273. #pragma inline(UnlinkFromParent)
  274. #endif
  275. static INLINE
  276. IMG_VOID UnlinkFromParent(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
  277. {
  278. HandleListRemove(psBase, HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sSiblings, offsetof(struct sHandle, sSiblings), offsetof(struct sHandle, sChildren));
  279. }
  280. #ifdef INLINE_IS_PRAGMA
  281. #pragma inline(HandleListIterate)
  282. #endif
  283. static INLINE
  284. PVRSRV_ERROR HandleListIterate(PVRSRV_HANDLE_BASE *psBase, struct sHandleList *psHead, IMG_SIZE_T uiParentOffset, IMG_SIZE_T uiEntryOffset, PVRSRV_ERROR (*pfnIterFunc)(PVRSRV_HANDLE_BASE *, struct sHandle *))
  285. {
  286. IMG_UINT32 ui32Index;
  287. IMG_UINT32 ui32Parent = HANDLE_TO_INDEX(psHead->hParent);
  288. PVR_ASSERT(psHead->hParent != IMG_NULL)
  289. for(ui32Index = psHead->ui32Next; ui32Index != ui32Parent; )
  290. {
  291. struct sHandle *psHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32Index);
  292. struct sHandleList *psEntry = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32Index, ui32Parent, uiParentOffset, uiEntryOffset);
  293. PVRSRV_ERROR eError;
  294. PVR_ASSERT(psEntry->hParent == psHead->hParent)
  295. ui32Index = psEntry->ui32Next;
  296. eError = (*pfnIterFunc)(psBase, psHandle);
  297. if (eError != PVRSRV_OK)
  298. {
  299. return eError;
  300. }
  301. }
  302. return PVRSRV_OK;
  303. }
  304. #ifdef INLINE_IS_PRAGMA
  305. #pragma inline(IterateOverChildren)
  306. #endif
  307. static INLINE
  308. PVRSRV_ERROR IterateOverChildren(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psParent, PVRSRV_ERROR (*pfnIterFunc)(PVRSRV_HANDLE_BASE *, struct sHandle *))
  309. {
  310. return HandleListIterate(psBase, &psParent->sChildren, offsetof(struct sHandle, sChildren), offsetof(struct sHandle, sSiblings), pfnIterFunc);
  311. }
  312. #ifdef INLINE_IS_PRAGMA
  313. #pragma inline(GetHandleStructure)
  314. #endif
  315. static INLINE
  316. #if defined (SUPPORT_SID_INTERFACE)
  317. PVRSRV_ERROR GetHandleStructure(PVRSRV_HANDLE_BASE *psBase, struct sHandle **ppsHandle, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType)
  318. #else
  319. PVRSRV_ERROR GetHandleStructure(PVRSRV_HANDLE_BASE *psBase, struct sHandle **ppsHandle, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
  320. #endif
  321. {
  322. IMG_UINT32 ui32Index = HANDLE_TO_INDEX(hHandle);
  323. struct sHandle *psHandle;
  324. if (!INDEX_IS_VALID(psBase, ui32Index))
  325. {
  326. PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle index out of range (%u >= %u)", ui32Index, psBase->ui32TotalHandCount));
  327. #if defined (SUPPORT_SID_INTERFACE)
  328. PVR_DBG_BREAK
  329. #endif
  330. return PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE;
  331. }
  332. psHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32Index);
  333. if (psHandle->eType == PVRSRV_HANDLE_TYPE_NONE)
  334. {
  335. PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle not allocated (index: %u)", ui32Index));
  336. #if defined (SUPPORT_SID_INTERFACE)
  337. PVR_DBG_BREAK
  338. #endif
  339. return PVRSRV_ERROR_HANDLE_NOT_ALLOCATED;
  340. }
  341. if (eType != PVRSRV_HANDLE_TYPE_NONE && eType != psHandle->eType)
  342. {
  343. PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle type mismatch (%d != %d)", eType, psHandle->eType));
  344. #if defined (SUPPORT_SID_INTERFACE)
  345. PVR_DBG_BREAK
  346. #endif
  347. return PVRSRV_ERROR_HANDLE_TYPE_MISMATCH;
  348. }
  349. *ppsHandle = psHandle;
  350. return PVRSRV_OK;
  351. }
  352. #ifdef INLINE_IS_PRAGMA
  353. #pragma inline(ParentIfPrivate)
  354. #endif
  355. static INLINE
  356. #if defined (SUPPORT_SID_INTERFACE)
  357. IMG_SID ParentIfPrivate(struct sHandle *psHandle)
  358. #else
  359. IMG_HANDLE ParentIfPrivate(struct sHandle *psHandle)
  360. #endif
  361. {
  362. return TEST_ALLOC_FLAG(psHandle, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ?
  363. ParentHandle(psHandle) : IMG_NULL;
  364. }
  365. #ifdef INLINE_IS_PRAGMA
  366. #pragma inline(InitKey)
  367. #endif
  368. static INLINE
  369. #if defined (SUPPORT_SID_INTERFACE)
  370. IMG_VOID InitKey(HAND_KEY aKey, PVRSRV_HANDLE_BASE *psBase, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, IMG_SID hParent)
  371. #else
  372. IMG_VOID InitKey(HAND_KEY aKey, PVRSRV_HANDLE_BASE *psBase, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hParent)
  373. #endif
  374. {
  375. PVR_UNREFERENCED_PARAMETER(psBase);
  376. aKey[HAND_KEY_DATA] = (IMG_UINTPTR_T)pvData;
  377. aKey[HAND_KEY_TYPE] = (IMG_UINTPTR_T)eType;
  378. aKey[HAND_KEY_PARENT] = (IMG_UINTPTR_T)hParent;
  379. }
  380. static
  381. PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCount)
  382. {
  383. struct sHandleIndex *psOldArray = psBase->psHandleArray;
  384. IMG_HANDLE hOldArrayBlockAlloc = psBase->hArrayBlockAlloc;
  385. IMG_UINT32 ui32OldCount = psBase->ui32TotalHandCount;
  386. struct sHandleIndex *psNewArray = IMG_NULL;
  387. IMG_HANDLE hNewArrayBlockAlloc = IMG_NULL;
  388. PVRSRV_ERROR eError;
  389. PVRSRV_ERROR eReturn = PVRSRV_OK;
  390. IMG_UINT32 ui32Index;
  391. if (ui32NewCount == ui32OldCount)
  392. {
  393. return PVRSRV_OK;
  394. }
  395. if (ui32NewCount != 0 && !psBase->bPurgingEnabled &&
  396. ui32NewCount < ui32OldCount)
  397. {
  398. return PVRSRV_ERROR_INVALID_PARAMS;
  399. }
  400. if (((ui32OldCount % HANDLE_BLOCK_SIZE) != 0) ||
  401. ((ui32NewCount % HANDLE_BLOCK_SIZE) != 0))
  402. {
  403. PVR_ASSERT((ui32OldCount % HANDLE_BLOCK_SIZE) == 0)
  404. PVR_ASSERT((ui32NewCount % HANDLE_BLOCK_SIZE) == 0)
  405. return PVRSRV_ERROR_INVALID_PARAMS;
  406. }
  407. if (ui32NewCount != 0)
  408. {
  409. eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
  410. HANDLE_ARRAY_SIZE(ui32NewCount) * sizeof(struct sHandleIndex),
  411. (IMG_VOID **)&psNewArray,
  412. &hNewArrayBlockAlloc,
  413. "Memory Area");
  414. if (eError != PVRSRV_OK)
  415. {
  416. PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't allocate new handle array (%d)", eError));
  417. eReturn = eError;
  418. goto error;
  419. }
  420. if (ui32OldCount != 0)
  421. {
  422. OSMemCopy(psNewArray, psOldArray, HANDLE_ARRAY_SIZE(MIN(ui32NewCount, ui32OldCount)) * sizeof(struct sHandleIndex));
  423. }
  424. }
  425. for(ui32Index = ui32NewCount; ui32Index < ui32OldCount; ui32Index += HANDLE_BLOCK_SIZE)
  426. {
  427. struct sHandleIndex *psIndex = INDEX_TO_INDEX_STRUCT_PTR(psOldArray, ui32Index);
  428. eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
  429. sizeof(struct sHandle) * HANDLE_BLOCK_SIZE,
  430. psIndex->psHandle,
  431. psIndex->hBlockAlloc);
  432. if (eError != PVRSRV_OK)
  433. {
  434. PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't free handle structures (%d)", eError));
  435. }
  436. }
  437. for(ui32Index = ui32OldCount; ui32Index < ui32NewCount; ui32Index += HANDLE_BLOCK_SIZE)
  438. {
  439. struct sHandleIndex *psIndex = INDEX_TO_INDEX_STRUCT_PTR(psNewArray, ui32Index);
  440. eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
  441. sizeof(struct sHandle) * HANDLE_BLOCK_SIZE,
  442. (IMG_VOID **)&psIndex->psHandle,
  443. &psIndex->hBlockAlloc,
  444. "Memory Area");
  445. if (eError != PVRSRV_OK)
  446. {
  447. psIndex->psHandle = IMG_NULL;
  448. PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't allocate handle structures (%d)", eError));
  449. eReturn = eError;
  450. }
  451. else
  452. {
  453. IMG_UINT32 ui32SubIndex;
  454. psIndex->ui32FreeHandBlockCount = HANDLE_BLOCK_SIZE;
  455. for(ui32SubIndex = 0; ui32SubIndex < HANDLE_BLOCK_SIZE; ui32SubIndex++)
  456. {
  457. struct sHandle *psHandle = psIndex->psHandle + ui32SubIndex;
  458. psHandle->ui32Index = ui32SubIndex + ui32Index;
  459. psHandle->eType = PVRSRV_HANDLE_TYPE_NONE;
  460. psHandle->eInternalFlag = INTERNAL_HANDLE_FLAG_NONE;
  461. psHandle->ui32NextIndexPlusOne = 0;
  462. }
  463. }
  464. }
  465. if (eReturn != PVRSRV_OK)
  466. {
  467. goto error;
  468. }
  469. #ifdef DEBUG_MAX_HANDLE_COUNT
  470. if (ui32NewCount > DEBUG_MAX_HANDLE_COUNT)
  471. {
  472. PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Max handle count (%u) reached", DEBUG_MAX_HANDLE_COUNT));
  473. eReturn = PVRSRV_ERROR_OUT_OF_MEMORY;
  474. goto error;
  475. }
  476. #endif
  477. if (psOldArray != IMG_NULL)
  478. {
  479. eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
  480. HANDLE_ARRAY_SIZE(ui32OldCount) * sizeof(struct sHandleIndex),
  481. psOldArray,
  482. hOldArrayBlockAlloc);
  483. if (eError != PVRSRV_OK)
  484. {
  485. PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't free old handle array (%d)", eError));
  486. }
  487. }
  488. psBase->psHandleArray = psNewArray;
  489. psBase->hArrayBlockAlloc = hNewArrayBlockAlloc;
  490. psBase->ui32TotalHandCount = ui32NewCount;
  491. if (ui32NewCount > ui32OldCount)
  492. {
  493. PVR_ASSERT(psBase->ui32FreeHandCount + (ui32NewCount - ui32OldCount) > psBase->ui32FreeHandCount)
  494. psBase->ui32FreeHandCount += (ui32NewCount - ui32OldCount);
  495. if (psBase->ui32FirstFreeIndex == 0)
  496. {
  497. PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0)
  498. psBase->ui32FirstFreeIndex = ui32OldCount;
  499. }
  500. else
  501. {
  502. if (!psBase->bPurgingEnabled)
  503. {
  504. PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0)
  505. PVR_ASSERT(INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0)
  506. INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne = ui32OldCount + 1;
  507. }
  508. }
  509. if (!psBase->bPurgingEnabled)
  510. {
  511. psBase->ui32LastFreeIndexPlusOne = ui32NewCount;
  512. }
  513. }
  514. else
  515. {
  516. PVR_ASSERT(ui32NewCount == 0 || psBase->bPurgingEnabled)
  517. PVR_ASSERT(ui32NewCount == 0 || psBase->ui32FirstFreeIndex <= ui32NewCount)
  518. PVR_ASSERT(psBase->ui32FreeHandCount - (ui32OldCount - ui32NewCount) < psBase->ui32FreeHandCount)
  519. psBase->ui32FreeHandCount -= (ui32OldCount - ui32NewCount);
  520. if (ui32NewCount == 0)
  521. {
  522. psBase->ui32FirstFreeIndex = 0;
  523. psBase->ui32LastFreeIndexPlusOne = 0;
  524. }
  525. }
  526. PVR_ASSERT(psBase->ui32FirstFreeIndex <= psBase->ui32TotalHandCount)
  527. return PVRSRV_OK;
  528. error:
  529. PVR_ASSERT(eReturn != PVRSRV_OK)
  530. if (psNewArray != IMG_NULL)
  531. {
  532. for(ui32Index = ui32OldCount; ui32Index < ui32NewCount; ui32Index += HANDLE_BLOCK_SIZE)
  533. {
  534. struct sHandleIndex *psIndex = INDEX_TO_INDEX_STRUCT_PTR(psNewArray, ui32Index);
  535. if (psIndex->psHandle != IMG_NULL)
  536. {
  537. eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
  538. sizeof(struct sHandle) * HANDLE_BLOCK_SIZE,
  539. psIndex->psHandle,
  540. psIndex->hBlockAlloc);
  541. if (eError != PVRSRV_OK)
  542. {
  543. PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't free handle structures (%d)", eError));
  544. }
  545. }
  546. }
  547. eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
  548. HANDLE_ARRAY_SIZE(ui32NewCount) * sizeof(struct sHandleIndex),
  549. psNewArray,
  550. hNewArrayBlockAlloc);
  551. if (eError != PVRSRV_OK)
  552. {
  553. PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't free new handle array (%d)", eError));
  554. }
  555. }
  556. return eReturn;
  557. }
  558. static PVRSRV_ERROR FreeHandleArray(PVRSRV_HANDLE_BASE *psBase)
  559. {
  560. return ReallocHandleArray(psBase, 0);
  561. }
  562. static PVRSRV_ERROR FreeHandle(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
  563. {
  564. HAND_KEY aKey;
  565. IMG_UINT32 ui32Index = HANDLE_PTR_TO_INDEX(psHandle);
  566. PVRSRV_ERROR eError;
  567. InitKey(aKey, psBase, psHandle->pvData, psHandle->eType, ParentIfPrivate(psHandle));
  568. if (!TEST_ALLOC_FLAG(psHandle, PVRSRV_HANDLE_ALLOC_FLAG_MULTI) && !BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
  569. {
  570. #if defined (SUPPORT_SID_INTERFACE)
  571. IMG_SID hHandle;
  572. hHandle = (IMG_SID) HASH_Remove_Extended(psBase->psHashTab, aKey);
  573. #else
  574. IMG_HANDLE hHandle;
  575. hHandle = (IMG_HANDLE) HASH_Remove_Extended(psBase->psHashTab, aKey);
  576. #endif
  577. PVR_ASSERT(hHandle != IMG_NULL)
  578. PVR_ASSERT(hHandle == INDEX_TO_HANDLE(ui32Index))
  579. PVR_UNREFERENCED_PARAMETER(hHandle);
  580. }
  581. UnlinkFromParent(psBase, psHandle);
  582. eError = IterateOverChildren(psBase, psHandle, FreeHandle);
  583. if (eError != PVRSRV_OK)
  584. {
  585. PVR_DPF((PVR_DBG_ERROR, "FreeHandle: Error whilst freeing subhandles (%d)", eError));
  586. return eError;
  587. }
  588. psHandle->eType = PVRSRV_HANDLE_TYPE_NONE;
  589. if (BATCHED_HANDLE(psHandle) && !BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
  590. {
  591. SET_BATCHED_HANDLE_PARTIALLY_FREE(psHandle);
  592. return PVRSRV_OK;
  593. }
  594. if (!psBase->bPurgingEnabled)
  595. {
  596. if (psBase->ui32FreeHandCount == 0)
  597. {
  598. PVR_ASSERT(psBase->ui32FirstFreeIndex == 0)
  599. PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0)
  600. psBase->ui32FirstFreeIndex = ui32Index;
  601. }
  602. else
  603. {
  604. PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0)
  605. PVR_ASSERT(INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0)
  606. INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne = ui32Index + 1;
  607. }
  608. PVR_ASSERT(psHandle->ui32NextIndexPlusOne == 0)
  609. psBase->ui32LastFreeIndexPlusOne = ui32Index + 1;
  610. }
  611. psBase->ui32FreeHandCount++;
  612. INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32Index)++;
  613. PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32Index)<= HANDLE_BLOCK_SIZE)
  614. #ifdef DEBUG
  615. {
  616. IMG_UINT32 ui32BlockedIndex;
  617. IMG_UINT32 ui32FreeHandCount = 0;
  618. for (ui32BlockedIndex = 0; ui32BlockedIndex < psBase->ui32TotalHandCount; ui32BlockedIndex += HANDLE_BLOCK_SIZE)
  619. {
  620. ui32FreeHandCount += INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32BlockedIndex);
  621. }
  622. PVR_ASSERT(ui32FreeHandCount == psBase->ui32FreeHandCount)
  623. }
  624. #endif
  625. return PVRSRV_OK;
  626. }
  627. static PVRSRV_ERROR FreeAllHandles(PVRSRV_HANDLE_BASE *psBase)
  628. {
  629. IMG_UINT32 i;
  630. PVRSRV_ERROR eError = PVRSRV_OK;
  631. if (psBase->ui32FreeHandCount == psBase->ui32TotalHandCount)
  632. {
  633. return eError;
  634. }
  635. for (i = 0; i < psBase->ui32TotalHandCount; i++)
  636. {
  637. struct sHandle *psHandle;
  638. psHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, i);
  639. if (psHandle->eType != PVRSRV_HANDLE_TYPE_NONE)
  640. {
  641. eError = FreeHandle(psBase, psHandle);
  642. if (eError != PVRSRV_OK)
  643. {
  644. PVR_DPF((PVR_DBG_ERROR, "FreeAllHandles: FreeHandle failed (%d)", eError));
  645. break;
  646. }
  647. if (psBase->ui32FreeHandCount == psBase->ui32TotalHandCount)
  648. {
  649. break;
  650. }
  651. }
  652. }
  653. return eError;
  654. }
  655. static PVRSRV_ERROR FreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
  656. {
  657. PVRSRV_ERROR eError;
  658. if (HANDLES_BATCHED(psBase))
  659. {
  660. PVR_DPF((PVR_DBG_WARNING, "FreeHandleBase: Uncommitted/Unreleased handle batch"));
  661. PVRSRVReleaseHandleBatch(psBase);
  662. }
  663. eError = FreeAllHandles(psBase);
  664. if (eError != PVRSRV_OK)
  665. {
  666. PVR_DPF((PVR_DBG_ERROR, "FreeHandleBase: Couldn't free handles (%d)", eError));
  667. return eError;
  668. }
  669. eError = FreeHandleArray(psBase);
  670. if (eError != PVRSRV_OK)
  671. {
  672. PVR_DPF((PVR_DBG_ERROR, "FreeHandleBase: Couldn't free handle array (%d)", eError));
  673. return eError;
  674. }
  675. if (psBase->psHashTab != IMG_NULL)
  676. {
  677. HASH_Delete(psBase->psHashTab);
  678. }
  679. eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
  680. sizeof(*psBase),
  681. psBase,
  682. psBase->hBaseBlockAlloc);
  683. if (eError != PVRSRV_OK)
  684. {
  685. PVR_DPF((PVR_DBG_ERROR, "FreeHandleBase: Couldn't free handle base (%d)", eError));
  686. return eError;
  687. }
  688. return PVRSRV_OK;
  689. }
  690. #ifdef INLINE_IS_PRAGMA
  691. #pragma inline(FindHandle)
  692. #endif
  693. static INLINE
  694. #if defined (SUPPORT_SID_INTERFACE)
  695. IMG_SID FindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, IMG_SID hParent)
  696. #else
  697. IMG_HANDLE FindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hParent)
  698. #endif
  699. {
  700. HAND_KEY aKey;
  701. PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
  702. InitKey(aKey, psBase, pvData, eType, hParent);
  703. #if defined (SUPPORT_SID_INTERFACE)
  704. return (IMG_SID) HASH_Retrieve_Extended(psBase->psHashTab, aKey);
  705. #else
  706. return (IMG_HANDLE) HASH_Retrieve_Extended(psBase->psHashTab, aKey);
  707. #endif
  708. }
  709. static PVRSRV_ERROR IncreaseHandleArraySize(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32Delta)
  710. {
  711. PVRSRV_ERROR eError;
  712. IMG_UINT32 ui32DeltaAdjusted = ROUND_UP_TO_MULTIPLE_OF_BLOCK_SIZE(ui32Delta);
  713. IMG_UINT32 ui32NewTotalHandCount = psBase->ui32TotalHandCount + ui32DeltaAdjusted;
  714. ;
  715. PVR_ASSERT(ui32Delta != 0)
  716. if (ui32NewTotalHandCount > psBase->ui32MaxIndexPlusOne || ui32NewTotalHandCount <= psBase->ui32TotalHandCount)
  717. {
  718. ui32NewTotalHandCount = psBase->ui32MaxIndexPlusOne;
  719. ui32DeltaAdjusted = ui32NewTotalHandCount - psBase->ui32TotalHandCount;
  720. if (ui32DeltaAdjusted < ui32Delta)
  721. {
  722. PVR_DPF((PVR_DBG_ERROR, "IncreaseHandleArraySize: Maximum handle limit reached (%d)", psBase->ui32MaxIndexPlusOne));
  723. return PVRSRV_ERROR_OUT_OF_MEMORY;
  724. }
  725. }
  726. PVR_ASSERT(ui32DeltaAdjusted >= ui32Delta)
  727. eError = ReallocHandleArray(psBase, ui32NewTotalHandCount);
  728. if (eError != PVRSRV_OK)
  729. {
  730. PVR_DPF((PVR_DBG_ERROR, "IncreaseHandleArraySize: ReallocHandleArray failed (%d)", eError));
  731. return eError;
  732. }
  733. return PVRSRV_OK;
  734. }
  735. static PVRSRV_ERROR EnsureFreeHandles(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32Free)
  736. {
  737. PVRSRV_ERROR eError;
  738. if (ui32Free > psBase->ui32FreeHandCount)
  739. {
  740. IMG_UINT32 ui32FreeHandDelta = ui32Free - psBase->ui32FreeHandCount;
  741. eError = IncreaseHandleArraySize(psBase, ui32FreeHandDelta);
  742. if (eError != PVRSRV_OK)
  743. {
  744. PVR_DPF((PVR_DBG_ERROR, "EnsureFreeHandles: Couldn't allocate %u handles to ensure %u free handles (IncreaseHandleArraySize failed with error %d)", ui32FreeHandDelta, ui32Free, eError));
  745. return eError;
  746. }
  747. }
  748. return PVRSRV_OK;
  749. }
  750. #if defined (SUPPORT_SID_INTERFACE)
  751. static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_SID hParent)
  752. #else
  753. static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent)
  754. #endif
  755. {
  756. IMG_UINT32 ui32NewIndex = DEFAULT_MAX_INDEX_PLUS_ONE;
  757. struct sHandle *psNewHandle = IMG_NULL;
  758. #if defined (SUPPORT_SID_INTERFACE)
  759. IMG_SID hHandle;
  760. #else
  761. IMG_HANDLE hHandle;
  762. #endif
  763. HAND_KEY aKey;
  764. PVRSRV_ERROR eError;
  765. PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
  766. PVR_ASSERT(psBase != IMG_NULL)
  767. PVR_ASSERT(psBase->psHashTab != IMG_NULL)
  768. if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
  769. {
  770. PVR_ASSERT(FindHandle(psBase, pvData, eType, hParent) == IMG_NULL)
  771. }
  772. if (psBase->ui32FreeHandCount == 0 && HANDLES_BATCHED(psBase))
  773. {
  774. PVR_DPF((PVR_DBG_WARNING, "AllocHandle: Handle batch size (%u) was too small, allocating additional space", psBase->ui32HandBatchSize));
  775. }
  776. eError = EnsureFreeHandles(psBase, 1);
  777. if (eError != PVRSRV_OK)
  778. {
  779. PVR_DPF((PVR_DBG_ERROR, "AllocHandle: EnsureFreeHandles failed (%d)", eError));
  780. return eError;
  781. }
  782. PVR_ASSERT(psBase->ui32FreeHandCount != 0)
  783. if (!psBase->bPurgingEnabled)
  784. {
  785. ui32NewIndex = psBase->ui32FirstFreeIndex;
  786. psNewHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32NewIndex);
  787. }
  788. else
  789. {
  790. IMG_UINT32 ui32BlockedIndex;
  791. PVR_ASSERT((psBase->ui32FirstFreeIndex % HANDLE_BLOCK_SIZE) == 0)
  792. for (ui32BlockedIndex = ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(psBase->ui32FirstFreeIndex); ui32BlockedIndex < psBase->ui32TotalHandCount; ui32BlockedIndex += HANDLE_BLOCK_SIZE)
  793. {
  794. struct sHandleIndex *psIndex = BASE_AND_INDEX_TO_INDEX_STRUCT_PTR(psBase, ui32BlockedIndex);
  795. if (psIndex->ui32FreeHandBlockCount == 0)
  796. {
  797. continue;
  798. }
  799. for (ui32NewIndex = ui32BlockedIndex; ui32NewIndex < ui32BlockedIndex + HANDLE_BLOCK_SIZE; ui32NewIndex++)
  800. {
  801. psNewHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32NewIndex);
  802. if (HANDLE_STRUCT_IS_FREE(psNewHandle))
  803. {
  804. break;
  805. }
  806. }
  807. }
  808. psBase->ui32FirstFreeIndex = 0;
  809. PVR_ASSERT(ui32NewIndex < psBase->ui32TotalHandCount)
  810. }
  811. PVR_ASSERT(psNewHandle != IMG_NULL)
  812. hHandle = INDEX_TO_HANDLE(ui32NewIndex);
  813. if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
  814. {
  815. InitKey(aKey, psBase, pvData, eType, hParent);
  816. if (!HASH_Insert_Extended(psBase->psHashTab, aKey, (IMG_UINTPTR_T)hHandle))
  817. {
  818. PVR_DPF((PVR_DBG_ERROR, "AllocHandle: Couldn't add handle to hash table"));
  819. return PVRSRV_ERROR_UNABLE_TO_ADD_HANDLE;
  820. }
  821. }
  822. psBase->ui32FreeHandCount--;
  823. PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex) <= HANDLE_BLOCK_SIZE)
  824. PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex) > 0)
  825. INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex)--;
  826. if (!psBase->bPurgingEnabled)
  827. {
  828. if (psBase->ui32FreeHandCount == 0)
  829. {
  830. PVR_ASSERT(psBase->ui32FirstFreeIndex == ui32NewIndex)
  831. PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == (ui32NewIndex + 1))
  832. psBase->ui32LastFreeIndexPlusOne = 0;
  833. psBase->ui32FirstFreeIndex = 0;
  834. }
  835. else
  836. {
  837. psBase->ui32FirstFreeIndex = (psNewHandle->ui32NextIndexPlusOne == 0) ?
  838. ui32NewIndex + 1 :
  839. psNewHandle->ui32NextIndexPlusOne - 1;
  840. }
  841. }
  842. PVR_ASSERT(psNewHandle->ui32Index == ui32NewIndex)
  843. psNewHandle->eType = eType;
  844. psNewHandle->pvData = pvData;
  845. psNewHandle->eInternalFlag = INTERNAL_HANDLE_FLAG_NONE;
  846. psNewHandle->eFlag = eFlag;
  847. InitParentList(psNewHandle);
  848. #if defined(DEBUG)
  849. PVR_ASSERT(NoChildren(psNewHandle))
  850. #endif
  851. InitChildEntry(psNewHandle);
  852. #if defined(DEBUG)
  853. PVR_ASSERT(NoParent(psNewHandle))
  854. #endif
  855. if (HANDLES_BATCHED(psBase))
  856. {
  857. psNewHandle->ui32NextIndexPlusOne = psBase->ui32FirstBatchIndexPlusOne;
  858. psBase->ui32FirstBatchIndexPlusOne = ui32NewIndex + 1;
  859. SET_BATCHED_HANDLE(psNewHandle);
  860. }
  861. else
  862. {
  863. psNewHandle->ui32NextIndexPlusOne = 0;
  864. }
  865. *phHandle = hHandle;
  866. return PVRSRV_OK;
  867. }
  868. #if defined (SUPPORT_SID_INTERFACE)
  869. PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag)
  870. #else
  871. PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag)
  872. #endif
  873. {
  874. #if defined (SUPPORT_SID_INTERFACE)
  875. IMG_SID hHandle;
  876. #else
  877. IMG_HANDLE hHandle;
  878. #endif
  879. PVRSRV_ERROR eError;
  880. #if defined (SUPPORT_SID_INTERFACE)
  881. *phHandle = 0;
  882. #else
  883. *phHandle = IMG_NULL;
  884. #endif
  885. if (HANDLES_BATCHED(psBase))
  886. {
  887. psBase->ui32BatchHandAllocFailures++;
  888. }
  889. PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
  890. if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
  891. {
  892. hHandle = FindHandle(psBase, pvData, eType, IMG_NULL);
  893. #if defined (SUPPORT_SID_INTERFACE)
  894. if (hHandle != 0)
  895. #else
  896. if (hHandle != IMG_NULL)
  897. #endif
  898. {
  899. struct sHandle *psHandle;
  900. eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
  901. if (eError != PVRSRV_OK)
  902. {
  903. PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandle: Lookup of existing handle failed"));
  904. return eError;
  905. }
  906. if (TEST_FLAG(psHandle->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED))
  907. {
  908. *phHandle = hHandle;
  909. eError = PVRSRV_OK;
  910. goto exit_ok;
  911. }
  912. #if defined (SUPPORT_SID_INTERFACE)
  913. PVR_DBG_BREAK
  914. #endif
  915. return PVRSRV_ERROR_HANDLE_NOT_SHAREABLE;
  916. }
  917. }
  918. eError = AllocHandle(psBase, phHandle, pvData, eType, eFlag, IMG_NULL);
  919. exit_ok:
  920. if (HANDLES_BATCHED(psBase) && (eError == PVRSRV_OK))
  921. {
  922. psBase->ui32BatchHandAllocFailures--;
  923. }
  924. return eError;
  925. }
  926. #if defined (SUPPORT_SID_INTERFACE)
  927. PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_SID hParent)
  928. #else
  929. PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent)
  930. #endif
  931. {
  932. struct sHandle *psPHand;
  933. struct sHandle *psCHand;
  934. PVRSRV_ERROR eError;
  935. #if defined (SUPPORT_SID_INTERFACE)
  936. IMG_SID hParentKey;
  937. IMG_SID hHandle;
  938. *phHandle = 0;
  939. #else
  940. IMG_HANDLE hParentKey;
  941. IMG_HANDLE hHandle;
  942. *phHandle = IMG_NULL;
  943. #endif
  944. if (HANDLES_BATCHED(psBase))
  945. {
  946. psBase->ui32BatchHandAllocFailures++;
  947. }
  948. PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
  949. hParentKey = TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ?
  950. hParent : IMG_NULL;
  951. eError = GetHandleStructure(psBase, &psPHand, hParent, PVRSRV_HANDLE_TYPE_NONE);
  952. if (eError != PVRSRV_OK)
  953. {
  954. return eError;
  955. }
  956. if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
  957. {
  958. hHandle = FindHandle(psBase, pvData, eType, hParentKey);
  959. #if defined (SUPPORT_SID_INTERFACE)
  960. if (hHandle != 0)
  961. #else
  962. if (hHandle != IMG_NULL)
  963. #endif
  964. {
  965. struct sHandle *psCHandle;
  966. PVRSRV_ERROR eErr;
  967. eErr = GetHandleStructure(psBase, &psCHandle, hHandle, eType);
  968. if (eErr != PVRSRV_OK)
  969. {
  970. PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSubHandle: Lookup of existing handle failed"));
  971. return eErr;
  972. }
  973. PVR_ASSERT(hParentKey != IMG_NULL && ParentHandle(HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle)) == hParent)
  974. if (TEST_FLAG(psCHandle->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED) && ParentHandle(HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle)) == hParent)
  975. {
  976. *phHandle = hHandle;
  977. goto exit_ok;
  978. }
  979. #if defined (SUPPORT_SID_INTERFACE)
  980. PVR_DBG_BREAK
  981. #endif
  982. return PVRSRV_ERROR_HANDLE_NOT_SHAREABLE;
  983. }
  984. }
  985. eError = AllocHandle(psBase, &hHandle, pvData, eType, eFlag, hParentKey);
  986. if (eError != PVRSRV_OK)
  987. {
  988. return eError;
  989. }
  990. psPHand = HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hParent);
  991. psCHand = HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle);
  992. AdoptChild(psBase, psPHand, psCHand);
  993. *phHandle = hHandle;
  994. exit_ok:
  995. if (HANDLES_BATCHED(psBase))
  996. {
  997. psBase->ui32BatchHandAllocFailures--;
  998. }
  999. return PVRSRV_OK;
  1000. }
  1001. #if defined (SUPPORT_SID_INTERFACE)
  1002. PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType)
  1003. #else
  1004. PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType)
  1005. #endif
  1006. {
  1007. #if defined (SUPPORT_SID_INTERFACE)
  1008. IMG_SID hHandle;
  1009. #else
  1010. IMG_HANDLE hHandle;
  1011. #endif
  1012. PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
  1013. #if defined (SUPPORT_SID_INTERFACE)
  1014. hHandle = (IMG_SID) FindHandle(psBase, pvData, eType, IMG_NULL);
  1015. #else
  1016. hHandle = (IMG_HANDLE) FindHandle(psBase, pvData, eType, IMG_NULL);
  1017. #endif
  1018. if (hHandle == IMG_NULL)
  1019. {
  1020. return PVRSRV_ERROR_HANDLE_NOT_FOUND;
  1021. }
  1022. *phHandle = hHandle;
  1023. return PVRSRV_OK;
  1024. }
  1025. #if defined (SUPPORT_SID_INTERFACE)
  1026. PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_SID hHandle)
  1027. #else
  1028. PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle)
  1029. #endif
  1030. {
  1031. struct sHandle *psHandle;
  1032. PVRSRV_ERROR eError;
  1033. eError = GetHandleStructure(psBase, &psHandle, hHandle, PVRSRV_HANDLE_TYPE_NONE);
  1034. if (eError != PVRSRV_OK)
  1035. {
  1036. PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupHandleAnyType: Error looking up handle (%d)", eError));
  1037. #if defined (SUPPORT_SID_INTERFACE)
  1038. PVR_DBG_BREAK
  1039. #endif
  1040. return eError;
  1041. }
  1042. *ppvData = psHandle->pvData;
  1043. *peType = psHandle->eType;
  1044. return PVRSRV_OK;
  1045. }
  1046. #if defined (SUPPORT_SID_INTERFACE)
  1047. PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType)
  1048. #else
  1049. PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
  1050. #endif
  1051. {
  1052. struct sHandle *psHandle;
  1053. PVRSRV_ERROR eError;
  1054. PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
  1055. #if defined (SUPPORT_SID_INTERFACE)
  1056. PVR_ASSERT(hHandle != 0)
  1057. #endif
  1058. eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
  1059. if (eError != PVRSRV_OK)
  1060. {
  1061. PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupHandle: Error looking up handle (%d)", eError));
  1062. #if defined (SUPPORT_SID_INTERFACE)
  1063. PVR_DBG_BREAK
  1064. #endif
  1065. return eError;
  1066. }
  1067. *ppvData = psHandle->pvData;
  1068. return PVRSRV_OK;
  1069. }
  1070. #if defined (SUPPORT_SID_INTERFACE)
  1071. PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType, IMG_SID hAncestor)
  1072. #else
  1073. PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hAncestor)
  1074. #endif
  1075. {
  1076. struct sHandle *psPHand;
  1077. struct sHandle *psCHand;
  1078. PVRSRV_ERROR eError;
  1079. PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
  1080. #if defined (SUPPORT_SID_INTERFACE)
  1081. PVR_ASSERT(hHandle != 0)
  1082. #endif
  1083. eError = GetHandleStructure(psBase, &psCHand, hHandle, eType);
  1084. if (eError != PVRSRV_OK)
  1085. {
  1086. PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupSubHandle: Error looking up subhandle (%d)", eError));
  1087. return eError;
  1088. }
  1089. for (psPHand = psCHand; ParentHandle(psPHand) != hAncestor; )
  1090. {
  1091. eError = GetHandleStructure(psBase, &psPHand, ParentHandle(psPHand), PVRSRV_HANDLE_TYPE_NONE);
  1092. if (eError != PVRSRV_OK)
  1093. {
  1094. PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupSubHandle: Subhandle doesn't belong to given ancestor"));
  1095. return PVRSRV_ERROR_INVALID_SUBHANDLE;
  1096. }
  1097. }
  1098. *ppvData = psCHand->pvData;
  1099. return PVRSRV_OK;
  1100. }
  1101. #if defined (SUPPORT_SID_INTERFACE)
  1102. PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phParent, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType)
  1103. #else
  1104. PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
  1105. #endif
  1106. {
  1107. struct sHandle *psHandle;
  1108. PVRSRV_ERROR eError;
  1109. PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
  1110. eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
  1111. if (eError != PVRSRV_OK)
  1112. {
  1113. PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetParentHandle: Error looking up subhandle (%d)", eError));
  1114. return eError;
  1115. }
  1116. *phParent = ParentHandle(psHandle);
  1117. return PVRSRV_OK;
  1118. }
  1119. #if defined (SUPPORT_SID_INTERFACE)
  1120. PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType)
  1121. #else
  1122. PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
  1123. #endif
  1124. {
  1125. struct sHandle *psHandle;
  1126. PVRSRV_ERROR eError;
  1127. PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
  1128. eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
  1129. if (eError != PVRSRV_OK)
  1130. {
  1131. PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupAndReleaseHandle: Error looking up handle (%d)", eError));
  1132. #if defined (SUPPORT_SID_INTERFACE)
  1133. PVR_DBG_BREAK
  1134. #endif
  1135. return eError;
  1136. }
  1137. *ppvData = psHandle->pvData;
  1138. eError = FreeHandle(psBase, psHandle);
  1139. return eError;
  1140. }
  1141. #if defined (SUPPORT_SID_INTERFACE)
  1142. PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType)
  1143. #else
  1144. PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
  1145. #endif
  1146. {
  1147. struct sHandle *psHandle;
  1148. PVRSRV_ERROR eError;
  1149. PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
  1150. eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
  1151. if (eError != PVRSRV_OK)
  1152. {
  1153. PVR_DPF((PVR_DBG_ERROR, "PVRSRVReleaseHandle: Error looking up handle (%d)", eError));
  1154. return eError;
  1155. }
  1156. eError = FreeHandle(psBase, psHandle);
  1157. return eError;
  1158. }
  1159. PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32BatchSize)
  1160. {
  1161. PVRSRV_ERROR eError;
  1162. if (HANDLES_BATCHED(psBase))
  1163. {
  1164. PVR_DPF((PVR_DBG_ERROR, "PVRSRVNewHandleBatch: There is a handle batch already in use (size %u)", psBase->ui32HandBatchSize));
  1165. return PVRSRV_ERROR_HANDLE_BATCH_IN_USE;
  1166. }
  1167. if (ui32BatchSize == 0)
  1168. {
  1169. PVR_DPF((PVR_DBG_ERROR, "PVRSRVNewHandleBatch: Invalid batch size (%u)", ui32BatchSize));
  1170. return PVRSRV_ERROR_INVALID_PARAMS;
  1171. }
  1172. eError = EnsureFreeHandles(psBase, ui32BatchSize);
  1173. if (eError != PVRSRV_OK)
  1174. {
  1175. PVR_DPF((PVR_DBG_ERROR, "PVRSRVNewHandleBatch: EnsureFreeHandles failed (error %d)", eError));
  1176. return eError;
  1177. }
  1178. psBase->ui32HandBatchSize = ui32BatchSize;
  1179. psBase->ui32TotalHandCountPreBatch = psBase->ui32TotalHandCount;
  1180. PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0)
  1181. PVR_ASSERT(psBase->ui32FirstBatchIndexPlusOne == 0)
  1182. PVR_ASSERT(HANDLES_BATCHED(psBase))
  1183. return PVRSRV_OK;
  1184. }
  1185. static PVRSRV_ERROR PVRSRVHandleBatchCommitOrRelease(PVRSRV_HANDLE_BASE *psBase, IMG_BOOL bCommit)
  1186. {
  1187. IMG_UINT32 ui32IndexPlusOne;
  1188. IMG_BOOL bCommitBatch = bCommit;
  1189. if (!HANDLES_BATCHED(psBase))
  1190. {
  1191. PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: There is no handle batch"));
  1192. return PVRSRV_ERROR_INVALID_PARAMS;
  1193. }
  1194. if (psBase->ui32BatchHandAllocFailures != 0)
  1195. {
  1196. if (bCommit)
  1197. {
  1198. PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: Attempting to commit batch with handle allocation failures."));
  1199. }
  1200. bCommitBatch = IMG_FALSE;
  1201. }
  1202. PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0 || !bCommit)
  1203. ui32IndexPlusOne = psBase->ui32FirstBatchIndexPlusOne;
  1204. while(ui32IndexPlusOne != 0)
  1205. {
  1206. struct sHandle *psHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32IndexPlusOne - 1);
  1207. IMG_UINT32 ui32NextIndexPlusOne = psHandle->ui32NextIndexPlusOne;
  1208. PVR_ASSERT(BATCHED_HANDLE(psHandle))
  1209. psHandle->ui32NextIndexPlusOne = 0;
  1210. if (!bCommitBatch || BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
  1211. {
  1212. PVRSRV_ERROR eError;
  1213. if (!BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
  1214. {
  1215. SET_UNBATCHED_HANDLE(psHandle);
  1216. }
  1217. eError = FreeHandle(psBase, psHandle);
  1218. if (eError != PVRSRV_OK)
  1219. {
  1220. PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: Error freeing handle (%d)", eError));
  1221. }
  1222. PVR_ASSERT(eError == PVRSRV_OK)
  1223. }
  1224. else
  1225. {
  1226. SET_UNBATCHED_HANDLE(psHandle);
  1227. }
  1228. ui32IndexPlusOne = ui32NextIndexPlusOne;
  1229. }
  1230. #ifdef DEBUG
  1231. if (psBase->ui32TotalHandCountPreBatch != psBase->ui32TotalHandCount)
  1232. {
  1233. IMG_UINT32 ui32Delta = psBase->ui32TotalHandCount - psBase->ui32TotalHandCountPreBatch;
  1234. PVR_ASSERT(psBase->ui32TotalHandCount > psBase->ui32TotalHandCountPreBatch)
  1235. PVR_DPF((PVR_DBG_WARNING, "PVRSRVHandleBatchCommitOrRelease: The batch size was too small. Batch size was %u, but needs to be %u", psBase->ui32HandBatchSize, psBase->ui32HandBatchSize + ui32Delta));
  1236. }
  1237. #endif
  1238. psBase->ui32HandBatchSize = 0;
  1239. psBase->ui32FirstBatchIndexPlusOne = 0;
  1240. psBase->ui32TotalHandCountPreBatch = 0;
  1241. psBase->ui32BatchHandAllocFailures = 0;
  1242. if (psBase->ui32BatchHandAllocFailures != 0 && bCommit)
  1243. {
  1244. PVR_ASSERT(!bCommitBatch)
  1245. return PVRSRV_ERROR_HANDLE_BATCH_COMMIT_FAILURE;
  1246. }
  1247. return PVRSRV_OK;
  1248. }
  1249. PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE *psBase)
  1250. {
  1251. return PVRSRVHandleBatchCommitOrRelease(psBase, IMG_TRUE);
  1252. }
  1253. IMG_VOID PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE *psBase)
  1254. {
  1255. (IMG_VOID) PVRSRVHandleBatchCommitOrRelease(psBase, IMG_FALSE);
  1256. }
  1257. PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHandle)
  1258. {
  1259. IMG_UINT32 ui32MaxHandleRounded;
  1260. if (HANDLES_BATCHED(psBase))
  1261. {
  1262. PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit cannot be set whilst in batch mode"));
  1263. return PVRSRV_ERROR_INVALID_PARAMS;
  1264. }
  1265. if (ui32MaxHandle == 0 || ui32MaxHandle > DEFAULT_MAX_HANDLE)
  1266. {
  1267. PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit must be between %u and %u, inclusive", 0, DEFAULT_MAX_HANDLE));
  1268. return PVRSRV_ERROR_INVALID_PARAMS;
  1269. }
  1270. if (psBase->ui32TotalHandCount != 0)
  1271. {
  1272. PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit cannot be set because handles have already been allocated"));
  1273. return PVRSRV_ERROR_INVALID_PARAMS;
  1274. }
  1275. ui32MaxHandleRounded = ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(ui32MaxHandle);
  1276. if (ui32MaxHandleRounded != 0 && ui32MaxHandleRounded < psBase->ui32MaxIndexPlusOne)
  1277. {
  1278. psBase->ui32MaxIndexPlusOne = ui32MaxHandleRounded;
  1279. }
  1280. PVR_ASSERT(psBase->ui32MaxIndexPlusOne != 0)
  1281. PVR_ASSERT(psBase->ui32MaxIndexPlusOne <= DEFAULT_MAX_INDEX_PLUS_ONE)
  1282. PVR_ASSERT((psBase->ui32MaxIndexPlusOne % HANDLE_BLOCK_SIZE) == 0)
  1283. return PVRSRV_OK;
  1284. }
  1285. IMG_UINT32 PVRSRVGetMaxHandle(PVRSRV_HANDLE_BASE *psBase)
  1286. {
  1287. return psBase->ui32MaxIndexPlusOne;
  1288. }
  1289. PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase)
  1290. {
  1291. if (psBase->bPurgingEnabled)
  1292. {
  1293. PVR_DPF((PVR_DBG_WARNING, "PVRSRVEnableHandlePurging: Purging already enabled"));
  1294. return PVRSRV_OK;
  1295. }
  1296. if (psBase->ui32TotalHandCount != 0)
  1297. {
  1298. PVR_DPF((PVR_DBG_ERROR, "PVRSRVEnableHandlePurging: Handles have already been allocated"));
  1299. return PVRSRV_ERROR_INVALID_PARAMS;
  1300. }
  1301. psBase->bPurgingEnabled = IMG_TRUE;
  1302. return PVRSRV_OK;
  1303. }
  1304. PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase)
  1305. {
  1306. IMG_UINT32 ui32BlockIndex;
  1307. IMG_UINT32 ui32NewHandCount;
  1308. if (!psBase->bPurgingEnabled)
  1309. {
  1310. PVR_DPF((PVR_DBG_ERROR, "PVRSRVPurgeHandles: Purging not enabled for this handle base"));
  1311. return PVRSRV_ERROR_NOT_SUPPORTED;
  1312. }
  1313. if (HANDLES_BATCHED(psBase))
  1314. {
  1315. PVR_DPF((PVR_DBG_ERROR, "PVRSRVPurgeHandles: Purging not allowed whilst in batch mode"));
  1316. return PVRSRV_ERROR_INVALID_PARAMS;
  1317. }
  1318. PVR_ASSERT((psBase->ui32TotalHandCount % HANDLE_BLOCK_SIZE) == 0)
  1319. for (ui32BlockIndex = INDEX_TO_BLOCK_INDEX(psBase->ui32TotalHandCount); ui32BlockIndex != 0; ui32BlockIndex--)
  1320. {
  1321. if (psBase->psHandleArray[ui32BlockIndex - 1].ui32FreeHandBlockCount != HANDLE_BLOCK_SIZE)
  1322. {
  1323. break;
  1324. }
  1325. }
  1326. ui32NewHandCount = BLOCK_INDEX_TO_INDEX(ui32BlockIndex);
  1327. if (ui32NewHandCount <= (psBase->ui32TotalHandCount/2))
  1328. {
  1329. PVRSRV_ERROR eError;
  1330. eError = ReallocHandleArray(psBase, ui32NewHandCount);
  1331. if (eError != PVRSRV_OK)
  1332. {
  1333. return eError;
  1334. }
  1335. }
  1336. return PVRSRV_OK;
  1337. }
  1338. PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase)
  1339. {
  1340. PVRSRV_HANDLE_BASE *psBase;
  1341. IMG_HANDLE hBlockAlloc;
  1342. PVRSRV_ERROR eError;
  1343. eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
  1344. sizeof(*psBase),
  1345. (IMG_PVOID *)&psBase,
  1346. &hBlockAlloc,
  1347. "Handle Base");
  1348. if (eError != PVRSRV_OK)
  1349. {
  1350. PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandleBase: Couldn't allocate handle base (%d)", eError));
  1351. return eError;
  1352. }
  1353. OSMemSet(psBase, 0, sizeof(*psBase));
  1354. psBase->psHashTab = HASH_Create_Extended(HANDLE_HASH_TAB_INIT_SIZE, sizeof(HAND_KEY), HASH_Func_Default, HASH_Key_Comp_Default);
  1355. if (psBase->psHashTab == IMG_NULL)
  1356. {
  1357. PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandleBase: Couldn't create data pointer hash table\n"));
  1358. (IMG_VOID)PVRSRVFreeHandleBase(psBase);
  1359. return PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE;
  1360. }
  1361. psBase->hBaseBlockAlloc = hBlockAlloc;
  1362. psBase->ui32MaxIndexPlusOne = DEFAULT_MAX_INDEX_PLUS_ONE;
  1363. *ppsBase = psBase;
  1364. return PVRSRV_OK;
  1365. }
  1366. PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
  1367. {
  1368. PVRSRV_ERROR eError;
  1369. PVR_ASSERT(psBase != gpsKernelHandleBase)
  1370. eError = FreeHandleBase(psBase);
  1371. if (eError != PVRSRV_OK)
  1372. {
  1373. PVR_DPF((PVR_DBG_ERROR, "PVRSRVFreeHandleBase: FreeHandleBase failed (%d)", eError));
  1374. }
  1375. return eError;
  1376. }
  1377. PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID)
  1378. {
  1379. PVRSRV_ERROR eError;
  1380. PVR_ASSERT(gpsKernelHandleBase == IMG_NULL)
  1381. eError = PVRSRVAllocHandleBase(&gpsKernelHandleBase);
  1382. if (eError != PVRSRV_OK)
  1383. {
  1384. PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleInit: PVRSRVAllocHandleBase failed (%d)", eError));
  1385. goto error;
  1386. }
  1387. eError = PVRSRVEnableHandlePurging(gpsKernelHandleBase);
  1388. if (eError != PVRSRV_OK)
  1389. {
  1390. PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleInit: PVRSRVEnableHandlePurging failed (%d)", eError));
  1391. goto error;
  1392. }
  1393. return PVRSRV_OK;
  1394. error:
  1395. (IMG_VOID) PVRSRVHandleDeInit();
  1396. return eError;
  1397. }
  1398. PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID)
  1399. {
  1400. PVRSRV_ERROR eError = PVRSRV_OK;
  1401. if (gpsKernelHandleBase != IMG_NULL)
  1402. {
  1403. eError = FreeHandleBase(gpsKernelHandleBase);
  1404. if (eError == PVRSRV_OK)
  1405. {
  1406. gpsKernelHandleBase = IMG_NULL;
  1407. }
  1408. else
  1409. {
  1410. PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleDeInit: FreeHandleBase failed (%d)", eError));
  1411. }
  1412. }
  1413. return eError;
  1414. }
  1415. #else
  1416. #endif