aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/pvr/handle.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/pvr/handle.c')
-rw-r--r--drivers/gpu/pvr/handle.c1723
1 files changed, 1723 insertions, 0 deletions
diff --git a/drivers/gpu/pvr/handle.c b/drivers/gpu/pvr/handle.c
new file mode 100644
index 00000000000..5e34af5b280
--- /dev/null
+++ b/drivers/gpu/pvr/handle.c
@@ -0,0 +1,1723 @@
1/**********************************************************************
2 *
3 * Copyright(c) 2008 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
27#ifdef PVR_SECURE_HANDLES
28#include <stddef.h>
29
30#include "services_headers.h"
31#include "handle.h"
32
33#ifdef DEBUG
34#define HANDLE_BLOCK_SHIFT 2
35#else
36#define HANDLE_BLOCK_SHIFT 8
37#endif
38
39#define DIVIDE_BY_BLOCK_SIZE(i) (((IMG_UINT32)(i)) >> HANDLE_BLOCK_SHIFT)
40#define MULTIPLY_BY_BLOCK_SIZE(i) (((IMG_UINT32)(i)) << HANDLE_BLOCK_SHIFT)
41
42#define HANDLE_BLOCK_SIZE MULTIPLY_BY_BLOCK_SIZE(1)
43#define HANDLE_SUB_BLOCK_MASK (HANDLE_BLOCK_SIZE - 1)
44#define HANDLE_BLOCK_MASK (~(HANDLE_SUB_BLOCK_MASK))
45
46#define HANDLE_HASH_TAB_INIT_SIZE 32
47
48#define INDEX_IS_VALID(psBase, i) ((i) < (psBase)->ui32TotalHandCount)
49
50#define INDEX_TO_HANDLE(i) ((IMG_HANDLE)((i) + 1))
51#define HANDLE_TO_INDEX(h) ((IMG_UINT32)(h) - 1)
52
53#define INDEX_TO_BLOCK_INDEX(i) DIVIDE_BY_BLOCK_SIZE(i)
54#define BLOCK_INDEX_TO_INDEX(i) MULTIPLY_BY_BLOCK_SIZE(i)
55#define INDEX_TO_SUB_BLOCK_INDEX(i) ((i) & HANDLE_SUB_BLOCK_MASK)
56
57#define INDEX_TO_INDEX_STRUCT_PTR(psArray, i) (&((psArray)[INDEX_TO_BLOCK_INDEX(i)]))
58#define BASE_AND_INDEX_TO_INDEX_STRUCT_PTR(psBase, i) INDEX_TO_INDEX_STRUCT_PTR((psBase)->psHandleArray, i)
59
60#define INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, i) (BASE_AND_INDEX_TO_INDEX_STRUCT_PTR(psBase, i)->ui32FreeHandBlockCount)
61
62#define INDEX_TO_HANDLE_STRUCT_PTR(psBase, i) (BASE_AND_INDEX_TO_INDEX_STRUCT_PTR(psBase, i)->psHandle + INDEX_TO_SUB_BLOCK_INDEX(i))
63
64#define HANDLE_TO_HANDLE_STRUCT_PTR(psBase, h) (INDEX_TO_HANDLE_STRUCT_PTR(psBase, HANDLE_TO_INDEX(h)))
65
66#define HANDLE_PTR_TO_INDEX(psHandle) ((psHandle)->ui32Index)
67#define HANDLE_PTR_TO_HANDLE(psHandle) INDEX_TO_HANDLE(HANDLE_PTR_TO_INDEX(psHandle))
68
69#define ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(a) (HANDLE_BLOCK_MASK & (a))
70#define ROUND_UP_TO_MULTIPLE_OF_BLOCK_SIZE(a) ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE((a) + HANDLE_BLOCK_SIZE - 1)
71
72#define DEFAULT_MAX_HANDLE 0x7fffffffu
73#define DEFAULT_MAX_INDEX_PLUS_ONE ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(DEFAULT_MAX_HANDLE)
74
75#define HANDLES_BATCHED(psBase) ((psBase)->ui32HandBatchSize != 0)
76
77#define HANDLE_ARRAY_SIZE(handleCount) DIVIDE_BY_BLOCK_SIZE(ROUND_UP_TO_MULTIPLE_OF_BLOCK_SIZE(handleCount))
78
79#define SET_FLAG(v, f) ((IMG_VOID)((v) |= (f)))
80#define CLEAR_FLAG(v, f) ((IMG_VOID)((v) &= ~(f)))
81#define TEST_FLAG(v, f) ((IMG_BOOL)(((v) & (f)) != 0))
82
83#define TEST_ALLOC_FLAG(psHandle, f) TEST_FLAG((psHandle)->eFlag, f)
84
85#define SET_INTERNAL_FLAG(psHandle, f) SET_FLAG((psHandle)->eInternalFlag, f)
86#define CLEAR_INTERNAL_FLAG(psHandle, f) CLEAR_FLAG((psHandle)->eInternalFlag, f)
87#define TEST_INTERNAL_FLAG(psHandle, f) TEST_FLAG((psHandle)->eInternalFlag, f)
88
89#define BATCHED_HANDLE(psHandle) TEST_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
90
91#define SET_BATCHED_HANDLE(psHandle) SET_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
92
93#define SET_UNBATCHED_HANDLE(psHandle) CLEAR_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
94
95#define BATCHED_HANDLE_PARTIALLY_FREE(psHandle) TEST_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE)
96
97#define SET_BATCHED_HANDLE_PARTIALLY_FREE(psHandle) SET_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE)
98
99#define HANDLE_STRUCT_IS_FREE(psHandle) ((psHandle)->eType == PVRSRV_HANDLE_TYPE_NONE && (psHandle)->eInternalFlag == INTERNAL_HANDLE_FLAG_NONE)
100
101#ifdef MIN
102#undef MIN
103#endif
104
105#define MIN(x, y) (((x) < (y)) ? (x) : (y))
106
107struct sHandleList
108{
109 IMG_UINT32 ui32Prev;
110 IMG_UINT32 ui32Next;
111 IMG_HANDLE hParent;
112};
113
114enum ePVRSRVInternalHandleFlag
115{
116 INTERNAL_HANDLE_FLAG_NONE = 0x00,
117 INTERNAL_HANDLE_FLAG_BATCHED = 0x01,
118 INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE = 0x02,
119};
120
121struct sHandle
122{
123
124 PVRSRV_HANDLE_TYPE eType;
125
126
127 IMG_VOID *pvData;
128
129
130 IMG_UINT32 ui32NextIndexPlusOne;
131
132
133 enum ePVRSRVInternalHandleFlag eInternalFlag;
134
135
136 PVRSRV_HANDLE_ALLOC_FLAG eFlag;
137
138
139 IMG_UINT32 ui32Index;
140
141
142 struct sHandleList sChildren;
143
144
145 struct sHandleList sSiblings;
146};
147
148struct sHandleIndex
149{
150
151 struct sHandle *psHandle;
152
153
154 IMG_HANDLE hBlockAlloc;
155
156
157 IMG_UINT32 ui32FreeHandBlockCount;
158};
159
160struct _PVRSRV_HANDLE_BASE_
161{
162
163 IMG_HANDLE hBaseBlockAlloc;
164
165
166 IMG_HANDLE hArrayBlockAlloc;
167
168
169 struct sHandleIndex *psHandleArray;
170
171
172 HASH_TABLE *psHashTab;
173
174
175 IMG_UINT32 ui32FreeHandCount;
176
177
178 IMG_UINT32 ui32FirstFreeIndex;
179
180
181 IMG_UINT32 ui32MaxIndexPlusOne;
182
183
184 IMG_UINT32 ui32TotalHandCount;
185
186
187 IMG_UINT32 ui32LastFreeIndexPlusOne;
188
189
190 IMG_UINT32 ui32HandBatchSize;
191
192
193 IMG_UINT32 ui32TotalHandCountPreBatch;
194
195
196 IMG_UINT32 ui32FirstBatchIndexPlusOne;
197
198
199 IMG_UINT32 ui32BatchHandAllocFailures;
200
201
202 IMG_BOOL bPurgingEnabled;
203};
204
205enum eHandKey {
206 HAND_KEY_DATA = 0,
207 HAND_KEY_TYPE,
208 HAND_KEY_PARENT,
209 HAND_KEY_LEN
210};
211
212PVRSRV_HANDLE_BASE *gpsKernelHandleBase = IMG_NULL;
213
214typedef IMG_UINTPTR_T HAND_KEY[HAND_KEY_LEN];
215
216#ifdef INLINE_IS_PRAGMA
217#pragma inline(HandleListInit)
218#endif
219static INLINE
220IMG_VOID HandleListInit(IMG_UINT32 ui32Index, struct sHandleList *psList, IMG_HANDLE hParent)
221{
222 psList->ui32Next = ui32Index;
223 psList->ui32Prev = ui32Index;
224 psList->hParent = hParent;
225}
226
227#ifdef INLINE_IS_PRAGMA
228#pragma inline(InitParentList)
229#endif
230static INLINE
231IMG_VOID InitParentList(struct sHandle *psHandle)
232{
233 IMG_UINT32 ui32Parent = HANDLE_PTR_TO_INDEX(psHandle);
234
235 HandleListInit(ui32Parent, &psHandle->sChildren, INDEX_TO_HANDLE(ui32Parent));
236}
237
238#ifdef INLINE_IS_PRAGMA
239#pragma inline(InitChildEntry)
240#endif
241static INLINE
242IMG_VOID InitChildEntry(struct sHandle *psHandle)
243{
244 HandleListInit(HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sSiblings, IMG_NULL);
245}
246
247#ifdef INLINE_IS_PRAGMA
248#pragma inline(HandleListIsEmpty)
249#endif
250static INLINE
251IMG_BOOL HandleListIsEmpty(IMG_UINT32 ui32Index, struct sHandleList *psList)
252{
253 IMG_BOOL bIsEmpty;
254
255 bIsEmpty = (IMG_BOOL)(psList->ui32Next == ui32Index);
256
257#ifdef DEBUG
258 {
259 IMG_BOOL bIsEmpty2;
260
261 bIsEmpty2 = (IMG_BOOL)(psList->ui32Prev == ui32Index);
262 PVR_ASSERT(bIsEmpty == bIsEmpty2);
263 }
264#endif
265
266 return bIsEmpty;
267}
268
269#ifdef DEBUG
270#ifdef INLINE_IS_PRAGMA
271#pragma inline(NoChildren)
272#endif
273static INLINE
274IMG_BOOL NoChildren(struct sHandle *psHandle)
275{
276 PVR_ASSERT(psHandle->sChildren.hParent == HANDLE_PTR_TO_HANDLE(psHandle));
277
278 return HandleListIsEmpty(HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sChildren);
279}
280
281#ifdef INLINE_IS_PRAGMA
282#pragma inline(NoParent)
283#endif
284static INLINE
285IMG_BOOL NoParent(struct sHandle *psHandle)
286{
287 if (HandleListIsEmpty(HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sSiblings))
288 {
289 PVR_ASSERT(psHandle->sSiblings.hParent == IMG_NULL);
290
291 return IMG_TRUE;
292 }
293 else
294 {
295 PVR_ASSERT(psHandle->sSiblings.hParent != IMG_NULL);
296 }
297 return IMG_FALSE;
298}
299#endif
300#ifdef INLINE_IS_PRAGMA
301#pragma inline(ParentHandle)
302#endif
303static INLINE
304IMG_HANDLE ParentHandle(struct sHandle *psHandle)
305{
306 return psHandle->sSiblings.hParent;
307}
308
309#define LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, i, p, po, eo) \
310 ((struct sHandleList *)((IMG_CHAR *)(INDEX_TO_HANDLE_STRUCT_PTR(psBase, i)) + (((i) == (p)) ? (po) : (eo))))
311
312#ifdef INLINE_IS_PRAGMA
313#pragma inline(HandleListInsertBefore)
314#endif
315static INLINE
316IMG_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)
317{
318
319 struct sHandleList *psPrevIns = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psIns->ui32Prev, ui32ParentIndex, uiParentOffset, uiEntryOffset);
320
321 PVR_ASSERT(psEntry->hParent == IMG_NULL);
322 PVR_ASSERT(ui32InsIndex == psPrevIns->ui32Next);
323 PVR_ASSERT(LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32ParentIndex, ui32ParentIndex, uiParentOffset, uiParentOffset)->hParent == INDEX_TO_HANDLE(ui32ParentIndex));
324
325 psEntry->ui32Prev = psIns->ui32Prev;
326 psIns->ui32Prev = ui32EntryIndex;
327 psEntry->ui32Next = ui32InsIndex;
328 psPrevIns->ui32Next = ui32EntryIndex;
329
330 psEntry->hParent = INDEX_TO_HANDLE(ui32ParentIndex);
331}
332
333#ifdef INLINE_IS_PRAGMA
334#pragma inline(AdoptChild)
335#endif
336static INLINE
337IMG_VOID AdoptChild(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psParent, struct sHandle *psChild)
338{
339 IMG_UINT32 ui32Parent = HANDLE_TO_INDEX(psParent->sChildren.hParent);
340
341 PVR_ASSERT(ui32Parent == HANDLE_PTR_TO_INDEX(psParent));
342
343 HandleListInsertBefore(psBase, ui32Parent, &psParent->sChildren, offsetof(struct sHandle, sChildren), HANDLE_PTR_TO_INDEX(psChild), &psChild->sSiblings, offsetof(struct sHandle, sSiblings), ui32Parent);
344
345}
346
347#ifdef INLINE_IS_PRAGMA
348#pragma inline(HandleListRemove)
349#endif
350static INLINE
351IMG_VOID HandleListRemove(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32EntryIndex, struct sHandleList *psEntry, IMG_SIZE_T uiEntryOffset, IMG_SIZE_T uiParentOffset)
352{
353 if (!HandleListIsEmpty(ui32EntryIndex, psEntry))
354 {
355
356 struct sHandleList *psPrev = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Prev, HANDLE_TO_INDEX(psEntry->hParent), uiParentOffset, uiEntryOffset);
357 struct sHandleList *psNext = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Next, HANDLE_TO_INDEX(psEntry->hParent), uiParentOffset, uiEntryOffset);
358
359
360 PVR_ASSERT(psEntry->hParent != IMG_NULL);
361
362 psPrev->ui32Next = psEntry->ui32Next;
363 psNext->ui32Prev = psEntry->ui32Prev;
364
365 HandleListInit(ui32EntryIndex, psEntry, IMG_NULL);
366 }
367}
368
369#ifdef INLINE_IS_PRAGMA
370#pragma inline(UnlinkFromParent)
371#endif
372static INLINE
373IMG_VOID UnlinkFromParent(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
374{
375 HandleListRemove(psBase, HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sSiblings, offsetof(struct sHandle, sSiblings), offsetof(struct sHandle, sChildren));
376}
377
378#ifdef INLINE_IS_PRAGMA
379#pragma inline(HandleListIterate)
380#endif
381static INLINE
382PVRSRV_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 *))
383{
384 IMG_UINT32 ui32Index;
385 IMG_UINT32 ui32Parent = HANDLE_TO_INDEX(psHead->hParent);
386
387 PVR_ASSERT(psHead->hParent != IMG_NULL);
388
389
390 for(ui32Index = psHead->ui32Next; ui32Index != ui32Parent; )
391 {
392 struct sHandle *psHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32Index);
393
394 struct sHandleList *psEntry = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32Index, ui32Parent, uiParentOffset, uiEntryOffset);
395 PVRSRV_ERROR eError;
396
397 PVR_ASSERT(psEntry->hParent == psHead->hParent);
398
399 ui32Index = psEntry->ui32Next;
400
401 eError = (*pfnIterFunc)(psBase, psHandle);
402 if (eError != PVRSRV_OK)
403 {
404 return eError;
405 }
406 }
407
408 return PVRSRV_OK;
409}
410
411#ifdef INLINE_IS_PRAGMA
412#pragma inline(IterateOverChildren)
413#endif
414static INLINE
415PVRSRV_ERROR IterateOverChildren(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psParent, PVRSRV_ERROR (*pfnIterFunc)(PVRSRV_HANDLE_BASE *, struct sHandle *))
416{
417 return HandleListIterate(psBase, &psParent->sChildren, offsetof(struct sHandle, sChildren), offsetof(struct sHandle, sSiblings), pfnIterFunc);
418}
419
420#ifdef INLINE_IS_PRAGMA
421#pragma inline(GetHandleStructure)
422#endif
423static INLINE
424PVRSRV_ERROR GetHandleStructure(PVRSRV_HANDLE_BASE *psBase, struct sHandle **ppsHandle, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
425{
426 IMG_UINT32 ui32Index = HANDLE_TO_INDEX(hHandle);
427 struct sHandle *psHandle;
428
429
430 if (!INDEX_IS_VALID(psBase, ui32Index))
431 {
432 PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle index out of range (%u >= %u)", ui32Index, psBase->ui32TotalHandCount));
433 return PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE;
434 }
435
436 psHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32Index);
437 if (psHandle->eType == PVRSRV_HANDLE_TYPE_NONE)
438 {
439 PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle not allocated (index: %u)", ui32Index));
440 return PVRSRV_ERROR_HANDLE_NOT_ALLOCATED;
441 }
442
443
444 if (eType != PVRSRV_HANDLE_TYPE_NONE && eType != psHandle->eType)
445 {
446 PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle type mismatch (%d != %d)", eType, psHandle->eType));
447 return PVRSRV_ERROR_HANDLE_TYPE_MISMATCH;
448 }
449
450
451 *ppsHandle = psHandle;
452
453 return PVRSRV_OK;
454}
455
456#ifdef INLINE_IS_PRAGMA
457#pragma inline(ParentIfPrivate)
458#endif
459static INLINE
460IMG_HANDLE ParentIfPrivate(struct sHandle *psHandle)
461{
462 return TEST_ALLOC_FLAG(psHandle, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ?
463 ParentHandle(psHandle) : IMG_NULL;
464}
465
466#ifdef INLINE_IS_PRAGMA
467#pragma inline(InitKey)
468#endif
469static INLINE
470IMG_VOID InitKey(HAND_KEY aKey, PVRSRV_HANDLE_BASE *psBase, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hParent)
471{
472 PVR_UNREFERENCED_PARAMETER(psBase);
473
474 aKey[HAND_KEY_DATA] = (IMG_UINTPTR_T)pvData;
475 aKey[HAND_KEY_TYPE] = (IMG_UINTPTR_T)eType;
476 aKey[HAND_KEY_PARENT] = (IMG_UINTPTR_T)hParent;
477}
478
479static
480PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCount)
481{
482 struct sHandleIndex *psOldArray = psBase->psHandleArray;
483 IMG_HANDLE hOldArrayBlockAlloc = psBase->hArrayBlockAlloc;
484 IMG_UINT32 ui32OldCount = psBase->ui32TotalHandCount;
485 struct sHandleIndex *psNewArray = IMG_NULL;
486 IMG_HANDLE hNewArrayBlockAlloc = IMG_NULL;
487 PVRSRV_ERROR eError;
488 PVRSRV_ERROR eReturn = PVRSRV_OK;
489 IMG_UINT32 ui32Index;
490
491 if (ui32NewCount == ui32OldCount)
492 {
493 return PVRSRV_OK;
494 }
495
496 if (ui32NewCount != 0 && !psBase->bPurgingEnabled &&
497 ui32NewCount < ui32OldCount)
498 {
499 return PVRSRV_ERROR_INVALID_PARAMS;
500 }
501
502 if (((ui32OldCount % HANDLE_BLOCK_SIZE) != 0) ||
503 ((ui32NewCount % HANDLE_BLOCK_SIZE) != 0))
504 {
505 PVR_ASSERT((ui32OldCount % HANDLE_BLOCK_SIZE) == 0);
506 PVR_ASSERT((ui32NewCount % HANDLE_BLOCK_SIZE) == 0);
507
508 return PVRSRV_ERROR_INVALID_PARAMS;
509 }
510
511 if (ui32NewCount != 0)
512 {
513
514 eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
515 HANDLE_ARRAY_SIZE(ui32NewCount) * sizeof(struct sHandleIndex),
516 (IMG_VOID **)&psNewArray,
517 &hNewArrayBlockAlloc,
518 "Memory Area");
519 if (eError != PVRSRV_OK)
520 {
521 PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't allocate new handle array (%d)", eError));
522 eReturn = eError;
523 goto error;
524 }
525
526 if (ui32OldCount != 0)
527 {
528 OSMemCopy(psNewArray, psOldArray, HANDLE_ARRAY_SIZE(MIN(ui32NewCount, ui32OldCount)) * sizeof(struct sHandleIndex));
529 }
530 }
531
532
533 for(ui32Index = ui32NewCount; ui32Index < ui32OldCount; ui32Index += HANDLE_BLOCK_SIZE)
534 {
535 struct sHandleIndex *psIndex = INDEX_TO_INDEX_STRUCT_PTR(psOldArray, ui32Index);
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
548 for(ui32Index = ui32OldCount; ui32Index < ui32NewCount; ui32Index += HANDLE_BLOCK_SIZE)
549 {
550
551 struct sHandleIndex *psIndex = INDEX_TO_INDEX_STRUCT_PTR(psNewArray, ui32Index);
552
553 eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
554 sizeof(struct sHandle) * HANDLE_BLOCK_SIZE,
555 (IMG_VOID **)&psIndex->psHandle,
556 &psIndex->hBlockAlloc,
557 "Memory Area");
558 if (eError != PVRSRV_OK)
559 {
560 psIndex->psHandle = IMG_NULL;
561 PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't allocate handle structures (%d)", eError));
562 eReturn = eError;
563 }
564 else
565 {
566 IMG_UINT32 ui32SubIndex;
567
568 psIndex->ui32FreeHandBlockCount = HANDLE_BLOCK_SIZE;
569
570 for(ui32SubIndex = 0; ui32SubIndex < HANDLE_BLOCK_SIZE; ui32SubIndex++)
571 {
572 struct sHandle *psHandle = psIndex->psHandle + ui32SubIndex;
573
574
575 psHandle->ui32Index = ui32SubIndex + ui32Index;
576 psHandle->eType = PVRSRV_HANDLE_TYPE_NONE;
577 psHandle->eInternalFlag = INTERNAL_HANDLE_FLAG_NONE;
578 psHandle->ui32NextIndexPlusOne = 0;
579 }
580 }
581 }
582 if (eReturn != PVRSRV_OK)
583 {
584 goto error;
585 }
586
587#ifdef DEBUG_MAX_HANDLE_COUNT
588
589 if (ui32NewCount > DEBUG_MAX_HANDLE_COUNT)
590 {
591 PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Max handle count (%u) reached", DEBUG_MAX_HANDLE_COUNT));
592 eReturn = PVRSRV_ERROR_OUT_OF_MEMORY;
593 goto error;
594 }
595#endif
596
597 if (psOldArray != IMG_NULL)
598 {
599
600 eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
601 HANDLE_ARRAY_SIZE(ui32OldCount) * sizeof(struct sHandleIndex),
602 psOldArray,
603 hOldArrayBlockAlloc);
604 if (eError != PVRSRV_OK)
605 {
606 PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't free old handle array (%d)", eError));
607 }
608 }
609
610 psBase->psHandleArray = psNewArray;
611 psBase->hArrayBlockAlloc = hNewArrayBlockAlloc;
612 psBase->ui32TotalHandCount = ui32NewCount;
613
614 if (ui32NewCount > ui32OldCount)
615 {
616
617 PVR_ASSERT(psBase->ui32FreeHandCount + (ui32NewCount - ui32OldCount) > psBase->ui32FreeHandCount)
618
619
620 psBase->ui32FreeHandCount += (ui32NewCount - ui32OldCount);
621
622
623 if (psBase->ui32FirstFreeIndex == 0)
624 {
625 PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0)
626
627 psBase->ui32FirstFreeIndex = ui32OldCount;
628 }
629 else
630 {
631 if (!psBase->bPurgingEnabled)
632 {
633 PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0)
634 PVR_ASSERT(INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0)
635
636 INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne = ui32OldCount + 1;
637 }
638 }
639
640 if (!psBase->bPurgingEnabled)
641 {
642 psBase->ui32LastFreeIndexPlusOne = ui32NewCount;
643 }
644 }
645 else
646 {
647 PVR_ASSERT(ui32NewCount == 0 || psBase->bPurgingEnabled)
648 PVR_ASSERT(ui32NewCount == 0 || psBase->ui32FirstFreeIndex <= ui32NewCount)
649 PVR_ASSERT(psBase->ui32FreeHandCount - (ui32OldCount - ui32NewCount) < psBase->ui32FreeHandCount)
650
651
652 psBase->ui32FreeHandCount -= (ui32OldCount - ui32NewCount);
653
654 if (ui32NewCount == 0)
655 {
656 psBase->ui32FirstFreeIndex = 0;
657 psBase->ui32LastFreeIndexPlusOne = 0;
658 }
659 }
660
661 PVR_ASSERT(psBase->ui32FirstFreeIndex <= psBase->ui32TotalHandCount);
662
663 return PVRSRV_OK;
664
665error:
666 PVR_ASSERT(eReturn != PVRSRV_OK);
667
668 if (psNewArray != IMG_NULL)
669 {
670
671 for(ui32Index = ui32OldCount; ui32Index < ui32NewCount; ui32Index += HANDLE_BLOCK_SIZE)
672 {
673 struct sHandleIndex *psIndex = INDEX_TO_INDEX_STRUCT_PTR(psNewArray, ui32Index);
674 if (psIndex->psHandle != IMG_NULL)
675 {
676 eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
677 sizeof(struct sHandle) * HANDLE_BLOCK_SIZE,
678 psIndex->psHandle,
679 psIndex->hBlockAlloc);
680 if (eError != PVRSRV_OK)
681 {
682 PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't free handle structures (%d)", eError));
683 }
684 }
685 }
686
687
688 eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
689 HANDLE_ARRAY_SIZE(ui32NewCount) * sizeof(struct sHandleIndex),
690 psNewArray,
691 hNewArrayBlockAlloc);
692 if (eError != PVRSRV_OK)
693 {
694 PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't free new handle array (%d)", eError));
695 }
696 }
697
698 return eReturn;
699}
700
701static PVRSRV_ERROR FreeHandleArray(PVRSRV_HANDLE_BASE *psBase)
702{
703 return ReallocHandleArray(psBase, 0);
704}
705
706static PVRSRV_ERROR FreeHandle(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
707{
708 HAND_KEY aKey;
709 IMG_UINT32 ui32Index = HANDLE_PTR_TO_INDEX(psHandle);
710 PVRSRV_ERROR eError;
711
712
713 InitKey(aKey, psBase, psHandle->pvData, psHandle->eType, ParentIfPrivate(psHandle));
714
715 if (!TEST_ALLOC_FLAG(psHandle, PVRSRV_HANDLE_ALLOC_FLAG_MULTI) && !BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
716 {
717 IMG_HANDLE hHandle;
718 hHandle = (IMG_HANDLE) HASH_Remove_Extended(psBase->psHashTab, aKey);
719
720 PVR_ASSERT(hHandle != IMG_NULL);
721 PVR_ASSERT(hHandle == INDEX_TO_HANDLE(ui32Index));
722 PVR_UNREFERENCED_PARAMETER(hHandle);
723 }
724
725
726 UnlinkFromParent(psBase, psHandle);
727
728
729 eError = IterateOverChildren(psBase, psHandle, FreeHandle);
730 if (eError != PVRSRV_OK)
731 {
732 PVR_DPF((PVR_DBG_ERROR, "FreeHandle: Error whilst freeing subhandles (%d)", eError));
733 return eError;
734 }
735
736
737 psHandle->eType = PVRSRV_HANDLE_TYPE_NONE;
738
739 if (BATCHED_HANDLE(psHandle) && !BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
740 {
741
742 SET_BATCHED_HANDLE_PARTIALLY_FREE(psHandle);
743
744 return PVRSRV_OK;
745 }
746
747
748 if (!psBase->bPurgingEnabled)
749 {
750 if (psBase->ui32FreeHandCount == 0)
751 {
752 PVR_ASSERT(psBase->ui32FirstFreeIndex == 0);
753 PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0);
754
755 psBase->ui32FirstFreeIndex = ui32Index;
756 }
757 else
758 {
759
760 PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0);
761 PVR_ASSERT(INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0);
762 INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne = ui32Index + 1;
763 }
764
765 PVR_ASSERT(psHandle->ui32NextIndexPlusOne == 0);
766
767
768 psBase->ui32LastFreeIndexPlusOne = ui32Index + 1;
769 }
770
771 psBase->ui32FreeHandCount++;
772 INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32Index)++;
773
774 PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32Index)<= HANDLE_BLOCK_SIZE);
775
776#ifdef DEBUG
777 {
778 IMG_UINT32 ui32BlockedIndex;
779 IMG_UINT32 ui32FreeHandCount = 0;
780
781 for (ui32BlockedIndex = 0; ui32BlockedIndex < psBase->ui32TotalHandCount; ui32BlockedIndex += HANDLE_BLOCK_SIZE)
782 {
783 ui32FreeHandCount += INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32BlockedIndex);
784 }
785
786 PVR_ASSERT(ui32FreeHandCount == psBase->ui32FreeHandCount);
787 }
788#endif
789
790 return PVRSRV_OK;
791}
792
793static PVRSRV_ERROR FreeAllHandles(PVRSRV_HANDLE_BASE *psBase)
794{
795 IMG_UINT32 i;
796 PVRSRV_ERROR eError = PVRSRV_OK;
797
798 if (psBase->ui32FreeHandCount == psBase->ui32TotalHandCount)
799 {
800 return eError;
801 }
802
803 for (i = 0; i < psBase->ui32TotalHandCount; i++)
804 {
805 struct sHandle *psHandle;
806
807 psHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, i);
808
809 if (psHandle->eType != PVRSRV_HANDLE_TYPE_NONE)
810 {
811 eError = FreeHandle(psBase, psHandle);
812 if (eError != PVRSRV_OK)
813 {
814 PVR_DPF((PVR_DBG_ERROR, "FreeAllHandles: FreeHandle failed (%d)", eError));
815 break;
816 }
817
818
819 if (psBase->ui32FreeHandCount == psBase->ui32TotalHandCount)
820 {
821 break;
822 }
823 }
824 }
825
826 return eError;
827}
828
829static PVRSRV_ERROR FreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
830{
831 PVRSRV_ERROR eError;
832
833 if (HANDLES_BATCHED(psBase))
834 {
835 PVR_DPF((PVR_DBG_WARNING, "FreeHandleBase: Uncommitted/Unreleased handle batch"));
836 PVRSRVReleaseHandleBatch(psBase);
837 }
838
839
840 eError = FreeAllHandles(psBase);
841 if (eError != PVRSRV_OK)
842 {
843 PVR_DPF((PVR_DBG_ERROR, "FreeHandleBase: Couldn't free handles (%d)", eError));
844 return eError;
845 }
846
847
848 eError = FreeHandleArray(psBase);
849 if (eError != PVRSRV_OK)
850 {
851 PVR_DPF((PVR_DBG_ERROR, "FreeHandleBase: Couldn't free handle array (%d)", eError));
852 return eError;
853 }
854
855 if (psBase->psHashTab != IMG_NULL)
856 {
857
858 HASH_Delete(psBase->psHashTab);
859 }
860
861 eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
862 sizeof(*psBase),
863 psBase,
864 psBase->hBaseBlockAlloc);
865 if (eError != PVRSRV_OK)
866 {
867 PVR_DPF((PVR_DBG_ERROR, "FreeHandleBase: Couldn't free handle base (%d)", eError));
868 return eError;
869 }
870
871 return PVRSRV_OK;
872}
873
874#ifdef INLINE_IS_PRAGMA
875#pragma inline(FindHandle)
876#endif
877static INLINE
878IMG_HANDLE FindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hParent)
879{
880 HAND_KEY aKey;
881
882 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
883
884 InitKey(aKey, psBase, pvData, eType, hParent);
885
886 return (IMG_HANDLE) HASH_Retrieve_Extended(psBase->psHashTab, aKey);
887}
888
889static PVRSRV_ERROR IncreaseHandleArraySize(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32Delta)
890{
891 PVRSRV_ERROR eError;
892 IMG_UINT32 ui32DeltaAdjusted = ROUND_UP_TO_MULTIPLE_OF_BLOCK_SIZE(ui32Delta);
893 IMG_UINT32 ui32NewTotalHandCount = psBase->ui32TotalHandCount + ui32DeltaAdjusted;
894;
895
896 PVR_ASSERT(ui32Delta != 0);
897
898
899 if (ui32NewTotalHandCount > psBase->ui32MaxIndexPlusOne || ui32NewTotalHandCount <= psBase->ui32TotalHandCount)
900 {
901 ui32NewTotalHandCount = psBase->ui32MaxIndexPlusOne;
902
903 ui32DeltaAdjusted = ui32NewTotalHandCount - psBase->ui32TotalHandCount;
904
905 if (ui32DeltaAdjusted < ui32Delta)
906 {
907 PVR_DPF((PVR_DBG_ERROR, "IncreaseHandleArraySize: Maximum handle limit reached (%d)", psBase->ui32MaxIndexPlusOne));
908 return PVRSRV_ERROR_OUT_OF_MEMORY;
909 }
910 }
911
912 PVR_ASSERT(ui32DeltaAdjusted >= ui32Delta);
913
914
915 eError = ReallocHandleArray(psBase, ui32NewTotalHandCount);
916 if (eError != PVRSRV_OK)
917 {
918 PVR_DPF((PVR_DBG_ERROR, "IncreaseHandleArraySize: ReallocHandleArray failed (%d)", eError));
919 return eError;
920 }
921
922 return PVRSRV_OK;
923}
924
925static PVRSRV_ERROR EnsureFreeHandles(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32Free)
926{
927 PVRSRV_ERROR eError;
928
929 if (ui32Free > psBase->ui32FreeHandCount)
930 {
931 IMG_UINT32 ui32FreeHandDelta = ui32Free - psBase->ui32FreeHandCount;
932 eError = IncreaseHandleArraySize(psBase, ui32FreeHandDelta);
933 if (eError != PVRSRV_OK)
934 {
935 PVR_DPF((PVR_DBG_ERROR, "EnsureFreeHandles: Couldn't allocate %u handles to ensure %u free handles (IncreaseHandleArraySize failed with error %d)", ui32FreeHandDelta, ui32Free, eError));
936
937 return eError;
938 }
939 }
940
941 return PVRSRV_OK;
942}
943
944static 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)
945{
946 IMG_UINT32 ui32NewIndex = DEFAULT_MAX_INDEX_PLUS_ONE;
947 struct sHandle *psNewHandle = IMG_NULL;
948 IMG_HANDLE hHandle;
949 HAND_KEY aKey;
950 PVRSRV_ERROR eError;
951
952
953 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
954 PVR_ASSERT(psBase != IMG_NULL);
955 PVR_ASSERT(psBase->psHashTab != IMG_NULL);
956
957 if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
958 {
959
960 PVR_ASSERT(FindHandle(psBase, pvData, eType, hParent) == IMG_NULL);
961 }
962
963 if (psBase->ui32FreeHandCount == 0 && HANDLES_BATCHED(psBase))
964 {
965 PVR_DPF((PVR_DBG_WARNING, "AllocHandle: Handle batch size (%u) was too small, allocating additional space", psBase->ui32HandBatchSize));
966 }
967
968
969 eError = EnsureFreeHandles(psBase, 1);
970 if (eError != PVRSRV_OK)
971 {
972 PVR_DPF((PVR_DBG_ERROR, "AllocHandle: EnsureFreeHandles failed (%d)", eError));
973 return eError;
974 }
975 PVR_ASSERT(psBase->ui32FreeHandCount != 0)
976
977 if (!psBase->bPurgingEnabled)
978 {
979
980 ui32NewIndex = psBase->ui32FirstFreeIndex;
981
982
983 psNewHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32NewIndex);
984 }
985 else
986 {
987 IMG_UINT32 ui32BlockedIndex;
988
989
990
991 PVR_ASSERT((psBase->ui32FirstFreeIndex % HANDLE_BLOCK_SIZE) == 0);
992
993 for (ui32BlockedIndex = ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(psBase->ui32FirstFreeIndex); ui32BlockedIndex < psBase->ui32TotalHandCount; ui32BlockedIndex += HANDLE_BLOCK_SIZE)
994 {
995 struct sHandleIndex *psIndex = BASE_AND_INDEX_TO_INDEX_STRUCT_PTR(psBase, ui32BlockedIndex);
996
997 if (psIndex->ui32FreeHandBlockCount == 0)
998 {
999 continue;
1000 }
1001
1002 for (ui32NewIndex = ui32BlockedIndex; ui32NewIndex < ui32BlockedIndex + HANDLE_BLOCK_SIZE; ui32NewIndex++)
1003 {
1004 psNewHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32NewIndex);
1005 if (HANDLE_STRUCT_IS_FREE(psNewHandle))
1006 {
1007 break;
1008 }
1009 }
1010 }
1011 psBase->ui32FirstFreeIndex = 0;
1012 PVR_ASSERT(ui32NewIndex < psBase->ui32TotalHandCount);
1013 }
1014 PVR_ASSERT(psNewHandle != IMG_NULL);
1015
1016
1017 hHandle = INDEX_TO_HANDLE(ui32NewIndex);
1018
1019
1020 if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
1021 {
1022
1023 InitKey(aKey, psBase, pvData, eType, hParent);
1024
1025
1026 if (!HASH_Insert_Extended(psBase->psHashTab, aKey, (IMG_UINTPTR_T)hHandle))
1027 {
1028 PVR_DPF((PVR_DBG_ERROR, "AllocHandle: Couldn't add handle to hash table"));
1029
1030 return PVRSRV_ERROR_UNABLE_TO_ADD_HANDLE;
1031 }
1032 }
1033
1034 psBase->ui32FreeHandCount--;
1035
1036 PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex) <= HANDLE_BLOCK_SIZE);
1037 PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex) > 0);
1038
1039 INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex)--;
1040
1041
1042 if (!psBase->bPurgingEnabled)
1043 {
1044
1045 if (psBase->ui32FreeHandCount == 0)
1046 {
1047 PVR_ASSERT(psBase->ui32FirstFreeIndex == ui32NewIndex);
1048 PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == (ui32NewIndex + 1));
1049
1050 psBase->ui32LastFreeIndexPlusOne = 0;
1051 psBase->ui32FirstFreeIndex = 0;
1052 }
1053 else
1054 {
1055
1056 psBase->ui32FirstFreeIndex = (psNewHandle->ui32NextIndexPlusOne == 0) ?
1057 ui32NewIndex + 1 :
1058 psNewHandle->ui32NextIndexPlusOne - 1;
1059 }
1060 }
1061
1062
1063 PVR_ASSERT(psNewHandle->ui32Index == ui32NewIndex);
1064
1065
1066 psNewHandle->eType = eType;
1067 psNewHandle->pvData = pvData;
1068 psNewHandle->eInternalFlag = INTERNAL_HANDLE_FLAG_NONE;
1069 psNewHandle->eFlag = eFlag;
1070
1071 InitParentList(psNewHandle);
1072#if defined(DEBUG)
1073 PVR_ASSERT(NoChildren(psNewHandle));
1074#endif
1075
1076 InitChildEntry(psNewHandle);
1077#if defined(DEBUG)
1078 PVR_ASSERT(NoParent(psNewHandle));
1079#endif
1080
1081 if (HANDLES_BATCHED(psBase))
1082 {
1083
1084 psNewHandle->ui32NextIndexPlusOne = psBase->ui32FirstBatchIndexPlusOne;
1085
1086 psBase->ui32FirstBatchIndexPlusOne = ui32NewIndex + 1;
1087
1088
1089 SET_BATCHED_HANDLE(psNewHandle);
1090 }
1091 else
1092 {
1093 psNewHandle->ui32NextIndexPlusOne = 0;
1094 }
1095
1096
1097 *phHandle = hHandle;
1098
1099 return PVRSRV_OK;
1100}
1101
1102PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag)
1103{
1104 IMG_HANDLE hHandle;
1105 PVRSRV_ERROR eError;
1106
1107 *phHandle = IMG_NULL;
1108
1109 if (HANDLES_BATCHED(psBase))
1110 {
1111
1112 psBase->ui32BatchHandAllocFailures++;
1113 }
1114
1115
1116 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1117
1118 if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
1119 {
1120
1121 hHandle = FindHandle(psBase, pvData, eType, IMG_NULL);
1122 if (hHandle != IMG_NULL)
1123 {
1124 struct sHandle *psHandle;
1125
1126 eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
1127 if (eError != PVRSRV_OK)
1128 {
1129 PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandle: Lookup of existing handle failed"));
1130 return eError;
1131 }
1132
1133
1134 if (TEST_FLAG(psHandle->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED))
1135 {
1136 *phHandle = hHandle;
1137 eError = PVRSRV_OK;
1138 goto exit_ok;
1139 }
1140 return PVRSRV_ERROR_HANDLE_NOT_SHAREABLE;
1141 }
1142 }
1143
1144 eError = AllocHandle(psBase, phHandle, pvData, eType, eFlag, IMG_NULL);
1145
1146exit_ok:
1147 if (HANDLES_BATCHED(psBase) && (eError == PVRSRV_OK))
1148 {
1149 psBase->ui32BatchHandAllocFailures--;
1150 }
1151
1152 return eError;
1153}
1154
1155PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent)
1156{
1157 struct sHandle *psPHand;
1158 struct sHandle *psCHand;
1159 PVRSRV_ERROR eError;
1160 IMG_HANDLE hParentKey;
1161 IMG_HANDLE hHandle;
1162
1163 *phHandle = IMG_NULL;
1164
1165 if (HANDLES_BATCHED(psBase))
1166 {
1167
1168 psBase->ui32BatchHandAllocFailures++;
1169 }
1170
1171
1172 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1173
1174 hParentKey = TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ?
1175 hParent : IMG_NULL;
1176
1177
1178 eError = GetHandleStructure(psBase, &psPHand, hParent, PVRSRV_HANDLE_TYPE_NONE);
1179 if (eError != PVRSRV_OK)
1180 {
1181 return eError;
1182 }
1183
1184 if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
1185 {
1186
1187 hHandle = FindHandle(psBase, pvData, eType, hParentKey);
1188 if (hHandle != IMG_NULL)
1189 {
1190 struct sHandle *psCHandle;
1191 PVRSRV_ERROR eErr;
1192
1193 eErr = GetHandleStructure(psBase, &psCHandle, hHandle, eType);
1194 if (eErr != PVRSRV_OK)
1195 {
1196 PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSubHandle: Lookup of existing handle failed"));
1197 return eErr;
1198 }
1199
1200 PVR_ASSERT(hParentKey != IMG_NULL && ParentHandle(HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle)) == hParent);
1201
1202
1203 if (TEST_FLAG(psCHandle->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED) && ParentHandle(HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle)) == hParent)
1204 {
1205 *phHandle = hHandle;
1206 goto exit_ok;
1207 }
1208 return PVRSRV_ERROR_HANDLE_NOT_SHAREABLE;
1209 }
1210 }
1211
1212 eError = AllocHandle(psBase, &hHandle, pvData, eType, eFlag, hParentKey);
1213 if (eError != PVRSRV_OK)
1214 {
1215 return eError;
1216 }
1217
1218
1219 psPHand = HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hParent);
1220
1221 psCHand = HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle);
1222
1223 AdoptChild(psBase, psPHand, psCHand);
1224
1225 *phHandle = hHandle;
1226
1227exit_ok:
1228 if (HANDLES_BATCHED(psBase))
1229 {
1230 psBase->ui32BatchHandAllocFailures--;
1231 }
1232
1233 return PVRSRV_OK;
1234}
1235
1236PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType)
1237{
1238 IMG_HANDLE hHandle;
1239
1240 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1241
1242
1243 hHandle = (IMG_HANDLE) FindHandle(psBase, pvData, eType, IMG_NULL);
1244 if (hHandle == IMG_NULL)
1245 {
1246 return PVRSRV_ERROR_HANDLE_NOT_FOUND;
1247 }
1248
1249 *phHandle = hHandle;
1250
1251 return PVRSRV_OK;
1252}
1253
1254PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle)
1255{
1256 struct sHandle *psHandle;
1257 PVRSRV_ERROR eError;
1258
1259 eError = GetHandleStructure(psBase, &psHandle, hHandle, PVRSRV_HANDLE_TYPE_NONE);
1260 if (eError != PVRSRV_OK)
1261 {
1262 PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupHandleAnyType: Error looking up handle (%d)", eError));
1263 return eError;
1264 }
1265
1266 *ppvData = psHandle->pvData;
1267 *peType = psHandle->eType;
1268
1269 return PVRSRV_OK;
1270}
1271
1272PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
1273{
1274 struct sHandle *psHandle;
1275 PVRSRV_ERROR eError;
1276
1277 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1278
1279 eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
1280 if (eError != PVRSRV_OK)
1281 {
1282 PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupHandle: Error looking up handle (%d)", eError));
1283 return eError;
1284 }
1285
1286 *ppvData = psHandle->pvData;
1287
1288 return PVRSRV_OK;
1289}
1290
1291PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hAncestor)
1292{
1293 struct sHandle *psPHand;
1294 struct sHandle *psCHand;
1295 PVRSRV_ERROR eError;
1296
1297 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1298
1299 eError = GetHandleStructure(psBase, &psCHand, hHandle, eType);
1300 if (eError != PVRSRV_OK)
1301 {
1302 PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupSubHandle: Error looking up subhandle (%d)", eError));
1303 return eError;
1304 }
1305
1306
1307 for (psPHand = psCHand; ParentHandle(psPHand) != hAncestor; )
1308 {
1309 eError = GetHandleStructure(psBase, &psPHand, ParentHandle(psPHand), PVRSRV_HANDLE_TYPE_NONE);
1310 if (eError != PVRSRV_OK)
1311 {
1312 PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupSubHandle: Subhandle doesn't belong to given ancestor"));
1313 return PVRSRV_ERROR_INVALID_SUBHANDLE;
1314 }
1315 }
1316
1317 *ppvData = psCHand->pvData;
1318
1319 return PVRSRV_OK;
1320}
1321
1322PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
1323{
1324 struct sHandle *psHandle;
1325 PVRSRV_ERROR eError;
1326
1327 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1328
1329 eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
1330 if (eError != PVRSRV_OK)
1331 {
1332 PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetParentHandle: Error looking up subhandle (%d)", eError));
1333 return eError;
1334 }
1335
1336 *phParent = ParentHandle(psHandle);
1337
1338 return PVRSRV_OK;
1339}
1340
1341PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
1342{
1343 struct sHandle *psHandle;
1344 PVRSRV_ERROR eError;
1345
1346 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1347
1348 eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
1349 if (eError != PVRSRV_OK)
1350 {
1351 PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupAndReleaseHandle: Error looking up handle (%d)", eError));
1352 return eError;
1353 }
1354
1355 *ppvData = psHandle->pvData;
1356
1357 eError = FreeHandle(psBase, psHandle);
1358
1359 return eError;
1360}
1361
1362PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
1363{
1364 struct sHandle *psHandle;
1365 PVRSRV_ERROR eError;
1366
1367 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1368
1369 eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
1370 if (eError != PVRSRV_OK)
1371 {
1372 PVR_DPF((PVR_DBG_ERROR, "PVRSRVReleaseHandle: Error looking up handle (%d)", eError));
1373 return eError;
1374 }
1375
1376 eError = FreeHandle(psBase, psHandle);
1377
1378 return eError;
1379}
1380
1381PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32BatchSize)
1382{
1383 PVRSRV_ERROR eError;
1384
1385 if (HANDLES_BATCHED(psBase))
1386 {
1387 PVR_DPF((PVR_DBG_ERROR, "PVRSRVNewHandleBatch: There is a handle batch already in use (size %u)", psBase->ui32HandBatchSize));
1388 return PVRSRV_ERROR_HANDLE_BATCH_IN_USE;
1389 }
1390
1391 if (ui32BatchSize == 0)
1392 {
1393 PVR_DPF((PVR_DBG_ERROR, "PVRSRVNewHandleBatch: Invalid batch size (%u)", ui32BatchSize));
1394 return PVRSRV_ERROR_INVALID_PARAMS;
1395 }
1396
1397 eError = EnsureFreeHandles(psBase, ui32BatchSize);
1398 if (eError != PVRSRV_OK)
1399 {
1400 PVR_DPF((PVR_DBG_ERROR, "PVRSRVNewHandleBatch: EnsureFreeHandles failed (error %d)", eError));
1401 return eError;
1402 }
1403
1404 psBase->ui32HandBatchSize = ui32BatchSize;
1405
1406
1407 psBase->ui32TotalHandCountPreBatch = psBase->ui32TotalHandCount;
1408
1409 PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0);
1410
1411 PVR_ASSERT(psBase->ui32FirstBatchIndexPlusOne == 0);
1412
1413 PVR_ASSERT(HANDLES_BATCHED(psBase));
1414
1415 return PVRSRV_OK;
1416}
1417
1418static PVRSRV_ERROR PVRSRVHandleBatchCommitOrRelease(PVRSRV_HANDLE_BASE *psBase, IMG_BOOL bCommit)
1419{
1420
1421 IMG_UINT32 ui32IndexPlusOne;
1422 IMG_BOOL bCommitBatch = bCommit;
1423
1424 if (!HANDLES_BATCHED(psBase))
1425 {
1426 PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: There is no handle batch"));
1427 return PVRSRV_ERROR_INVALID_PARAMS;
1428
1429 }
1430
1431 if (psBase->ui32BatchHandAllocFailures != 0)
1432 {
1433 if (bCommit)
1434 {
1435 PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: Attempting to commit batch with handle allocation failures."));
1436 }
1437 bCommitBatch = IMG_FALSE;
1438 }
1439
1440 PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0 || !bCommit);
1441
1442 ui32IndexPlusOne = psBase->ui32FirstBatchIndexPlusOne;
1443 while(ui32IndexPlusOne != 0)
1444 {
1445 struct sHandle *psHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32IndexPlusOne - 1);
1446 IMG_UINT32 ui32NextIndexPlusOne = psHandle->ui32NextIndexPlusOne;
1447 PVR_ASSERT(BATCHED_HANDLE(psHandle));
1448
1449 psHandle->ui32NextIndexPlusOne = 0;
1450
1451 if (!bCommitBatch || BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
1452 {
1453 PVRSRV_ERROR eError;
1454
1455
1456 if (!BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
1457 {
1458
1459 SET_UNBATCHED_HANDLE(psHandle);
1460 }
1461
1462 eError = FreeHandle(psBase, psHandle);
1463 if (eError != PVRSRV_OK)
1464 {
1465 PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: Error freeing handle (%d)", eError));
1466 }
1467 PVR_ASSERT(eError == PVRSRV_OK);
1468 }
1469 else
1470 {
1471
1472 SET_UNBATCHED_HANDLE(psHandle);
1473 }
1474
1475 ui32IndexPlusOne = ui32NextIndexPlusOne;
1476 }
1477
1478#ifdef DEBUG
1479 if (psBase->ui32TotalHandCountPreBatch != psBase->ui32TotalHandCount)
1480 {
1481 IMG_UINT32 ui32Delta = psBase->ui32TotalHandCount - psBase->ui32TotalHandCountPreBatch;
1482
1483 PVR_ASSERT(psBase->ui32TotalHandCount > psBase->ui32TotalHandCountPreBatch);
1484
1485 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));
1486
1487 }
1488#endif
1489
1490 psBase->ui32HandBatchSize = 0;
1491 psBase->ui32FirstBatchIndexPlusOne = 0;
1492 psBase->ui32TotalHandCountPreBatch = 0;
1493 psBase->ui32BatchHandAllocFailures = 0;
1494
1495 if (psBase->ui32BatchHandAllocFailures != 0 && bCommit)
1496 {
1497 PVR_ASSERT(!bCommitBatch);
1498
1499 return PVRSRV_ERROR_HANDLE_BATCH_COMMIT_FAILURE;
1500 }
1501
1502 return PVRSRV_OK;
1503}
1504
1505PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE *psBase)
1506{
1507 return PVRSRVHandleBatchCommitOrRelease(psBase, IMG_TRUE);
1508}
1509
1510IMG_VOID PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE *psBase)
1511{
1512 (IMG_VOID) PVRSRVHandleBatchCommitOrRelease(psBase, IMG_FALSE);
1513}
1514
1515PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHandle)
1516{
1517 IMG_UINT32 ui32MaxHandleRounded;
1518
1519 if (HANDLES_BATCHED(psBase))
1520 {
1521 PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit cannot be set whilst in batch mode"));
1522 return PVRSRV_ERROR_INVALID_PARAMS;
1523 }
1524
1525
1526 if (ui32MaxHandle == 0 || ui32MaxHandle > DEFAULT_MAX_HANDLE)
1527 {
1528 PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit must be between %u and %u, inclusive", 0, DEFAULT_MAX_HANDLE));
1529
1530 return PVRSRV_ERROR_INVALID_PARAMS;
1531 }
1532
1533
1534 if (psBase->ui32TotalHandCount != 0)
1535 {
1536 PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit cannot be set because handles have already been allocated"));
1537
1538 return PVRSRV_ERROR_INVALID_PARAMS;
1539 }
1540
1541 ui32MaxHandleRounded = ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(ui32MaxHandle);
1542
1543
1544 if (ui32MaxHandleRounded != 0 && ui32MaxHandleRounded < psBase->ui32MaxIndexPlusOne)
1545 {
1546 psBase->ui32MaxIndexPlusOne = ui32MaxHandleRounded;
1547 }
1548
1549 PVR_ASSERT(psBase->ui32MaxIndexPlusOne != 0);
1550 PVR_ASSERT(psBase->ui32MaxIndexPlusOne <= DEFAULT_MAX_INDEX_PLUS_ONE);
1551 PVR_ASSERT((psBase->ui32MaxIndexPlusOne % HANDLE_BLOCK_SIZE) == 0);
1552
1553 return PVRSRV_OK;
1554}
1555
1556IMG_UINT32 PVRSRVGetMaxHandle(PVRSRV_HANDLE_BASE *psBase)
1557{
1558 return psBase->ui32MaxIndexPlusOne;
1559}
1560
1561PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase)
1562{
1563 if (psBase->bPurgingEnabled)
1564 {
1565 PVR_DPF((PVR_DBG_WARNING, "PVRSRVEnableHandlePurging: Purging already enabled"));
1566 return PVRSRV_OK;
1567 }
1568
1569
1570 if (psBase->ui32TotalHandCount != 0)
1571 {
1572 PVR_DPF((PVR_DBG_ERROR, "PVRSRVEnableHandlePurging: Handles have already been allocated"));
1573 return PVRSRV_ERROR_INVALID_PARAMS;
1574 }
1575
1576 psBase->bPurgingEnabled = IMG_TRUE;
1577
1578 return PVRSRV_OK;
1579}
1580
1581PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase)
1582{
1583 IMG_UINT32 ui32BlockIndex;
1584 IMG_UINT32 ui32NewHandCount;
1585
1586 if (!psBase->bPurgingEnabled)
1587 {
1588 PVR_DPF((PVR_DBG_ERROR, "PVRSRVPurgeHandles: Purging not enabled for this handle base"));
1589 return PVRSRV_ERROR_NOT_SUPPORTED;
1590 }
1591
1592 if (HANDLES_BATCHED(psBase))
1593 {
1594 PVR_DPF((PVR_DBG_ERROR, "PVRSRVPurgeHandles: Purging not allowed whilst in batch mode"));
1595 return PVRSRV_ERROR_INVALID_PARAMS;
1596 }
1597
1598 PVR_ASSERT((psBase->ui32TotalHandCount % HANDLE_BLOCK_SIZE) == 0);
1599
1600 for (ui32BlockIndex = INDEX_TO_BLOCK_INDEX(psBase->ui32TotalHandCount); ui32BlockIndex != 0; ui32BlockIndex--)
1601 {
1602 if (psBase->psHandleArray[ui32BlockIndex - 1].ui32FreeHandBlockCount != HANDLE_BLOCK_SIZE)
1603 {
1604 break;
1605 }
1606 }
1607 ui32NewHandCount = BLOCK_INDEX_TO_INDEX(ui32BlockIndex);
1608
1609
1610 if (ui32NewHandCount <= (psBase->ui32TotalHandCount/2))
1611 {
1612 PVRSRV_ERROR eError;
1613
1614
1615
1616 eError = ReallocHandleArray(psBase, ui32NewHandCount);
1617 if (eError != PVRSRV_OK)
1618 {
1619 return eError;
1620 }
1621 }
1622
1623 return PVRSRV_OK;
1624}
1625
1626PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase)
1627{
1628 PVRSRV_HANDLE_BASE *psBase;
1629 IMG_HANDLE hBlockAlloc;
1630 PVRSRV_ERROR eError;
1631
1632 eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
1633 sizeof(*psBase),
1634 (IMG_PVOID *)&psBase,
1635 &hBlockAlloc,
1636 "Handle Base");
1637 if (eError != PVRSRV_OK)
1638 {
1639 PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandleBase: Couldn't allocate handle base (%d)", eError));
1640 return eError;
1641 }
1642 OSMemSet(psBase, 0, sizeof(*psBase));
1643
1644
1645 psBase->psHashTab = HASH_Create_Extended(HANDLE_HASH_TAB_INIT_SIZE, sizeof(HAND_KEY), HASH_Func_Default, HASH_Key_Comp_Default);
1646 if (psBase->psHashTab == IMG_NULL)
1647 {
1648 PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandleBase: Couldn't create data pointer hash table\n"));
1649 (IMG_VOID)PVRSRVFreeHandleBase(psBase);
1650 return PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE;
1651 }
1652
1653 psBase->hBaseBlockAlloc = hBlockAlloc;
1654
1655 psBase->ui32MaxIndexPlusOne = DEFAULT_MAX_INDEX_PLUS_ONE;
1656
1657 *ppsBase = psBase;
1658
1659 return PVRSRV_OK;
1660}
1661
1662PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
1663{
1664 PVRSRV_ERROR eError;
1665
1666 PVR_ASSERT(psBase != gpsKernelHandleBase);
1667
1668 eError = FreeHandleBase(psBase);
1669 if (eError != PVRSRV_OK)
1670 {
1671 PVR_DPF((PVR_DBG_ERROR, "PVRSRVFreeHandleBase: FreeHandleBase failed (%d)", eError));
1672 }
1673
1674 return eError;
1675}
1676
1677PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID)
1678{
1679 PVRSRV_ERROR eError;
1680
1681 PVR_ASSERT(gpsKernelHandleBase == IMG_NULL);
1682
1683 eError = PVRSRVAllocHandleBase(&gpsKernelHandleBase);
1684 if (eError != PVRSRV_OK)
1685 {
1686 PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleInit: PVRSRVAllocHandleBase failed (%d)", eError));
1687 goto error;
1688 }
1689
1690 eError = PVRSRVEnableHandlePurging(gpsKernelHandleBase);
1691 if (eError != PVRSRV_OK)
1692 {
1693 PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleInit: PVRSRVEnableHandlePurging failed (%d)", eError));
1694 goto error;
1695 }
1696
1697 return PVRSRV_OK;
1698error:
1699 (IMG_VOID) PVRSRVHandleDeInit();
1700 return eError;
1701}
1702
1703PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID)
1704{
1705 PVRSRV_ERROR eError = PVRSRV_OK;
1706
1707 if (gpsKernelHandleBase != IMG_NULL)
1708 {
1709 eError = FreeHandleBase(gpsKernelHandleBase);
1710 if (eError == PVRSRV_OK)
1711 {
1712 gpsKernelHandleBase = IMG_NULL;
1713 }
1714 else
1715 {
1716 PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleDeInit: FreeHandleBase failed (%d)", eError));
1717 }
1718 }
1719
1720 return eError;
1721}
1722#else
1723#endif