ovr_sdk
diff 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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/LibOVR/Src/CAPI/GL/CAPI_GL_Util.h Wed Jan 14 06:51:16 2015 +0200 1.3 @@ -0,0 +1,553 @@ 1.4 +/************************************************************************************ 1.5 + 1.6 +Filename : CAPI_GL_Util.h 1.7 +Content : Utility header for OpenGL 1.8 +Created : March 27, 2014 1.9 +Authors : Andrew Reisse, David Borel 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 +#ifndef INC_OVR_CAPI_GL_Util_h 1.31 +#define INC_OVR_CAPI_GL_Util_h 1.32 + 1.33 +#include "../../OVR_CAPI.h" 1.34 +#include "../../Kernel/OVR_Array.h" 1.35 +#include "../../Kernel/OVR_Math.h" 1.36 +#include "../../Kernel/OVR_RefCount.h" 1.37 +#include "../../Kernel/OVR_String.h" 1.38 +#include "../../Kernel/OVR_Types.h" 1.39 +#include "../../Kernel/OVR_Log.h" 1.40 + 1.41 +#if defined(OVR_OS_WIN32) 1.42 +#define WIN32_LEAN_AND_MEAN 1.43 +#include <Windows.h> 1.44 +#endif 1.45 + 1.46 +#if !defined(OVR_DISABLE_GLE) // By default we use the GLE module in order to link to OpenGL functions. However, if an external user 1.47 +#include "CAPI_GLE.h" // wants to use an alternative mechanism to connect to OpenGL functions, they can #define OVR_DISABLE_GLE. 1.48 +#endif 1.49 + 1.50 + 1.51 +#if defined(OVR_OS_MAC) 1.52 + #include <CoreGraphics/CGDirectDisplay.h> 1.53 + #include <OpenGL/CGLTypes.h> 1.54 +#endif 1.55 + 1.56 + 1.57 +namespace OVR 1.58 +{ 1.59 + // Get the shared LibOVR GLEContext instance. 1.60 + class GLEContext; 1.61 + GLEContext* GetGLEContext(); 1.62 +} 1.63 + 1.64 +namespace OVR { namespace CAPI { namespace GL { 1.65 +void InitGLExtensions(); 1.66 + 1.67 + 1.68 +// Rendering primitive type used to render Model. 1.69 +enum PrimitiveType 1.70 +{ 1.71 + Prim_Triangles, 1.72 + Prim_Lines, 1.73 + Prim_TriangleStrip, 1.74 + Prim_Unknown, 1.75 + Prim_Count 1.76 +}; 1.77 + 1.78 +// Types of shaders that can be stored together in a ShaderSet. 1.79 +enum ShaderStage 1.80 +{ 1.81 + Shader_Vertex = 0, 1.82 + Shader_Fragment = 2, 1.83 + Shader_Pixel = 2, 1.84 + Shader_Count = 3, 1.85 +}; 1.86 + 1.87 +enum MapFlags 1.88 +{ 1.89 + Map_Discard = 1, 1.90 + Map_Read = 2, // do not use 1.91 + Map_Unsynchronized = 4, // like D3D11_MAP_NO_OVERWRITE 1.92 +}; 1.93 + 1.94 + 1.95 +// Buffer types used for uploading geometry & constants. 1.96 +enum BufferUsage 1.97 +{ 1.98 + Buffer_Unknown = 0, 1.99 + Buffer_Vertex = 1, 1.100 + Buffer_Index = 2, 1.101 + Buffer_Uniform = 4, 1.102 + Buffer_TypeMask = 0xff, 1.103 + Buffer_ReadOnly = 0x100, // Buffer must be created with Data(). 1.104 +}; 1.105 + 1.106 +enum TextureFormat 1.107 +{ 1.108 + Texture_RGBA = 0x0100, 1.109 + Texture_Depth = 0x8000, 1.110 + Texture_TypeMask = 0xff00, 1.111 + Texture_SamplesMask = 0x00ff, 1.112 + Texture_RenderTarget = 0x10000, 1.113 + Texture_GenMipmaps = 0x20000, 1.114 +}; 1.115 + 1.116 +// Texture sampling modes. 1.117 +enum SampleMode 1.118 +{ 1.119 + Sample_Linear = 0, 1.120 + Sample_Nearest = 1, 1.121 + Sample_Anisotropic = 2, 1.122 + Sample_FilterMask = 3, 1.123 + 1.124 + Sample_Repeat = 0, 1.125 + Sample_Clamp = 4, 1.126 + Sample_ClampBorder = 8, // If unsupported Clamp is used instead. 1.127 + Sample_AddressMask =12, 1.128 + 1.129 + Sample_Count =13, 1.130 +}; 1.131 + 1.132 + 1.133 +// Rendering parameters/pointers describing GL rendering setup. 1.134 +struct RenderParams 1.135 +{ 1.136 +#if defined(OVR_OS_WIN32) 1.137 + HWND Window; 1.138 + HDC DC; 1.139 +#elif defined(OVR_OS_LINUX) 1.140 + struct _XDisplay* Disp; 1.141 +#endif 1.142 + 1.143 + ovrSizei BackBufferSize; 1.144 + int Multisample; 1.145 +}; 1.146 + 1.147 + 1.148 +class Buffer : public RefCountBase<Buffer> 1.149 +{ 1.150 +public: 1.151 + RenderParams* pParams; 1.152 + size_t Size; 1.153 + GLenum Use; 1.154 + GLuint GLBuffer; 1.155 + 1.156 +public: 1.157 + Buffer(RenderParams* r); 1.158 + ~Buffer(); 1.159 + 1.160 + GLuint GetBuffer() { return GLBuffer; } 1.161 + 1.162 + virtual size_t GetSize() { return Size; } 1.163 + virtual void* Map(size_t start, size_t size, int flags = 0); 1.164 + virtual bool Unmap(void *m); 1.165 + virtual bool Data(int use, const void* buffer, size_t size); 1.166 +}; 1.167 + 1.168 +class Texture : public RefCountBase<Texture> 1.169 +{ 1.170 + bool IsUserAllocated; 1.171 + 1.172 +public: 1.173 + RenderParams* pParams; 1.174 + GLuint TexId; 1.175 + int Width, Height; 1.176 + 1.177 + Texture(RenderParams* rp, int w, int h); 1.178 + ~Texture(); 1.179 + 1.180 + virtual int GetWidth() const { return Width; } 1.181 + virtual int GetHeight() const { return Height; } 1.182 + 1.183 + virtual void SetSampleMode(int sm); 1.184 + 1.185 + // Updates texture to point to specified resources 1.186 + // - used for slave rendering. 1.187 + void UpdatePlaceholderTexture(GLuint texId, 1.188 + const Sizei& textureSize); 1.189 + 1.190 + virtual void Set(int slot, ShaderStage stage = Shader_Fragment) const; 1.191 +}; 1.192 + 1.193 +// Base class for vertex and pixel shaders. Stored in ShaderSet. 1.194 +class Shader : public RefCountBase<Shader> 1.195 +{ 1.196 + friend class ShaderSet; 1.197 + 1.198 +protected: 1.199 + ShaderStage Stage; 1.200 + 1.201 +public: 1.202 + Shader(ShaderStage s) : Stage(s) {} 1.203 + virtual ~Shader() {} 1.204 + 1.205 + ShaderStage GetStage() const { return Stage; } 1.206 + 1.207 + virtual void Set(PrimitiveType) const { } 1.208 + virtual void SetUniformBuffer(class Buffer* buffers, int i = 0) { OVR_UNUSED2(buffers, i); } 1.209 + 1.210 +protected: 1.211 + virtual bool SetUniform(const char* name, int n, const float* v) { OVR_UNUSED3(name, n, v); return false; } 1.212 + virtual bool SetUniformBool(const char* name, int n, const bool* v) { OVR_UNUSED3(name, n, v); return false; } 1.213 +}; 1.214 + 1.215 + 1.216 + 1.217 +// A group of shaders, one per stage. 1.218 +// A ShaderSet is applied for rendering with a given fill. 1.219 +class ShaderSet : public RefCountBase<ShaderSet> 1.220 +{ 1.221 +protected: 1.222 + Ptr<Shader> Shaders[Shader_Count]; 1.223 + 1.224 + struct Uniform 1.225 + { 1.226 + String Name; 1.227 + int Location, Size; 1.228 + int Type; // currently number of floats in vector 1.229 + 1.230 + Uniform() : Name(), Location(0), Size(0), Type(0){} 1.231 + }; 1.232 + Array<Uniform> UniformInfo; 1.233 + 1.234 +public: 1.235 + GLuint Prog; 1.236 + GLint ProjLoc, ViewLoc; 1.237 + GLint TexLoc[8]; 1.238 + bool UsesLighting; 1.239 + int LightingVer; 1.240 + 1.241 + ShaderSet(); 1.242 + ~ShaderSet(); 1.243 + 1.244 + virtual void SetShader(Shader *s); 1.245 + virtual void UnsetShader(int stage); 1.246 + Shader* GetShader(int stage) { return Shaders[stage]; } 1.247 + 1.248 + virtual void Set(PrimitiveType prim) const 1.249 + { 1.250 + glUseProgram(Prog); 1.251 + 1.252 + for (int i = 0; i < Shader_Count; i++) 1.253 + if (Shaders[i]) 1.254 + Shaders[i]->Set(prim); 1.255 + } 1.256 + 1.257 + // Set a uniform (other than the standard matrices). It is undefined whether the 1.258 + // uniforms from one shader occupy the same space as those in other shaders 1.259 + // (unless a buffer is used, then each buffer is independent). 1.260 + virtual bool SetUniform(const char* name, int n, const float* v); 1.261 + bool SetUniform1f(const char* name, float x) 1.262 + { 1.263 + const float v[] = {x}; 1.264 + return SetUniform(name, 1, v); 1.265 + } 1.266 + bool SetUniform2f(const char* name, float x, float y) 1.267 + { 1.268 + const float v[] = {x,y}; 1.269 + return SetUniform(name, 2, v); 1.270 + } 1.271 + bool SetUniform3f(const char* name, float x, float y, float z) 1.272 + { 1.273 + const float v[] = {x,y,z}; 1.274 + return SetUniform(name, 3, v); 1.275 + } 1.276 + bool SetUniform4f(const char* name, float x, float y, float z, float w = 1) 1.277 + { 1.278 + const float v[] = {x,y,z,w}; 1.279 + return SetUniform(name, 4, v); 1.280 + } 1.281 + 1.282 + bool SetUniformv(const char* name, const Vector3f& v) 1.283 + { 1.284 + const float a[] = {v.x,v.y,v.z,1}; 1.285 + return SetUniform(name, 4, a); 1.286 + } 1.287 + 1.288 + virtual bool SetUniform4x4f(const char* name, const Matrix4f& m) 1.289 + { 1.290 + Matrix4f mt = m.Transposed(); 1.291 + return SetUniform(name, 16, &mt.M[0][0]); 1.292 + } 1.293 + 1.294 + virtual bool SetUniform3x3f(const char* name, const Matrix4f& m) 1.295 + { 1.296 + Matrix4f mt = m.Transposed(); 1.297 + // float3x3 is actually stored the same way as float4x3, with the last items ignored by the code. 1.298 + return SetUniform(name, 12, &mt.M[0][0]); 1.299 + } 1.300 + 1.301 + 1.302 +protected: 1.303 + GLint GetGLShader(Shader* s); 1.304 + bool Link(); 1.305 +}; 1.306 + 1.307 + 1.308 +// Fill combines a ShaderSet (vertex, pixel) with textures, if any. 1.309 +// Every model has a fill. 1.310 +class ShaderFill : public RefCountBase<ShaderFill> 1.311 +{ 1.312 + Ptr<ShaderSet> Shaders; 1.313 + Ptr<class Texture> Textures[8]; 1.314 + void* InputLayout; // HACK this should be abstracted 1.315 + 1.316 +public: 1.317 + ShaderFill(ShaderSet* sh) : Shaders(sh) { InputLayout = NULL; } 1.318 + ShaderFill(ShaderSet& sh) : Shaders(sh) { InputLayout = NULL; } 1.319 + 1.320 + ShaderSet* GetShaders() const { return Shaders; } 1.321 + void* GetInputLayout() const { return InputLayout; } 1.322 + 1.323 + virtual void Set(PrimitiveType prim = Prim_Unknown) const { 1.324 + Shaders->Set(prim); 1.325 + for(int i = 0; i < 8; i++) 1.326 + { 1.327 + if(Textures[i]) 1.328 + { 1.329 + Textures[i]->Set(i); 1.330 + } 1.331 + } 1.332 + } 1.333 + 1.334 + virtual void SetTexture(int i, class Texture* tex) { if (i < 8) Textures[i] = tex; } 1.335 +}; 1.336 + 1.337 + 1.338 +struct DisplayId 1.339 +{ 1.340 + // Windows 1.341 + String MonitorName; // Monitor name for fullscreen mode 1.342 + 1.343 + // MacOS 1.344 + long CgDisplayId; // CGDirectDisplayID 1.345 + 1.346 + DisplayId() : CgDisplayId(0) {} 1.347 + DisplayId(long id) : CgDisplayId(id) {} 1.348 + DisplayId(String m, long id=0) : MonitorName(m), CgDisplayId(id) {} 1.349 + 1.350 + operator bool () const 1.351 + { 1.352 + return MonitorName.GetLength() || CgDisplayId; 1.353 + } 1.354 + 1.355 + bool operator== (const DisplayId& b) const 1.356 + { 1.357 + return CgDisplayId == b.CgDisplayId && 1.358 + (strstr(MonitorName.ToCStr(), b.MonitorName.ToCStr()) || 1.359 + strstr(b.MonitorName.ToCStr(), MonitorName.ToCStr())); 1.360 + } 1.361 +}; 1.362 + 1.363 + 1.364 +class ShaderBase : public Shader 1.365 +{ 1.366 +public: 1.367 + RenderParams* pParams; 1.368 + unsigned char* UniformData; 1.369 + int UniformsSize; 1.370 + 1.371 + enum VarType 1.372 + { 1.373 + VARTYPE_FLOAT, 1.374 + VARTYPE_INT, 1.375 + VARTYPE_BOOL, 1.376 + }; 1.377 + 1.378 + struct Uniform 1.379 + { 1.380 + const char* Name; 1.381 + VarType Type; 1.382 + int Offset; 1.383 + int Size; 1.384 + }; 1.385 + 1.386 + const Uniform* UniformRefl; 1.387 + size_t UniformReflSize; 1.388 + 1.389 + ShaderBase(RenderParams* rp, ShaderStage stage) : 1.390 + Shader(stage), 1.391 + pParams(rp), 1.392 + UniformData(NULL), 1.393 + UniformsSize(0), 1.394 + UniformRefl(NULL), 1.395 + UniformReflSize(0) 1.396 + { 1.397 + } 1.398 + ~ShaderBase() 1.399 + { 1.400 + if (UniformData) 1.401 + { 1.402 + OVR_FREE(UniformData); 1.403 + UniformData = NULL; 1.404 + } 1.405 + 1.406 + // Do not need to free UniformRefl 1.407 + UniformRefl = NULL; 1.408 + } 1.409 + 1.410 + void InitUniforms(const Uniform* refl, size_t reflSize); 1.411 + bool SetUniform(const char* name, int n, const float* v); 1.412 + bool SetUniformBool(const char* name, int n, const bool* v); 1.413 +}; 1.414 + 1.415 + 1.416 +template<ShaderStage SStage, GLenum SType> 1.417 +class ShaderImpl : public ShaderBase 1.418 +{ 1.419 + friend class ShaderSet; 1.420 + 1.421 +public: 1.422 + ShaderImpl(RenderParams* rp, void* s, size_t size, const Uniform* refl, size_t reflSize) 1.423 + : ShaderBase(rp, SStage) 1.424 + , GLShader(0) 1.425 + { 1.426 + bool success; 1.427 + OVR_UNUSED(size); 1.428 + success = Compile((const char*) s); 1.429 + OVR_ASSERT(success); 1.430 + OVR_UNUSED(success); 1.431 + InitUniforms(refl, reflSize); 1.432 + } 1.433 + ~ShaderImpl() 1.434 + { 1.435 + if (GLShader) 1.436 + { 1.437 + glDeleteShader(GLShader); 1.438 + GLShader = 0; 1.439 + } 1.440 + } 1.441 + bool Compile(const char* src) 1.442 + { 1.443 + if (!GLShader) 1.444 + GLShader = glCreateShader(GLStage()); 1.445 + 1.446 + glShaderSource(GLShader, 1, &src, 0); 1.447 + glCompileShader(GLShader); 1.448 + GLint r; 1.449 + glGetShaderiv(GLShader, GL_COMPILE_STATUS, &r); 1.450 + if (!r) 1.451 + { 1.452 + GLchar msg[1024]; 1.453 + glGetShaderInfoLog(GLShader, sizeof(msg), 0, msg); 1.454 + if (msg[0]) 1.455 + OVR_DEBUG_LOG(("Compiling shader\n%s\nfailed: %s\n", src, msg)); 1.456 + 1.457 + return 0; 1.458 + } 1.459 + return 1; 1.460 + } 1.461 + 1.462 + GLenum GLStage() const 1.463 + { 1.464 + return SType; 1.465 + } 1.466 + 1.467 +private: 1.468 + GLuint GLShader; 1.469 +}; 1.470 + 1.471 +typedef ShaderImpl<Shader_Vertex, GL_VERTEX_SHADER> VertexShader; 1.472 +typedef ShaderImpl<Shader_Fragment, GL_FRAGMENT_SHADER> FragmentShader; 1.473 + 1.474 + 1.475 + 1.476 +// Allows us to have independent OpenGL contexts for our systems. 1.477 +class Context 1.478 +{ 1.479 + bool initialized; 1.480 + bool ownsContext; 1.481 + int incarnation; 1.482 +#if defined(OVR_OS_WIN32) 1.483 + HDC hdc; 1.484 + HGLRC systemContext; 1.485 +#elif defined(OVR_OS_LINUX) 1.486 + Display *x11Display; 1.487 + GLXDrawable x11Drawable; 1.488 + GLXContext systemContext; 1.489 + XVisualInfo x11Visual; 1.490 +#elif defined(OVR_OS_MAC) 1.491 + CGLContextObj systemContext; 1.492 +#endif 1.493 + 1.494 +public: 1.495 + 1.496 + Context(); 1.497 + void InitFromCurrent(); 1.498 + void CreateShared( Context & ctx ); 1.499 +#if defined(OVR_OS_MAC) 1.500 + void SetSurface( Context & ctx ); 1.501 +#endif 1.502 + void Destroy(); 1.503 + void Bind(); 1.504 + void Unbind(); 1.505 + int GetIncarnation() const { return incarnation; } 1.506 + 1.507 +}; 1.508 + 1.509 + 1.510 +// AutoContext 1.511 +// 1.512 +// Implements a common sequence of function calls with the Context class. 1.513 +// See the AutoContext constructor below for what it does. 1.514 +// 1.515 +// Example usage: 1.516 +// void SomeClass::Draw() 1.517 +// { 1.518 +// AutoContext autoContext(someClassContext); 1.519 +// 1.520 +// <draw calls> 1.521 +// } 1.522 + 1.523 +struct AutoContext 1.524 +{ 1.525 + Context savedCurrentContext; 1.526 + Context& ourContext; 1.527 + 1.528 + AutoContext(Context& context) : 1.529 + savedCurrentContext(), ourContext(context) 1.530 + { 1.531 + // We use a member savedCurrentContext which is initialized here, as opposed to having the user pass in a 1.532 + // pre-existing Context (which the user could declare as a global or C++ member variable). We have to do this 1.533 + // because if we were to use some pre-existing Context the app might delete its underlying GL context behind our back 1.534 + // or associate it with another thread, which would cause our bind of it in our dtor to be a bad operation. 1.535 + savedCurrentContext.InitFromCurrent(); 1.536 + if(ourContext.GetIncarnation() == 0) // If not yet initialized... 1.537 + ourContext.CreateShared(savedCurrentContext); 1.538 + ourContext.Bind(); 1.539 + #if defined(OVR_OS_MAC) // To consider: merge the following into the Bind function. 1.540 + ourContext.SetSurface(savedCurrentContext); 1.541 + #endif 1.542 + } 1.543 + 1.544 + ~AutoContext() 1.545 + { 1.546 + savedCurrentContext.Bind(); 1.547 + } 1.548 + 1.549 + OVR_NON_COPYABLE(AutoContext) 1.550 +}; 1.551 + 1.552 + 1.553 +}}} // namespace OVR::CAPI::GL 1.554 + 1.555 + 1.556 +#endif // INC_OVR_CAPI_GL_Util_h