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()).
authorSam Lantinga <slouken@libsdl.org>
Thu, 30 Jan 2014 12:30:40 -0800
changeset 8144855b1d6d7d8e
parent 8143 ce90b743882a
child 8145 663d7d9de9bf
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
include/SDL_hints.h
src/video/windows/SDL_windowsopengl.c
src/video/windows/SDL_windowsopengl.h
src/video/windows/SDL_windowswindow.c
     1.1 --- a/include/SDL_hints.h	Thu Jan 30 12:27:24 2014 -0800
     1.2 +++ b/include/SDL_hints.h	Thu Jan 30 12:30:40 2014 -0800
     1.3 @@ -329,6 +329,25 @@
     1.4  #define SDL_HINT_VIDEO_WIN_D3DCOMPILER              "SDL_VIDEO_WIN_D3DCOMPILER"
     1.5  
     1.6  /**
     1.7 +*  \brief  A variable that is the address of another SDL_Window* (as a hex string formatted with "%p").
     1.8 +*  
     1.9 +*  If this hint is set before SDL_CreateWindowFrom() and the SDL_Window* it is set to has
    1.10 +*  SDL_WINDOW_OPENGL set (and running on WGL only, currently), then two things will occur on the newly 
    1.11 +*  created SDL_Window:
    1.12 +
    1.13 +*  1. Its pixel format will be set to the same pixel format as this SDL_Window.  This is
    1.14 +*  needed for example when sharing an OpenGL context across multiple windows.
    1.15 +*
    1.16 +*  2. The flag SDL_WINDOW_OPENGL will be set on the new window so it can be used for
    1.17 +*  OpenGL rendering.
    1.18 +*
    1.19 +*  This variable can be set to the following values:
    1.20 +*    The address (as a string "%p") of the SDL_Window* that new windows created with SDL_CreateWindowFrom() should
    1.21 +*    share a pixel format with.
    1.22 +*/
    1.23 +#define SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT    "SDL_VIDEO_WINDOW_SHARE_PIXEL_FORMAT"
    1.24 +
    1.25 +/**
    1.26   *  \brief  An enumeration of hint priorities
    1.27   */
    1.28  typedef enum
     2.1 --- a/src/video/windows/SDL_windowsopengl.c	Thu Jan 30 12:27:24 2014 -0800
     2.2 +++ b/src/video/windows/SDL_windowsopengl.c	Thu Jan 30 12:30:40 2014 -0800
     2.3 @@ -759,6 +759,26 @@
     2.4      _this->gl_data->wglDeleteContext((HGLRC) context);
     2.5  }
     2.6  
     2.7 +
     2.8 +SDL_bool
     2.9 +WIN_GL_SetPixelFormatFrom(_THIS, SDL_Window * fromWindow, SDL_Window * toWindow)
    2.10 +{
    2.11 +    HDC hfromdc = ((SDL_WindowData *) fromWindow->driverdata)->hdc;
    2.12 +    HDC htodc = ((SDL_WindowData *) toWindow->driverdata)->hdc;
    2.13 +    BOOL result;
    2.14 +
    2.15 +    /* get the pixel format of the fromWindow */
    2.16 +    int pixel_format = GetPixelFormat(hfromdc);
    2.17 +    PIXELFORMATDESCRIPTOR pfd;
    2.18 +    SDL_memset(&pfd, 0, sizeof(pfd));
    2.19 +    DescribePixelFormat(hfromdc, pixel_format, sizeof(pfd), &pfd);
    2.20 +
    2.21 +    /* set the pixel format of the toWindow */
    2.22 +    result = SetPixelFormat(htodc, pixel_format, &pfd);
    2.23 +
    2.24 +    return result ? SDL_TRUE : SDL_FALSE;
    2.25 +}
    2.26 +
    2.27  #endif /* SDL_VIDEO_OPENGL_WGL */
    2.28  
    2.29  #endif /* SDL_VIDEO_DRIVER_WINDOWS */
     3.1 --- a/src/video/windows/SDL_windowsopengl.h	Thu Jan 30 12:27:24 2014 -0800
     3.2 +++ b/src/video/windows/SDL_windowsopengl.h	Thu Jan 30 12:30:40 2014 -0800
     3.3 @@ -64,6 +64,7 @@
     3.4  extern void WIN_GL_SwapWindow(_THIS, SDL_Window * window);
     3.5  extern void WIN_GL_DeleteContext(_THIS, SDL_GLContext context);
     3.6  extern void WIN_GL_InitExtensions(_THIS);
     3.7 +extern SDL_bool WIN_GL_SetPixelFormatFrom(_THIS, SDL_Window * fromWindow, SDL_Window * toWindow);
     3.8  
     3.9  #ifndef WGL_ARB_pixel_format
    3.10  #define WGL_NUMBER_PIXEL_FORMATS_ARB   0x2000
     4.1 --- a/src/video/windows/SDL_windowswindow.c	Thu Jan 30 12:27:24 2014 -0800
     4.2 +++ b/src/video/windows/SDL_windowswindow.c	Thu Jan 30 12:30:40 2014 -0800
     4.3 @@ -32,6 +32,7 @@
     4.4  
     4.5  #include "SDL_windowsvideo.h"
     4.6  #include "SDL_windowswindow.h"
     4.7 +#include "SDL_hints.h"
     4.8  
     4.9  /* Dropfile support */
    4.10  #include <shellapi.h>
    4.11 @@ -337,6 +338,31 @@
    4.12      if (SetupWindowData(_this, window, hwnd, SDL_FALSE) < 0) {
    4.13          return -1;
    4.14      }
    4.15 +
    4.16 +#if SDL_VIDEO_OPENGL_WGL
    4.17 +    {
    4.18 +        const char *hint = SDL_GetHint(SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT);
    4.19 +        if (hint) {
    4.20 +            // This hint is a pointer (in string form) of the address of
    4.21 +            // the window to share a pixel format with
    4.22 +            SDL_Window *otherWindow = NULL;
    4.23 +            SDL_sscanf(hint, "%p", (void**)&otherWindow);
    4.24 +
    4.25 +            // Do some error checking on the pointer
    4.26 +            if (otherWindow != NULL && otherWindow->magic == &_this->window_magic)
    4.27 +            {
    4.28 +                // If the otherWindow has SDL_WINDOW_OPENGL set, set it for the new window as well
    4.29 +                if (otherWindow->flags & SDL_WINDOW_OPENGL)
    4.30 +                {
    4.31 +                    window->flags |= SDL_WINDOW_OPENGL;
    4.32 +                    if(!WIN_GL_SetPixelFormatFrom(_this, otherWindow, window)) {
    4.33 +                        return -1;
    4.34 +                    }
    4.35 +                }
    4.36 +            }
    4.37 +        }
    4.38 +    }
    4.39 +#endif
    4.40      return 0;
    4.41  }
    4.42