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 int
1165 D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
1166 {
1167  D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
1168  D3D11_TextureData *textureData;
1169  HRESULT result;
1170  DXGI_FORMAT textureFormat = SDLPixelFormatToDXGIFormat(texture->format);
1171  D3D11_TEXTURE2D_DESC textureDesc;
1172  D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
1173 
1174  if (textureFormat == DXGI_FORMAT_UNKNOWN) {
1175  return SDL_SetError("%s, An unsupported SDL pixel format (0x%x) was specified",
1176  __FUNCTION__, texture->format);
1177  }
1178 
1179  textureData = (D3D11_TextureData*) SDL_calloc(1, sizeof(*textureData));
1180  if (!textureData) {
1181  SDL_OutOfMemory();
1182  return -1;
1183  }
1184  textureData->scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ? D3D11_FILTER_MIN_MAG_MIP_POINT : D3D11_FILTER_MIN_MAG_MIP_LINEAR;
1185 
1186  texture->driverdata = textureData;
1187 
1188  SDL_zero(textureDesc);
1189  textureDesc.Width = texture->w;
1190  textureDesc.Height = texture->h;
1191  textureDesc.MipLevels = 1;
1192  textureDesc.ArraySize = 1;
1193  textureDesc.Format = textureFormat;
1194  textureDesc.SampleDesc.Count = 1;
1195  textureDesc.SampleDesc.Quality = 0;
1196  textureDesc.MiscFlags = 0;
1197 
1198  if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
1199  textureDesc.Usage = D3D11_USAGE_DYNAMIC;
1200  textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
1201  } else {
1202  textureDesc.Usage = D3D11_USAGE_DEFAULT;
1203  textureDesc.CPUAccessFlags = 0;
1204  }
1205 
1206  if (texture->access == SDL_TEXTUREACCESS_TARGET) {
1207  textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
1208  } else {
1209  textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
1210  }
1211 
1212  result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
1213  &textureDesc,
1214  NULL,
1215  &textureData->mainTexture
1216  );
1217  if (FAILED(result)) {
1218  D3D11_DestroyTexture(renderer, texture);
1219  WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
1220  return -1;
1221  }
1222 
1223  if (texture->format == SDL_PIXELFORMAT_YV12 ||
1224  texture->format == SDL_PIXELFORMAT_IYUV) {
1225  textureData->yuv = SDL_TRUE;
1226 
1227  textureDesc.Width = (textureDesc.Width + 1) / 2;
1228  textureDesc.Height = (textureDesc.Height + 1) / 2;
1229 
1230  result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
1231  &textureDesc,
1232  NULL,
1233  &textureData->mainTextureU
1234  );
1235  if (FAILED(result)) {
1236  D3D11_DestroyTexture(renderer, texture);
1237  WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
1238  return -1;
1239  }
1240 
1241  result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
1242  &textureDesc,
1243  NULL,
1244  &textureData->mainTextureV
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 
1253  if (texture->format == SDL_PIXELFORMAT_NV12 ||
1254  texture->format == SDL_PIXELFORMAT_NV21) {
1255  D3D11_TEXTURE2D_DESC nvTextureDesc = textureDesc;
1256 
1257  textureData->nv12 = SDL_TRUE;
1258 
1259  nvTextureDesc.Format = DXGI_FORMAT_R8G8_UNORM;
1260  nvTextureDesc.Width = (textureDesc.Width + 1) / 2;
1261  nvTextureDesc.Height = (textureDesc.Height + 1) / 2;
1262 
1263  result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
1264  &nvTextureDesc,
1265  NULL,
1266  &textureData->mainTextureNV
1267  );
1268  if (FAILED(result)) {
1269  D3D11_DestroyTexture(renderer, texture);
1270  WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
1271  return -1;
1272  }
1273  }
1274 
1275  resourceViewDesc.Format = textureDesc.Format;
1276  resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
1277  resourceViewDesc.Texture2D.MostDetailedMip = 0;
1278  resourceViewDesc.Texture2D.MipLevels = textureDesc.MipLevels;
1279  result = ID3D11Device_CreateShaderResourceView(rendererData->d3dDevice,
1280  (ID3D11Resource *)textureData->mainTexture,
1281  &resourceViewDesc,
1282  &textureData->mainTextureResourceView
1283  );
1284  if (FAILED(result)) {
1285  D3D11_DestroyTexture(renderer, texture);
1286  WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result);
1287  return -1;
1288  }
1289 
1290  if (textureData->yuv) {
1291  result = ID3D11Device_CreateShaderResourceView(rendererData->d3dDevice,
1292  (ID3D11Resource *)textureData->mainTextureU,
1293  &resourceViewDesc,
1294  &textureData->mainTextureResourceViewU
1295  );
1296  if (FAILED(result)) {
1297  D3D11_DestroyTexture(renderer, texture);
1298  WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result);
1299  return -1;
1300  }
1301  result = ID3D11Device_CreateShaderResourceView(rendererData->d3dDevice,
1302  (ID3D11Resource *)textureData->mainTextureV,
1303  &resourceViewDesc,
1304  &textureData->mainTextureResourceViewV
1305  );
1306  if (FAILED(result)) {
1307  D3D11_DestroyTexture(renderer, texture);
1308  WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result);
1309  return -1;
1310  }
1311  }
1312 
1313  if (textureData->nv12) {
1314  D3D11_SHADER_RESOURCE_VIEW_DESC nvResourceViewDesc = resourceViewDesc;
1315 
1316  nvResourceViewDesc.Format = DXGI_FORMAT_R8G8_UNORM;
1317 
1318  result = ID3D11Device_CreateShaderResourceView(rendererData->d3dDevice,
1319  (ID3D11Resource *)textureData->mainTextureNV,
1320  &nvResourceViewDesc,
1321  &textureData->mainTextureResourceViewNV
1322  );
1323  if (FAILED(result)) {
1324  D3D11_DestroyTexture(renderer, texture);
1325  WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result);
1326  return -1;
1327  }
1328  }
1329 
1330  if (texture->access & SDL_TEXTUREACCESS_TARGET) {
1331  D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
1332  renderTargetViewDesc.Format = textureDesc.Format;
1333  renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
1334  renderTargetViewDesc.Texture2D.MipSlice = 0;
1335 
1336  result = ID3D11Device_CreateRenderTargetView(rendererData->d3dDevice,
1337  (ID3D11Resource *)textureData->mainTexture,
1338  &renderTargetViewDesc,
1339  &textureData->mainTextureRenderTargetView);
1340  if (FAILED(result)) {
1341  D3D11_DestroyTexture(renderer, texture);
1342  WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateRenderTargetView"), result);
1343  return -1;
1344  }
1345  }
1346 
1347  return 0;
1348 }
1349 
1350 static void
1351 D3D11_DestroyTexture(SDL_Renderer * renderer,
1352  SDL_Texture * texture)
1353 {
1354  D3D11_TextureData *data = (D3D11_TextureData *)texture->driverdata;
1355 
1356  if (!data) {
1357  return;
1358  }
1359 
1360  SAFE_RELEASE(data->mainTexture);
1361  SAFE_RELEASE(data->mainTextureResourceView);
1362  SAFE_RELEASE(data->mainTextureRenderTargetView);
1363  SAFE_RELEASE(data->stagingTexture);
1364  SAFE_RELEASE(data->mainTextureU);
1365  SAFE_RELEASE(data->mainTextureResourceViewU);
1366  SAFE_RELEASE(data->mainTextureV);
1367  SAFE_RELEASE(data->mainTextureResourceViewV);
1368  SDL_free(data->pixels);
1369  SDL_free(data);
1370  texture->driverdata = NULL;
1371 }
1372 
1373 static int
1374 D3D11_UpdateTextureInternal(D3D11_RenderData *rendererData, ID3D11Texture2D *texture, int bpp, int x, int y, int w, int h, const void *pixels, int pitch)
1375 {
1376  ID3D11Texture2D *stagingTexture;
1377  const Uint8 *src;
1378  Uint8 *dst;
1379  int row;
1380  UINT length;
1381  HRESULT result;
1382  D3D11_TEXTURE2D_DESC stagingTextureDesc;
1383  D3D11_MAPPED_SUBRESOURCE textureMemory;
1384 
1385  /* Create a 'staging' texture, which will be used to write to a portion of the main texture. */
1386  ID3D11Texture2D_GetDesc(texture, &stagingTextureDesc);
1387  stagingTextureDesc.Width = w;
1388  stagingTextureDesc.Height = h;
1389  stagingTextureDesc.BindFlags = 0;
1390  stagingTextureDesc.MiscFlags = 0;
1391  stagingTextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
1392  stagingTextureDesc.Usage = D3D11_USAGE_STAGING;
1393  result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
1394  &stagingTextureDesc,
1395  NULL,
1396  &stagingTexture);
1397  if (FAILED(result)) {
1398  WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D [create staging texture]"), result);
1399  return -1;
1400  }
1401 
1402  /* Get a write-only pointer to data in the staging texture: */
1403  result = ID3D11DeviceContext_Map(rendererData->d3dContext,
1404  (ID3D11Resource *)stagingTexture,
1405  0,
1406  D3D11_MAP_WRITE,
1407  0,
1408  &textureMemory
1409  );
1410  if (FAILED(result)) {
1411  WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [map staging texture]"), result);
1412  SAFE_RELEASE(stagingTexture);
1413  return -1;
1414  }
1415 
1416  src = (const Uint8 *)pixels;
1417  dst = textureMemory.pData;
1418  length = w * bpp;
1419  if (length == pitch && length == textureMemory.RowPitch) {
1420  SDL_memcpy(dst, src, length*h);
1421  } else {
1422  if (length > (UINT)pitch) {
1423  length = pitch;
1424  }
1425  if (length > textureMemory.RowPitch) {
1426  length = textureMemory.RowPitch;
1427  }
1428  for (row = 0; row < h; ++row) {
1429  SDL_memcpy(dst, src, length);
1430  src += pitch;
1431  dst += textureMemory.RowPitch;
1432  }
1433  }
1434 
1435  /* Commit the pixel buffer's changes back to the staging texture: */
1436  ID3D11DeviceContext_Unmap(rendererData->d3dContext,
1437  (ID3D11Resource *)stagingTexture,
1438  0);
1439 
1440  /* Copy the staging texture's contents back to the texture: */
1441  ID3D11DeviceContext_CopySubresourceRegion(rendererData->d3dContext,
1442  (ID3D11Resource *)texture,
1443  0,
1444  x,
1445  y,
1446  0,
1447  (ID3D11Resource *)stagingTexture,
1448  0,
1449  NULL);
1450 
1451  SAFE_RELEASE(stagingTexture);
1452 
1453  return 0;
1454 }
1455 
1456 static int
1457 D3D11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
1458  const SDL_Rect * rect, const void * srcPixels,
1459  int srcPitch)
1460 {
1461  D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata;
1462  D3D11_TextureData *textureData = (D3D11_TextureData *)texture->driverdata;
1463 
1464  if (!textureData) {
1465  SDL_SetError("Texture is not currently available");
1466  return -1;
1467  }
1468 
1469  if (D3D11_UpdateTextureInternal(rendererData, textureData->mainTexture, SDL_BYTESPERPIXEL(texture->format), rect->x, rect->y, rect->w, rect->h, srcPixels, srcPitch) < 0) {
1470  return -1;
1471  }
1472 
1473  if (textureData->yuv) {
1474  /* Skip to the correct offset into the next texture */
1475  srcPixels = (const void*)((const Uint8*)srcPixels + rect->h * srcPitch);
1476 
1477  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) {
1478  return -1;
1479  }
1480 
1481  /* Skip to the correct offset into the next texture */
1482  srcPixels = (const void*)((const Uint8*)srcPixels + ((rect->h + 1) / 2) * ((srcPitch + 1) / 2));
1483  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) {
1484  return -1;
1485  }
1486  }
1487 
1488  if (textureData->nv12) {
1489  /* Skip to the correct offset into the next texture */
1490  srcPixels = (const void*)((const Uint8*)srcPixels + rect->h * srcPitch);
1491 
1492  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) {
1493  return -1;
1494  }
1495  }
1496  return 0;
1497 }
1498 
1499 static int
1500 D3D11_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
1501  const SDL_Rect * rect,
1502  const Uint8 *Yplane, int Ypitch,
1503  const Uint8 *Uplane, int Upitch,
1504  const Uint8 *Vplane, int Vpitch)
1505 {
1506  D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata;
1507  D3D11_TextureData *textureData = (D3D11_TextureData *)texture->driverdata;
1508 
1509  if (!textureData) {
1510  SDL_SetError("Texture is not currently available");
1511  return -1;
1512  }
1513 
1514  if (D3D11_UpdateTextureInternal(rendererData, textureData->mainTexture, SDL_BYTESPERPIXEL(texture->format), rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch) < 0) {
1515  return -1;
1516  }
1517  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) {
1518  return -1;
1519  }
1520  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) {
1521  return -1;
1522  }
1523  return 0;
1524 }
1525 
1526 static int
1527 D3D11_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
1528  const SDL_Rect * rect, void **pixels, int *pitch)
1529 {
1530  D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
1531  D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
1532  HRESULT result = S_OK;
1533  D3D11_TEXTURE2D_DESC stagingTextureDesc;
1534  D3D11_MAPPED_SUBRESOURCE textureMemory;
1535 
1536  if (!textureData) {
1537  SDL_SetError("Texture is not currently available");
1538  return -1;
1539  }
1540 
1541  if (textureData->yuv || textureData->nv12) {
1542  /* It's more efficient to upload directly... */
1543  if (!textureData->pixels) {
1544  textureData->pitch = texture->w;
1545  textureData->pixels = (Uint8 *)SDL_malloc((texture->h * textureData->pitch * 3) / 2);
1546  if (!textureData->pixels) {
1547  return SDL_OutOfMemory();
1548  }
1549  }
1550  textureData->locked_rect = *rect;
1551  *pixels =
1552  (void *)((Uint8 *)textureData->pixels + rect->y * textureData->pitch +
1553  rect->x * SDL_BYTESPERPIXEL(texture->format));
1554  *pitch = textureData->pitch;
1555  return 0;
1556  }
1557 
1558  if (textureData->stagingTexture) {
1559  return SDL_SetError("texture is already locked");
1560  }
1561 
1562  /* Create a 'staging' texture, which will be used to write to a portion
1563  * of the main texture. This is necessary, as Direct3D 11.1 does not
1564  * have the ability to write a CPU-bound pixel buffer to a rectangular
1565  * subrect of a texture. Direct3D 11.1 can, however, write a pixel
1566  * buffer to an entire texture, hence the use of a staging texture.
1567  *
1568  * TODO, WinRT: consider avoiding the use of a staging texture in D3D11_LockTexture if/when the entire texture is being updated
1569  */
1570  ID3D11Texture2D_GetDesc(textureData->mainTexture, &stagingTextureDesc);
1571  stagingTextureDesc.Width = rect->w;
1572  stagingTextureDesc.Height = rect->h;
1573  stagingTextureDesc.BindFlags = 0;
1574  stagingTextureDesc.MiscFlags = 0;
1575  stagingTextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
1576  stagingTextureDesc.Usage = D3D11_USAGE_STAGING;
1577  result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
1578  &stagingTextureDesc,
1579  NULL,
1580  &textureData->stagingTexture);
1581  if (FAILED(result)) {
1582  WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D [create staging texture]"), result);
1583  return -1;
1584  }
1585 
1586  /* Get a write-only pointer to data in the staging texture: */
1587  result = ID3D11DeviceContext_Map(rendererData->d3dContext,
1588  (ID3D11Resource *)textureData->stagingTexture,
1589  0,
1590  D3D11_MAP_WRITE,
1591  0,
1592  &textureMemory
1593  );
1594  if (FAILED(result)) {
1595  WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [map staging texture]"), result);
1596  SAFE_RELEASE(textureData->stagingTexture);
1597  return -1;
1598  }
1599 
1600  /* Make note of where the staging texture will be written to
1601  * (on a call to SDL_UnlockTexture):
1602  */
1603  textureData->lockedTexturePositionX = rect->x;
1604  textureData->lockedTexturePositionY = rect->y;
1605 
1606  /* Make sure the caller has information on the texture's pixel buffer,
1607  * then return:
1608  */
1609  *pixels = textureMemory.pData;
1610  *pitch = textureMemory.RowPitch;
1611  return 0;
1612 }
1613 
1614 static void
1615 D3D11_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
1616 {
1617  D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
1618  D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
1619 
1620  if (!textureData) {
1621  return;
1622  }
1623 
1624  if (textureData->yuv || textureData->nv12) {
1625  const SDL_Rect *rect = &textureData->locked_rect;
1626  void *pixels =
1627  (void *) ((Uint8 *) textureData->pixels + rect->y * textureData->pitch +
1628  rect->x * SDL_BYTESPERPIXEL(texture->format));
1629  D3D11_UpdateTexture(renderer, texture, rect, pixels, textureData->pitch);
1630  return;
1631  }
1632 
1633  /* Commit the pixel buffer's changes back to the staging texture: */
1634  ID3D11DeviceContext_Unmap(rendererData->d3dContext,
1635  (ID3D11Resource *)textureData->stagingTexture,
1636  0);
1637 
1638  /* Copy the staging texture's contents back to the main texture: */
1639  ID3D11DeviceContext_CopySubresourceRegion(rendererData->d3dContext,
1640  (ID3D11Resource *)textureData->mainTexture,
1641  0,
1642  textureData->lockedTexturePositionX,
1643  textureData->lockedTexturePositionY,
1644  0,
1645  (ID3D11Resource *)textureData->stagingTexture,
1646  0,
1647  NULL);
1648 
1649  SAFE_RELEASE(textureData->stagingTexture);
1650 }
1651 
1652 static int
1653 D3D11_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
1654 {
1655  D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
1656  D3D11_TextureData *textureData = NULL;
1657 
1658  if (texture == NULL) {
1659  rendererData->currentOffscreenRenderTargetView = NULL;
1660  return 0;
1661  }
1662 
1663  textureData = (D3D11_TextureData *) texture->driverdata;
1664 
1665  if (!textureData->mainTextureRenderTargetView) {
1666  return SDL_SetError("specified texture is not a render target");
1667  }
1668 
1669  rendererData->currentOffscreenRenderTargetView = textureData->mainTextureRenderTargetView;
1670 
1671  return 0;
1672 }
1673 
1674 static void
1675 D3D11_SetModelMatrix(SDL_Renderer *renderer, const Float4X4 *matrix)
1676 {
1677  D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata;
1678 
1679  if (matrix) {
1680  data->vertexShaderConstantsData.model = *matrix;
1681  } else {
1682  data->vertexShaderConstantsData.model = MatrixIdentity();
1683  }
1684 
1685  ID3D11DeviceContext_UpdateSubresource(data->d3dContext,
1686  (ID3D11Resource *)data->vertexShaderConstants,
1687  0,
1688  NULL,
1689  &data->vertexShaderConstantsData,
1690  0,
1691  0
1692  );
1693 }
1694 
1695 static int
1696 D3D11_UpdateViewport(SDL_Renderer * renderer)
1697 {
1698  D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
1699  Float4X4 projection;
1700  Float4X4 view;
1701  SDL_FRect orientationAlignedViewport;
1702  BOOL swapDimensions;
1703  D3D11_VIEWPORT viewport;
1704  const int rotation = D3D11_GetRotationForCurrentRenderTarget(renderer);
1705 
1706  if (renderer->viewport.w == 0 || renderer->viewport.h == 0) {
1707  /* If the viewport is empty, assume that it is because
1708  * SDL_CreateRenderer is calling it, and will call it again later
1709  * with a non-empty viewport.
1710  */
1711  /* SDL_Log("%s, no viewport was set!\n", __FUNCTION__); */
1712  return 0;
1713  }
1714 
1715  /* Make sure the SDL viewport gets rotated to that of the physical display's rotation.
1716  * Keep in mind here that the Y-axis will be been inverted (from Direct3D's
1717  * default coordinate system) so rotations will be done in the opposite
1718  * direction of the DXGI_MODE_ROTATION enumeration.
1719  */
1720  switch (rotation) {
1721  case DXGI_MODE_ROTATION_IDENTITY:
1722  projection = MatrixIdentity();
1723  break;
1724  case DXGI_MODE_ROTATION_ROTATE270:
1725  projection = MatrixRotationZ(SDL_static_cast(float, M_PI * 0.5f));
1726  break;
1727  case DXGI_MODE_ROTATION_ROTATE180:
1728  projection = MatrixRotationZ(SDL_static_cast(float, M_PI));
1729  break;
1730  case DXGI_MODE_ROTATION_ROTATE90:
1731  projection = MatrixRotationZ(SDL_static_cast(float, -M_PI * 0.5f));
1732  break;
1733  default:
1734  return SDL_SetError("An unknown DisplayOrientation is being used");
1735  }
1736 
1737  /* Update the view matrix */
1738  view.m[0][0] = 2.0f / renderer->viewport.w;
1739  view.m[0][1] = 0.0f;
1740  view.m[0][2] = 0.0f;
1741  view.m[0][3] = 0.0f;
1742  view.m[1][0] = 0.0f;
1743  view.m[1][1] = -2.0f / renderer->viewport.h;
1744  view.m[1][2] = 0.0f;
1745  view.m[1][3] = 0.0f;
1746  view.m[2][0] = 0.0f;
1747  view.m[2][1] = 0.0f;
1748  view.m[2][2] = 1.0f;
1749  view.m[2][3] = 0.0f;
1750  view.m[3][0] = -1.0f;
1751  view.m[3][1] = 1.0f;
1752  view.m[3][2] = 0.0f;
1753  view.m[3][3] = 1.0f;
1754 
1755  /* Combine the projection + view matrix together now, as both only get
1756  * set here (as of this writing, on Dec 26, 2013). When done, store it
1757  * for eventual transfer to the GPU.
1758  */
1759  data->vertexShaderConstantsData.projectionAndView = MatrixMultiply(
1760  view,
1761  projection);
1762 
1763  /* Reset the model matrix */
1764  D3D11_SetModelMatrix(renderer, NULL);
1765 
1766  /* Update the Direct3D viewport, which seems to be aligned to the
1767  * swap buffer's coordinate space, which is always in either
1768  * a landscape mode, for all Windows 8/RT devices, or a portrait mode,
1769  * for Windows Phone devices.
1770  */
1771  swapDimensions = D3D11_IsDisplayRotated90Degrees(rotation);
1772  if (swapDimensions) {
1773  orientationAlignedViewport.x = (float) renderer->viewport.y;
1774  orientationAlignedViewport.y = (float) renderer->viewport.x;
1775  orientationAlignedViewport.w = (float) renderer->viewport.h;
1776  orientationAlignedViewport.h = (float) renderer->viewport.w;
1777  } else {
1778  orientationAlignedViewport.x = (float) renderer->viewport.x;
1779  orientationAlignedViewport.y = (float) renderer->viewport.y;
1780  orientationAlignedViewport.w = (float) renderer->viewport.w;
1781  orientationAlignedViewport.h = (float) renderer->viewport.h;
1782  }
1783  /* TODO, WinRT: get custom viewports working with non-Landscape modes (Portrait, PortraitFlipped, and LandscapeFlipped) */
1784 
1785  viewport.TopLeftX = orientationAlignedViewport.x;
1786  viewport.TopLeftY = orientationAlignedViewport.y;
1787  viewport.Width = orientationAlignedViewport.w;
1788  viewport.Height = orientationAlignedViewport.h;
1789  viewport.MinDepth = 0.0f;
1790  viewport.MaxDepth = 1.0f;
1791  /* SDL_Log("%s: D3D viewport = {%f,%f,%f,%f}\n", __FUNCTION__, viewport.TopLeftX, viewport.TopLeftY, viewport.Width, viewport.Height); */
1792  ID3D11DeviceContext_RSSetViewports(data->d3dContext, 1, &viewport);
1793 
1794  return 0;
1795 }
1796 
1797 static int
1798 D3D11_UpdateClipRect(SDL_Renderer * renderer)
1799 {
1800  D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
1801 
1802  if (!renderer->clipping_enabled) {
1803  ID3D11DeviceContext_RSSetScissorRects(data->d3dContext, 0, NULL);
1804  } else {
1805  D3D11_RECT scissorRect;
1806  if (D3D11_GetViewportAlignedD3DRect(renderer, &renderer->clip_rect, &scissorRect, TRUE) != 0) {
1807  /* D3D11_GetViewportAlignedD3DRect will have set the SDL error */
1808  return -1;
1809  }
1810  ID3D11DeviceContext_RSSetScissorRects(data->d3dContext, 1, &scissorRect);
1811  }
1812 
1813  return 0;
1814 }
1815 
1816 static void
1817 D3D11_ReleaseMainRenderTargetView(SDL_Renderer * renderer)
1818 {
1819  D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata;
1820  ID3D11DeviceContext_OMSetRenderTargets(data->d3dContext, 0, NULL, NULL);
1821  SAFE_RELEASE(data->mainRenderTargetView);
1822 }
1823 
1824 static ID3D11RenderTargetView *
1825 D3D11_GetCurrentRenderTargetView(SDL_Renderer * renderer)
1826 {
1827  D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
1828  if (data->currentOffscreenRenderTargetView) {
1829  return data->currentOffscreenRenderTargetView;
1830  } else {
1831  return data->mainRenderTargetView;
1832  }
1833 }
1834 
1835 static int
1836 D3D11_RenderClear(SDL_Renderer * renderer)
1837 {
1838  D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
1839  const float colorRGBA[] = {
1840  (renderer->r / 255.0f),
1841  (renderer->g / 255.0f),
1842  (renderer->b / 255.0f),
1843  (renderer->a / 255.0f)
1844  };
1845  ID3D11DeviceContext_ClearRenderTargetView(data->d3dContext,
1846  D3D11_GetCurrentRenderTargetView(renderer),
1847  colorRGBA
1848  );
1849  return 0;
1850 }
1851 
1852 static int
1853 D3D11_UpdateVertexBuffer(SDL_Renderer *renderer,
1854  const void * vertexData, size_t dataSizeInBytes)
1855 {
1856  D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
1857  D3D11_BUFFER_DESC vertexBufferDesc;
1858  HRESULT result = S_OK;
1859  D3D11_SUBRESOURCE_DATA vertexBufferData;
1860  const UINT stride = sizeof(VertexPositionColor);
1861  const UINT offset = 0;
1862 
1863  if (rendererData->vertexBuffer) {
1864  ID3D11Buffer_GetDesc(rendererData->vertexBuffer, &vertexBufferDesc);
1865  } else {
1866  SDL_zero(vertexBufferDesc);
1867  }
1868 
1869  if (rendererData->vertexBuffer && vertexBufferDesc.ByteWidth >= dataSizeInBytes) {
1870  D3D11_MAPPED_SUBRESOURCE mappedResource;
1871  result = ID3D11DeviceContext_Map(rendererData->d3dContext,
1872  (ID3D11Resource *)rendererData->vertexBuffer,
1873  0,
1874  D3D11_MAP_WRITE_DISCARD,
1875  0,
1876  &mappedResource
1877  );
1878  if (FAILED(result)) {
1879  WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [vertex buffer]"), result);
1880  return -1;
1881  }
1882  SDL_memcpy(mappedResource.pData, vertexData, dataSizeInBytes);
1883  ID3D11DeviceContext_Unmap(rendererData->d3dContext, (ID3D11Resource *)rendererData->vertexBuffer, 0);
1884  } else {
1885  SAFE_RELEASE(rendererData->vertexBuffer);
1886 
1887  vertexBufferDesc.ByteWidth = (UINT) dataSizeInBytes;
1888  vertexBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
1889  vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
1890  vertexBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
1891 
1892  SDL_zero(vertexBufferData);
1893  vertexBufferData.pSysMem = vertexData;
1894  vertexBufferData.SysMemPitch = 0;
1895  vertexBufferData.SysMemSlicePitch = 0;
1896 
1897  result = ID3D11Device_CreateBuffer(rendererData->d3dDevice,
1898  &vertexBufferDesc,
1899  &vertexBufferData,
1900  &rendererData->vertexBuffer
1901  );
1902  if (FAILED(result)) {
1903  WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateBuffer [vertex buffer]"), result);
1904  return -1;
1905  }
1906 
1907  ID3D11DeviceContext_IASetVertexBuffers(rendererData->d3dContext,
1908  0,
1909  1,
1910  &rendererData->vertexBuffer,
1911  &stride,
1912  &offset
1913  );
1914  }
1915 
1916  return 0;
1917 }
1918 
1919 static void
1920 D3D11_RenderStartDrawOp(SDL_Renderer * renderer)
1921 {
1922  D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata;
1923  ID3D11RasterizerState *rasterizerState;
1924  ID3D11RenderTargetView *renderTargetView = D3D11_GetCurrentRenderTargetView(renderer);
1925  if (renderTargetView != rendererData->currentRenderTargetView) {
1926  ID3D11DeviceContext_OMSetRenderTargets(rendererData->d3dContext,
1927  1,
1928  &renderTargetView,
1929  NULL
1930  );
1931  rendererData->currentRenderTargetView = renderTargetView;
1932  }
1933 
1934  if (!renderer->clipping_enabled) {
1935  rasterizerState = rendererData->mainRasterizer;
1936  } else {
1937  rasterizerState = rendererData->clippedRasterizer;
1938  }
1939  if (rasterizerState != rendererData->currentRasterizerState) {
1940  ID3D11DeviceContext_RSSetState(rendererData->d3dContext, rasterizerState);
1941  rendererData->currentRasterizerState = rasterizerState;
1942  }
1943 }
1944 
1945 static void
1946 D3D11_RenderSetBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
1947 {
1948  D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata;
1949  ID3D11BlendState *blendState = NULL;
1950  if (blendMode != SDL_BLENDMODE_NONE) {
1951  int i;
1952  for (i = 0; i < rendererData->blendModesCount; ++i) {
1953  if (blendMode == rendererData->blendModes[i].blendMode) {
1954  blendState = rendererData->blendModes[i].blendState;
1955  break;
1956  }
1957  }
1958  if (!blendState) {
1959  if (D3D11_CreateBlendState(renderer, blendMode)) {
1960  /* Successfully created the blend state, try again */
1961  D3D11_RenderSetBlendMode(renderer, blendMode);
1962  }
1963  return;
1964  }
1965  }
1966  if (blendState != rendererData->currentBlendState) {
1967  ID3D11DeviceContext_OMSetBlendState(rendererData->d3dContext, blendState, 0, 0xFFFFFFFF);
1968  rendererData->currentBlendState = blendState;
1969  }
1970 }
1971 
1972 static void
1973 D3D11_SetPixelShader(SDL_Renderer * renderer,
1974  ID3D11PixelShader * shader,
1975  int numShaderResources,
1976  ID3D11ShaderResourceView ** shaderResources,
1977  ID3D11SamplerState * sampler)
1978 {
1979  D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
1980  ID3D11ShaderResourceView *shaderResource;
1981  if (shader != rendererData->currentShader) {
1982  ID3D11DeviceContext_PSSetShader(rendererData->d3dContext, shader, NULL, 0);
1983  rendererData->currentShader = shader;
1984  }
1985  if (numShaderResources > 0) {
1986  shaderResource = shaderResources[0];
1987  } else {
1988  shaderResource = NULL;
1989  }
1990  if (shaderResource != rendererData->currentShaderResource) {
1991  ID3D11DeviceContext_PSSetShaderResources(rendererData->d3dContext, 0, numShaderResources, shaderResources);
1992  rendererData->currentShaderResource = shaderResource;
1993  }
1994  if (sampler != rendererData->currentSampler) {
1995  ID3D11DeviceContext_PSSetSamplers(rendererData->d3dContext, 0, 1, &sampler);
1996  rendererData->currentSampler = sampler;
1997  }
1998 }
1999 
2000 static void
2001 D3D11_RenderFinishDrawOp(SDL_Renderer * renderer,
2002  D3D11_PRIMITIVE_TOPOLOGY primitiveTopology,
2003  UINT vertexCount)
2004 {
2005  D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
2006 
2007  ID3D11DeviceContext_IASetPrimitiveTopology(rendererData->d3dContext, primitiveTopology);
2008  ID3D11DeviceContext_Draw(rendererData->d3dContext, vertexCount, 0);
2009 }
2010 
2011 static int
2012 D3D11_RenderDrawPoints(SDL_Renderer * renderer,
2013  const SDL_FPoint * points, int count)
2014 {
2015  D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
2016  float r, g, b, a;
2017  VertexPositionColor *vertices;
2018  int i;
2019 
2020  r = (float)(renderer->r / 255.0f);
2021  g = (float)(renderer->g / 255.0f);
2022  b = (float)(renderer->b / 255.0f);
2023  a = (float)(renderer->a / 255.0f);
2024 
2025  vertices = SDL_stack_alloc(VertexPositionColor, count);
2026  for (i = 0; i < count; ++i) {
2027  const VertexPositionColor v = { { points[i].x + 0.5f, points[i].y + 0.5f, 0.0f }, { 0.0f, 0.0f }, { r, g, b, a } };
2028  vertices[i] = v;
2029  }
2030 
2031  D3D11_RenderStartDrawOp(renderer);
2032  D3D11_RenderSetBlendMode(renderer, renderer->blendMode);
2033  if (D3D11_UpdateVertexBuffer(renderer, vertices, (unsigned int)count * sizeof(VertexPositionColor)) != 0) {
2034  SDL_stack_free(vertices);
2035  return -1;
2036  }
2037 
2038  D3D11_SetPixelShader(
2039  renderer,
2040  rendererData->pixelShaders[SHADER_SOLID],
2041  0,
2042  NULL,
2043  NULL);
2044 
2045  D3D11_RenderFinishDrawOp(renderer, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, count);
2046  SDL_stack_free(vertices);
2047  return 0;
2048 }
2049 
2050 static int
2051 D3D11_RenderDrawLines(SDL_Renderer * renderer,
2052  const SDL_FPoint * points, int count)
2053 {
2054  D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
2055  float r, g, b, a;
2056  VertexPositionColor *vertices;
2057  int i;
2058 
2059  r = (float)(renderer->r / 255.0f);
2060  g = (float)(renderer->g / 255.0f);
2061  b = (float)(renderer->b / 255.0f);
2062  a = (float)(renderer->a / 255.0f);
2063 
2064  vertices = SDL_stack_alloc(VertexPositionColor, count);
2065  for (i = 0; i < count; ++i) {
2066  const VertexPositionColor v = { { points[i].x + 0.5f, points[i].y + 0.5f, 0.0f }, { 0.0f, 0.0f }, { r, g, b, a } };
2067  vertices[i] = v;
2068  }
2069 
2070  D3D11_RenderStartDrawOp(renderer);
2071  D3D11_RenderSetBlendMode(renderer, renderer->blendMode);
2072  if (D3D11_UpdateVertexBuffer(renderer, vertices, (unsigned int)count * sizeof(VertexPositionColor)) != 0) {
2073  SDL_stack_free(vertices);
2074  return -1;
2075  }
2076 
2077  D3D11_SetPixelShader(
2078  renderer,
2079  rendererData->pixelShaders[SHADER_SOLID],
2080  0,
2081  NULL,
2082  NULL);
2083 
2084  D3D11_RenderFinishDrawOp(renderer, D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP, count);
2085 
2086  if (points[0].x != points[count - 1].x || points[0].y != points[count - 1].y) {
2087  ID3D11DeviceContext_IASetPrimitiveTopology(rendererData->d3dContext, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
2088  ID3D11DeviceContext_Draw(rendererData->d3dContext, 1, count - 1);
2089  }
2090 
2091  SDL_stack_free(vertices);
2092  return 0;
2093 }
2094 
2095 static int
2096 D3D11_RenderFillRects(SDL_Renderer * renderer,
2097  const SDL_FRect * rects, int count)
2098 {
2099  D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
2100  float r, g, b, a;
2101  int i;
2102 
2103  r = (float)(renderer->r / 255.0f);
2104  g = (float)(renderer->g / 255.0f);
2105  b = (float)(renderer->b / 255.0f);
2106  a = (float)(renderer->a / 255.0f);
2107 
2108  for (i = 0; i < count; ++i) {
2109  VertexPositionColor vertices[] = {
2110  { { rects[i].x, rects[i].y, 0.0f }, { 0.0f, 0.0f}, {r, g, b, a} },
2111  { { rects[i].x, rects[i].y + rects[i].h, 0.0f }, { 0.0f, 0.0f }, { r, g, b, a } },
2112  { { rects[i].x + rects[i].w, rects[i].y, 0.0f }, { 0.0f, 0.0f }, { r, g, b, a } },
2113  { { rects[i].x + rects[i].w, rects[i].y + rects[i].h, 0.0f }, { 0.0f, 0.0f }, { r, g, b, a } },
2114  };
2115 
2116  D3D11_RenderStartDrawOp(renderer);
2117  D3D11_RenderSetBlendMode(renderer, renderer->blendMode);
2118  if (D3D11_UpdateVertexBuffer(renderer, vertices, sizeof(vertices)) != 0) {
2119  return -1;
2120  }
2121 
2122  D3D11_SetPixelShader(
2123  renderer,
2124  rendererData->pixelShaders[SHADER_SOLID],
2125  0,
2126  NULL,
2127  NULL);
2128 
2129  D3D11_RenderFinishDrawOp(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, SDL_arraysize(vertices));
2130  }
2131 
2132  return 0;
2133 }
2134 
2135 static int
2136 D3D11_RenderSetupSampler(SDL_Renderer * renderer, SDL_Texture * texture)
2137 {
2138  D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
2139  D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
2140  ID3D11SamplerState *textureSampler;
2141 
2142  switch (textureData->scaleMode) {
2143  case D3D11_FILTER_MIN_MAG_MIP_POINT:
2144  textureSampler = rendererData->nearestPixelSampler;
2145  break;
2146  case D3D11_FILTER_MIN_MAG_MIP_LINEAR:
2147  textureSampler = rendererData->linearSampler;
2148  break;
2149  default:
2150  return SDL_SetError("Unknown scale mode: %d\n", textureData->scaleMode);
2151  }
2152 
2153  if (textureData->yuv) {
2154  ID3D11ShaderResourceView *shaderResources[] = {
2155  textureData->mainTextureResourceView,
2156  textureData->mainTextureResourceViewU,
2157  textureData->mainTextureResourceViewV
2158  };
2160 
2161  switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) {
2163  shader = SHADER_YUV_JPEG;
2164  break;
2166  shader = SHADER_YUV_BT601;
2167  break;
2169  shader = SHADER_YUV_BT709;
2170  break;
2171  default:
2172  return SDL_SetError("Unsupported YUV conversion mode");
2173  }
2174 
2175  D3D11_SetPixelShader(
2176  renderer,
2177  rendererData->pixelShaders[shader],
2178  SDL_arraysize(shaderResources),
2179  shaderResources,
2180  textureSampler);
2181 
2182  } else if (textureData->nv12) {
2183  ID3D11ShaderResourceView *shaderResources[] = {
2184  textureData->mainTextureResourceView,
2185  textureData->mainTextureResourceViewNV,
2186  };
2188 
2189  switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) {
2192  break;
2195  break;
2198  break;
2199  default:
2200  return SDL_SetError("Unsupported YUV conversion mode");
2201  }
2202 
2203  D3D11_SetPixelShader(
2204  renderer,
2205  rendererData->pixelShaders[shader],
2206  SDL_arraysize(shaderResources),
2207  shaderResources,
2208  textureSampler);
2209 
2210  } else {
2211  D3D11_SetPixelShader(
2212  renderer,
2213  rendererData->pixelShaders[SHADER_RGB],
2214  1,
2215  &textureData->mainTextureResourceView,
2216  textureSampler);
2217  }
2218 
2219  return 0;
2220 }
2221 
2222 static int
2223 D3D11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
2224  const SDL_Rect * srcrect, const SDL_FRect * dstrect)
2225 {
2226  float minu, maxu, minv, maxv;
2227  Float4 color;
2228  VertexPositionColor vertices[4];
2229 
2230  D3D11_RenderStartDrawOp(renderer);
2231  D3D11_RenderSetBlendMode(renderer, texture->blendMode);
2232 
2233  minu = (float) srcrect->x / texture->w;
2234  maxu = (float) (srcrect->x + srcrect->w) / texture->w;
2235  minv = (float) srcrect->y / texture->h;
2236  maxv = (float) (srcrect->y + srcrect->h) / texture->h;
2237 
2238  color.x = 1.0f; /* red */
2239  color.y = 1.0f; /* green */
2240  color.z = 1.0f; /* blue */
2241  color.w = 1.0f; /* alpha */
2242  if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
2243  color.x = (float)(texture->r / 255.0f); /* red */
2244  color.y = (float)(texture->g / 255.0f); /* green */
2245  color.z = (float)(texture->b / 255.0f); /* blue */
2246  }
2247  if (texture->modMode & SDL_TEXTUREMODULATE_ALPHA) {
2248  color.w = (float)(texture->a / 255.0f); /* alpha */
2249  }
2250 
2251  vertices[0].pos.x = dstrect->x;
2252  vertices[0].pos.y = dstrect->y;
2253  vertices[0].pos.z = 0.0f;
2254  vertices[0].tex.x = minu;
2255  vertices[0].tex.y = minv;
2256  vertices[0].color = color;
2257 
2258  vertices[1].pos.x = dstrect->x;
2259  vertices[1].pos.y = dstrect->y + dstrect->h;
2260  vertices[1].pos.z = 0.0f;
2261  vertices[1].tex.x = minu;
2262  vertices[1].tex.y = maxv;
2263  vertices[1].color = color;
2264 
2265  vertices[2].pos.x = dstrect->x + dstrect->w;
2266  vertices[2].pos.y = dstrect->y;
2267  vertices[2].pos.z = 0.0f;
2268  vertices[2].tex.x = maxu;
2269  vertices[2].tex.y = minv;
2270  vertices[2].color = color;
2271 
2272  vertices[3].pos.x = dstrect->x + dstrect->w;
2273  vertices[3].pos.y = dstrect->y + dstrect->h;
2274  vertices[3].pos.z = 0.0f;
2275  vertices[3].tex.x = maxu;
2276  vertices[3].tex.y = maxv;
2277  vertices[3].color = color;
2278 
2279  if (D3D11_UpdateVertexBuffer(renderer, vertices, sizeof(vertices)) != 0) {
2280  return -1;
2281  }
2282 
2283  if (D3D11_RenderSetupSampler(renderer, texture) < 0) {
2284  return -1;
2285  }
2286 
2287  D3D11_RenderFinishDrawOp(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, sizeof(vertices) / sizeof(VertexPositionColor));
2288 
2289  return 0;
2290 }
2291 
2292 static int
2293 D3D11_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
2294  const SDL_Rect * srcrect, const SDL_FRect * dstrect,
2295  const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip)
2296 {
2297  float minu, maxu, minv, maxv;
2298  Float4 color;
2299  Float4X4 modelMatrix;
2300  float minx, maxx, miny, maxy;
2301  VertexPositionColor vertices[4];
2302 
2303  D3D11_RenderStartDrawOp(renderer);
2304  D3D11_RenderSetBlendMode(renderer, texture->blendMode);
2305 
2306  minu = (float) srcrect->x / texture->w;
2307  maxu = (float) (srcrect->x + srcrect->w) / texture->w;
2308  minv = (float) srcrect->y / texture->h;
2309  maxv = (float) (srcrect->y + srcrect->h) / texture->h;
2310 
2311  color.x = 1.0f; /* red */
2312  color.y = 1.0f; /* green */
2313  color.z = 1.0f; /* blue */
2314  color.w = 1.0f; /* alpha */
2315  if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
2316  color.x = (float)(texture->r / 255.0f); /* red */
2317  color.y = (float)(texture->g / 255.0f); /* green */
2318  color.z = (float)(texture->b / 255.0f); /* blue */
2319  }
2320  if (texture->modMode & SDL_TEXTUREMODULATE_ALPHA) {
2321  color.w = (float)(texture->a / 255.0f); /* alpha */
2322  }
2323 
2324  if (flip & SDL_FLIP_HORIZONTAL) {
2325  float tmp = maxu;
2326  maxu = minu;
2327  minu = tmp;
2328  }
2329  if (flip & SDL_FLIP_VERTICAL) {
2330  float tmp = maxv;
2331  maxv = minv;
2332  minv = tmp;
2333  }
2334 
2335  modelMatrix = MatrixMultiply(
2336  MatrixRotationZ((float)(M_PI * (float) angle / 180.0f)),
2337  MatrixTranslation(dstrect->x + center->x, dstrect->y + center->y, 0)
2338  );
2339  D3D11_SetModelMatrix(renderer, &modelMatrix);
2340 
2341  minx = -center->x;
2342  maxx = dstrect->w - center->x;
2343  miny = -center->y;
2344  maxy = dstrect->h - center->y;
2345 
2346  vertices[0].pos.x = minx;
2347  vertices[0].pos.y = miny;
2348  vertices[0].pos.z = 0.0f;
2349  vertices[0].tex.x = minu;
2350  vertices[0].tex.y = minv;
2351  vertices[0].color = color;
2352 
2353  vertices[1].pos.x = minx;
2354  vertices[1].pos.y = maxy;
2355  vertices[1].pos.z = 0.0f;
2356  vertices[1].tex.x = minu;
2357  vertices[1].tex.y = maxv;
2358  vertices[1].color = color;
2359 
2360  vertices[2].pos.x = maxx;
2361  vertices[2].pos.y = miny;
2362  vertices[2].pos.z = 0.0f;
2363  vertices[2].tex.x = maxu;
2364  vertices[2].tex.y = minv;
2365  vertices[2].color = color;
2366 
2367  vertices[3].pos.x = maxx;
2368  vertices[3].pos.y = maxy;
2369  vertices[3].pos.z = 0.0f;
2370  vertices[3].tex.x = maxu;
2371  vertices[3].tex.y = maxv;
2372  vertices[3].color = color;
2373 
2374  if (D3D11_UpdateVertexBuffer(renderer, vertices, sizeof(vertices)) != 0) {
2375  return -1;
2376  }
2377 
2378  if (D3D11_RenderSetupSampler(renderer, texture) < 0) {
2379  return -1;
2380  }
2381 
2382  D3D11_RenderFinishDrawOp(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, sizeof(vertices) / sizeof(VertexPositionColor));
2383 
2384  D3D11_SetModelMatrix(renderer, NULL);
2385 
2386  return 0;
2387 }
2388 
2389 static int
2390 D3D11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
2391  Uint32 format, void * pixels, int pitch)
2392 {
2393  D3D11_RenderData * data = (D3D11_RenderData *) renderer->driverdata;
2394  ID3D11Texture2D *backBuffer = NULL;
2395  ID3D11Texture2D *stagingTexture = NULL;
2396  HRESULT result;
2397  int status = -1;
2398  D3D11_TEXTURE2D_DESC stagingTextureDesc;
2399  D3D11_RECT srcRect = {0, 0, 0, 0};
2400  D3D11_BOX srcBox;
2401  D3D11_MAPPED_SUBRESOURCE textureMemory;
2402 
2403  /* Retrieve a pointer to the back buffer: */
2404  result = IDXGISwapChain_GetBuffer(data->swapChain,
2405  0,
2406  &SDL_IID_ID3D11Texture2D,
2407  (void **)&backBuffer
2408  );
2409  if (FAILED(result)) {
2410  WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain1::GetBuffer [get back buffer]"), result);
2411  goto done;
2412  }
2413 
2414  /* Create a staging texture to copy the screen's data to: */
2415  ID3D11Texture2D_GetDesc(backBuffer, &stagingTextureDesc);
2416  stagingTextureDesc.Width = rect->w;
2417  stagingTextureDesc.Height = rect->h;
2418  stagingTextureDesc.BindFlags = 0;
2419  stagingTextureDesc.MiscFlags = 0;
2420  stagingTextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
2421  stagingTextureDesc.Usage = D3D11_USAGE_STAGING;
2422  result = ID3D11Device_CreateTexture2D(data->d3dDevice,
2423  &stagingTextureDesc,
2424  NULL,
2425  &stagingTexture);
2426  if (FAILED(result)) {
2427  WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D [create staging texture]"), result);
2428  goto done;
2429  }
2430 
2431  /* Copy the desired portion of the back buffer to the staging texture: */
2432  if (D3D11_GetViewportAlignedD3DRect(renderer, rect, &srcRect, FALSE) != 0) {
2433  /* D3D11_GetViewportAlignedD3DRect will have set the SDL error */
2434  goto done;
2435  }
2436 
2437  srcBox.left = srcRect.left;
2438  srcBox.right = srcRect.right;
2439  srcBox.top = srcRect.top;
2440  srcBox.bottom = srcRect.bottom;
2441  srcBox.front = 0;
2442  srcBox.back = 1;
2443  ID3D11DeviceContext_CopySubresourceRegion(data->d3dContext,
2444  (ID3D11Resource *)stagingTexture,
2445  0,
2446  0, 0, 0,
2447  (ID3D11Resource *)backBuffer,
2448  0,
2449  &srcBox);
2450 
2451  /* Map the staging texture's data to CPU-accessible memory: */
2452  result = ID3D11DeviceContext_Map(data->d3dContext,
2453  (ID3D11Resource *)stagingTexture,
2454  0,
2455  D3D11_MAP_READ,
2456  0,
2457  &textureMemory);
2458  if (FAILED(result)) {
2459  WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [map staging texture]"), result);
2460  goto done;
2461  }
2462 
2463  /* Copy the data into the desired buffer, converting pixels to the
2464  * desired format at the same time:
2465  */
2466  if (SDL_ConvertPixels(
2467  rect->w, rect->h,
2468  D3D11_DXGIFormatToSDLPixelFormat(stagingTextureDesc.Format),
2469  textureMemory.pData,
2470  textureMemory.RowPitch,
2471  format,
2472  pixels,
2473  pitch) != 0) {
2474  /* When SDL_ConvertPixels fails, it'll have already set the format.
2475  * Get the error message, and attach some extra data to it.
2476  */
2477  char errorMessage[1024];
2478  SDL_snprintf(errorMessage, sizeof(errorMessage), "%s, Convert Pixels failed: %s", __FUNCTION__, SDL_GetError());
2479  SDL_SetError("%s", errorMessage);
2480  goto done;
2481  }
2482 
2483  /* Unmap the texture: */
2484  ID3D11DeviceContext_Unmap(data->d3dContext,
2485  (ID3D11Resource *)stagingTexture,
2486  0);
2487 
2488  status = 0;
2489 
2490 done:
2491  SAFE_RELEASE(backBuffer);
2492  SAFE_RELEASE(stagingTexture);
2493  return status;
2494 }
2495 
2496 static void
2497 D3D11_RenderPresent(SDL_Renderer * renderer)
2498 {
2499  D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
2500  UINT syncInterval;
2501  UINT presentFlags;
2502  HRESULT result;
2503  DXGI_PRESENT_PARAMETERS parameters;
2504 
2505  SDL_zero(parameters);
2506 
2507 #if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
2508  syncInterval = 1;
2509  presentFlags = 0;
2510  result = IDXGISwapChain_Present(data->swapChain, syncInterval, presentFlags);
2511 #else
2512  if (renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) {
2513  syncInterval = 1;
2514  presentFlags = 0;
2515  } else {
2516  syncInterval = 0;
2517  presentFlags = DXGI_PRESENT_DO_NOT_WAIT;
2518  }
2519 
2520  /* The application may optionally specify "dirty" or "scroll"
2521  * rects to improve efficiency in certain scenarios.
2522  * This option is not available on Windows Phone 8, to note.
2523  */
2524  result = IDXGISwapChain1_Present1(data->swapChain, syncInterval, presentFlags, &parameters);
2525 #endif
2526 
2527  /* Discard the contents of the render target.
2528  * This is a valid operation only when the existing contents will be entirely
2529  * overwritten. If dirty or scroll rects are used, this call should be removed.
2530  */
2531  ID3D11DeviceContext1_DiscardView(data->d3dContext, (ID3D11View*)data->mainRenderTargetView);
2532 
2533  /* When the present flips, it unbinds the current view, so bind it again on the next draw call */
2534  data->currentRenderTargetView = NULL;
2535 
2536  if (FAILED(result) && result != DXGI_ERROR_WAS_STILL_DRAWING) {
2537  /* If the device was removed either by a disconnect or a driver upgrade, we
2538  * must recreate all device resources.
2539  *
2540  * TODO, WinRT: consider throwing an exception if D3D11_RenderPresent fails, especially if there is a way to salvage debug info from users' machines
2541  */
2542  if ( result == DXGI_ERROR_DEVICE_REMOVED ) {
2543  D3D11_HandleDeviceLost(renderer);
2544  } else if (result == DXGI_ERROR_INVALID_CALL) {
2545  /* We probably went through a fullscreen <-> windowed transition */
2546  D3D11_CreateWindowSizeDependentResources(renderer);
2547  } else {
2548  WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain::Present"), result);
2549  }
2550  }
2551 }
2552 
2553 #endif /* SDL_VIDEO_RENDER_D3D11 && !SDL_RENDER_DISABLED */
2554 
2555 /* vi: set ts=4 sw=4 expandtab: */
SDL_BlendFactor SDL_GetBlendModeSrcColorFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:2252
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:65
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)
#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:91
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1571
SDL_Rect rect
Definition: testrelative.c:27
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:2280
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld [DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp local skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
SDL_version version
Definition: SDL_syswm.h:196
SDL_BlendOperation SDL_GetBlendModeColorOperation(SDL_BlendMode blendMode)
Definition: SDL_render.c:2266
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
#define SDL_realloc
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp
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:99
int(* UpdateTextureYUV)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const Uint8 *Yplane, int Ypitch, const Uint8 *Uplane, int Upitch, const Uint8 *Vplane, int Vpitch)
#define SDL_GetWindowSize
#define FAILED(x)
Definition: SDL_directx.h:54
SDL_Texture * next
Definition: SDL_sysrender.h:81
#define SDL_memcpy
GLenum GLenum GLuint texture
SDL_BlendOperation SDL_GetBlendModeAlphaOperation(SDL_BlendMode blendMode)
Definition: SDL_render.c:2287
static SDL_Renderer * renderer
uint8_t Uint8
Definition: SDL_stdinc.h:179
#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:138
GLubyte GLubyte GLubyte GLubyte w
void(* UnlockTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
int x
Definition: SDL_rect.h: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:195
#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:161
SDL_BlendFactor SDL_GetBlendModeSrcAlphaFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:2273
#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
uint32_t Uint32
Definition: SDL_stdinc.h:203
SDL_Rect viewport
Definition: testviewport.c:28
SDL_BlendFactor SDL_GetBlendModeDstColorFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:2259
GLuint color
#define E_FAIL
Definition: SDL_directx.h:58
void(* WindowEvent)(SDL_Renderer *renderer, const SDL_WindowEvent *event)
Definition: SDL_sysrender.h:89
GLfloat angle
#define SDL_snprintf
Uint32 format
Definition: SDL_sysrender.h:60
union SDL_SysWMinfo::@18 info
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:115
void * driverdata
Definition: SDL_sysrender.h:78
General event structure.
Definition: SDL_events.h:557
#define SDL_malloc
#define SDL_ConvertPixels
void(* DestroyTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
void * SDL_LoadFunction(void *handle, const char *name)
int(* CreateTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
Definition: SDL_sysrender.h:92
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
SDL_ScaleMode scaleMode
Definition: SDL_sysrender.h:66
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