src/render/direct3d11/SDL_render_d3d11.c
author David Ludwig <dludwig@pobox.com>
Sat, 15 Mar 2014 13:27:18 -0400
changeset 8620 a27695b26b57
parent 8615 097646deaef2
child 8668 07dce0097f29
permissions -rw-r--r--
Fixed a crash on Windows Phone 8 that occurred after rotating a device

This changeset prevents IDXGISwapChain::ResizeBuffers from being invoked on
Windows Phone 8, a function that isn't available on the platform (but is
available on other Windows platforms). The call would fail, which ultimately
led to a crash.

This changeset also attempts to make sure that the D3D11 swap chain is created
at the correct size, when using Windows Phone 8.

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