I am writing and OpenGL application with SFML 2.0. According to the
tutorial, rendering can be performed in a separate thread with event handling in the main thread. So I set up my code like the tutorial (set the main thread context as not active, and then set the thread's context as active), and the application crashes when it goes to pop an event off the stack. The only documentation ( the tutorial ) says separating these into separate threads is doable, and the code worked fine when the application was single threaded. I am not sure what is wrong as I am still too new to SFML to know the ins and outs of the event handling system. Does anyone know what could be wrong?
Here is the relevant code:
int main(int argc, char *argv[]) {
sf::ContextSettings settings;
settings.depthBits = 0;
settings.stencilBits = 0;
settings.antialiasingLevel = 0;
settings.majorVersion = 2;
settings.minorVersion = 0;
//Close style disables window resizing :)
sf::Window window(sf::VideoMode(SCREEN_WIDTH, SCREEN_HEIGHT), "SFML Graphical Test", sf::Style::Close, settings);
// deactivate its OpenGL context
window.setActive(false);
// launch the rendering thread
sf::Thread thread(&renderThread, &window);
thread.launch();
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
// end the program
window.close();
}
else if (event.type == sf::Event::KeyPressed) {
if (event.key.code == sf::Keyboard::Escape) {
done = true;
}
if (event.key.code == sf::Keyboard::W) {
up = true;
}
if (event.key.code == sf::Keyboard::S) {
down = true;
}
if (event.key.code == sf::Keyboard::A) {
left = true;
}
if (event.key.code == sf::Keyboard::D) {
right = true;
}
}
else if (event.type == sf::Event::KeyReleased) {
if (event.key.code == sf::Keyboard::W) {
up = false;
}
if (event.key.code == sf::Keyboard::S) {
down = false;
}
if (event.key.code == sf::Keyboard::A) {
left = false;
}
if (event.key.code == sf::Keyboard::D) {
right = false;
}
}
}
}
thread.wait();
return 0;
}
void setupVBO(RenderInfo info) {
//Bind the VBO buffer
glBindBuffer(GL_ARRAY_BUFFER, verVBOID);
int vertBufferSize = sizeof(Vertex)*info.vertLength;
//Set up the buffer, but don't give it the data yet.
glBufferData(GL_ARRAY_BUFFER, vertBufferSize, NULL, GL_STATIC_DRAW);
//Put the vertex array in the buffer
glBufferSubData(GL_ARRAY_BUFFER, 0, vertBufferSize, &info.verticies[0].location[0]);
int indexBufferSize = sizeof(Vertex)*info.indexLength;
//Bind the index vob and set up the buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indVBOID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexBufferSize, NULL, GL_STATIC_DRAW);
//unsigned short *indicies = info.indecies;
//Put the index in the buffer
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indexBufferSize, &info.indecies[0]);
//Go back to the vertex buffer
glBindBuffer(GL_ARRAY_BUFFER, verVBOID);
//Enable the vertex array
glEnableClientState(GL_VERTEX_ARRAY);
//Point to where the vertexes are in the vertex struct
glVertexPointer(3, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(0));
//Enable first texture for rendering
glClientActiveTexture(GL_TEXTURE0);
//Enable use of the texture coordinates in the array
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
//Point to the texture coordinates in the buffer
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(12));
//Bind the index buffer again.
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indVBOID);
}
void renderThread(sf::Window* window) {
window->setFramerateLimit(FPS);
window->setVerticalSyncEnabled(true);
window->setActive(true);
//Enable Texturing and Alpha Tansparency
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//Set the viewport
glViewport( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
//Set the clear function
glClear( GL_COLOR_BUFFER_BIT );
//Switch to projection mode and reset the matrix
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
//Set up a 2D projection
gluOrtho2D(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0);
//Switch to modelview and reset to identity matrix
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
//Generate VBOIDs
glGenBuffers(1, &verVBOID);
glGenBuffers(1, &indVBOID);
//Set clear color and clear screen
glClearColor ( 0.0, 0.0, 0.0, 1.0 );
glClear ( GL_COLOR_BUFFER_BIT );
//Set initial camera position
camera.setPos(-1*SCREEN_WIDTH/2,-1*SCREEN_HEIGHT/2);
//Load stuff
Map testMap;
testMap.loadMap("maps/0.map");
RenderInfo info = testMap.makeRenderList(0);
setupVBO(info);
while(window->isOpen()) {
glLoadIdentity();
glClear( GL_COLOR_BUFFER_BIT );
if (up)
camera.moveUp(1);
if (down)
camera.moveDown(1);
if (left)
camera.moveLeft(1);
if (right)
camera.moveRight(1);
camera.place();
//Draw the elements in the buffer.
//We want to draw quads, we will render all elements, they are unsigned shorts, and they are at Buffer offset 0.
glDrawElements(GL_QUADS, info.indexLength, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));
window->display();
}
//Disable the client states we used
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
//Delete the buffers
glDeleteBuffers(1, &indVBOID);
glDeleteBuffers(1, &verVBOID);
}