src/render/direct3d11/SDL_render_d3d11.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 17 Oct 2019 18:07:52 -0700
changeset 13141 36a12351cdfd
parent 13048 44b0a095f4b7
permissions -rw-r--r--
Added support for the BDA PS4 Fightpad
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "../../SDL_internal.h"
    22 
    23 #if SDL_VIDEO_RENDER_D3D11 && !SDL_RENDER_DISABLED
    24 
    25 #define COBJMACROS
    26 #include "../../core/windows/SDL_windows.h"
    27 #include "SDL_hints.h"
    28 #include "SDL_loadso.h"
    29 #include "SDL_syswm.h"
    30 #include "../SDL_sysrender.h"
    31 #include "../SDL_d3dmath.h"
    32 
    33 #include <d3d11_1.h>
    34 
    35 #include "SDL_shaders_d3d11.h"
    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 SDL_COMPOSE_ERROR(str) SDL_STRINGIFY_ARG(__FUNCTION__) ", " str
    55 
    56 #define SAFE_RELEASE(X) if ((X)) { IUnknown_Release(SDL_static_cast(IUnknown*, X)); X = NULL; }
    57 
    58 
    59 /* !!! FIXME: vertex buffer bandwidth could be significantly lower; move color to a uniform, only use UV coords
    60    !!! FIXME:  when textures are needed, and don't ever pass Z, since it's always zero. */
    61 
    62 /* Vertex shader, common values */
    63 typedef struct
    64 {
    65     Float4X4 model;
    66     Float4X4 projectionAndView;
    67 } VertexShaderConstants;
    68 
    69 /* Per-vertex data */
    70 typedef struct
    71 {
    72     Float3 pos;
    73     Float2 tex;
    74     Float4 color;
    75 } VertexPositionColor;
    76 
    77 /* Per-texture data */
    78 typedef struct
    79 {
    80     ID3D11Texture2D *mainTexture;
    81     ID3D11ShaderResourceView *mainTextureResourceView;
    82     ID3D11RenderTargetView *mainTextureRenderTargetView;
    83     ID3D11Texture2D *stagingTexture;
    84     int lockedTexturePositionX;
    85     int lockedTexturePositionY;
    86     D3D11_FILTER scaleMode;
    87 
    88     /* YV12 texture support */
    89     SDL_bool yuv;
    90     ID3D11Texture2D *mainTextureU;
    91     ID3D11ShaderResourceView *mainTextureResourceViewU;
    92     ID3D11Texture2D *mainTextureV;
    93     ID3D11ShaderResourceView *mainTextureResourceViewV;
    94 
    95     /* NV12 texture support */
    96     SDL_bool nv12;
    97     ID3D11Texture2D *mainTextureNV;
    98     ID3D11ShaderResourceView *mainTextureResourceViewNV;
    99 
   100     Uint8 *pixels;
   101     int pitch;
   102     SDL_Rect locked_rect;
   103 } D3D11_TextureData;
   104 
   105 /* Blend mode data */
   106 typedef struct
   107 {
   108     SDL_BlendMode blendMode;
   109     ID3D11BlendState *blendState;
   110 } D3D11_BlendMode;
   111 
   112 /* Private renderer data */
   113 typedef struct
   114 {
   115     void *hDXGIMod;
   116     void *hD3D11Mod;
   117     IDXGIFactory2 *dxgiFactory;
   118     IDXGIAdapter *dxgiAdapter;
   119     ID3D11Device1 *d3dDevice;
   120     ID3D11DeviceContext1 *d3dContext;
   121     IDXGISwapChain1 *swapChain;
   122     DXGI_SWAP_EFFECT swapEffect;
   123     ID3D11RenderTargetView *mainRenderTargetView;
   124     ID3D11RenderTargetView *currentOffscreenRenderTargetView;
   125     ID3D11InputLayout *inputLayout;
   126     ID3D11Buffer *vertexBuffers[8];
   127     size_t vertexBufferSizes[8];
   128     ID3D11VertexShader *vertexShader;
   129     ID3D11PixelShader *pixelShaders[NUM_SHADERS];
   130     int blendModesCount;
   131     D3D11_BlendMode *blendModes;
   132     ID3D11SamplerState *nearestPixelSampler;
   133     ID3D11SamplerState *linearSampler;
   134     D3D_FEATURE_LEVEL featureLevel;
   135 
   136     /* Rasterizers */
   137     ID3D11RasterizerState *mainRasterizer;
   138     ID3D11RasterizerState *clippedRasterizer;
   139 
   140     /* Vertex buffer constants */
   141     VertexShaderConstants vertexShaderConstantsData;
   142     ID3D11Buffer *vertexShaderConstants;
   143 
   144     /* Cached renderer properties */
   145     DXGI_MODE_ROTATION rotation;
   146     ID3D11RenderTargetView *currentRenderTargetView;
   147     ID3D11RasterizerState *currentRasterizerState;
   148     ID3D11BlendState *currentBlendState;
   149     ID3D11PixelShader *currentShader;
   150     ID3D11ShaderResourceView *currentShaderResource;
   151     ID3D11SamplerState *currentSampler;
   152     SDL_bool cliprectDirty;
   153     SDL_bool currentCliprectEnabled;
   154     SDL_Rect currentCliprect;
   155     SDL_Rect currentViewport;
   156     int currentViewportRotation;
   157     SDL_bool viewportDirty;
   158     Float4X4 identity;
   159     int currentVertexBuffer;
   160 } D3D11_RenderData;
   161 
   162 
   163 /* Define D3D GUIDs here so we don't have to include uuid.lib.
   164 *
   165 * Fix for SDL bug https://bugzilla.libsdl.org/show_bug.cgi?id=3437:
   166 * The extra 'SDL_' was added to the start of each IID's name, in order
   167 * to prevent build errors on both MinGW-w64 and WinRT/UWP.
   168 * (SDL bug https://bugzilla.libsdl.org/show_bug.cgi?id=3336 led to
   169 * linker errors in WinRT/UWP builds.)
   170 */
   171 
   172 #ifdef __GNUC__
   173 #pragma GCC diagnostic push
   174 #pragma GCC diagnostic ignored "-Wunused-const-variable"
   175 #endif
   176 
   177 static const GUID SDL_IID_IDXGIFactory2 = { 0x50c83a1c, 0xe072, 0x4c48, { 0x87, 0xb0, 0x36, 0x30, 0xfa, 0x36, 0xa6, 0xd0 } };
   178 static const GUID SDL_IID_IDXGIDevice1 = { 0x77db970f, 0x6276, 0x48ba, { 0xba, 0x28, 0x07, 0x01, 0x43, 0xb4, 0x39, 0x2c } };
   179 static const GUID SDL_IID_IDXGIDevice3 = { 0x6007896c, 0x3244, 0x4afd, { 0xbf, 0x18, 0xa6, 0xd3, 0xbe, 0xda, 0x50, 0x23 } };
   180 static const GUID SDL_IID_ID3D11Texture2D = { 0x6f15aaf2, 0xd208, 0x4e89, { 0x9a, 0xb4, 0x48, 0x95, 0x35, 0xd3, 0x4f, 0x9c } };
   181 static const GUID SDL_IID_ID3D11Device1 = { 0xa04bfb29, 0x08ef, 0x43d6, { 0xa4, 0x9c, 0xa9, 0xbd, 0xbd, 0xcb, 0xe6, 0x86 } };
   182 static const GUID SDL_IID_ID3D11DeviceContext1 = { 0xbb2c6faa, 0xb5fb, 0x4082, { 0x8e, 0x6b, 0x38, 0x8b, 0x8c, 0xfa, 0x90, 0xe1 } };
   183 static const GUID SDL_IID_ID3D11Debug = { 0x79cf2233, 0x7536, 0x4948, { 0x9d, 0x36, 0x1e, 0x46, 0x92, 0xdc, 0x57, 0x60 } };
   184 
   185 #ifdef __GNUC__
   186 #pragma GCC diagnostic pop
   187 #endif
   188 
   189 
   190 
   191 Uint32
   192 D3D11_DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat)
   193 {
   194     switch (dxgiFormat) {
   195         case DXGI_FORMAT_B8G8R8A8_UNORM:
   196             return SDL_PIXELFORMAT_ARGB8888;
   197         case DXGI_FORMAT_B8G8R8X8_UNORM:
   198             return SDL_PIXELFORMAT_RGB888;
   199         default:
   200             return SDL_PIXELFORMAT_UNKNOWN;
   201     }
   202 }
   203 
   204 static DXGI_FORMAT
   205 SDLPixelFormatToDXGIFormat(Uint32 sdlFormat)
   206 {
   207     switch (sdlFormat) {
   208         case SDL_PIXELFORMAT_ARGB8888:
   209             return DXGI_FORMAT_B8G8R8A8_UNORM;
   210         case SDL_PIXELFORMAT_RGB888:
   211             return DXGI_FORMAT_B8G8R8X8_UNORM;
   212         case SDL_PIXELFORMAT_YV12:
   213         case SDL_PIXELFORMAT_IYUV:
   214         case SDL_PIXELFORMAT_NV12:  /* For the Y texture */
   215         case SDL_PIXELFORMAT_NV21:  /* For the Y texture */
   216             return DXGI_FORMAT_R8_UNORM;
   217         default:
   218             return DXGI_FORMAT_UNKNOWN;
   219     }
   220 }
   221 
   222 static void D3D11_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
   223 
   224 static void
   225 D3D11_ReleaseAll(SDL_Renderer * renderer)
   226 {
   227     D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
   228     SDL_Texture *texture = NULL;
   229 
   230     /* Release all textures */
   231     for (texture = renderer->textures; texture; texture = texture->next) {
   232         D3D11_DestroyTexture(renderer, texture);
   233     }
   234 
   235     /* Release/reset everything else */
   236     if (data) {
   237         int i;
   238 
   239         SAFE_RELEASE(data->dxgiFactory);
   240         SAFE_RELEASE(data->dxgiAdapter);
   241         SAFE_RELEASE(data->d3dDevice);
   242         SAFE_RELEASE(data->d3dContext);
   243         SAFE_RELEASE(data->swapChain);
   244         SAFE_RELEASE(data->mainRenderTargetView);
   245         SAFE_RELEASE(data->currentOffscreenRenderTargetView);
   246         SAFE_RELEASE(data->inputLayout);
   247         for (i = 0; i < SDL_arraysize(data->vertexBuffers); ++i) {
   248             SAFE_RELEASE(data->vertexBuffers[i]);
   249         }
   250         SAFE_RELEASE(data->vertexShader);
   251         for (i = 0; i < SDL_arraysize(data->pixelShaders); ++i) {
   252             SAFE_RELEASE(data->pixelShaders[i]);
   253         }
   254         if (data->blendModesCount > 0) {
   255             for (i = 0; i < data->blendModesCount; ++i) {
   256                 SAFE_RELEASE(data->blendModes[i].blendState);
   257             }
   258             SDL_free(data->blendModes);
   259 
   260             data->blendModesCount = 0;
   261         }
   262         SAFE_RELEASE(data->nearestPixelSampler);
   263         SAFE_RELEASE(data->linearSampler);
   264         SAFE_RELEASE(data->mainRasterizer);
   265         SAFE_RELEASE(data->clippedRasterizer);
   266         SAFE_RELEASE(data->vertexShaderConstants);
   267 
   268         data->swapEffect = (DXGI_SWAP_EFFECT) 0;
   269         data->rotation = DXGI_MODE_ROTATION_UNSPECIFIED;
   270         data->currentRenderTargetView = NULL;
   271         data->currentRasterizerState = NULL;
   272         data->currentBlendState = NULL;
   273         data->currentShader = NULL;
   274         data->currentShaderResource = NULL;
   275         data->currentSampler = NULL;
   276 
   277         /* Unload the D3D libraries.  This should be done last, in order
   278          * to prevent IUnknown::Release() calls from crashing.
   279          */
   280         if (data->hD3D11Mod) {
   281             SDL_UnloadObject(data->hD3D11Mod);
   282             data->hD3D11Mod = NULL;
   283         }
   284         if (data->hDXGIMod) {
   285             SDL_UnloadObject(data->hDXGIMod);
   286             data->hDXGIMod = NULL;
   287         }
   288     }
   289 }
   290 
   291 static void
   292 D3D11_DestroyRenderer(SDL_Renderer * renderer)
   293 {
   294     D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
   295     D3D11_ReleaseAll(renderer);
   296     if (data) {
   297         SDL_free(data);
   298     }
   299     SDL_free(renderer);
   300 }
   301 
   302 static D3D11_BLEND GetBlendFunc(SDL_BlendFactor factor)
   303 {
   304     switch (factor) {
   305     case SDL_BLENDFACTOR_ZERO:
   306         return D3D11_BLEND_ZERO;
   307     case SDL_BLENDFACTOR_ONE:
   308         return D3D11_BLEND_ONE;
   309     case SDL_BLENDFACTOR_SRC_COLOR:
   310         return D3D11_BLEND_SRC_COLOR;
   311     case SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR:
   312         return D3D11_BLEND_INV_SRC_COLOR;
   313     case SDL_BLENDFACTOR_SRC_ALPHA:
   314         return D3D11_BLEND_SRC_ALPHA;
   315     case SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA:
   316         return D3D11_BLEND_INV_SRC_ALPHA;
   317     case SDL_BLENDFACTOR_DST_COLOR:
   318         return D3D11_BLEND_DEST_COLOR;
   319     case SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR:
   320         return D3D11_BLEND_INV_DEST_COLOR;
   321     case SDL_BLENDFACTOR_DST_ALPHA:
   322         return D3D11_BLEND_DEST_ALPHA;
   323     case SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA:
   324         return D3D11_BLEND_INV_DEST_ALPHA;
   325     default:
   326         return (D3D11_BLEND)0;
   327     }
   328 }
   329 
   330 static D3D11_BLEND_OP GetBlendEquation(SDL_BlendOperation operation)
   331 {
   332     switch (operation) {
   333     case SDL_BLENDOPERATION_ADD:
   334         return D3D11_BLEND_OP_ADD;
   335     case SDL_BLENDOPERATION_SUBTRACT:
   336         return D3D11_BLEND_OP_SUBTRACT;
   337     case SDL_BLENDOPERATION_REV_SUBTRACT:
   338         return D3D11_BLEND_OP_REV_SUBTRACT;
   339     case SDL_BLENDOPERATION_MINIMUM:
   340         return D3D11_BLEND_OP_MIN;
   341     case SDL_BLENDOPERATION_MAXIMUM:
   342         return D3D11_BLEND_OP_MAX;
   343     default:
   344         return (D3D11_BLEND_OP)0;
   345     }
   346 }
   347 
   348 static ID3D11BlendState *
   349 D3D11_CreateBlendState(SDL_Renderer * renderer, SDL_BlendMode blendMode)
   350 {
   351     D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
   352     SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode);
   353     SDL_BlendFactor srcAlphaFactor = SDL_GetBlendModeSrcAlphaFactor(blendMode);
   354     SDL_BlendOperation colorOperation = SDL_GetBlendModeColorOperation(blendMode);
   355     SDL_BlendFactor dstColorFactor = SDL_GetBlendModeDstColorFactor(blendMode);
   356     SDL_BlendFactor dstAlphaFactor = SDL_GetBlendModeDstAlphaFactor(blendMode);
   357     SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode);
   358     ID3D11BlendState *blendState = NULL;
   359     D3D11_BlendMode *blendModes;
   360     HRESULT result = S_OK;
   361 
   362     D3D11_BLEND_DESC blendDesc;
   363     SDL_zero(blendDesc);
   364     blendDesc.AlphaToCoverageEnable = FALSE;
   365     blendDesc.IndependentBlendEnable = FALSE;
   366     blendDesc.RenderTarget[0].BlendEnable = TRUE;
   367     blendDesc.RenderTarget[0].SrcBlend = GetBlendFunc(srcColorFactor);
   368     blendDesc.RenderTarget[0].DestBlend = GetBlendFunc(dstColorFactor);
   369     blendDesc.RenderTarget[0].BlendOp = GetBlendEquation(colorOperation);
   370     blendDesc.RenderTarget[0].SrcBlendAlpha = GetBlendFunc(srcAlphaFactor);
   371     blendDesc.RenderTarget[0].DestBlendAlpha = GetBlendFunc(dstAlphaFactor);
   372     blendDesc.RenderTarget[0].BlendOpAlpha = GetBlendEquation(alphaOperation);
   373     blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
   374     result = ID3D11Device_CreateBlendState(data->d3dDevice, &blendDesc, &blendState);
   375     if (FAILED(result)) {
   376         WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateBlendState"), result);
   377         return NULL;
   378     }
   379 
   380     blendModes = (D3D11_BlendMode *)SDL_realloc(data->blendModes, (data->blendModesCount + 1) * sizeof(*blendModes));
   381     if (!blendModes) {
   382         SAFE_RELEASE(blendState);
   383         SDL_OutOfMemory();
   384         return NULL;
   385     }
   386     blendModes[data->blendModesCount].blendMode = blendMode;
   387     blendModes[data->blendModesCount].blendState = blendState;
   388     data->blendModes = blendModes;
   389     ++data->blendModesCount;
   390 
   391     return blendState;
   392 }
   393 
   394 /* Create resources that depend on the device. */
   395 static HRESULT
   396 D3D11_CreateDeviceResources(SDL_Renderer * renderer)
   397 {
   398     typedef HRESULT(WINAPI *PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory);
   399     PFN_CREATE_DXGI_FACTORY CreateDXGIFactoryFunc;
   400     D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
   401     PFN_D3D11_CREATE_DEVICE D3D11CreateDeviceFunc;
   402     ID3D11Device *d3dDevice = NULL;
   403     ID3D11DeviceContext *d3dContext = NULL;
   404     IDXGIDevice1 *dxgiDevice = NULL;
   405     HRESULT result = S_OK;
   406     UINT creationFlags;
   407     int i;
   408 
   409     /* This array defines the set of DirectX hardware feature levels this app will support.
   410      * Note the ordering should be preserved.
   411      * Don't forget to declare your application's minimum required feature level in its
   412      * description.  All applications are assumed to support 9.1 unless otherwise stated.
   413      */
   414     D3D_FEATURE_LEVEL featureLevels[] = 
   415     {
   416         D3D_FEATURE_LEVEL_11_1,
   417         D3D_FEATURE_LEVEL_11_0,
   418         D3D_FEATURE_LEVEL_10_1,
   419         D3D_FEATURE_LEVEL_10_0,
   420         D3D_FEATURE_LEVEL_9_3,
   421         D3D_FEATURE_LEVEL_9_2,
   422         D3D_FEATURE_LEVEL_9_1
   423     };
   424 
   425     D3D11_BUFFER_DESC constantBufferDesc;
   426     D3D11_SAMPLER_DESC samplerDesc;
   427     D3D11_RASTERIZER_DESC rasterDesc;
   428 
   429 #ifdef __WINRT__
   430     CreateDXGIFactoryFunc = CreateDXGIFactory1;
   431     D3D11CreateDeviceFunc = D3D11CreateDevice;
   432 #else
   433     data->hDXGIMod = SDL_LoadObject("dxgi.dll");
   434     if (!data->hDXGIMod) {
   435         result = E_FAIL;
   436         goto done;
   437     }
   438 
   439     CreateDXGIFactoryFunc = (PFN_CREATE_DXGI_FACTORY)SDL_LoadFunction(data->hDXGIMod, "CreateDXGIFactory");
   440     if (!CreateDXGIFactoryFunc) {
   441         result = E_FAIL;
   442         goto done;
   443     }
   444 
   445     data->hD3D11Mod = SDL_LoadObject("d3d11.dll");
   446     if (!data->hD3D11Mod) {
   447         result = E_FAIL;
   448         goto done;
   449     }
   450 
   451     D3D11CreateDeviceFunc = (PFN_D3D11_CREATE_DEVICE)SDL_LoadFunction(data->hD3D11Mod, "D3D11CreateDevice");
   452     if (!D3D11CreateDeviceFunc) {
   453         result = E_FAIL;
   454         goto done;
   455     }
   456 #endif /* __WINRT__ */
   457 
   458     result = CreateDXGIFactoryFunc(&SDL_IID_IDXGIFactory2, (void **)&data->dxgiFactory);
   459     if (FAILED(result)) {
   460         WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("CreateDXGIFactory"), result);
   461         goto done;
   462     }
   463 
   464     /* FIXME: Should we use the default adapter? */
   465     result = IDXGIFactory2_EnumAdapters(data->dxgiFactory, 0, &data->dxgiAdapter);
   466     if (FAILED(result)) {
   467         WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("D3D11CreateDevice"), result);
   468         goto done;
   469     }
   470 
   471     /* This flag adds support for surfaces with a different color channel ordering
   472      * than the API default. It is required for compatibility with Direct2D.
   473      */
   474     creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
   475 
   476     /* Make sure Direct3D's debugging feature gets used, if the app requests it. */
   477     if (SDL_GetHintBoolean(SDL_HINT_RENDER_DIRECT3D11_DEBUG, SDL_FALSE)) {
   478         creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
   479     }
   480 
   481     /* Create the Direct3D 11 API device object and a corresponding context. */
   482     result = D3D11CreateDeviceFunc(
   483         data->dxgiAdapter,
   484         D3D_DRIVER_TYPE_UNKNOWN,
   485         NULL,
   486         creationFlags, /* Set set debug and Direct2D compatibility flags. */
   487         featureLevels, /* List of feature levels this app can support. */
   488         SDL_arraysize(featureLevels),
   489         D3D11_SDK_VERSION, /* Always set this to D3D11_SDK_VERSION for Windows Store apps. */
   490         &d3dDevice, /* Returns the Direct3D device created. */
   491         &data->featureLevel, /* Returns feature level of device created. */
   492         &d3dContext /* Returns the device immediate context. */
   493         );
   494     if (FAILED(result)) {
   495         WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("D3D11CreateDevice"), result);
   496         goto done;
   497     }
   498 
   499     result = ID3D11Device_QueryInterface(d3dDevice, &SDL_IID_ID3D11Device1, (void **)&data->d3dDevice);
   500     if (FAILED(result)) {
   501         WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device to ID3D11Device1"), result);
   502         goto done;
   503     }
   504 
   505     result = ID3D11DeviceContext_QueryInterface(d3dContext, &SDL_IID_ID3D11DeviceContext1, (void **)&data->d3dContext);
   506     if (FAILED(result)) {
   507         WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext to ID3D11DeviceContext1"), result);
   508         goto done;
   509     }
   510 
   511     result = ID3D11Device_QueryInterface(d3dDevice, &SDL_IID_IDXGIDevice1, (void **)&dxgiDevice);
   512     if (FAILED(result)) {
   513         WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device to IDXGIDevice1"), result);
   514         goto done;
   515     }
   516 
   517     /* Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and
   518      * ensures that the application will only render after each VSync, minimizing power consumption.
   519      */
   520     result = IDXGIDevice1_SetMaximumFrameLatency(dxgiDevice, 1);
   521     if (FAILED(result)) {
   522         WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGIDevice1::SetMaximumFrameLatency"), result);
   523         goto done;
   524     }
   525 
   526     /* Make note of the maximum texture size
   527      * Max texture sizes are documented on MSDN, at:
   528      * http://msdn.microsoft.com/en-us/library/windows/apps/ff476876.aspx
   529      */
   530     switch (data->featureLevel) {
   531         case D3D_FEATURE_LEVEL_11_1:
   532         case D3D_FEATURE_LEVEL_11_0:
   533             renderer->info.max_texture_width = renderer->info.max_texture_height = 16384;
   534             break;
   535 
   536         case D3D_FEATURE_LEVEL_10_1:
   537         case D3D_FEATURE_LEVEL_10_0:
   538             renderer->info.max_texture_width = renderer->info.max_texture_height = 8192;
   539             break;
   540 
   541         case D3D_FEATURE_LEVEL_9_3:
   542             renderer->info.max_texture_width = renderer->info.max_texture_height = 4096;
   543             break;
   544 
   545         case D3D_FEATURE_LEVEL_9_2:
   546         case D3D_FEATURE_LEVEL_9_1:
   547             renderer->info.max_texture_width = renderer->info.max_texture_height = 2048;
   548             break;
   549 
   550         default:
   551             SDL_SetError("%s, Unexpected feature level: %d", __FUNCTION__, data->featureLevel);
   552             result = E_FAIL;
   553             goto done;
   554     }
   555 
   556     if (D3D11_CreateVertexShader(data->d3dDevice, &data->vertexShader, &data->inputLayout) < 0) {
   557         goto done;
   558     }
   559 
   560     for (i = 0; i < SDL_arraysize(data->pixelShaders); ++i) {
   561         if (D3D11_CreatePixelShader(data->d3dDevice, (D3D11_Shader)i, &data->pixelShaders[i]) < 0) {
   562             goto done;
   563         }
   564     }
   565 
   566     /* Setup space to hold vertex shader constants: */
   567     SDL_zero(constantBufferDesc);
   568     constantBufferDesc.ByteWidth = sizeof(VertexShaderConstants);
   569     constantBufferDesc.Usage = D3D11_USAGE_DEFAULT;
   570     constantBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
   571     result = ID3D11Device_CreateBuffer(data->d3dDevice,
   572         &constantBufferDesc,
   573         NULL,
   574         &data->vertexShaderConstants
   575         );
   576     if (FAILED(result)) {
   577         WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateBuffer [vertex shader constants]"), result);
   578         goto done;
   579     }
   580 
   581     /* Create samplers to use when drawing textures: */
   582     SDL_zero(samplerDesc);
   583     samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
   584     samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
   585     samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
   586     samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
   587     samplerDesc.MipLODBias = 0.0f;
   588     samplerDesc.MaxAnisotropy = 1;
   589     samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
   590     samplerDesc.MinLOD = 0.0f;
   591     samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
   592     result = ID3D11Device_CreateSamplerState(data->d3dDevice,
   593         &samplerDesc,
   594         &data->nearestPixelSampler
   595         );
   596     if (FAILED(result)) {
   597         WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateSamplerState [nearest-pixel filter]"), result);
   598         goto done;
   599     }
   600 
   601     samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
   602     result = ID3D11Device_CreateSamplerState(data->d3dDevice,
   603         &samplerDesc,
   604         &data->linearSampler
   605         );
   606     if (FAILED(result)) {
   607         WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateSamplerState [linear filter]"), result);
   608         goto done;
   609     }
   610 
   611     /* Setup Direct3D rasterizer states */
   612     SDL_zero(rasterDesc);
   613     rasterDesc.AntialiasedLineEnable = FALSE;
   614     rasterDesc.CullMode = D3D11_CULL_NONE;
   615     rasterDesc.DepthBias = 0;
   616     rasterDesc.DepthBiasClamp = 0.0f;
   617     rasterDesc.DepthClipEnable = TRUE;
   618     rasterDesc.FillMode = D3D11_FILL_SOLID;
   619     rasterDesc.FrontCounterClockwise = FALSE;
   620     rasterDesc.MultisampleEnable = FALSE;
   621     rasterDesc.ScissorEnable = FALSE;
   622     rasterDesc.SlopeScaledDepthBias = 0.0f;
   623     result = ID3D11Device_CreateRasterizerState(data->d3dDevice, &rasterDesc, &data->mainRasterizer);
   624     if (FAILED(result)) {
   625         WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateRasterizerState [main rasterizer]"), result);
   626         goto done;
   627     }
   628 
   629     rasterDesc.ScissorEnable = TRUE;
   630     result = ID3D11Device_CreateRasterizerState(data->d3dDevice, &rasterDesc, &data->clippedRasterizer);
   631     if (FAILED(result)) {
   632         WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateRasterizerState [clipped rasterizer]"), result);
   633         goto done;
   634     }
   635 
   636     /* Create blending states: */
   637     if (!D3D11_CreateBlendState(renderer, SDL_BLENDMODE_BLEND) ||
   638         !D3D11_CreateBlendState(renderer, SDL_BLENDMODE_ADD) ||
   639         !D3D11_CreateBlendState(renderer, SDL_BLENDMODE_MOD)) {
   640         /* D3D11_CreateBlendMode will set the SDL error, if it fails */
   641         goto done;
   642     }
   643 
   644     /* Setup render state that doesn't change */
   645     ID3D11DeviceContext_IASetInputLayout(data->d3dContext, data->inputLayout);
   646     ID3D11DeviceContext_VSSetShader(data->d3dContext, data->vertexShader, NULL, 0);
   647     ID3D11DeviceContext_VSSetConstantBuffers(data->d3dContext, 0, 1, &data->vertexShaderConstants);
   648 
   649 done:
   650     SAFE_RELEASE(d3dDevice);
   651     SAFE_RELEASE(d3dContext);
   652     SAFE_RELEASE(dxgiDevice);
   653     return result;
   654 }
   655 
   656 #ifdef __WIN32__
   657 
   658 static DXGI_MODE_ROTATION
   659 D3D11_GetCurrentRotation()
   660 {
   661     /* FIXME */
   662     return DXGI_MODE_ROTATION_IDENTITY;
   663 }
   664 
   665 #endif /* __WIN32__ */
   666 
   667 static BOOL
   668 D3D11_IsDisplayRotated90Degrees(DXGI_MODE_ROTATION rotation)
   669 {
   670     switch (rotation) {
   671         case DXGI_MODE_ROTATION_ROTATE90:
   672         case DXGI_MODE_ROTATION_ROTATE270:
   673             return TRUE;
   674         default:
   675             return FALSE;
   676     }
   677 }
   678 
   679 static int
   680 D3D11_GetRotationForCurrentRenderTarget(SDL_Renderer * renderer)
   681 {
   682     D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata;
   683     if (data->currentOffscreenRenderTargetView) {
   684         return DXGI_MODE_ROTATION_IDENTITY;
   685     } else {
   686         return data->rotation;
   687     }
   688 }
   689 
   690 static int
   691 D3D11_GetViewportAlignedD3DRect(SDL_Renderer * renderer, const SDL_Rect * sdlRect, D3D11_RECT * outRect, BOOL includeViewportOffset)
   692 {
   693     const int rotation = D3D11_GetRotationForCurrentRenderTarget(renderer);
   694     switch (rotation) {
   695         case DXGI_MODE_ROTATION_IDENTITY:
   696             outRect->left = sdlRect->x;
   697             outRect->right = sdlRect->x + sdlRect->w;
   698             outRect->top = sdlRect->y;
   699             outRect->bottom = sdlRect->y + sdlRect->h;
   700             if (includeViewportOffset) {
   701                 outRect->left += renderer->viewport.x;
   702                 outRect->right += renderer->viewport.x;
   703                 outRect->top += renderer->viewport.y;
   704                 outRect->bottom += renderer->viewport.y;
   705             }
   706             break;
   707         case DXGI_MODE_ROTATION_ROTATE270:
   708             outRect->left = sdlRect->y;
   709             outRect->right = sdlRect->y + sdlRect->h;
   710             outRect->top = renderer->viewport.w - sdlRect->x - sdlRect->w;
   711             outRect->bottom = renderer->viewport.w - sdlRect->x;
   712             break;
   713         case DXGI_MODE_ROTATION_ROTATE180:
   714             outRect->left = renderer->viewport.w - sdlRect->x - sdlRect->w;
   715             outRect->right = renderer->viewport.w - sdlRect->x;
   716             outRect->top = renderer->viewport.h - sdlRect->y - sdlRect->h;
   717             outRect->bottom = renderer->viewport.h - sdlRect->y;
   718             break;
   719         case DXGI_MODE_ROTATION_ROTATE90:
   720             outRect->left = renderer->viewport.h - sdlRect->y - sdlRect->h;
   721             outRect->right = renderer->viewport.h - sdlRect->y;
   722             outRect->top = sdlRect->x;
   723             outRect->bottom = sdlRect->x + sdlRect->h;
   724             break;
   725         default:
   726             return SDL_SetError("The physical display is in an unknown or unsupported rotation");
   727     }
   728     return 0;
   729 }
   730 
   731 static HRESULT
   732 D3D11_CreateSwapChain(SDL_Renderer * renderer, int w, int h)
   733 {
   734     D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata;
   735 #ifdef __WINRT__
   736     IUnknown *coreWindow = D3D11_GetCoreWindowFromSDLRenderer(renderer);
   737     const BOOL usingXAML = (coreWindow == NULL);
   738 #else
   739     IUnknown *coreWindow = NULL;
   740     const BOOL usingXAML = FALSE;
   741 #endif
   742     HRESULT result = S_OK;
   743 
   744     /* Create a swap chain using the same adapter as the existing Direct3D device. */
   745     DXGI_SWAP_CHAIN_DESC1 swapChainDesc;
   746     SDL_zero(swapChainDesc);
   747     swapChainDesc.Width = w;
   748     swapChainDesc.Height = h;
   749     swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; /* This is the most common swap chain format. */
   750     swapChainDesc.Stereo = FALSE;
   751     swapChainDesc.SampleDesc.Count = 1; /* Don't use multi-sampling. */
   752     swapChainDesc.SampleDesc.Quality = 0;
   753     swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
   754     swapChainDesc.BufferCount = 2; /* Use double-buffering to minimize latency. */
   755 #if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
   756     swapChainDesc.Scaling = DXGI_SCALING_STRETCH; /* On phone, only stretch and aspect-ratio stretch scaling are allowed. */
   757     swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; /* On phone, no swap effects are supported. */
   758     /* 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 */
   759 #else
   760     if (usingXAML) {
   761         swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
   762     } else {
   763         swapChainDesc.Scaling = DXGI_SCALING_NONE;
   764     }
   765     swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; /* All Windows Store apps must use this SwapEffect. */
   766 #endif
   767     swapChainDesc.Flags = 0;
   768 
   769     if (coreWindow) {
   770         result = IDXGIFactory2_CreateSwapChainForCoreWindow(data->dxgiFactory,
   771             (IUnknown *)data->d3dDevice,
   772             coreWindow,
   773             &swapChainDesc,
   774             NULL, /* Allow on all displays. */
   775             &data->swapChain
   776             );
   777         if (FAILED(result)) {
   778             WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGIFactory2::CreateSwapChainForCoreWindow"), result);
   779             goto done;
   780         }
   781     } else if (usingXAML) {
   782         result = IDXGIFactory2_CreateSwapChainForComposition(data->dxgiFactory,
   783             (IUnknown *)data->d3dDevice,
   784             &swapChainDesc,
   785             NULL,
   786             &data->swapChain);
   787         if (FAILED(result)) {
   788             WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGIFactory2::CreateSwapChainForComposition"), result);
   789             goto done;
   790         }
   791 
   792 #if WINAPI_FAMILY == WINAPI_FAMILY_APP
   793         result = ISwapChainBackgroundPanelNative_SetSwapChain(WINRT_GlobalSwapChainBackgroundPanelNative, (IDXGISwapChain *) data->swapChain);
   794         if (FAILED(result)) {
   795             WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ISwapChainBackgroundPanelNative::SetSwapChain"), result);
   796             goto done;
   797         }
   798 #else
   799         SDL_SetError(SDL_COMPOSE_ERROR("XAML support is not yet available for Windows Phone"));
   800         result = E_FAIL;
   801         goto done;
   802 #endif
   803     } else {
   804 #ifdef __WIN32__
   805         SDL_SysWMinfo windowinfo;
   806         SDL_VERSION(&windowinfo.version);
   807         SDL_GetWindowWMInfo(renderer->window, &windowinfo);
   808 
   809         result = IDXGIFactory2_CreateSwapChainForHwnd(data->dxgiFactory,
   810             (IUnknown *)data->d3dDevice,
   811             windowinfo.info.win.window,
   812             &swapChainDesc,
   813             NULL,
   814             NULL, /* Allow on all displays. */
   815             &data->swapChain
   816             );
   817         if (FAILED(result)) {
   818             WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGIFactory2::CreateSwapChainForHwnd"), result);
   819             goto done;
   820         }
   821 
   822         IDXGIFactory_MakeWindowAssociation(data->dxgiFactory, windowinfo.info.win.window, DXGI_MWA_NO_WINDOW_CHANGES);
   823 #else
   824         SDL_SetError(__FUNCTION__", Unable to find something to attach a swap chain to");
   825         goto done;
   826 #endif  /* ifdef __WIN32__ / else */
   827     }
   828     data->swapEffect = swapChainDesc.SwapEffect;
   829 
   830 done:
   831     SAFE_RELEASE(coreWindow);
   832     return result;
   833 }
   834 
   835 static void
   836 D3D11_ReleaseMainRenderTargetView(SDL_Renderer * renderer)
   837 {
   838     D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata;
   839     ID3D11DeviceContext_OMSetRenderTargets(data->d3dContext, 0, NULL, NULL);
   840     SAFE_RELEASE(data->mainRenderTargetView);
   841 }
   842 
   843 static HRESULT D3D11_UpdateForWindowSizeChange(SDL_Renderer * renderer);
   844 
   845 
   846 HRESULT
   847 D3D11_HandleDeviceLost(SDL_Renderer * renderer)
   848 {
   849     HRESULT result = S_OK;
   850 
   851     D3D11_ReleaseAll(renderer);
   852 
   853     result = D3D11_CreateDeviceResources(renderer);
   854     if (FAILED(result)) {
   855         /* D3D11_CreateDeviceResources will set the SDL error */
   856         return result;
   857     }
   858 
   859     result = D3D11_UpdateForWindowSizeChange(renderer);
   860     if (FAILED(result)) {
   861         /* D3D11_UpdateForWindowSizeChange will set the SDL error */
   862         return result;
   863     }
   864 
   865     /* Let the application know that the device has been reset */
   866     {
   867         SDL_Event event;
   868         event.type = SDL_RENDER_DEVICE_RESET;
   869         SDL_PushEvent(&event);
   870     }
   871 
   872     return S_OK;
   873 }
   874 
   875 /* Initialize all resources that change when the window's size changes. */
   876 static HRESULT
   877 D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
   878 {
   879     D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata;
   880     ID3D11Texture2D *backBuffer = NULL;
   881     HRESULT result = S_OK;
   882     int w, h;
   883 
   884     /* Release the previous render target view */
   885     D3D11_ReleaseMainRenderTargetView(renderer);
   886 
   887     /* The width and height of the swap chain must be based on the display's
   888      * non-rotated size.
   889      */
   890     SDL_GetWindowSize(renderer->window, &w, &h);
   891     data->rotation = D3D11_GetCurrentRotation();
   892     /* SDL_Log("%s: windowSize={%d,%d}, orientation=%d\n", __FUNCTION__, w, h, (int)data->rotation); */
   893     if (D3D11_IsDisplayRotated90Degrees(data->rotation)) {
   894         int tmp = w;
   895         w = h;
   896         h = tmp;
   897     }
   898 
   899     if (data->swapChain) {
   900         /* IDXGISwapChain::ResizeBuffers is not available on Windows Phone 8. */
   901 #if !defined(__WINRT__) || (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP)
   902         /* If the swap chain already exists, resize it. */
   903         result = IDXGISwapChain_ResizeBuffers(data->swapChain,
   904             0,
   905             w, h,
   906             DXGI_FORMAT_UNKNOWN,
   907             0
   908             );
   909         if (result == DXGI_ERROR_DEVICE_REMOVED) {
   910             /* If the device was removed for any reason, a new device and swap chain will need to be created. */
   911             D3D11_HandleDeviceLost(renderer);
   912 
   913             /* Everything is set up now. Do not continue execution of this method. HandleDeviceLost will reenter this method 
   914              * and correctly set up the new device.
   915              */
   916             goto done;
   917         } else if (FAILED(result)) {
   918             WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain::ResizeBuffers"), result);
   919             goto done;
   920         }
   921 #endif
   922     } else {
   923         result = D3D11_CreateSwapChain(renderer, w, h);
   924         if (FAILED(result)) {
   925             goto done;
   926         }
   927     }
   928     
   929 #if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
   930     /* Set the proper rotation for the swap chain.
   931      *
   932      * To note, the call for this, IDXGISwapChain1::SetRotation, is not necessary
   933      * on Windows Phone 8.0, nor is it supported there.
   934      *
   935      * IDXGISwapChain1::SetRotation does seem to be available on Windows Phone 8.1,
   936      * however I've yet to find a way to make it work.  It might have something to
   937      * do with IDXGISwapChain::ResizeBuffers appearing to not being available on
   938      * Windows Phone 8.1 (it wasn't on Windows Phone 8.0), but I'm not 100% sure of this.
   939      * The call doesn't appear to be entirely necessary though, and is a performance-related
   940      * call, at least according to the following page on MSDN:
   941      * http://code.msdn.microsoft.com/windowsapps/DXGI-swap-chain-rotation-21d13d71
   942      *   -- David L.
   943      *
   944      * TODO, WinRT: reexamine the docs for IDXGISwapChain1::SetRotation, see if might be available, usable, and prudent-to-call on WinPhone 8.1
   945      */
   946     if (data->swapEffect == DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL) {
   947         result = IDXGISwapChain1_SetRotation(data->swapChain, data->rotation);
   948         if (FAILED(result)) {
   949             WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain1::SetRotation"), result);
   950             goto done;
   951         }
   952     }
   953 #endif
   954 
   955     result = IDXGISwapChain_GetBuffer(data->swapChain,
   956         0,
   957         &SDL_IID_ID3D11Texture2D,
   958         (void **)&backBuffer
   959         );
   960     if (FAILED(result)) {
   961         WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain::GetBuffer [back-buffer]"), result);
   962         goto done;
   963     }
   964 
   965     /* Create a render target view of the swap chain back buffer. */
   966     result = ID3D11Device_CreateRenderTargetView(data->d3dDevice,
   967         (ID3D11Resource *)backBuffer,
   968         NULL,
   969         &data->mainRenderTargetView
   970         );
   971     if (FAILED(result)) {
   972         WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device::CreateRenderTargetView"), result);
   973         goto done;
   974     }
   975 
   976     data->viewportDirty = SDL_TRUE;
   977 
   978 done:
   979     SAFE_RELEASE(backBuffer);
   980     return result;
   981 }
   982 
   983 /* This method is called when the window's size changes. */
   984 static HRESULT
   985 D3D11_UpdateForWindowSizeChange(SDL_Renderer * renderer)
   986 {
   987     return D3D11_CreateWindowSizeDependentResources(renderer);
   988 }
   989 
   990 void
   991 D3D11_Trim(SDL_Renderer * renderer)
   992 {
   993 #ifdef __WINRT__
   994 #if NTDDI_VERSION > NTDDI_WIN8
   995     D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata;
   996     HRESULT result = S_OK;
   997     IDXGIDevice3 *dxgiDevice = NULL;
   998 
   999     result = ID3D11Device_QueryInterface(data->d3dDevice, &SDL_IID_IDXGIDevice3, &dxgiDevice);
  1000     if (FAILED(result)) {
  1001         //WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device to IDXGIDevice3", result);
  1002         return;
  1003     }
  1004 
  1005     IDXGIDevice3_Trim(dxgiDevice);
  1006     SAFE_RELEASE(dxgiDevice);
  1007 #endif
  1008 #endif
  1009 }
  1010 
  1011 static void
  1012 D3D11_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
  1013 {
  1014     if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) {
  1015         D3D11_UpdateForWindowSizeChange(renderer);
  1016     }
  1017 }
  1018 
  1019 static SDL_bool
  1020 D3D11_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
  1021 {
  1022     SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode);
  1023     SDL_BlendFactor srcAlphaFactor = SDL_GetBlendModeSrcAlphaFactor(blendMode);
  1024     SDL_BlendOperation colorOperation = SDL_GetBlendModeColorOperation(blendMode);
  1025     SDL_BlendFactor dstColorFactor = SDL_GetBlendModeDstColorFactor(blendMode);
  1026     SDL_BlendFactor dstAlphaFactor = SDL_GetBlendModeDstAlphaFactor(blendMode);
  1027     SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode);
  1028 
  1029     if (!GetBlendFunc(srcColorFactor) || !GetBlendFunc(srcAlphaFactor) ||
  1030         !GetBlendEquation(colorOperation) ||
  1031         !GetBlendFunc(dstColorFactor) || !GetBlendFunc(dstAlphaFactor) ||
  1032         !GetBlendEquation(alphaOperation)) {
  1033         return SDL_FALSE;
  1034     }
  1035     return SDL_TRUE;
  1036 }
  1037 
  1038 static int
  1039 D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
  1040 {
  1041     D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  1042     D3D11_TextureData *textureData;
  1043     HRESULT result;
  1044     DXGI_FORMAT textureFormat = SDLPixelFormatToDXGIFormat(texture->format);
  1045     D3D11_TEXTURE2D_DESC textureDesc;
  1046     D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
  1047 
  1048     if (textureFormat == DXGI_FORMAT_UNKNOWN) {
  1049         return SDL_SetError("%s, An unsupported SDL pixel format (0x%x) was specified",
  1050             __FUNCTION__, texture->format);
  1051     }
  1052 
  1053     textureData = (D3D11_TextureData*) SDL_calloc(1, sizeof(*textureData));
  1054     if (!textureData) {
  1055         SDL_OutOfMemory();
  1056         return -1;
  1057     }
  1058     textureData->scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ?  D3D11_FILTER_MIN_MAG_MIP_POINT : D3D11_FILTER_MIN_MAG_MIP_LINEAR;
  1059 
  1060     texture->driverdata = textureData;
  1061 
  1062     SDL_zero(textureDesc);
  1063     textureDesc.Width = texture->w;
  1064     textureDesc.Height = texture->h;
  1065     textureDesc.MipLevels = 1;
  1066     textureDesc.ArraySize = 1;
  1067     textureDesc.Format = textureFormat;
  1068     textureDesc.SampleDesc.Count = 1;
  1069     textureDesc.SampleDesc.Quality = 0;
  1070     textureDesc.MiscFlags = 0;
  1071 
  1072     if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
  1073         textureDesc.Usage = D3D11_USAGE_DYNAMIC;
  1074         textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
  1075     } else {
  1076         textureDesc.Usage = D3D11_USAGE_DEFAULT;
  1077         textureDesc.CPUAccessFlags = 0;
  1078     }
  1079 
  1080     if (texture->access == SDL_TEXTUREACCESS_TARGET) {
  1081         textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
  1082     } else {
  1083         textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
  1084     }
  1085 
  1086     result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
  1087         &textureDesc,
  1088         NULL,
  1089         &textureData->mainTexture
  1090         );
  1091     if (FAILED(result)) {
  1092         D3D11_DestroyTexture(renderer, texture);
  1093         WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
  1094         return -1;
  1095     }
  1096 
  1097     if (texture->format == SDL_PIXELFORMAT_YV12 ||
  1098         texture->format == SDL_PIXELFORMAT_IYUV) {
  1099         textureData->yuv = SDL_TRUE;
  1100 
  1101         textureDesc.Width = (textureDesc.Width + 1) / 2;
  1102         textureDesc.Height = (textureDesc.Height + 1) / 2;
  1103 
  1104         result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
  1105             &textureDesc,
  1106             NULL,
  1107             &textureData->mainTextureU
  1108             );
  1109         if (FAILED(result)) {
  1110             D3D11_DestroyTexture(renderer, texture);
  1111             WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
  1112             return -1;
  1113         }
  1114 
  1115         result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
  1116             &textureDesc,
  1117             NULL,
  1118             &textureData->mainTextureV
  1119             );
  1120         if (FAILED(result)) {
  1121             D3D11_DestroyTexture(renderer, texture);
  1122             WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
  1123             return -1;
  1124         }
  1125     }
  1126 
  1127     if (texture->format == SDL_PIXELFORMAT_NV12 ||
  1128         texture->format == SDL_PIXELFORMAT_NV21) {
  1129         D3D11_TEXTURE2D_DESC nvTextureDesc = textureDesc;
  1130 
  1131         textureData->nv12 = SDL_TRUE;
  1132 
  1133         nvTextureDesc.Format = DXGI_FORMAT_R8G8_UNORM;
  1134         nvTextureDesc.Width = (textureDesc.Width + 1) / 2;
  1135         nvTextureDesc.Height = (textureDesc.Height + 1) / 2;
  1136 
  1137         result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
  1138             &nvTextureDesc,
  1139             NULL,
  1140             &textureData->mainTextureNV
  1141             );
  1142         if (FAILED(result)) {
  1143             D3D11_DestroyTexture(renderer, texture);
  1144             WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
  1145             return -1;
  1146         }
  1147     }
  1148 
  1149     resourceViewDesc.Format = textureDesc.Format;
  1150     resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
  1151     resourceViewDesc.Texture2D.MostDetailedMip = 0;
  1152     resourceViewDesc.Texture2D.MipLevels = textureDesc.MipLevels;
  1153     result = ID3D11Device_CreateShaderResourceView(rendererData->d3dDevice,
  1154         (ID3D11Resource *)textureData->mainTexture,
  1155         &resourceViewDesc,
  1156         &textureData->mainTextureResourceView
  1157         );
  1158     if (FAILED(result)) {
  1159         D3D11_DestroyTexture(renderer, texture);
  1160         WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result);
  1161         return -1;
  1162     }
  1163 
  1164     if (textureData->yuv) {
  1165         result = ID3D11Device_CreateShaderResourceView(rendererData->d3dDevice,
  1166             (ID3D11Resource *)textureData->mainTextureU,
  1167             &resourceViewDesc,
  1168             &textureData->mainTextureResourceViewU
  1169             );
  1170         if (FAILED(result)) {
  1171             D3D11_DestroyTexture(renderer, texture);
  1172             WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result);
  1173             return -1;
  1174         }
  1175         result = ID3D11Device_CreateShaderResourceView(rendererData->d3dDevice,
  1176             (ID3D11Resource *)textureData->mainTextureV,
  1177             &resourceViewDesc,
  1178             &textureData->mainTextureResourceViewV
  1179             );
  1180         if (FAILED(result)) {
  1181             D3D11_DestroyTexture(renderer, texture);
  1182             WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result);
  1183             return -1;
  1184         }
  1185     }
  1186 
  1187     if (textureData->nv12) {
  1188         D3D11_SHADER_RESOURCE_VIEW_DESC nvResourceViewDesc = resourceViewDesc;
  1189 
  1190         nvResourceViewDesc.Format = DXGI_FORMAT_R8G8_UNORM;
  1191 
  1192         result = ID3D11Device_CreateShaderResourceView(rendererData->d3dDevice,
  1193             (ID3D11Resource *)textureData->mainTextureNV,
  1194             &nvResourceViewDesc,
  1195             &textureData->mainTextureResourceViewNV
  1196             );
  1197         if (FAILED(result)) {
  1198             D3D11_DestroyTexture(renderer, texture);
  1199             WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result);
  1200             return -1;
  1201         }
  1202     }
  1203 
  1204     if (texture->access & SDL_TEXTUREACCESS_TARGET) {
  1205         D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
  1206         renderTargetViewDesc.Format = textureDesc.Format;
  1207         renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
  1208         renderTargetViewDesc.Texture2D.MipSlice = 0;
  1209 
  1210         result = ID3D11Device_CreateRenderTargetView(rendererData->d3dDevice,
  1211             (ID3D11Resource *)textureData->mainTexture,
  1212             &renderTargetViewDesc,
  1213             &textureData->mainTextureRenderTargetView);
  1214         if (FAILED(result)) {
  1215             D3D11_DestroyTexture(renderer, texture);
  1216             WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateRenderTargetView"), result);
  1217             return -1;
  1218         }
  1219     }
  1220 
  1221     return 0;
  1222 }
  1223 
  1224 static void
  1225 D3D11_DestroyTexture(SDL_Renderer * renderer,
  1226                      SDL_Texture * texture)
  1227 {
  1228     D3D11_TextureData *data = (D3D11_TextureData *)texture->driverdata;
  1229 
  1230     if (!data) {
  1231         return;
  1232     }
  1233 
  1234     SAFE_RELEASE(data->mainTexture);
  1235     SAFE_RELEASE(data->mainTextureResourceView);
  1236     SAFE_RELEASE(data->mainTextureRenderTargetView);
  1237     SAFE_RELEASE(data->stagingTexture);
  1238     SAFE_RELEASE(data->mainTextureU);
  1239     SAFE_RELEASE(data->mainTextureResourceViewU);
  1240     SAFE_RELEASE(data->mainTextureV);
  1241     SAFE_RELEASE(data->mainTextureResourceViewV);
  1242     SDL_free(data->pixels);
  1243     SDL_free(data);
  1244     texture->driverdata = NULL;
  1245 }
  1246 
  1247 static int
  1248 D3D11_UpdateTextureInternal(D3D11_RenderData *rendererData, ID3D11Texture2D *texture, int bpp, int x, int y, int w, int h, const void *pixels, int pitch)
  1249 {
  1250     ID3D11Texture2D *stagingTexture;
  1251     const Uint8 *src;
  1252     Uint8 *dst;
  1253     int row;
  1254     UINT length;
  1255     HRESULT result;
  1256     D3D11_TEXTURE2D_DESC stagingTextureDesc;
  1257     D3D11_MAPPED_SUBRESOURCE textureMemory;
  1258 
  1259     /* Create a 'staging' texture, which will be used to write to a portion of the main texture. */
  1260     ID3D11Texture2D_GetDesc(texture, &stagingTextureDesc);
  1261     stagingTextureDesc.Width = w;
  1262     stagingTextureDesc.Height = h;
  1263     stagingTextureDesc.BindFlags = 0;
  1264     stagingTextureDesc.MiscFlags = 0;
  1265     stagingTextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
  1266     stagingTextureDesc.Usage = D3D11_USAGE_STAGING;
  1267     result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
  1268         &stagingTextureDesc,
  1269         NULL,
  1270         &stagingTexture);
  1271     if (FAILED(result)) {
  1272         WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D [create staging texture]"), result);
  1273         return -1;
  1274     }
  1275 
  1276     /* Get a write-only pointer to data in the staging texture: */
  1277     result = ID3D11DeviceContext_Map(rendererData->d3dContext,
  1278         (ID3D11Resource *)stagingTexture,
  1279         0,
  1280         D3D11_MAP_WRITE,
  1281         0,
  1282         &textureMemory
  1283         );
  1284     if (FAILED(result)) {
  1285         WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [map staging texture]"), result);
  1286         SAFE_RELEASE(stagingTexture);
  1287         return -1;
  1288     }
  1289 
  1290     src = (const Uint8 *)pixels;
  1291     dst = textureMemory.pData;
  1292     length = w * bpp;
  1293     if (length == pitch && length == textureMemory.RowPitch) {
  1294         SDL_memcpy(dst, src, length*h);
  1295     } else {
  1296         if (length > (UINT)pitch) {
  1297             length = pitch;
  1298         }
  1299         if (length > textureMemory.RowPitch) {
  1300             length = textureMemory.RowPitch;
  1301         }
  1302         for (row = 0; row < h; ++row) {
  1303             SDL_memcpy(dst, src, length);
  1304             src += pitch;
  1305             dst += textureMemory.RowPitch;
  1306         }
  1307     }
  1308 
  1309     /* Commit the pixel buffer's changes back to the staging texture: */
  1310     ID3D11DeviceContext_Unmap(rendererData->d3dContext,
  1311         (ID3D11Resource *)stagingTexture,
  1312         0);
  1313 
  1314     /* Copy the staging texture's contents back to the texture: */
  1315     ID3D11DeviceContext_CopySubresourceRegion(rendererData->d3dContext,
  1316         (ID3D11Resource *)texture,
  1317         0,
  1318         x,
  1319         y,
  1320         0,
  1321         (ID3D11Resource *)stagingTexture,
  1322         0,
  1323         NULL);
  1324 
  1325     SAFE_RELEASE(stagingTexture);
  1326 
  1327     return 0;
  1328 }
  1329 
  1330 static int
  1331 D3D11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
  1332                     const SDL_Rect * rect, const void * srcPixels,
  1333                     int srcPitch)
  1334 {
  1335     D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata;
  1336     D3D11_TextureData *textureData = (D3D11_TextureData *)texture->driverdata;
  1337 
  1338     if (!textureData) {
  1339         SDL_SetError("Texture is not currently available");
  1340         return -1;
  1341     }
  1342 
  1343     if (D3D11_UpdateTextureInternal(rendererData, textureData->mainTexture, SDL_BYTESPERPIXEL(texture->format), rect->x, rect->y, rect->w, rect->h, srcPixels, srcPitch) < 0) {
  1344         return -1;
  1345     }
  1346 
  1347     if (textureData->yuv) {
  1348         /* Skip to the correct offset into the next texture */
  1349         srcPixels = (const void*)((const Uint8*)srcPixels + rect->h * srcPitch);
  1350 
  1351         if (D3D11_UpdateTextureInternal(rendererData, texture->format == SDL_PIXELFORMAT_YV12 ? textureData->mainTextureV : textureData->mainTextureU, SDL_BYTESPERPIXEL(texture->format), rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, srcPixels, (srcPitch + 1) / 2) < 0) {
  1352             return -1;
  1353         }
  1354 
  1355         /* Skip to the correct offset into the next texture */
  1356         srcPixels = (const void*)((const Uint8*)srcPixels + ((rect->h + 1) / 2) * ((srcPitch + 1) / 2));
  1357         if (D3D11_UpdateTextureInternal(rendererData, texture->format == SDL_PIXELFORMAT_YV12 ? textureData->mainTextureU : textureData->mainTextureV, SDL_BYTESPERPIXEL(texture->format), rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, srcPixels, (srcPitch + 1) / 2) < 0) {
  1358             return -1;
  1359         }
  1360     }
  1361 
  1362     if (textureData->nv12) {
  1363         /* Skip to the correct offset into the next texture */
  1364         srcPixels = (const void*)((const Uint8*)srcPixels + rect->h * srcPitch);
  1365 
  1366         if (D3D11_UpdateTextureInternal(rendererData, textureData->mainTextureNV, 2, rect->x / 2, rect->y / 2, ((rect->w + 1) / 2), (rect->h + 1) / 2, srcPixels, 2*((srcPitch + 1) / 2)) < 0) {
  1367             return -1;
  1368         }
  1369     }
  1370     return 0;
  1371 }
  1372 
  1373 static int
  1374 D3D11_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
  1375                        const SDL_Rect * rect,
  1376                        const Uint8 *Yplane, int Ypitch,
  1377                        const Uint8 *Uplane, int Upitch,
  1378                        const Uint8 *Vplane, int Vpitch)
  1379 {
  1380     D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata;
  1381     D3D11_TextureData *textureData = (D3D11_TextureData *)texture->driverdata;
  1382 
  1383     if (!textureData) {
  1384         SDL_SetError("Texture is not currently available");
  1385         return -1;
  1386     }
  1387 
  1388     if (D3D11_UpdateTextureInternal(rendererData, textureData->mainTexture, SDL_BYTESPERPIXEL(texture->format), rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch) < 0) {
  1389         return -1;
  1390     }
  1391     if (D3D11_UpdateTextureInternal(rendererData, textureData->mainTextureU, SDL_BYTESPERPIXEL(texture->format), rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Uplane, Upitch) < 0) {
  1392         return -1;
  1393     }
  1394     if (D3D11_UpdateTextureInternal(rendererData, textureData->mainTextureV, SDL_BYTESPERPIXEL(texture->format), rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Vplane, Vpitch) < 0) {
  1395         return -1;
  1396     }
  1397     return 0;
  1398 }
  1399 
  1400 static int
  1401 D3D11_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
  1402                   const SDL_Rect * rect, void **pixels, int *pitch)
  1403 {
  1404     D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  1405     D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
  1406     HRESULT result = S_OK;
  1407     D3D11_TEXTURE2D_DESC stagingTextureDesc;
  1408     D3D11_MAPPED_SUBRESOURCE textureMemory;
  1409 
  1410     if (!textureData) {
  1411         SDL_SetError("Texture is not currently available");
  1412         return -1;
  1413     }
  1414 
  1415     if (textureData->yuv || textureData->nv12) {
  1416         /* It's more efficient to upload directly... */
  1417         if (!textureData->pixels) {
  1418             textureData->pitch = texture->w;
  1419             textureData->pixels = (Uint8 *)SDL_malloc((texture->h * textureData->pitch * 3) / 2);
  1420             if (!textureData->pixels) {
  1421                 return SDL_OutOfMemory();
  1422             }
  1423         }
  1424         textureData->locked_rect = *rect;
  1425         *pixels =
  1426             (void *)((Uint8 *)textureData->pixels + rect->y * textureData->pitch +
  1427             rect->x * SDL_BYTESPERPIXEL(texture->format));
  1428         *pitch = textureData->pitch;
  1429         return 0;
  1430     }
  1431 
  1432     if (textureData->stagingTexture) {
  1433         return SDL_SetError("texture is already locked");
  1434     }
  1435     
  1436     /* Create a 'staging' texture, which will be used to write to a portion
  1437      * of the main texture.  This is necessary, as Direct3D 11.1 does not
  1438      * have the ability to write a CPU-bound pixel buffer to a rectangular
  1439      * subrect of a texture.  Direct3D 11.1 can, however, write a pixel
  1440      * buffer to an entire texture, hence the use of a staging texture.
  1441      *
  1442      * TODO, WinRT: consider avoiding the use of a staging texture in D3D11_LockTexture if/when the entire texture is being updated
  1443      */
  1444     ID3D11Texture2D_GetDesc(textureData->mainTexture, &stagingTextureDesc);
  1445     stagingTextureDesc.Width = rect->w;
  1446     stagingTextureDesc.Height = rect->h;
  1447     stagingTextureDesc.BindFlags = 0;
  1448     stagingTextureDesc.MiscFlags = 0;
  1449     stagingTextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
  1450     stagingTextureDesc.Usage = D3D11_USAGE_STAGING;
  1451     result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
  1452         &stagingTextureDesc,
  1453         NULL,
  1454         &textureData->stagingTexture);
  1455     if (FAILED(result)) {
  1456         WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D [create staging texture]"), result);
  1457         return -1;
  1458     }
  1459 
  1460     /* Get a write-only pointer to data in the staging texture: */
  1461     result = ID3D11DeviceContext_Map(rendererData->d3dContext,
  1462         (ID3D11Resource *)textureData->stagingTexture,
  1463         0,
  1464         D3D11_MAP_WRITE,
  1465         0,
  1466         &textureMemory
  1467         );
  1468     if (FAILED(result)) {
  1469         WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [map staging texture]"), result);
  1470         SAFE_RELEASE(textureData->stagingTexture);
  1471         return -1;
  1472     }
  1473 
  1474     /* Make note of where the staging texture will be written to 
  1475      * (on a call to SDL_UnlockTexture):
  1476      */
  1477     textureData->lockedTexturePositionX = rect->x;
  1478     textureData->lockedTexturePositionY = rect->y;
  1479 
  1480     /* Make sure the caller has information on the texture's pixel buffer,
  1481      * then return:
  1482      */
  1483     *pixels = textureMemory.pData;
  1484     *pitch = textureMemory.RowPitch;
  1485     return 0;
  1486 }
  1487 
  1488 static void
  1489 D3D11_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
  1490 {
  1491     D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  1492     D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
  1493     
  1494     if (!textureData) {
  1495         return;
  1496     }
  1497 
  1498     if (textureData->yuv || textureData->nv12) {
  1499         const SDL_Rect *rect = &textureData->locked_rect;
  1500         void *pixels =
  1501             (void *) ((Uint8 *) textureData->pixels + rect->y * textureData->pitch +
  1502                       rect->x * SDL_BYTESPERPIXEL(texture->format));
  1503         D3D11_UpdateTexture(renderer, texture, rect, pixels, textureData->pitch);
  1504         return;
  1505     }
  1506 
  1507     /* Commit the pixel buffer's changes back to the staging texture: */
  1508     ID3D11DeviceContext_Unmap(rendererData->d3dContext,
  1509         (ID3D11Resource *)textureData->stagingTexture,
  1510         0);
  1511 
  1512     /* Copy the staging texture's contents back to the main texture: */
  1513     ID3D11DeviceContext_CopySubresourceRegion(rendererData->d3dContext,
  1514         (ID3D11Resource *)textureData->mainTexture,
  1515         0,
  1516         textureData->lockedTexturePositionX,
  1517         textureData->lockedTexturePositionY,
  1518         0,
  1519         (ID3D11Resource *)textureData->stagingTexture,
  1520         0,
  1521         NULL);
  1522 
  1523     SAFE_RELEASE(textureData->stagingTexture);
  1524 }
  1525 
  1526 static int
  1527 D3D11_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
  1528 {
  1529     D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  1530     D3D11_TextureData *textureData = NULL;
  1531 
  1532     if (texture == NULL) {
  1533         rendererData->currentOffscreenRenderTargetView = NULL;
  1534         return 0;
  1535     }
  1536 
  1537     textureData = (D3D11_TextureData *) texture->driverdata;
  1538 
  1539     if (!textureData->mainTextureRenderTargetView) {
  1540         return SDL_SetError("specified texture is not a render target");
  1541     }
  1542 
  1543     rendererData->currentOffscreenRenderTargetView = textureData->mainTextureRenderTargetView;
  1544 
  1545     return 0;
  1546 }
  1547 
  1548 static int
  1549 D3D11_QueueSetViewport(SDL_Renderer * renderer, SDL_RenderCommand *cmd)
  1550 {
  1551     return 0;  /* nothing to do in this backend. */
  1552 }
  1553 
  1554 static int
  1555 D3D11_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
  1556 {
  1557     VertexPositionColor *verts = (VertexPositionColor *) SDL_AllocateRenderVertices(renderer, count * sizeof (VertexPositionColor), 0, &cmd->data.draw.first);
  1558     const float r = (float)(cmd->data.draw.r / 255.0f);
  1559     const float g = (float)(cmd->data.draw.g / 255.0f);
  1560     const float b = (float)(cmd->data.draw.b / 255.0f);
  1561     const float a = (float)(cmd->data.draw.a / 255.0f);
  1562     int i;
  1563 
  1564     if (!verts) {
  1565         return -1;
  1566     }
  1567 
  1568     cmd->data.draw.count = count;
  1569 
  1570     for (i = 0; i < count; i++) {
  1571         verts->pos.x = points[i].x + 0.5f;
  1572         verts->pos.y = points[i].y + 0.5f;
  1573         verts->pos.z = 0.0f;
  1574         verts->tex.x = 0.0f;
  1575         verts->tex.y = 0.0f;
  1576         verts->color.x = r;
  1577         verts->color.y = g;
  1578         verts->color.z = b;
  1579         verts->color.w = a;
  1580         verts++;
  1581     }
  1582 
  1583     return 0;
  1584 }
  1585 
  1586 static int
  1587 D3D11_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
  1588 {
  1589     VertexPositionColor *verts = (VertexPositionColor *) SDL_AllocateRenderVertices(renderer, count * 4 * sizeof (VertexPositionColor), 0, &cmd->data.draw.first);
  1590     const float r = (float)(cmd->data.draw.r / 255.0f);
  1591     const float g = (float)(cmd->data.draw.g / 255.0f);
  1592     const float b = (float)(cmd->data.draw.b / 255.0f);
  1593     const float a = (float)(cmd->data.draw.a / 255.0f);
  1594     int i;
  1595 
  1596     if (!verts) {
  1597         return -1;
  1598     }
  1599 
  1600     cmd->data.draw.count = count;
  1601 
  1602     for (i = 0; i < count; i++) {
  1603         verts->pos.x = rects[i].x;
  1604         verts->pos.y = rects[i].y;
  1605         verts->pos.z = 0.0f;
  1606         verts->tex.x = 0.0f;
  1607         verts->tex.y = 0.0f;
  1608         verts->color.x = r;
  1609         verts->color.y = g;
  1610         verts->color.z = b;
  1611         verts->color.w = a;
  1612         verts++;
  1613 
  1614         verts->pos.x = rects[i].x;
  1615         verts->pos.y = rects[i].y + rects[i].h;
  1616         verts->pos.z = 0.0f;
  1617         verts->tex.x = 0.0f;
  1618         verts->tex.y = 0.0f;
  1619         verts->color.x = r;
  1620         verts->color.y = g;
  1621         verts->color.z = b;
  1622         verts->color.w = a;
  1623         verts++;
  1624 
  1625         verts->pos.x = rects[i].x + rects[i].w;
  1626         verts->pos.y = rects[i].y;
  1627         verts->pos.z = 0.0f;
  1628         verts->tex.x = 0.0f;
  1629         verts->tex.y = 0.0f;
  1630         verts->color.x = r;
  1631         verts->color.y = g;
  1632         verts->color.z = b;
  1633         verts->color.w = a;
  1634         verts++;
  1635 
  1636         verts->pos.x = rects[i].x + rects[i].w;
  1637         verts->pos.y = rects[i].y + rects[i].h;
  1638         verts->pos.z = 0.0f;
  1639         verts->tex.x = 0.0f;
  1640         verts->tex.y = 0.0f;
  1641         verts->color.x = r;
  1642         verts->color.y = g;
  1643         verts->color.z = b;
  1644         verts->color.w = a;
  1645         verts++;
  1646     }
  1647 
  1648     return 0;
  1649 }
  1650 
  1651 static int
  1652 D3D11_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
  1653              const SDL_Rect * srcrect, const SDL_FRect * dstrect)
  1654 {
  1655     VertexPositionColor *verts = (VertexPositionColor *) SDL_AllocateRenderVertices(renderer, 4 * sizeof (VertexPositionColor), 0, &cmd->data.draw.first);
  1656     const float r = (float)(cmd->data.draw.r / 255.0f);
  1657     const float g = (float)(cmd->data.draw.g / 255.0f);
  1658     const float b = (float)(cmd->data.draw.b / 255.0f);
  1659     const float a = (float)(cmd->data.draw.a / 255.0f);
  1660     const float minu = (float) srcrect->x / texture->w;
  1661     const float maxu = (float) (srcrect->x + srcrect->w) / texture->w;
  1662     const float minv = (float) srcrect->y / texture->h;
  1663     const float maxv = (float) (srcrect->y + srcrect->h) / texture->h;
  1664 
  1665     if (!verts) {
  1666         return -1;
  1667     }
  1668 
  1669     cmd->data.draw.count = 1;
  1670 
  1671     verts->pos.x = dstrect->x;
  1672     verts->pos.y = dstrect->y;
  1673     verts->pos.z = 0.0f;
  1674     verts->tex.x = minu;
  1675     verts->tex.y = minv;
  1676     verts->color.x = r;
  1677     verts->color.y = g;
  1678     verts->color.z = b;
  1679     verts->color.w = a;
  1680     verts++;
  1681 
  1682     verts->pos.x = dstrect->x;
  1683     verts->pos.y = dstrect->y + dstrect->h;
  1684     verts->pos.z = 0.0f;
  1685     verts->tex.x = minu;
  1686     verts->tex.y = maxv;
  1687     verts->color.x = r;
  1688     verts->color.y = g;
  1689     verts->color.z = b;
  1690     verts->color.w = a;
  1691     verts++;
  1692 
  1693     verts->pos.x = dstrect->x + dstrect->w;
  1694     verts->pos.y = dstrect->y;
  1695     verts->pos.z = 0.0f;
  1696     verts->tex.x = maxu;
  1697     verts->tex.y = minv;
  1698     verts->color.x = r;
  1699     verts->color.y = g;
  1700     verts->color.z = b;
  1701     verts->color.w = a;
  1702     verts++;
  1703 
  1704     verts->pos.x = dstrect->x + dstrect->w;
  1705     verts->pos.y = dstrect->y + dstrect->h;
  1706     verts->pos.z = 0.0f;
  1707     verts->tex.x = maxu;
  1708     verts->tex.y = maxv;
  1709     verts->color.x = r;
  1710     verts->color.y = g;
  1711     verts->color.z = b;
  1712     verts->color.w = a;
  1713     verts++;
  1714 
  1715     return 0;
  1716 }
  1717 
  1718 static int
  1719 D3D11_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
  1720                const SDL_Rect * srcrect, const SDL_FRect * dstrect,
  1721                const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
  1722 {
  1723     VertexPositionColor *verts = (VertexPositionColor *) SDL_AllocateRenderVertices(renderer, 5 * sizeof (VertexPositionColor), 0, &cmd->data.draw.first);
  1724     const float r = (float)(cmd->data.draw.r / 255.0f);
  1725     const float g = (float)(cmd->data.draw.g / 255.0f);
  1726     const float b = (float)(cmd->data.draw.b / 255.0f);
  1727     const float a = (float)(cmd->data.draw.a / 255.0f);
  1728     float minx, miny, maxx, maxy;
  1729     float minu, maxu, minv, maxv;
  1730 
  1731     if (flip & SDL_FLIP_HORIZONTAL) {
  1732         minu = (float) srcrect->x / texture->w;
  1733         maxu = (float) (srcrect->x + srcrect->w) / texture->w;
  1734     } else {
  1735         minu = (float) (srcrect->x + srcrect->w) / texture->w;
  1736         maxu = (float) srcrect->x / texture->w;
  1737     }
  1738 
  1739     if (flip & SDL_FLIP_VERTICAL) {
  1740         minv = (float) srcrect->y / texture->h;
  1741         maxv = (float) (srcrect->y + srcrect->h) / texture->h;
  1742     } else {
  1743         minv = (float) (srcrect->y + srcrect->h) / texture->h;
  1744         maxv = (float) srcrect->y / texture->h;
  1745     }
  1746 
  1747     minx = -center->x;
  1748     maxx = dstrect->w - center->x;
  1749     miny = -center->y;
  1750     maxy = dstrect->h - center->y;
  1751 
  1752     cmd->data.draw.count = 1;
  1753 
  1754     verts->pos.x = minx;
  1755     verts->pos.y = miny;
  1756     verts->pos.z = 0.0f;
  1757     verts->tex.x = minu;
  1758     verts->tex.y = minv;
  1759     verts->color.x = r;
  1760     verts->color.y = g;
  1761     verts->color.z = b;
  1762     verts->color.w = a;
  1763     verts++;
  1764 
  1765     verts->pos.x = minx;
  1766     verts->pos.y = maxy;
  1767     verts->pos.z = 0.0f;
  1768     verts->tex.x = minu;
  1769     verts->tex.y = maxv;
  1770     verts->color.x = r;
  1771     verts->color.y = g;
  1772     verts->color.z = b;
  1773     verts->color.w = a;
  1774     verts++;
  1775 
  1776     verts->pos.x = maxx;
  1777     verts->pos.y = miny;
  1778     verts->pos.z = 0.0f;
  1779     verts->tex.x = maxu;
  1780     verts->tex.y = minv;
  1781     verts->color.x = r;
  1782     verts->color.y = g;
  1783     verts->color.z = b;
  1784     verts->color.w = a;
  1785     verts++;
  1786 
  1787     verts->pos.x = maxx;
  1788     verts->pos.y = maxy;
  1789     verts->pos.z = 0.0f;
  1790     verts->tex.x = maxu;
  1791     verts->tex.y = maxv;
  1792     verts->color.x = r;
  1793     verts->color.y = g;
  1794     verts->color.z = b;
  1795     verts->color.w = a;
  1796     verts++;
  1797 
  1798     verts->pos.x = dstrect->x + center->x;  /* X translation */
  1799     verts->pos.y = dstrect->y + center->y;  /* Y translation */
  1800     verts->pos.z = (float)(M_PI * (float) angle / 180.0f);  /* rotation */
  1801     verts->tex.x = 0.0f;
  1802     verts->tex.y = 0.0f;
  1803     verts->color.x = 0;
  1804     verts->color.y = 0;
  1805     verts->color.z = 0;
  1806     verts->color.w = 0;
  1807     verts++;
  1808 
  1809     return 0;
  1810 }
  1811 
  1812 
  1813 static int
  1814 D3D11_UpdateVertexBuffer(SDL_Renderer *renderer,
  1815                          const void * vertexData, size_t dataSizeInBytes)
  1816 {
  1817     D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  1818     HRESULT result = S_OK;
  1819     const int vbidx = rendererData->currentVertexBuffer;
  1820 
  1821     if (rendererData->vertexBuffers[vbidx] && rendererData->vertexBufferSizes[vbidx] >= dataSizeInBytes) {
  1822         D3D11_MAPPED_SUBRESOURCE mappedResource;
  1823         result = ID3D11DeviceContext_Map(rendererData->d3dContext,
  1824             (ID3D11Resource *)rendererData->vertexBuffers[vbidx],
  1825             0,
  1826             D3D11_MAP_WRITE_DISCARD,
  1827             0,
  1828             &mappedResource
  1829             );
  1830         if (FAILED(result)) {
  1831             WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [vertex buffer]"), result);
  1832             return -1;
  1833         }
  1834         SDL_memcpy(mappedResource.pData, vertexData, dataSizeInBytes);
  1835         ID3D11DeviceContext_Unmap(rendererData->d3dContext, (ID3D11Resource *)rendererData->vertexBuffers[vbidx], 0);
  1836     } else {
  1837         D3D11_BUFFER_DESC vertexBufferDesc;
  1838         D3D11_SUBRESOURCE_DATA vertexBufferData;
  1839         const UINT stride = sizeof(VertexPositionColor);
  1840         const UINT offset = 0;
  1841 
  1842         SAFE_RELEASE(rendererData->vertexBuffers[vbidx]);
  1843 
  1844         SDL_zero(vertexBufferDesc);
  1845         vertexBufferDesc.ByteWidth = (UINT) dataSizeInBytes;
  1846         vertexBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
  1847         vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
  1848         vertexBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
  1849 
  1850         SDL_zero(vertexBufferData);
  1851         vertexBufferData.pSysMem = vertexData;
  1852         vertexBufferData.SysMemPitch = 0;
  1853         vertexBufferData.SysMemSlicePitch = 0;
  1854 
  1855         result = ID3D11Device_CreateBuffer(rendererData->d3dDevice,
  1856             &vertexBufferDesc,
  1857             &vertexBufferData,
  1858             &rendererData->vertexBuffers[vbidx]
  1859             );
  1860         if (FAILED(result)) {
  1861             WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateBuffer [vertex buffer]"), result);
  1862             return -1;
  1863         }
  1864 
  1865         rendererData->vertexBufferSizes[vbidx] = dataSizeInBytes;
  1866 
  1867         ID3D11DeviceContext_IASetVertexBuffers(rendererData->d3dContext,
  1868             0,
  1869             1,
  1870             &rendererData->vertexBuffers[vbidx],
  1871             &stride,
  1872             &offset
  1873             );
  1874     }
  1875 
  1876     rendererData->currentVertexBuffer++;
  1877     if (rendererData->currentVertexBuffer >= SDL_arraysize(rendererData->vertexBuffers)) {
  1878         rendererData->currentVertexBuffer = 0;
  1879     }
  1880 
  1881     return 0;
  1882 }
  1883 
  1884 static int
  1885 D3D11_UpdateViewport(SDL_Renderer * renderer)
  1886 {
  1887     D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
  1888     const SDL_Rect *viewport = &data->currentViewport;
  1889     Float4X4 projection;
  1890     Float4X4 view;
  1891     SDL_FRect orientationAlignedViewport;
  1892     BOOL swapDimensions;
  1893     D3D11_VIEWPORT d3dviewport;
  1894     const int rotation = D3D11_GetRotationForCurrentRenderTarget(renderer);
  1895 
  1896     if (viewport->w == 0 || viewport->h == 0) {
  1897         /* If the viewport is empty, assume that it is because
  1898          * SDL_CreateRenderer is calling it, and will call it again later
  1899          * with a non-empty viewport.
  1900          */
  1901         /* SDL_Log("%s, no viewport was set!\n", __FUNCTION__); */
  1902         return -1;
  1903     }
  1904 
  1905     /* Make sure the SDL viewport gets rotated to that of the physical display's rotation.
  1906      * Keep in mind here that the Y-axis will be been inverted (from Direct3D's
  1907      * default coordinate system) so rotations will be done in the opposite
  1908      * direction of the DXGI_MODE_ROTATION enumeration.
  1909      */
  1910     switch (rotation) {
  1911         case DXGI_MODE_ROTATION_IDENTITY:
  1912             projection = MatrixIdentity();
  1913             break;
  1914         case DXGI_MODE_ROTATION_ROTATE270:
  1915             projection = MatrixRotationZ(SDL_static_cast(float, M_PI * 0.5f));
  1916             break;
  1917         case DXGI_MODE_ROTATION_ROTATE180:
  1918             projection = MatrixRotationZ(SDL_static_cast(float, M_PI));
  1919             break;
  1920         case DXGI_MODE_ROTATION_ROTATE90:
  1921             projection = MatrixRotationZ(SDL_static_cast(float, -M_PI * 0.5f));
  1922             break;
  1923         default:
  1924             return SDL_SetError("An unknown DisplayOrientation is being used");
  1925     }
  1926 
  1927     /* Update the view matrix */
  1928     SDL_zero(view);
  1929     view.m[0][0] = 2.0f / viewport->w;
  1930     view.m[1][1] = -2.0f / viewport->h;
  1931     view.m[2][2] = 1.0f;
  1932     view.m[3][0] = -1.0f;
  1933     view.m[3][1] = 1.0f;
  1934     view.m[3][3] = 1.0f;
  1935 
  1936     /* Combine the projection + view matrix together now, as both only get
  1937      * set here (as of this writing, on Dec 26, 2013).  When done, store it
  1938      * for eventual transfer to the GPU.
  1939      */
  1940     data->vertexShaderConstantsData.projectionAndView = MatrixMultiply(
  1941             view,
  1942             projection);
  1943 
  1944     /* Update the Direct3D viewport, which seems to be aligned to the
  1945      * swap buffer's coordinate space, which is always in either
  1946      * a landscape mode, for all Windows 8/RT devices, or a portrait mode,
  1947      * for Windows Phone devices.
  1948      */
  1949     swapDimensions = D3D11_IsDisplayRotated90Degrees(rotation);
  1950     if (swapDimensions) {
  1951         orientationAlignedViewport.x = (float) viewport->y;
  1952         orientationAlignedViewport.y = (float) viewport->x;
  1953         orientationAlignedViewport.w = (float) viewport->h;
  1954         orientationAlignedViewport.h = (float) viewport->w;
  1955     } else {
  1956         orientationAlignedViewport.x = (float) viewport->x;
  1957         orientationAlignedViewport.y = (float) viewport->y;
  1958         orientationAlignedViewport.w = (float) viewport->w;
  1959         orientationAlignedViewport.h = (float) viewport->h;
  1960     }
  1961     /* TODO, WinRT: get custom viewports working with non-Landscape modes (Portrait, PortraitFlipped, and LandscapeFlipped) */
  1962 
  1963     d3dviewport.TopLeftX = orientationAlignedViewport.x;
  1964     d3dviewport.TopLeftY = orientationAlignedViewport.y;
  1965     d3dviewport.Width = orientationAlignedViewport.w;
  1966     d3dviewport.Height = orientationAlignedViewport.h;
  1967     d3dviewport.MinDepth = 0.0f;
  1968     d3dviewport.MaxDepth = 1.0f;
  1969     /* SDL_Log("%s: D3D viewport = {%f,%f,%f,%f}\n", __FUNCTION__, d3dviewport.TopLeftX, d3dviewport.TopLeftY, d3dviewport.Width, d3dviewport.Height); */
  1970     ID3D11DeviceContext_RSSetViewports(data->d3dContext, 1, &d3dviewport);
  1971 
  1972     data->viewportDirty = SDL_FALSE;
  1973 
  1974     return 0;
  1975 }
  1976 
  1977 static ID3D11RenderTargetView *
  1978 D3D11_GetCurrentRenderTargetView(SDL_Renderer * renderer)
  1979 {
  1980     D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata;
  1981     if (data->currentOffscreenRenderTargetView) {
  1982         return data->currentOffscreenRenderTargetView;
  1983     }
  1984     else {
  1985         return data->mainRenderTargetView;
  1986     }
  1987 }
  1988 
  1989 static int
  1990 D3D11_SetDrawState(SDL_Renderer * renderer, const SDL_RenderCommand *cmd, ID3D11PixelShader * shader,
  1991                      const int numShaderResources, ID3D11ShaderResourceView ** shaderResources,
  1992                      ID3D11SamplerState * sampler, const Float4X4 *matrix)
  1993 
  1994 {
  1995     D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata;
  1996     const Float4X4 *newmatrix = matrix ? matrix : &rendererData->identity;
  1997     ID3D11RasterizerState *rasterizerState;
  1998     ID3D11RenderTargetView *renderTargetView = D3D11_GetCurrentRenderTargetView(renderer);
  1999     ID3D11ShaderResourceView *shaderResource;
  2000     const SDL_BlendMode blendMode = cmd->data.draw.blend;
  2001     ID3D11BlendState *blendState = NULL;
  2002     SDL_bool updateSubresource = SDL_FALSE;
  2003 
  2004     if (renderTargetView != rendererData->currentRenderTargetView) {
  2005         ID3D11DeviceContext_OMSetRenderTargets(rendererData->d3dContext,
  2006             1,
  2007             &renderTargetView,
  2008             NULL
  2009             );
  2010         rendererData->currentRenderTargetView = renderTargetView;
  2011     }
  2012 
  2013     if (rendererData->viewportDirty) {
  2014         if (D3D11_UpdateViewport(renderer) == 0) {
  2015             /* vertexShaderConstantsData.projectionAndView has changed */
  2016             updateSubresource = SDL_TRUE;
  2017         }
  2018     }
  2019 
  2020     if (rendererData->cliprectDirty) {
  2021         if (!rendererData->currentCliprectEnabled) {
  2022             ID3D11DeviceContext_RSSetScissorRects(rendererData->d3dContext, 0, NULL);
  2023         } else {
  2024             D3D11_RECT scissorRect;
  2025             if (D3D11_GetViewportAlignedD3DRect(renderer, &rendererData->currentCliprect, &scissorRect, TRUE) != 0) {
  2026                 /* D3D11_GetViewportAlignedD3DRect will have set the SDL error */
  2027                 return -1;
  2028             }
  2029             ID3D11DeviceContext_RSSetScissorRects(rendererData->d3dContext, 1, &scissorRect);
  2030         }
  2031         rendererData->cliprectDirty = SDL_FALSE;
  2032     }
  2033 
  2034     if (!rendererData->currentCliprectEnabled) {
  2035         rasterizerState = rendererData->mainRasterizer;
  2036     } else {
  2037         rasterizerState = rendererData->clippedRasterizer;
  2038     }
  2039     if (rasterizerState != rendererData->currentRasterizerState) {
  2040         ID3D11DeviceContext_RSSetState(rendererData->d3dContext, rasterizerState);
  2041         rendererData->currentRasterizerState = rasterizerState;
  2042     }
  2043 
  2044     if (blendMode != SDL_BLENDMODE_NONE) {
  2045         int i;
  2046         for (i = 0; i < rendererData->blendModesCount; ++i) {
  2047             if (blendMode == rendererData->blendModes[i].blendMode) {
  2048                 blendState = rendererData->blendModes[i].blendState;
  2049                 break;
  2050             }
  2051         }
  2052         if (!blendState) {
  2053             blendState = D3D11_CreateBlendState(renderer, blendMode);
  2054             if (!blendState) {
  2055                 return -1;
  2056             }
  2057         }
  2058     }
  2059     if (blendState != rendererData->currentBlendState) {
  2060         ID3D11DeviceContext_OMSetBlendState(rendererData->d3dContext, blendState, 0, 0xFFFFFFFF);
  2061         rendererData->currentBlendState = blendState;
  2062     }
  2063 
  2064     if (shader != rendererData->currentShader) {
  2065         ID3D11DeviceContext_PSSetShader(rendererData->d3dContext, shader, NULL, 0);
  2066         rendererData->currentShader = shader;
  2067     }
  2068     if (numShaderResources > 0) {
  2069         shaderResource = shaderResources[0];
  2070     } else {
  2071         shaderResource = NULL;
  2072     }
  2073     if (shaderResource != rendererData->currentShaderResource) {
  2074         ID3D11DeviceContext_PSSetShaderResources(rendererData->d3dContext, 0, numShaderResources, shaderResources);
  2075         rendererData->currentShaderResource = shaderResource;
  2076     }
  2077     if (sampler != rendererData->currentSampler) {
  2078         ID3D11DeviceContext_PSSetSamplers(rendererData->d3dContext, 0, 1, &sampler);
  2079         rendererData->currentSampler = sampler;
  2080     }
  2081 
  2082     if (updateSubresource == SDL_TRUE || SDL_memcmp(&rendererData->vertexShaderConstantsData.model, newmatrix, sizeof (*newmatrix)) != 0) {
  2083         SDL_memcpy(&rendererData->vertexShaderConstantsData.model, newmatrix, sizeof (*newmatrix));
  2084         ID3D11DeviceContext_UpdateSubresource(rendererData->d3dContext,
  2085             (ID3D11Resource *)rendererData->vertexShaderConstants,
  2086             0,
  2087             NULL,
  2088             &rendererData->vertexShaderConstantsData,
  2089             0,
  2090             0
  2091             );
  2092     }
  2093 
  2094     return 0;
  2095 }
  2096 
  2097 static int
  2098 D3D11_SetCopyState(SDL_Renderer * renderer, const SDL_RenderCommand *cmd, const Float4X4 *matrix)
  2099 {
  2100     SDL_Texture *texture = cmd->data.draw.texture;
  2101     D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  2102     D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
  2103     ID3D11SamplerState *textureSampler;
  2104 
  2105     switch (textureData->scaleMode) {
  2106     case D3D11_FILTER_MIN_MAG_MIP_POINT:
  2107         textureSampler = rendererData->nearestPixelSampler;
  2108         break;
  2109     case D3D11_FILTER_MIN_MAG_MIP_LINEAR:
  2110         textureSampler = rendererData->linearSampler;
  2111         break;
  2112     default:
  2113         return SDL_SetError("Unknown scale mode: %d\n", textureData->scaleMode);
  2114     }
  2115 
  2116     if (textureData->yuv) {
  2117         ID3D11ShaderResourceView *shaderResources[] = {
  2118             textureData->mainTextureResourceView,
  2119             textureData->mainTextureResourceViewU,
  2120             textureData->mainTextureResourceViewV
  2121         };
  2122         D3D11_Shader shader;
  2123 
  2124         switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) {
  2125         case SDL_YUV_CONVERSION_JPEG:
  2126             shader = SHADER_YUV_JPEG;
  2127             break;
  2128         case SDL_YUV_CONVERSION_BT601:
  2129             shader = SHADER_YUV_BT601;
  2130             break;
  2131         case SDL_YUV_CONVERSION_BT709:
  2132             shader = SHADER_YUV_BT709;
  2133             break;
  2134         default:
  2135             return SDL_SetError("Unsupported YUV conversion mode");
  2136         }
  2137 
  2138         return D3D11_SetDrawState(renderer, cmd, rendererData->pixelShaders[shader],
  2139                                   SDL_arraysize(shaderResources), shaderResources, textureSampler, matrix);
  2140 
  2141     } else if (textureData->nv12) {
  2142         ID3D11ShaderResourceView *shaderResources[] = {
  2143             textureData->mainTextureResourceView,
  2144             textureData->mainTextureResourceViewNV,
  2145         };
  2146         D3D11_Shader shader;
  2147 
  2148         switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) {
  2149         case SDL_YUV_CONVERSION_JPEG:
  2150             shader = texture->format == SDL_PIXELFORMAT_NV12 ? SHADER_NV12_JPEG : SHADER_NV21_JPEG;
  2151             break;
  2152         case SDL_YUV_CONVERSION_BT601:
  2153             shader = texture->format == SDL_PIXELFORMAT_NV12 ? SHADER_NV12_BT601 : SHADER_NV21_BT601;
  2154             break;
  2155         case SDL_YUV_CONVERSION_BT709:
  2156             shader = texture->format == SDL_PIXELFORMAT_NV12 ? SHADER_NV12_BT709 : SHADER_NV21_BT709;
  2157             break;
  2158         default:
  2159             return SDL_SetError("Unsupported YUV conversion mode");
  2160         }
  2161 
  2162         return D3D11_SetDrawState(renderer, cmd, rendererData->pixelShaders[shader],
  2163                                   SDL_arraysize(shaderResources), shaderResources, textureSampler, matrix);
  2164 
  2165     }
  2166 
  2167     return D3D11_SetDrawState(renderer, cmd, rendererData->pixelShaders[SHADER_RGB],
  2168                               1, &textureData->mainTextureResourceView, textureSampler, matrix);
  2169 }
  2170 
  2171 static void
  2172 D3D11_DrawPrimitives(SDL_Renderer * renderer, D3D11_PRIMITIVE_TOPOLOGY primitiveTopology, const size_t vertexStart, const size_t vertexCount)
  2173 {
  2174     D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  2175     ID3D11DeviceContext_IASetPrimitiveTopology(rendererData->d3dContext, primitiveTopology);
  2176     ID3D11DeviceContext_Draw(rendererData->d3dContext, (UINT) vertexCount, (UINT) vertexStart);
  2177 }
  2178 
  2179 static int
  2180 D3D11_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
  2181 {
  2182     D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  2183     const int viewportRotation = D3D11_GetRotationForCurrentRenderTarget(renderer);
  2184     size_t i;
  2185 
  2186     if (rendererData->currentViewportRotation != viewportRotation) {
  2187         rendererData->currentViewportRotation = viewportRotation;
  2188         rendererData->viewportDirty = SDL_TRUE;
  2189     }
  2190 
  2191     if (D3D11_UpdateVertexBuffer(renderer, vertices, vertsize) < 0) {
  2192         return -1;
  2193     }
  2194 
  2195     while (cmd) {
  2196         switch (cmd->command) {
  2197             case SDL_RENDERCMD_SETDRAWCOLOR: {
  2198                 break;  /* this isn't currently used in this render backend. */
  2199             }
  2200 
  2201             case SDL_RENDERCMD_SETVIEWPORT: {
  2202                 SDL_Rect *viewport = &rendererData->currentViewport;
  2203                 if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect)) != 0) {
  2204                     SDL_memcpy(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect));
  2205                     rendererData->viewportDirty = SDL_TRUE;
  2206                 }
  2207                 break;
  2208             }
  2209 
  2210             case SDL_RENDERCMD_SETCLIPRECT: {
  2211                 const SDL_Rect *rect = &cmd->data.cliprect.rect;
  2212                 if (rendererData->currentCliprectEnabled != cmd->data.cliprect.enabled) {
  2213                     rendererData->currentCliprectEnabled = cmd->data.cliprect.enabled;
  2214                     rendererData->cliprectDirty = SDL_TRUE;
  2215                 }
  2216                 if (SDL_memcmp(&rendererData->currentCliprect, rect, sizeof (SDL_Rect)) != 0) {
  2217                     SDL_memcpy(&rendererData->currentCliprect, rect, sizeof (SDL_Rect));
  2218                     rendererData->cliprectDirty = SDL_TRUE;
  2219                 }
  2220                 break;
  2221             }
  2222 
  2223             case SDL_RENDERCMD_CLEAR: {
  2224                 const float colorRGBA[] = {
  2225                     (cmd->data.color.r / 255.0f),
  2226                     (cmd->data.color.g / 255.0f),
  2227                     (cmd->data.color.b / 255.0f),
  2228                     (cmd->data.color.a / 255.0f)
  2229                 };
  2230                 ID3D11DeviceContext_ClearRenderTargetView(rendererData->d3dContext, D3D11_GetCurrentRenderTargetView(renderer), colorRGBA);
  2231                 break;
  2232             }
  2233 
  2234             case SDL_RENDERCMD_DRAW_POINTS: {
  2235                 const size_t count = cmd->data.draw.count;
  2236                 const size_t first = cmd->data.draw.first;
  2237                 const size_t start = first / sizeof (VertexPositionColor);
  2238                 D3D11_SetDrawState(renderer, cmd, rendererData->pixelShaders[SHADER_SOLID], 0, NULL, NULL, NULL);
  2239                 D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, start, count);
  2240                 break;
  2241             }
  2242 
  2243             case SDL_RENDERCMD_DRAW_LINES: {
  2244                 const size_t count = cmd->data.draw.count;
  2245                 const size_t first = cmd->data.draw.first;
  2246                 const size_t start = first / sizeof (VertexPositionColor);
  2247                 const VertexPositionColor *verts = (VertexPositionColor *) (((Uint8 *) vertices) + first);
  2248                 D3D11_SetDrawState(renderer, cmd, rendererData->pixelShaders[SHADER_SOLID], 0, NULL, NULL, NULL);
  2249                 D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP, start, count);
  2250                 if (verts[0].pos.x != verts[count - 1].pos.x || verts[0].pos.y != verts[count - 1].pos.y) {
  2251                     D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, start + (count-1), 1);
  2252                 }
  2253                 break;
  2254             }
  2255 
  2256             case SDL_RENDERCMD_FILL_RECTS: {
  2257                 const size_t count = cmd->data.draw.count;
  2258                 const size_t first = cmd->data.draw.first;
  2259                 const size_t start = first / sizeof (VertexPositionColor);
  2260                 size_t offset = 0;
  2261                 D3D11_SetDrawState(renderer, cmd, rendererData->pixelShaders[SHADER_SOLID], 0, NULL, NULL, NULL);
  2262                 for (i = 0; i < count; i++, offset += 4) {
  2263                     D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, start + offset, 4);
  2264                 }
  2265                 break;
  2266             }
  2267 
  2268             case SDL_RENDERCMD_COPY: {
  2269                 const size_t first = cmd->data.draw.first;
  2270                 const size_t start = first / sizeof (VertexPositionColor);
  2271                 D3D11_SetCopyState(renderer, cmd, NULL);
  2272                 D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, start, 4);
  2273                 break;
  2274             }
  2275 
  2276             case SDL_RENDERCMD_COPY_EX: {
  2277                 const size_t first = cmd->data.draw.first;
  2278                 const size_t start = first / sizeof (VertexPositionColor);
  2279                 const VertexPositionColor *verts = (VertexPositionColor *) (((Uint8 *) vertices) + first);
  2280                 const VertexPositionColor *transvert = verts + 4;
  2281                 const float translatex = transvert->pos.x;
  2282                 const float translatey = transvert->pos.y;
  2283                 const float rotation = transvert->pos.z;
  2284                 const Float4X4 matrix = MatrixMultiply(MatrixRotationZ(rotation), MatrixTranslation(translatex, translatey, 0));
  2285                 D3D11_SetCopyState(renderer, cmd, &matrix);
  2286                 D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, start, 4);
  2287                 break;
  2288             }
  2289 
  2290             case SDL_RENDERCMD_NO_OP:
  2291                 break;
  2292         }
  2293 
  2294         cmd = cmd->next;
  2295     }
  2296 
  2297     return 0;
  2298 }
  2299 
  2300 static int
  2301 D3D11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
  2302                        Uint32 format, void * pixels, int pitch)
  2303 {
  2304     D3D11_RenderData * data = (D3D11_RenderData *) renderer->driverdata;
  2305     ID3D11Texture2D *backBuffer = NULL;
  2306     ID3D11Texture2D *stagingTexture = NULL;
  2307     HRESULT result;
  2308     int status = -1;
  2309     D3D11_TEXTURE2D_DESC stagingTextureDesc;
  2310     D3D11_RECT srcRect = {0, 0, 0, 0};
  2311     D3D11_BOX srcBox;
  2312     D3D11_MAPPED_SUBRESOURCE textureMemory;
  2313 
  2314     /* Retrieve a pointer to the back buffer: */
  2315     result = IDXGISwapChain_GetBuffer(data->swapChain,
  2316         0,
  2317         &SDL_IID_ID3D11Texture2D,
  2318         (void **)&backBuffer
  2319         );
  2320     if (FAILED(result)) {
  2321         WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain1::GetBuffer [get back buffer]"), result);
  2322         goto done;
  2323     }
  2324 
  2325     /* Create a staging texture to copy the screen's data to: */
  2326     ID3D11Texture2D_GetDesc(backBuffer, &stagingTextureDesc);
  2327     stagingTextureDesc.Width = rect->w;
  2328     stagingTextureDesc.Height = rect->h;
  2329     stagingTextureDesc.BindFlags = 0;
  2330     stagingTextureDesc.MiscFlags = 0;
  2331     stagingTextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
  2332     stagingTextureDesc.Usage = D3D11_USAGE_STAGING;
  2333     result = ID3D11Device_CreateTexture2D(data->d3dDevice,
  2334         &stagingTextureDesc,
  2335         NULL,
  2336         &stagingTexture);
  2337     if (FAILED(result)) {
  2338         WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D [create staging texture]"), result);
  2339         goto done;
  2340     }
  2341 
  2342     /* Copy the desired portion of the back buffer to the staging texture: */
  2343     if (D3D11_GetViewportAlignedD3DRect(renderer, rect, &srcRect, FALSE) != 0) {
  2344         /* D3D11_GetViewportAlignedD3DRect will have set the SDL error */
  2345         goto done;
  2346     }
  2347 
  2348     srcBox.left = srcRect.left;
  2349     srcBox.right = srcRect.right;
  2350     srcBox.top = srcRect.top;
  2351     srcBox.bottom = srcRect.bottom;
  2352     srcBox.front = 0;
  2353     srcBox.back = 1;
  2354     ID3D11DeviceContext_CopySubresourceRegion(data->d3dContext,
  2355         (ID3D11Resource *)stagingTexture,
  2356         0,
  2357         0, 0, 0,
  2358         (ID3D11Resource *)backBuffer,
  2359         0,
  2360         &srcBox);
  2361 
  2362     /* Map the staging texture's data to CPU-accessible memory: */
  2363     result = ID3D11DeviceContext_Map(data->d3dContext,
  2364         (ID3D11Resource *)stagingTexture,
  2365         0,
  2366         D3D11_MAP_READ,
  2367         0,
  2368         &textureMemory);
  2369     if (FAILED(result)) {
  2370         WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [map staging texture]"), result);
  2371         goto done;
  2372     }
  2373 
  2374     /* Copy the data into the desired buffer, converting pixels to the
  2375      * desired format at the same time:
  2376      */
  2377     if (SDL_ConvertPixels(
  2378         rect->w, rect->h,
  2379         D3D11_DXGIFormatToSDLPixelFormat(stagingTextureDesc.Format),
  2380         textureMemory.pData,
  2381         textureMemory.RowPitch,
  2382         format,
  2383         pixels,
  2384         pitch) != 0) {
  2385         /* When SDL_ConvertPixels fails, it'll have already set the format.
  2386          * Get the error message, and attach some extra data to it.
  2387          */
  2388         char errorMessage[1024];
  2389         SDL_snprintf(errorMessage, sizeof(errorMessage), "%s, Convert Pixels failed: %s", __FUNCTION__, SDL_GetError());
  2390         SDL_SetError("%s", errorMessage);
  2391         goto done;
  2392     }
  2393 
  2394     /* Unmap the texture: */
  2395     ID3D11DeviceContext_Unmap(data->d3dContext,
  2396         (ID3D11Resource *)stagingTexture,
  2397         0);
  2398 
  2399     status = 0;
  2400 
  2401 done:
  2402     SAFE_RELEASE(backBuffer);
  2403     SAFE_RELEASE(stagingTexture);
  2404     return status;
  2405 }
  2406 
  2407 static void
  2408 D3D11_RenderPresent(SDL_Renderer * renderer)
  2409 {
  2410     D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
  2411     UINT syncInterval;
  2412     UINT presentFlags;
  2413     HRESULT result;
  2414     DXGI_PRESENT_PARAMETERS parameters;
  2415 
  2416     SDL_zero(parameters);
  2417 
  2418 #if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
  2419     syncInterval = 1;
  2420     presentFlags = 0;
  2421     result = IDXGISwapChain_Present(data->swapChain, syncInterval, presentFlags);
  2422 #else
  2423     if (renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) {
  2424         syncInterval = 1;
  2425         presentFlags = 0;
  2426     } else {
  2427         syncInterval = 0;
  2428         presentFlags = DXGI_PRESENT_DO_NOT_WAIT;
  2429     }
  2430 
  2431     /* The application may optionally specify "dirty" or "scroll"
  2432      * rects to improve efficiency in certain scenarios.
  2433      * This option is not available on Windows Phone 8, to note.
  2434      */
  2435     result = IDXGISwapChain1_Present1(data->swapChain, syncInterval, presentFlags, &parameters);
  2436 #endif
  2437 
  2438     /* Discard the contents of the render target.
  2439      * This is a valid operation only when the existing contents will be entirely
  2440      * overwritten. If dirty or scroll rects are used, this call should be removed.
  2441      */
  2442     ID3D11DeviceContext1_DiscardView(data->d3dContext, (ID3D11View*)data->mainRenderTargetView);
  2443 
  2444     /* When the present flips, it unbinds the current view, so bind it again on the next draw call */
  2445     data->currentRenderTargetView = NULL;
  2446 
  2447     if (FAILED(result) && result != DXGI_ERROR_WAS_STILL_DRAWING) {
  2448         /* If the device was removed either by a disconnect or a driver upgrade, we 
  2449          * must recreate all device resources.
  2450          *
  2451          * TODO, WinRT: consider throwing an exception if D3D11_RenderPresent fails, especially if there is a way to salvage debug info from users' machines
  2452          */
  2453         if ( result == DXGI_ERROR_DEVICE_REMOVED ) {
  2454             D3D11_HandleDeviceLost(renderer);
  2455         } else if (result == DXGI_ERROR_INVALID_CALL) {
  2456             /* We probably went through a fullscreen <-> windowed transition */
  2457             D3D11_CreateWindowSizeDependentResources(renderer);
  2458         } else {
  2459             WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain::Present"), result);
  2460         }
  2461     }
  2462 }
  2463 
  2464 SDL_Renderer *
  2465 D3D11_CreateRenderer(SDL_Window * window, Uint32 flags)
  2466 {
  2467     SDL_Renderer *renderer;
  2468     D3D11_RenderData *data;
  2469 
  2470     renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
  2471     if (!renderer) {
  2472         SDL_OutOfMemory();
  2473         return NULL;
  2474     }
  2475 
  2476     data = (D3D11_RenderData *) SDL_calloc(1, sizeof(*data));
  2477     if (!data) {
  2478         SDL_OutOfMemory();
  2479         return NULL;
  2480     }
  2481 
  2482     data->identity = MatrixIdentity();
  2483 
  2484     renderer->WindowEvent = D3D11_WindowEvent;
  2485     renderer->SupportsBlendMode = D3D11_SupportsBlendMode;
  2486     renderer->CreateTexture = D3D11_CreateTexture;
  2487     renderer->UpdateTexture = D3D11_UpdateTexture;
  2488     renderer->UpdateTextureYUV = D3D11_UpdateTextureYUV;
  2489     renderer->LockTexture = D3D11_LockTexture;
  2490     renderer->UnlockTexture = D3D11_UnlockTexture;
  2491     renderer->SetRenderTarget = D3D11_SetRenderTarget;
  2492     renderer->QueueSetViewport = D3D11_QueueSetViewport;
  2493     renderer->QueueSetDrawColor = D3D11_QueueSetViewport;  /* SetViewport and SetDrawColor are (currently) no-ops. */
  2494     renderer->QueueDrawPoints = D3D11_QueueDrawPoints;
  2495     renderer->QueueDrawLines = D3D11_QueueDrawPoints;  /* lines and points queue vertices the same way. */
  2496     renderer->QueueFillRects = D3D11_QueueFillRects;
  2497     renderer->QueueCopy = D3D11_QueueCopy;
  2498     renderer->QueueCopyEx = D3D11_QueueCopyEx;
  2499     renderer->RunCommandQueue = D3D11_RunCommandQueue;
  2500     renderer->RenderReadPixels = D3D11_RenderReadPixels;
  2501     renderer->RenderPresent = D3D11_RenderPresent;
  2502     renderer->DestroyTexture = D3D11_DestroyTexture;
  2503     renderer->DestroyRenderer = D3D11_DestroyRenderer;
  2504     renderer->info = D3D11_RenderDriver.info;
  2505     renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
  2506     renderer->driverdata = data;
  2507 
  2508 #if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
  2509     /* VSync is required in Windows Phone, at least for Win Phone 8.0 and 8.1.
  2510      * Failure to use it seems to either result in:
  2511      *
  2512      *  - with the D3D11 debug runtime turned OFF, vsync seemingly gets turned
  2513      *    off (framerate doesn't get capped), but nothing appears on-screen
  2514      *
  2515      *  - with the D3D11 debug runtime turned ON, vsync gets automatically
  2516      *    turned back on, and the following gets output to the debug console:
  2517      *    
  2518      *    DXGI ERROR: IDXGISwapChain::Present: Interval 0 is not supported, changed to Interval 1. [ UNKNOWN ERROR #1024: ] 
  2519      */
  2520     renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
  2521 #else
  2522     if ((flags & SDL_RENDERER_PRESENTVSYNC)) {
  2523         renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
  2524     }
  2525 #endif
  2526 
  2527     /* HACK: make sure the SDL_Renderer references the SDL_Window data now, in
  2528      * order to give init functions access to the underlying window handle:
  2529      */
  2530     renderer->window = window;
  2531 
  2532     /* Initialize Direct3D resources */
  2533     if (FAILED(D3D11_CreateDeviceResources(renderer))) {
  2534         D3D11_DestroyRenderer(renderer);
  2535         return NULL;
  2536     }
  2537     if (FAILED(D3D11_CreateWindowSizeDependentResources(renderer))) {
  2538         D3D11_DestroyRenderer(renderer);
  2539         return NULL;
  2540     }
  2541 
  2542     return renderer;
  2543 }
  2544 
  2545 SDL_RenderDriver D3D11_RenderDriver = {
  2546     D3D11_CreateRenderer,
  2547     {
  2548         "direct3d11",
  2549         (
  2550             SDL_RENDERER_ACCELERATED |
  2551             SDL_RENDERER_PRESENTVSYNC |
  2552             SDL_RENDERER_TARGETTEXTURE
  2553         ),                          /* flags.  see SDL_RendererFlags */
  2554         6,                          /* num_texture_formats */
  2555         {                           /* texture_formats */
  2556             SDL_PIXELFORMAT_ARGB8888,
  2557             SDL_PIXELFORMAT_RGB888,
  2558             SDL_PIXELFORMAT_YV12,
  2559             SDL_PIXELFORMAT_IYUV,
  2560             SDL_PIXELFORMAT_NV12,
  2561             SDL_PIXELFORMAT_NV21
  2562         },
  2563         0,                          /* max_texture_width: will be filled in later */
  2564         0                           /* max_texture_height: will be filled in later */
  2565     }
  2566 };
  2567 
  2568 #endif /* SDL_VIDEO_RENDER_D3D11 && !SDL_RENDER_DISABLED */
  2569 
  2570 /* vi: set ts=4 sw=4 expandtab: */