SDL  2.0
SDL_windowsopengl.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2018 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 #include "SDL_hints.h"
30 
31 /* WGL implementation of SDL OpenGL support */
32 
33 #if SDL_VIDEO_OPENGL_WGL
34 #include "SDL_opengl.h"
35 
36 #define DEFAULT_OPENGL "OPENGL32.DLL"
37 
38 #ifndef WGL_ARB_create_context
39 #define WGL_ARB_create_context
40 #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
41 #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
42 #define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
43 #define WGL_CONTEXT_FLAGS_ARB 0x2094
44 #define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
45 #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
46 
47 #ifndef WGL_ARB_create_context_profile
48 #define WGL_ARB_create_context_profile
49 #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
50 #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
51 #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
52 #endif
53 
54 #ifndef WGL_ARB_create_context_robustness
55 #define WGL_ARB_create_context_robustness
56 #define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
57 #define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
58 #define WGL_NO_RESET_NOTIFICATION_ARB 0x8261
59 #define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
60 #endif
61 #endif
62 
63 #ifndef WGL_EXT_create_context_es2_profile
64 #define WGL_EXT_create_context_es2_profile
65 #define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
66 #endif
67 
68 #ifndef WGL_EXT_create_context_es_profile
69 #define WGL_EXT_create_context_es_profile
70 #define WGL_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004
71 #endif
72 
73 #ifndef WGL_ARB_framebuffer_sRGB
74 #define WGL_ARB_framebuffer_sRGB
75 #define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9
76 #endif
77 
78 #ifndef WGL_ARB_context_flush_control
79 #define WGL_ARB_context_flush_control
80 #define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
81 #define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0x0000
82 #define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
83 #endif
84 
85 #ifndef WGL_ARB_create_context_no_error
86 #define WGL_ARB_create_context_no_error
87 #define WGL_CONTEXT_OPENGL_NO_ERROR_ARB 0x31B3
88 #endif
89 
90 typedef HGLRC(APIENTRYP PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC,
91  HGLRC
92  hShareContext,
93  const int
94  *attribList);
95 
96 int
97 WIN_GL_LoadLibrary(_THIS, const char *path)
98 {
99  void *handle;
100 
101  if (path == NULL) {
102  path = SDL_getenv("SDL_OPENGL_LIBRARY");
103  }
104  if (path == NULL) {
105  path = DEFAULT_OPENGL;
106  }
108  if (!_this->gl_config.dll_handle) {
109  return -1;
110  }
113 
114  /* Allocate OpenGL memory */
115  _this->gl_data = (struct SDL_GLDriverData *) SDL_calloc(1, sizeof(struct SDL_GLDriverData));
116  if (!_this->gl_data) {
117  return SDL_OutOfMemory();
118  }
119 
120  /* Load function pointers */
121  handle = _this->gl_config.dll_handle;
122  _this->gl_data->wglGetProcAddress = (void *(WINAPI *) (const char *))
123  SDL_LoadFunction(handle, "wglGetProcAddress");
124  _this->gl_data->wglCreateContext = (HGLRC(WINAPI *) (HDC))
125  SDL_LoadFunction(handle, "wglCreateContext");
126  _this->gl_data->wglDeleteContext = (BOOL(WINAPI *) (HGLRC))
127  SDL_LoadFunction(handle, "wglDeleteContext");
128  _this->gl_data->wglMakeCurrent = (BOOL(WINAPI *) (HDC, HGLRC))
129  SDL_LoadFunction(handle, "wglMakeCurrent");
130  _this->gl_data->wglShareLists = (BOOL(WINAPI *) (HGLRC, HGLRC))
131  SDL_LoadFunction(handle, "wglShareLists");
132 
133  if (!_this->gl_data->wglGetProcAddress ||
134  !_this->gl_data->wglCreateContext ||
135  !_this->gl_data->wglDeleteContext ||
136  !_this->gl_data->wglMakeCurrent) {
137  return SDL_SetError("Could not retrieve OpenGL functions");
138  }
139 
140  /* XXX Too sleazy? WIN_GL_InitExtensions looks for certain OpenGL
141  extensions via SDL_GL_DeduceMaxSupportedESProfile. This uses
142  SDL_GL_ExtensionSupported which in turn calls SDL_GL_GetProcAddress.
143  However SDL_GL_GetProcAddress will fail if the library is not
144  loaded; it checks for gl_config.driver_loaded > 0. To avoid this
145  test failing, increment driver_loaded around the call to
146  WIN_GLInitExtensions.
147 
148  Successful loading of the library is normally indicated by
149  SDL_GL_LoadLibrary incrementing driver_loaded immediately after
150  this function returns 0 to it.
151 
152  Alternatives to this are:
153  - moving SDL_GL_DeduceMaxSupportedESProfile to both the WIN and
154  X11 platforms while adding a function equivalent to
155  SDL_GL_ExtensionSupported but which directly calls
156  glGetProcAddress(). Having 3 copies of the
157  SDL_GL_ExtensionSupported makes this alternative unattractive.
158  - moving SDL_GL_DeduceMaxSupportedESProfile to a new file shared
159  by the WIN and X11 platforms while adding a function equivalent
160  to SDL_GL_ExtensionSupported. This is unattractive due to the
161  number of project files that will need updating, plus there
162  will be 2 copies of the SDL_GL_ExtensionSupported code.
163  - Add a private equivalent of SDL_GL_ExtensionSupported to
164  SDL_video.c.
165  - Move the call to WIN_GL_InitExtensions back to WIN_CreateWindow
166  and add a flag to gl_data to avoid multiple calls to this
167  expensive function. This is probably the least objectionable
168  alternative if this increment/decrement trick is unacceptable.
169 
170  Note that the driver_loaded > 0 check needs to remain in
171  SDL_GL_ExtensionSupported and SDL_GL_GetProcAddress as they are
172  public API functions.
173  */
175  WIN_GL_InitExtensions(_this);
177 
178  return 0;
179 }
180 
181 void *
182 WIN_GL_GetProcAddress(_THIS, const char *proc)
183 {
184  void *func;
185 
186  /* This is to pick up extensions */
187  func = _this->gl_data->wglGetProcAddress(proc);
188  if (!func) {
189  /* This is probably a normal GL function */
190  func = GetProcAddress(_this->gl_config.dll_handle, proc);
191  }
192  return func;
193 }
194 
195 void
196 WIN_GL_UnloadLibrary(_THIS)
197 {
200 
201  /* Free OpenGL memory */
203  _this->gl_data = NULL;
204 }
205 
206 static void
207 WIN_GL_SetupPixelFormat(_THIS, PIXELFORMATDESCRIPTOR * pfd)
208 {
209  SDL_zerop(pfd);
210  pfd->nSize = sizeof(*pfd);
211  pfd->nVersion = 1;
212  pfd->dwFlags = (PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL);
214  pfd->dwFlags |= PFD_DOUBLEBUFFER;
215  }
216  if (_this->gl_config.stereo) {
217  pfd->dwFlags |= PFD_STEREO;
218  }
219  pfd->iLayerType = PFD_MAIN_PLANE;
220  pfd->iPixelType = PFD_TYPE_RGBA;
221  pfd->cRedBits = _this->gl_config.red_size;
222  pfd->cGreenBits = _this->gl_config.green_size;
223  pfd->cBlueBits = _this->gl_config.blue_size;
224  pfd->cAlphaBits = _this->gl_config.alpha_size;
225  if (_this->gl_config.buffer_size) {
226  pfd->cColorBits =
228  } else {
229  pfd->cColorBits = (pfd->cRedBits + pfd->cGreenBits + pfd->cBlueBits);
230  }
231  pfd->cAccumRedBits = _this->gl_config.accum_red_size;
232  pfd->cAccumGreenBits = _this->gl_config.accum_green_size;
233  pfd->cAccumBlueBits = _this->gl_config.accum_blue_size;
234  pfd->cAccumAlphaBits = _this->gl_config.accum_alpha_size;
235  pfd->cAccumBits =
236  (pfd->cAccumRedBits + pfd->cAccumGreenBits + pfd->cAccumBlueBits +
237  pfd->cAccumAlphaBits);
238  pfd->cDepthBits = _this->gl_config.depth_size;
239  pfd->cStencilBits = _this->gl_config.stencil_size;
240 }
241 
242 /* Choose the closest pixel format that meets or exceeds the target.
243  FIXME: Should we weight any particular attribute over any other?
244 */
245 static int
246 WIN_GL_ChoosePixelFormat(HDC hdc, PIXELFORMATDESCRIPTOR * target)
247 {
248  PIXELFORMATDESCRIPTOR pfd;
249  int count, index, best = 0;
250  unsigned int dist, best_dist = ~0U;
251 
252  count = DescribePixelFormat(hdc, 1, sizeof(pfd), NULL);
253 
254  for (index = 1; index <= count; index++) {
255 
256  if (!DescribePixelFormat(hdc, index, sizeof(pfd), &pfd)) {
257  continue;
258  }
259 
260  if ((pfd.dwFlags & target->dwFlags) != target->dwFlags) {
261  continue;
262  }
263 
264  if (pfd.iLayerType != target->iLayerType) {
265  continue;
266  }
267  if (pfd.iPixelType != target->iPixelType) {
268  continue;
269  }
270 
271  dist = 0;
272 
273  if (pfd.cColorBits < target->cColorBits) {
274  continue;
275  } else {
276  dist += (pfd.cColorBits - target->cColorBits);
277  }
278  if (pfd.cRedBits < target->cRedBits) {
279  continue;
280  } else {
281  dist += (pfd.cRedBits - target->cRedBits);
282  }
283  if (pfd.cGreenBits < target->cGreenBits) {
284  continue;
285  } else {
286  dist += (pfd.cGreenBits - target->cGreenBits);
287  }
288  if (pfd.cBlueBits < target->cBlueBits) {
289  continue;
290  } else {
291  dist += (pfd.cBlueBits - target->cBlueBits);
292  }
293  if (pfd.cAlphaBits < target->cAlphaBits) {
294  continue;
295  } else {
296  dist += (pfd.cAlphaBits - target->cAlphaBits);
297  }
298  if (pfd.cAccumBits < target->cAccumBits) {
299  continue;
300  } else {
301  dist += (pfd.cAccumBits - target->cAccumBits);
302  }
303  if (pfd.cAccumRedBits < target->cAccumRedBits) {
304  continue;
305  } else {
306  dist += (pfd.cAccumRedBits - target->cAccumRedBits);
307  }
308  if (pfd.cAccumGreenBits < target->cAccumGreenBits) {
309  continue;
310  } else {
311  dist += (pfd.cAccumGreenBits - target->cAccumGreenBits);
312  }
313  if (pfd.cAccumBlueBits < target->cAccumBlueBits) {
314  continue;
315  } else {
316  dist += (pfd.cAccumBlueBits - target->cAccumBlueBits);
317  }
318  if (pfd.cAccumAlphaBits < target->cAccumAlphaBits) {
319  continue;
320  } else {
321  dist += (pfd.cAccumAlphaBits - target->cAccumAlphaBits);
322  }
323  if (pfd.cDepthBits < target->cDepthBits) {
324  continue;
325  } else {
326  dist += (pfd.cDepthBits - target->cDepthBits);
327  }
328  if (pfd.cStencilBits < target->cStencilBits) {
329  continue;
330  } else {
331  dist += (pfd.cStencilBits - target->cStencilBits);
332  }
333 
334  if (dist < best_dist) {
335  best = index;
336  best_dist = dist;
337  }
338  }
339 
340  return best;
341 }
342 
343 static SDL_bool
344 HasExtension(const char *extension, const char *extensions)
345 {
346  const char *start;
347  const char *where, *terminator;
348 
349  /* Extension names should not have spaces. */
350  where = SDL_strchr(extension, ' ');
351  if (where || *extension == '\0')
352  return SDL_FALSE;
353 
354  if (!extensions)
355  return SDL_FALSE;
356 
357  /* It takes a bit of care to be fool-proof about parsing the
358  * OpenGL extensions string. Don't be fooled by sub-strings,
359  * etc. */
360 
361  start = extensions;
362 
363  for (;;) {
364  where = SDL_strstr(start, extension);
365  if (!where)
366  break;
367 
368  terminator = where + SDL_strlen(extension);
369  if (where == start || *(where - 1) == ' ')
370  if (*terminator == ' ' || *terminator == '\0')
371  return SDL_TRUE;
372 
373  start = terminator;
374  }
375  return SDL_FALSE;
376 }
377 
378 void
379 WIN_GL_InitExtensions(_THIS)
380 {
381  const char *(WINAPI * wglGetExtensionsStringARB) (HDC) = 0;
382  const char *extensions;
383  HWND hwnd;
384  HDC hdc;
385  HGLRC hglrc;
386  PIXELFORMATDESCRIPTOR pfd;
387 
388  if (!_this->gl_data) {
389  return;
390  }
391 
392  hwnd =
393  CreateWindow(SDL_Appname, SDL_Appname, (WS_POPUP | WS_DISABLED), 0, 0,
394  10, 10, NULL, NULL, SDL_Instance, NULL);
395  if (!hwnd) {
396  return;
397  }
399 
400  hdc = GetDC(hwnd);
401 
402  WIN_GL_SetupPixelFormat(_this, &pfd);
403 
404  SetPixelFormat(hdc, ChoosePixelFormat(hdc, &pfd), &pfd);
405 
406  hglrc = _this->gl_data->wglCreateContext(hdc);
407  if (!hglrc) {
408  return;
409  }
410  _this->gl_data->wglMakeCurrent(hdc, hglrc);
411 
412  wglGetExtensionsStringARB = (const char *(WINAPI *) (HDC))
413  _this->gl_data->wglGetProcAddress("wglGetExtensionsStringARB");
414  if (wglGetExtensionsStringARB) {
415  extensions = wglGetExtensionsStringARB(hdc);
416  } else {
417  extensions = NULL;
418  }
419 
420  /* Check for WGL_ARB_pixel_format */
421  _this->gl_data->HAS_WGL_ARB_pixel_format = SDL_FALSE;
422  if (HasExtension("WGL_ARB_pixel_format", extensions)) {
423  _this->gl_data->wglChoosePixelFormatARB = (BOOL(WINAPI *)
424  (HDC, const int *,
425  const FLOAT *, UINT,
426  int *, UINT *))
427  WIN_GL_GetProcAddress(_this, "wglChoosePixelFormatARB");
428  _this->gl_data->wglGetPixelFormatAttribivARB =
429  (BOOL(WINAPI *) (HDC, int, int, UINT, const int *, int *))
430  WIN_GL_GetProcAddress(_this, "wglGetPixelFormatAttribivARB");
431 
432  if ((_this->gl_data->wglChoosePixelFormatARB != NULL) &&
433  (_this->gl_data->wglGetPixelFormatAttribivARB != NULL)) {
434  _this->gl_data->HAS_WGL_ARB_pixel_format = SDL_TRUE;
435  }
436  }
437 
438  /* Check for WGL_EXT_swap_control */
439  _this->gl_data->HAS_WGL_EXT_swap_control_tear = SDL_FALSE;
440  if (HasExtension("WGL_EXT_swap_control", extensions)) {
441  _this->gl_data->wglSwapIntervalEXT =
442  WIN_GL_GetProcAddress(_this, "wglSwapIntervalEXT");
443  _this->gl_data->wglGetSwapIntervalEXT =
444  WIN_GL_GetProcAddress(_this, "wglGetSwapIntervalEXT");
445  if (HasExtension("WGL_EXT_swap_control_tear", extensions)) {
446  _this->gl_data->HAS_WGL_EXT_swap_control_tear = SDL_TRUE;
447  }
448  } else {
449  _this->gl_data->wglSwapIntervalEXT = NULL;
450  _this->gl_data->wglGetSwapIntervalEXT = NULL;
451  }
452 
453  /* Check for WGL_EXT_create_context_es2_profile */
454  if (HasExtension("WGL_EXT_create_context_es2_profile", extensions)) {
456  &_this->gl_data->es_profile_max_supported_version.major,
457  &_this->gl_data->es_profile_max_supported_version.minor
458  );
459  }
460 
461  /* Check for WGL_ARB_context_flush_control */
462  if (HasExtension("WGL_ARB_context_flush_control", extensions)) {
463  _this->gl_data->HAS_WGL_ARB_context_flush_control = SDL_TRUE;
464  }
465 
466  /* Check for WGL_ARB_create_context_robustness */
467  if (HasExtension("WGL_ARB_create_context_robustness", extensions)) {
468  _this->gl_data->HAS_WGL_ARB_create_context_robustness = SDL_TRUE;
469  }
470 
471  /* Check for WGL_ARB_create_context_no_error */
472  if (HasExtension("WGL_ARB_create_context_no_error", extensions)) {
473  _this->gl_data->HAS_WGL_ARB_create_context_no_error = SDL_TRUE;
474  }
475 
476  _this->gl_data->wglMakeCurrent(hdc, NULL);
477  _this->gl_data->wglDeleteContext(hglrc);
478  ReleaseDC(hwnd, hdc);
479  DestroyWindow(hwnd);
481 }
482 
483 static int
484 WIN_GL_ChoosePixelFormatARB(_THIS, int *iAttribs, float *fAttribs)
485 {
486  HWND hwnd;
487  HDC hdc;
488  PIXELFORMATDESCRIPTOR pfd;
489  HGLRC hglrc;
490  int pixel_format = 0;
491  unsigned int matching;
492 
493  hwnd =
494  CreateWindow(SDL_Appname, SDL_Appname, (WS_POPUP | WS_DISABLED), 0, 0,
495  10, 10, NULL, NULL, SDL_Instance, NULL);
497 
498  hdc = GetDC(hwnd);
499 
500  WIN_GL_SetupPixelFormat(_this, &pfd);
501 
502  SetPixelFormat(hdc, ChoosePixelFormat(hdc, &pfd), &pfd);
503 
504  hglrc = _this->gl_data->wglCreateContext(hdc);
505  if (hglrc) {
506  _this->gl_data->wglMakeCurrent(hdc, hglrc);
507 
508  if (_this->gl_data->HAS_WGL_ARB_pixel_format) {
509  _this->gl_data->wglChoosePixelFormatARB(hdc, iAttribs, fAttribs,
510  1, &pixel_format,
511  &matching);
512  }
513 
514  _this->gl_data->wglMakeCurrent(hdc, NULL);
515  _this->gl_data->wglDeleteContext(hglrc);
516  }
517  ReleaseDC(hwnd, hdc);
518  DestroyWindow(hwnd);
520 
521  return pixel_format;
522 }
523 
524 /* actual work of WIN_GL_SetupWindow() happens here. */
525 static int
526 WIN_GL_SetupWindowInternal(_THIS, SDL_Window * window)
527 {
528  HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc;
529  PIXELFORMATDESCRIPTOR pfd;
530  int pixel_format = 0;
531  int iAttribs[64];
532  int *iAttr;
533  int *iAccelAttr;
534  float fAttribs[1] = { 0 };
535 
536  WIN_GL_SetupPixelFormat(_this, &pfd);
537 
538  /* setup WGL_ARB_pixel_format attribs */
539  iAttr = &iAttribs[0];
540 
541  *iAttr++ = WGL_DRAW_TO_WINDOW_ARB;
542  *iAttr++ = GL_TRUE;
543  *iAttr++ = WGL_RED_BITS_ARB;
544  *iAttr++ = _this->gl_config.red_size;
545  *iAttr++ = WGL_GREEN_BITS_ARB;
546  *iAttr++ = _this->gl_config.green_size;
547  *iAttr++ = WGL_BLUE_BITS_ARB;
548  *iAttr++ = _this->gl_config.blue_size;
549 
550  if (_this->gl_config.alpha_size) {
551  *iAttr++ = WGL_ALPHA_BITS_ARB;
552  *iAttr++ = _this->gl_config.alpha_size;
553  }
554 
555  *iAttr++ = WGL_DOUBLE_BUFFER_ARB;
556  *iAttr++ = _this->gl_config.double_buffer;
557 
558  *iAttr++ = WGL_DEPTH_BITS_ARB;
559  *iAttr++ = _this->gl_config.depth_size;
560 
562  *iAttr++ = WGL_STENCIL_BITS_ARB;
563  *iAttr++ = _this->gl_config.stencil_size;
564  }
565 
567  *iAttr++ = WGL_ACCUM_RED_BITS_ARB;
568  *iAttr++ = _this->gl_config.accum_red_size;
569  }
570 
572  *iAttr++ = WGL_ACCUM_GREEN_BITS_ARB;
573  *iAttr++ = _this->gl_config.accum_green_size;
574  }
575 
577  *iAttr++ = WGL_ACCUM_BLUE_BITS_ARB;
578  *iAttr++ = _this->gl_config.accum_blue_size;
579  }
580 
582  *iAttr++ = WGL_ACCUM_ALPHA_BITS_ARB;
583  *iAttr++ = _this->gl_config.accum_alpha_size;
584  }
585 
586  if (_this->gl_config.stereo) {
587  *iAttr++ = WGL_STEREO_ARB;
588  *iAttr++ = GL_TRUE;
589  }
590 
592  *iAttr++ = WGL_SAMPLE_BUFFERS_ARB;
593  *iAttr++ = _this->gl_config.multisamplebuffers;
594  }
595 
597  *iAttr++ = WGL_SAMPLES_ARB;
598  *iAttr++ = _this->gl_config.multisamplesamples;
599  }
600 
602  *iAttr++ = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB;
604  }
605 
606  /* We always choose either FULL or NO accel on Windows, because of flaky
607  drivers. If the app didn't specify, we use FULL, because that's
608  probably what they wanted (and if you didn't care and got FULL, that's
609  a perfectly valid result in any case). */
610  *iAttr++ = WGL_ACCELERATION_ARB;
611  iAccelAttr = iAttr;
612  if (_this->gl_config.accelerated) {
613  *iAttr++ = WGL_FULL_ACCELERATION_ARB;
614  } else {
615  *iAttr++ = WGL_NO_ACCELERATION_ARB;
616  }
617 
618  *iAttr = 0;
619 
620  /* Choose and set the closest available pixel format */
621  pixel_format = WIN_GL_ChoosePixelFormatARB(_this, iAttribs, fAttribs);
622 
623  /* App said "don't care about accel" and FULL accel failed. Try NO. */
624  if ( ( !pixel_format ) && ( _this->gl_config.accelerated < 0 ) ) {
625  *iAccelAttr = WGL_NO_ACCELERATION_ARB;
626  pixel_format = WIN_GL_ChoosePixelFormatARB(_this, iAttribs, fAttribs);
627  *iAccelAttr = WGL_FULL_ACCELERATION_ARB; /* if we try again. */
628  }
629  if (!pixel_format) {
630  pixel_format = WIN_GL_ChoosePixelFormat(hdc, &pfd);
631  }
632  if (!pixel_format) {
633  return SDL_SetError("No matching GL pixel format available");
634  }
635  if (!SetPixelFormat(hdc, pixel_format, &pfd)) {
636  return WIN_SetError("SetPixelFormat()");
637  }
638  return 0;
639 }
640 
641 int
642 WIN_GL_SetupWindow(_THIS, SDL_Window * window)
643 {
644  /* The current context is lost in here; save it and reset it. */
645  SDL_Window *current_win = SDL_GL_GetCurrentWindow();
646  SDL_GLContext current_ctx = SDL_GL_GetCurrentContext();
647  const int retval = WIN_GL_SetupWindowInternal(_this, window);
648  WIN_GL_MakeCurrent(_this, current_win, current_ctx);
649  return retval;
650 }
651 
652 SDL_bool
653 WIN_GL_UseEGL(_THIS)
654 {
657 
659  || _this->gl_config.major_version == 1 /* No WGL extension for OpenGL ES 1.x profiles. */
660  || _this->gl_config.major_version > _this->gl_data->es_profile_max_supported_version.major
661  || (_this->gl_config.major_version == _this->gl_data->es_profile_max_supported_version.major
662  && _this->gl_config.minor_version > _this->gl_data->es_profile_max_supported_version.minor));
663 }
664 
666 WIN_GL_CreateContext(_THIS, SDL_Window * window)
667 {
668  HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc;
669  HGLRC context, share_context;
670 
671  if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES && WIN_GL_UseEGL(_this)) {
672 #if SDL_VIDEO_OPENGL_EGL
673  /* Switch to EGL based functions */
674  WIN_GL_UnloadLibrary(_this);
675  _this->GL_LoadLibrary = WIN_GLES_LoadLibrary;
676  _this->GL_GetProcAddress = WIN_GLES_GetProcAddress;
677  _this->GL_UnloadLibrary = WIN_GLES_UnloadLibrary;
678  _this->GL_CreateContext = WIN_GLES_CreateContext;
679  _this->GL_MakeCurrent = WIN_GLES_MakeCurrent;
680  _this->GL_SetSwapInterval = WIN_GLES_SetSwapInterval;
681  _this->GL_GetSwapInterval = WIN_GLES_GetSwapInterval;
682  _this->GL_SwapWindow = WIN_GLES_SwapWindow;
683  _this->GL_DeleteContext = WIN_GLES_DeleteContext;
684 
685  if (WIN_GLES_LoadLibrary(_this, NULL) != 0) {
686  return NULL;
687  }
688 
689  return WIN_GLES_CreateContext(_this, window);
690 #else
691  SDL_SetError("SDL not configured with EGL support");
692  return NULL;
693 #endif
694  }
695 
697  share_context = (HGLRC)SDL_GL_GetCurrentContext();
698  } else {
699  share_context = 0;
700  }
701 
702  if (_this->gl_config.major_version < 3 &&
703  _this->gl_config.profile_mask == 0 &&
704  _this->gl_config.flags == 0) {
705  /* Create legacy context */
706  context = _this->gl_data->wglCreateContext(hdc);
707  if( share_context != 0 ) {
708  _this->gl_data->wglShareLists(share_context, context);
709  }
710  } else {
711  PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
712  HGLRC temp_context = _this->gl_data->wglCreateContext(hdc);
713  if (!temp_context) {
714  SDL_SetError("Could not create GL context");
715  return NULL;
716  }
717 
718  /* Make the context current */
719  if (WIN_GL_MakeCurrent(_this, window, temp_context) < 0) {
720  WIN_GL_DeleteContext(_this, temp_context);
721  return NULL;
722  }
723 
724  wglCreateContextAttribsARB =
725  (PFNWGLCREATECONTEXTATTRIBSARBPROC) _this->gl_data->
726  wglGetProcAddress("wglCreateContextAttribsARB");
727  if (!wglCreateContextAttribsARB) {
728  SDL_SetError("GL 3.x is not supported");
729  context = temp_context;
730  } else {
731  int attribs[15]; /* max 14 attributes plus terminator */
732  int iattr = 0;
733 
734  attribs[iattr++] = WGL_CONTEXT_MAJOR_VERSION_ARB;
735  attribs[iattr++] = _this->gl_config.major_version;
736  attribs[iattr++] = WGL_CONTEXT_MINOR_VERSION_ARB;
737  attribs[iattr++] = _this->gl_config.minor_version;
738 
739  /* SDL profile bits match WGL profile bits */
740  if (_this->gl_config.profile_mask != 0) {
741  attribs[iattr++] = WGL_CONTEXT_PROFILE_MASK_ARB;
742  attribs[iattr++] = _this->gl_config.profile_mask;
743  }
744 
745  /* SDL flags match WGL flags */
746  if (_this->gl_config.flags != 0) {
747  attribs[iattr++] = WGL_CONTEXT_FLAGS_ARB;
748  attribs[iattr++] = _this->gl_config.flags;
749  }
750 
751  /* only set if wgl extension is available */
752  if (_this->gl_data->HAS_WGL_ARB_context_flush_control) {
753  attribs[iattr++] = WGL_CONTEXT_RELEASE_BEHAVIOR_ARB;
754  attribs[iattr++] = _this->gl_config.release_behavior ?
755  WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB :
756  WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB;
757  }
758 
759  /* only set if wgl extension is available */
760  if (_this->gl_data->HAS_WGL_ARB_create_context_robustness) {
761  attribs[iattr++] = WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB;
762  attribs[iattr++] = _this->gl_config.reset_notification ?
763  WGL_LOSE_CONTEXT_ON_RESET_ARB :
764  WGL_NO_RESET_NOTIFICATION_ARB;
765  }
766 
767  /* only set if wgl extension is available */
768  if (_this->gl_data->HAS_WGL_ARB_create_context_no_error) {
769  attribs[iattr++] = WGL_CONTEXT_OPENGL_NO_ERROR_ARB;
770  attribs[iattr++] = _this->gl_config.no_error;
771  }
772 
773  attribs[iattr++] = 0;
774 
775  /* Create the GL 3.x context */
776  context = wglCreateContextAttribsARB(hdc, share_context, attribs);
777  /* Delete the GL 2.x context */
778  _this->gl_data->wglDeleteContext(temp_context);
779  }
780  }
781 
782  if (!context) {
783  WIN_SetError("Could not create GL context");
784  return NULL;
785  }
786 
787  if (WIN_GL_MakeCurrent(_this, window, context) < 0) {
788  WIN_GL_DeleteContext(_this, context);
789  return NULL;
790  }
791 
792  return context;
793 }
794 
795 int
796 WIN_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
797 {
798  HDC hdc;
799 
800  if (!_this->gl_data) {
801  return SDL_SetError("OpenGL not initialized");
802  }
803 
804  /* sanity check that higher level handled this. */
805  SDL_assert(window || (!window && !context));
806 
807  /* Some Windows drivers freak out if hdc is NULL, even when context is
808  NULL, against spec. Since hdc is _supposed_ to be ignored if context
809  is NULL, we either use the current GL window, or do nothing if we
810  already have no current context. */
811  if (!window) {
812  window = SDL_GL_GetCurrentWindow();
813  if (!window) {
815  return 0; /* already done. */
816  }
817  }
818 
819  hdc = ((SDL_WindowData *) window->driverdata)->hdc;
820  if (!_this->gl_data->wglMakeCurrent(hdc, (HGLRC) context)) {
821  return WIN_SetError("wglMakeCurrent()");
822  }
823  return 0;
824 }
825 
826 int
827 WIN_GL_SetSwapInterval(_THIS, int interval)
828 {
829  if ((interval < 0) && (!_this->gl_data->HAS_WGL_EXT_swap_control_tear)) {
830  return SDL_SetError("Negative swap interval unsupported in this GL");
831  } else if (_this->gl_data->wglSwapIntervalEXT) {
832  if (_this->gl_data->wglSwapIntervalEXT(interval) != TRUE) {
833  return WIN_SetError("wglSwapIntervalEXT()");
834  }
835  } else {
836  return SDL_Unsupported();
837  }
838  return 0;
839 }
840 
841 int
842 WIN_GL_GetSwapInterval(_THIS)
843 {
844  int retval = 0;
845  if (_this->gl_data->wglGetSwapIntervalEXT) {
846  retval = _this->gl_data->wglGetSwapIntervalEXT();
847  }
848  return retval;
849 }
850 
851 int
852 WIN_GL_SwapWindow(_THIS, SDL_Window * window)
853 {
854  HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc;
855 
856  if (!SwapBuffers(hdc)) {
857  return WIN_SetError("SwapBuffers()");
858  }
859  return 0;
860 }
861 
862 void
863 WIN_GL_DeleteContext(_THIS, SDL_GLContext context)
864 {
865  if (!_this->gl_data) {
866  return;
867  }
868  _this->gl_data->wglDeleteContext((HGLRC) context);
869 }
870 
871 
872 SDL_bool
873 WIN_GL_SetPixelFormatFrom(_THIS, SDL_Window * fromWindow, SDL_Window * toWindow)
874 {
875  HDC hfromdc = ((SDL_WindowData *) fromWindow->driverdata)->hdc;
876  HDC htodc = ((SDL_WindowData *) toWindow->driverdata)->hdc;
877  BOOL result;
878 
879  /* get the pixel format of the fromWindow */
880  int pixel_format = GetPixelFormat(hfromdc);
881  PIXELFORMATDESCRIPTOR pfd;
882  SDL_memset(&pfd, 0, sizeof(pfd));
883  DescribePixelFormat(hfromdc, pixel_format, sizeof(pfd), &pfd);
884 
885  /* set the pixel format of the toWindow */
886  result = SetPixelFormat(htodc, pixel_format, &pfd);
887 
888  return result ? SDL_TRUE : SDL_FALSE;
889 }
890 
891 #endif /* SDL_VIDEO_OPENGL_WGL */
892 
893 #endif /* SDL_VIDEO_DRIVER_WINDOWS */
894 
895 /* 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:200
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1571
int(* GL_SetSwapInterval)(_THIS, int interval)
Definition: SDL_sysvideo.h:260
static screen_context_t context
Definition: video.c:25
LPTSTR SDL_Appname
GLuint start
Definition: SDL_opengl.h:1571
#define SDL_LoadObject
#define SDL_UnloadObject
#define SDL_zerop(x)
Definition: SDL_stdinc.h:417
int(* GL_LoadLibrary)(_THIS, const char *path)
Definition: SDL_sysvideo.h:254
struct SDL_GLDriverData * gl_data
Definition: SDL_sysvideo.h:378
#define SDL_strchr
#define SDL_GetHintBoolean
#define SDL_HINT_OPENGL_ES_DRIVER
A variable controlling what driver to use for OpenGL ES contexts.
Definition: SDL_hints.h:892
static SDL_VideoDevice * _this
Definition: SDL_video.c:121
SDL_bool retval
void * SDL_GLContext
An opaque handle to an OpenGL context.
Definition: SDL_video.h:175
SDL_GLContext(* GL_CreateContext)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:257
EGLImageKHR EGLint EGLint * handle
Definition: eglext.h:937
#define _THIS
int(* GL_MakeCurrent)(_THIS, SDL_Window *window, SDL_GLContext context)
Definition: SDL_sysvideo.h:258
#define SDL_free
#define TRUE
Definition: edid-parse.c:33
char driver_path[256]
Definition: SDL_sysvideo.h:350
void SDL_GL_DeduceMaxSupportedESProfile(int *major, int *minor)
Definition: SDL_video.c:2942
#define APIENTRYP
Definition: SDL_opengl.h:144
int framebuffer_srgb_capable
Definition: SDL_sysvideo.h:346
GLuint index
#define SDL_getenv
void(* GL_UnloadLibrary)(_THIS)
Definition: SDL_sysvideo.h:256
int share_with_current_context
Definition: SDL_sysvideo.h:343
#define SDL_assert(condition)
Definition: SDL_assert.h:169
GLenum target
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:139
#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_calloc
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
int(* GL_SwapWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:262
#define SDL_strlen
The type used to identify a window.
Definition: SDL_sysvideo.h:73
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:93
GLsizei const GLchar *const * path
struct SDL_VideoDevice::@34 gl_config
void * SDL_LoadFunction(void *handle, const char *name)
void * driverdata
Definition: SDL_sysvideo.h:111
void(* GL_DeleteContext)(_THIS, SDL_GLContext context)
Definition: SDL_sysvideo.h:263
int(* GL_GetSwapInterval)(_THIS)
Definition: SDL_sysvideo.h:261
#define SDL_Unsupported()
Definition: SDL_error.h:53
void *(* GL_GetProcAddress)(_THIS, const char *proc)
Definition: SDL_sysvideo.h:255
#define SDL_memset
#define SDL_strstr