0

I am developing a Linux application to draw information to a 24 bit LCD screen using Cairo. But the LCD display prints 3 images instead of one image which I drew. This also prints in the wrong colour I tried to change all the cairo_format options but had no luck.

My code is

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 memory\n");
        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, &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, &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,
            &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;
}

I tried CAIRO_FORMAT_ARGB32, CAIRO_FORMAT_RGB24,CAIRO_FORMAT_RGB16_565, CAIRO_FORMAT_RGB30. None of them worked correctly. Spend several days on the internet and not much information about the issue.

4

0 回答 0