Versuchen Sie, den Frame Buffer (/ dev / fbXX) unter Linux zu lesen und zu schreiben. Dieser Artikel erwähnt es speziell für den Raspberry Pi, aber ich denke, es ist das gleiche für andere Linux. Die bestätigte Umgebung ist Raspberry Pi 2, die Bildausgabe ist HDMI und die Auflösung ist DMT-Modus 9 (800 x 600). Hauptanwendung:
――Ich möchte den Bildschirm von Raspeye auf meinem eigenen Anzeigegerät ausgeben
Unter Linux können Sie über die Gerätedatei (/ dev / fbXX) auf den Frame-Puffer zugreifen. Es wird in Raspeye als / dev / fb0
vorbereitet. Dieser Inhalt wird auf dem Display und HDMI ausgegeben.
Sie können die Bilddaten speichern, indem Sie Folgendes über die Befehlszeile eingeben (wie bei der Bildschirmaufnahme). Wenn Sie das Gegenteil tun, können Sie schreiben (auf dem Display zeichnen).
cat /dev/fb0 > aaa.raw
Die erfassten RAW-Bilddaten bestehen aus 4 Bytes (32 Bit), z. B. ARGB pro Pixel. Dies sind im Gegensatz zu JPEG und BMP Rohpixeldaten. Daher ist es notwendig, beim Spielen die Größe usw. anzugeben. Mit dem folgenden Befehl erhalten Sie die benötigten Informationen.
fbset
mode "800x600"
geometry 800 600 800 600 32
timings 0 0 0 0 0 0 0
rgba 8/16,8/
Alternativ können Sie das gleiche Ergebnis mit dem folgenden Befehl erhalten.
cat /sys/class/graphics/fb0/bits_per_pixel
32
cat /sys/class/graphics/fb0/virtual_size
800,600
Dies ist ein Einstellungsbeispiel beim Anzeigen mit IrfanView. Durch Ziehen und Ablegen eines Bildes mit der Erweiterung RAW können verschiedene Einstellungen vorgenommen werden. Wenn das Display die oben genannten Einstellungen hat, sollten Sie in der Lage sein, mit den folgenden Einstellungen korrekt anzuzeigen. (Der Einstellwert ändert sich je nach Umgebung.)
Es sollte rot gestrichen sein, wird aber in VNC nicht aktualisiert. Wenn Sie es mit HDMI betrachten, ist es richtig gefüllt.
Dies ist der Code zum Abrufen der Bildpufferinformationen. Es gibt zwei Möglichkeiten, dies zu tun. Das Ergebnis ist das gleiche, unabhängig davon, welches Sie tun. getFrameBufferSize ()
liest Informationen als Zeichenfolge aus dem oben genannten / sys / class / graphics / fb0 / bits_per_pixel
. getFrameBufferSize2 ()
verwendetioctl ()
, um die Geräteinformationen abzurufen.
getSizeFrameBuffer.cpp
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/errno.h>
#include <sys/fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <linux/omapfb.h>
void getFrameBufferSize(int* width, int* height, int* colorWidth)
{
int fd;
int n;
char str[64];
/* Get Bit Per Pixel (usually 32-bit(4Byte) */
fd = open("/sys/class/graphics/fb0/bits_per_pixel", O_RDONLY);
n = read(fd, str, sizeof(str));
str[n] = '\0';
*colorWidth = atoi(str);
close(fd);
/* Get Frame Buffer Size */
fd = open("/sys/class/graphics/fb0/virtual_size", O_RDONLY);
n = read(fd, str, sizeof(str));
str[n] = '\0';
/* divide "800,600" into "800" and "600" */
*width = atoi(strtok(str, ","));
*height = atoi(strtok(NULL, ","));
close(fd);
}
void getFrameBufferSize2(int* width, int* height, int* colorWidth)
{
struct fb_var_screeninfo var;
int fd;
fd = open("/dev/fb0", O_RDWR);
ioctl(fd, FBIOGET_VSCREENINFO, &var);
*colorWidth = var.bits_per_pixel;
*width = var.xres_virtual;
*height = var.yres_virtual;
close(fd);
}
Code, der Bilddaten aus dem Bildspeicher liest. Es macht dasselbe wie die obige Katze, indem es / dev / fb0
öffnet, liest und schließt. Es kann auch durch Zuordnen von / dev / fb0
gelesen werden. Sie sind "readBuffer ()" bzw. "readBuffer2 ()". Sie können die Daten mit beiden Methoden lesen. Je nachdem, wie Sie sie verwenden, kann es jedoch zu einer nutzlosen Speicherkopie kommen. Daher ist es besser, sie je nach Verwendungszweck zu verwenden.
readFrameBuffer.cpp
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/errno.h>
#include <sys/fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <linux/omapfb.h>
void readBuffer(int width, int height, void* dstBuffer)
{
int fd;
fd = open("/dev/fb0", O_RDONLY);
read(fd, dstBuffer, width * height * 4);
close(fd);
}
void readBuffer2(int width, int height, void* dstBuffer)
{
int fd;
fd = open("/dev/fb0", O_RDONLY);
uint32_t *frameBuffer = (uint32_t *)mmap(NULL, width * height * 4, PROT_READ, MAP_SHARED, fd, 0);
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
((uint32_t*)dstBuffer)[x + y * width] = frameBuffer[x + y * width];
}
}
munmap(frameBuffer, width * height * 4);
close(fd);
}
Code, der Bilddaten in den Bildspeicher schreibt. Auf diese Weise können Sie direkt auf dem Display zeichnen (HDMI-Ausgang). Jedoch,
Es gibt ein Problem wie. Ich hätte gerne eine Möglichkeit, den Zugriff auf den Frame-Puffer vollständig zu entführen, aber ich untersuche dies.
Sie können schreiben, indem Sie / dev / fb0
öffnen, schreiben und schließen. Hier wird beispielsweise ein mit einer einzelnen Farbe gefüllter Puffer ausgegeben. Sie können dasselbe tun, indem Sie sowohl mmaping als auch lesen. Da mmap direkt schreiben kann, denke ich, dass es je nach Anwendung effizienter sein wird. Beachten Sie jedoch bei der Verwendung von mMap, dass der Wert möglicherweise erst geschrieben wird, wenn Sie "msync" aufrufen.
writeFrameBuffer.cpp
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/errno.h>
#include <sys/fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <linux/omapfb.h>
// color = AARRGGBB
void drawColor(int width, int height, int color)
{
uint32_t *canvas = new uint32_t[width * height];
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
canvas[x + y * width] = color;
}
}
int fd;
fd = open("/dev/fb0", O_WRONLY);
write(fd, canvas, width * height * 4);
close(fd);
delete[] canvas;
}
// color = AARRGGBB
void drawColor2(int width, int height, int color)
{
int fd;
fd = open("/dev/fb0", O_RDWR);
uint32_t *frameBuffer = (uint32_t *)mmap(NULL, width * height * 4, PROT_WRITE, MAP_SHARED, fd, 0);
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
frameBuffer[x + y * width] = color;
}
}
msync(frameBuffer, width * height * 4, 0);
munmap(frameBuffer, width * height * 4);
close(fd);
}
Ein Beispiel ist das Lesen der Bildpufferinformationen, das Aufnehmen einer Bildschirmaufnahme und das Ausfüllen des gesamten Bildschirms in Rot. Selbst wenn es rot gestrichen ist, werden der Bereich in der Nähe des Cursors im CUI-Modus und der Bereich in der Nähe der Menüleiste im GUI-Modus vom Betriebssystem überschrieben (es scheint, dass die Zeichnung nur aktualisiert wird, wenn sich auf dem Bildschirm etwas ändert).
Kompilieren Sie mit g ++ main.cpp getSizeFrameBuffer.cpp readFrameBuffer.cpp writeFrameBuffer.cpp
main.cpp
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void getFrameBufferSize(int* width, int* height, int* colorWidth);
void getFrameBufferSize2(int* width, int* height, int* colorWidth);
void drawColor(int width, int height, int color);
void drawColor2(int width, int height, int color);
void readBuffer(int width, int height, void* dstBuffer);
void readBuffer2(int width, int height, void* dstBuffer);
void saveFileBinary(const char* filename, void* data, int size);
// g++ main.cpp getSizeFrameBuffer.cpp readFrameBuffer.cpp writeFrameBuffer.cpp
int main()
{
int colorWidth;
int width;
int height;
/* get frame buffer size */
getFrameBufferSize(&width, &height, &colorWidth);
printf("%d(W) x %d(H) x %d(Bit)\n", width, height, colorWidth);
/* screen capture */
uint32_t *buffer = new uint32_t[width * height];
readBuffer(width, height, buffer);
saveFileBinary("capture.raw", buffer, width * height * 4);
delete[] buffer;
/* Fill solid color */
drawColor(width, height, 0xFFFF0000); // RED
}
void saveFileBinary(const char* filename, void* data, int size)
{
FILE *fp;
fp = fopen(filename, "wb");
fwrite(data, 1, size, fp);
fclose(fp);
}
Todo
http://archive.linux.or.jp/JF/JFdocs/kernel-docs-2.6/fb/framebuffer.txt.html
Recommended Posts