src/render/direct3d11/SDL_render_d3d11.c
author David Ludwig <dludwig@pobox.com>
Fri, 09 May 2014 20:16:21 -0400
changeset 8755 f2fc45874b9c
parent 8748 7ba9c0a0cad7
child 8969 7fb90df60b99
permissions -rw-r--r--
Fixed rendering-alignment issues on WinPhone 8.1, when the device was rotated

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