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