mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-26 18:20:44 +00:00
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
|
||
|
|
||
|
LPTSTR 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
|
||
|
LPSTR 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;
|
||
|
}
|
||
|
}
|