Bienvenue, Invité. Merci de vous connecter ou de vous inscrire.
Avez-vous perdu votre e-mail d'activation ?

Auteur Sujet: SFML et thread du c++11.  (Lu 4022 fois)

0 Membres et 1 Invité sur ce sujet

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
SFML et thread du c++11.
« le: Août 11, 2013, 10:15:29 pm »
Salut, j'ai testé un code pour faire l'affichage et gestion d'évènement dans un thread, et le rendu dans un autre thread, avec les thread du c++11, mais celà ne marche pas, voici le code :

Thread d'affichage :
#ifndef DISPLAYER
#define DISPLAYER
#include "updater.h"
#include <iostream>
class RenderComponent {
public :
    RenderComponent();
    void start();
    void run();
    void setActive(bool b);
private :
    sf::RenderWindow window;
    std::thread m_thread;
    Updater updater;
    bool running;
};
#endif // DISPLAYER
 
#include "displayer.h"
using namespace std;
using namespace sf;
RenderComponent::RenderComponent () : updater(*this), window (sf::VideoMode(800, 600), "My window") {
    running = false;
}
void RenderComponent::setActive(bool b) {
    window.setActive(b);
}
void RenderComponent::start() {
    updater.start();
    running = true;
    m_thread = thread (&RenderComponent::run, this);
}
void RenderComponent::run() {
     // création de la fenêtre

    while (running) {
        // on fait tourner le programme tant que la fenêtre n'a pas été fermée
        while (window.isOpen())
        {
            // on traite tous les évènements de la fenêtre qui ont été générés depuis la dernière itération de la boucle
            sf::Event event;
            while (window.pollEvent(event))
            {
                // fermeture de la fenêtre lorsque l'utilisateur le souhaite
                if (event.type == sf::Event::Closed) {
                    window.close();
                    running = false;
                    m_thread.join();
                }
            }

            // effacement de la fenêtre en noir
            /*unique_lock<mutex> locker(g_lock_update_component);
            g_signal.wait(locker, [&](){return !updater.isGDone();});*/


            window.clear(sf::Color::Black);
            window.draw(updater.getRectangle());
            window.display();
        }
    }
}
 
Thread de rendu :
#ifndef UPDATER
#define UPDATER
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/System.hpp>
#include <thread>
#include "globals.h"
#include <random>
class RenderComponent;
class Updater {
public :
    Updater(RenderComponent &renderComponent);
    void start();
    void stop ();
    void run();
    bool isGDone();
    sf::RectangleShape getRectangle ();
private :
    std::thread m_thread;
    sf::RectangleShape rectangle;
    bool running, gDone;
    RenderComponent &renderComponent;
};
#endif // UPDATER

[code=cpp]
#include "updater.h"
#include "displayer.h"
using namespace std;
using namespace sf;
Updater::Updater(RenderComponent &renderComponent) : renderComponent (renderComponent) {
    rectangle = RectangleShape(Vector2f(0, 0));
    rectangle.setSize(Vector2f(100, 100));
    running = gDone = false;
}
bool Updater::isGDone() {
    return gDone;
}
void Updater::start() {
    running = true;
    m_thread = thread (&Updater::run, this);
}
void Updater::stop() {
    running = false;
    m_thread.join();
}
void Updater::run() {
    while (running) {
        /*renderComponent.setActive(false);
        unique_lock<mutex> locker(g_lock_update_component);*/

       renderComponent.setActive(false);
        gDone=false;

        int posX = rand() % 800;
        int posY = rand() % 600;
        rectangle.setPosition(posX, posY);
        gDone = true;
        renderComponent.setActive(true);
       // g_signal.notify_one();
    }
}
RectangleShape Updater::getRectangle () {
    return rectangle;
}
 
Et le main :
#include "displayer.h"
#include <random>
#include <ctime>
int main () {
    srand(time(NULL));
    RenderComponent renderComponent;
    renderComponent.start();
    return EXIT_SUCCESS;
}
 

Il m'affiche le message suivant en console : Failed to activate the window's context.

« Modifié: Août 11, 2013, 10:20:16 pm par Lolilolight »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : SFML et thread du c++11.
« Réponse #1 le: Août 11, 2013, 10:37:18 pm »
Tout ce qu'il y a à savoir est très bien expliqué dans les tutoriels correspondants, je te laisse les relire tranquillement.
Laurent Gomila - SFML developer

Cpl.Bator

  • Hero Member
  • *****
  • Messages: 540
    • Voir le profil
Re : SFML et thread du c++11.
« Réponse #2 le: Août 11, 2013, 11:15:57 pm »
La SFML est mal foutue à tout les coups , ou encore un bug de l'os...
Tu n'as peu être pas écrit assez gros dans les tutoriels...

Allez , je suis sympa , je t’évite quelques clics :

Citer
Les évènements doivent être traités dans le thread de la fenêtre
C'est une limitation importante de la plupart des OS : la boucle d'évènements (plus précisément, la fonction pollEvent ou waitEvent) doit être appelée dans le thread qui a créé la fenêtre. Cela implique que si vous voulez créer un thread dédié à la gestion d'évènements, vous devrez vous assurer que la fenêtre est créée dans ce même thread. Si vous voulez vraiment séparer les choses en plusieurs threads, il est plutôt recommendé de garder le fenêtrage et les évènements dans le thread principal, et de bouger le reste (rendu, physique, logique, ...) dans des threads. Cette configuration a aussi l'avantage d'être compatible avec la limitation qui suit.



Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : SFML et thread du c++11.
« Réponse #3 le: Août 11, 2013, 11:28:17 pm »
Ce n'est pas le premier problème à régler (celui que le message d'erreur mentionne) ;)
Laurent Gomila - SFML developer

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
Re : SFML et thread du c++11.
« Réponse #4 le: Août 12, 2013, 09:10:26 am »
Bon je ne sais pas pourquoi mais en fait, quand on fait l'affichage autre part que dans le thread main, ça ne marche pas, ça, ça marche mieux : (J'en ai profité pour passer par Qt pour faire l'affichage dans un thread.)
#include "mycanvas.h"
using namespace sf;
using namespace std;
MyCanvas::MyCanvas(QWidget* Parent, const QPoint& Position, const QSize& Size) : QSFMLCanvas(Parent, Position, Size, 60) {
    sceneUpdater = new SceneUpdater();
    text.create(Size.width(), Size.height());
}

void MyCanvas::onInit() {
    sceneUpdater->start();
}
void MyCanvas::onUpdate() {
    unique_lock<mutex> locker(g_lock_update_component);
    g_signal.wait(locker, [&](){return sceneUpdater->isGDone();});
    clear(Color::Black);
    text.clear(Color::Black);
    text.draw(sceneUpdater->getRectangle());
    text.display();
    draw(Sprite(text.getTexture()));
}
 
#include "updater.h"

using namespace std;
using namespace sf;
SceneUpdater::SceneUpdater()  {
    rectangle = RectangleShape(Vector2f(0, 0));
    rectangle.setSize(Vector2f(100, 100));
    running = gDone = false;
}
bool SceneUpdater::isGDone() {
    return gDone;
}
void SceneUpdater::start() {
    running = true;
    m_thread = thread (&SceneUpdater::run, this);
}
void SceneUpdater::stop() {
    running = false;
    m_thread.join();
}
void SceneUpdater::run() {
    while (running) {
        unique_lock<mutex> locker(g_lock_update_component);
        gDone=false;
        int posX = rand() % 800;
        int posY = rand() % 600;
        rectangle.setPosition(posX, posY);
        gDone = true;
        g_signal.notify_one();
        this_thread::sleep_for(chrono::milliseconds(100));
    }
}
RectangleShape& SceneUpdater::getRectangle () {
    return rectangle;
}
 
#include "mycanvas.h"
#include <ctime>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QApplication>

using namespace std;
int main (int argc, char* argv[]) {
    QApplication app (argc, argv);
    srand(time(NULL));
    QMainWindow *mainWindow = new QMainWindow();
    mainWindow->resize(QSize(800, 600));
    MyCanvas my_canvas (mainWindow, QPoint(0, 0), QSize(800, 600));
    mainWindow->show();
    return app.exec();
}
 
La sfml possède pas mal de limitations, trop même, ce bout de code est vachement plus rapide que d'utiliser un mutex.
Tu devrait quand même impélmenter les variables de conditions dans la SFML.
Et c'est pas une question d'OS vu que quand je fais l'affichage avec Qt, ça marche. ;)
A ce que je sache QTimer utilise un thread non ?
« Modifié: Août 12, 2013, 09:15:37 am par Lolilolight »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : SFML et thread du c++11.
« Réponse #5 le: Août 12, 2013, 09:14:37 am »
Citer
Bon je ne sais pas pourquoi mais en fait, quand on fait l'affichage autre pert que dans le thread main, ça ne marche pas
Encore une fois, tout est expliqué dans les tutoriels si tu te donnes la peine de les lire.

Citer
J'en ai profité pour passer par Qt pour faire l'affichage dans un thread
Dans ce code l'affichage se fait dans le thread principal.
« Modifié: Août 12, 2013, 09:27:01 am par Laurent »
Laurent Gomila - SFML developer

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
Re : SFML et thread du c++11.
« Réponse #6 le: Août 12, 2013, 09:16:31 am »
Citer
Dans ce code l'affichage se fait dans le thread principal.

Ha bon, QTimer n'utilise pas de thread ???

Je pensais.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : SFML et thread du c++11.
« Réponse #7 le: Août 12, 2013, 09:28:00 am »
En programmation il ne faut pas "penser". Quand on ne sait pas, il faut chercher, lire la doc, faire des tests, etc.
Laurent Gomila - SFML developer

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
Re : SFML et thread du c++11.
« Réponse #8 le: Août 12, 2013, 10:12:07 am »
Ok.
Non mais parfois, je lis des bêtises.

cobra.one

  • Newbie
  • *
  • Messages: 26
    • Voir le profil
Re : Re : SFML et thread du c++11.
« Réponse #9 le: Août 12, 2013, 11:25:31 am »
Citer
Dans ce code l'affichage se fait dans le thread principal.

Ha bon, QTimer n'utilise pas de thread ???

Je pensais.

Ce qui est bien c'est qu'on te l'a déjà dis dans un autre thread (;))...
Je t'ai aussi dis que Qt n'acceptera pas non plus que tu manipules l'IHM depuis un autre thread.
T'es du genre tête dure toi non ?

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
Re : SFML et thread du c++11.
« Réponse #10 le: Août 12, 2013, 01:21:09 pm »
Oui ça, ça va, j'ai compris.