1 /* GDK - The GIMP Drawing Kit
2 *
3 * gdkglcontext-win32.c: Win32 specific OpenGL wrappers
4 *
5 * Copyright © 2014 Emmanuele Bassi
6 * Copyright © 2014 Alexander Larsson
7 * Copyright © 2014 Chun-wei Fan
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
18 *
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "config.h"
24
25 #include "gdkprivate-win32.h"
26 #include "gdksurface-win32.h"
27 #include "gdkglcontext-win32.h"
28 #include "gdkdisplay-win32.h"
29
30 #include "gdkwin32display.h"
31 #include "gdkwin32glcontext.h"
32 #include "gdkwin32misc.h"
33 #include "gdkwin32screen.h"
34 #include "gdkwin32surface.h"
35
36 #include "gdkglcontext.h"
37 #include "gdkprofilerprivate.h"
38 #include "gdkinternals.h"
39 #include "gdkintl.h"
40 #include "gdksurface.h"
41
42 #include <cairo.h>
43 #include <epoxy/wgl.h>
44
45 struct _GdkWin32GLContextWGL
46 {
47 GdkWin32GLContext parent_instance;
48
49 HGLRC wgl_context;
50 guint do_frame_sync : 1;
51 };
52
53 typedef struct _GdkWin32GLContextClass GdkWin32GLContextWGLClass;
54
G_DEFINE_TYPE(GdkWin32GLContextWGL,gdk_win32_gl_context_wgl,GDK_TYPE_WIN32_GL_CONTEXT)55 G_DEFINE_TYPE (GdkWin32GLContextWGL, gdk_win32_gl_context_wgl, GDK_TYPE_WIN32_GL_CONTEXT)
56
57 static void
58 gdk_win32_gl_context_wgl_dispose (GObject *gobject)
59 {
60 GdkWin32GLContextWGL *context_wgl = GDK_WIN32_GL_CONTEXT_WGL (gobject);
61
62 if (context_wgl->wgl_context != NULL)
63 {
64 if (wglGetCurrentContext () == context_wgl->wgl_context)
65 wglMakeCurrent (NULL, NULL);
66
67 GDK_NOTE (OPENGL, g_print ("Destroying WGL context\n"));
68
69 wglDeleteContext (context_wgl->wgl_context);
70 context_wgl->wgl_context = NULL;
71 }
72
73 G_OBJECT_CLASS (gdk_win32_gl_context_wgl_parent_class)->dispose (gobject);
74 }
75
76 static void
gdk_win32_gl_context_wgl_end_frame(GdkDrawContext * draw_context,cairo_region_t * painted)77 gdk_win32_gl_context_wgl_end_frame (GdkDrawContext *draw_context,
78 cairo_region_t *painted)
79 {
80 GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
81 GdkWin32GLContextWGL *context_wgl = GDK_WIN32_GL_CONTEXT_WGL (context);
82 GdkSurface *surface = gdk_gl_context_get_surface (context);
83 GdkWin32Display *display_win32 = (GDK_WIN32_DISPLAY (gdk_gl_context_get_display (context)));
84 cairo_rectangle_int_t whole_window;
85 gboolean can_wait = display_win32->hasWglOMLSyncControl;
86 HDC hdc;
87
88 GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_wgl_parent_class)->end_frame (draw_context, painted);
89
90 gdk_gl_context_make_current (context);
91 whole_window = (GdkRectangle) { 0, 0, gdk_surface_get_width (surface), gdk_surface_get_height (surface) };
92
93 gdk_profiler_add_mark (GDK_PROFILER_CURRENT_TIME, 0, "win32", "swap buffers");
94
95 if (surface != NULL)
96 hdc = GDK_WIN32_SURFACE (surface)->hdc;
97 else
98 hdc = display_win32->dummy_context_wgl.hdc;
99
100 if (context_wgl->do_frame_sync)
101 {
102
103 glFinish ();
104
105 if (can_wait)
106 {
107 gint64 ust, msc, sbc;
108
109 wglGetSyncValuesOML (hdc, &ust, &msc, &sbc);
110 wglWaitForMscOML (hdc,
111 0,
112 2,
113 (msc + 1) % 2,
114 &ust, &msc, &sbc);
115 }
116
117 }
118
119 SwapBuffers (hdc);
120 }
121
122 static void
gdk_win32_gl_context_wgl_begin_frame(GdkDrawContext * draw_context,cairo_region_t * update_area)123 gdk_win32_gl_context_wgl_begin_frame (GdkDrawContext *draw_context,
124 cairo_region_t *update_area)
125 {
126 GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
127 GdkSurface *surface;
128
129 surface = gdk_gl_context_get_surface (context);
130
131 gdk_win32_surface_handle_queued_move_resize (draw_context);
132
133 GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_wgl_parent_class)->begin_frame (draw_context, update_area);
134 }
135
136 static int
137 gdk_init_dummy_wgl_context (GdkWin32Display *display_win32);
138
139 #define PIXEL_ATTRIBUTES 17
140
141 static int
get_wgl_pfd(HDC hdc,PIXELFORMATDESCRIPTOR * pfd,GdkWin32Display * display_win32)142 get_wgl_pfd (HDC hdc,
143 PIXELFORMATDESCRIPTOR *pfd,
144 GdkWin32Display *display_win32)
145 {
146 int best_pf = 0;
147
148 pfd->nSize = sizeof (PIXELFORMATDESCRIPTOR);
149
150 if (display_win32 != NULL && display_win32->hasWglARBPixelFormat)
151 {
152 UINT num_formats;
153 int colorbits = GetDeviceCaps (hdc, BITSPIXEL);
154 int i = 0;
155 int pixelAttribs[PIXEL_ATTRIBUTES];
156
157 /* Save up the HDC and HGLRC that we are currently using, to restore back to it when we are done here */
158 HDC hdc_current = wglGetCurrentDC ();
159 HGLRC hglrc_current = wglGetCurrentContext ();
160
161 /* Update PIXEL_ATTRIBUTES above if any groups are added here! */
162 pixelAttribs[i] = WGL_DRAW_TO_WINDOW_ARB;
163 pixelAttribs[i++] = GL_TRUE;
164
165 pixelAttribs[i++] = WGL_SUPPORT_OPENGL_ARB;
166 pixelAttribs[i++] = GL_TRUE;
167
168 pixelAttribs[i++] = WGL_DOUBLE_BUFFER_ARB;
169 pixelAttribs[i++] = GL_TRUE;
170
171 pixelAttribs[i++] = WGL_ACCELERATION_ARB;
172 pixelAttribs[i++] = WGL_FULL_ACCELERATION_ARB;
173
174 pixelAttribs[i++] = WGL_PIXEL_TYPE_ARB;
175 pixelAttribs[i++] = WGL_TYPE_RGBA_ARB;
176
177 pixelAttribs[i++] = WGL_COLOR_BITS_ARB;
178 pixelAttribs[i++] = colorbits;
179
180 /* end of "Update PIXEL_ATTRIBUTES above if any groups are added here!" */
181
182 if (display_win32->hasWglARBmultisample)
183 {
184 pixelAttribs[i++] = WGL_SAMPLE_BUFFERS_ARB;
185 pixelAttribs[i++] = 1;
186
187 pixelAttribs[i++] = WGL_SAMPLES_ARB;
188 pixelAttribs[i++] = 8;
189 }
190
191 pixelAttribs[i++] = 0; /* end of pixelAttribs */
192 best_pf = gdk_init_dummy_wgl_context (display_win32);
193
194 if (!wglMakeCurrent (display_win32->dummy_context_wgl.hdc,
195 display_win32->dummy_context_wgl.hglrc))
196 {
197 wglMakeCurrent (hdc_current, hglrc_current);
198 return 0;
199 }
200
201 wglChoosePixelFormatARB (hdc,
202 pixelAttribs,
203 NULL,
204 1,
205 &best_pf,
206 &num_formats);
207
208 /* Go back to the HDC that we were using, since we are done with the dummy HDC and GL Context */
209 wglMakeCurrent (hdc_current, hglrc_current);
210 }
211 else
212 {
213 pfd->nVersion = 1;
214 pfd->dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER;
215 pfd->iPixelType = PFD_TYPE_RGBA;
216 pfd->cColorBits = GetDeviceCaps (hdc, BITSPIXEL);
217 pfd->cAlphaBits = 8;
218 pfd->dwLayerMask = PFD_MAIN_PLANE;
219
220 best_pf = ChoosePixelFormat (hdc, pfd);
221 }
222
223 return best_pf;
224 }
225
226 /* in WGL, for many OpenGL items, we need a dummy WGL context, so create
227 * one and cache it for later use
228 */
229 static int
gdk_init_dummy_wgl_context(GdkWin32Display * display_win32)230 gdk_init_dummy_wgl_context (GdkWin32Display *display_win32)
231 {
232 PIXELFORMATDESCRIPTOR pfd;
233 gboolean set_pixel_format_result = FALSE;
234 int best_idx = 0;
235
236 if (display_win32->dummy_context_wgl.hdc == NULL)
237 display_win32->dummy_context_wgl.hdc = GetDC (display_win32->hwnd);
238
239 memset (&pfd, 0, sizeof (PIXELFORMATDESCRIPTOR));
240
241 best_idx = get_wgl_pfd (display_win32->dummy_context_wgl.hdc, &pfd, NULL);
242
243 if (best_idx != 0)
244 set_pixel_format_result = SetPixelFormat (display_win32->dummy_context_wgl.hdc,
245 best_idx,
246 &pfd);
247
248 if (best_idx == 0 || !set_pixel_format_result)
249 return 0;
250
251 display_win32->dummy_context_wgl.hglrc =
252 wglCreateContext (display_win32->dummy_context_wgl.hdc);
253
254 if (display_win32->dummy_context_wgl.hglrc == NULL)
255 return 0;
256
257 return best_idx;
258 }
259
260 gboolean
gdk_win32_display_init_wgl(GdkDisplay * display,GError ** error)261 gdk_win32_display_init_wgl (GdkDisplay *display,
262 GError **error)
263 {
264 int best_idx = 0;
265 GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
266 HDC hdc;
267
268 if (!gdk_gl_backend_can_be_used (GDK_GL_WGL, error))
269 return FALSE;
270
271 if (display_win32->wgl_pixel_format != 0)
272 return TRUE;
273
274 /* acquire and cache dummy Window (HWND & HDC) and
275 * dummy GL Context, it is used to query functions
276 * and used for other stuff as well
277 */
278 best_idx = gdk_init_dummy_wgl_context (display_win32);
279 hdc = display_win32->dummy_context_wgl.hdc;
280
281 if (best_idx == 0 ||
282 !wglMakeCurrent (hdc, display_win32->dummy_context_wgl.hglrc))
283 {
284 if (display_win32->dummy_context_wgl.hglrc != NULL)
285 wglDeleteContext (display_win32->dummy_context_wgl.hglrc);
286
287 g_set_error_literal (error, GDK_GL_ERROR,
288 GDK_GL_ERROR_NOT_AVAILABLE,
289 _("No GL implementation is available"));
290
291 return FALSE;
292 }
293
294 display_win32->gl_version = epoxy_gl_version ();
295
296 /* We must have OpenGL/WGL 2.0 or later, or have the GL_ARB_shader_objects extension */
297 if (display_win32->gl_version < 20)
298 {
299 if (!epoxy_has_gl_extension ("GL_ARB_shader_objects"))
300 {
301 wglMakeCurrent (NULL, NULL);
302 wglDeleteContext (display_win32->dummy_context_wgl.hglrc);
303
304 g_set_error_literal (error, GDK_GL_ERROR,
305 GDK_GL_ERROR_NOT_AVAILABLE,
306 _("No GL implementation is available"));
307
308 return FALSE;
309 }
310 }
311
312 display_win32->wgl_pixel_format = best_idx;
313
314 display_win32->hasWglARBCreateContext =
315 epoxy_has_wgl_extension (hdc, "WGL_ARB_create_context");
316 display_win32->hasWglEXTSwapControl =
317 epoxy_has_wgl_extension (hdc, "WGL_EXT_swap_control");
318 display_win32->hasWglOMLSyncControl =
319 epoxy_has_wgl_extension (hdc, "WGL_OML_sync_control");
320 display_win32->hasWglARBPixelFormat =
321 epoxy_has_wgl_extension (hdc, "WGL_ARB_pixel_format");
322 display_win32->hasWglARBmultisample =
323 epoxy_has_wgl_extension (hdc, "WGL_ARB_multisample");
324
325 GDK_NOTE (OPENGL,
326 g_print ("WGL API version %d.%d found\n"
327 " - Vendor: %s\n"
328 " - Checked extensions:\n"
329 "\t* WGL_ARB_pixel_format: %s\n"
330 "\t* WGL_ARB_create_context: %s\n"
331 "\t* WGL_EXT_swap_control: %s\n"
332 "\t* WGL_OML_sync_control: %s\n"
333 "\t* WGL_ARB_multisample: %s\n",
334 display_win32->gl_version / 10,
335 display_win32->gl_version % 10,
336 glGetString (GL_VENDOR),
337 display_win32->hasWglARBPixelFormat ? "yes" : "no",
338 display_win32->hasWglARBCreateContext ? "yes" : "no",
339 display_win32->hasWglEXTSwapControl ? "yes" : "no",
340 display_win32->hasWglOMLSyncControl ? "yes" : "no",
341 display_win32->hasWglARBmultisample ? "yes" : "no"));
342
343 wglMakeCurrent (NULL, NULL);
344
345 return TRUE;
346 }
347
348 /* Setup the legacy context after creating it */
349 static gboolean
ensure_legacy_wgl_context(HDC hdc,HGLRC hglrc_legacy,GdkGLContext * share)350 ensure_legacy_wgl_context (HDC hdc,
351 HGLRC hglrc_legacy,
352 GdkGLContext *share)
353 {
354 GdkWin32GLContextWGL *context_wgl;
355
356 if (!wglMakeCurrent (hdc, hglrc_legacy))
357 return FALSE;
358
359 if (share != NULL)
360 {
361 context_wgl = GDK_WIN32_GL_CONTEXT_WGL (share);
362
363 return wglShareLists (hglrc_legacy, context_wgl->wgl_context);
364 }
365
366 return TRUE;
367 }
368
369 static HGLRC
create_wgl_context_with_attribs(HDC hdc,HGLRC hglrc_base,GdkGLContext * share,int flags,int major,int minor,gboolean * is_legacy)370 create_wgl_context_with_attribs (HDC hdc,
371 HGLRC hglrc_base,
372 GdkGLContext *share,
373 int flags,
374 int major,
375 int minor,
376 gboolean *is_legacy)
377 {
378 HGLRC hglrc;
379 GdkWin32GLContextWGL *context_wgl;
380
381 /* if we have wglCreateContextAttribsARB(), create a
382 * context with the compatibility profile if a legacy
383 * context is requested, or when we go into fallback mode
384 */
385 int profile = *is_legacy ? WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB :
386 WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
387
388 int attribs[] = {
389 WGL_CONTEXT_PROFILE_MASK_ARB, profile,
390 WGL_CONTEXT_MAJOR_VERSION_ARB, *is_legacy ? 3 : major,
391 WGL_CONTEXT_MINOR_VERSION_ARB, *is_legacy ? 0 : minor,
392 WGL_CONTEXT_FLAGS_ARB, flags,
393 0
394 };
395
396 if (share != NULL)
397 context_wgl = GDK_WIN32_GL_CONTEXT_WGL (share);
398
399 hglrc = wglCreateContextAttribsARB (hdc,
400 share != NULL ? context_wgl->wgl_context : NULL,
401 attribs);
402
403 return hglrc;
404 }
405
406 static HGLRC
create_wgl_context(HDC hdc,GdkGLContext * share,int flags,int major,int minor,gboolean * is_legacy,gboolean hasWglARBCreateContext)407 create_wgl_context (HDC hdc,
408 GdkGLContext *share,
409 int flags,
410 int major,
411 int minor,
412 gboolean *is_legacy,
413 gboolean hasWglARBCreateContext)
414 {
415 /* We need a legacy context for *all* cases */
416 HGLRC hglrc_base = wglCreateContext (hdc);
417 gboolean success = TRUE;
418
419 /* Save up the HDC and HGLRC that we are currently using, to restore back to it when we are done here */
420 HDC hdc_current = wglGetCurrentDC ();
421 HGLRC hglrc_current = wglGetCurrentContext ();
422
423 /* if we have no wglCreateContextAttribsARB(), return the legacy context when all is set */
424 if (*is_legacy && !hasWglARBCreateContext)
425 {
426 if (ensure_legacy_wgl_context (hdc, hglrc_base, share))
427 {
428 wglMakeCurrent (hdc_current, hglrc_current);
429 return hglrc_base;
430 }
431
432 success = FALSE;
433 goto gl_fail;
434 }
435 else
436 {
437 HGLRC hglrc = NULL;
438
439 if (!wglMakeCurrent (hdc, hglrc_base))
440 {
441 success = FALSE;
442 goto gl_fail;
443 }
444
445 /*
446 * We need a Core GL 4.1 context in order to use the GL support in
447 * the GStreamer media widget backend, but wglCreateContextAttribsARB()
448 * may only give us the GL context version that we ask for here, and
449 * nothing more. So, if we are asking for a pre-GL 4.1 context,
450 * try to ask for a 4.1 context explicitly first. If that is not supported,
451 * then we fall back to whatever version that we were asking for (or, even a
452 * legacy context if that fails), at a price of not able to have GL support
453 * for the media GStreamer backend.
454 */
455 if (major < 4 || (major == 4 && minor < 1))
456 hglrc = create_wgl_context_with_attribs (hdc,
457 hglrc_base,
458 share,
459 flags,
460 4,
461 1,
462 is_legacy);
463
464 if (hglrc == NULL)
465 hglrc = create_wgl_context_with_attribs (hdc,
466 hglrc_base,
467 share,
468 flags,
469 major,
470 minor,
471 is_legacy);
472
473 /* return the legacy context we have if it could be setup properly, in case the 3.0+ context creation failed */
474 if (hglrc == NULL)
475 {
476 if (!(*is_legacy))
477 {
478 /* If we aren't using a legacy context in the beginning, try again with a compatibility profile 3.0 context */
479 hglrc = create_wgl_context_with_attribs (hdc,
480 hglrc_base,
481 share,
482 flags,
483 0, 0,
484 is_legacy);
485
486 *is_legacy = TRUE;
487 }
488
489 if (hglrc == NULL)
490 {
491 if (!ensure_legacy_wgl_context (hdc, hglrc_base, share))
492 success = FALSE;
493 }
494
495 if (success)
496 GDK_NOTE (OPENGL, g_print ("Using legacy context as fallback\n"));
497 }
498
499 gl_fail:
500
501 if (!success)
502 {
503 wglMakeCurrent (NULL, NULL);
504 wglDeleteContext (hglrc_base);
505 return NULL;
506 }
507
508 wglMakeCurrent (hdc_current, hglrc_current);
509
510 if (hglrc != NULL)
511 {
512 wglDeleteContext (hglrc_base);
513 return hglrc;
514 }
515
516 return hglrc_base;
517 }
518 }
519
520 static gboolean
set_wgl_pixformat_for_hdc(HDC hdc,int * best_idx,GdkWin32Display * display_win32)521 set_wgl_pixformat_for_hdc (HDC hdc,
522 int *best_idx,
523 GdkWin32Display *display_win32)
524 {
525 gboolean already_checked = TRUE;
526 *best_idx = GetPixelFormat (hdc);
527
528 /* one is only allowed to call SetPixelFormat(), and so ChoosePixelFormat()
529 * one single time per window HDC
530 */
531 if (*best_idx == 0)
532 {
533 PIXELFORMATDESCRIPTOR pfd;
534 gboolean set_pixel_format_result = FALSE;
535
536 GDK_NOTE (OPENGL, g_print ("requesting pixel format...\n"));
537 already_checked = FALSE;
538 *best_idx = get_wgl_pfd (hdc, &pfd, display_win32);
539
540 if (*best_idx != 0)
541 set_pixel_format_result = SetPixelFormat (hdc, *best_idx, &pfd);
542
543 /* ChoosePixelFormat() or SetPixelFormat() failed, bail out */
544 if (*best_idx == 0 || !set_pixel_format_result)
545 return FALSE;
546 }
547
548 GDK_NOTE (OPENGL, g_print ("%s""requested and set pixel format: %d\n", already_checked ? "already " : "", *best_idx));
549
550 return TRUE;
551 }
552
553 static gboolean
gdk_win32_gl_context_wgl_realize(GdkGLContext * context,GError ** error)554 gdk_win32_gl_context_wgl_realize (GdkGLContext *context,
555 GError **error)
556 {
557 GdkWin32GLContextWGL *context_wgl = GDK_WIN32_GL_CONTEXT_WGL (context);
558
559 gboolean debug_bit, compat_bit, legacy_bit;
560
561 /* request flags and specific versions for core (3.2+) WGL context */
562 int flags = 0;
563 int major = 0;
564 int minor = 0;
565 HGLRC hglrc;
566 int pixel_format;
567 HDC hdc;
568 HWND hwnd;
569
570 GdkSurface *surface = gdk_gl_context_get_surface (context);
571 GdkDisplay *display = gdk_gl_context_get_display (context);
572 GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
573 GdkGLContext *share = gdk_display_get_gl_context (display);
574
575 gdk_gl_context_get_required_version (context, &major, &minor);
576 debug_bit = gdk_gl_context_get_debug_enabled (context);
577 compat_bit = gdk_gl_context_get_forward_compatible (context);
578
579 if (surface != NULL)
580 hdc = GDK_WIN32_SURFACE (surface)->hdc;
581 else
582 hdc = display_win32->dummy_context_wgl.hdc;
583
584 /*
585 * A legacy context cannot be shared with core profile ones, so this means we
586 * must stick to a legacy context if the shared context is a legacy context
587 */
588 legacy_bit = GDK_DISPLAY_DEBUG_CHECK (display, GL_LEGACY) ?
589 TRUE :
590 share != NULL && gdk_gl_context_is_legacy (share);
591
592 if (!set_wgl_pixformat_for_hdc (hdc,
593 &pixel_format,
594 display_win32))
595 {
596 g_set_error_literal (error, GDK_GL_ERROR,
597 GDK_GL_ERROR_UNSUPPORTED_FORMAT,
598 _("No available configurations for the given pixel format"));
599
600 return FALSE;
601 }
602
603 /* if there isn't wglCreateContextAttribsARB() on WGL, use a legacy context */
604 if (!legacy_bit)
605 legacy_bit = !display_win32->hasWglARBCreateContext;
606 if (debug_bit)
607 flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
608 if (compat_bit)
609 flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
610
611 GDK_NOTE (OPENGL,
612 g_print ("Creating %s WGL context (version:%d.%d, debug:%s, forward:%s, legacy: %s)\n",
613 compat_bit ? "core" : "compat",
614 major,
615 minor,
616 debug_bit ? "yes" : "no",
617 compat_bit ? "yes" : "no",
618 legacy_bit ? "yes" : "no"));
619
620 hglrc = create_wgl_context (hdc,
621 share,
622 flags,
623 major,
624 minor,
625 &legacy_bit,
626 display_win32->hasWglARBCreateContext);
627
628 if (hglrc == NULL)
629 {
630 g_set_error_literal (error, GDK_GL_ERROR,
631 GDK_GL_ERROR_NOT_AVAILABLE,
632 _("Unable to create a GL context"));
633 return FALSE;
634 }
635
636 GDK_NOTE (OPENGL,
637 g_print ("Created WGL context[%p], pixel_format=%d\n",
638 hglrc,
639 pixel_format));
640
641 context_wgl->wgl_context = hglrc;
642
643 /* No GLES, WGL does not support using EGL contexts */
644 gdk_gl_context_set_use_es (context, FALSE);
645
646 /* Ensure that any other context is created with a legacy bit set */
647 gdk_gl_context_set_is_legacy (context, legacy_bit);
648
649 return TRUE;
650 }
651
652 static gboolean
gdk_win32_gl_context_wgl_clear_current(GdkGLContext * context)653 gdk_win32_gl_context_wgl_clear_current (GdkGLContext *context)
654 {
655 return wglMakeCurrent (NULL, NULL);
656 }
657
658 static gboolean
gdk_win32_gl_context_wgl_make_current(GdkGLContext * context,gboolean surfaceless)659 gdk_win32_gl_context_wgl_make_current (GdkGLContext *context,
660 gboolean surfaceless)
661 {
662 GdkWin32GLContextWGL *context_wgl = GDK_WIN32_GL_CONTEXT_WGL (context);
663 GdkDisplay *display = gdk_gl_context_get_display (context);
664 GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
665 GdkSurface *surface = gdk_gl_context_get_surface (context);
666 HDC hdc;
667
668 if (surfaceless || surface == NULL)
669 hdc = display_win32->dummy_context_wgl.hdc;
670 else
671 hdc = GDK_WIN32_SURFACE (surface)->hdc;
672
673 if (!wglMakeCurrent (hdc, context_wgl->wgl_context))
674 return FALSE;
675
676 if (!surfaceless && display_win32->hasWglEXTSwapControl)
677 {
678 gboolean do_frame_sync = FALSE;
679
680 /* If there is compositing there is no particular need to delay
681 * the swap when drawing on the offscreen, rendering to the screen
682 * happens later anyway, and its up to the compositor to sync that
683 * to the vblank. */
684 do_frame_sync = ! gdk_display_is_composited (display);
685
686 if (do_frame_sync != context_wgl->do_frame_sync)
687 {
688 context_wgl->do_frame_sync = do_frame_sync;
689
690 wglSwapIntervalEXT (do_frame_sync ? 1 : 0);
691 }
692 }
693
694 return TRUE;
695 }
696
697 static void
gdk_win32_gl_context_wgl_class_init(GdkWin32GLContextWGLClass * klass)698 gdk_win32_gl_context_wgl_class_init (GdkWin32GLContextWGLClass *klass)
699 {
700 GdkGLContextClass *context_class = GDK_GL_CONTEXT_CLASS (klass);
701 GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass);
702 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
703
704 context_class->backend_type = GDK_GL_WGL;
705
706 context_class->realize = gdk_win32_gl_context_wgl_realize;
707 context_class->make_current = gdk_win32_gl_context_wgl_make_current;
708 context_class->clear_current = gdk_win32_gl_context_wgl_clear_current;
709
710 draw_context_class->begin_frame = gdk_win32_gl_context_wgl_begin_frame;
711 draw_context_class->end_frame = gdk_win32_gl_context_wgl_end_frame;
712 gobject_class->dispose = gdk_win32_gl_context_wgl_dispose;
713 }
714
715 static void
gdk_win32_gl_context_wgl_init(GdkWin32GLContextWGL * wgl_context)716 gdk_win32_gl_context_wgl_init (GdkWin32GLContextWGL *wgl_context)
717 {
718 }
719
720
721 /**
722 * gdk_win32_display_get_wgl_version:
723 * @display: a `GdkDisplay`
724 * @major: (out): return location for the WGL major version
725 * @minor: (out): return location for the WGL minor version
726 *
727 * Retrieves the version of the WGL implementation.
728 *
729 * Returns: %TRUE if WGL is available
730 */
731 gboolean
gdk_win32_display_get_wgl_version(GdkDisplay * display,int * major,int * minor)732 gdk_win32_display_get_wgl_version (GdkDisplay *display,
733 int *major,
734 int *minor)
735 {
736 GdkWin32Display *display_win32;
737 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
738
739 if (!GDK_IS_WIN32_DISPLAY (display))
740 return FALSE;
741
742 display_win32 = GDK_WIN32_DISPLAY (display);
743 if (display_win32->wgl_pixel_format == 0)
744 return FALSE;
745
746 if (major != NULL)
747 *major = display_win32->gl_version / 10;
748 if (minor != NULL)
749 *minor = display_win32->gl_version % 10;
750
751 return TRUE;
752 }
753