716 lines
20 KiB
C++
716 lines
20 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
|
||
|
|
||
|
TCHAR *WINAPI StringFromResource(TCHAR *pBuffer, int iResourceID)
|
||
|
{
|
||
|
if (LoadString(g_hInst,iResourceID,pBuffer,STR_MAX_LENGTH) == 0) {
|
||
|
return TEXT("");
|
||
|
}
|
||
|
return pBuffer;
|
||
|
}
|
||
|
|
||
|
#ifdef UNICODE
|
||
|
char *WINAPI StringFromResource(char *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
|
||
|
|
||
|
WCHAR * WINAPI WideStringFromResource(WCHAR *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,
|
||
|
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, 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,LPDIRECTDRAWCLIPPER *lplpDDClipper,IUnknown *pUnkOuter)
|
||
|
{
|
||
|
ASSERT(m_pDirectDraw);
|
||
|
return m_pDirectDraw->CreateClipper(dwFlags,lplpDDClipper,pUnkOuter);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDirectDraw::CreatePalette(DWORD dwFlags,LPPALETTEENTRY lpColorTable,LPDIRECTDRAWPALETTE *lplpDDPalette,IUnknown *pUnkOuter)
|
||
|
{
|
||
|
ASSERT(m_pDirectDraw);
|
||
|
return m_pDirectDraw->CreatePalette(dwFlags,lpColorTable,lplpDDPalette,pUnkOuter);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDirectDraw::CreateSurface(LPDDSURFACEDESC lpDDSurfaceDesc,LPDIRECTDRAWSURFACE *lplpDDSurface,IUnknown *pUnkOuter)
|
||
|
{
|
||
|
ASSERT(m_pDirectDraw);
|
||
|
return m_pDirectDraw->CreateSurface(lpDDSurfaceDesc,lplpDDSurface,pUnkOuter);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDirectDraw::DuplicateSurface(LPDIRECTDRAWSURFACE lpDDSurface,LPDIRECTDRAWSURFACE *lplpDupDDSurface)
|
||
|
{
|
||
|
ASSERT(m_pDirectDraw);
|
||
|
return m_pDirectDraw->DuplicateSurface(lpDDSurface,lplpDupDDSurface);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDirectDraw::EnumDisplayModes(DWORD dwSurfaceDescCount,LPDDSURFACEDESC lplpDDSurfaceDescList,LPVOID lpContext,LPDDENUMMODESCALLBACK lpEnumCallback)
|
||
|
{
|
||
|
ASSERT(m_pDirectDraw);
|
||
|
return m_pDirectDraw->EnumDisplayModes(dwSurfaceDescCount,lplpDDSurfaceDescList,lpContext,lpEnumCallback);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDirectDraw::EnumSurfaces(DWORD dwFlags,LPDDSURFACEDESC lpDDSD,LPVOID lpContext,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(LPDDCAPS lpDDDriverCaps,LPDDCAPS lpDDHELCaps)
|
||
|
{
|
||
|
ASSERT(m_pDirectDraw);
|
||
|
return m_pDirectDraw->GetCaps(lpDDDriverCaps,lpDDHELCaps);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDirectDraw::GetDisplayMode(LPDDSURFACEDESC lpDDSurfaceDesc)
|
||
|
{
|
||
|
ASSERT(m_pDirectDraw);
|
||
|
return m_pDirectDraw->GetDisplayMode(lpDDSurfaceDesc);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDirectDraw::GetFourCCCodes(LPDWORD lpNumCodes,LPDWORD lpCodes)
|
||
|
{
|
||
|
ASSERT(m_pDirectDraw);
|
||
|
return m_pDirectDraw->GetFourCCCodes(lpNumCodes,lpCodes);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDirectDraw::GetGDISurface(LPDIRECTDRAWSURFACE *lplpGDIDDSurface)
|
||
|
{
|
||
|
ASSERT(m_pDirectDraw);
|
||
|
return m_pDirectDraw->GetGDISurface(lplpGDIDDSurface);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDirectDraw::GetMonitorFrequency(LPDWORD lpdwFrequency)
|
||
|
{
|
||
|
ASSERT(m_pDirectDraw);
|
||
|
return m_pDirectDraw->GetMonitorFrequency(lpdwFrequency);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDirectDraw::GetScanLine(LPDWORD lpdwScanLine)
|
||
|
{
|
||
|
ASSERT(m_pDirectDraw);
|
||
|
return m_pDirectDraw->GetScanLine(lpdwScanLine);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDirectDraw::GetVerticalBlankStatus(LPBOOL lpblsInVB)
|
||
|
{
|
||
|
ASSERT(m_pDirectDraw);
|
||
|
return m_pDirectDraw->GetVerticalBlankStatus(lpblsInVB);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDirectDraw::Initialize(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, 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(LPDIRECTDRAWSURFACE lpDDSAttachedSurface)
|
||
|
{
|
||
|
ASSERT(m_pDirectDrawSurface);
|
||
|
return m_pDirectDrawSurface->AddAttachedSurface(lpDDSAttachedSurface);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDrawSurface::AddOverlayDirtyRect(LPRECT lpRect)
|
||
|
{
|
||
|
ASSERT(m_pDirectDrawSurface);
|
||
|
return m_pDirectDrawSurface->AddOverlayDirtyRect(lpRect);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDrawSurface::Blt(LPRECT lpDestRect,LPDIRECTDRAWSURFACE lpDDSrcSurface,LPRECT lpSrcRect,DWORD dwFlags,LPDDBLTFX lpDDBltFx)
|
||
|
{
|
||
|
ASSERT(m_pDirectDrawSurface);
|
||
|
return m_pDirectDrawSurface->Blt(lpDestRect,lpDDSrcSurface,lpSrcRect,dwFlags,lpDDBltFx);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDrawSurface::BltBatch(LPDDBLTBATCH lpDDBltBatch,DWORD dwCount,DWORD dwFlags)
|
||
|
{
|
||
|
ASSERT(m_pDirectDrawSurface);
|
||
|
return m_pDirectDrawSurface->BltBatch(lpDDBltBatch,dwCount,dwFlags);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDrawSurface::BltFast(DWORD dwX,DWORD dwY,LPDIRECTDRAWSURFACE lpDDSrcSurface,LPRECT lpSrcRect,DWORD dwTrans)
|
||
|
{
|
||
|
ASSERT(m_pDirectDrawSurface);
|
||
|
return m_pDirectDrawSurface->BltFast(dwX,dwY,lpDDSrcSurface,lpSrcRect,dwTrans);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDrawSurface::DeleteAttachedSurface(DWORD dwFlags,LPDIRECTDRAWSURFACE lpDDSAttachedSurface)
|
||
|
{
|
||
|
ASSERT(m_pDirectDrawSurface);
|
||
|
return m_pDirectDrawSurface->DeleteAttachedSurface(dwFlags,lpDDSAttachedSurface);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDrawSurface::EnumAttachedSurfaces(LPVOID lpContext,LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback)
|
||
|
{
|
||
|
ASSERT(m_pDirectDrawSurface);
|
||
|
return m_pDirectDrawSurface->EnumAttachedSurfaces(lpContext,lpEnumSurfacesCallback);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDrawSurface::EnumOverlayZOrders(DWORD dwFlags,LPVOID lpContext,LPDDENUMSURFACESCALLBACK lpfnCallback)
|
||
|
{
|
||
|
ASSERT(m_pDirectDrawSurface);
|
||
|
return m_pDirectDrawSurface->EnumOverlayZOrders(dwFlags,lpContext,lpfnCallback);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDrawSurface::Flip(LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride,DWORD dwFlags)
|
||
|
{
|
||
|
ASSERT(m_pDirectDrawSurface);
|
||
|
return m_pDirectDrawSurface->Flip(lpDDSurfaceTargetOverride,dwFlags);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDrawSurface::GetAttachedSurface(LPDDSCAPS lpDDSCaps,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(LPDDSCAPS lpDDSCaps)
|
||
|
{
|
||
|
ASSERT(m_pDirectDrawSurface);
|
||
|
return m_pDirectDrawSurface->GetCaps(lpDDSCaps);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDrawSurface::GetClipper(LPDIRECTDRAWCLIPPER *lplpDDClipper)
|
||
|
{
|
||
|
ASSERT(m_pDirectDrawSurface);
|
||
|
return m_pDirectDrawSurface->GetClipper(lplpDDClipper);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDrawSurface::GetColorKey(DWORD dwFlags,LPDDCOLORKEY lpDDColorKey)
|
||
|
{
|
||
|
ASSERT(m_pDirectDrawSurface);
|
||
|
return m_pDirectDrawSurface->GetColorKey(dwFlags,lpDDColorKey);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDrawSurface::GetDC(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(LPLONG lpdwX,LPLONG lpdwY)
|
||
|
{
|
||
|
ASSERT(m_pDirectDrawSurface);
|
||
|
return m_pDirectDrawSurface->GetOverlayPosition(lpdwX,lpdwY);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDrawSurface::GetPalette(LPDIRECTDRAWPALETTE *lplpDDPalette)
|
||
|
{
|
||
|
ASSERT(m_pDirectDrawSurface);
|
||
|
return m_pDirectDrawSurface->GetPalette(lplpDDPalette);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDrawSurface::GetPixelFormat(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(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(LPDIRECTDRAW lpDD,LPDDSURFACEDESC lpDDSurfaceDesc)
|
||
|
{
|
||
|
ASSERT(m_pDirectDrawSurface);
|
||
|
return m_pDirectDrawSurface->Initialize(lpDD,lpDDSurfaceDesc);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDrawSurface::IsLost()
|
||
|
{
|
||
|
ASSERT(m_pDirectDrawSurface);
|
||
|
return m_pDirectDrawSurface->IsLost();
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDrawSurface::Lock(LPRECT lpDestRect,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(LPDIRECTDRAWCLIPPER lpDDClipper)
|
||
|
{
|
||
|
ASSERT(m_pDirectDrawSurface);
|
||
|
return m_pDirectDrawSurface->SetClipper(lpDDClipper);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDrawSurface::SetColorKey(DWORD dwFlags,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(LPDIRECTDRAWPALETTE lpDDPalette)
|
||
|
{
|
||
|
ASSERT(m_pDirectDrawSurface);
|
||
|
return m_pDirectDrawSurface->SetPalette(lpDDPalette);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDrawSurface::Unlock(LPVOID lpSurfaceData)
|
||
|
{
|
||
|
ASSERT(m_pDirectDrawSurface);
|
||
|
return m_pDirectDrawSurface->Unlock(lpSurfaceData);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CAggDrawSurface::UpdateOverlay(LPRECT lpSrcRect,LPDIRECTDRAWSURFACE lpDDDestSurface,LPRECT lpDestRect,DWORD dwFlags,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,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(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;
|
||
|
}
|
||
|
}
|