Hi,
I recently started to work with SFML.. seems to be a really nice and slim framework which fit's my needs..
I ran into problems when using one window in multiple threads. Background: I want to split my application into different threads:
- thread which render things on screen
- thread which processes user input
- and a few more...
but sadly I can't get it to work without the following exception:
[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
...: poll_for_event: Assertion `!xcb_xlib_threads_sequence_lost' failed.
I called XInitThreads just to be shure that this is not the root of my problem.
My code has the following structure (simplified)
class RenderThread {
virtual void Run() {
while (active) {
window.setActive(true);
glClear(GL_COLOR_BUFFER_BIT);
window.Display();
}
}
}
int main() {
sf::Window window(sf::VideoMode(1024, 768, 32), "...");
window.SetActive(false);
window.UseVerticalSync(true);
RenderThread renderThread(window);
renderThread.Launch();
sf::Event event;
while (active) {
// wait a bit to limit frequecy to 100Hz
while (window.GetEvent(event)) {
if (event.Type == sf::Event::Closed) {
active = false;
}
}
}
renderThread.Wait();
window.close();
return EXIT_SUCCESS;
}
If i add Mutex Locks i can prevent the crash but everything get's extremly slow.
My Questions
- Is the general concept okay?
- When to call setActive? (it's used to connect the opengl context to the active thread, right?)
- If the concept is bullshit, what's the right way to split eventhandling, inputhandling and rendering?
- Is there an example which demonstrates how to do it?
Full source (it's still very simple): http://pastebin.com/hJKp7iBa
I switched to sfml2.0 and in combination with calling XInitThreads there is no exception anymore. Here is the code so far:
#include <iostream>
#include <SFML/Graphics.hpp>
#include <SFML/OpenGL.hpp>
#include <X11/Xlib.h>
class RenderTask
{
public:
RenderTask(sf::RenderWindow& window):window(window) {}
virtual ~RenderTask() {}
void run()
{
window.setActive();
sf::Clock clock;
while (window.isOpen()) {
std::cout << clock.getElapsedTime().asMilliseconds() << std::endl;
clock.restart();
glClear(GL_COLOR_BUFFER_BIT);
window.display();
}
}
private:
sf::RenderWindow& window;
};
int main(int argc, char **argv)
{
XInitThreads();
sf::RenderWindow window(sf::VideoMode(1024, 768), "Test", sf::Style::Close, sf::ContextSettings(32));
window.setVerticalSyncEnabled(true);
window.setActive(false);
RenderTask renderTask(window);
sf::Thread renderThread(&RenderTask::run, &renderTask);
renderThread.launch();
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed)
window.close();
}
}
renderThread.wait();
return 0;
}
But sadly there is still a problem. The printed framerates show very frequently peeks from up to 900ms.. i tried to fix this problems:
- replaced while condition with a boolean
- added a sf::sleep to the main loop to limit it at 100Hz
Maybe someone can test this code (removing X11 dependency) on windows or mac, and tell me if this issue exists there too. Just to make shure that this is a problem of SFMLs Xlib adapter.
My next step is to do the X stuff manually..