2016-06-22 18 views
1

Ich muss einen Cursor (Mauszeiger) auf dem Bildschirm unter Linux ohne X11 zeichnen. Dies ist zur Verwendung in einem eingebetteten System vorgesehen, wo alle anderen Zeichnungen direkt in einem Framebuffer (/dev/fb0) stattfinden.Müssen Cursor in Linux Framebuffer zeichnen

  1. Die GUI-Bibliothek, die ich derzeit betrachte, bietet keine Cursor-Unterstützung.
  2. Ich könnte die Blitting selbst tun, aber ich bin besorgt über Aussehen und Leistung, zum Teil, weil ich nicht in der Lage sein, mit vsync (FBIO_WAITFORVSYNC) zu synchronisieren scheinen.
  3. Ich weiß, dass fast jeder Grafikchip da draußen Hardware-Cursor unterstützt, aber DirectFB ist tot, libdrm benötigt X11, und ebenso für Mesa.

In What is hardware cursor and how does it work? behauptet die OP dieses mit ioctl Anrufen erreicht zu haben, die besagen, dass es war einfach, aber sinkende weitere Details zu liefern, weil sein Code proprietär ist. Ich bin mir bewusst, FBIO_CURSOR, aber es scheint nicht Standard und gibt immer EINVAL auf meinem 3.10.0 Kernel.

Was ist der richtige Weg, um einen Framebuffer-Cursor in Abwesenheit von X11 zu zeichnen?

+0

Josh, hast du das herausgefunden? Ich renne heute Abend selbst hinein. Nicht viel da draußen, wenn es um FBIO_CURSOR geht. –

+0

@ Stéphane Bitte sehen Sie die Antwort, die ich gerade gepostet habe. –

Antwort

1

Ich rollte meine eigene Cursor-Unterstützung, da es schien, dass die Kernel-Unterstützung davon abhängig war, was der jeweilige Grafiktreiber unterstützte. Die Aufführung endete für meine Zwecke großartig. Hier ist, was ich getan habe:

  • Öffnen Sie das/dev/fb0 Framebuffer, passen vinfo je nach Bedarf, mmap den Framebuffer und malloc zwei Puffer die gleiche Größe wie die Framebuffer. Einer der Puffer ist mein Backbuffer, wo die ganze Zeichnung passiert. Der andere ist mein "Cursor" -Puffer, wo der Cursor gezeichnet wird.
  • Öffnen Sie das entsprechende/dev/input/eventX in Vorbereitung für das Lesen von Mausereignissen.
  • Definieren Sie eine "Refresh" -Funktion, die aufgerufen wird, wenn etwas in den Back-Puffer gezogen wird oder wenn Mausaktivität vorhanden ist.
  • poll für Mausereignisse mit einem angemessenen Timeout. Ich habe ein Timeout von 500 ms verwendet und dieses in einen pthread gesetzt, so dass es sehr wenig Performance-Overhead hatte.
  • Die "Refresh" -Funktion memcpy versetzt den Rückpuffer in den Cursorpuffer und zeichnet den Cursor darüber. (Ich lösche die Maskenbits unter dem Cursor und zeichne die Cursorbits wie in den Bildern here.) Der Cursorpuffer wird dann in den Framebuffer memcpy editiert.
  • (Ich schütze die Refresh-Funktionalität mit zwei Mutex-Sperren für eine bessere Leistung. Ich erwerbe die erste vor dem Kopieren der Back-Puffer in den Cursor-Puffer und Freigabe nach dem Zeichnen des Cursors. Ich akquiriere die zweite vor dem Zeichnen des Cursors und danach freigeben . den Cursor-Puffer auf den Framebuffer Kopieren Dies verbessert die Leistung spürbar, wenn viele wirklich schnell Zeichnung tun)

einige Gründe für einige meiner Entscheidungen.

  • in den Framebuffer Schreiben recht schnell ist, aber davon zu lesen ist viel langsamer, daher die Verwendung von regulären malloc 'Ed-Speicher für die Rück- und Cursorpuffer.
  • memcpy ist viel schneller als alles, was ich schreiben kann und Thread-sicher ist.
  • Der gleichzeitige Zugriff auf den Framebuffer ist langsam, vermutlich weil memcpy Regionen und Blöcke sperrt, wenn versucht wird, auf eine aktuell verwendete Region zuzugreifen. Aus diesem Grund habe ich zwei Mutexe verwendet, um Kopien vom Rückpuffer zum Cursorpuffer und vom Cursorpuffer zum Framebuffer zu schützen.
  • poll mit einem 0 Timeout entspricht einer engen Schleife, die eine Menge CPU-Zyklen verwendet, daher die Verwendung eines Timeout ungleich Null. Aber poll kehrt zurück, sobald Aktivität am Eingang ist, so dass die Reaktionszeit groß ist. keine besondere Reiß

Auf meiner Hardware, fand ich nicht eine brauchbare Art und Weise mit der Vertikalaustastperiode (ein Teil der ioctl ‚s sind offenbar keine-ops) zu synchronisieren, aber der oben beschriebene Ansatz zeigte. Ja, dieser Ansatz verwendet zwei Offscreen-Puffer, von denen jeder 4 MB auf meinem 1920 x 1080 16-Bit/Pixel-Bildschirm erfordert, aber es ist sehr einfach und ausreichend für meine Bedürfnisse.