added linux makefile

This commit is contained in:
Colin Sherratt
2014-05-26 03:42:23 -04:00
parent cb5a46cd58
commit 6b733ba3a3
141 changed files with 53997 additions and 6 deletions

View File

@ -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, &currentSwapInterval);
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, &currentSwapInterval);
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

View File

@ -0,0 +1,178 @@
/************************************************************************************
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.
************************************************************************************/
#ifndef OVR_CAPI_GL_DistortionRenderer_h
#define OVR_CAPI_GL_DistortionRenderer_h
#include "../CAPI_DistortionRenderer.h"
#include "../../Kernel/OVR_Log.h"
#include "CAPI_GL_Util.h"
namespace OVR { namespace CAPI { namespace GL {
// ***** GL::DistortionRenderer
// Implementation of DistortionRenderer for GL.
class DistortionRenderer : public CAPI::DistortionRenderer
{
public:
DistortionRenderer(ovrHmd hmd,
FrameTimeManager& timeManager,
const HMDRenderState& renderState);
~DistortionRenderer();
// Creation function for the device.
static CAPI::DistortionRenderer* Create(ovrHmd hmd,
FrameTimeManager& timeManager,
const HMDRenderState& renderState);
// ***** Public DistortionRenderer interface
virtual bool Initialize(const ovrRenderAPIConfig* apiConfig,
unsigned distortionCaps);
virtual void SubmitEye(int eyeId, ovrTexture* eyeTexture);
virtual void EndFrame(bool swapBuffers, unsigned char* latencyTesterDrawColor, unsigned char* latencyTester2DrawColor);
void WaitUntilGpuIdle();
// Similar to ovr_WaitTillTime but it also flushes GPU.
// Note, it exits when time expires, even if GPU is not in idle state yet.
double FlushGpuAndWaitTillTime(double absTime);
protected:
class GraphicsState : public CAPI::DistortionRenderer::GraphicsState
{
public:
GraphicsState();
virtual void Save();
virtual void Restore();
protected:
void ApplyBool(GLenum Name, GLint Value);
public:
GLint GlMajorVersion;
GLint GlMinorVersion;
bool SupportsVao;
GLint Viewport[4];
GLfloat ClearColor[4];
GLint DepthTest;
GLint CullFace;
GLint Program;
GLint ActiveTexture;
GLint TextureBinding;
GLint VertexArray;
GLint FrameBufferBinding;
GLint Blend;
GLint ColorWritemask[4];
GLint Dither;
GLint Fog;
GLint Lighting;
GLint RasterizerDiscard;
GLint RenderMode;
GLint SampleMask;
GLint ScissorTest;
GLfloat ZoomX;
GLfloat ZoomY;
};
// TBD: Should we be using oe from RState instead?
unsigned DistortionCaps;
struct FOR_EACH_EYE
{
FOR_EACH_EYE() : TextureSize(0), RenderViewport(Sizei(0)) { }
#if 0
IDirect3DVertexBuffer9 * dxVerts;
IDirect3DIndexBuffer9 * dxIndices;
#endif
int numVerts;
int numIndices;
GLuint texture;
ovrVector2f UVScaleOffset[2];
Sizei TextureSize;
Recti RenderViewport;
} eachEye[2];
// GL context and utility variables.
RenderParams RParams;
// Helpers
void initBuffersAndShaders();
void initShaders();
void initFullscreenQuad();
void destroy();
void setViewport(const Recti& vp);
void renderDistortion(Texture* leftEyeTexture, Texture* rightEyeTexture);
void renderPrimitives(const ShaderFill* fill, Buffer* vertices, Buffer* indices,
int offset, int count,
PrimitiveType rprim, GLuint* vao, bool isDistortionMesh);
void createDrawQuad();
void renderLatencyQuad(unsigned char* latencyTesterDrawColor);
void renderLatencyPixel(unsigned char* latencyTesterPixelColor);
Ptr<Texture> pEyeTextures[2];
Ptr<Buffer> DistortionMeshVBs[2]; // one per-eye
Ptr<Buffer> DistortionMeshIBs[2]; // one per-eye
GLuint DistortionMeshVAOs[2]; // one per-eye
Ptr<ShaderSet> DistortionShader;
struct StandardUniformData
{
Matrix4f Proj;
Matrix4f View;
} StdUniforms;
GLuint LatencyVAO;
Ptr<Buffer> LatencyTesterQuadVB;
Ptr<ShaderSet> SimpleQuadShader;
Ptr<Texture> CurRenderTarget;
Array<Ptr<Texture> > DepthBuffers;
GLuint CurrentFbo;
GLint SavedViewport[4];
GLfloat SavedClearColor[4];
GLint SavedDepthTest;
GLint SavedCullFace;
GLint SavedProgram;
GLint SavedActiveTexture;
GLint SavedBoundTexture;
GLint SavedVertexArray;
GLint SavedBoundFrameBuffer;
};
}}} // OVR::CAPI::GL
#endif // OVR_CAPI_GL_DistortionRenderer_h

View File

@ -0,0 +1,326 @@
/************************************************************************************
Filename : CAPI_GL_Shaders.h
Content : Distortion shader header for GL
Created : November 11, 2013
Authors : David Borel, Volga Aksoy
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.
************************************************************************************/
#ifndef OVR_CAPI_GL_Shaders_h
#define OVR_CAPI_GL_Shaders_h
#include "CAPI_GL_Util.h"
namespace OVR { namespace CAPI { namespace GL {
static const char glsl2Prefix[] =
"#version 110\n"
"#extension GL_ARB_shader_texture_lod : enable\n"
"#define _FRAGCOLOR_DECLARATION\n"
"#define _VS_IN attribute\n"
"#define _VS_OUT varying\n"
"#define _FS_IN varying\n"
"#define _TEXTURELOD texture2DLod\n"
"#define _FRAGCOLOR gl_FragColor\n";
static const char glsl3Prefix[] =
"#version 150\n"
"#define _FRAGCOLOR_DECLARATION out vec4 FragColor;\n"
"#define _VS_IN in\n"
"#define _VS_OUT out\n"
"#define _FS_IN in\n"
"#define _TEXTURELOD textureLod\n"
"#define _FRAGCOLOR FragColor\n";
static const char SimpleQuad_vs[] =
"uniform vec2 PositionOffset;\n"
"uniform vec2 Scale;\n"
"_VS_IN vec3 Position;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(Position.xy * Scale + PositionOffset, 0.5, 1.0);\n"
"}\n";
const OVR::CAPI::GL::ShaderBase::Uniform SimpleQuad_vs_refl[] =
{
{ "PositionOffset", OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 0, 8 },
{ "Scale", OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 8, 8 },
};
static const char SimpleQuad_fs[] =
"uniform vec4 Color;\n"
"_FRAGCOLOR_DECLARATION\n"
"void main()\n"
"{\n"
" _FRAGCOLOR = Color;\n"
"}\n";
const OVR::CAPI::GL::ShaderBase::Uniform SimpleQuad_fs_refl[] =
{
{ "Color", OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 0, 16 },
};
static const char Distortion_vs[] =
"uniform vec2 EyeToSourceUVScale;\n"
"uniform vec2 EyeToSourceUVOffset;\n"
"_VS_IN vec2 Position;\n"
"_VS_IN vec4 Color;\n"
"_VS_IN vec2 TexCoord0;\n"
"_VS_OUT vec4 oColor;\n"
"_VS_OUT vec2 oTexCoord0;\n"
"void main()\n"
"{\n"
" gl_Position.x = Position.x;\n"
" gl_Position.y = Position.y;\n"
" gl_Position.z = 0.5;\n"
" gl_Position.w = 1.0;\n"
// Vertex inputs are in TanEyeAngle space for the R,G,B channels (i.e. after chromatic aberration and distortion).
// Scale them into the correct [0-1],[0-1] UV lookup space (depending on eye)
" oTexCoord0 = TexCoord0 * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
" oTexCoord0.y = 1.0 - oTexCoord0.y;\n"
" oColor = Color;\n" // Used for vignette fade.
"}\n";
const OVR::CAPI::GL::ShaderBase::Uniform Distortion_vs_refl[] =
{
{ "EyeToSourceUVScale", OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 0, 8 },
{ "EyeToSourceUVOffset", OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 8, 8 },
};
static const char Distortion_fs[] =
"uniform sampler2D Texture0;\n"
"_FS_IN vec4 oColor;\n"
"_FS_IN vec2 oTexCoord0;\n"
"_FRAGCOLOR_DECLARATION\n"
"void main()\n"
"{\n"
" _FRAGCOLOR = _TEXTURELOD(Texture0, oTexCoord0, 0.0);\n"
" _FRAGCOLOR.a = 1.0;\n"
"}\n";
static const char DistortionTimewarp_vs[] =
"uniform vec2 EyeToSourceUVScale;\n"
"uniform vec2 EyeToSourceUVOffset;\n"
"uniform mat4 EyeRotationStart;\n"
"uniform mat4 EyeRotationEnd;\n"
"_VS_IN vec2 Position;\n"
"_VS_IN vec4 Color;\n"
"_VS_IN vec2 TexCoord0;\n"
"_FS_IN vec4 oColor;\n"
"_FS_IN vec2 oTexCoord0;\n"
"void main()\n"
"{\n"
" gl_Position.x = Position.x;\n"
" gl_Position.y = Position.y;\n"
" gl_Position.z = 0.0;\n"
" gl_Position.w = 1.0;\n"
// Vertex inputs are in TanEyeAngle space for the R,G,B channels (i.e. after chromatic aberration and distortion).
// These are now "real world" vectors in direction (x,y,1) relative to the eye of the HMD.
" vec3 TanEyeAngle = vec3 ( TexCoord0.x, TexCoord0.y, 1.0 );\n"
// Accurate time warp lerp vs. faster
#if 1
// Apply the two 3x3 timewarp rotations to these vectors.
" vec3 TransformedStart = (EyeRotationStart * vec4(TanEyeAngle, 0)).xyz;\n"
" vec3 TransformedEnd = (EyeRotationEnd * vec4(TanEyeAngle, 0)).xyz;\n"
// And blend between them.
" vec3 Transformed = mix ( TransformedStart, TransformedEnd, Color.a );\n"
#else
" mat4 EyeRotation = mix ( EyeRotationStart, EyeRotationEnd, Color.a );\n"
" vec3 Transformed = EyeRotation * TanEyeAngle;\n"
#endif
// Project them back onto the Z=1 plane of the rendered images.
" float RecipZ = 1.0 / Transformed.z;\n"
" vec2 Flattened = vec2 ( Transformed.x * RecipZ, Transformed.y * RecipZ );\n"
// These are now still in TanEyeAngle space.
// Scale them into the correct [0-1],[0-1] UV lookup space (depending on eye)
" vec2 SrcCoord = Flattened * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
" oTexCoord0 = SrcCoord;\n"
" oTexCoord0.y = 1.0-oTexCoord0.y;\n"
" oColor = vec4(Color.r, Color.r, Color.r, Color.r);\n" // Used for vignette fade.
"}\n";
const OVR::CAPI::GL::ShaderBase::Uniform DistortionTimewarp_vs_refl[] =
{
{ "EyeToSourceUVScale", OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 0, 8 },
{ "EyeToSourceUVOffset", OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 8, 8 },
};
static const char DistortionChroma_vs[] =
"uniform vec2 EyeToSourceUVScale;\n"
"uniform vec2 EyeToSourceUVOffset;\n"
"_VS_IN vec2 Position;\n"
"_VS_IN vec4 Color;\n"
"_VS_IN vec2 TexCoord0;\n"
"_VS_IN vec2 TexCoord1;\n"
"_VS_IN vec2 TexCoord2;\n"
"_VS_OUT vec4 oColor;\n"
"_VS_OUT vec2 oTexCoord0;\n"
"_VS_OUT vec2 oTexCoord1;\n"
"_VS_OUT vec2 oTexCoord2;\n"
"void main()\n"
"{\n"
" gl_Position.x = Position.x;\n"
" gl_Position.y = Position.y;\n"
" gl_Position.z = 0.5;\n"
" gl_Position.w = 1.0;\n"
// Vertex inputs are in TanEyeAngle space for the R,G,B channels (i.e. after chromatic aberration and distortion).
// Scale them into the correct [0-1],[0-1] UV lookup space (depending on eye)
" oTexCoord0 = TexCoord0 * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
" oTexCoord0.y = 1.0-oTexCoord0.y;\n"
" oTexCoord1 = TexCoord1 * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
" oTexCoord1.y = 1.0-oTexCoord1.y;\n"
" oTexCoord2 = TexCoord2 * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
" oTexCoord2.y = 1.0-oTexCoord2.y;\n"
" oColor = Color;\n" // Used for vignette fade.
"}\n";
const OVR::CAPI::GL::ShaderBase::Uniform DistortionChroma_vs_refl[] =
{
{ "EyeToSourceUVScale", OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 0, 8 },
{ "EyeToSourceUVOffset", OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 8, 8 },
};
static const char DistortionChroma_fs[] =
"uniform sampler2D Texture0;\n"
"_FS_IN vec4 oColor;\n"
"_FS_IN vec2 oTexCoord0;\n"
"_FS_IN vec2 oTexCoord1;\n"
"_FS_IN vec2 oTexCoord2;\n"
"_FRAGCOLOR_DECLARATION\n"
"void main()\n"
"{\n"
" float ResultR = _TEXTURELOD(Texture0, oTexCoord0, 0.0).r;\n"
" float ResultG = _TEXTURELOD(Texture0, oTexCoord1, 0.0).g;\n"
" float ResultB = _TEXTURELOD(Texture0, oTexCoord2, 0.0).b;\n"
" _FRAGCOLOR = vec4(ResultR * oColor.r, ResultG * oColor.g, ResultB * oColor.b, 1.0);\n"
"}\n";
static const char DistortionTimewarpChroma_vs[] =
"uniform vec2 EyeToSourceUVScale;\n"
"uniform vec2 EyeToSourceUVOffset;\n"
"uniform mat4 EyeRotationStart;\n"
"uniform mat4 EyeRotationEnd;\n"
"_VS_IN vec2 Position;\n"
"_VS_IN vec4 Color;\n"
"_VS_IN vec2 TexCoord0;\n"
"_VS_IN vec2 TexCoord1;\n"
"_VS_IN vec2 TexCoord2;\n"
"_VS_OUT vec4 oColor;\n"
"_VS_OUT vec2 oTexCoord0;\n"
"_VS_OUT vec2 oTexCoord1;\n"
"_VS_OUT vec2 oTexCoord2;\n"
"void main()\n"
"{\n"
" gl_Position.x = Position.x;\n"
" gl_Position.y = Position.y;\n"
" gl_Position.z = 0.0;\n"
" gl_Position.w = 1.0;\n"
// Vertex inputs are in TanEyeAngle space for the R,G,B channels (i.e. after chromatic aberration and distortion).
// These are now "real world" vectors in direction (x,y,1) relative to the eye of the HMD.
" vec3 TanEyeAngleR = vec3 ( TexCoord0.x, TexCoord0.y, 1.0 );\n"
" vec3 TanEyeAngleG = vec3 ( TexCoord1.x, TexCoord1.y, 1.0 );\n"
" vec3 TanEyeAngleB = vec3 ( TexCoord2.x, TexCoord2.y, 1.0 );\n"
// Accurate time warp lerp vs. faster
#if 1
// Apply the two 3x3 timewarp rotations to these vectors.
" vec3 TransformedRStart = (EyeRotationStart * vec4(TanEyeAngleR, 0)).xyz;\n"
" vec3 TransformedGStart = (EyeRotationStart * vec4(TanEyeAngleG, 0)).xyz;\n"
" vec3 TransformedBStart = (EyeRotationStart * vec4(TanEyeAngleB, 0)).xyz;\n"
" vec3 TransformedREnd = (EyeRotationEnd * vec4(TanEyeAngleR, 0)).xyz;\n"
" vec3 TransformedGEnd = (EyeRotationEnd * vec4(TanEyeAngleG, 0)).xyz;\n"
" vec3 TransformedBEnd = (EyeRotationEnd * vec4(TanEyeAngleB, 0)).xyz;\n"
// And blend between them.
" vec3 TransformedR = mix ( TransformedRStart, TransformedREnd, Color.a );\n"
" vec3 TransformedG = mix ( TransformedGStart, TransformedGEnd, Color.a );\n"
" vec3 TransformedB = mix ( TransformedBStart, TransformedBEnd, Color.a );\n"
#else
" mat3 EyeRotation;\n"
" EyeRotation[0] = mix ( EyeRotationStart[0], EyeRotationEnd[0], Color.a ).xyz;\n"
" EyeRotation[1] = mix ( EyeRotationStart[1], EyeRotationEnd[1], Color.a ).xyz;\n"
" EyeRotation[2] = mix ( EyeRotationStart[2], EyeRotationEnd[2], Color.a ).xyz;\n"
" vec3 TransformedR = EyeRotation * TanEyeAngleR;\n"
" vec3 TransformedG = EyeRotation * TanEyeAngleG;\n"
" vec3 TransformedB = EyeRotation * TanEyeAngleB;\n"
#endif
// Project them back onto the Z=1 plane of the rendered images.
" float RecipZR = 1.0 / TransformedR.z;\n"
" float RecipZG = 1.0 / TransformedG.z;\n"
" float RecipZB = 1.0 / TransformedB.z;\n"
" vec2 FlattenedR = vec2 ( TransformedR.x * RecipZR, TransformedR.y * RecipZR );\n"
" vec2 FlattenedG = vec2 ( TransformedG.x * RecipZG, TransformedG.y * RecipZG );\n"
" vec2 FlattenedB = vec2 ( TransformedB.x * RecipZB, TransformedB.y * RecipZB );\n"
// These are now still in TanEyeAngle space.
// Scale them into the correct [0-1],[0-1] UV lookup space (depending on eye)
" vec2 SrcCoordR = FlattenedR * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
" vec2 SrcCoordG = FlattenedG * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
" vec2 SrcCoordB = FlattenedB * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
" oTexCoord0 = SrcCoordR;\n"
" oTexCoord0.y = 1.0-oTexCoord0.y;\n"
" oTexCoord1 = SrcCoordG;\n"
" oTexCoord1.y = 1.0-oTexCoord1.y;\n"
" oTexCoord2 = SrcCoordB;\n"
" oTexCoord2.y = 1.0-oTexCoord2.y;\n"
" oColor = vec4(Color.r, Color.r, Color.r, Color.r);\n" // Used for vignette fade.
"}\n";
const OVR::CAPI::GL::ShaderBase::Uniform DistortionTimewarpChroma_vs_refl[] =
{
{ "EyeToSourceUVScale", OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 0, 8 },
{ "EyeToSourceUVOffset", OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 8, 8 },
{ "EyeRotationStart", OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 16, 64 },
{ "EyeRotationEnd", OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 80, 64 },
};
}}} // OVR::CAPI::GL
#endif // OVR_CAPI_GL_Shaders_h

View File

@ -0,0 +1,530 @@
/************************************************************************************
Filename : Render_GL_Device.cpp
Content : RenderDevice implementation for OpenGL
Created : September 10, 2012
Authors : David Borel, Andrew Reisse
Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
************************************************************************************/
#include "CAPI_GL_Util.h"
#include "../../Kernel/OVR_Log.h"
#include <string.h>
namespace OVR { namespace CAPI { namespace GL {
// GL Hooks for non-Mac.
#if !defined(OVR_OS_MAC)
#if defined(OVR_OS_WIN32)
PFNWGLGETPROCADDRESS wglGetProcAddress;
PFNGLENABLEPROC glEnable;
PFNGLDISABLEPROC glDisable;
PFNGLGETFLOATVPROC glGetFloatv;
PFNGLGETINTEGERVPROC glGetIntegerv;
PFNGLGETSTRINGPROC glGetString;
PFNGLCOLORMASKPROC glColorMask;
PFNGLCLEARPROC glClear;
PFNGLCLEARCOLORPROC glClearColor;
PFNGLCLEARDEPTHPROC glClearDepth;
PFNGLVIEWPORTPROC glViewport;
PFNGLDRAWELEMENTSPROC glDrawElements;
PFNGLTEXPARAMETERIPROC glTexParameteri;
PFNGLFLUSHPROC glFlush;
PFNGLFINISHPROC glFinish;
PFNGLDRAWARRAYSPROC glDrawArrays;
PFNGLGENTEXTURESPROC glGenTextures;
PFNGLDELETETEXTURESPROC glDeleteTextures;
PFNGLBINDTEXTUREPROC glBindTexture;
PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT;
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
#elif defined(OVR_OS_LINUX)
PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT;
#endif
PFNGLDELETESHADERPROC glDeleteShader;
PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
PFNGLACTIVETEXTUREPROC glActiveTexture;
PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray;
PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
PFNGLBINDBUFFERPROC glBindBuffer;
PFNGLUNIFORMMATRIX3FVPROC glUniformMatrix3fv;
PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv;
PFNGLDELETEBUFFERSPROC glDeleteBuffers;
PFNGLBUFFERDATAPROC glBufferData;
PFNGLGENBUFFERSPROC glGenBuffers;
PFNGLMAPBUFFERPROC glMapBuffer;
PFNGLUNMAPBUFFERPROC glUnmapBuffer;
PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
PFNGLGETSHADERIVPROC glGetShaderiv;
PFNGLCOMPILESHADERPROC glCompileShader;
PFNGLSHADERSOURCEPROC glShaderSource;
PFNGLCREATESHADERPROC glCreateShader;
PFNGLCREATEPROGRAMPROC glCreateProgram;
PFNGLATTACHSHADERPROC glAttachShader;
PFNGLDETACHSHADERPROC glDetachShader;
PFNGLDELETEPROGRAMPROC glDeleteProgram;
PFNGLUNIFORM1IPROC glUniform1i;
PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
PFNGLGETACTIVEUNIFORMPROC glGetActiveUniform;
PFNGLUSEPROGRAMPROC glUseProgram;
PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
PFNGLGETPROGRAMIVPROC glGetProgramiv;
PFNGLLINKPROGRAMPROC glLinkProgram;
PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation;
PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation;
PFNGLUNIFORM4FVPROC glUniform4fv;
PFNGLUNIFORM3FVPROC glUniform3fv;
PFNGLUNIFORM2FVPROC glUniform2fv;
PFNGLUNIFORM1FVPROC glUniform1fv;
PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
#if defined(OVR_OS_WIN32)
void* GetFunction(const char* functionName)
{
return wglGetProcAddress(functionName);
}
#else
void (*GetFunction(const char *functionName))( void )
{
return glXGetProcAddress((GLubyte*)functionName);
}
#endif
void InitGLExtensions()
{
if (glGenVertexArrays)
return;
#if defined(OVR_OS_WIN32)
HINSTANCE hInst = LoadLibrary(L"Opengl32.dll");
if (!hInst)
return;
glGetFloatv = (PFNGLGETFLOATVPROC) GetProcAddress(hInst, "glGetFloatv");
glGetIntegerv = (PFNGLGETINTEGERVPROC) GetProcAddress(hInst, "glGetIntegerv");
glGetString = (PFNGLGETSTRINGPROC) GetProcAddress(hInst, "glGetString");
glEnable = (PFNGLENABLEPROC) GetProcAddress(hInst, "glEnable");
glDisable = (PFNGLDISABLEPROC) GetProcAddress(hInst, "glDisable");
glColorMask = (PFNGLCOLORMASKPROC) GetProcAddress(hInst, "glColorMask");
glClear = (PFNGLCLEARPROC) GetProcAddress(hInst, "glClear" );
glClearColor = (PFNGLCLEARCOLORPROC) GetProcAddress(hInst, "glClearColor");
glClearDepth = (PFNGLCLEARDEPTHPROC) GetProcAddress(hInst, "glClearDepth");
glViewport = (PFNGLVIEWPORTPROC) GetProcAddress(hInst, "glViewport");
glFlush = (PFNGLFLUSHPROC) GetProcAddress(hInst, "glFlush");
glFinish = (PFNGLFINISHPROC) GetProcAddress(hInst, "glFinish");
glDrawArrays = (PFNGLDRAWARRAYSPROC) GetProcAddress(hInst, "glDrawArrays");
glDrawElements = (PFNGLDRAWELEMENTSPROC) GetProcAddress(hInst, "glDrawElements");
glGenTextures = (PFNGLGENTEXTURESPROC) GetProcAddress(hInst,"glGenTextures");
glDeleteTextures = (PFNGLDELETETEXTURESPROC) GetProcAddress(hInst,"glDeleteTextures");
glBindTexture = (PFNGLBINDTEXTUREPROC) GetProcAddress(hInst,"glBindTexture");
glTexParameteri = (PFNGLTEXPARAMETERIPROC) GetProcAddress(hInst, "glTexParameteri");
wglGetProcAddress = (PFNWGLGETPROCADDRESS) GetProcAddress(hInst, "wglGetProcAddress");
wglGetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXTPROC) GetFunction("wglGetSwapIntervalEXT");
wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) GetFunction("wglSwapIntervalEXT");
#elif defined(OVR_OS_LINUX)
glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) GetFunction("glXSwapIntervalEXT");
#endif
glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) GetFunction("glBindFramebufferEXT");
glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) GetFunction("glGenVertexArrays");
glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC) GetFunction("glDeleteVertexArrays");
glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC) GetFunction("glBindVertexArray");
glGenBuffers = (PFNGLGENBUFFERSPROC) GetFunction("glGenBuffers");
glDeleteBuffers = (PFNGLDELETEBUFFERSPROC) GetFunction("glDeleteBuffers");
glBindBuffer = (PFNGLBINDBUFFERPROC) GetFunction("glBindBuffer");
glBufferData = (PFNGLBUFFERDATAPROC) GetFunction("glBufferData");
glMapBuffer = (PFNGLMAPBUFFERPROC) GetFunction("glMapBuffer");
glUnmapBuffer = (PFNGLUNMAPBUFFERPROC) GetFunction("glUnmapBuffer");
glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC) GetFunction("glDisableVertexAttribArray");
glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC) GetFunction("glVertexAttribPointer");
glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC) GetFunction("glEnableVertexAttribArray");
glActiveTexture = (PFNGLACTIVETEXTUREPROC) GetFunction("glActiveTexture");
glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC) GetFunction("glUniformMatrix3fv");
glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC) GetFunction("glUniformMatrix4fv");
glUniform1i = (PFNGLUNIFORM1IPROC) GetFunction("glUniform1i");
glUniform1fv = (PFNGLUNIFORM1FVPROC) GetFunction("glUniform1fv");
glUniform2fv = (PFNGLUNIFORM2FVPROC) GetFunction("glUniform2fv");
glUniform3fv = (PFNGLUNIFORM3FVPROC) GetFunction("glUniform3fv");
glUniform2fv = (PFNGLUNIFORM2FVPROC) GetFunction("glUniform2fv");
glUniform4fv = (PFNGLUNIFORM4FVPROC) GetFunction("glUniform4fv");
glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) GetFunction("glGetUniformLocation");
glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC) GetFunction("glGetActiveUniform");
glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) GetFunction("glGetShaderInfoLog");
glGetShaderiv = (PFNGLGETSHADERIVPROC) GetFunction("glGetShaderiv");
glCompileShader = (PFNGLCOMPILESHADERPROC) GetFunction("glCompileShader");
glShaderSource = (PFNGLSHADERSOURCEPROC) GetFunction("glShaderSource");
glCreateShader = (PFNGLCREATESHADERPROC) GetFunction("glCreateShader");
glDeleteShader = (PFNGLDELETESHADERPROC) GetFunction("glDeleteShader");
glCreateProgram = (PFNGLCREATEPROGRAMPROC) GetFunction("glCreateProgram");
glDeleteProgram = (PFNGLDELETEPROGRAMPROC) GetFunction("glDeleteProgram");
glUseProgram = (PFNGLUSEPROGRAMPROC) GetFunction("glUseProgram");
glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) GetFunction("glGetProgramInfoLog");
glGetProgramiv = (PFNGLGETPROGRAMIVPROC) GetFunction("glGetProgramiv");
glLinkProgram = (PFNGLLINKPROGRAMPROC) GetFunction("glLinkProgram");
glAttachShader = (PFNGLATTACHSHADERPROC) GetFunction("glAttachShader");
glDetachShader = (PFNGLDETACHSHADERPROC) GetFunction("glDetachShader");
glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC) GetFunction("glBindAttribLocation");
glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC) GetFunction("glGetAttribLocation");
}
#endif
Buffer::Buffer(RenderParams* rp) : pParams(rp), Size(0), Use(0), GLBuffer(0)
{
}
Buffer::~Buffer()
{
if (GLBuffer)
glDeleteBuffers(1, &GLBuffer);
}
bool Buffer::Data(int use, const void* buffer, size_t size)
{
Size = size;
switch (use & Buffer_TypeMask)
{
case Buffer_Index: Use = GL_ELEMENT_ARRAY_BUFFER; break;
default: Use = GL_ARRAY_BUFFER; break;
}
if (!GLBuffer)
glGenBuffers(1, &GLBuffer);
int mode = GL_DYNAMIC_DRAW;
if (use & Buffer_ReadOnly)
mode = GL_STATIC_DRAW;
glBindBuffer(Use, GLBuffer);
glBufferData(Use, size, buffer, mode);
return 1;
}
void* Buffer::Map(size_t, size_t, int)
{
int mode = GL_WRITE_ONLY;
//if (flags & Map_Unsynchronized)
// mode |= GL_MAP_UNSYNCHRONIZED;
glBindBuffer(Use, GLBuffer);
void* v = glMapBuffer(Use, mode);
return v;
}
bool Buffer::Unmap(void*)
{
glBindBuffer(Use, GLBuffer);
int r = glUnmapBuffer(Use);
return r != 0;
}
ShaderSet::ShaderSet()
{
Prog = glCreateProgram();
}
ShaderSet::~ShaderSet()
{
glDeleteProgram(Prog);
}
GLint ShaderSet::GetGLShader(Shader* s)
{
switch (s->Stage)
{
case Shader_Vertex: {
ShaderImpl<Shader_Vertex, GL_VERTEX_SHADER>* gls = (ShaderImpl<Shader_Vertex, GL_VERTEX_SHADER>*)s;
return gls->GLShader;
} break;
case Shader_Fragment: {
ShaderImpl<Shader_Fragment, GL_FRAGMENT_SHADER>* gls = (ShaderImpl<Shader_Fragment, GL_FRAGMENT_SHADER>*)s;
return gls->GLShader;
} break;
default: break;
}
return -1;
}
void ShaderSet::SetShader(Shader *s)
{
Shaders[s->Stage] = s;
GLint GLShader = GetGLShader(s);
glAttachShader(Prog, GLShader);
if (Shaders[Shader_Vertex] && Shaders[Shader_Fragment])
Link();
}
void ShaderSet::UnsetShader(int stage)
{
if (Shaders[stage] == NULL)
return;
GLint GLShader = GetGLShader(Shaders[stage]);
glDetachShader(Prog, GLShader);
Shaders[stage] = NULL;
}
bool ShaderSet::SetUniform(const char* name, int n, const float* v)
{
for (unsigned int i = 0; i < UniformInfo.GetSize(); i++)
if (!strcmp(UniformInfo[i].Name.ToCStr(), name))
{
OVR_ASSERT(UniformInfo[i].Location >= 0);
glUseProgram(Prog);
switch (UniformInfo[i].Type)
{
case 1: glUniform1fv(UniformInfo[i].Location, n, v); break;
case 2: glUniform2fv(UniformInfo[i].Location, n/2, v); break;
case 3: glUniform3fv(UniformInfo[i].Location, n/3, v); break;
case 4: glUniform4fv(UniformInfo[i].Location, n/4, v); break;
case 12: glUniformMatrix3fv(UniformInfo[i].Location, 1, 1, v); break;
case 16: glUniformMatrix4fv(UniformInfo[i].Location, 1, 1, v); break;
default: OVR_ASSERT(0);
}
return 1;
}
OVR_DEBUG_LOG(("Warning: uniform %s not present in selected shader", name));
return 0;
}
bool ShaderSet::Link()
{
glLinkProgram(Prog);
GLint r;
glGetProgramiv(Prog, GL_LINK_STATUS, &r);
if (!r)
{
GLchar msg[1024];
glGetProgramInfoLog(Prog, sizeof(msg), 0, msg);
OVR_DEBUG_LOG(("Linking shaders failed: %s\n", msg));
if (!r)
return 0;
}
glUseProgram(Prog);
UniformInfo.Clear();
LightingVer = 0;
UsesLighting = 0;
GLint uniformCount = 0;
glGetProgramiv(Prog, GL_ACTIVE_UNIFORMS, &uniformCount);
OVR_ASSERT(uniformCount >= 0);
for(GLuint i = 0; i < (GLuint)uniformCount; i++)
{
GLsizei namelen;
GLint size = 0;
GLenum type;
GLchar name[32];
glGetActiveUniform(Prog, i, sizeof(name), &namelen, &size, &type, name);
if (size)
{
int l = glGetUniformLocation(Prog, name);
char *np = name;
while (*np)
{
if (*np == '[')
*np = 0;
np++;
}
Uniform u;
u.Name = name;
u.Location = l;
u.Size = size;
switch (type)
{
case GL_FLOAT: u.Type = 1; break;
case GL_FLOAT_VEC2: u.Type = 2; break;
case GL_FLOAT_VEC3: u.Type = 3; break;
case GL_FLOAT_VEC4: u.Type = 4; break;
case GL_FLOAT_MAT3: u.Type = 12; break;
case GL_FLOAT_MAT4: u.Type = 16; break;
default:
continue;
}
UniformInfo.PushBack(u);
if (!strcmp(name, "LightCount"))
UsesLighting = 1;
}
else
break;
}
ProjLoc = glGetUniformLocation(Prog, "Proj");
ViewLoc = glGetUniformLocation(Prog, "View");
for (int i = 0; i < 8; i++)
{
char texv[32];
OVR_sprintf(texv, 10, "Texture%d", i);
TexLoc[i] = glGetUniformLocation(Prog, texv);
if (TexLoc[i] < 0)
break;
glUniform1i(TexLoc[i], i);
}
if (UsesLighting)
OVR_ASSERT(ProjLoc >= 0 && ViewLoc >= 0);
return 1;
}
bool ShaderBase::SetUniform(const char* name, int n, const float* v)
{
for(unsigned i = 0; i < UniformReflSize; i++)
{
if (!strcmp(UniformRefl[i].Name, name))
{
memcpy(UniformData + UniformRefl[i].Offset, v, n * sizeof(float));
return 1;
}
}
return 0;
}
bool ShaderBase::SetUniformBool(const char* name, int n, const bool* v)
{
OVR_UNUSED(n);
for(unsigned i = 0; i < UniformReflSize; i++)
{
if (!strcmp(UniformRefl[i].Name, name))
{
memcpy(UniformData + UniformRefl[i].Offset, v, UniformRefl[i].Size);
return 1;
}
}
return 0;
}
void ShaderBase::InitUniforms(const Uniform* refl, size_t reflSize)
{
if(!refl)
{
UniformRefl = NULL;
UniformReflSize = 0;
UniformsSize = 0;
if (UniformData)
{
OVR_FREE(UniformData);
UniformData = 0;
}
return; // no reflection data
}
UniformRefl = refl;
UniformReflSize = reflSize;
UniformsSize = UniformRefl[UniformReflSize-1].Offset + UniformRefl[UniformReflSize-1].Size;
UniformData = (unsigned char*)OVR_ALLOC(UniformsSize);
}
Texture::Texture(RenderParams* rp, int w, int h) : IsUserAllocated(true), pParams(rp), TexId(0), Width(w), Height(h)
{
if (w && h)
glGenTextures(1, &TexId);
}
Texture::~Texture()
{
if (TexId && !IsUserAllocated)
glDeleteTextures(1, &TexId);
}
void Texture::Set(int slot, ShaderStage) const
{
glActiveTexture(GL_TEXTURE0 + slot);
glBindTexture(GL_TEXTURE_2D, TexId);
}
void Texture::SetSampleMode(int sm)
{
glBindTexture(GL_TEXTURE_2D, TexId);
switch (sm & Sample_FilterMask)
{
case Sample_Linear:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
break;
case Sample_Anisotropic:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8);
break;
case Sample_Nearest:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
break;
}
switch (sm & Sample_AddressMask)
{
case Sample_Repeat:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
break;
case Sample_Clamp:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
break;
case Sample_ClampBorder:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
break;
}
}
void Texture::UpdatePlaceholderTexture(GLuint texId, const Sizei& textureSize)
{
if (!IsUserAllocated && TexId && texId != TexId)
glDeleteTextures(1, &TexId);
TexId = texId;
Width = textureSize.w;
Height = textureSize.h;
IsUserAllocated = true;
}
}}}

View File

@ -0,0 +1,537 @@
/************************************************************************************
Filename : CAPI_GL_Util.h
Content : Utility header for OpenGL
Created : March 27, 2014
Authors : Andrew Reisse, David Borel
Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
************************************************************************************/
#ifndef INC_OVR_CAPI_GL_Util_h
#define INC_OVR_CAPI_GL_Util_h
#include "../../OVR_CAPI.h"
#include "../../Kernel/OVR_Array.h"
#include "../../Kernel/OVR_Math.h"
#include "../../Kernel/OVR_RefCount.h"
#include "../../Kernel/OVR_String.h"
#include "../../Kernel/OVR_Types.h"
#include "../../Kernel/OVR_Log.h"
#if defined(OVR_OS_WIN32)
#include <Windows.h>
#endif
#if defined(OVR_OS_MAC)
#include <OpenGL/gl3.h>
#include <OpenGL/gl3ext.h>
#else
#ifndef GL_GLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES
#endif
#include <GL/gl.h>
#include <GL/glext.h>
#if defined(OVR_OS_WIN32)
#include <GL/wglext.h>
#elif defined(OVR_OS_LINUX)
#include <GL/glx.h>
#endif
#endif
namespace OVR { namespace CAPI { namespace GL {
// GL extension Hooks for Non-Mac.
#if !defined(OVR_OS_MAC)
// Let Windows apps build without linking GL.
#if defined(OVR_OS_WIN32)
typedef void (__stdcall *PFNGLENABLEPROC) (GLenum);
typedef void (__stdcall *PFNGLDISABLEPROC) (GLenum);
typedef void (__stdcall *PFNGLGETFLOATVPROC) (GLenum, GLfloat*);
typedef const GLubyte * (__stdcall *PFNGLGETSTRINGPROC) (GLenum);
typedef void (__stdcall *PFNGLGETINTEGERVPROC) (GLenum, GLint*);
typedef PROC (__stdcall *PFNWGLGETPROCADDRESS) (LPCSTR);
typedef void (__stdcall *PFNGLFLUSHPROC) ();
typedef void (__stdcall *PFNGLFINISHPROC) ();
typedef void (__stdcall *PFNGLDRAWARRAYSPROC) (GLenum mode, GLint first, GLsizei count);
typedef void (__stdcall *PFNGLCLEARPROC) (GLbitfield);
typedef void (__stdcall *PFNGLCOLORMASKPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
typedef void (__stdcall *PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
typedef void (__stdcall *PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
typedef void (__stdcall *PFNGLDELETETEXTURESPROC) (GLsizei n, GLuint *textures);
typedef void (__stdcall *PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
typedef void (__stdcall *PFNGLCLEARCOLORPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat a);
typedef void (__stdcall *PFNGLCLEARDEPTHPROC) (GLclampd depth);
typedef void (__stdcall *PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
typedef void (__stdcall *PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
extern PFNWGLGETPROCADDRESS wglGetProcAddress;
extern PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT;
extern PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
extern PFNGLENABLEPROC glEnable;
extern PFNGLDISABLEPROC glDisable;
extern PFNGLCOLORMASKPROC glColorMask;
extern PFNGLGETFLOATVPROC glGetFloatv;
extern PFNGLGETSTRINGPROC glGetString;
extern PFNGLGETINTEGERVPROC glGetIntegerv;
extern PFNGLCLEARPROC glClear;
extern PFNGLCLEARCOLORPROC glClearColor;
extern PFNGLCLEARDEPTHPROC glClearDepth;
extern PFNGLVIEWPORTPROC glViewport;
extern PFNGLDRAWARRAYSPROC glDrawArrays;
extern PFNGLDRAWELEMENTSPROC glDrawElements;
extern PFNGLGENTEXTURESPROC glGenTextures;
extern PFNGLDELETETEXTURESPROC glDeleteTextures;
extern PFNGLBINDTEXTUREPROC glBindTexture;
extern PFNGLTEXPARAMETERIPROC glTexParameteri;
extern PFNGLFLUSHPROC glFlush;
extern PFNGLFINISHPROC glFinish;
#elif defined(OVR_OS_LINUX)
extern PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT;
#endif // defined(OVR_OS_WIN32)
extern PFNGLDELETESHADERPROC glDeleteShader;
extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
extern PFNGLACTIVETEXTUREPROC glActiveTexture;
extern PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray;
extern PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
extern PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
extern PFNGLBINDBUFFERPROC glBindBuffer;
extern PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv;
extern PFNGLDELETEBUFFERSPROC glDeleteBuffers;
extern PFNGLBUFFERDATAPROC glBufferData;
extern PFNGLGENBUFFERSPROC glGenBuffers;
extern PFNGLMAPBUFFERPROC glMapBuffer;
extern PFNGLUNMAPBUFFERPROC glUnmapBuffer;
extern PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
extern PFNGLGETSHADERIVPROC glGetShaderiv;
extern PFNGLCOMPILESHADERPROC glCompileShader;
extern PFNGLSHADERSOURCEPROC glShaderSource;
extern PFNGLCREATESHADERPROC glCreateShader;
extern PFNGLCREATEPROGRAMPROC glCreateProgram;
extern PFNGLATTACHSHADERPROC glAttachShader;
extern PFNGLDETACHSHADERPROC glDetachShader;
extern PFNGLDELETEPROGRAMPROC glDeleteProgram;
extern PFNGLUNIFORM1IPROC glUniform1i;
extern PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
extern PFNGLGETACTIVEUNIFORMPROC glGetActiveUniform;
extern PFNGLUSEPROGRAMPROC glUseProgram;
extern PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
extern PFNGLGETPROGRAMIVPROC glGetProgramiv;
extern PFNGLLINKPROGRAMPROC glLinkProgram;
extern PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation;
extern PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation;
extern PFNGLUNIFORM4FVPROC glUniform4fv;
extern PFNGLUNIFORM3FVPROC glUniform3fv;
extern PFNGLUNIFORM2FVPROC glUniform2fv;
extern PFNGLUNIFORM1FVPROC glUniform1fv;
extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
extern void InitGLExtensions();
#endif // !defined(OVR_OS_MAC)
// Rendering primitive type used to render Model.
enum PrimitiveType
{
Prim_Triangles,
Prim_Lines,
Prim_TriangleStrip,
Prim_Unknown,
Prim_Count
};
// Types of shaders that can be stored together in a ShaderSet.
enum ShaderStage
{
Shader_Vertex = 0,
Shader_Fragment = 2,
Shader_Pixel = 2,
Shader_Count = 3,
};
enum MapFlags
{
Map_Discard = 1,
Map_Read = 2, // do not use
Map_Unsynchronized = 4, // like D3D11_MAP_NO_OVERWRITE
};
// Buffer types used for uploading geometry & constants.
enum BufferUsage
{
Buffer_Unknown = 0,
Buffer_Vertex = 1,
Buffer_Index = 2,
Buffer_Uniform = 4,
Buffer_TypeMask = 0xff,
Buffer_ReadOnly = 0x100, // Buffer must be created with Data().
};
enum TextureFormat
{
Texture_RGBA = 0x0100,
Texture_Depth = 0x8000,
Texture_TypeMask = 0xff00,
Texture_SamplesMask = 0x00ff,
Texture_RenderTarget = 0x10000,
Texture_GenMipmaps = 0x20000,
};
// Texture sampling modes.
enum SampleMode
{
Sample_Linear = 0,
Sample_Nearest = 1,
Sample_Anisotropic = 2,
Sample_FilterMask = 3,
Sample_Repeat = 0,
Sample_Clamp = 4,
Sample_ClampBorder = 8, // If unsupported Clamp is used instead.
Sample_AddressMask =12,
Sample_Count =13,
};
// Rendering parameters/pointers describing GL rendering setup.
struct RenderParams
{
#if defined(OVR_OS_WIN32)
HWND Window;
#elif defined(OVR_OS_LINUX)
Display* Disp;
Window Win;
#endif
ovrSizei RTSize;
int Multisample;
};
class Buffer : public RefCountBase<Buffer>
{
public:
RenderParams* pParams;
size_t Size;
GLenum Use;
GLuint GLBuffer;
public:
Buffer(RenderParams* r);
~Buffer();
GLuint GetBuffer() { return GLBuffer; }
virtual size_t GetSize() { return Size; }
virtual void* Map(size_t start, size_t size, int flags = 0);
virtual bool Unmap(void *m);
virtual bool Data(int use, const void* buffer, size_t size);
};
class Texture : public RefCountBase<Texture>
{
bool IsUserAllocated;
public:
RenderParams* pParams;
GLuint TexId;
int Width, Height;
Texture(RenderParams* rp, int w, int h);
~Texture();
virtual int GetWidth() const { return Width; }
virtual int GetHeight() const { return Height; }
virtual void SetSampleMode(int sm);
// Updates texture to point to specified resources
// - used for slave rendering.
void UpdatePlaceholderTexture(GLuint texId,
const Sizei& textureSize);
virtual void Set(int slot, ShaderStage stage = Shader_Fragment) const;
};
// Base class for vertex and pixel shaders. Stored in ShaderSet.
class Shader : public RefCountBase<Shader>
{
friend class ShaderSet;
protected:
ShaderStage Stage;
public:
Shader(ShaderStage s) : Stage(s) {}
virtual ~Shader() {}
ShaderStage GetStage() const { return Stage; }
virtual void Set(PrimitiveType) const { }
virtual void SetUniformBuffer(class Buffer* buffers, int i = 0) { OVR_UNUSED2(buffers, i); }
protected:
virtual bool SetUniform(const char* name, int n, const float* v) { OVR_UNUSED3(name, n, v); return false; }
virtual bool SetUniformBool(const char* name, int n, const bool* v) { OVR_UNUSED3(name, n, v); return false; }
};
// A group of shaders, one per stage.
// A ShaderSet is applied for rendering with a given fill.
class ShaderSet : public RefCountBase<ShaderSet>
{
protected:
Ptr<Shader> Shaders[Shader_Count];
struct Uniform
{
String Name;
int Location, Size;
int Type; // currently number of floats in vector
};
Array<Uniform> UniformInfo;
public:
GLuint Prog;
GLint ProjLoc, ViewLoc;
GLint TexLoc[8];
bool UsesLighting;
int LightingVer;
ShaderSet();
~ShaderSet();
virtual void SetShader(Shader *s);
virtual void UnsetShader(int stage);
Shader* GetShader(int stage) { return Shaders[stage]; }
virtual void Set(PrimitiveType prim) const
{
glUseProgram(Prog);
for (int i = 0; i < Shader_Count; i++)
if (Shaders[i])
Shaders[i]->Set(prim);
}
// Set a uniform (other than the standard matrices). It is undefined whether the
// uniforms from one shader occupy the same space as those in other shaders
// (unless a buffer is used, then each buffer is independent).
virtual bool SetUniform(const char* name, int n, const float* v);
bool SetUniform1f(const char* name, float x)
{
const float v[] = {x};
return SetUniform(name, 1, v);
}
bool SetUniform2f(const char* name, float x, float y)
{
const float v[] = {x,y};
return SetUniform(name, 2, v);
}
bool SetUniform3f(const char* name, float x, float y, float z)
{
const float v[] = {x,y,z};
return SetUniform(name, 3, v);
}
bool SetUniform4f(const char* name, float x, float y, float z, float w = 1)
{
const float v[] = {x,y,z,w};
return SetUniform(name, 4, v);
}
bool SetUniformv(const char* name, const Vector3f& v)
{
const float a[] = {v.x,v.y,v.z,1};
return SetUniform(name, 4, a);
}
virtual bool SetUniform4x4f(const char* name, const Matrix4f& m)
{
Matrix4f mt = m.Transposed();
return SetUniform(name, 16, &mt.M[0][0]);
}
protected:
GLint GetGLShader(Shader* s);
bool Link();
};
// Fill combines a ShaderSet (vertex, pixel) with textures, if any.
// Every model has a fill.
class ShaderFill : public RefCountBase<ShaderFill>
{
Ptr<ShaderSet> Shaders;
Ptr<class Texture> Textures[8];
void* InputLayout; // HACK this should be abstracted
public:
ShaderFill(ShaderSet* sh) : Shaders(sh) { InputLayout = NULL; }
ShaderFill(ShaderSet& sh) : Shaders(sh) { InputLayout = NULL; }
ShaderSet* GetShaders() const { return Shaders; }
void* GetInputLayout() const { return InputLayout; }
virtual void Set(PrimitiveType prim = Prim_Unknown) const {
Shaders->Set(prim);
for(int i = 0; i < 8; i++)
{
if(Textures[i])
{
Textures[i]->Set(i);
}
}
}
virtual void SetTexture(int i, class Texture* tex) { if (i < 8) Textures[i] = tex; }
};
struct DisplayId
{
// Windows
String MonitorName; // Monitor name for fullscreen mode
// MacOS
long CgDisplayId; // CGDirectDisplayID
DisplayId() : CgDisplayId(0) {}
DisplayId(long id) : CgDisplayId(id) {}
DisplayId(String m, long id=0) : MonitorName(m), CgDisplayId(id) {}
operator bool () const
{
return MonitorName.GetLength() || CgDisplayId;
}
bool operator== (const DisplayId& b) const
{
return CgDisplayId == b.CgDisplayId &&
(strstr(MonitorName.ToCStr(), b.MonitorName.ToCStr()) ||
strstr(b.MonitorName.ToCStr(), MonitorName.ToCStr()));
}
};
class ShaderBase : public Shader
{
public:
RenderParams* pParams;
unsigned char* UniformData;
int UniformsSize;
enum VarType
{
VARTYPE_FLOAT,
VARTYPE_INT,
VARTYPE_BOOL,
};
struct Uniform
{
const char* Name;
VarType Type;
int Offset, Size;
};
const Uniform* UniformRefl;
size_t UniformReflSize;
ShaderBase(RenderParams* rp, ShaderStage stage) : Shader(stage), pParams(rp), UniformData(0), UniformsSize(0) {}
~ShaderBase()
{
if (UniformData)
OVR_FREE(UniformData);
}
void InitUniforms(const Uniform* refl, size_t reflSize);
bool SetUniform(const char* name, int n, const float* v);
bool SetUniformBool(const char* name, int n, const bool* v);
};
template<ShaderStage SStage, GLenum SType>
class ShaderImpl : public ShaderBase
{
friend class ShaderSet;
public:
ShaderImpl(RenderParams* rp, void* s, size_t size, const Uniform* refl, size_t reflSize)
: ShaderBase(rp, SStage)
, GLShader(0)
{
bool success;
OVR_UNUSED(size);
success = Compile((const char*) s);
OVR_ASSERT(success);
InitUniforms(refl, reflSize);
}
~ShaderImpl()
{
if (GLShader)
{
glDeleteShader(GLShader);
GLShader = 0;
}
}
bool Compile(const char* src)
{
if (!GLShader)
GLShader = glCreateShader(GLStage());
glShaderSource(GLShader, 1, &src, 0);
glCompileShader(GLShader);
GLint r;
glGetShaderiv(GLShader, GL_COMPILE_STATUS, &r);
if (!r)
{
GLchar msg[1024];
glGetShaderInfoLog(GLShader, sizeof(msg), 0, msg);
if (msg[0])
OVR_DEBUG_LOG(("Compiling shader\n%s\nfailed: %s\n", src, msg));
return 0;
}
return 1;
}
GLenum GLStage() const
{
return SType;
}
private:
GLuint GLShader;
};
typedef ShaderImpl<Shader_Vertex, GL_VERTEX_SHADER> VertexShader;
typedef ShaderImpl<Shader_Fragment, GL_FRAGMENT_SHADER> FragmentShader;
}}}
#endif // INC_OVR_CAPI_GL_Util_h