| @@ -59,8 +59,10 @@ struct PuglInternalsImpl { | |||||
| HGLRC hglrc; | HGLRC hglrc; | ||||
| #endif | #endif | ||||
| #ifdef PUGL_HAVE_CAIRO | #ifdef PUGL_HAVE_CAIRO | ||||
| cairo_t* cr; | |||||
| cairo_t* buffer_cr; | |||||
| cairo_surface_t* buffer_surface; | |||||
| #endif | #endif | ||||
| HDC paintHdc; | |||||
| WNDCLASS wc; | WNDCLASS wc; | ||||
| }; | }; | ||||
| @@ -235,8 +237,14 @@ puglDestroy(PuglView* view) | |||||
| if (view->ctx_type == PUGL_GL) { | if (view->ctx_type == PUGL_GL) { | ||||
| wglMakeCurrent(NULL, NULL); | wglMakeCurrent(NULL, NULL); | ||||
| wglDeleteContext(impl->hglrc); | 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 | #endif | ||||
| DestroyWindow(impl->hwnd); | DestroyWindow(impl->hwnd); | ||||
| UnregisterClass(impl->wc.lpszClassName, NULL); | UnregisterClass(impl->wc.lpszClassName, NULL); | ||||
| @@ -263,14 +271,63 @@ puglReshape(PuglView* view, int width, int height) | |||||
| static void | static void | ||||
| puglDisplay(PuglView* view) | puglDisplay(PuglView* view) | ||||
| { | { | ||||
| PuglInternals* impl = view->impl; | |||||
| bool success = true; | |||||
| puglEnterContext(view); | 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 | static PuglKey | ||||
| @@ -359,32 +416,10 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) | |||||
| mmi->ptMinTrackSize.y = view->min_height; | mmi->ptMinTrackSize.y = view->min_height; | ||||
| break; | break; | ||||
| case WM_PAINT: | 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; | break; | ||||
| case WM_MOUSEMOVE: | case WM_MOUSEMOVE: | ||||
| if (view->motionFunc) { | if (view->motionFunc) { | ||||
| @@ -527,7 +562,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; | ||||