De la VDI, ça vous dit ?
Programmation GFA (6)

Si l'AES est un peu difficile à digérer, avec ses fenêtres, son tube GEM et ses fonctions hétéroclites, ça devient de l'eau de roche quand on a compris sa philosophie.
Il en est autrement de la VDI (du moins en ce qui me concerne ;-). Cette partie du GEM est assez facile à digérer : on se déclare une station virtuelle (graphique) et on récupère ainsi un handle qui est notre droit à utiliser la VDI (donc dessiner sur l'écran), on emploie des fonctions simples (et hop ! un v_bar (=rectangle)), et quand on n'en a plus besoin, on le déclare au GEM qui va libérer sa mémoire. Mais tout se complique lors de l'utilisation des fontes vectorielles, de l'affichage en True Color, et autres améliorations nécessaires pour la remise à niveau BeOS. C'est que la VDI date quelque peu, et c'est des méga-prises de têtes quand on doit débugger tout ça.

Si on peste contre les soit-disant bugs de NVDI, c'est parce que les programmes, dont les miens (mea culpa), ont tendance à demander trop de choses à cette VDI.
Par exemple, je dois me déclarer deux fois et utiliser deux handles VDI, l'un pour le texte, l'autre pour les rectangles. Car si j'emploie un seul en utilisant de la couleur et des fontes vectorielles, j'obtiens un texte qui ne s'affiche pas :( .
C'est pire en utilisant la méthode de l'affichage en offscreen. Fontes vectorielles + couleurs + cache-écran + activations/désactivation répétées de ce même cache donne des bugs fabuleux : la VDI corrompait la mémoire interne du GFA, et ceci sans plantage ! Mes chaînes de texte en étaient toutes retournées. Bref, j'ai dû abandonner, mais je vais quand même vous faire partager mon expérience.

Attention, débutants s'abstenir. Les pros éviteront, vu qu'ils connaissent tout ça par coeur. Cela s'adresse en fait à des gens comme moi qui découvrent les entrailles de leur OS (sic !) et ses subtilités.

Prenez quand même à côté de vous une bonne doc-dev : ça va être chaud :)

L'erreur première

C'est de déclarer une station qui n'est pas virtuelle ! Car l'écran ne nous appartient pas. C'est le GEM qui le gère en totalité. On demande donc au GEM une station virtuelle (v_opnvwk au lieu de v_opnwk). Le blème est que dans la fonction v_opnvwk, il faut donner en paramètre un handle VDI. Et comment je l'obtiens, vu que je suis même pas déclaré ?

Ben, heu... avant de se déclarer à la VDI, on s'était déclaré à l'AES avec ap_id&=APPL_INIT(), qui nous donne le droit d'utiliser l'AES (en théorie car le GFA fait déjà toutes les déclarations sans le dire).
Donc, logiquement il faut appeler l'AES pour nous donner le handle pour l'ouverture d'une station graphique VDI (capito ?). Bingo ! cette fonction s'appelle `GRAF_HANDLE`. On passe ci-dessous à un petit bricolage fait maison :

    FUNCTION open_virtual_screen_workstation
      '
      INT{ADD(CONTRL,2)}=0
      INT{ADD(CONTRL,6)}=11
      INT{ADD(CONTRL,12)}=@graf_handle
      '
      INT{INTIN}=1           ! Numéro ID du périphérique physique (écran)
      INT{ADD(INTIN,2)}=1    ! Type de ligne
      INT{ADD(INTIN,4)}=1    ! Index de couleur Polyline
      INT{ADD(INTIN,6)}=1    ! Type de marqueur
      INT{ADD(INTIN,8)}=1    ! Index de couleur Polymarker
      INT{ADD(INTIN,10)}=1   ! Fonte de caractères
      INT{ADD(INTIN,12)}=1   ! Index couleur texte
      INT{ADD(INTIN,14)}=1   ! Fill interior Style
      INT{ADD(INTIN,16)}=1   ! Fill style index
      INT{ADD(INTIN,18)}=1   ! Fill index couleur
      INT{ADD(INTIN,20)}=2   ! Flag coordonnées NDC ou RC
      '
      VDISYS 100 ! v_opnvwk
      '
      pixel_micron_w&=INT{ADD(INTOUT,6)} ! on récupère normalement une
      pixel_micron_h&=INT{ADD(INTOUT,8)} ! tonne de paramètres dans un
      '                                  ! gros buffer. ces deux variables
      '                                  ! sont intéressantes pour la
      '                                  ! suite .
      '
      RETURN INT{ADD(CONTRL,12)} ! notre handle VDI :)
      '                          ! attention si <1 alors => blèmes
      '
    ENDFUNC

avec

    FUNCTION graf_handle
      '
      INT{ADD(GCONTRL,2)}=0
      INT{ADD(GCONTRL,4)}=5
      LONG{ADD(GCONTRL,6)}=0
      '
      GEMSYS 77 ! graf_handle
      '
      RETURN INT{GINTOUT} ! handle de l'écran renvoyé
      '                   ! (le vrai et pas un virtuel)
      '
    ENDFUNC

Ne vous alarmez pas, ces deux fonctions ne sont que les retranscriptions très allégées tirées des doc-dev. Un euphémisme puique l'ouverture d'une station graphique renvoie plus d'une cinquantaine de valeurs.
Les amateurs du C ne l'utilisent pas comme cela : ils stockent les valeurs de retour dans un gros buffer (`work_out`) et ont des librairies toutes faites.
On aurait pu utiliser les fonctions du GFA, mais comme le dit mon illustre mentor d'EB, elle sont sévèrement buggées et insuffisantes. A ce propos, Emmanuel nous a réécrit les appels VDI, on peut les trouver dans les fichiers annexes de son Modéleur.

A propos de `GRAF_HANDLE`, si vous lisez des sources en C (saine lecture :), vous n'y voyez toujours pas d'appel à cette fonction. Normal, on peut employer 1 et ça marche. J'appelle cela de la tolérance de panne (si si, à la mode zin00), car c'est une erreur et cela marche quand même. Ça devrait moins marcher le jour où il y aura une carte graphique et que vous travaillez sur deux écrans. Ben oui ! En dépit de sa vétusté, la VDI est capable de bosser des graphiques sur n'importe quoi, donc plusieurs écrans, comme sur Mac. Cela s'est même réalisé en pratique (si je me rapelle bien un reportage dans ST Mag) chez nos amis allemands il y a fort longtemps. Malheureusement pas très viable vu le prix de la carte graphique et moniteur 21 pouces couleur. Et quand Zin98 annonce qu'il peut bosser sur plusieurs écran en 1998 ? Daubage et propagande : tu as 10 ans de retard, cher billou :(.

Toujours être propre sur soi

Voici ci-après comment on dit au revoir à la VDI :

    PROCEDURE close_virtual_screen_workstation(mon_handle_vdi&)
      INT{ADD(CONTRL,12)}=mon_handle_vdi&
      VDISYS 101,0,0 ! v_clsvwk
    RETURN

Attention ici, car j'utilise mon handle à moi. Entretemps, on aura utilisé toutes les fonctions de la VDI.
N'hésitez pas à ouvrir plusieurs stations virtuelles. J'en emploie, comme vous l'avez lu plus haut, 2 pour Joe et Blaise.

De même, je me suis aperçu qu'il y avait au moins une différence entre `QUIT` et `EDIT` en GFA compilé : la fermeture de la station VDI faite en douce par le GFA ! Ceci est quand même à vérifier, vu que j'ai découvert ça par hasard (Merci à Didier Briel au passage). Avec QUIT 0 (=Pterm(0)), le GFA déclare son v_clsvwk interne. Mais avec `EDIT`, apparemment rien de cela, et c'est logique : avec EDIT on retourne dans l'éditeur (en interprété) et le GFA travaille toujours et dessine à l'écran. Donc pas de fermeture de la station graphique du GFA. En compilé, cela peut ainsi donner des choses bizarres sur des cartes graphiques. Pensez bien donc, une fois votre petite merveille de GFA débuggée (ou suffisamment stable ;-) de terminer avec `QUIT 0` au lieu de EDIT pour la compilation. Ce serait dommage que cela foire en 1280*960*TC.

Plus fort que le Roquefort®

Dessiner sur l'écran c'est bien, ben il y a mieux : la méthode en cache-écran ou offscreen. Une zone mémoire est allouée et la VDI dessine là-dedans au lieu de le faire sur l'écran. C'est bête à dire mais l'écran EST une zone mémoire. Donc possibilité de faire de la VDI là où ça vous chante, et pas forcément dans la résolution de l'écran.

L'intérêt ? pour les redraws évidemment ! Et pas que cela d'ailleurs. Faire un long dessin qui prend du temps, et éviter ainsi d'accaparer le multitâche avec un bloquage de l'AES (WIND_UPDATE). Vous pouvez également ne travailler en offscreen que sur 1bitplane (ça va plus vite) et afficher le tout avec vrt_cpyfm (équivalent légal du BITBLT sans ligne A sur 1 bitplane (en couleur c'est vro_cpyfm)).

Le blème, enfin mon problème, était que j'allouais et désallouais ce cache-écran sans cesse, avec fontes vectorielles et avec le High Color (où l'on sait que la VDI n'est pas à l'aise). D'où des bugs géniaux. Faites donc attention et testez votre code sous plusieurs type de VDI, sur différents Atari... et surtout, faites simple !

Pour avoir le droit de dessiner dans ce cache-écran, il faut se déclarer à la VDI avec une fonction nommée v_opnbm (pour VDI OPEN BITMAP) qui comme par hasard possède le même opcode que v_opnvwk (avec des paramètres d'entrée qui se ressemblent). Attention, la méthode VDI offscreen n'est pas accessible dans les vieux TOS : il faut détecter la présence d'un cookie nommé EdDI.

    PROCEDURE open_bitmap
      '
      IF @test_cookie("EdDI")=TRUE ! on regarde la cookie jar, la fonction
        '                          ! n'est pas décrite dans cet article
        INT{ADD(CONTRL,2)}=0
        INT{ADD(CONTRL,6)}=20
        INT{ADD(CONTRL,10)}=1    ! important : différencie v_opnbm de v_opnvwk
        INT{ADD(CONTRL,12)}=@graf_handle   (ou mon handle vdi ?)
        LONG{ADD(CONTRL,14)}=offscreen% ! adresse d'une structure MFBD
        '
        ' Remplissez une MFBD à ce niveau. Pour les néophytes, il s'agit
        ' d'un buffer rempli de paramètres décrivant une zone image en
        ' mémoire (cf les doc-dev).
        ' Si tout est à 0, alors la VDI alloue une zone mémoire selon
        ' les valeurs de l'écran (larg+haut+bitplane) et remplie elle-même
        ' la MFBD.
        ' Si vous remplissez vous-même une MFBD (avec allocation mémoire
        ' pour l'image) et si c'est correct, le travail se fera alors par
        ' exemple en 640*400 monochrome alors que l'écran est 1280*960*TC.
        '
        INT{INTIN}=1           ! Numéro ID du périphérique physique (écran)
        INT{ADD(INTIN,2)}=1    ! Type de ligne
        INT{ADD(INTIN,4)}=1    ! Index de couleur Polyline
        INT{ADD(INTIN,6)}=1    ! Type de marqueur
        INT{ADD(INTIN,8)}=1    ! Index de couleur Polymarker
        INT{ADD(INTIN,10)}=1   ! Fonte de caractères
        INT{ADD(INTIN,12)}=1   ! Index couleur texte
        INT{ADD(INTIN,14)}=1   ! Fill interior Style
        INT{ADD(INTIN,16)}=1   ! Fill style index
        INT{ADD(INTIN,18)}=1   ! Fill index couleur
        INT{ADD(INTIN,20)}=2   ! Flag coordonnées NDC ou RC
        INT{ADD(INTIN,22)}=PRED(largeur&)    ! taille de l'écran -1
        INT{ADD(INTIN,24)}=PRED(hauteur&)    !
        INT{ADD(INTIN,26)}=pixel_micron_w&   ! largeur d'un pixel en microns
        INT{ADD(INTIN,28)}=pixel_micron_h&   ! hauteur d'un pixel en microns
        '                                    ! récupérés plus haut dans v_opnvwk
        '                                    ! (sert pour les calculs des fontes)
        FOR i&=30 TO 40 STEP 2
          INT{ADD(INTIN,i&)}=0   ! format spécifique
        NEXT i&
        ' 0 si la version d'EdDI est 1.0
        ' Il y a des extensions pour la 1.1 à ce niveau.
        '
        VDISYS 100
        '
        handle_offscreen&=INT{ADD(CONTRL,12)}
        ' si <1 lors blèmes : ça n'a pas marché
      ENDIF
      '
    RETURN

Vous récupérez ainsi un handle (et une tonne de paramètres, mais on a occulté ça avec notre appel bidouillé), vous pouvez ensuite dessiner en offscreen, puis afficher le résultat avec vro_cpyfm ou vrt_cpyfm.
Le seul blème vient de ces deux dernières fonctions : ou c'est le nombre de bitplanes de l'écran, ou c'est 1 bitplane. On ne peut pas afficher une zone 16 couleurs sur un écran en 256 par exemple. D'où une consommation mémoire importante, vu qu'en couleur vous devez travailler avec un nombre de bitplanes identique à celui de l'écran. Il faut alors se bricoler des routines fait-maison, ou utiliser des bibliothèques, de préférence très rapides.

Pour fermer votre écran offscreen :

    PROCEDURE close_bitmap
      IF handle_offscreen&>0
        INT{ADD(CONTRL,12)}=handle_offscreen&
        VDISYS 101,0,0,1
      ENDIF
      handle_offscreen&=0 ! petite sécurité
    RETURN

Les bons ouvrages à conseiller...

N'hésitez pas à chercher sur le Web et chez les copains les doc-dev de NVDI (il en existe une en anglais) car c'est une mine d'or pour celui qui voudrait exploiter et connaître la VDI.
Vous avez également le Compendium, dont la version HTML serait exploitable si les pages étaient plus fragmentées : les appels VDI sont sur une page unique faisant 200Ko, il faut alors plus de 4Mo de mémoire et un bon processeur overclocké pour pouvoir l'utiliser. Il y a toujours TOS.HYP, mais en germain...
Ya des volontaires pour retoucher ce Compendium HTML ?

Rajah Lone
écrit le 03/03/99