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.

514 lines
14 KiB

  1. /*******************************************************************************
  2. * DXSurfB.cpp *
  3. *------------*
  4. * Description:
  5. * This module contains the CDXBaseSurface implementaion.
  6. *-------------------------------------------------------------------------------
  7. * Created By: RAL Date: 02/12/1998
  8. * Copyright (C) 1998 Microsoft Corporation
  9. * All Rights Reserved
  10. *
  11. *-------------------------------------------------------------------------------
  12. * Revisions:
  13. *
  14. *******************************************************************************/
  15. //--- Additional includes
  16. #include <DXTrans.h>
  17. #include "DXSurfB.h"
  18. #include "new.h"
  19. CDXBaseSurface::CDXBaseSurface() :
  20. m_ulLocks(0),
  21. m_ulThreadsWaiting(0),
  22. m_Height(0),
  23. m_Width(0),
  24. m_pFreePtr(NULL),
  25. m_dwStatusFlags(DXSURF_READONLY),
  26. m_dwAppData(0)
  27. {
  28. m_hSemaphore = CreateSemaphore(NULL, 0, MAXLONG, NULL);
  29. m_ulNumInRequired = m_ulMaxInputs = 0;
  30. }
  31. HRESULT CDXBaseSurface::FinalConstruct()
  32. {
  33. return m_hSemaphore ? S_OK : E_OUTOFMEMORY;
  34. }
  35. void CDXBaseSurface::FinalRelease()
  36. {
  37. while (m_pFreePtr)
  38. {
  39. CDXBaseARGBPtr *pNext = m_pFreePtr->m_pNext;
  40. DeleteARGBPointer(m_pFreePtr);
  41. m_pFreePtr = pNext;
  42. }
  43. if (m_hSemaphore)
  44. {
  45. CloseHandle(m_hSemaphore);
  46. }
  47. }
  48. STDMETHODIMP CDXBaseSurface::GetGenerationId(ULONG *pGenerationId)
  49. {
  50. if (DXIsBadWritePtr(pGenerationId, sizeof(*pGenerationId)))
  51. {
  52. return E_POINTER;
  53. }
  54. Lock();
  55. OnUpdateGenerationId();
  56. *pGenerationId = m_dwGenerationId;
  57. Unlock();
  58. return S_OK;
  59. }
  60. STDMETHODIMP CDXBaseSurface::IncrementGenerationId(BOOL /*bRefresh */)
  61. {
  62. Lock();
  63. m_dwGenerationId++;
  64. Unlock();
  65. return S_OK;
  66. }
  67. STDMETHODIMP CDXBaseSurface::GetObjectSize(ULONG *pcbSize)
  68. {
  69. HRESULT hr = S_OK;
  70. if (DXIsBadWritePtr(pcbSize, sizeof(*pcbSize)))
  71. {
  72. hr = E_POINTER;
  73. }
  74. else
  75. {
  76. Lock();
  77. *pcbSize = OnGetObjectSize();
  78. Unlock();
  79. }
  80. return hr;
  81. }
  82. STDMETHODIMP CDXBaseSurface::MapBoundsIn2Out
  83. (const DXBNDS *pInBounds, ULONG ulNumInBnds, ULONG /*ulOutIndex*/, DXBNDS *pOutBounds)
  84. {
  85. HRESULT hr = S_OK;
  86. if (DXIsBadWritePtr(pOutBounds, sizeof(*pOutBounds)))
  87. {
  88. hr = E_POINTER;
  89. }
  90. else
  91. {
  92. Lock();
  93. new(pOutBounds) CDXDBnds(m_Width, m_Height);
  94. Unlock();
  95. }
  96. return hr;
  97. }
  98. STDMETHODIMP CDXBaseSurface::InitSurface(IUnknown *pDirectDraw,
  99. const DDSURFACEDESC * pDDSurfaceDesc,
  100. const GUID * pFormatId,
  101. const DXBNDS *pBounds,
  102. DWORD dwFlags)
  103. {
  104. HRESULT hr = S_OK;
  105. if (pDDSurfaceDesc || DXIsBadReadPtr(pBounds, sizeof(*pBounds)) || pBounds->eType != DXBT_DISCRETE)
  106. {
  107. hr = E_INVALIDARG;
  108. }
  109. else
  110. {
  111. _EnterCritWith0PtrLocks();
  112. if (m_Width)
  113. {
  114. hr = HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
  115. }
  116. else
  117. {
  118. CDXDBnds *pbnds = (CDXDBnds *)pBounds;
  119. hr = OnSetSize(pbnds->Width(), pbnds->Height());
  120. }
  121. Unlock();
  122. }
  123. return hr;
  124. }
  125. STDMETHODIMP CDXBaseSurface::GetPixelFormat(GUID *pFormat, DXSAMPLEFORMATENUM *pSampleFormatEnum)
  126. {
  127. HRESULT hr = S_OK;
  128. if (DX_IS_BAD_OPTIONAL_WRITE_PTR(pFormat) ||
  129. DX_IS_BAD_OPTIONAL_WRITE_PTR(pSampleFormatEnum))
  130. {
  131. hr = E_POINTER;
  132. }
  133. else
  134. {
  135. if (pFormat) *pFormat = SurfaceCLSID();
  136. if (pSampleFormatEnum) *pSampleFormatEnum = SampleFormatEnum();
  137. }
  138. return hr;
  139. }
  140. STDMETHODIMP CDXBaseSurface::GetBounds(DXBNDS* pBounds)
  141. {
  142. HRESULT hr = S_OK;
  143. if (DXIsBadWritePtr(pBounds, sizeof(*pBounds)))
  144. {
  145. hr = E_POINTER;
  146. }
  147. else
  148. {
  149. Lock();
  150. new(pBounds) CDXDBnds(m_Width, m_Height);
  151. Unlock();
  152. }
  153. return hr;
  154. }
  155. STDMETHODIMP CDXBaseSurface::GetStatusFlags(DWORD* pdwStatusFlags)
  156. {
  157. HRESULT hr = S_OK;
  158. if (DXIsBadWritePtr(pdwStatusFlags, sizeof(*pdwStatusFlags)))
  159. {
  160. hr = E_POINTER;
  161. }
  162. else
  163. {
  164. Lock();
  165. *pdwStatusFlags = m_dwStatusFlags;
  166. Unlock();
  167. }
  168. return hr;
  169. }
  170. STDMETHODIMP CDXBaseSurface::SetStatusFlags(DWORD dwStatusFlags )
  171. {
  172. _EnterCritWith0PtrLocks();
  173. m_dwStatusFlags = dwStatusFlags | DXSURF_READONLY;
  174. m_dwGenerationId++;
  175. Unlock();
  176. return S_OK;
  177. }
  178. STDMETHODIMP CDXBaseSurface::GetDirectDrawSurface(REFIID riid, void **ppSurface)
  179. {
  180. return E_NOTIMPL;
  181. }
  182. STDMETHODIMP CDXBaseSurface::LockSurface(const DXBNDS *pBounds, ULONG ulTimeOut,
  183. DWORD dwFlags, REFIID riid, void **ppPointer,
  184. DWORD * pGenerationId)
  185. {
  186. HRESULT hr = S_OK;
  187. BOOL bMPLockOnly = m_bInMultiThreadWorkProc;
  188. if (!bMPLockOnly) Lock();
  189. m_MPWorkProcCrit.Lock();
  190. if (m_Width == 0)
  191. {
  192. hr = E_FAIL;
  193. }
  194. else
  195. {
  196. RECT r;
  197. r.top = r.left = 0;
  198. r.right = m_Width;
  199. r.bottom = m_Height;
  200. if (pBounds)
  201. {
  202. if (pBounds->eType != DXBT_DISCRETE)
  203. {
  204. hr = DXTERR_INVALID_BOUNDS;
  205. }
  206. else
  207. {
  208. ((CDXDBnds *)pBounds)->GetXYRect(r);
  209. if (r.top < 0 || r.left < 0 || (ULONG)r.right > m_Width || (ULONG)r.bottom > m_Height || r.bottom <= r.top || r.right <= r.left)
  210. {
  211. hr = DXTERR_INVALID_BOUNDS;
  212. }
  213. }
  214. }
  215. if (SUCCEEDED(hr))
  216. {
  217. CDXBaseARGBPtr * pPtr = m_pFreePtr;
  218. if (pPtr)
  219. {
  220. m_pFreePtr = pPtr->m_pNext;
  221. }
  222. else
  223. {
  224. hr = CreateARGBPointer(this, &pPtr);
  225. }
  226. if (SUCCEEDED(hr))
  227. {
  228. hr = pPtr->InitFromLock(r, ulTimeOut, dwFlags, riid, ppPointer);
  229. if (pGenerationId)
  230. {
  231. if (DXIsBadWritePtr(pGenerationId, sizeof(*pGenerationId)))
  232. {
  233. hr = E_POINTER;
  234. }
  235. else
  236. {
  237. *pGenerationId = m_dwGenerationId;
  238. }
  239. }
  240. if (SUCCEEDED(hr))
  241. {
  242. m_ulLocks++;
  243. }
  244. else
  245. {
  246. pPtr->m_pNext = m_pFreePtr;
  247. m_pFreePtr = pPtr;
  248. }
  249. }
  250. }
  251. }
  252. m_MPWorkProcCrit.Unlock();
  253. if (!bMPLockOnly) Unlock();
  254. return hr;
  255. }
  256. void CDXBaseSurface::_InternalUnlock(CDXBaseARGBPtr *pPtrToUnlock)
  257. {
  258. BOOL bMPLockOnly = m_bInMultiThreadWorkProc;
  259. if (!bMPLockOnly) Lock();
  260. m_MPWorkProcCrit.Lock();
  261. pPtrToUnlock->m_pNext = m_pFreePtr;
  262. m_pFreePtr = pPtrToUnlock;
  263. m_ulLocks--;
  264. if ((m_ulLocks == 0) && m_ulThreadsWaiting)
  265. {
  266. ReleaseSemaphore(m_hSemaphore, m_ulThreadsWaiting, NULL);
  267. m_ulThreadsWaiting = 0;
  268. }
  269. m_MPWorkProcCrit.Unlock();
  270. if (!bMPLockOnly) Unlock();
  271. IUnknown *punkOuter = GetControllingUnknown();
  272. punkOuter->Release(); // Release pointer's reference to us
  273. // which could kill us! Don't touch
  274. // any members after this point.
  275. }
  276. //
  277. // Picking interface needs to test the appropriate point for hit testing
  278. //
  279. HRESULT CDXBaseSurface::OnSurfacePick(const CDXDBnds & OutPoint, ULONG & ulInputIndex, CDXDVec & InVec)
  280. {
  281. HRESULT hr;
  282. IDXARGBReadPtr *pPtr;
  283. hr = LockSurface(&OutPoint, m_ulLockTimeOut, DXLOCKF_READ,
  284. IID_IDXARGBReadPtr, (void **)&pPtr, NULL);
  285. if( SUCCEEDED(hr) )
  286. {
  287. DXPMSAMPLE val;
  288. pPtr->UnpackPremult(&val, 1, FALSE);
  289. pPtr->Release();
  290. hr = val.Alpha ? DXT_S_HITOUTPUT : S_FALSE;
  291. }
  292. else
  293. {
  294. if (hr == DXTERR_INVALID_BOUNDS) hr = S_FALSE;
  295. }
  296. return hr;
  297. }
  298. /*****************************************************************************
  299. * RegisterSurface (STATIC member function)
  300. *-----------------------------------------------------------------------------
  301. * Description:
  302. *-----------------------------------------------------------------------------
  303. * Created By: RAL Date: 12/10/97
  304. *-----------------------------------------------------------------------------
  305. * Parameters:
  306. *****************************************************************************/
  307. HRESULT CDXBaseSurface::
  308. RegisterSurface(REFCLSID rcid, int ResourceId, ULONG cCatImpl, const CATID * pCatImpl,
  309. ULONG cCatReq, const CATID * pCatReq, BOOL bRegister)
  310. {
  311. HRESULT hr = bRegister ? _Module.UpdateRegistryFromResource(ResourceId, bRegister) : S_OK;
  312. if (SUCCEEDED(hr))
  313. {
  314. CComPtr<ICatRegister> pCatRegister;
  315. HRESULT hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_ALL, IID_ICatRegister, (void **)&pCatRegister);
  316. if (SUCCEEDED(hr))
  317. {
  318. if (bRegister)
  319. {
  320. hr = pCatRegister->RegisterClassImplCategories(rcid, cCatImpl, (CATID *)pCatImpl);
  321. if (SUCCEEDED(hr) && cCatReq && pCatReq) {
  322. hr = pCatRegister->RegisterClassReqCategories(rcid, cCatReq, (CATID *)pCatReq);
  323. }
  324. }
  325. else
  326. {
  327. pCatRegister->UnRegisterClassImplCategories(rcid, cCatImpl, (CATID *)pCatImpl);
  328. if (cCatReq && pCatReq)
  329. {
  330. pCatRegister->UnRegisterClassReqCategories(rcid, cCatReq, (CATID *)pCatReq);
  331. }
  332. }
  333. }
  334. }
  335. if ((!bRegister) && SUCCEEDED(hr))
  336. {
  337. _Module.UpdateRegistryFromResource(ResourceId, bRegister);
  338. }
  339. return hr;
  340. }
  341. //
  342. // CDXBaseARGBPtr
  343. //
  344. STDMETHODIMP CDXBaseARGBPtr::QueryInterface(REFIID riid, void ** ppv)
  345. {
  346. if (IsEqualGUID(riid, IID_IUnknown) ||
  347. IsEqualGUID(riid, IID_IDXARGBReadPtr))
  348. {
  349. *ppv = (IDXARGBReadPtr *)this;
  350. m_ulRefCount++;
  351. return S_OK;
  352. }
  353. else
  354. {
  355. *ppv = NULL;
  356. return E_NOINTERFACE;
  357. }
  358. }
  359. ULONG STDMETHODCALLTYPE CDXBaseARGBPtr::AddRef()
  360. {
  361. return ++m_ulRefCount;
  362. }
  363. ULONG STDMETHODCALLTYPE CDXBaseARGBPtr::Release()
  364. {
  365. --m_ulRefCount;
  366. ULONG c = m_ulRefCount;
  367. if (c == 0)
  368. {
  369. m_pSurface->_InternalUnlock(this); // Don't touch members after this call.
  370. }
  371. return c;
  372. }
  373. HRESULT STDMETHODCALLTYPE CDXBaseARGBPtr::GetSurface(REFIID riid, void **ppSurface)
  374. {
  375. return m_pSurface->GetControllingUnknown()->QueryInterface(riid, ppSurface);
  376. }
  377. DXSAMPLEFORMATENUM STDMETHODCALLTYPE CDXBaseARGBPtr::GetNativeType(DXNATIVETYPEINFO *pInfo)
  378. {
  379. if (pInfo)
  380. {
  381. memset(pInfo, 0, sizeof(pInfo));
  382. }
  383. return m_pSurface->SampleFormatEnum();
  384. }
  385. void STDMETHODCALLTYPE CDXBaseARGBPtr::Move(long cSamples)
  386. {
  387. m_FillInfo.x += cSamples;
  388. //--- Moving one column past the end is okay
  389. _ASSERT((long)m_FillInfo.x <= m_LockedRect.right);
  390. }
  391. void STDMETHODCALLTYPE CDXBaseARGBPtr::MoveToRow(ULONG y)
  392. {
  393. m_FillInfo.x = m_LockedRect.left;
  394. m_FillInfo.y = y + m_LockedRect.top;
  395. _ASSERT((long)m_FillInfo.y < m_LockedRect.bottom);
  396. }
  397. void STDMETHODCALLTYPE CDXBaseARGBPtr::MoveToXY(ULONG x, ULONG y)
  398. {
  399. m_FillInfo.x = x + m_LockedRect.left;
  400. m_FillInfo.y = y + m_LockedRect.top;
  401. //--- Moving one column past the end is okay
  402. _ASSERT((long)m_FillInfo.x <= m_LockedRect.right);
  403. _ASSERT((long)m_FillInfo.y < m_LockedRect.bottom);
  404. }
  405. ULONG STDMETHODCALLTYPE CDXBaseARGBPtr::MoveAndGetRunInfo(ULONG Row, const DXRUNINFO ** ppInfo)
  406. {
  407. m_FillInfo.x = m_LockedRect.left;
  408. m_FillInfo.y = Row + m_LockedRect.top;
  409. _ASSERT((long)m_FillInfo.y < m_LockedRect.bottom);
  410. *ppInfo = &m_RunInfo;
  411. return 1;
  412. }
  413. DXSAMPLE *STDMETHODCALLTYPE CDXBaseARGBPtr::Unpack(DXSAMPLE *pSamples, ULONG cSamples, BOOL bMove)
  414. {
  415. m_FillInfo.pSamples = pSamples;
  416. m_FillInfo.cSamples = cSamples;
  417. m_FillInfo.bPremult = false;
  418. FillSamples(m_FillInfo);
  419. if (bMove) m_FillInfo.x += cSamples;
  420. return pSamples;
  421. }
  422. DXPMSAMPLE *STDMETHODCALLTYPE CDXBaseARGBPtr::UnpackPremult(DXPMSAMPLE *pSamples, ULONG cSamples, BOOL bMove)
  423. {
  424. m_FillInfo.pSamples = pSamples;
  425. m_FillInfo.cSamples = cSamples;
  426. m_FillInfo.bPremult = true;
  427. FillSamples(m_FillInfo);
  428. if (bMove) m_FillInfo.x += cSamples;
  429. return pSamples;
  430. }
  431. void STDMETHODCALLTYPE CDXBaseARGBPtr::UnpackRect(const DXPACKEDRECTDESC *pDesc)
  432. {
  433. DXPtrFillInfo FillInfo;
  434. FillInfo.pSamples = pDesc->pSamples;
  435. FillInfo.cSamples = pDesc->rect.right - pDesc->rect.left;
  436. FillInfo.x = pDesc->rect.left + m_LockedRect.left;
  437. FillInfo.bPremult = pDesc->bPremult;
  438. ULONG YLimit = pDesc->rect.bottom + m_LockedRect.top;
  439. for (FillInfo.y = pDesc->rect.top + m_LockedRect.top;
  440. FillInfo.y < YLimit;
  441. FillInfo.y++)
  442. {
  443. FillSamples(FillInfo);
  444. FillInfo.pSamples += FillInfo.cSamples;
  445. }
  446. }
  447. HRESULT CDXBaseARGBPtr::InitFromLock(const RECT & rect, ULONG /*ulTimeOut*/, DWORD dwLockFlags, REFIID riid, void ** ppv)
  448. {
  449. HRESULT hr = S_OK;
  450. if (dwLockFlags & DXLOCKF_READWRITE)
  451. {
  452. hr = E_INVALIDARG;
  453. }
  454. else
  455. {
  456. m_LockedRect = rect;
  457. m_RunInfo.Count = rect.right - rect.left;
  458. if (m_pSurface->SampleFormatEnum() & DXPF_TRANSPARENCY)
  459. {
  460. m_RunInfo.Type = DXRUNTYPE_UNKNOWN;
  461. }
  462. else
  463. {
  464. m_RunInfo.Type = DXRUNTYPE_OPAQUE;
  465. }
  466. m_FillInfo.x = rect.left;
  467. m_FillInfo.y = rect.top;
  468. hr = QueryInterface(riid, ppv);
  469. if (SUCCEEDED(hr))
  470. {
  471. m_pSurface->GetControllingUnknown()->AddRef();
  472. }
  473. }
  474. return hr;
  475. }