[cairo] cairo_paint crashing with 24 bit bpp

Petr Kobalíček kobalicek.petr at gmail.com
Fri Feb 27 11:52:37 PST 2015


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, <victorascroft at gmail.com> 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
> cairo at cairographics.org
> http://lists.cairographics.org/mailman/listinfo/cairo
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.cairographics.org/archives/cairo/attachments/20150227/e7a84976/attachment-0001.html>


More information about the cairo mailing list