summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJP Cimalando <jpcima@users.noreply.github.com>2018-12-27 13:39:11 +0100
committerFilipe Coelho <falktx@falktx.com>2019-01-06 19:10:11 +0100
commit7125eaace4ea0653e66c3e16e60b15acfce952d7 (patch)
tree890e1962c69342d4f40f658be37c4d0e739c46ec
parent45af3774591789ed2ad4e1187cbdcaafcde1fccf (diff)
double buffering for Cairo on Windows
-rw-r--r--dgl/src/pugl/pugl_win.cpp101
1 files changed, 68 insertions, 33 deletions
diff --git a/dgl/src/pugl/pugl_win.cpp b/dgl/src/pugl/pugl_win.cpp
index e8b2612f..a731b877 100644
--- a/dgl/src/pugl/pugl_win.cpp
+++ b/dgl/src/pugl/pugl_win.cpp
@@ -59,8 +59,10 @@ struct PuglInternalsImpl {
HGLRC hglrc;
#endif
#ifdef PUGL_HAVE_CAIRO
- cairo_t* cr;
+ cairo_t* buffer_cr;
+ cairo_surface_t* buffer_surface;
#endif
+ HDC paintHdc;
WNDCLASS wc;
};
@@ -235,8 +237,14 @@ puglDestroy(PuglView* view)
if (view->ctx_type == PUGL_GL) {
wglMakeCurrent(NULL, NULL);
wglDeleteContext(impl->hglrc);
+ ReleaseDC(impl->hwnd, impl->hdc);
+ }
+#endif
+#ifdef PUGL_HAVE_CAIRO
+ if (view->ctx_type == PUGL_CAIRO) {
+ cairo_destroy(impl->buffer_cr);
+ cairo_surface_destroy(impl->buffer_surface);
}
- ReleaseDC(impl->hwnd, impl->hdc);
#endif
DestroyWindow(impl->hwnd);
UnregisterClass(impl->wc.lpszClassName, NULL);
@@ -263,14 +271,63 @@ puglReshape(PuglView* view, int width, int height)
static void
puglDisplay(PuglView* view)
{
+ PuglInternals* impl = view->impl;
+ bool success = true;
+
puglEnterContext(view);
- view->redisplay = false;
- if (view->displayFunc) {
- view->displayFunc(view);
+#ifdef PUGL_HAVE_CAIRO
+ cairo_t *wc = NULL;
+ cairo_t *bc = NULL;
+ cairo_surface_t *ws = NULL;
+ cairo_surface_t *bs = NULL;
+
+ if (view->ctx_type == PUGL_CAIRO) {
+ HDC hdc = impl->paintHdc;
+ bc = impl->buffer_cr;
+ bs = impl->buffer_surface;
+ int w = view->width;
+ int h = view->height;
+ int bw = bs ? cairo_image_surface_get_width(bs) : -1;
+ int bh = bs ? cairo_image_surface_get_height(bs) : -1;
+ ws = hdc ? cairo_win32_surface_create(hdc) : NULL;
+ wc = ws ? cairo_create(ws) : NULL;
+ if (wc && (!bc || bw != w || bh != h)) {
+ cairo_destroy(bc);
+ cairo_surface_destroy(bs);
+ bs = cairo_surface_create_similar_image(ws, CAIRO_FORMAT_ARGB32, w, h);
+ bc = bs ? cairo_create(bs) : NULL;
+ impl->buffer_cr = bc;
+ impl->buffer_surface = bs;
+ }
+ success = wc != NULL && bc != NULL;
}
+#endif
- puglLeaveContext(view, true);
+ if (success) {
+ view->redisplay = false;
+ if (view->displayFunc) {
+ view->displayFunc(view);
+ }
+#ifdef PUGL_HAVE_CAIRO
+ if (view->ctx_type == PUGL_CAIRO) {
+ cairo_set_source_surface(wc, bs, 0, 0);
+ cairo_paint(wc);
+ }
+#endif
+ }
+
+ puglLeaveContext(view, success);
+
+#ifdef PUGL_HAVE_CAIRO
+ if (view->ctx_type == PUGL_CAIRO) {
+ cairo_destroy(wc);
+ cairo_surface_destroy(ws);
+ }
+#endif
+
+ return;
+ (void)impl;
}
static PuglKey
@@ -359,32 +416,10 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam)
mmi->ptMinTrackSize.y = view->min_height;
break;
case WM_PAINT:
-#ifdef PUGL_HAVE_GL
- if (view->ctx_type == PUGL_GL) {
- BeginPaint(view->impl->hwnd, &ps);
- puglDisplay(view);
- EndPaint(view->impl->hwnd, &ps);
- }
-#endif
-#ifdef PUGL_HAVE_CAIRO
- if (view->ctx_type == PUGL_CAIRO) {
- HDC hdc = BeginPaint(view->impl->hwnd, &ps);
- if (hdc == NULL)
- break;
- cairo_surface_t *surface = cairo_win32_surface_create(hdc);
- if (surface) {
- cairo_t *cr = cairo_create(surface);
- if (cr) {
- view->impl->cr = cr;
- puglDisplay(view);
- view->impl->cr = NULL;
- cairo_destroy(cr);
- }
- cairo_surface_destroy(surface);
- }
- EndPaint(view->impl->hwnd, &ps);
- }
-#endif
+ view->impl->paintHdc = BeginPaint(view->impl->hwnd, &ps);
+ puglDisplay(view);
+ view->impl->paintHdc = NULL;
+ EndPaint(view->impl->hwnd, &ps);
break;
case WM_MOUSEMOVE:
if (view->motionFunc) {
@@ -527,7 +562,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;