diff --git a/VisualC-WinRT/WinPhone80_VS2012/SDL-WinPhone80.vcxproj b/VisualC-WinRT/WinPhone80_VS2012/SDL-WinPhone80.vcxproj index b325cd0b9..3776d2433 100644 --- a/VisualC-WinRT/WinPhone80_VS2012/SDL-WinPhone80.vcxproj +++ b/VisualC-WinRT/WinPhone80_VS2012/SDL-WinPhone80.vcxproj @@ -237,6 +237,8 @@ + + @@ -264,6 +266,7 @@ + @@ -272,6 +275,7 @@ + @@ -345,6 +349,8 @@ true true + + @@ -387,6 +393,7 @@ + @@ -419,6 +426,12 @@ true true + + true + true + true + true + true true diff --git a/VisualC-WinRT/WinPhone80_VS2012/SDL-WinPhone80.vcxproj.filters b/VisualC-WinRT/WinPhone80_VS2012/SDL-WinPhone80.vcxproj.filters index f52e56bf8..1f4df44e4 100644 --- a/VisualC-WinRT/WinPhone80_VS2012/SDL-WinPhone80.vcxproj.filters +++ b/VisualC-WinRT/WinPhone80_VS2012/SDL-WinPhone80.vcxproj.filters @@ -360,6 +360,18 @@ Source Files + + Source Files + + + Source Files + + + Source Files + + + Source Files + @@ -650,5 +662,17 @@ Source Files + + Source Files + + + Source Files + + + Source Files + + + Source Files + \ No newline at end of file diff --git a/build-scripts/g++-fat.sh b/build-scripts/g++-fat.sh index 6e4f53e7c..b6fe7bb48 100755 --- a/build-scripts/g++-fat.sh +++ b/build-scripts/g++-fat.sh @@ -34,7 +34,7 @@ while test x$1 != x; do compile=no; link=no;; -c) link=no;; -o) output=$2;; - *.c|*.cc|*.cpp|*.S) source=$1;; + *.c|*.cc|*.cpp|*.S|*.m|*.mm) source=$1;; esac shift done diff --git a/build-scripts/gcc-fat.sh b/build-scripts/gcc-fat.sh index edabb0d87..e556c1dd1 100755 --- a/build-scripts/gcc-fat.sh +++ b/build-scripts/gcc-fat.sh @@ -35,7 +35,7 @@ while test x$1 != x; do compile=no; link=no;; -c) link=no;; -o) output=$2;; - *.c|*.cc|*.cpp|*.S) source=$1;; + *.c|*.cc|*.cpp|*.S|*.m|*.mm) source=$1;; esac shift done diff --git a/build-scripts/winrtbuild.bat b/build-scripts/winrtbuild.bat new file mode 100644 index 000000000..fb3159888 --- /dev/null +++ b/build-scripts/winrtbuild.bat @@ -0,0 +1,8 @@ +@ECHO OFF +REM +REM winrtbuild.bat: a batch file to help launch the winrtbuild.ps1 +REM Powershell script, either from Windows Explorer, or through Buildbot. +REM +SET ThisScriptsDirectory=%~dp0 +SET PowerShellScriptPath=%ThisScriptsDirectory%winrtbuild.ps1 +PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& '%PowerShellScriptPath%'"; \ No newline at end of file diff --git a/build-scripts/winrtbuild.ps1 b/build-scripts/winrtbuild.ps1 new file mode 100644 index 000000000..2b1186990 --- /dev/null +++ b/build-scripts/winrtbuild.ps1 @@ -0,0 +1,225 @@ +# +# winrtbuild.ps1 -- A Powershell script to build all SDL/WinRT variants, +# across all WinRT platforms, in all of their supported, CPU architectures. +# +# Initial version written by David Ludwig +# +# This script can be launched from Windows Explorer by double-clicking +# on winrtbuild.bat +# +# Output will be placed in the following subdirectories of the SDL source +# tree: +# * VisualC-WinRT\lib\ -- final .dll, .lib, and .pdb files +# * VisualC-WinRT\obj\ -- intermediate build files +# +# Recommended Dependencies: +# * Windows 8.1 or higher +# * Powershell 4.0 or higher (included as part of Windows 8.1) +# * Visual C++ 2012, for building Windows 8.0 and Windows Phone 8.0 binaries. +# * Visual C++ 2013, for building Windows 8.1 and Windows Phone 8.1 binaries +# * SDKs for Windows 8.0, Windows 8.1, Windows Phone 8.0, and +# Windows Phone 8.1, as needed +# +# Commom parameters/variables may include, but aren't strictly limited to: +# * PlatformToolset: the name of one of Visual Studio's build platforms. +# Different PlatformToolsets output different binaries. One +# PlatformToolset exists for each WinRT platform. Possible values +# may include: +# - "v110": Visual Studio 2012 build tools, plus the Windows 8.0 SDK +# - "v110_wp80": Visual Studio 2012 build tools, plus the Windows Phone 8.0 SDK +# - "v120": Visual Studio 2013 build tools, plus the Windows 8.1 SDK +# - "v120_wp81": Visual Studio 2013 build tools, plus the Windows Phone 8.1 SDK +# * VSProjectPath: the full path to a Visual Studio or Visual C++ project file +# * VSProjectName: the internal name of a Visual Studio or Visual C++ project +# file. Some of Visual Studio's own build tools use this name when +# calculating paths for build-output. +# * Platform: a Visual Studio platform name, which often maps to a CPU +# CPU architecture. Possible values may include: "Win32" (for 32-bit x86), +# "ARM", or "x64" (for 64-bit x86). +# + + +# Gets the .bat file that sets up an MSBuild environment, given one of +# Visual Studio's, "PlatformToolset"s. +function Get-MSBuild-Env-Launcher +{ + param( + [Parameter(Mandatory=$true,Position=1)][string]$PlatformToolset + ) + + if ($PlatformToolset -eq "v110") { # Windows 8.0 (not Windows Phone), via VS 2012 + return "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" + } + if ($PlatformToolset -eq "v110_wp80") { # Windows Phone 8.0, via VS 2012 + return "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\WPSDK\WP80\vcvarsphoneall.bat" + } + if ($PlatformToolset -eq "v120") { # Windows 8.1 (not Windows Phone), via VS 2013 + return "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" + } + if ($PlatformToolset -eq "v120_wp81") { # Windows Phone 8.1, via VS 2013 + return "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" + } + return "" +} + +# Gets a string that identifies the build-variant of SDL/WinRT that is specific +# to a particular Visual Studio PlatformToolset. +function Get-SDL-WinRT-Variant-Name +{ + param( + [Parameter(Mandatory=$true,Position=1)][string]$PlatformToolset, + + # If true, append a string to this function's output, identifying the + # build-variant's minimum-supported version of Visual Studio. + [switch]$IncludeVSSuffix = $false + ) + + if ($PlatformToolset -eq "v110") { # Windows 8.0 (not Windows Phone), via VS 2012 project files + if ($IncludeVSSuffix) { + return "WinRT80_VS2012" + } else { + return "WinRT80" + } + } + if ($PlatformToolset -eq "v110_wp80") { # Windows Phone 8.0, via VS 2012 project files + if ($IncludeVSSuffix) { + return "WinPhone80_VS2012" + } else { + return "WinPhone80" + } + } + if ($PlatformToolset -eq "v120") { # Windows 8.1 (not Windows Phone), via VS 2013 project files + if ($IncludeVSSuffix) { + return "WinRT81_VS2013" + } else { + return "WinRT81" + } + } + if ($PlatformToolset -eq "v120_wp81") { # Windows Phone 8.1, via VS 2013 project files + if ($IncludeVSSuffix) { + return "WinPhone81_VS2013" + } else { + return "WinPhone81" + } + } + return "" +} + +# Returns the internal name of a Visual Studio Project. +# +# The internal name of a VS Project is encoded inside the project file +# itself, inside a set of XML tags. +function Get-VS-ProjectName +{ + param( + [Parameter(Mandatory=$true,Position=1)]$VSProjectPath + ) + + # For now, just do a regex for the project name: + $matches = (Get-Content $VSProjectPath | Select-String -Pattern ".*([^<]+)<.*").Matches + foreach ($match in $matches) { + if ($match.Groups.Count -ge 1) { + return $match.Groups[1].Value + } + } + return $null +} + +# Build a specific variant of SDL/WinRT +function Build-SDL-WinRT-Variant +{ + # + # Read in arguments: + # + param ( + # name of an SDL project file, minus extensions and + # platform-identifying suffixes + [Parameter(Mandatory=$true,Position=1)][string]$SDLProjectName, + + [Parameter(Mandatory=$true,Position=2)][string]$PlatformToolset, + + [Parameter(Mandatory=$true,Position=3)][string]$Platform + ) + + # + # Derive other properties from read-in arguments: + # + + # The .bat file to setup a platform-appropriate MSBuild environment: + $BatchFileForMSBuildEnv = Get-MSBuild-Env-Launcher $PlatformToolset + + # The full path to the VS Project that'll be built: + $VSProjectPath = "$PSScriptRoot\..\VisualC-WinRT\$(Get-SDL-WinRT-Variant-Name $PlatformToolset -IncludeVSSuffix)\$SDLProjectName-$(Get-SDL-WinRT-Variant-Name $PlatformToolset).vcxproj" + + # The internal name of the VS Project, used in some post-build steps: + $VSProjectName = Get-VS-ProjectName $VSProjectPath + + # Where to place output binaries (.dll, .lib, and .pdb files): + $OutDir = "$PSScriptRoot\..\VisualC-WinRT\lib\$PlatformToolset\$Platform" + + # Where to place intermediate build files: + $IntermediateDir = "$PSScriptRoot\..\VisualC-WinRT\obj\$SDLProjectName-$(Get-SDL-WinRT-Variant-Name $PlatformToolset)\$Platform" + + # + # Build the VS Project: + # + cmd.exe /c " ""$BatchFileForMSBuildEnv"" x86 & msbuild ""$VSProjectPath"" /p:Platform=$Platform /p:OutDir=""$OutDir\\"" /p:IntDir=""$IntermediateDir\\""" | Out-Host + $BuildResult = $? + + # + # Move .dll files into place. This fixes a problem whereby MSBuild may + # put output files into a sub-directory of $OutDir, rather than $OutDir + # itself. + # + if (Test-Path "$OutDir\$VSProjectName\") { + Move-Item -Force "$OutDir\$VSProjectName\*" "$OutDir" + } + + # + # Clean up unneeded files in $OutDir: + # + if (Test-Path "$OutDir\$VSProjectName\") { + Remove-Item -Recurse "$OutDir\$VSProjectName" + } + Remove-Item "$OutDir\*.exp" + Remove-Item "$OutDir\*.ilk" + Remove-Item "$OutDir\*.pri" + + # + # All done. Indicate success, or failure, to the caller: + # + #echo "RESULT: $BuildResult" | Out-Host + return $BuildResult +} + + +# +# Build each variant, with corresponding .dll, .lib, and .pdb files: +# +$DidAnyFail = $false + +# Build for Windows Phone 8.0, via VC++ 2012: +if ( ! (Build-SDL-WinRT-Variant "SDL" "v110_wp80" "ARM")) { $DidAnyFail = $true } +if ( ! (Build-SDL-WinRT-Variant "SDL" "v110_wp80" "Win32")) { $DidAnyFail = $true } + +# Build for Windows Phone 8.1, via VC++ 2013: +if ( ! (Build-SDL-WinRT-Variant "SDL" "v120_wp81" "ARM")) { $DidAnyFail = $true } +if ( ! (Build-SDL-WinRT-Variant "SDL" "v120_wp81" "Win32")) { $DidAnyFail = $true } + +# Build for Windows 8.0 and Windows RT 8.0, via VC++ 2012: +if ( ! (Build-SDL-WinRT-Variant "SDL" "v110" "ARM")) { $DidAnyFail = $true } +if ( ! (Build-SDL-WinRT-Variant "SDL" "v110" "Win32")) { $DidAnyFail = $true } +if ( ! (Build-SDL-WinRT-Variant "SDL" "v110" "x64")) { $DidAnyFail = $true } + +# Build for Windows 8.1 and Windows RT 8.1, via VC++ 2013: +if ( ! (Build-SDL-WinRT-Variant "SDL" "v120" "ARM")) { $DidAnyFail = $true } +if ( ! (Build-SDL-WinRT-Variant "SDL" "v120" "Win32")) { $DidAnyFail = $true } +if ( ! (Build-SDL-WinRT-Variant "SDL" "v120" "x64")) { $DidAnyFail = $true } + +# Let the script's caller know whether or not any errors occurred. +# Exit codes compatible with Buildbot are used (1 for error, 0 for success). +if ($DidAnyFail -eq $true) { + exit 1 +} else { + exit 0 +} diff --git a/docs/README-winrt.md b/docs/README-winrt.md index b1f53809b..90d9889e0 100644 --- a/docs/README-winrt.md +++ b/docs/README-winrt.md @@ -19,21 +19,24 @@ Requirements ------------ * Microsoft Visual C++ (aka Visual Studio), either 2013 or 2012 versions - - Free, "Express" editions may be used, so long as they include support for - either "Windows Store" or "Windows Phone" apps. Versions marked as - supporting "Windows Desktop" development typically do not include support - for creating WinRT apps. - - Visual C++ 2012 can only build apps that target versions 8.0 of Windows, or - Windows Phone. 8.0-targetted apps will still run on devices running - 8.1 editions of Windows, however they will not be able to take advantage of + - Free, "Community" or "Express" editions may be used, so long as they + include support for either "Windows Store" or "Windows Phone" apps. + "Express" versions marked as supporting "Windows Desktop" development + typically do not include support for creating WinRT apps, to note. + (The "Community" edition of Visual C++ 2013 does, however, support both + desktop/Win32 and WinRT development). + - Visual C++ 2012 can only build apps that target versions 8.0 of Windows, + or Windows Phone. 8.0-targetted apps will run on devices running 8.1 + editions of Windows, however they will not be able to take advantage of 8.1-specific features. - - Visual C++ 2013 can only create app projects that target 8.1 versions - of Windows, which do NOT run on 8.0 devices. An optional Visual Studio - add-in, "Tools for Maintaining Store apps for Windows 8", allows projects - that are created with Visual C++ 2012, which can create Windows 8.0 apps, - to be loaded and built with non-Express editions of Visual C++ 2013. More - details on targeting different versions of Windows can found at the - following web pages: + - Visual C++ 2013 cannot create app projects that target Windows 8.0. + Visual C++ 2013 Update 4, can create app projects for Windows Phone 8.0, + Windows Phone 8.1, and Windows 8.1, but not Windows 8.0. An optional + Visual Studio add-in, "Tools for Maintaining Store apps for Windows 8", + allows Visual C++ 2013 to load and build Windows 8.0 projects that were + created with Visual C++ 2012, so long as Visual C++ 2012 is installed + on the same machine. More details on targeting different versions of + Windows can found at the following web pages: - [Develop apps by using Visual Studio 2013](http://msdn.microsoft.com/en-us/library/windows/apps/br211384.aspx) - [To add the Tools for Maintaining Store apps for Windows 8](http://msdn.microsoft.com/en-us/library/windows/apps/dn263114.aspx#AddMaintenanceTools) * A valid Microsoft account - This requirement is not imposed by SDL, but @@ -41,6 +44,79 @@ Requirements debug apps. +Status +------ + +Here is a rough list of what works, and what doens't: + +* What works: + * compilation via Visual C++ 2012 and 2013 + * compile-time platform detection for SDL programs. The C/C++ #define, + `__WINRT__`, will be set to 1 (by SDL) when compiling for WinRT. + * GPU-accelerated 2D rendering, via SDL_Renderer. + * software rendering, via either SDL_Surface (optionally in conjunction with + SDL_GetWindowSurface() and SDL_UpdateWindowSurface()) or via the + SDL_Renderer APIs + * threads. Significant chunks of Win32's threading APIs are not available in + WinRT. A new, SDL threading backend was built using C++11's threading APIs + (std::thread, std::mutex, std::condition_variable, etc.), which C or C++ + programs alike can access via SDL's threading APIs. Support for thread + priorities is not, however, currently available, due to restrictions in + WinRT's own API set. + * timers (via SDL_GetTicks(), SDL_AddTimer(), SDL_GetPerformanceCounter(), + SDL_GetPerformanceFrequency(), etc.) + * file I/O via SDL_RWops + * mouse input (unsupported on Windows Phone) + * audio, via a modified version of SDL's XAudio2 backend + * .DLL file loading. Libraries must be packaged inside applications. Loading + anything outside of the app is not supported. + * system path retrieval via SDL's filesystem APIs + * game controllers. Support is provided via the SDL_Joystick and + SDL_GameController APIs, and is backed by Microsoft's XInput API. + * multi-touch input + * app events. SDL_APP_WILLENTER* and SDL_APP_DIDENTER* events get sent out as + appropriate. + * window events. SDL_WINDOWEVENT_MINIMIZED and SDL_WINDOWEVENT_RESTORED are + sent out on app suspend and resume, respectively. SDL_WINDOWEVENT_SHOWN and + SDL_WINDOWEVENT_HIDDEN are also sent, but not necessarily on app suspend or + resume, as WinRT treats these two concepts differently.. + * using Direct3D 11.x APIs outside of SDL. Non-XAML / Direct3D-only apps can + choose to render content directly via Direct3D, using SDL to manage the + internal WinRT window, as well as input and audio. (Use + SDL_GetWindowWMInfo() to get the WinRT 'CoreWindow', and pass it into + IDXGIFactory2::CreateSwapChainForCoreWindow() as appropriate.) + +* What partially works: + * keyboard input. Most of WinRT's documented virtual keys are supported, as + well as many keys with documented hardware scancodes. + * OpenGL. Experimental support for OpenGL ES 2 is available via the ANGLE + project, using either MS Open Technologies' repository, at + https://github.com/msopentech/angle (both the "winrt" and "future-dev" + branches are supported), or the official ANGLE repository, at + https://chromium.googlesource.com/angle/angle + * SDLmain. WinRT uses a different signature for each app's main() function. + SDL-based apps that use this port must compile in SDL_winrt_main_NonXAML.cpp + (in `SDL\src\main\winrt\`) directly in order for their C-style main() + functions to be called. + * XAML interoperability. This feature is currently experimental (there are + **many** known bugs in this, at present!), preliminary, and only for + Windows 8.x/RT at the moment. Windows Phone + XAML support is still + pending. + +* What doesn't work: + * compilation with anything other than Visual C++ 2012 or 2013 + * programmatically-created custom cursors. These don't appear to be supported + by WinRT. Different OS-provided cursors can, however, be created via + SDL_CreateSystemCursor() (unsupported on Windows Phone) + * SDL_WarpMouseInWindow() or SDL_WarpMouseGlobal(). This are not currently + supported by WinRT itself. + * joysticks and game controllers that aren't supported by Microsoft's XInput + API. + * probably anything else that's not listed as supported + + + + Setup, High-Level Steps ----------------------- @@ -327,7 +403,8 @@ To setup Visual C++ to launch your app on an ARM device: 2. select "Debugging" 3. next to "Machine Name", enter the hostname or IP address of the ARM device - 4. if, and only if, you've turned off authentication in the Remote Debugger, then change the setting for "Require Authentication" to No + 4. if, and only if, you've turned off authentication in the Remote Debugger, + then change the setting for "Require Authentication" to No 5. click "OK" 4. build and run the app (from Visual C++). The first time you do this, a prompt will show up on the ARM device, asking for a Microsoft Account. You @@ -355,15 +432,3 @@ section. /nodefaultlib:vccorlibd /nodefaultlib:msvcrtd vccorlibd.lib msvcrtd.lib - -TODO ----- - -- Document details of SDL satellite library support -- Make [NuGet](https://www.nuget.org) packages for SDL/WinRT -- Create templates for both MSVC 2012 and MSVC 2013, and have the corresponding - VSIX packages either include pre-built copies of SDL, or reference binaries - available via MSVC's NuGet servers - - Write setup instructions that use MSVC 201x templates -- Write a list of caveats found in SDL/WinRT, such as APIs that don't work due - to platform restrictions, or things that need further work diff --git a/include/SDL_config_winrt.h b/include/SDL_config_winrt.h index d70a0bcd6..96c53c2e9 100644 --- a/include/SDL_config_winrt.h +++ b/include/SDL_config_winrt.h @@ -173,10 +173,8 @@ typedef unsigned int uintptr_t; #define SDL_VIDEO_DRIVER_DUMMY 1 /* Enable OpenGL ES 2.0 (via a modified ANGLE library) */ -#if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP /* TODO, WinRT: try adding OpenGL ES 2 support for Windows Phone 8 */ #define SDL_VIDEO_OPENGL_ES2 1 #define SDL_VIDEO_OPENGL_EGL 1 -#endif /* Enable appropriate renderer(s) */ #define SDL_VIDEO_RENDER_D3D11 1 diff --git a/src/SDL.c b/src/SDL.c index 1e2707d9c..69872dd6c 100644 --- a/src/SDL.c +++ b/src/SDL.c @@ -439,6 +439,8 @@ SDL_GetPlatform() return "Solaris"; #elif __WIN32__ return "Windows"; +#elif __WINRT__ + return "WinRT"; #elif __IPHONEOS__ return "iOS"; #elif __PSP__ diff --git a/src/SDL_hints.c b/src/SDL_hints.c index 365459ec7..ec5ed5b81 100644 --- a/src/SDL_hints.c +++ b/src/SDL_hints.c @@ -137,6 +137,10 @@ SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata) SDL_DelHintCallback(name, callback, userdata); entry = (SDL_HintWatch *)SDL_malloc(sizeof(*entry)); + if (!entry) { + SDL_OutOfMemory(); + return; + } entry->callback = callback; entry->userdata = userdata; @@ -149,6 +153,8 @@ SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata) /* Need to add a hint entry for this watcher */ hint = (SDL_Hint *)SDL_malloc(sizeof(*hint)); if (!hint) { + SDL_OutOfMemory(); + SDL_free(entry); return; } hint->name = SDL_strdup(name); diff --git a/src/joystick/sort_controllers.py b/src/joystick/sort_controllers.py index 03b857a02..af95d6513 100755 --- a/src/joystick/sort_controllers.py +++ b/src/joystick/sort_controllers.py @@ -30,9 +30,9 @@ def write_controllers(): for entry in sorted(controllers, key=lambda entry: entry[2]): line = "".join(entry) + "\n" if not line.endswith(",\n") and not line.endswith("*/\n"): - print "Warning: '%s' is missing a comma at the end of the line" % (line) + print("Warning: '%s' is missing a comma at the end of the line" % (line)) if (entry[1] in controller_guids): - print "Warning: entry '%s' is duplicate of entry '%s'" % (entry[2], controller_guids[entry[1]][2]) + print("Warning: entry '%s' is duplicate of entry '%s'" % (entry[2], controller_guids[entry[1]][2])) controller_guids[entry[1]] = entry output.write(line) @@ -40,15 +40,17 @@ def write_controllers(): controller_guids = {} for line in input: - if ( parsing_controllers ): + if (parsing_controllers): if (line.startswith("{")): output.write(line) - elif (line.startswith("#endif")): + elif (line.startswith(" NULL")): parsing_controllers = False write_controllers() output.write(line) - elif (line.startswith("#")): - print "Parsing " + line.strip() + elif (line.startswith("#if")): + print("Parsing " + line.strip()) + output.write(line) + elif (line.startswith("#endif")): write_controllers() output.write(line) else: @@ -60,4 +62,4 @@ for line in input: output.write(line) output.close() -print "Finished writing %s.new" % filename +print("Finished writing %s.new" % filename) diff --git a/src/timer/windows/SDL_systimer.c b/src/timer/windows/SDL_systimer.c index 07561636a..c9435c3e7 100644 --- a/src/timer/windows/SDL_systimer.c +++ b/src/timer/windows/SDL_systimer.c @@ -186,7 +186,19 @@ SDL_GetPerformanceFrequency(void) return frequency.QuadPart; } -#ifdef __WINRT__ +/* Sleep() is not publicly available to apps in early versions of WinRT. + * + * Visual C++ 2013 Update 4 re-introduced Sleep() for Windows 8.1 and + * Windows Phone 8.1. + * + * Use the compiler version to determine availability. + * + * NOTE #1: _MSC_FULL_VER == 180030723 for Visual C++ 2013 Update 3. + * NOTE #2: Visual C++ 2013, when compiling for Windows 8.0 and + * Windows Phone 8.0, uses the Visual C++ 2012 compiler to build + * apps and libraries. + */ +#if defined(__WINRT__) && defined(_MSC_FULL_VER) && (_MSC_FULL_VER <= 180030723) static void Sleep(DWORD timeout) { diff --git a/src/video/winrt/SDL_winrtopengles.cpp b/src/video/winrt/SDL_winrtopengles.cpp index 4a84174d0..e3a955be1 100644 --- a/src/video/winrt/SDL_winrtopengles.cpp +++ b/src/video/winrt/SDL_winrtopengles.cpp @@ -36,7 +36,10 @@ using namespace Windows::UI::Core; /* ANGLE/WinRT constants */ static const int ANGLE_D3D_FEATURE_LEVEL_ANY = 0; - +#define EGL_PLATFORM_ANGLE_ANGLE 0x3201 +#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3202 +#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3203 +#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3205 /* * SDL/EGL top-level implementation @@ -52,32 +55,56 @@ WINRT_GLES_LoadLibrary(_THIS, const char *path) } /* Load ANGLE/WinRT-specific functions */ - CreateWinrtEglWindow_Function CreateWinrtEglWindow = (CreateWinrtEglWindow_Function) SDL_LoadFunction(_this->egl_data->egl_dll_handle, "CreateWinrtEglWindow"); - if (!CreateWinrtEglWindow) { - return SDL_SetError("Could not retrieve ANGLE/WinRT function CreateWinrtEglWindow"); + CreateWinrtEglWindow_Old_Function CreateWinrtEglWindow = (CreateWinrtEglWindow_Old_Function) SDL_LoadFunction(_this->egl_data->egl_dll_handle, "CreateWinrtEglWindow"); + if (CreateWinrtEglWindow) { + /* 'CreateWinrtEglWindow' was found, which means that an an older + * version of ANGLE/WinRT is being used. Continue setting up EGL, + * as appropriate to this version of ANGLE. + */ + + /* Create an ANGLE/WinRT EGL-window */ + /* TODO, WinRT: check for XAML usage before accessing the CoreWindow, as not doing so could lead to a crash */ + CoreWindow ^ native_win = CoreWindow::GetForCurrentThread(); + Microsoft::WRL::ComPtr cpp_win = reinterpret_cast(native_win); + HRESULT result = CreateWinrtEglWindow(cpp_win, ANGLE_D3D_FEATURE_LEVEL_ANY, &(video_data->winrtEglWindow)); + if (FAILED(result)) { + return -1; + } + + /* Call eglGetDisplay and eglInitialize as appropriate. On other + * platforms, this would probably get done by SDL_EGL_LoadLibrary, + * however ANGLE/WinRT's current implementation (as of Mar 22, 2014) of + * eglGetDisplay requires that a C++ object be passed into it, so the + * call will be made in this file, a C++ file, instead. + */ + Microsoft::WRL::ComPtr cpp_display = video_data->winrtEglWindow; + _this->egl_data->egl_display = ((eglGetDisplay_Old_Function)_this->egl_data->eglGetDisplay)(cpp_display); + if (!_this->egl_data->egl_display) { + return SDL_SetError("Could not get EGL display"); + } + } else { + const EGLint displayAttributes[] = { + EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, + EGL_NONE, + }; + + /* 'CreateWinrtEglWindow' was NOT found, which either means that a + * newer version of ANGLE/WinRT is being used, or that we don't have + * a valid copy of ANGLE. + * + * Try loading ANGLE as if it were the newer version. + */ + eglGetPlatformDisplayEXT_Function eglGetPlatformDisplayEXT = (eglGetPlatformDisplayEXT_Function)_this->egl_data->eglGetProcAddress("eglGetPlatformDisplayEXT"); + if (!eglGetPlatformDisplayEXT) { + return SDL_SetError("Could not retrieve ANGLE/WinRT display function(s)"); + } + + _this->egl_data->egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, displayAttributes); + if (!_this->egl_data->egl_display) { + return SDL_SetError("Could not get EGL display"); + } } - /* Create an ANGLE/WinRT EGL-window */ - /* TODO, WinRT: check for XAML usage before accessing the CoreWindow, as not doing so could lead to a crash */ - CoreWindow ^ native_win = CoreWindow::GetForCurrentThread(); - Microsoft::WRL::ComPtr cpp_win = reinterpret_cast(native_win); - HRESULT result = CreateWinrtEglWindow(cpp_win, ANGLE_D3D_FEATURE_LEVEL_ANY, &(video_data->winrtEglWindow)); - if (FAILED(result)) { - return -1; - } - - /* Call eglGetDisplay and eglInitialize as appropriate. On other - * platforms, this would probably get done by SDL_EGL_LoadLibrary, - * however ANGLE/WinRT's current implementation (as of Mar 22, 2014) of - * eglGetDisplay requires that a C++ object be passed into it, so the - * call will be made in this file, a C++ file, instead. - */ - Microsoft::WRL::ComPtr cpp_display = video_data->winrtEglWindow; - _this->egl_data->egl_display = ((eglGetDisplay_Function)_this->egl_data->eglGetDisplay)(cpp_display); - if (!_this->egl_data->egl_display) { - return SDL_SetError("Could not get EGL display"); - } - if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) { return SDL_SetError("Could not initialize EGL"); } diff --git a/src/video/winrt/SDL_winrtopengles.h b/src/video/winrt/SDL_winrtopengles.h index ae1739171..f090f9b26 100644 --- a/src/video/winrt/SDL_winrtopengles.h +++ b/src/video/winrt/SDL_winrtopengles.h @@ -47,18 +47,22 @@ extern int WINRT_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext cont /* Typedefs for ANGLE/WinRT's C++-based native-display and native-window types, * which are used when calling eglGetDisplay and eglCreateWindowSurface. */ -typedef Microsoft::WRL::ComPtr WINRT_EGLNativeWindowType; -typedef WINRT_EGLNativeWindowType WINRT_EGLNativeDisplayType; +typedef Microsoft::WRL::ComPtr WINRT_EGLNativeWindowType_Old; -/* Function pointer typedefs for ANGLE/WinRT's functions that require - * parameter customization [by passing in C++ objects]. +/* Function pointer typedefs for 'old' ANGLE/WinRT's functions, which may + * require that C++ objects be passed in: */ -typedef EGLDisplay (EGLAPIENTRY *eglGetDisplay_Function)(WINRT_EGLNativeWindowType); -typedef EGLSurface (EGLAPIENTRY *eglCreateWindowSurface_Function)(EGLDisplay, EGLConfig, WINRT_EGLNativeWindowType, const EGLint *); -typedef HRESULT (EGLAPIENTRY *CreateWinrtEglWindow_Function)(Microsoft::WRL::ComPtr, int, IUnknown ** result); +typedef EGLDisplay (EGLAPIENTRY *eglGetDisplay_Old_Function)(WINRT_EGLNativeWindowType_Old); +typedef EGLSurface (EGLAPIENTRY *eglCreateWindowSurface_Old_Function)(EGLDisplay, EGLConfig, WINRT_EGLNativeWindowType_Old, const EGLint *); +typedef HRESULT (EGLAPIENTRY *CreateWinrtEglWindow_Old_Function)(Microsoft::WRL::ComPtr, int, IUnknown ** result); #endif /* __cplusplus */ +/* Function pointer typedefs for 'new' ANGLE/WinRT functions, which, unlike + * the old functions, do not require C++ support and work with plain C. + */ +typedef EGLDisplay (EGLAPIENTRY *eglGetPlatformDisplayEXT_Function)(EGLenum, void *, const EGLint *); + #endif /* SDL_VIDEO_DRIVER_WINRT && SDL_VIDEO_OPENGL_EGL */ #endif /* _SDL_winrtopengles_h */ diff --git a/src/video/winrt/SDL_winrtpointerinput.cpp b/src/video/winrt/SDL_winrtpointerinput.cpp index a2f7e4b54..d0494b097 100644 --- a/src/video/winrt/SDL_winrtpointerinput.cpp +++ b/src/video/winrt/SDL_winrtpointerinput.cpp @@ -262,7 +262,7 @@ WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Input::PointerPo if ( ! WINRT_IsTouchEvent(pointerPoint)) { SDL_SendMouseMotion(window, 0, 0, (int)windowPoint.X, (int)windowPoint.Y); - } else if (pointerPoint->PointerId == WINRT_LeftFingerDown) { + } else { if (pointerPoint->PointerId == WINRT_LeftFingerDown) { SDL_SendMouseMotion(window, 0, 0, (int)windowPoint.X, (int)windowPoint.Y); } diff --git a/src/video/winrt/SDL_winrtvideo.cpp b/src/video/winrt/SDL_winrtvideo.cpp index 6ec01609a..038a26d9f 100644 --- a/src/video/winrt/SDL_winrtvideo.cpp +++ b/src/video/winrt/SDL_winrtvideo.cpp @@ -318,9 +318,9 @@ WINRT_CreateWindow(_THIS, SDL_Window * window) SDL_VideoData * video_data = (SDL_VideoData *)_this->driverdata; /* Call SDL_EGL_ChooseConfig and eglCreateWindowSurface directly, - * rather than via SDL_EGL_CreateSurface, as ANGLE/WinRT requires - * a C++ object, ComPtr, to be passed into - * eglCreateWindowSurface. + * rather than via SDL_EGL_CreateSurface, as older versions of + * ANGLE/WinRT may require that a C++ object, ComPtr, + * be passed into eglCreateWindowSurface. */ if (SDL_EGL_ChooseConfig(_this) != 0) { char buf[512]; @@ -328,13 +328,33 @@ WINRT_CreateWindow(_THIS, SDL_Window * window) return SDL_SetError(buf); } - Microsoft::WRL::ComPtr cpp_winrtEglWindow = video_data->winrtEglWindow; - data->egl_surface = ((eglCreateWindowSurface_Function)_this->egl_data->eglCreateWindowSurface)( - _this->egl_data->egl_display, - _this->egl_data->egl_config, - cpp_winrtEglWindow, NULL); - if (data->egl_surface == NULL) { - return SDL_SetError("eglCreateWindowSurface failed"); + if (video_data->winrtEglWindow) { /* ... is the 'old' version of ANGLE/WinRT being used? */ + /* Attempt to create a window surface using older versions of + * ANGLE/WinRT: + */ + Microsoft::WRL::ComPtr cpp_winrtEglWindow = video_data->winrtEglWindow; + data->egl_surface = ((eglCreateWindowSurface_Old_Function)_this->egl_data->eglCreateWindowSurface)( + _this->egl_data->egl_display, + _this->egl_data->egl_config, + cpp_winrtEglWindow, NULL); + if (data->egl_surface == NULL) { + return SDL_SetError("eglCreateWindowSurface failed"); + } + } else if (data->coreWindow.Get() != nullptr) { + /* Attempt to create a window surface using newer versions of + * ANGLE/WinRT: + */ + IInspectable * coreWindowAsIInspectable = reinterpret_cast(data->coreWindow.Get()); + data->egl_surface = _this->egl_data->eglCreateWindowSurface( + _this->egl_data->egl_display, + _this->egl_data->egl_config, + coreWindowAsIInspectable, + NULL); + if (data->egl_surface == NULL) { + return SDL_SetError("eglCreateWindowSurface failed"); + } + } else { + return SDL_SetError("No supported means to create an EGL window surface are available"); } } #endif @@ -394,6 +414,7 @@ WINRT_DestroyWindow(_THIS, SDL_Window * window) // Delete the internal window data: delete data; data = NULL; + window->driverdata = NULL; } } diff --git a/src/video/x11/SDL_x11mouse.c b/src/video/x11/SDL_x11mouse.c index 02d96da77..6a0207e90 100644 --- a/src/video/x11/SDL_x11mouse.c +++ b/src/video/x11/SDL_x11mouse.c @@ -378,12 +378,18 @@ X11_GetGlobalMouseState(int *x, int *y) int rootx, rooty, winx, winy; unsigned int mask; if (X11_XQueryPointer(display, RootWindow(display, data->screen), &root, &child, &rootx, &rooty, &winx, &winy, &mask)) { + XWindowAttributes root_attrs; Uint32 retval = 0; retval |= (mask & Button1Mask) ? SDL_BUTTON_LMASK : 0; retval |= (mask & Button2Mask) ? SDL_BUTTON_MMASK : 0; retval |= (mask & Button3Mask) ? SDL_BUTTON_RMASK : 0; - *x = data->x + rootx; - *y = data->y + rooty; + /* SDL_DisplayData->x,y point to screen origin, and adding them to mouse coordinates relative to root window doesn't do the right thing + * (observed on dual monitor setup with primary display being the rightmost one - mouse was offset to the right). + * + * Adding root position to root-relative coordinates seems to be a better way to get absolute position. */ + X11_XGetWindowAttributes(display, root, &root_attrs); + *x = root_attrs.x + rootx; + *y = root_attrs.y + rooty; return retval; } } diff --git a/test/testautomation_audio.c b/test/testautomation_audio.c index 06071566f..bef838dde 100644 --- a/test/testautomation_audio.c +++ b/test/testautomation_audio.c @@ -92,7 +92,7 @@ int audio_initQuitAudio() /* Loop over all available audio drivers */ iMax = SDL_GetNumAudioDrivers(); - SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers"); + SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers()"); SDLTest_AssertCheck(iMax > 0, "Validate number of audio drivers; expected: >0 got: %d", iMax); for (i = 0; i < iMax; i++) { audioDriver = SDL_GetAudioDriver(i); @@ -149,7 +149,7 @@ int audio_initOpenCloseQuitAudio() /* Loop over all available audio drivers */ iMax = SDL_GetNumAudioDrivers(); - SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers"); + SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers()"); SDLTest_AssertCheck(iMax > 0, "Validate number of audio drivers; expected: >0 got: %d", iMax); for (i = 0; i < iMax; i++) { audioDriver = SDL_GetAudioDriver(i); @@ -238,7 +238,7 @@ int audio_pauseUnpauseAudio() /* Loop over all available audio drivers */ iMax = SDL_GetNumAudioDrivers(); - SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers"); + SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers()"); SDLTest_AssertCheck(iMax > 0, "Validate number of audio drivers; expected: >0 got: %d", iMax); for (i = 0; i < iMax; i++) { audioDriver = SDL_GetAudioDriver(i); diff --git a/test/testautomation_rwops.c b/test/testautomation_rwops.c index 32aa7f60c..ac7902295 100644 --- a/test/testautomation_rwops.c +++ b/test/testautomation_rwops.c @@ -647,22 +647,22 @@ rwops_testFileWriteReadEndian(void) /* Write test data */ objectsWritten = SDL_WriteBE16(rw, BE16value); - SDLTest_AssertPass("Call to SDL_WriteBE16"); + SDLTest_AssertPass("Call to SDL_WriteBE16()"); SDLTest_AssertCheck(objectsWritten == 1, "Validate number of objects written, expected: 1, got: %i", objectsWritten); objectsWritten = SDL_WriteBE32(rw, BE32value); - SDLTest_AssertPass("Call to SDL_WriteBE32"); + SDLTest_AssertPass("Call to SDL_WriteBE32()"); SDLTest_AssertCheck(objectsWritten == 1, "Validate number of objects written, expected: 1, got: %i", objectsWritten); objectsWritten = SDL_WriteBE64(rw, BE64value); - SDLTest_AssertPass("Call to SDL_WriteBE64"); + SDLTest_AssertPass("Call to SDL_WriteBE64()"); SDLTest_AssertCheck(objectsWritten == 1, "Validate number of objects written, expected: 1, got: %i", objectsWritten); objectsWritten = SDL_WriteLE16(rw, LE16value); - SDLTest_AssertPass("Call to SDL_WriteLE16"); + SDLTest_AssertPass("Call to SDL_WriteLE16()"); SDLTest_AssertCheck(objectsWritten == 1, "Validate number of objects written, expected: 1, got: %i", objectsWritten); objectsWritten = SDL_WriteLE32(rw, LE32value); - SDLTest_AssertPass("Call to SDL_WriteLE32"); + SDLTest_AssertPass("Call to SDL_WriteLE32()"); SDLTest_AssertCheck(objectsWritten == 1, "Validate number of objects written, expected: 1, got: %i", objectsWritten); objectsWritten = SDL_WriteLE64(rw, LE64value); - SDLTest_AssertPass("Call to SDL_WriteLE64"); + SDLTest_AssertPass("Call to SDL_WriteLE64()"); SDLTest_AssertCheck(objectsWritten == 1, "Validate number of objects written, expected: 1, got: %i", objectsWritten); /* Test seek to start */ @@ -672,22 +672,22 @@ rwops_testFileWriteReadEndian(void) /* Read test data */ BE16test = SDL_ReadBE16(rw); - SDLTest_AssertPass("Call to SDL_ReadBE16"); + SDLTest_AssertPass("Call to SDL_ReadBE16()"); SDLTest_AssertCheck(BE16test == BE16value, "Validate return value from SDL_ReadBE16, expected: %hu, got: %hu", BE16value, BE16test); BE32test = SDL_ReadBE32(rw); - SDLTest_AssertPass("Call to SDL_ReadBE32"); + SDLTest_AssertPass("Call to SDL_ReadBE32()"); SDLTest_AssertCheck(BE32test == BE32value, "Validate return value from SDL_ReadBE32, expected: %u, got: %u", BE32value, BE32test); BE64test = SDL_ReadBE64(rw); - SDLTest_AssertPass("Call to SDL_ReadBE64"); + SDLTest_AssertPass("Call to SDL_ReadBE64()"); SDLTest_AssertCheck(BE64test == BE64value, "Validate return value from SDL_ReadBE64, expected: %llu, got: %llu", BE64value, BE64test); LE16test = SDL_ReadLE16(rw); - SDLTest_AssertPass("Call to SDL_ReadLE16"); + SDLTest_AssertPass("Call to SDL_ReadLE16()"); SDLTest_AssertCheck(LE16test == LE16value, "Validate return value from SDL_ReadLE16, expected: %hu, got: %hu", LE16value, LE16test); LE32test = SDL_ReadLE32(rw); - SDLTest_AssertPass("Call to SDL_ReadLE32"); + SDLTest_AssertPass("Call to SDL_ReadLE32()"); SDLTest_AssertCheck(LE32test == LE32value, "Validate return value from SDL_ReadLE32, expected: %u, got: %u", LE32value, LE32test); LE64test = SDL_ReadLE64(rw); - SDLTest_AssertPass("Call to SDL_ReadLE64"); + SDLTest_AssertPass("Call to SDL_ReadLE64()"); SDLTest_AssertCheck(LE64test == LE64value, "Validate return value from SDL_ReadLE64, expected: %llu, got: %llu", LE64value, LE64test); /* Close handle */ diff --git a/test/testautomation_surface.c b/test/testautomation_surface.c index b517c7730..d65351a66 100644 --- a/test/testautomation_surface.c +++ b/test/testautomation_surface.c @@ -614,7 +614,7 @@ static const SDLTest_TestCaseReference surfaceTest8 = /* TODO: rewrite test case, define new test data and re-enable; current implementation fails */ static const SDLTest_TestCaseReference surfaceTest9 = - { (SDLTest_TestCaseFp)surface_testBlitBlendLoop, "surface_testBlitBlendLoop", "Test blittin routines with verious blending modes", TEST_DISABLED}; + { (SDLTest_TestCaseFp)surface_testBlitBlendLoop, "surface_testBlitBlendLoop", "Test blitting routines with various blending modes", TEST_DISABLED}; /* TODO: rewrite test case, define new test data and re-enable; current implementation fails */ static const SDLTest_TestCaseReference surfaceTest10 = diff --git a/test/testautomation_syswm.c b/test/testautomation_syswm.c index 3e368f63e..d9fd982b3 100644 --- a/test/testautomation_syswm.c +++ b/test/testautomation_syswm.c @@ -32,7 +32,7 @@ syswm_getWindowWMInfo(void *arg) /* Make call */ result = SDL_GetWindowWMInfo(window, &info); - SDLTest_AssertPass("Call to SDL_GetWindowWMInfo"); + SDLTest_AssertPass("Call to SDL_GetWindowWMInfo()"); SDLTest_Log((result == SDL_TRUE) ? "Got window information" : "Couldn't get window information"); SDL_DestroyWindow(window); diff --git a/test/testautomation_video.c b/test/testautomation_video.c index 3a7bfca05..8a9fc4755 100644 --- a/test/testautomation_video.c +++ b/test/testautomation_video.c @@ -51,7 +51,7 @@ void _destroyVideoSuiteTestWindow(SDL_Window *window) if (window != NULL) { SDL_DestroyWindow(window); window = NULL; - SDLTest_AssertPass("Call to SDL_DestroyWindow"); + SDLTest_AssertPass("Call to SDL_DestroyWindow()"); } } @@ -342,7 +342,7 @@ video_getWindowFlags(void *arg) window = _createVideoSuiteTestWindow(title); if (window != NULL) { actualFlags = SDL_GetWindowFlags(window); - SDLTest_AssertPass("Call to SDL_GetWindowFlags"); + SDLTest_AssertPass("Call to SDL_GetWindowFlags()"); SDLTest_AssertCheck((flags & actualFlags) == flags, "Verify returned value has flags %d set, got: %d", flags, actualFlags); } @@ -364,7 +364,7 @@ video_getNumDisplayModes(void *arg) /* Get number of displays */ displayNum = SDL_GetNumVideoDisplays(); - SDLTest_AssertPass("Call to SDL_GetNumVideoDisplays"); + SDLTest_AssertPass("Call to SDL_GetNumVideoDisplays()"); /* Make call for each display */ for (i=0; i= 0.0 && result <= 1.0, "Validate range of result value; expected: [0.0, 1.0], got: %f", result); } @@ -583,7 +583,7 @@ video_getWindowDisplayMode(void *arg) window = _createVideoSuiteTestWindow(title); if (window != NULL) { result = SDL_GetWindowDisplayMode(window, &mode); - SDLTest_AssertPass("Call to SDL_GetWindowDisplayMode"); + SDLTest_AssertPass("Call to SDL_GetWindowDisplayMode()"); SDLTest_AssertCheck(result == 0, "Validate result value; expected: 0, got: %d", result); SDLTest_AssertCheck(mode.w > 0, "Validate mode.w content; expected: >0, got: %d", mode.w); SDLTest_AssertCheck(mode.h > 0, "Validate mode.h content; expected: >0, got: %d", mode.h);