#pragma once #include #include #if defined(__linux__) || defined(__ANDROID__) || defined(__QNXNTO__) || defined(__APPLE__) #include #include #endif #if defined(_WIN32) #define WIN32_LEAN_AND_MIN_AND_MAX #define NOMINMAX #include #include #include #endif #if defined(_PVR_LOG_H) #define Log_Info(...) ((void)Log(LogLevel::Information, __VA_ARGS__)) #define Log_Warning(...) ((void)Log(LogLevel::Warning, __VA_ARGS__)) #define Log_Error(...) ((void)Log(LogLevel::Error, __VA_ARGS__)) #else #if defined(__ANDROID__) #define _ANDROID 1 #include #define Log_Info(...) ((void)__android_log_print(ANDROID_LOG_INFO, "com.imgtec.vk", __VA_ARGS__)) #define Log_Warning(...) ((void)__android_log_print(ANDROID_LOG_WARN, "com.imgtec.vk", __VA_ARGS__)) #define Log_Error(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "com.imgtec.vk", __VA_ARGS__)) #elif defined(_WIN32) static const char* procAddressMessageTypes[] = { "INFORMATION: ", "WARNING:", "ERROR: ", }; inline void logOutput(const int logLevel, const char* const formatString, va_list argumentList) { static char buffer[4096]; va_list tempList; memset(buffer, 0, sizeof(buffer)); #if (defined _MSC_VER) // Pre VS2013 tempList = argumentList; #else va_copy(tempList, argumentList); #endif vsnprintf(buffer, 4095, formatString, argumentList); #if defined(_WIN32) && !defined(_CONSOLE) if (IsDebuggerPresent()) { OutputDebugString(procAddressMessageTypes[logLevel]); OutputDebugString(buffer); OutputDebugString("\n"); } #else printf("%s", procAddressMessageTypes[error]); vprintf(formatString, tempList); printf("\n"); #endif } inline void Log_Info(const char* const formatString, ...) { va_list argumentList; va_start(argumentList, formatString); logOutput(0, formatString, argumentList); va_end(argumentList); } inline void Log_Warning(const char* const formatString, ...) { va_list argumentList; va_start(argumentList, formatString); logOutput(1, formatString, argumentList); va_end(argumentList); } inline void Log_Error(const char* const formatString, ...) { va_list argumentList; va_start(argumentList, formatString); logOutput(2, formatString, argumentList); va_end(argumentList); } #else #define Log_Info(...) ((void)printf(__VA_ARGS__)) #define Log_Warning(...) ((void)fprintf(stderr, __VA_ARGS__)) #define Log_Error(...) ((void)fprintf(stderr, __VA_ARGS__)) #endif #endif /** ABSTRACT THE PLATFORM SPEFCIFIC LIBRARY LOADING FUNCTIONS **/ #if defined(_WIN32) namespace pvr { namespace lib { typedef HINSTANCE LIBTYPE; } } // namespace pvr namespace pvr { namespace internal { inline pvr::lib::LIBTYPE OpenLibrary(const char* pszPath) { #if defined(_UNICODE) // UNDER_CE if (!pszPath) { Log_Error("Path must be valid '%s'", pszPath); return nullptr; } // Get full path of executable wchar_t pszPathW[_MAX_PATH]; // Convert char to wchar DWORD i = 0; for (i = 0; i <= strlen(pszPath); ++i) { pszPathW[i] = static_cast(pszPath[i]); } pszPathW[i] = ' '; pvr::lib::LIBTYPE hostLib = LoadLibraryW(pszPathW); #else pvr::lib::LIBTYPE hostLib = LoadLibraryA(pszPath); #endif if (!hostLib) { Log_Error("Could not load host library '%s'", pszPath); } Log_Info("Host library '%s' loaded", pszPath); return hostLib; } inline void CloseLibrary(pvr::lib::LIBTYPE hostLib) { FreeLibrary(hostLib); } inline void* getLibraryFunction(pvr::lib::LIBTYPE hostLib, const char* pszName) { if (hostLib) { #if defined(UNDER_CE) return win32::GetProcAddressA(hostLib, pszName); #else return GetProcAddress(hostLib, pszName); #endif } return nullptr; } } // namespace internal } // namespace pvr #elif defined(__linux__) || defined(__QNXNTO__) || defined(__APPLE__) #if defined(__APPLE__) #if !TARGET_OS_IPHONE #include "CoreFoundation/CoreFoundation.h" static const char* g_pszEnvVar = "PVRTRACE_LIB_PATH"; inline void* OpenFramework(const char* pszPath) { CFBundleRef mainBundle = CFBundleGetMainBundle(); CFURLRef resourceURL = CFBundleCopyPrivateFrameworksURL(mainBundle); char path[PATH_MAX]; if (!CFURLGetFileSystemRepresentation(resourceURL, TRUE, (UInt8*)path, PATH_MAX)) { return 0; } CFRelease(resourceURL); { void* lib = NULL; // --- Set a global environment variable to point to this path (for VFrame usage) const char* slash = strrchr(pszPath, '/'); if (slash) { char szPath[FILENAME_MAX]; memset(szPath, 0, sizeof(szPath)); strncpy(szPath, pszPath, slash - pszPath); setenv(g_pszEnvVar, szPath, 1); } else { // Use the current bundle path std::string framework = std::string(path) + "/../Frameworks/"; setenv(g_pszEnvVar, framework.c_str(), 1); } // --- Make a temp symlink char szTempFile[FILENAME_MAX]; memset(szTempFile, 0, sizeof(szTempFile)); char tmpdir[PATH_MAX]; size_t n = confstr(_CS_DARWIN_USER_TEMP_DIR, tmpdir, sizeof(tmpdir)); if ((n <= 0) || (n >= sizeof(tmpdir))) { strlcpy(tmpdir, getenv("TMPDIR"), sizeof(tmpdir)); } strcat(szTempFile, tmpdir); strcat(szTempFile, "tmp.XXXXXX"); if (mkstemp(szTempFile)) { if (symlink(pszPath, szTempFile) == 0) { lib = dlopen(szTempFile, RTLD_LAZY | RTLD_GLOBAL); remove(szTempFile); } } // --- Can't find the lib? Check the application framework folder instead. if (!lib) { std::string framework = std::string(path) + std::string("/") + pszPath; lib = dlopen(framework.c_str(), RTLD_LAZY | RTLD_GLOBAL); if (!lib) { const char* err = dlerror(); if (err) { // NSLog(@"dlopen failed with error: %s => %@", err, framework); } } } return lib; } } #endif #endif namespace pvr { namespace lib { typedef void* LIBTYPE; } } // namespace pvr namespace pvr { namespace internal { #if defined(__APPLE__) && !TARGET_OS_IPHONE inline pvr::lib::LIBTYPE OpenLibrary(const char* pszPath) { // An objective-C function that uses dlopen pvr::lib::LIBTYPE hostLib = OpenFramework(pszPath); if (!hostLib) { Log_Error("Could not load§ host library '%s'", pszPath); } Log_Info("Host library '%s' loaded", pszPath); return hostLib; } #else namespace { inline pvr::lib::LIBTYPE OpenLibrary_Helper(const char* pszPath) { pvr::lib::LIBTYPE hostLib = dlopen(pszPath, RTLD_LAZY | RTLD_GLOBAL); if (!hostLib) { char pathMod[256]; strcpy(pathMod, "./"); strcat(pathMod, pszPath); hostLib = dlopen(pathMod, RTLD_LAZY | RTLD_GLOBAL); } return hostLib; } } // namespace inline pvr::lib::LIBTYPE OpenLibrary(const char* pszPath) { size_t start = 0; std::string tmp; std::string LibPath(pszPath); pvr::lib::LIBTYPE hostLib = nullptr; while (!hostLib) { size_t end = LibPath.find_first_of(';', start); if (end == std::string::npos) { tmp = LibPath.substr(start, LibPath.length() - start); } else { tmp = LibPath.substr(start, end - start); } if (!tmp.empty()) { hostLib = OpenLibrary_Helper(tmp.c_str()); if (!hostLib) { // Remove the last character in case a new line character snuck in tmp = tmp.substr(0, tmp.size() - 1); hostLib = OpenLibrary_Helper(tmp.c_str()); } } if (end == std::string::npos) { break; } start = end + 1; } if (!hostLib) { const char* err = dlerror(); if (err) { Log_Error("Could not load host library '%s'", pszPath); Log_Error("dlopen failed with error '%s'", err); } } Log_Info("Host library '%s' loaded", pszPath); return hostLib; } #endif inline void CloseLibrary(pvr::lib::LIBTYPE hostLib) { dlclose(hostLib); } inline void* getLibraryFunction(pvr::lib::LIBTYPE hostLib, const char* pszName) { if (hostLib) { void* func = dlsym(hostLib, pszName); return func; } return nullptr; } } } // namespace pvr #elif defined(ANDROID) namespace pvr { namespace internal { inline pvr::lib::LIBTYPE OpenLibrary(const char* pszPath) { pvr::lib::LIBTYPE hostLib = dlopen(pszPath, RTLD_LAZY | RTLD_GLOBAL); if (!hostLib) { const char* err = dlerror(); if (err) { Log_Error("Could not load host library '%s'", pszPath); Log_Error("dlopen failed with error '%s'", err); } } Log_Info("Host library '%s' loaded", pszPath); return hostLib; } inline void CloseLibrary(pvr::lib::LIBTYPE hostLib) { dlclose(hostLib); } inline void* getLibraryFunction(pvr::lib::LIBTYPE hostLib, const char* pszName) { void* fnct = dlsym(hostLib, pszName); return fnct; } } // namespace internal } // namespace pvr #else #error Unsupported platform #endif namespace pvr { namespace lib { static pvr::lib::LIBTYPE hostLib = nullptr; static std::string libraryName; static inline pvr::lib::LIBTYPE openlib(const std::string& libName) { libraryName = libName; hostLib = pvr::internal::OpenLibrary(libName.c_str()); return hostLib; } static inline void closelib(pvr::lib::LIBTYPE lib) { pvr::internal::CloseLibrary(lib); } template PtrType_ inline getLibFunction(pvr::lib::LIBTYPE hostLib, const std::string& functionName) { return reinterpret_cast(pvr::internal::getLibraryFunction(hostLib, functionName.c_str())); } template PtrType_ inline getLibFunctionChecked(pvr::lib::LIBTYPE hostLib, const std::string& functionName) { PtrType_ func = getLibFunction(hostLib, functionName); if (!func) { Log_Error("Failed to load function [%s] from library '%s'.\n", functionName.c_str(), libraryName.c_str()); } return func; } } // namespace lib } // namespace pvr