Vous êtes ici

GtkGLArea3 pour Windows (avec un VAPI Vala)

Objectif : afficher un contexte OpenGL dans une fenêtre GTK+, sous Windows.

Il y a quelque mois, j'ai eu besoin d'afficher une scène 3D (qui était rendue, bien sûr, via OpenGL) dans une fenêtre GTK+3. Je me souvenais bien que des bibliothèques tierces permettaient de le faire, et une petite recherche m'en a localisée deux :
- GtkGLExt, vieille de trois ans
- GtkGLArea, vieille de quatre ans !

Elle fournissent toutes les deux plus ou moins la même API : l'on crée un widget dédié par-dessus lequel la scène OpenGL va s'afficher ; il y a une gestion automatique du déplacement et du redimensionnement, cependant certaines commodités (comme la mise à l'échelle) doivent être effectuées manuellement.
À mon grand désespoir, cependant, elles ne fonctionnaient toutes deux qu'avec GTK+2...

J'ai donc décidé d'effectuer quelques modifications au code de GtkGLArea, et voilà finalement ce que ça donne :


GtkGLArea2/3 pour Windows

J'ai écrit les VAPI pour Vala, empaqueté les bibliothèques et les fournis dans le dépôt ValaWinPKG.
Voici comment les utiliser.

Pré-requis

Si vous ne les avez pas déjà, nous allons installer le derner Vala pour Windows ainsi que ValaWinPKG :

- vala-0.20.1_(GTK+-3.6.4)(TARNYKO).exe (74,4 Mo)
- ValaWinPKG_0.9.d.exe (7,76 Mo)

1) Installer GtkGLArea3

Nous lançons ValaWinPKG depuis le menu Démarrer de Windows.
Nous cochons ensuite le paquet GtkGLArea3 et cliquons sur "Update !".



2) Compiler un exemple Vala simple

Nous allons d'abord afficher une scène GL avec un autre widget.
Dans ce code source joint, l'on remarque :

var glarea = new GLArea (attrlist);
glarea.set_size_request (100, 100);
glarea.realize.connect (on_glarea_realize_event);
glarea.draw.connect (on_glarea_draw_event);

Nous créons un objet GLArea, définissons sa taille à 100x100, et lui attachons 2 callbacks> : realize et draw.
Le premier, realize, ne sera exécuté qu'une fois au début, au premier affichage de la GLArea, et nous y définirons les propriétés de la scène GL :

void on_glarea_realize_event (Widget widget)
{
[...]
   if (glarea.make_current () == true)
   {
    [...]
    glMatrixMode (GL_PROJECTION);
    glLoadIdentity ();
    glOrtho (0,100, 100,0, -1,1);
    glMatrixMode (GL_MODELVIEW);
   }

Le second, draw, sera rappelé à chaque fois que la fenêtre sera rafraîchie, redimensionnée. C'est ici que nous allons réellement dessiner nos objets 3D :

bool on_glarea_draw_event (Widget widget, Cairo.Context cr)
{
[...]
   if (glarea.make_current () == true)
   {
    [...]
    // Draw simple triangle
    glBegin (GL_TRIANGLES);
    glVertex2f (10,10);
    glVertex2f (10,90);
    glVertex2f (90,90);
    glEnd ();
   
    // Swap backbuffer to front
    glarea.swap_buffers ();

Notez l'appel final à glarea.swap_buffers () pour rafraîchir la scène. Rien ne s'affichera sans ça.
Notez aussi que, dans les deux cas, nous utilisons glarea.make_current () à la fois comme un test (le contexte est-il toujours valide ?) et un "reciblage" (c'est dans ce contexte que nous voulons dessiner !).

Compilons et exécutons :
valac --pkg gtkgl-3.0 gtkglarea3-simple.vala -o gtkglarea3-simple.exe
gtkglarea3-simple.exe


Voilà !

3) Compiler un exemple Vala plus complexe (avec polices !)

L'autre code source est moins spectaculaire mais introduit la gestion des polices GL. Regardez :

GLuint fontbase;
fontbase = glGenLists (128);
Pango.FontDescription fontdesc = Pango.FontDescription.from_string ("Sans 10");
Gdk.gl_use_pango_font (fontdesc, 0, 128, fontbase);

Nous utilisons un GLuint pour nous référer à une liste de polices GL ; nous créons ensuite une police Pango/GTK+ traditionnelle, Sans de taille 10, et attachons les deux ensemble.
Plus tard, nous afficherons du texte avec :

glColor3f (1,1,0);
glRasterPos2f ((100-charwidth*fonttext.length)/2, (100-charheight)/2);
glListBase (fontbase);
glCallLists (fonttext.length, GL_UNSIGNED_BYTE, (GL.GLvoid[])fonttext);

Nous choisissons une couleur de police (rouge + vert = jaune), positionnons le texte au centre grâce à un calcul fait plus tôt, et utilisons glListBase/glCallLists () pour afficher la chaîne fonttext, qui contient en fait le texte "GTKGLAREA".

Et effectivement, à l'essai :
valac --pkg gtkgl-3.0 gtkglarea3-font.vala -o gtkglarea3-font.exe
gtkglarea3-font.exe


Joli !

Plans d'avenis

Le port Linux est toujours en chantier (la gestion des polices y est bien plus compilquée) et sortira sous peu. Cependant, et sans en dire trop, quelque chose qui marche presque...


:-)
Wayland, nous voilà !

(PS : j'ai appris récemment que GtkGLExt avait un port GTK+3 en chantier. Dommage !)