<div dir="ltr">Hi, without any further investigation, I think that the problem is that <div><br></div><div> <span style="font-size:12.8000001907349px">CAIRO_FORMAT_RGB24</span></div><div class="gmail_extra"><br></div><div class="gmail_extra">is actually 32-bit, not 24-bit.</div><div class="gmail_extra"><br></div><div class="gmail_extra">I would start here, hope that helps.</div><div class="gmail_extra"><br></div><div class="gmail_extra">Cheers,</div><div class="gmail_extra">Petr<br clear="all"><div><div class="gmail_signature"><br></div></div><div class="gmail_quote">On Fri, Feb 27, 2015 at 1:22 PM, <span dir="ltr"><<a href="mailto:victorascroft@gmail.com" target="_blank">victorascroft@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hello,<br>
<br>
I am using a Freescale Vybrid module and running the 3.18.5 kernel on<br>
it. Vybrid has a framebuffer driver and has the concept of multiple<br>
layers. The driver is not in the mainline due to it being a framebuffer<br>
driver and not DRM based.<br>
<br>
<a href="http://thread.gmane.org/gmane.linux.ports.arm.kernel/260784/focus=269349" target="_blank">http://thread.gmane.org/gmane.linux.ports.arm.kernel/260784/focus=269349</a><br>
<br>
It allows for setting BPP to 16, 24 and 32 for each of the framebuffer<br>
layers. The alpha values of each of the five framebuffer layers can be<br>
set by using IOCTL call provided by the driver. The layers have priority<br>
with the 0 layer being highest priority and the highest layer having<br>
lower priority. Depending on the alpha value of each of the individual<br>
layers, these interact to render a blended image. For example, I can set<br>
the alpha value of fb0 to 150 and then set the fb1 to have an alpha<br>
value of 200. What I write to fb1 will appear blended with what is on<br>
fb0.<br>
<br>
Now to write to the individual fbx I am using Cairo. The cairo version<br>
being used is 1.12.16 build using Openembedded. I do have LXDM and X on<br>
it but both are disabled and not required for the use of framebuffer<br>
which I want. X/LXDM is not much of use here as it does not seem to work<br>
with 32 bit bpp. Openembedded build is based on Yocto daisy.<br>
<br>
On using 16 bit bpp and 32 bit bpp I can write successfully to any of<br>
the framebuffers and get the results I am expecting. The alpha value for<br>
each of these framebuffers is being controlled by hardware and the<br>
driver. At 24 bit bpp, calling cairo_paint crashes. I tried using<br>
cairo_paint_with_alpha which also crashes if an alpha value > 0.0 is<br>
specified. If I set alpha to 0.0 and then call it, I can see the images<br>
being rendered but severely distorted kind of.<br>
<br>
I used gdb to track and make sure that it is cairo_paint where this<br>
crashes, using breakpoints at addresses inside cairo_paint to confirm.<br>
I do not have the disassembled output of cairo library with source, but,<br>
this is probably at the cr->backend->paint call. I was only able to<br>
trace the address based on PLT entries in disassembled output of my<br>
cairo application.<br>
<br>
Not being too well versed with cairo or graphics, can someone point me<br>
in the right direction here and give some inputs as to why I am<br>
observing this with 24 bit bpp.<br>
<br>
My code piece is as below:<br>
#include <stdio.h><br>
#include <stdlib.h><br>
#include <string.h><br>
#include <fcntl.h><br>
#include <linux/types.h><br>
#include <linux/ioctl.h><br>
#include <linux/fb.h><br>
#include <sys/mman.h><br>
#include <cairo/cairo.h><br>
<br>
#define DELAY_IN_SECS 5<br>
#define SCALE_WIDTH 256.0<br>
#define SCALE_HEIGHT 256.0<br>
<br>
typedef struct _cairo_linuxfb_device {<br>
int fb_fd;<br>
char *fb_data;<br>
long fb_screensize;<br>
struct fb_var_screeninfo fb_vinfo;<br>
struct fb_fix_screeninfo fb_finfo;<br>
} cairo_linuxfb_device_t;<br>
<br>
/* Destroy a cairo surface */<br>
void cairo_linuxfb_surface_destroy(void *device)<br>
{<br>
cairo_linuxfb_device_t *dev = (cairo_linuxfb_device_t *)device;<br>
<br>
if (dev == NULL)<br>
return;<br>
<br>
munmap(dev->fb_data, dev->fb_screensize);<br>
close(dev->fb_fd);<br>
free(dev);<br>
}<br>
<br>
/* Create a cairo surface using the specified framebuffer */<br>
cairo_surface_t *cairo_linuxfb_surface_create(const char *fb_name)<br>
{<br>
int color_input;<br>
cairo_linuxfb_device_t *device;<br>
cairo_surface_t *surface;<br>
<br>
/* Use fb0 if no fram buffer is specified */<br>
if (fb_name == NULL) {<br>
fb_name = "/dev/fb0";<br>
}<br>
<br>
device = malloc(sizeof(*device));<br>
if (!device) {<br>
perror("Error: cannot allocate memory\n");<br>
exit(1);<br>
}<br>
<br>
// Open the file for reading and writing<br>
device->fb_fd = open(fb_name, O_RDWR);<br>
if (device->fb_fd == -1) {<br>
perror("Error: cannot open framebuffer device");<br>
goto handle_allocate_error;<br>
}<br>
<br>
// Get variable screen information<br>
if (ioctl(device->fb_fd, FBIOGET_VSCREENINFO, &device->fb_vinfo)<br>
== -1) {<br>
perror("Error: reading variable information");<br>
goto handle_ioctl_error;<br>
}<br>
<br>
// Figure out the size of the screen in bytes<br>
device->fb_screensize = device->fb_vinfo.xres *<br>
device->fb_vinfo.yres<br>
* device->fb_vinfo.bits_per_pixel / 8;<br>
<br>
// Map the device to memory<br>
device->fb_data = (char *)mmap(0, device->fb_screensize,<br>
PROT_READ | PROT_WRITE,<br>
MAP_SHARED,<br>
device->fb_fd, 0);<br>
if ((int)device->fb_data == -1) {<br>
perror("Error: failed to map framebuffer device to<br>
memory");<br>
goto handle_ioctl_error;<br>
}<br>
<br>
// Get fixed screen information<br>
if (ioctl(device->fb_fd, FBIOGET_FSCREENINFO, &device->fb_finfo)<br>
== -1) {<br>
perror("Error reading fixed information");<br>
goto handle_ioctl_error;<br>
}<br>
<br>
printf("1. CAIRO_FORMAT_RGB16_565\n");<br>
printf("2. CAIRO_FORMAT_RGB24\n");<br>
printf("3. CAIRO_FORMAT_ARGB32\n");<br>
printf("Enter the color input:\t");<br>
scanf("%d", &color_input);<br>
switch(color_input) {<br>
case 1:<br>
/* Create the cairo surface which will be used to draw<br>
to */<br>
surface = cairo_image_surface_create_for_data(device->fb_data,<br>
CAIRO_FORMAT_RGB16_565,<br>
device->fb_vinfo.xres,<br>
device->fb_vinfo.yres,<br>
<br>
cairo_format_stride_for_width(CAIRO_FORMAT_RGB16_565,<br>
<br>
device->fb_vinfo.xres));<br>
break;<br>
case 2:<br>
/* Create the cairo surface which will be used to draw<br>
to */<br>
surface = cairo_image_surface_create_for_data(device->fb_data,<br>
CAIRO_FORMAT_RGB24,<br>
device->fb_vinfo.xres,<br>
device->fb_vinfo.yres,<br>
cairo_format_stride_for_width(CAIRO_FORMAT_RGB24,<br>
<br>
device->fb_vinfo.xres));<br>
break;<br>
case 3:<br>
/* Create the cairo surface which will be used to draw<br>
to */<br>
surface = cairo_image_surface_create_for_data(device->fb_data,<br>
CAIRO_FORMAT_ARGB32,<br>
device->fb_vinfo.xres,<br>
device->fb_vinfo.yres,<br>
cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32,<br>
<br>
device->fb_vinfo.xres));<br>
break;<br>
default:<br>
printf("Invalid input. Selecting<br>
CAIRO_FORMAT_RGB16_565\n");<br>
/* Create the cairo surface which will be used to draw<br>
to */<br>
surface = cairo_image_surface_create_for_data(device->fb_data,<br>
CAIRO_FORMAT_RGB16_565,<br>
device->fb_vinfo.xres,<br>
device->fb_vinfo.yres,<br>
<br>
cairo_format_stride_for_width(CAIRO_FORMAT_RGB16_565,<br>
<br>
device->fb_vinfo.xres));<br>
break;<br>
}<br>
<br>
if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {<br>
perror("Error in creating cairo surface\n");<br>
goto handle_ioctl_error;<br>
}<br>
<br>
cairo_surface_set_user_data(surface, NULL, device,<br>
<br>
&cairo_linuxfb_surface_destroy);<br>
<br>
return surface;<br>
<br>
handle_ioctl_error:<br>
close(device->fb_fd);<br>
handle_allocate_error:<br>
free(device);<br>
exit(1);<br>
}<br>
<br>
int main(int argc, char *argv[]) {<br>
int image_width;<br>
int image_height;<br>
float cairo_alpha_value;<br>
char frame_buffer_number;<br>
char fb_node[16] = {0};<br>
cairo_surface_t *surface;<br>
cairo_surface_t *image;<br>
cairo_t *cr;<br>
<br>
if (argc != 2) {<br>
printf("Usage: ./cairo /path/to/png/image\n");<br>
exit(1);<br>
}<br>
<br>
if (strstr(argv[1], ".png") == NULL) {<br>
printf("Only png images are supported with this<br>
example\n");<br>
exit(1);<br>
}<br>
<br>
printf("Enter frame buffer number:\t");<br>
scanf("%c", &frame_buffer_number);<br>
sprintf(fb_node, "/dev/fb");<br>
fb_node[strlen(fb_node)] = frame_buffer_number;<br>
fb_node[strlen(fb_node)] = '\0';<br>
printf("Frame buffer node is: %s\n", fb_node);<br>
<br>
surface = cairo_linuxfb_surface_create(fb_node);<br>
cr = cairo_create(surface);<br>
if (cairo_status(cr) != CAIRO_STATUS_SUCCESS) {<br>
printf("Error in creating cairo surface\n");<br>
cairo_surface_destroy(surface);<br>
exit(1);<br>
}<br>
<br>
printf("Enter the cairo alpha value to paint with:\t");<br>
scanf("%f", &cairo_alpha_value);<br>
<br>
/*<br>
* We clear the cairo surface here before drawing<br>
* This is required in case something was drawn on this surface<br>
* previously, the previous contents would not be cleared<br>
without this.<br>
*/<br>
cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);<br>
cairo_paint_with_alpha(cr, cairo_alpha_value);<br>
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);<br>
<br>
cairo_select_font_face(cr, "serif", CAIRO_FONT_SLANT_NORMAL,<br>
CAIRO_FONT_WEIGHT_BOLD);<br>
cairo_set_font_size(cr, 32.0);<br>
cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);<br>
cairo_move_to(cr, 100, 300);<br>
cairo_show_text(cr, "Toradex Cairo Example!");<br>
<br>
/* Wait for the result of drawing operation to persist for the<br>
user to see */<br>
sleep(DELAY_IN_SECS);<br>
/* Clear the surface and prepare for a new drawing operation */<br>
cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);<br>
cairo_paint_with_alpha(cr, cairo_alpha_value);<br>
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);<br>
<br>
image = cairo_image_surface_create_from_png(argv[1]);<br>
image_width = cairo_image_surface_get_width(image);<br>
image_height = cairo_image_surface_get_height(image);<br>
<br>
/* Scale the image arbitrarily */<br>
cairo_scale(cr, SCALE_WIDTH/image_width,<br>
SCALE_HEIGHT/image_height);<br>
<br>
cairo_set_source_surface(cr, image, 350, 200);<br>
cairo_paint(cr);<br>
/* Wait for the result of the drawing operation to persist for<br>
the user to see */<br>
sleep(DELAY_IN_SECS);<br>
<br>
/* Destroy and release all cairo related contexts */<br>
cairo_destroy(cr);<br>
cairo_surface_destroy(surface);<br>
<br>
return 0;<br>
}<br>
<br>
<br>
Regards,<br>
Victor.<br>
<span class="HOEnZb"><font color="#888888">--<br>
cairo mailing list<br>
<a href="mailto:cairo@cairographics.org">cairo@cairographics.org</a><br>
<a href="http://lists.cairographics.org/mailman/listinfo/cairo" target="_blank">http://lists.cairographics.org/mailman/listinfo/cairo</a></font></span></blockquote></div><br></div></div>