void OculusWorldDemoApp::InitMainFilePath() { // We try alternative relative locations for the file. const String contentBase = pPlatform->GetContentDirectory() + "/" + WORLDDEMO_ASSET_PATH; const char* baseDirectories[] = { "", contentBase.ToCStr(), #ifdef SHRDIR #define STR1(x) #x #define STR(x) STR1(x) STR(SHRDIR) "/OculusWorldDemo/Assets/Tuscany/" #endif }; String newPath; for(size_t i = 0; i < OVR_ARRAY_COUNT(baseDirectories); ++i) { newPath = baseDirectories[i]; newPath += WORLDDEMO_ASSET_FILE; OVR_DEBUG_LOG(("Trying to load the scene at: %s...", newPath.ToCStr())); if (SysFile(newPath).IsValid()) { OVR_DEBUG_LOG(("Success loading %s", newPath.ToCStr())); MainFilePath = newPath; return; } } OVR_DEBUG_LOG(("Unable to find any version of %s. Do you have your working directory set right?", WORLDDEMO_ASSET_FILE)); }
bool GetErrorCodeString(ovrResult resultIn, bool prefixErrorCode, OVR::String& sResult) { char codeBuffer[256]; const char* errorCodeName = GetErrorCodeName(resultIn); if (prefixErrorCode) { snprintf(codeBuffer, OVR_ARRAY_COUNT(codeBuffer), "0x%llx (%lld) %s", (uint64_t)resultIn, (int64_t)resultIn, errorCodeName); } else { snprintf(codeBuffer, OVR_ARRAY_COUNT(codeBuffer), "%s", errorCodeName); } sResult = codeBuffer; return true; }
void OVRError::SetCurrentValues() { OVRTime = Timer::GetSeconds(); // It would be better if we called ovr_GetTimeInSeconds, but that doesn't have a constant header to use. ClockTime = std::chrono::system_clock::now(); #if defined(OVR_ERROR_ENABLE_BACKTRACES) if (Symbols.IsInitialized()) { void* addressArray[32]; size_t n = Symbols.GetBacktrace(addressArray, OVR_ARRAY_COUNT(addressArray), 2, nullptr, OVR_THREADSYSID_INVALID); Backtrace.Clear(); Backtrace.Append(addressArray, n); } #endif }
void StringBuffer::AppendFormatV(const char* format, va_list argList) { char buffer[512]; char* bufferUsed = buffer; char* bufferAllocated = NULL; va_list argListSaved; va_copy(argListSaved, argList); int requiredStrlen = vsnprintf(bufferUsed, OVR_ARRAY_COUNT(buffer), format, argListSaved); // The large majority of the time this will succeed. if(requiredStrlen >= (int)sizeof(buffer)) // If the initial capacity wasn't enough... { bufferAllocated = (char*)OVR_ALLOC(sizeof(char) * (requiredStrlen + 1)); bufferUsed = bufferAllocated; if(bufferAllocated) { va_end(argListSaved); va_copy(argListSaved, argList); requiredStrlen = vsnprintf(bufferAllocated, (requiredStrlen + 1), format, argListSaved); } } if(requiredStrlen < 0) // If there was a printf format error... { bufferUsed = NULL; } va_end(argListSaved); if(bufferUsed) AppendString(bufferUsed); if(bufferAllocated) OVR_FREE(bufferAllocated); }
// We search the following paths relative to the executable: static const wchar_t* FWRelativePaths[] = { L"firmware.zip", L"../Tools/Firmware/firmware.zip", L"Firmware/firmware.zip", L"../Firmware/firmware.zip", L"../../Firmware/firmware.zip", L"../../../Firmware/firmware.zip", L"../../../../Firmware/firmware.zip", L"../../../../../Firmware/firmware.zip", L"../../../../../../Firmware/firmware.zip", L"../../../../../../../Firmware/firmware.zip", L"../../../../../../../../Firmware/firmware.zip", L"../oculus-tools/firmware/Firmware.zip" }; static const int RelativePathsCount = OVR_ARRAY_COUNT(FWRelativePaths); #ifdef OVR_OS_MS static std::wstring GetModulePath() { wchar_t wpath[MAX_PATH]; DWORD len = ::GetModuleFileNameW(nullptr, wpath, MAX_PATH); if (len <= 0 || len >= MAX_PATH) { return std::wstring(); } return wpath; }
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; }
void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) { if(RenderEnabled && eyeTexture) { // We need to render to the eyeTexture with the texture viewport. // Setup rendering to the texture. ovrGLTexture* eyeTextureGL = const_cast<ovrGLTexture*>(reinterpret_cast<const ovrGLTexture*>(eyeTexture)); OVR_ASSERT(eyeTextureGL->Texture.Header.API == ovrRenderAPI_OpenGL); // We init a temporary Context, Bind our own context, then Bind the temporary context below before exiting. // It's more exensive to have a temp context copy made here instead of having it as a saved member variable, // but we can't have a saved member variable because the app might delete the saved member behind our back // or associate it with another thread, which would cause our bind of it before exiting to be a bad operation. Context currentGLContext; // To do: Change this to use the AutoContext class that was recently created. currentGLContext.InitFromCurrent(); if(GLContext.GetIncarnation() == 0) // If not yet initialized... GLContext.CreateShared(currentGLContext); GLContext.Bind(); #if defined(OVR_OS_MAC) // To consider: merge the following into the Bind function. GLContext.SetSurface(currentGLContext); #endif // Load the graphics if not loaded already. if (!pTexture) LoadGraphics(); // Calculate ortho projection. GetOrthoProjection(RenderState, OrthoProjection); // Set the rendering to be to the eye texture. glBindFramebuffer(GL_FRAMEBUFFER, FrameBuffer); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, eyeTextureGL->OGL.TexId, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); // We aren't using depth, as we currently want this to overwrite everything. GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); OVR_ASSERT(status == GL_FRAMEBUFFER_COMPLETE); OVR_UNUSED(status); // Set up the viewport const GLint x = (GLint)eyeTextureGL->Texture.Header.RenderViewport.Pos.x; const GLint y = (GLint)eyeTextureGL->Texture.Header.RenderViewport.Pos.y; // Note that GL uses bottom-up coordinates. const GLsizei w = (GLsizei)eyeTextureGL->Texture.Header.RenderViewport.Size.w; const GLsizei h = (GLsizei)eyeTextureGL->Texture.Header.RenderViewport.Size.h; glViewport(x, y, w, h); // Set fixed-function render states. //glDepthRange(0.0, 1.0); // This is the default glDepthMask(GL_FALSE); glDisable(GL_DEPTH_TEST); glFrontFace(GL_CW); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Enable the buffer and shaders we use. ShaderFill fill(pShaderSet); if (pTexture) fill.SetTexture(0, pTexture); // Set shader uniforms. const float scale = HSWDISPLAY_SCALE * ((RenderState.OurHMDInfo.HmdType == HmdType_DK1) ? 0.70f : 1.f); pShaderSet->SetUniform2f("Scale", scale, scale / 2.f); // X and Y scale. Y is a fixed proportion to X in order to give a certain aspect ratio. pShaderSet->SetUniform2f("PositionOffset", OrthoProjection[eye].GetTranslation().x, 0.0f); // Set vertex attributes if (GLVersionInfo.SupportsVAO) { OVR_ASSERT(VAO != 0); glBindVertexArray(VAO); } if(!VAOInitialized) // This executes for the case that VAO isn't supported. { glBindBuffer(GL_ARRAY_BUFFER, pVB->GLBuffer); // This must be called before glVertexAttribPointer is called below. const GLuint shaderProgram = pShaderSet->Prog; GLint attributeLocationArray[3]; attributeLocationArray[0] = glGetAttribLocation(shaderProgram, "Position"); glVertexAttribPointer(attributeLocationArray[0], sizeof(Vector3f)/sizeof(float), GL_FLOAT, false, sizeof(HASWVertex), reinterpret_cast<char*>(offsetof(HASWVertex, Pos))); attributeLocationArray[1] = glGetAttribLocation(shaderProgram, "Color"); glVertexAttribPointer(attributeLocationArray[1], sizeof(Color)/sizeof(uint8_t), GL_UNSIGNED_BYTE, true, sizeof(HASWVertex), reinterpret_cast<char*>(offsetof(HASWVertex, C))); // True because we want it to convert [0,255] to [0,1] for us. attributeLocationArray[2] = glGetAttribLocation(shaderProgram, "TexCoord"); glVertexAttribPointer(attributeLocationArray[2], sizeof(float[2])/sizeof(float), GL_FLOAT, false, sizeof(HASWVertex), reinterpret_cast<char*>(offsetof(HASWVertex, U))); for (size_t i = 0; i < OVR_ARRAY_COUNT(attributeLocationArray); i++) glEnableVertexAttribArray((GLuint)i); } fill.Set(Prim_TriangleStrip); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); if (GLVersionInfo.SupportsVAO) { VAOInitialized = true; glBindVertexArray(0); } currentGLContext.Bind(); } }
void HSWDisplay::LoadGraphics() { // We assume here that the current GL context is the one our resources will be associated with. if(GLVersionInfo.MajorVersion == 0) GetGLVersionAndExtensions(GLVersionInfo); if (FrameBuffer == 0) { glGenFramebuffers(1, &FrameBuffer); } if (!pTexture) // To do: Add support for .dds files, which would be significantly smaller than the size of the tga. { size_t textureSize; const uint8_t* TextureData = GetDefaultTexture(textureSize); pTexture = *LoadTextureTga(RenderParams, Sample_Linear | Sample_Clamp, TextureData, (int)textureSize, 255); } if (!pShaderSet) { pShaderSet = *new ShaderSet(); } if(!pVertexShader) { OVR::String strShader((GLVersionInfo.MajorVersion >= 3) ? glsl3Prefix : glsl2Prefix); strShader += SimpleTexturedQuad_vs; pVertexShader = *new VertexShader(&RenderParams, const_cast<char*>(strShader.ToCStr()), strShader.GetLength(), SimpleTexturedQuad_vs_refl, OVR_ARRAY_COUNT(SimpleTexturedQuad_vs_refl)); pShaderSet->SetShader(pVertexShader); } if(!pFragmentShader) { OVR::String strShader((GLVersionInfo.MajorVersion >= 3) ? glsl3Prefix : glsl2Prefix); strShader += SimpleTexturedQuad_ps; pFragmentShader = *new FragmentShader(&RenderParams, const_cast<char*>(strShader.ToCStr()), strShader.GetLength(), SimpleTexturedQuad_ps_refl, OVR_ARRAY_COUNT(SimpleTexturedQuad_ps_refl)); pShaderSet->SetShader(pFragmentShader); } if(!pVB) { pVB = *new Buffer(&RenderParams); pVB->Data(Buffer_Vertex, NULL, 4 * sizeof(HASWVertex)); HASWVertex* pVertices = (HASWVertex*)pVB->Map(0, 4 * sizeof(HASWVertex), Map_Discard); OVR_ASSERT(pVertices); if(pVertices) { const bool flip = ((RenderState.DistortionCaps & ovrDistortionCap_FlipInput) != 0); const float left = -1.0f; // We currently draw this in normalized device coordinates with an stereo translation const float top = -1.1f; // applied as a vertex shader uniform. In the future when we have a more formal graphics const float right = 1.0f; // API abstraction we may move this draw to an overlay layer or to a more formal const float bottom = 0.9f; // model/mesh scheme with a perspective projection. pVertices[0] = HASWVertex(left, top, 0.f, Color(255, 255, 255, 255), 0.f, flip ? 1.f : 0.f); pVertices[1] = HASWVertex(left, bottom, 0.f, Color(255, 255, 255, 255), 0.f, flip ? 0.f : 1.f); pVertices[2] = HASWVertex(right, top, 0.f, Color(255, 255, 255, 255), 1.f, flip ? 1.f : 0.f); pVertices[3] = HASWVertex(right, bottom, 0.f, Color(255, 255, 255, 255), 1.f, flip ? 0.f : 1.f); pVB->Unmap(pVertices); } } // We don't generate the vertex arrays here if (!VAO && GLVersionInfo.SupportsVAO) { OVR_ASSERT(!VAOInitialized); #ifdef OVR_OS_MAC if(GLVersionInfo.WholeVersion >= 302) glGenVertexArrays(1, &VAO); else glGenVertexArraysAPPLE(1, &VAO); #else glGenVertexArrays(1, &VAO); #endif } }