aboutsummaryrefslogtreecommitdiffstats
path: root/Samples/CommonSrc/Render/Render_GL_Device.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Samples/CommonSrc/Render/Render_GL_Device.cpp')
-rw-r--r--Samples/CommonSrc/Render/Render_GL_Device.cpp801
1 files changed, 646 insertions, 155 deletions
diff --git a/Samples/CommonSrc/Render/Render_GL_Device.cpp b/Samples/CommonSrc/Render/Render_GL_Device.cpp
index 54a2b9b..64da492 100644
--- a/Samples/CommonSrc/Render/Render_GL_Device.cpp
+++ b/Samples/CommonSrc/Render/Render_GL_Device.cpp
@@ -5,7 +5,7 @@ Content : RenderDevice implementation for OpenGL
Created : September 10, 2012
Authors : Andrew Reisse
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -54,6 +54,7 @@ void (*GetFunction(const char *functionName))( void )
#endif
+PFNGLGETSTRINGIPROC glGetStringi;
PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers;
PFNGLDELETESHADERPROC glDeleteShader;
@@ -95,6 +96,7 @@ PFNGLUNIFORM3FVPROC glUniform3fv;
PFNGLUNIFORM2FVPROC glUniform2fv;
PFNGLUNIFORM1FVPROC glUniform1fv;
PFNGLCOMPRESSEDTEXIMAGE2DPROC glCompressedTexImage2D;
+PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample;
PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage;
PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer;
PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers;
@@ -102,6 +104,7 @@ PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers;
PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
+PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebuffer;
void InitGLExtensions()
{
@@ -115,6 +118,7 @@ void InitGLExtensions()
glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) GetFunction("glXSwapIntervalEXT");
#endif
+ glGetStringi = (PFNGLGETSTRINGIPROC) GetFunction("glGetStringi");
glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) GetFunction("glGenFramebuffersEXT");
glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) GetFunction("glDeleteFramebuffersEXT");
glDeleteShader = (PFNGLDELETESHADERPROC) GetFunction("glDeleteShader");
@@ -156,6 +160,7 @@ void InitGLExtensions()
glUniform2fv = (PFNGLUNIFORM2FVPROC) GetFunction("glUniform2fv");
glUniform1fv = (PFNGLUNIFORM1FVPROC) GetFunction("glUniform1fv");
glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC) GetFunction("glCompressedTexImage2D");
+ glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC) GetFunction("glTexImage2DMultisample");
glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC) GetFunction("glRenderbufferStorageEXT");
glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) GetFunction("glBindRenderbufferEXT");
glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) GetFunction("glGenRenderbuffersEXT");
@@ -163,13 +168,14 @@ void InitGLExtensions()
glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) GetFunction("glGenVertexArrays");
glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC) GetFunction("glDeleteVertexArrays");
glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC) GetFunction("glBindVertexArray");
+ glBlitFramebuffer = (PFNGLBLITFRAMEBUFFEREXTPROC) GetFunction("glBlitFramebufferEXT");
}
#endif
static const char* StdVertexShaderSrc =
- "#version 110\n"
-
+"#version 110\n"
+
"uniform mat4 Proj;\n"
"uniform mat4 View;\n"
@@ -252,28 +258,28 @@ static const char* TextureFragShaderSrc =
" discard;\n"
"}\n";
-#define LIGHTING_COMMON \
+#define LIGHTING_COMMON \
"#version 110\n" \
- "uniform vec3 Ambient;\n" \
- "uniform vec4 LightPos[8];\n" \
- "uniform vec4 LightColor[8];\n" \
- "uniform float LightCount;\n" \
+ "uniform vec3 Ambient;\n" \
+ "uniform vec4 LightPos[8];\n" \
+ "uniform vec4 LightColor[8];\n" \
+ "uniform float LightCount;\n" \
"varying vec4 oColor;\n" \
"varying vec2 oTexCoord;\n" \
"varying vec3 oNormal;\n" \
"varying vec3 oVPos;\n" \
- "vec4 DoLight()\n" \
- "{\n" \
- " vec3 norm = normalize(oNormal);\n" \
- " vec3 light = Ambient;\n" \
- " for (int i = 0; i < int(LightCount); i++)\n" \
- " {\n" \
- " vec3 ltp = (LightPos[i].xyz - oVPos);\n" \
- " float ldist = length(ltp);\n" \
- " ltp = normalize(ltp);\n" \
+ "vec4 DoLight()\n" \
+ "{\n" \
+ " vec3 norm = normalize(oNormal);\n" \
+ " vec3 light = Ambient;\n" \
+ " for (int i = 0; i < int(LightCount); i++)\n" \
+ " {\n" \
+ " vec3 ltp = (LightPos[i].xyz - oVPos);\n" \
+ " float ldist = length(ltp);\n" \
+ " ltp = normalize(ltp);\n" \
" light += clamp(LightColor[i].rgb * oColor.rgb * (dot(norm, ltp) / ldist), 0.0,1.0);\n" \
- " }\n" \
- " return vec4(light, oColor.a);\n" \
+ " }\n" \
+ " return vec4(light, oColor.a);\n" \
"}\n"
static const char* LitSolidFragShaderSrc =
@@ -308,21 +314,21 @@ static const char* AlphaTextureFragShaderSrc =
"}\n";
static const char* AlphaBlendedTextureFragShaderSrc =
- "#version 110\n"
-
- "uniform sampler2D Texture0;\n"
+ "#version 110\n"
- "varying vec4 oColor;\n"
- "varying vec2 oTexCoord;\n"
+ "uniform sampler2D Texture0;\n"
- "void main()\n"
- "{\n"
+ "varying vec4 oColor;\n"
+ "varying vec2 oTexCoord;\n"
+
+ "void main()\n"
+ "{\n"
" vec4 finalColor = oColor;\n"
" finalColor *= texture2D(Texture0, oTexCoord);\n"
// Blend state expects premultiplied alpha
" finalColor.rgb *= finalColor.a;\n"
- " gl_FragColor = finalColor;\n"
- "}\n";
+ " gl_FragColor = finalColor;\n"
+ "}\n";
static const char* MultiTextureFragShaderSrc =
"#version 110\n"
@@ -336,15 +342,15 @@ static const char* MultiTextureFragShaderSrc =
"void main()\n"
"{\n"
- " vec4 color = texture2D(Texture0, oTexCoord);\n"
+ " vec4 color = texture2D(Texture0, oTexCoord);\n"
- " gl_FragColor = texture2D(Texture1, oTexCoord1);\n"
- " gl_FragColor.rgb = gl_FragColor.rgb * mix(1.9, 1.2, clamp(length(gl_FragColor.rgb),0.0,1.0));\n"
+ " gl_FragColor = texture2D(Texture1, oTexCoord1);\n"
+ " gl_FragColor.rgb = gl_FragColor.rgb * mix(1.9, 1.2, clamp(length(gl_FragColor.rgb),0.0,1.0));\n"
- " gl_FragColor = color * gl_FragColor;\n"
+ " gl_FragColor = color * gl_FragColor;\n"
- " if (gl_FragColor.a <= 0.6)\n"
- " discard;\n"
+ " if (gl_FragColor.a <= 0.6)\n"
+ " discard;\n"
"}\n";
static const char* PostProcessMeshFragShaderSrc =
@@ -455,12 +461,12 @@ static const char* PostProcessMeshTimewarpVertexShaderSrc =
// Accurate time warp lerp vs. faster
#if 0
// Apply the two 3x3 timewarp rotations to these vectors.
- " vec3 TransformedRStart = (EyeRotationStart * vec4(TanEyeAngleR, 0)).xyz;\n"
- " vec3 TransformedGStart = (EyeRotationStart * vec4(TanEyeAngleG, 0)).xyz;\n"
- " vec3 TransformedBStart = (EyeRotationStart * vec4(TanEyeAngleB, 0)).xyz;\n"
- " vec3 TransformedREnd = (EyeRotationEnd * vec4(TanEyeAngleR, 0)).xyz;\n"
- " vec3 TransformedGEnd = (EyeRotationEnd * vec4(TanEyeAngleG, 0)).xyz;\n"
- " vec3 TransformedBEnd = (EyeRotationEnd * vec4(TanEyeAngleB, 0)).xyz;\n"
+ " vec3 TransformedRStart = (EyeRotationStart * vec4(TanEyeAngleR, 0)).xyz;\n"
+ " vec3 TransformedGStart = (EyeRotationStart * vec4(TanEyeAngleG, 0)).xyz;\n"
+ " vec3 TransformedBStart = (EyeRotationStart * vec4(TanEyeAngleB, 0)).xyz;\n"
+ " vec3 TransformedREnd = (EyeRotationEnd * vec4(TanEyeAngleR, 0)).xyz;\n"
+ " vec3 TransformedGEnd = (EyeRotationEnd * vec4(TanEyeAngleG, 0)).xyz;\n"
+ " vec3 TransformedBEnd = (EyeRotationEnd * vec4(TanEyeAngleB, 0)).xyz;\n"
// And blend between them.
" vec3 TransformedR = mix ( TransformedRStart, TransformedREnd, Color.a );\n"
" vec3 TransformedG = mix ( TransformedGStart, TransformedGEnd, Color.a );\n"
@@ -526,7 +532,7 @@ PostProcessMeshTimewarpVertexShaderSrc;
"{\n"
" vec2 eyeToSourceTexCoord = inTexCoord * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
" eyeToSourceTexCoord.y = 1.0 - eyeToSourceTexCoord.y;\n"
- " float depth = texelFetch(Texture0, ivec2(eyeToSourceTexCoord * DepthDimSize), 0).x;\n" //FIXME: Use Texture2DLod for #version 110 support.
+ " float depth = texelFetch(Texture0, ivec2(eyeToSourceTexCoord * DepthDimSize), 0).x;\n" //FIXME: Use Texture2DLod for #version 110 support.
" float linearDepth = DepthProjector.y / (depth - DepthProjector.x);\n"
" vec4 retVal = vec4(inTexCoord, 1, 1);\n"
" retVal.xyz *= linearDepth;\n"
@@ -616,7 +622,7 @@ PostProcessMeshTimewarpVertexShaderSrc;
" lerpedEyeRot[1] = mix(EyeXformStart[1], EyeXformEnd[1], timewarpLerpFactor);\n"
" lerpedEyeRot[2] = mix(EyeXformStart[2], EyeXformEnd[2], timewarpLerpFactor);\n"
" lerpedEyeRot[3] = mix(EyeXformStart[3], EyeXformEnd[3], timewarpLerpFactor);\n"
- //" float4x4 lerpedEyeRot = EyeXformStart;\n"
+ //" float4x4 lerpedEyeRot = EyeXformStart;\n"
// warped positions are a bit more involved, hence a separate function
" gl_Position = TimewarpPos(Position.xy, oTexCoord0, lerpedEyeRot);\n"
@@ -641,8 +647,8 @@ static const char* PostProcessFragShaderWithChromAbSrc =
"varying vec4 oPosition;\n"
"varying vec2 oTexCoord;\n"
-
- "void main()\n"
+
+ "void main()\n"
"{\n"
// Input oTexCoord is [-1,1] across the half of the screen used for a single eye.
" vec2 TanEyeAngleDistorted = oTexCoord * TanEyeAngleScale + TanEyeAngleOffset;\n" // Scales to tan(thetaX),tan(thetaY), but still distorted (i.e. only the center is correct)
@@ -661,15 +667,15 @@ static const char* PostProcessFragShaderWithChromAbSrc =
// Scale them into ([0,0.5],[0,1]) or ([0.5,0],[0,1]) UV lookup space (depending on eye)
" vec2 SourceCoordR = TanEyeAngleR * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
- " SourceCoordR.y = 1.0 - SourceCoordR.y;\n"
+ " SourceCoordR.y = 1.0 - SourceCoordR.y;\n"
" vec2 SourceCoordG = TanEyeAngleG * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
- " SourceCoordG.y = 1.0 - SourceCoordG.y;\n"
+ " SourceCoordG.y = 1.0 - SourceCoordG.y;\n"
" vec2 SourceCoordB = TanEyeAngleB * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
- " SourceCoordB.y = 1.0 - SourceCoordB.y;\n"
+ " SourceCoordB.y = 1.0 - SourceCoordB.y;\n"
// Find the distance to the nearest edge.
" vec2 NDCCoord = TanEyeAngleG * EyeToSourceNDCScale + EyeToSourceNDCOffset;\n"
- " float EdgeFadeIn = clamp ( EdgeFadeScale, 0.0, 1e5 ) * ( 1.0 - max ( abs ( NDCCoord.x ), abs ( NDCCoord.y ) ) );\n"
+ " float EdgeFadeIn = clamp ( EdgeFadeScale, 0.0, 1e5 ) * ( 1.0 - max ( abs ( NDCCoord.x ), abs ( NDCCoord.y ) ) );\n"
" if ( EdgeFadeIn < 0.0 )\n"
" {\n"
" gl_FragColor = vec4(DistortionClearColor.r, DistortionClearColor.g, DistortionClearColor.b, 1.0);\n"
@@ -692,7 +698,7 @@ static const char* VShaderSrcs[VShader_Count] =
DirectVertexShaderSrc,
StdVertexShaderSrc,
PostProcessVertexShaderSrc,
- PostProcessMeshVertexShaderSrc,
+ PostProcessMeshVertexShaderSrc,
PostProcessMeshTimewarpVertexShaderSrc,
PostProcessMeshPositionalTimewarpVertexShaderSrc,
PostProcessHeightmapTimewarpVertexShaderSrc,
@@ -703,7 +709,7 @@ static const char* FShaderSrcs[FShader_Count] =
GouraudFragShaderSrc,
TextureFragShaderSrc,
AlphaTextureFragShaderSrc,
- AlphaBlendedTextureFragShaderSrc,
+ AlphaBlendedTextureFragShaderSrc,
PostProcessFragShaderWithChromAbSrc,
LitSolidFragShaderSrc,
LitTextureFragShaderSrc,
@@ -716,11 +722,25 @@ static const char* FShaderSrcs[FShader_Count] =
RenderDevice::RenderDevice(const RendererParams&)
+ : VertexShaders(),
+ FragShaders(),
+ DefaultFill(),
+ Proj(),
+ Vao(0),
+ CurRenderTarget(),
+ DepthBuffers(),
+ CurrentFbo(0),
+ MsaaFbo(0),
+ GLVersionInfo(),
+ DebugCallbackControl(),
+ Lighting(NULL)
{
+ DebugCallbackControl.Initialize();
+
GetGLVersionAndExtensions(GLVersionInfo);
OVR_ASSERT(GLVersionInfo.MajorVersion >= 2);
-
+
for (int i = 0; i < VShader_Count; i++)
{
OVR_ASSERT ( VShaderSrcs[i] != NULL ); // You forgot a shader!
@@ -732,13 +752,14 @@ RenderDevice::RenderDevice(const RendererParams&)
OVR_ASSERT ( FShaderSrcs[i] != NULL ); // You forgot a shader!
FragShaders[i] = *new Shader(this, Shader_Fragment, FShaderSrcs[i]);
}
-
+
Ptr<ShaderSet> gouraudShaders = *new ShaderSet();
gouraudShaders->SetShader(VertexShaders[VShader_MVP]);
gouraudShaders->SetShader(FragShaders[FShader_Gouraud]);
DefaultFill = *new ShaderFill(gouraudShaders);
glGenFramebuffers(1, &CurrentFbo);
+ glGenFramebuffers(1, &MsaaFbo);
if (GLVersionInfo.SupportsVAO)
{
@@ -758,7 +779,8 @@ void RenderDevice::Shutdown()
// This runs before the subclass's Shutdown(), where the context, etc, may be deleted.
- glDeleteFramebuffers(1, &CurrentFbo);
+ glDeleteFramebuffers(1, &CurrentFbo);
+ glDeleteFramebuffers(1, &MsaaFbo);
if (GLVersionInfo.SupportsVAO)
{
@@ -777,12 +799,14 @@ void RenderDevice::Shutdown()
DefaultFill.Clear();
DepthBuffers.Clear();
+
+ DebugCallbackControl.Shutdown();
}
void RenderDevice::FillTexturedRect(float left, float top, float right, float bottom, float ul, float vt, float ur, float vb, Color c, Ptr<OVR::Render::Texture> tex)
{
- Render::RenderDevice::FillTexturedRect(left, top, right, bottom, ul, vb, ur, vt, c, tex);
+ Render::RenderDevice::FillTexturedRect(left, top, right, bottom, ul, vt, ur, vb, c, tex);
}
@@ -829,12 +853,7 @@ void RenderDevice::SetDepthMode(bool enable, bool write, CompareFunc func)
void RenderDevice::SetViewport(const Recti& vp)
{
- int wh;
- if (CurRenderTarget)
- wh = CurRenderTarget->Height;
- else
- wh = WindowHeight;
- glViewport(vp.x, wh - vp.y - vp.h, vp.w, vp.h);
+ glViewport(vp.x, vp.y, vp.w, vp.h);
}
void RenderDevice::Flush()
@@ -844,14 +863,14 @@ void RenderDevice::Flush()
void RenderDevice::WaitUntilGpuIdle()
{
- glFlush();
- glFinish();
+ glFlush();
+ glFinish();
}
void RenderDevice::Clear(float r, float g, float b, float a, float depth, bool clearColor /*= true*/, bool clearDepth /*= true*/)
{
- glClearColor(r,g,b,a);
- glClearDepth(depth);
+ glClearColor(r,g,b,a);
+ glClearDepth(depth);
glClear(
( clearColor ? ( GL_COLOR_BUFFER_BIT ) : 0 ) |
( clearDepth ? ( GL_DEPTH_BUFFER_BIT ) : 0 )
@@ -869,6 +888,31 @@ Texture* RenderDevice::GetDepthBuffer(int w, int h, int ms)
return newDepth.GetPtr();
}
+void RenderDevice::ResolveMsaa(OVR::Render::Texture* msaaTex, OVR::Render::Texture* outputTex)
+{
+ bool isMsaaTarget = msaaTex->GetSamples() > 1;
+ glBindFramebuffer( GL_READ_FRAMEBUFFER, MsaaFbo );
+ glFramebufferTexture2D( GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ isMsaaTarget ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D,
+ ((Texture*)msaaTex)->TexId, 0);
+ glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
+ OVR_ASSERT(glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
+
+ glBindFramebuffer( GL_DRAW_FRAMEBUFFER, CurrentFbo );
+ glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ((Texture*)outputTex)->TexId, 0);
+ glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
+
+ OVR_ASSERT(glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
+
+ //glReadBuffer(GL_TEXTURE_2D_MULTISAMPLE);
+ //glDrawBuffer(GL_COLOR_ATTACHMENT0);
+ glBlitFramebuffer( 0, 0, msaaTex->GetWidth(), msaaTex->GetHeight(),
+ 0, 0, outputTex->GetWidth(), outputTex->GetHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST );
+ glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+ GLint err = glGetError();
+ OVR_ASSERT(!err); OVR_UNUSED(err);
+}
+
void RenderDevice::SetRenderTarget(Render::Texture* color, Render::Texture* depth, Render::Texture* stencil)
{
OVR_UNUSED(stencil);
@@ -879,14 +923,19 @@ void RenderDevice::SetRenderTarget(Render::Texture* color, Render::Texture* dept
glBindFramebuffer(GL_FRAMEBUFFER, 0);
return;
}
-
- if (depth == NULL)
- depth = GetDepthBuffer(color->GetWidth(), color->GetHeight(), CurRenderTarget->GetSamples());
+
+ int sampleCount = CurRenderTarget->GetSamples();
+
+ if (depth == NULL)
+ depth = GetDepthBuffer(color->GetWidth(), color->GetHeight(), sampleCount);
glBindFramebuffer(GL_FRAMEBUFFER, CurrentFbo);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ((Texture*)color)->TexId, 0);
+
+ GLenum texTarget = (sampleCount > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
+
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texTarget, ((Texture*)color)->TexId, 0);
if (depth)
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, ((Texture*)depth)->TexId, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, texTarget, ((Texture*)depth)->TexId, 0);
else
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
@@ -904,7 +953,7 @@ void RenderDevice::SetWorldUniforms(const Matrix4f& proj)
void RenderDevice::SetTexture(Render::ShaderStage, int slot, const Texture* t)
{
glActiveTexture(GL_TEXTURE0 + slot);
- glBindTexture(GL_TEXTURE_2D, ((Texture*)t)->TexId);
+ glBindTexture((t->GetSamples() > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D, ((Texture*)t)->TexId);
}
Buffer* RenderDevice::CreateBuffer()
@@ -979,11 +1028,11 @@ void RenderDevice::Render(const Fill* fill, Render::Buffer* vertices, Render::Bu
Lighting->Set(shaders);
}
- glBindBuffer(GL_ARRAY_BUFFER, ((Buffer*)vertices)->GLBuffer);
- for (int i = 0; i < 5; i++)
- glEnableVertexAttribArray(i);
+ glBindBuffer(GL_ARRAY_BUFFER, ((Buffer*)vertices)->GLBuffer);
+ for (int i = 0; i < 5; i++)
+ glEnableVertexAttribArray(i);
- switch (meshType)
+ switch (meshType)
{
case Mesh_Distortion:
glVertexAttribPointer(0, 2, GL_FLOAT, false, sizeof(DistortionVertex), reinterpret_cast<char*>(offset) + offsetof(DistortionVertex, Pos));
@@ -1016,8 +1065,8 @@ void RenderDevice::Render(const Fill* fill, Render::Buffer* vertices, Render::Bu
glDrawArrays(prim, 0, count);
}
- for (int i = 0; i < 5; i++)
- glDisableVertexAttribArray(i);
+ for (int i = 0; i < 5; i++)
+ glDisableVertexAttribArray(i);
}
void RenderDevice::RenderWithAlpha(const Fill* fill, Render::Buffer* vertices, Render::Buffer* indices,
@@ -1104,8 +1153,16 @@ bool Shader::Compile(const char* src)
return 1;
}
-ShaderSet::ShaderSet()
+ShaderSet::ShaderSet() :
+ //Prog(0),
+ UniformInfo(),
+ ProjLoc(0),
+ ViewLoc(0),
+ //TexLoc[8];
+ UsesLighting(false),
+ LightingVer(0)
{
+ memset(TexLoc, 0, sizeof(TexLoc));
Prog = glCreateProgram();
}
ShaderSet::~ShaderSet()
@@ -1155,9 +1212,9 @@ bool ShaderSet::Link()
LightingVer = 0;
UsesLighting = 0;
- GLint uniformCount = 0;
- glGetProgramiv(Prog, GL_ACTIVE_UNIFORMS, &uniformCount);
- OVR_ASSERT(uniformCount >= 0);
+ GLint uniformCount = 0;
+ glGetProgramiv(Prog, GL_ACTIVE_UNIFORMS, &uniformCount);
+ OVR_ASSERT(uniformCount >= 0);
for(GLuint i = 0; i < (GLuint)uniformCount; i++)
{
@@ -1260,7 +1317,7 @@ bool ShaderSet::SetUniform4x4f(const char* name, const Matrix4f& m)
return 0;
}
-Texture::Texture(RenderDevice* r, int w, int h) : Ren(r), Width(w), Height(h)
+Texture::Texture(RenderDevice* r, int w, int h, int samples) : Ren(r), Width(w), Height(h), Samples(samples)
{
glGenTextures(1, &TexId);
}
@@ -1278,7 +1335,7 @@ void Texture::Set(int slot, Render::ShaderStage stage) const
void Texture::SetSampleMode(int sm)
{
- glBindTexture(GL_TEXTURE_2D, TexId);
+ glBindTexture((GetSamples() > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D, TexId);
switch (sm & Sample_FilterMask)
{
case Sample_Linear:
@@ -1294,7 +1351,7 @@ void Texture::SetSampleMode(int sm)
break;
case Sample_Nearest:
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
break;
@@ -1321,8 +1378,8 @@ void Texture::SetSampleMode(int sm)
ovrTexture Texture::Get_ovrTexture()
{
- ovrTexture tex;
- OVR::Sizei newRTSize(Width, Height);
+ ovrTexture tex;
+ OVR::Sizei newRTSize(Width, Height);
ovrGLTextureData* texData = (ovrGLTextureData*)&tex;
texData->Header.API = ovrRenderAPI_OpenGL;
@@ -1330,7 +1387,7 @@ ovrTexture Texture::Get_ovrTexture()
texData->Header.RenderViewport = Recti(newRTSize);
texData->TexId = TexId;
- return tex;
+ return tex;
}
Texture* RenderDevice::CreateTexture(int format, int width, int height, const void* data, int mipcount)
@@ -1340,23 +1397,34 @@ Texture* RenderDevice::CreateTexture(int format, int width, int height, const vo
{
case Texture_RGBA: glformat = GL_RGBA; break;
case Texture_R: glformat = GL_RED; break;
- case Texture_Depth: glformat = GL_DEPTH_COMPONENT; gltype = GL_FLOAT; break;
+ case Texture_Depth: glformat = GL_DEPTH_COMPONENT; gltype = GL_FLOAT; break;
case Texture_DXT1: glformat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break;
case Texture_DXT3: glformat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break;
case Texture_DXT5: glformat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break;
default:
return NULL;
}
- Texture* NewTex = new Texture(this, width, height);
- glBindTexture(GL_TEXTURE_2D, NewTex->TexId);
- GLint err = glGetError();
+ int samples = format & Texture_SamplesMask;
+ if(samples < 1 ||
+ GLVersionInfo.WholeVersion < 302) // disallow MSAA for low GL context versions
+ {
+ samples = 1;
+ }
+
+ GLenum textureTarget = (samples > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
+
+ Texture* NewTex = new Texture(this, width, height, samples);
+ glBindTexture(textureTarget, NewTex->TexId);
+ GLint err = glGetError();
+ #if ! defined(OVR_OS_MAC)
OVR_ASSERT(!err);
+ #endif
- if( err )
- {
- printf("%d\n", err);
- }
+ if( err )
+ {
+ printf("RenderDevice::CreateTexture glGetError result: %d\n", err);
+ }
if (format & Texture_Compressed)
{
@@ -1374,14 +1442,17 @@ Texture* RenderDevice::CreateTexture(int format, int width, int height, const vo
if (h < 1) h = 1;
}
}
- else
- {
- bool isSRGB = ((format & Texture_TypeMask) == Texture_RGBA && (format & Texture_SRGB) != 0);
- bool isDepth = ((format & Texture_Depth) != 0);
- GLenum internalFormat = (isSRGB) ? GL_SRGB_ALPHA : (isDepth) ? GL_DEPTH_COMPONENT32F : glformat;
+ else
+ {
+ bool isSRGB = ((format & Texture_TypeMask) == Texture_RGBA && (format & Texture_SRGB) != 0);
+ bool isDepth = ((format & Texture_Depth) != 0);
+ GLenum internalFormat = (isSRGB) ? GL_SRGB8_ALPHA8 : (isDepth) ? GL_DEPTH_COMPONENT32F : glformat;
- glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, glformat, gltype, data);
- }
+ if (samples > 1)
+ glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, internalFormat, width, height, false);
+ else
+ glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, glformat, gltype, data);
+ }
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
@@ -1435,9 +1506,397 @@ RBuffer::~RBuffer()
}
-//// GLVersion
-static void ParseGLVersion(GLVersionAndExtensions& versionInfo)
+
+
+
+DebugCallback::DebugCallback()
+ : Initialized(false),
+ MinLogSeverity(SeverityHigh),
+ MinAssertSeverity(SeverityHigh),
+ glDebugMessageCallback(NULL),
+ glDebugMessageControl(NULL),
+ glDebugMessageCallbackARB(NULL),
+ glDebugMessageControlARB(NULL),
+ glDebugMessageCallbackAMD(NULL),
+ glDebugMessageControlAMD(NULL)
+{
+}
+
+
+DebugCallback::~DebugCallback()
+{
+ Shutdown();
+}
+
+
+bool DebugCallback::GetGLDebugCallback(PFNGLDEBUGMESSAGECALLBACKPROC* debugCallback, const void** userParam) const
+{
+ // Curiously, the KHR and ARB callbacks use the same glGetPointerv defines, which means you can only have
+ // one of them active concurrently. This also implies that an OpenGL implementation which implements both
+ // KHR and ARB implements the latter as simply a passthrough (or alias) of the former.
+ #if defined(GL_ARB_debug_output) || defined(GL_KHR_debug)
+ // glGetPointerv requires at least OpenGL 4.3 headers and implementation,
+ // but will be present in the headers if GL_ARB_debug_output or GL_KHR_debug are.
+ if(glDebugMessageCallback || glDebugMessageCallbackARB)
+ {
+ glGetPointerv(GL_DEBUG_CALLBACK_FUNCTION, reinterpret_cast<GLvoid**>(debugCallback));
+ glGetPointerv(GL_DEBUG_CALLBACK_USER_PARAM, const_cast<GLvoid**>(userParam));
+ return true;
+ }
+ #endif
+
+ // AMD_debug_output doesn't provide an option to get the debug callback.
+ debugCallback = NULL;
+ userParam = NULL;
+ return false;
+}
+
+
+void DebugCallback::DebugCallbackInternal(Severity s, const char* pSource, const char* pType, GLuint id, const char* pSeverity, const char* message)
+{
+ if(s >= MinLogSeverity)
+ {
+ OVR::LogError("{ERR-xxxx} [GL Error] %s %s %#x %s: %s", pSource, pType, id, pSeverity, message);
+ }
+
+ if(s >= MinAssertSeverity)
+ {
+ OVR_ASSERT(s < MinAssertSeverity); // Unilateral fail.
+ }
+}
+
+
+void DebugCallback::Initialize()
+{
+ if(!Initialized)
+ {
+ Initialized = true;
+
+ int err = glGetError();
+ OVR_UNUSED(err);
+
+ // Used to see if a callback was already registered.
+ PFNGLDEBUGMESSAGECALLBACKPROC debugCallbackPrev = NULL;
+ const void* userParamPrev = NULL;
+
+ // Try getting the KHR interface.
+ #if defined(OVR_OS_MAC) // With Mac OpenGL, functions aren't dynamically linked. They are only directly called.
+ //glDebugMessageCallback = ::glDebugMessageCallback; // We can enable this some day when Apple includes support
+ //glDebugMessageControl = ::glDebugMessageControl; // for glDebugMessageCallback in their headers and SDK.
+ #else
+ glDebugMessageCallback = (PFNGLDEBUGMESSAGECALLBACKPROC) GetFunction("glDebugMessageCallback");
+ glDebugMessageControl = (PFNGLDEBUGMESSAGECONTROLPROC) GetFunction("glDebugMessageControl");
+ #endif
+
+ if(glDebugMessageCallback)
+ {
+ GetGLDebugCallback(&debugCallbackPrev, &userParamPrev);
+
+ if(!debugCallbackPrev) // If a callback isn't already registered...
+ {
+ glDebugMessageCallback(GLDEBUGPROC(DebugMessageCallback), this);
+ err = glGetError();
+ if(err)
+ {
+ glDebugMessageCallback = NULL;
+ glDebugMessageControl = NULL;
+ OVR_DEBUG_LOG(("glDebugMessageCallback error: %x (%d)\n", err, err));
+ }
+
+ glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+ err = glGetError();
+ if(err)
+ {
+ OVR_DEBUG_LOG(("GL_DEBUG_OUTPUT_SYNCHRONOUS error: %x (%d)\n", err, err));
+ }
+
+ // To consider: disable marker/push/pop
+ // glDebugMessageControl(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, GL_DONT_CARE, 0, NULL, GL_FALSE);
+ // glDebugMessageControl(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP, GL_DONT_CARE, 0, NULL, GL_FALSE);
+ // glDebugMessageControl(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP, GL_DONT_CARE, 0, NULL, GL_FALSE);
+ }
+ }
+
+ if(!glDebugMessageCallback) // If KHR_debug wasn't found, try ARB_debug_output.
+ {
+ #if !defined(OVR_OS_MAC)
+ glDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARBPROC) GetFunction("glDebugMessageCallbackARB");
+ glDebugMessageControlARB = (PFNGLDEBUGMESSAGECONTROLARBPROC) GetFunction("glDebugMessageControlARB");
+ #endif
+
+ if(glDebugMessageCallbackARB)
+ {
+ GetGLDebugCallback(&debugCallbackPrev, &userParamPrev);
+
+ if(!debugCallbackPrev) // If a callback isn't already registered...
+ {
+ glDebugMessageCallbackARB(GLDEBUGPROCARB(DebugMessageCallback), this);
+ err = glGetError();
+ if(err)
+ {
+ glDebugMessageCallbackARB = NULL;
+ glDebugMessageControlARB = NULL;
+ OVR_DEBUG_LOG(("glDebugMessageCallbackARB error: %x (%d)\n", err, err));
+ }
+
+ glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+ err = glGetError();
+ if(err)
+ {
+ OVR_DEBUG_LOG(("GL_DEBUG_OUTPUT_SYNCHRONOUS error: %x (%d)\n", err, err));
+ }
+
+ // To consider: disable marker/push/pop
+ // glDebugMessageControlARB(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, GL_DONT_CARE, 0, NULL, GL_FALSE);
+ // glDebugMessageControlARB(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP, GL_DONT_CARE, 0, NULL, GL_FALSE);
+ // glDebugMessageControlARB(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP, GL_DONT_CARE, 0, NULL, GL_FALSE);
+ }
+ }
+ }
+
+ if(!glDebugMessageCallback && !glDebugMessageCallbackARB)// If ARB_debug_output also wasn't found, try AMD_debug_output.
+ {
+ #if !defined(OVR_OS_MAC)
+ glDebugMessageCallbackAMD = (PFNGLDEBUGMESSAGECALLBACKAMDPROC) GetFunction("glDebugMessageCallbackAMD");
+ glDebugMessageControlAMD = (PFNGLDEBUGMESSAGEENABLEAMDPROC) GetFunction("glDebugMessageControlAMD");
+ #endif
+
+ if(glDebugMessageCallbackAMD)
+ {
+ if(!debugCallbackPrev) // If a callback isn't already registered...
+ {
+ glDebugMessageCallbackAMD(GLDEBUGPROCAMD(DebugMessageCallbackAMD), this);
+ err = glGetError();
+ if(err)
+ {
+ glDebugMessageCallbackAMD = NULL;
+ glDebugMessageControlAMD = NULL;
+ OVR_DEBUG_LOG(("glDebugMessageCallbackAMD error: %x (%d)\n", err, err));
+ }
+ // There is no control for synchronous/asynchronous with AMD_debug_output.
+ }
+ }
+ }
+ }
+}
+
+
+void DebugCallback::Shutdown()
+{
+ if(Initialized)
+ {
+ if(glDebugMessageCallbackAMD)
+ {
+ glDebugMessageCallbackAMD(NULL, NULL);
+ glDebugMessageCallbackAMD = NULL;
+ }
+
+ if(glDebugMessageCallbackARB)
+ {
+ glDebugMessageCallbackARB(NULL, NULL);
+ glDebugMessageCallbackARB = NULL;
+ }
+
+ if(glDebugMessageCallback)
+ {
+ glDebugMessageCallback(NULL, NULL);
+ glDebugMessageCallback = NULL;
+ }
+
+ Initialized = false;
+ }
+}
+
+
+void DebugCallback::SetMinSeverity(Severity minLogSeverity, Severity minAssertSeverity)
+{
+ MinLogSeverity = minLogSeverity;
+ MinAssertSeverity = minAssertSeverity;
+}
+
+
+DebugCallback::Implementation DebugCallback::GetImplementation() const
+{
+ if(glDebugMessageCallbackAMD)
+ return ImplementationAMD;
+
+ if(glDebugMessageCallbackARB)
+ return ImplementationARB;
+
+ if(glDebugMessageCallback)
+ return ImplementationKHR;
+
+ return ImplementationNone;
+}
+
+
+void DebugCallback::DebugMessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei /*length*/, const GLchar* message, GLvoid* userParam)
+{
+ const char* pSource = GetSource(source);
+ const char* pType = GetType(type);
+ const char* pSeverity = GetSeverity(severity);
+ Severity s;
+
+ switch(severity)
+ {
+ default:
+ case GL_DEBUG_SEVERITY_NOTIFICATION:
+ s = SeverityNotification;
+ break;
+ case GL_DEBUG_SEVERITY_LOW:
+ s = SeverityLow;
+ break;
+ case GL_DEBUG_SEVERITY_MEDIUM:
+ s = SeverityMedium;
+ break;
+ case GL_DEBUG_SEVERITY_HIGH:
+ s = SeverityHigh;
+ break;
+ }
+
+ DebugCallback* pThis = reinterpret_cast<DebugCallback*>(userParam);
+ pThis->DebugCallbackInternal(s, pSource, pType, id, pSeverity, message);
+}
+
+
+const char* DebugCallback::GetSource(GLenum Source)
+{
+ // There is one contiguous section of GL_DEBUG_SOURCE values.
+ static_assert((GL_DEBUG_SOURCE_OTHER - GL_DEBUG_SOURCE_API) == 5, "GL_DEBUG_SOURCE constants are not contiguous.");
+
+ static const char* GL_SourceStrings[] =
+ {
+ "API", // GL_DEBUG_SOURCE_API
+ "System", // GL_DEBUG_SOURCE_WINDOW_SYSTEM
+ "ShaderCompiler", // GL_DEBUG_SOURCE_SHADER_COMPILER
+ "ThirdParty", // GL_DEBUG_SOURCE_THIRD_PARTY
+ "Application", // GL_DEBUG_SOURCE_APPLICATION
+ "Other" // GL_DEBUG_SOURCE_OTHER
+ };
+
+ if ((Source >= GL_DEBUG_SOURCE_API) && (Source <= GL_DEBUG_SOURCE_OTHER))
+ return GL_SourceStrings[Source - GL_DEBUG_SOURCE_API];
+
+ return "Unknown";
+}
+
+
+
+const char* DebugCallback::GetType(GLenum Type)
+{
+ // There are two contiguous sections of GL_DEBUG_TYPE values.
+ static_assert((GL_DEBUG_TYPE_OTHER - GL_DEBUG_TYPE_ERROR) == 5, "GL_DEBUG_TYPE constants are not contiguous.");
+ static const char* TypeStrings[] =
+ {
+ "Error", // GL_DEBUG_TYPE_ERROR
+ "Deprecated", // GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR
+ "UndefinedBehavior", // GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR
+ "Portability", // GL_DEBUG_TYPE_PORTABILITY
+ "Performance", // GL_DEBUG_TYPE_PERFORMANCE
+ "Other" // GL_DEBUG_TYPE_OTHER
+ };
+
+ if ((Type >= GL_DEBUG_TYPE_ERROR) && (Type <= GL_DEBUG_TYPE_OTHER))
+ return TypeStrings[Type - GL_DEBUG_TYPE_ERROR];
+
+ // KHR_debug marker/push/pop functionality.
+ static_assert((GL_DEBUG_TYPE_POP_GROUP - GL_DEBUG_TYPE_MARKER) == 2, "GL_DEBUG_TYPE constants are not contiguous.");
+ static const char* TypeStrings2[] =
+ {
+ "Marker", // GL_DEBUG_TYPE_MARKER
+ "PushGroup", // GL_DEBUG_TYPE_PUSH_GROUP
+ "PopGroup", // GL_DEBUG_TYPE_POP_GROUP
+ };
+
+ if ((Type >= GL_DEBUG_TYPE_MARKER) && (Type <= GL_DEBUG_TYPE_POP_GROUP))
+ return TypeStrings2[Type - GL_DEBUG_TYPE_MARKER];
+
+ return "Unknown";
+}
+
+
+const char* DebugCallback::GetSeverity(GLenum Severity)
+{
+ // There are two sections of GL_DEBUG_SEVERITY.
+ static_assert((GL_DEBUG_SEVERITY_LOW - GL_DEBUG_SEVERITY_HIGH) == 2, "GL_DEBUG_SEVERITY constants are not contiguous.");
+ static const char* SeverityStrings[] =
+ {
+ "High",
+ "Medium",
+ "Low"
+ };
+
+ if ((Severity >= GL_DEBUG_SEVERITY_HIGH) && (Severity <= GL_DEBUG_SEVERITY_LOW))
+ return SeverityStrings[Severity - GL_DEBUG_SEVERITY_HIGH];
+
+ // There is just one value in this second section.
+ if(Severity == GL_DEBUG_SEVERITY_NOTIFICATION)
+ return "Notification";
+
+ return "Unknown";
+}
+
+
+void DebugCallback::DebugMessageCallbackAMD(GLuint id, GLenum category, GLenum severity, GLsizei /*length*/, const GLchar *message, GLvoid *userParam)
+{
+ static_assert(GL_DEBUG_SEVERITY_LOW_AMD == GL_DEBUG_SEVERITY_LOW, "Severity mismatch"); // Verify that AMD_debug_output severity constants are identical to KHR_debug severity contstants.
+
+ const char* pSource = GetCategoryAMD(category);
+ const char* pSeverity = GetSeverity(severity);
+ Severity s;
+
+ switch(severity)
+ {
+ default:
+ case GL_DEBUG_SEVERITY_NOTIFICATION:
+ s = SeverityNotification;
+ break;
+ case GL_DEBUG_SEVERITY_LOW:
+ s = SeverityLow;
+ break;
+ case GL_DEBUG_SEVERITY_MEDIUM:
+ s = SeverityMedium;
+ break;
+ case GL_DEBUG_SEVERITY_HIGH:
+ s = SeverityHigh;
+ break;
+ }
+
+ DebugCallback* pThis = reinterpret_cast<DebugCallback*>(userParam);
+ pThis->DebugCallbackInternal(s, pSource, "Other", id, pSeverity, message);
+}
+
+
+const char* DebugCallback::GetCategoryAMD(GLenum Category)
+{
+ static_assert((GL_DEBUG_CATEGORY_OTHER_AMD - GL_DEBUG_CATEGORY_API_ERROR_AMD) == 7, "GL_DEBUG_CATEGORY constants are not contiguous.");
+ static const char* CategoryStrings[] =
+ {
+ "API", // GL_DEBUG_CATEGORY_API_ERROR_AMD
+ "System", // GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD
+ "Deprecation", // GL_DEBUG_CATEGORY_DEPRECATION_AMD
+ "UndefinedBehavior", // GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD
+ "Performance", // GL_DEBUG_CATEGORY_PERFORMANCE_AMD
+ "ShaderCompiler", // GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD
+ "Application", // GL_DEBUG_CATEGORY_APPLICATION_AMD
+ "Other" // GL_DEBUG_CATEGORY_OTHER_AMD
+ };
+
+ if((Category >= GL_DEBUG_CATEGORY_API_ERROR_AMD) && (Category <= GL_DEBUG_CATEGORY_OTHER_AMD))
+ return CategoryStrings[Category - GL_DEBUG_CATEGORY_API_ERROR_AMD];
+
+ return "Unknown";
+}
+
+
+
+
+
+
+
+
+void GLVersionAndExtensions::ParseGLVersion()
{
const char* version = (const char*)glGetString(GL_VERSION);
int fields = 0, major = 0, minor = 0;
@@ -1448,23 +1907,14 @@ static void ParseGLVersion(GLVersionAndExtensions& versionInfo)
{
OVR_DEBUG_LOG(("GL_VERSION: %s", (const char*)version));
-#ifdef OVR_CC_MSVC
- // Hack: This is using sscanf_s on MSVC to kill the security warning.
- // Normally the two functions are not interchangeable because the string format
- // is different for %s types, however we only use %d so it's fine.
-#define TEMP_OVR_SSCANF sscanf_s
-#else
-#define TEMP_OVR_SSCANF sscanf
-#endif
-
// Skip all leading non-digits before reading %d.
// Example GL_VERSION strings:
// "1.5 ATI-1.4.18"
// "OpenGL ES-CM 3.2"
- fields = TEMP_OVR_SSCANF(version, isdigit(*version) ? "%d.%d" : "%*[^0-9]%d.%d", &major, &minor);
+ 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);
-
-#undef TEMP_OVR_SSCANF
+ OVR_RESTORE_MSVC_WARNING()
}
else
{
@@ -1481,81 +1931,122 @@ static void ParseGLVersion(GLVersionAndExtensions& versionInfo)
}
// Write version data
- versionInfo.MajorVersion = major;
- versionInfo.MinorVersion = minor;
- versionInfo.IsGLES = isGLES;
+ 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.
}
-static bool HasGLExtension(const char* extensions, const char* searchKey)
-{
- const int searchKeyLen = (int)strlen(searchKey);
- const char* p = extensions;
- for (;;)
+bool GLVersionAndExtensions::HasGLExtension(const char* searchKey) const
+{
+ if (Extensions && Extensions[0]) // If we have an extension string to search for individual extensions...
{
- p = strstr(p, searchKey);
+ const int searchKeyLen = (int)strlen(searchKey);
+ const char* p = Extensions;
- // If not found,
- if (p == NULL)
+ for (;;)
{
- break;
- }
+ p = strstr(p, searchKey);
- // Only match full string
- if ((p == extensions || p[-1] == ' ') &&
- (p[searchKeyLen] == '\0' || p[searchKeyLen] == ' '))
- {
- return true;
+ // 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();
- // Skip ahead
- p += searchKeyLen;
+ 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;
}
-static void ParseGLExtensions(GLVersionAndExtensions& versionInfo)
+void GLVersionAndExtensions::ParseGLExtensions()
{
- const char* extensions = (const char*)glGetString(GL_EXTENSIONS);
-
- OVR_ASSERT(extensions);
- if (!extensions)
+ if (MajorVersion >= 3)
{
- extensions = ""; // Note: glGetString() can return null
- LogText("Warning: GL_EXTENSIONS was NULL\n");
+ // Set to empty because we need to use glGetStringi to read extensions on recent OpenGL.
+ Extensions = "";
}
else
{
- // Cannot print this to debug log: It's too long!
- //OVR_DEBUG_LOG(("GL_EXTENSIONS: %s", (const char*)extensions));
+ 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;
}
- versionInfo.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 (versionInfo.MajorVersion >= 3)
+ if (MajorVersion >= 3)
{
- versionInfo.SupportsVAO = true;
+ SupportsVAO = true;
}
else
{
- versionInfo.SupportsVAO =
- HasGLExtension(extensions, "GL_ARB_vertex_array_object") ||
- HasGLExtension(extensions, "GL_APPLE_vertex_array_object");
+ SupportsVAO =
+ HasGLExtension("GL_ARB_vertex_array_object") ||
+ HasGLExtension("GL_APPLE_vertex_array_object");
}
- versionInfo.SupportsDrawBuffers = HasGLExtension(extensions, "GL_EXT_draw_buffers2");
+ SupportsDrawBuffers = HasGLExtension("GL_EXT_draw_buffers2");
// Add more extension checks here...
}
void GetGLVersionAndExtensions(GLVersionAndExtensions& versionInfo)
{
- ParseGLVersion(versionInfo);
-
+ versionInfo.ParseGLVersion();
// GL Version must be parsed before parsing extensions:
-
- ParseGLExtensions(versionInfo);
+ versionInfo.ParseGLExtensions();
+ // To consider: Call to glGetStringi(GL_SHADING_LANGUAGE_VERSION, ...) check/validate the GLSL support.
}