ovr_sdk
diff LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.cpp Wed Jan 14 06:51:16 2015 +0200 1.3 @@ -0,0 +1,1011 @@ 1.4 +/************************************************************************************ 1.5 + 1.6 +Filename : CAPI_GL_DistortionRenderer.h 1.7 +Content : Distortion renderer header for GL 1.8 +Created : November 11, 2013 1.9 +Authors : David Borel, Lee Cooper 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 +#include "CAPI_GL_DistortionRenderer.h" 1.31 + 1.32 +#include "CAPI_GL_DistortionShaders.h" 1.33 + 1.34 +#include "../../OVR_CAPI_GL.h" 1.35 +#include "../../Kernel/OVR_Color.h" 1.36 + 1.37 +#if defined(OVR_OS_LINUX) 1.38 + #include "../../Displays/OVR_Linux_SDKWindow.h" 1.39 +#elif defined(OVR_OS_MAC) 1.40 + #include <CoreGraphics/CGDirectDisplay.h> 1.41 + #include <OpenGL/OpenGL.h> 1.42 +#endif 1.43 + 1.44 +namespace OVR { namespace CAPI { namespace GL { 1.45 + 1.46 + 1.47 +// Distortion pixel shader lookup. 1.48 +// Bit 0: Chroma Correction 1.49 +// Bit 1: Timewarp 1.50 + 1.51 +enum { 1.52 + DistortionVertexShaderBitMask = 3, 1.53 + DistortionVertexShaderCount = DistortionVertexShaderBitMask + 1, 1.54 + DistortionPixelShaderBitMask = 1, 1.55 + DistortionPixelShaderCount = DistortionPixelShaderBitMask + 1 1.56 +}; 1.57 + 1.58 +struct ShaderInfo 1.59 +{ 1.60 + const char* ShaderData; 1.61 + size_t ShaderSize; 1.62 + const ShaderBase::Uniform* ReflectionData; 1.63 + size_t ReflectionSize; 1.64 +}; 1.65 + 1.66 +// Do add a new distortion shader use these macros (with or w/o reflection) 1.67 +#define SI_NOREFL(shader) { shader, sizeof(shader), NULL, 0 } 1.68 +#define SI_REFL__(shader) { shader, sizeof(shader), shader ## _refl, sizeof( shader ## _refl )/sizeof(*(shader ## _refl)) } 1.69 + 1.70 + 1.71 +static ShaderInfo DistortionVertexShaderLookup[DistortionVertexShaderCount] = 1.72 +{ 1.73 + SI_REFL__(Distortion_vs), 1.74 + SI_REFL__(DistortionChroma_vs), 1.75 + SI_REFL__(DistortionTimewarp_vs), 1.76 + SI_REFL__(DistortionTimewarpChroma_vs) 1.77 +}; 1.78 + 1.79 +static ShaderInfo DistortionPixelShaderLookup[DistortionPixelShaderCount] = 1.80 +{ 1.81 + SI_NOREFL(Distortion_fs), 1.82 + SI_NOREFL(DistortionChroma_fs) 1.83 +}; 1.84 + 1.85 +void DistortionShaderBitIndexCheck() 1.86 +{ 1.87 + OVR_COMPILER_ASSERT(ovrDistortionCap_Chromatic == 1); 1.88 + OVR_COMPILER_ASSERT(ovrDistortionCap_TimeWarp == 2); 1.89 +} 1.90 + 1.91 + 1.92 + 1.93 +struct DistortionVertex 1.94 +{ 1.95 + Vector2f ScreenPosNDC; 1.96 + Vector2f TanEyeAnglesR; 1.97 + Vector2f TanEyeAnglesG; 1.98 + Vector2f TanEyeAnglesB; 1.99 + Color Col; 1.100 +}; 1.101 + 1.102 + 1.103 +// Vertex type; same format is used for all shapes for simplicity. 1.104 +// Shapes are built by adding vertices to Model. 1.105 +struct LatencyVertex 1.106 +{ 1.107 + Vector3f Pos; 1.108 + LatencyVertex (const Vector3f& p) : Pos(p) {} 1.109 +}; 1.110 + 1.111 + 1.112 +//---------------------------------------------------------------------------- 1.113 +// ***** GL::DistortionRenderer 1.114 + 1.115 +DistortionRenderer::DistortionRenderer(ovrHmd hmd, FrameTimeManager& timeManager, 1.116 + const HMDRenderState& renderState) 1.117 + : CAPI::DistortionRenderer(ovrRenderAPI_OpenGL, hmd, timeManager, renderState) 1.118 + , RotateCCW90(false) 1.119 + , LatencyVAO(0) 1.120 + , OverdriveFbo(0) 1.121 +{ 1.122 + DistortionMeshVAOs[0] = 0; 1.123 + DistortionMeshVAOs[1] = 0; 1.124 + 1.125 + // Initialize render params. 1.126 + memset(&RParams, 0, sizeof(RParams)); 1.127 +} 1.128 + 1.129 +DistortionRenderer::~DistortionRenderer() 1.130 +{ 1.131 + destroy(); 1.132 +} 1.133 + 1.134 +// static 1.135 +CAPI::DistortionRenderer* DistortionRenderer::Create(ovrHmd hmd, 1.136 + FrameTimeManager& timeManager, 1.137 + const HMDRenderState& renderState) 1.138 +{ 1.139 + InitGLExtensions(); 1.140 + 1.141 + return new DistortionRenderer(hmd, timeManager, renderState); 1.142 +} 1.143 + 1.144 + 1.145 +bool DistortionRenderer::Initialize(const ovrRenderAPIConfig* apiConfig) 1.146 +{ 1.147 + const ovrGLConfig* config = (const ovrGLConfig*)apiConfig; 1.148 + 1.149 + if (!config) 1.150 + { 1.151 + // Cleanup 1.152 + pEyeTextures[0].Clear(); 1.153 + pEyeTextures[1].Clear(); 1.154 + memset(&RParams, 0, sizeof(RParams)); 1.155 + return true; 1.156 + } 1.157 + 1.158 + RParams.Multisample = config->OGL.Header.Multisample; 1.159 + RParams.BackBufferSize = config->OGL.Header.BackBufferSize; 1.160 +#if defined(OVR_OS_WIN32) 1.161 + RParams.Window = (config->OGL.Window) ? config->OGL.Window : GetActiveWindow(); 1.162 + RParams.DC = config->OGL.DC; 1.163 +#elif defined(OVR_OS_LINUX) 1.164 + RotateCCW90 = false; 1.165 + if ( RState.DistortionCaps & ovrDistortionCap_LinuxDevFullscreen 1.166 + && SDKWindow::getRotation(HMD) == DistRotateCCW90) 1.167 + { 1.168 + RotateCCW90 = true; 1.169 + } 1.170 + if (config->OGL.Disp) 1.171 + { 1.172 + RParams.Disp = config->OGL.Disp; 1.173 + } 1.174 + if (!RParams.Disp) 1.175 + { 1.176 + RParams.Disp = glXGetCurrentDisplay(); 1.177 + } 1.178 + if (!RParams.Disp) 1.179 + { 1.180 + OVR_DEBUG_LOG(("glXGetCurrentDisplay failed.")); 1.181 + return false; 1.182 + } 1.183 +#endif 1.184 + 1.185 + DistortionMeshVAOs[0] = 0; 1.186 + DistortionMeshVAOs[1] = 0; 1.187 + 1.188 + LatencyVAO = 0; 1.189 + 1.190 + GL::AutoContext autoGLContext(distortionContext); // Initializes distortionContext if not already, saves the current GL context, binds distortionContext, then at the end of scope re-binds the current GL context. 1.191 + 1.192 + pEyeTextures[0] = *new Texture(&RParams, 0, 0); 1.193 + pEyeTextures[1] = *new Texture(&RParams, 0, 0); 1.194 + 1.195 + initBuffersAndShaders(); 1.196 + 1.197 + initOverdrive(); 1.198 + 1.199 + return true; 1.200 +} 1.201 + 1.202 + 1.203 +void DistortionRenderer::initOverdrive() 1.204 +{ 1.205 + if(RState.DistortionCaps & ovrDistortionCap_Overdrive) 1.206 + { 1.207 + LastUsedOverdriveTextureIndex = 0; 1.208 + 1.209 + glGenFramebuffers(1, &OverdriveFbo); 1.210 + 1.211 + GLint internalFormat = (RState.DistortionCaps & ovrDistortionCap_SRGB) ? GL_SRGB_ALPHA : GL_RGBA; 1.212 + 1.213 + for (int i = 0; i < NumOverdriveTextures ; i++) 1.214 + { 1.215 + pOverdriveTextures[i] = *new Texture(&RParams, RParams.BackBufferSize.w, RParams.BackBufferSize.h); 1.216 + 1.217 + glBindTexture(GL_TEXTURE_2D, pOverdriveTextures[i]->TexId); 1.218 + glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, RParams.BackBufferSize.w, RParams.BackBufferSize.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 1.219 + OVR_ASSERT( glGetError() == GL_NO_ERROR ); 1.220 + 1.221 + pOverdriveTextures[i]->SetSampleMode(Sample_ClampBorder | Sample_Linear); 1.222 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); 1.223 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); 1.224 + OVR_ASSERT(glGetError() == 0); 1.225 + 1.226 + // clear the new buffer 1.227 + glBindFramebuffer(GL_FRAMEBUFFER, OverdriveFbo ); 1.228 + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pOverdriveTextures[i]->TexId, 0); 1.229 + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); 1.230 + OVR_ASSERT(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); 1.231 + GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0}; 1.232 + glDrawBuffers(OVR_ARRAY_COUNT(drawBuffers), drawBuffers); 1.233 + glClearColor(0,0,0,1); 1.234 + glClear(GL_COLOR_BUFFER_BIT); 1.235 + } 1.236 + 1.237 + { 1.238 + OverdriveBackBufferTexture = *new Texture(&RParams, RParams.BackBufferSize.w, RParams.BackBufferSize.h); 1.239 + 1.240 + glBindTexture(GL_TEXTURE_2D, OverdriveBackBufferTexture->TexId); 1.241 + glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, RParams.BackBufferSize.w, RParams.BackBufferSize.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 1.242 + OVR_ASSERT(glGetError() == 0); 1.243 + 1.244 + OverdriveBackBufferTexture->SetSampleMode(Sample_ClampBorder | Sample_Linear); 1.245 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); 1.246 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); 1.247 + OVR_ASSERT(glGetError() == 0); 1.248 + 1.249 + // clear the new buffer 1.250 + glBindFramebuffer(GL_FRAMEBUFFER, OverdriveFbo ); 1.251 + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, OverdriveBackBufferTexture->TexId, 0); 1.252 + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); 1.253 + OVR_ASSERT(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); 1.254 + GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0}; 1.255 + glDrawBuffers(OVR_ARRAY_COUNT(drawBuffers), drawBuffers); 1.256 + glClearColor(0,0,0,1); 1.257 + glClear(GL_COLOR_BUFFER_BIT); 1.258 + } 1.259 + 1.260 + glBindFramebuffer(GL_FRAMEBUFFER, 0); 1.261 + } 1.262 + else 1.263 + { 1.264 + LastUsedOverdriveTextureIndex = -1; 1.265 + } 1.266 +} 1.267 + 1.268 +void DistortionRenderer::SubmitEye(int eyeId, const ovrTexture* eyeTexture) 1.269 +{ 1.270 + // Doesn't do a lot in here?? 1.271 + const ovrGLTexture* tex = (const ovrGLTexture*)eyeTexture; 1.272 + 1.273 + if (tex) 1.274 + { 1.275 + // Write in values 1.276 + eachEye[eyeId].texture = tex->OGL.TexId; 1.277 + 1.278 + // Its only at this point we discover what the viewport of the texture is. 1.279 + // because presumably we allow users to realtime adjust the resolution. 1.280 + eachEye[eyeId].TextureSize = tex->OGL.Header.TextureSize; 1.281 + eachEye[eyeId].RenderViewport = tex->OGL.Header.RenderViewport; 1.282 + 1.283 + const ovrEyeRenderDesc& erd = RState.EyeRenderDesc[eyeId]; 1.284 + 1.285 + ovrHmd_GetRenderScaleAndOffset( erd.Fov, 1.286 + eachEye[eyeId].TextureSize, eachEye[eyeId].RenderViewport, 1.287 + eachEye[eyeId].UVScaleOffset ); 1.288 + 1.289 + if (!(RState.DistortionCaps & ovrDistortionCap_FlipInput)) 1.290 + { 1.291 + eachEye[eyeId].UVScaleOffset[0].y = -eachEye[eyeId].UVScaleOffset[0].y; 1.292 + eachEye[eyeId].UVScaleOffset[1].y = 1.0f - eachEye[eyeId].UVScaleOffset[1].y; 1.293 + } 1.294 + 1.295 + pEyeTextures[eyeId]->UpdatePlaceholderTexture(tex->OGL.TexId, 1.296 + tex->OGL.Header.TextureSize); 1.297 + } 1.298 +} 1.299 + 1.300 +void DistortionRenderer::renderEndFrame() 1.301 +{ 1.302 + renderDistortion(pEyeTextures[0], pEyeTextures[1]); 1.303 + 1.304 + // TODO: Add rendering context to callback. 1.305 + if(RegisteredPostDistortionCallback) 1.306 + RegisteredPostDistortionCallback(NULL); 1.307 + 1.308 + if(LatencyTest2Active) 1.309 + { 1.310 + renderLatencyPixel(LatencyTest2DrawColor); 1.311 + } 1.312 +} 1.313 + 1.314 +void DistortionRenderer::EndFrame(bool swapBuffers) 1.315 +{ 1.316 + Context currContext; 1.317 + currContext.InitFromCurrent(); 1.318 +#if defined(OVR_OS_MAC) 1.319 + distortionContext.SetSurface( currContext ); 1.320 +#endif 1.321 + 1.322 + // Don't spin if we are explicitly asked not to 1.323 + if ((RState.DistortionCaps & ovrDistortionCap_TimeWarp) && 1.324 + !(RState.DistortionCaps & ovrDistortionCap_ProfileNoTimewarpSpinWaits)) 1.325 + { 1.326 + if (!TimeManager.NeedDistortionTimeMeasurement()) 1.327 + { 1.328 + // Wait for timewarp distortion if it is time and Gpu idle 1.329 + FlushGpuAndWaitTillTime(TimeManager.GetFrameTiming().TimewarpPointTime); 1.330 + 1.331 + distortionContext.Bind(); 1.332 + renderEndFrame(); 1.333 + } 1.334 + else 1.335 + { 1.336 + // If needed, measure distortion time so that TimeManager can better estimate 1.337 + // latency-reducing time-warp wait timing. 1.338 + WaitUntilGpuIdle(); 1.339 + double distortionStartTime = ovr_GetTimeInSeconds(); 1.340 + 1.341 + distortionContext.Bind(); 1.342 + renderEndFrame(); 1.343 + 1.344 + WaitUntilGpuIdle(); 1.345 + TimeManager.AddDistortionTimeMeasurement(ovr_GetTimeInSeconds() - distortionStartTime); 1.346 + } 1.347 + } 1.348 + else 1.349 + { 1.350 + distortionContext.Bind(); 1.351 + renderEndFrame(); 1.352 + } 1.353 + 1.354 + if(LatencyTestActive) 1.355 + { 1.356 + renderLatencyQuad(LatencyTestDrawColor); 1.357 + } 1.358 + 1.359 + if (swapBuffers) 1.360 + { 1.361 + bool useVsync = ((RState.EnabledHmdCaps & ovrHmdCap_NoVSync) == 0); 1.362 + int ourSwapInterval = (useVsync) ? 1 : 0; 1.363 + int originalSwapInterval; 1.364 + 1.365 +#if defined(OVR_OS_WIN32) 1.366 + originalSwapInterval = wglGetSwapIntervalEXT(); 1.367 + 1.368 + if (ourSwapInterval != originalSwapInterval) 1.369 + wglSwapIntervalEXT(ourSwapInterval); 1.370 + 1.371 + HDC dc = (RParams.DC != NULL) ? RParams.DC : GetDC(RParams.Window); 1.372 + BOOL success = SwapBuffers(dc); 1.373 + OVR_ASSERT_AND_UNUSED(success, success); 1.374 + 1.375 + if (RParams.DC == NULL) 1.376 + ReleaseDC(RParams.Window, dc); 1.377 + 1.378 +#elif defined(OVR_OS_MAC) 1.379 + originalSwapInterval = 0; 1.380 + CGLContextObj context = CGLGetCurrentContext(); 1.381 + CGLError err = CGLGetParameter(context, kCGLCPSwapInterval, &originalSwapInterval); 1.382 + OVR_ASSERT_AND_UNUSED(err == kCGLNoError, err); 1.383 + 1.384 + if (ourSwapInterval != originalSwapInterval) 1.385 + CGLSetParameter(context, kCGLCPSwapInterval, &ourSwapInterval); 1.386 + 1.387 + CGLFlushDrawable(context); 1.388 + 1.389 +#elif defined(OVR_OS_LINUX) 1.390 + originalSwapInterval = 0; 1.391 + GLXDrawable drawable = glXGetCurrentDrawable(); 1.392 + struct _XDisplay* x11Display = RParams.Disp; 1.393 + 1.394 + if(GLE_GLX_EXT_swap_control) 1.395 + { 1.396 + static_assert(sizeof(GLuint) == sizeof(originalSwapInterval), "size mismatch"); 1.397 + glXQueryDrawable(x11Display, drawable, GLX_SWAP_INTERVAL_EXT, (GLuint*)&originalSwapInterval); 1.398 + 1.399 + if (ourSwapInterval != originalSwapInterval) 1.400 + glXSwapIntervalEXT(x11Display, drawable, ourSwapInterval); 1.401 + } 1.402 + else if (GLE_MESA_swap_control) // There is also GLX_SGI_swap_control 1.403 + { 1.404 + originalSwapInterval = glXGetSwapIntervalMESA(); 1.405 + 1.406 + if (ourSwapInterval != originalSwapInterval) 1.407 + glXSwapIntervalMESA(ourSwapInterval); 1.408 + } 1.409 + 1.410 + glXSwapBuffers(x11Display, drawable); 1.411 +#endif 1.412 + 1.413 + // Force GPU to flush the scene, resulting in the lowest possible latency. 1.414 + // It's critical that this flush is *after* present, because it results in the wait 1.415 + // below completing after the vsync. 1.416 + // With the display driver (direct mode) this flush is obsolete and theoretically 1.417 + // should be a no-op and so doesn't need to be done if running in direct mode. 1.418 + if (RState.OurHMDInfo.InCompatibilityMode && 1.419 + !(RState.DistortionCaps & ovrDistortionCap_ProfileNoTimewarpSpinWaits)) 1.420 + WaitUntilGpuIdle(); 1.421 + 1.422 + // Restore the original swap interval if we changed it above. 1.423 + if (originalSwapInterval != ourSwapInterval) 1.424 + { 1.425 +#if defined(OVR_OS_WIN32) 1.426 + wglSwapIntervalEXT(originalSwapInterval); 1.427 +#elif defined(OVR_OS_MAC) 1.428 + CGLSetParameter(context, kCGLCPSwapInterval, &originalSwapInterval); 1.429 +#elif defined(OVR_OS_LINUX) 1.430 + if(GLE_GLX_EXT_swap_control) 1.431 + glXSwapIntervalEXT(x11Display, drawable, (GLuint)originalSwapInterval); 1.432 + else if(GLE_MESA_swap_control) 1.433 + glXSwapIntervalMESA(originalSwapInterval); 1.434 +#endif 1.435 + } 1.436 + } 1.437 + 1.438 + currContext.Bind(); 1.439 +} 1.440 + 1.441 +void DistortionRenderer::WaitUntilGpuIdle() 1.442 +{ 1.443 + glFinish(); // Block until current OpenGL commands (including swap) are complete. 1.444 +} 1.445 + 1.446 +double DistortionRenderer::FlushGpuAndWaitTillTime(double absTime) 1.447 +{ 1.448 + // because glFlush() is not strict enough certain GL drivers 1.449 + // we do a glFinish(), but before doing so, we make sure we're not 1.450 + // running late 1.451 + double initialTime = ovr_GetTimeInSeconds(); 1.452 + if (initialTime >= absTime) 1.453 + return 0.0; 1.454 + 1.455 + glFinish(); 1.456 + 1.457 + return WaitTillTime(absTime); 1.458 +} 1.459 + 1.460 +void DistortionRenderer::initBuffersAndShaders() 1.461 +{ 1.462 + for ( int eyeNum = 0; eyeNum < 2; eyeNum++ ) 1.463 + { 1.464 + // Allocate & generate distortion mesh vertices. 1.465 + ovrDistortionMesh meshData; 1.466 + 1.467 + if (!ovrHmd_CreateDistortionMesh( HMD, 1.468 + RState.EyeRenderDesc[eyeNum].Eye, 1.469 + RState.EyeRenderDesc[eyeNum].Fov, 1.470 + RState.DistortionCaps, 1.471 + &meshData) ) 1.472 + { 1.473 + OVR_ASSERT(false); 1.474 + continue; 1.475 + } 1.476 + 1.477 + // Now parse the vertex data and create a render ready vertex buffer from it 1.478 + DistortionVertex * pVBVerts = (DistortionVertex*)OVR_ALLOC ( sizeof(DistortionVertex) * meshData.VertexCount ); 1.479 + DistortionVertex * pCurVBVert = pVBVerts; 1.480 + ovrDistortionVertex* pCurOvrVert = meshData.pVertexData; 1.481 + 1.482 + for ( unsigned vertNum = 0; vertNum < meshData.VertexCount; vertNum++ ) 1.483 + { 1.484 + pCurVBVert->ScreenPosNDC.x = pCurOvrVert->ScreenPosNDC.x; 1.485 + pCurVBVert->ScreenPosNDC.y = pCurOvrVert->ScreenPosNDC.y; 1.486 + 1.487 + if (RotateCCW90) 1.488 + { 1.489 + OVR::Alg::Swap(pCurVBVert->ScreenPosNDC.x, pCurVBVert->ScreenPosNDC.y); 1.490 + pCurVBVert->ScreenPosNDC.x = -pCurVBVert->ScreenPosNDC.x; 1.491 + } 1.492 + 1.493 + // Previous code here did this: pCurVBVert->TanEyeAnglesR = (*(Vector2f*)&pCurOvrVert->TanEyeAnglesR); However that's an usafe 1.494 + // cast of unrelated types which can result in undefined behavior by a conforming compiler. A safe equivalent is simply memcpy. 1.495 + static_assert(sizeof(OVR::Vector2f) == sizeof(ovrVector2f), "Mismatch of structs that are presumed binary equivalents."); 1.496 + memcpy(&pCurVBVert->TanEyeAnglesR, &pCurOvrVert->TanEyeAnglesR, sizeof(pCurVBVert->TanEyeAnglesR)); 1.497 + memcpy(&pCurVBVert->TanEyeAnglesG, &pCurOvrVert->TanEyeAnglesG, sizeof(pCurVBVert->TanEyeAnglesG)); 1.498 + memcpy(&pCurVBVert->TanEyeAnglesB, &pCurOvrVert->TanEyeAnglesB, sizeof(pCurVBVert->TanEyeAnglesB)); 1.499 + 1.500 + // Convert [0.0f,1.0f] to [0,255] 1.501 + if (RState.DistortionCaps & ovrDistortionCap_Vignette) 1.502 + { 1.503 + if(RState.DistortionCaps & ovrDistortionCap_SRGB) 1.504 + pCurOvrVert->VignetteFactor = pow(pCurOvrVert->VignetteFactor, 2.1f); 1.505 + 1.506 + pCurVBVert->Col.R = (uint8_t)( Alg::Max ( pCurOvrVert->VignetteFactor, 0.0f ) * 255.99f ); 1.507 + } 1.508 + else 1.509 + pCurVBVert->Col.R = 255; 1.510 + 1.511 + pCurVBVert->Col.G = pCurVBVert->Col.R; 1.512 + pCurVBVert->Col.B = pCurVBVert->Col.R; 1.513 + pCurVBVert->Col.A = (uint8_t)( pCurOvrVert->TimeWarpFactor * 255.99f );; 1.514 + pCurOvrVert++; 1.515 + pCurVBVert++; 1.516 + } 1.517 + 1.518 + DistortionMeshVBs[eyeNum] = *new Buffer(&RParams); 1.519 + DistortionMeshVBs[eyeNum]->Data ( Buffer_Vertex | Buffer_ReadOnly, pVBVerts, sizeof(DistortionVertex) * meshData.VertexCount ); 1.520 + DistortionMeshIBs[eyeNum] = *new Buffer(&RParams); 1.521 + DistortionMeshIBs[eyeNum]->Data ( Buffer_Index | Buffer_ReadOnly, meshData.pIndexData, ( sizeof(int16_t) * meshData.IndexCount ) ); 1.522 + 1.523 + OVR_FREE ( pVBVerts ); 1.524 + ovrHmd_DestroyDistortionMesh( &meshData ); 1.525 + } 1.526 + 1.527 + initShaders(); 1.528 +} 1.529 + 1.530 +void DistortionRenderer::renderDistortion(Texture* leftEyeTexture, Texture* rightEyeTexture) 1.531 +{ 1.532 + bool overdriveActive = IsOverdriveActive(); 1.533 + int currOverdriveTextureIndex = -1; 1.534 + 1.535 + if(overdriveActive) 1.536 + { 1.537 + currOverdriveTextureIndex = (LastUsedOverdriveTextureIndex + 1) % NumOverdriveTextures; 1.538 + 1.539 + //glBindFramebuffer(GL_FRAMEBUFFER, 0); 1.540 + glBindFramebuffer(GL_FRAMEBUFFER, OverdriveFbo ); 1.541 + 1.542 + GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}; 1.543 + glDrawBuffers(OVR_ARRAY_COUNT(drawBuffers), drawBuffers); 1.544 + 1.545 + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pOverdriveTextures[currOverdriveTextureIndex]->TexId, 0); 1.546 + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, OverdriveBackBufferTexture->TexId, 0); 1.547 + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); 1.548 + OVR_ASSERT(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); 1.549 + } 1.550 + else 1.551 + { 1.552 + glBindFramebuffer(GL_FRAMEBUFFER, 0); 1.553 + } 1.554 + 1.555 + setViewport( Recti(0,0, RParams.BackBufferSize.w, RParams.BackBufferSize.h) ); 1.556 + 1.557 + if (RState.DistortionCaps & ovrDistortionCap_SRGB) 1.558 + glEnable(GL_FRAMEBUFFER_SRGB); 1.559 + else 1.560 + glDisable(GL_FRAMEBUFFER_SRGB); 1.561 + 1.562 + glDisable(GL_CULL_FACE); 1.563 + glDisable(GL_DEPTH_TEST); 1.564 + 1.565 + if (GLE_EXT_draw_buffers2) 1.566 + { 1.567 + glDisablei(GL_BLEND, 0); 1.568 + glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); 1.569 + } 1.570 + else 1.571 + { 1.572 + glDisable(GL_BLEND); 1.573 + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); 1.574 + } 1.575 + 1.576 + glDisable(GL_DITHER); 1.577 + glDisable(GL_RASTERIZER_DISCARD); 1.578 + if (GLEContext::GetCurrentContext()->WholeVersion >= 302) 1.579 + { 1.580 + glDisable(GL_SAMPLE_MASK); 1.581 + } 1.582 + 1.583 + glClearColor( 1.584 + RState.ClearColor[0], 1.585 + RState.ClearColor[1], 1.586 + RState.ClearColor[2], 1.587 + RState.ClearColor[3] ); 1.588 + 1.589 + glClear(GL_COLOR_BUFFER_BIT); 1.590 + 1.591 + for (int eyeNum = 0; eyeNum < 2; eyeNum++) 1.592 + { 1.593 + ShaderFill distortionShaderFill(DistortionShader); 1.594 + distortionShaderFill.SetTexture(0, eyeNum == 0 ? leftEyeTexture : rightEyeTexture); 1.595 + 1.596 + if(overdriveActive) 1.597 + { 1.598 + distortionShaderFill.SetTexture(1, pOverdriveTextures[LastUsedOverdriveTextureIndex]); 1.599 + 1.600 + float overdriveScaleRegularRise; 1.601 + float overdriveScaleRegularFall; 1.602 + GetOverdriveScales(overdriveScaleRegularRise, overdriveScaleRegularFall); 1.603 + DistortionShader->SetUniform3f("OverdriveScales_IsSrgb", overdriveScaleRegularRise, overdriveScaleRegularFall, 1.604 + (RState.DistortionCaps & ovrDistortionCap_SRGB) ? 1.0f : -1.0f); 1.605 + } 1.606 + else 1.607 + { 1.608 + // -1.0f disables PLO 1.609 + DistortionShader->SetUniform3f("OverdriveScales_IsSrgb", -1.0f, -1.0f, -1.0f); 1.610 + } 1.611 + 1.612 + DistortionShader->SetUniform2f("EyeToSourceUVScale", eachEye[eyeNum].UVScaleOffset[0].x, eachEye[eyeNum].UVScaleOffset[0].y); 1.613 + // Convert Y to 1-Y as OpenGL is inverse of D3D 1.614 + DistortionShader->SetUniform2f("EyeToSourceUVOffset", eachEye[eyeNum].UVScaleOffset[1].x, 1.0f - eachEye[eyeNum].UVScaleOffset[1].y); 1.615 + 1.616 + if (RState.DistortionCaps & ovrDistortionCap_TimeWarp) 1.617 + { 1.618 + ovrMatrix4f timeWarpMatrices[2]; 1.619 + ovrHmd_GetEyeTimewarpMatrices(HMD, (ovrEyeType)eyeNum, 1.620 + RState.EyeRenderPoses[eyeNum], timeWarpMatrices); 1.621 + 1.622 + // Feed identity like matrices in until we get proper timewarp calculation going on 1.623 + DistortionShader->SetUniform4x4f("EyeRotationStart", Matrix4f(timeWarpMatrices[0]).Transposed()); 1.624 + DistortionShader->SetUniform4x4f("EyeRotationEnd", Matrix4f(timeWarpMatrices[1]).Transposed()); 1.625 + 1.626 + renderPrimitives(&distortionShaderFill, DistortionMeshVBs[eyeNum], DistortionMeshIBs[eyeNum], 1.627 + 0, (int)DistortionMeshIBs[eyeNum]->GetSize()/2, Prim_Triangles, &DistortionMeshVAOs[eyeNum], true); 1.628 + } 1.629 + else 1.630 + { 1.631 + renderPrimitives(&distortionShaderFill, DistortionMeshVBs[eyeNum], DistortionMeshIBs[eyeNum], 1.632 + 0, (int)DistortionMeshIBs[eyeNum]->GetSize()/2, Prim_Triangles, &DistortionMeshVAOs[eyeNum], true); 1.633 + } 1.634 + } 1.635 + 1.636 + LastUsedOverdriveTextureIndex = currOverdriveTextureIndex; 1.637 + 1.638 + // Re-activate to only draw on back buffer 1.639 + if(overdriveActive) 1.640 + { 1.641 + GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0}; 1.642 + glDrawBuffers(OVR_ARRAY_COUNT(drawBuffers), drawBuffers); 1.643 + 1.644 + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); 1.645 + //glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); 1.646 + //glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, 0, 0); 1.647 + OVR_ASSERT(glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); 1.648 + 1.649 + glBindFramebuffer( GL_READ_FRAMEBUFFER, OverdriveFbo ); 1.650 + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, OverdriveBackBufferTexture->TexId, 0); 1.651 + glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); 1.652 + OVR_ASSERT(glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); 1.653 + 1.654 + glBlitFramebuffer( 0, 0, OverdriveBackBufferTexture->GetWidth(), OverdriveBackBufferTexture->GetHeight(), 1.655 + 0, 0, OverdriveBackBufferTexture->GetWidth(), OverdriveBackBufferTexture->GetHeight(), 1.656 + GL_COLOR_BUFFER_BIT, GL_NEAREST ); 1.657 + 1.658 + glBindFramebuffer( GL_FRAMEBUFFER, 0 ); 1.659 + GLint err = glGetError(); 1.660 + OVR_ASSERT(!err); OVR_UNUSED(err); 1.661 + } 1.662 +} 1.663 + 1.664 + 1.665 +void DistortionRenderer::createDrawQuad() 1.666 +{ 1.667 + const int numQuadVerts = 4; 1.668 + LatencyTesterQuadVB = *new Buffer(&RParams); 1.669 + if(!LatencyTesterQuadVB) 1.670 + { 1.671 + return; 1.672 + } 1.673 + 1.674 + LatencyTesterQuadVB->Data(Buffer_Vertex, NULL, numQuadVerts * sizeof(LatencyVertex)); 1.675 + LatencyVertex* vertices = (LatencyVertex*)LatencyTesterQuadVB->Map(0, numQuadVerts * sizeof(LatencyVertex), Map_Discard); 1.676 + if(!vertices) 1.677 + { 1.678 + OVR_ASSERT(false); // failed to lock vertex buffer 1.679 + return; 1.680 + } 1.681 + 1.682 + const float left = -1.0f; 1.683 + const float top = -1.0f; 1.684 + const float right = 1.0f; 1.685 + const float bottom = 1.0f; 1.686 + 1.687 + vertices[0] = LatencyVertex(Vector3f(left, top, 0.0f)); 1.688 + vertices[1] = LatencyVertex(Vector3f(left, bottom, 0.0f)); 1.689 + vertices[2] = LatencyVertex(Vector3f(right, top, 0.0f)); 1.690 + vertices[3] = LatencyVertex(Vector3f(right, bottom, 0.0f)); 1.691 + 1.692 + LatencyTesterQuadVB->Unmap(vertices); 1.693 +} 1.694 + 1.695 +void DistortionRenderer::renderLatencyQuad(unsigned char* latencyTesterDrawColor) 1.696 +{ 1.697 + const int numQuadVerts = 4; 1.698 + 1.699 + if(!LatencyTesterQuadVB) 1.700 + { 1.701 + createDrawQuad(); 1.702 + } 1.703 + 1.704 + Ptr<ShaderSet> quadShader = (RState.DistortionCaps & ovrDistortionCap_SRGB) ? SimpleQuadGammaShader : SimpleQuadShader; 1.705 + ShaderFill quadFill(quadShader); 1.706 + //quadFill.SetInputLayout(SimpleQuadVertexIL); 1.707 + 1.708 + setViewport(Recti(0,0, RParams.BackBufferSize.w, RParams.BackBufferSize.h)); 1.709 + 1.710 + quadShader->SetUniform2f("Scale", 0.3f, 0.3f); 1.711 + quadShader->SetUniform4f("Color", (float)latencyTesterDrawColor[0] / 255.99f, 1.712 + (float)latencyTesterDrawColor[0] / 255.99f, 1.713 + (float)latencyTesterDrawColor[0] / 255.99f, 1.714 + 1.0f); 1.715 + 1.716 + for(int eyeNum = 0; eyeNum < 2; eyeNum++) 1.717 + { 1.718 + quadShader->SetUniform2f("PositionOffset", eyeNum == 0 ? -0.5f : 0.5f, 0.0f); 1.719 + renderPrimitives(&quadFill, LatencyTesterQuadVB, NULL, 0, numQuadVerts, Prim_TriangleStrip, &LatencyVAO, false); 1.720 + } 1.721 +} 1.722 + 1.723 +void DistortionRenderer::renderLatencyPixel(unsigned char* latencyTesterPixelColor) 1.724 +{ 1.725 + const int numQuadVerts = 4; 1.726 + 1.727 + if(!LatencyTesterQuadVB) 1.728 + { 1.729 + createDrawQuad(); 1.730 + } 1.731 + 1.732 + Ptr<ShaderSet> quadShader = (RState.DistortionCaps & ovrDistortionCap_SRGB) ? SimpleQuadGammaShader : SimpleQuadShader; 1.733 + ShaderFill quadFill(quadShader); 1.734 + 1.735 + setViewport(Recti(0,0, RParams.BackBufferSize.w, RParams.BackBufferSize.h)); 1.736 + 1.737 +#ifdef OVR_BUILD_DEBUG 1.738 + quadShader->SetUniform4f("Color", (float)latencyTesterPixelColor[0] / 255.99f, 1.739 + (float)latencyTesterPixelColor[1] / 255.99f, 1.740 + (float)latencyTesterPixelColor[2] / 255.99f, 1.741 + 1.0f); 1.742 + 1.743 + Vector2f scale(20.0f / RParams.BackBufferSize.w, 20.0f / RParams.BackBufferSize.h); 1.744 +#else 1.745 + quadShader->SetUniform4f("Color", (float)latencyTesterPixelColor[0] / 255.99f, 1.746 + (float)latencyTesterPixelColor[0] / 255.99f, 1.747 + (float)latencyTesterPixelColor[0] / 255.99f, 1.748 + 1.0f); 1.749 + 1.750 + Vector2f scale(1.0f / RParams.BackBufferSize.w, 1.0f / RParams.BackBufferSize.h); 1.751 +#endif 1.752 + quadShader->SetUniform2f("Scale", scale.x, scale.y); 1.753 + if (!RotateCCW90) 1.754 + quadShader->SetUniform2f("PositionOffset", 1.0f-scale.x, 1.0f-scale.y); 1.755 + else 1.756 + quadShader->SetUniform2f("PositionOffset", -(1.0f-scale.x), 1.0f-scale.y); 1.757 + renderPrimitives(&quadFill, LatencyTesterQuadVB, NULL, 0, numQuadVerts, Prim_TriangleStrip, &LatencyVAO, false); 1.758 +} 1.759 + 1.760 +void DistortionRenderer::renderPrimitives( 1.761 + const ShaderFill* fill, 1.762 + Buffer* vertices, Buffer* indices, 1.763 + int offset, int count, 1.764 + PrimitiveType rprim, GLuint* vao, bool isDistortionMesh) 1.765 +{ 1.766 + GLenum prim; 1.767 + switch (rprim) 1.768 + { 1.769 + case Prim_Triangles: 1.770 + prim = GL_TRIANGLES; 1.771 + break; 1.772 + case Prim_Lines: 1.773 + prim = GL_LINES; 1.774 + break; 1.775 + case Prim_TriangleStrip: 1.776 + prim = GL_TRIANGLE_STRIP; 1.777 + break; 1.778 + default: 1.779 + OVR_ASSERT(false); 1.780 + return; 1.781 + } 1.782 + 1.783 + fill->Set(); 1.784 + 1.785 + GLuint prog = fill->GetShaders()->Prog; 1.786 + 1.787 + if (vao != NULL) 1.788 + { 1.789 + if (*vao != 0) 1.790 + { 1.791 + glBindVertexArray(*vao); 1.792 + 1.793 + if (isDistortionMesh) 1.794 + glDrawElements(prim, count, GL_UNSIGNED_SHORT, NULL); 1.795 + else 1.796 + glDrawArrays(prim, 0, count); 1.797 + 1.798 + glBindVertexArray(0); 1.799 + } 1.800 + else 1.801 + { 1.802 + if (GL_ARB_vertex_array_object) 1.803 + { 1.804 + glGenVertexArrays(1, vao); 1.805 + glBindVertexArray(*vao); 1.806 + } 1.807 + 1.808 + int attributeCount = (isDistortionMesh) ? 5 : 1; 1.809 + int* locs = new int[attributeCount]; 1.810 + 1.811 + glBindBuffer(GL_ARRAY_BUFFER, ((Buffer*)vertices)->GLBuffer); 1.812 + 1.813 + if (isDistortionMesh) 1.814 + { 1.815 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ((Buffer*)indices)->GLBuffer); 1.816 + 1.817 + locs[0] = glGetAttribLocation(prog, "Position"); 1.818 + locs[1] = glGetAttribLocation(prog, "Color"); 1.819 + locs[2] = glGetAttribLocation(prog, "TexCoord0"); 1.820 + locs[3] = glGetAttribLocation(prog, "TexCoord1"); 1.821 + locs[4] = glGetAttribLocation(prog, "TexCoord2"); 1.822 + 1.823 + glVertexAttribPointer(locs[0], 2, GL_FLOAT, false, sizeof(DistortionVertex), reinterpret_cast<char*>(offset)+offsetof(DistortionVertex, ScreenPosNDC)); 1.824 + glVertexAttribPointer(locs[1], 4, GL_UNSIGNED_BYTE, true, sizeof(DistortionVertex), reinterpret_cast<char*>(offset)+offsetof(DistortionVertex, Col)); 1.825 + glVertexAttribPointer(locs[2], 2, GL_FLOAT, false, sizeof(DistortionVertex), reinterpret_cast<char*>(offset)+offsetof(DistortionVertex, TanEyeAnglesR)); 1.826 + glVertexAttribPointer(locs[3], 2, GL_FLOAT, false, sizeof(DistortionVertex), reinterpret_cast<char*>(offset)+offsetof(DistortionVertex, TanEyeAnglesG)); 1.827 + glVertexAttribPointer(locs[4], 2, GL_FLOAT, false, sizeof(DistortionVertex), reinterpret_cast<char*>(offset)+offsetof(DistortionVertex, TanEyeAnglesB)); 1.828 + } 1.829 + else 1.830 + { 1.831 + locs[0] = glGetAttribLocation(prog, "Position"); 1.832 + 1.833 + glVertexAttribPointer(locs[0], 3, GL_FLOAT, false, sizeof(LatencyVertex), reinterpret_cast<char*>(offset)+offsetof(LatencyVertex, Pos)); 1.834 + } 1.835 + 1.836 + for (int i = 0; i < attributeCount; ++i) 1.837 + glEnableVertexAttribArray(locs[i]); 1.838 + 1.839 + if (isDistortionMesh) 1.840 + glDrawElements(prim, count, GL_UNSIGNED_SHORT, NULL); 1.841 + else 1.842 + glDrawArrays(prim, 0, count); 1.843 + 1.844 + 1.845 + if (!GL_ARB_vertex_array_object) 1.846 + { 1.847 + for (int i = 0; i < attributeCount; ++i) 1.848 + glDisableVertexAttribArray(locs[i]); 1.849 + } 1.850 + 1.851 + delete[] locs; 1.852 + 1.853 + if (GL_ARB_vertex_array_object) 1.854 + { 1.855 + glBindVertexArray(0); 1.856 + } 1.857 + } 1.858 + } 1.859 +} 1.860 + 1.861 +void DistortionRenderer::setViewport(const Recti& vp) 1.862 +{ 1.863 + glViewport(vp.x, vp.y, vp.w, vp.h); 1.864 +} 1.865 + 1.866 + 1.867 +void DistortionRenderer::initShaders() 1.868 +{ 1.869 + const char* shaderPrefix = (GLEContext::GetCurrentContext()->WholeVersion >= 302) ? glsl3Prefix : glsl2Prefix; 1.870 + 1.871 + { 1.872 + ShaderInfo vsInfo = DistortionVertexShaderLookup[DistortionVertexShaderBitMask & RState.DistortionCaps]; 1.873 + 1.874 + size_t vsSize = strlen(shaderPrefix)+vsInfo.ShaderSize; 1.875 + char* vsSource = new char[vsSize]; 1.876 + OVR_strcpy(vsSource, vsSize, shaderPrefix); 1.877 + OVR_strcat(vsSource, vsSize, vsInfo.ShaderData); 1.878 + 1.879 + Ptr<GL::VertexShader> vs = *new GL::VertexShader( 1.880 + &RParams, 1.881 + (void*)vsSource, vsSize, 1.882 + vsInfo.ReflectionData, vsInfo.ReflectionSize); 1.883 + 1.884 + DistortionShader = *new ShaderSet; 1.885 + DistortionShader->SetShader(vs); 1.886 + 1.887 + delete[](vsSource); 1.888 + 1.889 + ShaderInfo psInfo = DistortionPixelShaderLookup[DistortionPixelShaderBitMask & RState.DistortionCaps]; 1.890 + 1.891 + size_t psSize = strlen(shaderPrefix)+psInfo.ShaderSize; 1.892 + char* psSource = new char[psSize]; 1.893 + OVR_strcpy(psSource, psSize, shaderPrefix); 1.894 + OVR_strcat(psSource, psSize, psInfo.ShaderData); 1.895 + 1.896 + Ptr<GL::FragmentShader> ps = *new GL::FragmentShader( 1.897 + &RParams, 1.898 + (void*)psSource, psSize, 1.899 + psInfo.ReflectionData, psInfo.ReflectionSize); 1.900 + 1.901 + DistortionShader->SetShader(ps); 1.902 + 1.903 + delete[](psSource); 1.904 + } 1.905 + { 1.906 + size_t vsSize = strlen(shaderPrefix)+sizeof(SimpleQuad_vs); 1.907 + char* vsSource = new char[vsSize]; 1.908 + OVR_strcpy(vsSource, vsSize, shaderPrefix); 1.909 + OVR_strcat(vsSource, vsSize, SimpleQuad_vs); 1.910 + 1.911 + Ptr<GL::VertexShader> vs = *new GL::VertexShader( 1.912 + &RParams, 1.913 + (void*)vsSource, vsSize, 1.914 + SimpleQuad_vs_refl, sizeof(SimpleQuad_vs_refl) / sizeof(SimpleQuad_vs_refl[0])); 1.915 + 1.916 + SimpleQuadShader = *new ShaderSet; 1.917 + SimpleQuadShader->SetShader(vs); 1.918 + 1.919 + delete[](vsSource); 1.920 + 1.921 + size_t psSize = strlen(shaderPrefix)+sizeof(SimpleQuad_fs); 1.922 + char* psSource = new char[psSize]; 1.923 + OVR_strcpy(psSource, psSize, shaderPrefix); 1.924 + OVR_strcat(psSource, psSize, SimpleQuad_fs); 1.925 + 1.926 + Ptr<GL::FragmentShader> ps = *new GL::FragmentShader( 1.927 + &RParams, 1.928 + (void*)psSource, psSize, 1.929 + SimpleQuad_fs_refl, sizeof(SimpleQuad_fs_refl) / sizeof(SimpleQuad_fs_refl[0])); 1.930 + 1.931 + SimpleQuadShader->SetShader(ps); 1.932 + 1.933 + delete[](psSource); 1.934 + } 1.935 + { 1.936 + size_t vsSize = strlen(shaderPrefix)+sizeof(SimpleQuad_vs); 1.937 + char* vsSource = new char[vsSize]; 1.938 + OVR_strcpy(vsSource, vsSize, shaderPrefix); 1.939 + OVR_strcat(vsSource, vsSize, SimpleQuad_vs); 1.940 + 1.941 + Ptr<GL::VertexShader> vs = *new GL::VertexShader( 1.942 + &RParams, 1.943 + (void*)vsSource, vsSize, 1.944 + SimpleQuad_vs_refl, sizeof(SimpleQuad_vs_refl) / sizeof(SimpleQuad_vs_refl[0])); 1.945 + 1.946 + SimpleQuadGammaShader = *new ShaderSet; 1.947 + SimpleQuadGammaShader->SetShader(vs); 1.948 + 1.949 + delete[](vsSource); 1.950 + 1.951 + size_t psSize = strlen(shaderPrefix)+sizeof(SimpleQuadGamma_fs); 1.952 + char* psSource = new char[psSize]; 1.953 + OVR_strcpy(psSource, psSize, shaderPrefix); 1.954 + OVR_strcat(psSource, psSize, SimpleQuadGamma_fs); 1.955 + 1.956 + Ptr<GL::FragmentShader> ps = *new GL::FragmentShader( 1.957 + &RParams, 1.958 + (void*)psSource, psSize, 1.959 + SimpleQuadGamma_fs_refl, sizeof(SimpleQuadGamma_fs_refl) / sizeof(SimpleQuadGamma_fs_refl[0])); 1.960 + 1.961 + SimpleQuadGammaShader->SetShader(ps); 1.962 + 1.963 + delete[](psSource); 1.964 + } 1.965 +} 1.966 + 1.967 + 1.968 +void DistortionRenderer::destroy() 1.969 +{ 1.970 + Context currContext; 1.971 + currContext.InitFromCurrent(); 1.972 + 1.973 + distortionContext.Bind(); 1.974 + 1.975 + for(int eyeNum = 0; eyeNum < 2; eyeNum++) 1.976 + { 1.977 + if (GL_ARB_vertex_array_object) 1.978 + { 1.979 + glDeleteVertexArrays(1, &DistortionMeshVAOs[eyeNum]); 1.980 + } 1.981 + 1.982 + DistortionMeshVAOs[eyeNum] = 0; 1.983 + 1.984 + DistortionMeshVBs[eyeNum].Clear(); 1.985 + DistortionMeshIBs[eyeNum].Clear(); 1.986 + } 1.987 + 1.988 + if (DistortionShader) 1.989 + { 1.990 + DistortionShader->UnsetShader(Shader_Vertex); 1.991 + DistortionShader->UnsetShader(Shader_Pixel); 1.992 + DistortionShader.Clear(); 1.993 + } 1.994 + 1.995 + LatencyTesterQuadVB.Clear(); 1.996 + 1.997 + if(LatencyVAO != 0) 1.998 + { 1.999 + glDeleteVertexArrays(1, &LatencyVAO); 1.1000 + LatencyVAO = 0; 1.1001 + } 1.1002 + 1.1003 + if(OverdriveFbo != 0) 1.1004 + { 1.1005 + glDeleteFramebuffers(1, &OverdriveFbo); 1.1006 + } 1.1007 + 1.1008 + currContext.Bind(); 1.1009 + distortionContext.Destroy(); 1.1010 + // Who is responsible for destroying the app's context? 1.1011 +} 1.1012 + 1.1013 + 1.1014 +}}} // OVR::CAPI::GL