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