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