4 * An object oriented GL/GLES Abstraction/Utility Layer
6 * Copyright (C) 2010,2011 Intel Corporation.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library. If not, see
20 * <http://www.gnu.org/licenses/>.
24 * Neil Roberts <neil@linux.intel.com>
35 #include "cogl-util.h"
36 #include "cogl-winsys-private.h"
37 #include "cogl-context-private.h"
38 #include "cogl-framebuffer.h"
39 #include "cogl-onscreen-private.h"
40 #include "cogl-swap-chain-private.h"
41 #include "cogl-renderer-private.h"
42 #include "cogl-display-private.h"
43 #include "cogl-onscreen-template-private.h"
44 #include "cogl-private.h"
45 #include "cogl-feature-private.h"
46 #include "cogl-win32-renderer.h"
47 #include "cogl-winsys-wgl-private.h"
49 typedef struct _CoglRendererWgl
53 /* Function pointers for GLX specific extensions */
54 #define COGL_WINSYS_FEATURE_BEGIN(a, b, c, d, e, f)
56 #define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args) \
57 ret (APIENTRY * pf_ ## name) args;
59 #define COGL_WINSYS_FEATURE_END()
61 #include "cogl-winsys-wgl-feature-functions.h"
63 #undef COGL_WINSYS_FEATURE_BEGIN
64 #undef COGL_WINSYS_FEATURE_FUNCTION
65 #undef COGL_WINSYS_FEATURE_END
68 typedef struct _CoglDisplayWgl
76 typedef struct _CoglOnscreenWin32
79 gboolean is_foreign_hwnd;
82 typedef struct _CoglContextWgl
87 typedef struct _CoglOnscreenWgl
89 CoglOnscreenWin32 _parent;
95 /* Define a set of arrays containing the functions required from GL
96 for each winsys feature */
97 #define COGL_WINSYS_FEATURE_BEGIN(name, namespaces, extension_names, \
98 feature_flags, feature_flags_private, \
100 static const CoglFeatureFunction \
101 cogl_wgl_feature_ ## name ## _funcs[] = {
102 #define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args) \
103 { G_STRINGIFY (name), G_STRUCT_OFFSET (CoglRendererWgl, pf_ ## name) },
104 #define COGL_WINSYS_FEATURE_END() \
107 #include "cogl-winsys-wgl-feature-functions.h"
109 /* Define an array of features */
110 #undef COGL_WINSYS_FEATURE_BEGIN
111 #define COGL_WINSYS_FEATURE_BEGIN(name, namespaces, extension_names, \
112 feature_flags, feature_flags_private, \
114 { 255, 255, 0, namespaces, extension_names, \
115 feature_flags, feature_flags_private, \
117 cogl_wgl_feature_ ## name ## _funcs },
118 #undef COGL_WINSYS_FEATURE_FUNCTION
119 #define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args)
120 #undef COGL_WINSYS_FEATURE_END
121 #define COGL_WINSYS_FEATURE_END()
123 static const CoglFeatureData winsys_feature_data[] =
125 #include "cogl-winsys-wgl-feature-functions.h"
129 _cogl_winsys_renderer_get_proc_address (CoglRenderer *renderer,
132 CoglRendererWgl *wgl_renderer = renderer->winsys;
133 void *proc = wglGetProcAddress ((LPCSTR) name);
135 /* The documentation for wglGetProcAddress implies that it only
136 returns pointers to extension functions so if it fails we'll try
137 resolving the symbol directly from the the GL library */
140 if (wgl_renderer->gl_module == NULL)
141 wgl_renderer->gl_module = g_module_open ("opengl32", 0);
143 if (wgl_renderer->gl_module)
144 g_module_symbol (wgl_renderer->gl_module, name, &proc);
151 _cogl_winsys_renderer_disconnect (CoglRenderer *renderer)
153 CoglRendererWgl *wgl_renderer = renderer->winsys;
155 if (wgl_renderer->gl_module)
156 g_module_close (wgl_renderer->gl_module);
158 g_slice_free (CoglRendererWgl, renderer->winsys);
161 static CoglOnscreen *
162 find_onscreen_for_hwnd (CoglContext *context, HWND hwnd)
164 CoglDisplayWgl *display_wgl = context->display->winsys;
167 /* If the hwnd has Cogl's window class then we can lookup the
168 onscreen pointer directly by reading the extra window data */
169 if (GetClassLongPtr (hwnd, GCW_ATOM) == display_wgl->window_class)
171 CoglOnscreen *onscreen = (CoglOnscreen *) GetWindowLongPtr (hwnd, 0);
177 for (l = context->framebuffers; l; l = l->next)
179 CoglFramebuffer *framebuffer = l->data;
181 if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
183 CoglOnscreenWin32 *win32_onscreen =
184 COGL_ONSCREEN (framebuffer)->winsys;
186 if (win32_onscreen->hwnd == hwnd)
187 return COGL_ONSCREEN (framebuffer);
194 static CoglFilterReturn
195 win32_event_filter_cb (MSG *msg, void *data)
197 CoglContext *context = data;
199 if (msg->message == WM_SIZE)
201 CoglOnscreen *onscreen =
202 find_onscreen_for_hwnd (context, msg->hwnd);
206 CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
208 /* Ignore size changes resulting from the stage being
209 minimized - otherwise it will think the window has been
211 if (msg->wParam != SIZE_MINIMIZED)
213 WORD new_width = LOWORD (msg->lParam);
214 WORD new_height = HIWORD (msg->lParam);
215 _cogl_framebuffer_winsys_update_size (framebuffer,
222 return COGL_FILTER_CONTINUE;
226 _cogl_winsys_renderer_connect (CoglRenderer *renderer,
229 renderer->winsys = g_slice_new0 (CoglRendererWgl);
234 static LRESULT CALLBACK
235 window_proc (HWND hwnd, UINT umsg,
236 WPARAM wparam, LPARAM lparam)
238 gboolean message_handled = FALSE;
239 CoglOnscreen *onscreen;
241 /* It's not clear what the best thing to do with messages sent to
242 the window proc is. We want the application to forward on all
243 messages through Cogl so that it can have a chance to process
244 them which might mean that that in it's GetMessage loop it could
245 call cogl_win32_renderer_handle_event for every message. However
246 the message loop would usually call DispatchMessage as well which
247 mean this window proc would be invoked and Cogl would see the
248 message twice. However we can't just ignore messages in the
249 window proc because some messages are sent directly from windows
250 without going through the message queue. This function therefore
251 just forwards on all messages directly. This means that the
252 application is not expected to forward on messages if it has let
253 Cogl create the window itself because it will already see them
254 via the window proc. This limits the kinds of messages that Cogl
255 can handle to ones that are sent to the windows it creates, but I
256 think that is a reasonable restriction */
258 /* Convert the message to a MSG struct and pass it through the Cogl
259 message handling mechanism */
261 /* This window proc is only called for messages created with Cogl's
262 window class so we should be able to work out the corresponding
263 window class by looking in the extra window data. Windows will
264 send some extra messages before we get a chance to set this value
265 so we have to ignore these */
266 onscreen = (CoglOnscreen *) GetWindowLongPtr (hwnd, 0);
268 if (onscreen != NULL)
270 CoglRenderer *renderer;
278 msg.time = GetMessageTime ();
279 /* Neither MAKE_POINTS nor GET_[XY]_LPARAM is defined in MinGW
280 headers so we need to convert to a signed type explicitly */
281 message_pos = GetMessagePos ();
282 msg.pt.x = (SHORT) LOWORD (message_pos);
283 msg.pt.y = (SHORT) HIWORD (message_pos);
285 renderer = COGL_FRAMEBUFFER (onscreen)->context->display->renderer;
288 cogl_win32_renderer_handle_event (renderer, &msg);
291 if (!message_handled)
292 return DefWindowProcW (hwnd, umsg, wparam, lparam);
298 pixel_format_is_better (const PIXELFORMATDESCRIPTOR *pfa,
299 const PIXELFORMATDESCRIPTOR *pfb)
301 /* Always prefer a format with a stencil buffer */
302 if (pfa->cStencilBits == 0)
304 if (pfb->cStencilBits > 0)
307 else if (pfb->cStencilBits == 0)
310 /* Prefer a bigger color buffer */
311 if (pfb->cColorBits > pfa->cColorBits)
313 else if (pfb->cColorBits < pfa->cColorBits)
316 /* Prefer a bigger depth buffer */
317 return pfb->cDepthBits > pfa->cDepthBits;
321 choose_pixel_format (CoglFramebufferConfig *config,
322 HDC dc, PIXELFORMATDESCRIPTOR *pfd)
324 int i, num_formats, best_pf = 0;
325 PIXELFORMATDESCRIPTOR best_pfd;
327 num_formats = DescribePixelFormat (dc, 0, sizeof (best_pfd), NULL);
329 /* XXX: currently we don't support multisampling on windows... */
330 if (config->samples_per_pixel)
333 for (i = 1; i <= num_formats; i++)
335 memset (pfd, 0, sizeof (*pfd));
337 if (DescribePixelFormat (dc, i, sizeof (best_pfd), pfd) &&
338 /* Check whether this format is useable by Cogl */
339 ((pfd->dwFlags & (PFD_SUPPORT_OPENGL |
342 PFD_GENERIC_FORMAT)) ==
343 (PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW)) &&
344 pfd->iPixelType == PFD_TYPE_RGBA &&
345 pfd->cColorBits >= 16 && pfd->cColorBits <= 32 &&
346 pfd->cDepthBits >= 16 && pfd->cDepthBits <= 32 &&
347 /* Check whether this is a better format than one we've
349 (best_pf == 0 || pixel_format_is_better (&best_pfd, pfd)))
351 if (config->swap_chain->has_alpha && pfd->cAlphaBits == 0)
353 if (config->need_stencil && pfd->cStencilBits == 0)
367 create_window_class (CoglDisplay *display, GError **error)
369 CoglDisplayWgl *wgl_display = display->winsys;
370 char *class_name_ascii, *src;
371 WCHAR *class_name_wchar, *dst;
374 /* We create a window class per display so that we have an
375 opportunity to clean up the class when the display is
378 /* Generate a unique name containing the address of the display */
379 class_name_ascii = g_strdup_printf ("CoglWindow0x%0*" G_GINTPTR_MODIFIER "x",
380 sizeof (guintptr) * 2,
382 /* Convert it to WCHARs */
383 class_name_wchar = g_malloc ((strlen (class_name_ascii) + 1) *
385 for (src = class_name_ascii, dst = class_name_wchar;
391 memset (&wndclass, 0, sizeof (wndclass));
392 wndclass.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
393 wndclass.lpfnWndProc = window_proc;
394 /* We reserve extra space in the window data for a pointer back to
396 wndclass.cbWndExtra = sizeof (LONG_PTR);
397 wndclass.hInstance = GetModuleHandleW (NULL);
398 wndclass.hIcon = LoadIconW (NULL, (LPWSTR) IDI_APPLICATION);
399 wndclass.hCursor = LoadCursorW (NULL, (LPWSTR) IDC_ARROW);
400 wndclass.hbrBackground = NULL;
401 wndclass.lpszMenuName = NULL;
402 wndclass.lpszClassName = class_name_wchar;
403 wgl_display->window_class = RegisterClassW (&wndclass);
405 g_free (class_name_wchar);
406 g_free (class_name_ascii);
408 if (wgl_display->window_class == 0)
410 g_set_error (error, COGL_WINSYS_ERROR,
411 COGL_WINSYS_ERROR_CREATE_CONTEXT,
412 "Unable to register window class");
420 create_context (CoglDisplay *display, GError **error)
422 CoglDisplayWgl *wgl_display = display->winsys;
424 _COGL_RETURN_VAL_IF_FAIL (wgl_display->wgl_context == NULL, FALSE);
426 /* Cogl assumes that there is always a GL context selected; in order
427 * to make sure that a WGL context exists and is made current, we
428 * use a small dummy window that never gets shown to which we can
429 * always fall back if no onscreen is available
431 if (wgl_display->dummy_hwnd == NULL)
433 wgl_display->dummy_hwnd =
434 CreateWindowW ((LPWSTR) MAKEINTATOM (wgl_display->window_class),
441 GetModuleHandle (NULL),
444 if (wgl_display->dummy_hwnd == NULL)
446 g_set_error (error, COGL_WINSYS_ERROR,
447 COGL_WINSYS_ERROR_CREATE_CONTEXT,
448 "Unable to create dummy window");
453 if (wgl_display->dummy_dc == NULL)
455 PIXELFORMATDESCRIPTOR pfd;
458 wgl_display->dummy_dc = GetDC (wgl_display->dummy_hwnd);
460 pf = choose_pixel_format (&display->onscreen_template->config,
461 wgl_display->dummy_dc, &pfd);
463 if (pf == 0 || !SetPixelFormat (wgl_display->dummy_dc, pf, &pfd))
465 g_set_error (error, COGL_WINSYS_ERROR,
466 COGL_WINSYS_ERROR_CREATE_CONTEXT,
467 "Unable to find suitable GL pixel format");
468 ReleaseDC (wgl_display->dummy_hwnd, wgl_display->dummy_dc);
469 wgl_display->dummy_dc = NULL;
474 if (wgl_display->wgl_context == NULL)
476 wgl_display->wgl_context = wglCreateContext (wgl_display->dummy_dc);
478 if (wgl_display->wgl_context == NULL)
480 g_set_error (error, COGL_WINSYS_ERROR,
481 COGL_WINSYS_ERROR_CREATE_CONTEXT,
482 "Unable to create suitable GL context");
487 COGL_NOTE (WINSYS, "Selecting dummy 0x%x for the WGL context",
488 (unsigned int) wgl_display->dummy_hwnd);
490 wglMakeCurrent (wgl_display->dummy_dc, wgl_display->wgl_context);
496 _cogl_winsys_display_destroy (CoglDisplay *display)
498 CoglDisplayWgl *wgl_display = display->winsys;
500 _COGL_RETURN_IF_FAIL (wgl_display != NULL);
502 if (wgl_display->wgl_context)
504 wglMakeCurrent (NULL, NULL);
505 wglDeleteContext (wgl_display->wgl_context);
508 if (wgl_display->dummy_dc)
509 ReleaseDC (wgl_display->dummy_hwnd, wgl_display->dummy_dc);
511 if (wgl_display->dummy_hwnd)
512 DestroyWindow (wgl_display->dummy_hwnd);
514 if (wgl_display->window_class)
515 UnregisterClassW ((LPWSTR) MAKEINTATOM (wgl_display->window_class),
516 GetModuleHandleW (NULL));
518 g_slice_free (CoglDisplayWgl, display->winsys);
519 display->winsys = NULL;
523 _cogl_winsys_display_setup (CoglDisplay *display,
526 CoglDisplayWgl *wgl_display;
528 _COGL_RETURN_VAL_IF_FAIL (display->winsys == NULL, FALSE);
530 wgl_display = g_slice_new0 (CoglDisplayWgl);
531 display->winsys = wgl_display;
533 if (!create_window_class (display, error))
536 if (!create_context (display, error))
542 _cogl_winsys_display_destroy (display);
547 get_wgl_extensions_string (HDC dc)
549 const char * (APIENTRY *pf_wglGetExtensionsStringARB) (HDC);
550 const char * (APIENTRY *pf_wglGetExtensionsStringEXT) (void);
552 _COGL_GET_CONTEXT (ctx, NULL);
554 /* According to the docs for these two extensions, you are supposed
555 to use wglGetProcAddress to detect their availability so
556 presumably it will return NULL if they are not available */
558 pf_wglGetExtensionsStringARB =
559 (void *) wglGetProcAddress ("wglGetExtensionsStringARB");
561 if (pf_wglGetExtensionsStringARB)
562 return pf_wglGetExtensionsStringARB (dc);
564 pf_wglGetExtensionsStringEXT =
565 (void *) wglGetProcAddress ("wglGetExtensionsStringEXT");
567 if (pf_wglGetExtensionsStringEXT)
568 return pf_wglGetExtensionsStringEXT ();
570 /* The WGL_EXT_swap_control is also advertised as a GL extension as
571 GL_EXT_SWAP_CONTROL so if the extension to get the list of WGL
572 extensions isn't supported then we can at least fake it to
573 support the swap control extension */
574 if (_cogl_check_extension ("WGL_EXT_swap_control",
575 (char *) ctx->glGetString (GL_EXTENSIONS)))
576 return "WGL_EXT_swap_control";
582 update_winsys_features (CoglContext *context, GError **error)
584 CoglDisplayWgl *wgl_display = context->display->winsys;
585 CoglRendererWgl *wgl_renderer = context->display->renderer->winsys;
586 const char *wgl_extensions;
589 _COGL_RETURN_VAL_IF_FAIL (wgl_display->wgl_context, FALSE);
591 if (!_cogl_context_update_features (context, error))
594 memset (context->winsys_features, 0, sizeof (context->winsys_features));
596 context->feature_flags |= COGL_FEATURE_ONSCREEN_MULTIPLE;
597 COGL_FLAGS_SET (context->features,
598 COGL_FEATURE_ID_ONSCREEN_MULTIPLE, TRUE);
599 COGL_FLAGS_SET (context->winsys_features,
600 COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN,
603 wgl_extensions = get_wgl_extensions_string (wgl_display->dummy_dc);
607 COGL_NOTE (WINSYS, " WGL Extensions: %s", wgl_extensions);
609 for (i = 0; i < G_N_ELEMENTS (winsys_feature_data); i++)
610 if (_cogl_feature_check (context->display->renderer,
611 "WGL", winsys_feature_data + i, 0, 0,
616 context->feature_flags |= winsys_feature_data[i].feature_flags;
617 if (winsys_feature_data[i].winsys_feature)
618 COGL_FLAGS_SET (context->winsys_features,
619 winsys_feature_data[i].winsys_feature,
628 _cogl_winsys_context_init (CoglContext *context, GError **error)
630 CoglContextWgl *wgl_context;
632 wgl_context = context->winsys = g_new0 (CoglContextWgl, 1);
634 cogl_win32_renderer_add_filter (context->display->renderer,
635 win32_event_filter_cb,
638 return update_winsys_features (context, error);
642 _cogl_winsys_context_deinit (CoglContext *context)
644 cogl_win32_renderer_remove_filter (context->display->renderer,
645 win32_event_filter_cb,
648 g_free (context->winsys);
652 _cogl_winsys_onscreen_bind (CoglOnscreen *onscreen)
655 CoglContext *context;
656 CoglContextWgl *wgl_context;
657 CoglDisplayWgl *wgl_display;
658 CoglOnscreenWgl *wgl_onscreen;
659 CoglRendererWgl *wgl_renderer;
661 /* The glx backend tries to bind the dummy context if onscreen ==
662 NULL, but this isn't really going to work because before checking
663 whether onscreen == NULL it reads the pointer to get the
665 _COGL_RETURN_IF_FAIL (onscreen != NULL);
667 fb = COGL_FRAMEBUFFER (onscreen);
668 context = fb->context;
669 wgl_context = context->winsys;
670 wgl_display = context->display->winsys;
671 wgl_onscreen = onscreen->winsys;
672 wgl_renderer = context->display->renderer->winsys;
674 if (wgl_context->current_dc == wgl_onscreen->client_dc)
677 wglMakeCurrent (wgl_onscreen->client_dc, wgl_display->wgl_context);
679 /* According to the specs for WGL_EXT_swap_control SwapInterval()
680 * applies to the current window not the context so we apply it here
681 * to ensure its up-to-date even for new windows.
683 if (wgl_renderer->pf_wglSwapInterval)
685 if (fb->config.swap_throttled)
686 wgl_renderer->pf_wglSwapInterval (1);
688 wgl_renderer->pf_wglSwapInterval (0);
691 wgl_context->current_dc = wgl_onscreen->client_dc;
695 _cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
697 CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
698 CoglContextWgl *wgl_context = context->winsys;
699 CoglOnscreenWin32 *win32_onscreen = onscreen->winsys;
700 CoglOnscreenWgl *wgl_onscreen = onscreen->winsys;
702 /* If we never successfully allocated then there's nothing to do */
703 if (wgl_onscreen == NULL)
706 if (wgl_onscreen->client_dc)
708 if (wgl_context->current_dc == wgl_onscreen->client_dc)
709 _cogl_winsys_onscreen_bind (NULL);
711 ReleaseDC (win32_onscreen->hwnd, wgl_onscreen->client_dc);
714 if (!win32_onscreen->is_foreign_hwnd && win32_onscreen->hwnd)
716 /* Drop the pointer to the onscreen in the window so that any
717 further messages won't be processed */
718 SetWindowLongPtrW (win32_onscreen->hwnd, 0, (LONG_PTR) 0);
719 DestroyWindow (win32_onscreen->hwnd);
722 g_slice_free (CoglOnscreenWgl, onscreen->winsys);
723 onscreen->winsys = NULL;
727 _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
730 CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
731 CoglContext *context = framebuffer->context;
732 CoglDisplay *display = context->display;
733 CoglDisplayWgl *wgl_display = display->winsys;
734 CoglOnscreenWgl *wgl_onscreen;
735 CoglOnscreenWin32 *win32_onscreen;
736 PIXELFORMATDESCRIPTOR pfd;
740 _COGL_RETURN_VAL_IF_FAIL (wgl_display->wgl_context, FALSE);
742 /* XXX: Note we ignore the user's original width/height when given a
744 if (onscreen->foreign_hwnd)
748 hwnd = onscreen->foreign_hwnd;
750 GetClientRect (hwnd, &client_rect);
752 _cogl_framebuffer_winsys_update_size (framebuffer,
760 width = COGL_FRAMEBUFFER (onscreen)->width;
761 height = COGL_FRAMEBUFFER (onscreen)->height;
763 /* The size of the window passed to CreateWindow for some reason
764 includes the window decorations so we need to compensate for
766 width += GetSystemMetrics (SM_CXSIZEFRAME) * 2;
767 height += (GetSystemMetrics (SM_CYSIZEFRAME) * 2 +
768 GetSystemMetrics (SM_CYCAPTION));
770 hwnd = CreateWindowW ((LPWSTR) MAKEINTATOM (wgl_display->window_class),
773 CW_USEDEFAULT, /* xpos */
774 CW_USEDEFAULT, /* ypos */
779 GetModuleHandle (NULL),
780 NULL /* lparam for the WM_CREATE message */);
784 g_set_error (error, COGL_WINSYS_ERROR,
785 COGL_WINSYS_ERROR_CREATE_ONSCREEN,
786 "Unable to create window");
790 /* Store a pointer back to the onscreen in the window extra data
791 so we can refer back to it quickly */
792 SetWindowLongPtrW (hwnd, 0, (LONG_PTR) onscreen);
795 onscreen->winsys = g_slice_new0 (CoglOnscreenWgl);
796 win32_onscreen = onscreen->winsys;
797 wgl_onscreen = onscreen->winsys;
799 win32_onscreen->hwnd = hwnd;
801 wgl_onscreen->client_dc = GetDC (hwnd);
803 /* Use the same pixel format as the dummy DC from the renderer */
804 pf = choose_pixel_format (&framebuffer->config,
805 wgl_onscreen->client_dc, &pfd);
807 if (pf == 0 || !SetPixelFormat (wgl_onscreen->client_dc, pf, &pfd))
809 g_set_error (error, COGL_WINSYS_ERROR,
810 COGL_WINSYS_ERROR_CREATE_ONSCREEN,
811 "Error setting pixel format on the window");
813 _cogl_winsys_onscreen_deinit (onscreen);
822 _cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
824 CoglOnscreenWgl *wgl_onscreen = onscreen->winsys;
826 SwapBuffers (wgl_onscreen->client_dc);
830 _cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen)
832 CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
833 CoglContextWgl *wgl_context = context->winsys;
834 CoglOnscreenWgl *wgl_onscreen = onscreen->winsys;
836 if (wgl_context->current_dc != wgl_onscreen->client_dc)
839 /* This will cause it to rebind the context and update the swap interval */
840 wgl_context->current_dc = NULL;
841 _cogl_winsys_onscreen_bind (onscreen);
845 _cogl_winsys_onscreen_win32_get_window (CoglOnscreen *onscreen)
847 CoglOnscreenWin32 *win32_onscreen = onscreen->winsys;
848 return win32_onscreen->hwnd;
852 _cogl_winsys_onscreen_set_visibility (CoglOnscreen *onscreen,
855 CoglOnscreenWin32 *win32_onscreen = onscreen->winsys;
857 ShowWindow (win32_onscreen->hwnd, visibility ? SW_SHOW : SW_HIDE);
860 const CoglWinsysVtable *
861 _cogl_winsys_wgl_get_vtable (void)
863 static gboolean vtable_inited = FALSE;
864 static CoglWinsysVtable vtable;
866 /* It would be nice if we could use C99 struct initializers here
867 like the GLX backend does. However this code is more likely to be
868 compiled using Visual Studio which (still!) doesn't support them
869 so we initialize it in code instead */
873 memset (&vtable, 0, sizeof (vtable));
875 vtable.id = COGL_WINSYS_ID_WGL;
877 vtable.renderer_get_proc_address = _cogl_winsys_renderer_get_proc_address;
878 vtable.renderer_connect = _cogl_winsys_renderer_connect;
879 vtable.renderer_disconnect = _cogl_winsys_renderer_disconnect;
880 vtable.display_setup = _cogl_winsys_display_setup;
881 vtable.display_destroy = _cogl_winsys_display_destroy;
882 vtable.context_init = _cogl_winsys_context_init;
883 vtable.context_deinit = _cogl_winsys_context_deinit;
884 vtable.onscreen_init = _cogl_winsys_onscreen_init;
885 vtable.onscreen_deinit = _cogl_winsys_onscreen_deinit;
886 vtable.onscreen_bind = _cogl_winsys_onscreen_bind;
887 vtable.onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers;
888 vtable.onscreen_update_swap_throttled =
889 _cogl_winsys_onscreen_update_swap_throttled;
890 vtable.onscreen_set_visibility = _cogl_winsys_onscreen_set_visibility;
891 vtable.onscreen_win32_get_window = _cogl_winsys_onscreen_win32_get_window;
893 vtable_inited = TRUE;