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