Add a new hint SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT that allows SDL_CreateWindowFrom() to set the pixel format of another SDL_Window (and also will set the SDL_WINDOW_OPENGL flag on the window created with SDL_CreateWindowFrom()). The reasoning behind this change is that source2 in -tools mode has a single OpenGL context that is used with multiple different windows. Some of those windows are created outside the engine (i.e. with Qt) and therefore we need to use SDL_CreateWindowFrom() to get an SDL_Window for those. The requirement for sharing an OpenGL context across multiple different windows is that each window has the same pixel format. To facilitate this, I now set SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT for the main window before calling SDL_CreateWindowFrom(). When I do this, SDL_CreateWindowFrom() will: 1. Set the pixel format of the returned window to the same pixel format as this SDL_Window passed in with the hint 2. The flag SDL_WINDOW_OPENGL will be set on the new window so it can be used for OpenGL rendering. I only currently implemented this for Win32/WGL so implementing it for other platforms (i.e. X11) remains a TODO. CR: SamL Some pseudocode that shows how this is used in Source2: HWND hExternalHwnd; // HWND that was established outside of SDL // Create main window (happens inside platwindow.cpp) SDL_Window *mainWindow = SDL_CreateWindow( , SDL_WINDOW_OPENGL .. ); // Create GL context, happens inside rendersystemgl SDL_GLContext onlyContext = SDL_GL_CreateContext( mainWindow ); // Now I need to create another window from hEternalHwnd for my swap chain that will have the same pixel format as mainWindow, so set the hint SDL_SetHint( SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT, CFmtStr( %p, mainWindow) ); // Create the secondary window. This returned window will have SDL_WINDOW_OPENGL set and share a pixel format with mainWindow from the hint SDL_Window *secondaryWindow = SDL_CreateWindowFrom( hExternalHwnd ); // To render to the main window: SDL_GL_MakeCurrent( mainWindow, onlyContext ); // Do some rendering to main window // To render to the secondary window: SDL_GLMakeCurrent( secondaryWindow, onlyContext ); // Do some rendering to secondary window
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
diff --git a/include/SDL_hints.h b/include/SDL_hints.h
index 9aad2e3..ab65c2a 100644
--- a/include/SDL_hints.h
+++ b/include/SDL_hints.h
@@ -329,6 +329,25 @@ extern "C" {
#define SDL_HINT_VIDEO_WIN_D3DCOMPILER "SDL_VIDEO_WIN_D3DCOMPILER"
/**
+* \brief A variable that is the address of another SDL_Window* (as a hex string formatted with "%p").
+*
+* If this hint is set before SDL_CreateWindowFrom() and the SDL_Window* it is set to has
+* SDL_WINDOW_OPENGL set (and running on WGL only, currently), then two things will occur on the newly
+* created SDL_Window:
+
+* 1. Its pixel format will be set to the same pixel format as this SDL_Window. This is
+* needed for example when sharing an OpenGL context across multiple windows.
+*
+* 2. The flag SDL_WINDOW_OPENGL will be set on the new window so it can be used for
+* OpenGL rendering.
+*
+* This variable can be set to the following values:
+* The address (as a string "%p") of the SDL_Window* that new windows created with SDL_CreateWindowFrom() should
+* share a pixel format with.
+*/
+#define SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT "SDL_VIDEO_WINDOW_SHARE_PIXEL_FORMAT"
+
+/**
* \brief An enumeration of hint priorities
*/
typedef enum
diff --git a/src/video/windows/SDL_windowsopengl.c b/src/video/windows/SDL_windowsopengl.c
index 247976b..53cf555 100644
--- a/src/video/windows/SDL_windowsopengl.c
+++ b/src/video/windows/SDL_windowsopengl.c
@@ -759,6 +759,26 @@ WIN_GL_DeleteContext(_THIS, SDL_GLContext context)
_this->gl_data->wglDeleteContext((HGLRC) context);
}
+
+SDL_bool
+WIN_GL_SetPixelFormatFrom(_THIS, SDL_Window * fromWindow, SDL_Window * toWindow)
+{
+ HDC hfromdc = ((SDL_WindowData *) fromWindow->driverdata)->hdc;
+ HDC htodc = ((SDL_WindowData *) toWindow->driverdata)->hdc;
+ BOOL result;
+
+ /* get the pixel format of the fromWindow */
+ int pixel_format = GetPixelFormat(hfromdc);
+ PIXELFORMATDESCRIPTOR pfd;
+ SDL_memset(&pfd, 0, sizeof(pfd));
+ DescribePixelFormat(hfromdc, pixel_format, sizeof(pfd), &pfd);
+
+ /* set the pixel format of the toWindow */
+ result = SetPixelFormat(htodc, pixel_format, &pfd);
+
+ return result ? SDL_TRUE : SDL_FALSE;
+}
+
#endif /* SDL_VIDEO_OPENGL_WGL */
#endif /* SDL_VIDEO_DRIVER_WINDOWS */
diff --git a/src/video/windows/SDL_windowsopengl.h b/src/video/windows/SDL_windowsopengl.h
index f8934b0..a331098 100644
--- a/src/video/windows/SDL_windowsopengl.h
+++ b/src/video/windows/SDL_windowsopengl.h
@@ -64,6 +64,7 @@ extern int WIN_GL_GetSwapInterval(_THIS);
extern void WIN_GL_SwapWindow(_THIS, SDL_Window * window);
extern void WIN_GL_DeleteContext(_THIS, SDL_GLContext context);
extern void WIN_GL_InitExtensions(_THIS);
+extern SDL_bool WIN_GL_SetPixelFormatFrom(_THIS, SDL_Window * fromWindow, SDL_Window * toWindow);
#ifndef WGL_ARB_pixel_format
#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c
index 5cba9ff..9617dc0 100644
--- a/src/video/windows/SDL_windowswindow.c
+++ b/src/video/windows/SDL_windowswindow.c
@@ -32,6 +32,7 @@
#include "SDL_windowsvideo.h"
#include "SDL_windowswindow.h"
+#include "SDL_hints.h"
/* Dropfile support */
#include <shellapi.h>
@@ -337,6 +338,31 @@ WIN_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
if (SetupWindowData(_this, window, hwnd, SDL_FALSE) < 0) {
return -1;
}
+
+#if SDL_VIDEO_OPENGL_WGL
+ {
+ const char *hint = SDL_GetHint(SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT);
+ if (hint) {
+ // This hint is a pointer (in string form) of the address of
+ // the window to share a pixel format with
+ SDL_Window *otherWindow = NULL;
+ SDL_sscanf(hint, "%p", (void**)&otherWindow);
+
+ // Do some error checking on the pointer
+ if (otherWindow != NULL && otherWindow->magic == &_this->window_magic)
+ {
+ // If the otherWindow has SDL_WINDOW_OPENGL set, set it for the new window as well
+ if (otherWindow->flags & SDL_WINDOW_OPENGL)
+ {
+ window->flags |= SDL_WINDOW_OPENGL;
+ if(!WIN_GL_SetPixelFormatFrom(_this, otherWindow, window)) {
+ return -1;
+ }
+ }
+ }
+ }
+ }
+#endif
return 0;
}