- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# 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 }