Рисуйте Непосредственно На 24 — Битном TFT — Дисплее С Помощью Cairo

#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.