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