diff options
| author | git perforce import user <a@b> | 2016-10-25 12:29:14 -0600 |
|---|---|---|
| committer | Sheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees> | 2016-10-25 18:56:37 -0500 |
| commit | 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch) | |
| tree | fa6485c169e50d7415a651bf838f5bcd0fd3bfbd /APEX_1.4/framework/src/ApexResourceProvider.cpp | |
| download | physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip | |
Initial commit:
PhysX 3.4.0 Update @ 21294896
APEX 1.4.0 Update @ 21275617
[CL 21300167]
Diffstat (limited to 'APEX_1.4/framework/src/ApexResourceProvider.cpp')
| -rw-r--r-- | APEX_1.4/framework/src/ApexResourceProvider.cpp | 702 |
1 files changed, 702 insertions, 0 deletions
diff --git a/APEX_1.4/framework/src/ApexResourceProvider.cpp b/APEX_1.4/framework/src/ApexResourceProvider.cpp new file mode 100644 index 00000000..ee4e4105 --- /dev/null +++ b/APEX_1.4/framework/src/ApexResourceProvider.cpp @@ -0,0 +1,702 @@ +/* + * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + + +#include "Apex.h" +#include "ResourceProviderIntl.h" +#include "ApexResourceProvider.h" +#include "PsUserAllocated.h" +#include "ApexSDKImpl.h" +#include "PsString.h" +#include <ctype.h> // for toupper() + +namespace nvidia +{ +namespace apex +{ + +#pragma warning(disable: 4355) + +ApexResourceProvider::ApexResourceProvider() +: mNSNames(this, 0, false, 0) +, mCaseSensitive(false) +{ +} + +ApexResourceProvider::~ApexResourceProvider() +{ +} + +/* == Public ResourceProvider interface == */ +void ApexResourceProvider::registerCallback(ResourceCallback* func) +{ + mUserCallback = func; +} + +void ApexResourceProvider::setResource(const char* nameSpace, const char* name, void* resource, bool incRefCount) +{ + setResource(nameSpace, name, resource, true, incRefCount); +} + +void ApexResourceProvider::setResource(const char* nameSpace, const char* name, void* resource, bool valueIsSet, bool incRefCount) +{ + PX_ASSERT(nameSpace); + PX_ASSERT(name); + uint32_t nsIndex = getNSIndex(createNameSpaceInternal(nameSpace, true)); + if (nsIndex < mNameSpaces.size()) + { + ResID id = mNameSpaces[nsIndex]->getOrCreateID(name, nameSpace); + PX_ASSERT(id < mResources.size()); + if (id < mResources.size()) + { + ApexResourceProvider::resource& res = mResources[id]; + res.ptr = resource; + res.valueIsSet = (uint8_t)valueIsSet; + if (incRefCount) + { + res.refCount++; + } + } + } +} + +void* ApexResourceProvider::getResource(const char* nameSpace, const char* name) +{ + PX_ASSERT(nameSpace); + PX_ASSERT(name); + uint32_t nsIndex = getNSIndex(createNameSpaceInternal(nameSpace, true)); + if (nsIndex < mNameSpaces.size()) + { + ResID id = mNameSpaces[nsIndex]->getOrCreateID(name, nameSpace); + PX_ASSERT(id < mResources.size()); + if (id < mResources.size()) + { + return getResource(id); + } + } + return NULL; +} + +/* == Internal ResourceProviderIntl interface == */ +ResID ApexResourceProvider::createNameSpaceInternal(const char* &nameSpace, bool releaseAtExit) +{ + /* create or get a name space */ + size_t nextID = mResources.size(); + ResID nsID = mNSNames.getOrCreateID(nameSpace, "NameSpace"); + if (nsID == (ResID) nextID) + { + NameSpace* ns = PX_NEW(NameSpace)(this, nsID, releaseAtExit, nameSpace); + if (ns) + { + ResID id = getNSID(nameSpace); + mNSID.insert(id, mNameSpaces.size()); + + mResources[nsID].ptr = (void*)(size_t) id; + mNameSpaces.pushBack(ns); + } + else + { + return INVALID_RESOURCE_ID; + } + } + ResID ret = (ResID)(size_t) mResources[nsID].ptr; + return ret; +} + +ResID ApexResourceProvider::createResource(ResID nameSpace, const char* name, bool refCount) +{ + uint32_t nsIndex = getNSIndex(nameSpace); + if (nsIndex < mNameSpaces.size()) + { + NameSpace* ns = mNameSpaces[nsIndex]; + ResID id = ns->getOrCreateID(name, mResources[ns->getID()].name); + PX_ASSERT(id < mResources.size()); + if (id < mResources.size() && refCount) + { + mResources[id].refCount++; + } + return id; + } + else + { + return INVALID_RESOURCE_ID; + } +} + +bool ApexResourceProvider::checkResource(ResID nameSpace, const char* name) +{ + /* Return true is named resource has known non-null pointer */ + uint32_t nsIndex = getNSIndex(nameSpace); + if (nsIndex < mNameSpaces.size()) + { + NameSpace* ns = mNameSpaces[nsIndex]; + ResID id = ns->getOrCreateID(name, mResources[ns->getID()].name); + PX_ASSERT(id < mResources.size()); + return checkResource(id); + } + return false; +} + +bool ApexResourceProvider::checkResource(ResID id) +{ + if (mResources.size() <= id) + { + return false; + } + + ApexResourceProvider::resource& res = mResources[id]; + + if (!res.valueIsSet) + { + return false; + } + + return true; +} + +void ApexResourceProvider::generateUniqueName(ResID nameSpace, ApexSimpleString& name) +{ + uint32_t nsIndex = getNSIndex(nameSpace); + if (nsIndex < mNameSpaces.size()) + { + ApexSimpleString test; + uint32_t count = 1; + char buf[64]; + *buf = '.'; + + do + { + shdfnd::snprintf(buf + 1,60, "%d", count); + test = name + ApexSimpleString(buf); + if (!checkResource(nameSpace, test.c_str())) + { + break; + } + } + while (++count < 0xFFFFFFF0); + + name = test; + } +} + +void ApexResourceProvider::releaseResource(ResID id) +{ + if (mResources.size() <= id) + { + return; + } + + ApexResourceProvider::resource& res = mResources[id]; + + PX_ASSERT(res.refCount); + if (res.refCount > 0) + { + res.refCount--; + + if (res.refCount == 0 && mUserCallback && + res.valueIsSet && res.ptr != NULL) + { + if (mResources[id].usedGetResource) // Defect DE641 only callback to the user, if this resource was created by a GetResource request + { + mUserCallback->releaseResource(res.nameSpace, res.name, res.ptr); + } + res.ptr = (void*) UnknownValue; + res.valueIsSet = false; + res.usedGetResource = false; + } + // if the ptr is NULL and we're releasing it, we do want to call requestResource next time it is requested, so valueIsSet = false + else if (res.refCount == 0 && res.valueIsSet && res.ptr == NULL) + { + res.ptr = (void*) UnknownValue; + res.valueIsSet = false; + res.usedGetResource = false; + } + } +} + +void* ApexResourceProvider::getResource(ResID id) +{ + if (mResources.size() <= id) + { + return NULL; + } + else if (!mResources[id].valueIsSet) + { + // PH: WARNING: This MUST not be a reference, mResource can be altered during the requestResource() operation!!!! + ApexResourceProvider::resource res = mResources[id]; + if (mUserCallback) + { + // tmp ensures that the [] operator is called AFTER mResources is possibly + // resized by something in requestResources + void* tmp = mUserCallback->requestResource(res.nameSpace, res.name); + res.ptr = tmp; + res.valueIsSet = true; + res.usedGetResource = true; + } + else + { + res.ptr = NULL; + } + mResources[id] = res; + } + return mResources[id].ptr; +} + +const char* ApexResourceProvider::getResourceName(ResID id) +{ + if (mResources.size() <= id) + { + return NULL; + } + return mResources[id].name; +} +const char* ApexResourceProvider::getResourceNameSpace(ResID id) +{ + if (mResources.size() <= id) + { + return NULL; + } + return mResources[id].nameSpace; +} + + +bool ApexResourceProvider::getResourceIDs(const char* nameSpace, ResID* outResIDs, uint32_t& outCount, uint32_t inCount) +{ + outCount = 0; + + if (!outResIDs) + { + return false; + } + + for (uint32_t i = 0; i < mResources.size(); i++) + { + if (stringsMatch(mResources[i].nameSpace, nameSpace)) + { + if (outCount > inCount) + { + outCount = 0; + return false; + } + outResIDs[outCount++] = i; + } + } + + return true; +} + +void ApexResourceProvider::destroy() +{ + if (mUserCallback) + { + for (uint32_t i = 0 ; i < mResources.size() ; i++) + { + ApexResourceProvider::resource& res = mResources[i]; + if (res.refCount != 0 && res.valueIsSet && res.ptr != NULL) + { + ResID resIndex = mNSNames.getOrCreateID(res.nameSpace, "NameSpace"); + PX_ASSERT(mResources[resIndex].ptr); + uint32_t nsIndex = getNSIndex((ResID)(size_t)mResources[resIndex].ptr); + if (nsIndex < mNameSpaces.size() && + mNameSpaces[nsIndex]->releaseAtExit()) + { + if (res.usedGetResource) // this check added for PhysXLab DE4349 + { + mUserCallback->releaseResource(res.nameSpace, res.name, res.ptr); + } + else + { + APEX_DEBUG_WARNING("Unreleased resource found during teardown: Namespace <%s>, Name <%s>", res.nameSpace, res.name); + } + } + } + } + } + mResources.clear(); + for (uint32_t i = 0 ; i < mNameSpaces.size() ; i++) + { + PX_DELETE(mNameSpaces[i]); + } + mNameSpaces.clear(); + delete this; +} + +ApexResourceProvider::NameSpace::NameSpace(ApexResourceProvider* arp, ResID nsid, bool releaseAtExit, const char* nameSpace) : + mReleaseAtExit(releaseAtExit), + mArp(arp), + mId(nsid) +{ + memset(hash, 0, sizeof(hash)); + mNameSpace = 0; + if (nameSpace) + { + uint32_t len = (uint32_t) strlen(nameSpace); + mNameSpace = (char*)PX_ALLOC(len + 1, PX_DEBUG_EXP("ApexResourceProvider::NameSpace")); + memcpy(mNameSpace, nameSpace, len + 1); + } +} + +ApexResourceProvider::NameSpace::~NameSpace() +{ + // Free up all collision chains in the hash table + for (uint32_t i = 0 ; i < HashSize ; i++) + { + while (hash[i]) + { + const char* entry = hash[i]; + const entryHeader* hdr = (const entryHeader*) entry; + const char* next = hdr->nextEntry; + PX_FREE((void*) entry); + hash[i] = next; + } + } + PX_FREE(mNameSpace); +} + +ResID ApexResourceProvider::NameSpace::getOrCreateID(const char* &name, const char* NSName) +{ + /* Hash Table Entry: | nextEntry* | ResID | name | */ + uint16_t h = genHash(name); + const char* entry = hash[h]; + + while (entry) + { + entryHeader* hdr = (entryHeader*) entry; + const char* entryName = entry + sizeof(entryHeader); + + if (mArp->stringsMatch(name, entryName)) + { + name = entryName; + return hdr->id; + } + + entry = hdr->nextEntry; + } + + size_t len = strlen(name); + size_t bufsize = len + 1 + sizeof(entryHeader); + char* newEntry = (char*) PX_ALLOC(bufsize, PX_DEBUG_EXP("ApexResourceProvider::NameSpace::getOrCreateID")); + if (newEntry) + { +#if defined(WIN32) + strncpy_s(newEntry + sizeof(entryHeader), bufsize - sizeof(entryHeader), name, len); +#else + strcpy(newEntry + sizeof(entryHeader), name); +#endif + entryHeader* hdr = (entryHeader*) newEntry; + hdr->nextEntry = hash[h]; + hdr->id = mArp->mResources.size(); + + resource res; + res.ptr = (void*) UnknownValue; + res.valueIsSet = false; + res.name = newEntry + sizeof(entryHeader); + res.nameSpace = NSName; + res.refCount = 0; + res.usedGetResource = 0; + mArp->mResources.pushBack(res); + + hash[h] = (const char*) newEntry; + + name = res.name; + return hdr->id; + } + + return INVALID_RESOURCE_ID; +} + +ResID ApexResourceProvider::getNSID(const char* nsName) +{ + physx::Hash<const char*> h; + ResID id = h(nsName); + const HashMapNSID::Entry* nsid = mNSID.find(id); + if (nsid) + { + PX_ASSERT(nsid->second < mNameSpaces.size() && mNameSpaces[nsid->second] != NULL); + if (nsid->second < mNameSpaces.size() && mNameSpaces[nsid->second] != NULL && !h.equal(nsName, mNameSpaces[nsid->second]->getNameSpace())) + { + PX_ALWAYS_ASSERT_MESSAGE("Hash collision detected for namespaces in ApexResourceProvider. Try to adjust hash function."); + return INVALID_RESOURCE_ID; + } + } + return id; +} + +uint32_t ApexResourceProvider::getNSIndex(ResID nameSpace) +{ + PX_ASSERT(nameSpace != INVALID_RESOURCE_ID); + if (nameSpace == INVALID_RESOURCE_ID) return INVALID_RESOURCE_ID; + const HashMapNSID::Entry* ns = mNSID.find(nameSpace); + PX_ASSERT(ns); + uint32_t nsIndex = ns ? ns->second : INVALID_RESOURCE_ID; + PX_ASSERT(nsIndex < mNameSpaces.size()); + return nsIndex; +} + +uint16_t ApexResourceProvider::NameSpace::genHash(const char* name) +{ + PX_ASSERT(name != NULL); + /* XOR each 32bit word together */ + uint32_t h = 0; + uint32_t* read32 = (uint32_t*)name; + size_t len = strlen(name); + + /* Add remaining bytes */ + uint8_t* read8 = (uint8_t*) read32; + while (len) + { + if (mArp->isCaseSensitive()) + { + h ^= *read8; + } + else + { + h ^= toupper(*read8); + } + read8++; + len -= sizeof(uint8_t); + } + + /* XOR fold top 16 bits over bottom 16 bits */ + h ^= (h >> 16); + + return (uint16_t)(h & (HashSize - 1)); +} + +void ApexResourceProvider::dumpResourceTable() +{ + APEX_DEBUG_INFO("ApexResourceProvider::dumpResourceTable"); + APEX_DEBUG_INFO("namespace name refcount pointer valueIsSet"); + + for (uint32_t i = 0; i < mResources.size(); i++) + { + APEX_DEBUG_INFO("%s %s %d 0x%08x %d", mResources[i].nameSpace, mResources[i].name, mResources[i].refCount, mResources[i].ptr, mResources[i].valueIsSet); + } +} + + +void ApexResourceProvider::setResourceU32(const char* nameSpace, const char* name, uint32_t id, bool incRefCount) +{ + setResource(nameSpace, name, (void*)(size_t)id, true, incRefCount); +} + +uint32_t ApexResourceProvider::releaseAllResourcesInNamespace(const char* nameSpace) +{ + uint32_t ret = 0; + + for (uint32_t i = 0; i < mResources.size(); i++) + { + ApexResourceProvider::resource& res = mResources[i]; + if (stringsMatch(res.nameSpace, nameSpace) && res.valueIsSet) + { + ret++; + PX_ASSERT(res.refCount); + if (res.refCount > 0) + { + res.refCount--; + if (res.refCount == 0 && mUserCallback && + res.valueIsSet && res.ptr != NULL) + { + mUserCallback->releaseResource(res.nameSpace, res.name, res.ptr); + res.ptr = (void*) UnknownValue; + res.valueIsSet = false; + } + } + } + } + + return ret; +} + +uint32_t ApexResourceProvider::releaseResource(const char* nameSpace, const char* name) +{ + uint32_t ret = 0; + + PX_ASSERT(nameSpace); + PX_ASSERT(name); + uint32_t nsIndex = getNSIndex(createNameSpaceInternal(nameSpace, true)); + if (nsIndex < mNameSpaces.size()) + { + ResID id = mNameSpaces[nsIndex]->getOrCreateID(name, nameSpace); + PX_ASSERT(id < mResources.size()); + if (id < mResources.size()) + { + ApexResourceProvider::resource& res = mResources[id]; + if (res.valueIsSet) + { + ret = (uint32_t)res.refCount - 1; + releaseResource(id); + } + } + } + + + return ret; +} + +bool ApexResourceProvider::findRefCount(const char* nameSpace, const char* name, uint32_t& refCount) +{ + bool ret = false; + refCount = 0; + PX_ASSERT(nameSpace); + PX_ASSERT(name); + uint32_t nsIndex = getNSIndex(createNameSpaceInternal(nameSpace, true)); + if (nsIndex < mNameSpaces.size()) + { + ResID id = mNameSpaces[nsIndex]->getOrCreateID(name, nameSpace); + PX_ASSERT(id < mResources.size()); + if (id < mResources.size()) + { + if (mResources[id].valueIsSet) + { + ret = true; + refCount = mResources[id].refCount; + } + } + } + + return ret; +} + +void* ApexResourceProvider::findResource(const char* nameSpace, const char* name) +{ + void* ret = NULL; + PX_ASSERT(nameSpace); + PX_ASSERT(name); + uint32_t nsIndex = getNSIndex(createNameSpaceInternal(nameSpace, true)); + if (nsIndex < mNameSpaces.size()) + { + ResID id = mNameSpaces[nsIndex]->getOrCreateID(name, nameSpace); + PX_ASSERT(id < mResources.size()); + if (id < mResources.size()) + { + if (mResources[id].valueIsSet) + { + ret = mResources[id].ptr; + } + } + } + return ret; +} + +uint32_t ApexResourceProvider::findResourceU32(const char* nameSpace, const char* name) // find an existing resource. +{ + uint32_t ret = 0; + PX_ASSERT(nameSpace); + PX_ASSERT(name); + uint32_t nsIndex = getNSIndex(createNameSpaceInternal(nameSpace, true)); + if (nsIndex < mNameSpaces.size()) + { + ResID id = mNameSpaces[nsIndex]->getOrCreateID(name, nameSpace); + PX_ASSERT(id < mResources.size()); + if (id < mResources.size()) + { + if (mResources[id].valueIsSet) + { +#if PX_X64 + uint64_t ret64 = (uint64_t)mResources[id].ptr; + ret = (uint32_t)ret64; +#else + ret = (uint32_t)mResources[id].ptr; +#endif + } + } + } + return ret; + +} + +void** ApexResourceProvider::findAllResources(const char* nameSpace, uint32_t& count) // find all resources in this namespace +{ + void** ret = 0; + count = 0; + + mCharResults.clear(); + for (uint32_t i = 0; i < mResources.size(); i++) + { + if (stringsMatch(nameSpace, mResources[i].nameSpace)) + { + if (mResources[i].valueIsSet) + { + mCharResults.pushBack((const char*)mResources[i].ptr); + } + } + } + if (!mCharResults.empty()) + { + ret = (void**)&mCharResults[0]; + count = mCharResults.size(); + } + + return ret; +} + +const char** ApexResourceProvider::findAllResourceNames(const char* nameSpace, uint32_t& count) // find all resources in this namespace +{ + const char** ret = 0; + count = 0; + + mCharResults.clear(); + for (uint32_t i = 0; i < mResources.size(); i++) + { + if (stringsMatch(nameSpace, mResources[i].nameSpace) && mResources[i].valueIsSet) + { + mCharResults.pushBack(mResources[i].name); + } + } + if (!mCharResults.empty()) + { + ret = &mCharResults[0]; + count = mCharResults.size(); + } + + return ret; +} + +const char** ApexResourceProvider::findNameSpaces(uint32_t& count) +{ + const char** ret = 0; + count = 0; + + mCharResults.clear(); + for (physx::Array<NameSpace*>::Iterator i = mNameSpaces.begin(); i != mNameSpaces.end(); ++i) + { + const char* nameSpace = (*i)->getNameSpace(); + if (nameSpace) + { + mCharResults.pushBack(nameSpace); + } + } + + if (!mCharResults.empty()) + { + count = mCharResults.size(); + ret = &mCharResults[0]; + } + + return ret; +} + +bool ApexResourceProvider::stringsMatch(const char* str0, const char* str1) +{ + if (mCaseSensitive) + { + return !nvidia::strcmp(str0, str1); + } + else + { + return !nvidia::stricmp(str0, str1); + } + +} + + +} +} // end namespace nvidia::apex |