[cairo] Slow painting of images

Evan Martin martine at danga.com
Wed Oct 26 07:54:58 PDT 2005


Just a guess (I looked through the Cairo source and couldn't confirm
it), but perhaps creating the xlib surface on every draw is expensive
-- it seems if that were cheap there wouldn't be an API for resizing
surfaces.  Other code I've seen that does similar things creates the
surface when you create the window.

On 10/26/05, Haakon Riiser <haakon.riiser at fys.uio.no> wrote:
> I've recently started experimenting with the Cairo library, and I
> think I'm doing something wrong.  I'm trying to display some PNG
> images, and although it works, it is _extremely_ slow.  Take a look
> at the test program shown below (btw, it is based on some sample code
> I found in the cairo-demo package).  At first I thought it was slow
> because the PNG image is reloaded every time the picture is drawn,
> but I tried moving the loading of the PNG image away so that it was
> only done once, and it didn't appear to make things faster.  Thanks
> in advance for any help!
>
> /* ------------------------------------------------------------------------ */
> #include <stdio.h>
> #include <stdlib.h>
> #include <cairo.h>
> #include <cairo-xlib.h>
>
> typedef struct win {
>         Display *dpy;
>         int scr;
>
>         Window win;
>         GC gc;
>
>         int width, height;
>         KeyCode quit_code;
> } win_t;
>
> static void win_init(win_t *win);
> static void win_draw(win_t *win);
> static void win_handle_events(win_t *win);
>
> int
> main(int argc, char *argv[])
> {
>         win_t win;
>
>         win.dpy = XOpenDisplay(0);
>         if (win.dpy == NULL) {
>                 fprintf(stderr, "failed to open display\n");
>                 return 1;
>         }
>
>         win_init(&win);
>         win_handle_events(&win);
>         XDestroyWindow(win.dpy, win.win);
>         XCloseDisplay(win.dpy);
>
>         return 0;
> }
>
> static void
> win_init(win_t *win)
> {
>         Window root;
>
>         win->width = 800;
>         win->height = 800;
>
>         root = DefaultRootWindow(win->dpy);
>         win->scr = DefaultScreen(win->dpy);
>         win->win = XCreateSimpleWindow(win->dpy, root, 0, 0,
>                                        win->width, win->height, 0,
>                                        BlackPixel(win->dpy, win->scr),
>                                        BlackPixel(win->dpy, win->scr));
>         win->quit_code = XKeysymToKeycode(win->dpy, XStringToKeysym("Q"));
>         XSelectInput(win->dpy, win->win, KeyPressMask |
>                                          StructureNotifyMask |
>                                          ExposureMask);
>         XMapWindow(win->dpy, win->win);
> }
>
> Visual *visual;
> cairo_t *cr;
> cairo_surface_t *surface;
> cairo_surface_t *surface_xlib;
>
> static void
> win_draw(win_t *win)
> {
>         int w, h;
>
>         visual = DefaultVisual(win->dpy, DefaultScreen(win->dpy));
>         XClearWindow(win->dpy, win->win);
>         surface_xlib = cairo_xlib_surface_create(win->dpy, win->win, visual,
>                                                  win->width, win->height);
>
>         cr = cairo_create(surface_xlib);
>         surface = cairo_image_surface_create_from_png("image.png");
>
>         w = cairo_image_surface_get_width(surface);
>         h = cairo_image_surface_get_height(surface);
>
>         cairo_scale(cr, (double) win->width / w, (double) win->height / h);
>         cairo_set_source_surface(cr, surface, 0, 0);
>         cairo_paint(cr);
>
>         if (cairo_status(cr)) {
>                 printf("Cairo is unhappy: %s\n",
>                        cairo_status_to_string (cairo_status (cr)));
>                 exit(0);
>         }
>
>         cairo_surface_destroy(surface);
>         cairo_destroy(cr);
> }
>
> static void
> win_handle_events(win_t *win)
> {
>         XEvent xev;
>
>         for (;;) {
>                 XNextEvent(win->dpy, &xev);
>                 switch(xev.type) {
>                 case KeyPress:
>                         {
>                                 XKeyEvent *kev = &xev.xkey;
>
>                                 if (kev->keycode == win->quit_code) {
>                                         return;
>                                 }
>                                 break;
>                         }
>                 case ConfigureNotify:
>                         {
>                                 XConfigureEvent *cev = &xev.xconfigure;
>
>                                 win->width = cev->width;
>                                 win->height = cev->height;
>                                 break;
>                         }
>                 case Expose:
>                         {
>                                 XExposeEvent *eev = &xev.xexpose;
>
>                                 if (eev->count == 0)
>                                         win_draw(win);
>                                 break;
>                         }
>                 }
>         }
> }
> /* ------------------------------------------------------------------------ */
>
> --
>  Haakon
> _______________________________________________
> cairo mailing list
> cairo at cairographics.org
> http://cairographics.org/cgi-bin/mailman/listinfo/cairo
>


More information about the cairo mailing list