src/render/direct3d11/SDL_render_d3d11.cpp
author Sam Lantinga <slouken@libsdl.org>
Sun, 09 Mar 2014 11:06:11 -0700
changeset 8582 c3e9a2b93517
parent 8575 97a2e1b1a019
permissions -rw-r--r--
Fixed line endings on WinRT source code
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2012 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 
    22 #include "SDL_config.h"
    23 
    24 #if SDL_VIDEO_RENDER_D3D11 && !SDL_RENDER_DISABLED
    25 
    26 #ifdef __WINRT__
    27 #include <windows.ui.core.h>
    28 #include <windows.foundation.h>
    29 
    30 #if WINAPI_FAMILY == WINAPI_FAMILY_APP
    31 #include <windows.ui.xaml.media.dxinterop.h>
    32 #endif
    33 
    34 #endif
    35 
    36 extern "C" {
    37 #include "../../core/windows/SDL_windows.h"
    38 #include "SDL_hints.h"
    39 #include "SDL_system.h"
    40 #include "SDL_syswm.h"
    41 #include "../SDL_sysrender.h"
    42 #include "../../video/SDL_sysvideo.h"
    43 }
    44 
    45 #include <string>
    46 #include <vector>
    47 
    48 #include <D3D11_1.h>
    49 #include <DirectXMath.h>
    50 #include <wrl/client.h>
    51 
    52 
    53 using namespace DirectX;
    54 using namespace Microsoft::WRL;
    55 using namespace std;
    56 
    57 #ifdef __WINRT__
    58 using namespace Windows::Graphics::Display;
    59 using namespace Windows::UI::Core;
    60 #endif
    61 
    62 /* Texture sampling types */
    63 static const D3D11_FILTER SDL_D3D11_NEAREST_PIXEL_FILTER = D3D11_FILTER_MIN_MAG_MIP_POINT;
    64 static const D3D11_FILTER SDL_D3D11_LINEAR_FILTER = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
    65 
    66 /* Vertex shader, common values */
    67 struct VertexShaderConstants
    68 {
    69     DirectX::XMFLOAT4X4 model;
    70     DirectX::XMFLOAT4X4 projectionAndView;
    71 };
    72 
    73 /* Per-vertex data */
    74 struct VertexPositionColor
    75 {
    76     DirectX::XMFLOAT3 pos;
    77     DirectX::XMFLOAT2 tex;
    78     DirectX::XMFLOAT4 color;
    79 };
    80 
    81 /* Per-texture data */
    82 typedef struct
    83 {
    84     Microsoft::WRL::ComPtr<ID3D11Texture2D> mainTexture;
    85     Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> mainTextureResourceView;
    86     Microsoft::WRL::ComPtr<ID3D11RenderTargetView> mainTextureRenderTargetView;
    87     SDL_PixelFormat * pixelFormat;
    88     Microsoft::WRL::ComPtr<ID3D11Texture2D> stagingTexture;
    89     DirectX::XMINT2 lockedTexturePosition;
    90     D3D11_FILTER scaleMode;
    91 } D3D11_TextureData;
    92 
    93 /* Private renderer data */
    94 typedef struct
    95 {
    96     Microsoft::WRL::ComPtr<ID3D11Device1> d3dDevice;
    97     Microsoft::WRL::ComPtr<ID3D11DeviceContext1> d3dContext;
    98     Microsoft::WRL::ComPtr<IDXGISwapChain1> swapChain;
    99     Microsoft::WRL::ComPtr<ID3D11RenderTargetView> mainRenderTargetView;
   100     Microsoft::WRL::ComPtr<ID3D11RenderTargetView> currentOffscreenRenderTargetView;
   101     Microsoft::WRL::ComPtr<ID3D11InputLayout> inputLayout;
   102     Microsoft::WRL::ComPtr<ID3D11Buffer> vertexBuffer;
   103     Microsoft::WRL::ComPtr<ID3D11VertexShader> vertexShader;
   104     Microsoft::WRL::ComPtr<ID3D11PixelShader> texturePixelShader;
   105     Microsoft::WRL::ComPtr<ID3D11PixelShader> colorPixelShader;
   106     Microsoft::WRL::ComPtr<ID3D11BlendState> blendModeBlend;
   107     Microsoft::WRL::ComPtr<ID3D11BlendState> blendModeAdd;
   108     Microsoft::WRL::ComPtr<ID3D11BlendState> blendModeMod;
   109     Microsoft::WRL::ComPtr<ID3D11SamplerState> nearestPixelSampler;
   110     Microsoft::WRL::ComPtr<ID3D11SamplerState> linearSampler;
   111     D3D_FEATURE_LEVEL featureLevel;
   112 
   113     // Rasterizers:
   114     // If this list starts to get unwieldy, then consider using a map<> of them.
   115     Microsoft::WRL::ComPtr<ID3D11RasterizerState> mainRasterizer;
   116     Microsoft::WRL::ComPtr<ID3D11RasterizerState> clippedRasterizer;
   117 
   118     // Vertex buffer constants:
   119     VertexShaderConstants vertexShaderConstantsData;
   120     Microsoft::WRL::ComPtr<ID3D11Buffer> vertexShaderConstants;
   121 
   122     // Cached renderer properties.
   123     DirectX::XMFLOAT2 windowSizeInDIPs;
   124     DirectX::XMFLOAT2 renderTargetSize;
   125     Windows::Graphics::Display::DisplayOrientations orientation;
   126 
   127     // Transform used for display orientation.
   128     DirectX::XMFLOAT4X4 orientationTransform3D;
   129 } D3D11_RenderData;
   130 
   131 
   132 /* Direct3D 11.x shaders
   133 
   134    SDL's shaders are compiled into SDL itself, to simplify distribution.
   135 
   136    All Direct3D 11.x shaders were compiled with the following:
   137 
   138    fxc /E"main" /T "<TYPE>" /Fo"<OUTPUT FILE>" "<INPUT FILE>"
   139 
   140      Variables:
   141      - <TYPE>: the type of shader.  A table of utilized shader types is
   142        listed below.
   143      - <OUTPUT FILE>: where to store compiled output
   144      - <INPUT FILE>: where to read shader source code from
   145 
   146      Shader types:
   147      - ps_4_0_level_9_1: Pixel shader for Windows 8+, including Windows RT
   148      - vs_4_0_level_9_1: Vertex shader for Windows 8+, including Windows RT
   149      - ps_4_0_level_9_3: Pixel shader for Windows Phone 8
   150      - vs_4_0_level_9_3: Vertex shader for Windows Phone 8
   151    
   152 
   153    Shader object code was converted to a list of DWORDs via the following
   154    *nix style command (available separately from Windows + MSVC):
   155 
   156      hexdump -v -e '6/4 "0x%08.8x, " "\n"' <FILE>
   157   */
   158 #if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
   159 #define D3D11_USE_SHADER_MODEL_4_0_level_9_3
   160 #else
   161 #define D3D11_USE_SHADER_MODEL_4_0_level_9_1
   162 #endif
   163 
   164 /* The texture-rendering pixel shader:
   165 
   166     --- D3D11_PixelShader_Textures.hlsl ---
   167     Texture2D theTexture : register(t0);
   168     SamplerState theSampler : register(s0);
   169 
   170     struct PixelShaderInput
   171     {
   172         float4 pos : SV_POSITION;
   173         float2 tex : TEXCOORD0;
   174         float4 color : COLOR0;
   175     };
   176 
   177     float4 main(PixelShaderInput input) : SV_TARGET
   178     {
   179         return theTexture.Sample(theSampler, input.tex) * input.color;
   180     }
   181 */
   182 #if defined(D3D11_USE_SHADER_MODEL_4_0_level_9_1)
   183 static const DWORD D3D11_PixelShader_Textures[] = {
   184     0x43425844, 0x6299b59f, 0x155258f2, 0x873ab86a, 0xfcbb6dcd, 0x00000001,
   185     0x00000330, 0x00000006, 0x00000038, 0x000000c0, 0x0000015c, 0x000001d8,
   186     0x00000288, 0x000002fc, 0x396e6f41, 0x00000080, 0x00000080, 0xffff0200,
   187     0x00000058, 0x00000028, 0x00280000, 0x00280000, 0x00280000, 0x00240001,
   188     0x00280000, 0x00000000, 0xffff0200, 0x0200001f, 0x80000000, 0xb0030000,
   189     0x0200001f, 0x80000000, 0xb00f0001, 0x0200001f, 0x90000000, 0xa00f0800,
   190     0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800, 0x03000005, 0x800f0000,
   191     0x80e40000, 0xb0e40001, 0x02000001, 0x800f0800, 0x80e40000, 0x0000ffff,
   192     0x52444853, 0x00000094, 0x00000040, 0x00000025, 0x0300005a, 0x00106000,
   193     0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x03001062,
   194     0x00101032, 0x00000001, 0x03001062, 0x001010f2, 0x00000002, 0x03000065,
   195     0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x09000045, 0x001000f2,
   196     0x00000000, 0x00101046, 0x00000001, 0x00107e46, 0x00000000, 0x00106000,
   197     0x00000000, 0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000,
   198     0x00101e46, 0x00000002, 0x0100003e, 0x54415453, 0x00000074, 0x00000003,
   199     0x00000001, 0x00000000, 0x00000003, 0x00000001, 0x00000000, 0x00000000,
   200     0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
   201     0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
   202     0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
   203     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x46454452, 0x000000a8,
   204     0x00000000, 0x00000000, 0x00000002, 0x0000001c, 0xffff0400, 0x00000100,
   205     0x00000072, 0x0000005c, 0x00000003, 0x00000000, 0x00000000, 0x00000000,
   206     0x00000000, 0x00000001, 0x00000001, 0x00000067, 0x00000002, 0x00000005,
   207     0x00000004, 0xffffffff, 0x00000000, 0x00000001, 0x0000000d, 0x53656874,
   208     0x6c706d61, 0x74007265, 0x65546568, 0x72757478, 0x694d0065, 0x736f7263,
   209     0x2074666f, 0x20295228, 0x4c534c48, 0x61685320, 0x20726564, 0x706d6f43,
   210     0x72656c69, 0x332e3920, 0x32392e30, 0x312e3030, 0x34383336, 0xababab00,
   211     0x4e475349, 0x0000006c, 0x00000003, 0x00000008, 0x00000050, 0x00000000,
   212     0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000000,
   213     0x00000000, 0x00000003, 0x00000001, 0x00000303, 0x00000065, 0x00000000,
   214     0x00000000, 0x00000003, 0x00000002, 0x00000f0f, 0x505f5653, 0x5449534f,
   215     0x004e4f49, 0x43584554, 0x44524f4f, 0x4c4f4300, 0xab00524f, 0x4e47534f,
   216     0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
   217     0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054
   218 };
   219 #elif defined(D3D11_USE_SHADER_MODEL_4_0_level_9_3)
   220 static const DWORD D3D11_PixelShader_Textures[] = {
   221     0x43425844, 0x5876569a, 0x01b6c87e, 0x8447454f, 0xc7f3ef10, 0x00000001,
   222     0x00000330, 0x00000006, 0x00000038, 0x000000c0, 0x0000015c, 0x000001d8,
   223     0x00000288, 0x000002fc, 0x396e6f41, 0x00000080, 0x00000080, 0xffff0200,
   224     0x00000058, 0x00000028, 0x00280000, 0x00280000, 0x00280000, 0x00240001,
   225     0x00280000, 0x00000000, 0xffff0201, 0x0200001f, 0x80000000, 0xb0030000,
   226     0x0200001f, 0x80000000, 0xb00f0001, 0x0200001f, 0x90000000, 0xa00f0800,
   227     0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800, 0x03000005, 0x800f0000,
   228     0x80e40000, 0xb0e40001, 0x02000001, 0x800f0800, 0x80e40000, 0x0000ffff,
   229     0x52444853, 0x00000094, 0x00000040, 0x00000025, 0x0300005a, 0x00106000,
   230     0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x03001062,
   231     0x00101032, 0x00000001, 0x03001062, 0x001010f2, 0x00000002, 0x03000065,
   232     0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x09000045, 0x001000f2,
   233     0x00000000, 0x00101046, 0x00000001, 0x00107e46, 0x00000000, 0x00106000,
   234     0x00000000, 0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000,
   235     0x00101e46, 0x00000002, 0x0100003e, 0x54415453, 0x00000074, 0x00000003,
   236     0x00000001, 0x00000000, 0x00000003, 0x00000001, 0x00000000, 0x00000000,
   237     0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
   238     0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
   239     0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
   240     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x46454452, 0x000000a8,
   241     0x00000000, 0x00000000, 0x00000002, 0x0000001c, 0xffff0400, 0x00000100,
   242     0x00000072, 0x0000005c, 0x00000003, 0x00000000, 0x00000000, 0x00000000,
   243     0x00000000, 0x00000001, 0x00000001, 0x00000067, 0x00000002, 0x00000005,
   244     0x00000004, 0xffffffff, 0x00000000, 0x00000001, 0x0000000d, 0x53656874,
   245     0x6c706d61, 0x74007265, 0x65546568, 0x72757478, 0x694d0065, 0x736f7263,
   246     0x2074666f, 0x20295228, 0x4c534c48, 0x61685320, 0x20726564, 0x706d6f43,
   247     0x72656c69, 0x332e3920, 0x32392e30, 0x312e3030, 0x34383336, 0xababab00,
   248     0x4e475349, 0x0000006c, 0x00000003, 0x00000008, 0x00000050, 0x00000000,
   249     0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000000,
   250     0x00000000, 0x00000003, 0x00000001, 0x00000303, 0x00000065, 0x00000000,
   251     0x00000000, 0x00000003, 0x00000002, 0x00000f0f, 0x505f5653, 0x5449534f,
   252     0x004e4f49, 0x43584554, 0x44524f4f, 0x4c4f4300, 0xab00524f, 0x4e47534f,
   253     0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
   254     0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054
   255 };
   256 #else
   257 #error "An appropriate 'textures' pixel shader is not defined"
   258 #endif
   259 
   260 /* The color-only-rendering pixel shader:
   261 
   262    --- D3D11_PixelShader_Colors.hlsl ---
   263    struct PixelShaderInput
   264    {
   265        float4 pos : SV_POSITION;
   266        float2 tex : TEXCOORD0;
   267        float4 color : COLOR0;
   268    };
   269 
   270    float4 main(PixelShaderInput input) : SV_TARGET
   271    {
   272        return input.color;
   273    }
   274 */
   275 #if defined(D3D11_USE_SHADER_MODEL_4_0_level_9_1)
   276 static const DWORD D3D11_PixelShader_Colors[] = {
   277     0x43425844, 0xd74c28fe, 0xa1eb8804, 0x269d512a, 0x7699723d, 0x00000001,
   278     0x00000240, 0x00000006, 0x00000038, 0x00000084, 0x000000c4, 0x00000140,
   279     0x00000198, 0x0000020c, 0x396e6f41, 0x00000044, 0x00000044, 0xffff0200,
   280     0x00000020, 0x00000024, 0x00240000, 0x00240000, 0x00240000, 0x00240000,
   281     0x00240000, 0xffff0200, 0x0200001f, 0x80000000, 0xb00f0001, 0x02000001,
   282     0x800f0800, 0xb0e40001, 0x0000ffff, 0x52444853, 0x00000038, 0x00000040,
   283     0x0000000e, 0x03001062, 0x001010f2, 0x00000002, 0x03000065, 0x001020f2,
   284     0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000002,
   285     0x0100003e, 0x54415453, 0x00000074, 0x00000002, 0x00000000, 0x00000000,
   286     0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000,
   287     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
   288     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0x00000000,
   289     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
   290     0x00000000, 0x00000000, 0x46454452, 0x00000050, 0x00000000, 0x00000000,
   291     0x00000000, 0x0000001c, 0xffff0400, 0x00000100, 0x0000001c, 0x7263694d,
   292     0x666f736f, 0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072,
   293     0x6c69706d, 0x39207265, 0x2e30332e, 0x30303239, 0x3336312e, 0xab003438,
   294     0x4e475349, 0x0000006c, 0x00000003, 0x00000008, 0x00000050, 0x00000000,
   295     0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000000,
   296     0x00000000, 0x00000003, 0x00000001, 0x00000003, 0x00000065, 0x00000000,
   297     0x00000000, 0x00000003, 0x00000002, 0x00000f0f, 0x505f5653, 0x5449534f,
   298     0x004e4f49, 0x43584554, 0x44524f4f, 0x4c4f4300, 0xab00524f, 0x4e47534f,
   299     0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
   300     0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054
   301 };
   302 #elif defined(D3D11_USE_SHADER_MODEL_4_0_level_9_3)
   303 static const DWORD D3D11_PixelShader_Colors[] = {
   304     0x43425844, 0x93f6ccfc, 0x5f919270, 0x7a11aa4f, 0x9148e931, 0x00000001,
   305     0x00000240, 0x00000006, 0x00000038, 0x00000084, 0x000000c4, 0x00000140,
   306     0x00000198, 0x0000020c, 0x396e6f41, 0x00000044, 0x00000044, 0xffff0200,
   307     0x00000020, 0x00000024, 0x00240000, 0x00240000, 0x00240000, 0x00240000,
   308     0x00240000, 0xffff0201, 0x0200001f, 0x80000000, 0xb00f0001, 0x02000001,
   309     0x800f0800, 0xb0e40001, 0x0000ffff, 0x52444853, 0x00000038, 0x00000040,
   310     0x0000000e, 0x03001062, 0x001010f2, 0x00000002, 0x03000065, 0x001020f2,
   311     0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000002,
   312     0x0100003e, 0x54415453, 0x00000074, 0x00000002, 0x00000000, 0x00000000,
   313     0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000,
   314     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
   315     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0x00000000,
   316     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
   317     0x00000000, 0x00000000, 0x46454452, 0x00000050, 0x00000000, 0x00000000,
   318     0x00000000, 0x0000001c, 0xffff0400, 0x00000100, 0x0000001c, 0x7263694d,
   319     0x666f736f, 0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072,
   320     0x6c69706d, 0x39207265, 0x2e30332e, 0x30303239, 0x3336312e, 0xab003438,
   321     0x4e475349, 0x0000006c, 0x00000003, 0x00000008, 0x00000050, 0x00000000,
   322     0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000000,
   323     0x00000000, 0x00000003, 0x00000001, 0x00000003, 0x00000065, 0x00000000,
   324     0x00000000, 0x00000003, 0x00000002, 0x00000f0f, 0x505f5653, 0x5449534f,
   325     0x004e4f49, 0x43584554, 0x44524f4f, 0x4c4f4300, 0xab00524f, 0x4e47534f,
   326     0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
   327     0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054
   328 };
   329 #else
   330 #error "An appropriate 'colors' pixel shader is not defined."
   331 #endif
   332 
   333 /* The sole vertex shader:
   334 
   335    --- D3D11_VertexShader.hlsl ---
   336    #pragma pack_matrix( row_major )
   337 
   338    cbuffer VertexShaderConstants : register(b0)
   339    {
   340        matrix model;
   341        matrix projectionAndView;
   342    };
   343 
   344    struct VertexShaderInput
   345    {
   346        float3 pos : POSITION;
   347        float2 tex : TEXCOORD0;
   348        float4 color : COLOR0;
   349    };
   350 
   351    struct VertexShaderOutput
   352    {
   353        float4 pos : SV_POSITION;
   354        float2 tex : TEXCOORD0;
   355        float4 color : COLOR0;
   356    };
   357 
   358    VertexShaderOutput main(VertexShaderInput input)
   359    {
   360        VertexShaderOutput output;
   361        float4 pos = float4(input.pos, 1.0f);
   362 
   363        // Transform the vertex position into projected space.
   364        pos = mul(pos, model);
   365        pos = mul(pos, projectionAndView);
   366        output.pos = pos;
   367 
   368        // Pass through texture coordinates and color values without transformation
   369        output.tex = input.tex;
   370        output.color = input.color;
   371 
   372        return output;
   373    }
   374 */
   375 #if defined(D3D11_USE_SHADER_MODEL_4_0_level_9_1)
   376 static const DWORD D3D11_VertexShader[] = {
   377     0x43425844, 0x62dfae5f, 0x3e8bd8df, 0x9ec97127, 0x5044eefb, 0x00000001,
   378     0x00000598, 0x00000006, 0x00000038, 0x0000016c, 0x00000334, 0x000003b0,
   379     0x000004b4, 0x00000524, 0x396e6f41, 0x0000012c, 0x0000012c, 0xfffe0200,
   380     0x000000f8, 0x00000034, 0x00240001, 0x00300000, 0x00300000, 0x00240000,
   381     0x00300001, 0x00000000, 0x00010008, 0x00000000, 0x00000000, 0xfffe0200,
   382     0x0200001f, 0x80000005, 0x900f0000, 0x0200001f, 0x80010005, 0x900f0001,
   383     0x0200001f, 0x80020005, 0x900f0002, 0x03000005, 0x800f0000, 0x90550000,
   384     0xa0e40002, 0x04000004, 0x800f0000, 0x90000000, 0xa0e40001, 0x80e40000,
   385     0x04000004, 0x800f0000, 0x90aa0000, 0xa0e40003, 0x80e40000, 0x03000002,
   386     0x800f0000, 0x80e40000, 0xa0e40004, 0x03000005, 0x800f0001, 0x80550000,
   387     0xa0e40006, 0x04000004, 0x800f0001, 0x80000000, 0xa0e40005, 0x80e40001,
   388     0x04000004, 0x800f0001, 0x80aa0000, 0xa0e40007, 0x80e40001, 0x04000004,
   389     0x800f0000, 0x80ff0000, 0xa0e40008, 0x80e40001, 0x04000004, 0xc0030000,
   390     0x80ff0000, 0xa0e40000, 0x80e40000, 0x02000001, 0xc00c0000, 0x80e40000,
   391     0x02000001, 0xe0030000, 0x90e40001, 0x02000001, 0xe00f0001, 0x90e40002,
   392     0x0000ffff, 0x52444853, 0x000001c0, 0x00010040, 0x00000070, 0x04000059,
   393     0x00208e46, 0x00000000, 0x00000008, 0x0300005f, 0x00101072, 0x00000000,
   394     0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x001010f2, 0x00000002,
   395     0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x00102032,
   396     0x00000001, 0x03000065, 0x001020f2, 0x00000002, 0x02000068, 0x00000002,
   397     0x08000038, 0x001000f2, 0x00000000, 0x00101556, 0x00000000, 0x00208e46,
   398     0x00000000, 0x00000001, 0x0a000032, 0x001000f2, 0x00000000, 0x00101006,
   399     0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x00100e46, 0x00000000,
   400     0x0a000032, 0x001000f2, 0x00000000, 0x00101aa6, 0x00000000, 0x00208e46,
   401     0x00000000, 0x00000002, 0x00100e46, 0x00000000, 0x08000000, 0x001000f2,
   402     0x00000000, 0x00100e46, 0x00000000, 0x00208e46, 0x00000000, 0x00000003,
   403     0x08000038, 0x001000f2, 0x00000001, 0x00100556, 0x00000000, 0x00208e46,
   404     0x00000000, 0x00000005, 0x0a000032, 0x001000f2, 0x00000001, 0x00100006,
   405     0x00000000, 0x00208e46, 0x00000000, 0x00000004, 0x00100e46, 0x00000001,
   406     0x0a000032, 0x001000f2, 0x00000001, 0x00100aa6, 0x00000000, 0x00208e46,
   407     0x00000000, 0x00000006, 0x00100e46, 0x00000001, 0x0a000032, 0x001020f2,
   408     0x00000000, 0x00100ff6, 0x00000000, 0x00208e46, 0x00000000, 0x00000007,
   409     0x00100e46, 0x00000001, 0x05000036, 0x00102032, 0x00000001, 0x00101046,
   410     0x00000001, 0x05000036, 0x001020f2, 0x00000002, 0x00101e46, 0x00000002,
   411     0x0100003e, 0x54415453, 0x00000074, 0x0000000b, 0x00000002, 0x00000000,
   412     0x00000006, 0x00000003, 0x00000000, 0x00000000, 0x00000001, 0x00000000,
   413     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
   414     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000000,
   415     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
   416     0x00000000, 0x00000000, 0x46454452, 0x000000fc, 0x00000001, 0x00000054,
   417     0x00000001, 0x0000001c, 0xfffe0400, 0x00000100, 0x000000c6, 0x0000003c,
   418     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
   419     0x00000001, 0x74726556, 0x68537865, 0x72656461, 0x736e6f43, 0x746e6174,
   420     0xabab0073, 0x0000003c, 0x00000002, 0x0000006c, 0x00000080, 0x00000000,
   421     0x00000000, 0x0000009c, 0x00000000, 0x00000040, 0x00000002, 0x000000a4,
   422     0x00000000, 0x000000b4, 0x00000040, 0x00000040, 0x00000002, 0x000000a4,
   423     0x00000000, 0x65646f6d, 0xabab006c, 0x00030002, 0x00040004, 0x00000000,
   424     0x00000000, 0x6a6f7270, 0x69746365, 0x6e416e6f, 0x65695664, 0x694d0077,
   425     0x736f7263, 0x2074666f, 0x20295228, 0x4c534c48, 0x61685320, 0x20726564,
   426     0x706d6f43, 0x72656c69, 0x332e3920, 0x32392e30, 0x312e3030, 0x34383336,
   427     0xababab00, 0x4e475349, 0x00000068, 0x00000003, 0x00000008, 0x00000050,
   428     0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000707, 0x00000059,
   429     0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000303, 0x00000062,
   430     0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000f0f, 0x49534f50,
   431     0x4e4f4954, 0x58455400, 0x524f4f43, 0x4f430044, 0x00524f4c, 0x4e47534f,
   432     0x0000006c, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000001,
   433     0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, 0x00000000,
   434     0x00000003, 0x00000001, 0x00000c03, 0x00000065, 0x00000000, 0x00000000,
   435     0x00000003, 0x00000002, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49,
   436     0x43584554, 0x44524f4f, 0x4c4f4300, 0xab00524f
   437 };
   438 #elif defined(D3D11_USE_SHADER_MODEL_4_0_level_9_3)
   439 static const DWORD D3D11_VertexShader[] = {
   440     0x43425844, 0x01a24e41, 0x696af551, 0x4b2a87d1, 0x82ea03f6, 0x00000001,
   441     0x00000598, 0x00000006, 0x00000038, 0x0000016c, 0x00000334, 0x000003b0,
   442     0x000004b4, 0x00000524, 0x396e6f41, 0x0000012c, 0x0000012c, 0xfffe0200,
   443     0x000000f8, 0x00000034, 0x00240001, 0x00300000, 0x00300000, 0x00240000,
   444     0x00300001, 0x00000000, 0x00010008, 0x00000000, 0x00000000, 0xfffe0201,
   445     0x0200001f, 0x80000005, 0x900f0000, 0x0200001f, 0x80010005, 0x900f0001,
   446     0x0200001f, 0x80020005, 0x900f0002, 0x03000005, 0x800f0000, 0x90550000,
   447     0xa0e40002, 0x04000004, 0x800f0000, 0x90000000, 0xa0e40001, 0x80e40000,
   448     0x04000004, 0x800f0000, 0x90aa0000, 0xa0e40003, 0x80e40000, 0x03000002,
   449     0x800f0000, 0x80e40000, 0xa0e40004, 0x03000005, 0x800f0001, 0x80550000,
   450     0xa0e40006, 0x04000004, 0x800f0001, 0x80000000, 0xa0e40005, 0x80e40001,
   451     0x04000004, 0x800f0001, 0x80aa0000, 0xa0e40007, 0x80e40001, 0x04000004,
   452     0x800f0000, 0x80ff0000, 0xa0e40008, 0x80e40001, 0x04000004, 0xc0030000,
   453     0x80ff0000, 0xa0e40000, 0x80e40000, 0x02000001, 0xc00c0000, 0x80e40000,
   454     0x02000001, 0xe0030000, 0x90e40001, 0x02000001, 0xe00f0001, 0x90e40002,
   455     0x0000ffff, 0x52444853, 0x000001c0, 0x00010040, 0x00000070, 0x04000059,
   456     0x00208e46, 0x00000000, 0x00000008, 0x0300005f, 0x00101072, 0x00000000,
   457     0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x001010f2, 0x00000002,
   458     0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x00102032,
   459     0x00000001, 0x03000065, 0x001020f2, 0x00000002, 0x02000068, 0x00000002,
   460     0x08000038, 0x001000f2, 0x00000000, 0x00101556, 0x00000000, 0x00208e46,
   461     0x00000000, 0x00000001, 0x0a000032, 0x001000f2, 0x00000000, 0x00101006,
   462     0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x00100e46, 0x00000000,
   463     0x0a000032, 0x001000f2, 0x00000000, 0x00101aa6, 0x00000000, 0x00208e46,
   464     0x00000000, 0x00000002, 0x00100e46, 0x00000000, 0x08000000, 0x001000f2,
   465     0x00000000, 0x00100e46, 0x00000000, 0x00208e46, 0x00000000, 0x00000003,
   466     0x08000038, 0x001000f2, 0x00000001, 0x00100556, 0x00000000, 0x00208e46,
   467     0x00000000, 0x00000005, 0x0a000032, 0x001000f2, 0x00000001, 0x00100006,
   468     0x00000000, 0x00208e46, 0x00000000, 0x00000004, 0x00100e46, 0x00000001,
   469     0x0a000032, 0x001000f2, 0x00000001, 0x00100aa6, 0x00000000, 0x00208e46,
   470     0x00000000, 0x00000006, 0x00100e46, 0x00000001, 0x0a000032, 0x001020f2,
   471     0x00000000, 0x00100ff6, 0x00000000, 0x00208e46, 0x00000000, 0x00000007,
   472     0x00100e46, 0x00000001, 0x05000036, 0x00102032, 0x00000001, 0x00101046,
   473     0x00000001, 0x05000036, 0x001020f2, 0x00000002, 0x00101e46, 0x00000002,
   474     0x0100003e, 0x54415453, 0x00000074, 0x0000000b, 0x00000002, 0x00000000,
   475     0x00000006, 0x00000003, 0x00000000, 0x00000000, 0x00000001, 0x00000000,
   476     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
   477     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000000,
   478     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
   479     0x00000000, 0x00000000, 0x46454452, 0x000000fc, 0x00000001, 0x00000054,
   480     0x00000001, 0x0000001c, 0xfffe0400, 0x00000100, 0x000000c6, 0x0000003c,
   481     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
   482     0x00000001, 0x74726556, 0x68537865, 0x72656461, 0x736e6f43, 0x746e6174,
   483     0xabab0073, 0x0000003c, 0x00000002, 0x0000006c, 0x00000080, 0x00000000,
   484     0x00000000, 0x0000009c, 0x00000000, 0x00000040, 0x00000002, 0x000000a4,
   485     0x00000000, 0x000000b4, 0x00000040, 0x00000040, 0x00000002, 0x000000a4,
   486     0x00000000, 0x65646f6d, 0xabab006c, 0x00030002, 0x00040004, 0x00000000,
   487     0x00000000, 0x6a6f7270, 0x69746365, 0x6e416e6f, 0x65695664, 0x694d0077,
   488     0x736f7263, 0x2074666f, 0x20295228, 0x4c534c48, 0x61685320, 0x20726564,
   489     0x706d6f43, 0x72656c69, 0x332e3920, 0x32392e30, 0x312e3030, 0x34383336,
   490     0xababab00, 0x4e475349, 0x00000068, 0x00000003, 0x00000008, 0x00000050,
   491     0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000707, 0x00000059,
   492     0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000303, 0x00000062,
   493     0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000f0f, 0x49534f50,
   494     0x4e4f4954, 0x58455400, 0x524f4f43, 0x4f430044, 0x00524f4c, 0x4e47534f,
   495     0x0000006c, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000001,
   496     0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, 0x00000000,
   497     0x00000003, 0x00000001, 0x00000c03, 0x00000065, 0x00000000, 0x00000000,
   498     0x00000003, 0x00000002, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49,
   499     0x43584554, 0x44524f4f, 0x4c4f4300, 0xab00524f
   500 };
   501 #else
   502 #error "An appropriate vertex shader is not defined."
   503 #endif
   504 
   505 /* Direct3D 11.1 renderer implementation */
   506 static SDL_Renderer *D3D11_CreateRenderer(SDL_Window * window, Uint32 flags);
   507 static void D3D11_WindowEvent(SDL_Renderer * renderer,
   508                             const SDL_WindowEvent *event);
   509 static int D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
   510 static int D3D11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   511                              const SDL_Rect * rect, const void *srcPixels,
   512                              int srcPitch);
   513 static int D3D11_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   514                              const SDL_Rect * rect, void **pixels, int *pitch);
   515 static void D3D11_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
   516 static int D3D11_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture);
   517 static int D3D11_UpdateViewport(SDL_Renderer * renderer);
   518 static int D3D11_UpdateClipRect(SDL_Renderer * renderer);
   519 static int D3D11_RenderClear(SDL_Renderer * renderer);
   520 static int D3D11_RenderDrawPoints(SDL_Renderer * renderer,
   521                                   const SDL_FPoint * points, int count);
   522 static int D3D11_RenderDrawLines(SDL_Renderer * renderer,
   523                                  const SDL_FPoint * points, int count);
   524 static int D3D11_RenderFillRects(SDL_Renderer * renderer,
   525                                  const SDL_FRect * rects, int count);
   526 static int D3D11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
   527                             const SDL_Rect * srcrect, const SDL_FRect * dstrect);
   528 static int D3D11_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
   529                               const SDL_Rect * srcrect, const SDL_FRect * dstrect,
   530                               const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip);
   531 static int D3D11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
   532                                   Uint32 format, void * pixels, int pitch);
   533 static void D3D11_RenderPresent(SDL_Renderer * renderer);
   534 static void D3D11_DestroyTexture(SDL_Renderer * renderer,
   535                                  SDL_Texture * texture);
   536 static void D3D11_DestroyRenderer(SDL_Renderer * renderer);
   537 
   538 /* Direct3D 11.1 Internal Functions */
   539 HRESULT D3D11_CreateDeviceResources(SDL_Renderer * renderer);
   540 HRESULT D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer);
   541 HRESULT D3D11_UpdateForWindowSizeChange(SDL_Renderer * renderer);
   542 HRESULT D3D11_HandleDeviceLost(SDL_Renderer * renderer);
   543 
   544 extern "C" SDL_RenderDriver D3D11_RenderDriver = {
   545     D3D11_CreateRenderer,
   546     {
   547         "direct3d 11.1",
   548         (
   549             SDL_RENDERER_ACCELERATED |
   550             SDL_RENDERER_PRESENTVSYNC |
   551             SDL_RENDERER_TARGETTEXTURE
   552         ),                          // flags.  see SDL_RendererFlags
   553         2,                          // num_texture_formats
   554         {                           // texture_formats
   555             SDL_PIXELFORMAT_RGB888,
   556             SDL_PIXELFORMAT_ARGB8888
   557         },
   558         0,                          // max_texture_width: will be filled in later
   559         0                           // max_texture_height: will be filled in later
   560     }
   561 };
   562 
   563 
   564 static Uint32
   565 DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat) {
   566     switch (dxgiFormat) {
   567         case DXGI_FORMAT_B8G8R8A8_UNORM:
   568             return SDL_PIXELFORMAT_ARGB8888;
   569         case DXGI_FORMAT_B8G8R8X8_UNORM:
   570             return SDL_PIXELFORMAT_RGB888;
   571         default:
   572             return SDL_PIXELFORMAT_UNKNOWN;
   573     }
   574 }
   575 
   576 static DXGI_FORMAT
   577 SDLPixelFormatToDXGIFormat(Uint32 sdlFormat)
   578 {
   579     switch (sdlFormat) {
   580         case SDL_PIXELFORMAT_ARGB8888:
   581             return DXGI_FORMAT_B8G8R8A8_UNORM;
   582         case SDL_PIXELFORMAT_RGB888:
   583             return DXGI_FORMAT_B8G8R8X8_UNORM;
   584         default:
   585             return DXGI_FORMAT_UNKNOWN;
   586     }
   587 }
   588 
   589 SDL_Renderer *
   590 D3D11_CreateRenderer(SDL_Window * window, Uint32 flags)
   591 {
   592     SDL_Renderer *renderer;
   593     D3D11_RenderData *data;
   594 
   595     renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
   596     if (!renderer) {
   597         SDL_OutOfMemory();
   598         return NULL;
   599     }
   600     SDL_zerop(renderer);
   601 
   602     data = new D3D11_RenderData;    // Use the C++ 'new' operator to make sure the struct's members initialize using C++ rules
   603     if (!data) {
   604         SDL_OutOfMemory();
   605         return NULL;
   606     }
   607     data->featureLevel = (D3D_FEATURE_LEVEL) 0;
   608     data->windowSizeInDIPs = XMFLOAT2(0, 0);
   609     data->renderTargetSize = XMFLOAT2(0, 0);
   610 
   611     renderer->WindowEvent = D3D11_WindowEvent;
   612     renderer->CreateTexture = D3D11_CreateTexture;
   613     renderer->UpdateTexture = D3D11_UpdateTexture;
   614     renderer->LockTexture = D3D11_LockTexture;
   615     renderer->UnlockTexture = D3D11_UnlockTexture;
   616     renderer->SetRenderTarget = D3D11_SetRenderTarget;
   617     renderer->UpdateViewport = D3D11_UpdateViewport;
   618     renderer->UpdateClipRect = D3D11_UpdateClipRect;
   619     renderer->RenderClear = D3D11_RenderClear;
   620     renderer->RenderDrawPoints = D3D11_RenderDrawPoints;
   621     renderer->RenderDrawLines = D3D11_RenderDrawLines;
   622     renderer->RenderFillRects = D3D11_RenderFillRects;
   623     renderer->RenderCopy = D3D11_RenderCopy;
   624     renderer->RenderCopyEx = D3D11_RenderCopyEx;
   625     renderer->RenderReadPixels = D3D11_RenderReadPixels;
   626     renderer->RenderPresent = D3D11_RenderPresent;
   627     renderer->DestroyTexture = D3D11_DestroyTexture;
   628     renderer->DestroyRenderer = D3D11_DestroyRenderer;
   629     renderer->info = D3D11_RenderDriver.info;
   630     renderer->driverdata = data;
   631 
   632     // HACK: make sure the SDL_Renderer references the SDL_Window data now, in
   633     // order to give init functions access to the underlying window handle:
   634     renderer->window = window;
   635 
   636     /* Initialize Direct3D resources */
   637     if (FAILED(D3D11_CreateDeviceResources(renderer))) {
   638         D3D11_DestroyRenderer(renderer);
   639         return NULL;
   640     }
   641     if (FAILED(D3D11_CreateWindowSizeDependentResources(renderer))) {
   642         D3D11_DestroyRenderer(renderer);
   643         return NULL;
   644     }
   645 
   646     // TODO, WinRT: fill in renderer->info.texture_formats where appropriate
   647 
   648     return renderer;
   649 }
   650 
   651 static void
   652 D3D11_DestroyRenderer(SDL_Renderer * renderer)
   653 {
   654     D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
   655     if (data) {
   656         delete data;
   657         data = NULL;
   658     }
   659 }
   660 
   661 static HRESULT
   662 D3D11_CreateBlendMode(SDL_Renderer * renderer,
   663                       BOOL enableBlending,
   664                       D3D11_BLEND srcBlend,
   665                       D3D11_BLEND destBlend,
   666                       D3D11_BLEND srcBlendAlpha,
   667                       D3D11_BLEND destBlendAlpha,
   668                       ID3D11BlendState ** blendStateOutput)
   669 {
   670     D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
   671     HRESULT result = S_OK;
   672 
   673     D3D11_BLEND_DESC blendDesc;
   674     memset(&blendDesc, 0, sizeof(blendDesc));
   675     blendDesc.AlphaToCoverageEnable = FALSE;
   676     blendDesc.IndependentBlendEnable = FALSE;
   677     blendDesc.RenderTarget[0].BlendEnable = enableBlending;
   678     blendDesc.RenderTarget[0].SrcBlend = srcBlend;
   679     blendDesc.RenderTarget[0].DestBlend = destBlend;
   680     blendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
   681     blendDesc.RenderTarget[0].SrcBlendAlpha = srcBlendAlpha;
   682     blendDesc.RenderTarget[0].DestBlendAlpha = destBlendAlpha;
   683     blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
   684     blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
   685     result = data->d3dDevice->CreateBlendState(&blendDesc, blendStateOutput);
   686     if (FAILED(result)) {
   687         WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateBlendState", result);
   688         return result;
   689     }
   690 
   691     return S_OK;
   692 }
   693 
   694 // Create resources that depend on the device.
   695 HRESULT
   696 D3D11_CreateDeviceResources(SDL_Renderer * renderer)
   697 {
   698     D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
   699 
   700     // This flag adds support for surfaces with a different color channel ordering
   701     // than the API default. It is required for compatibility with Direct2D.
   702     UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
   703 
   704     // Make sure Direct3D's debugging feature gets used, if the app requests it.
   705     const char *hint = SDL_GetHint(SDL_HINT_RENDER_DIRECT3D11_DEBUG);
   706     if (hint) {
   707         if (*hint == '1') {
   708             creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
   709         }
   710     }
   711 
   712     // This array defines the set of DirectX hardware feature levels this app will support.
   713     // Note the ordering should be preserved.
   714     // Don't forget to declare your application's minimum required feature level in its
   715     // description.  All applications are assumed to support 9.1 unless otherwise stated.
   716     D3D_FEATURE_LEVEL featureLevels[] = 
   717     {
   718         D3D_FEATURE_LEVEL_11_1,
   719         D3D_FEATURE_LEVEL_11_0,
   720         D3D_FEATURE_LEVEL_10_1,
   721         D3D_FEATURE_LEVEL_10_0,
   722         D3D_FEATURE_LEVEL_9_3,
   723         D3D_FEATURE_LEVEL_9_2,
   724         D3D_FEATURE_LEVEL_9_1
   725     };
   726 
   727     // Create the Direct3D 11 API device object and a corresponding context.
   728     ComPtr<ID3D11Device> device;
   729     ComPtr<ID3D11DeviceContext> context;
   730     HRESULT result = S_OK;
   731     result = D3D11CreateDevice(
   732         nullptr, // Specify nullptr to use the default adapter.
   733         D3D_DRIVER_TYPE_HARDWARE,
   734         nullptr,
   735         creationFlags, // Set set debug and Direct2D compatibility flags.
   736         featureLevels, // List of feature levels this app can support.
   737         ARRAYSIZE(featureLevels),
   738         D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps.
   739         &device, // Returns the Direct3D device created.
   740         &data->featureLevel, // Returns feature level of device created.
   741         &context // Returns the device immediate context.
   742         );
   743     if (FAILED(result)) {
   744         WIN_SetErrorFromHRESULT(__FUNCTION__ ", D3D11CreateDevice", result);
   745         return result;
   746     }
   747 
   748     // Get the Direct3D 11.1 API device and context interfaces.
   749     result = device.As(&(data->d3dDevice));
   750     if (FAILED(result)) {
   751         WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device to ID3D11Device1", result);
   752         return result;
   753     }
   754 
   755     result = context.As(&data->d3dContext);
   756     if (FAILED(result)) {
   757         WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11DeviceContext to ID3D11DeviceContext1", result);
   758         return result;
   759     }
   760 
   761     //
   762     // Make note of the maximum texture size
   763     // Max texture sizes are documented on MSDN, at:
   764     // http://msdn.microsoft.com/en-us/library/windows/apps/ff476876.aspx
   765     //
   766     switch (data->d3dDevice->GetFeatureLevel()) {
   767         case D3D_FEATURE_LEVEL_11_1:
   768         case D3D_FEATURE_LEVEL_11_0:
   769             renderer->info.max_texture_width = renderer->info.max_texture_height = 16384;
   770             break;
   771 
   772         case D3D_FEATURE_LEVEL_10_1:
   773         case D3D_FEATURE_LEVEL_10_0:
   774             renderer->info.max_texture_width = renderer->info.max_texture_height = 8192;
   775             break;
   776 
   777         case D3D_FEATURE_LEVEL_9_3:
   778             renderer->info.max_texture_width = renderer->info.max_texture_height = 4096;
   779             break;
   780 
   781         case D3D_FEATURE_LEVEL_9_2:
   782         case D3D_FEATURE_LEVEL_9_1:
   783             renderer->info.max_texture_width = renderer->info.max_texture_height = 2048;
   784             break;
   785     }
   786 
   787     //
   788     // Load in SDL's one and only vertex shader:
   789     //
   790     result = data->d3dDevice->CreateVertexShader(
   791         D3D11_VertexShader,
   792         sizeof(D3D11_VertexShader),
   793         nullptr,
   794         &data->vertexShader
   795         );
   796     if (FAILED(result)) {
   797         WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateVertexShader", result);
   798         return result;
   799     }
   800 
   801     //
   802     // Create an input layout for SDL's vertex shader:
   803     //
   804     const D3D11_INPUT_ELEMENT_DESC vertexDesc[] = 
   805     {
   806         { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
   807         { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
   808         { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 20, D3D11_INPUT_PER_VERTEX_DATA, 0 },
   809     };
   810 
   811     result = data->d3dDevice->CreateInputLayout(
   812         vertexDesc,
   813         ARRAYSIZE(vertexDesc),
   814         D3D11_VertexShader,
   815         sizeof(D3D11_VertexShader),
   816         &data->inputLayout
   817         );
   818     if (FAILED(result)) {
   819         WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateInputLayout", result);
   820         return result;
   821     }
   822 
   823     //
   824     // Load in SDL's pixel shaders
   825     //
   826 
   827     result = data->d3dDevice->CreatePixelShader(
   828         D3D11_PixelShader_Textures,
   829         sizeof(D3D11_PixelShader_Textures),
   830         nullptr,
   831         &data->texturePixelShader
   832         );
   833     if (FAILED(result)) {
   834         WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreatePixelShader ['textures' shader]", result);
   835         return result;
   836     }
   837 
   838     result = data->d3dDevice->CreatePixelShader(
   839         D3D11_PixelShader_Colors,
   840         sizeof(D3D11_PixelShader_Colors),
   841         nullptr,
   842         &data->colorPixelShader
   843         );
   844     if (FAILED(result)) {
   845         WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreatePixelShader ['color' shader]", result);
   846         return result;
   847     }
   848 
   849     //
   850     // Setup space to hold vertex shader constants:
   851     //
   852     CD3D11_BUFFER_DESC constantBufferDesc(sizeof(VertexShaderConstants), D3D11_BIND_CONSTANT_BUFFER);
   853     result = data->d3dDevice->CreateBuffer(
   854 		&constantBufferDesc,
   855 		nullptr,
   856         &data->vertexShaderConstants
   857 		);
   858     if (FAILED(result)) {
   859         WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateBuffer [vertex shader constants]", result);
   860         return result;
   861     }
   862 
   863     //
   864     // Make sure that the vertex buffer, if already created, gets freed.
   865     // It will be recreated later.
   866     //
   867     data->vertexBuffer = nullptr;
   868 
   869     //
   870     // Create samplers to use when drawing textures:
   871     //
   872     D3D11_SAMPLER_DESC samplerDesc;
   873     samplerDesc.Filter = SDL_D3D11_NEAREST_PIXEL_FILTER;
   874     samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
   875     samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
   876     samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
   877     samplerDesc.MipLODBias = 0.0f;
   878     samplerDesc.MaxAnisotropy = 1;
   879     samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
   880     samplerDesc.BorderColor[0] = 0.0f;
   881     samplerDesc.BorderColor[1] = 0.0f;
   882     samplerDesc.BorderColor[2] = 0.0f;
   883     samplerDesc.BorderColor[3] = 0.0f;
   884     samplerDesc.MinLOD = 0.0f;
   885     samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
   886     result = data->d3dDevice->CreateSamplerState(
   887         &samplerDesc,
   888         &data->nearestPixelSampler
   889         );
   890     if (FAILED(result)) {
   891         WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateSamplerState [nearest-pixel filter]", result);
   892         return result;
   893     }
   894 
   895     samplerDesc.Filter = SDL_D3D11_LINEAR_FILTER;
   896     result = data->d3dDevice->CreateSamplerState(
   897         &samplerDesc,
   898         &data->linearSampler
   899         );
   900     if (FAILED(result)) {
   901         WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateSamplerState [linear filter]", result);
   902         return result;
   903     }
   904 
   905     //
   906     // Setup Direct3D rasterizer states
   907     //
   908     D3D11_RASTERIZER_DESC rasterDesc;
   909     memset(&rasterDesc, 0, sizeof(rasterDesc));
   910 	rasterDesc.AntialiasedLineEnable = false;
   911 	rasterDesc.CullMode = D3D11_CULL_NONE;
   912 	rasterDesc.DepthBias = 0;
   913 	rasterDesc.DepthBiasClamp = 0.0f;
   914 	rasterDesc.DepthClipEnable = true;
   915 	rasterDesc.FillMode = D3D11_FILL_SOLID;
   916 	rasterDesc.FrontCounterClockwise = false;
   917 	rasterDesc.MultisampleEnable = false;
   918 	rasterDesc.ScissorEnable = false;
   919 	rasterDesc.SlopeScaledDepthBias = 0.0f;
   920 	result = data->d3dDevice->CreateRasterizerState(&rasterDesc, &data->mainRasterizer);
   921 	if (FAILED(result)) {
   922         WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateRasterizerState [main rasterizer]", result);
   923         return result;
   924     }
   925 
   926     rasterDesc.ScissorEnable = true;
   927     result = data->d3dDevice->CreateRasterizerState(&rasterDesc, &data->clippedRasterizer);
   928 	if (FAILED(result)) {
   929         WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateRasterizerState [clipped rasterizer]", result);
   930         return result;
   931     }
   932 
   933     //
   934     // Create blending states:
   935     //
   936     result = D3D11_CreateBlendMode(
   937         renderer,
   938         TRUE,
   939         D3D11_BLEND_SRC_ALPHA,          /* srcBlend */
   940         D3D11_BLEND_INV_SRC_ALPHA,      /* destBlend */
   941         D3D11_BLEND_ONE,                /* srcBlendAlpha */
   942         D3D11_BLEND_INV_SRC_ALPHA,      /* destBlendAlpha */
   943         &data->blendModeBlend);
   944     if (FAILED(result)) {
   945         // D3D11_CreateBlendMode will set the SDL error, if it fails
   946         return result;
   947     }
   948 
   949     result = D3D11_CreateBlendMode(
   950         renderer,
   951         TRUE,
   952         D3D11_BLEND_SRC_ALPHA,          /* srcBlend */
   953         D3D11_BLEND_ONE,                /* destBlend */
   954         D3D11_BLEND_ZERO,               /* srcBlendAlpha */
   955         D3D11_BLEND_ONE,                /* destBlendAlpha */
   956         &data->blendModeAdd);
   957     if (FAILED(result)) {
   958         // D3D11_CreateBlendMode will set the SDL error, if it fails
   959         return result;
   960     }
   961 
   962     result = D3D11_CreateBlendMode(
   963         renderer,
   964         TRUE,
   965         D3D11_BLEND_ZERO,               /* srcBlend */
   966         D3D11_BLEND_SRC_COLOR,          /* destBlend */
   967         D3D11_BLEND_ZERO,               /* srcBlendAlpha */
   968         D3D11_BLEND_ONE,                /* destBlendAlpha */
   969         &data->blendModeMod);
   970     if (FAILED(result)) {
   971         // D3D11_CreateBlendMode will set the SDL error, if it fails
   972         return result;
   973     }
   974 
   975     //
   976     // All done!
   977     //
   978     return S_OK;
   979 }
   980 
   981 #ifdef __WINRT__
   982 
   983 static ABI::Windows::UI::Core::ICoreWindow *
   984 D3D11_GetCoreWindowFromSDLRenderer(SDL_Renderer * renderer)
   985 {
   986     SDL_Window * sdlWindow = renderer->window;
   987     if ( ! renderer->window ) {
   988         return nullptr;
   989     }
   990 
   991     SDL_SysWMinfo sdlWindowInfo;
   992     SDL_VERSION(&sdlWindowInfo.version);
   993     if ( ! SDL_GetWindowWMInfo(sdlWindow, &sdlWindowInfo) ) {
   994         return nullptr;
   995     }
   996 
   997     if (sdlWindowInfo.subsystem != SDL_SYSWM_WINRT) {
   998         return nullptr;
   999     }
  1000 
  1001     if ( ! sdlWindowInfo.info.winrt.window ) {
  1002         return nullptr;
  1003     }
  1004 
  1005     ABI::Windows::UI::Core::ICoreWindow * coreWindow = nullptr;
  1006     if (FAILED(sdlWindowInfo.info.winrt.window->QueryInterface(&coreWindow))) {
  1007         return nullptr;
  1008     }
  1009 
  1010     return coreWindow;
  1011 }
  1012 
  1013 // Method to convert a length in device-independent pixels (DIPs) to a length in physical pixels.
  1014 static float
  1015 D3D11_ConvertDipsToPixels(float dips)
  1016 {
  1017     static const float dipsPerInch = 96.0f;
  1018     return floor(dips * DisplayProperties::LogicalDpi / dipsPerInch + 0.5f); // Round to nearest integer.
  1019 }
  1020 #endif
  1021 
  1022 #if WINAPI_FAMILY == WINAPI_FAMILY_APP
  1023 // TODO, WinRT, XAML: get the ISwapChainBackgroundPanelNative from something other than a global var
  1024 extern ISwapChainBackgroundPanelNative * WINRT_GlobalSwapChainBackgroundPanelNative;
  1025 #endif
  1026 
  1027 static DXGI_MODE_ROTATION
  1028 D3D11_GetRotationForOrientation(Windows::Graphics::Display::DisplayOrientations orientation)
  1029 {
  1030     switch (orientation)
  1031     {
  1032 #if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
  1033         //
  1034         // Windows Phone rotations
  1035         //
  1036         case DisplayOrientations::Landscape:
  1037             return DXGI_MODE_ROTATION_ROTATE90;
  1038         case DisplayOrientations::Portrait:
  1039             return DXGI_MODE_ROTATION_IDENTITY;
  1040         case DisplayOrientations::LandscapeFlipped:
  1041             return DXGI_MODE_ROTATION_ROTATE270;
  1042         case DisplayOrientations::PortraitFlipped:
  1043             return DXGI_MODE_ROTATION_ROTATE180;
  1044 #else
  1045         //
  1046         // Non-Windows-Phone rotations (ex: Windows 8, Windows RT)
  1047         //
  1048         case DisplayOrientations::Landscape:
  1049             return DXGI_MODE_ROTATION_IDENTITY;
  1050         case DisplayOrientations::Portrait:
  1051             return DXGI_MODE_ROTATION_ROTATE270;
  1052         case DisplayOrientations::LandscapeFlipped:
  1053             return DXGI_MODE_ROTATION_ROTATE180;
  1054         case DisplayOrientations::PortraitFlipped:
  1055             return DXGI_MODE_ROTATION_ROTATE90;
  1056 #endif // WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
  1057 
  1058         default:
  1059             return DXGI_MODE_ROTATION_UNSPECIFIED;
  1060     }
  1061 }
  1062 
  1063 static bool
  1064 D3D11_IsDisplayRotated90Degrees(Windows::Graphics::Display::DisplayOrientations orientation)
  1065 {
  1066     switch (D3D11_GetRotationForOrientation(orientation)) {
  1067         case DXGI_MODE_ROTATION_ROTATE90:
  1068         case DXGI_MODE_ROTATION_ROTATE270:
  1069             return true;
  1070         default:
  1071             return false;
  1072     }
  1073 }
  1074 
  1075 static int
  1076 D3D11_GetViewportAlignedD3DRect(SDL_Renderer * renderer, const SDL_Rect * sdlRect, D3D11_RECT * outRect)
  1077 {
  1078     D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
  1079     switch (D3D11_GetRotationForOrientation(data-> orientation)) {
  1080         case DXGI_MODE_ROTATION_IDENTITY:
  1081             outRect->left = sdlRect->x;
  1082             outRect->right = sdlRect->x + sdlRect->w;
  1083             outRect->top = sdlRect->y;
  1084             outRect->bottom = sdlRect->y + sdlRect->h;
  1085             break;
  1086         case DXGI_MODE_ROTATION_ROTATE270:
  1087             outRect->left = sdlRect->y;
  1088             outRect->right = sdlRect->y + sdlRect->h;
  1089             outRect->top = renderer->viewport.w - sdlRect->x - sdlRect->w;
  1090             outRect->bottom = renderer->viewport.w - sdlRect->x;
  1091             break;
  1092         case DXGI_MODE_ROTATION_ROTATE180:
  1093             outRect->left = renderer->viewport.w - sdlRect->x - sdlRect->w;
  1094             outRect->right = renderer->viewport.w - sdlRect->x;
  1095             outRect->top = renderer->viewport.h - sdlRect->y - sdlRect->h;
  1096             outRect->bottom = renderer->viewport.h - sdlRect->y;
  1097             break;
  1098         case DXGI_MODE_ROTATION_ROTATE90:
  1099             outRect->left = renderer->viewport.h - sdlRect->y - sdlRect->h;
  1100             outRect->right = renderer->viewport.h - sdlRect->y;
  1101             outRect->top = sdlRect->x;
  1102             outRect->bottom = sdlRect->x + sdlRect->h;
  1103             break;
  1104         default:
  1105             return SDL_SetError("The physical display is in an unknown or unsupported orientation");
  1106     }
  1107     return 0;
  1108 }
  1109 
  1110 
  1111 // Initialize all resources that change when the window's size changes.
  1112 // TODO, WinRT: get D3D11_CreateWindowSizeDependentResources working on Win32
  1113 HRESULT
  1114 D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
  1115 {
  1116     D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
  1117     HRESULT result = S_OK;
  1118     ABI::Windows::UI::Core::ICoreWindow * coreWindow = D3D11_GetCoreWindowFromSDLRenderer(renderer);
  1119 
  1120     // Store the window bounds so the next time we get a SizeChanged event we can
  1121     // avoid rebuilding everything if the size is identical.
  1122     ABI::Windows::Foundation::Rect nativeWindowBounds;
  1123     if (coreWindow) {
  1124         result = coreWindow->get_Bounds(&nativeWindowBounds);
  1125         if (FAILED(result)) {
  1126             WIN_SetErrorFromHRESULT(__FUNCTION__", ICoreWindow::get_Bounds [get native-window bounds]", result);
  1127             return result;
  1128         }
  1129     } else {
  1130         // TODO, WinRT, XAML: clean up window-bounds code in D3D11_CreateWindowSizeDependentResources
  1131         SDL_DisplayMode displayMode;
  1132         if (SDL_GetDesktopDisplayMode(0, &displayMode) < 0) {
  1133             SDL_SetError(__FUNCTION__", Get Window Bounds (XAML): Unable to retrieve the native window's size");
  1134             return E_FAIL;
  1135         }
  1136 
  1137         nativeWindowBounds.Width = (FLOAT) displayMode.w;
  1138         nativeWindowBounds.Height = (FLOAT) displayMode.h;
  1139     }
  1140 
  1141     // TODO, WinRT, XAML: see if window/control sizes are in DIPs, or something else.  If something else, then adjust renderer size tracking accordingly.
  1142     data->windowSizeInDIPs.x = nativeWindowBounds.Width;
  1143     data->windowSizeInDIPs.y = nativeWindowBounds.Height;
  1144 
  1145     // Calculate the necessary swap chain and render target size in pixels.
  1146     float windowWidth = D3D11_ConvertDipsToPixels(data->windowSizeInDIPs.x);
  1147     float windowHeight = D3D11_ConvertDipsToPixels(data->windowSizeInDIPs.y);
  1148 
  1149     // The width and height of the swap chain must be based on the window's
  1150     // landscape-oriented width and height. If the window is in a portrait
  1151     // orientation, the dimensions must be reversed.
  1152     data->orientation = DisplayProperties::CurrentOrientation;
  1153 
  1154 #if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
  1155     const bool swapDimensions = false;
  1156 #else
  1157     const bool swapDimensions = D3D11_IsDisplayRotated90Degrees(data->orientation);
  1158 #endif
  1159     data->renderTargetSize.x = swapDimensions ? windowHeight : windowWidth;
  1160     data->renderTargetSize.y = swapDimensions ? windowWidth : windowHeight;
  1161 
  1162     if(data->swapChain != nullptr)
  1163     {
  1164         // If the swap chain already exists, resize it.
  1165         result = data->swapChain->ResizeBuffers(
  1166             2, // Double-buffered swap chain.
  1167             static_cast<UINT>(data->renderTargetSize.x),
  1168             static_cast<UINT>(data->renderTargetSize.y),
  1169             DXGI_FORMAT_B8G8R8A8_UNORM,
  1170             0
  1171             );
  1172         if (FAILED(result)) {
  1173             WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGISwapChain1::ResizeBuffers", result);
  1174             return result;
  1175         }
  1176     }
  1177     else
  1178     {
  1179         const bool usingXAML = (coreWindow == nullptr);
  1180 
  1181         // Otherwise, create a new one using the same adapter as the existing Direct3D device.
  1182         DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
  1183         swapChainDesc.Width = static_cast<UINT>(data->renderTargetSize.x); // Match the size of the window.
  1184         swapChainDesc.Height = static_cast<UINT>(data->renderTargetSize.y);
  1185         swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // This is the most common swap chain format.
  1186         swapChainDesc.Stereo = false;
  1187         swapChainDesc.SampleDesc.Count = 1; // Don't use multi-sampling.
  1188         swapChainDesc.SampleDesc.Quality = 0;
  1189         swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
  1190         swapChainDesc.BufferCount = 2; // Use double-buffering to minimize latency.
  1191 #if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
  1192         swapChainDesc.Scaling = DXGI_SCALING_STRETCH; // On phone, only stretch and aspect-ratio stretch scaling are allowed.
  1193         swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; // On phone, no swap effects are supported.
  1194 #else
  1195         if (usingXAML) {
  1196             swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
  1197         } else {
  1198             swapChainDesc.Scaling = DXGI_SCALING_NONE;
  1199         }
  1200         swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // All Windows Store apps must use this SwapEffect.
  1201 #endif
  1202         swapChainDesc.Flags = 0;
  1203 
  1204         ComPtr<IDXGIDevice1> dxgiDevice;
  1205         result = data->d3dDevice.As(&dxgiDevice);
  1206         if (FAILED(result)) {
  1207             WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1 to IDXGIDevice1", result);
  1208             return result;
  1209         }
  1210 
  1211         ComPtr<IDXGIAdapter> dxgiAdapter;
  1212         result = dxgiDevice->GetAdapter(&dxgiAdapter);
  1213         if (FAILED(result)) {
  1214             WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIDevice1::GetAdapter", result);
  1215             return result;
  1216         }
  1217 
  1218         ComPtr<IDXGIFactory2> dxgiFactory;
  1219         result = dxgiAdapter->GetParent(
  1220             __uuidof(IDXGIFactory2), 
  1221             &dxgiFactory
  1222             );
  1223         if (FAILED(result)) {
  1224             WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIAdapter::GetParent", result);
  1225             return result;
  1226         }
  1227 
  1228         if (usingXAML) {
  1229             result = dxgiFactory->CreateSwapChainForComposition(
  1230                 data->d3dDevice.Get(),
  1231                 &swapChainDesc,
  1232                 nullptr,
  1233                 &data->swapChain);
  1234             if (FAILED(result)) {
  1235                 WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIFactory2::CreateSwapChainForComposition", result);
  1236                 return result;
  1237             }
  1238 
  1239 #if WINAPI_FAMILY == WINAPI_FAMILY_APP
  1240             result = WINRT_GlobalSwapChainBackgroundPanelNative->SetSwapChain(data->swapChain.Get());
  1241             if (FAILED(result)) {
  1242                 WIN_SetErrorFromHRESULT(__FUNCTION__ ", ISwapChainBackgroundPanelNative::SetSwapChain", result);
  1243                 return result;
  1244             }
  1245 #else
  1246             SDL_SetError(__FUNCTION__ ", XAML support is not yet available for Windows Phone");
  1247             return E_FAIL;
  1248 #endif
  1249         } else {
  1250             IUnknown * coreWindowAsIUnknown = nullptr;
  1251             result = coreWindow->QueryInterface(&coreWindowAsIUnknown);
  1252             if (FAILED(result)) {
  1253                 WIN_SetErrorFromHRESULT(__FUNCTION__ ", ICoreWindow to IUnknown", result);
  1254                 return result;
  1255             }
  1256 
  1257             result = dxgiFactory->CreateSwapChainForCoreWindow(
  1258                 data->d3dDevice.Get(),
  1259                 coreWindowAsIUnknown,
  1260                 &swapChainDesc,
  1261                 nullptr, // Allow on all displays.
  1262                 &data->swapChain
  1263                 );
  1264             if (FAILED(result)) {
  1265                 WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIFactory2::CreateSwapChainForCoreWindow", result);
  1266                 return result;
  1267             }
  1268         }
  1269         
  1270         // Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and
  1271         // ensures that the application will only render after each VSync, minimizing power consumption.
  1272         result = dxgiDevice->SetMaximumFrameLatency(1);
  1273         if (FAILED(result)) {
  1274             WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIDevice1::SetMaximumFrameLatency", result);
  1275             return result;
  1276         }
  1277     }
  1278     
  1279 #if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
  1280     // Set the proper orientation for the swap chain, and generate the
  1281     // 3D matrix transformation for rendering to the rotated swap chain.
  1282     //
  1283     // To note, the call for this, IDXGISwapChain1::SetRotation, is not necessary
  1284     // on Windows Phone, nor is it supported there.  It's only needed in Windows 8/RT.
  1285     DXGI_MODE_ROTATION rotation = D3D11_GetRotationForOrientation(data->orientation);
  1286     result = data->swapChain->SetRotation(rotation);
  1287     if (FAILED(result)) {
  1288         WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGISwapChain1::SetRotation" , result);
  1289         return result;
  1290     }
  1291 #endif
  1292 
  1293     // Create a render target view of the swap chain back buffer.
  1294     ComPtr<ID3D11Texture2D> backBuffer;
  1295     result = data->swapChain->GetBuffer(
  1296         0,
  1297         __uuidof(ID3D11Texture2D),
  1298         &backBuffer
  1299         );
  1300     if (FAILED(result)) {
  1301         WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGISwapChain1::GetBuffer [back-buffer]", result);
  1302         return result;
  1303     }
  1304 
  1305     result = data->d3dDevice->CreateRenderTargetView(
  1306         backBuffer.Get(),
  1307         nullptr,
  1308         &data->mainRenderTargetView
  1309         );
  1310     if (FAILED(result)) {
  1311         WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateRenderTargetView", result);
  1312         return result;
  1313     }
  1314 
  1315     if (D3D11_UpdateViewport(renderer) != 0) {
  1316         // D3D11_UpdateViewport will set the SDL error if it fails.
  1317         return E_FAIL;
  1318     }
  1319 
  1320     return S_OK;
  1321 }
  1322 
  1323 // This method is called when the window's size changes.
  1324 HRESULT
  1325 D3D11_UpdateForWindowSizeChange(SDL_Renderer * renderer)
  1326 {
  1327     D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
  1328     HRESULT result = S_OK;
  1329     ABI::Windows::UI::Core::ICoreWindow * coreWindow = D3D11_GetCoreWindowFromSDLRenderer(renderer);
  1330     ABI::Windows::Foundation::Rect coreWindowBounds;
  1331 
  1332     result = coreWindow->get_Bounds(&coreWindowBounds);
  1333     if (FAILED(result)) {
  1334         WIN_SetErrorFromHRESULT(__FUNCTION__ ", ICoreWindow::get_Bounds [get window bounds]", result);
  1335         return result;
  1336     }
  1337 
  1338     if (coreWindowBounds.Width  != data->windowSizeInDIPs.x ||
  1339         coreWindowBounds.Height != data->windowSizeInDIPs.y ||
  1340         data->orientation != DisplayProperties::CurrentOrientation)
  1341     {
  1342         ID3D11RenderTargetView* nullViews[] = {nullptr};
  1343         data->d3dContext->OMSetRenderTargets(ARRAYSIZE(nullViews), nullViews, nullptr);
  1344         data->mainRenderTargetView = nullptr;
  1345         data->d3dContext->Flush();
  1346         result = D3D11_CreateWindowSizeDependentResources(renderer);
  1347         if (FAILED(result)) {
  1348             /* D3D11_CreateWindowSizeDependentResources will set the SDL error */
  1349             return result;
  1350         }
  1351     }
  1352 
  1353     return S_OK;
  1354 }
  1355 
  1356 HRESULT
  1357 D3D11_HandleDeviceLost(SDL_Renderer * renderer)
  1358 {
  1359     D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
  1360     HRESULT result = S_OK;
  1361 
  1362     // Reset these member variables to ensure that D3D11_UpdateForWindowSizeChange recreates all resources.
  1363     data->windowSizeInDIPs.x = 0;
  1364     data->windowSizeInDIPs.y = 0;
  1365     data->swapChain = nullptr;
  1366 
  1367     result = D3D11_CreateDeviceResources(renderer);
  1368     if (FAILED(result)) {
  1369         /* D3D11_CreateDeviceResources will set the SDL error */
  1370         return result;
  1371     }
  1372 
  1373     result = D3D11_UpdateForWindowSizeChange(renderer);
  1374     if (FAILED(result)) {
  1375         /* D3D11_UpdateForWindowSizeChange will set the SDL error */
  1376         return result;
  1377     }
  1378 
  1379     return S_OK;
  1380 }
  1381 
  1382 static void
  1383 D3D11_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
  1384 {
  1385     //D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
  1386 
  1387     if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) {
  1388         D3D11_UpdateForWindowSizeChange(renderer);
  1389     }
  1390 }
  1391 
  1392 static D3D11_FILTER
  1393 GetScaleQuality(void)
  1394 {
  1395     const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
  1396     if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
  1397         return SDL_D3D11_NEAREST_PIXEL_FILTER;
  1398     } else /* if (*hint == '1' || SDL_strcasecmp(hint, "linear") == 0) */ {
  1399         return SDL_D3D11_LINEAR_FILTER;
  1400     }
  1401 }
  1402 
  1403 static int
  1404 D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
  1405 {
  1406     D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  1407     D3D11_TextureData *textureData;
  1408     HRESULT result;
  1409     DXGI_FORMAT textureFormat = SDLPixelFormatToDXGIFormat(texture->format);
  1410     if (textureFormat == SDL_PIXELFORMAT_UNKNOWN) {
  1411         return SDL_SetError("%s, An unsupported SDL pixel format (0x%x) was specified",
  1412             __FUNCTION__, texture->format);
  1413     }
  1414 
  1415     textureData = new D3D11_TextureData;
  1416     if (!textureData) {
  1417         SDL_OutOfMemory();
  1418         return -1;
  1419     }
  1420     textureData->pixelFormat = SDL_AllocFormat(texture->format);
  1421     textureData->lockedTexturePosition = XMINT2(0, 0);
  1422     textureData->scaleMode = GetScaleQuality();
  1423 
  1424     texture->driverdata = textureData;
  1425 
  1426     D3D11_TEXTURE2D_DESC textureDesc = {0};
  1427     textureDesc.Width = texture->w;
  1428     textureDesc.Height = texture->h;
  1429     textureDesc.MipLevels = 1;
  1430     textureDesc.ArraySize = 1;
  1431     textureDesc.Format = textureFormat;
  1432     textureDesc.SampleDesc.Count = 1;
  1433     textureDesc.SampleDesc.Quality = 0;
  1434     textureDesc.MiscFlags = 0;
  1435 
  1436     if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
  1437         textureDesc.Usage = D3D11_USAGE_DYNAMIC;
  1438         textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
  1439     } else {
  1440         textureDesc.Usage = D3D11_USAGE_DEFAULT;
  1441         textureDesc.CPUAccessFlags = 0;
  1442     }
  1443 
  1444     if (texture->access == SDL_TEXTUREACCESS_TARGET) {
  1445         textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
  1446     } else {
  1447         textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
  1448     }
  1449 
  1450 #if 0
  1451     // Fill the texture with a non-black color, for debugging purposes:
  1452     const int numPixels = textureDesc.Width * textureDesc.Height;
  1453     const int pixelSizeInBytes = textureData->pixelFormat->BytesPerPixel;
  1454     std::vector<uint8> initialTexturePixels(numPixels * pixelSizeInBytes, 0x00);
  1455     for (int i = 0; i < (numPixels * pixelSizeInBytes); i += pixelSizeInBytes) {
  1456         initialTexturePixels[i+0] = 0xff;
  1457         initialTexturePixels[i+1] = 0xff;
  1458         initialTexturePixels[i+2] = 0x00;
  1459         initialTexturePixels[i+3] = 0xff;
  1460     }
  1461     D3D11_SUBRESOURCE_DATA initialTextureData = {0};
  1462     initialTextureData.pSysMem = (void *)&(initialTexturePixels[0]);
  1463     initialTextureData.SysMemPitch = textureDesc.Width * pixelSizeInBytes;
  1464     initialTextureData.SysMemSlicePitch = numPixels * pixelSizeInBytes;
  1465 #endif
  1466 
  1467     result = rendererData->d3dDevice->CreateTexture2D(
  1468         &textureDesc,
  1469         NULL,   // &initialTextureData,
  1470         &textureData->mainTexture
  1471         );
  1472     if (FAILED(result)) {
  1473         D3D11_DestroyTexture(renderer, texture);
  1474         WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateTexture2D", result);
  1475         return -1;
  1476     }
  1477 
  1478     if (texture->access & SDL_TEXTUREACCESS_TARGET) {
  1479         D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
  1480         renderTargetViewDesc.Format = textureDesc.Format;
  1481         renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
  1482         renderTargetViewDesc.Texture2D.MipSlice = 0;
  1483 
  1484         result = rendererData->d3dDevice->CreateRenderTargetView(
  1485             textureData->mainTexture.Get(),
  1486             &renderTargetViewDesc,
  1487             &textureData->mainTextureRenderTargetView);
  1488         if (FAILED(result)) {
  1489             D3D11_DestroyTexture(renderer, texture);
  1490             WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateRenderTargetView", result);
  1491             return -1;
  1492         }
  1493     }
  1494 
  1495     D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
  1496     resourceViewDesc.Format = textureDesc.Format;
  1497     resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
  1498     resourceViewDesc.Texture2D.MostDetailedMip = 0;
  1499     resourceViewDesc.Texture2D.MipLevels = textureDesc.MipLevels;
  1500     result = rendererData->d3dDevice->CreateShaderResourceView(
  1501         textureData->mainTexture.Get(),
  1502         &resourceViewDesc,
  1503         &textureData->mainTextureResourceView
  1504         );
  1505     if (FAILED(result)) {
  1506         D3D11_DestroyTexture(renderer, texture);
  1507         WIN_SetErrorFromHRESULT(__FUNCTION__ "ID3D11Device1::CreateShaderResourceView", result);
  1508         return -1;
  1509     }
  1510 
  1511     return 0;
  1512 }
  1513 
  1514 static void
  1515 D3D11_DestroyTexture(SDL_Renderer * renderer,
  1516                      SDL_Texture * texture)
  1517 {
  1518     D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
  1519 
  1520     if (textureData) {
  1521         if (textureData->pixelFormat) {
  1522             SDL_FreeFormat(textureData->pixelFormat);
  1523             textureData->pixelFormat = NULL;
  1524         }
  1525 
  1526         delete textureData;
  1527         texture->driverdata = NULL;
  1528     }
  1529 }
  1530 
  1531 static int
  1532 D3D11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
  1533                     const SDL_Rect * rect, const void * srcPixels,
  1534                     int srcPitch)
  1535 {
  1536     // Lock the texture, retrieving a buffer to write pixel data to:
  1537     void * destPixels = NULL;
  1538     int destPitch = 0;
  1539     if (D3D11_LockTexture(renderer, texture, rect, &destPixels, &destPitch) != 0) {
  1540         // An error is already set.  Attach some info to it, then return to
  1541         // the caller.
  1542         std::string errorMessage = string(__FUNCTION__ ", Lock Texture Failed: ") + SDL_GetError();
  1543         return SDL_SetError(errorMessage.c_str());
  1544     }
  1545 
  1546     // Copy pixel data to the locked texture's memory:
  1547     for (int y = 0; y < rect->h; ++y) {
  1548         memcpy(
  1549             ((Uint8 *)destPixels) + (destPitch * y),
  1550             ((Uint8 *)srcPixels) + (srcPitch * y),
  1551             srcPitch
  1552             );
  1553     }
  1554 
  1555     // Commit the texture's memory back to Direct3D:
  1556     D3D11_UnlockTexture(renderer, texture);
  1557 
  1558     // Return to the caller:
  1559     return 0;
  1560 }
  1561 
  1562 static int
  1563 D3D11_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
  1564                   const SDL_Rect * rect, void **pixels, int *pitch)
  1565 {
  1566     D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  1567     D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
  1568     HRESULT result = S_OK;
  1569 
  1570     if (textureData->stagingTexture) {
  1571         return SDL_SetError("texture is already locked");
  1572     }
  1573     
  1574     // Create a 'staging' texture, which will be used to write to a portion
  1575     // of the main texture.  This is necessary, as Direct3D 11.1 does not
  1576     // have the ability to write a CPU-bound pixel buffer to a rectangular
  1577     // subrect of a texture.  Direct3D 11.1 can, however, write a pixel
  1578     // buffer to an entire texture, hence the use of a staging texture.
  1579     //
  1580     // TODO, WinRT: consider avoiding the use of a staging texture in D3D11_LockTexture if/when the entire texture is being updated
  1581     D3D11_TEXTURE2D_DESC stagingTextureDesc;
  1582     textureData->mainTexture->GetDesc(&stagingTextureDesc);
  1583     stagingTextureDesc.Width = rect->w;
  1584     stagingTextureDesc.Height = rect->h;
  1585     stagingTextureDesc.BindFlags = 0;
  1586     stagingTextureDesc.MiscFlags = 0;
  1587     stagingTextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
  1588     stagingTextureDesc.Usage = D3D11_USAGE_STAGING;
  1589     result = rendererData->d3dDevice->CreateTexture2D(
  1590         &stagingTextureDesc,
  1591         NULL,
  1592         &textureData->stagingTexture);
  1593     if (FAILED(result)) {
  1594         WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateTexture2D [create staging texture]", result);
  1595         return -1;
  1596     }
  1597 
  1598     // Get a write-only pointer to data in the staging texture:
  1599     D3D11_MAPPED_SUBRESOURCE textureMemory = {0};
  1600     result = rendererData->d3dContext->Map(
  1601         textureData->stagingTexture.Get(),
  1602         D3D11CalcSubresource(0, 0, 0),
  1603         D3D11_MAP_WRITE,
  1604         0,
  1605         &textureMemory
  1606         );
  1607     if (FAILED(result)) {
  1608         WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11DeviceContext1::Map [map staging texture]", result);
  1609         textureData->stagingTexture = nullptr;
  1610         return -1;
  1611     }
  1612 
  1613     // Make note of where the staging texture will be written to (on a
  1614     // call to SDL_UnlockTexture):
  1615     textureData->lockedTexturePosition = XMINT2(rect->x, rect->y);
  1616 
  1617     // Make sure the caller has information on the texture's pixel buffer,
  1618     // then return:
  1619     *pixels = textureMemory.pData;
  1620     *pitch = textureMemory.RowPitch;
  1621     return 0;
  1622 }
  1623 
  1624 static void
  1625 D3D11_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
  1626 {
  1627     D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  1628     D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
  1629 
  1630     // Commit the pixel buffer's changes back to the staging texture:
  1631     rendererData->d3dContext->Unmap(
  1632         textureData->stagingTexture.Get(),
  1633         0);
  1634 
  1635     // Copy the staging texture's contents back to the main texture:
  1636     rendererData->d3dContext->CopySubresourceRegion(
  1637         textureData->mainTexture.Get(),
  1638         D3D11CalcSubresource(0, 0, 0),
  1639         textureData->lockedTexturePosition.x,
  1640         textureData->lockedTexturePosition.y,
  1641         0,
  1642         textureData->stagingTexture.Get(),
  1643         D3D11CalcSubresource(0, 0, 0),
  1644         NULL);
  1645 
  1646     // Clean up and return:
  1647     textureData->stagingTexture = nullptr;
  1648     textureData->lockedTexturePosition = XMINT2(0, 0);
  1649 }
  1650 
  1651 static int
  1652 D3D11_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
  1653 {
  1654     D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  1655 
  1656     if (texture == NULL) {
  1657         rendererData->currentOffscreenRenderTargetView = nullptr;
  1658         return 0;
  1659     }
  1660 
  1661     D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
  1662 
  1663     if (!textureData->mainTextureRenderTargetView) {
  1664         return SDL_SetError("specified texture is not a render target");
  1665     }
  1666 
  1667     rendererData->currentOffscreenRenderTargetView = textureData->mainTextureRenderTargetView;
  1668 
  1669     return 0;
  1670 }
  1671 
  1672 static int
  1673 D3D11_UpdateViewport(SDL_Renderer * renderer)
  1674 {
  1675     D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
  1676 
  1677     if (renderer->viewport.w == 0 || renderer->viewport.h == 0) {
  1678         // If the viewport is empty, assume that it is because
  1679         // SDL_CreateRenderer is calling it, and will call it again later
  1680         // with a non-empty viewport.
  1681         return 0;
  1682     }
  1683 
  1684     // Make sure the SDL viewport gets rotated to that of the physical display's orientation.
  1685     // Keep in mind here that the Y-axis will be been inverted (from Direct3D's
  1686     // default coordinate system) so rotations will be done in the opposite
  1687     // direction of the DXGI_MODE_ROTATION enumeration.
  1688     DirectX::XMMATRIX projection;
  1689     switch (D3D11_GetRotationForOrientation(data->orientation))
  1690     {
  1691         case DXGI_MODE_ROTATION_IDENTITY:
  1692             projection = XMMatrixIdentity();
  1693             break;
  1694         case DXGI_MODE_ROTATION_ROTATE270:
  1695             projection = XMMatrixRotationZ(XM_PIDIV2);
  1696             break;
  1697         case DXGI_MODE_ROTATION_ROTATE180:
  1698             projection = XMMatrixRotationZ(XM_PI);
  1699             break;
  1700         case DXGI_MODE_ROTATION_ROTATE90:
  1701             projection = XMMatrixRotationZ(-XM_PIDIV2);
  1702             break;
  1703         default:
  1704             return SDL_SetError("An unknown DisplayOrientation is being used");
  1705     }
  1706 
  1707     //
  1708     // Update the view matrix
  1709     //
  1710     float viewportWidth = (float) renderer->viewport.w;
  1711     float viewportHeight = (float) renderer->viewport.h;
  1712     DirectX::XMMATRIX view = XMMatrixMultiply(
  1713         XMMatrixScaling(2.0f / viewportWidth, 2.0f / viewportHeight, 1.0f),
  1714         XMMatrixMultiply(
  1715             XMMatrixTranslation(-1, -1, 0),
  1716             XMMatrixRotationX(XM_PI)
  1717             ));
  1718 
  1719     //
  1720     // Combine the projection + view matrix together now, as both only get
  1721     // set here (as of this writing, on Dec 26, 2013).  When done, store it
  1722     // for eventual transfer to the GPU.
  1723     //
  1724     XMStoreFloat4x4(&data->vertexShaderConstantsData.projectionAndView,
  1725         XMMatrixMultiply(
  1726             view,
  1727             projection));
  1728 
  1729     //
  1730     // Reset the model matrix
  1731     //
  1732     XMStoreFloat4x4(&data->vertexShaderConstantsData.model, XMMatrixIdentity());
  1733 
  1734     //
  1735     // Update the Direct3D viewport, which seems to be aligned to the
  1736     // swap buffer's coordinate space, which is always in either
  1737     // a landscape mode, for all Windows 8/RT devices, or a portrait mode,
  1738     // for Windows Phone devices.
  1739     //
  1740     SDL_FRect orientationAlignedViewport;
  1741     const bool swapDimensions = D3D11_IsDisplayRotated90Degrees(data->orientation);
  1742     if (swapDimensions) {
  1743         orientationAlignedViewport.x = (float) renderer->viewport.y;
  1744         orientationAlignedViewport.y = (float) renderer->viewport.x;
  1745         orientationAlignedViewport.w = (float) renderer->viewport.h;
  1746         orientationAlignedViewport.h = (float) renderer->viewport.w;
  1747     } else {
  1748         orientationAlignedViewport.x = (float) renderer->viewport.x;
  1749         orientationAlignedViewport.y = (float) renderer->viewport.y;
  1750         orientationAlignedViewport.w = (float) renderer->viewport.w;
  1751         orientationAlignedViewport.h = (float) renderer->viewport.h;
  1752     }
  1753     // TODO, WinRT: get custom viewports working with non-Landscape modes (Portrait, PortraitFlipped, and LandscapeFlipped)
  1754 
  1755     D3D11_VIEWPORT viewport;
  1756     memset(&viewport, 0, sizeof(viewport));
  1757     viewport.TopLeftX = orientationAlignedViewport.x;
  1758     viewport.TopLeftY = orientationAlignedViewport.y;
  1759     viewport.Width = orientationAlignedViewport.w;
  1760     viewport.Height = orientationAlignedViewport.h;
  1761     viewport.MinDepth = 0.0f;
  1762     viewport.MaxDepth = 1.0f;
  1763     data->d3dContext->RSSetViewports(1, &viewport);
  1764 
  1765 #if 0
  1766     SDL_Log("%s, oav={%.0f,%.0f,%.0f,%.0f}, rend={%.0f,%.0f}\n",
  1767         __FUNCTION__,
  1768         orientationAlignedViewport.x,
  1769         orientationAlignedViewport.y,
  1770         orientationAlignedViewport.w,
  1771         orientationAlignedViewport.h,
  1772         data->renderTargetSize.x,
  1773         data->renderTargetSize.y);
  1774 #endif
  1775 
  1776     return 0;
  1777 }
  1778 
  1779 static int
  1780 D3D11_UpdateClipRect(SDL_Renderer * renderer)
  1781 {
  1782     D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
  1783     const SDL_Rect *rect = &renderer->clip_rect;
  1784 
  1785     if (SDL_RectEmpty(rect)) {
  1786         data->d3dContext->RSSetScissorRects(0, 0);
  1787     } else {
  1788         D3D11_RECT scissorRect;
  1789         if (D3D11_GetViewportAlignedD3DRect(renderer, rect, &scissorRect) != 0) {
  1790             /* D3D11_GetViewportAlignedD3DRect will have set the SDL error */
  1791             return -1;
  1792         }
  1793         data->d3dContext->RSSetScissorRects(1, &scissorRect);
  1794     }
  1795 
  1796     return 0;
  1797 }
  1798 
  1799 static ComPtr<ID3D11RenderTargetView> &
  1800 D3D11_GetCurrentRenderTargetView(SDL_Renderer * renderer)
  1801 {
  1802     D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
  1803     if (data->currentOffscreenRenderTargetView) {
  1804         return data->currentOffscreenRenderTargetView;
  1805     } else {
  1806         return data->mainRenderTargetView;
  1807     }
  1808 }
  1809 
  1810 static int
  1811 D3D11_RenderClear(SDL_Renderer * renderer)
  1812 {
  1813     D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
  1814     const float colorRGBA[] = {
  1815         (renderer->r / 255.0f),
  1816         (renderer->g / 255.0f),
  1817         (renderer->b / 255.0f),
  1818         (renderer->a / 255.0f)
  1819     };
  1820     data->d3dContext->ClearRenderTargetView(
  1821         D3D11_GetCurrentRenderTargetView(renderer).Get(),
  1822         colorRGBA
  1823         );
  1824     return 0;
  1825 }
  1826 
  1827 static int
  1828 D3D11_UpdateVertexBuffer(SDL_Renderer *renderer,
  1829                          const void * vertexData, size_t dataSizeInBytes)
  1830 {
  1831     D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  1832     HRESULT result = S_OK;
  1833     D3D11_BUFFER_DESC vertexBufferDesc;
  1834 
  1835     if (rendererData->vertexBuffer) {
  1836         rendererData->vertexBuffer->GetDesc(&vertexBufferDesc);
  1837     } else {
  1838         memset(&vertexBufferDesc, 0, sizeof(vertexBufferDesc));
  1839     }
  1840 
  1841     if (vertexBufferDesc.ByteWidth >= dataSizeInBytes) {
  1842         D3D11_MAPPED_SUBRESOURCE mappedResource;
  1843         ZeroMemory(&mappedResource, sizeof(D3D11_MAPPED_SUBRESOURCE));
  1844         result = rendererData->d3dContext->Map(rendererData->vertexBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
  1845         if (FAILED(result)) {
  1846             WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11DeviceContext1::Map [vertex buffer]", result);
  1847             return -1;
  1848         }
  1849         memcpy(mappedResource.pData, vertexData, dataSizeInBytes);
  1850         rendererData->d3dContext->Unmap(rendererData->vertexBuffer.Get(), 0);
  1851     } else {
  1852         vertexBufferDesc.ByteWidth = dataSizeInBytes;
  1853         vertexBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
  1854         vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
  1855         vertexBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
  1856 
  1857         D3D11_SUBRESOURCE_DATA vertexBufferData = {0};
  1858         vertexBufferData.pSysMem = vertexData;
  1859         vertexBufferData.SysMemPitch = 0;
  1860         vertexBufferData.SysMemSlicePitch = 0;
  1861 
  1862         result = rendererData->d3dDevice->CreateBuffer(
  1863             &vertexBufferDesc,
  1864             &vertexBufferData,
  1865             &rendererData->vertexBuffer
  1866             );
  1867         if (FAILED(result)) {
  1868             WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateBuffer [vertex buffer]", result);
  1869             return -1;
  1870         }
  1871     }
  1872 
  1873     UINT stride = sizeof(VertexPositionColor);
  1874     UINT offset = 0;
  1875     rendererData->d3dContext->IASetVertexBuffers(
  1876         0,
  1877         1,
  1878         rendererData->vertexBuffer.GetAddressOf(),
  1879         &stride,
  1880         &offset
  1881         );
  1882 
  1883     return 0;
  1884 }
  1885 
  1886 static void
  1887 D3D11_RenderStartDrawOp(SDL_Renderer * renderer)
  1888 {
  1889     D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  1890 
  1891     rendererData->d3dContext->OMSetRenderTargets(
  1892         1,
  1893         D3D11_GetCurrentRenderTargetView(renderer).GetAddressOf(),
  1894         nullptr
  1895         );
  1896 }
  1897 
  1898 static void
  1899 D3D11_RenderSetBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
  1900 {
  1901     D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  1902     switch (blendMode) {
  1903         case SDL_BLENDMODE_BLEND:
  1904             rendererData->d3dContext->OMSetBlendState(rendererData->blendModeBlend.Get(), 0, 0xFFFFFFFF);
  1905             break;
  1906         case SDL_BLENDMODE_ADD:
  1907             rendererData->d3dContext->OMSetBlendState(rendererData->blendModeAdd.Get(), 0, 0xFFFFFFFF);
  1908             break;
  1909         case SDL_BLENDMODE_MOD:
  1910             rendererData->d3dContext->OMSetBlendState(rendererData->blendModeMod.Get(), 0, 0xFFFFFFFF);
  1911             break;
  1912         case SDL_BLENDMODE_NONE:
  1913             rendererData->d3dContext->OMSetBlendState(NULL, 0, 0xFFFFFFFF);
  1914             break;
  1915     }
  1916 }
  1917 
  1918 static void
  1919 D3D11_SetPixelShader(SDL_Renderer * renderer,
  1920                      ID3D11PixelShader * shader,
  1921                      ID3D11ShaderResourceView * shaderResource,
  1922                      ID3D11SamplerState * sampler)
  1923 {
  1924     D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  1925     rendererData->d3dContext->PSSetShader(shader, nullptr, 0);
  1926     rendererData->d3dContext->PSSetShaderResources(0, 1, &shaderResource);
  1927     rendererData->d3dContext->PSSetSamplers(0, 1, &sampler);
  1928 }
  1929 
  1930 static void
  1931 D3D11_RenderFinishDrawOp(SDL_Renderer * renderer,
  1932                          D3D11_PRIMITIVE_TOPOLOGY primitiveTopology,
  1933                          UINT vertexCount)
  1934 {
  1935     D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  1936 
  1937     rendererData->d3dContext->UpdateSubresource(
  1938         rendererData->vertexShaderConstants.Get(),
  1939         0,
  1940         NULL,
  1941         &rendererData->vertexShaderConstantsData,
  1942         0,
  1943         0
  1944         );
  1945 
  1946     rendererData->d3dContext->IASetPrimitiveTopology(primitiveTopology);
  1947     rendererData->d3dContext->IASetInputLayout(rendererData->inputLayout.Get());
  1948     rendererData->d3dContext->VSSetShader(rendererData->vertexShader.Get(), nullptr, 0);
  1949     rendererData->d3dContext->VSSetConstantBuffers(0, 1, rendererData->vertexShaderConstants.GetAddressOf());
  1950     if (SDL_RectEmpty(&(renderer->clip_rect))) {
  1951         rendererData->d3dContext->RSSetState(rendererData->mainRasterizer.Get());
  1952     } else {
  1953         rendererData->d3dContext->RSSetState(rendererData->clippedRasterizer.Get());
  1954     }
  1955     rendererData->d3dContext->Draw(vertexCount, 0);
  1956 }
  1957 
  1958 static int
  1959 D3D11_RenderDrawPoints(SDL_Renderer * renderer,
  1960                        const SDL_FPoint * points, int count)
  1961 {
  1962     D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  1963     float r, g, b, a;
  1964 
  1965     r = (float)(renderer->r / 255.0f);
  1966     g = (float)(renderer->g / 255.0f);
  1967     b = (float)(renderer->b / 255.0f);
  1968     a = (float)(renderer->a / 255.0f);
  1969 
  1970     VertexPositionColor * vertices = SDL_stack_alloc(VertexPositionColor, count);
  1971     for (int i = 0; i < min(count, 128); ++i) {
  1972         const VertexPositionColor v = {XMFLOAT3(points[i].x, points[i].y, 0.0f),  XMFLOAT2(0.0f, 0.0f), XMFLOAT4(r, g, b, a)};
  1973         vertices[i] = v;
  1974     }
  1975 
  1976     D3D11_RenderStartDrawOp(renderer);
  1977     D3D11_RenderSetBlendMode(renderer, renderer->blendMode);
  1978     if (D3D11_UpdateVertexBuffer(renderer, vertices, (unsigned int)count * sizeof(VertexPositionColor)) != 0) {
  1979         SDL_stack_free(vertices);
  1980         return -1;
  1981     }
  1982 
  1983     D3D11_SetPixelShader(
  1984         renderer,
  1985         rendererData->colorPixelShader.Get(),
  1986         nullptr,
  1987         nullptr);
  1988 
  1989     D3D11_RenderFinishDrawOp(renderer, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, count);
  1990     SDL_stack_free(vertices);
  1991     return 0;
  1992 }
  1993 
  1994 static int
  1995 D3D11_RenderDrawLines(SDL_Renderer * renderer,
  1996                       const SDL_FPoint * points, int count)
  1997 {
  1998     D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  1999     float r, g, b, a;
  2000 
  2001     r = (float)(renderer->r / 255.0f);
  2002     g = (float)(renderer->g / 255.0f);
  2003     b = (float)(renderer->b / 255.0f);
  2004     a = (float)(renderer->a / 255.0f);
  2005 
  2006     VertexPositionColor * vertices = SDL_stack_alloc(VertexPositionColor, count);
  2007     for (int i = 0; i < count; ++i) {
  2008         const VertexPositionColor v = {XMFLOAT3(points[i].x, points[i].y, 0.0f),  XMFLOAT2(0.0f, 0.0f), XMFLOAT4(r, g, b, a)};
  2009         vertices[i] = v;
  2010     }
  2011 
  2012     D3D11_RenderStartDrawOp(renderer);
  2013     D3D11_RenderSetBlendMode(renderer, renderer->blendMode);
  2014     if (D3D11_UpdateVertexBuffer(renderer, vertices, (unsigned int)count * sizeof(VertexPositionColor)) != 0) {
  2015         SDL_stack_free(vertices);
  2016         return -1;
  2017     }
  2018 
  2019     D3D11_SetPixelShader(
  2020         renderer,
  2021         rendererData->colorPixelShader.Get(),
  2022         nullptr,
  2023         nullptr);
  2024 
  2025     D3D11_RenderFinishDrawOp(renderer, D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP, count);
  2026     SDL_stack_free(vertices);
  2027     return 0;
  2028 }
  2029 
  2030 static int
  2031 D3D11_RenderFillRects(SDL_Renderer * renderer,
  2032                       const SDL_FRect * rects, int count)
  2033 {
  2034     D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  2035     float r, g, b, a;
  2036 
  2037     r = (float)(renderer->r / 255.0f);
  2038     g = (float)(renderer->g / 255.0f);
  2039     b = (float)(renderer->b / 255.0f);
  2040     a = (float)(renderer->a / 255.0f);
  2041 
  2042 #if 0
  2043     // Set up a test pattern:
  2044     SDL_FRect _rects[] = {
  2045         {-1.1f, 1.1f, 1.1f, -1.1f},
  2046         {-1.0f, 1.0f, 1.0f, -1.0f},     // red
  2047         {0.0f, 1.0f, 1.0f, -1.0f},      // green
  2048         {-1.0f, 0.0f, 1.0f, -1.0f},     // blue
  2049         {0.0f, 0.0f, 1.0f, -1.0f}       // white
  2050     };
  2051     count = sizeof(_rects) / sizeof(SDL_FRect);
  2052 #define rects _rects
  2053 #endif
  2054 
  2055     for (int i = 0; i < count; ++i) {
  2056         D3D11_RenderStartDrawOp(renderer);
  2057         D3D11_RenderSetBlendMode(renderer, renderer->blendMode);
  2058 
  2059 #if 0
  2060         // Set colors for the test pattern:
  2061         a = 1.0f;
  2062         switch (i) {
  2063             case 0: r = 1.0f; g = 1.0f; b = 0.0f; break;
  2064             case 1: r = 1.0f; g = 0.0f; b = 0.0f; break;
  2065             case 2: r = 0.0f; g = 1.0f; b = 0.0f; break;
  2066             case 3: r = 0.0f; g = 0.0f; b = 1.0f; break;
  2067             case 4: r = 1.0f; g = 1.0f; b = 1.0f; break;
  2068         }
  2069 #endif
  2070 
  2071         VertexPositionColor vertices[] = {
  2072             {XMFLOAT3(rects[i].x, rects[i].y, 0.0f),                           XMFLOAT2(0.0f, 0.0f), XMFLOAT4(r, g, b, a)},
  2073             {XMFLOAT3(rects[i].x, rects[i].y + rects[i].h, 0.0f),              XMFLOAT2(0.0f, 0.0f), XMFLOAT4(r, g, b, a)},
  2074             {XMFLOAT3(rects[i].x + rects[i].w, rects[i].y, 0.0f),              XMFLOAT2(0.0f, 0.0f), XMFLOAT4(r, g, b, a)},
  2075             {XMFLOAT3(rects[i].x + rects[i].w, rects[i].y + rects[i].h, 0.0f), XMFLOAT2(0.0f, 0.0f), XMFLOAT4(r, g, b, a)},
  2076         };
  2077         if (D3D11_UpdateVertexBuffer(renderer, vertices, sizeof(vertices)) != 0) {
  2078             return -1;
  2079         }
  2080 
  2081         D3D11_SetPixelShader(
  2082             renderer,
  2083             rendererData->colorPixelShader.Get(),
  2084             nullptr,
  2085             nullptr);
  2086 
  2087         D3D11_RenderFinishDrawOp(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, sizeof(vertices) / sizeof(VertexPositionColor));
  2088     }
  2089 
  2090     return 0;
  2091 }
  2092 
  2093 static ID3D11SamplerState *
  2094 D3D11_RenderGetSampler(SDL_Renderer * renderer, SDL_Texture * texture)
  2095 {
  2096     D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  2097     D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
  2098 
  2099     switch (textureData->scaleMode) {
  2100         case SDL_D3D11_NEAREST_PIXEL_FILTER:
  2101             return rendererData->nearestPixelSampler.Get();
  2102         case SDL_D3D11_LINEAR_FILTER:
  2103             return rendererData->linearSampler.Get();
  2104         default:
  2105             return NULL;
  2106     }
  2107 }
  2108 
  2109 static int
  2110 D3D11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
  2111                  const SDL_Rect * srcrect, const SDL_FRect * dstrect)
  2112 {
  2113     D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  2114     D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
  2115 
  2116     D3D11_RenderStartDrawOp(renderer);
  2117     D3D11_RenderSetBlendMode(renderer, texture->blendMode);
  2118 
  2119     float minu = (float) srcrect->x / texture->w;
  2120     float maxu = (float) (srcrect->x + srcrect->w) / texture->w;
  2121     float minv = (float) srcrect->y / texture->h;
  2122     float maxv = (float) (srcrect->y + srcrect->h) / texture->h;
  2123 
  2124     float r = 1.0f;
  2125     float g = 1.0f;
  2126     float b = 1.0f;
  2127     float a = 1.0f;
  2128     if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
  2129         r = (float)(texture->r / 255.0f);
  2130         g = (float)(texture->g / 255.0f);
  2131         b = (float)(texture->b / 255.0f);
  2132     }
  2133     if (texture->modMode & SDL_TEXTUREMODULATE_ALPHA) {
  2134         a = (float)(texture->a / 255.0f);
  2135     }
  2136 
  2137     VertexPositionColor vertices[] = {
  2138         {XMFLOAT3(dstrect->x, dstrect->y, 0.0f),                           XMFLOAT2(minu, minv), XMFLOAT4(r, g, b, a)},
  2139         {XMFLOAT3(dstrect->x, dstrect->y + dstrect->h, 0.0f),              XMFLOAT2(minu, maxv), XMFLOAT4(r, g, b, a)},
  2140         {XMFLOAT3(dstrect->x + dstrect->w, dstrect->y, 0.0f),              XMFLOAT2(maxu, minv), XMFLOAT4(r, g, b, a)},
  2141         {XMFLOAT3(dstrect->x + dstrect->w, dstrect->y + dstrect->h, 0.0f), XMFLOAT2(maxu, maxv), XMFLOAT4(r, g, b, a)},
  2142     };
  2143     if (D3D11_UpdateVertexBuffer(renderer, vertices, sizeof(vertices)) != 0) {
  2144         return -1;
  2145     }
  2146 
  2147     ID3D11SamplerState *textureSampler = D3D11_RenderGetSampler(renderer, texture);
  2148     D3D11_SetPixelShader(
  2149         renderer,
  2150         rendererData->texturePixelShader.Get(),
  2151         textureData->mainTextureResourceView.Get(),
  2152         textureSampler);
  2153 
  2154     D3D11_RenderFinishDrawOp(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, sizeof(vertices) / sizeof(VertexPositionColor));
  2155 
  2156     return 0;
  2157 }
  2158 
  2159 static int
  2160 D3D11_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
  2161                    const SDL_Rect * srcrect, const SDL_FRect * dstrect,
  2162                    const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip)
  2163 {
  2164     D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  2165     D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
  2166 
  2167     D3D11_RenderStartDrawOp(renderer);
  2168     D3D11_RenderSetBlendMode(renderer, texture->blendMode);
  2169 
  2170     float minu = (float) srcrect->x / texture->w;
  2171     float maxu = (float) (srcrect->x + srcrect->w) / texture->w;
  2172     float minv = (float) srcrect->y / texture->h;
  2173     float maxv = (float) (srcrect->y + srcrect->h) / texture->h;
  2174 
  2175     float r = 1.0f;
  2176     float g = 1.0f;
  2177     float b = 1.0f;
  2178     float a = 1.0f;
  2179     if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
  2180         r = (float)(texture->r / 255.0f);
  2181         g = (float)(texture->g / 255.0f);
  2182         b = (float)(texture->b / 255.0f);
  2183     }
  2184     if (texture->modMode & SDL_TEXTUREMODULATE_ALPHA) {
  2185         a = (float)(texture->a / 255.0f);
  2186     }
  2187 
  2188     if (flip & SDL_FLIP_HORIZONTAL) {
  2189         float tmp = maxu;
  2190         maxu = minu;
  2191         minu = tmp;
  2192     }
  2193     if (flip & SDL_FLIP_VERTICAL) {
  2194         float tmp = maxv;
  2195         maxv = minv;
  2196         minv = tmp;
  2197     }
  2198 
  2199     XMFLOAT4X4 oldModelMatrix = rendererData->vertexShaderConstantsData.model;
  2200     XMStoreFloat4x4(
  2201         &rendererData->vertexShaderConstantsData.model,
  2202         XMMatrixMultiply(
  2203             XMMatrixRotationZ((float)(XM_PI * (float) angle / 180.0f)),
  2204             XMMatrixTranslation(dstrect->x + center->x, dstrect->y + center->y, 0)
  2205             ));
  2206 
  2207     const float minx = -center->x;
  2208     const float maxx = dstrect->w - center->x;
  2209     const float miny = -center->y;
  2210     const float maxy = dstrect->h - center->y;
  2211 
  2212     VertexPositionColor vertices[] = {
  2213         {XMFLOAT3(minx, miny, 0.0f), XMFLOAT2(minu, minv), XMFLOAT4(r, g, b, a)},
  2214         {XMFLOAT3(minx, maxy, 0.0f), XMFLOAT2(minu, maxv), XMFLOAT4(r, g, b, a)},
  2215         {XMFLOAT3(maxx, miny, 0.0f), XMFLOAT2(maxu, minv), XMFLOAT4(r, g, b, a)},
  2216         {XMFLOAT3(maxx, maxy, 0.0f), XMFLOAT2(maxu, maxv), XMFLOAT4(r, g, b, a)},
  2217     };
  2218     if (D3D11_UpdateVertexBuffer(renderer, vertices, sizeof(vertices)) != 0) {
  2219         return -1;
  2220     }
  2221 
  2222     ID3D11SamplerState *textureSampler = D3D11_RenderGetSampler(renderer, texture);
  2223     D3D11_SetPixelShader(
  2224         renderer,
  2225         rendererData->texturePixelShader.Get(),
  2226         textureData->mainTextureResourceView.Get(),
  2227         textureSampler);
  2228 
  2229     D3D11_RenderFinishDrawOp(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, sizeof(vertices) / sizeof(VertexPositionColor));
  2230 
  2231     rendererData->vertexShaderConstantsData.model = oldModelMatrix;
  2232 
  2233     return 0;
  2234 }
  2235 
  2236 static int
  2237 D3D11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
  2238                        Uint32 format, void * pixels, int pitch)
  2239 {
  2240     D3D11_RenderData * data = (D3D11_RenderData *) renderer->driverdata;
  2241     HRESULT result = S_OK;
  2242 
  2243     // Retrieve a pointer to the back buffer:
  2244     ComPtr<ID3D11Texture2D> backBuffer;
  2245     result = data->swapChain->GetBuffer(
  2246         0,
  2247         __uuidof(ID3D11Texture2D),
  2248         &backBuffer
  2249         );
  2250     if (FAILED(result)) {
  2251         WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGISwapChain1::GetBuffer [get back buffer]", result);
  2252         return -1;
  2253     }
  2254 
  2255     // Create a staging texture to copy the screen's data to:
  2256     ComPtr<ID3D11Texture2D> stagingTexture;
  2257     D3D11_TEXTURE2D_DESC stagingTextureDesc;
  2258     backBuffer->GetDesc(&stagingTextureDesc);
  2259     stagingTextureDesc.Width = rect->w;
  2260     stagingTextureDesc.Height = rect->h;
  2261     stagingTextureDesc.BindFlags = 0;
  2262     stagingTextureDesc.MiscFlags = 0;
  2263     stagingTextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
  2264     stagingTextureDesc.Usage = D3D11_USAGE_STAGING;
  2265     result = data->d3dDevice->CreateTexture2D(
  2266         &stagingTextureDesc,
  2267         NULL,
  2268         &stagingTexture);
  2269     if (FAILED(result)) {
  2270         WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateTexture2D [create staging texture]", result);
  2271         return -1;
  2272     }
  2273 
  2274     // Copy the desired portion of the back buffer to the staging texture:
  2275     D3D11_RECT srcRect;
  2276     if (D3D11_GetViewportAlignedD3DRect(renderer, rect, &srcRect) != 0) {
  2277         /* D3D11_GetViewportAlignedD3DRect will have set the SDL error */
  2278         return -1;
  2279     }
  2280 
  2281     D3D11_BOX srcBox;
  2282     srcBox.left = srcRect.left;
  2283     srcBox.right = srcRect.right;
  2284     srcBox.top = srcRect.top;
  2285     srcBox.bottom = srcRect.bottom;
  2286     srcBox.front = 0;
  2287     srcBox.back = 1;
  2288     data->d3dContext->CopySubresourceRegion(
  2289         stagingTexture.Get(),
  2290         D3D11CalcSubresource(0, 0, 0),
  2291         0, 0, 0,
  2292         backBuffer.Get(),
  2293         D3D11CalcSubresource(0, 0, 0),
  2294         &srcBox);
  2295 
  2296     // Map the staging texture's data to CPU-accessible memory:
  2297     D3D11_MAPPED_SUBRESOURCE textureMemory = {0};
  2298     result = data->d3dContext->Map(
  2299         stagingTexture.Get(),
  2300         D3D11CalcSubresource(0, 0, 0),
  2301         D3D11_MAP_READ,
  2302         0,
  2303         &textureMemory);
  2304     if (FAILED(result)) {
  2305         WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11DeviceContext1::Map [map staging texture]", result);
  2306         return -1;
  2307     }
  2308 
  2309     // Copy the data into the desired buffer, converting pixels to the
  2310     // desired format at the same time:
  2311     if (SDL_ConvertPixels(
  2312         rect->w, rect->h,
  2313         DXGIFormatToSDLPixelFormat(stagingTextureDesc.Format),
  2314         textureMemory.pData,
  2315         textureMemory.RowPitch,
  2316         format,
  2317         pixels,
  2318         pitch) != 0)
  2319     {
  2320         // When SDL_ConvertPixels fails, it'll have already set the format.
  2321         // Get the error message, and attach some extra data to it.
  2322         std::string errorMessage = string(__FUNCTION__ ", Convert Pixels failed: ") + SDL_GetError();
  2323         return SDL_SetError(errorMessage.c_str());
  2324     }
  2325 
  2326     // Unmap the texture:
  2327     data->d3dContext->Unmap(
  2328         stagingTexture.Get(),
  2329         D3D11CalcSubresource(0, 0, 0));
  2330 
  2331     // All done.  The staging texture will be cleaned up in it's container
  2332     // ComPtr<>'s destructor.
  2333     return 0;
  2334 }
  2335 
  2336 static void
  2337 D3D11_RenderPresent(SDL_Renderer * renderer)
  2338 {
  2339     D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
  2340 
  2341 #if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
  2342     // The first argument instructs DXGI to block until VSync, putting the application
  2343     // to sleep until the next VSync. This ensures we don't waste any cycles rendering
  2344     // frames that will never be displayed to the screen.
  2345     HRESULT hr = data->swapChain->Present(1, 0);
  2346 #else
  2347     // The application may optionally specify "dirty" or "scroll"
  2348     // rects to improve efficiency in certain scenarios.
  2349     // This option is not available on Windows Phone 8, to note.
  2350     DXGI_PRESENT_PARAMETERS parameters = {0};
  2351     parameters.DirtyRectsCount = 0;
  2352     parameters.pDirtyRects = nullptr;
  2353     parameters.pScrollRect = nullptr;
  2354     parameters.pScrollOffset = nullptr;
  2355     
  2356     // The first argument instructs DXGI to block until VSync, putting the application
  2357     // to sleep until the next VSync. This ensures we don't waste any cycles rendering
  2358     // frames that will never be displayed to the screen.
  2359     HRESULT hr = data->swapChain->Present1(1, 0, &parameters);
  2360 #endif
  2361 
  2362     // Discard the contents of the render target.
  2363     // This is a valid operation only when the existing contents will be entirely
  2364     // overwritten. If dirty or scroll rects are used, this call should be removed.
  2365     data->d3dContext->DiscardView(data->mainRenderTargetView.Get());
  2366 
  2367     // If the device was removed either by a disconnect or a driver upgrade, we 
  2368     // must recreate all device resources.
  2369     //
  2370     // TODO, WinRT: consider throwing an exception if D3D11_RenderPresent fails, especially if there is a way to salvedge debug info from users' machines
  2371     if (hr == DXGI_ERROR_DEVICE_REMOVED)
  2372     {
  2373         hr = D3D11_HandleDeviceLost(renderer);
  2374         if (FAILED(hr)) {
  2375             /* D3D11_HandleDeviceLost will set the SDL error */
  2376         }
  2377     }
  2378     else
  2379     {
  2380         WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11DeviceContext1::DiscardView", hr);
  2381     }
  2382 }
  2383 
  2384 #endif /* SDL_VIDEO_RENDER_D3D11 && !SDL_RENDER_DISABLED */
  2385 
  2386 /* vi: set ts=4 sw=4 expandtab: */