ovr_sdk
diff LibOVR/Src/CAPI/GL/CAPI_GL_Util.cpp @ 0:1b39a1b46319
initial 0.4.4
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 14 Jan 2015 06:51:16 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/LibOVR/Src/CAPI/GL/CAPI_GL_Util.cpp Wed Jan 14 06:51:16 2015 +0200 1.3 @@ -0,0 +1,571 @@ 1.4 +/************************************************************************************ 1.5 + 1.6 +Filename : CAPI_GL_Util.cpp 1.7 +Content : RenderDevice implementation for OpenGL 1.8 +Created : September 10, 2012 1.9 +Authors : David Borel, Andrew Reisse 1.10 + 1.11 +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. 1.12 + 1.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 1.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 1.15 +which is provided at the time of installation or download, or which 1.16 +otherwise accompanies this software in either electronic or hard copy form. 1.17 + 1.18 +You may obtain a copy of the License at 1.19 + 1.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 1.21 + 1.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 1.23 +distributed under the License is distributed on an "AS IS" BASIS, 1.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.25 +See the License for the specific language governing permissions and 1.26 +limitations under the License. 1.27 + 1.28 +************************************************************************************/ 1.29 + 1.30 +#include "CAPI_GL_Util.h" 1.31 +#include "../../Kernel/OVR_Log.h" 1.32 +#include <string.h> 1.33 + 1.34 +#if defined(OVR_OS_LINUX) 1.35 + #include "../../Displays/OVR_Linux_SDKWindow.h" 1.36 +#endif 1.37 + 1.38 +#if defined(OVR_OS_MAC) 1.39 + #include <CoreGraphics/CGDirectDisplay.h> 1.40 + #include <OpenGL/OpenGL.h> 1.41 + 1.42 +typedef void *CGSConnectionID; 1.43 +typedef int32_t CGSWindowID; 1.44 +typedef int32_t CGSSurfaceID; 1.45 + 1.46 +extern "C" CGLError CGLGetSurface(CGLContextObj ctx, CGSConnectionID *cid, CGSWindowID *wid, CGSSurfaceID *sid); 1.47 +extern "C" CGLError CGLSetSurface(CGLContextObj ctx, CGSConnectionID cid, CGSWindowID wid, CGSSurfaceID sid); 1.48 +#endif 1.49 + 1.50 + 1.51 + 1.52 + 1.53 +namespace OVR { 1.54 + 1.55 + 1.56 +OVR::GLEContext gleContext; 1.57 + 1.58 + 1.59 +OVR::GLEContext* GetGLEContext() 1.60 +{ 1.61 + return &gleContext; 1.62 +} 1.63 + 1.64 + 1.65 +namespace CAPI { namespace GL { 1.66 + 1.67 + 1.68 +void InitGLExtensions() 1.69 +{ 1.70 + if(!gleContext.IsInitialized()) 1.71 + { 1.72 + gleContext.SetCurrentContext(&gleContext); 1.73 + gleContext.Init(); 1.74 + } 1.75 +} 1.76 + 1.77 + 1.78 +Buffer::Buffer(RenderParams* rp) : pParams(rp), Size(0), Use(0), GLBuffer(0) 1.79 +{ 1.80 +} 1.81 + 1.82 +Buffer::~Buffer() 1.83 +{ 1.84 + if (GLBuffer) 1.85 + glDeleteBuffers(1, &GLBuffer); 1.86 +} 1.87 + 1.88 +bool Buffer::Data(int use, const void* buffer, size_t size) 1.89 +{ 1.90 + Size = size; 1.91 + 1.92 + switch (use & Buffer_TypeMask) 1.93 + { 1.94 + case Buffer_Index: Use = GL_ELEMENT_ARRAY_BUFFER; break; 1.95 + default: Use = GL_ARRAY_BUFFER; break; 1.96 + } 1.97 + 1.98 + if (!GLBuffer) 1.99 + glGenBuffers(1, &GLBuffer); 1.100 + 1.101 + int mode = GL_DYNAMIC_DRAW; 1.102 + if (use & Buffer_ReadOnly) 1.103 + mode = GL_STATIC_DRAW; 1.104 + 1.105 + glBindBuffer(Use, GLBuffer); 1.106 + glBufferData(Use, size, buffer, mode); 1.107 + return 1; 1.108 +} 1.109 + 1.110 +void* Buffer::Map(size_t, size_t, int) 1.111 +{ 1.112 + int mode = GL_WRITE_ONLY; 1.113 + //if (flags & Map_Unsynchronized) 1.114 + // mode |= GL_MAP_UNSYNCHRONIZED; 1.115 + 1.116 + glBindBuffer(Use, GLBuffer); 1.117 + void* v = glMapBuffer(Use, mode); 1.118 + return v; 1.119 +} 1.120 + 1.121 +bool Buffer::Unmap(void*) 1.122 +{ 1.123 + glBindBuffer(Use, GLBuffer); 1.124 + int r = glUnmapBuffer(Use); 1.125 + return r != 0; 1.126 +} 1.127 + 1.128 +ShaderSet::ShaderSet() : 1.129 + //Shaders[], 1.130 + UniformInfo(), 1.131 + //Prog(0) 1.132 + ProjLoc(0), 1.133 + ViewLoc(0), 1.134 + //TexLoc[], 1.135 + UsesLighting(false), 1.136 + LightingVer(0) 1.137 +{ 1.138 + memset(TexLoc, 0, sizeof(TexLoc)); 1.139 + Prog = glCreateProgram(); 1.140 +} 1.141 +ShaderSet::~ShaderSet() 1.142 +{ 1.143 + glDeleteProgram(Prog); 1.144 +} 1.145 + 1.146 +GLint ShaderSet::GetGLShader(Shader* s) 1.147 +{ 1.148 + switch (s->Stage) 1.149 + { 1.150 + case Shader_Vertex: { 1.151 + ShaderImpl<Shader_Vertex, GL_VERTEX_SHADER>* gls = (ShaderImpl<Shader_Vertex, GL_VERTEX_SHADER>*)s; 1.152 + return gls->GLShader; 1.153 + } break; 1.154 + case Shader_Fragment: { 1.155 + ShaderImpl<Shader_Fragment, GL_FRAGMENT_SHADER>* gls = (ShaderImpl<Shader_Fragment, GL_FRAGMENT_SHADER>*)s; 1.156 + return gls->GLShader; 1.157 + } break; 1.158 + default: break; 1.159 + } 1.160 + 1.161 + return -1; 1.162 +} 1.163 + 1.164 +void ShaderSet::SetShader(Shader *s) 1.165 +{ 1.166 + Shaders[s->Stage] = s; 1.167 + GLint GLShader = GetGLShader(s); 1.168 + glAttachShader(Prog, GLShader); 1.169 + if (Shaders[Shader_Vertex] && Shaders[Shader_Fragment]) 1.170 + Link(); 1.171 +} 1.172 + 1.173 +void ShaderSet::UnsetShader(int stage) 1.174 +{ 1.175 + if (Shaders[stage] == NULL) 1.176 + return; 1.177 + 1.178 + GLint GLShader = GetGLShader(Shaders[stage]); 1.179 + glDetachShader(Prog, GLShader); 1.180 + 1.181 + Shaders[stage] = NULL; 1.182 +} 1.183 + 1.184 +bool ShaderSet::SetUniform(const char* name, int n, const float* v) 1.185 +{ 1.186 + for (unsigned int i = 0; i < UniformInfo.GetSize(); i++) 1.187 + if (!strcmp(UniformInfo[i].Name.ToCStr(), name)) 1.188 + { 1.189 + OVR_ASSERT(UniformInfo[i].Location >= 0); 1.190 + glUseProgram(Prog); 1.191 + switch (UniformInfo[i].Type) 1.192 + { 1.193 + case 1: glUniform1fv(UniformInfo[i].Location, n, v); break; 1.194 + case 2: glUniform2fv(UniformInfo[i].Location, n/2, v); break; 1.195 + case 3: glUniform3fv(UniformInfo[i].Location, n/3, v); break; 1.196 + case 4: glUniform4fv(UniformInfo[i].Location, n/4, v); break; 1.197 + case 12: glUniformMatrix3fv(UniformInfo[i].Location, 1, 1, v); break; 1.198 + case 16: glUniformMatrix4fv(UniformInfo[i].Location, 1, 1, v); break; 1.199 + default: OVR_ASSERT(0); 1.200 + } 1.201 + return 1; 1.202 + } 1.203 + 1.204 + OVR_DEBUG_LOG(("Warning: uniform %s not present in selected shader", name)); 1.205 + return 0; 1.206 +} 1.207 + 1.208 +bool ShaderSet::Link() 1.209 +{ 1.210 + glLinkProgram(Prog); 1.211 + GLint r; 1.212 + glGetProgramiv(Prog, GL_LINK_STATUS, &r); 1.213 + if (!r) 1.214 + { 1.215 + GLchar msg[1024]; 1.216 + glGetProgramInfoLog(Prog, sizeof(msg), 0, msg); 1.217 + OVR_DEBUG_LOG(("Linking shaders failed: %s\n", msg)); 1.218 + if (!r) 1.219 + return 0; 1.220 + } 1.221 + glUseProgram(Prog); 1.222 + 1.223 + UniformInfo.Clear(); 1.224 + LightingVer = 0; 1.225 + UsesLighting = 0; 1.226 + 1.227 + GLint uniformCount = 0; 1.228 + glGetProgramiv(Prog, GL_ACTIVE_UNIFORMS, &uniformCount); 1.229 + OVR_ASSERT(uniformCount >= 0); 1.230 + 1.231 + for(GLuint i = 0; i < (GLuint)uniformCount; i++) 1.232 + { 1.233 + GLsizei namelen; 1.234 + GLint size = 0; 1.235 + GLenum type; 1.236 + GLchar name[32]; 1.237 + glGetActiveUniform(Prog, i, sizeof(name), &namelen, &size, &type, name); 1.238 + 1.239 + if (size) 1.240 + { 1.241 + int l = glGetUniformLocation(Prog, name); 1.242 + char *np = name; 1.243 + while (*np) 1.244 + { 1.245 + if (*np == '[') 1.246 + *np = 0; 1.247 + np++; 1.248 + } 1.249 + Uniform u; 1.250 + u.Name = name; 1.251 + u.Location = l; 1.252 + u.Size = size; 1.253 + switch (type) 1.254 + { 1.255 + case GL_FLOAT: u.Type = 1; break; 1.256 + case GL_FLOAT_VEC2: u.Type = 2; break; 1.257 + case GL_FLOAT_VEC3: u.Type = 3; break; 1.258 + case GL_FLOAT_VEC4: u.Type = 4; break; 1.259 + case GL_FLOAT_MAT3: u.Type = 12; break; 1.260 + case GL_FLOAT_MAT4: u.Type = 16; break; 1.261 + default: 1.262 + continue; 1.263 + } 1.264 + UniformInfo.PushBack(u); 1.265 + if (!strcmp(name, "LightCount")) 1.266 + UsesLighting = 1; 1.267 + } 1.268 + else 1.269 + break; 1.270 + } 1.271 + 1.272 + ProjLoc = glGetUniformLocation(Prog, "Proj"); 1.273 + ViewLoc = glGetUniformLocation(Prog, "View"); 1.274 + for (int i = 0; i < 8; i++) 1.275 + { 1.276 + char texv[32]; 1.277 + OVR_sprintf(texv, 10, "Texture%d", i); 1.278 + TexLoc[i] = glGetUniformLocation(Prog, texv); 1.279 + if (TexLoc[i] < 0) 1.280 + break; 1.281 + 1.282 + glUniform1i(TexLoc[i], i); 1.283 + } 1.284 + if (UsesLighting) 1.285 + OVR_ASSERT(ProjLoc >= 0 && ViewLoc >= 0); 1.286 + return 1; 1.287 +} 1.288 + 1.289 +bool ShaderBase::SetUniform(const char* name, int n, const float* v) 1.290 +{ 1.291 + for(unsigned i = 0; i < UniformReflSize; i++) 1.292 + { 1.293 + if (!strcmp(UniformRefl[i].Name, name)) 1.294 + { 1.295 + memcpy(UniformData + UniformRefl[i].Offset, v, n * sizeof(float)); 1.296 + return 1; 1.297 + } 1.298 + } 1.299 + return 0; 1.300 +} 1.301 + 1.302 +bool ShaderBase::SetUniformBool(const char* name, int n, const bool* v) 1.303 +{ 1.304 + OVR_UNUSED(n); 1.305 + for(unsigned i = 0; i < UniformReflSize; i++) 1.306 + { 1.307 + if (!strcmp(UniformRefl[i].Name, name)) 1.308 + { 1.309 + memcpy(UniformData + UniformRefl[i].Offset, v, UniformRefl[i].Size); 1.310 + return 1; 1.311 + } 1.312 + } 1.313 + return 0; 1.314 +} 1.315 + 1.316 +void ShaderBase::InitUniforms(const Uniform* refl, size_t reflSize) 1.317 +{ 1.318 + if(!refl) 1.319 + { 1.320 + UniformRefl = NULL; 1.321 + UniformReflSize = 0; 1.322 + 1.323 + UniformsSize = 0; 1.324 + if (UniformData) 1.325 + { 1.326 + OVR_FREE(UniformData); 1.327 + UniformData = 0; 1.328 + } 1.329 + return; // no reflection data 1.330 + } 1.331 + 1.332 + UniformRefl = refl; 1.333 + UniformReflSize = reflSize; 1.334 + 1.335 + UniformsSize = UniformRefl[UniformReflSize-1].Offset + UniformRefl[UniformReflSize-1].Size; 1.336 + UniformData = (unsigned char*)OVR_ALLOC(UniformsSize); 1.337 +} 1.338 + 1.339 +Texture::Texture(RenderParams* rp, int w, int h) : IsUserAllocated(false), pParams(rp), TexId(0), Width(w), Height(h) 1.340 +{ 1.341 + if (w && h) 1.342 + glGenTextures(1, &TexId); 1.343 +} 1.344 + 1.345 +Texture::~Texture() 1.346 +{ 1.347 + if (TexId && !IsUserAllocated) 1.348 + glDeleteTextures(1, &TexId); 1.349 +} 1.350 + 1.351 +void Texture::Set(int slot, ShaderStage) const 1.352 +{ 1.353 + glActiveTexture(GL_TEXTURE0 + slot); 1.354 + glBindTexture(GL_TEXTURE_2D, TexId); 1.355 +} 1.356 + 1.357 +void Texture::SetSampleMode(int sm) 1.358 +{ 1.359 + glBindTexture(GL_TEXTURE_2D, TexId); 1.360 + switch (sm & Sample_FilterMask) 1.361 + { 1.362 + case Sample_Linear: 1.363 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 1.364 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1.365 + if(GLE_EXT_texture_filter_anisotropic) 1.366 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1); 1.367 + break; 1.368 + 1.369 + case Sample_Anisotropic: 1.370 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 1.371 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1.372 + if(GLE_EXT_texture_filter_anisotropic) 1.373 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8); 1.374 + break; 1.375 + 1.376 + case Sample_Nearest: 1.377 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1.378 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1.379 + if(GLE_EXT_texture_filter_anisotropic) 1.380 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1); 1.381 + break; 1.382 + } 1.383 + 1.384 + switch (sm & Sample_AddressMask) 1.385 + { 1.386 + case Sample_Repeat: 1.387 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 1.388 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 1.389 + break; 1.390 + 1.391 + case Sample_Clamp: 1.392 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 1.393 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 1.394 + break; 1.395 + 1.396 + case Sample_ClampBorder: 1.397 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); 1.398 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); 1.399 + break; 1.400 + } 1.401 +} 1.402 + 1.403 +void Texture::UpdatePlaceholderTexture(GLuint texId, const Sizei& textureSize) 1.404 +{ 1.405 + if (!IsUserAllocated && TexId && texId != TexId) 1.406 + glDeleteTextures(1, &TexId); 1.407 + 1.408 + TexId = texId; 1.409 + Width = textureSize.w; 1.410 + Height = textureSize.h; 1.411 + 1.412 + IsUserAllocated = true; 1.413 +} 1.414 + 1.415 + 1.416 + 1.417 + 1.418 + 1.419 +Context::Context() : initialized(false), ownsContext(true), incarnation(0) 1.420 +{ 1.421 +#if defined(OVR_OS_MAC) 1.422 + systemContext = 0; 1.423 +#elif defined(OVR_OS_WIN32) 1.424 + hdc = 0; 1.425 + systemContext = 0; 1.426 +#elif defined(OVR_OS_LINUX) 1.427 + x11Display = NULL; 1.428 + x11Drawable = 0; 1.429 + systemContext = 0; 1.430 + memset(&x11Visual, 0, sizeof(x11Visual)); 1.431 +#endif 1.432 + 1.433 +} 1.434 + 1.435 +void Context::InitFromCurrent() 1.436 +{ 1.437 + Destroy(); 1.438 + 1.439 + initialized = true; 1.440 + ownsContext = false; 1.441 + incarnation++; 1.442 + 1.443 +#if defined(OVR_OS_MAC) 1.444 + systemContext = CGLGetCurrentContext(); 1.445 + { 1.446 + CGSConnectionID cid; 1.447 + CGSWindowID wid; 1.448 + CGSSurfaceID sid; 1.449 + CGLError e = kCGLNoError; 1.450 + e = CGLGetSurface(systemContext, &cid, &wid, &sid); 1.451 + OVR_ASSERT(e == kCGLNoError); OVR_UNUSED(e); 1.452 + } 1.453 + 1.454 +#elif defined(OVR_OS_WIN32) 1.455 + hdc = wglGetCurrentDC(); 1.456 + systemContext = wglGetCurrentContext(); 1.457 +#elif defined(OVR_OS_LINUX) 1.458 + x11Display = glXGetCurrentDisplay(); 1.459 + x11Drawable = glXGetCurrentDrawable(); 1.460 + systemContext = glXGetCurrentContext(); 1.461 + if (!SDKWindow::getVisualFromDrawable(x11Drawable, &x11Visual)) 1.462 + { 1.463 + OVR::LogError("[Context] Unable to obtain x11 visual from context"); 1.464 + memset(&x11Visual, 0, sizeof(x11Visual)); 1.465 + } 1.466 +#endif 1.467 +} 1.468 + 1.469 + 1.470 +void Context::CreateShared( Context & ctx ) 1.471 +{ 1.472 + Destroy(); 1.473 + OVR_ASSERT( ctx.initialized == true ); 1.474 + if( ctx.initialized == false ) 1.475 + { 1.476 + return; 1.477 + } 1.478 + 1.479 + initialized = true; 1.480 + ownsContext = true; 1.481 + incarnation++; 1.482 + 1.483 +#if defined(OVR_OS_MAC) 1.484 + CGLPixelFormatObj pixelFormat = CGLGetPixelFormat( ctx.systemContext ); 1.485 + CGLError e = CGLCreateContext( pixelFormat, ctx.systemContext, &systemContext ); 1.486 + OVR_ASSERT(e == kCGLNoError); OVR_UNUSED(e); 1.487 + SetSurface(ctx); 1.488 +#elif defined(OVR_OS_WIN32) 1.489 + hdc = ctx.hdc; 1.490 + systemContext = wglCreateContext( ctx.hdc ); 1.491 + BOOL success = wglShareLists(ctx.systemContext, systemContext ); 1.492 + OVR_ASSERT( success == TRUE ); 1.493 + OVR_UNUSED(success); 1.494 +#elif defined(OVR_OS_LINUX) 1.495 + x11Display = ctx.x11Display; 1.496 + x11Drawable = ctx.x11Drawable; 1.497 + x11Visual = ctx.x11Visual; 1.498 + systemContext = glXCreateContext( ctx.x11Display, &x11Visual, ctx.systemContext, True ); 1.499 + OVR_ASSERT( systemContext != NULL ); 1.500 +#endif 1.501 +} 1.502 + 1.503 +#if defined(OVR_OS_MAC) 1.504 +void Context::SetSurface( Context & ctx ) { 1.505 + CGLError e = kCGLNoError; 1.506 + CGSConnectionID cid, cid2; 1.507 + CGSWindowID wid, wid2; 1.508 + CGSSurfaceID sid, sid2; 1.509 + 1.510 + e = CGLGetSurface(ctx.systemContext, &cid, &wid, &sid); 1.511 + OVR_ASSERT(e == kCGLNoError); OVR_UNUSED(e); 1.512 + e = CGLGetSurface(systemContext, &cid2, &wid2, &sid2); 1.513 + OVR_ASSERT(e == kCGLNoError); OVR_UNUSED(e); 1.514 + if( sid && sid != sid2 ) { 1.515 + e = CGLSetSurface(systemContext, cid, wid, sid); 1.516 + OVR_ASSERT(e == kCGLNoError); OVR_UNUSED(e); 1.517 + } 1.518 +} 1.519 +#endif 1.520 + 1.521 +void Context::Destroy() 1.522 +{ 1.523 + if( initialized == false ) 1.524 + { 1.525 + return; 1.526 + } 1.527 + 1.528 + if (systemContext) 1.529 + { 1.530 +#if defined(OVR_OS_MAC) 1.531 + CGLDestroyContext( systemContext ); 1.532 +#elif defined(OVR_OS_WIN32) 1.533 + BOOL success = wglDeleteContext( systemContext ); 1.534 + OVR_ASSERT( success == TRUE ); 1.535 + OVR_UNUSED( success ); 1.536 +#elif defined(OVR_OS_LINUX) 1.537 + glXDestroyContext( x11Display, systemContext ); 1.538 +#endif 1.539 + 1.540 + systemContext = NULL; 1.541 + } 1.542 + 1.543 + initialized = false; 1.544 + ownsContext = true; 1.545 +} 1.546 + 1.547 +void Context::Bind() 1.548 +{ 1.549 + if(systemContext) 1.550 + { 1.551 +#if defined(OVR_OS_MAC) 1.552 + glFlush(); //Apple doesn't automatically flush within CGLSetCurrentContext, unlike other platforms. 1.553 + CGLSetCurrentContext( systemContext ); 1.554 +#elif defined(OVR_OS_WIN32) 1.555 + wglMakeCurrent( hdc, systemContext ); 1.556 +#elif defined(OVR_OS_LINUX) 1.557 + glXMakeCurrent( x11Display, x11Drawable, systemContext ); 1.558 +#endif 1.559 + } 1.560 +} 1.561 + 1.562 +void Context::Unbind() 1.563 +{ 1.564 +#if defined(OVR_OS_MAC) 1.565 + glFlush(); //Apple doesn't automatically flush within CGLSetCurrentContext, unlike other platforms. 1.566 + CGLSetCurrentContext( NULL ); 1.567 +#elif defined(OVR_OS_WIN32) 1.568 + wglMakeCurrent( hdc, NULL ); 1.569 +#elif defined(OVR_OS_LINUX) 1.570 + glXMakeCurrent( x11Display, None, NULL ); 1.571 +#endif 1.572 +} 1.573 + 1.574 +}}} // namespace OVR::CAPI::GL