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