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.

1681 lines
56 KiB

  1. /*******************************************************************************
  2. * DTBase.cpp *
  3. *------------*
  4. * Description:
  5. * This module contains the CDXBaseNTo1 transform
  6. *-------------------------------------------------------------------------------
  7. * Created By: Edward W. Connell Date: 07/28/97
  8. * Copyright (C) 1997 Microsoft Corporation
  9. * All Rights Reserved
  10. *
  11. *-------------------------------------------------------------------------------
  12. * Revisions:
  13. *
  14. *******************************************************************************/
  15. //--- Additional includes
  16. #include <DXTrans.h>
  17. #include "DTBase.h"
  18. #include "new.h"
  19. //--- Initialize static member of debug scope class
  20. #ifdef _DEBUG
  21. CDXTDbgFlags CDXTDbgScope::m_DebugFlags;
  22. #endif
  23. //--- This should only be used locally in this file. We duplicated this GUID
  24. // value to avoid having to include DDraw.
  25. static const IID IID_IDXDupDirectDraw =
  26. { 0x6C14DB80,0xA733,0x11CE, { 0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 } };
  27. static const IID IID_IDXDupDDrawSurface =
  28. { 0x6C14DB81,0xA733,0x11CE, { 0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 } };
  29. static const IID IID_IDXDupDirect3DRM =
  30. {0x2bc49361, 0x8327, 0x11cf, {0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1 } };
  31. static const IID IID_IDXDupDirect3DRM3 =
  32. {0x4516ec83, 0x8f20, 0x11d0, {0x9b, 0x6d, 0x00, 0x00, 0xc0, 0x78, 0x1b, 0xc3 } };
  33. static const IID IID_IDXDupDirect3DRMMeshBuilder3 =
  34. { 0x4516ec82, 0x8f20, 0x11d0, { 0x9b, 0x6d, 0x00, 0x00, 0xc0, 0x78, 0x1b, 0xc3} };
  35. HRESULT CDXDataPtr::Assign(BOOL bMesh, IUnknown * pObject, IDXSurfaceFactory *pSurfaceFactory)
  36. {
  37. HRESULT hr = S_OK;
  38. if (pObject)
  39. {
  40. IUnknown *pNative = NULL;
  41. if (!bMesh)
  42. {
  43. //--- Try to get a DX surface
  44. hr = pObject->QueryInterface( IID_IDXSurface, (void **)&pNative );
  45. if( FAILED( hr ) )
  46. {
  47. IDirectDrawSurface *pSurf;
  48. //--- Try to get a DDraw surface
  49. hr = pObject->QueryInterface( IID_IDXDupDDrawSurface, (void **)&pSurf );
  50. if( SUCCEEDED( hr ) )
  51. {
  52. //--- Create a DXSurface from the DDraw surface
  53. hr = pSurfaceFactory->CreateFromDDSurface(
  54. pSurf, NULL, 0, NULL, IID_IDXSurface,
  55. (void **)&pNative );
  56. pSurf->Release();
  57. }
  58. }
  59. }
  60. else // Must be a mesh builder
  61. {
  62. hr = pObject->QueryInterface(IID_IDXDupDirect3DRMMeshBuilder3, (void **)&pNative);
  63. }
  64. if (SUCCEEDED(hr))
  65. {
  66. Release();
  67. m_pNativeInterface = pNative;
  68. pObject->AddRef();
  69. m_pUnkOriginalObject = pObject;
  70. if (SUCCEEDED(pNative->QueryInterface(IID_IDXBaseObject, (void **)&m_pBaseObj)))
  71. {
  72. m_pBaseObj->GetGenerationId(&m_dwLastDirtyGenId);
  73. m_dwLastDirtyGenId--;
  74. }
  75. if (!bMesh)
  76. {
  77. ((IDXSurface *)pNative)->GetPixelFormat(NULL, &m_SampleFormat);
  78. }
  79. }
  80. else
  81. {
  82. if (hr == E_NOINTERFACE)
  83. {
  84. hr = E_INVALIDARG;
  85. }
  86. }
  87. }
  88. else
  89. {
  90. Release();
  91. }
  92. return hr;
  93. } /* CDXDataPtr::Assign */
  94. bool CDXDataPtr::IsDirty(void)
  95. {
  96. if (m_pBaseObj)
  97. {
  98. DWORD dwOldId = m_dwLastDirtyGenId;
  99. m_pBaseObj->GetGenerationId(&m_dwLastDirtyGenId);
  100. return dwOldId != m_dwLastDirtyGenId;
  101. }
  102. else
  103. {
  104. return false;
  105. }
  106. }
  107. DWORD CDXDataPtr::GenerationId(void)
  108. {
  109. if (m_pBaseObj)
  110. {
  111. DWORD dwGenId;
  112. m_pBaseObj->GetGenerationId(&dwGenId);
  113. return dwGenId;
  114. }
  115. else
  116. {
  117. return 0;
  118. }
  119. }
  120. bool CDXDataPtr::UpdateGenerationId(void)
  121. {
  122. if (m_pBaseObj)
  123. {
  124. DWORD dwOldId = m_dwLastUpdGenId;
  125. m_pBaseObj->GetGenerationId(&m_dwLastUpdGenId);
  126. return dwOldId != m_dwLastUpdGenId;
  127. }
  128. else
  129. {
  130. return false;
  131. }
  132. } /* CDXDataPtr::UpdateGenerationId */
  133. ULONG CDXDataPtr::ObjectSize(void)
  134. {
  135. ULONG ulSize = 0;
  136. if (m_pBaseObj)
  137. {
  138. m_pBaseObj->GetObjectSize(&ulSize);
  139. }
  140. return ulSize;
  141. }
  142. /*****************************************************************************
  143. * CDXBaseNTo1::CDXBaseNTo1 *
  144. *--------------------------*
  145. * Description:
  146. * Constructor
  147. *-----------------------------------------------------------------------------
  148. * Created By: Ed Connell Date: 07/28/97
  149. *-----------------------------------------------------------------------------
  150. * Parameters:
  151. *****************************************************************************/
  152. CDXBaseNTo1::CDXBaseNTo1() :
  153. m_aInputs(NULL),
  154. m_ulNumInputs(0),
  155. m_ulNumProcessors(1), // Default to one until task manager is set
  156. m_dwGenerationId(1),
  157. m_dwCleanGenId(0),
  158. m_Duration(1.0f),
  159. m_StepResolution(0.0f),
  160. m_Progress(0.0f),
  161. m_dwBltFlags(0),
  162. m_bPickDoneByBase(false),
  163. m_bInMultiThreadWorkProc(FALSE),
  164. m_fQuality(0.5f), // Default to normal quality.
  165. // Wait forever before timing out on a lock by default
  166. m_ulLockTimeOut(INFINITE),
  167. //
  168. // Override these flags if your object does not support one or more of these options.
  169. // Typically, 3-D effects should set this member to 0.
  170. //
  171. m_dwMiscFlags(DXTMF_BLEND_WITH_OUTPUT | DXTMF_DITHER_OUTPUT |
  172. DXTMF_BLEND_SUPPORTED | DXTMF_DITHER_SUPPORTED | DXTMF_BOUNDS_SUPPORTED | DXTMF_PLACEMENT_SUPPORTED),
  173. //
  174. // If your object has a different number of objects or a different number of
  175. // required objects than 1, simply set these members in the body of your
  176. // constructor or in FinalConstruct(). For every input that is > the number
  177. // required, that input will be reported as optional.
  178. //
  179. // If your transform takes 2 required inputs, set both to 2.
  180. // If your transform takes 2 optional inputs, set MaxInputs = 2, NumInRequired = 0
  181. // If your transform takes 1 required and 2 optional inputs,
  182. // set MaxInputs = 2, NumInRequired = 1
  183. //
  184. // For more complex combinations of optinal/required, you will need to override
  185. // the OnSetup method of this base class, and override the methods
  186. // GetInOutInfo
  187. //
  188. m_ulMaxInputs(1),
  189. m_ulNumInRequired(1),
  190. //
  191. // If the intputs or output types are not surfaces then set appropriate object type
  192. //
  193. m_dwOptionFlags(0), // Inputs and output are surfaces, don't have to be the same size
  194. m_ulMaxImageBands(DXB_MAX_IMAGE_BANDS),
  195. m_fIsSetup(false)
  196. {
  197. DXTDBG_FUNC( "CDXBaseNTo1::CDXBaseNTo1" );
  198. //
  199. // Set event handles to NULL.
  200. //
  201. memset(m_aEvent, 0, sizeof(m_aEvent));
  202. } /* CDXBaseNTo1::CDXBaseNTo1 */
  203. /*****************************************************************************
  204. * CDXBaseNTo1::~CDXBaseNTo1 *
  205. *---------------------------*
  206. * Description:
  207. * Constructor
  208. *-----------------------------------------------------------------------------
  209. * Created By: Ed Connell Date: 07/28/97
  210. *-----------------------------------------------------------------------------
  211. * Parameters:
  212. *****************************************************************************/
  213. CDXBaseNTo1::~CDXBaseNTo1()
  214. {
  215. DXTDBG_FUNC( "CDXBaseNTo1::~CDXBaseNTo1" );
  216. _ReleaseReferences();
  217. delete[] m_aInputs;
  218. //--- Release event objects
  219. for(ULONG i = 0; i < DXB_MAX_IMAGE_BANDS; ++i )
  220. {
  221. if( m_aEvent[i] ) ::CloseHandle( m_aEvent[i] );
  222. }
  223. } /* CDXBaseNTo1::~CDXBaseNTo1 */
  224. /*****************************************************************************
  225. * CDXBaseNTo1::_ReleaseRefernces *
  226. *--------------------------------*
  227. * Description:
  228. * Releases all references to input and output objects
  229. *-----------------------------------------------------------------------------
  230. * Created By: RAL
  231. *-----------------------------------------------------------------------------
  232. * Parameters:
  233. *****************************************************************************/
  234. void CDXBaseNTo1::_ReleaseReferences()
  235. {
  236. //--- Release data objects
  237. if( m_aInputs )
  238. {
  239. for( ULONG i = 0; i < m_ulNumInputs; ++i )
  240. {
  241. m_aInputs[i].Release();
  242. }
  243. }
  244. m_Output.Release();
  245. m_fIsSetup = false;
  246. } /* CDXBaseNTo1::_ReleaseRefernces */
  247. STDMETHODIMP CDXBaseNTo1::GetGenerationId(ULONG *pGenerationId)
  248. {
  249. DXTDBG_FUNC( "CDXBaseNTo1::GetGenerationId" );
  250. if (DXIsBadWritePtr(pGenerationId, sizeof(*pGenerationId)))
  251. {
  252. return E_POINTER;
  253. }
  254. Lock();
  255. OnUpdateGenerationId();
  256. *pGenerationId = m_dwGenerationId;
  257. Unlock();
  258. return S_OK;
  259. }
  260. STDMETHODIMP CDXBaseNTo1::IncrementGenerationId(BOOL bRefresh)
  261. {
  262. DXTDBG_FUNC( "CDXBaseNTo1::IncrementGenerationId" );
  263. HRESULT hr = S_OK;
  264. Lock();
  265. m_dwGenerationId++;
  266. if (bRefresh)
  267. {
  268. //
  269. // If we have any inputs or outputs, call Setup again to refresh all internal
  270. // knowledge about the surfaces (formats, height or width could change, etc.)
  271. //
  272. // Note that we need to AddRef the objects prior to calling Setup becuase the
  273. // DXTransform may be the only object holding a referec
  274. //
  275. ULONG cInputs = m_ulNumInputs;
  276. ULONG cOutputs = 0;
  277. IUnknown *pOutput = m_Output.m_pUnkOriginalObject;
  278. if (pOutput)
  279. {
  280. cOutputs = 1;
  281. pOutput->AddRef();
  282. }
  283. IUnknown ** ppInputs = NULL;
  284. if (cInputs)
  285. {
  286. ppInputs = (IUnknown **)_alloca(m_ulNumInputs * sizeof(IUnknown *));
  287. for (ULONG i = 0; i < cInputs; i++)
  288. {
  289. ppInputs[i] = m_aInputs[i].m_pUnkOriginalObject;
  290. if (ppInputs[i]) ppInputs[i]->AddRef();
  291. }
  292. }
  293. if (cInputs || cOutputs) // If we're not setup, skip this step.
  294. {
  295. hr = Setup(ppInputs, cInputs, &pOutput, cOutputs, 0);
  296. if (pOutput) pOutput->Release();
  297. for (ULONG i = 0; i < cInputs; i++)
  298. {
  299. if (ppInputs[i]) ppInputs[i]->Release();
  300. }
  301. }
  302. }
  303. Unlock();
  304. return hr;
  305. }
  306. STDMETHODIMP CDXBaseNTo1::GetObjectSize(ULONG *pcbSize)
  307. {
  308. DXTDBG_FUNC( "CDXBaseNTo1::GetObjectSize" );
  309. HRESULT hr = S_OK;
  310. if (DXIsBadWritePtr(pcbSize, sizeof(*pcbSize)))
  311. {
  312. hr = E_POINTER;
  313. }
  314. else
  315. {
  316. Lock();
  317. *pcbSize = OnGetObjectSize();
  318. Unlock();
  319. }
  320. return hr;
  321. }
  322. void CDXBaseNTo1::_ReleaseServices(void)
  323. {
  324. m_cpTransFact.Release();
  325. m_cpSurfFact.Release();
  326. m_cpTaskMgr.Release();
  327. m_cpDirectDraw.Release();
  328. m_cpDirect3DRM.Release();
  329. }
  330. //
  331. // The documentation for SetSite indicates that it is invaid to return
  332. // an error from this function, even if the site does not support the
  333. // functionality we want. So, even if there is no service provider, or
  334. // the required services are not available, we will return S_OK.
  335. //
  336. STDMETHODIMP CDXBaseNTo1::SetSite(IUnknown * pUnkSite)
  337. {
  338. DXTDBG_FUNC( "CDXBaseNTo1::SetSite" );
  339. HRESULT hr = S_OK;
  340. Lock();
  341. m_cpUnkSite = pUnkSite;
  342. _ReleaseServices();
  343. if (pUnkSite)
  344. {
  345. if (DXIsBadInterfacePtr(pUnkSite))
  346. {
  347. hr = E_INVALIDARG;
  348. }
  349. else
  350. {
  351. HRESULT hr2;
  352. hr2 = pUnkSite->QueryInterface(IID_IDXTransformFactory, (void **)&m_cpTransFact);
  353. if (SUCCEEDED(hr2))
  354. {
  355. //
  356. // Allocate memory for inputs if necessary
  357. //
  358. if (m_aInputs == NULL && m_ulMaxInputs)
  359. {
  360. m_aInputs = new CDXDataPtr[m_ulMaxInputs];
  361. if (!m_aInputs)
  362. {
  363. _ASSERT(TRUE);
  364. hr2 = E_OUTOFMEMORY;
  365. }
  366. }
  367. hr2 = m_cpTransFact->QueryService( SID_SDXSurfaceFactory, IID_IDXSurfaceFactory, (void **)&m_cpSurfFact);
  368. if (SUCCEEDED(hr2))
  369. {
  370. hr2 = m_cpTransFact->QueryService( SID_SDXTaskManager, IID_IDXTaskManager, (void **)&m_cpTaskMgr);
  371. }
  372. if (SUCCEEDED(hr2))
  373. {
  374. m_cpTaskMgr->QueryNumProcessors(&m_ulNumProcessors);
  375. if (m_ulMaxImageBands && (m_dwOptionFlags & (DXBOF_INPUTS_MESHBUILDER | DXBOF_OUTPUT_MESHBUILDER)) == 0)
  376. {
  377. for (ULONG i = 0; SUCCEEDED(hr2) && i < m_ulMaxImageBands; i++)
  378. {
  379. //
  380. // In theory we could get back here after failing to create an event, or
  381. // by getting a new site, so make sure it's non-null before creating one.
  382. //
  383. if (m_aEvent[i] == NULL)
  384. {
  385. m_aEvent[i] = ::CreateEvent(NULL, true, false, NULL);
  386. if (m_aEvent[i] == NULL)
  387. {
  388. hr2 = E_OUTOFMEMORY;
  389. }
  390. }
  391. }
  392. }
  393. }
  394. if (SUCCEEDED(hr2))
  395. {
  396. hr2 = m_cpTransFact->QueryService(SID_SDirectDraw, IID_IDXDupDirectDraw, (void**)&m_cpDirectDraw);
  397. }
  398. if (SUCCEEDED(hr2) &&
  399. (m_dwOptionFlags & (DXBOF_INPUTS_MESHBUILDER | DXBOF_OUTPUT_MESHBUILDER)))
  400. {
  401. hr2 = m_cpTransFact->QueryService(SID_SDirect3DRM, IID_IDXDupDirect3DRM3, (void **)&m_cpDirect3DRM);
  402. }
  403. if (FAILED(hr2))
  404. {
  405. _ASSERT(TRUE);
  406. _ReleaseServices();
  407. }
  408. }
  409. }
  410. }
  411. Unlock();
  412. return hr;
  413. }
  414. STDMETHODIMP CDXBaseNTo1::GetSite(REFIID riid, void **ppv)
  415. {
  416. DXTDBG_FUNC( "CDXBaseNTo1::GetSite" );
  417. HRESULT hr = S_OK;
  418. if( DXIsBadWritePtr(ppv, sizeof(*ppv)) )
  419. {
  420. hr = E_POINTER;
  421. }
  422. else
  423. {
  424. Lock();
  425. if (m_cpUnkSite)
  426. {
  427. hr = m_cpUnkSite->QueryInterface(riid, ppv);
  428. }
  429. else
  430. {
  431. *ppv = NULL;
  432. hr = E_FAIL; // This is the proper documented return code
  433. // for this interface if no service provider.
  434. }
  435. Unlock();
  436. }
  437. return hr;
  438. }
  439. void CDXBaseNTo1::_UpdateBltFlags(void)
  440. {
  441. m_dwBltFlags = 0;
  442. if ((m_dwOptionFlags & DXBOF_OUTPUT_MESHBUILDER) == 0)
  443. {
  444. if (m_dwMiscFlags & DXTMF_BLEND_WITH_OUTPUT)
  445. {
  446. if ((m_dwOptionFlags & DXBOF_INPUTS_MESHBUILDER) || m_ulNumInputs == 0)
  447. {
  448. m_dwBltFlags |= DXBOF_DO_OVER;
  449. }
  450. else
  451. {
  452. for(ULONG i = 0; i < m_ulNumInputs; ++i )
  453. {
  454. if (InputSampleFormat(i) & DXPF_TRANSPARENCY)
  455. {
  456. m_dwBltFlags |= DXBOF_DO_OVER;
  457. break;
  458. }
  459. }
  460. }
  461. }
  462. //
  463. // Set the dither flag to true only if output error is > at least one input
  464. //
  465. if (m_dwMiscFlags & DXTMF_DITHER_OUTPUT)
  466. {
  467. ULONG OutputErr = (OutputSampleFormat() & DXPF_ERRORMASK);
  468. if (OutputErr)
  469. {
  470. if (m_ulNumInputs)
  471. {
  472. for(ULONG i = 0; i < m_ulNumInputs; ++i )
  473. {
  474. if (InputSurface(i) && (ULONG)(InputSampleFormat(i) & DXPF_ERRORMASK) < OutputErr)
  475. {
  476. m_dwBltFlags |= DXBOF_DITHER;
  477. break;
  478. }
  479. }
  480. }
  481. else
  482. {
  483. //
  484. // If output has no error then don't set dither in blt flags
  485. //
  486. if (OutputErr)
  487. {
  488. m_dwBltFlags |= DXBOF_DITHER;
  489. }
  490. }
  491. }
  492. }
  493. }
  494. }
  495. /*****************************************************************************
  496. * CDXBaseNTo1::Setup *
  497. *--------------------*
  498. * Description:
  499. * The Setup method is used to perform any required one-time setup
  500. * before the Execute method is called. Single surfaces or SurfaceSets may
  501. * be used as arguments in any combination.
  502. * If punkOutputs is NULL, Execute will allocate an output result of the
  503. * appropriate size and return it.
  504. * if punkInputs and punkOutputs are NULL and it is a quick setup, the current
  505. * input and output objects are released.
  506. *-----------------------------------------------------------------------------
  507. * Created By: Ed Connell Date: 07/28/97
  508. *-----------------------------------------------------------------------------
  509. * Parameters:
  510. *****************************************************************************/
  511. STDMETHODIMP CDXBaseNTo1::Setup( IUnknown * const * punkInputs, ULONG ulNumInputs,
  512. IUnknown * const * punkOutputs, ULONG ulNumOutputs, DWORD dwFlags )
  513. {
  514. DXTDBG_FUNC( "CDXBaseNTo1::Setup" );
  515. //--- Lock object so state cannot change during setup
  516. DXAUTO_OBJ_LOCK
  517. HRESULT hr = S_OK;
  518. ULONG i;
  519. //
  520. // Early out for null setup. Forget about all other param validation, just do it.
  521. //
  522. if (ulNumInputs == 0 && ulNumOutputs == 0)
  523. {
  524. _ReleaseReferences();
  525. OnReleaseObjects();
  526. return hr;
  527. }
  528. //--- Validate Params
  529. //--- Make sure we have a reference to the transform factory
  530. if( !m_cpTransFact )
  531. {
  532. hr = DXTERR_UNINITIALIZED;
  533. DXTDBG_MSG0( _CRT_ERROR, "\nTransform has not been initialized" );
  534. }
  535. else
  536. {
  537. //
  538. // We know that if we have a transform factory that we must also have
  539. // allocated m_aInputs since this is done on SetSite to avoid work during
  540. // each setup.
  541. //
  542. _ASSERT(m_aInputs || m_ulMaxInputs == 0);
  543. if( dwFlags || // No flags are valid
  544. ulNumOutputs != 1 ||
  545. ulNumInputs < m_ulNumInRequired ||
  546. ulNumInputs > m_ulMaxInputs ||
  547. (ulNumInputs && DXIsBadReadPtr( punkInputs , sizeof( *punkInputs ) * ulNumInputs )) ||
  548. DXIsBadReadPtr(punkOutputs, sizeof(*punkOutputs)) ||
  549. DXIsBadInterfacePtr(punkOutputs[0]))
  550. {
  551. hr = E_INVALIDARG;
  552. DXTDBG_MSG0( _CRT_ERROR, "\nTransform setup with invalid args" );
  553. }
  554. else
  555. {
  556. for( i = 0; i < ulNumInputs; ++i )
  557. {
  558. if((punkInputs[i] && DXIsBadInterfacePtr(punkInputs[i])) ||
  559. (punkInputs[i] == NULL && i < m_ulNumInRequired))
  560. {
  561. hr = E_INVALIDARG;
  562. DXTDBG_MSG0( _CRT_ERROR, "\nTransform setup with invalid args" );
  563. break;
  564. }
  565. }
  566. }
  567. }
  568. //--- Allocate slots for input data object pointers
  569. if( SUCCEEDED( hr ) )
  570. {
  571. //--- Release data objects
  572. _ReleaseReferences();
  573. m_ulNumInputs = ulNumInputs;
  574. }
  575. //
  576. // Assign
  577. //
  578. for( i = 0; SUCCEEDED(hr) && i < m_ulNumInputs; ++i )
  579. {
  580. hr = m_aInputs[i].Assign((m_dwOptionFlags & DXBOF_INPUTS_MESHBUILDER), punkInputs[i], m_cpSurfFact);
  581. }
  582. if( SUCCEEDED(hr) )
  583. {
  584. hr = m_Output.Assign((m_dwOptionFlags & DXBOF_OUTPUT_MESHBUILDER), punkOutputs[0], m_cpSurfFact);
  585. }
  586. if (SUCCEEDED(hr) && (m_dwOptionFlags & DXBOF_SAME_SIZE_INPUTS))
  587. {
  588. hr = _MakeInputsSameSize();
  589. }
  590. if (SUCCEEDED(hr))
  591. {
  592. _UpdateBltFlags(); // Do this before calling OnSetup...
  593. hr = OnSetup(dwFlags);
  594. }
  595. if (FAILED(hr))
  596. {
  597. _ReleaseReferences();
  598. OnReleaseObjects();
  599. DXTDBG_MSG0( _CRT_ERROR, "\nTransform setup failed" );
  600. }
  601. else
  602. {
  603. m_fIsSetup = true;
  604. }
  605. return hr;
  606. } /* CDXBaseNTo1::Setup */
  607. /*****************************************************************************
  608. * CDXBaseNTo1::_MakeInputsSameSize *
  609. *----------------------------------*
  610. * Description:
  611. *-----------------------------------------------------------------------------
  612. * Created By: RAL Date: 03/31/98
  613. *-----------------------------------------------------------------------------
  614. * Parameters:
  615. *****************************************************************************/
  616. HRESULT CDXBaseNTo1::_MakeInputsSameSize(void)
  617. {
  618. _ASSERT((m_dwOptionFlags & DXBOF_INPUTS_MESHBUILDER) == 0);
  619. HRESULT hr = S_OK;
  620. if (m_ulNumInputs > 1) // No need to do this for just one input!
  621. {
  622. CDXDBnds SurfBnds(false);
  623. CDXDBnds Union(true);
  624. ULONG i;
  625. for (i = 0; SUCCEEDED(hr) && i < m_ulNumInputs; i++)
  626. {
  627. if (InputSurface(i))
  628. {
  629. hr = SurfBnds.SetToSurfaceBounds(InputSurface(i));
  630. Union |= SurfBnds;
  631. }
  632. }
  633. for (i = 0; SUCCEEDED(hr) && i < m_ulNumInputs; i++)
  634. {
  635. if (InputSurface(i))
  636. {
  637. hr = SurfBnds.SetToSurfaceBounds(InputSurface(i));
  638. if (SUCCEEDED(hr) && SurfBnds != Union)
  639. {
  640. IDXSurfaceModifier *pSurfMod;
  641. hr = ::CoCreateInstance(CLSID_DXSurfaceModifier, NULL, CLSCTX_INPROC,
  642. IID_IDXSurfaceModifier, (void **)&pSurfMod);
  643. if (SUCCEEDED(hr))
  644. {
  645. POINT p;
  646. p.x = p.y = 0;
  647. if (m_dwOptionFlags & DXBOF_CENTER_INPUTS)
  648. {
  649. p.x = (Union.Width() - SurfBnds.Width()) / 2;
  650. p.y = (Union.Height() - SurfBnds.Height()) / 2;
  651. }
  652. pSurfMod->SetForeground(InputSurface(i), FALSE, &p);
  653. pSurfMod->SetBounds(&Union);
  654. InputSurface(i)->Release();
  655. pSurfMod->QueryInterface(IID_IDXSurface, (void **)&(m_aInputs[i].m_pNativeInterface));
  656. ((IDXSurface *)m_aInputs[i].m_pNativeInterface)->GetPixelFormat(NULL, &m_aInputs[i].m_SampleFormat);
  657. pSurfMod->Release();
  658. }
  659. }
  660. }
  661. }
  662. }
  663. return hr;
  664. }
  665. /*****************************************************************************
  666. * CDXBaseNTo1::Execute *
  667. *----------------------*
  668. * Description:
  669. * The Execute method is used to walk the inputs/outputs and break up the
  670. * work into suitably sized pieces to spread symetrically accross the available
  671. * processors in the system.
  672. *-----------------------------------------------------------------------------
  673. * Created By: Ed Connell Date: 07/28/97
  674. *-----------------------------------------------------------------------------
  675. * Parameters:
  676. *****************************************************************************/
  677. STDMETHODIMP CDXBaseNTo1::
  678. Execute( const GUID* pRequestID, const DXBNDS *pClipBnds, const DXVEC *pPlacement )
  679. {
  680. DXTDBG_FUNC( "CDXBaseNTo1::Execute" );
  681. //--- Lock object so state cannot change during execution
  682. DXAUTO_OBJ_LOCK
  683. HRESULT hr = S_OK;
  684. //--- Check args
  685. if( !HaveOutput() )
  686. {
  687. DXTDBG_MSG0( _CRT_ERROR, "\nTransform has not been initialized" );
  688. return DXTERR_UNINITIALIZED;
  689. }
  690. if (m_ulMaxImageBands == 0 ||
  691. (m_dwOptionFlags & (DXBOF_INPUTS_MESHBUILDER | DXBOF_OUTPUT_MESHBUILDER)))
  692. {
  693. if ((pClipBnds && (m_dwMiscFlags & DXTMF_BOUNDS_SUPPORTED) == 0) ||
  694. (pPlacement && (m_dwMiscFlags & DXTMF_PLACEMENT_SUPPORTED) == 0) )
  695. {
  696. DXTDBG_MSG0( _CRT_ERROR, "\nTransform setup with invalid args" );
  697. return E_INVALIDARG;
  698. }
  699. return OnExecute( pRequestID, pClipBnds, pPlacement );
  700. }
  701. //--- Banded image working variables
  702. CDXTWorkInfoNTo1 WI;
  703. if ((pClipBnds && pClipBnds->eType != DXBT_DISCRETE) ||
  704. (pPlacement && pPlacement->eType != DXBT_DISCRETE))
  705. {
  706. hr = E_INVALIDARG;
  707. DXTDBG_MSG0( _CRT_ERROR, "\nTransform setup with invalid args" );
  708. }
  709. else
  710. {
  711. hr = MapBoundsIn2Out( NULL, 0, 0, &WI.DoBnds );
  712. if( hr == S_OK )
  713. {
  714. hr = WI.OutputBnds.SetToSurfaceBounds(OutputSurface());
  715. if (hr == S_OK)
  716. {
  717. hr = DXClipToOutputWithPlacement(WI.DoBnds, (CDXDBnds *)pClipBnds, WI.OutputBnds, (CDXDVec *)pPlacement);
  718. }
  719. }
  720. }
  721. //--- Check for clipping early exit
  722. if( hr != S_OK )
  723. {
  724. return hr;
  725. }
  726. //=== Process ====================================================
  727. _ASSERT(m_ulMaxImageBands <= DXB_MAX_IMAGE_BANDS);
  728. ULONG ulNumBandsToDo = m_ulNumProcessors;
  729. if( ulNumBandsToDo > 1 )
  730. {
  731. ulNumBandsToDo = 1 + ((WI.OutputBnds.Width() * WI.OutputBnds.Height()) / 0x1000);
  732. if (ulNumBandsToDo > m_ulMaxImageBands)
  733. {
  734. ulNumBandsToDo = m_ulMaxImageBands;
  735. }
  736. if (ulNumBandsToDo > m_ulNumProcessors)
  737. {
  738. ulNumBandsToDo = m_ulNumProcessors;
  739. }
  740. }
  741. hr = OnInitInstData(WI, ulNumBandsToDo);
  742. if( SUCCEEDED( hr ) )
  743. {
  744. if (ulNumBandsToDo == 1 && pRequestID == NULL)
  745. {
  746. static BOOL bContinue = TRUE;
  747. hr = WorkProc(WI, &bContinue);
  748. }
  749. else
  750. {
  751. _ASSERT( ulNumBandsToDo <= DXB_MAX_IMAGE_BANDS );
  752. _ASSERT( m_aEvent[ulNumBandsToDo-1] );
  753. long lStartAtRow = WI.DoBnds[DXB_Y].Min;
  754. ULONG ulRowCount = WI.DoBnds[DXB_Y].Max - lStartAtRow;
  755. _ASSERT( ( ulRowCount / ulNumBandsToDo ) != 0 );
  756. //--- Init the work info structures
  757. ULONG ulBand, RowsPerBand = ulRowCount / ulNumBandsToDo;
  758. CDXTWorkInfoNTo1 *WIArray = (CDXTWorkInfoNTo1*)alloca( sizeof(CDXTWorkInfoNTo1) *
  759. ulNumBandsToDo );
  760. DWORD *TaskIDs = (DWORD*)alloca( sizeof(DWORD) * ulNumBandsToDo );
  761. DXTMTASKINFO* TaskInfo = (DXTMTASKINFO*)alloca( sizeof( DXTMTASKINFO ) *
  762. ulNumBandsToDo );
  763. //--- Build task info list
  764. WI.hr = S_OK;
  765. WI.pvThis = this;
  766. long Start = lStartAtRow;
  767. ULONG Count = RowsPerBand;
  768. long OutputYDelta = WI.OutputBnds[DXB_Y].Min - WI.DoBnds[DXB_Y].Min;
  769. for (ulBand = 0; ulBand < ulNumBandsToDo; ++ulBand)
  770. {
  771. memcpy(&WIArray[ulBand], &WI, sizeof(WI));
  772. WIArray[ulBand].DoBnds[DXB_Y].Min = Start;
  773. WIArray[ulBand].OutputBnds[DXB_Y].Min = Start + OutputYDelta;
  774. // If this is the last band, make sure it includes the last row.
  775. if (ulBand == ulNumBandsToDo - 1)
  776. {
  777. WIArray[ulBand].DoBnds[DXB_Y].Max = WI.DoBnds[DXB_Y].Max;
  778. WIArray[ulBand].OutputBnds[DXB_Y].Max = WI.OutputBnds[DXB_Y].Max;
  779. }
  780. else // Not the last band.
  781. {
  782. WIArray[ulBand].DoBnds[DXB_Y].Max = Start + Count;
  783. WIArray[ulBand].OutputBnds[DXB_Y].Max = Start + Count
  784. + OutputYDelta;
  785. }
  786. TaskInfo[ulBand].pfnTaskProc = _TaskProc;
  787. TaskInfo[ulBand].pTaskData = &WIArray[ulBand];
  788. TaskInfo[ulBand].pfnCompletionAPC = NULL;
  789. TaskInfo[ulBand].dwCompletionData = 0;
  790. TaskInfo[ulBand].pRequestID = pRequestID;
  791. // Advance.
  792. Start += Count;
  793. }
  794. //
  795. // Procedural surfaces (and perhaps some transforms) need to "know" that
  796. // they are in a multi-threaded work procedure to avoid deadlocks. Procedural
  797. // surfaces need to allow LockSurface to work WITHOUT taking the object
  798. // critical section. Other transforms may also want to know this information
  799. // to avoid deadlocks.
  800. //
  801. m_bInMultiThreadWorkProc = TRUE;
  802. //--- Schedule the work and wait for it to complete
  803. hr = m_cpTaskMgr->ScheduleTasks( TaskInfo, m_aEvent,
  804. TaskIDs, ulNumBandsToDo, m_ulLockTimeOut );
  805. m_bInMultiThreadWorkProc = FALSE;
  806. //--- Check return codes from work info structures
  807. // return the first bad hr if any
  808. for( ulBand = 0; SUCCEEDED( hr ) && ( ulBand < ulNumBandsToDo ); ++ulBand )
  809. {
  810. hr = WIArray[ulBand].hr;
  811. if( hr != S_OK ) break;
  812. }
  813. }
  814. OnFreeInstData( WI );
  815. }
  816. #ifdef _DEBUG
  817. if( FAILED( hr ) ) DXTDBG_MSG1( _CRT_ERROR, "\nExecute failed. HR = %X", hr );
  818. #endif
  819. return hr;
  820. } /* CDXBaseNTo1::Execute */
  821. /*****************************************************************************
  822. * CDXBaseNTo1::_ImageMapIn2Out *
  823. *------------------------------*
  824. * Description:
  825. *-----------------------------------------------------------------------------
  826. * Created By: RAL Date: 07/28/97
  827. *****************************************************************************/
  828. HRESULT CDXBaseNTo1::_ImageMapIn2Out( CDXDBnds & bnds, ULONG ulNumInBnds,
  829. const CDXDBnds * pInBounds )
  830. {
  831. HRESULT hr = S_OK;
  832. if(ulNumInBnds)
  833. {
  834. for(ULONG i = 0; i < ulNumInBnds; ++i )
  835. {
  836. bnds |= pInBounds[i];
  837. }
  838. }
  839. else
  840. {
  841. for( ULONG i = 0; SUCCEEDED(hr) && i < m_ulNumInputs; ++i )
  842. {
  843. if (InputSurface(i))
  844. {
  845. CDXDBnds SurfBnds(InputSurface(i), hr);
  846. bnds |= SurfBnds;
  847. }
  848. }
  849. }
  850. if (SUCCEEDED(hr))
  851. {
  852. hr = DetermineBnds(bnds);
  853. }
  854. return hr;
  855. } /* CDXBaseNTo1::_ImageMapIn2Out */
  856. /*****************************************************************************
  857. * CDXBaseNTo1::_MeshMapIn2Out *
  858. *-----------------------------*
  859. * Description:
  860. *-----------------------------------------------------------------------------
  861. * Created By: RAL Date: 07/28/97
  862. *****************************************************************************/
  863. HRESULT CDXBaseNTo1::_MeshMapIn2Out(CDXCBnds & bnds, ULONG ulNumInBnds, CDXCBnds * pInBounds)
  864. {
  865. HRESULT hr = S_OK;
  866. if (m_dwOptionFlags & DXBOF_INPUTS_MESHBUILDER)
  867. {
  868. if(ulNumInBnds)
  869. {
  870. for(ULONG i = 0; i < ulNumInBnds; ++i )
  871. {
  872. bnds |= pInBounds[i];
  873. }
  874. }
  875. else
  876. {
  877. for(ULONG i = 0; SUCCEEDED(hr) && i < m_ulNumInputs; ++i )
  878. {
  879. if (InputMeshBuilder(i))
  880. {
  881. CDXCBnds MeshBnds(InputMeshBuilder(i), hr);
  882. bnds |= MeshBnds;
  883. }
  884. }
  885. }
  886. }
  887. else
  888. {
  889. // Already done -> bnds[DXB_T].Min = 0.0f;
  890. bnds[DXB_X].Min = bnds[DXB_Y].Min = bnds[DXB_Z].Min = -1.0f;
  891. bnds[DXB_X].Max = bnds[DXB_Y].Max = bnds[DXB_Z].Max = bnds[DXB_T].Max = 1.0f;
  892. }
  893. //
  894. // Call the derived class to get the scale values.
  895. //
  896. if (SUCCEEDED(hr))
  897. {
  898. // Increase the size just a bit so we won't have rounding errors
  899. // result in bounds that don't actually contain the result.
  900. const float fBndsIncrease = 0.0001F;
  901. float fTemp = bnds.Width() * fBndsIncrease;
  902. bnds[DXB_X].Min -= fTemp;
  903. bnds[DXB_X].Max += fTemp;
  904. fTemp = fBndsIncrease * bnds.Height();
  905. bnds[DXB_Y].Min -= fTemp;
  906. bnds[DXB_Y].Max += fTemp;
  907. fTemp = fBndsIncrease * bnds.Depth();
  908. bnds[DXB_Z].Min -= fTemp;
  909. bnds[DXB_Z].Max += fTemp;
  910. hr = DetermineBnds(bnds);
  911. }
  912. return hr;
  913. } /* CDXBaseNTo1::_MeshMapIn2Out */
  914. /*****************************************************************************
  915. * CDXBaseNTo1::MapBoundsIn2Out *
  916. *------------------------------*
  917. * Description:
  918. * The MapBoundsIn2Out method is used to perform coordinate transformation
  919. * from the input to the output coordinate space.
  920. *-----------------------------------------------------------------------------
  921. * Created By: Ed Connell Date: 07/28/97
  922. *-----------------------------------------------------------------------------
  923. * Parameters:
  924. *****************************************************************************/
  925. STDMETHODIMP CDXBaseNTo1::MapBoundsIn2Out( const DXBNDS *pInBounds, ULONG ulNumInBnds,
  926. ULONG ulOutIndex, DXBNDS *pOutBounds )
  927. {
  928. DXTDBG_FUNC( "CDXBaseNTo1::MapBoundsIn2Out" );
  929. if((ulNumInBnds && DXIsBadReadPtr( pInBounds, ulNumInBnds * sizeof( *pInBounds ) )) ||
  930. ulOutIndex)
  931. {
  932. return E_INVALIDARG;
  933. }
  934. if( DXIsBadWritePtr( pOutBounds, sizeof( *pOutBounds ) ) )
  935. {
  936. return E_POINTER;
  937. }
  938. //
  939. // Set the bounds to empty and the appropriate type.
  940. //
  941. memset(pOutBounds, 0, sizeof(*pOutBounds));
  942. _ASSERT(DXBT_DISCRETE == 0);
  943. if (m_dwOptionFlags & DXBOF_OUTPUT_MESHBUILDER)
  944. {
  945. pOutBounds->eType = DXBT_CONTINUOUS;
  946. }
  947. //
  948. // Make sure all input bounds are of the correct type.
  949. //
  950. if( ulNumInBnds )
  951. {
  952. DXBNDTYPE eType = (m_dwOptionFlags & DXBOF_INPUTS_MESHBUILDER) ? DXBT_CONTINUOUS : DXBT_DISCRETE;
  953. for (ULONG i = 0; i < ulNumInBnds; i++)
  954. {
  955. if (pInBounds[i].eType != eType)
  956. {
  957. return E_INVALIDARG;
  958. }
  959. }
  960. }
  961. //
  962. // Now do the appropriate mapping
  963. //
  964. if (m_dwOptionFlags & DXBOF_OUTPUT_MESHBUILDER)
  965. {
  966. //
  967. // NOTE: In the case of non-mesh inputs, the inputs are discrete, but they will
  968. // be completely ignored by the function so it's OK to cast them to CDXCBnds
  969. //
  970. return _MeshMapIn2Out(*((CDXCBnds *)pOutBounds), ulNumInBnds, (CDXCBnds *)pInBounds);
  971. }
  972. else
  973. {
  974. return _ImageMapIn2Out(*(CDXDBnds *)pOutBounds, ulNumInBnds, (CDXDBnds *)pInBounds);
  975. }
  976. } /* CDXBaseNTo1::MapBoundsIn2Out */
  977. /*****************************************************************************
  978. * CDXBaseNTo1::MapBoundsOut2In *
  979. *------------------------------*
  980. * Description:
  981. * The MapBoundsOut2In method is used to perform coordinate transformation
  982. * from the input to the output coordinate space.
  983. *-----------------------------------------------------------------------------
  984. * Created By: Ed Connell Date: 07/28/97
  985. *-----------------------------------------------------------------------------
  986. * Parameters:
  987. *****************************************************************************/
  988. STDMETHODIMP CDXBaseNTo1::
  989. MapBoundsOut2In( ULONG ulOutIndex, const DXBNDS *pOutBounds, ULONG ulInIndex, DXBNDS *pInBounds )
  990. {
  991. DXTDBG_FUNC( "CDXBaseNTo1::MapBoundsOut2In" );
  992. HRESULT hr = S_OK;
  993. if (m_dwOptionFlags & DXBOF_OUTPUT_MESHBUILDER)
  994. {
  995. hr = E_NOTIMPL; // This is pointless for meshes.
  996. }
  997. else if(ulInIndex >= m_ulMaxInputs || ulOutIndex || DXIsBadReadPtr( pOutBounds, sizeof( *pOutBounds ) ) )
  998. {
  999. hr = E_INVALIDARG;
  1000. }
  1001. else if( DXIsBadWritePtr( pInBounds, sizeof( *pInBounds ) ) )
  1002. {
  1003. hr = E_POINTER;
  1004. }
  1005. else
  1006. {
  1007. *pInBounds = *pOutBounds;
  1008. }
  1009. return hr;
  1010. } /* CDXBaseNTo1::MapBoundsOut2In */
  1011. /*****************************************************************************
  1012. * CDXBaseNTo1::SetMiscFlags *
  1013. *---------------------------*
  1014. * Description:
  1015. *-----------------------------------------------------------------------------
  1016. * Created By: RAL Date: 10/30.97
  1017. *-----------------------------------------------------------------------------
  1018. * Parameters:
  1019. * bMiscFlags - New value to set
  1020. *****************************************************************************/
  1021. STDMETHODIMP CDXBaseNTo1::SetMiscFlags( DWORD dwMiscFlags )
  1022. {
  1023. DXTDBG_FUNC( "CDXBaseNTo1::SetMiscFlags" );
  1024. HRESULT hr = S_OK;
  1025. Lock();
  1026. WORD wOpts = (WORD)dwMiscFlags; // Ignore high word. Only set low word.
  1027. if (((WORD)m_dwMiscFlags) != wOpts)
  1028. {
  1029. if ((wOpts & (~DXTMF_VALID_OPTIONS)) ||
  1030. ((wOpts & DXTMF_BLEND_WITH_OUTPUT) && (m_dwMiscFlags & DXTMF_BLEND_SUPPORTED) == 0) ||
  1031. ((wOpts & DXTMF_DITHER_OUTPUT) && (m_dwMiscFlags & DXTMF_DITHER_SUPPORTED) == 0))
  1032. {
  1033. hr = E_INVALIDARG;
  1034. }
  1035. else
  1036. {
  1037. m_dwMiscFlags &= 0xFFFF0000;
  1038. m_dwMiscFlags |= wOpts;
  1039. _UpdateBltFlags();
  1040. m_dwGenerationId++;
  1041. }
  1042. }
  1043. Unlock();
  1044. return hr;
  1045. } /* CDXBaseNTo1::SetMiscFlags */
  1046. /*****************************************************************************
  1047. * CDXBaseNTo1::GetMiscFlags *
  1048. *----------------------------*
  1049. * Description:
  1050. *-----------------------------------------------------------------------------
  1051. * Created By: RAL Date: 10/30/97
  1052. *-----------------------------------------------------------------------------
  1053. * Parameters:
  1054. *****************************************************************************/
  1055. STDMETHODIMP CDXBaseNTo1::GetMiscFlags( DWORD* pdwMiscFlags )
  1056. {
  1057. if( DXIsBadWritePtr( pdwMiscFlags, sizeof( *pdwMiscFlags ) ) )
  1058. {
  1059. return E_POINTER;
  1060. }
  1061. *pdwMiscFlags = m_dwMiscFlags;
  1062. return S_OK;
  1063. } /* CDXBaseNTo1::GetMiscFlags */
  1064. /*****************************************************************************
  1065. * CDXBaseNTo1::SetQuality *
  1066. *----------------------------*
  1067. * Description:
  1068. *-----------------------------------------------------------------------------
  1069. * Created By: RAL Date: 10/30/97
  1070. *-----------------------------------------------------------------------------
  1071. * Parameters:
  1072. *****************************************************************************/
  1073. STDMETHODIMP CDXBaseNTo1::SetQuality(float fQuality)
  1074. {
  1075. if ((m_dwMiscFlags & DXTMF_QUALITY_SUPPORTED) == 0)
  1076. {
  1077. return E_NOTIMPL;
  1078. }
  1079. if (fQuality < 0.0f || fQuality > 1.0f)
  1080. {
  1081. return E_INVALIDARG;
  1082. }
  1083. Lock();
  1084. if (m_fQuality != fQuality)
  1085. {
  1086. m_fQuality = fQuality;
  1087. m_dwGenerationId++;
  1088. }
  1089. Unlock();
  1090. return S_OK;
  1091. }
  1092. /*****************************************************************************
  1093. * CDXBaseNTo1::GetQuality *
  1094. *-------------------------*
  1095. * Description:
  1096. *-----------------------------------------------------------------------------
  1097. * Created By: RAL Date: 10/30/97
  1098. *-----------------------------------------------------------------------------
  1099. * Parameters:
  1100. *****************************************************************************/
  1101. STDMETHODIMP CDXBaseNTo1::GetQuality(float *pfQuality)
  1102. {
  1103. HRESULT hr = S_OK;
  1104. if ((m_dwMiscFlags & DXTMF_QUALITY_SUPPORTED) == 0)
  1105. {
  1106. hr = E_NOTIMPL;
  1107. }
  1108. else
  1109. {
  1110. if( DXIsBadWritePtr( pfQuality, sizeof( *pfQuality ) ) )
  1111. {
  1112. hr = E_POINTER;
  1113. }
  1114. else
  1115. {
  1116. *pfQuality = m_fQuality;
  1117. }
  1118. }
  1119. return hr;
  1120. }
  1121. /*****************************************************************************
  1122. * GetInOutInfo
  1123. *-----------------------------------------------------------------------------
  1124. * Description:
  1125. *-----------------------------------------------------------------------------
  1126. * Created By: RAL Date: 12/10/97
  1127. *-----------------------------------------------------------------------------
  1128. * Parameters:
  1129. *****************************************************************************/
  1130. STDMETHODIMP CDXBaseNTo1::GetInOutInfo( BOOL bOutput, ULONG ulIndex, DWORD *pdwFlags,
  1131. GUID * pIDs, ULONG *pcIDs, IUnknown **ppUnkCurObj )
  1132. {
  1133. DXTDBG_FUNC( "CDXBaseNTo1::GetInOutInfo" );
  1134. HRESULT hr = S_FALSE;
  1135. DWORD dwFlags = 0;
  1136. BOOL bImage;
  1137. if( bOutput )
  1138. {
  1139. bImage = !(m_dwOptionFlags & DXBOF_OUTPUT_MESHBUILDER);
  1140. if (ulIndex == 0)
  1141. {
  1142. hr = S_OK;
  1143. }
  1144. }
  1145. else
  1146. {
  1147. bImage = !(m_dwOptionFlags & DXBOF_INPUTS_MESHBUILDER);
  1148. if (ulIndex < m_ulMaxInputs)
  1149. {
  1150. hr = S_OK;
  1151. if (ulIndex >= m_ulNumInRequired)
  1152. {
  1153. dwFlags = DXINOUTF_OPTIONAL;
  1154. }
  1155. }
  1156. }
  1157. if( hr == S_OK )
  1158. {
  1159. if( pdwFlags && !DXIsBadWritePtr( pdwFlags, sizeof( *pdwFlags ) ) )
  1160. {
  1161. *pdwFlags = dwFlags;
  1162. }
  1163. if( pIDs )
  1164. {
  1165. if( DXIsBadWritePtr( pcIDs, sizeof( *pcIDs ) ) ||
  1166. DXIsBadWritePtr( pIDs, *pcIDs * sizeof( *pIDs ) ) )
  1167. {
  1168. hr = E_INVALIDARG;
  1169. }
  1170. else
  1171. {
  1172. if (bImage)
  1173. {
  1174. if (*pcIDs > 0)
  1175. {
  1176. pIDs[0] = IID_IDXSurface;
  1177. }
  1178. if (*pcIDs > 1)
  1179. {
  1180. pIDs[1] = IID_IDXDupDDrawSurface;
  1181. }
  1182. else
  1183. {
  1184. hr = HRESULT_FROM_WIN32(ERROR_MORE_DATA);
  1185. }
  1186. *pcIDs = 2;
  1187. }
  1188. else
  1189. {
  1190. if (*pcIDs > 0)
  1191. {
  1192. pIDs[0] = IID_IDXDupDirect3DRMMeshBuilder3;
  1193. }
  1194. else
  1195. {
  1196. hr = HRESULT_FROM_WIN32(ERROR_MORE_DATA);
  1197. }
  1198. *pcIDs = 1;
  1199. }
  1200. }
  1201. }
  1202. else if( pcIDs )
  1203. {
  1204. if( DXIsBadWritePtr( pcIDs, sizeof( *pcIDs ) ) )
  1205. {
  1206. hr = E_POINTER;
  1207. }
  1208. else
  1209. {
  1210. *pcIDs = bImage ? 2 : 1;
  1211. }
  1212. }
  1213. if (hr == S_OK && ppUnkCurObj)
  1214. {
  1215. if (DXIsBadWritePtr(ppUnkCurObj, sizeof(*ppUnkCurObj)))
  1216. {
  1217. hr = E_POINTER;
  1218. }
  1219. else
  1220. {
  1221. if (bOutput)
  1222. {
  1223. *ppUnkCurObj = m_Output.m_pNativeInterface;
  1224. }
  1225. else
  1226. {
  1227. *ppUnkCurObj = NULL;
  1228. if (ulIndex < GetNumInputs())
  1229. {
  1230. *ppUnkCurObj = m_aInputs[ulIndex].m_pUnkOriginalObject;
  1231. }
  1232. }
  1233. if (*ppUnkCurObj)
  1234. {
  1235. (*ppUnkCurObj)->AddRef();
  1236. }
  1237. }
  1238. }
  1239. }
  1240. return hr;
  1241. } /* CDXBaseNTo1::GetInOutInfo */
  1242. /*****************************************************************************
  1243. * CDXBaseNTo1::OnUpdateGenerationId *
  1244. *-----------------------------------*
  1245. * Description:
  1246. *-----------------------------------------------------------------------------
  1247. * Created By: RAL Date: 12/10/97
  1248. *-----------------------------------------------------------------------------
  1249. * Parameters:
  1250. *****************************************************************************/
  1251. void CDXBaseNTo1::OnUpdateGenerationId(void)
  1252. {
  1253. DXTDBG_FUNC( "CDXBaseNTo1::OnUpdateGenerationId" );
  1254. if( (m_dwMiscFlags & DXTMF_INPLACE_OPERATION) &&
  1255. m_Output.UpdateGenerationId())
  1256. {
  1257. m_dwGenerationId++;
  1258. }
  1259. for (ULONG i = 0; i < m_ulNumInputs; i++)
  1260. {
  1261. if (m_aInputs[i].UpdateGenerationId())
  1262. {
  1263. m_dwGenerationId++;
  1264. }
  1265. }
  1266. } /* CDXBaseNTo1::OnUpdateGenerationId */
  1267. /*****************************************************************************
  1268. * CDXBaseNTo1::OnGetObjectSize *
  1269. *------------------------------*
  1270. * Description:
  1271. *-----------------------------------------------------------------------------
  1272. * Created By: RAL Date: 12/10/97
  1273. *****************************************************************************/
  1274. ULONG CDXBaseNTo1::OnGetObjectSize(void)
  1275. {
  1276. return sizeof(*this);
  1277. }
  1278. //
  1279. // Effect interface
  1280. //
  1281. /*****************************************************************************
  1282. * CDXBaseNTo1::get_Progress *
  1283. *---------------------------*
  1284. * Description:
  1285. *-----------------------------------------------------------------------------
  1286. * Created By: RAL Date: 12/10/97
  1287. *****************************************************************************/
  1288. STDMETHODIMP CDXBaseNTo1::get_Progress(float *pVal)
  1289. {
  1290. DXTDBG_FUNC( "CDXBaseNTo1::get_Progress" );
  1291. HRESULT hr = S_OK;
  1292. if( DXIsBadWritePtr(pVal, sizeof(*pVal)) )
  1293. {
  1294. hr = E_POINTER;
  1295. }
  1296. else
  1297. {
  1298. *pVal = m_Progress;
  1299. }
  1300. return hr;
  1301. }
  1302. /*****************************************************************************
  1303. * CDXBaseNTo1::put_Progress *
  1304. *---------------------------*
  1305. * Description:
  1306. *-----------------------------------------------------------------------------
  1307. * Created By: RAL Date: 12/10/97
  1308. *****************************************************************************/
  1309. STDMETHODIMP CDXBaseNTo1::put_Progress(float newVal)
  1310. {
  1311. DXTDBG_FUNC( "CDXBaseNTo1::put_Progress" );
  1312. HRESULT hr = S_OK;
  1313. if (newVal < 0.0 || newVal > 1.0f)
  1314. {
  1315. hr = E_INVALIDARG;
  1316. }
  1317. else
  1318. {
  1319. Lock();
  1320. m_Progress = newVal;
  1321. m_dwCleanGenId++; // This should not make the transform "dirty" internally
  1322. m_dwGenerationId++;
  1323. Unlock();
  1324. }
  1325. return hr;
  1326. }
  1327. /*****************************************************************************
  1328. * CDXBaseNTo1::get_StepResolution *
  1329. *---------------------------------*
  1330. * Description:
  1331. *-----------------------------------------------------------------------------
  1332. * Created By: RAL Date: 12/10/97
  1333. *****************************************************************************/
  1334. STDMETHODIMP CDXBaseNTo1::get_StepResolution(float *pVal)
  1335. {
  1336. DXTDBG_FUNC( "CDXBaseNTo1::get_StepResolution" );
  1337. HRESULT hr = S_OK;
  1338. if( DXIsBadWritePtr(pVal, sizeof(*pVal)) )
  1339. {
  1340. hr = E_POINTER;
  1341. }
  1342. else
  1343. {
  1344. *pVal = m_StepResolution;
  1345. }
  1346. return hr;
  1347. }
  1348. /*****************************************************************************
  1349. * CDXBaseNTo1::get_Duration *
  1350. *---------------------------*
  1351. * Description:
  1352. *-----------------------------------------------------------------------------
  1353. * Created By: RAL Date: 12/10/97
  1354. *****************************************************************************/
  1355. STDMETHODIMP CDXBaseNTo1::get_Duration(float *pVal)
  1356. {
  1357. DXTDBG_FUNC( "CDXBaseNTo1::get_Duration" );
  1358. if( DXIsBadWritePtr(pVal, sizeof(*pVal)) )
  1359. {
  1360. return E_POINTER;
  1361. }
  1362. else
  1363. {
  1364. *pVal = m_Duration;
  1365. }
  1366. return S_OK;
  1367. }
  1368. /*****************************************************************************
  1369. * CDXBaseNTo1::put_Duration *
  1370. *---------------------------*
  1371. * Description:
  1372. *-----------------------------------------------------------------------------
  1373. * Created By: RAL Date: 12/10/97
  1374. *****************************************************************************/
  1375. STDMETHODIMP CDXBaseNTo1::put_Duration(float newVal)
  1376. {
  1377. DXTDBG_FUNC( "CDXBaseNTo1::put_Duration" );
  1378. if (newVal <= 0.)
  1379. {
  1380. return E_INVALIDARG;
  1381. }
  1382. if(newVal != m_Duration)
  1383. {
  1384. Lock();
  1385. m_dwGenerationId++;
  1386. m_dwCleanGenId++; // This should not make the transform "dirty" internally
  1387. m_Duration = newVal;
  1388. Unlock();
  1389. }
  1390. return S_OK;
  1391. }
  1392. /*****************************************************************************
  1393. * CDXBaseNTo1::PointPick *
  1394. *------------------------*
  1395. * Description:
  1396. *-----------------------------------------------------------------------------
  1397. * Created By: RAL Date: 5/5/98
  1398. *****************************************************************************/
  1399. STDMETHODIMP CDXBaseNTo1::PointPick(const DXVEC *pPoint,
  1400. ULONG * pulInputSurfaceIndex,
  1401. DXVEC *pInputPoint)
  1402. {
  1403. HRESULT hr = S_OK;
  1404. BOOL bFoundIt = FALSE;
  1405. // If we haven't been set up yet, we will just act as if we're transparent.
  1406. if (!m_fIsSetup)
  1407. {
  1408. hr = S_FALSE;
  1409. goto done;
  1410. }
  1411. if (DXIsBadReadPtr(pPoint, sizeof(*pPoint)) || pPoint->eType != DXBT_DISCRETE)
  1412. {
  1413. hr = E_INVALIDARG;
  1414. }
  1415. else
  1416. {
  1417. if (DXIsBadWritePtr(pulInputSurfaceIndex, sizeof(*pulInputSurfaceIndex)) ||
  1418. DXIsBadWritePtr(pInputPoint, sizeof(*pInputPoint)))
  1419. {
  1420. hr = E_POINTER;
  1421. }
  1422. else
  1423. {
  1424. HRESULT hr2 = S_OK;
  1425. CDXDBnds bndsOutput;
  1426. CDXDBnds OutBndsPoint(*((CDXDVec *)pPoint));
  1427. CDXDVec & InVec = *(new(pInputPoint) CDXDVec(*((CDXDVec *)pPoint)));
  1428. // Get the output size of the DXTransform. If this point is not on
  1429. // the output at all, we can return S_FALSE right now.
  1430. hr = MapBoundsIn2Out(NULL, 0, 0, &bndsOutput);
  1431. if (FAILED(hr))
  1432. {
  1433. goto done;
  1434. }
  1435. if (!bndsOutput.TestIntersect(OutBndsPoint))
  1436. {
  1437. hr = S_FALSE;
  1438. goto done;
  1439. }
  1440. hr2 = OnSurfacePick(OutBndsPoint, *pulInputSurfaceIndex, InVec);
  1441. if (hr2 != E_NOTIMPL)
  1442. {
  1443. hr = hr2;
  1444. }
  1445. else
  1446. {
  1447. //--- The derived class does not implement so we will do
  1448. // the hit test against the input for them.
  1449. ULONG * aulInIndex = (ULONG *)_alloca(sizeof(ULONG) * m_ulMaxInputs);
  1450. BYTE * aWeights = (BYTE *)_alloca(sizeof(BYTE) * m_ulMaxInputs);
  1451. ULONG ulNumToTest;
  1452. OnGetSurfacePickOrder(OutBndsPoint, ulNumToTest, aulInIndex, aWeights);
  1453. if( m_bPickDoneByBase && ( m_ulNumInputs > 1 ) )
  1454. {
  1455. //--- We don't know how to do multi-input picking from the base.
  1456. hr = E_NOTIMPL;
  1457. }
  1458. for (ULONG i = 0; SUCCEEDED(hr) && i < ulNumToTest; i++)
  1459. {
  1460. ULONG ulInput = aulInIndex[i];
  1461. if (HaveInput(ulInput) && aWeights[i])
  1462. {
  1463. CDXDBnds Out2InBnds(false);
  1464. hr = MapBoundsOut2In(0, &OutBndsPoint, ulInput, &Out2InBnds);
  1465. if (SUCCEEDED(hr))
  1466. {
  1467. CDXDBnds InSurfBnds(InputSurface(ulInput), hr);
  1468. if (SUCCEEDED(hr) && InSurfBnds.IntersectBounds(Out2InBnds))
  1469. {
  1470. IDXARGBReadPtr * pPtr;
  1471. hr = InputSurface(ulInput)->LockSurface(&InSurfBnds, m_ulLockTimeOut, DXLOCKF_READ,
  1472. IID_IDXARGBReadPtr, (void **)&pPtr, NULL);
  1473. if( SUCCEEDED(hr) )
  1474. {
  1475. DXPMSAMPLE val;
  1476. pPtr->UnpackPremult(&val, 1, FALSE);
  1477. pPtr->Release();
  1478. if (val.Alpha * aWeights[i] / 255)
  1479. {
  1480. InSurfBnds.GetMinVector(InVec);
  1481. bFoundIt = TRUE;
  1482. *pulInputSurfaceIndex = ulInput;
  1483. break;
  1484. }
  1485. }
  1486. }
  1487. }
  1488. }
  1489. }
  1490. if (SUCCEEDED(hr) & (!bFoundIt))
  1491. {
  1492. hr = S_FALSE;
  1493. }
  1494. }
  1495. }
  1496. }
  1497. done:
  1498. return hr;
  1499. } /* CDXBaseNTo1::PointPick */
  1500. /*****************************************************************************
  1501. * RegisterTansform (STATIC member function)
  1502. *-----------------------------------------------------------------------------
  1503. * Description:
  1504. *-----------------------------------------------------------------------------
  1505. * Created By: RAL Date: 12/10/97
  1506. *-----------------------------------------------------------------------------
  1507. * Parameters:
  1508. *****************************************************************************/
  1509. HRESULT CDXBaseNTo1::
  1510. RegisterTransform(REFCLSID rcid, int ResourceId, ULONG cCatImpl, const CATID * pCatImpl,
  1511. ULONG cCatReq, const CATID * pCatReq, BOOL bRegister)
  1512. {
  1513. DXTDBG_FUNC( "CDXBaseNTo1::RegisterTransform" );
  1514. HRESULT hr = bRegister ? _Module.UpdateRegistryFromResource(ResourceId, bRegister) : S_OK;
  1515. if (SUCCEEDED(hr))
  1516. {
  1517. CComPtr<ICatRegister> pCatRegister;
  1518. HRESULT hr = ::CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC, IID_ICatRegister, (void **)&pCatRegister);
  1519. if (SUCCEEDED(hr))
  1520. {
  1521. if (bRegister)
  1522. {
  1523. hr = pCatRegister->RegisterClassImplCategories(rcid, cCatImpl, (CATID *)pCatImpl);
  1524. if (SUCCEEDED(hr) && cCatReq && pCatReq) {
  1525. hr = pCatRegister->RegisterClassReqCategories(rcid, cCatReq, (CATID *)pCatReq);
  1526. }
  1527. }
  1528. else
  1529. {
  1530. pCatRegister->UnRegisterClassImplCategories(rcid, cCatImpl, (CATID *)pCatImpl);
  1531. if (cCatReq && pCatReq)
  1532. {
  1533. pCatRegister->UnRegisterClassReqCategories(rcid, cCatReq, (CATID *)pCatReq);
  1534. }
  1535. }
  1536. }
  1537. }
  1538. if ((!bRegister) && SUCCEEDED(hr))
  1539. {
  1540. _Module.UpdateRegistryFromResource(ResourceId, bRegister);
  1541. }
  1542. return hr;
  1543. }
  1544. void CDXBaseNTo1::_TaskProc(void* pTaskInfo, BOOL* pbContinue )
  1545. {
  1546. _ASSERT( pTaskInfo );
  1547. CDXTWorkInfoNTo1& WI = *((CDXTWorkInfoNTo1 *)pTaskInfo);
  1548. CDXBaseNTo1& This = *((CDXBaseNTo1 *)WI.pvThis);
  1549. WI.hr = This.WorkProc(WI, pbContinue);
  1550. }