DX9AllocatorPresenter.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:51k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* 
  2.  * Copyright (C) 2003-2005 Gabest
  3.  * http://www.gabest.org
  4.  *
  5.  *  This Program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2, or (at your option)
  8.  *  any later version.
  9.  *   
  10.  *  This Program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13.  *  GNU General Public License for more details.
  14.  *   
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with GNU Make; see the file COPYING.  If not, write to
  17.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  18.  *  http://www.gnu.org/copyleft/gpl.html
  19.  *
  20.  */
  21. #include "stdafx.h"
  22. #include "mplayerc.h"
  23. #include <atlbase.h>
  24. #include <atlcoll.h>
  25. #include "....DSUtilDSUtil.h"
  26. #include <Videoacc.h>
  27. #include <initguid.h>
  28. #include "DX9AllocatorPresenter.h"
  29. #include <d3d9.h>
  30. #include <d3dx9.h>
  31. #include <Vmr9.h>
  32. #include "....SubPicDX9SubPic.h"
  33. #include "......includeRealMediapntypes.h"
  34. #include "......includeRealMediapnwintyp.h"
  35. #include "......includeRealMediapncom.h"
  36. #include "......includeRealMediarmavsurf.h"
  37. #include "IQTVideoSurface.h"
  38. #include "MacrovisionKicker.h"
  39. #include "IPinHook.h"
  40. #include "PixelShaderCompiler.h"
  41. bool IsVMR9InGraph(IFilterGraph* pFG)
  42. {
  43. BeginEnumFilters(pFG, pEF, pBF)
  44. if(CComQIPtr<IVMRWindowlessControl9>(pBF)) return(true);
  45. EndEnumFilters
  46. return(false);
  47. }
  48. namespace DSObjects
  49. {
  50. class CDX9AllocatorPresenter
  51. : public ISubPicAllocatorPresenterImpl
  52. {
  53. protected:
  54. CSize m_ScreenSize;
  55. bool m_fVMRSyncFix;
  56. CComPtr<IDirect3D9> m_pD3D;
  57.     CComPtr<IDirect3DDevice9> m_pD3DDev;
  58. CComPtr<IDirect3DTexture9> m_pVideoTexture[2];
  59. CComPtr<IDirect3DSurface9> m_pVideoSurface[2];
  60. CComPtr<IDirect3DPixelShader9> m_pPixelShader, m_pResizerPixelShader[4];
  61. D3DTEXTUREFILTERTYPE m_Filter;
  62. CAutoPtr<CPixelShaderCompiler> m_pPSC;
  63. virtual HRESULT CreateDevice();
  64. virtual HRESULT AllocSurfaces();
  65. virtual void DeleteSurfaces();
  66.     UINT  GetAdapter(IDirect3D9 *pD3D);
  67. public:
  68. CDX9AllocatorPresenter(HWND hWnd, HRESULT& hr);
  69. // ISubPicAllocatorPresenter
  70. STDMETHODIMP CreateRenderer(IUnknown** ppRenderer);
  71. STDMETHODIMP_(bool) Paint(bool fAll);
  72. STDMETHODIMP GetDIB(BYTE* lpDib, DWORD* size);
  73. STDMETHODIMP SetPixelShader(LPCSTR pSrcData, LPCSTR pTarget);
  74. };
  75. class CVMR9AllocatorPresenter
  76. : public CDX9AllocatorPresenter
  77. , public IVMRSurfaceAllocator9
  78. , public IVMRImagePresenter9
  79. , public IVMRWindowlessControl9
  80. {
  81. protected:
  82. CComPtr<IVMRSurfaceAllocatorNotify9> m_pIVMRSurfAllocNotify;
  83. CInterfaceArray<IDirect3DSurface9> m_pSurfaces;
  84. HRESULT CreateDevice();
  85. void DeleteSurfaces();
  86. bool m_fUseInternalTimer;
  87. public:
  88. CVMR9AllocatorPresenter(HWND hWnd, HRESULT& hr);
  89. DECLARE_IUNKNOWN
  90.     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
  91. // ISubPicAllocatorPresenter
  92. STDMETHODIMP CreateRenderer(IUnknown** ppRenderer);
  93. STDMETHODIMP_(void) SetTime(REFERENCE_TIME rtNow);
  94.     // IVMRSurfaceAllocator9
  95.     STDMETHODIMP InitializeDevice(DWORD_PTR dwUserID, VMR9AllocationInfo* lpAllocInfo, DWORD* lpNumBuffers);
  96.     STDMETHODIMP TerminateDevice(DWORD_PTR dwID);
  97.     STDMETHODIMP GetSurface(DWORD_PTR dwUserID, DWORD SurfaceIndex, DWORD SurfaceFlags, IDirect3DSurface9** lplpSurface);
  98.     STDMETHODIMP AdviseNotify(IVMRSurfaceAllocatorNotify9* lpIVMRSurfAllocNotify);
  99.     // IVMRImagePresenter9
  100.     STDMETHODIMP StartPresenting(DWORD_PTR dwUserID);
  101.     STDMETHODIMP StopPresenting(DWORD_PTR dwUserID);
  102.     STDMETHODIMP PresentImage(DWORD_PTR dwUserID, VMR9PresentationInfo* lpPresInfo);
  103. // IVMRWindowlessControl9
  104. STDMETHODIMP GetNativeVideoSize(LONG* lpWidth, LONG* lpHeight, LONG* lpARWidth, LONG* lpARHeight);
  105. STDMETHODIMP GetMinIdealVideoSize(LONG* lpWidth, LONG* lpHeight);
  106. STDMETHODIMP GetMaxIdealVideoSize(LONG* lpWidth, LONG* lpHeight);
  107. STDMETHODIMP SetVideoPosition(const LPRECT lpSRCRect, const LPRECT lpDSTRect);
  108.     STDMETHODIMP GetVideoPosition(LPRECT lpSRCRect, LPRECT lpDSTRect);
  109. STDMETHODIMP GetAspectRatioMode(DWORD* lpAspectRatioMode);
  110. STDMETHODIMP SetAspectRatioMode(DWORD AspectRatioMode);
  111. STDMETHODIMP SetVideoClippingWindow(HWND hwnd);
  112. STDMETHODIMP RepaintVideo(HWND hwnd, HDC hdc);
  113. STDMETHODIMP DisplayModeChanged();
  114. STDMETHODIMP GetCurrentImage(BYTE** lpDib);
  115. STDMETHODIMP SetBorderColor(COLORREF Clr);
  116. STDMETHODIMP GetBorderColor(COLORREF* lpClr);
  117. };
  118. class CRM9AllocatorPresenter
  119. : public CDX9AllocatorPresenter
  120. , public IRMAVideoSurface
  121. {
  122. CComPtr<IDirect3DSurface9> m_pVideoSurfaceOff;
  123. CComPtr<IDirect3DSurface9> m_pVideoSurfaceYUY2;
  124.     RMABitmapInfoHeader m_bitmapInfo;
  125.     RMABitmapInfoHeader m_lastBitmapInfo;
  126. protected:
  127. HRESULT AllocSurfaces();
  128. void DeleteSurfaces();
  129. public:
  130. CRM9AllocatorPresenter(HWND hWnd, HRESULT& hr);
  131. DECLARE_IUNKNOWN
  132.     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
  133. // IRMAVideoSurface
  134.     STDMETHODIMP Blt(UCHAR* pImageData, RMABitmapInfoHeader* pBitmapInfo, REF(PNxRect) inDestRect, REF(PNxRect) inSrcRect);
  135. STDMETHODIMP BeginOptimizedBlt(RMABitmapInfoHeader* pBitmapInfo);
  136. STDMETHODIMP OptimizedBlt(UCHAR* pImageBits, REF(PNxRect) rDestRect, REF(PNxRect) rSrcRect);
  137. STDMETHODIMP EndOptimizedBlt();
  138. STDMETHODIMP GetOptimizedFormat(REF(RMA_COMPRESSION_TYPE) ulType);
  139.     STDMETHODIMP GetPreferredFormat(REF(RMA_COMPRESSION_TYPE) ulType);
  140. };
  141. class CQT9AllocatorPresenter
  142. : public CDX9AllocatorPresenter
  143. , public IQTVideoSurface
  144. {
  145. CComPtr<IDirect3DSurface9> m_pVideoSurfaceOff;
  146. protected:
  147.  HRESULT AllocSurfaces();
  148.  void DeleteSurfaces();
  149. public:
  150. CQT9AllocatorPresenter(HWND hWnd, HRESULT& hr);
  151. DECLARE_IUNKNOWN
  152.     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
  153. // IQTVideoSurface
  154. STDMETHODIMP BeginBlt(const BITMAP& bm);
  155. STDMETHODIMP DoBlt(const BITMAP& bm);
  156. };
  157. }
  158. using namespace DSObjects;
  159. //
  160. HRESULT CreateAP9(const CLSID& clsid, HWND hWnd, ISubPicAllocatorPresenter** ppAP)
  161. {
  162. CheckPointer(ppAP, E_POINTER);
  163. *ppAP = NULL;
  164. HRESULT hr;
  165. if(clsid == CLSID_VMR9AllocatorPresenter && !(*ppAP = new CVMR9AllocatorPresenter(hWnd, hr))
  166. || clsid == CLSID_RM9AllocatorPresenter && !(*ppAP = new CRM9AllocatorPresenter(hWnd, hr))
  167. || clsid == CLSID_QT9AllocatorPresenter && !(*ppAP = new CQT9AllocatorPresenter(hWnd, hr)))
  168. return E_OUTOFMEMORY;
  169. if(*ppAP == NULL)
  170. return E_FAIL;
  171. (*ppAP)->AddRef();
  172. if(FAILED(hr))
  173. {
  174. (*ppAP)->Release();
  175. *ppAP = NULL;
  176. }
  177. return hr;
  178. }
  179. //
  180. static HRESULT TextureBlt(CComPtr<IDirect3DTexture9> pTexture, Vector dst[4], CRect src, DWORD filter = D3DTEXF_LINEAR)
  181. {
  182. if(!pTexture)
  183. return E_POINTER;
  184. CComPtr<IDirect3DDevice9> pD3DDev;
  185. if(FAILED(pTexture->GetDevice(&pD3DDev)) || !pD3DDev)
  186. return E_FAIL;
  187. HRESULT hr;
  188.     do
  189. {
  190. D3DSURFACE_DESC d3dsd;
  191. ZeroMemory(&d3dsd, sizeof(d3dsd));
  192. if(FAILED(pTexture->GetLevelDesc(0, &d3dsd)))
  193. break;
  194.         float w = (float)d3dsd.Width;
  195.         float h = (float)d3dsd.Height;
  196. struct
  197. {
  198. float x, y, z, rhw;
  199. float tu, tv;
  200. }
  201. pVertices[] =
  202. {
  203. // {(float)dst[0].x, (float)dst[0].y, (float)dst[0].z, 1.0f/(float)dst[0].z, (float)src.left / w, (float)src.top / h },
  204. // {(float)(dst[0].x + 2*(dst[1].x-dst[0].x)), (float)(dst[0].y + 2*(dst[1].y-dst[0].y)), (float)dst[1].z, 1.0f/(float)dst[1].z, (float)(src.left + 2*(src.right-src.left)) / w, (float)src.top / h},
  205. // {(float)(dst[0].x + 2*(dst[2].x-dst[0].x)), (float)(dst[0].y + 2*(dst[2].y-dst[0].y)), (float)dst[2].z, 1.0f/(float)dst[2].z, (float)src.left / w, (float)(src.top + 2*(src.bottom-src.top)) / h},
  206. {(float)dst[0].x, (float)dst[0].y, (float)dst[0].z, 1.0f/(float)dst[0].z, (float)src.left / w, (float)src.top / h},
  207. {(float)dst[1].x, (float)dst[1].y, (float)dst[1].z, 1.0f/(float)dst[1].z, (float)src.right / w, (float)src.top / h},
  208. {(float)dst[2].x, (float)dst[2].y, (float)dst[2].z, 1.0f/(float)dst[2].z, (float)src.left / w, (float)src.bottom / h},
  209. {(float)dst[3].x, (float)dst[3].y, (float)dst[3].z, 1.0f/(float)dst[3].z, (float)src.right / w, (float)src.bottom / h},
  210. };
  211. for(int i = 0; i < countof(pVertices); i++)
  212. {
  213. pVertices[i].x -= 0.5;
  214. pVertices[i].y -= 0.5;
  215. }
  216.         hr = pD3DDev->SetTexture(0, pTexture);
  217.         hr = pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
  218.         hr = pD3DDev->SetRenderState(D3DRS_LIGHTING, FALSE);
  219. hr = pD3DDev->SetRenderState(D3DRS_ZENABLE, FALSE);
  220.      hr = pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  221. hr = pD3DDev->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); 
  222. hr = pD3DDev->SetSamplerState(0, D3DSAMP_MAGFILTER, filter);
  223.         hr = pD3DDev->SetSamplerState(0, D3DSAMP_MINFILTER, filter);
  224.         hr = pD3DDev->SetSamplerState(0, D3DSAMP_MIPFILTER, filter);
  225. hr = pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
  226. hr = pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
  227. //
  228. if(FAILED(hr = pD3DDev->BeginScene()))
  229. break;
  230.         hr = pD3DDev->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
  231. //     hr = pD3DDev->DrawPrimitiveUP(D3DPT_TRIANGLELIST, 1, pVertices, sizeof(pVertices[0]));
  232. hr = pD3DDev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pVertices, sizeof(pVertices[0]));
  233. hr = pD3DDev->EndScene();
  234.         //
  235. pD3DDev->SetTexture(0, NULL);
  236. return S_OK;
  237.     }
  238. while(0);
  239.     return E_FAIL;
  240. }
  241. static HRESULT TextureBlt(CComPtr<IDirect3DTexture9> pTexture, CRect dst, CRect src, DWORD filter = D3DTEXF_LINEAR)
  242. {
  243. if(!pTexture)
  244. return E_POINTER;
  245. CComPtr<IDirect3DDevice9> pD3DDev;
  246. if(FAILED(pTexture->GetDevice(&pD3DDev)) || !pD3DDev)
  247. return E_FAIL;
  248. HRESULT hr;
  249.     do
  250. {
  251. D3DSURFACE_DESC d3dsd;
  252. ZeroMemory(&d3dsd, sizeof(d3dsd));
  253. if(FAILED(pTexture->GetLevelDesc(0, &d3dsd)))
  254. break;
  255.         float w = (float)d3dsd.Width;
  256.         float h = (float)d3dsd.Height;
  257. struct
  258. {
  259. float x, y, z, rhw;
  260. float tu, tv;
  261. }
  262. pVertices[] =
  263. {
  264. {(float)dst.left, (float)dst.top, 0.5f, 2.0f, (float)src.left / w, (float)src.top / h},
  265. {(float)dst.right, (float)dst.top, 0.5f, 2.0f, (float)src.right / w, (float)src.top / h},
  266. {(float)dst.left, (float)dst.bottom, 0.5f, 2.0f, (float)src.left / w, (float)src.bottom / h},
  267. {(float)dst.right, (float)dst.bottom, 0.5f, 2.0f, (float)src.right / w, (float)src.bottom / h},
  268. };
  269. for(int i = 0; i < countof(pVertices); i++)
  270. {
  271. pVertices[i].x -= 0.5;
  272. pVertices[i].y -= 0.5;
  273. }
  274.         hr = pD3DDev->SetTexture(0, pTexture);
  275.         hr = pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
  276.         hr = pD3DDev->SetRenderState(D3DRS_LIGHTING, FALSE);
  277. hr = pD3DDev->SetRenderState(D3DRS_ZENABLE, FALSE);
  278.      hr = pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  279. hr = pD3DDev->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); 
  280. hr = pD3DDev->SetSamplerState(0, D3DSAMP_MAGFILTER, filter);
  281.         hr = pD3DDev->SetSamplerState(0, D3DSAMP_MINFILTER, filter);
  282.         hr = pD3DDev->SetSamplerState(0, D3DSAMP_MIPFILTER, filter);
  283. hr = pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
  284. hr = pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
  285. //
  286. if(FAILED(hr = pD3DDev->BeginScene()))
  287. break;
  288.         hr = pD3DDev->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
  289. hr = pD3DDev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pVertices, sizeof(pVertices[0]));
  290. hr = pD3DDev->EndScene();
  291.         //
  292. pD3DDev->SetTexture(0, NULL);
  293. return S_OK;
  294.     }
  295. while(0);
  296.     return E_FAIL;
  297. }
  298. // CDX9AllocatorPresenter
  299. CDX9AllocatorPresenter::CDX9AllocatorPresenter(HWND hWnd, HRESULT& hr) 
  300. : ISubPicAllocatorPresenterImpl(hWnd)
  301. , m_ScreenSize(0, 0)
  302. {
  303.     if(!IsWindow(m_hWnd))
  304.     {
  305.         hr = E_INVALIDARG;
  306.         return;
  307.     }
  308. m_pD3D.Attach(Direct3DCreate9(D3D_SDK_VERSION));
  309. if(!m_pD3D) m_pD3D.Attach(Direct3DCreate9(D3D_SDK_VERSION));
  310. if(!m_pD3D)
  311. {
  312. hr = E_FAIL;
  313. return;
  314. }
  315. GetWindowRect(m_hWnd, &m_WindowRect);
  316. hr = CreateDevice();
  317. }
  318. HRESULT CDX9AllocatorPresenter::CreateDevice()
  319. {
  320. m_pPSC.Free();
  321.     m_pD3DDev = NULL;
  322. D3DDISPLAYMODE d3ddm;
  323. ZeroMemory(&d3ddm, sizeof(d3ddm));
  324. if(FAILED(m_pD3D->GetAdapterDisplayMode(GetAdapter(m_pD3D), &d3ddm)))
  325. return E_UNEXPECTED;
  326. m_ScreenSize.SetSize(d3ddm.Width, d3ddm.Height);
  327.     D3DPRESENT_PARAMETERS pp;
  328.     ZeroMemory(&pp, sizeof(pp));
  329.     pp.Windowed = TRUE;
  330.     pp.hDeviceWindow = m_hWnd;
  331.     pp.SwapEffect = D3DSWAPEFFECT_COPY;
  332. pp.Flags = D3DPRESENTFLAG_VIDEO;
  333. pp.BackBufferWidth = d3ddm.Width;
  334. pp.BackBufferHeight = d3ddm.Height;
  335. if(m_fVMRSyncFix = AfxGetMyApp()->m_s.fVMRSyncFix)
  336. pp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
  337. HRESULT hr = m_pD3D->CreateDevice(
  338. GetAdapter(m_pD3D), D3DDEVTYPE_HAL, m_hWnd,
  339. D3DCREATE_SOFTWARE_VERTEXPROCESSING|D3DCREATE_MULTITHREADED, //D3DCREATE_MANAGED 
  340. &pp, &m_pD3DDev);
  341. if(FAILED(hr))
  342. return hr;
  343. m_pPSC.Attach(new CPixelShaderCompiler(m_pD3DDev, true));
  344. //
  345. m_Filter = D3DTEXF_NONE;
  346. D3DCAPS9 caps;
  347.     ZeroMemory(&caps, sizeof(caps));
  348. m_pD3DDev->GetDeviceCaps(&caps);
  349. if((caps.StretchRectFilterCaps&D3DPTFILTERCAPS_MINFLINEAR)
  350. && (caps.StretchRectFilterCaps&D3DPTFILTERCAPS_MAGFLINEAR))
  351. m_Filter = D3DTEXF_LINEAR;
  352. //
  353. if(caps.PixelShaderVersion >= D3DVS_VERSION(2, 0))
  354. {
  355. CStringA data;
  356. if(LoadResource(IDF_SHADER_RESIZER, data, _T("FILE")))
  357. {
  358. m_pPSC->CompileShader(data, "main_bilinear", "ps_2_0", 0, &m_pResizerPixelShader[0]);
  359. {
  360. CStringA str = data;
  361. str.Replace("_The_Value_Of_A_Is_Set_Here_", "(-0.60)");
  362. m_pPSC->CompileShader(str, "main_bicubic", "ps_2_0", 0, &m_pResizerPixelShader[1]);
  363. }
  364. {
  365. CStringA str = data;
  366. str.Replace("_The_Value_Of_A_Is_Set_Here_", "(-0.75)");
  367. m_pPSC->CompileShader(str, "main_bicubic", "ps_2_0", 0, &m_pResizerPixelShader[2]);
  368. }
  369. {
  370. CStringA str = data;
  371. str.Replace("_The_Value_Of_A_Is_Set_Here_", "(-1.00)");
  372. m_pPSC->CompileShader(str, "main_bicubic", "ps_2_0", 0, &m_pResizerPixelShader[3]);
  373. }
  374. }
  375. }
  376. //
  377. CComPtr<ISubPicProvider> pSubPicProvider;
  378. if(m_pSubPicQueue) m_pSubPicQueue->GetSubPicProvider(&pSubPicProvider);
  379. CSize size;
  380. switch(AfxGetAppSettings().nSPCMaxRes)
  381. {
  382. case 0: default: size = m_ScreenSize; break;
  383. case 1: size.SetSize(1024, 768); break;
  384. case 2: size.SetSize(800, 600); break;
  385. case 3: size.SetSize(640, 480); break;
  386. case 4: size.SetSize(512, 384); break;
  387. case 5: size.SetSize(384, 288); break;
  388. }
  389. if(m_pAllocator)
  390. {
  391. m_pAllocator->ChangeDevice(m_pD3DDev);
  392. }
  393. else
  394. {
  395. m_pAllocator = new CDX9SubPicAllocator(m_pD3DDev, size, AfxGetAppSettings().fSPCPow2Tex);
  396. if(!m_pAllocator)
  397. return E_FAIL;
  398. }
  399. hr = S_OK;
  400. m_pSubPicQueue = AfxGetAppSettings().nSPCSize > 0 
  401. ? (ISubPicQueue*)new CSubPicQueue(AfxGetAppSettings().nSPCSize, m_pAllocator, &hr)
  402. : (ISubPicQueue*)new CSubPicQueueNoThread(m_pAllocator, &hr);
  403. if(!m_pSubPicQueue || FAILED(hr))
  404. return E_FAIL;
  405. if(pSubPicProvider) m_pSubPicQueue->SetSubPicProvider(pSubPicProvider);
  406. return S_OK;
  407. HRESULT CDX9AllocatorPresenter::AllocSurfaces()
  408. {
  409.     CAutoLock cAutoLock(this);
  410. AppSettings& s = AfxGetAppSettings();
  411. m_pVideoTexture[0] = NULL;
  412. m_pVideoTexture[1] = NULL;
  413. m_pVideoSurface[0] = NULL;
  414. m_pVideoSurface[1] = NULL;
  415. HRESULT hr;
  416. if(s.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE2D || s.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D)
  417. {
  418. if(FAILED(hr = m_pD3DDev->CreateTexture(
  419. m_NativeVideoSize.cx, m_NativeVideoSize.cy, 1, D3DUSAGE_RENDERTARGET, /*D3DFMT_X8R8G8B8*/D3DFMT_A8R8G8B8, 
  420. D3DPOOL_DEFAULT, &m_pVideoTexture[0], NULL)))
  421. return hr;
  422. if(FAILED(hr = m_pVideoTexture[0]->GetSurfaceLevel(0, &m_pVideoSurface[0])))
  423. return hr;
  424. if(s.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D)
  425. {
  426. if(FAILED(hr = m_pD3DDev->CreateTexture(
  427. m_NativeVideoSize.cx, m_NativeVideoSize.cy, 1, D3DUSAGE_RENDERTARGET, /*D3DFMT_X8R8G8B8*/D3DFMT_A8R8G8B8, 
  428. D3DPOOL_DEFAULT, &m_pVideoTexture[1], NULL)))
  429. return hr;
  430. if(FAILED(hr = m_pVideoTexture[1]->GetSurfaceLevel(0, &m_pVideoSurface[1])))
  431. return hr;
  432. }
  433. if(s.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE2D)
  434. m_pVideoTexture[0] = NULL, m_pVideoTexture[1] = NULL;
  435. }
  436. else
  437. {
  438. if(FAILED(hr = m_pD3DDev->CreateOffscreenPlainSurface(
  439. m_NativeVideoSize.cx, m_NativeVideoSize.cy, D3DFMT_X8R8G8B8/*D3DFMT_A8R8G8B8*/, 
  440. D3DPOOL_DEFAULT, &m_pVideoSurface[0], NULL)))
  441. return hr;
  442. }
  443. hr = m_pD3DDev->ColorFill(m_pVideoSurface[0], NULL, 0);
  444. return S_OK;
  445. }
  446. void CDX9AllocatorPresenter::DeleteSurfaces()
  447. {
  448.     CAutoLock cAutoLock(this);
  449. m_pVideoTexture[0] = m_pVideoTexture[1] = NULL;
  450. m_pVideoSurface[0] = m_pVideoSurface[1] = NULL;
  451. }
  452. UINT CDX9AllocatorPresenter::GetAdapter(IDirect3D9 *pD3D)
  453. {
  454. if(m_hWnd == NULL || pD3D == NULL)
  455. return D3DADAPTER_DEFAULT;
  456. HMONITOR hMonitor = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST);
  457. if(hMonitor == NULL) return D3DADAPTER_DEFAULT;
  458. for(UINT adp = 0, num_adp = pD3D->GetAdapterCount(); adp < num_adp; ++adp)
  459. {
  460. HMONITOR hAdpMon = pD3D->GetAdapterMonitor(adp);
  461. if(hAdpMon == hMonitor) return adp;
  462. }
  463. return D3DADAPTER_DEFAULT;
  464. }
  465. // ISubPicAllocatorPresenter
  466. STDMETHODIMP CDX9AllocatorPresenter::CreateRenderer(IUnknown** ppRenderer)
  467. {
  468. return E_NOTIMPL;
  469. }
  470. static bool ClipToSurface(IDirect3DSurface9* pSurface, CRect& s, CRect& d)   
  471. {   
  472. D3DSURFACE_DESC d3dsd;   
  473. ZeroMemory(&d3dsd, sizeof(d3dsd));   
  474. if(FAILED(pSurface->GetDesc(&d3dsd)))   
  475. return(false);   
  476. int w = d3dsd.Width, h = d3dsd.Height;   
  477. int sw = s.Width(), sh = s.Height();   
  478. int dw = d.Width(), dh = d.Height();   
  479. if(d.left >= w || d.right < 0 || d.top >= h || d.bottom < 0   
  480. || sw <= 0 || sh <= 0 || dw <= 0 || dh <= 0)   
  481. {   
  482. s.SetRectEmpty();   
  483. d.SetRectEmpty();   
  484. return(true);   
  485. }   
  486. if(d.right > w) {s.right -= (d.right-w)*sw/dw; d.right = w;}   
  487. if(d.bottom > h) {s.bottom -= (d.bottom-h)*sh/dh; d.bottom = h;}   
  488. if(d.left < 0) {s.left += (0-d.left)*sw/dw; d.left = 0;}   
  489. if(d.top < 0) {s.top += (0-d.top)*sh/dh; d.top = 0;}   
  490. return(true);   
  491. STDMETHODIMP_(bool) CDX9AllocatorPresenter::Paint(bool fAll)
  492. {
  493. CAutoLock cAutoLock(this);
  494. if(m_WindowRect.right <= m_WindowRect.left || m_WindowRect.bottom <= m_WindowRect.top
  495. || m_NativeVideoSize.cx <= 0 || m_NativeVideoSize.cy <= 0
  496. || !m_pVideoSurface)
  497. return(false);
  498. HRESULT hr;
  499. CRect rSrcVid(CPoint(0, 0), m_NativeVideoSize);
  500. CRect rDstVid(m_VideoRect);
  501. CRect rSrcPri(CPoint(0, 0), m_WindowRect.Size());
  502. CRect rDstPri(m_WindowRect);
  503. CComPtr<IDirect3DSurface9> pBackBuffer;
  504. m_pD3DDev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
  505. if(fAll)
  506. {
  507. // clear the backbuffer
  508. hr = m_pD3DDev->Clear(0, NULL, D3DCLEAR_TARGET, 0, 1.0f, 0);
  509. // paint the video on the backbuffer
  510. if(!rDstVid.IsRectEmpty())
  511. {
  512. if(m_pVideoTexture[0])
  513. {
  514. CComPtr<IDirect3DTexture9> pVideoTexture = m_pVideoTexture[0];
  515. if(m_pVideoTexture[1] && m_pPixelShader)
  516. {
  517. static __int64 counter = 0;
  518. static long start = clock();
  519. long stop = clock();
  520. long diff = stop - start;
  521. if(diff >= 10*60*CLOCKS_PER_SEC) start = stop; // reset after 10 min (ps float has its limits in both range and accuracy)
  522. float fConstData[][4] = 
  523. {
  524. {(float)m_NativeVideoSize.cx, (float)m_NativeVideoSize.cy, (float)(counter++), (float)diff / CLOCKS_PER_SEC},
  525. {1.0f / m_NativeVideoSize.cx, 1.0f / m_NativeVideoSize.cy, 0, 0},
  526. };
  527. CComPtr<IDirect3DSurface9> pRT;
  528. hr = m_pD3DDev->GetRenderTarget(0, &pRT);
  529. hr = m_pD3DDev->SetRenderTarget(0, m_pVideoSurface[1]);
  530. hr = m_pD3DDev->SetPixelShaderConstantF(0, (float*)fConstData, countof(fConstData));
  531. hr = m_pD3DDev->SetPixelShader(m_pPixelShader);
  532. TextureBlt(m_pVideoTexture[0], rSrcVid, rSrcVid);
  533. hr = m_pD3DDev->SetRenderTarget(0, pRT);
  534. hr = m_pD3DDev->SetPixelShader(NULL);
  535. pVideoTexture = m_pVideoTexture[1];
  536. }
  537. DWORD resizer = AfxGetAppSettings().iDX9Resizer;
  538. DWORD filter = resizer == 0 ? D3DTEXF_POINT : D3DTEXF_LINEAR;
  539. CComPtr<IDirect3DPixelShader9> pResizerPixelShader;
  540. if(rSrcVid != rDstVid)
  541. {
  542. if(resizer == 2 && m_pResizerPixelShader[0]) pResizerPixelShader = m_pResizerPixelShader[0];
  543. else if(resizer == 3 && m_pResizerPixelShader[1]) pResizerPixelShader = m_pResizerPixelShader[1];
  544. else if(resizer == 4 && m_pResizerPixelShader[2]) pResizerPixelShader = m_pResizerPixelShader[2];
  545. else if(resizer == 5 && m_pResizerPixelShader[3]) pResizerPixelShader = m_pResizerPixelShader[3];
  546. }
  547. if(pResizerPixelShader)
  548. {
  549. float fConstData[][4] = 
  550. {
  551. {(float)m_NativeVideoSize.cx, (float)m_NativeVideoSize.cy, 0, 0},
  552. {1.0f / m_NativeVideoSize.cx, 1.0f / m_NativeVideoSize.cy, 0, 0},
  553. {1.0f / m_NativeVideoSize.cx, 0, 0, 0},
  554. {0, 1.0f / m_NativeVideoSize.cy, 0, 0},
  555. };
  556. hr = m_pD3DDev->SetPixelShaderConstantF(0, (float*)fConstData, countof(fConstData));
  557. hr = m_pD3DDev->SetPixelShader(pResizerPixelShader);
  558. filter = D3DTEXF_POINT;
  559. }
  560. Vector v[4];
  561. Transform(rDstVid, v);
  562. hr = TextureBlt(pVideoTexture, v, rSrcVid, filter);
  563. if(pResizerPixelShader)
  564. hr = m_pD3DDev->SetPixelShader(NULL);
  565. }
  566. else
  567. {
  568. if(pBackBuffer)
  569. {
  570. ClipToSurface(pBackBuffer, rSrcVid, rDstVid); // grrr
  571. // IMPORTANT: rSrcVid has to be aligned on mod2 for yuy2->rgb conversion with StretchRect!!!
  572. rSrcVid.left &= ~1; rSrcVid.right &= ~1;
  573. rSrcVid.top &= ~1; rSrcVid.bottom &= ~1;
  574. hr = m_pD3DDev->StretchRect(m_pVideoSurface[0], rSrcVid, pBackBuffer, rDstVid, m_Filter);
  575. }
  576. }
  577. }
  578. // paint the text on the backbuffer
  579. AlphaBltSubPic(rSrcPri.Size());
  580. }
  581. if(m_fVMRSyncFix)
  582. {
  583. D3DLOCKED_RECT lr;
  584. if(SUCCEEDED(pBackBuffer->LockRect(&lr, NULL, 0)))
  585. pBackBuffer->UnlockRect();
  586. }
  587. hr = m_pD3DDev->Present(rSrcPri, rDstPri, NULL, NULL);
  588. if(hr == D3DERR_DEVICELOST)
  589. {
  590. if(m_pD3DDev->TestCooperativeLevel() == D3DERR_DEVICENOTRESET) 
  591. {
  592. DeleteSurfaces();
  593. if(FAILED(hr = CreateDevice()) || FAILED(hr = AllocSurfaces()))
  594. return(false);
  595. }
  596. hr = S_OK;
  597. }
  598. return(true);
  599. }
  600. STDMETHODIMP CDX9AllocatorPresenter::GetDIB(BYTE* lpDib, DWORD* size)
  601. {
  602. CheckPointer(size, E_POINTER);
  603. HRESULT hr;
  604. D3DSURFACE_DESC desc;
  605. memset(&desc, 0, sizeof(desc));
  606. m_pVideoSurface[0]->GetDesc(&desc);
  607. DWORD required = sizeof(BITMAPINFOHEADER) + (desc.Width * desc.Height * 32 >> 3);
  608. if(!lpDib) {*size = required; return S_OK;}
  609. if(*size < required) return E_OUTOFMEMORY;
  610. *size = required;
  611. CComPtr<IDirect3DSurface9> pSurface = m_pVideoSurface[0];
  612. D3DLOCKED_RECT r;
  613. if(FAILED(hr = pSurface->LockRect(&r, NULL, D3DLOCK_READONLY)))
  614. {
  615. pSurface = NULL;
  616. if(FAILED(hr = m_pD3DDev->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &pSurface, NULL))
  617. || FAILED(hr = m_pD3DDev->GetRenderTargetData(m_pVideoSurface[0], pSurface))
  618. || FAILED(hr = pSurface->LockRect(&r, NULL, D3DLOCK_READONLY)))
  619. return hr;
  620. }
  621. BITMAPINFOHEADER* bih = (BITMAPINFOHEADER*)lpDib;
  622. memset(bih, 0, sizeof(BITMAPINFOHEADER));
  623. bih->biSize = sizeof(BITMAPINFOHEADER);
  624. bih->biWidth = desc.Width;
  625. bih->biHeight = desc.Height;
  626. bih->biBitCount = 32;
  627. bih->biPlanes = 1;
  628. bih->biSizeImage = bih->biWidth * bih->biHeight * bih->biBitCount >> 3;
  629. BitBltFromRGBToRGB(
  630. bih->biWidth, bih->biHeight, 
  631. (BYTE*)(bih + 1), bih->biWidth*bih->biBitCount>>3, bih->biBitCount,
  632. (BYTE*)r.pBits + r.Pitch*(desc.Height-1), -(int)r.Pitch, 32);
  633. pSurface->UnlockRect();
  634. return S_OK;
  635. }
  636. STDMETHODIMP CDX9AllocatorPresenter::SetPixelShader(LPCSTR pSrcData, LPCSTR pTarget)
  637. {
  638. CAutoLock cAutoLock(this);
  639. m_pPixelShader = NULL;
  640. m_pD3DDev->SetPixelShader(NULL);
  641. if(!pSrcData || !pTarget)
  642. return E_INVALIDARG;
  643. HRESULT hr = m_pPSC->CompileShader(pSrcData, "main", pTarget, 0, &m_pPixelShader);
  644. if(FAILED(hr)) return hr;
  645. Paint(true);
  646. return S_OK;
  647. }
  648. //
  649. // CVMR9AllocatorPresenter
  650. //
  651. #define MY_USER_ID 0x6ABE51
  652. CVMR9AllocatorPresenter::CVMR9AllocatorPresenter(HWND hWnd, HRESULT& hr) 
  653. : CDX9AllocatorPresenter(hWnd, hr)
  654. , m_fUseInternalTimer(true)
  655. {
  656. }
  657. STDMETHODIMP CVMR9AllocatorPresenter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  658. {
  659.     CheckPointer(ppv, E_POINTER);
  660. return 
  661. QI(IVMRSurfaceAllocator9)
  662. QI(IVMRImagePresenter9)
  663. QI(IVMRWindowlessControl9)
  664. __super::NonDelegatingQueryInterface(riid, ppv);
  665. }
  666. HRESULT CVMR9AllocatorPresenter::CreateDevice()
  667. {
  668. HRESULT hr = __super::CreateDevice();
  669. if(FAILED(hr)) return hr;
  670. if(m_pIVMRSurfAllocNotify)
  671. {
  672. HMONITOR hMonitor = m_pD3D->GetAdapterMonitor(GetAdapter(m_pD3D));
  673. if(FAILED(hr = m_pIVMRSurfAllocNotify->ChangeD3DDevice(m_pD3DDev, hMonitor)))
  674. return(false);
  675. }
  676. return hr;
  677. }
  678. void CVMR9AllocatorPresenter::DeleteSurfaces()
  679. {
  680.     CAutoLock cAutoLock(this);
  681. m_pSurfaces.RemoveAll();
  682. return __super::DeleteSurfaces();
  683. }
  684. // ISubPicAllocatorPresenter
  685. class COuterVMR9
  686. : public CUnknown
  687. , public IVideoWindow
  688. , public IBasicVideo2
  689. , public IVMRWindowlessControl
  690. {
  691. CComPtr<IUnknown> m_pVMR;
  692. public:
  693. COuterVMR9(const TCHAR* pName, LPUNKNOWN pUnk) : CUnknown(pName, pUnk)
  694. {
  695. m_pVMR.CoCreateInstance(CLSID_VideoMixingRenderer9, GetOwner());
  696. }
  697. DECLARE_IUNKNOWN;
  698. STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv)
  699. {
  700. HRESULT hr = m_pVMR ? m_pVMR->QueryInterface(riid, ppv) : E_NOINTERFACE;
  701. if(m_pVMR && FAILED(hr))
  702. {
  703. if(riid == __uuidof(IVideoWindow))
  704. return GetInterface((IVideoWindow*)this, ppv);
  705. if(riid == __uuidof(IBasicVideo))
  706. return GetInterface((IBasicVideo*)this, ppv);
  707. if(riid == __uuidof(IBasicVideo2))
  708. return GetInterface((IBasicVideo2*)this, ppv);
  709. /* if(riid == __uuidof(IVMRWindowlessControl))
  710. return GetInterface((IVMRWindowlessControl*)this, ppv);
  711. */ }
  712. return SUCCEEDED(hr) ? hr : __super::NonDelegatingQueryInterface(riid, ppv);
  713. }
  714. // IVMRWindowlessControl
  715. STDMETHODIMP GetNativeVideoSize(LONG* lpWidth, LONG* lpHeight, LONG* lpARWidth, LONG* lpARHeight)
  716. {
  717. if(CComQIPtr<IVMRWindowlessControl9> pWC9 = m_pVMR)
  718. {
  719. return pWC9->GetNativeVideoSize(lpWidth, lpHeight, lpARWidth, lpARHeight);
  720. }
  721. return E_NOTIMPL;
  722. }
  723. STDMETHODIMP GetMinIdealVideoSize(LONG* lpWidth, LONG* lpHeight) {return E_NOTIMPL;}
  724. STDMETHODIMP GetMaxIdealVideoSize(LONG* lpWidth, LONG* lpHeight) {return E_NOTIMPL;}
  725. STDMETHODIMP SetVideoPosition(const LPRECT lpSRCRect, const LPRECT lpDSTRect) {return E_NOTIMPL;}
  726.     STDMETHODIMP GetVideoPosition(LPRECT lpSRCRect, LPRECT lpDSTRect)
  727. {
  728. if(CComQIPtr<IVMRWindowlessControl9> pWC9 = m_pVMR)
  729. {
  730. return pWC9->GetVideoPosition(lpSRCRect, lpDSTRect);
  731. }
  732. return E_NOTIMPL;
  733. }
  734. STDMETHODIMP GetAspectRatioMode(DWORD* lpAspectRatioMode)
  735. {
  736. if(CComQIPtr<IVMRWindowlessControl9> pWC9 = m_pVMR)
  737. {
  738. *lpAspectRatioMode = VMR_ARMODE_NONE;
  739. return S_OK;
  740. }
  741. return E_NOTIMPL;
  742. }
  743. STDMETHODIMP SetAspectRatioMode(DWORD AspectRatioMode) {return E_NOTIMPL;}
  744. STDMETHODIMP SetVideoClippingWindow(HWND hwnd) {return E_NOTIMPL;}
  745. STDMETHODIMP RepaintVideo(HWND hwnd, HDC hdc) {return E_NOTIMPL;}
  746. STDMETHODIMP DisplayModeChanged() {return E_NOTIMPL;}
  747. STDMETHODIMP GetCurrentImage(BYTE** lpDib) {return E_NOTIMPL;}
  748. STDMETHODIMP SetBorderColor(COLORREF Clr) {return E_NOTIMPL;}
  749. STDMETHODIMP GetBorderColor(COLORREF* lpClr) {return E_NOTIMPL;}
  750. STDMETHODIMP SetColorKey(COLORREF Clr) {return E_NOTIMPL;}
  751. STDMETHODIMP GetColorKey(COLORREF* lpClr) {return E_NOTIMPL;}
  752. // IVideoWindow
  753. STDMETHODIMP GetTypeInfoCount(UINT* pctinfo) {return E_NOTIMPL;}
  754. STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) {return E_NOTIMPL;}
  755. STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) {return E_NOTIMPL;}
  756. STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) {return E_NOTIMPL;}
  757.     STDMETHODIMP put_Caption(BSTR strCaption) {return E_NOTIMPL;}
  758.     STDMETHODIMP get_Caption(BSTR* strCaption) {return E_NOTIMPL;}
  759. STDMETHODIMP put_WindowStyle(long WindowStyle) {return E_NOTIMPL;}
  760. STDMETHODIMP get_WindowStyle(long* WindowStyle) {return E_NOTIMPL;}
  761. STDMETHODIMP put_WindowStyleEx(long WindowStyleEx) {return E_NOTIMPL;}
  762. STDMETHODIMP get_WindowStyleEx(long* WindowStyleEx) {return E_NOTIMPL;}
  763. STDMETHODIMP put_AutoShow(long AutoShow) {return E_NOTIMPL;}
  764. STDMETHODIMP get_AutoShow(long* AutoShow) {return E_NOTIMPL;}
  765. STDMETHODIMP put_WindowState(long WindowState) {return E_NOTIMPL;}
  766. STDMETHODIMP get_WindowState(long* WindowState) {return E_NOTIMPL;}
  767. STDMETHODIMP put_BackgroundPalette(long BackgroundPalette) {return E_NOTIMPL;}
  768. STDMETHODIMP get_BackgroundPalette(long* pBackgroundPalette) {return E_NOTIMPL;}
  769. STDMETHODIMP put_Visible(long Visible) {return E_NOTIMPL;}
  770. STDMETHODIMP get_Visible(long* pVisible) {return E_NOTIMPL;}
  771. STDMETHODIMP put_Left(long Left) {return E_NOTIMPL;}
  772. STDMETHODIMP get_Left(long* pLeft) {return E_NOTIMPL;}
  773. STDMETHODIMP put_Width(long Width) {return E_NOTIMPL;}
  774. STDMETHODIMP get_Width(long* pWidth)
  775. {
  776. if(CComQIPtr<IVMRWindowlessControl9> pWC9 = m_pVMR)
  777. {
  778. CRect s, d;
  779. HRESULT hr = pWC9->GetVideoPosition(&s, &d);
  780. *pWidth = d.Width();
  781. return hr;
  782. }
  783. return E_NOTIMPL;
  784. }
  785. STDMETHODIMP put_Top(long Top) {return E_NOTIMPL;}
  786. STDMETHODIMP get_Top(long* pTop) {return E_NOTIMPL;}
  787. STDMETHODIMP put_Height(long Height) {return E_NOTIMPL;}
  788. STDMETHODIMP get_Height(long* pHeight)
  789. {
  790. if(CComQIPtr<IVMRWindowlessControl9> pWC9 = m_pVMR)
  791. {
  792. CRect s, d;
  793. HRESULT hr = pWC9->GetVideoPosition(&s, &d);
  794. *pHeight = d.Height();
  795. return hr;
  796. }
  797. return E_NOTIMPL;
  798. }
  799. STDMETHODIMP put_Owner(OAHWND Owner) {return E_NOTIMPL;}
  800. STDMETHODIMP get_Owner(OAHWND* Owner) {return E_NOTIMPL;}
  801. STDMETHODIMP put_MessageDrain(OAHWND Drain) {return E_NOTIMPL;}
  802. STDMETHODIMP get_MessageDrain(OAHWND* Drain) {return E_NOTIMPL;}
  803. STDMETHODIMP get_BorderColor(long* Color) {return E_NOTIMPL;}
  804. STDMETHODIMP put_BorderColor(long Color) {return E_NOTIMPL;}
  805. STDMETHODIMP get_FullScreenMode(long* FullScreenMode) {return E_NOTIMPL;}
  806. STDMETHODIMP put_FullScreenMode(long FullScreenMode) {return E_NOTIMPL;}
  807.     STDMETHODIMP SetWindowForeground(long Focus) {return E_NOTIMPL;}
  808.     STDMETHODIMP NotifyOwnerMessage(OAHWND hwnd, long uMsg, LONG_PTR wParam, LONG_PTR lParam) {return E_NOTIMPL;}
  809.     STDMETHODIMP SetWindowPosition(long Left, long Top, long Width, long Height) {return E_NOTIMPL;}
  810. STDMETHODIMP GetWindowPosition(long* pLeft, long* pTop, long* pWidth, long* pHeight) {return E_NOTIMPL;}
  811. STDMETHODIMP GetMinIdealImageSize(long* pWidth, long* pHeight) {return E_NOTIMPL;}
  812. STDMETHODIMP GetMaxIdealImageSize(long* pWidth, long* pHeight) {return E_NOTIMPL;}
  813. STDMETHODIMP GetRestorePosition(long* pLeft, long* pTop, long* pWidth, long* pHeight) {return E_NOTIMPL;}
  814. STDMETHODIMP HideCursor(long HideCursor) {return E_NOTIMPL;}
  815. STDMETHODIMP IsCursorHidden(long* CursorHidden) {return E_NOTIMPL;}
  816. // IBasicVideo2
  817.     STDMETHODIMP get_AvgTimePerFrame(REFTIME* pAvgTimePerFrame) {return E_NOTIMPL;}
  818.     STDMETHODIMP get_BitRate(long* pBitRate) {return E_NOTIMPL;}
  819.     STDMETHODIMP get_BitErrorRate(long* pBitErrorRate) {return E_NOTIMPL;}
  820.     STDMETHODIMP get_VideoWidth(long* pVideoWidth) {return E_NOTIMPL;}
  821.     STDMETHODIMP get_VideoHeight(long* pVideoHeight) {return E_NOTIMPL;}
  822.     STDMETHODIMP put_SourceLeft(long SourceLeft) {return E_NOTIMPL;}
  823.     STDMETHODIMP get_SourceLeft(long* pSourceLeft) {return E_NOTIMPL;}
  824.     STDMETHODIMP put_SourceWidth(long SourceWidth) {return E_NOTIMPL;}
  825.     STDMETHODIMP get_SourceWidth(long* pSourceWidth) {return E_NOTIMPL;}
  826.     STDMETHODIMP put_SourceTop(long SourceTop) {return E_NOTIMPL;}
  827.     STDMETHODIMP get_SourceTop(long* pSourceTop) {return E_NOTIMPL;}
  828.     STDMETHODIMP put_SourceHeight(long SourceHeight) {return E_NOTIMPL;}
  829.     STDMETHODIMP get_SourceHeight(long* pSourceHeight) {return E_NOTIMPL;}
  830.     STDMETHODIMP put_DestinationLeft(long DestinationLeft) {return E_NOTIMPL;}
  831.     STDMETHODIMP get_DestinationLeft(long* pDestinationLeft) {return E_NOTIMPL;}
  832.     STDMETHODIMP put_DestinationWidth(long DestinationWidth) {return E_NOTIMPL;}
  833.     STDMETHODIMP get_DestinationWidth(long* pDestinationWidth) {return E_NOTIMPL;}
  834.     STDMETHODIMP put_DestinationTop(long DestinationTop) {return E_NOTIMPL;}
  835.     STDMETHODIMP get_DestinationTop(long* pDestinationTop) {return E_NOTIMPL;}
  836.     STDMETHODIMP put_DestinationHeight(long DestinationHeight) {return E_NOTIMPL;}
  837.     STDMETHODIMP get_DestinationHeight(long* pDestinationHeight) {return E_NOTIMPL;}
  838.     STDMETHODIMP SetSourcePosition(long Left, long Top, long Width, long Height) {return E_NOTIMPL;}
  839.     STDMETHODIMP GetSourcePosition(long* pLeft, long* pTop, long* pWidth, long* pHeight)
  840. {
  841. // DVD Nav. bug workaround fix
  842. {
  843. *pLeft = *pTop = 0;
  844. return GetVideoSize(pWidth, pHeight);
  845. }
  846. /*
  847. if(CComQIPtr<IVMRWindowlessControl9> pWC9 = m_pVMR)
  848. {
  849. CRect s, d;
  850. HRESULT hr = pWC9->GetVideoPosition(&s, &d);
  851. *pLeft = s.left;
  852. *pTop = s.top;
  853. *pWidth = s.Width();
  854. *pHeight = s.Height();
  855. return hr;
  856. }
  857. */
  858. return E_NOTIMPL;
  859. }
  860.     STDMETHODIMP SetDefaultSourcePosition() {return E_NOTIMPL;}
  861.     STDMETHODIMP SetDestinationPosition(long Left, long Top, long Width, long Height) {return E_NOTIMPL;}
  862.     STDMETHODIMP GetDestinationPosition(long* pLeft, long* pTop, long* pWidth, long* pHeight)
  863. {
  864. if(CComQIPtr<IVMRWindowlessControl9> pWC9 = m_pVMR)
  865. {
  866. CRect s, d;
  867. HRESULT hr = pWC9->GetVideoPosition(&s, &d);
  868. *pLeft = d.left;
  869. *pTop = d.top;
  870. *pWidth = d.Width();
  871. *pHeight = d.Height();
  872. return hr;
  873. }
  874. return E_NOTIMPL;
  875. }
  876.     STDMETHODIMP SetDefaultDestinationPosition() {return E_NOTIMPL;}
  877.     STDMETHODIMP GetVideoSize(long* pWidth, long* pHeight)
  878. {
  879. if(CComQIPtr<IVMRWindowlessControl9> pWC9 = m_pVMR)
  880. {
  881. LONG aw, ah;
  882. // return pWC9->GetNativeVideoSize(pWidth, pHeight, &aw, &ah);
  883. // DVD Nav. bug workaround fix
  884. HRESULT hr = pWC9->GetNativeVideoSize(pWidth, pHeight, &aw, &ah);
  885. *pWidth = *pHeight * aw / ah;
  886. return hr;
  887. }
  888. return E_NOTIMPL;
  889. }
  890.     STDMETHODIMP GetVideoPaletteEntries(long StartIndex, long Entries, long* pRetrieved, long* pPalette) {return E_NOTIMPL;}
  891.     STDMETHODIMP GetCurrentImage(long* pBufferSize, long* pDIBImage) {return E_NOTIMPL;}
  892.     STDMETHODIMP IsUsingDefaultSource() {return E_NOTIMPL;}
  893.     STDMETHODIMP IsUsingDefaultDestination() {return E_NOTIMPL;}
  894. STDMETHODIMP GetPreferredAspectRatio(long* plAspectX, long* plAspectY)
  895. {
  896. if(CComQIPtr<IVMRWindowlessControl9> pWC9 = m_pVMR)
  897. {
  898. LONG w, h;
  899. return pWC9->GetNativeVideoSize(&w, &h, plAspectX, plAspectY);
  900. }
  901. return E_NOTIMPL;
  902. }
  903. };
  904. STDMETHODIMP CVMR9AllocatorPresenter::CreateRenderer(IUnknown** ppRenderer)
  905. {
  906.     CheckPointer(ppRenderer, E_POINTER);
  907. *ppRenderer = NULL;
  908. HRESULT hr;
  909. do
  910. {
  911. CMacrovisionKicker* pMK = new CMacrovisionKicker(NAME("CMacrovisionKicker"), NULL);
  912. CComPtr<IUnknown> pUnk = (IUnknown*)(INonDelegatingUnknown*)pMK;
  913. pMK->SetInner((IUnknown*)(INonDelegatingUnknown*)new COuterVMR9(NAME("COuterVMR9"), pUnk));
  914. CComQIPtr<IBaseFilter> pBF = pUnk;
  915. /*
  916. CComQIPtr<IBaseFilter> pBF = (IUnknown*)(INonDelegatingUnknown*)new COuterVMR9(NAME("COuterVMR9"), NULL);
  917. if(!pBF) pBF.CoCreateInstance(CLSID_VideoMixingRenderer9);
  918. */
  919. CComQIPtr<IVMRFilterConfig9> pConfig = pBF;
  920. if(!pConfig)
  921. break;
  922. if(FAILED(hr = pConfig->SetRenderingMode(VMR9Mode_Renderless)))
  923. break;
  924. CComQIPtr<IVMRSurfaceAllocatorNotify9> pSAN = pBF;
  925. if(!pSAN)
  926. break;
  927. if(FAILED(hr = pSAN->AdviseSurfaceAllocator(MY_USER_ID, static_cast<IVMRSurfaceAllocator9*>(this)))
  928. || FAILED(hr = AdviseNotify(pSAN)))
  929. break;
  930. CComPtr<IPin> pPin = GetFirstPin(pBF);
  931. HookNewSegment((IPinC*)(IPin*)pPin);
  932. *ppRenderer = (IUnknown*)pBF.Detach();
  933. return S_OK;
  934. }
  935. while(0);
  936.     return E_FAIL;
  937. }
  938. STDMETHODIMP_(void) CVMR9AllocatorPresenter::SetTime(REFERENCE_TIME rtNow)
  939. {
  940. m_fUseInternalTimer = false;
  941. __super::SetTime(rtNow);
  942. }
  943. // IVMRSurfaceAllocator9
  944. STDMETHODIMP CVMR9AllocatorPresenter::InitializeDevice(DWORD_PTR dwUserID, VMR9AllocationInfo* lpAllocInfo, DWORD* lpNumBuffers)
  945. {
  946. if(!lpAllocInfo || !lpNumBuffers)
  947. return E_POINTER;
  948. if(!m_pIVMRSurfAllocNotify)
  949. return E_FAIL;
  950. // StretchRect's yv12 -> rgb conversion looks horribly bright compared to the result of yuy2 -> rgb
  951. if(lpAllocInfo->Format == '21VY' || lpAllocInfo->Format == '024Y')
  952. return E_FAIL;
  953. DeleteSurfaces();
  954. m_pSurfaces.SetCount(*lpNumBuffers);
  955.     HRESULT hr;
  956. hr = m_pIVMRSurfAllocNotify->AllocateSurfaceHelper(lpAllocInfo, lpNumBuffers, &m_pSurfaces[0]);
  957. if(FAILED(hr))
  958. return hr;
  959. m_NativeVideoSize = CSize(lpAllocInfo->dwWidth, abs((int)lpAllocInfo->dwHeight));
  960. m_AspectRatio = m_NativeVideoSize;
  961. int arx = lpAllocInfo->szAspectRatio.cx, ary = lpAllocInfo->szAspectRatio.cy;
  962. if(arx > 0 && ary > 0) m_AspectRatio.SetSize(arx, ary);
  963. if(FAILED(hr = AllocSurfaces()))
  964. return hr;
  965. // test if the colorspace is acceptable
  966. if(FAILED(hr = m_pD3DDev->StretchRect(m_pSurfaces[0], NULL, m_pVideoSurface[0], NULL, D3DTEXF_NONE)))
  967. {
  968. DeleteSurfaces();
  969. return E_FAIL;
  970. }
  971. hr = m_pD3DDev->ColorFill(m_pVideoSurface[0], NULL, 0);
  972. return hr;
  973. }
  974. STDMETHODIMP CVMR9AllocatorPresenter::TerminateDevice(DWORD_PTR dwUserID)
  975. {
  976.     DeleteSurfaces();
  977.     return S_OK;
  978. }
  979. STDMETHODIMP CVMR9AllocatorPresenter::GetSurface(DWORD_PTR dwUserID, DWORD SurfaceIndex, DWORD SurfaceFlags, IDirect3DSurface9** lplpSurface)
  980. {
  981.     if(!lplpSurface)
  982. return E_POINTER;
  983. if(SurfaceIndex >= m_pSurfaces.GetCount()) 
  984.         return E_FAIL;
  985.     CAutoLock cAutoLock(this);
  986. (*lplpSurface = m_pSurfaces[SurfaceIndex])->AddRef();
  987. return S_OK;
  988. }
  989. STDMETHODIMP CVMR9AllocatorPresenter::AdviseNotify(IVMRSurfaceAllocatorNotify9* lpIVMRSurfAllocNotify)
  990. {
  991.     CAutoLock cAutoLock(this);
  992. m_pIVMRSurfAllocNotify = lpIVMRSurfAllocNotify;
  993. HRESULT hr;
  994.     HMONITOR hMonitor = m_pD3D->GetAdapterMonitor(GetAdapter(m_pD3D));
  995.     if(FAILED(hr = m_pIVMRSurfAllocNotify->SetD3DDevice(m_pD3DDev, hMonitor)))
  996. return hr;
  997.     return S_OK;
  998. }
  999. // IVMRImagePresenter9
  1000. STDMETHODIMP CVMR9AllocatorPresenter::StartPresenting(DWORD_PTR dwUserID)
  1001. {
  1002.     CAutoLock cAutoLock(this);
  1003.     ASSERT(m_pD3DDev);
  1004. return m_pD3DDev ? S_OK : E_FAIL;
  1005. }
  1006. STDMETHODIMP CVMR9AllocatorPresenter::StopPresenting(DWORD_PTR dwUserID)
  1007. {
  1008. return S_OK;
  1009. }
  1010. STDMETHODIMP CVMR9AllocatorPresenter::PresentImage(DWORD_PTR dwUserID, VMR9PresentationInfo* lpPresInfo)
  1011. {
  1012.     HRESULT hr;
  1013. {
  1014. if(!m_pIVMRSurfAllocNotify)
  1015. return E_FAIL;
  1016. D3DDEVICE_CREATION_PARAMETERS Parameters;
  1017. if(FAILED(m_pD3DDev->GetCreationParameters(&Parameters)))
  1018. {
  1019. ASSERT(0);
  1020. return E_FAIL;
  1021. }
  1022. HMONITOR hCurMonitor = m_pD3D->GetAdapterMonitor(Parameters.AdapterOrdinal);
  1023. HMONITOR hMonitor = m_pD3D->GetAdapterMonitor(GetAdapter(m_pD3D));
  1024. if(hMonitor != hCurMonitor)
  1025. {
  1026. ASSERT(0);
  1027. }
  1028. }
  1029. /*
  1030.     // if we are in the middle of the display change
  1031.     if(NeedToHandleDisplayChange())
  1032.     {
  1033.         // NOTE: this piece of code is left as a user exercise.  
  1034.         // The D3DDevice here needs to be switched
  1035.         // to the device that is using another adapter
  1036.     }
  1037. */
  1038. {
  1039. if(!lpPresInfo || !lpPresInfo->lpSurf)
  1040. return E_POINTER;
  1041. CAutoLock cAutoLock(this);
  1042. hr = m_pD3DDev->StretchRect(lpPresInfo->lpSurf, NULL, m_pVideoSurface[0], NULL, D3DTEXF_NONE);
  1043. if(lpPresInfo->rtEnd > lpPresInfo->rtStart)
  1044. {
  1045. REFERENCE_TIME rtTimePerFrame = lpPresInfo->rtEnd - lpPresInfo->rtStart;
  1046. m_fps = 10000000.0 / rtTimePerFrame;
  1047. if(m_pSubPicQueue)
  1048. {
  1049. m_pSubPicQueue->SetFPS(m_fps);
  1050. if(m_fUseInternalTimer) __super::SetTime(g_tSegmentStart + lpPresInfo->rtStart);
  1051. }
  1052. }
  1053. CSize VideoSize = m_NativeVideoSize;
  1054. int arx = lpPresInfo->szAspectRatio.cx, ary = lpPresInfo->szAspectRatio.cy;
  1055. if(arx > 0 && ary > 0) VideoSize.cx = VideoSize.cy*arx/ary;
  1056. if(VideoSize != GetVideoSize())
  1057. {
  1058. m_AspectRatio.SetSize(arx, ary);
  1059. AfxGetApp()->m_pMainWnd->PostMessage(WM_REARRANGERENDERLESS);
  1060. }
  1061. Paint(true);
  1062. hr = S_OK;
  1063. }
  1064.     return hr;
  1065. }
  1066. // IVMRWindowlessControl9
  1067. //
  1068. // It is only implemented (partially) for the dvd navigator's 
  1069. // menu handling, which needs to know a few things about the 
  1070. // location of our window.
  1071. STDMETHODIMP CVMR9AllocatorPresenter::GetNativeVideoSize(LONG* lpWidth, LONG* lpHeight, LONG* lpARWidth, LONG* lpARHeight)
  1072. {
  1073. if(lpWidth) *lpWidth = m_NativeVideoSize.cx;
  1074. if(lpHeight) *lpHeight = m_NativeVideoSize.cy;
  1075. if(lpARWidth) *lpARWidth = m_AspectRatio.cx;
  1076. if(lpARHeight) *lpARHeight = m_AspectRatio.cy;
  1077. return S_OK;
  1078. }
  1079. STDMETHODIMP CVMR9AllocatorPresenter::GetMinIdealVideoSize(LONG* lpWidth, LONG* lpHeight) {return E_NOTIMPL;}
  1080. STDMETHODIMP CVMR9AllocatorPresenter::GetMaxIdealVideoSize(LONG* lpWidth, LONG* lpHeight) {return E_NOTIMPL;}
  1081. STDMETHODIMP CVMR9AllocatorPresenter::SetVideoPosition(const LPRECT lpSRCRect, const LPRECT lpDSTRect) {return E_NOTIMPL;} // we have our own method for this
  1082. STDMETHODIMP CVMR9AllocatorPresenter::GetVideoPosition(LPRECT lpSRCRect, LPRECT lpDSTRect)
  1083. {
  1084. CopyRect(lpSRCRect, CRect(CPoint(0, 0), m_NativeVideoSize));
  1085. CopyRect(lpDSTRect, &m_VideoRect);
  1086. return S_OK;
  1087. }
  1088. STDMETHODIMP CVMR9AllocatorPresenter::GetAspectRatioMode(DWORD* lpAspectRatioMode)
  1089. {
  1090. if(lpAspectRatioMode) *lpAspectRatioMode = AM_ARMODE_STRETCHED;
  1091. return S_OK;
  1092. }
  1093. STDMETHODIMP CVMR9AllocatorPresenter::SetAspectRatioMode(DWORD AspectRatioMode) {return E_NOTIMPL;}
  1094. STDMETHODIMP CVMR9AllocatorPresenter::SetVideoClippingWindow(HWND hwnd) {return E_NOTIMPL;}
  1095. STDMETHODIMP CVMR9AllocatorPresenter::RepaintVideo(HWND hwnd, HDC hdc) {return E_NOTIMPL;}
  1096. STDMETHODIMP CVMR9AllocatorPresenter::DisplayModeChanged() {return E_NOTIMPL;}
  1097. STDMETHODIMP CVMR9AllocatorPresenter::GetCurrentImage(BYTE** lpDib) {return E_NOTIMPL;}
  1098. STDMETHODIMP CVMR9AllocatorPresenter::SetBorderColor(COLORREF Clr) {return E_NOTIMPL;}
  1099. STDMETHODIMP CVMR9AllocatorPresenter::GetBorderColor(COLORREF* lpClr)
  1100. {
  1101. if(lpClr) *lpClr = 0;
  1102. return S_OK;
  1103. }
  1104. //
  1105. // CRM9AllocatorPresenter
  1106. //
  1107. CRM9AllocatorPresenter::CRM9AllocatorPresenter(HWND hWnd, HRESULT& hr) 
  1108. : CDX9AllocatorPresenter(hWnd, hr)
  1109. {
  1110. }
  1111. STDMETHODIMP CRM9AllocatorPresenter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  1112. {
  1113.     CheckPointer(ppv, E_POINTER);
  1114. return 
  1115. QI2(IRMAVideoSurface)
  1116. __super::NonDelegatingQueryInterface(riid, ppv);
  1117. }
  1118. HRESULT CRM9AllocatorPresenter::AllocSurfaces()
  1119. {
  1120.     CAutoLock cAutoLock(this);
  1121. m_pVideoSurfaceOff = NULL;
  1122. m_pVideoSurfaceYUY2 = NULL;
  1123. HRESULT hr;
  1124. if(FAILED(hr = m_pD3DDev->CreateOffscreenPlainSurface(
  1125. m_NativeVideoSize.cx, m_NativeVideoSize.cy, D3DFMT_X8R8G8B8, 
  1126. D3DPOOL_DEFAULT, &m_pVideoSurfaceOff, NULL)))
  1127. return hr;
  1128. m_pD3DDev->ColorFill(m_pVideoSurfaceOff, NULL, 0);
  1129. if(FAILED(hr = m_pD3DDev->CreateOffscreenPlainSurface(
  1130. m_NativeVideoSize.cx, m_NativeVideoSize.cy, D3DFMT_YUY2, 
  1131. D3DPOOL_DEFAULT, &m_pVideoSurfaceYUY2, NULL)))
  1132. m_pVideoSurfaceYUY2 = NULL;
  1133. if(m_pVideoSurfaceYUY2)
  1134. {
  1135. m_pD3DDev->ColorFill(m_pVideoSurfaceOff, NULL, 0x80108010);
  1136. }
  1137. return __super::AllocSurfaces();
  1138. }
  1139. void CRM9AllocatorPresenter::DeleteSurfaces()
  1140. {
  1141.     CAutoLock cAutoLock(this);
  1142. m_pVideoSurfaceOff = NULL;
  1143. m_pVideoSurfaceYUY2 = NULL;
  1144. __super::DeleteSurfaces();
  1145. }
  1146. // IRMAVideoSurface
  1147. STDMETHODIMP CRM9AllocatorPresenter::Blt(UCHAR* pImageData, RMABitmapInfoHeader* pBitmapInfo, REF(PNxRect) inDestRect, REF(PNxRect) inSrcRect)
  1148. {
  1149. if(!m_pVideoSurface || !m_pVideoSurfaceOff)
  1150. return E_FAIL;
  1151. bool fRGB = false;
  1152. bool fYUY2 = false;
  1153. CRect src((RECT*)&inSrcRect), dst((RECT*)&inDestRect), src2(CPoint(0,0), src.Size());
  1154. if(src.Width() > dst.Width() || src.Height() > dst.Height())
  1155. return E_FAIL;
  1156. D3DSURFACE_DESC d3dsd;
  1157. ZeroMemory(&d3dsd, sizeof(d3dsd));
  1158. if(FAILED(m_pVideoSurfaceOff->GetDesc(&d3dsd)))
  1159. return E_FAIL;
  1160. int dbpp = 
  1161. d3dsd.Format == D3DFMT_R8G8B8 || d3dsd.Format == D3DFMT_X8R8G8B8 || d3dsd.Format == D3DFMT_A8R8G8B8 ? 32 : 
  1162. d3dsd.Format == D3DFMT_R5G6B5 ? 16 : 0;
  1163. if(pBitmapInfo->biCompression == '024I')
  1164. {
  1165. DWORD pitch = pBitmapInfo->biWidth;
  1166. DWORD size = pitch*abs(pBitmapInfo->biHeight);
  1167. BYTE* y = pImageData + src.top*pitch + src.left;
  1168. BYTE* u = pImageData + size + src.top*(pitch/2) + src.left/2;
  1169. BYTE* v = pImageData + size + size/4 + src.top*(pitch/2) + src.left/2;
  1170. if(m_pVideoSurfaceYUY2)
  1171. {
  1172. D3DLOCKED_RECT r;
  1173. if(SUCCEEDED(m_pVideoSurfaceYUY2->LockRect(&r, src2, 0)))
  1174. {
  1175. BitBltFromI420ToYUY2(src.Width(), src.Height(), (BYTE*)r.pBits, r.Pitch, y, u, v, pitch);
  1176. m_pVideoSurfaceYUY2->UnlockRect();
  1177. fYUY2 = true;
  1178. }
  1179. }
  1180. else
  1181. {
  1182. D3DLOCKED_RECT r;
  1183. if(SUCCEEDED(m_pVideoSurfaceOff->LockRect(&r, src2, 0)))
  1184. {
  1185. BitBltFromI420ToRGB(src.Width(), src.Height(), (BYTE*)r.pBits, r.Pitch, dbpp, y, u, v, pitch);
  1186. m_pVideoSurfaceOff->UnlockRect();
  1187. fRGB = true;
  1188. }
  1189. }
  1190. }
  1191. else if(pBitmapInfo->biCompression == '2YUY')
  1192. {
  1193. DWORD w = pBitmapInfo->biWidth;
  1194. DWORD h = abs(pBitmapInfo->biHeight);
  1195. DWORD pitch = pBitmapInfo->biWidth*2;
  1196. BYTE* yvyu = pImageData + src.top*pitch + src.left*2;
  1197. if(m_pVideoSurfaceYUY2)
  1198. {
  1199. D3DLOCKED_RECT r;
  1200. if(SUCCEEDED(m_pVideoSurfaceYUY2->LockRect(&r, src2, 0)))
  1201. {
  1202. BitBltFromYUY2ToYUY2(src.Width(), src.Height(), (BYTE*)r.pBits, r.Pitch, yvyu, pitch);
  1203. m_pVideoSurfaceYUY2->UnlockRect();
  1204. fYUY2 = true;
  1205. }
  1206. }
  1207. else
  1208. {
  1209. D3DLOCKED_RECT r;
  1210. if(SUCCEEDED(m_pVideoSurfaceOff->LockRect(&r, src2, 0)))
  1211. {
  1212. BitBltFromYUY2ToRGB(src.Width(), src.Height(), (BYTE*)r.pBits, r.Pitch, dbpp, yvyu, pitch);
  1213. m_pVideoSurfaceOff->UnlockRect();
  1214. fRGB = true;
  1215. }
  1216. }
  1217. }
  1218. else if(pBitmapInfo->biCompression == 0 || pBitmapInfo->biCompression == 3
  1219.  || pBitmapInfo->biCompression == 'BGRA')
  1220. {
  1221. DWORD w = pBitmapInfo->biWidth;
  1222. DWORD h = abs(pBitmapInfo->biHeight);
  1223. DWORD pitch = pBitmapInfo->biWidth*pBitmapInfo->biBitCount>>3;
  1224. BYTE* rgb = pImageData + src.top*pitch + src.left*(pBitmapInfo->biBitCount>>3);
  1225. D3DLOCKED_RECT r;
  1226. if(SUCCEEDED(m_pVideoSurfaceOff->LockRect(&r, src2, 0)))
  1227. {
  1228. BYTE* pBits = (BYTE*)r.pBits;
  1229. if(pBitmapInfo->biHeight > 0) {pBits += r.Pitch*(src.Height()-1); r.Pitch = -r.Pitch;}
  1230. BitBltFromRGBToRGB(src.Width(), src.Height(), pBits, r.Pitch, dbpp, rgb, pitch, pBitmapInfo->biBitCount);
  1231. m_pVideoSurfaceOff->UnlockRect();
  1232. fRGB = true;
  1233. }
  1234. }
  1235. if(!fRGB && !fYUY2)
  1236. {
  1237. m_pD3DDev->ColorFill(m_pVideoSurfaceOff, NULL, 0);
  1238. HDC hDC;
  1239. if(SUCCEEDED(m_pVideoSurfaceOff->GetDC(&hDC)))
  1240. {
  1241. CString str;
  1242. str.Format(_T("Sorry, this format is not supported"));
  1243. SetBkColor(hDC, 0);
  1244. SetTextColor(hDC, 0x404040);
  1245. TextOut(hDC, 10, 10, str, str.GetLength());
  1246. m_pVideoSurfaceOff->ReleaseDC(hDC);
  1247. fRGB = true;
  1248. }
  1249. }
  1250. HRESULT hr;
  1251. if(fRGB)
  1252. hr = m_pD3DDev->StretchRect(m_pVideoSurfaceOff, src2, m_pVideoSurface[0], dst, D3DTEXF_NONE);
  1253. if(fYUY2)
  1254. hr = m_pD3DDev->StretchRect(m_pVideoSurfaceYUY2, src2, m_pVideoSurface[0], dst, D3DTEXF_NONE);
  1255. Paint(true);
  1256. return PNR_OK;
  1257. }
  1258. STDMETHODIMP CRM9AllocatorPresenter::BeginOptimizedBlt(RMABitmapInfoHeader* pBitmapInfo)
  1259. {
  1260.     CAutoLock cAutoLock(this);
  1261. DeleteSurfaces();
  1262. m_NativeVideoSize = m_AspectRatio = CSize(pBitmapInfo->biWidth, abs(pBitmapInfo->biHeight));
  1263. if(FAILED(AllocSurfaces())) return E_FAIL;
  1264. return PNR_NOTIMPL;
  1265. }
  1266. STDMETHODIMP CRM9AllocatorPresenter::OptimizedBlt(UCHAR* pImageBits, REF(PNxRect) rDestRect, REF(PNxRect) rSrcRect)
  1267. {
  1268. return PNR_NOTIMPL;
  1269. }
  1270. STDMETHODIMP CRM9AllocatorPresenter::EndOptimizedBlt()
  1271. {
  1272. return PNR_NOTIMPL;
  1273. }
  1274. STDMETHODIMP CRM9AllocatorPresenter::GetOptimizedFormat(REF(RMA_COMPRESSION_TYPE) ulType)
  1275. {
  1276. return PNR_NOTIMPL;
  1277. }
  1278. STDMETHODIMP CRM9AllocatorPresenter::GetPreferredFormat(REF(RMA_COMPRESSION_TYPE) ulType)
  1279. {
  1280. ulType = RMA_I420;
  1281. return PNR_OK;
  1282. }
  1283. //
  1284. // CQT9AllocatorPresenter
  1285. //
  1286. CQT9AllocatorPresenter::CQT9AllocatorPresenter(HWND hWnd, HRESULT& hr) 
  1287. : CDX9AllocatorPresenter(hWnd, hr)
  1288. {
  1289. }
  1290. STDMETHODIMP CQT9AllocatorPresenter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  1291. {
  1292.     CheckPointer(ppv, E_POINTER);
  1293. return 
  1294. QI(IQTVideoSurface)
  1295. __super::NonDelegatingQueryInterface(riid, ppv);
  1296. }
  1297. HRESULT CQT9AllocatorPresenter::AllocSurfaces()
  1298. {
  1299. HRESULT hr;
  1300. m_pVideoSurfaceOff = NULL;
  1301. if(FAILED(hr = m_pD3DDev->CreateOffscreenPlainSurface(
  1302. m_NativeVideoSize.cx, m_NativeVideoSize.cy, D3DFMT_X8R8G8B8, 
  1303. D3DPOOL_DEFAULT, &m_pVideoSurfaceOff, NULL)))
  1304. return hr;
  1305. return __super::AllocSurfaces();
  1306. }
  1307. void CQT9AllocatorPresenter::DeleteSurfaces()
  1308. {
  1309. m_pVideoSurfaceOff = NULL;
  1310. __super::DeleteSurfaces();
  1311. }
  1312. // IQTVideoSurface
  1313. STDMETHODIMP CQT9AllocatorPresenter::BeginBlt(const BITMAP& bm)
  1314. {
  1315.     CAutoLock cAutoLock(this);
  1316. DeleteSurfaces();
  1317. m_NativeVideoSize = m_AspectRatio = CSize(bm.bmWidth, abs(bm.bmHeight));
  1318. if(FAILED(AllocSurfaces())) return E_FAIL;
  1319. return S_OK;
  1320. }
  1321. STDMETHODIMP CQT9AllocatorPresenter::DoBlt(const BITMAP& bm)
  1322. {
  1323. if(!m_pVideoSurface || !m_pVideoSurfaceOff)
  1324. return E_FAIL;
  1325. bool fOk = false;
  1326. D3DSURFACE_DESC d3dsd;
  1327. ZeroMemory(&d3dsd, sizeof(d3dsd));
  1328. if(FAILED(m_pVideoSurfaceOff->GetDesc(&d3dsd)))
  1329. return E_FAIL;
  1330. int w = bm.bmWidth;
  1331. int h = abs(bm.bmHeight);
  1332. int bpp = bm.bmBitsPixel;
  1333. int dbpp = 
  1334. d3dsd.Format == D3DFMT_R8G8B8 || d3dsd.Format == D3DFMT_X8R8G8B8 || d3dsd.Format == D3DFMT_A8R8G8B8 ? 32 : 
  1335. d3dsd.Format == D3DFMT_R5G6B5 ? 16 : 0;
  1336. if((bpp == 16 || bpp == 24 || bpp == 32) && w == d3dsd.Width && h == d3dsd.Height)
  1337. {
  1338. D3DLOCKED_RECT r;
  1339. if(SUCCEEDED(m_pVideoSurfaceOff->LockRect(&r, NULL, 0)))
  1340. {
  1341. BitBltFromRGBToRGB(
  1342. w, h,
  1343. (BYTE*)r.pBits, r.Pitch, dbpp,
  1344. (BYTE*)bm.bmBits, bm.bmWidthBytes, bm.bmBitsPixel);
  1345. m_pVideoSurfaceOff->UnlockRect();
  1346. fOk = true;
  1347. }
  1348. }
  1349. if(!fOk)
  1350. {
  1351. m_pD3DDev->ColorFill(m_pVideoSurfaceOff, NULL, 0);
  1352. HDC hDC;
  1353. if(SUCCEEDED(m_pVideoSurfaceOff->GetDC(&hDC)))
  1354. {
  1355. CString str;
  1356. str.Format(_T("Sorry, this color format is not supported"));
  1357. SetBkColor(hDC, 0);
  1358. SetTextColor(hDC, 0x404040);
  1359. TextOut(hDC, 10, 10, str, str.GetLength());
  1360. m_pVideoSurfaceOff->ReleaseDC(hDC);
  1361. }
  1362. }
  1363. m_pD3DDev->StretchRect(m_pVideoSurfaceOff, NULL, m_pVideoSurface[0], NULL, D3DTEXF_NONE);
  1364. Paint(true);
  1365. return S_OK;
  1366. }