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