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
WIN_GL_LoadLibrary(_THIS,const char * path)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 }
101 _this->gl_config.dll_handle = SDL_LoadObject(path);
102 if (!_this->gl_config.dll_handle) {
103 return -1;
104 }
105 SDL_strlcpy(_this->gl_config.driver_path, path,
106 SDL_arraysize(_this->gl_config.driver_path));
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 *
WIN_GL_GetProcAddress(_THIS,const char * proc)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
WIN_GL_UnloadLibrary(_THIS)152 WIN_GL_UnloadLibrary(_THIS)
153 {
154 SDL_UnloadObject(_this->gl_config.dll_handle);
155 _this->gl_config.dll_handle = NULL;
156
157 /* Free OpenGL memory */
158 SDL_free(_this->gl_data);
159 _this->gl_data = NULL;
160 }
161
162 static void
WIN_GL_SetupPixelFormat(_THIS,PIXELFORMATDESCRIPTOR * pfd)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);
169 if (_this->gl_config.double_buffer) {
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 =
183 _this->gl_config.buffer_size - _this->gl_config.alpha_size;
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
WIN_GL_ChoosePixelFormat(HDC hdc,PIXELFORMATDESCRIPTOR * target)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
HasExtension(const char * extension,const char * extensions)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
WIN_GL_InitExtensions(_THIS)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 }
354 WIN_PumpEvents(_this);
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);
424 WIN_PumpEvents(_this);
425 }
426
427 static int
WIN_GL_ChoosePixelFormatARB(_THIS,int * iAttribs,float * fAttribs)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);
440 WIN_PumpEvents(_this);
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);
463 WIN_PumpEvents(_this);
464
465 return pixel_format;
466 }
467
468 /* actual work of WIN_GL_SetupWindow() happens here. */
469 static int
WIN_GL_SetupWindowInternal(_THIS,SDL_Window * window)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
505 if (_this->gl_config.stencil_size) {
506 *iAttr++ = WGL_STENCIL_BITS_ARB;
507 *iAttr++ = _this->gl_config.stencil_size;
508 }
509
510 if (_this->gl_config.accum_red_size) {
511 *iAttr++ = WGL_ACCUM_RED_BITS_ARB;
512 *iAttr++ = _this->gl_config.accum_red_size;
513 }
514
515 if (_this->gl_config.accum_green_size) {
516 *iAttr++ = WGL_ACCUM_GREEN_BITS_ARB;
517 *iAttr++ = _this->gl_config.accum_green_size;
518 }
519
520 if (_this->gl_config.accum_blue_size) {
521 *iAttr++ = WGL_ACCUM_BLUE_BITS_ARB;
522 *iAttr++ = _this->gl_config.accum_blue_size;
523 }
524
525 if (_this->gl_config.accum_alpha_size) {
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
535 if (_this->gl_config.multisamplebuffers) {
536 *iAttr++ = WGL_SAMPLE_BUFFERS_ARB;
537 *iAttr++ = _this->gl_config.multisamplebuffers;
538 }
539
540 if (_this->gl_config.multisamplesamples) {
541 *iAttr++ = WGL_SAMPLES_ARB;
542 *iAttr++ = _this->gl_config.multisamplesamples;
543 }
544
545 if (_this->gl_config.framebuffer_srgb_capable) {
546 *iAttr++ = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB;
547 *iAttr++ = _this->gl_config.framebuffer_srgb_capable;
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
WIN_GL_SetupWindow(_THIS,SDL_Window * window)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
596 SDL_GLContext
WIN_GL_CreateContext(_THIS,SDL_Window * window)597 WIN_GL_CreateContext(_THIS, SDL_Window * window)
598 {
599 HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc;
600 HGLRC context, share_context;
601
602 if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES &&
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
628 if (_this->gl_config.share_with_current_context) {
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
WIN_GL_MakeCurrent(_THIS,SDL_Window * window,SDL_GLContext context)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) {
732 SDL_assert(SDL_GL_GetCurrentContext() == NULL);
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
WIN_GL_SetSwapInterval(_THIS,int interval)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
WIN_GL_GetSwapInterval(_THIS)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
WIN_GL_SwapWindow(_THIS,SDL_Window * window)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
WIN_GL_DeleteContext(_THIS,SDL_GLContext context)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
WIN_GL_SetPixelFormatFrom(_THIS,SDL_Window * fromWindow,SDL_Window * toWindow)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: */
811