Essayez de lire et d'écrire le tampon de trame (/ dev / fbXX) sous Linux. Cet article le mentionne spécifiquement pour le Raspberry Pi, mais je pense que c'est la même chose pour les autres Linux. L'environnement confirmé est Raspberry Pi 2, la sortie d'image est HDMI et la résolution est le mode DMT 9 (800x600). Utilisation principale:
――Je veux sortir l'écran de Raspeye sur mon propre périphérique d'affichage
Sous Linux, vous pouvez accéder au frame buffer via le fichier de périphérique (/ dev / fbXX). Il est préparé en tant que / dev / fb0
dans Raspeye. Ce contenu est émis vers l'écran et HDMI.
Vous pouvez enregistrer les données d'image en tapant ce qui suit à partir de la ligne de commande (identique à la capture d'écran). Si vous faites le contraire, vous pouvez écrire (dessiner sur l'écran).
cat /dev/fb0 > aaa.raw
Les données d'image RAW acquises sont composées de 4 octets (32 bits) tels que ARGB par pixel. Il s'agit de données de pixels brutes, contrairement au JPEG et au BMP. Par conséquent, il est nécessaire de spécifier la taille, etc. lors de la lecture. Vous pouvez obtenir les informations dont vous avez besoin avec la commande suivante.
fbset
mode "800x600"
geometry 800 600 800 600 32
timings 0 0 0 0 0 0 0
rgba 8/16,8/
Vous pouvez également obtenir le même résultat avec la commande suivante.
cat /sys/class/graphics/fb0/bits_per_pixel
32
cat /sys/class/graphics/fb0/virtual_size
800,600
Ceci est un exemple de réglage lors de la visualisation avec IrfanView. Différents paramètres peuvent être définis en faisant glisser et en déposant une image avec l'extension définie sur RAW. Si l'écran possède les paramètres ci-dessus, vous devriez pouvoir afficher correctement avec les paramètres suivants. (La valeur de réglage change en fonction de l'environnement)
Il aurait dû être peint en rouge, mais il ne sera pas mis à jour dans VNC. En le regardant avec HDMI, il est correctement rempli.
Ceci est le code pour obtenir les informations sur le tampon de trame. Il y a deux manières de procéder. Le résultat est le même quel que soit celui que vous faites. getFrameBufferSize ()
lit les informations sous forme de chaîne de caractères à partir de ce qui précède / sys / class / graphics / fb0 / bits_per_pixel
. getFrameBufferSize2 ()
utilise ʻioctl () `pour obtenir des informations sur le périphérique.
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 qui lit les données d'image à partir du tampon de trame. Il fait la même chose que cat ci-dessus en ouvrant, lisant et se fermant sur / dev / fb0
. Il peut également être lu en mappant / dev / fb0
. Ce sont respectivement «readBuffer ()» et «readBuffer2 ()». Vous pouvez lire les données en utilisant l'un ou l'autre, mais selon la façon dont vous les utilisez, une copie de mémoire inutile peut se produire, il est donc préférable de l'utiliser en fonction de l'objectif.
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 qui écrit les données d'image dans le tampon de trame. Cela vous permet de dessiner directement sur l'écran (sortie HDMI). cependant,
Il y a un problème tel que. Je voudrais avoir un moyen de détourner complètement l'accès au tampon de trame, mais j'enquête.
Vous pouvez écrire en ouvrant, en écrivant et en fermant vers / dev / fb0
. Ici, à titre d'exemple, un tampon rempli d'une seule couleur est sorti. Vous pouvez faire la même chose en mmaping ainsi qu'en lisant. Puisque mmap peut écrire directement, je pense que ce sera plus efficace en fonction de l'application. Cependant, lorsque vous utilisez mMap, sachez que la valeur peut ne pas être écrite tant que vous n'avez pas appelé msync
.
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);
}
Ceci est un exemple de lecture des informations du tampon de trame, de capture d'écran et de remplissage de tout l'écran en rouge. Cependant, même s'il est peint en rouge, la zone près du curseur en mode CUI et la zone près de la barre de menu en mode GUI seront écrasées par le système d'exploitation (il semble que le dessin ne soit mis à jour que là où il y a un changement à l'écran).
Compilez avec 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