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