1 /**********************************************************************
2 Copyright (c) Imagination Technologies Ltd.
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 ******************************************************************************/
23 #ifdef PVR_SECURE_HANDLES
26 #include "services_headers.h"
30 #define HANDLE_BLOCK_SIZE 1
32 #define HANDLE_BLOCK_SIZE 256
35 #define HANDLE_HASH_TAB_INIT_SIZE 32
37 #define DEFAULT_MAX_INDEX_PLUS_ONE 0xfffffffful
38 #define DEFAULT_MAX_HANDLE DEFAULT_MAX_INDEX_PLUS_ONE
40 #define INDEX_IS_VALID(psBase, i) ((i) < (psBase)->ui32TotalHandCount)
42 #define INDEX_TO_HANDLE(psBase, idx) ((IMG_HANDLE)((idx) + 1))
43 #define HANDLE_TO_INDEX(psBase, hand) ((IMG_UINT32)(hand) - 1)
45 #define INDEX_TO_HANDLE_PTR(psBase, i) (((psBase)->psHandleArray) + (i))
46 #define HANDLE_TO_HANDLE_PTR(psBase, h) (INDEX_TO_HANDLE_PTR(psBase, HANDLE_TO_INDEX(psBase, h)))
48 #define HANDLE_PTR_TO_INDEX(psBase, psHandle) (IMG_UINT32)((psHandle) - ((psBase)->psHandleArray))
49 #define HANDLE_PTR_TO_HANDLE(psBase, psHandle) \
50 INDEX_TO_HANDLE(psBase, HANDLE_PTR_TO_INDEX(psBase, psHandle))
52 #define ROUND_UP_TO_MULTIPLE(a, b) ((((a) + (b) - 1) / (b)) * (b))
54 #define HANDLES_BATCHED(psBase) ((psBase)->ui32HandBatchSize != 0)
56 #define SET_FLAG(v, f) ((IMG_VOID)((v) |= (f)))
57 #define CLEAR_FLAG(v, f) ((IMG_VOID)((v) &= ~(f)))
58 #define TEST_FLAG(v, f) ((IMG_BOOL)(((v) & (f)) != 0))
60 #define TEST_ALLOC_FLAG(psHandle, f) TEST_FLAG((psHandle)->eFlag, f)
62 #define SET_INTERNAL_FLAG(psHandle, f) SET_FLAG((psHandle)->eInternalFlag, f)
63 #define CLEAR_INTERNAL_FLAG(psHandle, f) CLEAR_FLAG((psHandle)->eInternalFlag, f)
64 #define TEST_INTERNAL_FLAG(psHandle, f) TEST_FLAG((psHandle)->eInternalFlag, f)
66 #define BATCHED_HANDLE(psHandle) TEST_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
68 #define SET_BATCHED_HANDLE(psHandle) SET_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
70 #define SET_UNBATCHED_HANDLE(psHandle) CLEAR_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
72 #define BATCHED_HANDLE_PARTIALLY_FREE(psHandle) TEST_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE)
74 #define SET_BATCHED_HANDLE_PARTIALLY_FREE(psHandle) SET_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE)
76 #define HANDLE_STRUCT_IS_FREE(psHandle) ((psHandle)->eType == PVRSRV_HANDLE_TYPE_NONE && (psHandle)->eInternalFlag == INTERNAL_HANDLE_FLAG_NONE)
82 #define MIN(x, y) (((x) < (y)) ? (x) : (y))
91 enum ePVRSRVInternalHandleFlag
93 INTERNAL_HANDLE_FLAG_NONE = 0x00,
94 INTERNAL_HANDLE_FLAG_BATCHED = 0x01,
95 INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE = 0x02,
101 PVRSRV_HANDLE_TYPE eType;
107 IMG_UINT32 ui32NextIndexPlusOne;
110 enum ePVRSRVInternalHandleFlag eInternalFlag;
113 PVRSRV_HANDLE_ALLOC_FLAG eFlag;
116 IMG_UINT32 ui32Index;
119 struct sHandleList sChildren;
122 struct sHandleList sSiblings;
125 struct _PVRSRV_HANDLE_BASE_
128 IMG_HANDLE hBaseBlockAlloc;
131 IMG_HANDLE hHandBlockAlloc;
134 struct sHandle *psHandleArray;
137 HASH_TABLE *psHashTab;
140 IMG_UINT32 ui32FreeHandCount;
143 IMG_UINT32 ui32FirstFreeIndex;
146 IMG_UINT32 ui32MaxIndexPlusOne;
149 IMG_UINT32 ui32TotalHandCount;
152 IMG_UINT32 ui32LastFreeIndexPlusOne;
155 IMG_UINT32 ui32HandBatchSize;
158 IMG_UINT32 ui32TotalHandCountPreBatch;
161 IMG_UINT32 ui32FirstBatchIndexPlusOne;
164 IMG_UINT32 ui32BatchHandAllocFailures;
167 IMG_BOOL bPurgingEnabled;
177 PVRSRV_HANDLE_BASE *gpsKernelHandleBase = IMG_NULL;
179 typedef IMG_UINTPTR_T HAND_KEY[HAND_KEY_LEN];
181 #ifdef INLINE_IS_PRAGMA
182 #pragma inline(HandleListInit)
185 IMG_VOID HandleListInit(IMG_UINT32 ui32Index, struct sHandleList *psList, IMG_HANDLE hParent)
187 psList->ui32Next = ui32Index;
188 psList->ui32Prev = ui32Index;
189 psList->hParent = hParent;
192 #ifdef INLINE_IS_PRAGMA
193 #pragma inline(InitParentList)
196 IMG_VOID InitParentList(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
198 IMG_UINT32 ui32Parent = HANDLE_PTR_TO_INDEX(psBase, psHandle);
200 HandleListInit(ui32Parent, &psHandle->sChildren, INDEX_TO_HANDLE(psBase, ui32Parent));
203 #ifdef INLINE_IS_PRAGMA
204 #pragma inline(InitChildEntry)
207 IMG_VOID InitChildEntry(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
209 HandleListInit(HANDLE_PTR_TO_INDEX(psBase, psHandle), &psHandle->sSiblings, IMG_NULL);
212 #ifdef INLINE_IS_PRAGMA
213 #pragma inline(HandleListIsEmpty)
216 IMG_BOOL HandleListIsEmpty(IMG_UINT32 ui32Index, struct sHandleList *psList)
220 bIsEmpty = (IMG_BOOL)(psList->ui32Next == ui32Index);
226 bIsEmpty2 = (IMG_BOOL)(psList->ui32Prev == ui32Index);
227 PVR_ASSERT(bIsEmpty == bIsEmpty2);
235 #ifdef INLINE_IS_PRAGMA
236 #pragma inline(NoChildren)
239 IMG_BOOL NoChildren(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
241 PVR_ASSERT(psHandle->sChildren.hParent == HANDLE_PTR_TO_HANDLE(psBase, psHandle));
243 return HandleListIsEmpty(HANDLE_PTR_TO_INDEX(psBase, psHandle), &psHandle->sChildren);
246 #ifdef INLINE_IS_PRAGMA
247 #pragma inline(NoParent)
250 IMG_BOOL NoParent(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
252 if (HandleListIsEmpty(HANDLE_PTR_TO_INDEX(psBase, psHandle), &psHandle->sSiblings))
254 PVR_ASSERT(psHandle->sSiblings.hParent == IMG_NULL);
260 PVR_ASSERT(psHandle->sSiblings.hParent != IMG_NULL);
265 #ifdef INLINE_IS_PRAGMA
266 #pragma inline(ParentHandle)
269 IMG_HANDLE ParentHandle(struct sHandle *psHandle)
271 return psHandle->sSiblings.hParent;
274 #define LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, i, p, po, eo) \
275 ((struct sHandleList *)((IMG_CHAR *)(INDEX_TO_HANDLE_PTR(psBase, i)) + (((i) == (p)) ? (po) : (eo))))
277 #ifdef INLINE_IS_PRAGMA
278 #pragma inline(HandleListInsertBefore)
281 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)
284 struct sHandleList *psPrevIns = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psIns->ui32Prev, ui32ParentIndex, uiParentOffset, uiEntryOffset);
286 PVR_ASSERT(psEntry->hParent == IMG_NULL);
287 PVR_ASSERT(ui32InsIndex == psPrevIns->ui32Next);
288 PVR_ASSERT(LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32ParentIndex, ui32ParentIndex, uiParentOffset, uiParentOffset)->hParent == INDEX_TO_HANDLE(psBase, ui32ParentIndex));
290 psEntry->ui32Prev = psIns->ui32Prev;
291 psIns->ui32Prev = ui32EntryIndex;
292 psEntry->ui32Next = ui32InsIndex;
293 psPrevIns->ui32Next = ui32EntryIndex;
295 psEntry->hParent = INDEX_TO_HANDLE(psBase, ui32ParentIndex);
298 #ifdef INLINE_IS_PRAGMA
299 #pragma inline(AdoptChild)
302 IMG_VOID AdoptChild(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psParent, struct sHandle *psChild)
304 IMG_UINT32 ui32Parent = HANDLE_TO_INDEX(psBase, psParent->sChildren.hParent);
306 PVR_ASSERT(ui32Parent == HANDLE_PTR_TO_INDEX(psBase, psParent));
308 HandleListInsertBefore(psBase, ui32Parent, &psParent->sChildren, offsetof(struct sHandle, sChildren), HANDLE_PTR_TO_INDEX(psBase, psChild), &psChild->sSiblings, offsetof(struct sHandle, sSiblings), ui32Parent);
312 #ifdef INLINE_IS_PRAGMA
313 #pragma inline(HandleListRemove)
316 IMG_VOID HandleListRemove(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32EntryIndex, struct sHandleList *psEntry, IMG_SIZE_T uiEntryOffset, IMG_SIZE_T uiParentOffset)
318 if (!HandleListIsEmpty(ui32EntryIndex, psEntry))
321 struct sHandleList *psPrev = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Prev, HANDLE_TO_INDEX(psBase, psEntry->hParent), uiParentOffset, uiEntryOffset);
322 struct sHandleList *psNext = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Next, HANDLE_TO_INDEX(psBase, psEntry->hParent), uiParentOffset, uiEntryOffset);
325 PVR_ASSERT(psEntry->hParent != IMG_NULL);
327 psPrev->ui32Next = psEntry->ui32Next;
328 psNext->ui32Prev = psEntry->ui32Prev;
330 HandleListInit(ui32EntryIndex, psEntry, IMG_NULL);
334 #ifdef INLINE_IS_PRAGMA
335 #pragma inline(UnlinkFromParent)
338 IMG_VOID UnlinkFromParent(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
340 HandleListRemove(psBase, HANDLE_PTR_TO_INDEX(psBase, psHandle), &psHandle->sSiblings, offsetof(struct sHandle, sSiblings), offsetof(struct sHandle, sChildren));
343 #ifdef INLINE_IS_PRAGMA
344 #pragma inline(HandleListIterate)
347 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 *))
349 IMG_UINT32 ui32Index;
350 IMG_UINT32 ui32Parent = HANDLE_TO_INDEX(psBase, psHead->hParent);
352 PVR_ASSERT(psHead->hParent != IMG_NULL);
355 for(ui32Index = psHead->ui32Next; ui32Index != ui32Parent; )
357 struct sHandle *psHandle = INDEX_TO_HANDLE_PTR(psBase, ui32Index);
359 struct sHandleList *psEntry = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32Index, ui32Parent, uiParentOffset, uiEntryOffset);
362 PVR_ASSERT(psEntry->hParent == psHead->hParent);
364 ui32Index = psEntry->ui32Next;
366 eError = (*pfnIterFunc)(psBase, psHandle);
367 if (eError != PVRSRV_OK)
376 #ifdef INLINE_IS_PRAGMA
377 #pragma inline(IterateOverChildren)
380 PVRSRV_ERROR IterateOverChildren(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psParent, PVRSRV_ERROR (*pfnIterFunc)(PVRSRV_HANDLE_BASE *, struct sHandle *))
382 return HandleListIterate(psBase, &psParent->sChildren, offsetof(struct sHandle, sChildren), offsetof(struct sHandle, sSiblings), pfnIterFunc);
385 #ifdef INLINE_IS_PRAGMA
386 #pragma inline(GetHandleStructure)
389 PVRSRV_ERROR GetHandleStructure(PVRSRV_HANDLE_BASE *psBase, struct sHandle **ppsHandle, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
391 IMG_UINT32 ui32Index = HANDLE_TO_INDEX(psBase, hHandle);
392 struct sHandle *psHandle;
395 if (!INDEX_IS_VALID(psBase, ui32Index))
397 PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle index out of range (%u >= %u)", ui32Index, psBase->ui32TotalHandCount));
398 return PVRSRV_ERROR_GENERIC;
401 psHandle = INDEX_TO_HANDLE_PTR(psBase, ui32Index);
402 if (psHandle->eType == PVRSRV_HANDLE_TYPE_NONE)
404 PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle not allocated (index: %u)", ui32Index));
405 return PVRSRV_ERROR_GENERIC;
409 if (eType != PVRSRV_HANDLE_TYPE_NONE && eType != psHandle->eType)
411 PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle type mismatch (%d != %d)", eType, psHandle->eType));
412 return PVRSRV_ERROR_GENERIC;
416 *ppsHandle = psHandle;
421 #ifdef INLINE_IS_PRAGMA
422 #pragma inline(ParentIfPrivate)
425 IMG_HANDLE ParentIfPrivate(struct sHandle *psHandle)
427 return TEST_ALLOC_FLAG(psHandle, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ?
428 ParentHandle(psHandle) : IMG_NULL;
431 #ifdef INLINE_IS_PRAGMA
432 #pragma inline(InitKey)
435 IMG_VOID InitKey(HAND_KEY aKey, PVRSRV_HANDLE_BASE *psBase, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hParent)
437 PVR_UNREFERENCED_PARAMETER(psBase);
439 aKey[HAND_KEY_DATA] = (IMG_UINTPTR_T)pvData;
440 aKey[HAND_KEY_TYPE] = (IMG_UINTPTR_T)eType;
441 aKey[HAND_KEY_PARENT] = (IMG_UINTPTR_T)hParent;
444 static PVRSRV_ERROR FreeHandleArray(PVRSRV_HANDLE_BASE *psBase)
446 PVRSRV_ERROR eError = PVRSRV_OK;
448 if (psBase->psHandleArray != IMG_NULL)
450 eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
451 psBase->ui32TotalHandCount * sizeof(struct sHandle),
452 psBase->psHandleArray,
453 psBase->hHandBlockAlloc);
455 if (eError != PVRSRV_OK)
457 PVR_DPF((PVR_DBG_ERROR, "FreeHandleArray: Error freeing memory (%d)", eError));
461 psBase->psHandleArray = IMG_NULL;
468 static PVRSRV_ERROR FreeHandle(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
471 IMG_UINT32 ui32Index = HANDLE_PTR_TO_INDEX(psBase, psHandle);
475 InitKey(aKey, psBase, psHandle->pvData, psHandle->eType, ParentIfPrivate(psHandle));
477 if (!TEST_ALLOC_FLAG(psHandle, PVRSRV_HANDLE_ALLOC_FLAG_MULTI) && !BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
480 hHandle = (IMG_HANDLE) HASH_Remove_Extended(psBase->psHashTab, aKey);
482 PVR_ASSERT(hHandle != IMG_NULL);
483 PVR_ASSERT(hHandle == INDEX_TO_HANDLE(psBase, ui32Index));
484 PVR_UNREFERENCED_PARAMETER(hHandle);
488 UnlinkFromParent(psBase, psHandle);
491 eError = IterateOverChildren(psBase, psHandle, FreeHandle);
492 if (eError != PVRSRV_OK)
494 PVR_DPF((PVR_DBG_ERROR, "FreeHandle: Error whilst freeing subhandles (%d)", eError));
499 psHandle->eType = PVRSRV_HANDLE_TYPE_NONE;
501 if (BATCHED_HANDLE(psHandle) && !BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
504 SET_BATCHED_HANDLE_PARTIALLY_FREE(psHandle);
510 if (!psBase->bPurgingEnabled)
512 if (psBase->ui32FreeHandCount == 0)
514 PVR_ASSERT(psBase->ui32FirstFreeIndex == 0);
515 PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0);
517 psBase->ui32FirstFreeIndex = ui32Index;
522 PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0);
523 PVR_ASSERT(INDEX_TO_HANDLE_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0);
524 INDEX_TO_HANDLE_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne = ui32Index + 1;
527 PVR_ASSERT(psHandle->ui32NextIndexPlusOne == 0);
530 psBase->ui32LastFreeIndexPlusOne = ui32Index + 1;
533 psBase->ui32FreeHandCount++;
538 static PVRSRV_ERROR FreeAllHandles(PVRSRV_HANDLE_BASE *psBase)
541 PVRSRV_ERROR eError = PVRSRV_OK;
543 if (psBase->ui32FreeHandCount == psBase->ui32TotalHandCount)
548 for (i = 0; i < psBase->ui32TotalHandCount; i++)
550 struct sHandle *psHandle;
552 psHandle = INDEX_TO_HANDLE_PTR(psBase, i);
554 if (psHandle->eType != PVRSRV_HANDLE_TYPE_NONE)
556 eError = FreeHandle(psBase, psHandle);
557 if (eError != PVRSRV_OK)
559 PVR_DPF((PVR_DBG_ERROR, "FreeAllHandles: FreeHandle failed (%d)", eError));
564 if (psBase->ui32FreeHandCount == psBase->ui32TotalHandCount)
574 static PVRSRV_ERROR FreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
578 if (HANDLES_BATCHED(psBase))
580 PVR_DPF((PVR_DBG_WARNING, "FreeHandleBase: Uncommitted/Unreleased handle batch"));
581 PVRSRVReleaseHandleBatch(psBase);
585 eError = FreeAllHandles(psBase);
586 if (eError != PVRSRV_OK)
588 PVR_DPF((PVR_DBG_ERROR, "FreeHandleBase: Couldn't free handles (%d)", eError));
593 eError = FreeHandleArray(psBase);
594 if (eError != PVRSRV_OK)
596 PVR_DPF((PVR_DBG_ERROR, "FreeHandleBase: Couldn't free handle array (%d)", eError));
600 if (psBase->psHashTab != IMG_NULL)
603 HASH_Delete(psBase->psHashTab);
606 eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
609 psBase->hBaseBlockAlloc);
610 if (eError != PVRSRV_OK)
612 PVR_DPF((PVR_DBG_ERROR, "FreeHandleBase: Couldn't free handle base (%d)", eError));
619 #ifdef INLINE_IS_PRAGMA
620 #pragma inline(FindHandle)
623 IMG_HANDLE FindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hParent)
627 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
629 InitKey(aKey, psBase, pvData, eType, hParent);
631 return (IMG_HANDLE) HASH_Retrieve_Extended(psBase->psHashTab, aKey);
634 static PVRSRV_ERROR ReallocMem(IMG_PVOID *ppvMem, IMG_HANDLE *phBlockAlloc, IMG_UINT32 ui32NewSize, IMG_UINT32 ui32OldSize)
636 IMG_VOID *pvOldMem = *ppvMem;
637 IMG_HANDLE hOldBlockAlloc = *phBlockAlloc;
638 IMG_UINT32 ui32CopySize = MIN(ui32NewSize, ui32OldSize);
639 IMG_VOID *pvNewMem = IMG_NULL;
640 IMG_HANDLE hNewBlockAlloc = IMG_NULL;
643 if (ui32NewSize == ui32OldSize)
648 if (ui32NewSize != 0)
651 eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
656 if (eError != PVRSRV_OK)
658 PVR_DPF((PVR_DBG_ERROR, "ReallocMem: Couldn't allocate new memory area (%d)", eError));
663 if (ui32CopySize != 0)
666 OSMemCopy(pvNewMem, pvOldMem, ui32CopySize);
669 if (ui32OldSize != 0)
672 eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
676 if (eError != PVRSRV_OK)
678 PVR_DPF((PVR_DBG_ERROR, "ReallocMem: Couldn't free old memory area (%d)", eError));
683 *phBlockAlloc = hNewBlockAlloc;
688 #ifdef INLINE_IS_PRAGMA
689 #pragma inline(ReallocHandleArray)
692 PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCount, IMG_UINT32 ui32OldCount)
694 return ReallocMem((IMG_PVOID *)&psBase->psHandleArray,
695 &psBase->hHandBlockAlloc,
696 ui32NewCount * sizeof(struct sHandle),
697 ui32OldCount * sizeof(struct sHandle));
700 static PVRSRV_ERROR IncreaseHandleArraySize(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32Delta)
703 struct sHandle *psHandle;
704 IMG_UINT32 ui32DeltaAdjusted = ROUND_UP_TO_MULTIPLE(ui32Delta, HANDLE_BLOCK_SIZE);
705 IMG_UINT32 ui32NewTotalHandCount = psBase->ui32TotalHandCount + ui32DeltaAdjusted;
708 PVR_ASSERT(ui32Delta != 0);
711 if (ui32NewTotalHandCount > psBase->ui32MaxIndexPlusOne || ui32NewTotalHandCount <= psBase->ui32TotalHandCount)
713 ui32NewTotalHandCount = psBase->ui32MaxIndexPlusOne;
715 ui32DeltaAdjusted = ui32NewTotalHandCount - psBase->ui32TotalHandCount;
717 if (ui32DeltaAdjusted < ui32Delta)
719 PVR_DPF((PVR_DBG_ERROR, "IncreaseHandleArraySize: Maximum handle limit reached (%d)", psBase->ui32MaxIndexPlusOne));
720 return PVRSRV_ERROR_OUT_OF_MEMORY;
724 PVR_ASSERT(ui32DeltaAdjusted >= ui32Delta);
727 eError = ReallocHandleArray(psBase, ui32NewTotalHandCount, psBase->ui32TotalHandCount);
728 if (eError != PVRSRV_OK)
730 PVR_DPF((PVR_DBG_ERROR, "IncreaseHandleArraySize: ReallocHandleArray failed (%d)", eError));
735 for(psHandle = psBase->psHandleArray + psBase->ui32TotalHandCount;
736 psHandle < psBase->psHandleArray + ui32NewTotalHandCount;
739 psHandle->eType = PVRSRV_HANDLE_TYPE_NONE;
740 psHandle->eInternalFlag = INTERNAL_HANDLE_FLAG_NONE;
741 psHandle->ui32NextIndexPlusOne = 0;
745 psBase->ui32FreeHandCount += ui32DeltaAdjusted;
747 if (psBase->ui32FirstFreeIndex == 0)
749 PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0);
751 psBase->ui32FirstFreeIndex = psBase->ui32TotalHandCount;
755 if (!psBase->bPurgingEnabled)
757 PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0)
758 PVR_ASSERT(INDEX_TO_HANDLE_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0);
760 INDEX_TO_HANDLE_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne = psBase->ui32TotalHandCount + 1;
764 if (!psBase->bPurgingEnabled)
766 psBase->ui32LastFreeIndexPlusOne = ui32NewTotalHandCount;
769 psBase->ui32TotalHandCount = ui32NewTotalHandCount;
774 static PVRSRV_ERROR EnsureFreeHandles(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32Free)
778 if (ui32Free > psBase->ui32FreeHandCount)
780 IMG_UINT32 ui32FreeHandDelta = ui32Free - psBase->ui32FreeHandCount;
781 eError = IncreaseHandleArraySize(psBase, ui32FreeHandDelta);
782 if (eError != PVRSRV_OK)
784 PVR_DPF((PVR_DBG_ERROR, "EnsureFreeHandles: Couldn't allocate %u handles to ensure %u free handles (IncreaseHandleArraySize failed with error %d)", ui32FreeHandDelta, ui32Free, eError));
793 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)
795 IMG_UINT32 ui32NewIndex;
796 struct sHandle *psNewHandle = IMG_NULL;
802 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
804 PVR_ASSERT(psBase->psHashTab != IMG_NULL);
806 if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
809 PVR_ASSERT(FindHandle(psBase, pvData, eType, hParent) == IMG_NULL);
812 if (psBase->ui32FreeHandCount == 0 && HANDLES_BATCHED(psBase))
814 PVR_DPF((PVR_DBG_WARNING, "AllocHandle: Handle batch size (%u) was too small, allocating additional space", psBase->ui32HandBatchSize));
818 eError = EnsureFreeHandles(psBase, 1);
819 if (eError != PVRSRV_OK)
821 PVR_DPF((PVR_DBG_ERROR, "AllocHandle: EnsureFreeHandles failed (%d)", eError));
824 PVR_ASSERT(psBase->ui32FreeHandCount != 0)
826 if (!psBase->bPurgingEnabled)
829 ui32NewIndex = psBase->ui32FirstFreeIndex;
832 psNewHandle = INDEX_TO_HANDLE_PTR(psBase, ui32NewIndex);
837 for(ui32NewIndex = psBase->ui32FirstFreeIndex; ui32NewIndex < psBase->ui32TotalHandCount; ui32NewIndex++)
839 psNewHandle = INDEX_TO_HANDLE_PTR(psBase, ui32NewIndex);
840 if (HANDLE_STRUCT_IS_FREE(psNewHandle))
846 psBase->ui32FirstFreeIndex = 0;
847 PVR_ASSERT(ui32NewIndex < psBase->ui32TotalHandCount);
849 PVR_ASSERT(psNewHandle != IMG_NULL);
852 hHandle = INDEX_TO_HANDLE(psBase, ui32NewIndex);
855 if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
858 InitKey(aKey, psBase, pvData, eType, hParent);
861 if (!HASH_Insert_Extended(psBase->psHashTab, aKey, (IMG_UINTPTR_T)hHandle))
863 PVR_DPF((PVR_DBG_ERROR, "AllocHandle: Couldn't add handle to hash table"));
865 return PVRSRV_ERROR_GENERIC;
869 psBase->ui32FreeHandCount--;
872 if (!psBase->bPurgingEnabled)
875 if (psBase->ui32FreeHandCount == 0)
877 PVR_ASSERT(psBase->ui32FirstFreeIndex == ui32NewIndex);
878 PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == (ui32NewIndex + 1));
880 psBase->ui32LastFreeIndexPlusOne = 0;
881 psBase->ui32FirstFreeIndex = 0;
886 psBase->ui32FirstFreeIndex = (psNewHandle->ui32NextIndexPlusOne == 0) ?
888 psNewHandle->ui32NextIndexPlusOne - 1;
893 psNewHandle->eType = eType;
894 psNewHandle->pvData = pvData;
895 psNewHandle->eInternalFlag = INTERNAL_HANDLE_FLAG_NONE;
896 psNewHandle->eFlag = eFlag;
897 psNewHandle->ui32Index = ui32NewIndex;
899 InitParentList(psBase, psNewHandle);
901 PVR_ASSERT(NoChildren(psBase, psNewHandle));
904 InitChildEntry(psBase, psNewHandle);
906 PVR_ASSERT(NoParent(psBase, psNewHandle));
909 if (HANDLES_BATCHED(psBase))
912 psNewHandle->ui32NextIndexPlusOne = psBase->ui32FirstBatchIndexPlusOne;
914 psBase->ui32FirstBatchIndexPlusOne = ui32NewIndex + 1;
917 SET_BATCHED_HANDLE(psNewHandle);
921 psNewHandle->ui32NextIndexPlusOne = 0;
930 PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag)
935 *phHandle = IMG_NULL;
937 if (HANDLES_BATCHED(psBase))
940 psBase->ui32BatchHandAllocFailures++;
944 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
946 if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
949 hHandle = FindHandle(psBase, pvData, eType, IMG_NULL);
950 if (hHandle != IMG_NULL)
952 struct sHandle *psHandle;
954 eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
955 if (eError != PVRSRV_OK)
957 PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandle: Lookup of existing handle failed"));
962 if (TEST_FLAG(psHandle->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED))
968 return PVRSRV_ERROR_GENERIC;
972 eError = AllocHandle(psBase, phHandle, pvData, eType, eFlag, IMG_NULL);
975 if (HANDLES_BATCHED(psBase) && (eError == PVRSRV_OK))
977 psBase->ui32BatchHandAllocFailures--;
983 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)
985 struct sHandle *psPHand;
986 struct sHandle *psCHand;
988 IMG_HANDLE hParentKey;
991 *phHandle = IMG_NULL;
993 if (HANDLES_BATCHED(psBase))
996 psBase->ui32BatchHandAllocFailures++;
1000 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1002 hParentKey = TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ?
1006 eError = GetHandleStructure(psBase, &psPHand, hParent, PVRSRV_HANDLE_TYPE_NONE);
1007 if (eError != PVRSRV_OK)
1009 return PVRSRV_ERROR_GENERIC;
1012 if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
1015 hHandle = FindHandle(psBase, pvData, eType, hParentKey);
1016 if (hHandle != IMG_NULL)
1018 struct sHandle *psCHandle;
1021 eErr = GetHandleStructure(psBase, &psCHandle, hHandle, eType);
1022 if (eErr != PVRSRV_OK)
1024 PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSubHandle: Lookup of existing handle failed"));
1028 PVR_ASSERT(hParentKey != IMG_NULL && ParentHandle(HANDLE_TO_HANDLE_PTR(psBase, hHandle)) == hParent);
1031 if (TEST_FLAG(psCHandle->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED) && ParentHandle(HANDLE_TO_HANDLE_PTR(psBase, hHandle)) == hParent)
1033 *phHandle = hHandle;
1036 return PVRSRV_ERROR_GENERIC;
1040 eError = AllocHandle(psBase, &hHandle, pvData, eType, eFlag, hParentKey);
1041 if (eError != PVRSRV_OK)
1047 psPHand = HANDLE_TO_HANDLE_PTR(psBase, hParent);
1049 psCHand = HANDLE_TO_HANDLE_PTR(psBase, hHandle);
1051 AdoptChild(psBase, psPHand, psCHand);
1053 *phHandle = hHandle;
1056 if (HANDLES_BATCHED(psBase))
1058 psBase->ui32BatchHandAllocFailures--;
1064 PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType)
1068 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1071 hHandle = (IMG_HANDLE) FindHandle(psBase, pvData, eType, IMG_NULL);
1072 if (hHandle == IMG_NULL)
1074 return PVRSRV_ERROR_GENERIC;
1077 *phHandle = hHandle;
1082 PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle)
1084 struct sHandle *psHandle;
1085 PVRSRV_ERROR eError;
1087 eError = GetHandleStructure(psBase, &psHandle, hHandle, PVRSRV_HANDLE_TYPE_NONE);
1088 if (eError != PVRSRV_OK)
1090 PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupHandleAnyType: Error looking up handle (%d)", eError));
1094 *ppvData = psHandle->pvData;
1095 *peType = psHandle->eType;
1100 PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
1102 struct sHandle *psHandle;
1103 PVRSRV_ERROR eError;
1105 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1107 eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
1108 if (eError != PVRSRV_OK)
1110 PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupHandle: Error looking up handle (%d)", eError));
1114 *ppvData = psHandle->pvData;
1119 PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hAncestor)
1121 struct sHandle *psPHand;
1122 struct sHandle *psCHand;
1123 PVRSRV_ERROR eError;
1125 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1127 eError = GetHandleStructure(psBase, &psCHand, hHandle, eType);
1128 if (eError != PVRSRV_OK)
1130 PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupSubHandle: Error looking up subhandle (%d)", eError));
1135 for (psPHand = psCHand; ParentHandle(psPHand) != hAncestor; )
1137 eError = GetHandleStructure(psBase, &psPHand, ParentHandle(psPHand), PVRSRV_HANDLE_TYPE_NONE);
1138 if (eError != PVRSRV_OK)
1140 PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupSubHandle: Subhandle doesn't belong to given ancestor"));
1141 return PVRSRV_ERROR_GENERIC;
1145 *ppvData = psCHand->pvData;
1150 PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
1152 struct sHandle *psHandle;
1153 PVRSRV_ERROR eError;
1155 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1157 eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
1158 if (eError != PVRSRV_OK)
1160 PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetParentHandle: Error looking up subhandle (%d)", eError));
1164 *phParent = ParentHandle(psHandle);
1169 PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
1171 struct sHandle *psHandle;
1172 PVRSRV_ERROR eError;
1174 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1176 eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
1177 if (eError != PVRSRV_OK)
1179 PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupAndReleaseHandle: Error looking up handle (%d)", eError));
1183 *ppvData = psHandle->pvData;
1185 eError = FreeHandle(psBase, psHandle);
1190 PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
1192 struct sHandle *psHandle;
1193 PVRSRV_ERROR eError;
1195 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1197 eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
1198 if (eError != PVRSRV_OK)
1200 PVR_DPF((PVR_DBG_ERROR, "PVRSRVReleaseHandle: Error looking up handle (%d)", eError));
1204 eError = FreeHandle(psBase, psHandle);
1209 PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32BatchSize)
1211 PVRSRV_ERROR eError;
1213 if (HANDLES_BATCHED(psBase))
1215 PVR_DPF((PVR_DBG_ERROR, "PVRSRVNewHandleBatch: There is a handle batch already in use (size %u)", psBase->ui32HandBatchSize));
1216 return PVRSRV_ERROR_GENERIC;
1219 if (ui32BatchSize == 0)
1221 PVR_DPF((PVR_DBG_ERROR, "PVRSRVNewHandleBatch: Invalid batch size (%u)", ui32BatchSize));
1222 return PVRSRV_ERROR_INVALID_PARAMS;
1225 eError = EnsureFreeHandles(psBase, ui32BatchSize);
1226 if (eError != PVRSRV_OK)
1228 PVR_DPF((PVR_DBG_ERROR, "PVRSRVNewHandleBatch: EnsureFreeHandles failed (error %d)", eError));
1232 psBase->ui32HandBatchSize = ui32BatchSize;
1235 psBase->ui32TotalHandCountPreBatch = psBase->ui32TotalHandCount;
1237 PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0);
1239 PVR_ASSERT(psBase->ui32FirstBatchIndexPlusOne == 0);
1241 PVR_ASSERT(HANDLES_BATCHED(psBase));
1246 static PVRSRV_ERROR PVRSRVHandleBatchCommitOrRelease(PVRSRV_HANDLE_BASE *psBase, IMG_BOOL bCommit)
1249 IMG_UINT32 ui32IndexPlusOne;
1250 IMG_BOOL bCommitBatch = bCommit;
1252 if (!HANDLES_BATCHED(psBase))
1254 PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: There is no handle batch"));
1255 return PVRSRV_ERROR_INVALID_PARAMS;
1259 if (psBase->ui32BatchHandAllocFailures != 0)
1263 PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: Attempting to commit batch with handle allocation failures."));
1265 bCommitBatch = IMG_FALSE;
1268 PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0 || !bCommit);
1270 ui32IndexPlusOne = psBase->ui32FirstBatchIndexPlusOne;
1271 while(ui32IndexPlusOne != 0)
1273 struct sHandle *psHandle = INDEX_TO_HANDLE_PTR(psBase, ui32IndexPlusOne - 1);
1274 IMG_UINT32 ui32NextIndexPlusOne = psHandle->ui32NextIndexPlusOne;
1275 PVR_ASSERT(BATCHED_HANDLE(psHandle));
1277 psHandle->ui32NextIndexPlusOne = 0;
1279 if (!bCommitBatch || BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
1281 PVRSRV_ERROR eError;
1284 if (!BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
1286 SET_UNBATCHED_HANDLE(psHandle);
1289 eError = FreeHandle(psBase, psHandle);
1290 if (eError != PVRSRV_OK)
1292 PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: Error freeing handle (%d)", eError));
1294 PVR_ASSERT(eError == PVRSRV_OK);
1298 SET_UNBATCHED_HANDLE(psHandle);
1301 ui32IndexPlusOne = ui32NextIndexPlusOne;
1305 if (psBase->ui32TotalHandCountPreBatch != psBase->ui32TotalHandCount)
1307 IMG_UINT32 ui32Delta = psBase->ui32TotalHandCount - psBase->ui32TotalHandCountPreBatch;
1309 PVR_ASSERT(psBase->ui32TotalHandCount > psBase->ui32TotalHandCountPreBatch);
1311 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));
1316 psBase->ui32HandBatchSize = 0;
1317 psBase->ui32FirstBatchIndexPlusOne = 0;
1318 psBase->ui32TotalHandCountPreBatch = 0;
1319 psBase->ui32BatchHandAllocFailures = 0;
1321 if (psBase->ui32BatchHandAllocFailures != 0 && bCommit)
1323 PVR_ASSERT(!bCommitBatch);
1325 return PVRSRV_ERROR_GENERIC;
1331 PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE *psBase)
1333 return PVRSRVHandleBatchCommitOrRelease(psBase, IMG_TRUE);
1336 IMG_VOID PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE *psBase)
1338 (IMG_VOID) PVRSRVHandleBatchCommitOrRelease(psBase, IMG_FALSE);
1341 PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHandle)
1343 if (HANDLES_BATCHED(psBase))
1345 PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit cannot be set whilst in batch mode"));
1346 return PVRSRV_ERROR_INVALID_PARAMS;
1350 if (ui32MaxHandle == 0 || ui32MaxHandle >= DEFAULT_MAX_HANDLE)
1352 PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit must be between %u and %u, inclusive", 0, DEFAULT_MAX_HANDLE));
1354 return PVRSRV_ERROR_INVALID_PARAMS;
1358 if (psBase->ui32TotalHandCount != 0)
1360 PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit cannot be set becuase handles have already been allocated"));
1362 return PVRSRV_ERROR_INVALID_PARAMS;
1365 psBase->ui32MaxIndexPlusOne = ui32MaxHandle;
1370 IMG_UINT32 PVRSRVGetMaxHandle(PVRSRV_HANDLE_BASE *psBase)
1372 return psBase->ui32MaxIndexPlusOne;
1375 PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase)
1377 if (psBase->bPurgingEnabled)
1379 PVR_DPF((PVR_DBG_WARNING, "PVRSRVEnableHandlePurging: Purging already enabled"));
1384 if (psBase->ui32TotalHandCount != 0)
1386 PVR_DPF((PVR_DBG_ERROR, "PVRSRVEnableHandlePurging: Handles have already been allocated"));
1387 return PVRSRV_ERROR_INVALID_PARAMS;
1390 psBase->bPurgingEnabled = IMG_TRUE;
1395 PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase)
1397 IMG_UINT32 ui32Handle;
1398 IMG_UINT32 ui32NewHandCount;
1400 if (!psBase->bPurgingEnabled)
1402 PVR_DPF((PVR_DBG_ERROR, "PVRSRVPurgeHandles: Purging not enabled for this handle base"));
1403 return PVRSRV_ERROR_NOT_SUPPORTED;
1406 if (HANDLES_BATCHED(psBase))
1408 PVR_DPF((PVR_DBG_ERROR, "PVRSRVPurgeHandles: Purging not allowed whilst in batch mode"));
1409 return PVRSRV_ERROR_INVALID_PARAMS;
1412 for (ui32Handle = psBase->ui32TotalHandCount; ui32Handle != 0; ui32Handle--)
1414 struct sHandle *psHandle = HANDLE_TO_HANDLE_PTR(psBase, ui32Handle);
1415 if (!HANDLE_STRUCT_IS_FREE(psHandle))
1421 ui32NewHandCount = ROUND_UP_TO_MULTIPLE(ui32Handle, HANDLE_BLOCK_SIZE);
1424 if (ui32NewHandCount >= ui32Handle && ui32NewHandCount <= (psBase->ui32TotalHandCount/2))
1426 IMG_UINT32 ui32Delta = psBase->ui32TotalHandCount - ui32NewHandCount;
1427 PVRSRV_ERROR eError;
1431 eError = ReallocHandleArray(psBase, ui32NewHandCount, psBase->ui32TotalHandCount);
1432 if (eError != PVRSRV_OK)
1438 psBase->ui32TotalHandCount = ui32NewHandCount;
1439 psBase->ui32FreeHandCount -= ui32Delta;
1440 psBase->ui32FirstFreeIndex = 0;
1446 PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase)
1448 PVRSRV_HANDLE_BASE *psBase;
1449 IMG_HANDLE hBlockAlloc;
1450 PVRSRV_ERROR eError;
1452 eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
1454 (IMG_PVOID *)&psBase,
1457 if (eError != PVRSRV_OK)
1459 PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandleBase: Couldn't allocate handle base (%d)", eError));
1462 OSMemSet(psBase, 0, sizeof(*psBase));
1465 psBase->psHashTab = HASH_Create_Extended(HANDLE_HASH_TAB_INIT_SIZE, sizeof(HAND_KEY), HASH_Func_Default, HASH_Key_Comp_Default);
1466 if (psBase->psHashTab == IMG_NULL)
1468 PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandleBase: Couldn't create data pointer hash table\n"));
1472 psBase->hBaseBlockAlloc = hBlockAlloc;
1474 psBase->ui32MaxIndexPlusOne = DEFAULT_MAX_INDEX_PLUS_ONE;
1480 (IMG_VOID)PVRSRVFreeHandleBase(psBase);
1481 return PVRSRV_ERROR_GENERIC;
1484 PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
1486 PVRSRV_ERROR eError;
1488 PVR_ASSERT(psBase != gpsKernelHandleBase);
1490 eError = FreeHandleBase(psBase);
1491 if (eError != PVRSRV_OK)
1493 PVR_DPF((PVR_DBG_ERROR, "PVRSRVFreeHandleBase: FreeHandleBase failed (%d)", eError));
1499 PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID)
1501 PVRSRV_ERROR eError;
1503 PVR_ASSERT(gpsKernelHandleBase == IMG_NULL);
1505 eError = PVRSRVAllocHandleBase(&gpsKernelHandleBase);
1506 if (eError != PVRSRV_OK)
1508 PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleInit: PVRSRVAllocHandleBase failed (%d)", eError));
1512 eError = PVRSRVEnableHandlePurging(gpsKernelHandleBase);
1513 if (eError != PVRSRV_OK)
1515 PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleInit: PVRSRVEnableHandlePurging failed (%d)", eError));
1521 (IMG_VOID) PVRSRVHandleDeInit();
1525 PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID)
1527 PVRSRV_ERROR eError = PVRSRV_OK;
1529 if (gpsKernelHandleBase != IMG_NULL)
1531 eError = FreeHandleBase(gpsKernelHandleBase);
1532 if (eError == PVRSRV_OK)
1534 gpsKernelHandleBase = IMG_NULL;
1538 PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleDeInit: FreeHandleBase failed (%d)", eError));