12
votes

Comment dessiner le graphique dans la tramebuffer à l'aide de la langue C.?

Je suis nouveau dans ce cadre Linux Framebuffer, de sorte que quelqu'un me guide pour dessiner le graphique de ligne dans la tramebuffer. Et j'ai le code pour dessiner un graphique dans Turbo C mais maintenant sous Linux. Alors s'il vous plaît aidez-moi à sortir.

merci, Rahul


0 commentaires

3 Réponses :


19
votes

Utilisez Ouvrir () Code> sur le fichier de droite Dans / dev code> (par exemple, / dev / fb0 code>), puis utilisez MMAP () CODE> Pour mapper en mémoire. Les mangages aideront pour ces systèmes SysCalls si vous ne savez pas comment les utiliser.

Il y a des structures et des constantes pour certains ioctl () code> s dans code>. Comme beaucoup d'en-têtes de noyau, vous pouvez apprendre beaucoup simplement parcourir le fichier. P>

particulièrement intéressant est le ioctl fbioget_vscreeninfo code> avec struct fb_var_screeninfo code>. Notez que cela a xres code>, yres code> (résolution) et bits_per_pixel code>. Ensuite, il y a fbioget_fscreeninfo code> et struct fb_fix_screeninfo code> Donc, un pixel à (x, y) peut être à mmap_base_address + x * bits_per_pixel / 8 + y * line_length code>. Le format exact des pixels dépendra des structures que vous récupérez via IOCTL; C'est votre travail de décider comment les lire / les écrire. P>

Cela fait longtemps que j'ai travaillé avec cela, donc je suis un peu floue sur plus de détails. P>

Voici Un échantillon de code rapide et sale vient d'illustrer comment c'est fait ... Je n'ai pas testé cela. P>

#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/mman.h>

#include <linux/fb.h>

#include <unistd.h>
#include <fcntl.h>

#include <stdio.h>

int main()
{
   struct fb_var_screeninfo screen_info;
   struct fb_fix_screeninfo fixed_info;
   char *buffer = NULL;
   size_t buflen;
   int fd = -1;
   int r = 1;

   fd = open("/dev/fb0", O_RDWR);
   if (fd >= 0)
   {
      if (!ioctl(fd, FBIOGET_VSCREENINFO, &screen_info) &&
          !ioctl(fd, FBIOGET_FSCREENINFO, &fixed_info))
      {
         buflen = screen_info.yres_virtual * fixed_info.line_length;
         buffer = mmap(NULL,
                       buflen,
                       PROT_READ|PROT_WRITE,
                       MAP_SHARED,
                       fd,
                       0);
         if (buffer != MAP_FAILED)
         {
            /*
             * TODO: something interesting here.
             * "buffer" now points to screen pixels.
             * Each individual pixel might be at:
             *    buffer + x * screen_info.bits_per_pixel/8
             *           + y * fixed_info.line_length
             * Then you can write pixels at locations such as that.
             */

             r = 0;   /* Indicate success */
         }
         else
         {
            perror("mmap");
         }
      }
      else
      {
         perror("ioctl");
      }
   }
   else
   {
      perror("open");
   }

   /*
    * Clean up
    */
   if (buffer && buffer != MAP_FAILED)
      munmap(buffer, buflen);
   if (fd >= 0)
      close(fd);

   return r;
}


9 commentaires

Lorsque je compile, je reçois des erreurs comme celle-ci, dans le fichier inclus de GC: / EUSR/include/sys/mman.h:38: Erreur: Types de conflit pour 'Mode_T' /USR/include/linux/TTTYPES.H : 15: ERREUR: déclaration précédente de 'Mode_T' était ici dans le fichier inclus de GC: / FUSR/include/unistd.h:203: Erreur: Types de conflit pour 'gid_t' /usr/include/linux/types.h : 27: ERREUR: déclaration précédente de 'gid_t' était ici /usr/include/unistd.h:208: Erreur: Types de conflit pour 'uid_t' /usr/include/linux/types.h:26: Erreur: Déclaration précédente de 'uid_t' était ici dans le fichier inclus de /usr/include/bits/fcntl.h:25,


@Rahul - Doit être l'ordre dans lequel je mets les en-têtes ... peut-être essayer sys / type.h d'abord?


J'ai ajouté la ligne d'en-tête SYS / Tys.h, mais le nouveau refuge d'erreurs a été apparu comme, /usr/include/sys/mman.h:38: Erreur: Types de conflit pour 'Mode_T' /USR/include/Linux/TTTYPES.H : 15: Error: déclaration précédente de 'mode_t' était ici


Je ne sais pas quoi dire. Je jouerais avec l'ordre de l'inclure. Peut-être que l'UNISTD devrait aller plus tôt? Tout compile ok ici.


Sinon peut-être peut-être copier Linux / fb.h localement et résoudre ce problème pour ne pas inclure Linux / Types. (hacjou, mais vos en-têtes semblent être cassés.)


Envoyez-moi un programme entier. En ce que je peux voir les valeurs comment vous avez attribué "x" et "y" à l'aide de tampon ..?


Je ne me compose pas d'erreurs de compilation, mais quand j'essaie de l'exécuter (en X11 et TTY1), rien n'apparaît. Rien n'est dessiné à la tramebuffer.


@ B1kmusic - Le code que j'ai ici ne fait que disposer la configuration de l'appareil, il ne fait aucun écrit. Avez-vous essayé de remplir des choses à la partie "TODO"?


@ASVEIKAU AH, je pensais ça. Et nope. Comme je ne pouvais pas sembler trouver de la documentation sur la tramebuffer à part /usr/include/linux/fb.h , je suis allé planifier B: Ecour Internet pour au moins une démo de travail que je pourrait gâcher pour gagner une expérience pratique avec elle. J'ai fini par trouver un, cependant, et maintenant j'ai une bien meilleure compréhension de la façon d'écrire sur l'appareil. Sans parler, je n'ai pas presque autant d'expérience en C tel que je fais à JavaScript, alors j'apprends encore beaucoup de choses. D'après ce que j'ai vécu jusqu'à présent, c'est une belle langue.




0
votes

de mon synaptic sur Rasbian: "DirectFB est une bibliothèque graphique conçue avec des systèmes embarqués en tête. Il offre une performance accélérée matérielle maximale au minimum d'utilisation des ressources et de frais généraux."

Quoi qu'il en soit, je n'ai pas encore vu ce travail dans un tampon de cadre mais j'espère que c'est comme si je fais la plupart de mes graphismes. Vous avez un peu d'espace d'adresse linéaire, de la largeur de hauteur * * d'octets par pixel nombre d'octets. Si vous souhaitez écrire sur un emplacement X, Y particulier, la position dans cet espace est donnée par (Y * largeur * octets par pixel) + (x * 3). Les couleurs sont des octets adjacents RGB (généralement) de sorte que vous obtenez l'adresse du pixel rouge, ajoutez 1 pour vert, 2 pour le bleu. Vous malloc (hauteur * largeur * octets par pixel) un espace d'adressage, écrivez-y, puis choisissez votre choix de libpng, libjourg, libtiff d'écrire ce tampon dans un fichier. Si vous voulez mettre du texte, il vous suffit de rouler le vôtre, alors j'ai volé un d'un vieil libgif. J'ai atteint le niveau d'âge et de l'expérience où il est plus facile de le faire moi-même que d'apprendre comment quelqu'un d'autre pensait que cela devrait être fait. Mes graphismes sortent comme ça: Données prises comme CSV de RTL_Power

J'ai essayé d'utiliser une tramebuffer comme décrit à http://raspberrycompote.blogspot.com/2014/04/low-level-graphics-on-raspberry-pi.html Mais quelque chose ne va pas. Je suis sur un PI 3, il a probablement été écrit pour un PI 1 puisqu'il était 2014, pas 2017 alors. Mais le PI est différent des framebuffers traditionnels car le GPU gère le spectacle. Utilisez cette méthode: http://elinux.org/rpi_framebuffer


5 commentaires

Alan, graphique intéressant :) . On ignore si vous fournissez une réponse à la question initiale, ou une nouvelle question sous la forme de la réponse. (Je l'ai lu comme un peu des deux ...) Si votre intention est d'obtenir de l'aide avec votre problème, il est préférable de poser une nouvelle question, car les questions de votre réponse sont susceptibles d'inviter toute nouvelle réponse. De plus, puisqu'il s'agit de RambeauPi liée, votre meilleur pari est probablement de poster sur Raspberry Pi Stackexchange . Bonne chance de toute façon.


Je n'ai pas encore d'utiliser une tramebuffer puisque OpenBSD ne les a pas et c'est surtout ce que j'ai couru pendant 15 ans. Ne cherchez pas de l'aide, expliquez simplement des graphiques sans bibliothèques. Je suis sur le point de donner à LibVNC un essai puisqu'il donne un cadre virtuel que vous pouvez vous connecter avec un client VNC, et il s'exécute dans une fenêtre au lieu de prendre tout l'affichage. J'essaie de faire du SDR avec une cascade alors j'ai besoin de graphiques qui bougent, pas seulement des images fixes.


VNC est essentiellement un cadre distant distant, c'est ce qui m'a donné l'idée: Raspberrypi.org /forums/viewtopic.php?f=67&t=189032 (mon fil là-bas)


Oui, il semble fonctionner exactement comme je m'y attendais. J'ai écrit une boucle envoi de 900 octets à la trame virtuelle et elle a dessiné une ligne comme on m'y attendait. Je me suis connecté d'une autre machine pour le voir, c'était sur un PI de framboise, j'étais sur une boîte openbsd i386. La mauvaise documentation m'a pris la plus longue période, l'Argc et l'ARGV dans les démos ne font rien du tout, ce ne sont que des espaces réservés.


C'est plutôt cool, je suis content que vous ayez de travailler. J'ai un PI3 que j'interface généralement avec Via SSH, mais je suis intrigué par vos résultats. (Je suis en fait émerveillé de ce qu'ils sont entassés dans le PI3 et de la façon dont Debian l'exécute) à l'aide du cadre VNC à la place du matériel. Probablement plus pardonnant aussi. Tant que vous avez la bonne adresse pour la trame virtuelle - je suppose que le pire des cas est en train de casser VNC au lieu de prendre la boîte.