DX9AllocatorPresenter.cpp

00001 /* 
00002  *      Copyright (C) 2003-2005 Gabest
00003  *      http://www.gabest.org
00004  *
00005  *  This Program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2, or (at your option)
00008  *  any later version.
00009  *   
00010  *  This Program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013  *  GNU General Public License for more details.
00014  *   
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with GNU Make; see the file COPYING.  If not, write to
00017  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
00018  *  http://www.gnu.org/copyleft/gpl.html
00019  *
00020  */
00021 
00022 #include "stdafx.h"
00023 #include "mplayerc.h"
00024 #include <atlbase.h>
00025 #include <atlcoll.h>
00026 #include "..\..\DSUtil\DSUtil.h"
00027 
00028 #include <Videoacc.h>
00029 
00030 #include <initguid.h>
00031 #include "DX9AllocatorPresenter.h"
00032 #include <d3d9.h>
00033 #include <d3dx9.h>
00034 #include <Vmr9.h>
00035 #include "..\..\SubPic\DX9SubPic.h"
00036 #include "..\..\..\include\RealMedia\pntypes.h"
00037 #include "..\..\..\include\RealMedia\pnwintyp.h"
00038 #include "..\..\..\include\RealMedia\pncom.h"
00039 #include "..\..\..\include\RealMedia\rmavsurf.h"
00040 #include "IQTVideoSurface.h"
00041 
00042 #include "MacrovisionKicker.h"
00043 #include "IPinHook.h"
00044 
00045 #include "PixelShaderCompiler.h"
00046 
00047 bool IsVMR9InGraph(IFilterGraph* pFG)
00048 {
00049         BeginEnumFilters(pFG, pEF, pBF)
00050                 if(CComQIPtr<IVMRWindowlessControl9>(pBF)) return(true);
00051         EndEnumFilters
00052         return(false);
00053 }
00054 
00055 namespace DSObjects
00056 {
00057 
00058 class CDX9AllocatorPresenter
00059         : public ISubPicAllocatorPresenterImpl
00060 {
00061 protected:
00062         CSize m_ScreenSize;
00063         bool m_fVMRSyncFix;
00064 
00065         CComPtr<IDirect3D9> m_pD3D;
00066     CComPtr<IDirect3DDevice9> m_pD3DDev;
00067         CComPtr<IDirect3DTexture9> m_pVideoTexture[2];
00068         CComPtr<IDirect3DSurface9> m_pVideoSurface[2];
00069         CComPtr<IDirect3DPixelShader9> m_pPixelShader, m_pResizerPixelShader[4];
00070         D3DTEXTUREFILTERTYPE m_Filter;
00071 
00072         CAutoPtr<CPixelShaderCompiler> m_pPSC;
00073 
00074         virtual HRESULT CreateDevice();
00075         virtual HRESULT AllocSurfaces();
00076         virtual void DeleteSurfaces();
00077 
00078     UINT  GetAdapter(IDirect3D9 *pD3D);
00079 
00080 public:
00081         CDX9AllocatorPresenter(HWND hWnd, HRESULT& hr);
00082 
00083         // ISubPicAllocatorPresenter
00084         STDMETHODIMP CreateRenderer(IUnknown** ppRenderer);
00085         STDMETHODIMP_(bool) Paint(bool fAll);
00086         STDMETHODIMP GetDIB(BYTE* lpDib, DWORD* size);
00087         STDMETHODIMP SetPixelShader(LPCSTR pSrcData, LPCSTR pTarget);
00088 };
00089 
00090 class CVMR9AllocatorPresenter
00091         : public CDX9AllocatorPresenter
00092         , public IVMRSurfaceAllocator9
00093         , public IVMRImagePresenter9
00094         , public IVMRWindowlessControl9
00095 {
00096 protected:
00097         CComPtr<IVMRSurfaceAllocatorNotify9> m_pIVMRSurfAllocNotify;
00098         CInterfaceArray<IDirect3DSurface9> m_pSurfaces;
00099 
00100         HRESULT CreateDevice();
00101         void DeleteSurfaces();
00102 
00103         bool m_fUseInternalTimer;
00104 
00105 public:
00106         CVMR9AllocatorPresenter(HWND hWnd, HRESULT& hr);
00107 
00108         DECLARE_IUNKNOWN
00109     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
00110 
00111         // ISubPicAllocatorPresenter
00112         STDMETHODIMP CreateRenderer(IUnknown** ppRenderer);
00113         STDMETHODIMP_(void) SetTime(REFERENCE_TIME rtNow);
00114 
00115     // IVMRSurfaceAllocator9
00116     STDMETHODIMP InitializeDevice(DWORD_PTR dwUserID, VMR9AllocationInfo* lpAllocInfo, DWORD* lpNumBuffers);
00117     STDMETHODIMP TerminateDevice(DWORD_PTR dwID);
00118     STDMETHODIMP GetSurface(DWORD_PTR dwUserID, DWORD SurfaceIndex, DWORD SurfaceFlags, IDirect3DSurface9** lplpSurface);
00119     STDMETHODIMP AdviseNotify(IVMRSurfaceAllocatorNotify9* lpIVMRSurfAllocNotify);
00120 
00121     // IVMRImagePresenter9
00122     STDMETHODIMP StartPresenting(DWORD_PTR dwUserID);
00123     STDMETHODIMP StopPresenting(DWORD_PTR dwUserID);
00124     STDMETHODIMP PresentImage(DWORD_PTR dwUserID, VMR9PresentationInfo* lpPresInfo);
00125 
00126         // IVMRWindowlessControl9
00127         STDMETHODIMP GetNativeVideoSize(LONG* lpWidth, LONG* lpHeight, LONG* lpARWidth, LONG* lpARHeight);
00128         STDMETHODIMP GetMinIdealVideoSize(LONG* lpWidth, LONG* lpHeight);
00129         STDMETHODIMP GetMaxIdealVideoSize(LONG* lpWidth, LONG* lpHeight);
00130         STDMETHODIMP SetVideoPosition(const LPRECT lpSRCRect, const LPRECT lpDSTRect);
00131     STDMETHODIMP GetVideoPosition(LPRECT lpSRCRect, LPRECT lpDSTRect);
00132         STDMETHODIMP GetAspectRatioMode(DWORD* lpAspectRatioMode);
00133         STDMETHODIMP SetAspectRatioMode(DWORD AspectRatioMode);
00134         STDMETHODIMP SetVideoClippingWindow(HWND hwnd);
00135         STDMETHODIMP RepaintVideo(HWND hwnd, HDC hdc);
00136         STDMETHODIMP DisplayModeChanged();
00137         STDMETHODIMP GetCurrentImage(BYTE** lpDib);
00138         STDMETHODIMP SetBorderColor(COLORREF Clr);
00139         STDMETHODIMP GetBorderColor(COLORREF* lpClr);
00140 };
00141 
00142 class CRM9AllocatorPresenter
00143         : public CDX9AllocatorPresenter
00144         , public IRMAVideoSurface
00145 {
00146         CComPtr<IDirect3DSurface9> m_pVideoSurfaceOff;
00147         CComPtr<IDirect3DSurface9> m_pVideoSurfaceYUY2;
00148 
00149     RMABitmapInfoHeader m_bitmapInfo;
00150     RMABitmapInfoHeader m_lastBitmapInfo;
00151 
00152 protected:
00153         HRESULT AllocSurfaces();
00154         void DeleteSurfaces();
00155 
00156 public:
00157         CRM9AllocatorPresenter(HWND hWnd, HRESULT& hr);
00158 
00159         DECLARE_IUNKNOWN
00160     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
00161 
00162         // IRMAVideoSurface
00163     STDMETHODIMP Blt(UCHAR*     pImageData, RMABitmapInfoHeader* pBitmapInfo, REF(PNxRect) inDestRect, REF(PNxRect) inSrcRect);
00164         STDMETHODIMP BeginOptimizedBlt(RMABitmapInfoHeader* pBitmapInfo);
00165         STDMETHODIMP OptimizedBlt(UCHAR* pImageBits, REF(PNxRect) rDestRect, REF(PNxRect) rSrcRect);
00166         STDMETHODIMP EndOptimizedBlt();
00167         STDMETHODIMP GetOptimizedFormat(REF(RMA_COMPRESSION_TYPE) ulType);
00168     STDMETHODIMP GetPreferredFormat(REF(RMA_COMPRESSION_TYPE) ulType);
00169 };
00170 
00171 class CQT9AllocatorPresenter
00172         : public CDX9AllocatorPresenter
00173         , public IQTVideoSurface
00174 {
00175         CComPtr<IDirect3DSurface9> m_pVideoSurfaceOff;
00176 
00177 protected:
00178          HRESULT AllocSurfaces();
00179          void DeleteSurfaces();
00180 
00181 public:
00182         CQT9AllocatorPresenter(HWND hWnd, HRESULT& hr);
00183 
00184         DECLARE_IUNKNOWN
00185     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
00186 
00187         // IQTVideoSurface
00188         STDMETHODIMP BeginBlt(const BITMAP& bm);
00189         STDMETHODIMP DoBlt(const BITMAP& bm);
00190 };
00191 
00192 }
00193 using namespace DSObjects;
00194 
00195 //
00196 
00197 HRESULT CreateAP9(const CLSID& clsid, HWND hWnd, ISubPicAllocatorPresenter** ppAP)
00198 {
00199         CheckPointer(ppAP, E_POINTER);
00200 
00201         *ppAP = NULL;
00202 
00203         HRESULT hr;
00204         if(clsid == CLSID_VMR9AllocatorPresenter && !(*ppAP = new CVMR9AllocatorPresenter(hWnd, hr))
00205         || clsid == CLSID_RM9AllocatorPresenter && !(*ppAP = new CRM9AllocatorPresenter(hWnd, hr))
00206         || clsid == CLSID_QT9AllocatorPresenter && !(*ppAP = new CQT9AllocatorPresenter(hWnd, hr)))
00207                 return E_OUTOFMEMORY;
00208 
00209         if(*ppAP == NULL)
00210                 return E_FAIL;
00211 
00212         (*ppAP)->AddRef();
00213 
00214         if(FAILED(hr))
00215         {
00216                 (*ppAP)->Release();
00217                 *ppAP = NULL;
00218         }
00219 
00220         return hr;
00221 }
00222 
00223 //
00224 
00225 static HRESULT TextureBlt(CComPtr<IDirect3DTexture9> pTexture, Vector dst[4], CRect src, DWORD filter = D3DTEXF_LINEAR)
00226 {
00227         if(!pTexture)
00228                 return E_POINTER;
00229 
00230         CComPtr<IDirect3DDevice9> pD3DDev;
00231         if(FAILED(pTexture->GetDevice(&pD3DDev)) || !pD3DDev)
00232                 return E_FAIL;
00233 
00234         HRESULT hr;
00235 
00236     do
00237         {
00238                 D3DSURFACE_DESC d3dsd;
00239                 ZeroMemory(&d3dsd, sizeof(d3dsd));
00240                 if(FAILED(pTexture->GetLevelDesc(0, &d3dsd)))
00241                         break;
00242 
00243         float w = (float)d3dsd.Width;
00244         float h = (float)d3dsd.Height;
00245 
00246                 struct
00247                 {
00248                         float x, y, z, rhw;
00249                         float tu, tv;
00250                 }
00251                 pVertices[] =
00252                 {
00253 //                      {(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 },
00254 //                      {(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},
00255 //                      {(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},
00256                         {(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},
00257                         {(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},
00258                         {(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},
00259                         {(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},
00260                 };
00261 
00262                 for(int i = 0; i < countof(pVertices); i++)
00263                 {
00264                         pVertices[i].x -= 0.5;
00265                         pVertices[i].y -= 0.5;
00266                 }
00267 
00268         hr = pD3DDev->SetTexture(0, pTexture);
00269 
00270         hr = pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
00271         hr = pD3DDev->SetRenderState(D3DRS_LIGHTING, FALSE);
00272                 hr = pD3DDev->SetRenderState(D3DRS_ZENABLE, FALSE);
00273         hr = pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
00274                 hr = pD3DDev->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); 
00275 
00276                 hr = pD3DDev->SetSamplerState(0, D3DSAMP_MAGFILTER, filter);
00277         hr = pD3DDev->SetSamplerState(0, D3DSAMP_MINFILTER, filter);
00278         hr = pD3DDev->SetSamplerState(0, D3DSAMP_MIPFILTER, filter);
00279 
00280                 hr = pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
00281                 hr = pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
00282 
00283                 //
00284 
00285                 if(FAILED(hr = pD3DDev->BeginScene()))
00286                         break;
00287 
00288         hr = pD3DDev->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
00289 //          hr = pD3DDev->DrawPrimitiveUP(D3DPT_TRIANGLELIST, 1, pVertices, sizeof(pVertices[0]));
00290                 hr = pD3DDev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pVertices, sizeof(pVertices[0]));
00291 
00292                 hr = pD3DDev->EndScene();
00293 
00294         //
00295 
00296                 pD3DDev->SetTexture(0, NULL);
00297 
00298                 return S_OK;
00299     }
00300         while(0);
00301 
00302     return E_FAIL;
00303 }
00304 
00305 static HRESULT TextureBlt(CComPtr<IDirect3DTexture9> pTexture, CRect dst, CRect src, DWORD filter = D3DTEXF_LINEAR)
00306 {
00307         if(!pTexture)
00308                 return E_POINTER;
00309 
00310         CComPtr<IDirect3DDevice9> pD3DDev;
00311         if(FAILED(pTexture->GetDevice(&pD3DDev)) || !pD3DDev)
00312                 return E_FAIL;
00313 
00314         HRESULT hr;
00315 
00316     do
00317         {
00318                 D3DSURFACE_DESC d3dsd;
00319                 ZeroMemory(&d3dsd, sizeof(d3dsd));
00320                 if(FAILED(pTexture->GetLevelDesc(0, &d3dsd)))
00321                         break;
00322 
00323         float w = (float)d3dsd.Width;
00324         float h = (float)d3dsd.Height;
00325 
00326                 struct
00327                 {
00328                         float x, y, z, rhw;
00329                         float tu, tv;
00330                 }
00331                 pVertices[] =
00332                 {
00333                         {(float)dst.left, (float)dst.top, 0.5f, 2.0f, (float)src.left / w, (float)src.top / h},
00334                         {(float)dst.right, (float)dst.top, 0.5f, 2.0f, (float)src.right / w, (float)src.top / h},
00335                         {(float)dst.left, (float)dst.bottom, 0.5f, 2.0f, (float)src.left / w, (float)src.bottom / h},
00336                         {(float)dst.right, (float)dst.bottom, 0.5f, 2.0f, (float)src.right / w, (float)src.bottom / h},
00337                 };
00338 
00339                 for(int i = 0; i < countof(pVertices); i++)
00340                 {
00341                         pVertices[i].x -= 0.5;
00342                         pVertices[i].y -= 0.5;
00343                 }
00344 
00345         hr = pD3DDev->SetTexture(0, pTexture);
00346 
00347         hr = pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
00348         hr = pD3DDev->SetRenderState(D3DRS_LIGHTING, FALSE);
00349                 hr = pD3DDev->SetRenderState(D3DRS_ZENABLE, FALSE);
00350         hr = pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
00351                 hr = pD3DDev->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); 
00352 
00353                 hr = pD3DDev->SetSamplerState(0, D3DSAMP_MAGFILTER, filter);
00354         hr = pD3DDev->SetSamplerState(0, D3DSAMP_MINFILTER, filter);
00355         hr = pD3DDev->SetSamplerState(0, D3DSAMP_MIPFILTER, filter);
00356 
00357                 hr = pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
00358                 hr = pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
00359 
00360                 //
00361 
00362                 if(FAILED(hr = pD3DDev->BeginScene()))
00363                         break;
00364 
00365         hr = pD3DDev->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
00366                 hr = pD3DDev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pVertices, sizeof(pVertices[0]));
00367 
00368                 hr = pD3DDev->EndScene();
00369 
00370         //
00371 
00372                 pD3DDev->SetTexture(0, NULL);
00373 
00374                 return S_OK;
00375     }
00376         while(0);
00377 
00378     return E_FAIL;
00379 }
00380 
00381 // CDX9AllocatorPresenter
00382 
00383 CDX9AllocatorPresenter::CDX9AllocatorPresenter(HWND hWnd, HRESULT& hr) 
00384         : ISubPicAllocatorPresenterImpl(hWnd)
00385         , m_ScreenSize(0, 0)
00386 {
00387     if(!IsWindow(m_hWnd))
00388     {
00389         hr = E_INVALIDARG;
00390         return;
00391     }
00392 
00393         m_pD3D.Attach(Direct3DCreate9(D3D_SDK_VERSION));
00394         if(!m_pD3D) m_pD3D.Attach(Direct3DCreate9(D3D9b_SDK_VERSION));
00395 
00396         if(!m_pD3D)
00397         {
00398                 hr = E_FAIL;
00399                 return;
00400         }
00401 
00402         GetWindowRect(m_hWnd, &m_WindowRect);
00403 
00404         hr = CreateDevice();
00405 }
00406 
00407 HRESULT CDX9AllocatorPresenter::CreateDevice()
00408 {
00409         m_pPSC.Free();
00410     m_pD3DDev = NULL;
00411 
00412         D3DDISPLAYMODE d3ddm;
00413         ZeroMemory(&d3ddm, sizeof(d3ddm));
00414         if(FAILED(m_pD3D->GetAdapterDisplayMode(GetAdapter(m_pD3D), &d3ddm)))
00415                 return E_UNEXPECTED;
00416 
00417         m_ScreenSize.SetSize(d3ddm.Width, d3ddm.Height);
00418 
00419     D3DPRESENT_PARAMETERS pp;
00420     ZeroMemory(&pp, sizeof(pp));
00421     pp.Windowed = TRUE;
00422     pp.hDeviceWindow = m_hWnd;
00423     pp.SwapEffect = D3DSWAPEFFECT_COPY;
00424         pp.Flags = D3DPRESENTFLAG_VIDEO;
00425         pp.BackBufferWidth = d3ddm.Width;
00426         pp.BackBufferHeight = d3ddm.Height;
00427 
00428         if(m_fVMRSyncFix = AfxGetMyApp()->m_s.fVMRSyncFix)
00429                 pp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
00430 
00431         HRESULT hr = m_pD3D->CreateDevice(
00432                                                 GetAdapter(m_pD3D), D3DDEVTYPE_HAL, m_hWnd,
00433                                                 D3DCREATE_SOFTWARE_VERTEXPROCESSING|D3DCREATE_MULTITHREADED, //D3DCREATE_MANAGED 
00434                                                 &pp, &m_pD3DDev);
00435         if(FAILED(hr))
00436                 return hr;
00437 
00438         m_pPSC.Attach(new CPixelShaderCompiler(m_pD3DDev, true));
00439 
00440         //
00441 
00442         m_Filter = D3DTEXF_NONE;
00443 
00444         D3DCAPS9 caps;
00445     ZeroMemory(&caps, sizeof(caps));
00446         m_pD3DDev->GetDeviceCaps(&caps);
00447         if((caps.StretchRectFilterCaps&D3DPTFILTERCAPS_MINFLINEAR)
00448         && (caps.StretchRectFilterCaps&D3DPTFILTERCAPS_MAGFLINEAR))
00449                 m_Filter = D3DTEXF_LINEAR;
00450 
00451         //
00452 
00453         if(caps.PixelShaderVersion >= D3DVS_VERSION(2, 0))
00454         {
00455                 CStringA data;
00456                 if(LoadResource(IDF_SHADER_RESIZER, data, _T("FILE")))
00457                 {
00458                         m_pPSC->CompileShader(data, "main_bilinear", "ps_2_0", 0, &m_pResizerPixelShader[0]);
00459 
00460                         {
00461                                 CStringA str = data;
00462                                 str.Replace("_The_Value_Of_A_Is_Set_Here_", "(-0.60)");
00463                                 m_pPSC->CompileShader(str, "main_bicubic", "ps_2_0", 0, &m_pResizerPixelShader[1]);
00464                         }
00465 
00466                         {
00467                                 CStringA str = data;
00468                                 str.Replace("_The_Value_Of_A_Is_Set_Here_", "(-0.75)");
00469                                 m_pPSC->CompileShader(str, "main_bicubic", "ps_2_0", 0, &m_pResizerPixelShader[2]);
00470                         }
00471 
00472                         {
00473                                 CStringA str = data;
00474                                 str.Replace("_The_Value_Of_A_Is_Set_Here_", "(-1.00)");
00475                                 m_pPSC->CompileShader(str, "main_bicubic", "ps_2_0", 0, &m_pResizerPixelShader[3]);
00476                         }
00477                 }
00478         }
00479 
00480         //
00481 
00482         CComPtr<ISubPicProvider> pSubPicProvider;
00483         if(m_pSubPicQueue) m_pSubPicQueue->GetSubPicProvider(&pSubPicProvider);
00484 
00485         CSize size;
00486         switch(AfxGetAppSettings().nSPCMaxRes)
00487         {
00488         case 0: default: size = m_ScreenSize; break;
00489         case 1: size.SetSize(1024, 768); break;
00490         case 2: size.SetSize(800, 600); break;
00491         case 3: size.SetSize(640, 480); break;
00492         case 4: size.SetSize(512, 384); break;
00493         case 5: size.SetSize(384, 288); break;
00494         }
00495 
00496         if(m_pAllocator)
00497         {
00498                 m_pAllocator->ChangeDevice(m_pD3DDev);
00499         }
00500         else
00501         {
00502                 m_pAllocator = new CDX9SubPicAllocator(m_pD3DDev, size, AfxGetAppSettings().fSPCPow2Tex);
00503                 if(!m_pAllocator)
00504                         return E_FAIL;
00505         }
00506 
00507         hr = S_OK;
00508         m_pSubPicQueue = AfxGetAppSettings().nSPCSize > 0 
00509                 ? (ISubPicQueue*)new CSubPicQueue(AfxGetAppSettings().nSPCSize, m_pAllocator, &hr)
00510                 : (ISubPicQueue*)new CSubPicQueueNoThread(m_pAllocator, &hr);
00511         if(!m_pSubPicQueue || FAILED(hr))
00512                 return E_FAIL;
00513 
00514         if(pSubPicProvider) m_pSubPicQueue->SetSubPicProvider(pSubPicProvider);
00515 
00516         return S_OK;
00517 } 
00518 
00519 HRESULT CDX9AllocatorPresenter::AllocSurfaces()
00520 {
00521     CAutoLock cAutoLock(this);
00522 
00523         AppSettings& s = AfxGetAppSettings();
00524 
00525         m_pVideoTexture[0] = NULL;
00526         m_pVideoTexture[1] = NULL;
00527         m_pVideoSurface[0] = NULL;
00528         m_pVideoSurface[1] = NULL;
00529 
00530         HRESULT hr;
00531 
00532         if(s.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE2D || s.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D)
00533         {
00534                 if(FAILED(hr = m_pD3DDev->CreateTexture(
00535                         m_NativeVideoSize.cx, m_NativeVideoSize.cy, 1, D3DUSAGE_RENDERTARGET, /*D3DFMT_X8R8G8B8*/D3DFMT_A8R8G8B8, 
00536                         D3DPOOL_DEFAULT, &m_pVideoTexture[0], NULL)))
00537                         return hr;
00538 
00539                 if(FAILED(hr = m_pVideoTexture[0]->GetSurfaceLevel(0, &m_pVideoSurface[0])))
00540                         return hr;
00541 
00542                 if(s.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D)
00543                 {
00544                         if(FAILED(hr = m_pD3DDev->CreateTexture(
00545                                 m_NativeVideoSize.cx, m_NativeVideoSize.cy, 1, D3DUSAGE_RENDERTARGET, /*D3DFMT_X8R8G8B8*/D3DFMT_A8R8G8B8, 
00546                                 D3DPOOL_DEFAULT, &m_pVideoTexture[1], NULL)))
00547                                 return hr;
00548 
00549                         if(FAILED(hr = m_pVideoTexture[1]->GetSurfaceLevel(0, &m_pVideoSurface[1])))
00550                                 return hr;
00551                 }
00552 
00553                 if(s.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE2D)
00554                         m_pVideoTexture[0] = NULL, m_pVideoTexture[1] = NULL;
00555         }
00556         else
00557         {
00558                 if(FAILED(hr = m_pD3DDev->CreateOffscreenPlainSurface(
00559                         m_NativeVideoSize.cx, m_NativeVideoSize.cy, D3DFMT_X8R8G8B8/*D3DFMT_A8R8G8B8*/, 
00560                         D3DPOOL_DEFAULT, &m_pVideoSurface[0], NULL)))
00561                         return hr;
00562         }
00563 
00564         hr = m_pD3DDev->ColorFill(m_pVideoSurface[0], NULL, 0);
00565 
00566         return S_OK;
00567 }
00568 
00569 void CDX9AllocatorPresenter::DeleteSurfaces()
00570 {
00571     CAutoLock cAutoLock(this);
00572 
00573         m_pVideoTexture[0] = m_pVideoTexture[1] = NULL;
00574         m_pVideoSurface[0] = m_pVideoSurface[1] = NULL;
00575 }
00576 
00577 UINT CDX9AllocatorPresenter::GetAdapter(IDirect3D9 *pD3D)
00578 {
00579         if(m_hWnd == NULL || pD3D == NULL)
00580                 return D3DADAPTER_DEFAULT;
00581 
00582         HMONITOR hMonitor = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST);
00583         if(hMonitor == NULL) return D3DADAPTER_DEFAULT;
00584 
00585         for(UINT adp = 0, num_adp = pD3D->GetAdapterCount(); adp < num_adp; ++adp)
00586         {
00587                 HMONITOR hAdpMon = pD3D->GetAdapterMonitor(adp);
00588                 if(hAdpMon == hMonitor) return adp;
00589         }
00590 
00591         return D3DADAPTER_DEFAULT;
00592 }
00593 
00594 // ISubPicAllocatorPresenter
00595 
00596 STDMETHODIMP CDX9AllocatorPresenter::CreateRenderer(IUnknown** ppRenderer)
00597 {
00598         return E_NOTIMPL;
00599 }
00600 
00601 static bool ClipToSurface(IDirect3DSurface9* pSurface, CRect& s, CRect& d)   
00602 {   
00603         D3DSURFACE_DESC d3dsd;   
00604         ZeroMemory(&d3dsd, sizeof(d3dsd));   
00605         if(FAILED(pSurface->GetDesc(&d3dsd)))   
00606                 return(false);   
00607 
00608         int w = d3dsd.Width, h = d3dsd.Height;   
00609         int sw = s.Width(), sh = s.Height();   
00610         int dw = d.Width(), dh = d.Height();   
00611 
00612         if(d.left >= w || d.right < 0 || d.top >= h || d.bottom < 0   
00613         || sw <= 0 || sh <= 0 || dw <= 0 || dh <= 0)   
00614         {   
00615                 s.SetRectEmpty();   
00616                 d.SetRectEmpty();   
00617                 return(true);   
00618         }   
00619 
00620         if(d.right > w) {s.right -= (d.right-w)*sw/dw; d.right = w;}   
00621         if(d.bottom > h) {s.bottom -= (d.bottom-h)*sh/dh; d.bottom = h;}   
00622         if(d.left < 0) {s.left += (0-d.left)*sw/dw; d.left = 0;}   
00623         if(d.top < 0) {s.top += (0-d.top)*sh/dh; d.top = 0;}   
00624 
00625         return(true);   
00626 } 
00627 
00628 STDMETHODIMP_(bool) CDX9AllocatorPresenter::Paint(bool fAll)
00629 {
00630         CAutoLock cAutoLock(this);
00631 
00632         if(m_WindowRect.right <= m_WindowRect.left || m_WindowRect.bottom <= m_WindowRect.top
00633         || m_NativeVideoSize.cx <= 0 || m_NativeVideoSize.cy <= 0
00634         || !m_pVideoSurface)
00635                 return(false);
00636 
00637         HRESULT hr;
00638 
00639         CRect rSrcVid(CPoint(0, 0), m_NativeVideoSize);
00640         CRect rDstVid(m_VideoRect);
00641 
00642         CRect rSrcPri(CPoint(0, 0), m_WindowRect.Size());
00643         CRect rDstPri(m_WindowRect);
00644 
00645         CComPtr<IDirect3DSurface9> pBackBuffer;
00646         m_pD3DDev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
00647 
00648         if(fAll)
00649         {
00650                 // clear the backbuffer
00651 
00652                 hr = m_pD3DDev->Clear(0, NULL, D3DCLEAR_TARGET, 0, 1.0f, 0);
00653 
00654                 // paint the video on the backbuffer
00655 
00656                 if(!rDstVid.IsRectEmpty())
00657                 {
00658                         if(m_pVideoTexture[0])
00659                         {
00660                                 CComPtr<IDirect3DTexture9> pVideoTexture = m_pVideoTexture[0];
00661 
00662                                 if(m_pVideoTexture[1] && m_pPixelShader)
00663                                 {
00664                                         static __int64 counter = 0;
00665                                         static long start = clock();
00666 
00667                                         long stop = clock();
00668                                         long diff = stop - start;
00669 
00670                                         if(diff >= 10*60*CLOCKS_PER_SEC) start = stop; // reset after 10 min (ps float has its limits in both range and accuracy)
00671 
00672                                         float fConstData[][4] = 
00673                                         {
00674                                                 {(float)m_NativeVideoSize.cx, (float)m_NativeVideoSize.cy, (float)(counter++), (float)diff / CLOCKS_PER_SEC},
00675                                                 {1.0f / m_NativeVideoSize.cx, 1.0f / m_NativeVideoSize.cy, 0, 0},
00676                                         };
00677 
00678                                         CComPtr<IDirect3DSurface9> pRT;
00679                                         hr = m_pD3DDev->GetRenderTarget(0, &pRT);
00680                                         hr = m_pD3DDev->SetRenderTarget(0, m_pVideoSurface[1]);
00681                                         hr = m_pD3DDev->SetPixelShaderConstantF(0, (float*)fConstData, countof(fConstData));
00682                                         hr = m_pD3DDev->SetPixelShader(m_pPixelShader);
00683 
00684                                         TextureBlt(m_pVideoTexture[0], rSrcVid, rSrcVid);
00685 
00686                                         hr = m_pD3DDev->SetRenderTarget(0, pRT);
00687                                         hr = m_pD3DDev->SetPixelShader(NULL);
00688 
00689                                         pVideoTexture = m_pVideoTexture[1];
00690                                 }
00691 
00692                                 DWORD resizer = AfxGetAppSettings().iDX9Resizer;
00693                                 DWORD filter = resizer == 0 ? D3DTEXF_POINT : D3DTEXF_LINEAR;
00694 
00695                                 CComPtr<IDirect3DPixelShader9> pResizerPixelShader;
00696 
00697                                 if(rSrcVid != rDstVid)
00698                                 {
00699                                         if(resizer == 2 && m_pResizerPixelShader[0]) pResizerPixelShader = m_pResizerPixelShader[0];
00700                                         else if(resizer == 3 && m_pResizerPixelShader[1]) pResizerPixelShader = m_pResizerPixelShader[1];
00701                                         else if(resizer == 4 && m_pResizerPixelShader[2]) pResizerPixelShader = m_pResizerPixelShader[2];
00702                                         else if(resizer == 5 && m_pResizerPixelShader[3]) pResizerPixelShader = m_pResizerPixelShader[3];
00703                                 }
00704 
00705                                 if(pResizerPixelShader)
00706                                 {
00707                                         float fConstData[][4] = 
00708                                         {
00709                                                 {(float)m_NativeVideoSize.cx, (float)m_NativeVideoSize.cy, 0, 0},
00710                                                 {1.0f / m_NativeVideoSize.cx, 1.0f / m_NativeVideoSize.cy, 0, 0},
00711                                                 {1.0f / m_NativeVideoSize.cx, 0, 0, 0},
00712                                                 {0, 1.0f / m_NativeVideoSize.cy, 0, 0},
00713                                         };
00714 
00715                                         hr = m_pD3DDev->SetPixelShaderConstantF(0, (float*)fConstData, countof(fConstData));
00716                                         hr = m_pD3DDev->SetPixelShader(pResizerPixelShader);
00717 
00718                                         filter = D3DTEXF_POINT;
00719                                 }
00720 
00721                                 Vector v[4];
00722                                 Transform(rDstVid, v);
00723                                 hr = TextureBlt(pVideoTexture, v, rSrcVid, filter);
00724 
00725                                 if(pResizerPixelShader)
00726                                         hr = m_pD3DDev->SetPixelShader(NULL);
00727                         }
00728                         else
00729                         {
00730                                 if(pBackBuffer)
00731                                 {
00732                                         ClipToSurface(pBackBuffer, rSrcVid, rDstVid); // grrr
00733                                         // IMPORTANT: rSrcVid has to be aligned on mod2 for yuy2->rgb conversion with StretchRect!!!
00734                                         rSrcVid.left &= ~1; rSrcVid.right &= ~1;
00735                                         rSrcVid.top &= ~1; rSrcVid.bottom &= ~1;
00736                                         hr = m_pD3DDev->StretchRect(m_pVideoSurface[0], rSrcVid, pBackBuffer, rDstVid, m_Filter);
00737                                 }
00738                         }
00739                 }
00740 
00741                 // paint the text on the backbuffer
00742 
00743                 AlphaBltSubPic(rSrcPri.Size());
00744         }
00745 
00746         if(m_fVMRSyncFix)
00747         {
00748                 D3DLOCKED_RECT lr;
00749                 if(SUCCEEDED(pBackBuffer->LockRect(&lr, NULL, 0)))
00750                         pBackBuffer->UnlockRect();
00751         }
00752 
00753         hr = m_pD3DDev->Present(rSrcPri, rDstPri, NULL, NULL);
00754 
00755         if(hr == D3DERR_DEVICELOST)
00756         {
00757                 if(m_pD3DDev->TestCooperativeLevel() == D3DERR_DEVICENOTRESET) 
00758                 {
00759                         DeleteSurfaces();
00760                         if(FAILED(hr = CreateDevice()) || FAILED(hr = AllocSurfaces()))
00761                                 return(false);
00762                 }
00763 
00764                 hr = S_OK;
00765         }
00766 
00767         return(true);
00768 }
00769 
00770 STDMETHODIMP CDX9AllocatorPresenter::GetDIB(BYTE* lpDib, DWORD* size)
00771 {
00772         CheckPointer(size, E_POINTER);
00773 
00774         HRESULT hr;
00775 
00776         D3DSURFACE_DESC desc;
00777         memset(&desc, 0, sizeof(desc));
00778         m_pVideoSurface[0]->GetDesc(&desc);
00779 
00780         DWORD required = sizeof(BITMAPINFOHEADER) + (desc.Width * desc.Height * 32 >> 3);
00781         if(!lpDib) {*size = required; return S_OK;}
00782         if(*size < required) return E_OUTOFMEMORY;
00783         *size = required;
00784 
00785         CComPtr<IDirect3DSurface9> pSurface = m_pVideoSurface[0];
00786         D3DLOCKED_RECT r;
00787         if(FAILED(hr = pSurface->LockRect(&r, NULL, D3DLOCK_READONLY)))
00788         {
00789                 pSurface = NULL;
00790                 if(FAILED(hr = m_pD3DDev->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &pSurface, NULL))
00791                 || FAILED(hr = m_pD3DDev->GetRenderTargetData(m_pVideoSurface[0], pSurface))
00792                 || FAILED(hr = pSurface->LockRect(&r, NULL, D3DLOCK_READONLY)))
00793                         return hr;
00794         }
00795 
00796         BITMAPINFOHEADER* bih = (BITMAPINFOHEADER*)lpDib;
00797         memset(bih, 0, sizeof(BITMAPINFOHEADER));
00798         bih->biSize = sizeof(BITMAPINFOHEADER);
00799         bih->biWidth = desc.Width;
00800         bih->biHeight = desc.Height;
00801         bih->biBitCount = 32;
00802         bih->biPlanes = 1;
00803         bih->biSizeImage = bih->biWidth * bih->biHeight * bih->biBitCount >> 3;
00804 
00805         BitBltFromRGBToRGB(
00806                 bih->biWidth, bih->biHeight, 
00807                 (BYTE*)(bih + 1), bih->biWidth*bih->biBitCount>>3, bih->biBitCount,
00808                 (BYTE*)r.pBits + r.Pitch*(desc.Height-1), -(int)r.Pitch, 32);
00809 
00810         pSurface->UnlockRect();
00811 
00812         return S_OK;
00813 }
00814 
00815 STDMETHODIMP CDX9AllocatorPresenter::SetPixelShader(LPCSTR pSrcData, LPCSTR pTarget)
00816 {
00817         CAutoLock cAutoLock(this);
00818 
00819         m_pPixelShader = NULL;
00820         m_pD3DDev->SetPixelShader(NULL);
00821 
00822         if(!pSrcData || !pTarget)
00823                 return E_INVALIDARG;
00824 
00825         HRESULT hr = m_pPSC->CompileShader(pSrcData, "main", pTarget, 0, &m_pPixelShader);
00826         if(FAILED(hr)) return hr;
00827 
00828         Paint(true);
00829 
00830         return S_OK;
00831 }
00832 
00833 //
00834 // CVMR9AllocatorPresenter
00835 //
00836 
00837 #define MY_USER_ID 0x6ABE51
00838 
00839 CVMR9AllocatorPresenter::CVMR9AllocatorPresenter(HWND hWnd, HRESULT& hr) 
00840         : CDX9AllocatorPresenter(hWnd, hr)
00841         , m_fUseInternalTimer(true)
00842 {
00843 }
00844 
00845 STDMETHODIMP CVMR9AllocatorPresenter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
00846 {
00847     CheckPointer(ppv, E_POINTER);
00848 
00849         return 
00850                 QI(IVMRSurfaceAllocator9)
00851                 QI(IVMRImagePresenter9)
00852                 QI(IVMRWindowlessControl9)
00853                 __super::NonDelegatingQueryInterface(riid, ppv);
00854 }
00855 
00856 HRESULT CVMR9AllocatorPresenter::CreateDevice()
00857 {
00858         HRESULT hr = __super::CreateDevice();
00859         if(FAILED(hr)) return hr;
00860 
00861         if(m_pIVMRSurfAllocNotify)
00862         {
00863                 HMONITOR hMonitor = m_pD3D->GetAdapterMonitor(GetAdapter(m_pD3D));
00864                 if(FAILED(hr = m_pIVMRSurfAllocNotify->ChangeD3DDevice(m_pD3DDev, hMonitor)))
00865                         return(false);
00866         }
00867 
00868         return hr;
00869 }
00870 
00871 void CVMR9AllocatorPresenter::DeleteSurfaces()
00872 {
00873     CAutoLock cAutoLock(this);
00874 
00875         m_pSurfaces.RemoveAll();
00876 
00877         return __super::DeleteSurfaces();
00878 }
00879 
00880 // ISubPicAllocatorPresenter
00881 
00882 class COuterVMR9
00883         : public CUnknown
00884         , public IVideoWindow
00885         , public IBasicVideo2
00886         , public IVMRWindowlessControl
00887 {
00888         CComPtr<IUnknown> m_pVMR;
00889 
00890 public:
00891 
00892         COuterVMR9(const TCHAR* pName, LPUNKNOWN pUnk) : CUnknown(pName, pUnk)
00893         {
00894                 m_pVMR.CoCreateInstance(CLSID_VideoMixingRenderer9, GetOwner());
00895         }
00896 
00897         DECLARE_IUNKNOWN;
00898         STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv)
00899         {
00900                 HRESULT hr = m_pVMR ? m_pVMR->QueryInterface(riid, ppv) : E_NOINTERFACE;
00901 
00902                 if(m_pVMR && FAILED(hr))
00903                 {
00904                         if(riid == __uuidof(IVideoWindow))
00905                                 return GetInterface((IVideoWindow*)this, ppv);
00906                         if(riid == __uuidof(IBasicVideo))
00907                                 return GetInterface((IBasicVideo*)this, ppv);
00908                         if(riid == __uuidof(IBasicVideo2))
00909                                 return GetInterface((IBasicVideo2*)this, ppv);
00910 /*                      if(riid == __uuidof(IVMRWindowlessControl))
00911                                 return GetInterface((IVMRWindowlessControl*)this, ppv);
00912 */              }
00913 
00914                 return SUCCEEDED(hr) ? hr : __super::NonDelegatingQueryInterface(riid, ppv);
00915         }
00916 
00917         // IVMRWindowlessControl
00918 
00919         STDMETHODIMP GetNativeVideoSize(LONG* lpWidth, LONG* lpHeight, LONG* lpARWidth, LONG* lpARHeight)
00920         {
00921                 if(CComQIPtr<IVMRWindowlessControl9> pWC9 = m_pVMR)
00922                 {
00923                         return pWC9->GetNativeVideoSize(lpWidth, lpHeight, lpARWidth, lpARHeight);
00924                 }
00925 
00926                 return E_NOTIMPL;
00927         }
00928         STDMETHODIMP GetMinIdealVideoSize(LONG* lpWidth, LONG* lpHeight) {return E_NOTIMPL;}
00929         STDMETHODIMP GetMaxIdealVideoSize(LONG* lpWidth, LONG* lpHeight) {return E_NOTIMPL;}
00930         STDMETHODIMP SetVideoPosition(const LPRECT lpSRCRect, const LPRECT lpDSTRect) {return E_NOTIMPL;}
00931     STDMETHODIMP GetVideoPosition(LPRECT lpSRCRect, LPRECT lpDSTRect)
00932         {
00933                 if(CComQIPtr<IVMRWindowlessControl9> pWC9 = m_pVMR)
00934                 {
00935                         return pWC9->GetVideoPosition(lpSRCRect, lpDSTRect);
00936                 }
00937 
00938                 return E_NOTIMPL;
00939         }
00940         STDMETHODIMP GetAspectRatioMode(DWORD* lpAspectRatioMode)
00941         {
00942                 if(CComQIPtr<IVMRWindowlessControl9> pWC9 = m_pVMR)
00943                 {
00944                         *lpAspectRatioMode = VMR_ARMODE_NONE;
00945                         return S_OK;
00946                 }
00947 
00948                 return E_NOTIMPL;
00949         }
00950         STDMETHODIMP SetAspectRatioMode(DWORD AspectRatioMode) {return E_NOTIMPL;}
00951         STDMETHODIMP SetVideoClippingWindow(HWND hwnd) {return E_NOTIMPL;}
00952         STDMETHODIMP RepaintVideo(HWND hwnd, HDC hdc) {return E_NOTIMPL;}
00953         STDMETHODIMP DisplayModeChanged() {return E_NOTIMPL;}
00954         STDMETHODIMP GetCurrentImage(BYTE** lpDib) {return E_NOTIMPL;}
00955         STDMETHODIMP SetBorderColor(COLORREF Clr) {return E_NOTIMPL;}
00956         STDMETHODIMP GetBorderColor(COLORREF* lpClr) {return E_NOTIMPL;}
00957         STDMETHODIMP SetColorKey(COLORREF Clr) {return E_NOTIMPL;}
00958         STDMETHODIMP GetColorKey(COLORREF* lpClr) {return E_NOTIMPL;}
00959 
00960         // IVideoWindow
00961         STDMETHODIMP GetTypeInfoCount(UINT* pctinfo) {return E_NOTIMPL;}
00962         STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) {return E_NOTIMPL;}
00963         STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) {return E_NOTIMPL;}
00964         STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) {return E_NOTIMPL;}
00965     STDMETHODIMP put_Caption(BSTR strCaption) {return E_NOTIMPL;}
00966     STDMETHODIMP get_Caption(BSTR* strCaption) {return E_NOTIMPL;}
00967         STDMETHODIMP put_WindowStyle(long WindowStyle) {return E_NOTIMPL;}
00968         STDMETHODIMP get_WindowStyle(long* WindowStyle) {return E_NOTIMPL;}
00969         STDMETHODIMP put_WindowStyleEx(long WindowStyleEx) {return E_NOTIMPL;}
00970         STDMETHODIMP get_WindowStyleEx(long* WindowStyleEx) {return E_NOTIMPL;}
00971         STDMETHODIMP put_AutoShow(long AutoShow) {return E_NOTIMPL;}
00972         STDMETHODIMP get_AutoShow(long* AutoShow) {return E_NOTIMPL;}
00973         STDMETHODIMP put_WindowState(long WindowState) {return E_NOTIMPL;}
00974         STDMETHODIMP get_WindowState(long* WindowState) {return E_NOTIMPL;}
00975         STDMETHODIMP put_BackgroundPalette(long BackgroundPalette) {return E_NOTIMPL;}
00976         STDMETHODIMP get_BackgroundPalette(long* pBackgroundPalette) {return E_NOTIMPL;}
00977         STDMETHODIMP put_Visible(long Visible) {return E_NOTIMPL;}
00978         STDMETHODIMP get_Visible(long* pVisible) {return E_NOTIMPL;}
00979         STDMETHODIMP put_Left(long Left) {return E_NOTIMPL;}
00980         STDMETHODIMP get_Left(long* pLeft) {return E_NOTIMPL;}
00981         STDMETHODIMP put_Width(long Width) {return E_NOTIMPL;}
00982         STDMETHODIMP get_Width(long* pWidth)
00983         {
00984                 if(CComQIPtr<IVMRWindowlessControl9> pWC9 = m_pVMR)
00985                 {
00986                         CRect s, d;
00987                         HRESULT hr = pWC9->GetVideoPosition(&s, &d);
00988                         *pWidth = d.Width();
00989                         return hr;
00990                 }
00991 
00992                 return E_NOTIMPL;
00993         }
00994         STDMETHODIMP put_Top(long Top) {return E_NOTIMPL;}
00995         STDMETHODIMP get_Top(long* pTop) {return E_NOTIMPL;}
00996         STDMETHODIMP put_Height(long Height) {return E_NOTIMPL;}
00997         STDMETHODIMP get_Height(long* pHeight)
00998         {
00999                 if(CComQIPtr<IVMRWindowlessControl9> pWC9 = m_pVMR)
01000                 {
01001                         CRect s, d;
01002                         HRESULT hr = pWC9->GetVideoPosition(&s, &d);
01003                         *pHeight = d.Height();
01004                         return hr;
01005                 }
01006 
01007                 return E_NOTIMPL;
01008         }
01009         STDMETHODIMP put_Owner(OAHWND Owner) {return E_NOTIMPL;}
01010         STDMETHODIMP get_Owner(OAHWND* Owner) {return E_NOTIMPL;}
01011         STDMETHODIMP put_MessageDrain(OAHWND Drain) {return E_NOTIMPL;}
01012         STDMETHODIMP get_MessageDrain(OAHWND* Drain) {return E_NOTIMPL;}
01013         STDMETHODIMP get_BorderColor(long* Color) {return E_NOTIMPL;}
01014         STDMETHODIMP put_BorderColor(long Color) {return E_NOTIMPL;}
01015         STDMETHODIMP get_FullScreenMode(long* FullScreenMode) {return E_NOTIMPL;}
01016         STDMETHODIMP put_FullScreenMode(long FullScreenMode) {return E_NOTIMPL;}
01017     STDMETHODIMP SetWindowForeground(long Focus) {return E_NOTIMPL;}
01018     STDMETHODIMP NotifyOwnerMessage(OAHWND hwnd, long uMsg, LONG_PTR wParam, LONG_PTR lParam) {return E_NOTIMPL;}
01019     STDMETHODIMP SetWindowPosition(long Left, long Top, long Width, long Height) {return E_NOTIMPL;}
01020         STDMETHODIMP GetWindowPosition(long* pLeft, long* pTop, long* pWidth, long* pHeight) {return E_NOTIMPL;}
01021         STDMETHODIMP GetMinIdealImageSize(long* pWidth, long* pHeight) {return E_NOTIMPL;}
01022         STDMETHODIMP GetMaxIdealImageSize(long* pWidth, long* pHeight) {return E_NOTIMPL;}
01023         STDMETHODIMP GetRestorePosition(long* pLeft, long* pTop, long* pWidth, long* pHeight) {return E_NOTIMPL;}
01024         STDMETHODIMP HideCursor(long HideCursor) {return E_NOTIMPL;}
01025         STDMETHODIMP IsCursorHidden(long* CursorHidden) {return E_NOTIMPL;}
01026 
01027         // IBasicVideo2
01028     STDMETHODIMP get_AvgTimePerFrame(REFTIME* pAvgTimePerFrame) {return E_NOTIMPL;}
01029     STDMETHODIMP get_BitRate(long* pBitRate) {return E_NOTIMPL;}
01030     STDMETHODIMP get_BitErrorRate(long* pBitErrorRate) {return E_NOTIMPL;}
01031     STDMETHODIMP get_VideoWidth(long* pVideoWidth) {return E_NOTIMPL;}
01032     STDMETHODIMP get_VideoHeight(long* pVideoHeight) {return E_NOTIMPL;}
01033     STDMETHODIMP put_SourceLeft(long SourceLeft) {return E_NOTIMPL;}
01034     STDMETHODIMP get_SourceLeft(long* pSourceLeft) {return E_NOTIMPL;}
01035     STDMETHODIMP put_SourceWidth(long SourceWidth) {return E_NOTIMPL;}
01036     STDMETHODIMP get_SourceWidth(long* pSourceWidth) {return E_NOTIMPL;}
01037     STDMETHODIMP put_SourceTop(long SourceTop) {return E_NOTIMPL;}
01038     STDMETHODIMP get_SourceTop(long* pSourceTop) {return E_NOTIMPL;}
01039     STDMETHODIMP put_SourceHeight(long SourceHeight) {return E_NOTIMPL;}
01040     STDMETHODIMP get_SourceHeight(long* pSourceHeight) {return E_NOTIMPL;}
01041     STDMETHODIMP put_DestinationLeft(long DestinationLeft) {return E_NOTIMPL;}
01042     STDMETHODIMP get_DestinationLeft(long* pDestinationLeft) {return E_NOTIMPL;}
01043     STDMETHODIMP put_DestinationWidth(long DestinationWidth) {return E_NOTIMPL;}
01044     STDMETHODIMP get_DestinationWidth(long* pDestinationWidth) {return E_NOTIMPL;}
01045     STDMETHODIMP put_DestinationTop(long DestinationTop) {return E_NOTIMPL;}
01046     STDMETHODIMP get_DestinationTop(long* pDestinationTop) {return E_NOTIMPL;}
01047     STDMETHODIMP put_DestinationHeight(long DestinationHeight) {return E_NOTIMPL;}
01048     STDMETHODIMP get_DestinationHeight(long* pDestinationHeight) {return E_NOTIMPL;}
01049     STDMETHODIMP SetSourcePosition(long Left, long Top, long Width, long Height) {return E_NOTIMPL;}
01050     STDMETHODIMP GetSourcePosition(long* pLeft, long* pTop, long* pWidth, long* pHeight)
01051         {
01052                 // DVD Nav. bug workaround fix
01053                 {
01054                         *pLeft = *pTop = 0;
01055                         return GetVideoSize(pWidth, pHeight);
01056                 }
01057 /*
01058                 if(CComQIPtr<IVMRWindowlessControl9> pWC9 = m_pVMR)
01059                 {
01060                         CRect s, d;
01061                         HRESULT hr = pWC9->GetVideoPosition(&s, &d);
01062                         *pLeft = s.left;
01063                         *pTop = s.top;
01064                         *pWidth = s.Width();
01065                         *pHeight = s.Height();
01066                         return hr;
01067                 }
01068 */
01069                 return E_NOTIMPL;
01070         }
01071     STDMETHODIMP SetDefaultSourcePosition() {return E_NOTIMPL;}
01072     STDMETHODIMP SetDestinationPosition(long Left, long Top, long Width, long Height) {return E_NOTIMPL;}
01073     STDMETHODIMP GetDestinationPosition(long* pLeft, long* pTop, long* pWidth, long* pHeight)
01074         {
01075                 if(CComQIPtr<IVMRWindowlessControl9> pWC9 = m_pVMR)
01076                 {
01077                         CRect s, d;
01078                         HRESULT hr = pWC9->GetVideoPosition(&s, &d);
01079                         *pLeft = d.left;
01080                         *pTop = d.top;
01081                         *pWidth = d.Width();
01082                         *pHeight = d.Height();
01083                         return hr;
01084                 }
01085 
01086                 return E_NOTIMPL;
01087         }
01088     STDMETHODIMP SetDefaultDestinationPosition() {return E_NOTIMPL;}
01089     STDMETHODIMP GetVideoSize(long* pWidth, long* pHeight)
01090         {
01091                 if(CComQIPtr<IVMRWindowlessControl9> pWC9 = m_pVMR)
01092                 {
01093                         LONG aw, ah;
01094 //                      return pWC9->GetNativeVideoSize(pWidth, pHeight, &aw, &ah);
01095                         // DVD Nav. bug workaround fix
01096                         HRESULT hr = pWC9->GetNativeVideoSize(pWidth, pHeight, &aw, &ah);
01097                         *pWidth = *pHeight * aw / ah;
01098                         return hr;
01099                 }
01100 
01101                 return E_NOTIMPL;
01102         }
01103     STDMETHODIMP GetVideoPaletteEntries(long StartIndex, long Entries, long* pRetrieved, long* pPalette) {return E_NOTIMPL;}
01104     STDMETHODIMP GetCurrentImage(long* pBufferSize, long* pDIBImage) {return E_NOTIMPL;}
01105     STDMETHODIMP IsUsingDefaultSource() {return E_NOTIMPL;}
01106     STDMETHODIMP IsUsingDefaultDestination() {return E_NOTIMPL;}
01107 
01108         STDMETHODIMP GetPreferredAspectRatio(long* plAspectX, long* plAspectY)
01109         {
01110                 if(CComQIPtr<IVMRWindowlessControl9> pWC9 = m_pVMR)
01111                 {
01112                         LONG w, h;
01113                         return pWC9->GetNativeVideoSize(&w, &h, plAspectX, plAspectY);
01114                 }
01115 
01116                 return E_NOTIMPL;
01117         }
01118 };
01119 
01120 STDMETHODIMP CVMR9AllocatorPresenter::CreateRenderer(IUnknown** ppRenderer)
01121 {
01122     CheckPointer(ppRenderer, E_POINTER);
01123 
01124         *ppRenderer = NULL;
01125 
01126         HRESULT hr;
01127 
01128         do
01129         {
01130                 CMacrovisionKicker* pMK = new CMacrovisionKicker(NAME("CMacrovisionKicker"), NULL);
01131                 CComPtr<IUnknown> pUnk = (IUnknown*)(INonDelegatingUnknown*)pMK;
01132                 pMK->SetInner((IUnknown*)(INonDelegatingUnknown*)new COuterVMR9(NAME("COuterVMR9"), pUnk));
01133                 CComQIPtr<IBaseFilter> pBF = pUnk;
01134 /*
01135                 CComQIPtr<IBaseFilter> pBF = (IUnknown*)(INonDelegatingUnknown*)new COuterVMR9(NAME("COuterVMR9"), NULL);
01136                 if(!pBF) pBF.CoCreateInstance(CLSID_VideoMixingRenderer9);
01137 */
01138 
01139                 CComQIPtr<IVMRFilterConfig9> pConfig = pBF;
01140                 if(!pConfig)
01141                         break;
01142 
01143                 if(FAILED(hr = pConfig->SetRenderingMode(VMR9Mode_Renderless)))
01144                         break;
01145 
01146                 CComQIPtr<IVMRSurfaceAllocatorNotify9> pSAN = pBF;
01147                 if(!pSAN)
01148                         break;
01149 
01150                 if(FAILED(hr = pSAN->AdviseSurfaceAllocator(MY_USER_ID, static_cast<IVMRSurfaceAllocator9*>(this)))
01151                 || FAILED(hr = AdviseNotify(pSAN)))
01152                         break;
01153 
01154                 CComPtr<IPin> pPin = GetFirstPin(pBF);
01155                 HookNewSegment((IPinC*)(IPin*)pPin);
01156 
01157                 *ppRenderer = (IUnknown*)pBF.Detach();
01158 
01159                 return S_OK;
01160         }
01161         while(0);
01162 
01163     return E_FAIL;
01164 }
01165 
01166 STDMETHODIMP_(void) CVMR9AllocatorPresenter::SetTime(REFERENCE_TIME rtNow)
01167 {
01168         m_fUseInternalTimer = false;
01169         __super::SetTime(rtNow);
01170 }
01171 
01172 // IVMRSurfaceAllocator9
01173 
01174 STDMETHODIMP CVMR9AllocatorPresenter::InitializeDevice(DWORD_PTR dwUserID, VMR9AllocationInfo* lpAllocInfo, DWORD* lpNumBuffers)
01175 {
01176         if(!lpAllocInfo || !lpNumBuffers)
01177                 return E_POINTER;
01178 
01179         if(!m_pIVMRSurfAllocNotify)
01180                 return E_FAIL;
01181 
01182         // StretchRect's yv12 -> rgb conversion looks horribly bright compared to the result of yuy2 -> rgb
01183         if(lpAllocInfo->Format == '21VY' || lpAllocInfo->Format == '024Y')
01184                 return E_FAIL;
01185 
01186         DeleteSurfaces();
01187         m_pSurfaces.SetCount(*lpNumBuffers);
01188 
01189     HRESULT hr;
01190 
01191         hr = m_pIVMRSurfAllocNotify->AllocateSurfaceHelper(lpAllocInfo, lpNumBuffers, &m_pSurfaces[0]);
01192         if(FAILED(hr))
01193                 return hr;
01194 
01195         m_NativeVideoSize = CSize(lpAllocInfo->dwWidth, abs((int)lpAllocInfo->dwHeight));
01196         m_AspectRatio = m_NativeVideoSize;
01197         int arx = lpAllocInfo->szAspectRatio.cx, ary = lpAllocInfo->szAspectRatio.cy;
01198         if(arx > 0 && ary > 0) m_AspectRatio.SetSize(arx, ary);
01199 
01200         if(FAILED(hr = AllocSurfaces()))
01201                 return hr;
01202 
01203         // test if the colorspace is acceptable
01204         if(FAILED(hr = m_pD3DDev->StretchRect(m_pSurfaces[0], NULL, m_pVideoSurface[0], NULL, D3DTEXF_NONE)))
01205         {
01206                 DeleteSurfaces();
01207                 return E_FAIL;
01208         }
01209 
01210         hr = m_pD3DDev->ColorFill(m_pVideoSurface[0], NULL, 0);
01211 
01212         return hr;
01213 }
01214 
01215 STDMETHODIMP CVMR9AllocatorPresenter::TerminateDevice(DWORD_PTR dwUserID)
01216 {
01217     DeleteSurfaces();
01218     return S_OK;
01219 }
01220 
01221 STDMETHODIMP CVMR9AllocatorPresenter::GetSurface(DWORD_PTR dwUserID, DWORD SurfaceIndex, DWORD SurfaceFlags, IDirect3DSurface9** lplpSurface)
01222 {
01223     if(!lplpSurface)
01224                 return E_POINTER;
01225 
01226         if(SurfaceIndex >= m_pSurfaces.GetCount()) 
01227         return E_FAIL;
01228 
01229     CAutoLock cAutoLock(this);
01230 
01231         (*lplpSurface = m_pSurfaces[SurfaceIndex])->AddRef();
01232 
01233         return S_OK;
01234 }
01235 
01236 STDMETHODIMP CVMR9AllocatorPresenter::AdviseNotify(IVMRSurfaceAllocatorNotify9* lpIVMRSurfAllocNotify)
01237 {
01238     CAutoLock cAutoLock(this);
01239         
01240         m_pIVMRSurfAllocNotify = lpIVMRSurfAllocNotify;
01241 
01242         HRESULT hr;
01243     HMONITOR hMonitor = m_pD3D->GetAdapterMonitor(GetAdapter(m_pD3D));
01244     if(FAILED(hr = m_pIVMRSurfAllocNotify->SetD3DDevice(m_pD3DDev, hMonitor)))
01245                 return hr;
01246 
01247     return S_OK;
01248 }
01249 
01250 // IVMRImagePresenter9
01251 
01252 STDMETHODIMP CVMR9AllocatorPresenter::StartPresenting(DWORD_PTR dwUserID)
01253 {
01254     CAutoLock cAutoLock(this);
01255 
01256     ASSERT(m_pD3DDev);
01257 
01258         return m_pD3DDev ? S_OK : E_FAIL;
01259 }
01260 
01261 STDMETHODIMP CVMR9AllocatorPresenter::StopPresenting(DWORD_PTR dwUserID)
01262 {
01263         return S_OK;
01264 }
01265 
01266 STDMETHODIMP CVMR9AllocatorPresenter::PresentImage(DWORD_PTR dwUserID, VMR9PresentationInfo* lpPresInfo)
01267 {
01268     HRESULT hr;
01269 
01270         {
01271                 if(!m_pIVMRSurfAllocNotify)
01272                         return E_FAIL;
01273 
01274                 D3DDEVICE_CREATION_PARAMETERS Parameters;
01275                 if(FAILED(m_pD3DDev->GetCreationParameters(&Parameters)))
01276                 {
01277                         ASSERT(0);
01278                         return E_FAIL;
01279                 }
01280 
01281                 HMONITOR hCurMonitor = m_pD3D->GetAdapterMonitor(Parameters.AdapterOrdinal);
01282                 HMONITOR hMonitor = m_pD3D->GetAdapterMonitor(GetAdapter(m_pD3D));
01283 
01284                 if(hMonitor != hCurMonitor)
01285                 {
01286                         ASSERT(0);
01287                 }
01288         }
01289 
01290 /*
01291     // if we are in the middle of the display change
01292     if(NeedToHandleDisplayChange())
01293     {
01294         // NOTE: this piece of code is left as a user exercise.  
01295         // The D3DDevice here needs to be switched
01296         // to the device that is using another adapter
01297     }
01298 */
01299         {
01300                 if(!lpPresInfo || !lpPresInfo->lpSurf)
01301                         return E_POINTER;
01302 
01303                 CAutoLock cAutoLock(this);
01304 
01305                 hr = m_pD3DDev->StretchRect(lpPresInfo->lpSurf, NULL, m_pVideoSurface[0], NULL, D3DTEXF_NONE);
01306 
01307                 if(lpPresInfo->rtEnd > lpPresInfo->rtStart)
01308                 {
01309                         REFERENCE_TIME rtTimePerFrame = lpPresInfo->rtEnd - lpPresInfo->rtStart;
01310                         m_fps = 10000000.0 / rtTimePerFrame;
01311 
01312                         if(m_pSubPicQueue)
01313                         {
01314                                 m_pSubPicQueue->SetFPS(m_fps);
01315                                 if(m_fUseInternalTimer) __super::SetTime(g_tSegmentStart + lpPresInfo->rtStart);
01316                         }
01317                 }
01318 
01319                 CSize VideoSize = m_NativeVideoSize;
01320                 int arx = lpPresInfo->szAspectRatio.cx, ary = lpPresInfo->szAspectRatio.cy;
01321                 if(arx > 0 && ary > 0) VideoSize.cx = VideoSize.cy*arx/ary;
01322                 if(VideoSize != GetVideoSize())
01323                 {
01324                         m_AspectRatio.SetSize(arx, ary);
01325                         AfxGetApp()->m_pMainWnd->PostMessage(WM_REARRANGERENDERLESS);
01326                 }
01327 
01328                 Paint(true);
01329 
01330                 hr = S_OK;
01331         }
01332 
01333     return hr;
01334 }
01335 
01336 // IVMRWindowlessControl9
01337 //
01338 // It is only implemented (partially) for the dvd navigator's 
01339 // menu handling, which needs to know a few things about the 
01340 // location of our window.
01341 
01342 STDMETHODIMP CVMR9AllocatorPresenter::GetNativeVideoSize(LONG* lpWidth, LONG* lpHeight, LONG* lpARWidth, LONG* lpARHeight)
01343 {
01344         if(lpWidth) *lpWidth = m_NativeVideoSize.cx;
01345         if(lpHeight) *lpHeight = m_NativeVideoSize.cy;
01346         if(lpARWidth) *lpARWidth = m_AspectRatio.cx;
01347         if(lpARHeight) *lpARHeight = m_AspectRatio.cy;
01348         return S_OK;
01349 }
01350 STDMETHODIMP CVMR9AllocatorPresenter::GetMinIdealVideoSize(LONG* lpWidth, LONG* lpHeight) {return E_NOTIMPL;}
01351 STDMETHODIMP CVMR9AllocatorPresenter::GetMaxIdealVideoSize(LONG* lpWidth, LONG* lpHeight) {return E_NOTIMPL;}
01352 STDMETHODIMP CVMR9AllocatorPresenter::SetVideoPosition(const LPRECT lpSRCRect, const LPRECT lpDSTRect) {return E_NOTIMPL;} // we have our own method for this
01353 STDMETHODIMP CVMR9AllocatorPresenter::GetVideoPosition(LPRECT lpSRCRect, LPRECT lpDSTRect)
01354 {
01355         CopyRect(lpSRCRect, CRect(CPoint(0, 0), m_NativeVideoSize));
01356         CopyRect(lpDSTRect, &m_VideoRect);
01357         return S_OK;
01358 }
01359 STDMETHODIMP CVMR9AllocatorPresenter::GetAspectRatioMode(DWORD* lpAspectRatioMode)
01360 {
01361         if(lpAspectRatioMode) *lpAspectRatioMode = AM_ARMODE_STRETCHED;
01362         return S_OK;
01363 }
01364 STDMETHODIMP CVMR9AllocatorPresenter::SetAspectRatioMode(DWORD AspectRatioMode) {return E_NOTIMPL;}
01365 STDMETHODIMP CVMR9AllocatorPresenter::SetVideoClippingWindow(HWND hwnd) {return E_NOTIMPL;}
01366 STDMETHODIMP CVMR9AllocatorPresenter::RepaintVideo(HWND hwnd, HDC hdc) {return E_NOTIMPL;}
01367 STDMETHODIMP CVMR9AllocatorPresenter::DisplayModeChanged() {return E_NOTIMPL;}
01368 STDMETHODIMP CVMR9AllocatorPresenter::GetCurrentImage(BYTE** lpDib) {return E_NOTIMPL;}
01369 STDMETHODIMP CVMR9AllocatorPresenter::SetBorderColor(COLORREF Clr) {return E_NOTIMPL;}
01370 STDMETHODIMP CVMR9AllocatorPresenter::GetBorderColor(COLORREF* lpClr)
01371 {
01372         if(lpClr) *lpClr = 0;
01373         return S_OK;
01374 }
01375 
01376 //
01377 // CRM9AllocatorPresenter
01378 //
01379 
01380 CRM9AllocatorPresenter::CRM9AllocatorPresenter(HWND hWnd, HRESULT& hr) 
01381         : CDX9AllocatorPresenter(hWnd, hr)
01382 {
01383 }
01384 
01385 STDMETHODIMP CRM9AllocatorPresenter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
01386 {
01387     CheckPointer(ppv, E_POINTER);
01388 
01389         return 
01390                 QI2(IRMAVideoSurface)
01391                 __super::NonDelegatingQueryInterface(riid, ppv);
01392 }
01393 
01394 HRESULT CRM9AllocatorPresenter::AllocSurfaces()
01395 {
01396     CAutoLock cAutoLock(this);
01397 
01398         m_pVideoSurfaceOff = NULL;
01399         m_pVideoSurfaceYUY2 = NULL;
01400 
01401         HRESULT hr;
01402 
01403         if(FAILED(hr = m_pD3DDev->CreateOffscreenPlainSurface(
01404                 m_NativeVideoSize.cx, m_NativeVideoSize.cy, D3DFMT_X8R8G8B8, 
01405                 D3DPOOL_DEFAULT, &m_pVideoSurfaceOff, NULL)))
01406                 return hr;
01407 
01408         m_pD3DDev->ColorFill(m_pVideoSurfaceOff, NULL, 0);
01409 
01410         if(FAILED(hr = m_pD3DDev->CreateOffscreenPlainSurface(
01411                 m_NativeVideoSize.cx, m_NativeVideoSize.cy, D3DFMT_YUY2, 
01412                 D3DPOOL_DEFAULT, &m_pVideoSurfaceYUY2, NULL)))
01413                 m_pVideoSurfaceYUY2 = NULL;
01414 
01415         if(m_pVideoSurfaceYUY2)
01416         {
01417                 m_pD3DDev->ColorFill(m_pVideoSurfaceOff, NULL, 0x80108010);
01418         }
01419 
01420         return __super::AllocSurfaces();
01421 }
01422 
01423 void CRM9AllocatorPresenter::DeleteSurfaces()
01424 {
01425     CAutoLock cAutoLock(this);
01426         m_pVideoSurfaceOff = NULL;
01427         m_pVideoSurfaceYUY2 = NULL;
01428         __super::DeleteSurfaces();
01429 }
01430 
01431 // IRMAVideoSurface
01432 
01433 STDMETHODIMP CRM9AllocatorPresenter::Blt(UCHAR* pImageData, RMABitmapInfoHeader* pBitmapInfo, REF(PNxRect) inDestRect, REF(PNxRect) inSrcRect)
01434 {
01435         if(!m_pVideoSurface || !m_pVideoSurfaceOff)
01436                 return E_FAIL;
01437 
01438         bool fRGB = false;
01439         bool fYUY2 = false;
01440 
01441         CRect src((RECT*)&inSrcRect), dst((RECT*)&inDestRect), src2(CPoint(0,0), src.Size());
01442         if(src.Width() > dst.Width() || src.Height() > dst.Height())
01443                 return E_FAIL;
01444 
01445         D3DSURFACE_DESC d3dsd;
01446         ZeroMemory(&d3dsd, sizeof(d3dsd));
01447         if(FAILED(m_pVideoSurfaceOff->GetDesc(&d3dsd)))
01448                 return E_FAIL;
01449 
01450         int dbpp = 
01451                 d3dsd.Format == D3DFMT_R8G8B8 || d3dsd.Format == D3DFMT_X8R8G8B8 || d3dsd.Format == D3DFMT_A8R8G8B8 ? 32 : 
01452                 d3dsd.Format == D3DFMT_R5G6B5 ? 16 : 0;
01453 
01454         if(pBitmapInfo->biCompression == '024I')
01455         {
01456                 DWORD pitch = pBitmapInfo->biWidth;
01457                 DWORD size = pitch*abs(pBitmapInfo->biHeight);
01458 
01459                 BYTE* y = pImageData                                    + src.top*pitch + src.left;
01460                 BYTE* u = pImageData + size                             + src.top*(pitch/2) + src.left/2;
01461                 BYTE* v = pImageData + size + size/4    + src.top*(pitch/2) + src.left/2;
01462 
01463                 if(m_pVideoSurfaceYUY2)
01464                 {
01465                         D3DLOCKED_RECT r;
01466                         if(SUCCEEDED(m_pVideoSurfaceYUY2->LockRect(&r, src2, 0)))
01467                         {
01468                                 BitBltFromI420ToYUY2(src.Width(), src.Height(), (BYTE*)r.pBits, r.Pitch, y, u, v, pitch);
01469                                 m_pVideoSurfaceYUY2->UnlockRect();
01470                                 fYUY2 = true;
01471                         }
01472                 }
01473                 else
01474                 {
01475                         D3DLOCKED_RECT r;
01476                         if(SUCCEEDED(m_pVideoSurfaceOff->LockRect(&r, src2, 0)))
01477                         {
01478                                 BitBltFromI420ToRGB(src.Width(), src.Height(), (BYTE*)r.pBits, r.Pitch, dbpp, y, u, v, pitch);
01479                                 m_pVideoSurfaceOff->UnlockRect();
01480                                 fRGB = true;
01481                         }
01482                 }
01483         }
01484         else if(pBitmapInfo->biCompression == '2YUY')
01485         {
01486                 DWORD w = pBitmapInfo->biWidth;
01487                 DWORD h = abs(pBitmapInfo->biHeight);
01488                 DWORD pitch = pBitmapInfo->biWidth*2;
01489 
01490                 BYTE* yvyu = pImageData + src.top*pitch + src.left*2;
01491 
01492                 if(m_pVideoSurfaceYUY2)
01493                 {
01494                         D3DLOCKED_RECT r;
01495                         if(SUCCEEDED(m_pVideoSurfaceYUY2->LockRect(&r, src2, 0)))
01496                         {
01497                                 BitBltFromYUY2ToYUY2(src.Width(), src.Height(), (BYTE*)r.pBits, r.Pitch, yvyu, pitch);
01498                                 m_pVideoSurfaceYUY2->UnlockRect();
01499                                 fYUY2 = true;
01500                         }
01501                 }
01502                 else
01503                 {
01504                         D3DLOCKED_RECT r;
01505                         if(SUCCEEDED(m_pVideoSurfaceOff->LockRect(&r, src2, 0)))
01506                         {
01507                                 BitBltFromYUY2ToRGB(src.Width(), src.Height(), (BYTE*)r.pBits, r.Pitch, dbpp, yvyu, pitch);
01508                                 m_pVideoSurfaceOff->UnlockRect();
01509                                 fRGB = true;
01510                         }
01511                 }
01512         }
01513         else if(pBitmapInfo->biCompression == 0 || pBitmapInfo->biCompression == 3
01514                  || pBitmapInfo->biCompression == 'BGRA')
01515         {
01516                 DWORD w = pBitmapInfo->biWidth;
01517                 DWORD h = abs(pBitmapInfo->biHeight);
01518                 DWORD pitch = pBitmapInfo->biWidth*pBitmapInfo->biBitCount>>3;
01519 
01520                 BYTE* rgb = pImageData + src.top*pitch + src.left*(pBitmapInfo->biBitCount>>3);
01521 
01522                 D3DLOCKED_RECT r;
01523                 if(SUCCEEDED(m_pVideoSurfaceOff->LockRect(&r, src2, 0)))
01524                 {
01525                         BYTE* pBits = (BYTE*)r.pBits;
01526                         if(pBitmapInfo->biHeight > 0) {pBits += r.Pitch*(src.Height()-1); r.Pitch = -r.Pitch;}
01527                         BitBltFromRGBToRGB(src.Width(), src.Height(), pBits, r.Pitch, dbpp, rgb, pitch, pBitmapInfo->biBitCount);
01528                         m_pVideoSurfaceOff->UnlockRect();
01529                         fRGB = true;
01530                 }
01531         }
01532 
01533         if(!fRGB && !fYUY2)
01534         {
01535                 m_pD3DDev->ColorFill(m_pVideoSurfaceOff, NULL, 0);
01536 
01537                 HDC hDC;
01538                 if(SUCCEEDED(m_pVideoSurfaceOff->GetDC(&hDC)))
01539                 {
01540                         CString str;
01541                         str.Format(_T("Sorry, this format is not supported"));
01542 
01543                         SetBkColor(hDC, 0);
01544                         SetTextColor(hDC, 0x404040);
01545                         TextOut(hDC, 10, 10, str, str.GetLength());
01546 
01547                         m_pVideoSurfaceOff->ReleaseDC(hDC);
01548 
01549                         fRGB = true;
01550                 }
01551         }
01552 
01553         HRESULT hr;
01554         
01555         if(fRGB)
01556                 hr = m_pD3DDev->StretchRect(m_pVideoSurfaceOff, src2, m_pVideoSurface[0], dst, D3DTEXF_NONE);
01557         if(fYUY2)
01558                 hr = m_pD3DDev->StretchRect(m_pVideoSurfaceYUY2, src2, m_pVideoSurface[0], dst, D3DTEXF_NONE);
01559 
01560         Paint(true);
01561 
01562         return PNR_OK;
01563 }
01564 
01565 STDMETHODIMP CRM9AllocatorPresenter::BeginOptimizedBlt(RMABitmapInfoHeader* pBitmapInfo)
01566 {
01567     CAutoLock cAutoLock(this);
01568         DeleteSurfaces();
01569         m_NativeVideoSize = m_AspectRatio = CSize(pBitmapInfo->biWidth, abs(pBitmapInfo->biHeight));
01570         if(FAILED(AllocSurfaces())) return E_FAIL;
01571         return PNR_NOTIMPL;
01572 }
01573 
01574 STDMETHODIMP CRM9AllocatorPresenter::OptimizedBlt(UCHAR* pImageBits, REF(PNxRect) rDestRect, REF(PNxRect) rSrcRect)
01575 {
01576         return PNR_NOTIMPL;
01577 }
01578 
01579 STDMETHODIMP CRM9AllocatorPresenter::EndOptimizedBlt()
01580 {
01581         return PNR_NOTIMPL;
01582 }
01583 
01584 STDMETHODIMP CRM9AllocatorPresenter::GetOptimizedFormat(REF(RMA_COMPRESSION_TYPE) ulType)
01585 {
01586         return PNR_NOTIMPL;
01587 }
01588 
01589 STDMETHODIMP CRM9AllocatorPresenter::GetPreferredFormat(REF(RMA_COMPRESSION_TYPE) ulType)
01590 {
01591         ulType = RMA_I420;
01592         return PNR_OK;
01593 }
01594 
01595 //
01596 // CQT9AllocatorPresenter
01597 //
01598 
01599 CQT9AllocatorPresenter::CQT9AllocatorPresenter(HWND hWnd, HRESULT& hr) 
01600         : CDX9AllocatorPresenter(hWnd, hr)
01601 {
01602 }
01603 
01604 STDMETHODIMP CQT9AllocatorPresenter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
01605 {
01606     CheckPointer(ppv, E_POINTER);
01607 
01608         return 
01609                 QI(IQTVideoSurface)
01610                 __super::NonDelegatingQueryInterface(riid, ppv);
01611 }
01612 
01613 HRESULT CQT9AllocatorPresenter::AllocSurfaces()
01614 {
01615         HRESULT hr;
01616 
01617         m_pVideoSurfaceOff = NULL;
01618 
01619         if(FAILED(hr = m_pD3DDev->CreateOffscreenPlainSurface(
01620                 m_NativeVideoSize.cx, m_NativeVideoSize.cy, D3DFMT_X8R8G8B8, 
01621                 D3DPOOL_DEFAULT, &m_pVideoSurfaceOff, NULL)))
01622                 return hr;
01623 
01624         return __super::AllocSurfaces();
01625 }
01626 
01627 void CQT9AllocatorPresenter::DeleteSurfaces()
01628 {
01629         m_pVideoSurfaceOff = NULL;
01630 
01631         __super::DeleteSurfaces();
01632 }
01633 
01634 // IQTVideoSurface
01635 
01636 STDMETHODIMP CQT9AllocatorPresenter::BeginBlt(const BITMAP& bm)
01637 {
01638     CAutoLock cAutoLock(this);
01639         DeleteSurfaces();
01640         m_NativeVideoSize = m_AspectRatio = CSize(bm.bmWidth, abs(bm.bmHeight));
01641         if(FAILED(AllocSurfaces())) return E_FAIL;
01642         return S_OK;
01643 }
01644 
01645 STDMETHODIMP CQT9AllocatorPresenter::DoBlt(const BITMAP& bm)
01646 {
01647         if(!m_pVideoSurface || !m_pVideoSurfaceOff)
01648                 return E_FAIL;
01649 
01650         bool fOk = false;
01651 
01652         D3DSURFACE_DESC d3dsd;
01653         ZeroMemory(&d3dsd, sizeof(d3dsd));
01654         if(FAILED(m_pVideoSurfaceOff->GetDesc(&d3dsd)))
01655                 return E_FAIL;
01656 
01657         int w = bm.bmWidth;
01658         int h = abs(bm.bmHeight);
01659         int bpp = bm.bmBitsPixel;
01660         int dbpp = 
01661                 d3dsd.Format == D3DFMT_R8G8B8 || d3dsd.Format == D3DFMT_X8R8G8B8 || d3dsd.Format == D3DFMT_A8R8G8B8 ? 32 : 
01662                 d3dsd.Format == D3DFMT_R5G6B5 ? 16 : 0;
01663 
01664         if((bpp == 16 || bpp == 24 || bpp == 32) && w == d3dsd.Width && h == d3dsd.Height)
01665         {
01666                 D3DLOCKED_RECT r;
01667                 if(SUCCEEDED(m_pVideoSurfaceOff->LockRect(&r, NULL, 0)))
01668                 {
01669                         BitBltFromRGBToRGB(
01670                                 w, h,
01671                                 (BYTE*)r.pBits, r.Pitch, dbpp,
01672                                 (BYTE*)bm.bmBits, bm.bmWidthBytes, bm.bmBitsPixel);
01673                         m_pVideoSurfaceOff->UnlockRect();
01674                         fOk = true;
01675                 }
01676         }
01677 
01678         if(!fOk)
01679         {
01680                 m_pD3DDev->ColorFill(m_pVideoSurfaceOff, NULL, 0);
01681 
01682                 HDC hDC;
01683                 if(SUCCEEDED(m_pVideoSurfaceOff->GetDC(&hDC)))
01684                 {
01685                         CString str;
01686                         str.Format(_T("Sorry, this color format is not supported"));
01687 
01688                         SetBkColor(hDC, 0);
01689                         SetTextColor(hDC, 0x404040);
01690                         TextOut(hDC, 10, 10, str, str.GetLength());
01691 
01692                         m_pVideoSurfaceOff->ReleaseDC(hDC);
01693                 }
01694         }
01695 
01696         m_pD3DDev->StretchRect(m_pVideoSurfaceOff, NULL, m_pVideoSurface[0], NULL, D3DTEXF_NONE);
01697 
01698         Paint(true);
01699 
01700         return S_OK;
01701 }

Generated on Tue Dec 13 14:46:49 2005 for guliverkli by  doxygen 1.4.5