diff options
Diffstat (limited to 'LibOVR/Src/CAPI/GL')
-rw-r--r-- | LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.cpp | 122 | ||||
-rw-r--r-- | LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.h | 5 | ||||
-rw-r--r-- | LibOVR/Src/CAPI/GL/CAPI_GL_DistortionShaders.h | 4 | ||||
-rw-r--r-- | LibOVR/Src/CAPI/GL/CAPI_GL_HSWDisplay.cpp | 219 | ||||
-rw-r--r-- | LibOVR/Src/CAPI/GL/CAPI_GL_HSWDisplay.h | 4 | ||||
-rw-r--r-- | LibOVR/Src/CAPI/GL/CAPI_GL_Util.cpp | 165 | ||||
-rw-r--r-- | LibOVR/Src/CAPI/GL/CAPI_GL_Util.h | 60 |
7 files changed, 368 insertions, 211 deletions
diff --git a/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.cpp b/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.cpp index bb52d98..2c903b6 100644 --- a/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.cpp +++ b/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.cpp @@ -98,6 +98,9 @@ DistortionRenderer::DistortionRenderer(ovrHmd hmd, FrameTimeManager& timeManager { DistortionMeshVAOs[0] = 0; DistortionMeshVAOs[1] = 0; + + // Initialize render params. + memset(&RParams, 0, sizeof(RParams)); } DistortionRenderer::~DistortionRenderer() @@ -155,7 +158,6 @@ bool DistortionRenderer::Initialize(const ovrRenderAPIConfig* apiConfig, RParams.Win = config->OGL.Win; if (!RParams.Win) { - int unused; RParams.Win = glXGetCurrentDrawable(); } if (!RParams.Win) @@ -270,9 +272,16 @@ void DistortionRenderer::EndFrame(bool swapBuffers) if (swapBuffers) { bool useVsync = ((RState.EnabledHmdCaps & ovrHmdCap_NoVSync) == 0); - int swapInterval = (useVsync) ? 1 : 0; + int swapInterval = (useVsync) ? 1 : 0; #if defined(OVR_OS_WIN32) - if (wglGetSwapIntervalEXT() != swapInterval) +#ifndef NO_SCREEN_TEAR_HEALING + if (TimeManager.ScreenTearingReaction()) + { + swapInterval = 0; + useVsync = false; + } +#endif // NO_SCREEN_TEAR_HEALING + if (wglGetSwapIntervalEXT() != swapInterval) wglSwapIntervalEXT(swapInterval); HDC dc = (RParams.DC != NULL) ? RParams.DC : GetDC(RParams.Window); @@ -297,7 +306,7 @@ void DistortionRenderer::EndFrame(bool swapBuffers) { GLuint currentSwapInterval = 0; glXQueryDrawable(RParams.Disp, RParams.Win, GLX_SWAP_INTERVAL_EXT, ¤tSwapInterval); - if (currentSwapInterval != swapInterval) + if (currentSwapInterval != (GLuint)swapInterval) glXSwapIntervalEXT(RParams.Disp, RParams.Win, swapInterval); } @@ -332,58 +341,17 @@ double DistortionRenderer::FlushGpuAndWaitTillTime(double absTime) return WaitTillTime(absTime); } - - + + DistortionRenderer::GraphicsState::GraphicsState() { - bool foundVersion = false; - const char* glVersionString = (const char*)glGetString(GL_VERSION); - if (glVersionString) - { - OVR_DEBUG_LOG(("GL_VERSION STRING: %s", (const char*)glVersionString)); - char prefix[64]; + GetGLVersionAndExtensions(GLVersionInfo); +} - for (int i = 10; i < 30; ++i) - { - int major = i / 10; - int minor = i % 10; - OVR_sprintf(prefix, 64, "%d.%d", major, minor); - if (strstr(glVersionString, prefix) == glVersionString) - { - GlMajorVersion = major; - GlMinorVersion = minor; - foundVersion = true; - break; - } - } - } - - if (!foundVersion) - { - glGetIntegerv(GL_MAJOR_VERSION, &GlMajorVersion); - glGetIntegerv(GL_MAJOR_VERSION, &GlMinorVersion); - } - OVR_ASSERT(GlMajorVersion >= 2); - - if (GlMajorVersion >= 3) - { - SupportsVao = true; - SupportsDrawBuffers = true; - } - else - { - const char* extensions = (const char*)glGetString(GL_EXTENSIONS); - SupportsVao = (strstr(extensions, "GL_ARB_vertex_array_object") != NULL - || strstr(extensions, "GL_APPLE_vertex_array_object") != NULL); - SupportsDrawBuffers = (strstr(extensions, "GL_EXT_draw_buffers2") != NULL); - } -} - - void DistortionRenderer::GraphicsState::ApplyBool(GLenum Name, GLint Value, GLint index) { - if (SupportsDrawBuffers && index != -1) + if (GLVersionInfo.SupportsDrawBuffers && index != -1) { if (Value != 0) glEnablei(Name, index); @@ -410,7 +378,7 @@ void DistortionRenderer::GraphicsState::Save() glGetIntegerv(GL_CURRENT_PROGRAM, &Program); glGetIntegerv(GL_ACTIVE_TEXTURE, &ActiveTexture); glGetIntegerv(GL_TEXTURE_BINDING_2D, &TextureBinding); - if (SupportsVao) + if (GLVersionInfo.SupportsVAO) { glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &VertexArrayBinding); } @@ -420,7 +388,7 @@ void DistortionRenderer::GraphicsState::Save() glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &ArrayBufferBinding); } glGetIntegerv(GL_FRAMEBUFFER_BINDING, &FrameBufferBinding); - if (SupportsDrawBuffers) + if (GLVersionInfo.SupportsDrawBuffers) { glGetIntegeri_v(GL_BLEND, 0, &Blend); glGetIntegeri_v(GL_COLOR_WRITEMASK, 0, ColorWritemask); @@ -432,8 +400,10 @@ void DistortionRenderer::GraphicsState::Save() } glGetIntegerv(GL_DITHER, &Dither); glGetIntegerv(GL_RASTERIZER_DISCARD, &RasterizerDiscard); - if ((GlMajorVersion == 3 && GlMinorVersion >= 2) || GlMajorVersion >= 4) + if ((GLVersionInfo.MajorVersion == 3 && GLVersionInfo.MinorVersion >= 2) || GLVersionInfo.MajorVersion >= 4) + { glGetIntegerv(GL_SAMPLE_MASK, &SampleMask); + } IsValid = true; } @@ -441,7 +411,7 @@ void DistortionRenderer::GraphicsState::Save() #ifdef OVR_OS_MAC bool DistortionRenderer::GraphicsState::isAtLeastOpenGL3() { - return !(GlMajorVersion < 3|| (GlMajorVersion == 3 && GlMinorVersion < 2)); + return (((GLVersionInfo.MajorVersion * 100) + GLVersionInfo.MinorVersion) >= 302); // OpenGL 3.2 or later } #endif @@ -461,7 +431,7 @@ void DistortionRenderer::GraphicsState::Restore() glUseProgram(Program); glActiveTexture(ActiveTexture); glBindTexture(GL_TEXTURE_2D, TextureBinding); - if (SupportsVao) + if (GLVersionInfo.SupportsVAO) { #ifdef OVR_OS_MAC if (isAtLeastOpenGL3()) @@ -485,15 +455,22 @@ void DistortionRenderer::GraphicsState::Restore() ApplyBool(GL_BLEND, Blend, 0); - if (SupportsDrawBuffers) + if (GLVersionInfo.SupportsDrawBuffers) + { glColorMaski(0, (GLboolean)ColorWritemask[0], (GLboolean)ColorWritemask[1], (GLboolean)ColorWritemask[2], (GLboolean)ColorWritemask[3]); + } else + { glColorMask((GLboolean)ColorWritemask[0], (GLboolean)ColorWritemask[1], (GLboolean)ColorWritemask[2], (GLboolean)ColorWritemask[3]); + } ApplyBool(GL_DITHER, Dither); ApplyBool(GL_RASTERIZER_DISCARD, RasterizerDiscard); - if ((GlMajorVersion == 3 && GlMinorVersion >= 2) || GlMajorVersion >= 4) + if ((GLVersionInfo.MajorVersion == 3 && GLVersionInfo.MinorVersion >= 2) || + GLVersionInfo.MajorVersion >= 4) + { ApplyBool(GL_SAMPLE_MASK, SampleMask); + } } @@ -525,9 +502,13 @@ void DistortionRenderer::initBuffersAndShaders() { pCurVBVert->ScreenPosNDC.x = pCurOvrVert->ScreenPosNDC.x; pCurVBVert->ScreenPosNDC.y = pCurOvrVert->ScreenPosNDC.y; - pCurVBVert->TanEyeAnglesR = (*(Vector2f*)&pCurOvrVert->TanEyeAnglesR); - pCurVBVert->TanEyeAnglesG = (*(Vector2f*)&pCurOvrVert->TanEyeAnglesG); - pCurVBVert->TanEyeAnglesB = (*(Vector2f*)&pCurOvrVert->TanEyeAnglesB); + + // Previous code here did this: pCurVBVert->TanEyeAnglesR = (*(Vector2f*)&pCurOvrVert->TanEyeAnglesR); However that's an usafe + // cast of unrelated types which can result in undefined behavior by a conforming compiler. A safe equivalent is simply memcpy. + static_assert(sizeof(OVR::Vector2f) == sizeof(ovrVector2f), "Mismatch of structs that are presumed binary equivalents."); + memcpy(&pCurVBVert->TanEyeAnglesR, &pCurOvrVert->TanEyeAnglesR, sizeof(pCurVBVert->TanEyeAnglesR)); + memcpy(&pCurVBVert->TanEyeAnglesG, &pCurOvrVert->TanEyeAnglesG, sizeof(pCurVBVert->TanEyeAnglesG)); + memcpy(&pCurVBVert->TanEyeAnglesB, &pCurOvrVert->TanEyeAnglesB, sizeof(pCurVBVert->TanEyeAnglesB)); // Convert [0.0f,1.0f] to [0,255] if (DistortionCaps & ovrDistortionCap_Vignette) @@ -569,7 +550,7 @@ void DistortionRenderer::renderDistortion(Texture* leftEyeTexture, Texture* righ glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); - if (glState->SupportsDrawBuffers) + if (glState->GLVersionInfo.SupportsDrawBuffers) { glDisablei(GL_BLEND, 0); glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); @@ -582,8 +563,10 @@ void DistortionRenderer::renderDistortion(Texture* leftEyeTexture, Texture* righ glDisable(GL_DITHER); glDisable(GL_RASTERIZER_DISCARD); - if ((glState->GlMajorVersion >= 3 && glState->GlMinorVersion >= 2) || glState->GlMajorVersion >= 4) + if ((glState->GLVersionInfo.MajorVersion >= 3 && glState->GLVersionInfo.MinorVersion >= 2) || glState->GLVersionInfo.MajorVersion >= 4) + { glDisable(GL_SAMPLE_MASK); + } glClearColor( RState.ClearColor[0], @@ -780,7 +763,7 @@ void DistortionRenderer::renderPrimitives( } else { - if (glState->SupportsVao) + if (glState->GLVersionInfo.SupportsVAO) { #ifdef OVR_OS_MAC if (glState->isAtLeastOpenGL3()) @@ -836,7 +819,7 @@ void DistortionRenderer::renderPrimitives( glDrawArrays(prim, 0, count); - if (!glState->SupportsVao) + if (!glState->GLVersionInfo.SupportsVAO) { for (int i = 0; i < attributeCount; ++i) glDisableVertexAttribArray(locs[i]); @@ -844,7 +827,7 @@ void DistortionRenderer::renderPrimitives( delete[] locs; - if (glState->SupportsVao) + if (glState->GLVersionInfo.SupportsVAO) { #ifdef OVR_OS_MAC if (glState->isAtLeastOpenGL3()) @@ -874,7 +857,8 @@ void DistortionRenderer::initShaders() GraphicsState* glState = (GraphicsState*)GfxState.GetPtr(); const char* shaderPrefix = - (glState->GlMajorVersion < 3 || (glState->GlMajorVersion == 3 && glState->GlMinorVersion < 2)) ? + (glState->GLVersionInfo.MajorVersion < 3 || + (glState->GLVersionInfo.MajorVersion == 3 && glState->GLVersionInfo.MinorVersion < 2)) ? glsl2Prefix : glsl3Prefix; { @@ -979,11 +963,13 @@ void DistortionRenderer::destroy() SaveGraphicsState(); GraphicsState* glState = (GraphicsState*)GfxState.GetPtr(); - + for(int eyeNum = 0; eyeNum < 2; eyeNum++) { - if (glState->SupportsVao) + if (glState->GLVersionInfo.SupportsVAO) + { glDeleteVertexArrays(1, &DistortionMeshVAOs[eyeNum]); + } DistortionMeshVAOs[eyeNum] = 0; diff --git a/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.h b/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.h index 9189ae6..1017c6e 100644 --- a/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.h +++ b/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.h @@ -77,10 +77,7 @@ protected: void ApplyBool(GLenum Name, GLint Value, GLint index = -1); public: - GLint GlMajorVersion; - GLint GlMinorVersion; - bool SupportsVao; - bool SupportsDrawBuffers; + GLVersionAndExtensions GLVersionInfo; GLint Viewport[4]; GLfloat ClearColor[4]; diff --git a/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionShaders.h b/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionShaders.h index 5c68c50..76e8c81 100644 --- a/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionShaders.h +++ b/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionShaders.h @@ -30,6 +30,7 @@ namespace OVR { namespace CAPI { namespace GL { "#define _VS_OUT varying\n" "#define _FS_IN varying\n" "#define _TEXTURELOD texture2DLod\n" + "#define _TEXTURE texture2D\n" "#define _FRAGCOLOR gl_FragColor\n"; static const char glsl3Prefix[] = @@ -39,6 +40,7 @@ namespace OVR { namespace CAPI { namespace GL { "#define _VS_OUT out\n" "#define _FS_IN in\n" "#define _TEXTURELOD textureLod\n" + "#define _TEXTURE texture\n" "#define _FRAGCOLOR FragColor\n"; static const char SimpleQuad_vs[] = @@ -127,7 +129,7 @@ namespace OVR { namespace CAPI { namespace GL { "void main()\n" "{\n" - " _FRAGCOLOR = oColor * texture2D(Texture0, oTexCoord);\n" + " _FRAGCOLOR = oColor * _TEXTURE(Texture0, oTexCoord);\n" "}\n"; // The following is copied from the generated D3D SimpleTexturedQuad_ps_refl.h file, with D3D_NS renamed to GL. diff --git a/LibOVR/Src/CAPI/GL/CAPI_GL_HSWDisplay.cpp b/LibOVR/Src/CAPI/GL/CAPI_GL_HSWDisplay.cpp index 6c0106d..f024ac5 100644 --- a/LibOVR/Src/CAPI/GL/CAPI_GL_HSWDisplay.cpp +++ b/LibOVR/Src/CAPI/GL/CAPI_GL_HSWDisplay.cpp @@ -232,9 +232,6 @@ Texture* LoadTextureTga(RenderParams& rParams, int samplerMode, const uint8_t* p HSWDisplay::HSWDisplay(ovrRenderAPIType api, ovrHmd hmd, const HMDRenderState& renderState) : OVR::CAPI::HSWDisplay(api, hmd, renderState) , RenderParams() - , GLMajorVersion(0) - , GLMinorVersion(0) - , SupportsVao(false) , FrameBuffer(0) , pTexture() , pShaderSet() @@ -276,10 +273,8 @@ bool HSWDisplay::Initialize(const ovrRenderAPIConfig* apiConfig) if (config->OGL.Win) RenderParams.Win= config->OGL.Win; if (!RenderParams.Win) - { - int unused; RenderParams.Win = glXGetCurrentDrawable(); - } + if (!RenderParams.Win) { OVR_DEBUG_LOG(("XGetInputFocus failed.")); @@ -332,17 +327,14 @@ void HSWDisplay::UnloadGraphics() if(VAO) { #ifdef OVR_OS_MAC - if(GLMajorVersion >= 3) - { - glDeleteVertexArrays(1, &VAO); - } - else - { - glDeleteVertexArraysAPPLE(1, &VAO); - } - #else + if(GLVersionInfo.WholeVersion >= 302) + glDeleteVertexArrays(1, &VAO); + else + glDeleteVertexArraysAPPLE(1, &VAO); + #else glDeleteVertexArrays(1, &VAO); #endif + VAO = 0; VAOInitialized = false; } @@ -352,31 +344,10 @@ void HSWDisplay::UnloadGraphics() void HSWDisplay::LoadGraphics() { - const char* glVersionString = (const char*)glGetString(GL_VERSION); - - OVR_ASSERT(glVersionString); - if (glVersionString) - { - int fieldCount = sscanf(glVersionString, isdigit(*glVersionString) ? "%d.%d" : "%*[^0-9]%d.%d", &GLMajorVersion, &GLMinorVersion); // Skip all leading non-digits before reading %d. Example glVersionStrings: "1.5 ATI-1.4.18", "OpenGL ES-CM 3.2" - - if(fieldCount != 2) - { - static_assert(sizeof(GLMajorVersion) == sizeof(GLint), "type mis-match"); - glGetIntegerv(GL_MAJOR_VERSION, &GLMajorVersion); - } - } - - // SupportsVao - if(GLMajorVersion >= 3) - SupportsVao = true; - else - { - const char* extensions = (const char*)glGetString(GL_EXTENSIONS); - SupportsVao = (strstr(extensions, "GL_ARB_vertex_array_object") || strstr(extensions, "GL_APPLE_vertex_array_object")); - } - 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. { @@ -385,12 +356,14 @@ void HSWDisplay::LoadGraphics() pTexture = *LoadTextureTga(RenderParams, Sample_Linear | Sample_Clamp, TextureData, (int)textureSize, 255); } - if(!pShaderSet) + if (!pShaderSet) + { pShaderSet = *new ShaderSet(); + } if(!pVertexShader) { - OVR::String strShader((GLMajorVersion >= 3) ? glsl3Prefix : glsl2Prefix); + 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)); @@ -399,7 +372,7 @@ void HSWDisplay::LoadGraphics() if(!pFragmentShader) { - OVR::String strShader((GLMajorVersion >= 3) ? glsl3Prefix : glsl2Prefix); + 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)); @@ -432,18 +405,15 @@ void HSWDisplay::LoadGraphics() } // We don't generate the vertex arrays here - if(!VAO && SupportsVao) + if (!VAO && GLVersionInfo.SupportsVAO) { OVR_ASSERT(!VAOInitialized); + #ifdef OVR_OS_MAC - if(GLMajorVersion >= 3) - { - glGenVertexArrays(1, &VAO); - } - else - { - glGenVertexArraysAPPLE(1, &VAO); - } + if(GLVersionInfo.WholeVersion >= 302) + glGenVertexArrays(1, &VAO); + else + glGenVertexArraysAPPLE(1, &VAO); #else glGenVertexArrays(1, &VAO); #endif @@ -455,9 +425,13 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) { if(RenderEnabled && eyeTexture) { - // Hack - Clear previous errors. + // glGetError clears any previous error state. We call it here in order to start with + // a clean slate, as we are asserting below that our calls do not generate errors. glGetError(); + if(GLVersionInfo.MajorVersion == 0) // If not yet initialized... + GetGLVersionAndExtensions(GLVersionInfo); + // 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)); @@ -468,15 +442,19 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) // Save state // To do: Converge this with the state setting/restoring functionality present in the distortion renderer. + // Consider usage of the EXT_direct_state_access (http://www.opengl.org/registry/specs/EXT/direct_state_access.txt) extension. // Note that the glGet functions below will block until command buffer has completed. // glPushAttrib is deprecated, so we use glGet* to save/restore fixed-function settings. // https://www.opengl.org/sdk/docs/man/docbook4/xhtml/glGet.xml // - GLint RenderModeSaved; - glGetIntegerv(GL_RENDER_MODE, &RenderModeSaved); - OVR_ASSERT(glGetError() == 0); - OVR_ASSERT(RenderModeSaved == GL_RENDER); // Make sure it's not GL_SELECT or GL_FEEDBACK. - + GLint RenderModeSaved = 0; + if(!GLVersionInfo.IsCoreProfile) // glGetIntegerv can fail if an OpenGL 3.x+ core profile is enabled due to GL_RENDER_MODE being no longer supported. + { + glGetIntegerv(GL_RENDER_MODE, &RenderModeSaved); + OVR_ASSERT(glGetError() == 0); + OVR_ASSERT(RenderModeSaved == GL_RENDER); // Make sure it's not GL_SELECT or GL_FEEDBACK. + } + GLint FrameBufferBindingSaved; // OpenGL renamed GL_FRAMEBUFFER_BINDING to GL_DRAW_FRAMEBUFFER_BINDING and adds GL_READ_FRAMEBUFFER_BINDING. glGetIntegerv(GL_FRAMEBUFFER_BINDING, &FrameBufferBindingSaved); OVR_ASSERT(glGetError() == 0); @@ -494,8 +472,8 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) OVR_ASSERT(glGetError() == 0); GLdouble DepthRangeSaved[2]; - #if defined(OVR_OS_MAC) - // Using glDepthRange as a conditional will always evaluate to true on Mac. + #if defined(OVR_OS_MAC) || defined(OVR_OS_LINUX) + // Using glDepthRange as a conditional will always evaluate to true on Mac/Linux. glGetDoublev(GL_DEPTH_RANGE, DepthRangeSaved); #else GLfloat DepthRangefSaved[2]; @@ -547,7 +525,7 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) OVR_ASSERT(glGetError() == 0); GLint SampleMaskSaved = 0; - if(((GLMajorVersion * 100) + GLMinorVersion) >= 302) // OpenGL 3.2 or later + if (GLVersionInfo.WholeVersion >= 302) // OpenGL 3.2 or later { glGetIntegerv(GL_SAMPLE_MASK, &SampleMaskSaved); OVR_ASSERT(glGetError() == 0); @@ -572,37 +550,46 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) glGetIntegerv(GL_TEXTURE_BINDING_2D, &TextureBindingSaved); OVR_ASSERT(glGetError() == 0); - // https://www.opengl.org/sdk/docs/man/docbook4/xhtml/glVertexAttribPointer.xml + GLint VertexArrayBindingSaved = 0; + if (GLVersionInfo.SupportsVAO) + glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &VertexArrayBindingSaved); + + // If the core profile is enabled then we can't get the vertex attributes unless there is + // an active VAO. Otherwise there can be an error with some OpenGL implementations (notably Apple's). + // If the core profile is not enabled then pre-OpenGL 3.0 behavior is possible in which the + // application may not be using VAOs and thus there may be active vertex attributes. GLint VertexAttribEnabledSaved[kSavedVertexAttribCount]; GLint VertexAttribSizeSaved[kSavedVertexAttribCount]; GLint VertexAttribTypeSaved[kSavedVertexAttribCount]; GLint VertexAttribNormalizedSaved[kSavedVertexAttribCount]; GLint VertexAttribStrideSaved[kSavedVertexAttribCount]; GLvoid* VertexAttribPointerSaved[kSavedVertexAttribCount]; - for(GLuint i = 0; i < kSavedVertexAttribCount; i++) + + if(VertexArrayBindingSaved || !GLVersionInfo.IsCoreProfile) { - glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &VertexAttribEnabledSaved[i]); + for(GLuint i = 0; i < kSavedVertexAttribCount; i++) + { + // https://www.opengl.org/sdk/docs/man/docbook4/xhtml/glVertexAttribPointer.xml + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &VertexAttribEnabledSaved[i]); - glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_SIZE, &VertexAttribSizeSaved[i]); - glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_TYPE, &VertexAttribTypeSaved[i]); - glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &VertexAttribNormalizedSaved[i]); - glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &VertexAttribStrideSaved[i]); - glGetVertexAttribPointerv(i, GL_VERTEX_ATTRIB_ARRAY_POINTER, &VertexAttribPointerSaved[i]); + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_SIZE, &VertexAttribSizeSaved[i]); + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_TYPE, &VertexAttribTypeSaved[i]); + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &VertexAttribNormalizedSaved[i]); + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &VertexAttribStrideSaved[i]); + glGetVertexAttribPointerv(i, GL_VERTEX_ATTRIB_ARRAY_POINTER, &VertexAttribPointerSaved[i]); - OVR_ASSERT(glGetError() == 0); + OVR_ASSERT(glGetError() == 0); + } } - - GLint VertexArrayBindingSaved = 0; - if (SupportsVao) - glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &VertexArrayBindingSaved); - // // End of save state // Load the graphics if not loaded already. if (!pTexture) + { LoadGraphics(); + } // Calculate ortho projection. GetOrthoProjection(RenderState, OrthoProjection); @@ -628,10 +615,10 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) // Set fixed-function render states glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); OVR_ASSERT(glGetError() == 0); - #if defined(OVR_OS_MAC) // On Mac we are directly using OpenGL functions instead of function pointers. + #if defined(OVR_OS_MAC) || defined(OVR_OS_LINUX) // On Mac/Linux we are directly using OpenGL functions instead of function pointers. glDepthRange(0.0, 1.0); #else - if(glDepthRange) // If we can use the double version (glDepthRangef may not be available)... + if(glDepthRange) // If we can use the double version (glDepthRangef isn't available with older OpenGL, glDepthRange isn't available with OpenGL ES)... glDepthRange(0.0, 1.0); else glDepthRangef(0.f, 1.f); @@ -645,8 +632,10 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) glDisable(GL_DITHER); glDisable(GL_RASTERIZER_DISCARD); glDisable(GL_SCISSOR_TEST); - if(((GLMajorVersion * 100) + GLMinorVersion) >= 302) // OpenGL 3.2 or later + if (GLVersionInfo.WholeVersion >= 302) // OpenGL 3.2 or later + { glDisable(GL_SAMPLE_MASK); + } glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); OVR_ASSERT(glGetError() == 0); @@ -668,18 +657,15 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) // To do: We must add support for vertext array objects (VAOs) here. When using an OpenGL 3.2+ core profile, // the application is required to use vertex array objects and glVertexAttribPointer will fail otherwise. - if(SupportsVao) + if (GLVersionInfo.SupportsVAO) { OVR_ASSERT(VAO != 0); + #ifdef OVR_OS_MAC - if(GLMajorVersion >= 3) - { - glBindVertexArray(VAO); - } - else - { - glBindVertexArrayAPPLE(VAO); - } + if(GLVersionInfo.WholeVersion >= 302) + glBindVertexArray(VAO); + else + glBindVertexArrayAPPLE(VAO); #else glBindVertexArray(VAO); #endif @@ -718,19 +704,15 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); OVR_ASSERT(glGetError() == 0); - if(SupportsVao) + if (GLVersionInfo.SupportsVAO) { VAOInitialized = true; #ifdef OVR_OS_MAC - if(GLMajorVersion >= 3) - { - glBindVertexArray(0); - } - else - { + if(GLVersionInfo.WholeVersion >= 302) + glBindVertexArray(0); + else glBindVertexArrayAPPLE(0); - } #else glBindVertexArray(0); #endif @@ -740,31 +722,21 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) // We restore the state in the reverse order that we saved it. // To do: Make the code below avoid changes that are effectively no-ops. // - if (SupportsVao) + if (GLVersionInfo.SupportsVAO) { -#ifdef OVR_OS_MAC - if(GLMajorVersion >= 3) - { + #ifdef OVR_OS_MAC + if(GLVersionInfo.WholeVersion >= 302) + glBindVertexArray(VertexArrayBindingSaved); + else + glBindVertexArrayAPPLE(VertexArrayBindingSaved); + #else glBindVertexArray(VertexArrayBindingSaved); - } - else - { - glBindVertexArrayAPPLE(VertexArrayBindingSaved); - } -#else - glBindVertexArray(VertexArrayBindingSaved); -#endif + #endif } - for (GLuint i = 0; i < kSavedVertexAttribCount; i++) + if(VertexArrayBindingSaved || !GLVersionInfo.IsCoreProfile) // If the OpenGL version is older or in core profile compatibility mode, or if there's a VAO currently installed... { - // We have a problem here: if the GL context was initialized with a core profile version 3.x or later, calls to glVertexAttribPointer can fail when there is no Vertex Array Object - // in place. That case is possible here, and we don't have an easy means to detect that a core profile was specified and thus that the glVertexAttribPointer call below could fail. - // Our current solution is to call glVertexAttribPointer only if vertex array objects are not supported. We cannot simply decide based on whether the given vertex attrib was enabled - // or if there was a vertex array object installed. With our solution below a problem can occur when using OpenGL 3.x+ which supports VAOs, the user has vertex attrib pointers installed, - // the currently installed VAO is 0, and the user is somehow dependent on us returning to the user with those vertex attrib pointers reinstalled. - - if (!SupportsVao || (VertexArrayBindingSaved != 0)) // If the OpenGL version is older or in core profile compatibility mode, or if there's a VAO currently installed... + for (GLuint i = 0; i < kSavedVertexAttribCount; i++) { glVertexAttribPointer(i, VertexAttribSizeSaved[i], VertexAttribTypeSaved[i], (GLboolean)VertexAttribNormalizedSaved[i], VertexAttribStrideSaved[i], VertexAttribPointerSaved[i]); @@ -776,14 +748,14 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) OVR_ASSERT(glGetError() == 0); } } - + glBindTexture(GL_TEXTURE_2D, TextureBindingSaved); glActiveTexture(ActiveTextureSaved); glUseProgram(ProgramSaved); glBindBuffer(GL_ARRAY_BUFFER, ArrayBufferBindingSaved); glColorMask((GLboolean)ColorWriteMaskSaved[0], (GLboolean)ColorWriteMaskSaved[1], (GLboolean)ColorWriteMaskSaved[2], (GLboolean)ColorWriteMaskSaved[3]); - if(((GLMajorVersion * 100) + GLMinorVersion) >= 302) // OpenGL 3.2 or later + if (GLVersionInfo.WholeVersion >= 302) // OpenGL 3.2 or later { if(SampleMaskSaved) glEnable(GL_SAMPLE_MASK); @@ -806,7 +778,8 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) else glDisable(GL_DITHER); - glBlendFunc(BlendSrcRGBSaved, BlendDstRGBSaved); // What about BlendSrcAlphaSaved / BlendDstAlphaSaved? + // With OpenGL 4.0+, we may need to be aware of glBlendFuncSeparatei. + glBlendFuncSeparate(BlendSrcRGBSaved, BlendDstRGBSaved, BlendSrcAlphaSaved, BlendDstAlphaSaved); if(BlendSaved) glEnable(GL_BLEND); @@ -826,7 +799,7 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) glDisable(GL_DEPTH_TEST); glDepthMask(DepthWriteMaskSaved ? GL_TRUE : GL_FALSE); - #if defined(OVR_OS_MAC) // On Mac we are directly using OpenGL functions instead of function pointers. + #if defined(OVR_OS_MAC) || defined(OVR_OS_LINUX) // On Mac/Linux we are directly using OpenGL functions instead of function pointers. glDepthRange(DepthRangeSaved[0], DepthRangeSaved[1]); #else if(glDepthRange) // If we can use the double version (glDepthRangef may not be available)... @@ -839,7 +812,9 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) glViewport(ViewportSaved[0], ViewportSaved[1], ViewportSaved[2], ViewportSaved[3]); glBindTexture(GL_TEXTURE_2D, TextureBinding2DSaved); glBindFramebuffer(GL_FRAMEBUFFER, FrameBufferBindingSaved); - //glRenderMode(RenderModeSaved); + + if(!GLVersionInfo.IsCoreProfile) + glRenderMode(RenderModeSaved); OVR_ASSERT(glGetError() == 0); // @@ -848,12 +823,4 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) } - }}} // namespace OVR::CAPI::GL - - - - - - - diff --git a/LibOVR/Src/CAPI/GL/CAPI_GL_HSWDisplay.h b/LibOVR/Src/CAPI/GL/CAPI_GL_HSWDisplay.h index 3517157..4b110d5 100644 --- a/LibOVR/Src/CAPI/GL/CAPI_GL_HSWDisplay.h +++ b/LibOVR/Src/CAPI/GL/CAPI_GL_HSWDisplay.h @@ -55,9 +55,7 @@ namespace OVR { namespace CAPI { namespace GL { void LoadGraphics(); OVR::CAPI::GL::RenderParams RenderParams; - int GLMajorVersion; // Derived from glGetString(GL_VERSION). To consider: Move this into GL::RenderParams. - int GLMinorVersion; // - bool SupportsVao; // True if Vertex Array Objects are supported by the OpenGL version. + GLVersionAndExtensions GLVersionInfo; GLuint FrameBuffer; // This is a container for a texture, depth buffer, stencil buffer to be rendered to. To consider: Make a wrapper class, like the OculusWorldDemo RBuffer class. Ptr<OVR::CAPI::GL::Texture> pTexture; Ptr<OVR::CAPI::GL::ShaderSet> pShaderSet; diff --git a/LibOVR/Src/CAPI/GL/CAPI_GL_Util.cpp b/LibOVR/Src/CAPI/GL/CAPI_GL_Util.cpp index 22482d8..ed9e654 100644 --- a/LibOVR/Src/CAPI/GL/CAPI_GL_Util.cpp +++ b/LibOVR/Src/CAPI/GL/CAPI_GL_Util.cpp @@ -28,7 +28,6 @@ limitations under the License. namespace OVR { namespace CAPI { namespace GL { - // GL Hooks for non-Mac. #if !defined(OVR_OS_MAC) @@ -78,6 +77,7 @@ PFNGLENABLEIPROC glEnablei; PFNGLDISABLEIPROC glDisablei; PFNGLCOLORMASKIPROC glColorMaski; PFNGLGETINTEGERI_VPROC glGetIntegeri_v; +PFNGLGETSTRINGIPROC glGetStringi; PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers; PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers; PFNGLDELETESHADERPROC glDeleteShader; @@ -124,7 +124,7 @@ PFNGLUNIFORM1FVPROC glUniform1fv; PFNGLGENVERTEXARRAYSPROC glGenVertexArrays; PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays; PFNGLBINDVERTEXARRAYPROC glBindVertexArray; -PFNGLFEEDBACKBUFFERPROC glFeedbackBuffer; +PFNGLBLENDFUNCSEPARATEPROC glBlendFuncSeparate; #if defined(OVR_OS_WIN32) @@ -191,6 +191,7 @@ void InitGLExtensions() glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) GetFunction("glXSwapIntervalEXT"); #endif + glGetStringi = (PFNGLGETSTRINGIPROC) GetFunction("glGetStringi"); glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) GetFunction("glGenFramebuffersEXT"); glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) GetFunction("glDeleteFramebuffersEXT"); glEnablei = (PFNGLENABLEIPROC) GetFunction("glEnableIndexedEXT"); @@ -242,7 +243,7 @@ void InitGLExtensions() glDetachShader = (PFNGLDETACHSHADERPROC) GetFunction("glDetachShader"); glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC) GetFunction("glBindAttribLocation"); glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC) GetFunction("glGetAttribLocation"); - glFeedbackBuffer = (PFNGLFEEDBACKBUFFERPROC) GetFunction("glFeedbackBuffer"); + glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC) GetFunction("glBlendFuncSeparate"); } #endif @@ -499,7 +500,7 @@ void ShaderBase::InitUniforms(const Uniform* refl, size_t reflSize) UniformData = (unsigned char*)OVR_ALLOC(UniformsSize); } -Texture::Texture(RenderParams* rp, int w, int h) : IsUserAllocated(true), pParams(rp), TexId(0), Width(w), Height(h) +Texture::Texture(RenderParams* rp, int w, int h) : IsUserAllocated(false), pParams(rp), TexId(0), Width(w), Height(h) { if (w && h) glGenTextures(1, &TexId); @@ -573,6 +574,160 @@ void Texture::UpdatePlaceholderTexture(GLuint texId, const Sizei& textureSize) } -}}} +//// GLVersion + +void GLVersionAndExtensions::ParseGLVersion() +{ + const char* version = (const char*)glGetString(GL_VERSION); + int fields = 0, major = 0, minor = 0; + bool isGLES = false; + + OVR_ASSERT(version); + if (version) + { + OVR_DEBUG_LOG(("GL_VERSION: %s", (const char*)version)); + + // Skip all leading non-digits before reading %d. + // Example GL_VERSION strings: + // "1.5 ATI-1.4.18" + // "OpenGL ES-CM 3.2" + OVR_DISABLE_MSVC_WARNING(4996) // "scanf may be unsafe" + fields = sscanf(version, isdigit(*version) ? "%d.%d" : "%*[^0-9]%d.%d", &major, &minor); + isGLES = (strstr(version, "OpenGL ES") != NULL); + OVR_RESTORE_MSVC_WARNING() + } + else + { + LogText("Warning: GL_VERSION was NULL\n"); + } + + // If two fields were not found, + if (fields != 2) + { + static_assert(sizeof(major) == sizeof(GLint), "type mis-match"); + + glGetIntegerv(GL_MAJOR_VERSION, &major); + glGetIntegerv(GL_MINOR_VERSION, &minor); + } + + // Write version data + MajorVersion = major; + MinorVersion = minor; + WholeVersion = (major * 100) + minor; + IsGLES = isGLES; + IsCoreProfile = (MajorVersion >= 3); // Until we get a better way to detect core profiles, we err on the conservative side and set to true if the version is >= 3. +} + + +bool GLVersionAndExtensions::HasGLExtension(const char* searchKey) const +{ + if(Extensions && Extensions[0]) // If we have an extension string to search for individual extensions... + { + const int searchKeyLen = (int)strlen(searchKey); + const char* p = Extensions; + + for (;;) + { + p = strstr(p, searchKey); + + // If not found, + if (p == NULL) + { + break; + } + + // Only match full string + if ((p == Extensions || p[-1] == ' ') && + (p[searchKeyLen] == '\0' || p[searchKeyLen] == ' ')) + { + return true; + } + + // Skip ahead + p += searchKeyLen; + } + } + else + { + if(MajorVersion >= 3) // If glGetIntegerv(GL_NUM_EXTENSIONS, ...) is supported... + { + GLint extensionCount = 0; + glGetIntegerv(GL_NUM_EXTENSIONS, &extensionCount); + GLenum err = glGetError(); + + if(err == 0) + { + for(GLint i = 0; i != extensionCount; ++i) + { + const char* extension = (const char*)glGetStringi(GL_EXTENSIONS, (GLuint)i); + + if(extension) // glGetStringi returns NULL upon error. + { + if(strcmp(extension, searchKey) == 0) + return true; + } + else + break; + } + } + } + } + + return false; +} + +void GLVersionAndExtensions::ParseGLExtensions() +{ + if(MajorVersion >= 3) + { + // Set to empty because we need to use glGetStringi to read extensions on recent OpenGL. + Extensions = ""; + } + else + { + const char* extensions = (const char*)glGetString(GL_EXTENSIONS); + + OVR_ASSERT(extensions); + if (!extensions) + { + extensions = ""; // Note: glGetString() can return null + LogText("Warning: GL_EXTENSIONS was NULL\n"); + } + else + { + // Cannot print this to debug log: It's too long! + //OVR_DEBUG_LOG(("GL_EXTENSIONS: %s", (const char*)extensions)); + } + + Extensions = extensions; + } + + // To do: revise the code below to loop through calls to glGetStringi(GL_EXTENSIONS, ...) so that all extensions below + // can be searched with a single pass over the extensions instead of a full loop per HasGLExtensionCall. + + if (MajorVersion >= 3) + { + SupportsVAO = true; + } + else + { + SupportsVAO = + HasGLExtension("GL_ARB_vertex_array_object") || + HasGLExtension("GL_APPLE_vertex_array_object"); + } + + SupportsDrawBuffers = HasGLExtension("GL_EXT_draw_buffers2"); + + // Add more extension checks here... +} + +void GetGLVersionAndExtensions(GLVersionAndExtensions& versionInfo) +{ + versionInfo.ParseGLVersion(); + // GL Version must be parsed before parsing extensions: + versionInfo.ParseGLExtensions(); + // To consider: Call to glGetStringi(GL_SHADING_LANGUAGE_VERSION, ...) check/validate the GLSL support. +} +}}} // namespace OVR::CAPI::GL diff --git a/LibOVR/Src/CAPI/GL/CAPI_GL_Util.h b/LibOVR/Src/CAPI/GL/CAPI_GL_Util.h index bc7c8ab..aa6a26b 100644 --- a/LibOVR/Src/CAPI/GL/CAPI_GL_Util.h +++ b/LibOVR/Src/CAPI/GL/CAPI_GL_Util.h @@ -58,6 +58,7 @@ limitations under the License. namespace OVR { namespace CAPI { namespace GL { + // GL extension Hooks for Non-Mac. #if !defined(OVR_OS_MAC) @@ -69,7 +70,8 @@ typedef void (__stdcall *PFNGLENABLEPROC) (GLenum); typedef void (__stdcall *PFNGLDISABLEPROC) (GLenum); typedef void (__stdcall *PFNGLGETFLOATVPROC) (GLenum, GLfloat*); typedef const GLubyte * (__stdcall *PFNGLGETSTRINGPROC) (GLenum); -typedef void (__stdcall *PFNGLGETINTEGERVPROC) (GLenum, GLint*); +typedef const GLubyte * (__stdcall *PFNGLGETSTRINGIPROC) (GLenum, GLuint); +typedef void(__stdcall *PFNGLGETINTEGERVPROC) (GLenum, GLint*); typedef void (__stdcall *PFNGLGETDOUBLEVPROC) (GLenum, GLdouble*); typedef PROC (__stdcall *PFNWGLGETPROCADDRESS) (LPCSTR); typedef void (__stdcall *PFNGLFLUSHPROC) (); @@ -91,7 +93,6 @@ typedef void (__stdcall *PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, G typedef void (__stdcall *PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height); typedef void (__stdcall *PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor); typedef void (__stdcall *PFNGLFRONTFACEPROC) (GLenum mode); -typedef void (__stdcall *PFNGLFEEDBACKBUFFERPROC) (GLsizei size, GLenum type, GLfloat *buffer); typedef GLint (__stdcall *PFNGLRENDERMODEPROC) (GLenum mode); typedef void (__stdcall *PFNGLPOLYGONMODEPROC) (GLenum face, GLenum mode); @@ -138,6 +139,7 @@ extern PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT; #endif // defined(OVR_OS_WIN32) +extern PFNGLGETSTRINGIPROC glGetStringi; extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers; extern PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers; extern PFNGLDELETESHADERPROC glDeleteShader; @@ -183,7 +185,7 @@ extern PFNGLUNIFORM1FVPROC glUniform1fv; extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays; extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays; extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray; -extern PFNGLFEEDBACKBUFFERPROC glFeedbackBuffer; +extern PFNGLBLENDFUNCSEPARATEPROC glBlendFuncSeparate; extern void InitGLExtensions(); @@ -527,6 +529,7 @@ public: OVR_UNUSED(size); success = Compile((const char*) s); OVR_ASSERT(success); + OVR_UNUSED(success); InitUniforms(refl, reflSize); } ~ShaderImpl() @@ -571,7 +574,56 @@ typedef ShaderImpl<Shader_Vertex, GL_VERTEX_SHADER> VertexShader; typedef ShaderImpl<Shader_Fragment, GL_FRAGMENT_SHADER> FragmentShader; -}}} +//// GLVersionAndExtensions +// +// FIXME: CODE DUPLICATION WARNING +// Right now we have this same code in CommonSrc and in CAPI::GL. +// At some point we need to consolidate these, in Kernel or Util. +// Be sure to update both locations for now! +// +// This class needs to be initialized at runtime with GetGLVersionAndExtensions, +// after an OpenGL context has been created. It must be re-initialized any time +// a new OpenGL context is created, as the new context may differ in version or +// supported functionality. +struct GLVersionAndExtensions +{ + // Version information + int MajorVersion; // Best guess at major version + int MinorVersion; // Best guess at minor version + int WholeVersion; // Equals ((MajorVersion * 100) + MinorVersion). Example usage: if(glv.WholeVersion >= 302) // If OpenGL v3.02+ ... + bool IsGLES; // Open GL ES? + bool IsCoreProfile; // Is the current OpenGL context a core profile context? Its trueness may be a false positive but will never be a false negative. + + // Extension information + bool SupportsVAO; // Supports Vertex Array Objects? + bool SupportsDrawBuffers; // Supports Draw Buffers? + const char* Extensions; // Other extensions string (will not be null) + + GLVersionAndExtensions() + : MajorVersion(0), + MinorVersion(0), + WholeVersion(0), + IsGLES(false), + IsCoreProfile(false), + SupportsDrawBuffers(false), + SupportsVAO(false), + Extensions("") + { + } + + bool HasGLExtension(const char* searchKey) const; + +protected: + friend void GetGLVersionAndExtensions(GLVersionAndExtensions& versionInfo); + + void ParseGLVersion(); + void ParseGLExtensions(); +}; + +void GetGLVersionAndExtensions(GLVersionAndExtensions& versionInfo); + + +}}} // namespace OVR::CAPI::GL #endif // INC_OVR_CAPI_GL_Util_h |