www.pudn.com > VCMPlayerClassic_Coder.rar > DX9AllocatorPresenter.cpp
/* * Copyright (C) 2003-2006 Gabest * http://www.gabest.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Make; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "stdafx.h" #include "mplayerc.h" #include#include #include "..\..\DSUtil\DSUtil.h" #include #include #include "DX9AllocatorPresenter.h" #include #include #include #include "..\..\SubPic\DX9SubPic.h" #include "..\..\..\include\RealMedia\pntypes.h" #include "..\..\..\include\RealMedia\pnwintyp.h" #include "..\..\..\include\RealMedia\pncom.h" #include "..\..\..\include\RealMedia\rmavsurf.h" #include "IQTVideoSurface.h" #include "..\..\..\include\moreuuids.h" #include "MacrovisionKicker.h" #include "IPinHook.h" #include "PixelShaderCompiler.h" bool IsVMR9InGraph(IFilterGraph* pFG) { BeginEnumFilters(pFG, pEF, pBF) if(CComQIPtr (pBF)) return(true); EndEnumFilters return(false); } namespace DSObjects { class CDX9AllocatorPresenter : public ISubPicAllocatorPresenterImpl { protected: CSize m_ScreenSize; bool m_fVMRSyncFix; CComPtr m_pD3D; CComPtr m_pD3DDev; CComPtr m_pVideoTexture[3]; CComPtr m_pVideoSurface[3]; CInterfaceList m_pPixelShaders; CComPtr m_pResizerPixelShader[3]; // bl, bc1, bc2 CComPtr m_pResizerBicubic1stPass; D3DTEXTUREFILTERTYPE m_filter; D3DCAPS9 m_caps; CAutoPtr m_pPSC; virtual HRESULT CreateDevice(); virtual HRESULT AllocSurfaces(); virtual void DeleteSurfaces(); UINT GetAdapter(IDirect3D9 *pD3D); float m_bicubicA; HRESULT InitResizers(float bicubicA); HRESULT TextureCopy(CComPtr pTexture); HRESULT TextureResize(CComPtr pTexture, Vector dst[4], D3DTEXTUREFILTERTYPE filter); HRESULT TextureResizeBilinear(CComPtr pTexture, Vector dst[4]); HRESULT TextureResizeBicubic1pass(CComPtr pTexture, Vector dst[4]); HRESULT TextureResizeBicubic2pass(CComPtr pTexture, Vector dst[4]); public: CDX9AllocatorPresenter(HWND hWnd, HRESULT& hr); // ISubPicAllocatorPresenter STDMETHODIMP CreateRenderer(IUnknown** ppRenderer); STDMETHODIMP_(bool) Paint(bool fAll); STDMETHODIMP GetDIB(BYTE* lpDib, DWORD* size); STDMETHODIMP SetPixelShader(LPCSTR pSrcData, LPCSTR pTarget); }; class CVMR9AllocatorPresenter : public CDX9AllocatorPresenter , public IVMRSurfaceAllocator9 , public IVMRImagePresenter9 , public IVMRWindowlessControl9 { protected: CComPtr m_pIVMRSurfAllocNotify; CInterfaceArray m_pSurfaces; HRESULT CreateDevice(); void DeleteSurfaces(); bool m_fUseInternalTimer; REFERENCE_TIME m_rtPrevStart; public: CVMR9AllocatorPresenter(HWND hWnd, HRESULT& hr); DECLARE_IUNKNOWN STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv); // ISubPicAllocatorPresenter STDMETHODIMP CreateRenderer(IUnknown** ppRenderer); STDMETHODIMP_(void) SetTime(REFERENCE_TIME rtNow); // IVMRSurfaceAllocator9 STDMETHODIMP InitializeDevice(DWORD_PTR dwUserID, VMR9AllocationInfo* lpAllocInfo, DWORD* lpNumBuffers); STDMETHODIMP TerminateDevice(DWORD_PTR dwID); STDMETHODIMP GetSurface(DWORD_PTR dwUserID, DWORD SurfaceIndex, DWORD SurfaceFlags, IDirect3DSurface9** lplpSurface); STDMETHODIMP AdviseNotify(IVMRSurfaceAllocatorNotify9* lpIVMRSurfAllocNotify); // IVMRImagePresenter9 STDMETHODIMP StartPresenting(DWORD_PTR dwUserID); STDMETHODIMP StopPresenting(DWORD_PTR dwUserID); STDMETHODIMP PresentImage(DWORD_PTR dwUserID, VMR9PresentationInfo* lpPresInfo); // IVMRWindowlessControl9 STDMETHODIMP GetNativeVideoSize(LONG* lpWidth, LONG* lpHeight, LONG* lpARWidth, LONG* lpARHeight); STDMETHODIMP GetMinIdealVideoSize(LONG* lpWidth, LONG* lpHeight); STDMETHODIMP GetMaxIdealVideoSize(LONG* lpWidth, LONG* lpHeight); STDMETHODIMP SetVideoPosition(const LPRECT lpSRCRect, const LPRECT lpDSTRect); STDMETHODIMP GetVideoPosition(LPRECT lpSRCRect, LPRECT lpDSTRect); STDMETHODIMP GetAspectRatioMode(DWORD* lpAspectRatioMode); STDMETHODIMP SetAspectRatioMode(DWORD AspectRatioMode); STDMETHODIMP SetVideoClippingWindow(HWND hwnd); STDMETHODIMP RepaintVideo(HWND hwnd, HDC hdc); STDMETHODIMP DisplayModeChanged(); STDMETHODIMP GetCurrentImage(BYTE** lpDib); STDMETHODIMP SetBorderColor(COLORREF Clr); STDMETHODIMP GetBorderColor(COLORREF* lpClr); }; class CRM9AllocatorPresenter : public CDX9AllocatorPresenter , public IRMAVideoSurface { CComPtr m_pVideoSurfaceOff; CComPtr m_pVideoSurfaceYUY2; RMABitmapInfoHeader m_bitmapInfo; RMABitmapInfoHeader m_lastBitmapInfo; protected: HRESULT AllocSurfaces(); void DeleteSurfaces(); public: CRM9AllocatorPresenter(HWND hWnd, HRESULT& hr); DECLARE_IUNKNOWN STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv); // IRMAVideoSurface STDMETHODIMP Blt(UCHAR* pImageData, RMABitmapInfoHeader* pBitmapInfo, REF(PNxRect) inDestRect, REF(PNxRect) inSrcRect); STDMETHODIMP BeginOptimizedBlt(RMABitmapInfoHeader* pBitmapInfo); STDMETHODIMP OptimizedBlt(UCHAR* pImageBits, REF(PNxRect) rDestRect, REF(PNxRect) rSrcRect); STDMETHODIMP EndOptimizedBlt(); STDMETHODIMP GetOptimizedFormat(REF(RMA_COMPRESSION_TYPE) ulType); STDMETHODIMP GetPreferredFormat(REF(RMA_COMPRESSION_TYPE) ulType); }; class CQT9AllocatorPresenter : public CDX9AllocatorPresenter , public IQTVideoSurface { CComPtr m_pVideoSurfaceOff; protected: HRESULT AllocSurfaces(); void DeleteSurfaces(); public: CQT9AllocatorPresenter(HWND hWnd, HRESULT& hr); DECLARE_IUNKNOWN STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv); // IQTVideoSurface STDMETHODIMP BeginBlt(const BITMAP& bm); STDMETHODIMP DoBlt(const BITMAP& bm); }; class CDXRAllocatorPresenter : public ISubPicAllocatorPresenterImpl { class CSubRenderCallback : public CUnknown, public ISubRenderCallback, public CCritSec { CDXRAllocatorPresenter* m_pDXRAP; public: CSubRenderCallback(CDXRAllocatorPresenter* pDXRAP) : CUnknown(_T("CSubRender"), NULL) , m_pDXRAP(pDXRAP) { } DECLARE_IUNKNOWN STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv) { return QI(ISubRenderCallback) __super::NonDelegatingQueryInterface(riid, ppv); } void SetDXRAP(CDXRAllocatorPresenter* pDXRAP) { CAutoLock cAutoLock(this); m_pDXRAP = pDXRAP; } // ISubRenderCallback STDMETHODIMP SetDevice(IDirect3DDevice9* pD3DDev) { CAutoLock cAutoLock(this); return m_pDXRAP ? m_pDXRAP->SetDevice(pD3DDev) : E_UNEXPECTED; } STDMETHODIMP Render(REFERENCE_TIME rtStart, int left, int top, int right, int bottom, int width, int height) { CAutoLock cAutoLock(this); return m_pDXRAP ? m_pDXRAP->Render(rtStart, 0, 0, left, top, right, bottom, width, height) : E_UNEXPECTED; } // ISubRendererCallback2 STDMETHODIMP RenderEx(REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, REFERENCE_TIME AvgTimePerFrame, int left, int top, int right, int bottom, int width, int height) { CAutoLock cAutoLock(this); return m_pDXRAP ? m_pDXRAP->Render(rtStart, rtStop, AvgTimePerFrame, left, top, right, bottom, width, height) : E_UNEXPECTED; } }; CComPtr m_pDXR; CComPtr m_pSRCB; public: CDXRAllocatorPresenter(HWND hWnd, HRESULT& hr); virtual ~CDXRAllocatorPresenter(); DECLARE_IUNKNOWN STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv); HRESULT SetDevice(IDirect3DDevice9* pD3DDev); HRESULT Render( REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, REFERENCE_TIME atpf, int left, int top, int bottom, int right, int width, int height); // ISubPicAllocatorPresenter STDMETHODIMP CreateRenderer(IUnknown** ppRenderer); STDMETHODIMP_(void) SetPosition(RECT w, RECT v); STDMETHODIMP_(SIZE) GetVideoSize(bool fCorrectAR); STDMETHODIMP_(bool) Paint(bool fAll); STDMETHODIMP GetDIB(BYTE* lpDib, DWORD* size); STDMETHODIMP SetPixelShader(LPCSTR pSrcData, LPCSTR pTarget); }; } using namespace DSObjects; // HRESULT CreateAP9(const CLSID& clsid, HWND hWnd, ISubPicAllocatorPresenter** ppAP) { CheckPointer(ppAP, E_POINTER); *ppAP = NULL; HRESULT hr = E_FAIL; if(clsid == CLSID_VMR9AllocatorPresenter && !(*ppAP = new CVMR9AllocatorPresenter(hWnd, hr)) || clsid == CLSID_RM9AllocatorPresenter && !(*ppAP = new CRM9AllocatorPresenter(hWnd, hr)) || clsid == CLSID_QT9AllocatorPresenter && !(*ppAP = new CQT9AllocatorPresenter(hWnd, hr)) || clsid == CLSID_DXRAllocatorPresenter && !(*ppAP = new CDXRAllocatorPresenter(hWnd, hr))) return E_OUTOFMEMORY; if(*ppAP == NULL) return E_FAIL; (*ppAP)->AddRef(); if(FAILED(hr)) { (*ppAP)->Release(); *ppAP = NULL; } return hr; } // #pragma pack(push, 1) template struct MYD3DVERTEX {float x, y, z, rhw; struct {float u, v;} t[texcoords];}; #pragma pack(pop) template static void AdjustQuad(MYD3DVERTEX * v, float dx, float dy) { float offset = 0.5f; for(int i = 0; i < 4; i++) { v[i].x -= offset; v[i].y -= offset; for(int j = 0; j < texcoords-1; j++) { v[i].t[j].u -= offset*dx; v[i].t[j].v -= offset*dy; } if(texcoords > 1) { v[i].t[texcoords-1].u -= offset; v[i].t[texcoords-1].v -= offset; } } } template static HRESULT TextureBlt(CComPtr pD3DDev, MYD3DVERTEX v[4], D3DTEXTUREFILTERTYPE filter = D3DTEXF_LINEAR) { if(!pD3DDev) return E_POINTER; DWORD FVF = 0; switch(texcoords) { case 1: FVF = D3DFVF_TEX1; break; case 2: FVF = D3DFVF_TEX2; break; case 3: FVF = D3DFVF_TEX3; break; case 4: FVF = D3DFVF_TEX4; break; case 5: FVF = D3DFVF_TEX5; break; case 6: FVF = D3DFVF_TEX6; break; case 7: FVF = D3DFVF_TEX7; break; case 8: FVF = D3DFVF_TEX8; break; default: return E_FAIL; } HRESULT hr; do { hr = pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); hr = pD3DDev->SetRenderState(D3DRS_LIGHTING, FALSE); hr = pD3DDev->SetRenderState(D3DRS_ZENABLE, FALSE); hr = pD3DDev->SetRenderState(D3DRS_STENCILENABLE, FALSE); hr = pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); hr = pD3DDev->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); hr = pD3DDev->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); hr = pD3DDev->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA|D3DCOLORWRITEENABLE_BLUE|D3DCOLORWRITEENABLE_GREEN|D3DCOLORWRITEENABLE_RED); for(int i = 0; i < texcoords; i++) { hr = pD3DDev->SetSamplerState(i, D3DSAMP_MAGFILTER, filter); hr = pD3DDev->SetSamplerState(i, D3DSAMP_MINFILTER, filter); hr = pD3DDev->SetSamplerState(i, D3DSAMP_MIPFILTER, filter); hr = pD3DDev->SetSamplerState(i, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); hr = pD3DDev->SetSamplerState(i, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); } // if(FAILED(hr = pD3DDev->BeginScene())) break; hr = pD3DDev->SetFVF(D3DFVF_XYZRHW | FVF); // hr = pD3DDev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v, sizeof(v[0])); MYD3DVERTEX tmp = v[2]; v[2] = v[3]; v[3] = tmp; hr = pD3DDev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, v, sizeof(v[0])); hr = pD3DDev->EndScene(); // for(int i = 0; i < texcoords; i++) { pD3DDev->SetTexture(i, NULL); } return S_OK; } while(0); return E_FAIL; } // CDX9AllocatorPresenter CDX9AllocatorPresenter::CDX9AllocatorPresenter(HWND hWnd, HRESULT& hr) : ISubPicAllocatorPresenterImpl(hWnd, hr) , m_ScreenSize(0, 0) , m_bicubicA(0) { if(FAILED(hr)) return; m_pD3D.Attach(Direct3DCreate9(D3D_SDK_VERSION)); if(!m_pD3D) m_pD3D.Attach(Direct3DCreate9(D3D9b_SDK_VERSION)); if(!m_pD3D) {hr = E_FAIL; return;} hr = CreateDevice(); } HRESULT CDX9AllocatorPresenter::CreateDevice() { m_pPSC.Free(); m_pD3DDev = NULL; D3DDISPLAYMODE d3dd