ovr_sdk

view 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 source
1 /************************************************************************************
3 Filename : CAPI_GL_Util.cpp
4 Content : RenderDevice implementation for OpenGL
5 Created : September 10, 2012
6 Authors : David Borel, Andrew Reisse
8 Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
10 Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
11 you may not use the Oculus VR Rift SDK except in compliance with the License,
12 which is provided at the time of installation or download, or which
13 otherwise accompanies this software in either electronic or hard copy form.
15 You may obtain a copy of the License at
17 http://www.oculusvr.com/licenses/LICENSE-3.2
19 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
20 distributed under the License is distributed on an "AS IS" BASIS,
21 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 See the License for the specific language governing permissions and
23 limitations under the License.
25 ************************************************************************************/
27 #include "CAPI_GL_Util.h"
28 #include "../../Kernel/OVR_Log.h"
29 #include <string.h>
31 #if defined(OVR_OS_LINUX)
32 #include "../../Displays/OVR_Linux_SDKWindow.h"
33 #endif
35 #if defined(OVR_OS_MAC)
36 #include <CoreGraphics/CGDirectDisplay.h>
37 #include <OpenGL/OpenGL.h>
39 typedef void *CGSConnectionID;
40 typedef int32_t CGSWindowID;
41 typedef int32_t CGSSurfaceID;
43 extern "C" CGLError CGLGetSurface(CGLContextObj ctx, CGSConnectionID *cid, CGSWindowID *wid, CGSSurfaceID *sid);
44 extern "C" CGLError CGLSetSurface(CGLContextObj ctx, CGSConnectionID cid, CGSWindowID wid, CGSSurfaceID sid);
45 #endif
50 namespace OVR {
53 OVR::GLEContext gleContext;
56 OVR::GLEContext* GetGLEContext()
57 {
58 return &gleContext;
59 }
62 namespace CAPI { namespace GL {
65 void InitGLExtensions()
66 {
67 if(!gleContext.IsInitialized())
68 {
69 gleContext.SetCurrentContext(&gleContext);
70 gleContext.Init();
71 }
72 }
75 Buffer::Buffer(RenderParams* rp) : pParams(rp), Size(0), Use(0), GLBuffer(0)
76 {
77 }
79 Buffer::~Buffer()
80 {
81 if (GLBuffer)
82 glDeleteBuffers(1, &GLBuffer);
83 }
85 bool Buffer::Data(int use, const void* buffer, size_t size)
86 {
87 Size = size;
89 switch (use & Buffer_TypeMask)
90 {
91 case Buffer_Index: Use = GL_ELEMENT_ARRAY_BUFFER; break;
92 default: Use = GL_ARRAY_BUFFER; break;
93 }
95 if (!GLBuffer)
96 glGenBuffers(1, &GLBuffer);
98 int mode = GL_DYNAMIC_DRAW;
99 if (use & Buffer_ReadOnly)
100 mode = GL_STATIC_DRAW;
102 glBindBuffer(Use, GLBuffer);
103 glBufferData(Use, size, buffer, mode);
104 return 1;
105 }
107 void* Buffer::Map(size_t, size_t, int)
108 {
109 int mode = GL_WRITE_ONLY;
110 //if (flags & Map_Unsynchronized)
111 // mode |= GL_MAP_UNSYNCHRONIZED;
113 glBindBuffer(Use, GLBuffer);
114 void* v = glMapBuffer(Use, mode);
115 return v;
116 }
118 bool Buffer::Unmap(void*)
119 {
120 glBindBuffer(Use, GLBuffer);
121 int r = glUnmapBuffer(Use);
122 return r != 0;
123 }
125 ShaderSet::ShaderSet() :
126 //Shaders[],
127 UniformInfo(),
128 //Prog(0)
129 ProjLoc(0),
130 ViewLoc(0),
131 //TexLoc[],
132 UsesLighting(false),
133 LightingVer(0)
134 {
135 memset(TexLoc, 0, sizeof(TexLoc));
136 Prog = glCreateProgram();
137 }
138 ShaderSet::~ShaderSet()
139 {
140 glDeleteProgram(Prog);
141 }
143 GLint ShaderSet::GetGLShader(Shader* s)
144 {
145 switch (s->Stage)
146 {
147 case Shader_Vertex: {
148 ShaderImpl<Shader_Vertex, GL_VERTEX_SHADER>* gls = (ShaderImpl<Shader_Vertex, GL_VERTEX_SHADER>*)s;
149 return gls->GLShader;
150 } break;
151 case Shader_Fragment: {
152 ShaderImpl<Shader_Fragment, GL_FRAGMENT_SHADER>* gls = (ShaderImpl<Shader_Fragment, GL_FRAGMENT_SHADER>*)s;
153 return gls->GLShader;
154 } break;
155 default: break;
156 }
158 return -1;
159 }
161 void ShaderSet::SetShader(Shader *s)
162 {
163 Shaders[s->Stage] = s;
164 GLint GLShader = GetGLShader(s);
165 glAttachShader(Prog, GLShader);
166 if (Shaders[Shader_Vertex] && Shaders[Shader_Fragment])
167 Link();
168 }
170 void ShaderSet::UnsetShader(int stage)
171 {
172 if (Shaders[stage] == NULL)
173 return;
175 GLint GLShader = GetGLShader(Shaders[stage]);
176 glDetachShader(Prog, GLShader);
178 Shaders[stage] = NULL;
179 }
181 bool ShaderSet::SetUniform(const char* name, int n, const float* v)
182 {
183 for (unsigned int i = 0; i < UniformInfo.GetSize(); i++)
184 if (!strcmp(UniformInfo[i].Name.ToCStr(), name))
185 {
186 OVR_ASSERT(UniformInfo[i].Location >= 0);
187 glUseProgram(Prog);
188 switch (UniformInfo[i].Type)
189 {
190 case 1: glUniform1fv(UniformInfo[i].Location, n, v); break;
191 case 2: glUniform2fv(UniformInfo[i].Location, n/2, v); break;
192 case 3: glUniform3fv(UniformInfo[i].Location, n/3, v); break;
193 case 4: glUniform4fv(UniformInfo[i].Location, n/4, v); break;
194 case 12: glUniformMatrix3fv(UniformInfo[i].Location, 1, 1, v); break;
195 case 16: glUniformMatrix4fv(UniformInfo[i].Location, 1, 1, v); break;
196 default: OVR_ASSERT(0);
197 }
198 return 1;
199 }
201 OVR_DEBUG_LOG(("Warning: uniform %s not present in selected shader", name));
202 return 0;
203 }
205 bool ShaderSet::Link()
206 {
207 glLinkProgram(Prog);
208 GLint r;
209 glGetProgramiv(Prog, GL_LINK_STATUS, &r);
210 if (!r)
211 {
212 GLchar msg[1024];
213 glGetProgramInfoLog(Prog, sizeof(msg), 0, msg);
214 OVR_DEBUG_LOG(("Linking shaders failed: %s\n", msg));
215 if (!r)
216 return 0;
217 }
218 glUseProgram(Prog);
220 UniformInfo.Clear();
221 LightingVer = 0;
222 UsesLighting = 0;
224 GLint uniformCount = 0;
225 glGetProgramiv(Prog, GL_ACTIVE_UNIFORMS, &uniformCount);
226 OVR_ASSERT(uniformCount >= 0);
228 for(GLuint i = 0; i < (GLuint)uniformCount; i++)
229 {
230 GLsizei namelen;
231 GLint size = 0;
232 GLenum type;
233 GLchar name[32];
234 glGetActiveUniform(Prog, i, sizeof(name), &namelen, &size, &type, name);
236 if (size)
237 {
238 int l = glGetUniformLocation(Prog, name);
239 char *np = name;
240 while (*np)
241 {
242 if (*np == '[')
243 *np = 0;
244 np++;
245 }
246 Uniform u;
247 u.Name = name;
248 u.Location = l;
249 u.Size = size;
250 switch (type)
251 {
252 case GL_FLOAT: u.Type = 1; break;
253 case GL_FLOAT_VEC2: u.Type = 2; break;
254 case GL_FLOAT_VEC3: u.Type = 3; break;
255 case GL_FLOAT_VEC4: u.Type = 4; break;
256 case GL_FLOAT_MAT3: u.Type = 12; break;
257 case GL_FLOAT_MAT4: u.Type = 16; break;
258 default:
259 continue;
260 }
261 UniformInfo.PushBack(u);
262 if (!strcmp(name, "LightCount"))
263 UsesLighting = 1;
264 }
265 else
266 break;
267 }
269 ProjLoc = glGetUniformLocation(Prog, "Proj");
270 ViewLoc = glGetUniformLocation(Prog, "View");
271 for (int i = 0; i < 8; i++)
272 {
273 char texv[32];
274 OVR_sprintf(texv, 10, "Texture%d", i);
275 TexLoc[i] = glGetUniformLocation(Prog, texv);
276 if (TexLoc[i] < 0)
277 break;
279 glUniform1i(TexLoc[i], i);
280 }
281 if (UsesLighting)
282 OVR_ASSERT(ProjLoc >= 0 && ViewLoc >= 0);
283 return 1;
284 }
286 bool ShaderBase::SetUniform(const char* name, int n, const float* v)
287 {
288 for(unsigned i = 0; i < UniformReflSize; i++)
289 {
290 if (!strcmp(UniformRefl[i].Name, name))
291 {
292 memcpy(UniformData + UniformRefl[i].Offset, v, n * sizeof(float));
293 return 1;
294 }
295 }
296 return 0;
297 }
299 bool ShaderBase::SetUniformBool(const char* name, int n, const bool* v)
300 {
301 OVR_UNUSED(n);
302 for(unsigned i = 0; i < UniformReflSize; i++)
303 {
304 if (!strcmp(UniformRefl[i].Name, name))
305 {
306 memcpy(UniformData + UniformRefl[i].Offset, v, UniformRefl[i].Size);
307 return 1;
308 }
309 }
310 return 0;
311 }
313 void ShaderBase::InitUniforms(const Uniform* refl, size_t reflSize)
314 {
315 if(!refl)
316 {
317 UniformRefl = NULL;
318 UniformReflSize = 0;
320 UniformsSize = 0;
321 if (UniformData)
322 {
323 OVR_FREE(UniformData);
324 UniformData = 0;
325 }
326 return; // no reflection data
327 }
329 UniformRefl = refl;
330 UniformReflSize = reflSize;
332 UniformsSize = UniformRefl[UniformReflSize-1].Offset + UniformRefl[UniformReflSize-1].Size;
333 UniformData = (unsigned char*)OVR_ALLOC(UniformsSize);
334 }
336 Texture::Texture(RenderParams* rp, int w, int h) : IsUserAllocated(false), pParams(rp), TexId(0), Width(w), Height(h)
337 {
338 if (w && h)
339 glGenTextures(1, &TexId);
340 }
342 Texture::~Texture()
343 {
344 if (TexId && !IsUserAllocated)
345 glDeleteTextures(1, &TexId);
346 }
348 void Texture::Set(int slot, ShaderStage) const
349 {
350 glActiveTexture(GL_TEXTURE0 + slot);
351 glBindTexture(GL_TEXTURE_2D, TexId);
352 }
354 void Texture::SetSampleMode(int sm)
355 {
356 glBindTexture(GL_TEXTURE_2D, TexId);
357 switch (sm & Sample_FilterMask)
358 {
359 case Sample_Linear:
360 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
361 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
362 if(GLE_EXT_texture_filter_anisotropic)
363 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
364 break;
366 case Sample_Anisotropic:
367 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
368 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
369 if(GLE_EXT_texture_filter_anisotropic)
370 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8);
371 break;
373 case Sample_Nearest:
374 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
375 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
376 if(GLE_EXT_texture_filter_anisotropic)
377 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
378 break;
379 }
381 switch (sm & Sample_AddressMask)
382 {
383 case Sample_Repeat:
384 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
385 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
386 break;
388 case Sample_Clamp:
389 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
390 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
391 break;
393 case Sample_ClampBorder:
394 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
395 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
396 break;
397 }
398 }
400 void Texture::UpdatePlaceholderTexture(GLuint texId, const Sizei& textureSize)
401 {
402 if (!IsUserAllocated && TexId && texId != TexId)
403 glDeleteTextures(1, &TexId);
405 TexId = texId;
406 Width = textureSize.w;
407 Height = textureSize.h;
409 IsUserAllocated = true;
410 }
416 Context::Context() : initialized(false), ownsContext(true), incarnation(0)
417 {
418 #if defined(OVR_OS_MAC)
419 systemContext = 0;
420 #elif defined(OVR_OS_WIN32)
421 hdc = 0;
422 systemContext = 0;
423 #elif defined(OVR_OS_LINUX)
424 x11Display = NULL;
425 x11Drawable = 0;
426 systemContext = 0;
427 memset(&x11Visual, 0, sizeof(x11Visual));
428 #endif
430 }
432 void Context::InitFromCurrent()
433 {
434 Destroy();
436 initialized = true;
437 ownsContext = false;
438 incarnation++;
440 #if defined(OVR_OS_MAC)
441 systemContext = CGLGetCurrentContext();
442 {
443 CGSConnectionID cid;
444 CGSWindowID wid;
445 CGSSurfaceID sid;
446 CGLError e = kCGLNoError;
447 e = CGLGetSurface(systemContext, &cid, &wid, &sid);
448 OVR_ASSERT(e == kCGLNoError); OVR_UNUSED(e);
449 }
451 #elif defined(OVR_OS_WIN32)
452 hdc = wglGetCurrentDC();
453 systemContext = wglGetCurrentContext();
454 #elif defined(OVR_OS_LINUX)
455 x11Display = glXGetCurrentDisplay();
456 x11Drawable = glXGetCurrentDrawable();
457 systemContext = glXGetCurrentContext();
458 if (!SDKWindow::getVisualFromDrawable(x11Drawable, &x11Visual))
459 {
460 OVR::LogError("[Context] Unable to obtain x11 visual from context");
461 memset(&x11Visual, 0, sizeof(x11Visual));
462 }
463 #endif
464 }
467 void Context::CreateShared( Context & ctx )
468 {
469 Destroy();
470 OVR_ASSERT( ctx.initialized == true );
471 if( ctx.initialized == false )
472 {
473 return;
474 }
476 initialized = true;
477 ownsContext = true;
478 incarnation++;
480 #if defined(OVR_OS_MAC)
481 CGLPixelFormatObj pixelFormat = CGLGetPixelFormat( ctx.systemContext );
482 CGLError e = CGLCreateContext( pixelFormat, ctx.systemContext, &systemContext );
483 OVR_ASSERT(e == kCGLNoError); OVR_UNUSED(e);
484 SetSurface(ctx);
485 #elif defined(OVR_OS_WIN32)
486 hdc = ctx.hdc;
487 systemContext = wglCreateContext( ctx.hdc );
488 BOOL success = wglShareLists(ctx.systemContext, systemContext );
489 OVR_ASSERT( success == TRUE );
490 OVR_UNUSED(success);
491 #elif defined(OVR_OS_LINUX)
492 x11Display = ctx.x11Display;
493 x11Drawable = ctx.x11Drawable;
494 x11Visual = ctx.x11Visual;
495 systemContext = glXCreateContext( ctx.x11Display, &x11Visual, ctx.systemContext, True );
496 OVR_ASSERT( systemContext != NULL );
497 #endif
498 }
500 #if defined(OVR_OS_MAC)
501 void Context::SetSurface( Context & ctx ) {
502 CGLError e = kCGLNoError;
503 CGSConnectionID cid, cid2;
504 CGSWindowID wid, wid2;
505 CGSSurfaceID sid, sid2;
507 e = CGLGetSurface(ctx.systemContext, &cid, &wid, &sid);
508 OVR_ASSERT(e == kCGLNoError); OVR_UNUSED(e);
509 e = CGLGetSurface(systemContext, &cid2, &wid2, &sid2);
510 OVR_ASSERT(e == kCGLNoError); OVR_UNUSED(e);
511 if( sid && sid != sid2 ) {
512 e = CGLSetSurface(systemContext, cid, wid, sid);
513 OVR_ASSERT(e == kCGLNoError); OVR_UNUSED(e);
514 }
515 }
516 #endif
518 void Context::Destroy()
519 {
520 if( initialized == false )
521 {
522 return;
523 }
525 if (systemContext)
526 {
527 #if defined(OVR_OS_MAC)
528 CGLDestroyContext( systemContext );
529 #elif defined(OVR_OS_WIN32)
530 BOOL success = wglDeleteContext( systemContext );
531 OVR_ASSERT( success == TRUE );
532 OVR_UNUSED( success );
533 #elif defined(OVR_OS_LINUX)
534 glXDestroyContext( x11Display, systemContext );
535 #endif
537 systemContext = NULL;
538 }
540 initialized = false;
541 ownsContext = true;
542 }
544 void Context::Bind()
545 {
546 if(systemContext)
547 {
548 #if defined(OVR_OS_MAC)
549 glFlush(); //Apple doesn't automatically flush within CGLSetCurrentContext, unlike other platforms.
550 CGLSetCurrentContext( systemContext );
551 #elif defined(OVR_OS_WIN32)
552 wglMakeCurrent( hdc, systemContext );
553 #elif defined(OVR_OS_LINUX)
554 glXMakeCurrent( x11Display, x11Drawable, systemContext );
555 #endif
556 }
557 }
559 void Context::Unbind()
560 {
561 #if defined(OVR_OS_MAC)
562 glFlush(); //Apple doesn't automatically flush within CGLSetCurrentContext, unlike other platforms.
563 CGLSetCurrentContext( NULL );
564 #elif defined(OVR_OS_WIN32)
565 wglMakeCurrent( hdc, NULL );
566 #elif defined(OVR_OS_LINUX)
567 glXMakeCurrent( x11Display, None, NULL );
568 #endif
569 }
571 }}} // namespace OVR::CAPI::GL