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