diff options
author | Sven Gothel <[email protected]> | 2014-06-19 17:03:28 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-06-19 17:03:28 +0200 |
commit | d9a584844a60542519d813b5dc1a62428f14a0ae (patch) | |
tree | 942c10a5ebcd0aab65e9d6facb59778468f39d3b /LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.cpp |
Add OculusSDK 0.3.2 Linux Source Code w/o Samples, docs or binaries (libs or tools)
Diffstat (limited to 'LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.cpp')
-rw-r--r-- | LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.cpp | 784 |
1 files changed, 784 insertions, 0 deletions
diff --git a/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.cpp b/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.cpp new file mode 100644 index 0000000..21b6509 --- /dev/null +++ b/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.cpp @@ -0,0 +1,784 @@ +/************************************************************************************ + +Filename : CAPI_GL_DistortionRenderer.h +Content : Distortion renderer header for GL +Created : November 11, 2013 +Authors : David Borel, Lee Cooper + +Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. + +Use of this software is subject to the terms of the Oculus Inc license +agreement provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +************************************************************************************/ + +#include "CAPI_GL_DistortionRenderer.h" + +#include "CAPI_GL_DistortionShaders.h" + +#include "../../OVR_CAPI_GL.h" + +namespace OVR { namespace CAPI { namespace GL { + +// Distortion pixel shader lookup. +// Bit 0: Chroma Correction +// Bit 1: Timewarp + +enum { + DistortionVertexShaderBitMask = 3, + DistortionVertexShaderCount = DistortionVertexShaderBitMask + 1, + DistortionPixelShaderBitMask = 1, + DistortionPixelShaderCount = DistortionPixelShaderBitMask + 1 +}; + +struct ShaderInfo +{ + const char* ShaderData; + size_t ShaderSize; + const ShaderBase::Uniform* ReflectionData; + size_t ReflectionSize; +}; + +// Do add a new distortion shader use these macros (with or w/o reflection) +#define SI_NOREFL(shader) { shader, sizeof(shader), NULL, 0 } +#define SI_REFL__(shader) { shader, sizeof(shader), shader ## _refl, sizeof( shader ## _refl )/sizeof(*(shader ## _refl)) } + + +static ShaderInfo DistortionVertexShaderLookup[DistortionVertexShaderCount] = +{ + SI_REFL__(Distortion_vs), + SI_REFL__(DistortionChroma_vs), + SI_REFL__(DistortionTimewarp_vs), + SI_REFL__(DistortionTimewarpChroma_vs) +}; + +static ShaderInfo DistortionPixelShaderLookup[DistortionPixelShaderCount] = +{ + SI_NOREFL(Distortion_fs), + SI_NOREFL(DistortionChroma_fs) +}; + +void DistortionShaderBitIndexCheck() +{ + OVR_COMPILER_ASSERT(ovrDistortionCap_Chromatic == 1); + OVR_COMPILER_ASSERT(ovrDistortionCap_TimeWarp == 2); +} + + + +struct DistortionVertex +{ + Vector2f Pos; + Vector2f TexR; + Vector2f TexG; + Vector2f TexB; + Color Col; +}; + + +// Vertex type; same format is used for all shapes for simplicity. +// Shapes are built by adding vertices to Model. +struct LatencyVertex +{ + Vector3f Pos; + LatencyVertex (const Vector3f& p) : Pos(p) {} +}; + + +//---------------------------------------------------------------------------- +// ***** GL::DistortionRenderer + +DistortionRenderer::DistortionRenderer(ovrHmd hmd, FrameTimeManager& timeManager, + const HMDRenderState& renderState) + : CAPI::DistortionRenderer(ovrRenderAPI_OpenGL, hmd, timeManager, renderState) + , LatencyVAO(0) +{ + DistortionMeshVAOs[0] = 0; + DistortionMeshVAOs[1] = 0; +} + +DistortionRenderer::~DistortionRenderer() +{ + destroy(); +} + +// static +CAPI::DistortionRenderer* DistortionRenderer::Create(ovrHmd hmd, + FrameTimeManager& timeManager, + const HMDRenderState& renderState) +{ +#if !defined(OVR_OS_MAC) + InitGLExtensions(); +#endif + return new DistortionRenderer(hmd, timeManager, renderState); +} + + +bool DistortionRenderer::Initialize(const ovrRenderAPIConfig* apiConfig, + unsigned distortionCaps) +{ + GfxState = *new GraphicsState(); + + const ovrGLConfig* config = (const ovrGLConfig*)apiConfig; + + if (!config) + { + // Cleanup + pEyeTextures[0].Clear(); + pEyeTextures[1].Clear(); + memset(&RParams, 0, sizeof(RParams)); + return true; + } + + RParams.Multisample = config->OGL.Header.Multisample; + RParams.RTSize = config->OGL.Header.RTSize; +#if defined(OVR_OS_WIN32) + RParams.Window = (config->OGL.Window) ? config->OGL.Window : GetActiveWindow(); +#elif defined(OVR_OS_LINUX) + RParams.Disp = (config->OGL.Disp) ? config->OGL.Disp : XOpenDisplay(NULL); + RParams.Win = config->OGL.Win; + if (!RParams.Win) + { + int unused; + XGetInputFocus(RParams.Disp, &RParams.Win, &unused); + } +#endif + + DistortionCaps = distortionCaps; + + //DistortionWarper.SetVsync((hmdCaps & ovrHmdCap_NoVSync) ? false : true); + + pEyeTextures[0] = *new Texture(&RParams, 0, 0); + pEyeTextures[1] = *new Texture(&RParams, 0, 0); + + initBuffersAndShaders(); + + return true; +} + + +void DistortionRenderer::SubmitEye(int eyeId, ovrTexture* eyeTexture) +{ + // Doesn't do a lot in here?? + const ovrGLTexture* tex = (const ovrGLTexture*)eyeTexture; + + // Write in values + eachEye[eyeId].texture = tex->OGL.TexId; + + if (tex) + { + // Its only at this point we discover what the viewport of the texture is. + // because presumably we allow users to realtime adjust the resolution. + eachEye[eyeId].TextureSize = tex->OGL.Header.TextureSize; + eachEye[eyeId].RenderViewport = tex->OGL.Header.RenderViewport; + + const ovrEyeRenderDesc& erd = RState.EyeRenderDesc[eyeId]; + + ovrHmd_GetRenderScaleAndOffset( erd.Fov, + eachEye[eyeId].TextureSize, eachEye[eyeId].RenderViewport, + eachEye[eyeId].UVScaleOffset ); + + pEyeTextures[eyeId]->UpdatePlaceholderTexture(tex->OGL.TexId, + tex->OGL.Header.TextureSize); + } +} + +void DistortionRenderer::EndFrame(bool swapBuffers, + unsigned char* latencyTesterDrawColor, unsigned char* latencyTester2DrawColor) +{ + if (!TimeManager.NeedDistortionTimeMeasurement()) + { + if (RState.DistortionCaps & ovrDistortionCap_TimeWarp) + { + // Wait for timewarp distortion if it is time and Gpu idle + FlushGpuAndWaitTillTime(TimeManager.GetFrameTiming().TimewarpPointTime); + } + + renderDistortion(pEyeTextures[0], pEyeTextures[1]); + } + else + { + // If needed, measure distortion time so that TimeManager can better estimate + // latency-reducing time-warp wait timing. + WaitUntilGpuIdle(); + double distortionStartTime = ovr_GetTimeInSeconds(); + + renderDistortion(pEyeTextures[0], pEyeTextures[1]); + + WaitUntilGpuIdle(); + TimeManager.AddDistortionTimeMeasurement(ovr_GetTimeInSeconds() - distortionStartTime); + } + + if(latencyTesterDrawColor) + { + renderLatencyQuad(latencyTesterDrawColor); + } + else if(latencyTester2DrawColor) + { + renderLatencyPixel(latencyTester2DrawColor); + } + + if (swapBuffers) + { + bool useVsync = ((RState.EnabledHmdCaps & ovrHmdCap_NoVSync) == 0); + int swapInterval = (useVsync) ? 1 : 0; +#if defined(OVR_OS_WIN32) + if (wglGetSwapIntervalEXT() != swapInterval) + wglSwapIntervalEXT(swapInterval); + + HDC dc = GetDC(RParams.Window); + BOOL success = SwapBuffers(dc); + ReleaseDC(RParams.Window, dc); + OVR_ASSERT(success); + OVR_UNUSED(success); +#elif defined(OVR_OS_MAC) + CGLContextObj context = CGLGetCurrentContext(); + GLint currentSwapInterval = 0; + CGLGetParameter(context, kCGLCPSwapInterval, ¤tSwapInterval); + if (currentSwapInterval != swapInterval) + CGLSetParameter(context, kCGLCPSwapInterval, &swapInterval); + + CGLFlushDrawable(context); +#elif defined(OVR_OS_LINUX) + static const char* extensions = glXQueryExtensionsString(RParams.Disp, 0); + static bool supportsVSync = (extensions != NULL && strstr(extensions, "GLX_EXT_swap_control")); + if (supportsVSync) + { + GLuint currentSwapInterval = 0; + glXQueryDrawable(RParams.Disp, RParams.Win, GLX_SWAP_INTERVAL_EXT, ¤tSwapInterval); + if (currentSwapInterval != swapInterval) + glXSwapIntervalEXT(RParams.Disp, RParams.Win, swapInterval); + } + + glXSwapBuffers(RParams.Disp, RParams.Win); +#endif + } +} + +void DistortionRenderer::WaitUntilGpuIdle() +{ + glFlush(); + glFinish(); +} + +double DistortionRenderer::FlushGpuAndWaitTillTime(double absTime) +{ + double initialTime = ovr_GetTimeInSeconds(); + if (initialTime >= absTime) + return 0.0; + + glFlush(); + glFinish(); + + double newTime = initialTime; + volatile int i; + + while (newTime < absTime) + { + for (int j = 0; j < 50; j++) + i = 0; + + newTime = ovr_GetTimeInSeconds(); + } + + // How long we waited + return newTime - initialTime; +} + + +DistortionRenderer::GraphicsState::GraphicsState() +{ + const char* glVersionString = (const char*)glGetString(GL_VERSION); + OVR_DEBUG_LOG(("GL_VERSION STRING: %s", (const char*)glVersionString)); + char prefix[64]; + bool foundVersion = false; + + for (int i = 10; i < 30; ++i) + { + int major = i / 10; + int minor = i % 10; + OVR_sprintf(prefix, 64, "%d.%d", major, minor); + if (strstr(glVersionString, prefix) == glVersionString) + { + GlMajorVersion = major; + GlMinorVersion = minor; + foundVersion = true; + break; + } + } + + if (!foundVersion) + { + glGetIntegerv(GL_MAJOR_VERSION, &GlMajorVersion); + glGetIntegerv(GL_MAJOR_VERSION, &GlMinorVersion); + } + + OVR_ASSERT(GlMajorVersion >= 2); + + if (GlMajorVersion >= 3) + { + SupportsVao = true; + } + else + { + const char* extensions = (const char*)glGetString(GL_EXTENSIONS); + SupportsVao = (strstr("GL_ARB_vertex_array_object", extensions) != NULL); + } +} + + +void DistortionRenderer::GraphicsState::ApplyBool(GLenum Name, GLint Value) +{ + if (Value != 0) + glEnable(Name); + else + glDisable(Name); +} + + +void DistortionRenderer::GraphicsState::Save() +{ + glGetIntegerv(GL_VIEWPORT, Viewport); + glGetFloatv(GL_COLOR_CLEAR_VALUE, ClearColor); + glGetIntegerv(GL_DEPTH_TEST, &DepthTest); + glGetIntegerv(GL_CULL_FACE, &CullFace); + glGetIntegerv(GL_CURRENT_PROGRAM, &Program); + glGetIntegerv(GL_ACTIVE_TEXTURE, &ActiveTexture); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &TextureBinding); + glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &VertexArray); + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &FrameBufferBinding); + glGetIntegerv(GL_BLEND, &Blend); + glGetIntegerv(GL_COLOR_WRITEMASK, ColorWritemask); + glGetIntegerv(GL_DITHER, &Dither); + glGetIntegerv(GL_RASTERIZER_DISCARD, &RasterizerDiscard); + if (GlMajorVersion >= 3 && GlMajorVersion >= 2) + glGetIntegerv(GL_SAMPLE_MASK, &SampleMask); + glGetIntegerv(GL_SCISSOR_TEST, &ScissorTest); + + IsValid = true; +} + + +void DistortionRenderer::GraphicsState::Restore() +{ + // Don't allow restore-before-save. + if (!IsValid) + return; + + glViewport(Viewport[0], Viewport[1], Viewport[2], Viewport[3]); + glClearColor(ClearColor[0], ClearColor[1], ClearColor[2], ClearColor[3]); + + ApplyBool(GL_DEPTH_TEST, DepthTest); + ApplyBool(GL_CULL_FACE, CullFace); + + glUseProgram(Program); + glActiveTexture(ActiveTexture); + glBindTexture(GL_TEXTURE_2D, TextureBinding); + if (SupportsVao) + glBindVertexArray(VertexArray); + glBindFramebuffer(GL_FRAMEBUFFER, FrameBufferBinding); + + ApplyBool(GL_BLEND, Blend); + + glColorMask((GLboolean)ColorWritemask[0], (GLboolean)ColorWritemask[1], (GLboolean)ColorWritemask[2], (GLboolean)ColorWritemask[3]); + ApplyBool(GL_DITHER, Dither); + ApplyBool(GL_RASTERIZER_DISCARD, RasterizerDiscard); + if (GlMajorVersion >= 3 && GlMajorVersion >= 2) + ApplyBool(GL_SAMPLE_MASK, SampleMask); + ApplyBool(GL_SCISSOR_TEST, ScissorTest); +} + + +void DistortionRenderer::initBuffersAndShaders() +{ + for ( int eyeNum = 0; eyeNum < 2; eyeNum++ ) + { + // Allocate & generate distortion mesh vertices. + ovrDistortionMesh meshData; + +// double startT = ovr_GetTimeInSeconds(); + + if (!ovrHmd_CreateDistortionMesh( HMD, + RState.EyeRenderDesc[eyeNum].Eye, + RState.EyeRenderDesc[eyeNum].Fov, + RState.DistortionCaps, + &meshData) ) + { + OVR_ASSERT(false); + continue; + } + + // Now parse the vertex data and create a render ready vertex buffer from it + DistortionVertex * pVBVerts = (DistortionVertex*)OVR_ALLOC ( sizeof(DistortionVertex) * meshData.VertexCount ); + DistortionVertex * pCurVBVert = pVBVerts; + ovrDistortionVertex* pCurOvrVert = meshData.pVertexData; + + for ( unsigned vertNum = 0; vertNum < meshData.VertexCount; vertNum++ ) + { + pCurVBVert->Pos.x = pCurOvrVert->Pos.x; + pCurVBVert->Pos.y = pCurOvrVert->Pos.y; + pCurVBVert->TexR = (*(Vector2f*)&pCurOvrVert->TexR); + pCurVBVert->TexG = (*(Vector2f*)&pCurOvrVert->TexG); + pCurVBVert->TexB = (*(Vector2f*)&pCurOvrVert->TexB); + // Convert [0.0f,1.0f] to [0,255] + pCurVBVert->Col.R = (OVR::UByte)( pCurOvrVert->VignetteFactor * 255.99f ); + pCurVBVert->Col.G = pCurVBVert->Col.R; + pCurVBVert->Col.B = pCurVBVert->Col.R; + pCurVBVert->Col.A = (OVR::UByte)( pCurOvrVert->TimeWarpFactor * 255.99f );; + pCurOvrVert++; + pCurVBVert++; + } + + DistortionMeshVBs[eyeNum] = *new Buffer(&RParams); + DistortionMeshVBs[eyeNum]->Data ( Buffer_Vertex | Buffer_ReadOnly, pVBVerts, sizeof(DistortionVertex) * meshData.VertexCount ); + DistortionMeshIBs[eyeNum] = *new Buffer(&RParams); + DistortionMeshIBs[eyeNum]->Data ( Buffer_Index | Buffer_ReadOnly, meshData.pIndexData, ( sizeof(SInt16) * meshData.IndexCount ) ); + + OVR_FREE ( pVBVerts ); + ovrHmd_DestroyDistortionMesh( &meshData ); + } + + initShaders(); +} + +void DistortionRenderer::renderDistortion(Texture* leftEyeTexture, Texture* rightEyeTexture) +{ + GraphicsState* glState = (GraphicsState*)GfxState.GetPtr(); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + setViewport( Recti(0,0, RParams.RTSize.w, RParams.RTSize.h) ); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); + glDisable(GL_DITHER); + glDisable(GL_RASTERIZER_DISCARD); + if (glState->GlMajorVersion >= 3 && glState->GlMajorVersion >= 2) + glDisable(GL_SAMPLE_MASK); + glDisable(GL_SCISSOR_TEST); + + glClearColor( + RState.ClearColor[0], + RState.ClearColor[1], + RState.ClearColor[2], + RState.ClearColor[3] ); + + glClear(GL_COLOR_BUFFER_BIT); + + for (int eyeNum = 0; eyeNum < 2; eyeNum++) + { + ShaderFill distortionShaderFill(DistortionShader); + distortionShaderFill.SetTexture(0, eyeNum == 0 ? leftEyeTexture : rightEyeTexture); + + DistortionShader->SetUniform2f("EyeToSourceUVScale", eachEye[eyeNum].UVScaleOffset[0].x, eachEye[eyeNum].UVScaleOffset[0].y); + DistortionShader->SetUniform2f("EyeToSourceUVOffset", eachEye[eyeNum].UVScaleOffset[1].x, eachEye[eyeNum].UVScaleOffset[1].y); + + if (DistortionCaps & ovrDistortionCap_TimeWarp) + { + ovrMatrix4f timeWarpMatrices[2]; + ovrHmd_GetEyeTimewarpMatrices(HMD, (ovrEyeType)eyeNum, + RState.EyeRenderPoses[eyeNum], timeWarpMatrices); + + // Feed identity like matrices in until we get proper timewarp calculation going on + DistortionShader->SetUniform4x4f("EyeRotationStart", Matrix4f(timeWarpMatrices[0]).Transposed()); + DistortionShader->SetUniform4x4f("EyeRotationEnd", Matrix4f(timeWarpMatrices[1]).Transposed()); + + renderPrimitives(&distortionShaderFill, DistortionMeshVBs[eyeNum], DistortionMeshIBs[eyeNum], + 0, (int)DistortionMeshIBs[eyeNum]->GetSize()/2, Prim_Triangles, &DistortionMeshVAOs[eyeNum], true); + } + else + { + renderPrimitives(&distortionShaderFill, DistortionMeshVBs[eyeNum], DistortionMeshIBs[eyeNum], + 0, (int)DistortionMeshIBs[eyeNum]->GetSize()/2, Prim_Triangles, &DistortionMeshVAOs[eyeNum], true); + } + } +} + +void DistortionRenderer::createDrawQuad() +{ + const int numQuadVerts = 4; + LatencyTesterQuadVB = *new Buffer(&RParams); + if(!LatencyTesterQuadVB) + { + return; + } + + LatencyTesterQuadVB->Data(Buffer_Vertex, NULL, numQuadVerts * sizeof(LatencyVertex)); + LatencyVertex* vertices = (LatencyVertex*)LatencyTesterQuadVB->Map(0, numQuadVerts * sizeof(LatencyVertex), Map_Discard); + if(!vertices) + { + OVR_ASSERT(false); // failed to lock vertex buffer + return; + } + + const float left = -1.0f; + const float top = -1.0f; + const float right = 1.0f; + const float bottom = 1.0f; + + vertices[0] = LatencyVertex(Vector3f(left, top, 0.0f)); + vertices[1] = LatencyVertex(Vector3f(left, bottom, 0.0f)); + vertices[2] = LatencyVertex(Vector3f(right, top, 0.0f)); + vertices[3] = LatencyVertex(Vector3f(right, bottom, 0.0f)); + + LatencyTesterQuadVB->Unmap(vertices); +} + +void DistortionRenderer::renderLatencyQuad(unsigned char* latencyTesterDrawColor) +{ + const int numQuadVerts = 4; + + if(!LatencyTesterQuadVB) + { + createDrawQuad(); + } + + ShaderFill quadFill(SimpleQuadShader); + //quadFill.SetInputLayout(SimpleQuadVertexIL); + + setViewport(Recti(0,0, RParams.RTSize.w, RParams.RTSize.h)); + + SimpleQuadShader->SetUniform2f("Scale", 0.2f, 0.2f); + SimpleQuadShader->SetUniform4f("Color", (float)latencyTesterDrawColor[0] / 255.99f, + (float)latencyTesterDrawColor[0] / 255.99f, + (float)latencyTesterDrawColor[0] / 255.99f, + 1.0f); + + for(int eyeNum = 0; eyeNum < 2; eyeNum++) + { + SimpleQuadShader->SetUniform2f("PositionOffset", eyeNum == 0 ? -0.4f : 0.4f, 0.0f); + renderPrimitives(&quadFill, LatencyTesterQuadVB, NULL, 0, numQuadVerts, Prim_TriangleStrip, &LatencyVAO, false); + } +} + +void DistortionRenderer::renderLatencyPixel(unsigned char* latencyTesterPixelColor) +{ + const int numQuadVerts = 4; + + if(!LatencyTesterQuadVB) + { + createDrawQuad(); + } + + ShaderFill quadFill(SimpleQuadShader); + + setViewport(Recti(0,0, RParams.RTSize.w, RParams.RTSize.h)); + + SimpleQuadShader->SetUniform4f("Color", (float)latencyTesterPixelColor[0] / 255.99f, + (float)latencyTesterPixelColor[0] / 255.99f, + (float)latencyTesterPixelColor[0] / 255.99f, + 1.0f); + + Vector2f scale(2.0f / RParams.RTSize.w, 2.0f / RParams.RTSize.h); + SimpleQuadShader->SetUniform2f("Scale", scale.x, scale.y); + SimpleQuadShader->SetUniform2f("PositionOffset", 1.0f, 1.0f); + renderPrimitives(&quadFill, LatencyTesterQuadVB, NULL, 0, numQuadVerts, Prim_TriangleStrip, &LatencyVAO, false); +} + +void DistortionRenderer::renderPrimitives( + const ShaderFill* fill, + Buffer* vertices, Buffer* indices, + int offset, int count, + PrimitiveType rprim, GLuint* vao, bool isDistortionMesh) +{ + GraphicsState* glState = (GraphicsState*)GfxState.GetPtr(); + + GLenum prim; + switch (rprim) + { + case Prim_Triangles: + prim = GL_TRIANGLES; + break; + case Prim_Lines: + prim = GL_LINES; + break; + case Prim_TriangleStrip: + prim = GL_TRIANGLE_STRIP; + break; + default: + OVR_ASSERT(false); + return; + } + + fill->Set(); + + GLuint prog = fill->GetShaders()->Prog; + + if (vao != NULL) + { + if (*vao != 0) + { + glBindVertexArray(*vao); + + if (isDistortionMesh) + glDrawElements(prim, count, GL_UNSIGNED_SHORT, NULL); + else + glDrawArrays(prim, 0, count); + } + else + { + if (glState->SupportsVao) + { + glGenVertexArrays(1, vao); + glBindVertexArray(*vao); + } + + int attributeCount = (isDistortionMesh) ? 5 : 1; + int* locs = new int[attributeCount]; + + glBindBuffer(GL_ARRAY_BUFFER, ((Buffer*)vertices)->GLBuffer); + + if (isDistortionMesh) + { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ((Buffer*)indices)->GLBuffer); + + locs[0] = glGetAttribLocation(prog, "Position"); + locs[1] = glGetAttribLocation(prog, "Color"); + locs[2] = glGetAttribLocation(prog, "TexCoord0"); + locs[3] = glGetAttribLocation(prog, "TexCoord1"); + locs[4] = glGetAttribLocation(prog, "TexCoord2"); + + glVertexAttribPointer(locs[0], 2, GL_FLOAT, false, sizeof(DistortionVertex), reinterpret_cast<char*>(offset)+offsetof(DistortionVertex, Pos)); + glVertexAttribPointer(locs[1], 4, GL_UNSIGNED_BYTE, true, sizeof(DistortionVertex), reinterpret_cast<char*>(offset)+offsetof(DistortionVertex, Col)); + glVertexAttribPointer(locs[2], 2, GL_FLOAT, false, sizeof(DistortionVertex), reinterpret_cast<char*>(offset)+offsetof(DistortionVertex, TexR)); + glVertexAttribPointer(locs[3], 2, GL_FLOAT, false, sizeof(DistortionVertex), reinterpret_cast<char*>(offset)+offsetof(DistortionVertex, TexG)); + glVertexAttribPointer(locs[4], 2, GL_FLOAT, false, sizeof(DistortionVertex), reinterpret_cast<char*>(offset)+offsetof(DistortionVertex, TexB)); + } + else + { + locs[0] = glGetAttribLocation(prog, "Position"); + + glVertexAttribPointer(locs[0], 3, GL_FLOAT, false, sizeof(LatencyVertex), reinterpret_cast<char*>(offset)+offsetof(LatencyVertex, Pos)); + } + + for (int i = 0; i < attributeCount; ++i) + glEnableVertexAttribArray(locs[i]); + + if (isDistortionMesh) + glDrawElements(prim, count, GL_UNSIGNED_SHORT, NULL); + else + glDrawArrays(prim, 0, count); + + + if (!glState->SupportsVao) + { + for (int i = 0; i < attributeCount; ++i) + glDisableVertexAttribArray(locs[i]); + } + + delete[] locs; + } + } +} + +void DistortionRenderer::setViewport(const Recti& vp) +{ + glViewport(vp.x, vp.y, vp.w, vp.h); +} + + +void DistortionRenderer::initShaders() +{ + GraphicsState* glState = (GraphicsState*)GfxState.GetPtr(); + + const char* shaderPrefix = + (glState->GlMajorVersion < 3 || (glState->GlMajorVersion == 3 && glState->GlMinorVersion < 2)) ? + glsl2Prefix : glsl3Prefix; + + { + ShaderInfo vsInfo = DistortionVertexShaderLookup[DistortionVertexShaderBitMask & DistortionCaps]; + + size_t vsSize = strlen(shaderPrefix)+vsInfo.ShaderSize; + char* vsSource = new char[vsSize]; + OVR_strcpy(vsSource, vsSize, shaderPrefix); + OVR_strcat(vsSource, vsSize, vsInfo.ShaderData); + + Ptr<GL::VertexShader> vs = *new GL::VertexShader( + &RParams, + (void*)vsSource, vsSize, + vsInfo.ReflectionData, vsInfo.ReflectionSize); + + DistortionShader = *new ShaderSet; + DistortionShader->SetShader(vs); + + delete[](vsSource); + + ShaderInfo psInfo = DistortionPixelShaderLookup[DistortionPixelShaderBitMask & DistortionCaps]; + + size_t psSize = strlen(shaderPrefix)+psInfo.ShaderSize; + char* psSource = new char[psSize]; + OVR_strcpy(psSource, psSize, shaderPrefix); + OVR_strcat(psSource, psSize, psInfo.ShaderData); + + Ptr<GL::FragmentShader> ps = *new GL::FragmentShader( + &RParams, + (void*)psSource, psSize, + psInfo.ReflectionData, psInfo.ReflectionSize); + + DistortionShader->SetShader(ps); + + delete[](psSource); + } + { + size_t vsSize = strlen(shaderPrefix)+sizeof(SimpleQuad_vs); + char* vsSource = new char[vsSize]; + OVR_strcpy(vsSource, vsSize, shaderPrefix); + OVR_strcat(vsSource, vsSize, SimpleQuad_vs); + + Ptr<GL::VertexShader> vs = *new GL::VertexShader( + &RParams, + (void*)vsSource, vsSize, + SimpleQuad_vs_refl, sizeof(SimpleQuad_vs_refl) / sizeof(SimpleQuad_vs_refl[0])); + + SimpleQuadShader = *new ShaderSet; + SimpleQuadShader->SetShader(vs); + + delete[](vsSource); + + size_t psSize = strlen(shaderPrefix)+sizeof(SimpleQuad_fs); + char* psSource = new char[psSize]; + OVR_strcpy(psSource, psSize, shaderPrefix); + OVR_strcat(psSource, psSize, SimpleQuad_fs); + + Ptr<GL::FragmentShader> ps = *new GL::FragmentShader( + &RParams, + (void*)psSource, psSize, + SimpleQuad_fs_refl, sizeof(SimpleQuad_fs_refl) / sizeof(SimpleQuad_fs_refl[0])); + + SimpleQuadShader->SetShader(ps); + + delete[](psSource); + } +} + + +void DistortionRenderer::destroy() +{ + GraphicsState* glState = (GraphicsState*)GfxState.GetPtr(); + + for(int eyeNum = 0; eyeNum < 2; eyeNum++) + { + if (glState->SupportsVao) + glDeleteVertexArrays(1, &DistortionMeshVAOs[eyeNum]); + + DistortionMeshVAOs[eyeNum] = 0; + + DistortionMeshVBs[eyeNum].Clear(); + DistortionMeshIBs[eyeNum].Clear(); + } + + if (DistortionShader) + { + DistortionShader->UnsetShader(Shader_Vertex); + DistortionShader->UnsetShader(Shader_Pixel); + DistortionShader.Clear(); + } + + LatencyTesterQuadVB.Clear(); + LatencyVAO = 0; +} + +}}} // OVR::CAPI::GL |