SDL  2.0
SDL_windowsopengl.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../../SDL_internal.h"
22 
23 #if SDL_VIDEO_DRIVER_WINDOWS
24 
25 #include "SDL_assert.h"
26 #include "SDL_loadso.h"
27 #include "SDL_windowsvideo.h"
28 #include "SDL_windowsopengles.h"
29 
30 /* WGL implementation of SDL OpenGL support */
31 
32 #if SDL_VIDEO_OPENGL_WGL
33 #include "SDL_opengl.h"
34 
35 #define DEFAULT_OPENGL "OPENGL32.DLL"
36 
37 #ifndef WGL_ARB_create_context
38 #define WGL_ARB_create_context
39 #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
40 #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
41 #define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
42 #define WGL_CONTEXT_FLAGS_ARB 0x2094
43 #define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
44 #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
45 
46 #ifndef WGL_ARB_create_context_profile
47 #define WGL_ARB_create_context_profile
48 #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
49 #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
50 #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
51 #endif
52 
53 #ifndef WGL_ARB_create_context_robustness
54 #define WGL_ARB_create_context_robustness
55 #define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
56 #define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
57 #define WGL_NO_RESET_NOTIFICATION_ARB 0x8261
58 #define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
59 #endif
60 #endif
61 
62 #ifndef WGL_EXT_create_context_es2_profile
63 #define WGL_EXT_create_context_es2_profile
64 #define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
65 #endif
66 
67 #ifndef WGL_EXT_create_context_es_profile
68 #define WGL_EXT_create_context_es_profile
69 #define WGL_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004
70 #endif
71 
72 #ifndef WGL_ARB_framebuffer_sRGB
73 #define WGL_ARB_framebuffer_sRGB
74 #define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9
75 #endif
76 
77 #ifndef WGL_ARB_context_flush_control
78 #define WGL_ARB_context_flush_control
79 #define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
80 #define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0x0000
81 #define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
82 #endif
83 
84 typedef HGLRC(APIENTRYP PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC,
85  HGLRC
86  hShareContext,
87  const int
88  *attribList);
89 
90 int
91 WIN_GL_LoadLibrary(_THIS, const char *path)
92 {
93  void *handle;
94 
95  if (path == NULL) {
96  path = SDL_getenv("SDL_OPENGL_LIBRARY");
97  }
98  if (path == NULL) {
99  path = DEFAULT_OPENGL;
100  }
102  if (!_this->gl_config.dll_handle) {
103  return -1;
104  }
107 
108  /* Allocate OpenGL memory */
109  _this->gl_data = (struct SDL_GLDriverData *) SDL_calloc(1, sizeof(struct SDL_GLDriverData));
110  if (!_this->gl_data) {
111  return SDL_OutOfMemory();
112  }
113 
114  /* Load function pointers */
115  handle = _this->gl_config.dll_handle;
116  _this->gl_data->wglGetProcAddress = (void *(WINAPI *) (const char *))
117  SDL_LoadFunction(handle, "wglGetProcAddress");
118  _this->gl_data->wglCreateContext = (HGLRC(WINAPI *) (HDC))
119  SDL_LoadFunction(handle, "wglCreateContext");
120  _this->gl_data->wglDeleteContext = (BOOL(WINAPI *) (HGLRC))
121  SDL_LoadFunction(handle, "wglDeleteContext");
122  _this->gl_data->wglMakeCurrent = (BOOL(WINAPI *) (HDC, HGLRC))
123  SDL_LoadFunction(handle, "wglMakeCurrent");
124  _this->gl_data->wglShareLists = (BOOL(WINAPI *) (HGLRC, HGLRC))
125  SDL_LoadFunction(handle, "wglShareLists");
126 
127  if (!_this->gl_data->wglGetProcAddress ||
128  !_this->gl_data->wglCreateContext ||
129  !_this->gl_data->wglDeleteContext ||
130  !_this->gl_data->wglMakeCurrent) {
131  return SDL_SetError("Could not retrieve OpenGL functions");
132  }
133 
134  return 0;
135 }
136 
137 void *
138 WIN_GL_GetProcAddress(_THIS, const char *proc)
139 {
140  void *func;
141 
142  /* This is to pick up extensions */
143  func = _this->gl_data->wglGetProcAddress(proc);
144  if (!func) {
145  /* This is probably a normal GL function */
146  func = GetProcAddress(_this->gl_config.dll_handle, proc);
147  }
148  return func;
149 }
150 
151 void
152 WIN_GL_UnloadLibrary(_THIS)
153 {
156 
157  /* Free OpenGL memory */
159  _this->gl_data = NULL;
160 }
161 
162 static void
163 WIN_GL_SetupPixelFormat(_THIS, PIXELFORMATDESCRIPTOR * pfd)
164 {
165  SDL_zerop(pfd);
166  pfd->nSize = sizeof(*pfd);
167  pfd->nVersion = 1;
168  pfd->dwFlags = (PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL);
170  pfd->dwFlags |= PFD_DOUBLEBUFFER;
171  }
172  if (_this->gl_config.stereo) {
173  pfd->dwFlags |= PFD_STEREO;
174  }
175  pfd->iLayerType = PFD_MAIN_PLANE;
176  pfd->iPixelType = PFD_TYPE_RGBA;
177  pfd->cRedBits = _this->gl_config.red_size;
178  pfd->cGreenBits = _this->gl_config.green_size;
179  pfd->cBlueBits = _this->gl_config.blue_size;
180  pfd->cAlphaBits = _this->gl_config.alpha_size;
181  if (_this->gl_config.buffer_size) {
182  pfd->cColorBits =
184  } else {
185  pfd->cColorBits = (pfd->cRedBits + pfd->cGreenBits + pfd->cBlueBits);
186  }
187  pfd->cAccumRedBits = _this->gl_config.accum_red_size;
188  pfd->cAccumGreenBits = _this->gl_config.accum_green_size;
189  pfd->cAccumBlueBits = _this->gl_config.accum_blue_size;
190  pfd->cAccumAlphaBits = _this->gl_config.accum_alpha_size;
191  pfd->cAccumBits =
192  (pfd->cAccumRedBits + pfd->cAccumGreenBits + pfd->cAccumBlueBits +
193  pfd->cAccumAlphaBits);
194  pfd->cDepthBits = _this->gl_config.depth_size;
195  pfd->cStencilBits = _this->gl_config.stencil_size;
196 }
197 
198 /* Choose the closest pixel format that meets or exceeds the target.
199  FIXME: Should we weight any particular attribute over any other?
200 */
201 static int
202 WIN_GL_ChoosePixelFormat(HDC hdc, PIXELFORMATDESCRIPTOR * target)
203 {
204  PIXELFORMATDESCRIPTOR pfd;
205  int count, index, best = 0;
206  unsigned int dist, best_dist = ~0U;
207 
208  count = DescribePixelFormat(hdc, 1, sizeof(pfd), NULL);
209 
210  for (index = 1; index <= count; index++) {
211 
212  if (!DescribePixelFormat(hdc, index, sizeof(pfd), &pfd)) {
213  continue;
214  }
215 
216  if ((pfd.dwFlags & target->dwFlags) != target->dwFlags) {
217  continue;
218  }
219 
220  if (pfd.iLayerType != target->iLayerType) {
221  continue;
222  }
223  if (pfd.iPixelType != target->iPixelType) {
224  continue;
225  }
226 
227  dist = 0;
228 
229  if (pfd.cColorBits < target->cColorBits) {
230  continue;
231  } else {
232  dist += (pfd.cColorBits - target->cColorBits);
233  }
234  if (pfd.cRedBits < target->cRedBits) {
235  continue;
236  } else {
237  dist += (pfd.cRedBits - target->cRedBits);
238  }
239  if (pfd.cGreenBits < target->cGreenBits) {
240  continue;
241  } else {
242  dist += (pfd.cGreenBits - target->cGreenBits);
243  }
244  if (pfd.cBlueBits < target->cBlueBits) {
245  continue;
246  } else {
247  dist += (pfd.cBlueBits - target->cBlueBits);
248  }
249  if (pfd.cAlphaBits < target->cAlphaBits) {
250  continue;
251  } else {
252  dist += (pfd.cAlphaBits - target->cAlphaBits);
253  }
254  if (pfd.cAccumBits < target->cAccumBits) {
255  continue;
256  } else {
257  dist += (pfd.cAccumBits - target->cAccumBits);
258  }
259  if (pfd.cAccumRedBits < target->cAccumRedBits) {
260  continue;
261  } else {
262  dist += (pfd.cAccumRedBits - target->cAccumRedBits);
263  }
264  if (pfd.cAccumGreenBits < target->cAccumGreenBits) {
265  continue;
266  } else {
267  dist += (pfd.cAccumGreenBits - target->cAccumGreenBits);
268  }
269  if (pfd.cAccumBlueBits < target->cAccumBlueBits) {
270  continue;
271  } else {
272  dist += (pfd.cAccumBlueBits - target->cAccumBlueBits);
273  }
274  if (pfd.cAccumAlphaBits < target->cAccumAlphaBits) {
275  continue;
276  } else {
277  dist += (pfd.cAccumAlphaBits - target->cAccumAlphaBits);
278  }
279  if (pfd.cDepthBits < target->cDepthBits) {
280  continue;
281  } else {
282  dist += (pfd.cDepthBits - target->cDepthBits);
283  }
284  if (pfd.cStencilBits < target->cStencilBits) {
285  continue;
286  } else {
287  dist += (pfd.cStencilBits - target->cStencilBits);
288  }
289 
290  if (dist < best_dist) {
291  best = index;
292  best_dist = dist;
293  }
294  }
295 
296  return best;
297 }
298 
299 static SDL_bool
300 HasExtension(const char *extension, const char *extensions)
301 {
302  const char *start;
303  const char *where, *terminator;
304 
305  /* Extension names should not have spaces. */
306  where = SDL_strchr(extension, ' ');
307  if (where || *extension == '\0')
308  return SDL_FALSE;
309 
310  if (!extensions)
311  return SDL_FALSE;
312 
313  /* It takes a bit of care to be fool-proof about parsing the
314  * OpenGL extensions string. Don't be fooled by sub-strings,
315  * etc. */
316 
317  start = extensions;
318 
319  for (;;) {
320  where = SDL_strstr(start, extension);
321  if (!where)
322  break;
323 
324  terminator = where + SDL_strlen(extension);
325  if (where == start || *(where - 1) == ' ')
326  if (*terminator == ' ' || *terminator == '\0')
327  return SDL_TRUE;
328 
329  start = terminator;
330  }
331  return SDL_FALSE;
332 }
333 
334 void
335 WIN_GL_InitExtensions(_THIS)
336 {
337  const char *(WINAPI * wglGetExtensionsStringARB) (HDC) = 0;
338  const char *extensions;
339  HWND hwnd;
340  HDC hdc;
341  HGLRC hglrc;
342  PIXELFORMATDESCRIPTOR pfd;
343 
344  if (!_this->gl_data) {
345  return;
346  }
347 
348  hwnd =
349  CreateWindow(SDL_Appname, SDL_Appname, (WS_POPUP | WS_DISABLED), 0, 0,
350  10, 10, NULL, NULL, SDL_Instance, NULL);
351  if (!hwnd) {
352  return;
353  }
355 
356  hdc = GetDC(hwnd);
357 
358  WIN_GL_SetupPixelFormat(_this, &pfd);
359 
360  SetPixelFormat(hdc, ChoosePixelFormat(hdc, &pfd), &pfd);
361 
362  hglrc = _this->gl_data->wglCreateContext(hdc);
363  if (!hglrc) {
364  return;
365  }
366  _this->gl_data->wglMakeCurrent(hdc, hglrc);
367 
368  wglGetExtensionsStringARB = (const char *(WINAPI *) (HDC))
369  _this->gl_data->wglGetProcAddress("wglGetExtensionsStringARB");
370  if (wglGetExtensionsStringARB) {
371  extensions = wglGetExtensionsStringARB(hdc);
372  } else {
373  extensions = NULL;
374  }
375 
376  /* Check for WGL_ARB_pixel_format */
377  _this->gl_data->HAS_WGL_ARB_pixel_format = SDL_FALSE;
378  if (HasExtension("WGL_ARB_pixel_format", extensions)) {
379  _this->gl_data->wglChoosePixelFormatARB = (BOOL(WINAPI *)
380  (HDC, const int *,
381  const FLOAT *, UINT,
382  int *, UINT *))
383  WIN_GL_GetProcAddress(_this, "wglChoosePixelFormatARB");
384  _this->gl_data->wglGetPixelFormatAttribivARB =
385  (BOOL(WINAPI *) (HDC, int, int, UINT, const int *, int *))
386  WIN_GL_GetProcAddress(_this, "wglGetPixelFormatAttribivARB");
387 
388  if ((_this->gl_data->wglChoosePixelFormatARB != NULL) &&
389  (_this->gl_data->wglGetPixelFormatAttribivARB != NULL)) {
390  _this->gl_data->HAS_WGL_ARB_pixel_format = SDL_TRUE;
391  }
392  }
393 
394  /* Check for WGL_EXT_swap_control */
395  _this->gl_data->HAS_WGL_EXT_swap_control_tear = SDL_FALSE;
396  if (HasExtension("WGL_EXT_swap_control", extensions)) {
397  _this->gl_data->wglSwapIntervalEXT =
398  WIN_GL_GetProcAddress(_this, "wglSwapIntervalEXT");
399  _this->gl_data->wglGetSwapIntervalEXT =
400  WIN_GL_GetProcAddress(_this, "wglGetSwapIntervalEXT");
401  if (HasExtension("WGL_EXT_swap_control_tear", extensions)) {
402  _this->gl_data->HAS_WGL_EXT_swap_control_tear = SDL_TRUE;
403  }
404  } else {
405  _this->gl_data->wglSwapIntervalEXT = NULL;
406  _this->gl_data->wglGetSwapIntervalEXT = NULL;
407  }
408 
409  /* Check for WGL_EXT_create_context_es2_profile */
410  _this->gl_data->HAS_WGL_EXT_create_context_es2_profile = SDL_FALSE;
411  if (HasExtension("WGL_EXT_create_context_es2_profile", extensions)) {
412  _this->gl_data->HAS_WGL_EXT_create_context_es2_profile = SDL_TRUE;
413  }
414 
415  /* Check for GLX_ARB_context_flush_control */
416  if (HasExtension("WGL_ARB_context_flush_control", extensions)) {
417  _this->gl_data->HAS_WGL_ARB_context_flush_control = SDL_TRUE;
418  }
419 
420  _this->gl_data->wglMakeCurrent(hdc, NULL);
421  _this->gl_data->wglDeleteContext(hglrc);
422  ReleaseDC(hwnd, hdc);
423  DestroyWindow(hwnd);
425 }
426 
427 static int
428 WIN_GL_ChoosePixelFormatARB(_THIS, int *iAttribs, float *fAttribs)
429 {
430  HWND hwnd;
431  HDC hdc;
432  PIXELFORMATDESCRIPTOR pfd;
433  HGLRC hglrc;
434  int pixel_format = 0;
435  unsigned int matching;
436 
437  hwnd =
438  CreateWindow(SDL_Appname, SDL_Appname, (WS_POPUP | WS_DISABLED), 0, 0,
439  10, 10, NULL, NULL, SDL_Instance, NULL);
441 
442  hdc = GetDC(hwnd);
443 
444  WIN_GL_SetupPixelFormat(_this, &pfd);
445 
446  SetPixelFormat(hdc, ChoosePixelFormat(hdc, &pfd), &pfd);
447 
448  hglrc = _this->gl_data->wglCreateContext(hdc);
449  if (hglrc) {
450  _this->gl_data->wglMakeCurrent(hdc, hglrc);
451 
452  if (_this->gl_data->HAS_WGL_ARB_pixel_format) {
453  _this->gl_data->wglChoosePixelFormatARB(hdc, iAttribs, fAttribs,
454  1, &pixel_format,
455  &matching);
456  }
457 
458  _this->gl_data->wglMakeCurrent(hdc, NULL);
459  _this->gl_data->wglDeleteContext(hglrc);
460  }
461  ReleaseDC(hwnd, hdc);
462  DestroyWindow(hwnd);
464 
465  return pixel_format;
466 }
467 
468 /* actual work of WIN_GL_SetupWindow() happens here. */
469 static int
470 WIN_GL_SetupWindowInternal(_THIS, SDL_Window * window)
471 {
472  HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc;
473  PIXELFORMATDESCRIPTOR pfd;
474  int pixel_format = 0;
475  int iAttribs[64];
476  int *iAttr;
477  int *iAccelAttr;
478  float fAttribs[1] = { 0 };
479 
480  WIN_GL_SetupPixelFormat(_this, &pfd);
481 
482  /* setup WGL_ARB_pixel_format attribs */
483  iAttr = &iAttribs[0];
484 
485  *iAttr++ = WGL_DRAW_TO_WINDOW_ARB;
486  *iAttr++ = GL_TRUE;
487  *iAttr++ = WGL_RED_BITS_ARB;
488  *iAttr++ = _this->gl_config.red_size;
489  *iAttr++ = WGL_GREEN_BITS_ARB;
490  *iAttr++ = _this->gl_config.green_size;
491  *iAttr++ = WGL_BLUE_BITS_ARB;
492  *iAttr++ = _this->gl_config.blue_size;
493 
494  if (_this->gl_config.alpha_size) {
495  *iAttr++ = WGL_ALPHA_BITS_ARB;
496  *iAttr++ = _this->gl_config.alpha_size;
497  }
498 
499  *iAttr++ = WGL_DOUBLE_BUFFER_ARB;
500  *iAttr++ = _this->gl_config.double_buffer;
501 
502  *iAttr++ = WGL_DEPTH_BITS_ARB;
503  *iAttr++ = _this->gl_config.depth_size;
504 
506  *iAttr++ = WGL_STENCIL_BITS_ARB;
507  *iAttr++ = _this->gl_config.stencil_size;
508  }
509 
511  *iAttr++ = WGL_ACCUM_RED_BITS_ARB;
512  *iAttr++ = _this->gl_config.accum_red_size;
513  }
514 
516  *iAttr++ = WGL_ACCUM_GREEN_BITS_ARB;
517  *iAttr++ = _this->gl_config.accum_green_size;
518  }
519 
521  *iAttr++ = WGL_ACCUM_BLUE_BITS_ARB;
522  *iAttr++ = _this->gl_config.accum_blue_size;
523  }
524 
526  *iAttr++ = WGL_ACCUM_ALPHA_BITS_ARB;
527  *iAttr++ = _this->gl_config.accum_alpha_size;
528  }
529 
530  if (_this->gl_config.stereo) {
531  *iAttr++ = WGL_STEREO_ARB;
532  *iAttr++ = GL_TRUE;
533  }
534 
536  *iAttr++ = WGL_SAMPLE_BUFFERS_ARB;
537  *iAttr++ = _this->gl_config.multisamplebuffers;
538  }
539 
541  *iAttr++ = WGL_SAMPLES_ARB;
542  *iAttr++ = _this->gl_config.multisamplesamples;
543  }
544 
546  *iAttr++ = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB;
548  }
549 
550  /* We always choose either FULL or NO accel on Windows, because of flaky
551  drivers. If the app didn't specify, we use FULL, because that's
552  probably what they wanted (and if you didn't care and got FULL, that's
553  a perfectly valid result in any case). */
554  *iAttr++ = WGL_ACCELERATION_ARB;
555  iAccelAttr = iAttr;
556  if (_this->gl_config.accelerated) {
557  *iAttr++ = WGL_FULL_ACCELERATION_ARB;
558  } else {
559  *iAttr++ = WGL_NO_ACCELERATION_ARB;
560  }
561 
562  *iAttr = 0;
563 
564  /* Choose and set the closest available pixel format */
565  pixel_format = WIN_GL_ChoosePixelFormatARB(_this, iAttribs, fAttribs);
566 
567  /* App said "don't care about accel" and FULL accel failed. Try NO. */
568  if ( ( !pixel_format ) && ( _this->gl_config.accelerated < 0 ) ) {
569  *iAccelAttr = WGL_NO_ACCELERATION_ARB;
570  pixel_format = WIN_GL_ChoosePixelFormatARB(_this, iAttribs, fAttribs);
571  *iAccelAttr = WGL_FULL_ACCELERATION_ARB; /* if we try again. */
572  }
573  if (!pixel_format) {
574  pixel_format = WIN_GL_ChoosePixelFormat(hdc, &pfd);
575  }
576  if (!pixel_format) {
577  return SDL_SetError("No matching GL pixel format available");
578  }
579  if (!SetPixelFormat(hdc, pixel_format, &pfd)) {
580  return WIN_SetError("SetPixelFormat()");
581  }
582  return 0;
583 }
584 
585 int
586 WIN_GL_SetupWindow(_THIS, SDL_Window * window)
587 {
588  /* The current context is lost in here; save it and reset it. */
589  SDL_Window *current_win = SDL_GL_GetCurrentWindow();
590  SDL_GLContext current_ctx = SDL_GL_GetCurrentContext();
591  const int retval = WIN_GL_SetupWindowInternal(_this, window);
592  WIN_GL_MakeCurrent(_this, current_win, current_ctx);
593  return retval;
594 }
595 
597 WIN_GL_CreateContext(_THIS, SDL_Window * window)
598 {
599  HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc;
600  HGLRC context, share_context;
601 
603  !_this->gl_data->HAS_WGL_EXT_create_context_es2_profile) {
604 #if SDL_VIDEO_OPENGL_EGL
605  /* Switch to EGL based functions */
606  WIN_GL_UnloadLibrary(_this);
607  _this->GL_LoadLibrary = WIN_GLES_LoadLibrary;
608  _this->GL_GetProcAddress = WIN_GLES_GetProcAddress;
609  _this->GL_UnloadLibrary = WIN_GLES_UnloadLibrary;
610  _this->GL_CreateContext = WIN_GLES_CreateContext;
611  _this->GL_MakeCurrent = WIN_GLES_MakeCurrent;
612  _this->GL_SetSwapInterval = WIN_GLES_SetSwapInterval;
613  _this->GL_GetSwapInterval = WIN_GLES_GetSwapInterval;
614  _this->GL_SwapWindow = WIN_GLES_SwapWindow;
615  _this->GL_DeleteContext = WIN_GLES_DeleteContext;
616 
617  if (WIN_GLES_LoadLibrary(_this, NULL) != 0) {
618  return NULL;
619  }
620 
621  return WIN_GLES_CreateContext(_this, window);
622 #else
623  SDL_SetError("SDL not configured with EGL support");
624  return NULL;
625 #endif
626  }
627 
629  share_context = (HGLRC)SDL_GL_GetCurrentContext();
630  } else {
631  share_context = 0;
632  }
633 
634  if (_this->gl_config.major_version < 3 &&
635  _this->gl_config.profile_mask == 0 &&
636  _this->gl_config.flags == 0) {
637  /* Create legacy context */
638  context = _this->gl_data->wglCreateContext(hdc);
639  if( share_context != 0 ) {
640  _this->gl_data->wglShareLists(share_context, context);
641  }
642  } else {
643  PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
644  HGLRC temp_context = _this->gl_data->wglCreateContext(hdc);
645  if (!temp_context) {
646  SDL_SetError("Could not create GL context");
647  return NULL;
648  }
649 
650  /* Make the context current */
651  if (WIN_GL_MakeCurrent(_this, window, temp_context) < 0) {
652  WIN_GL_DeleteContext(_this, temp_context);
653  return NULL;
654  }
655 
656  wglCreateContextAttribsARB =
657  (PFNWGLCREATECONTEXTATTRIBSARBPROC) _this->gl_data->
658  wglGetProcAddress("wglCreateContextAttribsARB");
659  if (!wglCreateContextAttribsARB) {
660  SDL_SetError("GL 3.x is not supported");
661  context = temp_context;
662  } else {
663  /* max 10 attributes plus terminator */
664  int attribs[11] = {
665  WGL_CONTEXT_MAJOR_VERSION_ARB, _this->gl_config.major_version,
666  WGL_CONTEXT_MINOR_VERSION_ARB, _this->gl_config.minor_version,
667  0
668  };
669  int iattr = 4;
670 
671  /* SDL profile bits match WGL profile bits */
672  if (_this->gl_config.profile_mask != 0) {
673  attribs[iattr++] = WGL_CONTEXT_PROFILE_MASK_ARB;
674  attribs[iattr++] = _this->gl_config.profile_mask;
675  }
676 
677  /* SDL flags match WGL flags */
678  if (_this->gl_config.flags != 0) {
679  attribs[iattr++] = WGL_CONTEXT_FLAGS_ARB;
680  attribs[iattr++] = _this->gl_config.flags;
681  }
682 
683  /* only set if wgl extension is available */
684  if (_this->gl_data->HAS_WGL_ARB_context_flush_control) {
685  attribs[iattr++] = WGL_CONTEXT_RELEASE_BEHAVIOR_ARB;
686  attribs[iattr++] = _this->gl_config.release_behavior ?
687  WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB :
688  WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB;
689  }
690 
691  attribs[iattr++] = 0;
692 
693  /* Create the GL 3.x context */
694  context = wglCreateContextAttribsARB(hdc, share_context, attribs);
695  /* Delete the GL 2.x context */
696  _this->gl_data->wglDeleteContext(temp_context);
697  }
698  }
699 
700  if (!context) {
701  WIN_SetError("Could not create GL context");
702  return NULL;
703  }
704 
705  if (WIN_GL_MakeCurrent(_this, window, context) < 0) {
706  WIN_GL_DeleteContext(_this, context);
707  return NULL;
708  }
709 
710  return context;
711 }
712 
713 int
714 WIN_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
715 {
716  HDC hdc;
717 
718  if (!_this->gl_data) {
719  return SDL_SetError("OpenGL not initialized");
720  }
721 
722  /* sanity check that higher level handled this. */
723  SDL_assert(window || (!window && !context));
724 
725  /* Some Windows drivers freak out if hdc is NULL, even when context is
726  NULL, against spec. Since hdc is _supposed_ to be ignored if context
727  is NULL, we either use the current GL window, or do nothing if we
728  already have no current context. */
729  if (!window) {
730  window = SDL_GL_GetCurrentWindow();
731  if (!window) {
733  return 0; /* already done. */
734  }
735  }
736 
737  hdc = ((SDL_WindowData *) window->driverdata)->hdc;
738  if (!_this->gl_data->wglMakeCurrent(hdc, (HGLRC) context)) {
739  return WIN_SetError("wglMakeCurrent()");
740  }
741  return 0;
742 }
743 
744 int
745 WIN_GL_SetSwapInterval(_THIS, int interval)
746 {
747  if ((interval < 0) && (!_this->gl_data->HAS_WGL_EXT_swap_control_tear)) {
748  return SDL_SetError("Negative swap interval unsupported in this GL");
749  } else if (_this->gl_data->wglSwapIntervalEXT) {
750  if (_this->gl_data->wglSwapIntervalEXT(interval) != TRUE) {
751  return WIN_SetError("wglSwapIntervalEXT()");
752  }
753  } else {
754  return SDL_Unsupported();
755  }
756  return 0;
757 }
758 
759 int
760 WIN_GL_GetSwapInterval(_THIS)
761 {
762  int retval = 0;
763  if (_this->gl_data->wglGetSwapIntervalEXT) {
764  retval = _this->gl_data->wglGetSwapIntervalEXT();
765  }
766  return retval;
767 }
768 
769 void
770 WIN_GL_SwapWindow(_THIS, SDL_Window * window)
771 {
772  HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc;
773 
774  SwapBuffers(hdc);
775 }
776 
777 void
778 WIN_GL_DeleteContext(_THIS, SDL_GLContext context)
779 {
780  if (!_this->gl_data) {
781  return;
782  }
783  _this->gl_data->wglDeleteContext((HGLRC) context);
784 }
785 
786 
787 SDL_bool
788 WIN_GL_SetPixelFormatFrom(_THIS, SDL_Window * fromWindow, SDL_Window * toWindow)
789 {
790  HDC hfromdc = ((SDL_WindowData *) fromWindow->driverdata)->hdc;
791  HDC htodc = ((SDL_WindowData *) toWindow->driverdata)->hdc;
792  BOOL result;
793 
794  /* get the pixel format of the fromWindow */
795  int pixel_format = GetPixelFormat(hfromdc);
796  PIXELFORMATDESCRIPTOR pfd;
797  SDL_memset(&pfd, 0, sizeof(pfd));
798  DescribePixelFormat(hfromdc, pixel_format, sizeof(pfd), &pfd);
799 
800  /* set the pixel format of the toWindow */
801  result = SetPixelFormat(htodc, pixel_format, &pfd);
802 
803  return result ? SDL_TRUE : SDL_FALSE;
804 }
805 
806 #endif /* SDL_VIDEO_OPENGL_WGL */
807 
808 #endif /* SDL_VIDEO_DRIVER_WINDOWS */
809 
810 /* vi: set ts=4 sw=4 expandtab: */
#define SDL_strlcpy
HINSTANCE SDL_Instance
const GLint * attribs
GLuint64EXT * result
#define GL_TRUE
Definition: SDL_opengl.h:193
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1564
static SDL_Window * window
int(* GL_SetSwapInterval)(_THIS, int interval)
Definition: SDL_sysvideo.h:253
LPTSTR SDL_Appname
GLuint start
Definition: SDL_opengl.h:1564
void(* GL_SwapWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:255
#define SDL_LoadObject
#define SDL_UnloadObject
#define SDL_zerop(x)
Definition: SDL_stdinc.h:360
int(* GL_LoadLibrary)(_THIS, const char *path)
Definition: SDL_sysvideo.h:247
struct SDL_GLDriverData * gl_data
Definition: SDL_sysvideo.h:346
#define SDL_strchr
static SDL_VideoDevice * _this
Definition: SDL_video.c:118
struct SDL_VideoDevice::@29 gl_config
SDL_bool retval
void * SDL_calloc(size_t nmemb, size_t size)
void * SDL_GLContext
An opaque handle to an OpenGL context.
Definition: SDL_video.h:172
SDL_GLContext(* GL_CreateContext)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:250
#define _THIS
int(* GL_MakeCurrent)(_THIS, SDL_Window *window, SDL_GLContext context)
Definition: SDL_sysvideo.h:251
void SDL_free(void *mem)
GLenum target
#define TRUE
Definition: edid-parse.c:33
char driver_path[256]
Definition: SDL_sysvideo.h:329
#define APIENTRYP
Definition: SDL_opengl.h:137
int framebuffer_srgb_capable
Definition: SDL_sysvideo.h:326
GLuint index
#define SDL_getenv
void(* GL_UnloadLibrary)(_THIS)
Definition: SDL_sysvideo.h:249
int share_with_current_context
Definition: SDL_sysvideo.h:324
#define SDL_assert(condition)
Definition: SDL_assert.h:167
#define NULL
Definition: begin_code.h:143
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:130
#define SDL_GL_GetCurrentContext
int WIN_SetError(const char *prefix)
#define SDL_SetError
#define SDL_GL_GetCurrentWindow
void WIN_PumpEvents(_THIS)
GLenum func
#define SDL_strlen
The type used to identify a window.
Definition: SDL_sysvideo.h:71
Uint32 pixel_format
Definition: testoverlay2.c:152
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:90
GLsizei const GLchar *const * path
void * SDL_LoadFunction(void *handle, const char *name)
void * driverdata
Definition: SDL_sysvideo.h:109
void(* GL_DeleteContext)(_THIS, SDL_GLContext context)
Definition: SDL_sysvideo.h:256
EGLContext context
Definition: SDL_pspgl_c.h:34
int(* GL_GetSwapInterval)(_THIS)
Definition: SDL_sysvideo.h:254
#define SDL_Unsupported()
Definition: SDL_error.h:53
void *(* GL_GetProcAddress)(_THIS, const char *proc)
Definition: SDL_sysvideo.h:248
#define SDL_memset
#define SDL_strstr