From 6654533e40da87858d5f73f6db594f37a1abbce2 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Tue, 10 May 2011 19:53:00 +0100 Subject: [PATCH] cogl-winsys-wgl: Plug leak on error from SetPixelFormat When SetPixelFormat fails, the DC would get released but none of the other resources would be freed. This patch makes it call _cogl_winsys_onscreen_deinit on failure to clean up all of the resources. The patch looks big because it moves the onscreen_deinit and onscreen_bind functions. --- cogl/winsys/cogl-winsys-wgl.c | 133 ++++++++++++++++++---------------- 1 file changed, 69 insertions(+), 64 deletions(-) diff --git a/cogl/winsys/cogl-winsys-wgl.c b/cogl/winsys/cogl-winsys-wgl.c index 47dd6f0ec..1cd81b60d 100644 --- a/cogl/winsys/cogl-winsys-wgl.c +++ b/cogl/winsys/cogl-winsys-wgl.c @@ -605,6 +605,72 @@ _cogl_winsys_context_deinit (CoglContext *context) g_free (context->winsys); } +static void +_cogl_winsys_onscreen_bind (CoglOnscreen *onscreen) +{ + CoglContext *context; + CoglContextWgl *wgl_context; + CoglDisplayWgl *wgl_display; + CoglOnscreenWgl *wgl_onscreen; + CoglRendererWgl *wgl_renderer; + + /* The glx backend tries to bind the dummy context if onscreen == + NULL, but this isn't really going to work because before checking + whether onscreen == NULL it reads the pointer to get the + context */ + g_return_if_fail (onscreen != NULL); + + context = COGL_FRAMEBUFFER (onscreen)->context; + wgl_context = context->winsys; + wgl_display = context->display->winsys; + wgl_onscreen = onscreen->winsys; + wgl_renderer = context->display->renderer->winsys; + + if (wgl_context->current_dc == wgl_onscreen->client_dc) + return; + + wglMakeCurrent (wgl_onscreen->client_dc, wgl_display->wgl_context); + + /* According to the specs for WGL_EXT_swap_control SwapInterval() + * applies to the current window not the context so we apply it here + * to ensure its up-to-date even for new windows. + */ + if (wgl_renderer->pf_wglSwapInterval) + { + if (onscreen->swap_throttled) + wgl_renderer->pf_wglSwapInterval (1); + else + wgl_renderer->pf_wglSwapInterval (0); + } + + wgl_context->current_dc = wgl_onscreen->client_dc; +} + +static void +_cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen) +{ + CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context; + CoglContextWgl *wgl_context = context->winsys; + CoglOnscreenWin32 *win32_onscreen = onscreen->winsys; + CoglOnscreenWgl *wgl_onscreen = onscreen->winsys; + + if (wgl_onscreen->client_dc) + { + if (wgl_context->current_dc == wgl_onscreen->client_dc) + _cogl_winsys_onscreen_bind (NULL); + + ReleaseDC (win32_onscreen->hwnd, wgl_onscreen->client_dc); + } + + if (!win32_onscreen->is_foreign_hwnd && win32_onscreen->hwnd) + { + /* Drop the pointer to the onscreen in the window so that any + further messages won't be processed */ + SetWindowLongPtrW (win32_onscreen->hwnd, 0, (LONG_PTR) 0); + DestroyWindow (win32_onscreen->hwnd); + } +} + static gboolean _cogl_winsys_onscreen_init (CoglOnscreen *onscreen, GError **error) @@ -690,76 +756,15 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen, g_set_error (error, COGL_WINSYS_ERROR, COGL_WINSYS_ERROR_CREATE_ONSCREEN, "Error setting pixel format on the window"); - ReleaseDC (hwnd, wgl_onscreen->client_dc); + + _cogl_winsys_onscreen_deinit (onscreen); + return FALSE; } return TRUE; } -static void -_cogl_winsys_onscreen_bind (CoglOnscreen *onscreen) -{ - CoglContext *context; - CoglContextWgl *wgl_context; - CoglDisplayWgl *wgl_display; - CoglOnscreenWgl *wgl_onscreen; - CoglRendererWgl *wgl_renderer; - - /* The glx backend tries to bind the dummy context if onscreen == - NULL, but this isn't really going to work because before checking - whether onscreen == NULL it reads the pointer to get the - context */ - g_return_if_fail (onscreen != NULL); - - context = COGL_FRAMEBUFFER (onscreen)->context; - wgl_context = context->winsys; - wgl_display = context->display->winsys; - wgl_onscreen = onscreen->winsys; - wgl_renderer = context->display->renderer->winsys; - - if (wgl_context->current_dc == wgl_onscreen->client_dc) - return; - - wglMakeCurrent (wgl_onscreen->client_dc, wgl_display->wgl_context); - - /* According to the specs for WGL_EXT_swap_control SwapInterval() - * applies to the current window not the context so we apply it here - * to ensure its up-to-date even for new windows. - */ - if (wgl_renderer->pf_wglSwapInterval) - { - if (onscreen->swap_throttled) - wgl_renderer->pf_wglSwapInterval (1); - else - wgl_renderer->pf_wglSwapInterval (0); - } - - wgl_context->current_dc = wgl_onscreen->client_dc; -} - -static void -_cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen) -{ - CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context; - CoglContextWgl *wgl_context = context->winsys; - CoglOnscreenWin32 *win32_onscreen = onscreen->winsys; - CoglOnscreenWgl *wgl_onscreen = onscreen->winsys; - - if (wgl_context->current_dc == wgl_onscreen->client_dc) - _cogl_winsys_onscreen_bind (NULL); - - ReleaseDC (win32_onscreen->hwnd, wgl_onscreen->client_dc); - - if (!win32_onscreen->is_foreign_hwnd) - { - /* Drop the pointer to the onscreen in the window so that any - further messages won't be processed */ - SetWindowLongPtrW (win32_onscreen->hwnd, 0, (LONG_PTR) 0); - DestroyWindow (win32_onscreen->hwnd); - } -} - static void _cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen) {