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