aboutsummaryrefslogtreecommitdiff
path: root/APEX_1.4/framework/src/ApexResourceProvider.cpp
diff options
context:
space:
mode:
authorgit perforce import user <a@b>2016-10-25 12:29:14 -0600
committerSheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees>2016-10-25 18:56:37 -0500
commit3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch)
treefa6485c169e50d7415a651bf838f5bcd0fd3bfbd /APEX_1.4/framework/src/ApexResourceProvider.cpp
downloadphysx-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.cpp702
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