| @@ -60,8 +60,10 @@ struct PuglInternalsImpl { | |||||
| int screen; | int screen; | ||||
| Window win; | Window win; | ||||
| #ifdef PUGL_HAVE_CAIRO | #ifdef PUGL_HAVE_CAIRO | ||||
| cairo_t* cr; | |||||
| cairo_surface_t* surface; | |||||
| cairo_t* xlib_cr; | |||||
| cairo_t* buffer_cr; | |||||
| cairo_surface_t* xlib_surface; | |||||
| cairo_surface_t* buffer_surface; | |||||
| #endif | #endif | ||||
| #ifdef PUGL_HAVE_GL | #ifdef PUGL_HAVE_GL | ||||
| GLXContext ctx; | GLXContext ctx; | ||||
| @@ -257,17 +259,17 @@ puglCreateWindow(PuglView* view, const char* title) | |||||
| #ifdef PUGL_HAVE_CAIRO | #ifdef PUGL_HAVE_CAIRO | ||||
| if (view->ctx_type == PUGL_CAIRO) { | if (view->ctx_type == PUGL_CAIRO) { | ||||
| impl->surface = cairo_xlib_surface_create( | |||||
| impl->xlib_surface = cairo_xlib_surface_create( | |||||
| impl->display, impl->win, vi->visual, view->width, view->height); | impl->display, impl->win, vi->visual, view->width, view->height); | ||||
| if (impl->surface == NULL || cairo_surface_status(impl->surface) != CAIRO_STATUS_SUCCESS) { | |||||
| if (impl->xlib_surface == NULL || cairo_surface_status(impl->xlib_surface) != CAIRO_STATUS_SUCCESS) { | |||||
| printf("puGL: failed to create cairo surface\n"); | printf("puGL: failed to create cairo surface\n"); | ||||
| } | } | ||||
| else { | else { | ||||
| impl->cr = cairo_create(impl->surface); | |||||
| impl->xlib_cr = cairo_create(impl->xlib_surface); | |||||
| } | } | ||||
| if (impl->cr == NULL || cairo_status(impl->cr) != CAIRO_STATUS_SUCCESS) { | |||||
| cairo_destroy(impl->cr); | |||||
| cairo_surface_destroy(impl->surface); | |||||
| if (impl->xlib_cr == NULL || cairo_status(impl->xlib_cr) != CAIRO_STATUS_SUCCESS) { | |||||
| cairo_destroy(impl->xlib_cr); | |||||
| cairo_surface_destroy(impl->xlib_surface); | |||||
| XDestroyWindow(impl->display, impl->win); | XDestroyWindow(impl->display, impl->win); | ||||
| XFree(vi); | XFree(vi); | ||||
| XCloseDisplay(impl->display); | XCloseDisplay(impl->display); | ||||
| @@ -332,8 +334,10 @@ puglDestroy(PuglView* view) | |||||
| #endif | #endif | ||||
| #ifdef PUGL_HAVE_CAIRO | #ifdef PUGL_HAVE_CAIRO | ||||
| if (view->ctx_type == PUGL_CAIRO) { | if (view->ctx_type == PUGL_CAIRO) { | ||||
| cairo_destroy(impl->cr); | |||||
| cairo_surface_destroy(impl->surface); | |||||
| cairo_destroy(impl->xlib_cr); | |||||
| cairo_destroy(impl->buffer_cr); | |||||
| cairo_surface_destroy(impl->xlib_surface); | |||||
| cairo_surface_destroy(impl->buffer_surface); | |||||
| } | } | ||||
| #endif | #endif | ||||
| XDestroyWindow(impl->display, impl->win); | XDestroyWindow(impl->display, impl->win); | ||||
| @@ -374,14 +378,51 @@ puglReshape(PuglView* view, int width, int height) | |||||
| static void | static void | ||||
| puglDisplay(PuglView* view) | puglDisplay(PuglView* view) | ||||
| { | { | ||||
| PuglInternals* impl = view->impl; | |||||
| puglEnterContext(view); | puglEnterContext(view); | ||||
| #ifdef PUGL_HAVE_CAIRO | |||||
| if (view->ctx_type == PUGL_CAIRO) { | |||||
| cairo_t* bc = impl->buffer_cr; | |||||
| cairo_surface_t* xs = impl->xlib_surface; | |||||
| cairo_surface_t* bs = impl->buffer_surface; | |||||
| int w = cairo_xlib_surface_get_width(xs); | |||||
| int h = cairo_xlib_surface_get_height(xs); | |||||
| int bw = bs ? cairo_image_surface_get_width(bs) : -1; | |||||
| int bh = bs ? cairo_image_surface_get_height(bs) : -1; | |||||
| if (!bc || bw != w || bh != h) { | |||||
| cairo_destroy(bc); | |||||
| cairo_surface_destroy(bs); | |||||
| bs = cairo_surface_create_similar_image(xs, CAIRO_FORMAT_ARGB32, w, h); | |||||
| bc = bs ? cairo_create(bs) : NULL; | |||||
| impl->buffer_cr = bc; | |||||
| impl->buffer_surface = bs; | |||||
| } | |||||
| if (!bc) { | |||||
| puglLeaveContext(view, false); | |||||
| return; | |||||
| } | |||||
| } | |||||
| #endif | |||||
| view->redisplay = false; | view->redisplay = false; | ||||
| if (view->displayFunc) { | if (view->displayFunc) { | ||||
| view->displayFunc(view); | view->displayFunc(view); | ||||
| } | } | ||||
| #ifdef PUGL_HAVE_CAIRO | |||||
| if (view->ctx_type == PUGL_CAIRO) { | |||||
| cairo_t* xc = impl->xlib_cr; | |||||
| cairo_set_source_surface(xc, impl->buffer_surface, 0, 0); | |||||
| cairo_paint(xc); | |||||
| } | |||||
| #endif | |||||
| puglLeaveContext(view, true); | puglLeaveContext(view, true); | ||||
| (void)impl; | |||||
| } | } | ||||
| static void | static void | ||||
| @@ -645,7 +686,7 @@ puglProcessEvents(PuglView* view) | |||||
| if (view->ctx_type == PUGL_CAIRO) { | if (view->ctx_type == PUGL_CAIRO) { | ||||
| // Resize surfaces/contexts before dispatching | // Resize surfaces/contexts before dispatching | ||||
| view->redisplay = true; | view->redisplay = true; | ||||
| cairo_xlib_surface_set_size(view->impl->surface, | |||||
| cairo_xlib_surface_set_size(view->impl->xlib_surface, | |||||
| conf_width, conf_height); | conf_width, conf_height); | ||||
| } | } | ||||
| #endif | #endif | ||||
| @@ -686,7 +727,7 @@ puglGetContext(PuglView* view) | |||||
| { | { | ||||
| #ifdef PUGL_HAVE_CAIRO | #ifdef PUGL_HAVE_CAIRO | ||||
| if (view->ctx_type == PUGL_CAIRO) { | if (view->ctx_type == PUGL_CAIRO) { | ||||
| return view->impl->cr; | |||||
| return view->impl->buffer_cr; | |||||
| } | } | ||||
| #endif | #endif | ||||
| return NULL; | return NULL; | ||||