diff options
author | JP Cimalando <jpcima@users.noreply.github.com> | 2018-12-27 12:09:21 +0100 |
---|---|---|
committer | Filipe Coelho <falktx@falktx.com> | 2019-01-06 19:10:11 +0100 |
commit | 45af3774591789ed2ad4e1187cbdcaafcde1fccf (patch) | |
tree | 0cd37162743ee36f587f8e4f0b216e134d7b14f3 | |
parent | c6f5d34be6ee0a292f044edaa47c72c8a71257a5 (diff) |
double buffering for Cairo on X11
-rw-r--r-- | dgl/src/pugl/pugl_x11.c | 65 |
1 files changed, 53 insertions, 12 deletions
diff --git a/dgl/src/pugl/pugl_x11.c b/dgl/src/pugl/pugl_x11.c index 20f86b73..a0dee411 100644 --- a/dgl/src/pugl/pugl_x11.c +++ b/dgl/src/pugl/pugl_x11.c @@ -60,8 +60,10 @@ struct PuglInternalsImpl { int screen; Window win; #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 #ifdef PUGL_HAVE_GL GLXContext ctx; @@ -257,17 +259,17 @@ puglCreateWindow(PuglView* view, const char* title) #ifdef PUGL_HAVE_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); - 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"); } 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); XFree(vi); XCloseDisplay(impl->display); @@ -332,8 +334,10 @@ puglDestroy(PuglView* view) #endif #ifdef PUGL_HAVE_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 XDestroyWindow(impl->display, impl->win); @@ -374,14 +378,51 @@ puglReshape(PuglView* view, int width, int height) static void puglDisplay(PuglView* view) { + PuglInternals* impl = view->impl; + 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; if (view->displayFunc) { 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); + (void)impl; } static void @@ -645,7 +686,7 @@ puglProcessEvents(PuglView* view) if (view->ctx_type == PUGL_CAIRO) { // Resize surfaces/contexts before dispatching view->redisplay = true; - cairo_xlib_surface_set_size(view->impl->surface, + cairo_xlib_surface_set_size(view->impl->xlib_surface, conf_width, conf_height); } #endif @@ -686,7 +727,7 @@ puglGetContext(PuglView* view) { #ifdef PUGL_HAVE_CAIRO if (view->ctx_type == PUGL_CAIRO) { - return view->impl->cr; + return view->impl->buffer_cr; } #endif return NULL; |