#ubuntu #raspbian #cairo #framebuffer #pangocairo
Вопрос:
Я разрабатываю приложение Linux для отображения информации на 24-битном ЖК — экране с помощью Cairo. Но ЖК — дисплей выводит 3 изображения вместо одного изображения, которое я нарисовал. Это также печатает неправильный цвет, я попытался изменить все параметры cairo_format, но безуспешно.
Мой код таков
typedef struct _cairo_linuxfb_device {
int fb_fd;
char *fb_data;
long fb_screensize;
struct fb_var_screeninfo fb_vinfo;
struct fb_fix_screeninfo fb_finfo;
} cairo_linuxfb_device_t;
void cairo_linuxfb_surface_destroy(void *device)
{
cairo_linuxfb_device_t *dev = (cairo_linuxfb_device_t *)device;
if (dev == NULL)
return;
munmap(dev->fb_data, dev->fb_screensize);
close(dev->fb_fd);
free(dev);
}
cairo_surface_t *cairo_linuxfb_surface_create(const char *fb_name)
{
cairo_linuxfb_device_t *device;
cairo_surface_t *surface;
if (fb_name == NULL) {
fb_name = "/dev/fb0";
}
device = malloc(sizeof(*device));
if (!device) {
perror("Error: cannot allocate memoryn");
exit(1);
}
// Open the file for reading and writing
device->fb_fd = open(fb_name, O_RDWR);
if (device->fb_fd == -1) {
perror("Error: cannot open framebuffer device");
goto handle_allocate_error;
}
// Get variable screen information
if (ioctl(device->fb_fd, FBIOGET_VSCREENINFO, amp;device->fb_vinfo) == -1) {
perror("Error: reading variable information");
goto handle_ioctl_error;
}
// Figure out the size of the screen in bytes
device->fb_screensize = device->fb_vinfo.xres * device->fb_vinfo.yres
* device->fb_vinfo.bits_per_pixel / 8;
// Map the device to memory
device->fb_data = (char *)mmap(0, device->fb_screensize,
PROT_READ | PROT_WRITE, MAP_SHARED,
device->fb_fd, 0);
if ((int)device->fb_data == -1) {
perror("Error: failed to map framebuffer device to memory");
goto handle_ioctl_error;
}
// Get fixed screen information
if (ioctl(device->fb_fd, FBIOGET_FSCREENINFO, amp;device->fb_finfo) == -1) {
perror("Error reading fixed information");
goto handle_ioctl_error;
}
surface = cairo_image_surface_create_for_data(device->fb_data,
CAIRO_FORMAT_RGB24,
device->fb_vinfo.xres,
device->fb_vinfo.yres,
cairo_format_stride_for_width(CAIRO_FORMAT_RGB24,
device->fb_vinfo.xres));
cairo_surface_set_user_data(surface, NULL, device,
amp;cairo_linuxfb_surface_destroy);
return surface;
handle_ioctl_error:
close(device->fb_fd);
handle_allocate_error:
free(device);
exit(1);
}
int main(int argc, char *argv[]) {
cairo_surface_t *surface;
cairo_t *cr;
surface = cairo_linuxfb_surface_create("/dev/fb1");
cr = cairo_create(surface);
cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
cairo_paint(cr);
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
cairo_select_font_face(cr, "serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
cairo_set_font_size(cr, 30.0);
cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
//Draw lines
cairo_move_to (cr, 10, 10);
cairo_line_to (cr, 150, 10);
cairo_stroke (cr);
cairo_move_to(cr, 30, 40);
cairo_show_text(cr, "Cairo!");
cairo_destroy(cr);
cairo_surface_destroy(surface);
return 0;
}
Я пробовал CAIRO_FORMAT_ARGB32, CAIRO_FORMAT_RGB24,CAIRO_FORMAT_RGB16_565, CAIRO_FORMAT_RGB30. Ни один из них не работал правильно. Проведите несколько дней в Интернете и не получите много информации о проблеме.
Комментарии:
1. Хорошо. Я понятия не имею об этом API буфера кадров. Google нашел kernel.org/doc/Documentation/fb/api.txt . Итак… какие у вас есть значения для
fb_fix_screeninfo->visual
иfb_var_screeninfo->bits_per_pixel
. Хм… а также поляred
,green
,blue
могут быть интересными, я думаю.2. fb_fix_screeninfo->визуальный = 2 и fb_var_screeninfo->>bits_per_pixel = 24
3. Да, это не пиксельный формат, который напрямую поддерживается cairo. У вас каждый пиксель занимает три байта (я думаю: красный, зеленый, синий). Каир может делать только четыре байта на пиксель. Вам придется вручную конвертировать в этот пиксельный формат после каждого розыгрыша.
4. У меня нет большого опыта в программировании на Linux C, можете ли вы объяснить это примером кода
5. Обращение? Хм… что-то вроде
uint8_t *to = [...], *from = [...]; for each pixel { to[0] = from[0]; to[1] = from[1]; to[2] = from[2]; to = 4; from = 3; }
. Понятия не имею, правильно ли я понял представление байтов. Возможно также, что, напримерto[0] = from[1]
, требуется etc.