intptr_t DefaultAssertionHandler(intptr_t /*userParameter*/, const char* title, const char* message) { if(OVRIsDebuggerPresent()) { OVR_DEBUG_BREAK; } else { #if defined(OVR_BUILD_DEBUG) // Print a stack trace of all threads. OVR::String s; OVR::String threadListOutput; static OVR::SymbolLookup symbolLookup; s = "Failure: "; s += message; if(symbolLookup.Initialize() && symbolLookup.ReportThreadCallstack(threadListOutput, 4)) // This '4' is there to skip our internal handling and retrieve starting at the assertion location (our caller) only. { s += "\r\n\r\n"; s += threadListOutput; } OVR::Util::DisplayMessageBox(title, s.ToCStr()); #else OVR::Util::DisplayMessageBox(title, message); #endif } return 0; }
intptr_t DefaultAssertionHandler(intptr_t /*userParameter*/, const char* title, const char* message) { if(OVRIsDebuggerPresent()) { OVR_DEBUG_BREAK; } else { OVR_UNUSED(title); OVR_UNUSED(message); #if defined(OVR_BUILD_DEBUG) if(Allocator::GetInstance()) // The code below currently depends on having a valid Allocator. { // Print a stack trace of all threads. OVR::String s; OVR::String threadListOutput; static OVR::SymbolLookup symbolLookup; s = "Failure: "; s += message; if(symbolLookup.Initialize() && symbolLookup.ReportThreadCallstack(threadListOutput, 4)) // This '4' is there to skip our internal handling and retrieve starting at the assertion location (our caller) only. { // threadListOutput has newlines that are merely \n, whereas Windows MessageBox wants \r\n newlines. So we insert \r in front of all \n. for(size_t i = 0, iEnd = threadListOutput.GetSize(); i < iEnd; i++) { if(threadListOutput[i] == '\n') { threadListOutput.Insert("\r", i, 1); ++i; ++iEnd; } } s += "\r\n\r\n"; s += threadListOutput; } OVR::Util::DisplayMessageBox(title, s.ToCStr()); } else { OVR::Util::DisplayMessageBox(title, message); } #else OVR::Util::DisplayMessageBox(title, message); #endif } return 0; }
bool CoreTexture::RebuildTexture(JSContext* cx, OVR::String pathStr) { OVR::FreeTexture(texture); if (pathStr.IsEmpty()) { return true; } OVR::MemBufferFile bufferFile(OVR::MemBufferFile::NoInit); if (CURRENT_BASE_DIR.IsEmpty()) { if (!OVR::ovr_ReadFileFromApplicationPackage(pathStr.ToCStr(), bufferFile)) { JS_ReportError(cx, "Could not read texture from application package"); return false; } } else { OVR::String fullFileStr = FullFilePath(pathStr); if (!bufferFile.LoadFile(fullFileStr.ToCStr())) { JS_ReportError(cx, "Could not read texture %s", fullFileStr.ToCStr()); return false; } } // Now load it texture = OVR::LoadTextureFromBuffer( pathStr.ToCStr(), bufferFile, OVR::TextureFlags_t(OVR::TEXTUREFLAG_NO_DEFAULT), // TODO: Make configurable width, height ); BuildTextureMipmaps(texture); // Optional? Also does this happen in LoadTextureFromBuffer? // TODO: MakeTextureClamped MakeTextureLodClamped MakeTextureTrilinear // MakeTextureLinear, MakeTextureAniso return true; }
bool GetSysErrorCodeString(ovrSysErrorCode sysErrorCode, bool prefixErrorCode, OVR::String& sResult) { char errorBuffer[1024]; errorBuffer[0] = '\0'; if (prefixErrorCode) { char prefixBuffer[64]; snprintf(prefixBuffer, OVR_ARRAY_COUNT(prefixBuffer), "0x%llx (%lld): ", (uint64_t)sysErrorCode, (int64_t)sysErrorCode); sResult = prefixBuffer; } else { sResult.Clear(); } #if defined(OVR_OS_WIN32) // Note: It may be useful to use FORMAT_MESSAGE_FROM_HMODULE here to get a module-specific error string if our source of errors // ends up including more than just system-native errors. For example, a third party module with custom errors defined in it. WCHAR errorBufferW[1024]; DWORD errorBufferWCapacity = OVR_ARRAY_COUNT(errorBufferW); DWORD length = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, (DWORD)sysErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errorBufferW, errorBufferWCapacity, nullptr); if (!length) // If failed... { if (HRESULT_FACILITY(sysErrorCode) == _FACDXGI) // If it is a DXGI error... { // This situation occurs on Windows 7. You can't use FORMAT_MESSAGE_FROM_HMODULE to solve it either. We can only use DXGetErrorString or manually handle it. const wchar_t* pStr = OVR_DXGetErrorStringW(sysErrorCode); if (pStr) { wcscpy_s(errorBufferW, OVR_ARRAY_COUNT(errorBufferW), pStr); length = (DWORD)wcslen(errorBufferW); } } } if (length) // If errorBufferW contains what we are looking for... { // Need to convert WCHAR errorBuffer to UTF8 char sResult; const auto requiredUTF8Length = OVR::UTF8Util::Strlcpy(errorBuffer, OVR_ARRAY_COUNT(errorBuffer), errorBufferW); if (requiredUTF8Length >= OVR_ARRAY_COUNT(errorBuffer)) // Zero out if too big (XXX truncate instead?) errorBuffer[0] = '\0'; // Else fall through } // Else fall through #else #if (((_POSIX_C_SOURCE >= 200112L) || (_XOPEN_SOURCE >= 600)) && !_GNU_SOURCE) || defined(__APPLE__) || defined(__BSD__) const int result = strerror_r((int)sysErrorCode, errorBuffer, OVR_ARRAY_COUNT(errorBuffer)); if (result != 0) // If failed... [result is 0 upon success; result will be EINVAL if the code is not recognized; ERANGE if buffer didn't have enough capacity.] errorBuffer[0] = '\0'; // re-null-terminate, in case strerror_r left it in an invalid state. #else const char* result = strerror_r((int)sysErrorCode, errorBuffer, OVR_ARRAY_COUNT(errorBuffer)); if (result == nullptr) // Implementations in practice seem to always return a pointer, though the behavior isn't formally standardized. errorBuffer[0] = '\0'; // re-null-terminate, in case strerror_r left it in an invalid state. #endif #endif // Fall through functionality of simply printing the value as an integer. if (errorBuffer[0]) // If errorBuffer was successfully written above... { sResult += errorBuffer; return true; } sResult += "(unknown)"; // This is not localized. Question: Is there a way to get the error formatting functions above to print this themselves in a localized way? return false; }
String OVRError::GetErrorString() const { StringBuffer stringBuffer("OVR Error:\n"); // Code OVR::String errorCodeString; GetErrorCodeString(Code, false, errorCodeString); stringBuffer.AppendFormat(" Code: %d -- %s\n", Code, errorCodeString.ToCStr()); // SysCode if (SysCode != ovrSysErrorCodeSuccess) { OVR::String sysErrorString; GetSysErrorCodeString(SysCode, false, sysErrorString); OVRRemoveTrailingNewlines(sysErrorString); stringBuffer.AppendFormat(" System error: %d (%x) -- %s\n", (int)SysCode, (int)SysCode, sysErrorString.ToCStr()); } // Description if (Description.GetLength()) { stringBuffer.AppendFormat(" Description: %s\n", Description.ToCStr()); } // OVRTime stringBuffer.AppendFormat(" OVRTime: %f\n", OVRTime); // SysClockTime OVR::String sysClockTimeString; OVRFormatDateTime(ClockTime, sysClockTimeString); stringBuffer.AppendFormat(" Time: %s\n", sysClockTimeString.ToCStr()); // Context if (Context.GetLength()) { stringBuffer.AppendFormat(" Context: %s\n", Context.ToCStr()); } // If LogLine is set, if (LogLine != kLogLineUnset) { stringBuffer.AppendFormat(" LogLine: %lld\n", LogLine); } // FILE/LINE if (SourceFilePath.GetLength()) { stringBuffer.AppendFormat(" File/Line: %s:%d\n", SourceFilePath.ToCStr(), SourceFileLine); } // Backtrace if (Backtrace.GetSize()) { // We can trace symbols in a debug build here or we can trace just addresses. See other code for // examples of how to trace symbols. stringBuffer.AppendFormat(" Backtrace: "); for (size_t i = 0, iEnd = Backtrace.GetSize(); i != iEnd; ++i) stringBuffer.AppendFormat(" %p", Backtrace[i]); stringBuffer.AppendChar('\n'); } return OVR::String(stringBuffer.ToCStr(), stringBuffer.GetSize()); }
bool CoreTexture::RebuildCubemap(JSContext* cx, OVR::String pathStr) { OVR::FreeTexture(texture); if (pathStr.IsEmpty()) { return true; } // Get the file extension, and a copy of the path with no extension OVR::String ext = pathStr.GetExtension(); OVR::String noExt(pathStr); noExt.StripExtension(); // Create some membuffers for the files we're going to open OVR::MemBufferFile mbfs[6] = { OVR::MemBufferFile(OVR::MemBufferFile::NoInit), OVR::MemBufferFile(OVR::MemBufferFile::NoInit), OVR::MemBufferFile(OVR::MemBufferFile::NoInit), OVR::MemBufferFile(OVR::MemBufferFile::NoInit), OVR::MemBufferFile(OVR::MemBufferFile::NoInit), OVR::MemBufferFile(OVR::MemBufferFile::NoInit) }; // Load all of them up const char* const cubeSuffix[6] = {"_px", "_nx", "_py", "_ny", "_pz", "_nz"}; for (int side = 0; side < 6; ++side) { OVR::String sidePath = noExt + OVR::String(cubeSuffix[side]) + ext; if (CURRENT_BASE_DIR.IsEmpty()) { if (!OVR::ovr_ReadFileFromApplicationPackage(sidePath.ToCStr(), mbfs[side])) { JS_ReportError(cx, "Could not load cube file"); return false; } } else { OVR::String fullFileStr = FullFilePath(sidePath); if (!mbfs[side].LoadFile(fullFileStr.ToCStr())) { JS_ReportError(cx, "Could not load cube file"); return false; } } } unsigned char* data[6]; int comp, imgWidth, imgHeight; // For each side of the cube for (int i = 0; i < 6; ++i) { // Load the image data[i] = (unsigned char *)stbi_load_from_memory( (unsigned char *)mbfs[i].Buffer, mbfs[i].Length, &imgWidth, &imgHeight, &comp, 4); // Sanity check image dimensions if (imgWidth != width) { JS_ReportError(cx, "Cubemap has mismatched image width"); return false; } if (imgHeight != height) { JS_ReportError(cx, "Cubemap has mismatched image height"); return false; } if (imgWidth <= 0 || imgWidth > 32768 || imgHeight <= 0 || imgHeight > 32768) { JS_ReportError(cx, "Invalid texture size"); return false; } } GLenum glFormat; GLenum glInternalFormat; if (!TextureFormatToGlFormat(OVR::Texture_RGBA, true, glFormat, glInternalFormat)) { JS_ReportError(cx, "Invalid texture format OVR::Texture_RGBA"); return false; } GLuint texId; glGenTextures(1, &texId); glBindTexture(GL_TEXTURE_CUBE_MAP, texId); // Get the total size (GetOvrTextureSize(OVR::Texture_RGBA, width, height) * 6) // size_t totalSize = (((width + 3) / 4) * ((height + 3) / 4) * 8) * 6; for (int i = 0; i < 6; ++i) { glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, width, height, 0, glFormat, GL_UNSIGNED_BYTE, data[i]); } // Generate mipmaps and bind the texture glGenerateMipmap(GL_TEXTURE_CUBE_MAP); glBindTexture(GL_TEXTURE_CUBE_MAP, 0); // Construct our actual texture object texture = OVR::GlTexture(texId, GL_TEXTURE_CUBE_MAP); // Free our image data for (int i = 0; i < 6; ++i) { free(data[i]); } // Wait for the upload to complete. glFinish(); return true; }
OVR::String FullFilePath(OVR::String & fileStr) { OVR::String base = CURRENT_BASE_DIR; base.StripTrailing("/"); // TODO: Strip leading "/" in fileStr return base + "/" + fileStr; }