Salut à tous !

J’ai converti le deuxième tutoriel de NeHe sur OpenGL de telle sorte qu’il utilise GtkGlExtmm. Cependant, j’ai une bogue surprenante : sur mon ordinateur portable, utilisant le pilote libre pour processeur graphique Intel Sandy bridge mobile sur Debian Wheezy, tout ce passe bien. En particulier, je peux commencer immédiatement en mode plein écran.

En revanche, sur mon ordinateur fixe, qui utilise Flgrx toujours sur Debian Wheezy, si je peux basculer en (puis quitter le) mode plein écran à partir du moment où je commence en mode fenêtré, le serveur X crash (écran entièrement noir) si je veux commencer immédiatement en mode plein écran. Dans ce cas-là, plus possible d’obtenir une console virtuelle. Cependant, je suis certain que seul X crash, dans la mesure où j’entends encore la musique que j’écoutais éventuellement à ce moment-là et je peux me connecter par SSH sur l’ordinateur fixe depuis le portable (c’est ce que je fais pour reprendre la main).

Je ne sais pas trop comment résoudre le problème, je suis donc preneur de toute aide éventuelle.

Je génère le code à l’aide de CMake. Le fichier « CMakeLists.txt » associé se situe dans la racine du projet, tandis que tous les codes sont dans le sous-répertoire « src/ ».

Fichier « CMakeLists.txt » :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
## Génération des tutoriels OpenGL de NeHe version Gtkmm.
 
cmake_minimum_required(VERSION 2.6)
 
project(Tutoriel1)
 
# Répertoire où placer l’exécutable.
set(EXECUTABLE_OUTPUT_PATH bin/${CMAKE_BUILD_TYPE})
# Nom de l’exécutable.
set(EXECUTABLE_NAME tutoriel1)
 
find_package(OpenGL)
 
find_package(PkgConfig)
 
pkg_check_modules(Glibmm glibmm-2.4>=2.4.0)
pkg_check_modules(GTKmm gtkmm-2.4>=2.4.0)
pkg_check_modules(GLExtmm gtkglextmm-1.2>=1.2.0)
link_directories(
        ${OPENGL_LIBRARY_DIRS}
        ${Glibmm_LIBRARY_DIRS}
        ${GTKmm_LIBRARY_DIRS}
        ${GLExtmm_LIBRARY_DIRS}
)
include_directories(
        ${OPENGL_INCLUDE_DIRS}
        ${Glibmm_INCLUDE_DIRS}
        ${GTKmm_INCLUDE_DIRS}
        ${GLExtmm_INCLUDE_DIRS}
)
 
file(
        GLOB_RECURSE
        source_files
        src/*
)
 
add_executable(
        ${EXECUTABLE_NAME}
        ${source_files}
)
 
target_link_libraries(
        ${EXECUTABLE_NAME}
        ${OPENGL_LIBRARIES}
        ${Glibmm_LIBRARIES}
        ${GTKmm_LIBRARIES}
        ${GLExtmm_LIBRARIES}
)
Fichier « src/erreurs.hpp » :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#ifndef ERREURS_HPP
#define ERREURS_HPP
 
/*
 * Exceptions pour la gestions des erreurs.
 */
 
#include <exception>
 
/* Espace de nommage pour la gestion des erreurs. */
namespace Erreurs {
/* -- Erreurs provoquées par l’interface graphique. ---------------------- */
  class ErreurInterface: public std::exception {
    public:
      /* Constructeur par défaut. */
      ErreurInterface () throw () {}
 
      /* Destructeur. */
      virtual ~ErreurInterface () throw () {}
 
      /* Génére le message d’erreur. */
      virtual const char* what () const throw () {
        return "une erreur s’est produite dans l’interface graphique";
      }
  };
 
/* -- Erreur lors de la configuration d’OpenGL. -------------------------- */
  class ErreurConfigurationGL: public ErreurInterface {
    public:
      /* Constructeur par défaut. */
      ErreurConfigurationGL () throw () {}
 
      /* Destructeur. */
      virtual ~ErreurConfigurationGL () throw () {}
 
      /* Génère le message d’erreur. */
      virtual const char* what () const throw () {
        return "erreur lors de la configuration d’OpenGL";
      }
  };
 
/* -- Erreur lors de la création du contexte OpenGL. --------------------- */
  class ErreurCreationContexte: public ErreurInterface {
    public:
      /* Constructeur par défaut. */
      ErreurCreationContexte () throw () {}
 
      /* Destructeur. */
      virtual ~ErreurCreationContexte () throw () {}
 
      /* Génère le message d’erreur. */
      virtual const char* what () const throw () {
        return "impossible de créer un contexte OpenGL";
      }
  };
 
/* -- Erreur à l’obtention du contexte OpenGL. --------------------------- */
  class ErreurObtentionContexte: public ErreurInterface {
    public:
      /* Constructeur par défaut. */
      ErreurObtentionContexte () throw () {}
 
      /* Destructeur. */
      virtual ~ErreurObtentionContexte () throw () {}
 
      /* Génère le message d’erreur. */
      virtual const char* what () const throw () {
        return "impossible d’obtenir le contexte OpenGL";
      }
  };
}
 
#endif  // #ifndef ERREURS_HPP
Fichier « src/fenetre.hpp » :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#ifndef FENETRE_HPP
#define FENETRE_HPP
 
/*
 * Définitions des classes gérants le fenêtrage OpenGL.
 */
 
#include <gtkmm/window.h>
#include <gtkmm/drawingarea.h>
#include <gtkglmm.h>
 
#include "erreurs.hpp"
 
/* Espace de nommage pour la gestion de l’interface. */
namespace Interface {
  /* Classe pour la zone de rendu OpenGL. */
  class GlDrawingArea: public Gtk::DrawingArea,
                       public Gtk::GL::Widget<GlDrawingArea> {
    public:
      GlDrawingArea ();
      virtual ~GlDrawingArea ();
 
    protected:
      /* -- Controleurs: */
 
      /* À l’initialisation de la fenêtre. */
      virtual void on_realize ();
 
      /* À la demande d’affichage. */
      virtual bool on_expose_event (GdkEventExpose* event);
 
      /* Au changement de taille de la fenêtre. */
      virtual bool on_configure_event (GdkEventConfigure* event);
  };
 
/* ----------------------------------------------------------------------- */
 
  /* Classe pour la fenetre principale. */
  class Fenetre: public Gtk::Window {
    public:
      Fenetre ();
      virtual ~Fenetre();
 
    protected:
      /* -- Controleurs : */
 
      /* Gestion des évènements clavier. */
      bool on_key_release (GdkEventKey* evenement);
 
      /* Lors du passage du mode fenêtré au mode plein écran. */
      bool on_window_state_event (GdkEventWindowState *pEven);
 
      /* -- Composant membre : */
 
      /* Zone de rendu OpenGL. */
      GlDrawingArea zoneRendu;
 
    private:
      /* Indique si on se trouve en mode plein écran. */
      bool enPleinEcran;
  };
}
 
#endif  // #ifndef FENETRE_HPP
Fichier « src/fenetre.cpp »

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
/*
 * Implémentations du fenêtrage OpenGL.
 */
 
#include <glibmm/error.h>
#include <cstdlib>
#include <GL/gl.h>
#include <GL/glu.h>
#include <sstream>
#include <gtkmm/messagedialog.h>
#include <gdk/gdkkeysyms.h>
 
#include "fenetre.hpp"
 
/* -- Constructeur par défaut de GlDrawingArea. -------------------------- */
Interface::GlDrawingArea::GlDrawingArea (): Gtk::DrawingArea () {
  /* Configuration d’OpenGL */
  Glib::RefPtr<Gdk::GL::Config> configuration;
 
  /* Tente d’ouvrir une espace à double tampon. */
  configuration = Gdk::GL::Config::create(Gdk::GL::MODE_RGBA   |
                                          Gdk::GL::MODE_DEPTH  |
                                          Gdk::GL::MODE_DOUBLE);
  if (!configuration) {
    /* Message d’avertissement. */
    std::stringstream message;
    message << "Impossible de configurer OpenGL en mode double tampon, "
            << "tente le mode simple tampon.\n";
    g_warning(message.str().c_str());
    /* Tente de configurer un tampon simple. */
    configuration = Gdk::GL::Config::create(Gdk::GL::MODE_RGBA  |
                                            Gdk::GL::MODE_DEPTH);
    if (!configuration) throw Erreurs::ErreurConfigurationGL ();
  }
 
  /* Donne accès à OpenGL au composant. */
  set_gl_capability(configuration);
}
 
/* -- Destructeur de GlDrawingArea. -------------------------------------- */
Interface::GlDrawingArea::~GlDrawingArea () {
}
 
/* -- Initialisation du contexte OpenGL. --------------------------------- */
void Interface::GlDrawingArea::on_realize () {
  /* D’abord l’initialisation standard. */
  Gtk::Widget::on_realize();
 
  if (!create_gl_context()) throw Erreurs::ErreurCreationContexte ();
  /* Fenêtre OpenGL. */
  Glib::RefPtr<Gdk::GL::Window> fenetreGl = get_gl_window();
  if (!fenetreGl) throw Erreurs::ErreurObtentionContexte ();
 
  fenetreGl->gl_begin(get_gl_context());
 
    /* Permet un joli ombrage. */
    glShadeModel(GL_SMOOTH);
 
    /* Fond noir. */
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 
    /* Mis en place du tampon de profondeur. */
    glClearDepth(1.0f);
    /* Mis en place du test de profondeur. */
    glEnable(GL_DEPTH_TEST);
    /* Le type de test de profondeur . */
    glDepthFunc(GL_LEQUAL);
 
    /* Très jolis calculs de perspective. */
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
 
  fenetreGl->gl_end();
}
 
/* -- À la demande  d’affichage de GlDrawingArea. ------------------------ */
bool Interface::GlDrawingArea::on_expose_event (GdkEventExpose* event) {
  /* Fenêtre OpenGL. */
  Glib::RefPtr<Gdk::GL::Window> fenetreGl = get_gl_window();
  if (!fenetreGl)  throw Erreurs::ErreurObtentionContexte ();
 
  fenetreGl->gl_begin(get_gl_context());
 
    /* Vide l'écran et le Z-Buffer (Depth Buffer : contient les informations
       de profondeur de chaque pixel). */
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    /* Repositionne la caméra. */
    glLoadIdentity();
 
    /* Bouge de 1.5 unités vers la gauche et de 6.0 unités vers l'intérieur
       de l'écran. */
    glTranslatef(-1.5f,0.0f,-6.0f);
 
    /* Dessiner un Triangle. */
    glBegin(GL_TRIANGLES);
      /* Point du haut. */
      glVertex3f( 0.0f, 1.0f, 0.0f);
      /* Point en bas à gauche. */
      glVertex3f(-1.0f,-1.0f, 0.0f);
      /* Point en bas à droite */
      glVertex3f( 1.0f,-1.0f, 0.0f);
    /* Le dessin du Triangle est fini */
    glEnd();
 
    /* Bouge de 3.0f unités vers la droite. */
    glTranslatef(3.0f,0.0f,0.0f);
 
    /* Dessin d'un quadrilatère. */
    glBegin(GL_QUADS);
      /* Haut Gauche. */
      glVertex3f(-1.0f, 1.0f, 0.0f);
      /* Haut Droite. */
      glVertex3f( 1.0f, 1.0f, 0.0f);
      /* Bas Droite. */
      glVertex3f( 1.0f,-1.0f, 0.0f);
      /* Bas Gauche. */
      glVertex3f(-1.0f,-1.0f, 0.0f);
    glEnd();
 
  fenetreGl->gl_end();
  fenetreGl->swap_buffers();
 
  /* Partie standard de la la procédure d’affichage. */
  return Gtk::Widget::on_expose_event(event);
}
 
/* -- Lorsque la fenêtre est redimensionnée. ----------------------------- */
bool Interface::GlDrawingArea::on_configure_event (GdkEventConfigure* event) {
  /* Fenêtre OpenGL. */
  Glib::RefPtr<Gdk::GL::Window> fenetreGl = get_gl_window();
  if (!fenetreGl)  throw Erreurs::ErreurObtentionContexte ();
 
  fenetreGl->gl_begin(get_gl_context());
 
    /* Choisir la matrice de projection. */
    glMatrixMode(GL_PROJECTION);
    /* Remettre a zéro de la matrice de projection. */
    glLoadIdentity();
 
    /* Calculer le ratio pour la perspective de la fenêtre. */
    gluPerspective(45.0f, static_cast<GLfloat>(get_width())
                            / static_cast<GLfloat>(get_height()),
                   0.1f,100.0f);
    /* Choisir la matrice de modélisation. */
    glMatrixMode(GL_MODELVIEW);
    /* Remetre à zéro la matrice de modélisation. */
    glLoadIdentity();
 
  fenetreGl->gl_end();
 
  /* Partie standard du redimensionnement. */
  return Gtk::Widget::on_configure_event(event);
}
 
/* -- Constructeur par défaut de la fenêtre. ----------------------------- */
Interface::Fenetre::Fenetre (): Gtk::Window (), zoneRendu () {
  set_title("Tutoriel 2");
  set_default_size(640, 480);
  /* Taille minimum pour éviter les divisions par zéro. */
  set_size_request(1, 1);
 
  add(zoneRendu);
 
  add_events(Gdk::KEY_RELEASE_MASK);
 
  signal_key_release_event().connect(sigc::mem_fun(*this,
                                                  &Fenetre::on_key_release));
  signal_window_state_event().connect(sigc::mem_fun(*this,
                                           &Fenetre::on_window_state_event));
 
  /* Boîte de dialogue pour le plein écran. */
  Gtk::MessageDialog pleinEcran (*this, "Passer en mode plein écran ?",
                                 false, Gtk::MESSAGE_QUESTION,
                                 Gtk::BUTTONS_YES_NO);
  /* Choix de l’utilisateur. */
  int choix = pleinEcran.run();
 
  if (choix == Gtk::RESPONSE_YES) {
    enPleinEcran = true;
    fullscreen();
  }
  else {
    set_border_width(2);
    enPleinEcran = false;
  }
 
  show_all_children();
}
 
/* -- Destructeur de la fenêtre. ----------------------------------------- */
 
Interface::Fenetre::~Fenetre () {
}
 
/* -- Gestion des évènements claviers. ----------------------------------- */
bool Interface::Fenetre::on_key_release (GdkEventKey* evenement) {
  switch (evenement->keyval) {
    case GDK_KEY_Escape:
      hide();
      break;
    case GDK_KEY_F1:
      if (enPleinEcran) {
        enPleinEcran = false;
	set_border_width(2);
        unfullscreen();
      }
      else {
        enPleinEcran = true;
	set_border_width(0);
        fullscreen();
      }
  }
 
  return true;
}
 
/* -- Lors du passage du mode plein écran au mode fenêtré. --------------- */
bool Interface::Fenetre::on_window_state_event(GdkEventWindowState* pEven) {
  /* Résultat de la mise à jour standard de la fenêtre. */
  const bool resultat = Gtk::Widget::on_window_state_event(pEven);
 
  if (resultat) {
    /* Vérifie que l’écran est bien dans le mode souhaité. */
    if (enPleinEcran
        && (pEven->changed_mask != GDK_WINDOW_STATE_FULLSCREEN)) {
      set_border_width(2);
      enPleinEcran = false;
      unfullscreen();
 
      /* Boîte de dialogue signifiant l’échec de l’opération. */
      Gtk::MessageDialog pleinEcran (*this,
                                  "Impossible de passer en mode plein écran",
                                     false, Gtk::MESSAGE_QUESTION,
                                     Gtk::BUTTONS_YES_NO);
      pleinEcran.set_secondary_text("Rester en mode fenêtré ?");
      /* Choix de l’utilisateur. */
      int choix = pleinEcran.run();
      if (choix == Gtk::RESPONSE_NO) return false;
    }
  }
 
  return resultat;
}
Fichier « src/main.cpp » :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/*
 * Deuxième tutoriel : création d’un triangle et d’un carré.
 */
 
#include <iostream>
#include <gtkmm/main.h>
#include <sstream>
#include <glibmm/error.h>
#include <exception>
 
#include "erreurs.hpp"
#include "fenetre.hpp"
 
/*
 * Principale fonction du programme.
 * Entrées :
 *   argc  Nombre d’arguments.
 *   argv  Valeures des arguments.
 * Retourne :
 *   0 si tout s’est bien passé.
 *   -1 en cas d’erreur venant de la GLib ou de ses dérivés.
 *   -2 en cas d’erreur en provenance d’OpenGL.
 *   -3 en cas d’erreur en provenance de la bibliothèque standard.
 *   -4 en cas d’erreur non standard.
 */
int main (int argc, char** argv) {
  try {
    /* Boucle d’évènements. */
    const Gtk::Main kit(argc, argv);
    Gtk::GL::init(argc, argv);
 
    /* Fenêtre principale. */
    Interface::Fenetre principale;
 
    kit.run(principale);
 
    return 0;
  }
  catch(const Glib::Error &ex) {
    /* Message d’erreur. */
    std::ostringstream message;
    message << "Erreur venant de GLib : " <<  ex.what() << '\n';
    g_warning(message.str().c_str());
    return -1;
  }
  catch (const Erreurs::ErreurInterface &e) {
    /* Message d’erreur. */
    std::stringstream message;
    message << "Erreur de contexte OpenGL : " << e.what() << ".\n";
    g_critical(message.str().c_str());
    return -2;
  }
  catch (const std::exception &e) {
    /* Message d’erreur. */
    std::stringstream message;
    message << "Erreur venant de la bibliothèque standard : " << e.what()
            << '\n';
    g_critical(message.str().c_str());
    return -3;
  }
  catch (...) {
    g_critical("Exception non-standard.\n");
    return -4;
  }
}
À bientôt.

Le Farfadet Spatial