SFML community forums
Help => General => Topic started by: Fx8qkaoy on February 01, 2020, 05:28:58 pm
-
To be honest, I work right now on a cheat for a specific game. I have to use threads as I need to perform different instructions at regular time intervals and I also don't want to block the main thread. While some of them are just for computation (such as a console, fetching game data, etc) I also have some that should handle different windows. As example: I need to make a thread which creates a window that will draw a radar. I managed it to open, but not to close, which means it works partially. Below is a resume of the part that involves SFML:
void modifyRadar() {
if (radarActive) {
radarWindow = new sf::RenderWindow(sf::VideoMode(200, 200), "", sf::Style::None);
radarWindow->setFramerateLimit(fps);
radarDrawThread = new std::thread([&]() {
while (radarWindow->isOpen()) {
radarWindow->clear();
for (auto circle : radar)
if (circle->getPosition().x != -99999)
radarWindow->draw(*circle);
radarWindow->display();
}
delete radarWindow;
radarWindow = 0;
});
return;
}
radarWindow->close();
radarDrawThread->join();
delete radarDrawThread;
}
All the variable are available in the outer scope. I did read posts about what I want to do and tried changes such as:
radarDrawThread = new std::thread([&]() {
sf::Context context;
radarWindow->setActive();
while (radarWindow->isOpen()) {
radarWindow->clear();
for (auto circle : radar)
In the first example, this is what stdout shows:
...
An internal OpenGL call failed in RenderTarget.cpp(152).
Expression:
glClearColor(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f)
Error description:
GL_INVALID_OPERATION
The specified operation is not allowed in the current state.
An internal OpenGL call failed in RenderTarget.cpp(153).
Expression:
glClear(GL_COLOR_BUFFER_BIT)
Error description:
GL_INVALID_OPERATION
The specified operation is not allowed in the current state.
An internal OpenGL call failed in Texture.cpp(782).
Expression:
glBindTexture(GL_TEXTURE_2D, 0)
Error description:
GL_INVALID_OPERATION
The specified operation is not allowed in the current state.
...
The functions in the while loop are not hit anymore since the window has closed (expected behavior). When I use the example with sf::Context, when the sf::Context object has to destruct itself an exception is thrown:
Exception thrown: read access violation.
this-> was 0xFFFFFFFFFFFFFFE7.
I do realize that there may be better options for the thing I want to do, especially that I didn't shown the full code due to its size, and while I appreciate very much the opinions, I would like to know how to render different windows in different threads at least for knowledge. I tried different combinations of the sf::Context, setActive(), and the order the windows are created. Before the exception is thrown, this is what stdout has:
Failed to activate OpenGL context: The operation completed successfully.
From what I understand: to draw multiple windows u can use the default sf::Context and use setActive() to manage where the OpenGL calls go, or use multiple sf::Context and no need for setActive() since every window has its context. I also seen that setActive() shall be called also when I render a specific window in another thread rather than where it was made
-
Hi,
take my information with a grain of salt, but I seem to remember the windows message loop must be run from the main thread, and from the main thread only. In other words, you cannot create a window and handle events from another thread.
Correct me if I'm wrong...
-
I just seen the mistake. I don't handle events in the other thread, but indeed may cause problems later, so I updated how to thread works:
drawThread = new std::thread([&]() {
window = new sf::RenderWindow(sf::VideoMode(200, 200), "", sf::Style::None);
window->setFramerateLimit(fps);
handle = window->getSystemHandle();
while (window->isOpen()) {
window->clear();
for (auto circle : radar)
if (circle->getPosition().x != -99999)
window->draw(*circle);
window->display();
}
delete window;
window = 0;
});
The results are EXACTLY the same, regardless using sf::Context or setActive(). Do u have any idea from here?
-
I fixed the problem. Regardless the last code edit, I had to make sure to close() the window from the thread it was created. I expected this one to work from a different thread
If someone use this thread as reference for his problem, I had change the while within thread from while(window->isOpen()) to while(settings.radarActive) which leads to the close() function be actually called by the window destructor (since I do delete at end) rather than me manually (which I did in order to make window->isOpen() return false)