ovr_sdk

view LibOVR/Src/CAPI/GL/CAPI_GL_Util.h @ 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.h
4 Content : Utility header for OpenGL
5 Created : March 27, 2014
6 Authors : Andrew Reisse, David Borel
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 #ifndef INC_OVR_CAPI_GL_Util_h
28 #define INC_OVR_CAPI_GL_Util_h
30 #include "../../OVR_CAPI.h"
31 #include "../../Kernel/OVR_Array.h"
32 #include "../../Kernel/OVR_Math.h"
33 #include "../../Kernel/OVR_RefCount.h"
34 #include "../../Kernel/OVR_String.h"
35 #include "../../Kernel/OVR_Types.h"
36 #include "../../Kernel/OVR_Log.h"
38 #if defined(OVR_OS_WIN32)
39 #define WIN32_LEAN_AND_MEAN
40 #include <Windows.h>
41 #endif
43 #if !defined(OVR_DISABLE_GLE) // By default we use the GLE module in order to link to OpenGL functions. However, if an external user
44 #include "CAPI_GLE.h" // wants to use an alternative mechanism to connect to OpenGL functions, they can #define OVR_DISABLE_GLE.
45 #endif
48 #if defined(OVR_OS_MAC)
49 #include <CoreGraphics/CGDirectDisplay.h>
50 #include <OpenGL/CGLTypes.h>
51 #endif
54 namespace OVR
55 {
56 // Get the shared LibOVR GLEContext instance.
57 class GLEContext;
58 GLEContext* GetGLEContext();
59 }
61 namespace OVR { namespace CAPI { namespace GL {
62 void InitGLExtensions();
65 // Rendering primitive type used to render Model.
66 enum PrimitiveType
67 {
68 Prim_Triangles,
69 Prim_Lines,
70 Prim_TriangleStrip,
71 Prim_Unknown,
72 Prim_Count
73 };
75 // Types of shaders that can be stored together in a ShaderSet.
76 enum ShaderStage
77 {
78 Shader_Vertex = 0,
79 Shader_Fragment = 2,
80 Shader_Pixel = 2,
81 Shader_Count = 3,
82 };
84 enum MapFlags
85 {
86 Map_Discard = 1,
87 Map_Read = 2, // do not use
88 Map_Unsynchronized = 4, // like D3D11_MAP_NO_OVERWRITE
89 };
92 // Buffer types used for uploading geometry & constants.
93 enum BufferUsage
94 {
95 Buffer_Unknown = 0,
96 Buffer_Vertex = 1,
97 Buffer_Index = 2,
98 Buffer_Uniform = 4,
99 Buffer_TypeMask = 0xff,
100 Buffer_ReadOnly = 0x100, // Buffer must be created with Data().
101 };
103 enum TextureFormat
104 {
105 Texture_RGBA = 0x0100,
106 Texture_Depth = 0x8000,
107 Texture_TypeMask = 0xff00,
108 Texture_SamplesMask = 0x00ff,
109 Texture_RenderTarget = 0x10000,
110 Texture_GenMipmaps = 0x20000,
111 };
113 // Texture sampling modes.
114 enum SampleMode
115 {
116 Sample_Linear = 0,
117 Sample_Nearest = 1,
118 Sample_Anisotropic = 2,
119 Sample_FilterMask = 3,
121 Sample_Repeat = 0,
122 Sample_Clamp = 4,
123 Sample_ClampBorder = 8, // If unsupported Clamp is used instead.
124 Sample_AddressMask =12,
126 Sample_Count =13,
127 };
130 // Rendering parameters/pointers describing GL rendering setup.
131 struct RenderParams
132 {
133 #if defined(OVR_OS_WIN32)
134 HWND Window;
135 HDC DC;
136 #elif defined(OVR_OS_LINUX)
137 struct _XDisplay* Disp;
138 #endif
140 ovrSizei BackBufferSize;
141 int Multisample;
142 };
145 class Buffer : public RefCountBase<Buffer>
146 {
147 public:
148 RenderParams* pParams;
149 size_t Size;
150 GLenum Use;
151 GLuint GLBuffer;
153 public:
154 Buffer(RenderParams* r);
155 ~Buffer();
157 GLuint GetBuffer() { return GLBuffer; }
159 virtual size_t GetSize() { return Size; }
160 virtual void* Map(size_t start, size_t size, int flags = 0);
161 virtual bool Unmap(void *m);
162 virtual bool Data(int use, const void* buffer, size_t size);
163 };
165 class Texture : public RefCountBase<Texture>
166 {
167 bool IsUserAllocated;
169 public:
170 RenderParams* pParams;
171 GLuint TexId;
172 int Width, Height;
174 Texture(RenderParams* rp, int w, int h);
175 ~Texture();
177 virtual int GetWidth() const { return Width; }
178 virtual int GetHeight() const { return Height; }
180 virtual void SetSampleMode(int sm);
182 // Updates texture to point to specified resources
183 // - used for slave rendering.
184 void UpdatePlaceholderTexture(GLuint texId,
185 const Sizei& textureSize);
187 virtual void Set(int slot, ShaderStage stage = Shader_Fragment) const;
188 };
190 // Base class for vertex and pixel shaders. Stored in ShaderSet.
191 class Shader : public RefCountBase<Shader>
192 {
193 friend class ShaderSet;
195 protected:
196 ShaderStage Stage;
198 public:
199 Shader(ShaderStage s) : Stage(s) {}
200 virtual ~Shader() {}
202 ShaderStage GetStage() const { return Stage; }
204 virtual void Set(PrimitiveType) const { }
205 virtual void SetUniformBuffer(class Buffer* buffers, int i = 0) { OVR_UNUSED2(buffers, i); }
207 protected:
208 virtual bool SetUniform(const char* name, int n, const float* v) { OVR_UNUSED3(name, n, v); return false; }
209 virtual bool SetUniformBool(const char* name, int n, const bool* v) { OVR_UNUSED3(name, n, v); return false; }
210 };
214 // A group of shaders, one per stage.
215 // A ShaderSet is applied for rendering with a given fill.
216 class ShaderSet : public RefCountBase<ShaderSet>
217 {
218 protected:
219 Ptr<Shader> Shaders[Shader_Count];
221 struct Uniform
222 {
223 String Name;
224 int Location, Size;
225 int Type; // currently number of floats in vector
227 Uniform() : Name(), Location(0), Size(0), Type(0){}
228 };
229 Array<Uniform> UniformInfo;
231 public:
232 GLuint Prog;
233 GLint ProjLoc, ViewLoc;
234 GLint TexLoc[8];
235 bool UsesLighting;
236 int LightingVer;
238 ShaderSet();
239 ~ShaderSet();
241 virtual void SetShader(Shader *s);
242 virtual void UnsetShader(int stage);
243 Shader* GetShader(int stage) { return Shaders[stage]; }
245 virtual void Set(PrimitiveType prim) const
246 {
247 glUseProgram(Prog);
249 for (int i = 0; i < Shader_Count; i++)
250 if (Shaders[i])
251 Shaders[i]->Set(prim);
252 }
254 // Set a uniform (other than the standard matrices). It is undefined whether the
255 // uniforms from one shader occupy the same space as those in other shaders
256 // (unless a buffer is used, then each buffer is independent).
257 virtual bool SetUniform(const char* name, int n, const float* v);
258 bool SetUniform1f(const char* name, float x)
259 {
260 const float v[] = {x};
261 return SetUniform(name, 1, v);
262 }
263 bool SetUniform2f(const char* name, float x, float y)
264 {
265 const float v[] = {x,y};
266 return SetUniform(name, 2, v);
267 }
268 bool SetUniform3f(const char* name, float x, float y, float z)
269 {
270 const float v[] = {x,y,z};
271 return SetUniform(name, 3, v);
272 }
273 bool SetUniform4f(const char* name, float x, float y, float z, float w = 1)
274 {
275 const float v[] = {x,y,z,w};
276 return SetUniform(name, 4, v);
277 }
279 bool SetUniformv(const char* name, const Vector3f& v)
280 {
281 const float a[] = {v.x,v.y,v.z,1};
282 return SetUniform(name, 4, a);
283 }
285 virtual bool SetUniform4x4f(const char* name, const Matrix4f& m)
286 {
287 Matrix4f mt = m.Transposed();
288 return SetUniform(name, 16, &mt.M[0][0]);
289 }
291 virtual bool SetUniform3x3f(const char* name, const Matrix4f& m)
292 {
293 Matrix4f mt = m.Transposed();
294 // float3x3 is actually stored the same way as float4x3, with the last items ignored by the code.
295 return SetUniform(name, 12, &mt.M[0][0]);
296 }
299 protected:
300 GLint GetGLShader(Shader* s);
301 bool Link();
302 };
305 // Fill combines a ShaderSet (vertex, pixel) with textures, if any.
306 // Every model has a fill.
307 class ShaderFill : public RefCountBase<ShaderFill>
308 {
309 Ptr<ShaderSet> Shaders;
310 Ptr<class Texture> Textures[8];
311 void* InputLayout; // HACK this should be abstracted
313 public:
314 ShaderFill(ShaderSet* sh) : Shaders(sh) { InputLayout = NULL; }
315 ShaderFill(ShaderSet& sh) : Shaders(sh) { InputLayout = NULL; }
317 ShaderSet* GetShaders() const { return Shaders; }
318 void* GetInputLayout() const { return InputLayout; }
320 virtual void Set(PrimitiveType prim = Prim_Unknown) const {
321 Shaders->Set(prim);
322 for(int i = 0; i < 8; i++)
323 {
324 if(Textures[i])
325 {
326 Textures[i]->Set(i);
327 }
328 }
329 }
331 virtual void SetTexture(int i, class Texture* tex) { if (i < 8) Textures[i] = tex; }
332 };
335 struct DisplayId
336 {
337 // Windows
338 String MonitorName; // Monitor name for fullscreen mode
340 // MacOS
341 long CgDisplayId; // CGDirectDisplayID
343 DisplayId() : CgDisplayId(0) {}
344 DisplayId(long id) : CgDisplayId(id) {}
345 DisplayId(String m, long id=0) : MonitorName(m), CgDisplayId(id) {}
347 operator bool () const
348 {
349 return MonitorName.GetLength() || CgDisplayId;
350 }
352 bool operator== (const DisplayId& b) const
353 {
354 return CgDisplayId == b.CgDisplayId &&
355 (strstr(MonitorName.ToCStr(), b.MonitorName.ToCStr()) ||
356 strstr(b.MonitorName.ToCStr(), MonitorName.ToCStr()));
357 }
358 };
361 class ShaderBase : public Shader
362 {
363 public:
364 RenderParams* pParams;
365 unsigned char* UniformData;
366 int UniformsSize;
368 enum VarType
369 {
370 VARTYPE_FLOAT,
371 VARTYPE_INT,
372 VARTYPE_BOOL,
373 };
375 struct Uniform
376 {
377 const char* Name;
378 VarType Type;
379 int Offset;
380 int Size;
381 };
383 const Uniform* UniformRefl;
384 size_t UniformReflSize;
386 ShaderBase(RenderParams* rp, ShaderStage stage) :
387 Shader(stage),
388 pParams(rp),
389 UniformData(NULL),
390 UniformsSize(0),
391 UniformRefl(NULL),
392 UniformReflSize(0)
393 {
394 }
395 ~ShaderBase()
396 {
397 if (UniformData)
398 {
399 OVR_FREE(UniformData);
400 UniformData = NULL;
401 }
403 // Do not need to free UniformRefl
404 UniformRefl = NULL;
405 }
407 void InitUniforms(const Uniform* refl, size_t reflSize);
408 bool SetUniform(const char* name, int n, const float* v);
409 bool SetUniformBool(const char* name, int n, const bool* v);
410 };
413 template<ShaderStage SStage, GLenum SType>
414 class ShaderImpl : public ShaderBase
415 {
416 friend class ShaderSet;
418 public:
419 ShaderImpl(RenderParams* rp, void* s, size_t size, const Uniform* refl, size_t reflSize)
420 : ShaderBase(rp, SStage)
421 , GLShader(0)
422 {
423 bool success;
424 OVR_UNUSED(size);
425 success = Compile((const char*) s);
426 OVR_ASSERT(success);
427 OVR_UNUSED(success);
428 InitUniforms(refl, reflSize);
429 }
430 ~ShaderImpl()
431 {
432 if (GLShader)
433 {
434 glDeleteShader(GLShader);
435 GLShader = 0;
436 }
437 }
438 bool Compile(const char* src)
439 {
440 if (!GLShader)
441 GLShader = glCreateShader(GLStage());
443 glShaderSource(GLShader, 1, &src, 0);
444 glCompileShader(GLShader);
445 GLint r;
446 glGetShaderiv(GLShader, GL_COMPILE_STATUS, &r);
447 if (!r)
448 {
449 GLchar msg[1024];
450 glGetShaderInfoLog(GLShader, sizeof(msg), 0, msg);
451 if (msg[0])
452 OVR_DEBUG_LOG(("Compiling shader\n%s\nfailed: %s\n", src, msg));
454 return 0;
455 }
456 return 1;
457 }
459 GLenum GLStage() const
460 {
461 return SType;
462 }
464 private:
465 GLuint GLShader;
466 };
468 typedef ShaderImpl<Shader_Vertex, GL_VERTEX_SHADER> VertexShader;
469 typedef ShaderImpl<Shader_Fragment, GL_FRAGMENT_SHADER> FragmentShader;
473 // Allows us to have independent OpenGL contexts for our systems.
474 class Context
475 {
476 bool initialized;
477 bool ownsContext;
478 int incarnation;
479 #if defined(OVR_OS_WIN32)
480 HDC hdc;
481 HGLRC systemContext;
482 #elif defined(OVR_OS_LINUX)
483 Display *x11Display;
484 GLXDrawable x11Drawable;
485 GLXContext systemContext;
486 XVisualInfo x11Visual;
487 #elif defined(OVR_OS_MAC)
488 CGLContextObj systemContext;
489 #endif
491 public:
493 Context();
494 void InitFromCurrent();
495 void CreateShared( Context & ctx );
496 #if defined(OVR_OS_MAC)
497 void SetSurface( Context & ctx );
498 #endif
499 void Destroy();
500 void Bind();
501 void Unbind();
502 int GetIncarnation() const { return incarnation; }
504 };
507 // AutoContext
508 //
509 // Implements a common sequence of function calls with the Context class.
510 // See the AutoContext constructor below for what it does.
511 //
512 // Example usage:
513 // void SomeClass::Draw()
514 // {
515 // AutoContext autoContext(someClassContext);
516 //
517 // <draw calls>
518 // }
520 struct AutoContext
521 {
522 Context savedCurrentContext;
523 Context& ourContext;
525 AutoContext(Context& context) :
526 savedCurrentContext(), ourContext(context)
527 {
528 // We use a member savedCurrentContext which is initialized here, as opposed to having the user pass in a
529 // pre-existing Context (which the user could declare as a global or C++ member variable). We have to do this
530 // because if we were to use some pre-existing Context the app might delete its underlying GL context behind our back
531 // or associate it with another thread, which would cause our bind of it in our dtor to be a bad operation.
532 savedCurrentContext.InitFromCurrent();
533 if(ourContext.GetIncarnation() == 0) // If not yet initialized...
534 ourContext.CreateShared(savedCurrentContext);
535 ourContext.Bind();
536 #if defined(OVR_OS_MAC) // To consider: merge the following into the Bind function.
537 ourContext.SetSurface(savedCurrentContext);
538 #endif
539 }
541 ~AutoContext()
542 {
543 savedCurrentContext.Bind();
544 }
546 OVR_NON_COPYABLE(AutoContext)
547 };
550 }}} // namespace OVR::CAPI::GL
553 #endif // INC_OVR_CAPI_GL_Util_h