summaryrefslogtreecommitdiff
path: root/third_party/BaseClasses/videoctl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/BaseClasses/videoctl.cpp')
-rw-r--r--third_party/BaseClasses/videoctl.cpp746
1 files changed, 746 insertions, 0 deletions
diff --git a/third_party/BaseClasses/videoctl.cpp b/third_party/BaseClasses/videoctl.cpp
new file mode 100644
index 00000000..b12ccbd3
--- /dev/null
+++ b/third_party/BaseClasses/videoctl.cpp
@@ -0,0 +1,746 @@
+//------------------------------------------------------------------------------
+// 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;
+ }
+}