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