Forum Discussion

🚨 This forum is archived and read-only. To submit a forum post, please visit our new Developer Forum. 🚨
philigaultier's avatar
philigaultier
Honored Guest
11 years ago

ovrHmd_EndFrame triggers GLXBadDrawable (SDK 0.3.2)

Hi,
I'm trying to port this glfw example (https://developer.oculusvr.com/forums/viewtopic.php?f=20&t=8680) into glut.
I have more or less the same code. I'm only working on Linux for now.

The window opens and I can see the scene (with the screen being divided in 2 eye panels) during 1 second, then it crashes.

When I call
ovrHmd_EndFrame(l_Hmd);
, I get this OpenGL error:

X Error of failed request: GLXBadDrawable
Major opcode of failed request: 157 (GLX)
Minor opcode of failed request: 29 (X_GLXGetDrawableAttributes)
Serial number of failed request: 202
Current serial number in output stream: 202
zsh: segmentation fault (core dumped) ./exe


Valgrind and gdb don't tell much, just that the crashing point is located in the driver librairy (/usr/lib/x86_64-linux-gnu/dri/fglrx_dri.so)

The original example with glfw works fine, as well as other Oculus demos.

Do you see any problem with my code?

Thank you for your time.


My code (a bit messy for now, but organized in functions):

#include <GL/glew.h>
#include <GL/freeglut.h>
#include <GL/freeglut_ext.h>
#include <stdexcept>
#include <exception>
#include <stdio.h>
#include <iostream>
using namespace std;





#include <OVR.h>
#include <OVR_CAPI.h>
#include <OVR_CAPI_GL.h>

int window;

const bool l_MultiSampling = false;
const bool l_Spin = true;

ovrHmd l_Hmd;
ovrHmdDesc l_HmdDesc;
ovrFovPort l_EyeFov[2];
ovrGLConfig l_Cfg;
ovrEyeRenderDesc l_EyeRenderDesc[2];
ovrGLTexture l_EyeTexture[2];
int l_DistortionCaps;
ovrSizei l_TextureSize;
GLuint l_TextureId;
GLuint l_FBOId;
GLuint l_DepthBufferId;
float vertices[] = {-0.5, -0.5, 0.0, 0.5, 0.5, -0.5};

GLfloat l_VAPoints[] =
{
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f,-0.5f, 0.5f,
0.5f,-0.5f, 0.5f,
-0.5f,-0.5f,-0.5f,
-0.5f, 0.5f,-0.5f,
0.5f, 0.5f,-0.5f,
0.5f,-0.5f,-0.5f,
0.5f, 0.5f, 0.5f,
0.5f, 0.5f,-0.5f,
-0.5f, 0.5f,-0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f,-0.5f,-0.5f,
0.5f,-0.5f,-0.5f,
0.5f,-0.5f, 0.5f,
-0.5f,-0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
0.5f,-0.5f, 0.5f,
0.5f,-0.5f,-0.5f,
0.5f, 0.5f,-0.5f,
-0.5f,-0.5f,-0.5f,
-0.5f,-0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, 0.5f,-0.5f
};

GLfloat l_VANormals[] =
{
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f,-1.0f,
0.0f, 0.0f,-1.0f,
0.0f, 0.0f,-1.0f,
0.0f, 0.0f,-1.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f,-1.0f, 0.0f,
0.0f,-1.0f, 0.0f,
0.0f,-1.0f, 0.0f,
0.0f,-1.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f
};

GLuint l_VAIndici[] =
{
0, 1, 2, 3,
4, 5, 6, 7,
8, 9, 10, 11,
12, 13, 14, 15,
16, 17, 18, 19,
20, 21, 22, 23
};

void configureHmd(int w = 640, int h = 480);


void RenderCubeVertexArrays(void)
{
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, l_VAPoints);

glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, 0, l_VANormals);

glDrawElements(GL_QUADS, 6*4, GL_UNSIGNED_INT, l_VAIndici);

glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
}

// ============================================================================

void RenderCubeFixedFunction(void)
{
// Obsolete, remains as a fall back for the vertex arrays version...
glBegin(GL_QUADS);
glNormal3f( 0.0f, 0.0f, 1.0f);
glVertex3f( 0.5f, 0.5f, 0.5f);
glVertex3f(-0.5f, 0.5f, 0.5f);
glVertex3f(-0.5f,-0.5f, 0.5f);
glVertex3f( 0.5f,-0.5f, 0.5f);

glNormal3f( 0.0f, 0.0f,-1.0f);
glVertex3f(-0.5f,-0.5f,-0.5f);
glVertex3f(-0.5f, 0.5f,-0.5f);
glVertex3f( 0.5f, 0.5f,-0.5f);
glVertex3f( 0.5f,-0.5f,-0.5f);

glNormal3f( 0.0f, 1.0f, 0.0f);
glVertex3f( 0.5f, 0.5f, 0.5f);
glVertex3f( 0.5f, 0.5f,-0.5f);
glVertex3f(-0.5f, 0.5f,-0.5f);
glVertex3f(-0.5f, 0.5f, 0.5f);

glNormal3f( 0.0f,-1.0f, 0.0f);
glVertex3f(-0.5f,-0.5f,-0.5f);
glVertex3f( 0.5f,-0.5f,-0.5f);
glVertex3f( 0.5f,-0.5f, 0.5f);
glVertex3f(-0.5f,-0.5f, 0.5f);

glNormal3f( 1.0f, 0.0f, 0.0f);
glVertex3f( 0.5f, 0.5f, 0.5f);
glVertex3f( 0.5f,-0.5f, 0.5f);
glVertex3f( 0.5f,-0.5f,-0.5f);
glVertex3f( 0.5f, 0.5f,-0.5f);

glNormal3f(-1.0f, 0.0f, 0.0f);
glVertex3f(-0.5f,-0.5f,-0.5f);
glVertex3f(-0.5f,-0.5f, 0.5f);
glVertex3f(-0.5f, 0.5f, 0.5f);
glVertex3f(-0.5f, 0.5f,-0.5f);
glEnd();
}

// ============================================================================


void getError()
{

for(GLenum currError = glGetError(); currError != GL_NO_ERROR; currError = glGetError())
{
cout << "Error: ";

switch(currError)
{
case GL_INVALID_ENUM:
cout << "GL_INVALID_ENUM";
break;
case GL_INVALID_VALUE:
cout << "GL_INVALID_VALUE";
break;
case GL_INVALID_OPERATION:
cout << "GL_INVALID_OPERATION";
break;
case GL_STACK_OVERFLOW:
cout << "GL_STACK_OVERFLOW";
break;
case GL_STACK_UNDERFLOW:
cout << "GL_STACK_UNDERFLOW";
break;
case GL_OUT_OF_MEMORY:
cout << "GL_OUT_OF_MEMORY";
break;
case GL_INVALID_FRAMEBUFFER_OPERATION:
cout << "GL_INVALID_FRAMEBUFFER_OPERATION";
break;
case GL_TABLE_TOO_LARGE:
cout << "GL_TABLE_TOO_LARGE";
break;
default:
cout << "Unknow error";
break;
}
cout << endl;
}
cout << "No error left" << endl;
}

static void SetOpenGLState(void)
{
// Some state...
glEnable(GL_CULL_FACE);
glEnable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
if (l_MultiSampling) glEnable(GL_MULTISAMPLE);

// Some (stationary) lights...
GLfloat l_Light0Position[] = { 5.0f, 6.0f, 3.0f, 0.0f };
GLfloat l_Light0Diffuse[] = { 1.0f, 0.8f, 0.6f, 1.0f };
glLightfv(GL_LIGHT0, GL_POSITION, l_Light0Position);
glLightfv(GL_LIGHT0, GL_DIFFUSE, l_Light0Diffuse);
glEnable(GL_LIGHT0);

GLfloat l_Light1Position[] = { -5.0f, -6.0f, 5.0f, 0.0f };
GLfloat l_Light1Diffuse[] = { 0.6f, 0.8f, 1.0f, 1.0f };
glLightfv(GL_LIGHT1, GL_POSITION, l_Light1Position);
glLightfv(GL_LIGHT1, GL_DIFFUSE, l_Light1Diffuse);
glEnable(GL_LIGHT1);

// Material...
GLfloat l_MaterialSpecular[] = { 0.3f, 0.3f, 0.3f, 1.0f };
GLfloat l_MaterialShininess[] = { 10.0f };
glMaterialfv(GL_FRONT, GL_SPECULAR, l_MaterialSpecular);
glMaterialfv(GL_FRONT, GL_SHININESS, l_MaterialShininess);
}

// =============================================================================






void reshape(int w, int h)
{
cout << "Reshape" << endl;

configureHmd(w, h);


glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glUseProgram(0);

cout << "End reshape" << endl;
}

void initHmd()
{
// Initialize LibOVR...
ovr_Initialize();

l_Hmd = ovrHmd_Create(0);
if (!l_Hmd) l_Hmd = ovrHmd_CreateDebug(ovrHmd_DK1);
if(!l_Hmd) throw runtime_error("Cannot create the debug dk1");

ovrHmd_GetDesc(l_Hmd, &l_HmdDesc);

// Start the sensor which provides the Rift’s pose and motion.
ovrHmd_StartSensor(l_Hmd, ovrSensorCap_Orientation | ovrSensorCap_YawCorrection | ovrSensorCap_Position, ovrSensorCap_Orientation);

}

void initTexture()
{


// The texture we're going to render to...

glGenTextures(1, &l_TextureId);
// "Bind" the newly created texture : all future texture functions will modify this texture...
glBindTexture(GL_TEXTURE_2D, l_TextureId);
// Give an empty image to OpenGL (the last "0")
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, l_TextureSize.w, l_TextureSize.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
// Linear filtering...
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

}

void initFBO()
{
// We will do some offscreen rendering, setup FBO...
ovrSizei l_TextureSizeLeft = ovrHmd_GetFovTextureSize(l_Hmd, ovrEye_Left, l_HmdDesc.DefaultEyeFov[0], 1.0f);
ovrSizei l_TextureSizeRight = ovrHmd_GetFovTextureSize(l_Hmd, ovrEye_Right, l_HmdDesc.DefaultEyeFov[1], 1.0f);


l_TextureSize.w = l_TextureSizeLeft.w + l_TextureSizeRight.w;
l_TextureSize.h = (l_TextureSizeLeft.h>l_TextureSizeRight.h ? l_TextureSizeLeft.h : l_TextureSizeRight.h);

// Create Depth Buffer...
cout << "Texture: " << l_TextureSize.w << " " << l_TextureSize.h << endl;

// Create FBO...

glGenFramebuffers(1, &l_FBOId);
glBindFramebuffer(GL_FRAMEBUFFER, l_FBOId);

}

void initDepthBuffer()
{


glGenRenderbuffers(1, &l_DepthBufferId);
glBindRenderbuffer(GL_RENDERBUFFER, l_DepthBufferId);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, l_TextureSize.w, l_TextureSize.h);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, l_DepthBufferId);

// Set the texture as our colour attachment #0...
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, l_TextureId, 0);

// Set the list of draw buffers...
GLenum l_GLDrawBuffers[1] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, l_GLDrawBuffers); // "1" is the size of DrawBuffers

// Check if everything is OK...
GLenum l_Check = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
if (l_Check!=GL_FRAMEBUFFER_COMPLETE)
{


printf("There is a problem with the FBO.\n");
getError();

exit(EXIT_FAILURE);
}

// Unbind...
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);

}

void configureHmd(int w, int h)
{
cout << "configure Hmd" << endl;
// Oculus Rift eye configurations...
l_EyeFov[0] = l_HmdDesc.DefaultEyeFov[0];
l_EyeFov[1] = l_HmdDesc.DefaultEyeFov[1];

l_Cfg.OGL.Header.API = ovrRenderAPI_OpenGL;
l_Cfg.OGL.Header.Multisample = (l_MultiSampling ? 1 : 0);
l_Cfg.OGL.Header.RTSize.w = w;
l_Cfg.OGL.Header.RTSize.h = h;
l_Cfg.OGL.Win = window;
l_Cfg.OGL.Disp = glXGetCurrentDisplay();




l_DistortionCaps = ovrDistortionCap_Chromatic | ovrDistortionCap_TimeWarp;

if(!ovrHmd_ConfigureRendering(l_Hmd, &l_Cfg.Config, l_DistortionCaps, l_EyeFov, l_EyeRenderDesc))
throw runtime_error("Cannot configure rendering");


l_EyeTexture[0].OGL.Header.API = ovrRenderAPI_OpenGL;
l_EyeTexture[0].OGL.Header.TextureSize.w = l_TextureSize.w;
l_EyeTexture[0].OGL.Header.TextureSize.h = l_TextureSize.h;
l_EyeTexture[0].OGL.Header.RenderViewport.Pos.x = 0;
l_EyeTexture[0].OGL.Header.RenderViewport.Pos.y = 0;
l_EyeTexture[0].OGL.Header.RenderViewport.Size.w = l_TextureSize.w/2;
l_EyeTexture[0].OGL.Header.RenderViewport.Size.h = l_TextureSize.h;
l_EyeTexture[0].OGL.TexId = l_TextureId;

cout << "Texture id: " << l_TextureId << endl;
cout << "FBO id: " << l_FBOId << endl;

// Right eye the same, except for the x-position in the texture...
l_EyeTexture[1] = l_EyeTexture[0];
l_EyeTexture[1].OGL.Header.RenderViewport.Pos.x = (l_TextureSize.w+1)/2;

cout << "End configure Hmd" << endl;
}

void release()
{

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glUseProgram(0);
}

void setupHmd()
{



printf("Vendor: %s\n", (char*)glGetString(GL_VENDOR));
printf("Renderer: %s\n", (char*)glGetString(GL_RENDERER));

// Create some lights, materials, etc...
SetOpenGLState();
initHmd();

initFBO();
initTexture();
initDepthBuffer();

release();

}

void display()
{
cout << "Display" << endl;
configureHmd();

GLfloat l_SpinX;
GLfloat l_SpinY;

if (l_Spin)
{
l_SpinX = 30.0f;
l_SpinY = 40.0f;
}
else
{
l_SpinX = 30.0f;
l_SpinY = 40.0f;
}

ovrFrameTiming m_HmdFrameTiming = ovrHmd_BeginFrame(l_Hmd, 0);

// Bind the FBO...
glBindFramebuffer(GL_FRAMEBUFFER, l_FBOId);
// Clear...
glClearColor(0.2f, 0.3f, 0.4f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

cout << "Before eye loop" << endl;
for (int l_EyeIndex=0; l_EyeIndex<ovrEye_Count; l_EyeIndex++)
{
ovrEyeType l_Eye = l_HmdDesc.EyeRenderOrder[l_EyeIndex];
ovrPosef l_EyePose = ovrHmd_BeginEyeRender(l_Hmd, l_Eye);

glViewport(l_EyeTexture[l_Eye].OGL.Header.RenderViewport.Pos.x,
l_EyeTexture[l_Eye].OGL.Header.RenderViewport.Pos.y,
l_EyeTexture[l_Eye].OGL.Header.RenderViewport.Size.w,
l_EyeTexture[l_Eye].OGL.Header.RenderViewport.Size.h
);

// Get Projection and ModelView matrici from the device...
OVR::Matrix4f l_ProjectionMatrix = ovrMatrix4f_Projection(
l_EyeRenderDesc[l_Eye].Fov, 0.3f, 100.0f, true);
OVR::Quatf l_Orientation = OVR::Quatf(l_EyePose.Orientation);
OVR::Matrix4f l_ModelViewMatrix = OVR::Matrix4f(l_Orientation.Inverted());

// Pass matrici on to OpenGL...
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMultMatrixf(&(l_ProjectionMatrix.Transposed().M[0][0]));
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Translate for specific eye based on IPD...
glTranslatef(l_EyeRenderDesc[l_Eye].ViewAdjust.x,
l_EyeRenderDesc[l_Eye].ViewAdjust.y,
l_EyeRenderDesc[l_Eye].ViewAdjust.z);
// Multiply with orientation retrieved from sensor...
glMultMatrixf(&(l_ModelViewMatrix.Transposed().M[0][0]));
// Move back a bit to show scene in front of us...
glTranslatef(0.0f, 0.0f, -2.0f);
// Make the cube spin...
glRotatef(l_SpinX, 1.0f, 0.0f, 0.0f);
glRotatef(l_SpinY, 0.0f, 1.0f, 0.0f);

// Render...
// RenderCubeFixedFunction();
RenderCubeVertexArrays();

ovrHmd_EndEyeRender(l_Hmd, l_Eye, l_EyePose, &l_EyeTexture[l_Eye].Texture);
}
cout << "End eye loop" << endl;

// Unbind the FBO, back to normal drawing...
glBindFramebuffer(GL_FRAMEBUFFER, 0);

cout << "End frame" << endl;
getError();
ovrHmd_EndFrame(l_Hmd);

cout << "End end frame" << endl;

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glUseProgram(0);

cout << "End Display" << endl;
}


int main( int argc, char *argv[ ])
{


glutInit(&argc, argv);
//glutInitContextVersion (3, 3);
//glutInitContextFlags (GLUT_FORWARD_COMPATIBLE | GLUT_DEBUG);
//glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH | GLUT_MULTISAMPLE);
glutInitWindowSize(640,480);
window = glutCreateWindow("Glut/Oculus example");
//glutFullScreen();

glewExperimental = GL_TRUE;
GLenum l_Result = glewInit();
if (l_Result!=GLEW_OK)
{
printf("glewInit() error.\n");
exit(EXIT_FAILURE);
}
getError();


setupHmd();



glutDisplayFunc(display);

glutReshapeFunc(reshape);


glutMainLoop();


ovrHmd_Destroy(l_Hmd);
ovr_Shutdown();

exit(EXIT_SUCCESS);
}



Makefile:

CC = clang++


OVR_SDK = /home/gaultier/OculusSDK0.3.2/LibOVR


FLAGS = -Wall -ggdb -rdynamic
CFLAGS = -I$(OVR_SDK)/Include/ -I$(OVR_SDK)/Src
LDFLAGS += -L/usr/X11R6/lib64 -L$(OVR_SDK)/Lib/Linux/Debug/x86_64
#OVR
LDFLAGS += -lovr -lpthread -lX11 -ludev -lXinerama
#Glut
LDFLAGS += -lGL -lglut -lGLEW -lXxf86vm -lXext -lXcursor -lXrandr -lXi
TARGET = exe

all: target

target: main.o
$(CC) -o $(TARGET) $^ $(LDFLAGS) $(FLAGS)

main.o: main.cpp
$(CC) -c $(CFLAGS) $^ $(FLAGS)


clean:
rm -rf *o *.gch $(TARGET)

2 Replies

  • "philigaultier" wrote:

    window = glutCreateWindow("Glut/Oculus example");

    ...

      l_Cfg.OGL.Win = window;
      l_Cfg.OGL.Disp = glXGetCurrentDisplay();

    The int returned by glutCreateWindow(..) is not the right kind of "window". You need an X drawable.

    It might work to call glXGetCurrentDrawable() just after glutCreateWindow(..) instead and pass the result of the glX function:

    glutCreateWindow("Glut/Oculus example");
    window = glXGetCurrentDrawable();