747 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			747 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //------------------------------------------------------------------------------
 | |
| // File: VideoCtl.cpp
 | |
| //
 | |
| // Desc: DirectShow base classes.
 | |
| //
 | |
| // Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
 | |
| //------------------------------------------------------------------------------
 | |
| 
 | |
| 
 | |
| #include <streams.h>
 | |
| #include "ddmm.h"
 | |
| 
 | |
| // Load a string from the resource file string table. The buffer must be at
 | |
| // least STR_MAX_LENGTH bytes. The easiest way to use this is to declare a
 | |
| // buffer in the property page class and use it for all string loading. It
 | |
| // cannot be static as multiple property pages may be active simultaneously
 | |
| 
 | |
| LPCTSTR WINAPI StringFromResource(__out_ecount(STR_MAX_LENGTH) LPTSTR pBuffer, int iResourceID)
 | |
| {
 | |
|     if (LoadString(g_hInst,iResourceID,pBuffer,STR_MAX_LENGTH) == 0) {
 | |
|         return TEXT("");
 | |
|     }
 | |
|     return pBuffer;
 | |
| }
 | |
| 
 | |
| #ifdef UNICODE
 | |
| LPCSTR WINAPI StringFromResource(__out_ecount(STR_MAX_LENGTH) LPSTR pBuffer, int iResourceID)
 | |
| {
 | |
|     if (LoadStringA(g_hInst,iResourceID,pBuffer,STR_MAX_LENGTH) == 0) {
 | |
|         return "";
 | |
|     }
 | |
|     return pBuffer;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| 
 | |
| 
 | |
| // Property pages typically are called through their OLE interfaces. These
 | |
| // use UNICODE strings regardless of how the binary is built. So when we
 | |
| // load strings from the resource file we sometimes want to convert them
 | |
| // to UNICODE. This method is passed the target UNICODE buffer and does a
 | |
| // convert after loading the string (if built UNICODE this is not needed)
 | |
| // On WinNT we can explicitly call LoadStringW which saves two conversions
 | |
| 
 | |
| #ifndef UNICODE
 | |
| 
 | |
| LPWSTR WINAPI WideStringFromResource(__out_ecount(STR_MAX_LENGTH) LPWSTR pBuffer, int iResourceID)
 | |
| {
 | |
|     *pBuffer = 0;
 | |
| 
 | |
|     if (g_amPlatform == VER_PLATFORM_WIN32_NT) {
 | |
| 	LoadStringW(g_hInst,iResourceID,pBuffer,STR_MAX_LENGTH);
 | |
|     } else {
 | |
| 
 | |
| 	CHAR szBuffer[STR_MAX_LENGTH];
 | |
| 	DWORD dwStringLength = LoadString(g_hInst,iResourceID,szBuffer,STR_MAX_LENGTH);
 | |
| 	// if we loaded a string convert it to wide characters, ensuring
 | |
| 	// that we also null terminate the result.
 | |
| 	if (dwStringLength++) {
 | |
| 	    MultiByteToWideChar(CP_ACP,0,szBuffer,dwStringLength,pBuffer,STR_MAX_LENGTH);
 | |
| 	}
 | |
|     }
 | |
|     return pBuffer;
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| 
 | |
| // Helper function to calculate the size of the dialog
 | |
| 
 | |
| BOOL WINAPI GetDialogSize(int iResourceID,
 | |
|                           DLGPROC pDlgProc,
 | |
|                           LPARAM lParam,
 | |
|                           __out SIZE *pResult)
 | |
| {
 | |
|     RECT rc;
 | |
|     HWND hwnd;
 | |
| 
 | |
|     // Create a temporary property page
 | |
| 
 | |
|     hwnd = CreateDialogParam(g_hInst,
 | |
|                              MAKEINTRESOURCE(iResourceID),
 | |
|                              GetDesktopWindow(),
 | |
|                              pDlgProc,
 | |
|                              lParam);
 | |
|     if (hwnd == NULL) {
 | |
|         return FALSE;
 | |
|     }
 | |
| 
 | |
|     GetWindowRect(hwnd, &rc);
 | |
|     pResult->cx = rc.right - rc.left;
 | |
|     pResult->cy = rc.bottom - rc.top;
 | |
| 
 | |
|     DestroyWindow(hwnd);
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Class that aggregates on the IDirectDraw interface. Although DirectDraw
 | |
| // has the ability in its interfaces to be aggregated they're not currently
 | |
| // implemented. This makes it difficult for various parts of Quartz that want
 | |
| // to aggregate these interfaces. In particular the video renderer passes out
 | |
| // media samples that expose IDirectDraw and IDirectDrawSurface. The filter
 | |
| // graph manager also exposes IDirectDraw as a plug in distributor. For these
 | |
| // objects we provide these aggregation classes that republish the interfaces
 | |
| 
 | |
| STDMETHODIMP CAggDirectDraw::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
 | |
| {
 | |
|     ASSERT(m_pDirectDraw);
 | |
| 
 | |
|     // Do we have this interface
 | |
| 
 | |
|     if (riid == IID_IDirectDraw) {
 | |
|         return GetInterface((IDirectDraw *)this,ppv);
 | |
|     } else {
 | |
|         return CUnknown::NonDelegatingQueryInterface(riid,ppv);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDirectDraw::Compact()
 | |
| {
 | |
|     ASSERT(m_pDirectDraw);
 | |
|     return m_pDirectDraw->Compact();
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDirectDraw::CreateClipper(DWORD dwFlags, __deref_out LPDIRECTDRAWCLIPPER *lplpDDClipper, __inout_opt IUnknown *pUnkOuter)
 | |
| {
 | |
|     ASSERT(m_pDirectDraw);
 | |
|     return m_pDirectDraw->CreateClipper(dwFlags,lplpDDClipper,pUnkOuter);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDirectDraw::CreatePalette(DWORD dwFlags,
 | |
|                                            __in LPPALETTEENTRY lpColorTable,
 | |
|                                            __deref_out LPDIRECTDRAWPALETTE *lplpDDPalette,
 | |
|                                            __inout_opt IUnknown *pUnkOuter)
 | |
| {
 | |
|     ASSERT(m_pDirectDraw);
 | |
|     return m_pDirectDraw->CreatePalette(dwFlags,lpColorTable,lplpDDPalette,pUnkOuter);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDirectDraw::CreateSurface(__in LPDDSURFACEDESC lpDDSurfaceDesc,
 | |
|                                            __deref_out LPDIRECTDRAWSURFACE *lplpDDSurface,
 | |
|                                            __inout_opt IUnknown *pUnkOuter)
 | |
| {
 | |
|     ASSERT(m_pDirectDraw);
 | |
|     return m_pDirectDraw->CreateSurface(lpDDSurfaceDesc,lplpDDSurface,pUnkOuter);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDirectDraw::DuplicateSurface(__in LPDIRECTDRAWSURFACE lpDDSurface,
 | |
|                                               __deref_out LPDIRECTDRAWSURFACE *lplpDupDDSurface)
 | |
| {
 | |
|     ASSERT(m_pDirectDraw);
 | |
|     return m_pDirectDraw->DuplicateSurface(lpDDSurface,lplpDupDDSurface);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDirectDraw::EnumDisplayModes(DWORD dwSurfaceDescCount,
 | |
|                                               __in LPDDSURFACEDESC lplpDDSurfaceDescList,
 | |
|                                               __in LPVOID lpContext,
 | |
|                                               __in LPDDENUMMODESCALLBACK lpEnumCallback)
 | |
| {
 | |
|     ASSERT(m_pDirectDraw);
 | |
|     return m_pDirectDraw->EnumDisplayModes(dwSurfaceDescCount,lplpDDSurfaceDescList,lpContext,lpEnumCallback);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDirectDraw::EnumSurfaces(DWORD dwFlags,
 | |
|                                           __in LPDDSURFACEDESC lpDDSD,
 | |
|                                           __in LPVOID lpContext,
 | |
|                                           __in LPDDENUMSURFACESCALLBACK lpEnumCallback)
 | |
| {
 | |
|     ASSERT(m_pDirectDraw);
 | |
|     return m_pDirectDraw->EnumSurfaces(dwFlags,lpDDSD,lpContext,lpEnumCallback);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDirectDraw::FlipToGDISurface()
 | |
| {
 | |
|     ASSERT(m_pDirectDraw);
 | |
|     return m_pDirectDraw->FlipToGDISurface();
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDirectDraw::GetCaps(__out LPDDCAPS lpDDDriverCaps,__out LPDDCAPS lpDDHELCaps)
 | |
| {
 | |
|     ASSERT(m_pDirectDraw);
 | |
|     return m_pDirectDraw->GetCaps(lpDDDriverCaps,lpDDHELCaps);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDirectDraw::GetDisplayMode(__out LPDDSURFACEDESC lpDDSurfaceDesc)
 | |
| {
 | |
|     ASSERT(m_pDirectDraw);
 | |
|     return m_pDirectDraw->GetDisplayMode(lpDDSurfaceDesc);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDirectDraw::GetFourCCCodes(__inout LPDWORD lpNumCodes,__out_ecount(*lpNumCodes) LPDWORD lpCodes)
 | |
| {
 | |
|     ASSERT(m_pDirectDraw);
 | |
|     return m_pDirectDraw->GetFourCCCodes(lpNumCodes,lpCodes);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDirectDraw::GetGDISurface(__deref_out LPDIRECTDRAWSURFACE *lplpGDIDDSurface)
 | |
| {
 | |
|     ASSERT(m_pDirectDraw);
 | |
|     return m_pDirectDraw->GetGDISurface(lplpGDIDDSurface);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDirectDraw::GetMonitorFrequency(__out LPDWORD lpdwFrequency)
 | |
| {
 | |
|     ASSERT(m_pDirectDraw);
 | |
|     return m_pDirectDraw->GetMonitorFrequency(lpdwFrequency);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDirectDraw::GetScanLine(__out LPDWORD lpdwScanLine)
 | |
| {
 | |
|     ASSERT(m_pDirectDraw);
 | |
|     return m_pDirectDraw->GetScanLine(lpdwScanLine);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDirectDraw::GetVerticalBlankStatus(__out LPBOOL lpblsInVB)
 | |
| {
 | |
|     ASSERT(m_pDirectDraw);
 | |
|     return m_pDirectDraw->GetVerticalBlankStatus(lpblsInVB);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDirectDraw::Initialize(__in GUID *lpGUID)
 | |
| {
 | |
|     ASSERT(m_pDirectDraw);
 | |
|     return m_pDirectDraw->Initialize(lpGUID);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDirectDraw::RestoreDisplayMode()
 | |
| {
 | |
|     ASSERT(m_pDirectDraw);
 | |
|     return m_pDirectDraw->RestoreDisplayMode();
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDirectDraw::SetCooperativeLevel(HWND hWnd,DWORD dwFlags)
 | |
| {
 | |
|     ASSERT(m_pDirectDraw);
 | |
|     return m_pDirectDraw->SetCooperativeLevel(hWnd,dwFlags);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDirectDraw::SetDisplayMode(DWORD dwWidth,DWORD dwHeight,DWORD dwBpp)
 | |
| {
 | |
|     ASSERT(m_pDirectDraw);
 | |
|     return m_pDirectDraw->SetDisplayMode(dwWidth,dwHeight,dwBpp);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDirectDraw::WaitForVerticalBlank(DWORD dwFlags,HANDLE hEvent)
 | |
| {
 | |
|     ASSERT(m_pDirectDraw);
 | |
|     return m_pDirectDraw->WaitForVerticalBlank(dwFlags,hEvent);
 | |
| }
 | |
| 
 | |
| 
 | |
| // Class that aggregates an IDirectDrawSurface interface. Although DirectDraw
 | |
| // has the ability in its interfaces to be aggregated they're not currently
 | |
| // implemented. This makes it difficult for various parts of Quartz that want
 | |
| // to aggregate these interfaces. In particular the video renderer passes out
 | |
| // media samples that expose IDirectDraw and IDirectDrawSurface. The filter
 | |
| // graph manager also exposes IDirectDraw as a plug in distributor. For these
 | |
| // objects we provide these aggregation classes that republish the interfaces
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
| 
 | |
|     // Do we have this interface
 | |
| 
 | |
|     if (riid == IID_IDirectDrawSurface) {
 | |
|         return GetInterface((IDirectDrawSurface *)this,ppv);
 | |
|     } else {
 | |
|         return CUnknown::NonDelegatingQueryInterface(riid,ppv);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::AddAttachedSurface(__in LPDIRECTDRAWSURFACE lpDDSAttachedSurface)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->AddAttachedSurface(lpDDSAttachedSurface);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::AddOverlayDirtyRect(__in LPRECT lpRect)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->AddOverlayDirtyRect(lpRect);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::Blt(__in LPRECT lpDestRect,
 | |
|                                   __in LPDIRECTDRAWSURFACE lpDDSrcSurface,
 | |
|                                   __in LPRECT lpSrcRect,
 | |
|                                   DWORD dwFlags,
 | |
|                                   __in LPDDBLTFX lpDDBltFx)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->Blt(lpDestRect,lpDDSrcSurface,lpSrcRect,dwFlags,lpDDBltFx);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::BltBatch(__in_ecount(dwCount) LPDDBLTBATCH lpDDBltBatch,DWORD dwCount,DWORD dwFlags)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->BltBatch(lpDDBltBatch,dwCount,dwFlags);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::BltFast(DWORD dwX,DWORD dwY,
 | |
|                                       __in LPDIRECTDRAWSURFACE lpDDSrcSurface,
 | |
|                                       __in LPRECT lpSrcRect,
 | |
|                                       DWORD dwTrans)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->BltFast(dwX,dwY,lpDDSrcSurface,lpSrcRect,dwTrans);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::DeleteAttachedSurface(DWORD dwFlags,
 | |
|                                                     __in LPDIRECTDRAWSURFACE lpDDSAttachedSurface)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->DeleteAttachedSurface(dwFlags,lpDDSAttachedSurface);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::EnumAttachedSurfaces(__in LPVOID lpContext,
 | |
|                                                    __in LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->EnumAttachedSurfaces(lpContext,lpEnumSurfacesCallback);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::EnumOverlayZOrders(DWORD dwFlags,
 | |
|                                                  __in LPVOID lpContext,
 | |
|                                                  __in LPDDENUMSURFACESCALLBACK lpfnCallback)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->EnumOverlayZOrders(dwFlags,lpContext,lpfnCallback);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::Flip(__in LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride,DWORD dwFlags)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->Flip(lpDDSurfaceTargetOverride,dwFlags);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::GetAttachedSurface(__in LPDDSCAPS lpDDSCaps,
 | |
|                                                  __deref_out LPDIRECTDRAWSURFACE *lplpDDAttachedSurface)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->GetAttachedSurface(lpDDSCaps,lplpDDAttachedSurface);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::GetBltStatus(DWORD dwFlags)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->GetBltStatus(dwFlags);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::GetCaps(__out LPDDSCAPS lpDDSCaps)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->GetCaps(lpDDSCaps);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::GetClipper(__deref_out LPDIRECTDRAWCLIPPER *lplpDDClipper)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->GetClipper(lplpDDClipper);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::GetColorKey(DWORD dwFlags,__out LPDDCOLORKEY lpDDColorKey)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->GetColorKey(dwFlags,lpDDColorKey);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::GetDC(__out HDC *lphDC)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->GetDC(lphDC);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::GetFlipStatus(DWORD dwFlags)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->GetFlipStatus(dwFlags);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::GetOverlayPosition(__out LPLONG lpdwX,__out LPLONG lpdwY)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->GetOverlayPosition(lpdwX,lpdwY);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::GetPalette(__deref_out LPDIRECTDRAWPALETTE *lplpDDPalette)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->GetPalette(lplpDDPalette);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::GetPixelFormat(__out LPDDPIXELFORMAT lpDDPixelFormat)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->GetPixelFormat(lpDDPixelFormat);
 | |
| }
 | |
| 
 | |
| 
 | |
| // A bit of a warning here: Our media samples in DirectShow aggregate on
 | |
| // IDirectDraw and IDirectDrawSurface (ie are available through IMediaSample
 | |
| // by QueryInterface). Unfortunately the underlying DirectDraw code cannot
 | |
| // be aggregated so we have to use these classes. The snag is that when we
 | |
| // call a different surface and pass in this interface as perhaps the source
 | |
| // surface the call will fail because DirectDraw dereferences the pointer to
 | |
| // get at its private data structures. Therefore we supply this workaround to give
 | |
| // access to the real IDirectDraw surface. A filter can call GetSurfaceDesc
 | |
| // and we will fill in the lpSurface pointer with the real underlying surface
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::GetSurfaceDesc(__out LPDDSURFACEDESC lpDDSurfaceDesc)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
| 
 | |
|     // First call down to the underlying DirectDraw
 | |
| 
 | |
|     HRESULT hr = m_pDirectDrawSurface->GetSurfaceDesc(lpDDSurfaceDesc);
 | |
|     if (FAILED(hr)) {
 | |
|         return hr;
 | |
|     }
 | |
| 
 | |
|     // Store the real DirectDrawSurface interface
 | |
|     lpDDSurfaceDesc->lpSurface = m_pDirectDrawSurface;
 | |
|     return hr;
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::Initialize(__in LPDIRECTDRAW lpDD,__in LPDDSURFACEDESC lpDDSurfaceDesc)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->Initialize(lpDD,lpDDSurfaceDesc);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::IsLost()
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->IsLost();
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::Lock(__in LPRECT lpDestRect,
 | |
|                                    __inout LPDDSURFACEDESC lpDDSurfaceDesc,
 | |
|                                    DWORD dwFlags,
 | |
|                                    HANDLE hEvent)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->Lock(lpDestRect,lpDDSurfaceDesc,dwFlags,hEvent);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::ReleaseDC(HDC hDC)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->ReleaseDC(hDC);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::Restore()
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->Restore();
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::SetClipper(__in LPDIRECTDRAWCLIPPER lpDDClipper)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->SetClipper(lpDDClipper);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::SetColorKey(DWORD dwFlags,__in LPDDCOLORKEY lpDDColorKey)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->SetColorKey(dwFlags,lpDDColorKey);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::SetOverlayPosition(LONG dwX,LONG dwY)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->SetOverlayPosition(dwX,dwY);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::SetPalette(__in LPDIRECTDRAWPALETTE lpDDPalette)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->SetPalette(lpDDPalette);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::Unlock(__in LPVOID lpSurfaceData)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->Unlock(lpSurfaceData);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::UpdateOverlay(__in LPRECT lpSrcRect,
 | |
|                                             __in LPDIRECTDRAWSURFACE lpDDDestSurface,
 | |
|                                             __in LPRECT lpDestRect,
 | |
|                                             DWORD dwFlags,
 | |
|                                             __in LPDDOVERLAYFX lpDDOverlayFX)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->UpdateOverlay(lpSrcRect,lpDDDestSurface,lpDestRect,dwFlags,lpDDOverlayFX);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::UpdateOverlayDisplay(DWORD dwFlags)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->UpdateOverlayDisplay(dwFlags);
 | |
| }
 | |
| 
 | |
| 
 | |
| STDMETHODIMP CAggDrawSurface::UpdateOverlayZOrder(DWORD dwFlags,__in LPDIRECTDRAWSURFACE lpDDSReference)
 | |
| {
 | |
|     ASSERT(m_pDirectDrawSurface);
 | |
|     return m_pDirectDrawSurface->UpdateOverlayZOrder(dwFlags,lpDDSReference);
 | |
| }
 | |
| 
 | |
| 
 | |
| // DirectShow must work on multiple platforms.  In particular, it also runs on
 | |
| // Windows NT 3.51 which does not have DirectDraw capabilities. The filters
 | |
| // cannot therefore link statically to the DirectDraw library. To make their
 | |
| // lives that little bit easier we provide this class that manages loading
 | |
| // and unloading the library and creating the initial IDirectDraw interface
 | |
| 
 | |
| CLoadDirectDraw::CLoadDirectDraw() :
 | |
|     m_pDirectDraw(NULL),
 | |
|     m_hDirectDraw(NULL)
 | |
| {
 | |
| }
 | |
| 
 | |
| 
 | |
| // Destructor forces unload
 | |
| 
 | |
| CLoadDirectDraw::~CLoadDirectDraw()
 | |
| {
 | |
|     ReleaseDirectDraw();
 | |
| 
 | |
|     if (m_hDirectDraw) {
 | |
|         NOTE("Unloading library");
 | |
|         FreeLibrary(m_hDirectDraw);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| // We can't be sure that DirectDraw is always available so we can't statically
 | |
| // link to the library. Therefore we load the library, get the function entry
 | |
| // point addresses and call them to create the driver objects. We return S_OK
 | |
| // if we manage to load DirectDraw correctly otherwise we return E_NOINTERFACE
 | |
| // We initialise a DirectDraw instance by explicitely loading the library and
 | |
| // calling GetProcAddress on the DirectDrawCreate entry point that it exports
 | |
| 
 | |
| // On a multi monitor system, we can get the DirectDraw object for any
 | |
| // monitor (device) with the optional szDevice parameter
 | |
| 
 | |
| HRESULT CLoadDirectDraw::LoadDirectDraw(__in LPSTR szDevice)
 | |
| {
 | |
|     PDRAWCREATE pDrawCreate;
 | |
|     PDRAWENUM pDrawEnum;
 | |
|     LPDIRECTDRAWENUMERATEEXA pDrawEnumEx;
 | |
|     HRESULT hr = NOERROR;
 | |
| 
 | |
|     NOTE("Entering DoLoadDirectDraw");
 | |
| 
 | |
|     // Is DirectDraw already loaded
 | |
| 
 | |
|     if (m_pDirectDraw) {
 | |
|         NOTE("Already loaded");
 | |
|         ASSERT(m_hDirectDraw);
 | |
|         return NOERROR;
 | |
|     }
 | |
| 
 | |
|     // Make sure the library is available
 | |
| 
 | |
|     if(!m_hDirectDraw)
 | |
|     {
 | |
|         UINT ErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX);
 | |
|         m_hDirectDraw = LoadLibrary(TEXT("DDRAW.DLL"));
 | |
|         SetErrorMode(ErrorMode);
 | |
| 
 | |
|         if (m_hDirectDraw == NULL) {
 | |
|             DbgLog((LOG_ERROR,1,TEXT("Can't load DDRAW.DLL")));
 | |
|             NOTE("No library");
 | |
|             return E_NOINTERFACE;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // Get the DLL address for the creator function
 | |
| 
 | |
|     pDrawCreate = (PDRAWCREATE)GetProcAddress(m_hDirectDraw,"DirectDrawCreate");
 | |
|     // force ANSI, we assume it
 | |
|     pDrawEnum = (PDRAWENUM)GetProcAddress(m_hDirectDraw,"DirectDrawEnumerateA");
 | |
|     pDrawEnumEx = (LPDIRECTDRAWENUMERATEEXA)GetProcAddress(m_hDirectDraw,
 | |
| 						"DirectDrawEnumerateExA");
 | |
| 
 | |
|     // We don't NEED DirectDrawEnumerateEx, that's just for multimon stuff
 | |
|     if (pDrawCreate == NULL || pDrawEnum == NULL) {
 | |
|         DbgLog((LOG_ERROR,1,TEXT("Can't get functions: Create=%x Enum=%x"),
 | |
| 			pDrawCreate, pDrawEnum));
 | |
|         NOTE("No entry point");
 | |
|         ReleaseDirectDraw();
 | |
|         return E_NOINTERFACE;
 | |
|     }
 | |
| 
 | |
|     DbgLog((LOG_TRACE,3,TEXT("Creating DDraw for device %s"),
 | |
| 					szDevice ? szDevice : "<NULL>"));
 | |
| 
 | |
|     // Create a DirectDraw display provider for this device, using the fancy
 | |
|     // multimon-aware version, if it exists
 | |
|     if (pDrawEnumEx)
 | |
|         m_pDirectDraw = DirectDrawCreateFromDeviceEx(szDevice, pDrawCreate,
 | |
| 								pDrawEnumEx);
 | |
|     else
 | |
|         m_pDirectDraw = DirectDrawCreateFromDevice(szDevice, pDrawCreate,
 | |
| 								pDrawEnum);
 | |
| 
 | |
|     if (m_pDirectDraw == NULL) {
 | |
|             DbgLog((LOG_ERROR,1,TEXT("Can't create DDraw")));
 | |
|             NOTE("No instance");
 | |
|             ReleaseDirectDraw();
 | |
|             return E_NOINTERFACE;
 | |
|     }
 | |
|     return NOERROR;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Called to release any DirectDraw provider we previously loaded. We may be
 | |
| // called at any time especially when something goes horribly wrong and when
 | |
| // we need to clean up before returning so we can't guarantee that all state
 | |
| // variables are consistent so free only those really allocated allocated
 | |
| // This should only be called once all reference counts have been released
 | |
| 
 | |
| void CLoadDirectDraw::ReleaseDirectDraw()
 | |
| {
 | |
|     NOTE("Releasing DirectDraw driver");
 | |
| 
 | |
|     // Release any DirectDraw provider interface
 | |
| 
 | |
|     if (m_pDirectDraw) {
 | |
|         NOTE("Releasing instance");
 | |
|         m_pDirectDraw->Release();
 | |
|         m_pDirectDraw = NULL;
 | |
|     }
 | |
| 
 | |
| }
 | |
| 
 | |
| 
 | |
| // Return NOERROR (S_OK) if DirectDraw has been loaded by this object
 | |
| 
 | |
| HRESULT CLoadDirectDraw::IsDirectDrawLoaded()
 | |
| {
 | |
|     NOTE("Entering IsDirectDrawLoaded");
 | |
| 
 | |
|     if (m_pDirectDraw == NULL) {
 | |
|         NOTE("DirectDraw not loaded");
 | |
|         return S_FALSE;
 | |
|     }
 | |
|     return NOERROR;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Return the IDirectDraw interface we look after
 | |
| 
 | |
| LPDIRECTDRAW CLoadDirectDraw::GetDirectDraw()
 | |
| {
 | |
|     NOTE("Entering GetDirectDraw");
 | |
| 
 | |
|     if (m_pDirectDraw == NULL) {
 | |
|         NOTE("No DirectDraw");
 | |
|         return NULL;
 | |
|     }
 | |
| 
 | |
|     NOTE("Returning DirectDraw");
 | |
|     m_pDirectDraw->AddRef();
 | |
|     return m_pDirectDraw;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Are we running on Direct Draw version 1?  We need to find out as
 | |
| // we rely on specific bug fixes in DirectDraw 2 for fullscreen playback. To
 | |
| // find out, we simply see if it supports IDirectDraw2.  Only version 2 and
 | |
| // higher support this.
 | |
| 
 | |
| BOOL CLoadDirectDraw::IsDirectDrawVersion1()
 | |
| {
 | |
| 
 | |
|     if (m_pDirectDraw == NULL)
 | |
| 	return FALSE;
 | |
| 
 | |
|     IDirectDraw2 *p = NULL;
 | |
|     HRESULT hr = m_pDirectDraw->QueryInterface(IID_IDirectDraw2, (void **)&p);
 | |
|     if (p)
 | |
| 	p->Release();
 | |
|     if (hr == NOERROR) {
 | |
|         DbgLog((LOG_TRACE,3,TEXT("Direct Draw Version 2 or greater")));
 | |
| 	return FALSE;
 | |
|     } else {
 | |
|         DbgLog((LOG_TRACE,3,TEXT("Direct Draw Version 1")));
 | |
| 	return TRUE;
 | |
|     }
 | |
| }
 |