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));
}
Example #2
0
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;
}
Example #3
0
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;
}
Example #6
0
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
    }
}