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