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