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