2 Simple DirectMedia Layer
3 Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
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.
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:
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.
21 #include "../../SDL_internal.h"
23 #if SDL_VIDEO_RENDER_D3D11 && !SDL_RENDER_DISABLED
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"
35 #include "SDL_shaders_d3d11.h"
39 #if NTDDI_VERSION > NTDDI_WIN8
43 #include "SDL_render_winrt.h"
45 #if WINAPI_FAMILY == WINAPI_FAMILY_APP
46 #include <windows.ui.xaml.media.dxinterop.h>
47 /* TODO, WinRT, XAML: get the ISwapChainBackgroundPanelNative from something other than a global var */
48 extern ISwapChainBackgroundPanelNative * WINRT_GlobalSwapChainBackgroundPanelNative;
49 #endif /* WINAPI_FAMILY == WINAPI_FAMILY_APP */
51 #endif /* __WINRT__ */
54 #define SDL_COMPOSE_ERROR(str) SDL_STRINGIFY_ARG(__FUNCTION__) ", " str
56 #define SAFE_RELEASE(X) if ((X)) { IUnknown_Release(SDL_static_cast(IUnknown*, X)); X = NULL; }
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. */
62 /* Vertex shader, common values */
66 Float4X4 projectionAndView;
67 } VertexShaderConstants;
75 } VertexPositionColor;
77 /* Per-texture data */
80 ID3D11Texture2D *mainTexture;
81 ID3D11ShaderResourceView *mainTextureResourceView;
82 ID3D11RenderTargetView *mainTextureRenderTargetView;
83 ID3D11Texture2D *stagingTexture;
84 int lockedTexturePositionX;
85 int lockedTexturePositionY;
86 D3D11_FILTER scaleMode;
88 /* YV12 texture support */
90 ID3D11Texture2D *mainTextureU;
91 ID3D11ShaderResourceView *mainTextureResourceViewU;
92 ID3D11Texture2D *mainTextureV;
93 ID3D11ShaderResourceView *mainTextureResourceViewV;
95 /* NV12 texture support */
97 ID3D11Texture2D *mainTextureNV;
98 ID3D11ShaderResourceView *mainTextureResourceViewNV;
102 SDL_Rect locked_rect;
105 /* Blend mode data */
108 SDL_BlendMode blendMode;
109 ID3D11BlendState *blendState;
112 /* Private renderer data */
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];
131 D3D11_BlendMode *blendModes;
132 ID3D11SamplerState *nearestPixelSampler;
133 ID3D11SamplerState *linearSampler;
134 D3D_FEATURE_LEVEL featureLevel;
137 ID3D11RasterizerState *mainRasterizer;
138 ID3D11RasterizerState *clippedRasterizer;
140 /* Vertex buffer constants */
141 VertexShaderConstants vertexShaderConstantsData;
142 ID3D11Buffer *vertexShaderConstants;
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;
159 int currentVertexBuffer;
163 /* Define D3D GUIDs here so we don't have to include uuid.lib.
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.)
173 #pragma GCC diagnostic push
174 #pragma GCC diagnostic ignored "-Wunused-const-variable"
177 static const GUID SDL_IID_IDXGIFactory2 = { 0x50c83a1c, 0xe072, 0x4c48, { 0x87, 0xb0, 0x36, 0x30, 0xfa, 0x36, 0xa6, 0xd0 } };
178 static const GUID SDL_IID_IDXGIDevice1 = { 0x77db970f, 0x6276, 0x48ba, { 0xba, 0x28, 0x07, 0x01, 0x43, 0xb4, 0x39, 0x2c } };
179 static const GUID SDL_IID_IDXGIDevice3 = { 0x6007896c, 0x3244, 0x4afd, { 0xbf, 0x18, 0xa6, 0xd3, 0xbe, 0xda, 0x50, 0x23 } };
180 static const GUID SDL_IID_ID3D11Texture2D = { 0x6f15aaf2, 0xd208, 0x4e89, { 0x9a, 0xb4, 0x48, 0x95, 0x35, 0xd3, 0x4f, 0x9c } };
181 static const GUID SDL_IID_ID3D11Device1 = { 0xa04bfb29, 0x08ef, 0x43d6, { 0xa4, 0x9c, 0xa9, 0xbd, 0xbd, 0xcb, 0xe6, 0x86 } };
182 static const GUID SDL_IID_ID3D11DeviceContext1 = { 0xbb2c6faa, 0xb5fb, 0x4082, { 0x8e, 0x6b, 0x38, 0x8b, 0x8c, 0xfa, 0x90, 0xe1 } };
183 static const GUID SDL_IID_ID3D11Debug = { 0x79cf2233, 0x7536, 0x4948, { 0x9d, 0x36, 0x1e, 0x46, 0x92, 0xdc, 0x57, 0x60 } };
186 #pragma GCC diagnostic pop
192 D3D11_DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat)
194 switch (dxgiFormat) {
195 case DXGI_FORMAT_B8G8R8A8_UNORM:
196 return SDL_PIXELFORMAT_ARGB8888;
197 case DXGI_FORMAT_B8G8R8X8_UNORM:
198 return SDL_PIXELFORMAT_RGB888;
200 return SDL_PIXELFORMAT_UNKNOWN;
205 SDLPixelFormatToDXGIFormat(Uint32 sdlFormat)
208 case SDL_PIXELFORMAT_ARGB8888:
209 return DXGI_FORMAT_B8G8R8A8_UNORM;
210 case SDL_PIXELFORMAT_RGB888:
211 return DXGI_FORMAT_B8G8R8X8_UNORM;
212 case SDL_PIXELFORMAT_YV12:
213 case SDL_PIXELFORMAT_IYUV:
214 case SDL_PIXELFORMAT_NV12: /* For the Y texture */
215 case SDL_PIXELFORMAT_NV21: /* For the Y texture */
216 return DXGI_FORMAT_R8_UNORM;
218 return DXGI_FORMAT_UNKNOWN;
222 static void D3D11_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
225 D3D11_ReleaseAll(SDL_Renderer * renderer)
227 D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
228 SDL_Texture *texture = NULL;
230 /* Release all textures */
231 for (texture = renderer->textures; texture; texture = texture->next) {
232 D3D11_DestroyTexture(renderer, texture);
235 /* Release/reset everything else */
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]);
250 SAFE_RELEASE(data->vertexShader);
251 for (i = 0; i < SDL_arraysize(data->pixelShaders); ++i) {
252 SAFE_RELEASE(data->pixelShaders[i]);
254 if (data->blendModesCount > 0) {
255 for (i = 0; i < data->blendModesCount; ++i) {
256 SAFE_RELEASE(data->blendModes[i].blendState);
258 SDL_free(data->blendModes);
260 data->blendModesCount = 0;
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);
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;
277 /* Unload the D3D libraries. This should be done last, in order
278 * to prevent IUnknown::Release() calls from crashing.
280 if (data->hD3D11Mod) {
281 SDL_UnloadObject(data->hD3D11Mod);
282 data->hD3D11Mod = NULL;
284 if (data->hDXGIMod) {
285 SDL_UnloadObject(data->hDXGIMod);
286 data->hDXGIMod = NULL;
292 D3D11_DestroyRenderer(SDL_Renderer * renderer)
294 D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
295 D3D11_ReleaseAll(renderer);
302 static D3D11_BLEND GetBlendFunc(SDL_BlendFactor factor)
305 case SDL_BLENDFACTOR_ZERO:
306 return D3D11_BLEND_ZERO;
307 case SDL_BLENDFACTOR_ONE:
308 return D3D11_BLEND_ONE;
309 case SDL_BLENDFACTOR_SRC_COLOR:
310 return D3D11_BLEND_SRC_COLOR;
311 case SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR:
312 return D3D11_BLEND_INV_SRC_COLOR;
313 case SDL_BLENDFACTOR_SRC_ALPHA:
314 return D3D11_BLEND_SRC_ALPHA;
315 case SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA:
316 return D3D11_BLEND_INV_SRC_ALPHA;
317 case SDL_BLENDFACTOR_DST_COLOR:
318 return D3D11_BLEND_DEST_COLOR;
319 case SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR:
320 return D3D11_BLEND_INV_DEST_COLOR;
321 case SDL_BLENDFACTOR_DST_ALPHA:
322 return D3D11_BLEND_DEST_ALPHA;
323 case SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA:
324 return D3D11_BLEND_INV_DEST_ALPHA;
326 return (D3D11_BLEND)0;
330 static D3D11_BLEND_OP GetBlendEquation(SDL_BlendOperation operation)
333 case SDL_BLENDOPERATION_ADD:
334 return D3D11_BLEND_OP_ADD;
335 case SDL_BLENDOPERATION_SUBTRACT:
336 return D3D11_BLEND_OP_SUBTRACT;
337 case SDL_BLENDOPERATION_REV_SUBTRACT:
338 return D3D11_BLEND_OP_REV_SUBTRACT;
339 case SDL_BLENDOPERATION_MINIMUM:
340 return D3D11_BLEND_OP_MIN;
341 case SDL_BLENDOPERATION_MAXIMUM:
342 return D3D11_BLEND_OP_MAX;
344 return (D3D11_BLEND_OP)0;
348 static ID3D11BlendState *
349 D3D11_CreateBlendState(SDL_Renderer * renderer, SDL_BlendMode blendMode)
351 D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
352 SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode);
353 SDL_BlendFactor srcAlphaFactor = SDL_GetBlendModeSrcAlphaFactor(blendMode);
354 SDL_BlendOperation colorOperation = SDL_GetBlendModeColorOperation(blendMode);
355 SDL_BlendFactor dstColorFactor = SDL_GetBlendModeDstColorFactor(blendMode);
356 SDL_BlendFactor dstAlphaFactor = SDL_GetBlendModeDstAlphaFactor(blendMode);
357 SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode);
358 ID3D11BlendState *blendState = NULL;
359 D3D11_BlendMode *blendModes;
360 HRESULT result = S_OK;
362 D3D11_BLEND_DESC 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);
380 blendModes = (D3D11_BlendMode *)SDL_realloc(data->blendModes, (data->blendModesCount + 1) * sizeof(*blendModes));
382 SAFE_RELEASE(blendState);
386 blendModes[data->blendModesCount].blendMode = blendMode;
387 blendModes[data->blendModesCount].blendState = blendState;
388 data->blendModes = blendModes;
389 ++data->blendModesCount;
394 /* Create resources that depend on the device. */
396 D3D11_CreateDeviceResources(SDL_Renderer * renderer)
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;
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.
414 D3D_FEATURE_LEVEL featureLevels[] =
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
425 D3D11_BUFFER_DESC constantBufferDesc;
426 D3D11_SAMPLER_DESC samplerDesc;
427 D3D11_RASTERIZER_DESC rasterDesc;
430 CreateDXGIFactoryFunc = CreateDXGIFactory1;
431 D3D11CreateDeviceFunc = D3D11CreateDevice;
433 data->hDXGIMod = SDL_LoadObject("dxgi.dll");
434 if (!data->hDXGIMod) {
439 CreateDXGIFactoryFunc = (PFN_CREATE_DXGI_FACTORY)SDL_LoadFunction(data->hDXGIMod, "CreateDXGIFactory");
440 if (!CreateDXGIFactoryFunc) {
445 data->hD3D11Mod = SDL_LoadObject("d3d11.dll");
446 if (!data->hD3D11Mod) {
451 D3D11CreateDeviceFunc = (PFN_D3D11_CREATE_DEVICE)SDL_LoadFunction(data->hD3D11Mod, "D3D11CreateDevice");
452 if (!D3D11CreateDeviceFunc) {
456 #endif /* __WINRT__ */
458 result = CreateDXGIFactoryFunc(&SDL_IID_IDXGIFactory2, (void **)&data->dxgiFactory);
459 if (FAILED(result)) {
460 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("CreateDXGIFactory"), result);
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);
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.
474 creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
476 /* Make sure Direct3D's debugging feature gets used, if the app requests it. */
477 if (SDL_GetHintBoolean(SDL_HINT_RENDER_DIRECT3D11_DEBUG, SDL_FALSE)) {
478 creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
481 /* Create the Direct3D 11 API device object and a corresponding context. */
482 result = D3D11CreateDeviceFunc(
484 D3D_DRIVER_TYPE_UNKNOWN,
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. */
494 if (FAILED(result)) {
495 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("D3D11CreateDevice"), result);
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);
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);
511 result = ID3D11Device_QueryInterface(d3dDevice, &SDL_IID_IDXGIDevice1, (void **)&dxgiDevice);
512 if (FAILED(result)) {
513 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device to IDXGIDevice1"), result);
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.
520 result = IDXGIDevice1_SetMaximumFrameLatency(dxgiDevice, 1);
521 if (FAILED(result)) {
522 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGIDevice1::SetMaximumFrameLatency"), result);
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
530 switch (data->featureLevel) {
531 case D3D_FEATURE_LEVEL_11_1:
532 case D3D_FEATURE_LEVEL_11_0:
533 renderer->info.max_texture_width = renderer->info.max_texture_height = 16384;
536 case D3D_FEATURE_LEVEL_10_1:
537 case D3D_FEATURE_LEVEL_10_0:
538 renderer->info.max_texture_width = renderer->info.max_texture_height = 8192;
541 case D3D_FEATURE_LEVEL_9_3:
542 renderer->info.max_texture_width = renderer->info.max_texture_height = 4096;
545 case D3D_FEATURE_LEVEL_9_2:
546 case D3D_FEATURE_LEVEL_9_1:
547 renderer->info.max_texture_width = renderer->info.max_texture_height = 2048;
551 SDL_SetError("%s, Unexpected feature level: %d", __FUNCTION__, data->featureLevel);
556 if (D3D11_CreateVertexShader(data->d3dDevice, &data->vertexShader, &data->inputLayout) < 0) {
560 for (i = 0; i < SDL_arraysize(data->pixelShaders); ++i) {
561 if (D3D11_CreatePixelShader(data->d3dDevice, (D3D11_Shader)i, &data->pixelShaders[i]) < 0) {
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,
574 &data->vertexShaderConstants
576 if (FAILED(result)) {
577 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateBuffer [vertex shader constants]"), result);
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,
594 &data->nearestPixelSampler
596 if (FAILED(result)) {
597 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateSamplerState [nearest-pixel filter]"), result);
601 samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
602 result = ID3D11Device_CreateSamplerState(data->d3dDevice,
606 if (FAILED(result)) {
607 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateSamplerState [linear filter]"), result);
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);
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);
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_CreateBlendState(renderer, SDL_BLENDMODE_MUL)) {
641 /* D3D11_CreateBlendMode will set the SDL error, if it fails */
645 /* Setup render state that doesn't change */
646 ID3D11DeviceContext_IASetInputLayout(data->d3dContext, data->inputLayout);
647 ID3D11DeviceContext_VSSetShader(data->d3dContext, data->vertexShader, NULL, 0);
648 ID3D11DeviceContext_VSSetConstantBuffers(data->d3dContext, 0, 1, &data->vertexShaderConstants);
651 SAFE_RELEASE(d3dDevice);
652 SAFE_RELEASE(d3dContext);
653 SAFE_RELEASE(dxgiDevice);
659 static DXGI_MODE_ROTATION
660 D3D11_GetCurrentRotation()
663 return DXGI_MODE_ROTATION_IDENTITY;
666 #endif /* __WIN32__ */
669 D3D11_IsDisplayRotated90Degrees(DXGI_MODE_ROTATION rotation)
672 case DXGI_MODE_ROTATION_ROTATE90:
673 case DXGI_MODE_ROTATION_ROTATE270:
681 D3D11_GetRotationForCurrentRenderTarget(SDL_Renderer * renderer)
683 D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata;
684 if (data->currentOffscreenRenderTargetView) {
685 return DXGI_MODE_ROTATION_IDENTITY;
687 return data->rotation;
692 D3D11_GetViewportAlignedD3DRect(SDL_Renderer * renderer, const SDL_Rect * sdlRect, D3D11_RECT * outRect, BOOL includeViewportOffset)
694 const int rotation = D3D11_GetRotationForCurrentRenderTarget(renderer);
696 case DXGI_MODE_ROTATION_IDENTITY:
697 outRect->left = sdlRect->x;
698 outRect->right = sdlRect->x + sdlRect->w;
699 outRect->top = sdlRect->y;
700 outRect->bottom = sdlRect->y + sdlRect->h;
701 if (includeViewportOffset) {
702 outRect->left += renderer->viewport.x;
703 outRect->right += renderer->viewport.x;
704 outRect->top += renderer->viewport.y;
705 outRect->bottom += renderer->viewport.y;
708 case DXGI_MODE_ROTATION_ROTATE270:
709 outRect->left = sdlRect->y;
710 outRect->right = sdlRect->y + sdlRect->h;
711 outRect->top = renderer->viewport.w - sdlRect->x - sdlRect->w;
712 outRect->bottom = renderer->viewport.w - sdlRect->x;
714 case DXGI_MODE_ROTATION_ROTATE180:
715 outRect->left = renderer->viewport.w - sdlRect->x - sdlRect->w;
716 outRect->right = renderer->viewport.w - sdlRect->x;
717 outRect->top = renderer->viewport.h - sdlRect->y - sdlRect->h;
718 outRect->bottom = renderer->viewport.h - sdlRect->y;
720 case DXGI_MODE_ROTATION_ROTATE90:
721 outRect->left = renderer->viewport.h - sdlRect->y - sdlRect->h;
722 outRect->right = renderer->viewport.h - sdlRect->y;
723 outRect->top = sdlRect->x;
724 outRect->bottom = sdlRect->x + sdlRect->h;
727 return SDL_SetError("The physical display is in an unknown or unsupported rotation");
733 D3D11_CreateSwapChain(SDL_Renderer * renderer, int w, int h)
735 D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata;
737 IUnknown *coreWindow = D3D11_GetCoreWindowFromSDLRenderer(renderer);
738 const BOOL usingXAML = (coreWindow == NULL);
740 IUnknown *coreWindow = NULL;
741 const BOOL usingXAML = FALSE;
743 HRESULT result = S_OK;
745 /* Create a swap chain using the same adapter as the existing Direct3D device. */
746 DXGI_SWAP_CHAIN_DESC1 swapChainDesc;
747 SDL_zero(swapChainDesc);
748 swapChainDesc.Width = w;
749 swapChainDesc.Height = h;
750 swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; /* This is the most common swap chain format. */
751 swapChainDesc.Stereo = FALSE;
752 swapChainDesc.SampleDesc.Count = 1; /* Don't use multi-sampling. */
753 swapChainDesc.SampleDesc.Quality = 0;
754 swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
755 swapChainDesc.BufferCount = 2; /* Use double-buffering to minimize latency. */
756 #if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
757 swapChainDesc.Scaling = DXGI_SCALING_STRETCH; /* On phone, only stretch and aspect-ratio stretch scaling are allowed. */
758 swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; /* On phone, no swap effects are supported. */
759 /* 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 */
762 swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
764 swapChainDesc.Scaling = DXGI_SCALING_NONE;
766 swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; /* All Windows Store apps must use this SwapEffect. */
768 swapChainDesc.Flags = 0;
771 result = IDXGIFactory2_CreateSwapChainForCoreWindow(data->dxgiFactory,
772 (IUnknown *)data->d3dDevice,
775 NULL, /* Allow on all displays. */
778 if (FAILED(result)) {
779 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGIFactory2::CreateSwapChainForCoreWindow"), result);
782 } else if (usingXAML) {
783 result = IDXGIFactory2_CreateSwapChainForComposition(data->dxgiFactory,
784 (IUnknown *)data->d3dDevice,
788 if (FAILED(result)) {
789 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGIFactory2::CreateSwapChainForComposition"), result);
793 #if WINAPI_FAMILY == WINAPI_FAMILY_APP
794 result = ISwapChainBackgroundPanelNative_SetSwapChain(WINRT_GlobalSwapChainBackgroundPanelNative, (IDXGISwapChain *) data->swapChain);
795 if (FAILED(result)) {
796 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ISwapChainBackgroundPanelNative::SetSwapChain"), result);
800 SDL_SetError(SDL_COMPOSE_ERROR("XAML support is not yet available for Windows Phone"));
806 SDL_SysWMinfo windowinfo;
807 SDL_VERSION(&windowinfo.version);
808 SDL_GetWindowWMInfo(renderer->window, &windowinfo);
810 result = IDXGIFactory2_CreateSwapChainForHwnd(data->dxgiFactory,
811 (IUnknown *)data->d3dDevice,
812 windowinfo.info.win.window,
815 NULL, /* Allow on all displays. */
818 if (FAILED(result)) {
819 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGIFactory2::CreateSwapChainForHwnd"), result);
823 IDXGIFactory_MakeWindowAssociation(data->dxgiFactory, windowinfo.info.win.window, DXGI_MWA_NO_WINDOW_CHANGES);
825 SDL_SetError(__FUNCTION__", Unable to find something to attach a swap chain to");
827 #endif /* ifdef __WIN32__ / else */
829 data->swapEffect = swapChainDesc.SwapEffect;
832 SAFE_RELEASE(coreWindow);
837 D3D11_ReleaseMainRenderTargetView(SDL_Renderer * renderer)
839 D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata;
840 ID3D11DeviceContext_OMSetRenderTargets(data->d3dContext, 0, NULL, NULL);
841 SAFE_RELEASE(data->mainRenderTargetView);
844 static HRESULT D3D11_UpdateForWindowSizeChange(SDL_Renderer * renderer);
848 D3D11_HandleDeviceLost(SDL_Renderer * renderer)
850 HRESULT result = S_OK;
852 D3D11_ReleaseAll(renderer);
854 result = D3D11_CreateDeviceResources(renderer);
855 if (FAILED(result)) {
856 /* D3D11_CreateDeviceResources will set the SDL error */
860 result = D3D11_UpdateForWindowSizeChange(renderer);
861 if (FAILED(result)) {
862 /* D3D11_UpdateForWindowSizeChange will set the SDL error */
866 /* Let the application know that the device has been reset */
869 event.type = SDL_RENDER_DEVICE_RESET;
870 SDL_PushEvent(&event);
876 /* Initialize all resources that change when the window's size changes. */
878 D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
880 D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata;
881 ID3D11Texture2D *backBuffer = NULL;
882 HRESULT result = S_OK;
885 /* Release the previous render target view */
886 D3D11_ReleaseMainRenderTargetView(renderer);
888 /* The width and height of the swap chain must be based on the display's
891 SDL_GetWindowSize(renderer->window, &w, &h);
892 data->rotation = D3D11_GetCurrentRotation();
893 /* SDL_Log("%s: windowSize={%d,%d}, orientation=%d\n", __FUNCTION__, w, h, (int)data->rotation); */
894 if (D3D11_IsDisplayRotated90Degrees(data->rotation)) {
900 if (data->swapChain) {
901 /* IDXGISwapChain::ResizeBuffers is not available on Windows Phone 8. */
902 #if !defined(__WINRT__) || (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP)
903 /* If the swap chain already exists, resize it. */
904 result = IDXGISwapChain_ResizeBuffers(data->swapChain,
910 if (result == DXGI_ERROR_DEVICE_REMOVED) {
911 /* If the device was removed for any reason, a new device and swap chain will need to be created. */
912 D3D11_HandleDeviceLost(renderer);
914 /* Everything is set up now. Do not continue execution of this method. HandleDeviceLost will reenter this method
915 * and correctly set up the new device.
918 } else if (FAILED(result)) {
919 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain::ResizeBuffers"), result);
924 result = D3D11_CreateSwapChain(renderer, w, h);
925 if (FAILED(result)) {
930 #if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
931 /* Set the proper rotation for the swap chain.
933 * To note, the call for this, IDXGISwapChain1::SetRotation, is not necessary
934 * on Windows Phone 8.0, nor is it supported there.
936 * IDXGISwapChain1::SetRotation does seem to be available on Windows Phone 8.1,
937 * however I've yet to find a way to make it work. It might have something to
938 * do with IDXGISwapChain::ResizeBuffers appearing to not being available on
939 * Windows Phone 8.1 (it wasn't on Windows Phone 8.0), but I'm not 100% sure of this.
940 * The call doesn't appear to be entirely necessary though, and is a performance-related
941 * call, at least according to the following page on MSDN:
942 * http://code.msdn.microsoft.com/windowsapps/DXGI-swap-chain-rotation-21d13d71
945 * TODO, WinRT: reexamine the docs for IDXGISwapChain1::SetRotation, see if might be available, usable, and prudent-to-call on WinPhone 8.1
947 if (data->swapEffect == DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL) {
948 result = IDXGISwapChain1_SetRotation(data->swapChain, data->rotation);
949 if (FAILED(result)) {
950 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain1::SetRotation"), result);
956 result = IDXGISwapChain_GetBuffer(data->swapChain,
958 &SDL_IID_ID3D11Texture2D,
961 if (FAILED(result)) {
962 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain::GetBuffer [back-buffer]"), result);
966 /* Create a render target view of the swap chain back buffer. */
967 result = ID3D11Device_CreateRenderTargetView(data->d3dDevice,
968 (ID3D11Resource *)backBuffer,
970 &data->mainRenderTargetView
972 if (FAILED(result)) {
973 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device::CreateRenderTargetView"), result);
977 data->viewportDirty = SDL_TRUE;
980 SAFE_RELEASE(backBuffer);
984 /* This method is called when the window's size changes. */
986 D3D11_UpdateForWindowSizeChange(SDL_Renderer * renderer)
988 return D3D11_CreateWindowSizeDependentResources(renderer);
992 D3D11_Trim(SDL_Renderer * renderer)
995 #if NTDDI_VERSION > NTDDI_WIN8
996 D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata;
997 HRESULT result = S_OK;
998 IDXGIDevice3 *dxgiDevice = NULL;
1000 result = ID3D11Device_QueryInterface(data->d3dDevice, &SDL_IID_IDXGIDevice3, &dxgiDevice);
1001 if (FAILED(result)) {
1002 //WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device to IDXGIDevice3", result);
1006 IDXGIDevice3_Trim(dxgiDevice);
1007 SAFE_RELEASE(dxgiDevice);
1013 D3D11_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
1015 if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) {
1016 D3D11_UpdateForWindowSizeChange(renderer);
1021 D3D11_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
1023 SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode);
1024 SDL_BlendFactor srcAlphaFactor = SDL_GetBlendModeSrcAlphaFactor(blendMode);
1025 SDL_BlendOperation colorOperation = SDL_GetBlendModeColorOperation(blendMode);
1026 SDL_BlendFactor dstColorFactor = SDL_GetBlendModeDstColorFactor(blendMode);
1027 SDL_BlendFactor dstAlphaFactor = SDL_GetBlendModeDstAlphaFactor(blendMode);
1028 SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode);
1030 if (!GetBlendFunc(srcColorFactor) || !GetBlendFunc(srcAlphaFactor) ||
1031 !GetBlendEquation(colorOperation) ||
1032 !GetBlendFunc(dstColorFactor) || !GetBlendFunc(dstAlphaFactor) ||
1033 !GetBlendEquation(alphaOperation)) {
1040 D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
1042 D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
1043 D3D11_TextureData *textureData;
1045 DXGI_FORMAT textureFormat = SDLPixelFormatToDXGIFormat(texture->format);
1046 D3D11_TEXTURE2D_DESC textureDesc;
1047 D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
1049 if (textureFormat == DXGI_FORMAT_UNKNOWN) {
1050 return SDL_SetError("%s, An unsupported SDL pixel format (0x%x) was specified",
1051 __FUNCTION__, texture->format);
1054 textureData = (D3D11_TextureData*) SDL_calloc(1, sizeof(*textureData));
1059 textureData->scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ? D3D11_FILTER_MIN_MAG_MIP_POINT : D3D11_FILTER_MIN_MAG_MIP_LINEAR;
1061 texture->driverdata = textureData;
1063 SDL_zero(textureDesc);
1064 textureDesc.Width = texture->w;
1065 textureDesc.Height = texture->h;
1066 textureDesc.MipLevels = 1;
1067 textureDesc.ArraySize = 1;
1068 textureDesc.Format = textureFormat;
1069 textureDesc.SampleDesc.Count = 1;
1070 textureDesc.SampleDesc.Quality = 0;
1071 textureDesc.MiscFlags = 0;
1073 if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
1074 textureDesc.Usage = D3D11_USAGE_DYNAMIC;
1075 textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
1077 textureDesc.Usage = D3D11_USAGE_DEFAULT;
1078 textureDesc.CPUAccessFlags = 0;
1081 if (texture->access == SDL_TEXTUREACCESS_TARGET) {
1082 textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
1084 textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
1087 result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
1090 &textureData->mainTexture
1092 if (FAILED(result)) {
1093 D3D11_DestroyTexture(renderer, texture);
1094 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
1098 if (texture->format == SDL_PIXELFORMAT_YV12 ||
1099 texture->format == SDL_PIXELFORMAT_IYUV) {
1100 textureData->yuv = SDL_TRUE;
1102 textureDesc.Width = (textureDesc.Width + 1) / 2;
1103 textureDesc.Height = (textureDesc.Height + 1) / 2;
1105 result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
1108 &textureData->mainTextureU
1110 if (FAILED(result)) {
1111 D3D11_DestroyTexture(renderer, texture);
1112 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
1116 result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
1119 &textureData->mainTextureV
1121 if (FAILED(result)) {
1122 D3D11_DestroyTexture(renderer, texture);
1123 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
1128 if (texture->format == SDL_PIXELFORMAT_NV12 ||
1129 texture->format == SDL_PIXELFORMAT_NV21) {
1130 D3D11_TEXTURE2D_DESC nvTextureDesc = textureDesc;
1132 textureData->nv12 = SDL_TRUE;
1134 nvTextureDesc.Format = DXGI_FORMAT_R8G8_UNORM;
1135 nvTextureDesc.Width = (textureDesc.Width + 1) / 2;
1136 nvTextureDesc.Height = (textureDesc.Height + 1) / 2;
1138 result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
1141 &textureData->mainTextureNV
1143 if (FAILED(result)) {
1144 D3D11_DestroyTexture(renderer, texture);
1145 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
1150 resourceViewDesc.Format = textureDesc.Format;
1151 resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
1152 resourceViewDesc.Texture2D.MostDetailedMip = 0;
1153 resourceViewDesc.Texture2D.MipLevels = textureDesc.MipLevels;
1154 result = ID3D11Device_CreateShaderResourceView(rendererData->d3dDevice,
1155 (ID3D11Resource *)textureData->mainTexture,
1157 &textureData->mainTextureResourceView
1159 if (FAILED(result)) {
1160 D3D11_DestroyTexture(renderer, texture);
1161 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result);
1165 if (textureData->yuv) {
1166 result = ID3D11Device_CreateShaderResourceView(rendererData->d3dDevice,
1167 (ID3D11Resource *)textureData->mainTextureU,
1169 &textureData->mainTextureResourceViewU
1171 if (FAILED(result)) {
1172 D3D11_DestroyTexture(renderer, texture);
1173 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result);
1176 result = ID3D11Device_CreateShaderResourceView(rendererData->d3dDevice,
1177 (ID3D11Resource *)textureData->mainTextureV,
1179 &textureData->mainTextureResourceViewV
1181 if (FAILED(result)) {
1182 D3D11_DestroyTexture(renderer, texture);
1183 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result);
1188 if (textureData->nv12) {
1189 D3D11_SHADER_RESOURCE_VIEW_DESC nvResourceViewDesc = resourceViewDesc;
1191 nvResourceViewDesc.Format = DXGI_FORMAT_R8G8_UNORM;
1193 result = ID3D11Device_CreateShaderResourceView(rendererData->d3dDevice,
1194 (ID3D11Resource *)textureData->mainTextureNV,
1195 &nvResourceViewDesc,
1196 &textureData->mainTextureResourceViewNV
1198 if (FAILED(result)) {
1199 D3D11_DestroyTexture(renderer, texture);
1200 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result);
1205 if (texture->access & SDL_TEXTUREACCESS_TARGET) {
1206 D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
1207 renderTargetViewDesc.Format = textureDesc.Format;
1208 renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
1209 renderTargetViewDesc.Texture2D.MipSlice = 0;
1211 result = ID3D11Device_CreateRenderTargetView(rendererData->d3dDevice,
1212 (ID3D11Resource *)textureData->mainTexture,
1213 &renderTargetViewDesc,
1214 &textureData->mainTextureRenderTargetView);
1215 if (FAILED(result)) {
1216 D3D11_DestroyTexture(renderer, texture);
1217 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateRenderTargetView"), result);
1226 D3D11_DestroyTexture(SDL_Renderer * renderer,
1227 SDL_Texture * texture)
1229 D3D11_TextureData *data = (D3D11_TextureData *)texture->driverdata;
1235 SAFE_RELEASE(data->mainTexture);
1236 SAFE_RELEASE(data->mainTextureResourceView);
1237 SAFE_RELEASE(data->mainTextureRenderTargetView);
1238 SAFE_RELEASE(data->stagingTexture);
1239 SAFE_RELEASE(data->mainTextureU);
1240 SAFE_RELEASE(data->mainTextureResourceViewU);
1241 SAFE_RELEASE(data->mainTextureV);
1242 SAFE_RELEASE(data->mainTextureResourceViewV);
1243 SDL_free(data->pixels);
1245 texture->driverdata = NULL;
1249 D3D11_UpdateTextureInternal(D3D11_RenderData *rendererData, ID3D11Texture2D *texture, int bpp, int x, int y, int w, int h, const void *pixels, int pitch)
1251 ID3D11Texture2D *stagingTexture;
1257 D3D11_TEXTURE2D_DESC stagingTextureDesc;
1258 D3D11_MAPPED_SUBRESOURCE textureMemory;
1260 /* Create a 'staging' texture, which will be used to write to a portion of the main texture. */
1261 ID3D11Texture2D_GetDesc(texture, &stagingTextureDesc);
1262 stagingTextureDesc.Width = w;
1263 stagingTextureDesc.Height = h;
1264 stagingTextureDesc.BindFlags = 0;
1265 stagingTextureDesc.MiscFlags = 0;
1266 stagingTextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
1267 stagingTextureDesc.Usage = D3D11_USAGE_STAGING;
1268 result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
1269 &stagingTextureDesc,
1272 if (FAILED(result)) {
1273 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D [create staging texture]"), result);
1277 /* Get a write-only pointer to data in the staging texture: */
1278 result = ID3D11DeviceContext_Map(rendererData->d3dContext,
1279 (ID3D11Resource *)stagingTexture,
1285 if (FAILED(result)) {
1286 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [map staging texture]"), result);
1287 SAFE_RELEASE(stagingTexture);
1291 src = (const Uint8 *)pixels;
1292 dst = textureMemory.pData;
1294 if (length == pitch && length == textureMemory.RowPitch) {
1295 SDL_memcpy(dst, src, length*h);
1297 if (length > (UINT)pitch) {
1300 if (length > textureMemory.RowPitch) {
1301 length = textureMemory.RowPitch;
1303 for (row = 0; row < h; ++row) {
1304 SDL_memcpy(dst, src, length);
1306 dst += textureMemory.RowPitch;
1310 /* Commit the pixel buffer's changes back to the staging texture: */
1311 ID3D11DeviceContext_Unmap(rendererData->d3dContext,
1312 (ID3D11Resource *)stagingTexture,
1315 /* Copy the staging texture's contents back to the texture: */
1316 ID3D11DeviceContext_CopySubresourceRegion(rendererData->d3dContext,
1317 (ID3D11Resource *)texture,
1322 (ID3D11Resource *)stagingTexture,
1326 SAFE_RELEASE(stagingTexture);
1332 D3D11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
1333 const SDL_Rect * rect, const void * srcPixels,
1336 D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata;
1337 D3D11_TextureData *textureData = (D3D11_TextureData *)texture->driverdata;
1340 SDL_SetError("Texture is not currently available");
1344 if (D3D11_UpdateTextureInternal(rendererData, textureData->mainTexture, SDL_BYTESPERPIXEL(texture->format), rect->x, rect->y, rect->w, rect->h, srcPixels, srcPitch) < 0) {
1348 if (textureData->yuv) {
1349 /* Skip to the correct offset into the next texture */
1350 srcPixels = (const void*)((const Uint8*)srcPixels + rect->h * srcPitch);
1352 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) {
1356 /* Skip to the correct offset into the next texture */
1357 srcPixels = (const void*)((const Uint8*)srcPixels + ((rect->h + 1) / 2) * ((srcPitch + 1) / 2));
1358 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) {
1363 if (textureData->nv12) {
1364 /* Skip to the correct offset into the next texture */
1365 srcPixels = (const void*)((const Uint8*)srcPixels + rect->h * srcPitch);
1367 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) {
1375 D3D11_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
1376 const SDL_Rect * rect,
1377 const Uint8 *Yplane, int Ypitch,
1378 const Uint8 *Uplane, int Upitch,
1379 const Uint8 *Vplane, int Vpitch)
1381 D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata;
1382 D3D11_TextureData *textureData = (D3D11_TextureData *)texture->driverdata;
1385 SDL_SetError("Texture is not currently available");
1389 if (D3D11_UpdateTextureInternal(rendererData, textureData->mainTexture, SDL_BYTESPERPIXEL(texture->format), rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch) < 0) {
1392 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) {
1395 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) {
1402 D3D11_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
1403 const SDL_Rect * rect, void **pixels, int *pitch)
1405 D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
1406 D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
1407 HRESULT result = S_OK;
1408 D3D11_TEXTURE2D_DESC stagingTextureDesc;
1409 D3D11_MAPPED_SUBRESOURCE textureMemory;
1412 SDL_SetError("Texture is not currently available");
1416 if (textureData->yuv || textureData->nv12) {
1417 /* It's more efficient to upload directly... */
1418 if (!textureData->pixels) {
1419 textureData->pitch = texture->w;
1420 textureData->pixels = (Uint8 *)SDL_malloc((texture->h * textureData->pitch * 3) / 2);
1421 if (!textureData->pixels) {
1422 return SDL_OutOfMemory();
1425 textureData->locked_rect = *rect;
1427 (void *)((Uint8 *)textureData->pixels + rect->y * textureData->pitch +
1428 rect->x * SDL_BYTESPERPIXEL(texture->format));
1429 *pitch = textureData->pitch;
1433 if (textureData->stagingTexture) {
1434 return SDL_SetError("texture is already locked");
1437 /* Create a 'staging' texture, which will be used to write to a portion
1438 * of the main texture. This is necessary, as Direct3D 11.1 does not
1439 * have the ability to write a CPU-bound pixel buffer to a rectangular
1440 * subrect of a texture. Direct3D 11.1 can, however, write a pixel
1441 * buffer to an entire texture, hence the use of a staging texture.
1443 * TODO, WinRT: consider avoiding the use of a staging texture in D3D11_LockTexture if/when the entire texture is being updated
1445 ID3D11Texture2D_GetDesc(textureData->mainTexture, &stagingTextureDesc);
1446 stagingTextureDesc.Width = rect->w;
1447 stagingTextureDesc.Height = rect->h;
1448 stagingTextureDesc.BindFlags = 0;
1449 stagingTextureDesc.MiscFlags = 0;
1450 stagingTextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
1451 stagingTextureDesc.Usage = D3D11_USAGE_STAGING;
1452 result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
1453 &stagingTextureDesc,
1455 &textureData->stagingTexture);
1456 if (FAILED(result)) {
1457 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D [create staging texture]"), result);
1461 /* Get a write-only pointer to data in the staging texture: */
1462 result = ID3D11DeviceContext_Map(rendererData->d3dContext,
1463 (ID3D11Resource *)textureData->stagingTexture,
1469 if (FAILED(result)) {
1470 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [map staging texture]"), result);
1471 SAFE_RELEASE(textureData->stagingTexture);
1475 /* Make note of where the staging texture will be written to
1476 * (on a call to SDL_UnlockTexture):
1478 textureData->lockedTexturePositionX = rect->x;
1479 textureData->lockedTexturePositionY = rect->y;
1481 /* Make sure the caller has information on the texture's pixel buffer,
1484 *pixels = textureMemory.pData;
1485 *pitch = textureMemory.RowPitch;
1490 D3D11_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
1492 D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
1493 D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
1499 if (textureData->yuv || textureData->nv12) {
1500 const SDL_Rect *rect = &textureData->locked_rect;
1502 (void *) ((Uint8 *) textureData->pixels + rect->y * textureData->pitch +
1503 rect->x * SDL_BYTESPERPIXEL(texture->format));
1504 D3D11_UpdateTexture(renderer, texture, rect, pixels, textureData->pitch);
1508 /* Commit the pixel buffer's changes back to the staging texture: */
1509 ID3D11DeviceContext_Unmap(rendererData->d3dContext,
1510 (ID3D11Resource *)textureData->stagingTexture,
1513 /* Copy the staging texture's contents back to the main texture: */
1514 ID3D11DeviceContext_CopySubresourceRegion(rendererData->d3dContext,
1515 (ID3D11Resource *)textureData->mainTexture,
1517 textureData->lockedTexturePositionX,
1518 textureData->lockedTexturePositionY,
1520 (ID3D11Resource *)textureData->stagingTexture,
1524 SAFE_RELEASE(textureData->stagingTexture);
1528 D3D11_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture, SDL_ScaleMode scaleMode)
1530 D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
1536 textureData->scaleMode = (scaleMode == SDL_ScaleModeNearest) ? D3D11_FILTER_MIN_MAG_MIP_POINT : D3D11_FILTER_MIN_MAG_MIP_LINEAR;
1540 D3D11_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
1542 D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
1543 D3D11_TextureData *textureData = NULL;
1545 if (texture == NULL) {
1546 rendererData->currentOffscreenRenderTargetView = NULL;
1550 textureData = (D3D11_TextureData *) texture->driverdata;
1552 if (!textureData->mainTextureRenderTargetView) {
1553 return SDL_SetError("specified texture is not a render target");
1556 rendererData->currentOffscreenRenderTargetView = textureData->mainTextureRenderTargetView;
1562 D3D11_QueueSetViewport(SDL_Renderer * renderer, SDL_RenderCommand *cmd)
1564 return 0; /* nothing to do in this backend. */
1568 D3D11_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
1570 VertexPositionColor *verts = (VertexPositionColor *) SDL_AllocateRenderVertices(renderer, count * sizeof (VertexPositionColor), 0, &cmd->data.draw.first);
1571 const float r = (float)(cmd->data.draw.r / 255.0f);
1572 const float g = (float)(cmd->data.draw.g / 255.0f);
1573 const float b = (float)(cmd->data.draw.b / 255.0f);
1574 const float a = (float)(cmd->data.draw.a / 255.0f);
1581 cmd->data.draw.count = count;
1583 for (i = 0; i < count; i++) {
1584 verts->pos.x = points[i].x + 0.5f;
1585 verts->pos.y = points[i].y + 0.5f;
1586 verts->pos.z = 0.0f;
1587 verts->tex.x = 0.0f;
1588 verts->tex.y = 0.0f;
1600 D3D11_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
1602 VertexPositionColor *verts = (VertexPositionColor *) SDL_AllocateRenderVertices(renderer, count * 4 * sizeof (VertexPositionColor), 0, &cmd->data.draw.first);
1603 const float r = (float)(cmd->data.draw.r / 255.0f);
1604 const float g = (float)(cmd->data.draw.g / 255.0f);
1605 const float b = (float)(cmd->data.draw.b / 255.0f);
1606 const float a = (float)(cmd->data.draw.a / 255.0f);
1613 cmd->data.draw.count = count;
1615 for (i = 0; i < count; i++) {
1616 verts->pos.x = rects[i].x;
1617 verts->pos.y = rects[i].y;
1618 verts->pos.z = 0.0f;
1619 verts->tex.x = 0.0f;
1620 verts->tex.y = 0.0f;
1627 verts->pos.x = rects[i].x;
1628 verts->pos.y = rects[i].y + rects[i].h;
1629 verts->pos.z = 0.0f;
1630 verts->tex.x = 0.0f;
1631 verts->tex.y = 0.0f;
1638 verts->pos.x = rects[i].x + rects[i].w;
1639 verts->pos.y = rects[i].y;
1640 verts->pos.z = 0.0f;
1641 verts->tex.x = 0.0f;
1642 verts->tex.y = 0.0f;
1649 verts->pos.x = rects[i].x + rects[i].w;
1650 verts->pos.y = rects[i].y + rects[i].h;
1651 verts->pos.z = 0.0f;
1652 verts->tex.x = 0.0f;
1653 verts->tex.y = 0.0f;
1665 D3D11_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
1666 const SDL_Rect * srcrect, const SDL_FRect * dstrect)
1668 VertexPositionColor *verts = (VertexPositionColor *) SDL_AllocateRenderVertices(renderer, 4 * sizeof (VertexPositionColor), 0, &cmd->data.draw.first);
1669 const float r = (float)(cmd->data.draw.r / 255.0f);
1670 const float g = (float)(cmd->data.draw.g / 255.0f);
1671 const float b = (float)(cmd->data.draw.b / 255.0f);
1672 const float a = (float)(cmd->data.draw.a / 255.0f);
1673 const float minu = (float) srcrect->x / texture->w;
1674 const float maxu = (float) (srcrect->x + srcrect->w) / texture->w;
1675 const float minv = (float) srcrect->y / texture->h;
1676 const float maxv = (float) (srcrect->y + srcrect->h) / texture->h;
1682 cmd->data.draw.count = 1;
1684 verts->pos.x = dstrect->x;
1685 verts->pos.y = dstrect->y;
1686 verts->pos.z = 0.0f;
1687 verts->tex.x = minu;
1688 verts->tex.y = minv;
1695 verts->pos.x = dstrect->x;
1696 verts->pos.y = dstrect->y + dstrect->h;
1697 verts->pos.z = 0.0f;
1698 verts->tex.x = minu;
1699 verts->tex.y = maxv;
1706 verts->pos.x = dstrect->x + dstrect->w;
1707 verts->pos.y = dstrect->y;
1708 verts->pos.z = 0.0f;
1709 verts->tex.x = maxu;
1710 verts->tex.y = minv;
1717 verts->pos.x = dstrect->x + dstrect->w;
1718 verts->pos.y = dstrect->y + dstrect->h;
1719 verts->pos.z = 0.0f;
1720 verts->tex.x = maxu;
1721 verts->tex.y = maxv;
1732 D3D11_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
1733 const SDL_Rect * srcrect, const SDL_FRect * dstrect,
1734 const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
1736 VertexPositionColor *verts = (VertexPositionColor *) SDL_AllocateRenderVertices(renderer, 5 * sizeof (VertexPositionColor), 0, &cmd->data.draw.first);
1737 const float r = (float)(cmd->data.draw.r / 255.0f);
1738 const float g = (float)(cmd->data.draw.g / 255.0f);
1739 const float b = (float)(cmd->data.draw.b / 255.0f);
1740 const float a = (float)(cmd->data.draw.a / 255.0f);
1741 float minx, miny, maxx, maxy;
1742 float minu, maxu, minv, maxv;
1748 cmd->data.draw.count = 1;
1751 maxx = dstrect->w - center->x;
1753 maxy = dstrect->h - center->y;
1755 if (flip & SDL_FLIP_HORIZONTAL) {
1756 minu = (float) (srcrect->x + srcrect->w) / texture->w;
1757 maxu = (float) srcrect->x / texture->w;
1759 minu = (float) srcrect->x / texture->w;
1760 maxu = (float) (srcrect->x + srcrect->w) / texture->w;
1763 if (flip & SDL_FLIP_VERTICAL) {
1764 minv = (float) (srcrect->y + srcrect->h) / texture->h;
1765 maxv = (float) srcrect->y / texture->h;
1767 minv = (float) srcrect->y / texture->h;
1768 maxv = (float) (srcrect->y + srcrect->h) / texture->h;
1773 verts->pos.x = minx;
1774 verts->pos.y = miny;
1775 verts->pos.z = 0.0f;
1780 verts->tex.x = minu;
1781 verts->tex.y = minv;
1784 verts->pos.x = minx;
1785 verts->pos.y = maxy;
1786 verts->pos.z = 0.0f;
1791 verts->tex.x = minu;
1792 verts->tex.y = maxv;
1795 verts->pos.x = maxx;
1796 verts->pos.y = miny;
1797 verts->pos.z = 0.0f;
1802 verts->tex.x = maxu;
1803 verts->tex.y = minv;
1806 verts->pos.x = maxx;
1807 verts->pos.y = maxy;
1808 verts->pos.z = 0.0f;
1813 verts->tex.x = maxu;
1814 verts->tex.y = maxv;
1817 verts->pos.x = dstrect->x + center->x; /* X translation */
1818 verts->pos.y = dstrect->y + center->y; /* Y translation */
1819 verts->pos.z = (float)(M_PI * (float) angle / 180.0f); /* rotation */
1824 verts->tex.x = 0.0f;
1825 verts->tex.y = 0.0f;
1833 D3D11_UpdateVertexBuffer(SDL_Renderer *renderer,
1834 const void * vertexData, size_t dataSizeInBytes)
1836 D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
1837 HRESULT result = S_OK;
1838 const int vbidx = rendererData->currentVertexBuffer;
1839 const UINT stride = sizeof(VertexPositionColor);
1840 const UINT offset = 0;
1842 if (dataSizeInBytes == 0) {
1843 return 0; /* nothing to do. */
1846 if (rendererData->vertexBuffers[vbidx] && rendererData->vertexBufferSizes[vbidx] >= dataSizeInBytes) {
1847 D3D11_MAPPED_SUBRESOURCE mappedResource;
1848 result = ID3D11DeviceContext_Map(rendererData->d3dContext,
1849 (ID3D11Resource *)rendererData->vertexBuffers[vbidx],
1851 D3D11_MAP_WRITE_DISCARD,
1855 if (FAILED(result)) {
1856 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [vertex buffer]"), result);
1859 SDL_memcpy(mappedResource.pData, vertexData, dataSizeInBytes);
1860 ID3D11DeviceContext_Unmap(rendererData->d3dContext, (ID3D11Resource *)rendererData->vertexBuffers[vbidx], 0);
1862 D3D11_BUFFER_DESC vertexBufferDesc;
1863 D3D11_SUBRESOURCE_DATA vertexBufferData;
1865 SAFE_RELEASE(rendererData->vertexBuffers[vbidx]);
1867 SDL_zero(vertexBufferDesc);
1868 vertexBufferDesc.ByteWidth = (UINT) dataSizeInBytes;
1869 vertexBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
1870 vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
1871 vertexBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
1873 SDL_zero(vertexBufferData);
1874 vertexBufferData.pSysMem = vertexData;
1875 vertexBufferData.SysMemPitch = 0;
1876 vertexBufferData.SysMemSlicePitch = 0;
1878 result = ID3D11Device_CreateBuffer(rendererData->d3dDevice,
1881 &rendererData->vertexBuffers[vbidx]
1883 if (FAILED(result)) {
1884 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateBuffer [vertex buffer]"), result);
1888 rendererData->vertexBufferSizes[vbidx] = dataSizeInBytes;
1891 ID3D11DeviceContext_IASetVertexBuffers(rendererData->d3dContext,
1894 &rendererData->vertexBuffers[vbidx],
1899 rendererData->currentVertexBuffer++;
1900 if (rendererData->currentVertexBuffer >= SDL_arraysize(rendererData->vertexBuffers)) {
1901 rendererData->currentVertexBuffer = 0;
1908 D3D11_UpdateViewport(SDL_Renderer * renderer)
1910 D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
1911 const SDL_Rect *viewport = &data->currentViewport;
1912 Float4X4 projection;
1914 SDL_FRect orientationAlignedViewport;
1915 BOOL swapDimensions;
1916 D3D11_VIEWPORT d3dviewport;
1917 const int rotation = D3D11_GetRotationForCurrentRenderTarget(renderer);
1919 if (viewport->w == 0 || viewport->h == 0) {
1920 /* If the viewport is empty, assume that it is because
1921 * SDL_CreateRenderer is calling it, and will call it again later
1922 * with a non-empty viewport.
1924 /* SDL_Log("%s, no viewport was set!\n", __FUNCTION__); */
1928 /* Make sure the SDL viewport gets rotated to that of the physical display's rotation.
1929 * Keep in mind here that the Y-axis will be been inverted (from Direct3D's
1930 * default coordinate system) so rotations will be done in the opposite
1931 * direction of the DXGI_MODE_ROTATION enumeration.
1934 case DXGI_MODE_ROTATION_IDENTITY:
1935 projection = MatrixIdentity();
1937 case DXGI_MODE_ROTATION_ROTATE270:
1938 projection = MatrixRotationZ(SDL_static_cast(float, M_PI * 0.5f));
1940 case DXGI_MODE_ROTATION_ROTATE180:
1941 projection = MatrixRotationZ(SDL_static_cast(float, M_PI));
1943 case DXGI_MODE_ROTATION_ROTATE90:
1944 projection = MatrixRotationZ(SDL_static_cast(float, -M_PI * 0.5f));
1947 return SDL_SetError("An unknown DisplayOrientation is being used");
1950 /* Update the view matrix */
1952 view.m[0][0] = 2.0f / viewport->w;
1953 view.m[1][1] = -2.0f / viewport->h;
1954 view.m[2][2] = 1.0f;
1955 view.m[3][0] = -1.0f;
1956 view.m[3][1] = 1.0f;
1957 view.m[3][3] = 1.0f;
1959 /* Combine the projection + view matrix together now, as both only get
1960 * set here (as of this writing, on Dec 26, 2013). When done, store it
1961 * for eventual transfer to the GPU.
1963 data->vertexShaderConstantsData.projectionAndView = MatrixMultiply(
1967 /* Update the Direct3D viewport, which seems to be aligned to the
1968 * swap buffer's coordinate space, which is always in either
1969 * a landscape mode, for all Windows 8/RT devices, or a portrait mode,
1970 * for Windows Phone devices.
1972 swapDimensions = D3D11_IsDisplayRotated90Degrees(rotation);
1973 if (swapDimensions) {
1974 orientationAlignedViewport.x = (float) viewport->y;
1975 orientationAlignedViewport.y = (float) viewport->x;
1976 orientationAlignedViewport.w = (float) viewport->h;
1977 orientationAlignedViewport.h = (float) viewport->w;
1979 orientationAlignedViewport.x = (float) viewport->x;
1980 orientationAlignedViewport.y = (float) viewport->y;
1981 orientationAlignedViewport.w = (float) viewport->w;
1982 orientationAlignedViewport.h = (float) viewport->h;
1984 /* TODO, WinRT: get custom viewports working with non-Landscape modes (Portrait, PortraitFlipped, and LandscapeFlipped) */
1986 d3dviewport.TopLeftX = orientationAlignedViewport.x;
1987 d3dviewport.TopLeftY = orientationAlignedViewport.y;
1988 d3dviewport.Width = orientationAlignedViewport.w;
1989 d3dviewport.Height = orientationAlignedViewport.h;
1990 d3dviewport.MinDepth = 0.0f;
1991 d3dviewport.MaxDepth = 1.0f;
1992 /* SDL_Log("%s: D3D viewport = {%f,%f,%f,%f}\n", __FUNCTION__, d3dviewport.TopLeftX, d3dviewport.TopLeftY, d3dviewport.Width, d3dviewport.Height); */
1993 ID3D11DeviceContext_RSSetViewports(data->d3dContext, 1, &d3dviewport);
1995 data->viewportDirty = SDL_FALSE;
2000 static ID3D11RenderTargetView *
2001 D3D11_GetCurrentRenderTargetView(SDL_Renderer * renderer)
2003 D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata;
2004 if (data->currentOffscreenRenderTargetView) {
2005 return data->currentOffscreenRenderTargetView;
2008 return data->mainRenderTargetView;
2013 D3D11_SetDrawState(SDL_Renderer * renderer, const SDL_RenderCommand *cmd, ID3D11PixelShader * shader,
2014 const int numShaderResources, ID3D11ShaderResourceView ** shaderResources,
2015 ID3D11SamplerState * sampler, const Float4X4 *matrix)
2018 D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata;
2019 const Float4X4 *newmatrix = matrix ? matrix : &rendererData->identity;
2020 ID3D11RasterizerState *rasterizerState;
2021 ID3D11RenderTargetView *renderTargetView = D3D11_GetCurrentRenderTargetView(renderer);
2022 ID3D11ShaderResourceView *shaderResource;
2023 const SDL_BlendMode blendMode = cmd->data.draw.blend;
2024 ID3D11BlendState *blendState = NULL;
2025 SDL_bool updateSubresource = SDL_FALSE;
2027 if (renderTargetView != rendererData->currentRenderTargetView) {
2028 ID3D11DeviceContext_OMSetRenderTargets(rendererData->d3dContext,
2033 rendererData->currentRenderTargetView = renderTargetView;
2036 if (rendererData->viewportDirty) {
2037 if (D3D11_UpdateViewport(renderer) == 0) {
2038 /* vertexShaderConstantsData.projectionAndView has changed */
2039 updateSubresource = SDL_TRUE;
2043 if (rendererData->cliprectDirty) {
2044 if (!rendererData->currentCliprectEnabled) {
2045 ID3D11DeviceContext_RSSetScissorRects(rendererData->d3dContext, 0, NULL);
2047 D3D11_RECT scissorRect;
2048 if (D3D11_GetViewportAlignedD3DRect(renderer, &rendererData->currentCliprect, &scissorRect, TRUE) != 0) {
2049 /* D3D11_GetViewportAlignedD3DRect will have set the SDL error */
2052 ID3D11DeviceContext_RSSetScissorRects(rendererData->d3dContext, 1, &scissorRect);
2054 rendererData->cliprectDirty = SDL_FALSE;
2057 if (!rendererData->currentCliprectEnabled) {
2058 rasterizerState = rendererData->mainRasterizer;
2060 rasterizerState = rendererData->clippedRasterizer;
2062 if (rasterizerState != rendererData->currentRasterizerState) {
2063 ID3D11DeviceContext_RSSetState(rendererData->d3dContext, rasterizerState);
2064 rendererData->currentRasterizerState = rasterizerState;
2067 if (blendMode != SDL_BLENDMODE_NONE) {
2069 for (i = 0; i < rendererData->blendModesCount; ++i) {
2070 if (blendMode == rendererData->blendModes[i].blendMode) {
2071 blendState = rendererData->blendModes[i].blendState;
2076 blendState = D3D11_CreateBlendState(renderer, blendMode);
2082 if (blendState != rendererData->currentBlendState) {
2083 ID3D11DeviceContext_OMSetBlendState(rendererData->d3dContext, blendState, 0, 0xFFFFFFFF);
2084 rendererData->currentBlendState = blendState;
2087 if (shader != rendererData->currentShader) {
2088 ID3D11DeviceContext_PSSetShader(rendererData->d3dContext, shader, NULL, 0);
2089 rendererData->currentShader = shader;
2091 if (numShaderResources > 0) {
2092 shaderResource = shaderResources[0];
2094 shaderResource = NULL;
2096 if (shaderResource != rendererData->currentShaderResource) {
2097 ID3D11DeviceContext_PSSetShaderResources(rendererData->d3dContext, 0, numShaderResources, shaderResources);
2098 rendererData->currentShaderResource = shaderResource;
2100 if (sampler != rendererData->currentSampler) {
2101 ID3D11DeviceContext_PSSetSamplers(rendererData->d3dContext, 0, 1, &sampler);
2102 rendererData->currentSampler = sampler;
2105 if (updateSubresource == SDL_TRUE || SDL_memcmp(&rendererData->vertexShaderConstantsData.model, newmatrix, sizeof (*newmatrix)) != 0) {
2106 SDL_memcpy(&rendererData->vertexShaderConstantsData.model, newmatrix, sizeof (*newmatrix));
2107 ID3D11DeviceContext_UpdateSubresource(rendererData->d3dContext,
2108 (ID3D11Resource *)rendererData->vertexShaderConstants,
2111 &rendererData->vertexShaderConstantsData,
2121 D3D11_SetCopyState(SDL_Renderer * renderer, const SDL_RenderCommand *cmd, const Float4X4 *matrix)
2123 SDL_Texture *texture = cmd->data.draw.texture;
2124 D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
2125 D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
2126 ID3D11SamplerState *textureSampler;
2128 switch (textureData->scaleMode) {
2129 case D3D11_FILTER_MIN_MAG_MIP_POINT:
2130 textureSampler = rendererData->nearestPixelSampler;
2132 case D3D11_FILTER_MIN_MAG_MIP_LINEAR:
2133 textureSampler = rendererData->linearSampler;
2136 return SDL_SetError("Unknown scale mode: %d\n", textureData->scaleMode);
2139 if (textureData->yuv) {
2140 ID3D11ShaderResourceView *shaderResources[] = {
2141 textureData->mainTextureResourceView,
2142 textureData->mainTextureResourceViewU,
2143 textureData->mainTextureResourceViewV
2145 D3D11_Shader shader;
2147 switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) {
2148 case SDL_YUV_CONVERSION_JPEG:
2149 shader = SHADER_YUV_JPEG;
2151 case SDL_YUV_CONVERSION_BT601:
2152 shader = SHADER_YUV_BT601;
2154 case SDL_YUV_CONVERSION_BT709:
2155 shader = SHADER_YUV_BT709;
2158 return SDL_SetError("Unsupported YUV conversion mode");
2161 return D3D11_SetDrawState(renderer, cmd, rendererData->pixelShaders[shader],
2162 SDL_arraysize(shaderResources), shaderResources, textureSampler, matrix);
2164 } else if (textureData->nv12) {
2165 ID3D11ShaderResourceView *shaderResources[] = {
2166 textureData->mainTextureResourceView,
2167 textureData->mainTextureResourceViewNV,
2169 D3D11_Shader shader;
2171 switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) {
2172 case SDL_YUV_CONVERSION_JPEG:
2173 shader = texture->format == SDL_PIXELFORMAT_NV12 ? SHADER_NV12_JPEG : SHADER_NV21_JPEG;
2175 case SDL_YUV_CONVERSION_BT601:
2176 shader = texture->format == SDL_PIXELFORMAT_NV12 ? SHADER_NV12_BT601 : SHADER_NV21_BT601;
2178 case SDL_YUV_CONVERSION_BT709:
2179 shader = texture->format == SDL_PIXELFORMAT_NV12 ? SHADER_NV12_BT709 : SHADER_NV21_BT709;
2182 return SDL_SetError("Unsupported YUV conversion mode");
2185 return D3D11_SetDrawState(renderer, cmd, rendererData->pixelShaders[shader],
2186 SDL_arraysize(shaderResources), shaderResources, textureSampler, matrix);
2190 return D3D11_SetDrawState(renderer, cmd, rendererData->pixelShaders[SHADER_RGB],
2191 1, &textureData->mainTextureResourceView, textureSampler, matrix);
2195 D3D11_DrawPrimitives(SDL_Renderer * renderer, D3D11_PRIMITIVE_TOPOLOGY primitiveTopology, const size_t vertexStart, const size_t vertexCount)
2197 D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
2198 ID3D11DeviceContext_IASetPrimitiveTopology(rendererData->d3dContext, primitiveTopology);
2199 ID3D11DeviceContext_Draw(rendererData->d3dContext, (UINT) vertexCount, (UINT) vertexStart);
2203 D3D11_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
2205 D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
2206 const int viewportRotation = D3D11_GetRotationForCurrentRenderTarget(renderer);
2209 if (rendererData->currentViewportRotation != viewportRotation) {
2210 rendererData->currentViewportRotation = viewportRotation;
2211 rendererData->viewportDirty = SDL_TRUE;
2214 if (D3D11_UpdateVertexBuffer(renderer, vertices, vertsize) < 0) {
2219 switch (cmd->command) {
2220 case SDL_RENDERCMD_SETDRAWCOLOR: {
2221 break; /* this isn't currently used in this render backend. */
2224 case SDL_RENDERCMD_SETVIEWPORT: {
2225 SDL_Rect *viewport = &rendererData->currentViewport;
2226 if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect)) != 0) {
2227 SDL_memcpy(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect));
2228 rendererData->viewportDirty = SDL_TRUE;
2233 case SDL_RENDERCMD_SETCLIPRECT: {
2234 const SDL_Rect *rect = &cmd->data.cliprect.rect;
2235 if (rendererData->currentCliprectEnabled != cmd->data.cliprect.enabled) {
2236 rendererData->currentCliprectEnabled = cmd->data.cliprect.enabled;
2237 rendererData->cliprectDirty = SDL_TRUE;
2239 if (SDL_memcmp(&rendererData->currentCliprect, rect, sizeof (SDL_Rect)) != 0) {
2240 SDL_memcpy(&rendererData->currentCliprect, rect, sizeof (SDL_Rect));
2241 rendererData->cliprectDirty = SDL_TRUE;
2246 case SDL_RENDERCMD_CLEAR: {
2247 const float colorRGBA[] = {
2248 (cmd->data.color.r / 255.0f),
2249 (cmd->data.color.g / 255.0f),
2250 (cmd->data.color.b / 255.0f),
2251 (cmd->data.color.a / 255.0f)
2253 ID3D11DeviceContext_ClearRenderTargetView(rendererData->d3dContext, D3D11_GetCurrentRenderTargetView(renderer), colorRGBA);
2257 case SDL_RENDERCMD_DRAW_POINTS: {
2258 const size_t count = cmd->data.draw.count;
2259 const size_t first = cmd->data.draw.first;
2260 const size_t start = first / sizeof (VertexPositionColor);
2261 D3D11_SetDrawState(renderer, cmd, rendererData->pixelShaders[SHADER_SOLID], 0, NULL, NULL, NULL);
2262 D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, start, count);
2266 case SDL_RENDERCMD_DRAW_LINES: {
2267 const size_t count = cmd->data.draw.count;
2268 const size_t first = cmd->data.draw.first;
2269 const size_t start = first / sizeof (VertexPositionColor);
2270 const VertexPositionColor *verts = (VertexPositionColor *) (((Uint8 *) vertices) + first);
2271 D3D11_SetDrawState(renderer, cmd, rendererData->pixelShaders[SHADER_SOLID], 0, NULL, NULL, NULL);
2272 D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP, start, count);
2273 if (verts[0].pos.x != verts[count - 1].pos.x || verts[0].pos.y != verts[count - 1].pos.y) {
2274 D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, start + (count-1), 1);
2279 case SDL_RENDERCMD_FILL_RECTS: {
2280 const size_t count = cmd->data.draw.count;
2281 const size_t first = cmd->data.draw.first;
2282 const size_t start = first / sizeof (VertexPositionColor);
2284 D3D11_SetDrawState(renderer, cmd, rendererData->pixelShaders[SHADER_SOLID], 0, NULL, NULL, NULL);
2285 for (i = 0; i < count; i++, offset += 4) {
2286 D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, start + offset, 4);
2291 case SDL_RENDERCMD_COPY: {
2292 const size_t first = cmd->data.draw.first;
2293 const size_t start = first / sizeof (VertexPositionColor);
2294 D3D11_SetCopyState(renderer, cmd, NULL);
2295 D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, start, 4);
2299 case SDL_RENDERCMD_COPY_EX: {
2300 const size_t first = cmd->data.draw.first;
2301 const size_t start = first / sizeof (VertexPositionColor);
2302 const VertexPositionColor *verts = (VertexPositionColor *) (((Uint8 *) vertices) + first);
2303 const VertexPositionColor *transvert = verts + 4;
2304 const float translatex = transvert->pos.x;
2305 const float translatey = transvert->pos.y;
2306 const float rotation = transvert->pos.z;
2307 const Float4X4 matrix = MatrixMultiply(MatrixRotationZ(rotation), MatrixTranslation(translatex, translatey, 0));
2308 D3D11_SetCopyState(renderer, cmd, &matrix);
2309 D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, start, 4);
2313 case SDL_RENDERCMD_NO_OP:
2324 D3D11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
2325 Uint32 format, void * pixels, int pitch)
2327 D3D11_RenderData * data = (D3D11_RenderData *) renderer->driverdata;
2328 ID3D11RenderTargetView *renderTargetView = NULL;
2329 ID3D11Texture2D *backBuffer = NULL;
2330 ID3D11Texture2D *stagingTexture = NULL;
2333 D3D11_TEXTURE2D_DESC stagingTextureDesc;
2334 D3D11_RECT srcRect = {0, 0, 0, 0};
2336 D3D11_MAPPED_SUBRESOURCE textureMemory;
2338 ID3D11DeviceContext_OMGetRenderTargets(data->d3dContext, 1, &renderTargetView, NULL);
2339 if (renderTargetView == NULL) {
2340 SDL_SetError("%s, ID3D11DeviceContext::OMGetRenderTargets failed", __FUNCTION__);
2344 ID3D11View_GetResource(renderTargetView, (ID3D11Resource**)&backBuffer);
2345 if (backBuffer == NULL) {
2346 SDL_SetError("%s, ID3D11View::GetResource failed", __FUNCTION__);
2350 /* Create a staging texture to copy the screen's data to: */
2351 ID3D11Texture2D_GetDesc(backBuffer, &stagingTextureDesc);
2352 stagingTextureDesc.Width = rect->w;
2353 stagingTextureDesc.Height = rect->h;
2354 stagingTextureDesc.BindFlags = 0;
2355 stagingTextureDesc.MiscFlags = 0;
2356 stagingTextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
2357 stagingTextureDesc.Usage = D3D11_USAGE_STAGING;
2358 result = ID3D11Device_CreateTexture2D(data->d3dDevice,
2359 &stagingTextureDesc,
2362 if (FAILED(result)) {
2363 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D [create staging texture]"), result);
2367 /* Copy the desired portion of the back buffer to the staging texture: */
2368 if (D3D11_GetViewportAlignedD3DRect(renderer, rect, &srcRect, FALSE) != 0) {
2369 /* D3D11_GetViewportAlignedD3DRect will have set the SDL error */
2373 srcBox.left = srcRect.left;
2374 srcBox.right = srcRect.right;
2375 srcBox.top = srcRect.top;
2376 srcBox.bottom = srcRect.bottom;
2379 ID3D11DeviceContext_CopySubresourceRegion(data->d3dContext,
2380 (ID3D11Resource *)stagingTexture,
2383 (ID3D11Resource *)backBuffer,
2387 /* Map the staging texture's data to CPU-accessible memory: */
2388 result = ID3D11DeviceContext_Map(data->d3dContext,
2389 (ID3D11Resource *)stagingTexture,
2394 if (FAILED(result)) {
2395 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [map staging texture]"), result);
2399 /* Copy the data into the desired buffer, converting pixels to the
2400 * desired format at the same time:
2402 if (SDL_ConvertPixels(
2404 D3D11_DXGIFormatToSDLPixelFormat(stagingTextureDesc.Format),
2405 textureMemory.pData,
2406 textureMemory.RowPitch,
2410 /* When SDL_ConvertPixels fails, it'll have already set the format.
2411 * Get the error message, and attach some extra data to it.
2413 char errorMessage[1024];
2414 SDL_snprintf(errorMessage, sizeof(errorMessage), "%s, Convert Pixels failed: %s", __FUNCTION__, SDL_GetError());
2415 SDL_SetError("%s", errorMessage);
2419 /* Unmap the texture: */
2420 ID3D11DeviceContext_Unmap(data->d3dContext,
2421 (ID3D11Resource *)stagingTexture,
2427 SAFE_RELEASE(backBuffer);
2428 SAFE_RELEASE(stagingTexture);
2433 D3D11_RenderPresent(SDL_Renderer * renderer)
2435 D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
2439 DXGI_PRESENT_PARAMETERS parameters;
2441 SDL_zero(parameters);
2443 #if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
2446 result = IDXGISwapChain_Present(data->swapChain, syncInterval, presentFlags);
2448 if (renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) {
2453 presentFlags = DXGI_PRESENT_DO_NOT_WAIT;
2456 /* The application may optionally specify "dirty" or "scroll"
2457 * rects to improve efficiency in certain scenarios.
2458 * This option is not available on Windows Phone 8, to note.
2460 result = IDXGISwapChain1_Present1(data->swapChain, syncInterval, presentFlags, ¶meters);
2463 /* Discard the contents of the render target.
2464 * This is a valid operation only when the existing contents will be entirely
2465 * overwritten. If dirty or scroll rects are used, this call should be removed.
2467 ID3D11DeviceContext1_DiscardView(data->d3dContext, (ID3D11View*)data->mainRenderTargetView);
2469 /* When the present flips, it unbinds the current view, so bind it again on the next draw call */
2470 data->currentRenderTargetView = NULL;
2472 if (FAILED(result) && result != DXGI_ERROR_WAS_STILL_DRAWING) {
2473 /* If the device was removed either by a disconnect or a driver upgrade, we
2474 * must recreate all device resources.
2476 * TODO, WinRT: consider throwing an exception if D3D11_RenderPresent fails, especially if there is a way to salvage debug info from users' machines
2478 if ( result == DXGI_ERROR_DEVICE_REMOVED ) {
2479 D3D11_HandleDeviceLost(renderer);
2480 } else if (result == DXGI_ERROR_INVALID_CALL) {
2481 /* We probably went through a fullscreen <-> windowed transition */
2482 D3D11_CreateWindowSizeDependentResources(renderer);
2484 WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain::Present"), result);
2490 D3D11_CreateRenderer(SDL_Window * window, Uint32 flags)
2492 SDL_Renderer *renderer;
2493 D3D11_RenderData *data;
2495 renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
2501 data = (D3D11_RenderData *) SDL_calloc(1, sizeof(*data));
2507 data->identity = MatrixIdentity();
2509 renderer->WindowEvent = D3D11_WindowEvent;
2510 renderer->SupportsBlendMode = D3D11_SupportsBlendMode;
2511 renderer->CreateTexture = D3D11_CreateTexture;
2512 renderer->UpdateTexture = D3D11_UpdateTexture;
2513 renderer->UpdateTextureYUV = D3D11_UpdateTextureYUV;
2514 renderer->LockTexture = D3D11_LockTexture;
2515 renderer->UnlockTexture = D3D11_UnlockTexture;
2516 renderer->SetTextureScaleMode = D3D11_SetTextureScaleMode;
2517 renderer->SetRenderTarget = D3D11_SetRenderTarget;
2518 renderer->QueueSetViewport = D3D11_QueueSetViewport;
2519 renderer->QueueSetDrawColor = D3D11_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
2520 renderer->QueueDrawPoints = D3D11_QueueDrawPoints;
2521 renderer->QueueDrawLines = D3D11_QueueDrawPoints; /* lines and points queue vertices the same way. */
2522 renderer->QueueFillRects = D3D11_QueueFillRects;
2523 renderer->QueueCopy = D3D11_QueueCopy;
2524 renderer->QueueCopyEx = D3D11_QueueCopyEx;
2525 renderer->RunCommandQueue = D3D11_RunCommandQueue;
2526 renderer->RenderReadPixels = D3D11_RenderReadPixels;
2527 renderer->RenderPresent = D3D11_RenderPresent;
2528 renderer->DestroyTexture = D3D11_DestroyTexture;
2529 renderer->DestroyRenderer = D3D11_DestroyRenderer;
2530 renderer->info = D3D11_RenderDriver.info;
2531 renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
2532 renderer->driverdata = data;
2534 #if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
2535 /* VSync is required in Windows Phone, at least for Win Phone 8.0 and 8.1.
2536 * Failure to use it seems to either result in:
2538 * - with the D3D11 debug runtime turned OFF, vsync seemingly gets turned
2539 * off (framerate doesn't get capped), but nothing appears on-screen
2541 * - with the D3D11 debug runtime turned ON, vsync gets automatically
2542 * turned back on, and the following gets output to the debug console:
2544 * DXGI ERROR: IDXGISwapChain::Present: Interval 0 is not supported, changed to Interval 1. [ UNKNOWN ERROR #1024: ]
2546 renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
2548 if ((flags & SDL_RENDERER_PRESENTVSYNC)) {
2549 renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
2553 /* HACK: make sure the SDL_Renderer references the SDL_Window data now, in
2554 * order to give init functions access to the underlying window handle:
2556 renderer->window = window;
2558 /* Initialize Direct3D resources */
2559 if (FAILED(D3D11_CreateDeviceResources(renderer))) {
2560 D3D11_DestroyRenderer(renderer);
2563 if (FAILED(D3D11_CreateWindowSizeDependentResources(renderer))) {
2564 D3D11_DestroyRenderer(renderer);
2571 SDL_RenderDriver D3D11_RenderDriver = {
2572 D3D11_CreateRenderer,
2576 SDL_RENDERER_ACCELERATED |
2577 SDL_RENDERER_PRESENTVSYNC |
2578 SDL_RENDERER_TARGETTEXTURE
2579 ), /* flags. see SDL_RendererFlags */
2580 6, /* num_texture_formats */
2581 { /* texture_formats */
2582 SDL_PIXELFORMAT_ARGB8888,
2583 SDL_PIXELFORMAT_RGB888,
2584 SDL_PIXELFORMAT_YV12,
2585 SDL_PIXELFORMAT_IYUV,
2586 SDL_PIXELFORMAT_NV12,
2587 SDL_PIXELFORMAT_NV21
2589 0, /* max_texture_width: will be filled in later */
2590 0 /* max_texture_height: will be filled in later */
2594 #endif /* SDL_VIDEO_RENDER_D3D11 && !SDL_RENDER_DISABLED */
2596 /* vi: set ts=4 sw=4 expandtab: */