[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