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