ovr_sdk

annotate 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
rev   line source
nuclear@0 1 /************************************************************************************
nuclear@0 2
nuclear@0 3 Filename : CAPI_GL_DistortionRenderer.h
nuclear@0 4 Content : Distortion renderer header for GL
nuclear@0 5 Created : November 11, 2013
nuclear@0 6 Authors : David Borel, Lee Cooper
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_DistortionRenderer.h"
nuclear@0 28
nuclear@0 29 #include "CAPI_GL_DistortionShaders.h"
nuclear@0 30
nuclear@0 31 #include "../../OVR_CAPI_GL.h"
nuclear@0 32 #include "../../Kernel/OVR_Color.h"
nuclear@0 33
nuclear@0 34 #if defined(OVR_OS_LINUX)
nuclear@0 35 #include "../../Displays/OVR_Linux_SDKWindow.h"
nuclear@0 36 #elif defined(OVR_OS_MAC)
nuclear@0 37 #include <CoreGraphics/CGDirectDisplay.h>
nuclear@0 38 #include <OpenGL/OpenGL.h>
nuclear@0 39 #endif
nuclear@0 40
nuclear@0 41 namespace OVR { namespace CAPI { namespace GL {
nuclear@0 42
nuclear@0 43
nuclear@0 44 // Distortion pixel shader lookup.
nuclear@0 45 // Bit 0: Chroma Correction
nuclear@0 46 // Bit 1: Timewarp
nuclear@0 47
nuclear@0 48 enum {
nuclear@0 49 DistortionVertexShaderBitMask = 3,
nuclear@0 50 DistortionVertexShaderCount = DistortionVertexShaderBitMask + 1,
nuclear@0 51 DistortionPixelShaderBitMask = 1,
nuclear@0 52 DistortionPixelShaderCount = DistortionPixelShaderBitMask + 1
nuclear@0 53 };
nuclear@0 54
nuclear@0 55 struct ShaderInfo
nuclear@0 56 {
nuclear@0 57 const char* ShaderData;
nuclear@0 58 size_t ShaderSize;
nuclear@0 59 const ShaderBase::Uniform* ReflectionData;
nuclear@0 60 size_t ReflectionSize;
nuclear@0 61 };
nuclear@0 62
nuclear@0 63 // Do add a new distortion shader use these macros (with or w/o reflection)
nuclear@0 64 #define SI_NOREFL(shader) { shader, sizeof(shader), NULL, 0 }
nuclear@0 65 #define SI_REFL__(shader) { shader, sizeof(shader), shader ## _refl, sizeof( shader ## _refl )/sizeof(*(shader ## _refl)) }
nuclear@0 66
nuclear@0 67
nuclear@0 68 static ShaderInfo DistortionVertexShaderLookup[DistortionVertexShaderCount] =
nuclear@0 69 {
nuclear@0 70 SI_REFL__(Distortion_vs),
nuclear@0 71 SI_REFL__(DistortionChroma_vs),
nuclear@0 72 SI_REFL__(DistortionTimewarp_vs),
nuclear@0 73 SI_REFL__(DistortionTimewarpChroma_vs)
nuclear@0 74 };
nuclear@0 75
nuclear@0 76 static ShaderInfo DistortionPixelShaderLookup[DistortionPixelShaderCount] =
nuclear@0 77 {
nuclear@0 78 SI_NOREFL(Distortion_fs),
nuclear@0 79 SI_NOREFL(DistortionChroma_fs)
nuclear@0 80 };
nuclear@0 81
nuclear@0 82 void DistortionShaderBitIndexCheck()
nuclear@0 83 {
nuclear@0 84 OVR_COMPILER_ASSERT(ovrDistortionCap_Chromatic == 1);
nuclear@0 85 OVR_COMPILER_ASSERT(ovrDistortionCap_TimeWarp == 2);
nuclear@0 86 }
nuclear@0 87
nuclear@0 88
nuclear@0 89
nuclear@0 90 struct DistortionVertex
nuclear@0 91 {
nuclear@0 92 Vector2f ScreenPosNDC;
nuclear@0 93 Vector2f TanEyeAnglesR;
nuclear@0 94 Vector2f TanEyeAnglesG;
nuclear@0 95 Vector2f TanEyeAnglesB;
nuclear@0 96 Color Col;
nuclear@0 97 };
nuclear@0 98
nuclear@0 99
nuclear@0 100 // Vertex type; same format is used for all shapes for simplicity.
nuclear@0 101 // Shapes are built by adding vertices to Model.
nuclear@0 102 struct LatencyVertex
nuclear@0 103 {
nuclear@0 104 Vector3f Pos;
nuclear@0 105 LatencyVertex (const Vector3f& p) : Pos(p) {}
nuclear@0 106 };
nuclear@0 107
nuclear@0 108
nuclear@0 109 //----------------------------------------------------------------------------
nuclear@0 110 // ***** GL::DistortionRenderer
nuclear@0 111
nuclear@0 112 DistortionRenderer::DistortionRenderer(ovrHmd hmd, FrameTimeManager& timeManager,
nuclear@0 113 const HMDRenderState& renderState)
nuclear@0 114 : CAPI::DistortionRenderer(ovrRenderAPI_OpenGL, hmd, timeManager, renderState)
nuclear@0 115 , RotateCCW90(false)
nuclear@0 116 , LatencyVAO(0)
nuclear@0 117 , OverdriveFbo(0)
nuclear@0 118 {
nuclear@0 119 DistortionMeshVAOs[0] = 0;
nuclear@0 120 DistortionMeshVAOs[1] = 0;
nuclear@0 121
nuclear@0 122 // Initialize render params.
nuclear@0 123 memset(&RParams, 0, sizeof(RParams));
nuclear@0 124 }
nuclear@0 125
nuclear@0 126 DistortionRenderer::~DistortionRenderer()
nuclear@0 127 {
nuclear@0 128 destroy();
nuclear@0 129 }
nuclear@0 130
nuclear@0 131 // static
nuclear@0 132 CAPI::DistortionRenderer* DistortionRenderer::Create(ovrHmd hmd,
nuclear@0 133 FrameTimeManager& timeManager,
nuclear@0 134 const HMDRenderState& renderState)
nuclear@0 135 {
nuclear@0 136 InitGLExtensions();
nuclear@0 137
nuclear@0 138 return new DistortionRenderer(hmd, timeManager, renderState);
nuclear@0 139 }
nuclear@0 140
nuclear@0 141
nuclear@0 142 bool DistortionRenderer::Initialize(const ovrRenderAPIConfig* apiConfig)
nuclear@0 143 {
nuclear@0 144 const ovrGLConfig* config = (const ovrGLConfig*)apiConfig;
nuclear@0 145
nuclear@0 146 if (!config)
nuclear@0 147 {
nuclear@0 148 // Cleanup
nuclear@0 149 pEyeTextures[0].Clear();
nuclear@0 150 pEyeTextures[1].Clear();
nuclear@0 151 memset(&RParams, 0, sizeof(RParams));
nuclear@0 152 return true;
nuclear@0 153 }
nuclear@0 154
nuclear@0 155 RParams.Multisample = config->OGL.Header.Multisample;
nuclear@0 156 RParams.BackBufferSize = config->OGL.Header.BackBufferSize;
nuclear@0 157 #if defined(OVR_OS_WIN32)
nuclear@0 158 RParams.Window = (config->OGL.Window) ? config->OGL.Window : GetActiveWindow();
nuclear@0 159 RParams.DC = config->OGL.DC;
nuclear@0 160 #elif defined(OVR_OS_LINUX)
nuclear@0 161 RotateCCW90 = false;
nuclear@0 162 if ( RState.DistortionCaps & ovrDistortionCap_LinuxDevFullscreen
nuclear@0 163 && SDKWindow::getRotation(HMD) == DistRotateCCW90)
nuclear@0 164 {
nuclear@0 165 RotateCCW90 = true;
nuclear@0 166 }
nuclear@0 167 if (config->OGL.Disp)
nuclear@0 168 {
nuclear@0 169 RParams.Disp = config->OGL.Disp;
nuclear@0 170 }
nuclear@0 171 if (!RParams.Disp)
nuclear@0 172 {
nuclear@0 173 RParams.Disp = glXGetCurrentDisplay();
nuclear@0 174 }
nuclear@0 175 if (!RParams.Disp)
nuclear@0 176 {
nuclear@0 177 OVR_DEBUG_LOG(("glXGetCurrentDisplay failed."));
nuclear@0 178 return false;
nuclear@0 179 }
nuclear@0 180 #endif
nuclear@0 181
nuclear@0 182 DistortionMeshVAOs[0] = 0;
nuclear@0 183 DistortionMeshVAOs[1] = 0;
nuclear@0 184
nuclear@0 185 LatencyVAO = 0;
nuclear@0 186
nuclear@0 187 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.
nuclear@0 188
nuclear@0 189 pEyeTextures[0] = *new Texture(&RParams, 0, 0);
nuclear@0 190 pEyeTextures[1] = *new Texture(&RParams, 0, 0);
nuclear@0 191
nuclear@0 192 initBuffersAndShaders();
nuclear@0 193
nuclear@0 194 initOverdrive();
nuclear@0 195
nuclear@0 196 return true;
nuclear@0 197 }
nuclear@0 198
nuclear@0 199
nuclear@0 200 void DistortionRenderer::initOverdrive()
nuclear@0 201 {
nuclear@0 202 if(RState.DistortionCaps & ovrDistortionCap_Overdrive)
nuclear@0 203 {
nuclear@0 204 LastUsedOverdriveTextureIndex = 0;
nuclear@0 205
nuclear@0 206 glGenFramebuffers(1, &OverdriveFbo);
nuclear@0 207
nuclear@0 208 GLint internalFormat = (RState.DistortionCaps & ovrDistortionCap_SRGB) ? GL_SRGB_ALPHA : GL_RGBA;
nuclear@0 209
nuclear@0 210 for (int i = 0; i < NumOverdriveTextures ; i++)
nuclear@0 211 {
nuclear@0 212 pOverdriveTextures[i] = *new Texture(&RParams, RParams.BackBufferSize.w, RParams.BackBufferSize.h);
nuclear@0 213
nuclear@0 214 glBindTexture(GL_TEXTURE_2D, pOverdriveTextures[i]->TexId);
nuclear@0 215 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, RParams.BackBufferSize.w, RParams.BackBufferSize.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
nuclear@0 216 OVR_ASSERT( glGetError() == GL_NO_ERROR );
nuclear@0 217
nuclear@0 218 pOverdriveTextures[i]->SetSampleMode(Sample_ClampBorder | Sample_Linear);
nuclear@0 219 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
nuclear@0 220 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
nuclear@0 221 OVR_ASSERT(glGetError() == 0);
nuclear@0 222
nuclear@0 223 // clear the new buffer
nuclear@0 224 glBindFramebuffer(GL_FRAMEBUFFER, OverdriveFbo );
nuclear@0 225 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pOverdriveTextures[i]->TexId, 0);
nuclear@0 226 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
nuclear@0 227 OVR_ASSERT(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
nuclear@0 228 GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0};
nuclear@0 229 glDrawBuffers(OVR_ARRAY_COUNT(drawBuffers), drawBuffers);
nuclear@0 230 glClearColor(0,0,0,1);
nuclear@0 231 glClear(GL_COLOR_BUFFER_BIT);
nuclear@0 232 }
nuclear@0 233
nuclear@0 234 {
nuclear@0 235 OverdriveBackBufferTexture = *new Texture(&RParams, RParams.BackBufferSize.w, RParams.BackBufferSize.h);
nuclear@0 236
nuclear@0 237 glBindTexture(GL_TEXTURE_2D, OverdriveBackBufferTexture->TexId);
nuclear@0 238 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, RParams.BackBufferSize.w, RParams.BackBufferSize.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
nuclear@0 239 OVR_ASSERT(glGetError() == 0);
nuclear@0 240
nuclear@0 241 OverdriveBackBufferTexture->SetSampleMode(Sample_ClampBorder | Sample_Linear);
nuclear@0 242 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
nuclear@0 243 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
nuclear@0 244 OVR_ASSERT(glGetError() == 0);
nuclear@0 245
nuclear@0 246 // clear the new buffer
nuclear@0 247 glBindFramebuffer(GL_FRAMEBUFFER, OverdriveFbo );
nuclear@0 248 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, OverdriveBackBufferTexture->TexId, 0);
nuclear@0 249 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
nuclear@0 250 OVR_ASSERT(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
nuclear@0 251 GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0};
nuclear@0 252 glDrawBuffers(OVR_ARRAY_COUNT(drawBuffers), drawBuffers);
nuclear@0 253 glClearColor(0,0,0,1);
nuclear@0 254 glClear(GL_COLOR_BUFFER_BIT);
nuclear@0 255 }
nuclear@0 256
nuclear@0 257 glBindFramebuffer(GL_FRAMEBUFFER, 0);
nuclear@0 258 }
nuclear@0 259 else
nuclear@0 260 {
nuclear@0 261 LastUsedOverdriveTextureIndex = -1;
nuclear@0 262 }
nuclear@0 263 }
nuclear@0 264
nuclear@0 265 void DistortionRenderer::SubmitEye(int eyeId, const ovrTexture* eyeTexture)
nuclear@0 266 {
nuclear@0 267 // Doesn't do a lot in here??
nuclear@0 268 const ovrGLTexture* tex = (const ovrGLTexture*)eyeTexture;
nuclear@0 269
nuclear@0 270 if (tex)
nuclear@0 271 {
nuclear@0 272 // Write in values
nuclear@0 273 eachEye[eyeId].texture = tex->OGL.TexId;
nuclear@0 274
nuclear@0 275 // Its only at this point we discover what the viewport of the texture is.
nuclear@0 276 // because presumably we allow users to realtime adjust the resolution.
nuclear@0 277 eachEye[eyeId].TextureSize = tex->OGL.Header.TextureSize;
nuclear@0 278 eachEye[eyeId].RenderViewport = tex->OGL.Header.RenderViewport;
nuclear@0 279
nuclear@0 280 const ovrEyeRenderDesc& erd = RState.EyeRenderDesc[eyeId];
nuclear@0 281
nuclear@0 282 ovrHmd_GetRenderScaleAndOffset( erd.Fov,
nuclear@0 283 eachEye[eyeId].TextureSize, eachEye[eyeId].RenderViewport,
nuclear@0 284 eachEye[eyeId].UVScaleOffset );
nuclear@0 285
nuclear@0 286 if (!(RState.DistortionCaps & ovrDistortionCap_FlipInput))
nuclear@0 287 {
nuclear@0 288 eachEye[eyeId].UVScaleOffset[0].y = -eachEye[eyeId].UVScaleOffset[0].y;
nuclear@0 289 eachEye[eyeId].UVScaleOffset[1].y = 1.0f - eachEye[eyeId].UVScaleOffset[1].y;
nuclear@0 290 }
nuclear@0 291
nuclear@0 292 pEyeTextures[eyeId]->UpdatePlaceholderTexture(tex->OGL.TexId,
nuclear@0 293 tex->OGL.Header.TextureSize);
nuclear@0 294 }
nuclear@0 295 }
nuclear@0 296
nuclear@0 297 void DistortionRenderer::renderEndFrame()
nuclear@0 298 {
nuclear@0 299 renderDistortion(pEyeTextures[0], pEyeTextures[1]);
nuclear@0 300
nuclear@0 301 // TODO: Add rendering context to callback.
nuclear@0 302 if(RegisteredPostDistortionCallback)
nuclear@0 303 RegisteredPostDistortionCallback(NULL);
nuclear@0 304
nuclear@0 305 if(LatencyTest2Active)
nuclear@0 306 {
nuclear@0 307 renderLatencyPixel(LatencyTest2DrawColor);
nuclear@0 308 }
nuclear@0 309 }
nuclear@0 310
nuclear@0 311 void DistortionRenderer::EndFrame(bool swapBuffers)
nuclear@0 312 {
nuclear@0 313 Context currContext;
nuclear@0 314 currContext.InitFromCurrent();
nuclear@0 315 #if defined(OVR_OS_MAC)
nuclear@0 316 distortionContext.SetSurface( currContext );
nuclear@0 317 #endif
nuclear@0 318
nuclear@0 319 // Don't spin if we are explicitly asked not to
nuclear@0 320 if ((RState.DistortionCaps & ovrDistortionCap_TimeWarp) &&
nuclear@0 321 !(RState.DistortionCaps & ovrDistortionCap_ProfileNoTimewarpSpinWaits))
nuclear@0 322 {
nuclear@0 323 if (!TimeManager.NeedDistortionTimeMeasurement())
nuclear@0 324 {
nuclear@0 325 // Wait for timewarp distortion if it is time and Gpu idle
nuclear@0 326 FlushGpuAndWaitTillTime(TimeManager.GetFrameTiming().TimewarpPointTime);
nuclear@0 327
nuclear@0 328 distortionContext.Bind();
nuclear@0 329 renderEndFrame();
nuclear@0 330 }
nuclear@0 331 else
nuclear@0 332 {
nuclear@0 333 // If needed, measure distortion time so that TimeManager can better estimate
nuclear@0 334 // latency-reducing time-warp wait timing.
nuclear@0 335 WaitUntilGpuIdle();
nuclear@0 336 double distortionStartTime = ovr_GetTimeInSeconds();
nuclear@0 337
nuclear@0 338 distortionContext.Bind();
nuclear@0 339 renderEndFrame();
nuclear@0 340
nuclear@0 341 WaitUntilGpuIdle();
nuclear@0 342 TimeManager.AddDistortionTimeMeasurement(ovr_GetTimeInSeconds() - distortionStartTime);
nuclear@0 343 }
nuclear@0 344 }
nuclear@0 345 else
nuclear@0 346 {
nuclear@0 347 distortionContext.Bind();
nuclear@0 348 renderEndFrame();
nuclear@0 349 }
nuclear@0 350
nuclear@0 351 if(LatencyTestActive)
nuclear@0 352 {
nuclear@0 353 renderLatencyQuad(LatencyTestDrawColor);
nuclear@0 354 }
nuclear@0 355
nuclear@0 356 if (swapBuffers)
nuclear@0 357 {
nuclear@0 358 bool useVsync = ((RState.EnabledHmdCaps & ovrHmdCap_NoVSync) == 0);
nuclear@0 359 int ourSwapInterval = (useVsync) ? 1 : 0;
nuclear@0 360 int originalSwapInterval;
nuclear@0 361
nuclear@0 362 #if defined(OVR_OS_WIN32)
nuclear@0 363 originalSwapInterval = wglGetSwapIntervalEXT();
nuclear@0 364
nuclear@0 365 if (ourSwapInterval != originalSwapInterval)
nuclear@0 366 wglSwapIntervalEXT(ourSwapInterval);
nuclear@0 367
nuclear@0 368 HDC dc = (RParams.DC != NULL) ? RParams.DC : GetDC(RParams.Window);
nuclear@0 369 BOOL success = SwapBuffers(dc);
nuclear@0 370 OVR_ASSERT_AND_UNUSED(success, success);
nuclear@0 371
nuclear@0 372 if (RParams.DC == NULL)
nuclear@0 373 ReleaseDC(RParams.Window, dc);
nuclear@0 374
nuclear@0 375 #elif defined(OVR_OS_MAC)
nuclear@0 376 originalSwapInterval = 0;
nuclear@0 377 CGLContextObj context = CGLGetCurrentContext();
nuclear@0 378 CGLError err = CGLGetParameter(context, kCGLCPSwapInterval, &originalSwapInterval);
nuclear@0 379 OVR_ASSERT_AND_UNUSED(err == kCGLNoError, err);
nuclear@0 380
nuclear@0 381 if (ourSwapInterval != originalSwapInterval)
nuclear@0 382 CGLSetParameter(context, kCGLCPSwapInterval, &ourSwapInterval);
nuclear@0 383
nuclear@0 384 CGLFlushDrawable(context);
nuclear@0 385
nuclear@0 386 #elif defined(OVR_OS_LINUX)
nuclear@0 387 originalSwapInterval = 0;
nuclear@0 388 GLXDrawable drawable = glXGetCurrentDrawable();
nuclear@0 389 struct _XDisplay* x11Display = RParams.Disp;
nuclear@0 390
nuclear@0 391 if(GLE_GLX_EXT_swap_control)
nuclear@0 392 {
nuclear@0 393 static_assert(sizeof(GLuint) == sizeof(originalSwapInterval), "size mismatch");
nuclear@0 394 glXQueryDrawable(x11Display, drawable, GLX_SWAP_INTERVAL_EXT, (GLuint*)&originalSwapInterval);
nuclear@0 395
nuclear@0 396 if (ourSwapInterval != originalSwapInterval)
nuclear@0 397 glXSwapIntervalEXT(x11Display, drawable, ourSwapInterval);
nuclear@0 398 }
nuclear@0 399 else if (GLE_MESA_swap_control) // There is also GLX_SGI_swap_control
nuclear@0 400 {
nuclear@0 401 originalSwapInterval = glXGetSwapIntervalMESA();
nuclear@0 402
nuclear@0 403 if (ourSwapInterval != originalSwapInterval)
nuclear@0 404 glXSwapIntervalMESA(ourSwapInterval);
nuclear@0 405 }
nuclear@0 406
nuclear@0 407 glXSwapBuffers(x11Display, drawable);
nuclear@0 408 #endif
nuclear@0 409
nuclear@0 410 // Force GPU to flush the scene, resulting in the lowest possible latency.
nuclear@0 411 // It's critical that this flush is *after* present, because it results in the wait
nuclear@0 412 // below completing after the vsync.
nuclear@0 413 // With the display driver (direct mode) this flush is obsolete and theoretically
nuclear@0 414 // should be a no-op and so doesn't need to be done if running in direct mode.
nuclear@0 415 if (RState.OurHMDInfo.InCompatibilityMode &&
nuclear@0 416 !(RState.DistortionCaps & ovrDistortionCap_ProfileNoTimewarpSpinWaits))
nuclear@0 417 WaitUntilGpuIdle();
nuclear@0 418
nuclear@0 419 // Restore the original swap interval if we changed it above.
nuclear@0 420 if (originalSwapInterval != ourSwapInterval)
nuclear@0 421 {
nuclear@0 422 #if defined(OVR_OS_WIN32)
nuclear@0 423 wglSwapIntervalEXT(originalSwapInterval);
nuclear@0 424 #elif defined(OVR_OS_MAC)
nuclear@0 425 CGLSetParameter(context, kCGLCPSwapInterval, &originalSwapInterval);
nuclear@0 426 #elif defined(OVR_OS_LINUX)
nuclear@0 427 if(GLE_GLX_EXT_swap_control)
nuclear@0 428 glXSwapIntervalEXT(x11Display, drawable, (GLuint)originalSwapInterval);
nuclear@0 429 else if(GLE_MESA_swap_control)
nuclear@0 430 glXSwapIntervalMESA(originalSwapInterval);
nuclear@0 431 #endif
nuclear@0 432 }
nuclear@0 433 }
nuclear@0 434
nuclear@0 435 currContext.Bind();
nuclear@0 436 }
nuclear@0 437
nuclear@0 438 void DistortionRenderer::WaitUntilGpuIdle()
nuclear@0 439 {
nuclear@0 440 glFinish(); // Block until current OpenGL commands (including swap) are complete.
nuclear@0 441 }
nuclear@0 442
nuclear@0 443 double DistortionRenderer::FlushGpuAndWaitTillTime(double absTime)
nuclear@0 444 {
nuclear@0 445 // because glFlush() is not strict enough certain GL drivers
nuclear@0 446 // we do a glFinish(), but before doing so, we make sure we're not
nuclear@0 447 // running late
nuclear@0 448 double initialTime = ovr_GetTimeInSeconds();
nuclear@0 449 if (initialTime >= absTime)
nuclear@0 450 return 0.0;
nuclear@0 451
nuclear@0 452 glFinish();
nuclear@0 453
nuclear@0 454 return WaitTillTime(absTime);
nuclear@0 455 }
nuclear@0 456
nuclear@0 457 void DistortionRenderer::initBuffersAndShaders()
nuclear@0 458 {
nuclear@0 459 for ( int eyeNum = 0; eyeNum < 2; eyeNum++ )
nuclear@0 460 {
nuclear@0 461 // Allocate & generate distortion mesh vertices.
nuclear@0 462 ovrDistortionMesh meshData;
nuclear@0 463
nuclear@0 464 if (!ovrHmd_CreateDistortionMesh( HMD,
nuclear@0 465 RState.EyeRenderDesc[eyeNum].Eye,
nuclear@0 466 RState.EyeRenderDesc[eyeNum].Fov,
nuclear@0 467 RState.DistortionCaps,
nuclear@0 468 &meshData) )
nuclear@0 469 {
nuclear@0 470 OVR_ASSERT(false);
nuclear@0 471 continue;
nuclear@0 472 }
nuclear@0 473
nuclear@0 474 // Now parse the vertex data and create a render ready vertex buffer from it
nuclear@0 475 DistortionVertex * pVBVerts = (DistortionVertex*)OVR_ALLOC ( sizeof(DistortionVertex) * meshData.VertexCount );
nuclear@0 476 DistortionVertex * pCurVBVert = pVBVerts;
nuclear@0 477 ovrDistortionVertex* pCurOvrVert = meshData.pVertexData;
nuclear@0 478
nuclear@0 479 for ( unsigned vertNum = 0; vertNum < meshData.VertexCount; vertNum++ )
nuclear@0 480 {
nuclear@0 481 pCurVBVert->ScreenPosNDC.x = pCurOvrVert->ScreenPosNDC.x;
nuclear@0 482 pCurVBVert->ScreenPosNDC.y = pCurOvrVert->ScreenPosNDC.y;
nuclear@0 483
nuclear@0 484 if (RotateCCW90)
nuclear@0 485 {
nuclear@0 486 OVR::Alg::Swap(pCurVBVert->ScreenPosNDC.x, pCurVBVert->ScreenPosNDC.y);
nuclear@0 487 pCurVBVert->ScreenPosNDC.x = -pCurVBVert->ScreenPosNDC.x;
nuclear@0 488 }
nuclear@0 489
nuclear@0 490 // Previous code here did this: pCurVBVert->TanEyeAnglesR = (*(Vector2f*)&pCurOvrVert->TanEyeAnglesR); However that's an usafe
nuclear@0 491 // cast of unrelated types which can result in undefined behavior by a conforming compiler. A safe equivalent is simply memcpy.
nuclear@0 492 static_assert(sizeof(OVR::Vector2f) == sizeof(ovrVector2f), "Mismatch of structs that are presumed binary equivalents.");
nuclear@0 493 memcpy(&pCurVBVert->TanEyeAnglesR, &pCurOvrVert->TanEyeAnglesR, sizeof(pCurVBVert->TanEyeAnglesR));
nuclear@0 494 memcpy(&pCurVBVert->TanEyeAnglesG, &pCurOvrVert->TanEyeAnglesG, sizeof(pCurVBVert->TanEyeAnglesG));
nuclear@0 495 memcpy(&pCurVBVert->TanEyeAnglesB, &pCurOvrVert->TanEyeAnglesB, sizeof(pCurVBVert->TanEyeAnglesB));
nuclear@0 496
nuclear@0 497 // Convert [0.0f,1.0f] to [0,255]
nuclear@0 498 if (RState.DistortionCaps & ovrDistortionCap_Vignette)
nuclear@0 499 {
nuclear@0 500 if(RState.DistortionCaps & ovrDistortionCap_SRGB)
nuclear@0 501 pCurOvrVert->VignetteFactor = pow(pCurOvrVert->VignetteFactor, 2.1f);
nuclear@0 502
nuclear@0 503 pCurVBVert->Col.R = (uint8_t)( Alg::Max ( pCurOvrVert->VignetteFactor, 0.0f ) * 255.99f );
nuclear@0 504 }
nuclear@0 505 else
nuclear@0 506 pCurVBVert->Col.R = 255;
nuclear@0 507
nuclear@0 508 pCurVBVert->Col.G = pCurVBVert->Col.R;
nuclear@0 509 pCurVBVert->Col.B = pCurVBVert->Col.R;
nuclear@0 510 pCurVBVert->Col.A = (uint8_t)( pCurOvrVert->TimeWarpFactor * 255.99f );;
nuclear@0 511 pCurOvrVert++;
nuclear@0 512 pCurVBVert++;
nuclear@0 513 }
nuclear@0 514
nuclear@0 515 DistortionMeshVBs[eyeNum] = *new Buffer(&RParams);
nuclear@0 516 DistortionMeshVBs[eyeNum]->Data ( Buffer_Vertex | Buffer_ReadOnly, pVBVerts, sizeof(DistortionVertex) * meshData.VertexCount );
nuclear@0 517 DistortionMeshIBs[eyeNum] = *new Buffer(&RParams);
nuclear@0 518 DistortionMeshIBs[eyeNum]->Data ( Buffer_Index | Buffer_ReadOnly, meshData.pIndexData, ( sizeof(int16_t) * meshData.IndexCount ) );
nuclear@0 519
nuclear@0 520 OVR_FREE ( pVBVerts );
nuclear@0 521 ovrHmd_DestroyDistortionMesh( &meshData );
nuclear@0 522 }
nuclear@0 523
nuclear@0 524 initShaders();
nuclear@0 525 }
nuclear@0 526
nuclear@0 527 void DistortionRenderer::renderDistortion(Texture* leftEyeTexture, Texture* rightEyeTexture)
nuclear@0 528 {
nuclear@0 529 bool overdriveActive = IsOverdriveActive();
nuclear@0 530 int currOverdriveTextureIndex = -1;
nuclear@0 531
nuclear@0 532 if(overdriveActive)
nuclear@0 533 {
nuclear@0 534 currOverdriveTextureIndex = (LastUsedOverdriveTextureIndex + 1) % NumOverdriveTextures;
nuclear@0 535
nuclear@0 536 //glBindFramebuffer(GL_FRAMEBUFFER, 0);
nuclear@0 537 glBindFramebuffer(GL_FRAMEBUFFER, OverdriveFbo );
nuclear@0 538
nuclear@0 539 GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
nuclear@0 540 glDrawBuffers(OVR_ARRAY_COUNT(drawBuffers), drawBuffers);
nuclear@0 541
nuclear@0 542 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pOverdriveTextures[currOverdriveTextureIndex]->TexId, 0);
nuclear@0 543 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, OverdriveBackBufferTexture->TexId, 0);
nuclear@0 544 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
nuclear@0 545 OVR_ASSERT(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
nuclear@0 546 }
nuclear@0 547 else
nuclear@0 548 {
nuclear@0 549 glBindFramebuffer(GL_FRAMEBUFFER, 0);
nuclear@0 550 }
nuclear@0 551
nuclear@0 552 setViewport( Recti(0,0, RParams.BackBufferSize.w, RParams.BackBufferSize.h) );
nuclear@0 553
nuclear@0 554 if (RState.DistortionCaps & ovrDistortionCap_SRGB)
nuclear@0 555 glEnable(GL_FRAMEBUFFER_SRGB);
nuclear@0 556 else
nuclear@0 557 glDisable(GL_FRAMEBUFFER_SRGB);
nuclear@0 558
nuclear@0 559 glDisable(GL_CULL_FACE);
nuclear@0 560 glDisable(GL_DEPTH_TEST);
nuclear@0 561
nuclear@0 562 if (GLE_EXT_draw_buffers2)
nuclear@0 563 {
nuclear@0 564 glDisablei(GL_BLEND, 0);
nuclear@0 565 glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
nuclear@0 566 }
nuclear@0 567 else
nuclear@0 568 {
nuclear@0 569 glDisable(GL_BLEND);
nuclear@0 570 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
nuclear@0 571 }
nuclear@0 572
nuclear@0 573 glDisable(GL_DITHER);
nuclear@0 574 glDisable(GL_RASTERIZER_DISCARD);
nuclear@0 575 if (GLEContext::GetCurrentContext()->WholeVersion >= 302)
nuclear@0 576 {
nuclear@0 577 glDisable(GL_SAMPLE_MASK);
nuclear@0 578 }
nuclear@0 579
nuclear@0 580 glClearColor(
nuclear@0 581 RState.ClearColor[0],
nuclear@0 582 RState.ClearColor[1],
nuclear@0 583 RState.ClearColor[2],
nuclear@0 584 RState.ClearColor[3] );
nuclear@0 585
nuclear@0 586 glClear(GL_COLOR_BUFFER_BIT);
nuclear@0 587
nuclear@0 588 for (int eyeNum = 0; eyeNum < 2; eyeNum++)
nuclear@0 589 {
nuclear@0 590 ShaderFill distortionShaderFill(DistortionShader);
nuclear@0 591 distortionShaderFill.SetTexture(0, eyeNum == 0 ? leftEyeTexture : rightEyeTexture);
nuclear@0 592
nuclear@0 593 if(overdriveActive)
nuclear@0 594 {
nuclear@0 595 distortionShaderFill.SetTexture(1, pOverdriveTextures[LastUsedOverdriveTextureIndex]);
nuclear@0 596
nuclear@0 597 float overdriveScaleRegularRise;
nuclear@0 598 float overdriveScaleRegularFall;
nuclear@0 599 GetOverdriveScales(overdriveScaleRegularRise, overdriveScaleRegularFall);
nuclear@0 600 DistortionShader->SetUniform3f("OverdriveScales_IsSrgb", overdriveScaleRegularRise, overdriveScaleRegularFall,
nuclear@0 601 (RState.DistortionCaps & ovrDistortionCap_SRGB) ? 1.0f : -1.0f);
nuclear@0 602 }
nuclear@0 603 else
nuclear@0 604 {
nuclear@0 605 // -1.0f disables PLO
nuclear@0 606 DistortionShader->SetUniform3f("OverdriveScales_IsSrgb", -1.0f, -1.0f, -1.0f);
nuclear@0 607 }
nuclear@0 608
nuclear@0 609 DistortionShader->SetUniform2f("EyeToSourceUVScale", eachEye[eyeNum].UVScaleOffset[0].x, eachEye[eyeNum].UVScaleOffset[0].y);
nuclear@0 610 // Convert Y to 1-Y as OpenGL is inverse of D3D
nuclear@0 611 DistortionShader->SetUniform2f("EyeToSourceUVOffset", eachEye[eyeNum].UVScaleOffset[1].x, 1.0f - eachEye[eyeNum].UVScaleOffset[1].y);
nuclear@0 612
nuclear@0 613 if (RState.DistortionCaps & ovrDistortionCap_TimeWarp)
nuclear@0 614 {
nuclear@0 615 ovrMatrix4f timeWarpMatrices[2];
nuclear@0 616 ovrHmd_GetEyeTimewarpMatrices(HMD, (ovrEyeType)eyeNum,
nuclear@0 617 RState.EyeRenderPoses[eyeNum], timeWarpMatrices);
nuclear@0 618
nuclear@0 619 // Feed identity like matrices in until we get proper timewarp calculation going on
nuclear@0 620 DistortionShader->SetUniform4x4f("EyeRotationStart", Matrix4f(timeWarpMatrices[0]).Transposed());
nuclear@0 621 DistortionShader->SetUniform4x4f("EyeRotationEnd", Matrix4f(timeWarpMatrices[1]).Transposed());
nuclear@0 622
nuclear@0 623 renderPrimitives(&distortionShaderFill, DistortionMeshVBs[eyeNum], DistortionMeshIBs[eyeNum],
nuclear@0 624 0, (int)DistortionMeshIBs[eyeNum]->GetSize()/2, Prim_Triangles, &DistortionMeshVAOs[eyeNum], true);
nuclear@0 625 }
nuclear@0 626 else
nuclear@0 627 {
nuclear@0 628 renderPrimitives(&distortionShaderFill, DistortionMeshVBs[eyeNum], DistortionMeshIBs[eyeNum],
nuclear@0 629 0, (int)DistortionMeshIBs[eyeNum]->GetSize()/2, Prim_Triangles, &DistortionMeshVAOs[eyeNum], true);
nuclear@0 630 }
nuclear@0 631 }
nuclear@0 632
nuclear@0 633 LastUsedOverdriveTextureIndex = currOverdriveTextureIndex;
nuclear@0 634
nuclear@0 635 // Re-activate to only draw on back buffer
nuclear@0 636 if(overdriveActive)
nuclear@0 637 {
nuclear@0 638 GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0};
nuclear@0 639 glDrawBuffers(OVR_ARRAY_COUNT(drawBuffers), drawBuffers);
nuclear@0 640
nuclear@0 641 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
nuclear@0 642 //glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
nuclear@0 643 //glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, 0, 0);
nuclear@0 644 OVR_ASSERT(glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
nuclear@0 645
nuclear@0 646 glBindFramebuffer( GL_READ_FRAMEBUFFER, OverdriveFbo );
nuclear@0 647 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, OverdriveBackBufferTexture->TexId, 0);
nuclear@0 648 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
nuclear@0 649 OVR_ASSERT(glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
nuclear@0 650
nuclear@0 651 glBlitFramebuffer( 0, 0, OverdriveBackBufferTexture->GetWidth(), OverdriveBackBufferTexture->GetHeight(),
nuclear@0 652 0, 0, OverdriveBackBufferTexture->GetWidth(), OverdriveBackBufferTexture->GetHeight(),
nuclear@0 653 GL_COLOR_BUFFER_BIT, GL_NEAREST );
nuclear@0 654
nuclear@0 655 glBindFramebuffer( GL_FRAMEBUFFER, 0 );
nuclear@0 656 GLint err = glGetError();
nuclear@0 657 OVR_ASSERT(!err); OVR_UNUSED(err);
nuclear@0 658 }
nuclear@0 659 }
nuclear@0 660
nuclear@0 661
nuclear@0 662 void DistortionRenderer::createDrawQuad()
nuclear@0 663 {
nuclear@0 664 const int numQuadVerts = 4;
nuclear@0 665 LatencyTesterQuadVB = *new Buffer(&RParams);
nuclear@0 666 if(!LatencyTesterQuadVB)
nuclear@0 667 {
nuclear@0 668 return;
nuclear@0 669 }
nuclear@0 670
nuclear@0 671 LatencyTesterQuadVB->Data(Buffer_Vertex, NULL, numQuadVerts * sizeof(LatencyVertex));
nuclear@0 672 LatencyVertex* vertices = (LatencyVertex*)LatencyTesterQuadVB->Map(0, numQuadVerts * sizeof(LatencyVertex), Map_Discard);
nuclear@0 673 if(!vertices)
nuclear@0 674 {
nuclear@0 675 OVR_ASSERT(false); // failed to lock vertex buffer
nuclear@0 676 return;
nuclear@0 677 }
nuclear@0 678
nuclear@0 679 const float left = -1.0f;
nuclear@0 680 const float top = -1.0f;
nuclear@0 681 const float right = 1.0f;
nuclear@0 682 const float bottom = 1.0f;
nuclear@0 683
nuclear@0 684 vertices[0] = LatencyVertex(Vector3f(left, top, 0.0f));
nuclear@0 685 vertices[1] = LatencyVertex(Vector3f(left, bottom, 0.0f));
nuclear@0 686 vertices[2] = LatencyVertex(Vector3f(right, top, 0.0f));
nuclear@0 687 vertices[3] = LatencyVertex(Vector3f(right, bottom, 0.0f));
nuclear@0 688
nuclear@0 689 LatencyTesterQuadVB->Unmap(vertices);
nuclear@0 690 }
nuclear@0 691
nuclear@0 692 void DistortionRenderer::renderLatencyQuad(unsigned char* latencyTesterDrawColor)
nuclear@0 693 {
nuclear@0 694 const int numQuadVerts = 4;
nuclear@0 695
nuclear@0 696 if(!LatencyTesterQuadVB)
nuclear@0 697 {
nuclear@0 698 createDrawQuad();
nuclear@0 699 }
nuclear@0 700
nuclear@0 701 Ptr<ShaderSet> quadShader = (RState.DistortionCaps & ovrDistortionCap_SRGB) ? SimpleQuadGammaShader : SimpleQuadShader;
nuclear@0 702 ShaderFill quadFill(quadShader);
nuclear@0 703 //quadFill.SetInputLayout(SimpleQuadVertexIL);
nuclear@0 704
nuclear@0 705 setViewport(Recti(0,0, RParams.BackBufferSize.w, RParams.BackBufferSize.h));
nuclear@0 706
nuclear@0 707 quadShader->SetUniform2f("Scale", 0.3f, 0.3f);
nuclear@0 708 quadShader->SetUniform4f("Color", (float)latencyTesterDrawColor[0] / 255.99f,
nuclear@0 709 (float)latencyTesterDrawColor[0] / 255.99f,
nuclear@0 710 (float)latencyTesterDrawColor[0] / 255.99f,
nuclear@0 711 1.0f);
nuclear@0 712
nuclear@0 713 for(int eyeNum = 0; eyeNum < 2; eyeNum++)
nuclear@0 714 {
nuclear@0 715 quadShader->SetUniform2f("PositionOffset", eyeNum == 0 ? -0.5f : 0.5f, 0.0f);
nuclear@0 716 renderPrimitives(&quadFill, LatencyTesterQuadVB, NULL, 0, numQuadVerts, Prim_TriangleStrip, &LatencyVAO, false);
nuclear@0 717 }
nuclear@0 718 }
nuclear@0 719
nuclear@0 720 void DistortionRenderer::renderLatencyPixel(unsigned char* latencyTesterPixelColor)
nuclear@0 721 {
nuclear@0 722 const int numQuadVerts = 4;
nuclear@0 723
nuclear@0 724 if(!LatencyTesterQuadVB)
nuclear@0 725 {
nuclear@0 726 createDrawQuad();
nuclear@0 727 }
nuclear@0 728
nuclear@0 729 Ptr<ShaderSet> quadShader = (RState.DistortionCaps & ovrDistortionCap_SRGB) ? SimpleQuadGammaShader : SimpleQuadShader;
nuclear@0 730 ShaderFill quadFill(quadShader);
nuclear@0 731
nuclear@0 732 setViewport(Recti(0,0, RParams.BackBufferSize.w, RParams.BackBufferSize.h));
nuclear@0 733
nuclear@0 734 #ifdef OVR_BUILD_DEBUG
nuclear@0 735 quadShader->SetUniform4f("Color", (float)latencyTesterPixelColor[0] / 255.99f,
nuclear@0 736 (float)latencyTesterPixelColor[1] / 255.99f,
nuclear@0 737 (float)latencyTesterPixelColor[2] / 255.99f,
nuclear@0 738 1.0f);
nuclear@0 739
nuclear@0 740 Vector2f scale(20.0f / RParams.BackBufferSize.w, 20.0f / RParams.BackBufferSize.h);
nuclear@0 741 #else
nuclear@0 742 quadShader->SetUniform4f("Color", (float)latencyTesterPixelColor[0] / 255.99f,
nuclear@0 743 (float)latencyTesterPixelColor[0] / 255.99f,
nuclear@0 744 (float)latencyTesterPixelColor[0] / 255.99f,
nuclear@0 745 1.0f);
nuclear@0 746
nuclear@0 747 Vector2f scale(1.0f / RParams.BackBufferSize.w, 1.0f / RParams.BackBufferSize.h);
nuclear@0 748 #endif
nuclear@0 749 quadShader->SetUniform2f("Scale", scale.x, scale.y);
nuclear@0 750 if (!RotateCCW90)
nuclear@0 751 quadShader->SetUniform2f("PositionOffset", 1.0f-scale.x, 1.0f-scale.y);
nuclear@0 752 else
nuclear@0 753 quadShader->SetUniform2f("PositionOffset", -(1.0f-scale.x), 1.0f-scale.y);
nuclear@0 754 renderPrimitives(&quadFill, LatencyTesterQuadVB, NULL, 0, numQuadVerts, Prim_TriangleStrip, &LatencyVAO, false);
nuclear@0 755 }
nuclear@0 756
nuclear@0 757 void DistortionRenderer::renderPrimitives(
nuclear@0 758 const ShaderFill* fill,
nuclear@0 759 Buffer* vertices, Buffer* indices,
nuclear@0 760 int offset, int count,
nuclear@0 761 PrimitiveType rprim, GLuint* vao, bool isDistortionMesh)
nuclear@0 762 {
nuclear@0 763 GLenum prim;
nuclear@0 764 switch (rprim)
nuclear@0 765 {
nuclear@0 766 case Prim_Triangles:
nuclear@0 767 prim = GL_TRIANGLES;
nuclear@0 768 break;
nuclear@0 769 case Prim_Lines:
nuclear@0 770 prim = GL_LINES;
nuclear@0 771 break;
nuclear@0 772 case Prim_TriangleStrip:
nuclear@0 773 prim = GL_TRIANGLE_STRIP;
nuclear@0 774 break;
nuclear@0 775 default:
nuclear@0 776 OVR_ASSERT(false);
nuclear@0 777 return;
nuclear@0 778 }
nuclear@0 779
nuclear@0 780 fill->Set();
nuclear@0 781
nuclear@0 782 GLuint prog = fill->GetShaders()->Prog;
nuclear@0 783
nuclear@0 784 if (vao != NULL)
nuclear@0 785 {
nuclear@0 786 if (*vao != 0)
nuclear@0 787 {
nuclear@0 788 glBindVertexArray(*vao);
nuclear@0 789
nuclear@0 790 if (isDistortionMesh)
nuclear@0 791 glDrawElements(prim, count, GL_UNSIGNED_SHORT, NULL);
nuclear@0 792 else
nuclear@0 793 glDrawArrays(prim, 0, count);
nuclear@0 794
nuclear@0 795 glBindVertexArray(0);
nuclear@0 796 }
nuclear@0 797 else
nuclear@0 798 {
nuclear@0 799 if (GL_ARB_vertex_array_object)
nuclear@0 800 {
nuclear@0 801 glGenVertexArrays(1, vao);
nuclear@0 802 glBindVertexArray(*vao);
nuclear@0 803 }
nuclear@0 804
nuclear@0 805 int attributeCount = (isDistortionMesh) ? 5 : 1;
nuclear@0 806 int* locs = new int[attributeCount];
nuclear@0 807
nuclear@0 808 glBindBuffer(GL_ARRAY_BUFFER, ((Buffer*)vertices)->GLBuffer);
nuclear@0 809
nuclear@0 810 if (isDistortionMesh)
nuclear@0 811 {
nuclear@0 812 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ((Buffer*)indices)->GLBuffer);
nuclear@0 813
nuclear@0 814 locs[0] = glGetAttribLocation(prog, "Position");
nuclear@0 815 locs[1] = glGetAttribLocation(prog, "Color");
nuclear@0 816 locs[2] = glGetAttribLocation(prog, "TexCoord0");
nuclear@0 817 locs[3] = glGetAttribLocation(prog, "TexCoord1");
nuclear@0 818 locs[4] = glGetAttribLocation(prog, "TexCoord2");
nuclear@0 819
nuclear@0 820 glVertexAttribPointer(locs[0], 2, GL_FLOAT, false, sizeof(DistortionVertex), reinterpret_cast<char*>(offset)+offsetof(DistortionVertex, ScreenPosNDC));
nuclear@0 821 glVertexAttribPointer(locs[1], 4, GL_UNSIGNED_BYTE, true, sizeof(DistortionVertex), reinterpret_cast<char*>(offset)+offsetof(DistortionVertex, Col));
nuclear@0 822 glVertexAttribPointer(locs[2], 2, GL_FLOAT, false, sizeof(DistortionVertex), reinterpret_cast<char*>(offset)+offsetof(DistortionVertex, TanEyeAnglesR));
nuclear@0 823 glVertexAttribPointer(locs[3], 2, GL_FLOAT, false, sizeof(DistortionVertex), reinterpret_cast<char*>(offset)+offsetof(DistortionVertex, TanEyeAnglesG));
nuclear@0 824 glVertexAttribPointer(locs[4], 2, GL_FLOAT, false, sizeof(DistortionVertex), reinterpret_cast<char*>(offset)+offsetof(DistortionVertex, TanEyeAnglesB));
nuclear@0 825 }
nuclear@0 826 else
nuclear@0 827 {
nuclear@0 828 locs[0] = glGetAttribLocation(prog, "Position");
nuclear@0 829
nuclear@0 830 glVertexAttribPointer(locs[0], 3, GL_FLOAT, false, sizeof(LatencyVertex), reinterpret_cast<char*>(offset)+offsetof(LatencyVertex, Pos));
nuclear@0 831 }
nuclear@0 832
nuclear@0 833 for (int i = 0; i < attributeCount; ++i)
nuclear@0 834 glEnableVertexAttribArray(locs[i]);
nuclear@0 835
nuclear@0 836 if (isDistortionMesh)
nuclear@0 837 glDrawElements(prim, count, GL_UNSIGNED_SHORT, NULL);
nuclear@0 838 else
nuclear@0 839 glDrawArrays(prim, 0, count);
nuclear@0 840
nuclear@0 841
nuclear@0 842 if (!GL_ARB_vertex_array_object)
nuclear@0 843 {
nuclear@0 844 for (int i = 0; i < attributeCount; ++i)
nuclear@0 845 glDisableVertexAttribArray(locs[i]);
nuclear@0 846 }
nuclear@0 847
nuclear@0 848 delete[] locs;
nuclear@0 849
nuclear@0 850 if (GL_ARB_vertex_array_object)
nuclear@0 851 {
nuclear@0 852 glBindVertexArray(0);
nuclear@0 853 }
nuclear@0 854 }
nuclear@0 855 }
nuclear@0 856 }
nuclear@0 857
nuclear@0 858 void DistortionRenderer::setViewport(const Recti& vp)
nuclear@0 859 {
nuclear@0 860 glViewport(vp.x, vp.y, vp.w, vp.h);
nuclear@0 861 }
nuclear@0 862
nuclear@0 863
nuclear@0 864 void DistortionRenderer::initShaders()
nuclear@0 865 {
nuclear@0 866 const char* shaderPrefix = (GLEContext::GetCurrentContext()->WholeVersion >= 302) ? glsl3Prefix : glsl2Prefix;
nuclear@0 867
nuclear@0 868 {
nuclear@0 869 ShaderInfo vsInfo = DistortionVertexShaderLookup[DistortionVertexShaderBitMask & RState.DistortionCaps];
nuclear@0 870
nuclear@0 871 size_t vsSize = strlen(shaderPrefix)+vsInfo.ShaderSize;
nuclear@0 872 char* vsSource = new char[vsSize];
nuclear@0 873 OVR_strcpy(vsSource, vsSize, shaderPrefix);
nuclear@0 874 OVR_strcat(vsSource, vsSize, vsInfo.ShaderData);
nuclear@0 875
nuclear@0 876 Ptr<GL::VertexShader> vs = *new GL::VertexShader(
nuclear@0 877 &RParams,
nuclear@0 878 (void*)vsSource, vsSize,
nuclear@0 879 vsInfo.ReflectionData, vsInfo.ReflectionSize);
nuclear@0 880
nuclear@0 881 DistortionShader = *new ShaderSet;
nuclear@0 882 DistortionShader->SetShader(vs);
nuclear@0 883
nuclear@0 884 delete[](vsSource);
nuclear@0 885
nuclear@0 886 ShaderInfo psInfo = DistortionPixelShaderLookup[DistortionPixelShaderBitMask & RState.DistortionCaps];
nuclear@0 887
nuclear@0 888 size_t psSize = strlen(shaderPrefix)+psInfo.ShaderSize;
nuclear@0 889 char* psSource = new char[psSize];
nuclear@0 890 OVR_strcpy(psSource, psSize, shaderPrefix);
nuclear@0 891 OVR_strcat(psSource, psSize, psInfo.ShaderData);
nuclear@0 892
nuclear@0 893 Ptr<GL::FragmentShader> ps = *new GL::FragmentShader(
nuclear@0 894 &RParams,
nuclear@0 895 (void*)psSource, psSize,
nuclear@0 896 psInfo.ReflectionData, psInfo.ReflectionSize);
nuclear@0 897
nuclear@0 898 DistortionShader->SetShader(ps);
nuclear@0 899
nuclear@0 900 delete[](psSource);
nuclear@0 901 }
nuclear@0 902 {
nuclear@0 903 size_t vsSize = strlen(shaderPrefix)+sizeof(SimpleQuad_vs);
nuclear@0 904 char* vsSource = new char[vsSize];
nuclear@0 905 OVR_strcpy(vsSource, vsSize, shaderPrefix);
nuclear@0 906 OVR_strcat(vsSource, vsSize, SimpleQuad_vs);
nuclear@0 907
nuclear@0 908 Ptr<GL::VertexShader> vs = *new GL::VertexShader(
nuclear@0 909 &RParams,
nuclear@0 910 (void*)vsSource, vsSize,
nuclear@0 911 SimpleQuad_vs_refl, sizeof(SimpleQuad_vs_refl) / sizeof(SimpleQuad_vs_refl[0]));
nuclear@0 912
nuclear@0 913 SimpleQuadShader = *new ShaderSet;
nuclear@0 914 SimpleQuadShader->SetShader(vs);
nuclear@0 915
nuclear@0 916 delete[](vsSource);
nuclear@0 917
nuclear@0 918 size_t psSize = strlen(shaderPrefix)+sizeof(SimpleQuad_fs);
nuclear@0 919 char* psSource = new char[psSize];
nuclear@0 920 OVR_strcpy(psSource, psSize, shaderPrefix);
nuclear@0 921 OVR_strcat(psSource, psSize, SimpleQuad_fs);
nuclear@0 922
nuclear@0 923 Ptr<GL::FragmentShader> ps = *new GL::FragmentShader(
nuclear@0 924 &RParams,
nuclear@0 925 (void*)psSource, psSize,
nuclear@0 926 SimpleQuad_fs_refl, sizeof(SimpleQuad_fs_refl) / sizeof(SimpleQuad_fs_refl[0]));
nuclear@0 927
nuclear@0 928 SimpleQuadShader->SetShader(ps);
nuclear@0 929
nuclear@0 930 delete[](psSource);
nuclear@0 931 }
nuclear@0 932 {
nuclear@0 933 size_t vsSize = strlen(shaderPrefix)+sizeof(SimpleQuad_vs);
nuclear@0 934 char* vsSource = new char[vsSize];
nuclear@0 935 OVR_strcpy(vsSource, vsSize, shaderPrefix);
nuclear@0 936 OVR_strcat(vsSource, vsSize, SimpleQuad_vs);
nuclear@0 937
nuclear@0 938 Ptr<GL::VertexShader> vs = *new GL::VertexShader(
nuclear@0 939 &RParams,
nuclear@0 940 (void*)vsSource, vsSize,
nuclear@0 941 SimpleQuad_vs_refl, sizeof(SimpleQuad_vs_refl) / sizeof(SimpleQuad_vs_refl[0]));
nuclear@0 942
nuclear@0 943 SimpleQuadGammaShader = *new ShaderSet;
nuclear@0 944 SimpleQuadGammaShader->SetShader(vs);
nuclear@0 945
nuclear@0 946 delete[](vsSource);
nuclear@0 947
nuclear@0 948 size_t psSize = strlen(shaderPrefix)+sizeof(SimpleQuadGamma_fs);
nuclear@0 949 char* psSource = new char[psSize];
nuclear@0 950 OVR_strcpy(psSource, psSize, shaderPrefix);
nuclear@0 951 OVR_strcat(psSource, psSize, SimpleQuadGamma_fs);
nuclear@0 952
nuclear@0 953 Ptr<GL::FragmentShader> ps = *new GL::FragmentShader(
nuclear@0 954 &RParams,
nuclear@0 955 (void*)psSource, psSize,
nuclear@0 956 SimpleQuadGamma_fs_refl, sizeof(SimpleQuadGamma_fs_refl) / sizeof(SimpleQuadGamma_fs_refl[0]));
nuclear@0 957
nuclear@0 958 SimpleQuadGammaShader->SetShader(ps);
nuclear@0 959
nuclear@0 960 delete[](psSource);
nuclear@0 961 }
nuclear@0 962 }
nuclear@0 963
nuclear@0 964
nuclear@0 965 void DistortionRenderer::destroy()
nuclear@0 966 {
nuclear@0 967 Context currContext;
nuclear@0 968 currContext.InitFromCurrent();
nuclear@0 969
nuclear@0 970 distortionContext.Bind();
nuclear@0 971
nuclear@0 972 for(int eyeNum = 0; eyeNum < 2; eyeNum++)
nuclear@0 973 {
nuclear@0 974 if (GL_ARB_vertex_array_object)
nuclear@0 975 {
nuclear@0 976 glDeleteVertexArrays(1, &DistortionMeshVAOs[eyeNum]);
nuclear@0 977 }
nuclear@0 978
nuclear@0 979 DistortionMeshVAOs[eyeNum] = 0;
nuclear@0 980
nuclear@0 981 DistortionMeshVBs[eyeNum].Clear();
nuclear@0 982 DistortionMeshIBs[eyeNum].Clear();
nuclear@0 983 }
nuclear@0 984
nuclear@0 985 if (DistortionShader)
nuclear@0 986 {
nuclear@0 987 DistortionShader->UnsetShader(Shader_Vertex);
nuclear@0 988 DistortionShader->UnsetShader(Shader_Pixel);
nuclear@0 989 DistortionShader.Clear();
nuclear@0 990 }
nuclear@0 991
nuclear@0 992 LatencyTesterQuadVB.Clear();
nuclear@0 993
nuclear@0 994 if(LatencyVAO != 0)
nuclear@0 995 {
nuclear@0 996 glDeleteVertexArrays(1, &LatencyVAO);
nuclear@0 997 LatencyVAO = 0;
nuclear@0 998 }
nuclear@0 999
nuclear@0 1000 if(OverdriveFbo != 0)
nuclear@0 1001 {
nuclear@0 1002 glDeleteFramebuffers(1, &OverdriveFbo);
nuclear@0 1003 }
nuclear@0 1004
nuclear@0 1005 currContext.Bind();
nuclear@0 1006 distortionContext.Destroy();
nuclear@0 1007 // Who is responsible for destroying the app's context?
nuclear@0 1008 }
nuclear@0 1009
nuclear@0 1010
nuclear@0 1011 }}} // OVR::CAPI::GL