Linux-framebuffer-Grafik und VSync
Mache ich ein Spiel in C, das funktioniert auf dem linux-framebuffer. Bisher habe ich eine rot 100x100 Quadrat, das bewegt sich im tandem mit der Maus, ebenso wie ein Zeiger. Ich habe double buffering implementiert und es funktioniert einwandfrei (der Platz nicht flackert). Das problem ist, es ist ziemlich viel reißen geschieht horizontal. Was ich damit meine, ist, wenn das Quadrat verschiebt sich auf der x-Achse, es ist wie es ist horizontal geteilt und ein Teil der es Fortschritte slithgly mehr als die anderen. Diese "rip" langsam ausbreitet, von oben nach unten auf den Platz, wenn ich halten Sie es bewegen.
Ich glaube, dass es geschieht, weil die hardware liest den framebuffer während der moment, als ich die Kopie der Doppel-Puffer in die main-Puffer.
Habe ich versucht um das problem zu bekämpfen mit der FBIO_WAITFORVSYNC ioctl, aber kein Erfolg.
Irgendwelche Ideen, wie ich tun konnte, VSync auf den framebuffer? Bitte fügen Sie Details zu Ihren Erklärungen, wie dies das erste mal, dass ich bin, solch Zeug auf ein Linux-basiertes OS, also kann ich nicht verstehen, sonst.
Hier ist mein code: http://pastebin.com/KJ4iaVEL
- Welche video-hardware verwenden Sie? Linux hat tearing-Probleme mit Sandy Bridge Intel-Grafik, zum Beispiel. Bitte klären Sie.
- Ich habe eine Nvidia 7800 GTX, sorry fürs nicht erwähnen, dass. Es ist kein tearing bei normaler Nutzung (als ich z.B. das verschieben von Fenstern um in X).
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dies ist nicht der richtige Weg, das zu tun double-buffering. Du hast Recht, alles zu tun, die Malerei auf ein back-buffer, aber dann müssen Sie ein memcpy, um die Datenübertragung auf der Vorderseite. Ein Bildschirm-refresh könnte leicht passieren, während die Kopie.
Um dies richtig tun, sollten Sie nur Schalter ein Zeiger auf die Daten; kopiert nicht die Daten selbst. Mit dem Linux-framebuffer-Gerät, dies geschieht durch eine "virtuelle" Bildschirm, der doppelt so groß ist wie der physische Bildschirm, und mit einem offset-variable zu setzen, egal, ob Sie zeigt die oberen oder unteren Hälfte. Sie können die Abfrage der Größe und legen Sie den offset mit der
FBIOGET_VSCREENINFO
,FBIOPUT_VSCREENINFO
, undFBIOPAN_DISPLAY
ioctl
Anrufe.Dieser Seite kurz gibt einige details dazu: http://www.ummon.eu/Linux/API/Devices/framebuffer.html
Alle relevanten Daten-Strukturen sind in der
linux/fb.h
header-Datei.Leider habe ich auf die harte Tour gelernt, dass @Steven Bell ' s Antwort ist nicht ganz richtig. Wenn er ist Recht, dass ein Bildschirm-refresh könnte leicht passieren, während die memcpy die richtige Lösung ist nicht das erstellen einer virtuellen framebuffer-double die Größe des Bildschirms und pan zwischen Ihnen, wie so vielen threads vorschlagen. Wer versucht dieser Lösung, erhalten Sie eine Fehlermeldung, die hier beschrieben: invalid argument Fehler bei der Einstellung yres_virtual in fb_var_screeninfo.
Laut diesem thread: https://forum.odroid.com/viewtopic.php?f=55&t=8741 es ist nicht ganz möglich, wirklich Doppel-Puffer in den framebuffer (/dev/fb0, obwohl ich habe gehört, dass der raspberry PI ist vielleicht eine Ausnahme zu dieser Regel). Aber das bedeutet nicht, dass es nicht möglich ist, Doppel-Puffer in linux mit low-level-Grafiken.
Die richtige Lösung hier ist die Verwendung von libdrm (/dev/dri/card0) zu ziehen low-level-Grafiken auf dem Bildschirm. Es ist ein wirklich schönes Beispiel, wie das geht steht hier: https://github.com/dvdhrm/docs/blob/master/drm-howto/modeset-vsync.c, dass ich mich selbst, wenn ich versuche, dieses problem zu lösen.
Anyways ich hoffe, ich habe Sie gespeichert jemand die erstaunliche Kopfschmerzen, die ich hatte, durch zu gehen, um dies herauszufinden, werden in der Zukunft.