Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

420 lines
13 KiB

/******************************Module*Header**********************************\
*
* *******************
* * D3D SAMPLE CODE *
* *******************
*
* Module Name: d3dstrct.c
*
* Content: Internal D3D structure management.
*
* Copyright (c) 1994-1999 3Dlabs Inc. Ltd. All rights reserved.
* Copyright (c) 1995-2003 Microsoft Corporation. All rights reserved.
\*****************************************************************************/
#include "glint.h"
#include "d3dstrct.h"
//----------------------------------------------------------------------------
// This file provides a centralized place where we manage ans use internal
// data structures for the driver. This way, we can change the data structure
// or its management without affecting the rest of the code.
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//********************** A R R A Y S T R U C T U R E *********************
//----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
// PA_CreateArray
//
// Creates an array of pointers.
//
//-----------------------------------------------------------------------------
PointerArray*
PA_CreateArray()
{
PointerArray* pNewArray;
pNewArray = HEAP_ALLOC(HEAP_ZERO_MEMORY,
sizeof(PointerArray),
ALLOC_TAG_DX(5));
if (!pNewArray)
{
DISPDBG((ERRLVL,"ERROR: PointerArray allocation failed"));
return NULL;
}
// Explicit initialization
pNewArray->pPointers = NULL;
pNewArray->dwNumPointers = 0;
pNewArray->pfnDestroyCallback = NULL;
return pNewArray;
} // PA_CreateArray
//-----------------------------------------------------------------------------
//
// PA_SetDataDestroyCallback
//
// Records the data pointer destroy callback.
//
//-----------------------------------------------------------------------------
void
PA_SetDataDestroyCallback(
PointerArray* pArray,
PA_DestroyCB DestroyCallback)
{
pArray->pfnDestroyCallback = DestroyCallback;
} // PA_SetDataDestroyCallback
//-----------------------------------------------------------------------------
//
// PA_DestroyArray
//
// Destroys all the pointers in the array. Optionally calls a callback with
// each pointer to allow clients to free objects associated with the pointer
//-----------------------------------------------------------------------------
BOOL
PA_DestroyArray(PointerArray* pArray, VOID *pExtra)
{
if (pArray != NULL)
{
if (pArray->pPointers != NULL)
{
DWORD dwCount;
// If there is a registered destroy callback, call it for every
// non-null data pointer
if (pArray->pfnDestroyCallback != NULL)
{
for (dwCount = 0; dwCount < pArray->dwNumPointers; dwCount++)
{
if (pArray->pPointers[dwCount] != 0)
{
// Call the data destroy callback
pArray->pfnDestroyCallback(
pArray,
(void*)pArray->pPointers[dwCount],
pExtra);
}
}
}
// Free the Array of Pointers
HEAP_FREE(pArray->pPointers);
pArray->pPointers = NULL;
}
// Free the pointer array
HEAP_FREE(pArray);
}
return TRUE;
} // PA_DestroyArray
//-----------------------------------------------------------------------------
//
// PA_GetEntry
//
// Look up the Pointer in the array an return it
//
//-----------------------------------------------------------------------------
void*
PA_GetEntry(PointerArray* pArray, DWORD dwNum)
{
ASSERTDD((pArray != NULL), "ERROR: Bad Pointer array!");
if ((pArray->dwNumPointers == 0) ||
(dwNum > (pArray->dwNumPointers - 1)) )
{
// We will be getting called frequently by D3DCreateSurfaceEx for
// handles which might not be initialized so this will be hit often
DISPDBG((DBGLVL,"PA_GetEntry: Ptr outside of range (usually OK)"));
return NULL;
}
return (void*)pArray->pPointers[dwNum];
} // PA_GetEntry
//-----------------------------------------------------------------------------
//
// PA_SetEntry
//
// Sets an entry in the array of pointers. If the entry is larger than
// the array, the array is grown to accomodate it. Returns FALSE if we
// fail to set the data for any reason (mainly out of memory).
//
//-----------------------------------------------------------------------------
BOOL
PA_SetEntry(
PointerArray* pArray,
DWORD dwNum,
void* pData)
{
ASSERTDD(pArray != NULL, "Bad pointer array");
if ( (dwNum + 1 ) > pArray->dwNumPointers )
{
ULONG_PTR* pNewArray;
DWORD dwNewArrayLength, dwNewArraySize;
//
// The array either already exists and has to be grown in size
// or doesnt exist at all
//
DISPDBG((DBGLVL, "Expanding/creating pointer array"));
dwNewArrayLength = (dwNum * 2) + 1; // Tunable heuristic
// ask for double of the space
// needed for the new element
dwNewArraySize = dwNewArrayLength * sizeof(ULONG_PTR);
pNewArray = (ULONG_PTR*)HEAP_ALLOC(HEAP_ZERO_MEMORY,
dwNewArraySize,
ALLOC_TAG_DX(7));
if (pNewArray == NULL)
{
DISPDBG((DBGLVL,"ERROR: Failed to allocate new Pointer array!!"));
return FALSE;
}
if (pArray->pPointers != NULL)
{
// We had an old valid array before this, so we need to transfer
// old array elements into the new array and destroy the old array
memcpy( pNewArray,
pArray->pPointers,
(pArray->dwNumPointers * sizeof(ULONG_PTR)) );
HEAP_FREE(pArray->pPointers);
}
// Update our pointer to the array and its size info
pArray->pPointers = pNewArray;
pArray->dwNumPointers = dwNewArrayLength;
}
pArray->pPointers[dwNum] = (ULONG_PTR)pData;
return TRUE;
} // PA_SetEntry
//----------------------------------------------------------------------------
//********************** H A S H S T R U C T U R E *********************
//----------------------------------------------------------------------------
// Manages a hash table
// Each slot contains front and back pointers, a handle, and an app-specific
// data pointer. Entries are the things that the clients add/remove
// Slots are the internal data chunks that are managed as part of the hash table
//-----------------------------------------------------------------------------
//
// HT_CreateHashTable
//
//-----------------------------------------------------------------------------
HashTable*
HT_CreateHashTable()
{
HashTable* pHashTable;
DISPDBG((DBGLVL,"In HT_CreateHashTable"));
pHashTable = (HashTable*)HEAP_ALLOC(HEAP_ZERO_MEMORY,
sizeof(HashTable),
ALLOC_TAG_DX(8));
if (pHashTable == NULL)
{
DISPDBG((DBGLVL,"Hash table alloc failed!"));
return NULL;
}
return pHashTable;
} // HT_CreateHashTable
//-----------------------------------------------------------------------------
//
// HT_SetDataDestroyCallback
//
//-----------------------------------------------------------------------------
void
HT_SetDataDestroyCallback(
HashTable* pHashTable,
DataDestroyCB DestroyCallback)
{
DISPDBG((DBGLVL,"In HT_SetDataDestroyCallback"));
ASSERTDD(pHashTable != NULL,"ERROR: HashTable passed in is not valid!");
pHashTable->pfnDestroyCallback = DestroyCallback;
} // HT_SetDataDestroyCallback
//-----------------------------------------------------------------------------
//
// HT_ClearEntriesHashTable
//
//-----------------------------------------------------------------------------
void
HT_ClearEntriesHashTable(HashTable* pHashTable, VOID* pExtra)
{
int i;
HashSlot* pHashSlot = NULL;
DISPDBG((DBGLVL,"In HT_ClearEntriesHashTable"));
ASSERTDD(pHashTable != NULL,"ERROR: HashTable passed in is not valid!");
for (i = 0; i < HASH_SIZE; i++)
{
while (pHashSlot = pHashTable->Slots[i])
{
HT_RemoveEntry(pHashTable, pHashSlot->dwHandle, pExtra);
}
pHashTable->Slots[i] = NULL;
}
} // HT_ClearEntriesHashTable
//-----------------------------------------------------------------------------
//
// HT_DestroyHashTable
//
//-----------------------------------------------------------------------------
void
HT_DestroyHashTable(HashTable* pHashTable, VOID* pExtra)
{
HT_ClearEntriesHashTable(pHashTable, pExtra);
HEAP_FREE(pHashTable);
} // HT_DestroyHashTable
//-----------------------------------------------------------------------------
//
// vBOOL HT_AddEntry
//
//-----------------------------------------------------------------------------
BOOL HT_AddEntry(HashTable* pTable, ULONG_PTR dwHandle, void* pData)
{
HashSlot* pHashSlot = NULL;
DISPDBG((DBGLVL,"In HT_AddEntry"));
ASSERTDD(pTable != NULL,"ERROR: HashTable passed in is not valid!");
pHashSlot = HEAP_ALLOC(HEAP_ZERO_MEMORY,
sizeof(HashSlot),
ALLOC_TAG_DX(9));
if (pHashSlot == NULL)
{
DISPDBG((ERRLVL,"Hash entry alloc failed!"));
return FALSE;
}
// Sew this new entry into the hash table
if (pTable->Slots[HT_HASH_OF(dwHandle)])
{
pTable->Slots[HT_HASH_OF(dwHandle)]->pPrev = pHashSlot;
}
// Carry on a next pointer
pHashSlot->pNext = pTable->Slots[HT_HASH_OF(dwHandle)];
pHashSlot->pPrev = NULL;
// Remember the app-supplied data and the handle
pHashSlot->pData = pData;
pHashSlot->dwHandle = dwHandle;
// hash table refers to this one now.
pTable->Slots[HT_HASH_OF(dwHandle)] = pHashSlot;
return TRUE;
} // HT_AddEntry
//-----------------------------------------------------------------------------
//
// BOOL HT_RemoveEntry
//
//-----------------------------------------------------------------------------
BOOL HT_RemoveEntry(HashTable* pTable, ULONG_PTR dwHandle, VOID *pExtra)
{
HashSlot* pSlot = HT_GetSlotFromHandle(pTable, dwHandle);
DISPDBG((DBGLVL,"In HT_RemoveEntry"));
ASSERTDD(pTable != NULL,"ERROR: HashTable passed in is not valid!");
if (pSlot == NULL)
{
DISPDBG((WRNLVL,"WARNING: Hash entry does not exist"));
return FALSE;
}
// Mark the entry as gone from the hash table if it is at the front
if (pTable->Slots[HT_HASH_OF(dwHandle)]->dwHandle == pSlot->dwHandle)
{
pTable->Slots[HT_HASH_OF(dwHandle)] =
pTable->Slots[HT_HASH_OF(dwHandle)]->pNext;
}
// and sew the list back together.
if (pSlot->pPrev)
{
pSlot->pPrev->pNext = pSlot->pNext;
}
if (pSlot->pNext)
{
pSlot->pNext->pPrev = pSlot->pPrev;
}
// If the destroy data callback is setup, call it.
if ((pSlot->pData != NULL) && (pTable->pfnDestroyCallback))
{
DISPDBG((WRNLVL,"Calling DestroyCallback for undestroyed data"));
pTable->pfnDestroyCallback(pTable, pSlot->pData, pExtra);
}
// Free the memory associated with the slot
HEAP_FREE(pSlot);
return TRUE;
} // HT_RemoveEntry
//-----------------------------------------------------------------------------
//
// BOOL HT_SwapEntries
//
//-----------------------------------------------------------------------------
BOOL HT_SwapEntries(HashTable* pTable, DWORD dwHandle1, DWORD dwHandle2)
{
HashSlot* pEntry1;
HashSlot* pEntry2;
void* pDataTemp;
ASSERTDD(pTable != NULL,"ERROR: HashTable passed in is not valid!");
pEntry1 = HT_GetSlotFromHandle(pTable, dwHandle1);
pEntry2 = HT_GetSlotFromHandle(pTable, dwHandle2);
// The handle remains the same, the pointers to the actual data are swapped
if (pEntry1 && pEntry2)
{
pDataTemp = pEntry1->pData;
pEntry1->pData = pEntry2->pData;
pEntry2->pData = pDataTemp;
return TRUE;
}
DISPDBG((ERRLVL,"ERROR: Swapped entries are invalid!"));
return FALSE;
} // HT_SwapEntries