WinRT: fixed a crash in SDL_Quit
SDL was expected that each SDL_DisplayMode had a driverdata field that was SDL_malloc'ed, and was calling SDL_free on them. This change moves WinRT's driverdata content into a SDL_malloc'ed field.main
parent
abfbed92cf
commit
f4a5a0fad1
|
@ -157,8 +157,15 @@ WINRT_ProcessWindowSizeChange()
|
||||||
// window-resize event as it appeared the SDL window didn't change
|
// window-resize event as it appeared the SDL window didn't change
|
||||||
// size, and the Direct3D 11.1 renderer wouldn't resize its swap
|
// size, and the Direct3D 11.1 renderer wouldn't resize its swap
|
||||||
// chain.
|
// chain.
|
||||||
SDL_DisplayMode resizedDisplayMode = WINRT_CalcDisplayModeUsingNativeWindow();
|
SDL_DisplayMode resizedDisplayMode;
|
||||||
|
if (WINRT_CalcDisplayModeUsingNativeWindow(&resizedDisplayMode) != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (resizedDisplayMode.w == 0 || resizedDisplayMode.h == 0) {
|
if (resizedDisplayMode.w == 0 || resizedDisplayMode.h == 0) {
|
||||||
|
if (resizedDisplayMode.driverdata) {
|
||||||
|
SDL_free(resizedDisplayMode.driverdata);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,8 +173,14 @@ WINRT_ProcessWindowSizeChange()
|
||||||
SDL_zero(oldDisplayMode);
|
SDL_zero(oldDisplayMode);
|
||||||
if (WINRT_GlobalSDLVideoDevice) {
|
if (WINRT_GlobalSDLVideoDevice) {
|
||||||
oldDisplayMode = WINRT_GlobalSDLVideoDevice->displays[0].desktop_mode;
|
oldDisplayMode = WINRT_GlobalSDLVideoDevice->displays[0].desktop_mode;
|
||||||
|
if (WINRT_DuplicateDisplayMode(&(WINRT_GlobalSDLVideoDevice->displays[0].desktop_mode), &resizedDisplayMode) != 0) {
|
||||||
|
SDL_free(resizedDisplayMode.driverdata);
|
||||||
|
return;
|
||||||
|
}
|
||||||
WINRT_GlobalSDLVideoDevice->displays[0].current_mode = resizedDisplayMode;
|
WINRT_GlobalSDLVideoDevice->displays[0].current_mode = resizedDisplayMode;
|
||||||
WINRT_GlobalSDLVideoDevice->displays[0].desktop_mode = resizedDisplayMode;
|
if (WINRT_GlobalSDLVideoDevice->displays[0].display_modes[0].driverdata) {
|
||||||
|
SDL_free(WINRT_GlobalSDLVideoDevice->displays[0].display_modes[0].driverdata);
|
||||||
|
}
|
||||||
WINRT_GlobalSDLVideoDevice->displays[0].display_modes[0] = resizedDisplayMode;
|
WINRT_GlobalSDLVideoDevice->displays[0].display_modes[0] = resizedDisplayMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,8 +197,8 @@ WINRT_ProcessWindowSizeChange()
|
||||||
// Landscape to LandscapeFlipped, Portrait to PortraitFlipped,
|
// Landscape to LandscapeFlipped, Portrait to PortraitFlipped,
|
||||||
// or vice-versa on either of those two, lead to the Direct3D renderer
|
// or vice-versa on either of those two, lead to the Direct3D renderer
|
||||||
// getting updated.
|
// getting updated.
|
||||||
const DisplayOrientations oldOrientation = (DisplayOrientations) (unsigned int) oldDisplayMode.driverdata;
|
const DisplayOrientations oldOrientation = ((SDL_DisplayModeData *)oldDisplayMode.driverdata)->currentOrientation;
|
||||||
const DisplayOrientations newOrientation = (DisplayOrientations) (unsigned int) resizedDisplayMode.driverdata;
|
const DisplayOrientations newOrientation = ((SDL_DisplayModeData *)resizedDisplayMode.driverdata)->currentOrientation;
|
||||||
|
|
||||||
if ((oldOrientation == DisplayOrientations::Landscape && newOrientation == DisplayOrientations::LandscapeFlipped) ||
|
if ((oldOrientation == DisplayOrientations::Landscape && newOrientation == DisplayOrientations::LandscapeFlipped) ||
|
||||||
(oldOrientation == DisplayOrientations::LandscapeFlipped && newOrientation == DisplayOrientations::Landscape) ||
|
(oldOrientation == DisplayOrientations::LandscapeFlipped && newOrientation == DisplayOrientations::Landscape) ||
|
||||||
|
@ -212,6 +225,10 @@ WINRT_ProcessWindowSizeChange()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (oldDisplayMode.driverdata) {
|
||||||
|
SDL_free(oldDisplayMode.driverdata);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_WinRTApp::SDL_WinRTApp() :
|
SDL_WinRTApp::SDL_WinRTApp() :
|
||||||
|
|
|
@ -147,33 +147,42 @@ WINRT_VideoInit(_THIS)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_DisplayMode
|
int
|
||||||
WINRT_CalcDisplayModeUsingNativeWindow()
|
WINRT_CalcDisplayModeUsingNativeWindow(SDL_DisplayMode * mode)
|
||||||
{
|
{
|
||||||
|
SDL_DisplayModeData * driverdata;
|
||||||
|
|
||||||
using namespace Windows::Graphics::Display;
|
using namespace Windows::Graphics::Display;
|
||||||
|
|
||||||
// Create an empty, zeroed-out display mode:
|
// Initialize the mode to all zeros:
|
||||||
SDL_DisplayMode mode;
|
SDL_zerop(mode);
|
||||||
SDL_zero(mode);
|
|
||||||
|
|
||||||
// Go no further if a native window cannot be accessed. This can happen,
|
// Go no further if a native window cannot be accessed. This can happen,
|
||||||
// for example, if this function is called from certain threads, such as
|
// for example, if this function is called from certain threads, such as
|
||||||
// the SDL/XAML thread.
|
// the SDL/XAML thread.
|
||||||
if (!CoreWindow::GetForCurrentThread()) {
|
if (!CoreWindow::GetForCurrentThread()) {
|
||||||
return mode;
|
return SDL_SetError("SDL/WinRT display modes cannot be calculated outside of the main thread, such as in SDL's XAML thread");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a driverdata field:
|
||||||
|
driverdata = (SDL_DisplayModeData *) SDL_malloc(sizeof(*driverdata));
|
||||||
|
if (!driverdata) {
|
||||||
|
return SDL_OutOfMemory();
|
||||||
|
}
|
||||||
|
SDL_zerop(driverdata);
|
||||||
|
|
||||||
// Fill in most fields:
|
// Fill in most fields:
|
||||||
mode.format = SDL_PIXELFORMAT_RGB888;
|
mode->format = SDL_PIXELFORMAT_RGB888;
|
||||||
mode.refresh_rate = 0; // TODO, WinRT: see if refresh rate data is available, or relevant (for WinRT apps)
|
mode->refresh_rate = 0; // TODO, WinRT: see if refresh rate data is available, or relevant (for WinRT apps)
|
||||||
mode.driverdata = (void *) DisplayProperties::CurrentOrientation;
|
mode->driverdata = driverdata;
|
||||||
|
driverdata->currentOrientation = DisplayProperties::CurrentOrientation;
|
||||||
|
|
||||||
// Calculate the display size given the window size, taking into account
|
// Calculate the display size given the window size, taking into account
|
||||||
// the current display's DPI:
|
// the current display's DPI:
|
||||||
const float currentDPI = Windows::Graphics::Display::DisplayProperties::LogicalDpi;
|
const float currentDPI = Windows::Graphics::Display::DisplayProperties::LogicalDpi;
|
||||||
const float dipsPerInch = 96.0f;
|
const float dipsPerInch = 96.0f;
|
||||||
mode.w = (int) ((CoreWindow::GetForCurrentThread()->Bounds.Width * currentDPI) / dipsPerInch);
|
mode->w = (int) ((CoreWindow::GetForCurrentThread()->Bounds.Width * currentDPI) / dipsPerInch);
|
||||||
mode.h = (int) ((CoreWindow::GetForCurrentThread()->Bounds.Height * currentDPI) / dipsPerInch);
|
mode->h = (int) ((CoreWindow::GetForCurrentThread()->Bounds.Height * currentDPI) / dipsPerInch);
|
||||||
|
|
||||||
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||||
// On Windows Phone, the native window's size is always in portrait,
|
// On Windows Phone, the native window's size is always in portrait,
|
||||||
|
@ -186,32 +195,52 @@ WINRT_CalcDisplayModeUsingNativeWindow()
|
||||||
case DisplayOrientations::Landscape:
|
case DisplayOrientations::Landscape:
|
||||||
case DisplayOrientations::LandscapeFlipped:
|
case DisplayOrientations::LandscapeFlipped:
|
||||||
{
|
{
|
||||||
const int tmp = mode.h;
|
const int tmp = mode->h;
|
||||||
mode.h = mode.w;
|
mode->h = mode->w;
|
||||||
mode.w = tmp;
|
mode->w = tmp;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attach the mode to te
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return mode;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
WINRT_DuplicateDisplayMode(SDL_DisplayMode * dest, const SDL_DisplayMode * src)
|
||||||
|
{
|
||||||
|
SDL_DisplayModeData * driverdata;
|
||||||
|
driverdata = (SDL_DisplayModeData *) SDL_malloc(sizeof(*driverdata));
|
||||||
|
if (!driverdata) {
|
||||||
|
return SDL_OutOfMemory();
|
||||||
|
}
|
||||||
|
SDL_memcpy(driverdata, src->driverdata, sizeof(SDL_DisplayModeData));
|
||||||
|
SDL_memcpy(dest, src, sizeof(SDL_DisplayMode));
|
||||||
|
dest->driverdata = driverdata;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
WINRT_InitModes(_THIS)
|
WINRT_InitModes(_THIS)
|
||||||
{
|
{
|
||||||
// Retrieve the display mode:
|
// Retrieve the display mode:
|
||||||
SDL_DisplayMode mode = WINRT_CalcDisplayModeUsingNativeWindow();
|
SDL_DisplayMode mode, desktop_mode;
|
||||||
|
if (WINRT_CalcDisplayModeUsingNativeWindow(&mode) != 0) {
|
||||||
|
return -1; // If WINRT_CalcDisplayModeUsingNativeWindow fails, it'll already have set the SDL error
|
||||||
|
}
|
||||||
|
|
||||||
if (mode.w == 0 || mode.h == 0) {
|
if (mode.w == 0 || mode.h == 0) {
|
||||||
|
SDL_free(mode.driverdata);
|
||||||
return SDL_SetError("Unable to calculate the WinRT window/display's size");
|
return SDL_SetError("Unable to calculate the WinRT window/display's size");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SDL_AddBasicVideoDisplay(&mode) < 0) {
|
if (WINRT_DuplicateDisplayMode(&desktop_mode, &mode) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (SDL_AddBasicVideoDisplay(&desktop_mode) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,9 +44,25 @@ extern SDL_Window * WINRT_GlobalSDLWindow;
|
||||||
/* The global, WinRT, video device. */
|
/* The global, WinRT, video device. */
|
||||||
extern SDL_VideoDevice * WINRT_GlobalSDLVideoDevice;
|
extern SDL_VideoDevice * WINRT_GlobalSDLVideoDevice;
|
||||||
|
|
||||||
/* Computes the current display mode for Plain Direct3D (non-XAML) apps */
|
/* Creates a display mode for Plain Direct3D (non-XAML) apps, using the lone, native window's settings.
|
||||||
extern SDL_DisplayMode WINRT_CalcDisplayModeUsingNativeWindow();
|
|
||||||
|
|
||||||
|
Pass in an allocated SDL_DisplayMode field to store the data in.
|
||||||
|
|
||||||
|
This function will return 0 on success, -1 on failure.
|
||||||
|
|
||||||
|
If this function succeeds, be sure to call SDL_free on the
|
||||||
|
SDL_DisplayMode's driverdata field.
|
||||||
|
*/
|
||||||
|
extern int WINRT_CalcDisplayModeUsingNativeWindow(SDL_DisplayMode * mode);
|
||||||
|
|
||||||
|
/* Duplicates a display mode, copying over driverdata as necessary */
|
||||||
|
extern int WINRT_DuplicateDisplayMode(SDL_DisplayMode * dest, const SDL_DisplayMode * src);
|
||||||
|
|
||||||
|
/* Display mode internals */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Windows::Graphics::Display::DisplayOrientations currentOrientation;
|
||||||
|
} SDL_DisplayModeData;
|
||||||
|
|
||||||
#ifdef __cplusplus_winrt
|
#ifdef __cplusplus_winrt
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue