SDL_render_d3d11.cpp 63 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816
  1. /*
  2. Simple DirectMedia Layer
  3. Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any damages
  6. arising from the use of this software.
  7. Permission is granted to anyone to use this software for any purpose,
  8. including commercial applications, and to alter it and redistribute it
  9. freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you must not
  11. claim that you wrote the original software. If you use this software
  12. in a product, an acknowledgment in the product documentation would be
  13. appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and must not be
  15. misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source distribution.
  17. */
  18. #include "SDL_config.h"
  19. #if SDL_VIDEO_RENDER_D3D11 && !SDL_RENDER_DISABLED
  20. #ifdef __WINRT__
  21. #include <windows.ui.core.h>
  22. #include <windows.foundation.h>
  23. #endif
  24. extern "C" {
  25. #include "../../core/windows/SDL_windows.h"
  26. //#include "SDL_hints.h"
  27. //#include "SDL_loadso.h"
  28. #include "SDL_system.h"
  29. #include "SDL_syswm.h"
  30. #include "../SDL_sysrender.h"
  31. #include "SDL_log.h"
  32. #include "../../video/SDL_sysvideo.h"
  33. //#include "stdio.h"
  34. }
  35. #include <fstream>
  36. #include <string>
  37. #include <vector>
  38. #include "SDL_render_d3d11_cpp.h"
  39. using namespace DirectX;
  40. using namespace Microsoft::WRL;
  41. using namespace std;
  42. #ifdef __WINRT__
  43. using namespace Windows::Graphics::Display;
  44. using namespace Windows::UI::Core;
  45. #endif
  46. /* Direct3D 11.1 renderer implementation */
  47. static SDL_Renderer *D3D11_CreateRenderer(SDL_Window * window, Uint32 flags);
  48. static void D3D11_WindowEvent(SDL_Renderer * renderer,
  49. const SDL_WindowEvent *event);
  50. static int D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
  51. static int D3D11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
  52. const SDL_Rect * rect, const void *srcPixels,
  53. int srcPitch);
  54. static int D3D11_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
  55. const SDL_Rect * rect, void **pixels, int *pitch);
  56. static void D3D11_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
  57. static int D3D11_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture);
  58. static int D3D11_UpdateViewport(SDL_Renderer * renderer);
  59. static int D3D11_UpdateClipRect(SDL_Renderer * renderer);
  60. static int D3D11_RenderClear(SDL_Renderer * renderer);
  61. static int D3D11_RenderDrawPoints(SDL_Renderer * renderer,
  62. const SDL_FPoint * points, int count);
  63. static int D3D11_RenderDrawLines(SDL_Renderer * renderer,
  64. const SDL_FPoint * points, int count);
  65. static int D3D11_RenderFillRects(SDL_Renderer * renderer,
  66. const SDL_FRect * rects, int count);
  67. static int D3D11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
  68. const SDL_Rect * srcrect, const SDL_FRect * dstrect);
  69. static int D3D11_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
  70. const SDL_Rect * srcrect, const SDL_FRect * dstrect,
  71. const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip);
  72. static int D3D11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
  73. Uint32 format, void * pixels, int pitch);
  74. static void D3D11_RenderPresent(SDL_Renderer * renderer);
  75. static void D3D11_DestroyTexture(SDL_Renderer * renderer,
  76. SDL_Texture * texture);
  77. static void D3D11_DestroyRenderer(SDL_Renderer * renderer);
  78. /* Direct3D 11.1 Internal Functions */
  79. HRESULT D3D11_CreateDeviceResources(SDL_Renderer * renderer);
  80. HRESULT D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer);
  81. HRESULT D3D11_UpdateForWindowSizeChange(SDL_Renderer * renderer);
  82. HRESULT D3D11_HandleDeviceLost(SDL_Renderer * renderer);
  83. extern "C" SDL_RenderDriver D3D11_RenderDriver = {
  84. D3D11_CreateRenderer,
  85. {
  86. "direct3d 11.1",
  87. (
  88. SDL_RENDERER_ACCELERATED |
  89. SDL_RENDERER_PRESENTVSYNC |
  90. SDL_RENDERER_TARGETTEXTURE
  91. ), // flags. see SDL_RendererFlags
  92. 2, // num_texture_formats
  93. { // texture_formats
  94. SDL_PIXELFORMAT_RGB888,
  95. SDL_PIXELFORMAT_ARGB8888
  96. },
  97. 0, // max_texture_width: will be filled in later
  98. 0 // max_texture_height: will be filled in later
  99. }
  100. };
  101. static Uint32
  102. DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat) {
  103. switch (dxgiFormat) {
  104. case DXGI_FORMAT_B8G8R8A8_UNORM:
  105. return SDL_PIXELFORMAT_ARGB8888;
  106. case DXGI_FORMAT_B8G8R8X8_UNORM:
  107. return SDL_PIXELFORMAT_RGB888;
  108. default:
  109. return SDL_PIXELFORMAT_UNKNOWN;
  110. }
  111. }
  112. static DXGI_FORMAT
  113. SDLPixelFormatToDXGIFormat(Uint32 sdlFormat)
  114. {
  115. switch (sdlFormat) {
  116. case SDL_PIXELFORMAT_ARGB8888:
  117. return DXGI_FORMAT_B8G8R8A8_UNORM;
  118. case SDL_PIXELFORMAT_RGB888:
  119. return DXGI_FORMAT_B8G8R8X8_UNORM;
  120. default:
  121. return DXGI_FORMAT_UNKNOWN;
  122. }
  123. }
  124. //typedef struct
  125. //{
  126. // float x, y, z;
  127. // DWORD color;
  128. // float u, v;
  129. //} Vertex;
  130. SDL_Renderer *
  131. D3D11_CreateRenderer(SDL_Window * window, Uint32 flags)
  132. {
  133. SDL_Renderer *renderer;
  134. D3D11_RenderData *data;
  135. renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
  136. if (!renderer) {
  137. SDL_OutOfMemory();
  138. return NULL;
  139. }
  140. SDL_zerop(renderer);
  141. data = new D3D11_RenderData; // Use the C++ 'new' operator to make sure the struct's members initialize using C++ rules
  142. if (!data) {
  143. SDL_OutOfMemory();
  144. return NULL;
  145. }
  146. data->featureLevel = (D3D_FEATURE_LEVEL) 0;
  147. data->windowSizeInDIPs = XMFLOAT2(0, 0);
  148. data->renderTargetSize = XMFLOAT2(0, 0);
  149. renderer->WindowEvent = D3D11_WindowEvent;
  150. renderer->CreateTexture = D3D11_CreateTexture;
  151. renderer->UpdateTexture = D3D11_UpdateTexture;
  152. renderer->LockTexture = D3D11_LockTexture;
  153. renderer->UnlockTexture = D3D11_UnlockTexture;
  154. renderer->SetRenderTarget = D3D11_SetRenderTarget;
  155. renderer->UpdateViewport = D3D11_UpdateViewport;
  156. renderer->UpdateClipRect = D3D11_UpdateClipRect;
  157. renderer->RenderClear = D3D11_RenderClear;
  158. renderer->RenderDrawPoints = D3D11_RenderDrawPoints;
  159. renderer->RenderDrawLines = D3D11_RenderDrawLines;
  160. renderer->RenderFillRects = D3D11_RenderFillRects;
  161. renderer->RenderCopy = D3D11_RenderCopy;
  162. renderer->RenderCopyEx = D3D11_RenderCopyEx;
  163. renderer->RenderReadPixels = D3D11_RenderReadPixels;
  164. renderer->RenderPresent = D3D11_RenderPresent;
  165. renderer->DestroyTexture = D3D11_DestroyTexture;
  166. renderer->DestroyRenderer = D3D11_DestroyRenderer;
  167. renderer->info = D3D11_RenderDriver.info;
  168. renderer->driverdata = data;
  169. // HACK: make sure the SDL_Renderer references the SDL_Window data now, in
  170. // order to give init functions access to the underlying window handle:
  171. renderer->window = window;
  172. /* Initialize Direct3D resources */
  173. if (FAILED(D3D11_CreateDeviceResources(renderer))) {
  174. D3D11_DestroyRenderer(renderer);
  175. return NULL;
  176. }
  177. if (FAILED(D3D11_CreateWindowSizeDependentResources(renderer))) {
  178. D3D11_DestroyRenderer(renderer);
  179. return NULL;
  180. }
  181. // TODO, WinRT: fill in renderer->info.texture_formats where appropriate
  182. return renderer;
  183. }
  184. static void
  185. D3D11_DestroyRenderer(SDL_Renderer * renderer)
  186. {
  187. D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
  188. if (data) {
  189. delete data;
  190. data = NULL;
  191. }
  192. }
  193. static bool
  194. D3D11_ReadFileContents(const wstring & fileName, vector<char> & out)
  195. {
  196. ifstream in(fileName, ios::in | ios::binary);
  197. if (!in) {
  198. return false;
  199. }
  200. in.seekg(0, ios::end);
  201. out.resize((size_t) in.tellg());
  202. in.seekg(0, ios::beg);
  203. in.read(&out[0], out.size());
  204. return in.good();
  205. }
  206. static bool
  207. D3D11_ReadShaderContents(const wstring & shaderName, vector<char> & out)
  208. {
  209. wstring fileName;
  210. #if WINAPI_FAMILY == WINAPI_FAMILY_APP
  211. fileName = SDL_WinRTGetFSPathUNICODE(SDL_WINRT_PATH_INSTALLED_LOCATION);
  212. fileName += L"\\SDL_VS2012_WinRT\\";
  213. #elif WINAPI_FAMILY == WINAPI_PHONE_APP
  214. fileName = SDL_WinRTGetFSPathUNICODE(SDL_WINRT_PATH_INSTALLED_LOCATION);
  215. fileName += L"\\";
  216. #endif
  217. // TODO, WinRT: test Direct3D 11.1 shader loading on Win32
  218. fileName += shaderName;
  219. return D3D11_ReadFileContents(fileName, out);
  220. }
  221. static HRESULT
  222. D3D11_LoadPixelShader(SDL_Renderer * renderer,
  223. const wstring & shaderName,
  224. ID3D11PixelShader ** shaderOutput)
  225. {
  226. D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
  227. HRESULT result = S_OK;
  228. vector<char> fileData;
  229. if (!D3D11_ReadShaderContents(shaderName, fileData)) {
  230. SDL_SetError("Unable to open SDL's pixel shader file.");
  231. return E_FAIL;
  232. }
  233. result = data->d3dDevice->CreatePixelShader(
  234. &fileData[0],
  235. fileData.size(),
  236. nullptr,
  237. shaderOutput
  238. );
  239. if (FAILED(result)) {
  240. WIN_SetErrorFromHRESULT(__FUNCTION__, result);
  241. return result;
  242. }
  243. return S_OK;
  244. }
  245. static HRESULT
  246. D3D11_CreateBlendMode(SDL_Renderer * renderer,
  247. BOOL enableBlending,
  248. D3D11_BLEND srcBlend,
  249. D3D11_BLEND destBlend,
  250. ID3D11BlendState ** blendStateOutput)
  251. {
  252. D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
  253. HRESULT result = S_OK;
  254. D3D11_BLEND_DESC blendDesc;
  255. memset(&blendDesc, 0, sizeof(blendDesc));
  256. blendDesc.AlphaToCoverageEnable = FALSE;
  257. blendDesc.IndependentBlendEnable = FALSE;
  258. blendDesc.RenderTarget[0].BlendEnable = enableBlending;
  259. blendDesc.RenderTarget[0].SrcBlend = srcBlend;
  260. blendDesc.RenderTarget[0].DestBlend = destBlend;
  261. blendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
  262. blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
  263. blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
  264. blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
  265. blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
  266. result = data->d3dDevice->CreateBlendState(&blendDesc, blendStateOutput);
  267. if (FAILED(result)) {
  268. WIN_SetErrorFromHRESULT(__FUNCTION__, result);
  269. return result;
  270. }
  271. return S_OK;
  272. }
  273. // Create resources that depend on the device.
  274. HRESULT
  275. D3D11_CreateDeviceResources(SDL_Renderer * renderer)
  276. {
  277. D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
  278. // This flag adds support for surfaces with a different color channel ordering
  279. // than the API default. It is required for compatibility with Direct2D.
  280. UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
  281. #if defined(_DEBUG)
  282. // If the project is in a debug build, enable debugging via SDK Layers with this flag.
  283. creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
  284. #endif
  285. // This array defines the set of DirectX hardware feature levels this app will support.
  286. // Note the ordering should be preserved.
  287. // Don't forget to declare your application's minimum required feature level in its
  288. // description. All applications are assumed to support 9.1 unless otherwise stated.
  289. D3D_FEATURE_LEVEL featureLevels[] =
  290. {
  291. D3D_FEATURE_LEVEL_11_1,
  292. D3D_FEATURE_LEVEL_11_0,
  293. D3D_FEATURE_LEVEL_10_1,
  294. D3D_FEATURE_LEVEL_10_0,
  295. D3D_FEATURE_LEVEL_9_3,
  296. D3D_FEATURE_LEVEL_9_2,
  297. D3D_FEATURE_LEVEL_9_1
  298. };
  299. // Create the Direct3D 11 API device object and a corresponding context.
  300. ComPtr<ID3D11Device> device;
  301. ComPtr<ID3D11DeviceContext> context;
  302. HRESULT result = S_OK;
  303. result = D3D11CreateDevice(
  304. nullptr, // Specify nullptr to use the default adapter.
  305. D3D_DRIVER_TYPE_HARDWARE,
  306. nullptr,
  307. creationFlags, // Set set debug and Direct2D compatibility flags.
  308. featureLevels, // List of feature levels this app can support.
  309. ARRAYSIZE(featureLevels),
  310. D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps.
  311. &device, // Returns the Direct3D device created.
  312. &data->featureLevel, // Returns feature level of device created.
  313. &context // Returns the device immediate context.
  314. );
  315. if (FAILED(result)) {
  316. WIN_SetErrorFromHRESULT(__FUNCTION__, result);
  317. return result;
  318. }
  319. // Get the Direct3D 11.1 API device and context interfaces.
  320. Microsoft::WRL::ComPtr<ID3D11Device1> d3dDevice1;
  321. result = device.As(&(data->d3dDevice));
  322. if (FAILED(result)) {
  323. WIN_SetErrorFromHRESULT(__FUNCTION__, result);
  324. return result;
  325. }
  326. result = context.As(&data->d3dContext);
  327. if (FAILED(result)) {
  328. return result;
  329. }
  330. //
  331. // Make note of the maximum texture size
  332. // Max texture sizes are documented on MSDN, at:
  333. // http://msdn.microsoft.com/en-us/library/windows/apps/ff476876.aspx
  334. //
  335. switch (data->d3dDevice->GetFeatureLevel()) {
  336. case D3D_FEATURE_LEVEL_11_1:
  337. case D3D_FEATURE_LEVEL_11_0:
  338. renderer->info.max_texture_width = renderer->info.max_texture_height = 16384;
  339. break;
  340. case D3D_FEATURE_LEVEL_10_1:
  341. case D3D_FEATURE_LEVEL_10_0:
  342. renderer->info.max_texture_width = renderer->info.max_texture_height = 8192;
  343. break;
  344. case D3D_FEATURE_LEVEL_9_3:
  345. renderer->info.max_texture_width = renderer->info.max_texture_height = 4096;
  346. break;
  347. case D3D_FEATURE_LEVEL_9_2:
  348. case D3D_FEATURE_LEVEL_9_1:
  349. renderer->info.max_texture_width = renderer->info.max_texture_height = 2048;
  350. break;
  351. }
  352. //
  353. // Load in SDL's one and only vertex shader:
  354. //
  355. vector<char> fileData;
  356. if (!D3D11_ReadShaderContents(L"SDL_D3D11_VertexShader_Default.cso", fileData)) {
  357. SDL_SetError("Unable to open SDL's vertex shader file.");
  358. return E_FAIL;
  359. }
  360. result = data->d3dDevice->CreateVertexShader(
  361. &fileData[0],
  362. fileData.size(),
  363. nullptr,
  364. &data->vertexShader
  365. );
  366. if (FAILED(result)) {
  367. WIN_SetErrorFromHRESULT(__FUNCTION__, result);
  368. return result;
  369. }
  370. //
  371. // Create an input layout for SDL's vertex shader:
  372. //
  373. const D3D11_INPUT_ELEMENT_DESC vertexDesc[] =
  374. {
  375. { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
  376. { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
  377. { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 20, D3D11_INPUT_PER_VERTEX_DATA, 0 },
  378. };
  379. result = data->d3dDevice->CreateInputLayout(
  380. vertexDesc,
  381. ARRAYSIZE(vertexDesc),
  382. &fileData[0],
  383. fileData.size(),
  384. &data->inputLayout
  385. );
  386. if (FAILED(result)) {
  387. WIN_SetErrorFromHRESULT(__FUNCTION__, result);
  388. return result;
  389. }
  390. //
  391. // Load in SDL's pixel shaders
  392. //
  393. result = D3D11_LoadPixelShader(renderer, L"SDL_D3D11_PixelShader_TextureColored.cso", &data->texturePixelShader);
  394. if (FAILED(result)) {
  395. // D3D11_LoadPixelShader will have aleady set the SDL error
  396. return result;
  397. }
  398. result = D3D11_LoadPixelShader(renderer, L"SDL_D3D11_PixelShader_FixedColor.cso", &data->colorPixelShader);
  399. if (FAILED(result)) {
  400. // D3D11_LoadPixelShader will have aleady set the SDL error
  401. return result;
  402. }
  403. //
  404. // Setup space to hold vertex shader constants:
  405. //
  406. CD3D11_BUFFER_DESC constantBufferDesc(sizeof(SDL_VertexShaderConstants), D3D11_BIND_CONSTANT_BUFFER);
  407. result = data->d3dDevice->CreateBuffer(
  408. &constantBufferDesc,
  409. nullptr,
  410. &data->vertexShaderConstants
  411. );
  412. if (FAILED(result)) {
  413. WIN_SetErrorFromHRESULT(__FUNCTION__, result);
  414. return result;
  415. }
  416. //
  417. // Make sure that the vertex buffer, if already created, gets freed.
  418. // It will be recreated later.
  419. //
  420. data->vertexBuffer = nullptr;
  421. //
  422. // Create a sampler to use when drawing textures:
  423. //
  424. D3D11_SAMPLER_DESC samplerDesc;
  425. samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
  426. samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
  427. samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
  428. samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
  429. samplerDesc.MipLODBias = 0.0f;
  430. samplerDesc.MaxAnisotropy = 1;
  431. samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
  432. samplerDesc.BorderColor[0] = 0.0f;
  433. samplerDesc.BorderColor[1] = 0.0f;
  434. samplerDesc.BorderColor[2] = 0.0f;
  435. samplerDesc.BorderColor[3] = 0.0f;
  436. samplerDesc.MinLOD = 0.0f;
  437. samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
  438. result = data->d3dDevice->CreateSamplerState(
  439. &samplerDesc,
  440. &data->mainSampler
  441. );
  442. if (FAILED(result)) {
  443. WIN_SetErrorFromHRESULT(__FUNCTION__, result);
  444. return result;
  445. }
  446. //
  447. // Setup the Direct3D rasterizer
  448. //
  449. D3D11_RASTERIZER_DESC rasterDesc;
  450. memset(&rasterDesc, 0, sizeof(rasterDesc));
  451. rasterDesc.AntialiasedLineEnable = false;
  452. rasterDesc.CullMode = D3D11_CULL_NONE;
  453. rasterDesc.DepthBias = 0;
  454. rasterDesc.DepthBiasClamp = 0.0f;
  455. rasterDesc.DepthClipEnable = true;
  456. rasterDesc.FillMode = D3D11_FILL_SOLID;
  457. rasterDesc.FrontCounterClockwise = false;
  458. rasterDesc.MultisampleEnable = false;
  459. rasterDesc.ScissorEnable = false;
  460. rasterDesc.SlopeScaledDepthBias = 0.0f;
  461. result = data->d3dDevice->CreateRasterizerState(&rasterDesc, &data->mainRasterizer);
  462. if (FAILED(result)) {
  463. WIN_SetErrorFromHRESULT(__FUNCTION__, result);
  464. return result;
  465. }
  466. //
  467. // Create blending states:
  468. //
  469. result = D3D11_CreateBlendMode(
  470. renderer,
  471. TRUE,
  472. D3D11_BLEND_SRC_ALPHA,
  473. D3D11_BLEND_INV_SRC_ALPHA,
  474. &data->blendModeBlend);
  475. if (FAILED(result)) {
  476. // D3D11_CreateBlendMode will set the SDL error, if it fails
  477. return result;
  478. }
  479. result = D3D11_CreateBlendMode(
  480. renderer,
  481. TRUE,
  482. D3D11_BLEND_SRC_ALPHA,
  483. D3D11_BLEND_ONE,
  484. &data->blendModeAdd);
  485. if (FAILED(result)) {
  486. // D3D11_CreateBlendMode will set the SDL error, if it fails
  487. return result;
  488. }
  489. result = D3D11_CreateBlendMode(
  490. renderer,
  491. TRUE,
  492. D3D11_BLEND_ZERO,
  493. D3D11_BLEND_SRC_COLOR,
  494. &data->blendModeMod);
  495. if (FAILED(result)) {
  496. // D3D11_CreateBlendMode will set the SDL error, if it fails
  497. return result;
  498. }
  499. //
  500. // All done!
  501. //
  502. return S_OK;
  503. }
  504. #ifdef __WINRT__
  505. static ABI::Windows::UI::Core::ICoreWindow *
  506. D3D11_GetCoreWindowFromSDLRenderer(SDL_Renderer * renderer)
  507. {
  508. SDL_Window * sdlWindow = renderer->window;
  509. if ( ! renderer->window ) {
  510. return nullptr;
  511. }
  512. SDL_SysWMinfo sdlWindowInfo;
  513. SDL_VERSION(&sdlWindowInfo.version);
  514. if ( ! SDL_GetWindowWMInfo(sdlWindow, &sdlWindowInfo) ) {
  515. return nullptr;
  516. }
  517. if (sdlWindowInfo.subsystem != SDL_SYSWM_WINRT) {
  518. return nullptr;
  519. }
  520. if ( ! sdlWindowInfo.info.winrt.window ) {
  521. return nullptr;
  522. }
  523. ABI::Windows::UI::Core::ICoreWindow * coreWindow = nullptr;
  524. if (FAILED(sdlWindowInfo.info.winrt.window->QueryInterface(&coreWindow))) {
  525. return nullptr;
  526. }
  527. return coreWindow;
  528. }
  529. // Method to convert a length in device-independent pixels (DIPs) to a length in physical pixels.
  530. static float
  531. D3D11_ConvertDipsToPixels(float dips)
  532. {
  533. static const float dipsPerInch = 96.0f;
  534. return floor(dips * DisplayProperties::LogicalDpi / dipsPerInch + 0.5f); // Round to nearest integer.
  535. }
  536. #endif
  537. // Initialize all resources that change when the window's size changes.
  538. // TODO, WinRT: get D3D11_CreateWindowSizeDependentResources working on Win32
  539. HRESULT
  540. D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
  541. {
  542. D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
  543. HRESULT result = S_OK;
  544. ABI::Windows::UI::Core::ICoreWindow * coreWindow = D3D11_GetCoreWindowFromSDLRenderer(renderer);
  545. // Store the window bounds so the next time we get a SizeChanged event we can
  546. // avoid rebuilding everything if the size is identical.
  547. ABI::Windows::Foundation::Rect coreWindowBounds;
  548. result = coreWindow->get_Bounds(&coreWindowBounds);
  549. if (FAILED(result)) {
  550. WIN_SetErrorFromHRESULT(__FUNCTION__", Get Window Bounds", result);
  551. return result;
  552. }
  553. data->windowSizeInDIPs.x = coreWindowBounds.Width;
  554. data->windowSizeInDIPs.y = coreWindowBounds.Height;
  555. // Calculate the necessary swap chain and render target size in pixels.
  556. float windowWidth = D3D11_ConvertDipsToPixels(data->windowSizeInDIPs.x);
  557. float windowHeight = D3D11_ConvertDipsToPixels(data->windowSizeInDIPs.y);
  558. // The width and height of the swap chain must be based on the window's
  559. // landscape-oriented width and height. If the window is in a portrait
  560. // orientation, the dimensions must be reversed.
  561. data->orientation = DisplayProperties::CurrentOrientation;
  562. const bool swapDimensions =
  563. data->orientation == DisplayOrientations::Portrait ||
  564. data->orientation == DisplayOrientations::PortraitFlipped;
  565. data->renderTargetSize.x = swapDimensions ? windowHeight : windowWidth;
  566. data->renderTargetSize.y = swapDimensions ? windowWidth : windowHeight;
  567. if(data->swapChain != nullptr)
  568. {
  569. // If the swap chain already exists, resize it.
  570. result = data->swapChain->ResizeBuffers(
  571. 2, // Double-buffered swap chain.
  572. static_cast<UINT>(data->renderTargetSize.x),
  573. static_cast<UINT>(data->renderTargetSize.y),
  574. DXGI_FORMAT_B8G8R8A8_UNORM,
  575. 0
  576. );
  577. if (FAILED(result)) {
  578. WIN_SetErrorFromHRESULT(__FUNCTION__, result);
  579. return result;
  580. }
  581. }
  582. else
  583. {
  584. // Otherwise, create a new one using the same adapter as the existing Direct3D device.
  585. DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
  586. swapChainDesc.Width = static_cast<UINT>(data->renderTargetSize.x); // Match the size of the window.
  587. swapChainDesc.Height = static_cast<UINT>(data->renderTargetSize.y);
  588. swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // This is the most common swap chain format.
  589. swapChainDesc.Stereo = false;
  590. swapChainDesc.SampleDesc.Count = 1; // Don't use multi-sampling.
  591. swapChainDesc.SampleDesc.Quality = 0;
  592. swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
  593. swapChainDesc.BufferCount = 2; // Use double-buffering to minimize latency.
  594. #if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
  595. swapChainDesc.Scaling = DXGI_SCALING_STRETCH; // On phone, only stretch and aspect-ratio stretch scaling are allowed.
  596. swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; // On phone, no swap effects are supported.
  597. #else
  598. swapChainDesc.Scaling = DXGI_SCALING_NONE;
  599. swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // All Windows Store apps must use this SwapEffect.
  600. #endif
  601. swapChainDesc.Flags = 0;
  602. ComPtr<IDXGIDevice1> dxgiDevice;
  603. result = data->d3dDevice.As(&dxgiDevice);
  604. if (FAILED(result)) {
  605. WIN_SetErrorFromHRESULT(__FUNCTION__, result);
  606. return result;
  607. }
  608. ComPtr<IDXGIAdapter> dxgiAdapter;
  609. result = dxgiDevice->GetAdapter(&dxgiAdapter);
  610. if (FAILED(result)) {
  611. WIN_SetErrorFromHRESULT(__FUNCTION__, result);
  612. return result;
  613. }
  614. ComPtr<IDXGIFactory2> dxgiFactory;
  615. result = dxgiAdapter->GetParent(
  616. __uuidof(IDXGIFactory2),
  617. &dxgiFactory
  618. );
  619. if (FAILED(result)) {
  620. WIN_SetErrorFromHRESULT(__FUNCTION__, result);
  621. return result;
  622. }
  623. IUnknown * coreWindowAsIUnknown = nullptr;
  624. result = coreWindow->QueryInterface(&coreWindowAsIUnknown);
  625. if (FAILED(result)) {
  626. WIN_SetErrorFromHRESULT(__FUNCTION__ ", CoreWindow to IUnknown", result);
  627. return result;
  628. }
  629. result = dxgiFactory->CreateSwapChainForCoreWindow(
  630. data->d3dDevice.Get(),
  631. coreWindowAsIUnknown,
  632. &swapChainDesc,
  633. nullptr, // Allow on all displays.
  634. &data->swapChain
  635. );
  636. if (FAILED(result)) {
  637. WIN_SetErrorFromHRESULT(__FUNCTION__, result);
  638. return result;
  639. }
  640. // Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and
  641. // ensures that the application will only render after each VSync, minimizing power consumption.
  642. result = dxgiDevice->SetMaximumFrameLatency(1);
  643. if (FAILED(result)) {
  644. WIN_SetErrorFromHRESULT(__FUNCTION__, result);
  645. return result;
  646. }
  647. }
  648. // Set the proper orientation for the swap chain, and generate the
  649. // 3D matrix transformation for rendering to the rotated swap chain.
  650. DXGI_MODE_ROTATION rotation = DXGI_MODE_ROTATION_UNSPECIFIED;
  651. switch (data->orientation)
  652. {
  653. case DisplayOrientations::Landscape:
  654. rotation = DXGI_MODE_ROTATION_IDENTITY;
  655. break;
  656. case DisplayOrientations::Portrait:
  657. rotation = DXGI_MODE_ROTATION_ROTATE270;
  658. break;
  659. case DisplayOrientations::LandscapeFlipped:
  660. rotation = DXGI_MODE_ROTATION_ROTATE180;
  661. break;
  662. case DisplayOrientations::PortraitFlipped:
  663. rotation = DXGI_MODE_ROTATION_ROTATE90;
  664. break;
  665. default:
  666. throw ref new Platform::FailureException();
  667. }
  668. #if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
  669. // TODO, WinRT: Windows Phone does not have the IDXGISwapChain1::SetRotation method. Check if an alternative is available, or needed.
  670. result = data->swapChain->SetRotation(rotation);
  671. if (FAILED(result)) {
  672. WIN_SetErrorFromHRESULT(__FUNCTION__, result);
  673. return result;
  674. }
  675. #endif
  676. // Create a render target view of the swap chain back buffer.
  677. ComPtr<ID3D11Texture2D> backBuffer;
  678. result = data->swapChain->GetBuffer(
  679. 0,
  680. __uuidof(ID3D11Texture2D),
  681. &backBuffer
  682. );
  683. if (FAILED(result)) {
  684. WIN_SetErrorFromHRESULT(__FUNCTION__, result);
  685. return result;
  686. }
  687. result = data->d3dDevice->CreateRenderTargetView(
  688. backBuffer.Get(),
  689. nullptr,
  690. &data->mainRenderTargetView
  691. );
  692. if (FAILED(result)) {
  693. WIN_SetErrorFromHRESULT(__FUNCTION__, result);
  694. return result;
  695. }
  696. if (D3D11_UpdateViewport(renderer) != 0) {
  697. // D3D11_UpdateViewport will set the SDL error if it fails.
  698. return E_FAIL;
  699. }
  700. return S_OK;
  701. }
  702. // This method is called when the window's size changes.
  703. HRESULT
  704. D3D11_UpdateForWindowSizeChange(SDL_Renderer * renderer)
  705. {
  706. D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
  707. HRESULT result = S_OK;
  708. ABI::Windows::UI::Core::ICoreWindow * coreWindow = D3D11_GetCoreWindowFromSDLRenderer(renderer);
  709. ABI::Windows::Foundation::Rect coreWindowBounds;
  710. result = coreWindow->get_Bounds(&coreWindowBounds);
  711. if (FAILED(result)) {
  712. WIN_SetErrorFromHRESULT(__FUNCTION__ ", Get Window Bounds", result);
  713. return result;
  714. }
  715. if (coreWindowBounds.Width != data->windowSizeInDIPs.x ||
  716. coreWindowBounds.Height != data->windowSizeInDIPs.y ||
  717. data->orientation != DisplayProperties::CurrentOrientation)
  718. {
  719. ID3D11RenderTargetView* nullViews[] = {nullptr};
  720. data->d3dContext->OMSetRenderTargets(ARRAYSIZE(nullViews), nullViews, nullptr);
  721. data->mainRenderTargetView = nullptr;
  722. data->d3dContext->Flush();
  723. result = D3D11_CreateWindowSizeDependentResources(renderer);
  724. if (FAILED(result)) {
  725. WIN_SetErrorFromHRESULT(__FUNCTION__, result);
  726. return result;
  727. }
  728. }
  729. return S_OK;
  730. }
  731. HRESULT
  732. D3D11_HandleDeviceLost(SDL_Renderer * renderer)
  733. {
  734. D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
  735. HRESULT result = S_OK;
  736. // Reset these member variables to ensure that D3D11_UpdateForWindowSizeChange recreates all resources.
  737. data->windowSizeInDIPs.x = 0;
  738. data->windowSizeInDIPs.y = 0;
  739. data->swapChain = nullptr;
  740. result = D3D11_CreateDeviceResources(renderer);
  741. if (FAILED(result)) {
  742. WIN_SetErrorFromHRESULT(__FUNCTION__, result);
  743. return result;
  744. }
  745. result = D3D11_UpdateForWindowSizeChange(renderer);
  746. if (FAILED(result)) {
  747. WIN_SetErrorFromHRESULT(__FUNCTION__, result);
  748. return result;
  749. }
  750. return S_OK;
  751. }
  752. static void
  753. D3D11_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
  754. {
  755. //D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
  756. if (event->event == SDL_WINDOWEVENT_RESIZED) {
  757. D3D11_UpdateForWindowSizeChange(renderer);
  758. }
  759. }
  760. static int
  761. D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
  762. {
  763. D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  764. D3D11_TextureData *textureData;
  765. HRESULT result;
  766. DXGI_FORMAT textureFormat = SDLPixelFormatToDXGIFormat(texture->format);
  767. if (textureFormat == SDL_PIXELFORMAT_UNKNOWN) {
  768. SDL_SetError("%s, An unsupported SDL pixel format (0x%x) was specified",
  769. __FUNCTION__, texture->format);
  770. return -1;
  771. }
  772. textureData = new D3D11_TextureData;
  773. if (!textureData) {
  774. SDL_OutOfMemory();
  775. return -1;
  776. }
  777. textureData->pixelFormat = SDL_AllocFormat(texture->format);
  778. textureData->lockedTexturePosition = XMINT2(0, 0);
  779. texture->driverdata = textureData;
  780. D3D11_TEXTURE2D_DESC textureDesc = {0};
  781. textureDesc.Width = texture->w;
  782. textureDesc.Height = texture->h;
  783. textureDesc.MipLevels = 1;
  784. textureDesc.ArraySize = 1;
  785. textureDesc.Format = textureFormat;
  786. textureDesc.SampleDesc.Count = 1;
  787. textureDesc.SampleDesc.Quality = 0;
  788. textureDesc.MiscFlags = 0;
  789. if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
  790. textureDesc.Usage = D3D11_USAGE_DYNAMIC;
  791. textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
  792. } else {
  793. textureDesc.Usage = D3D11_USAGE_DEFAULT;
  794. textureDesc.CPUAccessFlags = 0;
  795. }
  796. if (texture->access == SDL_TEXTUREACCESS_TARGET) {
  797. textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
  798. } else {
  799. textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
  800. }
  801. #if 0
  802. // Fill the texture with a non-black color, for debugging purposes:
  803. const int numPixels = textureDesc.Width * textureDesc.Height;
  804. const int pixelSizeInBytes = textureData->pixelFormat->BytesPerPixel;
  805. std::vector<uint8> initialTexturePixels(numPixels * pixelSizeInBytes, 0x00);
  806. for (int i = 0; i < (numPixels * pixelSizeInBytes); i += pixelSizeInBytes) {
  807. initialTexturePixels[i+0] = 0xff;
  808. initialTexturePixels[i+1] = 0xff;
  809. initialTexturePixels[i+2] = 0x00;
  810. initialTexturePixels[i+3] = 0xff;
  811. }
  812. D3D11_SUBRESOURCE_DATA initialTextureData = {0};
  813. initialTextureData.pSysMem = (void *)&(initialTexturePixels[0]);
  814. initialTextureData.SysMemPitch = textureDesc.Width * pixelSizeInBytes;
  815. initialTextureData.SysMemSlicePitch = numPixels * pixelSizeInBytes;
  816. #endif
  817. result = rendererData->d3dDevice->CreateTexture2D(
  818. &textureDesc,
  819. NULL, // &initialTextureData,
  820. &textureData->mainTexture
  821. );
  822. if (FAILED(result)) {
  823. D3D11_DestroyTexture(renderer, texture);
  824. WIN_SetErrorFromHRESULT(__FUNCTION__, result);
  825. return -1;
  826. }
  827. if (texture->access & SDL_TEXTUREACCESS_TARGET) {
  828. D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
  829. renderTargetViewDesc.Format = textureDesc.Format;
  830. renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
  831. renderTargetViewDesc.Texture2D.MipSlice = 0;
  832. result = rendererData->d3dDevice->CreateRenderTargetView(
  833. textureData->mainTexture.Get(),
  834. &renderTargetViewDesc,
  835. &textureData->mainTextureRenderTargetView);
  836. if (FAILED(result)) {
  837. D3D11_DestroyTexture(renderer, texture);
  838. WIN_SetErrorFromHRESULT(__FUNCTION__, result);
  839. return -1;
  840. }
  841. }
  842. D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
  843. resourceViewDesc.Format = textureDesc.Format;
  844. resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
  845. resourceViewDesc.Texture2D.MostDetailedMip = 0;
  846. resourceViewDesc.Texture2D.MipLevels = textureDesc.MipLevels;
  847. result = rendererData->d3dDevice->CreateShaderResourceView(
  848. textureData->mainTexture.Get(),
  849. &resourceViewDesc,
  850. &textureData->mainTextureResourceView
  851. );
  852. if (FAILED(result)) {
  853. D3D11_DestroyTexture(renderer, texture);
  854. WIN_SetErrorFromHRESULT(__FUNCTION__, result);
  855. return -1;
  856. }
  857. return 0;
  858. }
  859. static void
  860. D3D11_DestroyTexture(SDL_Renderer * renderer,
  861. SDL_Texture * texture)
  862. {
  863. D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
  864. if (textureData) {
  865. if (textureData->pixelFormat) {
  866. SDL_FreeFormat(textureData->pixelFormat);
  867. textureData->pixelFormat = NULL;
  868. }
  869. delete textureData;
  870. texture->driverdata = NULL;
  871. }
  872. }
  873. static int
  874. D3D11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
  875. const SDL_Rect * rect, const void * srcPixels,
  876. int srcPitch)
  877. {
  878. // Lock the texture, retrieving a buffer to write pixel data to:
  879. void * destPixels = NULL;
  880. int destPitch = 0;
  881. if (D3D11_LockTexture(renderer, texture, rect, &destPixels, &destPitch) != 0) {
  882. // An error is already set. Attach some info to it, then return to
  883. // the caller.
  884. std::string errorMessage = string(__FUNCTION__ ", Lock Texture Failed: ") + SDL_GetError();
  885. SDL_SetError(errorMessage.c_str());
  886. return -1;
  887. }
  888. // Copy pixel data to the locked texture's memory:
  889. for (int y = 0; y < rect->h; ++y) {
  890. memcpy(
  891. ((Uint8 *)destPixels) + (destPitch * y),
  892. ((Uint8 *)srcPixels) + (srcPitch * y),
  893. srcPitch
  894. );
  895. }
  896. // Commit the texture's memory back to Direct3D:
  897. D3D11_UnlockTexture(renderer, texture);
  898. // Return to the caller:
  899. return 0;
  900. }
  901. static int
  902. D3D11_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
  903. const SDL_Rect * rect, void **pixels, int *pitch)
  904. {
  905. D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  906. D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
  907. HRESULT result = S_OK;
  908. if (textureData->stagingTexture) {
  909. SDL_SetError("texture is already locked");
  910. return -1;
  911. }
  912. // Create a 'staging' texture, which will be used to write to a portion
  913. // of the main texture. This is necessary, as Direct3D 11.1 does not
  914. // have the ability to write a CPU-bound pixel buffer to a rectangular
  915. // subrect of a texture. Direct3D 11.1 can, however, write a pixel
  916. // buffer to an entire texture, hence the use of a staging texture.
  917. D3D11_TEXTURE2D_DESC stagingTextureDesc;
  918. textureData->mainTexture->GetDesc(&stagingTextureDesc);
  919. stagingTextureDesc.Width = rect->w;
  920. stagingTextureDesc.Height = rect->h;
  921. stagingTextureDesc.BindFlags = 0;
  922. stagingTextureDesc.MiscFlags = 0;
  923. stagingTextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
  924. stagingTextureDesc.Usage = D3D11_USAGE_STAGING;
  925. result = rendererData->d3dDevice->CreateTexture2D(
  926. &stagingTextureDesc,
  927. NULL,
  928. &textureData->stagingTexture);
  929. if (FAILED(result)) {
  930. WIN_SetErrorFromHRESULT(__FUNCTION__ ", Create Staging Texture", result);
  931. return -1;
  932. }
  933. // Get a write-only pointer to data in the staging texture:
  934. D3D11_MAPPED_SUBRESOURCE textureMemory = {0};
  935. result = rendererData->d3dContext->Map(
  936. textureData->stagingTexture.Get(),
  937. D3D11CalcSubresource(0, 0, 0),
  938. D3D11_MAP_WRITE,
  939. 0,
  940. &textureMemory
  941. );
  942. if (FAILED(result)) {
  943. WIN_SetErrorFromHRESULT(__FUNCTION__ ", Map Staging Texture", result);
  944. textureData->stagingTexture = nullptr;
  945. return -1;
  946. }
  947. // Make note of where the staging texture will be written to (on a
  948. // call to SDL_UnlockTexture):
  949. textureData->lockedTexturePosition = XMINT2(rect->x, rect->y);
  950. // Make sure the caller has information on the texture's pixel buffer,
  951. // then return:
  952. *pixels = textureMemory.pData;
  953. *pitch = textureMemory.RowPitch;
  954. return 0;
  955. }
  956. static void
  957. D3D11_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
  958. {
  959. D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  960. D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
  961. // Commit the pixel buffer's changes back to the staging texture:
  962. rendererData->d3dContext->Unmap(
  963. textureData->stagingTexture.Get(),
  964. 0);
  965. // Copy the staging texture's contents back to the main texture:
  966. rendererData->d3dContext->CopySubresourceRegion(
  967. textureData->mainTexture.Get(),
  968. D3D11CalcSubresource(0, 0, 0),
  969. textureData->lockedTexturePosition.x,
  970. textureData->lockedTexturePosition.y,
  971. 0,
  972. textureData->stagingTexture.Get(),
  973. D3D11CalcSubresource(0, 0, 0),
  974. NULL);
  975. // Clean up and return:
  976. textureData->stagingTexture = nullptr;
  977. textureData->lockedTexturePosition = XMINT2(0, 0);
  978. }
  979. static int
  980. D3D11_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
  981. {
  982. D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  983. if (texture == NULL) {
  984. rendererData->currentOffscreenRenderTargetView = nullptr;
  985. return 0;
  986. }
  987. D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
  988. if (!textureData->mainTextureRenderTargetView) {
  989. std::string errorMessage = string(__FUNCTION__) + ": specified texture is not a render target";
  990. SDL_SetError(errorMessage.c_str());
  991. return -1;
  992. }
  993. rendererData->currentOffscreenRenderTargetView = textureData->mainTextureRenderTargetView;
  994. return 0;
  995. }
  996. static int
  997. D3D11_UpdateViewport(SDL_Renderer * renderer)
  998. {
  999. D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
  1000. if (renderer->viewport.w == 0 || renderer->viewport.h == 0) {
  1001. // If the viewport is empty, assume that it is because
  1002. // SDL_CreateRenderer is calling it, and will call it again later
  1003. // with a non-empty viewport.
  1004. return 0;
  1005. }
  1006. switch (data->orientation)
  1007. {
  1008. case DisplayOrientations::Landscape:
  1009. data->vertexShaderConstantsData.projection = XMFLOAT4X4( // 0-degree Z-rotation
  1010. 1.0f, 0.0f, 0.0f, 0.0f,
  1011. 0.0f, 1.0f, 0.0f, 0.0f,
  1012. 0.0f, 0.0f, 1.0f, 0.0f,
  1013. 0.0f, 0.0f, 0.0f, 1.0f
  1014. );
  1015. break;
  1016. case DisplayOrientations::Portrait:
  1017. data->vertexShaderConstantsData.projection = XMFLOAT4X4( // 90-degree Z-rotation
  1018. 0.0f, 1.0f, 0.0f, 0.0f,
  1019. -1.0f, 0.0f, 0.0f, 0.0f,
  1020. 0.0f, 0.0f, 1.0f, 0.0f,
  1021. 0.0f, 0.0f, 0.0f, 1.0f
  1022. );
  1023. break;
  1024. case DisplayOrientations::LandscapeFlipped:
  1025. data->vertexShaderConstantsData.projection = XMFLOAT4X4( // 180-degree Z-rotation
  1026. -1.0f, 0.0f, 0.0f, 0.0f,
  1027. 0.0f, -1.0f, 0.0f, 0.0f,
  1028. 0.0f, 0.0f, 1.0f, 0.0f,
  1029. 0.0f, 0.0f, 0.0f, 1.0f
  1030. );
  1031. break;
  1032. case DisplayOrientations::PortraitFlipped:
  1033. data->vertexShaderConstantsData.projection = XMFLOAT4X4( // 270-degree Z-rotation
  1034. 0.0f, -1.0f, 0.0f, 0.0f,
  1035. 1.0f, 0.0f, 0.0f, 0.0f,
  1036. 0.0f, 0.0f, 1.0f, 0.0f,
  1037. 0.0f, 0.0f, 0.0f, 1.0f
  1038. );
  1039. break;
  1040. default:
  1041. SDL_SetError("An unknown DisplayOrientation is being used");
  1042. return -1;
  1043. }
  1044. //
  1045. // Update the view matrix
  1046. //
  1047. float viewportWidth = (float) renderer->viewport.w;
  1048. float viewportHeight = (float) renderer->viewport.h;
  1049. XMStoreFloat4x4(&data->vertexShaderConstantsData.view,
  1050. XMMatrixMultiply(
  1051. XMMatrixScaling(2.0f / viewportWidth, 2.0f / viewportHeight, 1.0f),
  1052. XMMatrixMultiply(
  1053. XMMatrixTranslation(-1, -1, 0),
  1054. XMMatrixRotationX(XM_PI)
  1055. )));
  1056. #if 0
  1057. data->vertexShaderConstantsData.view = XMMatrixIdentity();
  1058. #endif
  1059. //
  1060. // Reset the model matrix
  1061. //
  1062. XMStoreFloat4x4(&data->vertexShaderConstantsData.model, XMMatrixIdentity());
  1063. //
  1064. // Update the Direct3D viewport, which seems to be aligned to the
  1065. // swap buffer's coordinate space, which is always in landscape:
  1066. //
  1067. SDL_FRect orientationAlignedViewport;
  1068. const bool swapDimensions =
  1069. data->orientation == DisplayOrientations::Portrait ||
  1070. data->orientation == DisplayOrientations::PortraitFlipped;
  1071. if (swapDimensions) {
  1072. orientationAlignedViewport.x = (float) renderer->viewport.y;
  1073. orientationAlignedViewport.y = (float) renderer->viewport.x;
  1074. orientationAlignedViewport.w = (float) renderer->viewport.h;
  1075. orientationAlignedViewport.h = (float) renderer->viewport.w;
  1076. } else {
  1077. orientationAlignedViewport.x = (float) renderer->viewport.x;
  1078. orientationAlignedViewport.y = (float) renderer->viewport.y;
  1079. orientationAlignedViewport.w = (float) renderer->viewport.w;
  1080. orientationAlignedViewport.h = (float) renderer->viewport.h;
  1081. }
  1082. // TODO, WinRT: get custom viewports working with non-Landscape modes (Portrait, PortraitFlipped, and LandscapeFlipped)
  1083. D3D11_VIEWPORT viewport;
  1084. memset(&viewport, 0, sizeof(viewport));
  1085. viewport.TopLeftX = orientationAlignedViewport.x;
  1086. viewport.TopLeftY = orientationAlignedViewport.y;
  1087. viewport.Width = orientationAlignedViewport.w;
  1088. viewport.Height = orientationAlignedViewport.h;
  1089. viewport.MinDepth = 0.0f;
  1090. viewport.MaxDepth = 1.0f;
  1091. data->d3dContext->RSSetViewports(1, &viewport);
  1092. #if 0
  1093. SDL_Log("%s, oav={%.0f,%.0f,%.0f,%.0f}, rend={%.0f,%.0f}\n",
  1094. __FUNCTION__,
  1095. orientationAlignedViewport.x,
  1096. orientationAlignedViewport.y,
  1097. orientationAlignedViewport.w,
  1098. orientationAlignedViewport.h,
  1099. data->renderTargetSize.x,
  1100. data->renderTargetSize.y);
  1101. #endif
  1102. return 0;
  1103. }
  1104. static int
  1105. D3D11_UpdateClipRect(SDL_Renderer * renderer)
  1106. {
  1107. // TODO, WinRT: implement D3D11_UpdateClipRect
  1108. return 0;
  1109. }
  1110. static ComPtr<ID3D11RenderTargetView> &
  1111. D3D11_GetCurrentRenderTargetView(SDL_Renderer * renderer)
  1112. {
  1113. D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
  1114. if (data->currentOffscreenRenderTargetView) {
  1115. return data->currentOffscreenRenderTargetView;
  1116. } else {
  1117. return data->mainRenderTargetView;
  1118. }
  1119. }
  1120. static int
  1121. D3D11_RenderClear(SDL_Renderer * renderer)
  1122. {
  1123. D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
  1124. const float colorRGBA[] = {
  1125. (renderer->r / 255.0f),
  1126. (renderer->g / 255.0f),
  1127. (renderer->b / 255.0f),
  1128. (renderer->a / 255.0f)
  1129. };
  1130. data->d3dContext->ClearRenderTargetView(
  1131. D3D11_GetCurrentRenderTargetView(renderer).Get(),
  1132. colorRGBA
  1133. );
  1134. return 0;
  1135. }
  1136. static int
  1137. D3D11_UpdateVertexBuffer(SDL_Renderer *renderer,
  1138. const void * vertexData, unsigned int dataSizeInBytes)
  1139. {
  1140. D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  1141. HRESULT result = S_OK;
  1142. D3D11_BUFFER_DESC vertexBufferDesc;
  1143. if (rendererData->vertexBuffer) {
  1144. rendererData->vertexBuffer->GetDesc(&vertexBufferDesc);
  1145. } else {
  1146. memset(&vertexBufferDesc, 0, sizeof(vertexBufferDesc));
  1147. }
  1148. if (vertexBufferDesc.ByteWidth >= dataSizeInBytes) {
  1149. rendererData->d3dContext->UpdateSubresource(rendererData->vertexBuffer.Get(), 0, NULL, vertexData, dataSizeInBytes, 0);
  1150. } else {
  1151. vertexBufferDesc.ByteWidth = dataSizeInBytes;
  1152. vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
  1153. D3D11_SUBRESOURCE_DATA vertexBufferData = {0};
  1154. vertexBufferData.pSysMem = vertexData;
  1155. vertexBufferData.SysMemPitch = 0;
  1156. vertexBufferData.SysMemSlicePitch = 0;
  1157. result = rendererData->d3dDevice->CreateBuffer(
  1158. &vertexBufferDesc,
  1159. &vertexBufferData,
  1160. &rendererData->vertexBuffer
  1161. );
  1162. if (FAILED(result)) {
  1163. WIN_SetErrorFromHRESULT(__FUNCTION__, result);
  1164. return -1;
  1165. }
  1166. }
  1167. UINT stride = sizeof(VertexPositionColor);
  1168. UINT offset = 0;
  1169. rendererData->d3dContext->IASetVertexBuffers(
  1170. 0,
  1171. 1,
  1172. rendererData->vertexBuffer.GetAddressOf(),
  1173. &stride,
  1174. &offset
  1175. );
  1176. return 0;
  1177. }
  1178. static void
  1179. D3D11_RenderStartDrawOp(SDL_Renderer * renderer)
  1180. {
  1181. D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  1182. rendererData->d3dContext->OMSetRenderTargets(
  1183. 1,
  1184. D3D11_GetCurrentRenderTargetView(renderer).GetAddressOf(),
  1185. nullptr
  1186. );
  1187. }
  1188. static void
  1189. D3D11_RenderSetBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
  1190. {
  1191. D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  1192. switch (blendMode) {
  1193. case SDL_BLENDMODE_BLEND:
  1194. rendererData->d3dContext->OMSetBlendState(rendererData->blendModeBlend.Get(), 0, 0xFFFFFFFF);
  1195. break;
  1196. case SDL_BLENDMODE_ADD:
  1197. rendererData->d3dContext->OMSetBlendState(rendererData->blendModeAdd.Get(), 0, 0xFFFFFFFF);
  1198. break;
  1199. case SDL_BLENDMODE_MOD:
  1200. rendererData->d3dContext->OMSetBlendState(rendererData->blendModeMod.Get(), 0, 0xFFFFFFFF);
  1201. break;
  1202. case SDL_BLENDMODE_NONE:
  1203. rendererData->d3dContext->OMSetBlendState(NULL, 0, 0xFFFFFFFF);
  1204. break;
  1205. }
  1206. }
  1207. static void
  1208. D3D11_SetPixelShader(SDL_Renderer * renderer,
  1209. ID3D11PixelShader * shader,
  1210. ID3D11ShaderResourceView * shaderResource,
  1211. ID3D11SamplerState * sampler)
  1212. {
  1213. D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  1214. rendererData->d3dContext->PSSetShader(shader, nullptr, 0);
  1215. rendererData->d3dContext->PSSetShaderResources(0, 1, &shaderResource);
  1216. rendererData->d3dContext->PSSetSamplers(0, 1, &sampler);
  1217. }
  1218. static void
  1219. D3D11_RenderFinishDrawOp(SDL_Renderer * renderer,
  1220. D3D11_PRIMITIVE_TOPOLOGY primitiveTopology,
  1221. UINT vertexCount)
  1222. {
  1223. D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  1224. rendererData->d3dContext->UpdateSubresource(
  1225. rendererData->vertexShaderConstants.Get(),
  1226. 0,
  1227. NULL,
  1228. &rendererData->vertexShaderConstantsData,
  1229. 0,
  1230. 0
  1231. );
  1232. rendererData->d3dContext->IASetPrimitiveTopology(primitiveTopology);
  1233. rendererData->d3dContext->IASetInputLayout(rendererData->inputLayout.Get());
  1234. rendererData->d3dContext->VSSetShader(rendererData->vertexShader.Get(), nullptr, 0);
  1235. rendererData->d3dContext->VSSetConstantBuffers(0, 1, rendererData->vertexShaderConstants.GetAddressOf());
  1236. rendererData->d3dContext->RSSetState(rendererData->mainRasterizer.Get());
  1237. rendererData->d3dContext->Draw(vertexCount, 0);
  1238. }
  1239. static int
  1240. D3D11_RenderDrawPoints(SDL_Renderer * renderer,
  1241. const SDL_FPoint * points, int count)
  1242. {
  1243. D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  1244. float r, g, b, a;
  1245. r = (float)(renderer->r / 255.0f);
  1246. g = (float)(renderer->g / 255.0f);
  1247. b = (float)(renderer->b / 255.0f);
  1248. a = (float)(renderer->a / 255.0f);
  1249. vector<VertexPositionColor> vertices;
  1250. vertices.reserve(count);
  1251. for (int i = 0; i < count; ++i) {
  1252. VertexPositionColor v = {XMFLOAT3(points[i].x, points[i].y, 0.0f), XMFLOAT2(0.0f, 0.0f), XMFLOAT4(r, g, b, a)};
  1253. vertices.push_back(v);
  1254. }
  1255. D3D11_RenderStartDrawOp(renderer);
  1256. D3D11_RenderSetBlendMode(renderer, renderer->blendMode);
  1257. if (D3D11_UpdateVertexBuffer(renderer, &vertices[0], vertices.size() * sizeof(VertexPositionColor)) != 0) {
  1258. return -1;
  1259. }
  1260. D3D11_SetPixelShader(
  1261. renderer,
  1262. rendererData->colorPixelShader.Get(),
  1263. nullptr,
  1264. nullptr);
  1265. D3D11_RenderFinishDrawOp(renderer, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, vertices.size());
  1266. return 0;
  1267. }
  1268. static int
  1269. D3D11_RenderDrawLines(SDL_Renderer * renderer,
  1270. const SDL_FPoint * points, int count)
  1271. {
  1272. D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  1273. float r, g, b, a;
  1274. r = (float)(renderer->r / 255.0f);
  1275. g = (float)(renderer->g / 255.0f);
  1276. b = (float)(renderer->b / 255.0f);
  1277. a = (float)(renderer->a / 255.0f);
  1278. vector<VertexPositionColor> vertices;
  1279. vertices.reserve(count);
  1280. for (int i = 0; i < count; ++i) {
  1281. VertexPositionColor v = {XMFLOAT3(points[i].x, points[i].y, 0.0f), XMFLOAT2(0.0f, 0.0f), XMFLOAT4(r, g, b, a)};
  1282. vertices.push_back(v);
  1283. }
  1284. D3D11_RenderStartDrawOp(renderer);
  1285. D3D11_RenderSetBlendMode(renderer, renderer->blendMode);
  1286. if (D3D11_UpdateVertexBuffer(renderer, &vertices[0], vertices.size() * sizeof(VertexPositionColor)) != 0) {
  1287. return -1;
  1288. }
  1289. D3D11_SetPixelShader(
  1290. renderer,
  1291. rendererData->colorPixelShader.Get(),
  1292. nullptr,
  1293. nullptr);
  1294. D3D11_RenderFinishDrawOp(renderer, D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP, vertices.size());
  1295. return 0;
  1296. }
  1297. static int
  1298. D3D11_RenderFillRects(SDL_Renderer * renderer,
  1299. const SDL_FRect * rects, int count)
  1300. {
  1301. D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  1302. float r, g, b, a;
  1303. r = (float)(renderer->r / 255.0f);
  1304. g = (float)(renderer->g / 255.0f);
  1305. b = (float)(renderer->b / 255.0f);
  1306. a = (float)(renderer->a / 255.0f);
  1307. #if 0
  1308. // Set up a test pattern:
  1309. SDL_FRect _rects[] = {
  1310. {-1.1f, 1.1f, 1.1f, -1.1f},
  1311. {-1.0f, 1.0f, 1.0f, -1.0f}, // red
  1312. {0.0f, 1.0f, 1.0f, -1.0f}, // green
  1313. {-1.0f, 0.0f, 1.0f, -1.0f}, // blue
  1314. {0.0f, 0.0f, 1.0f, -1.0f} // white
  1315. };
  1316. count = sizeof(_rects) / sizeof(SDL_FRect);
  1317. #define rects _rects
  1318. #endif
  1319. for (int i = 0; i < count; ++i) {
  1320. D3D11_RenderStartDrawOp(renderer);
  1321. D3D11_RenderSetBlendMode(renderer, renderer->blendMode);
  1322. #if 0
  1323. // Set colors for the test pattern:
  1324. a = 1.0f;
  1325. switch (i) {
  1326. case 0: r = 1.0f; g = 1.0f; b = 0.0f; break;
  1327. case 1: r = 1.0f; g = 0.0f; b = 0.0f; break;
  1328. case 2: r = 0.0f; g = 1.0f; b = 0.0f; break;
  1329. case 3: r = 0.0f; g = 0.0f; b = 1.0f; break;
  1330. case 4: r = 1.0f; g = 1.0f; b = 1.0f; break;
  1331. }
  1332. #endif
  1333. VertexPositionColor vertices[] = {
  1334. {XMFLOAT3(rects[i].x, rects[i].y, 0.0f), XMFLOAT2(0.0f, 0.0f), XMFLOAT4(r, g, b, a)},
  1335. {XMFLOAT3(rects[i].x, rects[i].y + rects[i].h, 0.0f), XMFLOAT2(0.0f, 0.0f), XMFLOAT4(r, g, b, a)},
  1336. {XMFLOAT3(rects[i].x + rects[i].w, rects[i].y, 0.0f), XMFLOAT2(0.0f, 0.0f), XMFLOAT4(r, g, b, a)},
  1337. {XMFLOAT3(rects[i].x + rects[i].w, rects[i].y + rects[i].h, 0.0f), XMFLOAT2(0.0f, 0.0f), XMFLOAT4(r, g, b, a)},
  1338. };
  1339. if (D3D11_UpdateVertexBuffer(renderer, vertices, sizeof(vertices)) != 0) {
  1340. return -1;
  1341. }
  1342. D3D11_SetPixelShader(
  1343. renderer,
  1344. rendererData->colorPixelShader.Get(),
  1345. nullptr,
  1346. nullptr);
  1347. D3D11_RenderFinishDrawOp(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, sizeof(vertices) / sizeof(VertexPositionColor));
  1348. }
  1349. return 0;
  1350. }
  1351. static int
  1352. D3D11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
  1353. const SDL_Rect * srcrect, const SDL_FRect * dstrect)
  1354. {
  1355. D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  1356. D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
  1357. D3D11_RenderStartDrawOp(renderer);
  1358. D3D11_RenderSetBlendMode(renderer, texture->blendMode);
  1359. float minu = (float) srcrect->x / texture->w;
  1360. float maxu = (float) (srcrect->x + srcrect->w) / texture->w;
  1361. float minv = (float) srcrect->y / texture->h;
  1362. float maxv = (float) (srcrect->y + srcrect->h) / texture->h;
  1363. float r = 1.0f;
  1364. float g = 1.0f;
  1365. float b = 1.0f;
  1366. float a = 1.0f;
  1367. if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
  1368. r = (float)(texture->r / 255.0f);
  1369. g = (float)(texture->g / 255.0f);
  1370. b = (float)(texture->b / 255.0f);
  1371. }
  1372. if (texture->modMode & SDL_TEXTUREMODULATE_ALPHA) {
  1373. a = (float)(texture->a / 255.0f);
  1374. }
  1375. VertexPositionColor vertices[] = {
  1376. {XMFLOAT3(dstrect->x, dstrect->y, 0.0f), XMFLOAT2(minu, minv), XMFLOAT4(r, g, b, a)},
  1377. {XMFLOAT3(dstrect->x, dstrect->y + dstrect->h, 0.0f), XMFLOAT2(minu, maxv), XMFLOAT4(r, g, b, a)},
  1378. {XMFLOAT3(dstrect->x + dstrect->w, dstrect->y, 0.0f), XMFLOAT2(maxu, minv), XMFLOAT4(r, g, b, a)},
  1379. {XMFLOAT3(dstrect->x + dstrect->w, dstrect->y + dstrect->h, 0.0f), XMFLOAT2(maxu, maxv), XMFLOAT4(r, g, b, a)},
  1380. };
  1381. if (D3D11_UpdateVertexBuffer(renderer, vertices, sizeof(vertices)) != 0) {
  1382. return -1;
  1383. }
  1384. D3D11_SetPixelShader(
  1385. renderer,
  1386. rendererData->texturePixelShader.Get(),
  1387. textureData->mainTextureResourceView.Get(),
  1388. rendererData->mainSampler.Get());
  1389. D3D11_RenderFinishDrawOp(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, sizeof(vertices) / sizeof(VertexPositionColor));
  1390. return 0;
  1391. }
  1392. static int
  1393. D3D11_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
  1394. const SDL_Rect * srcrect, const SDL_FRect * dstrect,
  1395. const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip)
  1396. {
  1397. D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
  1398. D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
  1399. D3D11_RenderStartDrawOp(renderer);
  1400. D3D11_RenderSetBlendMode(renderer, texture->blendMode);
  1401. float minu = (float) srcrect->x / texture->w;
  1402. float maxu = (float) (srcrect->x + srcrect->w) / texture->w;
  1403. float minv = (float) srcrect->y / texture->h;
  1404. float maxv = (float) (srcrect->y + srcrect->h) / texture->h;
  1405. float r = 1.0f;
  1406. float g = 1.0f;
  1407. float b = 1.0f;
  1408. float a = 1.0f;
  1409. if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
  1410. r = (float)(texture->r / 255.0f);
  1411. g = (float)(texture->g / 255.0f);
  1412. b = (float)(texture->b / 255.0f);
  1413. }
  1414. if (texture->modMode & SDL_TEXTUREMODULATE_ALPHA) {
  1415. a = (float)(texture->a / 255.0f);
  1416. }
  1417. if (flip & SDL_FLIP_HORIZONTAL) {
  1418. float tmp = maxu;
  1419. maxu = minu;
  1420. minu = tmp;
  1421. }
  1422. if (flip & SDL_FLIP_VERTICAL) {
  1423. float tmp = maxv;
  1424. maxv = minv;
  1425. minv = tmp;
  1426. }
  1427. XMFLOAT4X4 oldModelMatrix = rendererData->vertexShaderConstantsData.model;
  1428. XMStoreFloat4x4(
  1429. &rendererData->vertexShaderConstantsData.model,
  1430. XMMatrixMultiply(
  1431. XMMatrixRotationZ((float)(XM_PI * (float) angle / 180.0f)),
  1432. XMMatrixTranslation(dstrect->x + center->x, dstrect->y + center->y, 0)
  1433. ));
  1434. const float minx = -center->x;
  1435. const float maxx = dstrect->w - center->x;
  1436. const float miny = -center->y;
  1437. const float maxy = dstrect->h - center->y;
  1438. VertexPositionColor vertices[] = {
  1439. {XMFLOAT3(minx, miny, 0.0f), XMFLOAT2(minu, minv), XMFLOAT4(r, g, b, a)},
  1440. {XMFLOAT3(minx, maxy, 0.0f), XMFLOAT2(minu, maxv), XMFLOAT4(r, g, b, a)},
  1441. {XMFLOAT3(maxx, miny, 0.0f), XMFLOAT2(maxu, minv), XMFLOAT4(r, g, b, a)},
  1442. {XMFLOAT3(maxx, maxy, 0.0f), XMFLOAT2(maxu, maxv), XMFLOAT4(r, g, b, a)},
  1443. };
  1444. if (D3D11_UpdateVertexBuffer(renderer, vertices, sizeof(vertices)) != 0) {
  1445. return -1;
  1446. }
  1447. D3D11_SetPixelShader(
  1448. renderer,
  1449. rendererData->texturePixelShader.Get(),
  1450. textureData->mainTextureResourceView.Get(),
  1451. rendererData->mainSampler.Get());
  1452. D3D11_RenderFinishDrawOp(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, sizeof(vertices) / sizeof(VertexPositionColor));
  1453. rendererData->vertexShaderConstantsData.model = oldModelMatrix;
  1454. return 0;
  1455. }
  1456. static int
  1457. D3D11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
  1458. Uint32 format, void * pixels, int pitch)
  1459. {
  1460. D3D11_RenderData * data = (D3D11_RenderData *) renderer->driverdata;
  1461. HRESULT result = S_OK;
  1462. // Retrieve a pointer to the back buffer:
  1463. ComPtr<ID3D11Texture2D> backBuffer;
  1464. result = data->swapChain->GetBuffer(
  1465. 0,
  1466. __uuidof(ID3D11Texture2D),
  1467. &backBuffer
  1468. );
  1469. if (FAILED(result)) {
  1470. WIN_SetErrorFromHRESULT(__FUNCTION__ ", Get Back Buffer", result);
  1471. return -1;
  1472. }
  1473. // Create a staging texture to copy the screen's data to:
  1474. ComPtr<ID3D11Texture2D> stagingTexture;
  1475. D3D11_TEXTURE2D_DESC stagingTextureDesc;
  1476. backBuffer->GetDesc(&stagingTextureDesc);
  1477. stagingTextureDesc.Width = rect->w;
  1478. stagingTextureDesc.Height = rect->h;
  1479. stagingTextureDesc.BindFlags = 0;
  1480. stagingTextureDesc.MiscFlags = 0;
  1481. stagingTextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
  1482. stagingTextureDesc.Usage = D3D11_USAGE_STAGING;
  1483. result = data->d3dDevice->CreateTexture2D(
  1484. &stagingTextureDesc,
  1485. NULL,
  1486. &stagingTexture);
  1487. if (FAILED(result)) {
  1488. WIN_SetErrorFromHRESULT(__FUNCTION__ ", Create Staging Texture", result);
  1489. return -1;
  1490. }
  1491. // Copy the desired portion of the back buffer to the staging texture:
  1492. D3D11_BOX srcBox;
  1493. srcBox.left = rect->x;
  1494. srcBox.right = rect->x + rect->w;
  1495. srcBox.top = rect->y;
  1496. srcBox.bottom = rect->y + rect->h;
  1497. srcBox.front = 0;
  1498. srcBox.back = 1;
  1499. data->d3dContext->CopySubresourceRegion(
  1500. stagingTexture.Get(),
  1501. D3D11CalcSubresource(0, 0, 0),
  1502. 0, 0, 0,
  1503. backBuffer.Get(),
  1504. D3D11CalcSubresource(0, 0, 0),
  1505. &srcBox);
  1506. // Map the staging texture's data to CPU-accessible memory:
  1507. D3D11_MAPPED_SUBRESOURCE textureMemory = {0};
  1508. result = data->d3dContext->Map(
  1509. stagingTexture.Get(),
  1510. D3D11CalcSubresource(0, 0, 0),
  1511. D3D11_MAP_READ,
  1512. 0,
  1513. &textureMemory);
  1514. if (FAILED(result)) {
  1515. WIN_SetErrorFromHRESULT(__FUNCTION__ ", Map Staging Texture to CPU Memory", result);
  1516. return -1;
  1517. }
  1518. // Copy the data into the desired buffer, converting pixels to the
  1519. // desired format at the same time:
  1520. if (SDL_ConvertPixels(
  1521. rect->w, rect->h,
  1522. DXGIFormatToSDLPixelFormat(stagingTextureDesc.Format),
  1523. textureMemory.pData,
  1524. textureMemory.RowPitch,
  1525. format,
  1526. pixels,
  1527. pitch) != 0)
  1528. {
  1529. // When SDL_ConvertPixels fails, it'll have already set the format.
  1530. // Get the error message, and attach some extra data to it.
  1531. std::string errorMessage = string(__FUNCTION__ ", Convert Pixels failed: ") + SDL_GetError();
  1532. SDL_SetError(errorMessage.c_str());
  1533. return -1;
  1534. }
  1535. // Unmap the texture:
  1536. data->d3dContext->Unmap(
  1537. stagingTexture.Get(),
  1538. D3D11CalcSubresource(0, 0, 0));
  1539. // All done. The staging texture will be cleaned up in it's container
  1540. // ComPtr<>'s destructor.
  1541. return 0;
  1542. }
  1543. static void
  1544. D3D11_RenderPresent(SDL_Renderer * renderer)
  1545. {
  1546. D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
  1547. #if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
  1548. // The first argument instructs DXGI to block until VSync, putting the application
  1549. // to sleep until the next VSync. This ensures we don't waste any cycles rendering
  1550. // frames that will never be displayed to the screen.
  1551. HRESULT hr = data->swapChain->Present(1, 0);
  1552. #else
  1553. // The application may optionally specify "dirty" or "scroll"
  1554. // rects to improve efficiency in certain scenarios.
  1555. // This option is not available on Windows Phone 8, to note.
  1556. DXGI_PRESENT_PARAMETERS parameters = {0};
  1557. parameters.DirtyRectsCount = 0;
  1558. parameters.pDirtyRects = nullptr;
  1559. parameters.pScrollRect = nullptr;
  1560. parameters.pScrollOffset = nullptr;
  1561. // The first argument instructs DXGI to block until VSync, putting the application
  1562. // to sleep until the next VSync. This ensures we don't waste any cycles rendering
  1563. // frames that will never be displayed to the screen.
  1564. HRESULT hr = data->swapChain->Present1(1, 0, &parameters);
  1565. #endif
  1566. // Discard the contents of the render target.
  1567. // This is a valid operation only when the existing contents will be entirely
  1568. // overwritten. If dirty or scroll rects are used, this call should be removed.
  1569. data->d3dContext->DiscardView(data->mainRenderTargetView.Get());
  1570. // If the device was removed either by a disconnect or a driver upgrade, we
  1571. // must recreate all device resources.
  1572. //
  1573. // TODO, WinRT: consider throwing an exception if D3D11_RenderPresent fails, especially if there is a way to salvedge debug info from users' machines
  1574. if (hr == DXGI_ERROR_DEVICE_REMOVED)
  1575. {
  1576. hr = D3D11_HandleDeviceLost(renderer);
  1577. if (FAILED(hr)) {
  1578. WIN_SetErrorFromHRESULT(__FUNCTION__, hr);
  1579. }
  1580. }
  1581. else
  1582. {
  1583. WIN_SetErrorFromHRESULT(__FUNCTION__, hr);
  1584. }
  1585. }
  1586. #endif /* SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED */
  1587. /* vi: set ts=4 sw=4 expandtab: */