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