Re: cairo_paint crashing with 24 bit bpp
Petr Kobalíček <[email protected]>
| Newsgroups | gmane.comp.lib.cairo |
|---|---|
| Message-ID | <CAB2Z3OdxwPdFFN0z5EZfJKztjLAKfCkdhvXVnUwxNssris8wrw@mail.gmail.com> |
Hi, without any further investigation, I think that the problem is that CAIRO_FORMAT_RGB24 is actually 32-bit, not 24-bit. I would start here, hope that helps. Cheers, Petr On Fri, Feb 27, 2015 at 1:22 PM, <[email protected]> wrote: > Hello, > > I am using a Freescale Vybrid module and running the 3.18.5 kernel on > it. Vybrid has a framebuffer driver and has the concept of multiple > layers. The driver is not in the mainline due to it being a framebuffer > driver and not DRM based. > > http://thread.gmane.org/gmane.linux.ports.arm.kernel/260784/focus=269349 > > It allows for setting BPP to 16, 24 and 32 for each of the framebuffer > layers. The alpha values of each of the five framebuffer layers can be > set by using IOCTL call provided by the driver. The layers have priority > with the 0 layer being highest priority and the highest layer having > lower priority. Depending on the alpha value of each of the individual > layers, these interact to render a blended image. For example, I can set > the alpha value of fb0 to 150 and then set the fb1 to have an alpha > value of 200. What I write to fb1 will appear blended with what is on > fb0. > > Now to write to the individual fbx I am using Cairo. The cairo version > being used is 1.12.16 build using Openembedded. I do have LXDM and X on > it but both are disabled and not required for the use of framebuffer > which I want. X/LXDM is not much of use here as it does not seem to work > with 32 bit bpp. Openembedded build is based on Yocto daisy. > > On using 16 bit bpp and 32 bit bpp I can write successfully to any of > the framebuffers and get the results I am expecting. The alpha value for > each of these framebuffers is being controlled by hardware and the > driver. At 24 bit bpp, calling cairo_paint crashes. I tried using > cairo_paint_with_alpha which also crashes if an alpha value > 0.0 is > specified. If I set alpha to 0.0 and then call it, I can see the images > being rendered but severely distorted kind of. > > I used gdb to track and make sure that it is cairo_paint where this > crashes, using breakpoints at addresses inside cairo_paint to confirm. > I do not have the disassembled output of cairo library with source, but, > this is probably at the cr->backend->paint call. I was only able to > trace the address based on PLT entries in disassembled output of my > cairo application. > > Not being too well versed with cairo or graphics, can someone point me > in the right direction here and give some inputs as to why I am > observing this with 24 bit bpp. > > My code piece is as below: > #include <stdio.h> > #include <stdlib.h> > #include <string.h> > #include <fcntl.h> > #include <linux/types.h> > #include <linux/ioctl.h> > #include <linux/fb.h> > #include <sys/mman.h> > #include <cairo/cairo.h> > > #define DELAY_IN_SECS 5 > #define SCALE_WIDTH 256.0 > #define SCALE_HEIGHT 256.0 > > 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; > > /* Destroy a cairo surface */ > 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); > } > > /* Create a cairo surface using the specified framebuffer */ > cairo_surface_t *cairo_linuxfb_surface_create(const char *fb_name) > { > int color_input; > cairo_linuxfb_device_t *device; > cairo_surface_t *surface; > > /* Use fb0 if no fram buffer is specified */ > 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; > } > > printf("1. CAIRO_FORMAT_RGB16_565\n"); > printf("2. CAIRO_FORMAT_RGB24\n"); > printf("3. CAIRO_FORMAT_ARGB32\n"); > printf("Enter the color input:\t"); > scanf("%d", &color_input); > switch(color_input) { > case 1: > /* Create the cairo surface which will be used to draw > to */ > surface = cairo_image_surface_create_for_data(device->fb_data, > CAIRO_FORMAT_RGB16_565, > device->fb_vinfo.xres, > device->fb_vinfo.yres, > > cairo_format_stride_for_width(CAIRO_FORMAT_RGB16_565, > > device->fb_vinfo.xres)); > break; > case 2: > /* Create the cairo surface which will be used to draw > to */ > 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)); > break; > case 3: > /* Create the cairo surface which will be used to draw > to */ > surface = cairo_image_surface_create_for_data(device->fb_data, > CAIRO_FORMAT_ARGB32, > device->fb_vinfo.xres, > device->fb_vinfo.yres, > cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, > > device->fb_vinfo.xres)); > break; > default: > printf("Invalid input. Selecting > CAIRO_FORMAT_RGB16_565\n"); > /* Create the cairo surface which will be used to draw > to */ > surface = cairo_image_surface_create_for_data(device->fb_data, > CAIRO_FORMAT_RGB16_565, > device->fb_vinfo.xres, > device->fb_vinfo.yres, > > cairo_format_stride_for_width(CAIRO_FORMAT_RGB16_565, > > device->fb_vinfo.xres)); > break; > } > > if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) { > perror("Error in creating cairo surface\n"); > goto handle_ioctl_error; > } > > 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[]) { > int image_width; > int image_height; > float cairo_alpha_value; > char frame_buffer_number; > char fb_node[16] = {0}; > cairo_surface_t *surface; > cairo_surface_t *image; > cairo_t *cr; > > if (argc != 2) { > printf("Usage: ./cairo /path/to/png/image\n"); > exit(1); > } > > if (strstr(argv[1], ".png") == NULL) { > printf("Only png images are supported with this > example\n"); > exit(1); > } > > printf("Enter frame buffer number:\t"); > scanf("%c", &frame_buffer_number); > sprintf(fb_node, "/dev/fb"); > fb_node[strlen(fb_node)] = frame_buffer_number; > fb_node[strlen(fb_node)] = '\0'; > printf("Frame buffer node is: %s\n", fb_node); > > surface = cairo_linuxfb_surface_create(fb_node); > cr = cairo_create(surface); > if (cairo_status(cr) != CAIRO_STATUS_SUCCESS) { > printf("Error in creating cairo surface\n"); > cairo_surface_destroy(surface); > exit(1); > } > > printf("Enter the cairo alpha value to paint with:\t"); > scanf("%f", &cairo_alpha_value); > > /* > * We clear the cairo surface here before drawing > * This is required in case something was drawn on this surface > * previously, the previous contents would not be cleared > without this. > */ > cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); > cairo_paint_with_alpha(cr, cairo_alpha_value); > 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, 32.0); > cairo_set_source_rgb(cr, 1.0, 1.0, 0.0); > cairo_move_to(cr, 100, 300); > cairo_show_text(cr, "Toradex Cairo Example!"); > > /* Wait for the result of drawing operation to persist for the > user to see */ > sleep(DELAY_IN_SECS); > /* Clear the surface and prepare for a new drawing operation */ > cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); > cairo_paint_with_alpha(cr, cairo_alpha_value); > cairo_set_operator(cr, CAIRO_OPERATOR_OVER); > > image = cairo_image_surface_create_from_png(argv[1]); > image_width = cairo_image_surface_get_width(image); > image_height = cairo_image_surface_get_height(image); > > /* Scale the image arbitrarily */ > cairo_scale(cr, SCALE_WIDTH/image_width, > SCALE_HEIGHT/image_height); > > cairo_set_source_surface(cr, image, 350, 200); > cairo_paint(cr); > /* Wait for the result of the drawing operation to persist for > the user to see */ > sleep(DELAY_IN_SECS); > > /* Destroy and release all cairo related contexts */ > cairo_destroy(cr); > cairo_surface_destroy(surface); > > return 0; > } > > > Regards, > Victor. > -- > cairo mailing list > [email protected] > http://lists.cairographics.org/mailman/listinfo/cairo -- cairo mailing list [email protected] http://lists.cairographics.org/mailman/listinfo/cairo