Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

647 lines
16 KiB

  1. /***************************************************************************\
  2. *
  3. * File: DxManager.cpp
  4. *
  5. * Description:
  6. * DxManager.cpp implements the process-wide DirectX manager used for all
  7. * DirectDraw, Direct3D, and DirectX Transforms services.
  8. *
  9. *
  10. * History:
  11. * 1/18/2000: JStall: Created
  12. *
  13. * Copyright (C) 2000 by Microsoft Corporation. All rights reserved.
  14. *
  15. \***************************************************************************/
  16. #include "stdafx.h"
  17. #include "Services.h"
  18. #include "DxManager.h"
  19. #include "GdiCache.h"
  20. #include "Buffer.h"
  21. #include "ResourceManager.h"
  22. /***************************************************************************\
  23. *****************************************************************************
  24. *
  25. * class DxManager
  26. *
  27. *****************************************************************************
  28. \***************************************************************************/
  29. //------------------------------------------------------------------------------
  30. DxManager::DxManager()
  31. {
  32. m_cDDrawRef = 0;
  33. m_cDxTxRef = 0;
  34. }
  35. //------------------------------------------------------------------------------
  36. DxManager::~DxManager()
  37. {
  38. #if DBG
  39. if (m_hDllDxDraw != NULL) {
  40. Trace("DUser Warning: Application did not call UninitGadgetComponent() to\n");
  41. Trace(" deinitialize properly\n");
  42. }
  43. #endif // DBG
  44. }
  45. /***************************************************************************\
  46. *
  47. * DxManager::Init
  48. *
  49. * Init() initializes the DxManager by loading COM and core DirectX services.
  50. *
  51. \***************************************************************************/
  52. HRESULT
  53. DxManager::Init(GUID * pguidDriver)
  54. {
  55. if (m_hDllDxDraw == NULL) {
  56. //
  57. // Normal DirectDraw does not need COM to be initialized.
  58. //
  59. m_hDllDxDraw = LoadLibrary("ddraw.dll");
  60. if (m_hDllDxDraw == NULL) {
  61. return DU_E_GENERIC;
  62. }
  63. //
  64. // Load the functions.
  65. //
  66. // NOTE: On older versions of DirectDraw, DirectDrawCreateEx() doesn't
  67. // exist. We need to specifically check this.
  68. //
  69. m_pfnCreate = (DirectDrawCreateProc) GetProcAddress(m_hDllDxDraw, _T("DirectDrawCreate"));
  70. m_pfnCreateEx = (DirectDrawCreateExProc) GetProcAddress(m_hDllDxDraw, _T("DirectDrawCreateEx"));
  71. if (m_pfnCreate == NULL) {
  72. goto errorexit;
  73. }
  74. //
  75. // First, try creating the most advance interface.
  76. //
  77. HRESULT hr;
  78. if (m_pfnCreateEx != NULL) {
  79. hr = (m_pfnCreateEx)(pguidDriver, (void **) &m_pDD7, IID_IDirectDraw7, NULL);
  80. if (SUCCEEDED(hr)) {
  81. AssertReadPtr(m_pDD7);
  82. m_pDD7->SetCooperativeLevel(NULL, DDSCL_NORMAL);
  83. //
  84. // Try to get an IDirectDraw interface as well.
  85. //
  86. m_pDD7->QueryInterface(IID_IDirectDraw, (void **) &m_pDD);
  87. {
  88. HRESULT hRet;
  89. DDSURFACEDESC2 ddsd;
  90. IDirectDrawSurface7 * pDD;
  91. ZeroMemory(&ddsd, sizeof(ddsd));
  92. ddsd.dwSize = sizeof(ddsd);
  93. ddsd.dwFlags = DDSD_CAPS;
  94. ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  95. hRet = m_pDD7->CreateSurface(&ddsd, &pDD, NULL);
  96. if (hRet == DD_OK)
  97. pDD->Release();
  98. }
  99. } else {
  100. //
  101. // Explicitly set to NULL
  102. //
  103. m_pDD7 = NULL;
  104. }
  105. }
  106. //
  107. // If can't create advanced interface, go for backup
  108. //
  109. if (m_pDD7 == NULL) {
  110. AssertReadPtr(m_pfnCreate);
  111. hr = (m_pfnCreate)(pguidDriver, &m_pDD, NULL);
  112. if (SUCCEEDED(hr)) {
  113. m_pDD->SetCooperativeLevel(NULL, DDSCL_NORMAL);
  114. } else {
  115. //
  116. // Unable to initialize DirectDraw, so need to bail.
  117. //
  118. goto errorexit;
  119. }
  120. }
  121. }
  122. m_cDDrawRef++;
  123. return S_OK;
  124. errorexit:
  125. Uninit();
  126. return DU_E_GENERIC;
  127. }
  128. //------------------------------------------------------------------------------
  129. void
  130. DxManager::Uninit()
  131. {
  132. if (m_cDDrawRef <= 0) {
  133. return;
  134. }
  135. m_cDDrawRef--;
  136. if (m_cDDrawRef <= 0) {
  137. //
  138. // Can't call Release() on the IDirectDraw interfaces here b/c we are
  139. // shutting down and their v-tbl's are messed up. Bummer.
  140. //
  141. SafeRelease(m_pDD7);
  142. SafeRelease(m_pDD);
  143. if (m_hDllDxDraw != NULL) {
  144. FreeLibrary(m_hDllDxDraw);
  145. m_hDllDxDraw = NULL;
  146. }
  147. m_pfnCreate = NULL;
  148. m_pfnCreateEx = NULL;
  149. }
  150. }
  151. //------------------------------------------------------------------------------
  152. HRESULT
  153. DxManager::InitDxTx()
  154. {
  155. AssertMsg(IsInit(), "DxManager must be first initialized");
  156. if (m_pdxXformFac == NULL) {
  157. //
  158. // DxTx needs COM to be initialized first.
  159. //
  160. if (!GetComManager()->Init(ComManager::sCOM)) {
  161. return DU_E_GENERIC;
  162. }
  163. // Build and initialize a Transform Factory
  164. HRESULT hr;
  165. hr = GetComManager()->CreateInstance(CLSID_DXTransformFactory, NULL,
  166. IID_IDXTransformFactory, (void **)&m_pdxXformFac);
  167. if (FAILED(hr) || (m_pdxXformFac == NULL)) {
  168. goto Error;
  169. }
  170. hr = m_pdxXformFac->SetService(SID_SDirectDraw, m_pDD, FALSE);
  171. if (FAILED(hr)) {
  172. goto Error;
  173. }
  174. // Build a Surface Factory
  175. hr = m_pdxXformFac->QueryService(SID_SDXSurfaceFactory, IID_IDXSurfaceFactory,
  176. (void **)&m_pdxSurfFac);
  177. if (FAILED(hr) || (m_pdxSurfFac == NULL)) {
  178. goto Error;
  179. }
  180. }
  181. m_cDxTxRef++;
  182. return S_OK;
  183. Error:
  184. SafeRelease(m_pdxSurfFac);
  185. SafeRelease(m_pdxXformFac);
  186. return DU_E_GENERIC;
  187. }
  188. //------------------------------------------------------------------------------
  189. void
  190. DxManager::UninitDxTx()
  191. {
  192. if (m_cDxTxRef <= 0) {
  193. return;
  194. }
  195. m_cDxTxRef--;
  196. if (m_cDxTxRef <= 0) {
  197. GetBufferManager()->FlushTrxBuffers();
  198. SafeRelease(m_pdxSurfFac);
  199. SafeRelease(m_pdxXformFac);
  200. }
  201. }
  202. //------------------------------------------------------------------------------
  203. HRESULT
  204. DxManager::BuildSurface(SIZE sizePxl, IDirectDrawSurface7 * pddSurfNew)
  205. {
  206. AssertMsg(IsInit(), "DxManager must be first initialized");
  207. AssertMsg(m_pDD7 != NULL, "Must have DX7");
  208. #if 0
  209. HDC hdc = GetGdiCache()->GetTempDC();
  210. int nBitDepth = GetDeviceCaps(hdc, BITSPIXEL);
  211. #endif
  212. DDSURFACEDESC2 ddsd;
  213. ZeroMemory(&ddsd, sizeof(ddsd));
  214. ddsd.dwSize = sizeof(ddsd);
  215. ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
  216. ddsd.dwWidth = sizePxl.cx;
  217. ddsd.dwHeight = sizePxl.cy;
  218. ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  219. #if 0
  220. GetGdiCache()->ReleaseTempDC(hdc);
  221. #endif
  222. // TODO: Want to optimize where this surface is being created
  223. return m_pDD7->CreateSurface(&ddsd, &pddSurfNew, NULL);
  224. }
  225. //------------------------------------------------------------------------------
  226. HRESULT
  227. DxManager::BuildDxSurface(SIZE sizePxl, REFGUID guidFormat, IDXSurface ** ppdxSurfNew)
  228. {
  229. AssertWritePtr(ppdxSurfNew);
  230. CDXDBnds bnds;
  231. bnds.SetXYSize(sizePxl.cx, sizePxl.cy);
  232. HRESULT hr = GetSurfaceFactory()->CreateSurface(m_pDD, NULL,
  233. &guidFormat, &bnds, 0, NULL, IID_IDXSurface, (void**)ppdxSurfNew);
  234. if (FAILED(hr)) {
  235. return hr;
  236. }
  237. AssertMsg(*ppdxSurfNew != NULL, "Ensure valid surface");
  238. return TRUE;
  239. }
  240. /***************************************************************************\
  241. *****************************************************************************
  242. *
  243. * class DxSurface
  244. *
  245. *****************************************************************************
  246. \***************************************************************************/
  247. //------------------------------------------------------------------------------
  248. DxSurface::DxSurface()
  249. {
  250. m_pdxSurface = NULL;
  251. m_sizePxl.cx = 0;
  252. m_sizePxl.cy = 0;
  253. }
  254. //------------------------------------------------------------------------------
  255. DxSurface::~DxSurface()
  256. {
  257. SafeRelease(m_pdxSurface);
  258. }
  259. /***************************************************************************\
  260. *
  261. * DxSurface::Create
  262. *
  263. * Create() initializes a new instance of DxSurface.
  264. *
  265. \***************************************************************************/
  266. HRESULT
  267. DxSurface::Create(SIZE sizePxl)
  268. {
  269. HRESULT hr;
  270. //
  271. // Build the surface
  272. //
  273. #if 0
  274. m_guidFormat = DDPF_ARGB32;
  275. m_sf = DXPF_ARGB32;
  276. #elif 0
  277. m_guidFormat = DDPF_PMARGB32
  278. m_sf = DXPF_PMARGB32
  279. #elif 1
  280. m_guidFormat = DDPF_RGB565;
  281. m_sf = DXPF_RGB565;
  282. #elif 0
  283. m_guidFormat = DDPF_RGB555;
  284. m_sf = DXPF_RGB555;
  285. #elif 0
  286. m_guidFormat = DDPF_ARGB4444;
  287. m_sf = DXPF_ARGB4444;
  288. #endif
  289. hr = GetDxManager()->BuildDxSurface(sizePxl, m_guidFormat, &m_pdxSurface);
  290. if (FAILED(hr)) {
  291. return hr;
  292. }
  293. DXPMSAMPLE sam;
  294. sam.Red = 0xC0;
  295. sam.Green = 0x00;
  296. sam.Blue = 0x00;
  297. sam.Alpha = 0xFF;
  298. DXFillSurface(m_pdxSurface, sam, FALSE);
  299. m_sizePxl.cx = sizePxl.cx;
  300. m_sizePxl.cy = sizePxl.cy;
  301. return S_OK;
  302. }
  303. /***************************************************************************\
  304. *
  305. * DxSurface::CopyDC
  306. *
  307. * CopyDC() copies a given HDC into the DxSurface, converting properly from
  308. * the GDI object into the Dx object.
  309. *
  310. \***************************************************************************/
  311. BOOL
  312. DxSurface::CopyDC(
  313. IN HDC hdcSrc, // HDC to copy bits from
  314. IN const RECT & rcCrop) // Area to copy
  315. {
  316. HRESULT hr;
  317. // Check parameters
  318. if (m_pdxSurface == NULL) {
  319. return FALSE;
  320. }
  321. if (hdcSrc == NULL) {
  322. return FALSE;
  323. }
  324. //
  325. // Copy the bitmap to the surface
  326. //
  327. BOOL fSuccess = FALSE;
  328. IDXDCLock * pdxLock = NULL;
  329. #if 0
  330. {
  331. DXPMSAMPLE sam;
  332. sam.Red = 0x00;
  333. sam.Green = 0x00;
  334. sam.Blue = 0x00;
  335. sam.Alpha = 0xFF;
  336. DXFillSurface(m_pdxSurface, sam, FALSE);
  337. }
  338. #endif
  339. pdxLock = NULL;
  340. hr = m_pdxSurface->LockSurfaceDC(NULL, INFINITE, DXLOCKF_READWRITE, &pdxLock);
  341. if (FAILED(hr) || (pdxLock == NULL)) {
  342. goto Cleanup;
  343. }
  344. {
  345. HDC hdcSurface = pdxLock->GetDC();
  346. BitBlt(hdcSurface, 0, 0, rcCrop.right - rcCrop.left, rcCrop.bottom - rcCrop.top,
  347. hdcSrc, rcCrop.left, rcCrop.top, SRCCOPY);
  348. }
  349. pdxLock->Release();
  350. fSuccess = FixAlpha();
  351. Cleanup:
  352. return fSuccess;
  353. }
  354. /***************************************************************************\
  355. *
  356. * DxSurface::CopyBitmap
  357. *
  358. * CopyBitmap() copies a given HBITMAP into the DxSurface, converting
  359. * properly from the GDI object into the Dx object.
  360. *
  361. \***************************************************************************/
  362. BOOL
  363. DxSurface::CopyBitmap(
  364. IN HBITMAP hbmpSrc, // Bitmap to copy from
  365. IN const RECT * prcCrop) // Optional cropping area
  366. {
  367. HRESULT hr;
  368. // Check parameters
  369. if (m_pdxSurface == NULL) {
  370. return FALSE;
  371. }
  372. if (hbmpSrc == NULL) {
  373. return FALSE;
  374. }
  375. //
  376. // Determine the area to copy
  377. //
  378. BITMAP bmpInfo;
  379. if (GetObject(hbmpSrc, sizeof(bmpInfo), &bmpInfo) == 0) {
  380. return FALSE;
  381. }
  382. POINT ptSrcOffset;
  383. SIZE sizeBmp;
  384. ptSrcOffset.x = 0;
  385. ptSrcOffset.y = 0;
  386. sizeBmp.cx = bmpInfo.bmWidth;
  387. sizeBmp.cy = bmpInfo.bmHeight;
  388. if (prcCrop != NULL) {
  389. SIZE sizeCrop;
  390. sizeCrop.cx = prcCrop->right - prcCrop->left;
  391. sizeCrop.cy = prcCrop->bottom - prcCrop->top;
  392. ptSrcOffset.x = prcCrop->left;
  393. ptSrcOffset.y = prcCrop->top;
  394. sizeBmp.cx = min(sizeBmp.cx, sizeCrop.cx);
  395. sizeBmp.cy = min(sizeBmp.cy, sizeCrop.cy);
  396. }
  397. //
  398. // Copy the bitmap to the surface
  399. //
  400. BOOL fSuccess = FALSE;
  401. HDC hdcBitmap = NULL;
  402. IDXDCLock * pdxLock = NULL;
  403. hdcBitmap = GetGdiCache()->GetCompatibleDC();
  404. if (hdcBitmap == NULL) {
  405. goto Cleanup;
  406. }
  407. #if 0
  408. {
  409. DXPMSAMPLE sam;
  410. sam.Red = 0x00;
  411. sam.Green = 0x00;
  412. sam.Blue = 0x00;
  413. sam.Alpha = 0xFF;
  414. DXFillSurface(m_pdxSurface, sam, FALSE);
  415. }
  416. #endif
  417. hr = m_pdxSurface->LockSurfaceDC(NULL, INFINITE, DXLOCKF_READWRITE, &pdxLock);
  418. if (FAILED(hr) || (pdxLock == NULL)) {
  419. goto Cleanup;
  420. }
  421. {
  422. HDC hdcSurface = pdxLock->GetDC();
  423. HBITMAP hbmpOld = (HBITMAP) SelectObject(hdcBitmap, hbmpSrc);
  424. BitBlt(hdcSurface, 0, 0, sizeBmp.cx, sizeBmp.cy,
  425. hdcBitmap, ptSrcOffset.x, ptSrcOffset.y, SRCCOPY);
  426. SelectObject(hdcBitmap, hbmpOld);
  427. }
  428. pdxLock->Release();
  429. fSuccess = FixAlpha();
  430. Cleanup:
  431. if (hdcBitmap != NULL) {
  432. GetGdiCache()->ReleaseCompatibleDC(hdcBitmap);
  433. }
  434. return fSuccess;
  435. }
  436. /***************************************************************************\
  437. *
  438. * DxSurface::FixAlpha
  439. *
  440. * FixAlpha() fixes the alpha values in a surface. This usually needs to be
  441. * done after copying a GDI HBITMAP to a DXSurface, depending on the format.
  442. *
  443. \***************************************************************************/
  444. BOOL
  445. DxSurface::FixAlpha()
  446. {
  447. IDXARGBReadWritePtr * pRW;
  448. HRESULT hr = m_pdxSurface->LockSurface(NULL, INFINITE, DXLOCKF_READWRITE,
  449. __uuidof(IDXARGBReadWritePtr), (void **)&pRW, NULL);
  450. if (FAILED(hr)) {
  451. return FALSE;
  452. }
  453. BOOL fSuccess = FALSE;
  454. if (!TestFlag(m_sf, DXPF_TRANSLUCENCY)) {
  455. //
  456. // Sample doesn't have any alpha, so okay
  457. //
  458. fSuccess = TRUE;
  459. } else if (m_sf == DXPF_ARGB32) {
  460. //
  461. // Format is 8:8:8:8 with alpha in MSB.
  462. // Need to use Unpack() to get bits.
  463. // Each pixel is 32 bits.
  464. //
  465. DXSAMPLE * psam;
  466. for (int y = 0; y < m_sizePxl.cy; y++) {
  467. pRW->MoveToRow(y);
  468. psam = pRW->Unpack(NULL, m_sizePxl.cx, FALSE);
  469. Assert(psam != NULL);
  470. int x = m_sizePxl.cx;
  471. while (x-- > 0) {
  472. *psam = *psam | 0xFF000000;
  473. psam++;
  474. }
  475. }
  476. fSuccess = TRUE;
  477. } else if (m_sf == DXPF_PMARGB32) {
  478. //
  479. // Format is 8:8:8:8 with alpha in MSB.
  480. // Need to use UnpackPremult() to get bits.
  481. // Each pixel is 32 bits
  482. //
  483. DXPMSAMPLE * psam;
  484. for (int y = 0; y < m_sizePxl.cy; y++) {
  485. pRW->MoveToRow(y);
  486. psam = pRW->UnpackPremult(NULL, m_sizePxl.cx, FALSE);
  487. Assert(psam != NULL);
  488. int x = m_sizePxl.cx;
  489. while (x-- > 0) {
  490. *psam = *psam | 0xFF000000;
  491. psam++;
  492. }
  493. }
  494. fSuccess = TRUE;
  495. } else if (m_sf == DXPF_ARGB4444) {
  496. //
  497. // Format is 4:4:4:4 with alpha in MSN.
  498. // Need to use Unpack() to get bits.
  499. // Each pixel is 16 bits
  500. //
  501. int cb = m_sizePxl.cx * sizeof(DXSAMPLE);
  502. DXSAMPLE * rgam = (DXSAMPLE *) _alloca(cb);
  503. DXSAMPLE * psam;
  504. for (int y = 0; y < m_sizePxl.cy; y++) {
  505. pRW->MoveToRow(y);
  506. psam = pRW->Unpack(rgam, m_sizePxl.cx, FALSE);
  507. Assert(psam != NULL);
  508. int x = m_sizePxl.cx;
  509. while (x-- > 0) {
  510. *psam = *psam | 0xFF000000;
  511. psam++;
  512. }
  513. pRW->PackAndMove(rgam, m_sizePxl.cx);
  514. }
  515. fSuccess = TRUE;
  516. }
  517. pRW->Release();
  518. return fSuccess;
  519. }