home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Game Programming for Teens / VBGPFT.cdr / DirectX8 / dx8a_sdk.exe / samples / multimedia / directshow / baseclasses / videoctl.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-02  |  21.1 KB  |  716 lines

  1. //------------------------------------------------------------------------------
  2. // File: VideoCtl.cpp
  3. //
  4. // Desc: DirectShow base classes.
  5. //
  6. // Copyright (c) 1992 - 2000, Microsoft Corporation.  All rights reserved.
  7. //------------------------------------------------------------------------------
  8.  
  9.  
  10. #include <streams.h>
  11. #include "ddmm.h"
  12.  
  13. // Load a string from the resource file string table. The buffer must be at
  14. // least STR_MAX_LENGTH bytes. The easiest way to use this is to declare a
  15. // buffer in the property page class and use it for all string loading. It
  16. // cannot be static as multiple property pages may be active simultaneously
  17.  
  18. TCHAR *WINAPI StringFromResource(TCHAR *pBuffer, int iResourceID)
  19. {
  20.     if (LoadString(g_hInst,iResourceID,pBuffer,STR_MAX_LENGTH) == 0) {
  21.         return TEXT("");
  22.     }
  23.     return pBuffer;
  24. }
  25.  
  26. #ifdef UNICODE
  27. char *WINAPI StringFromResource(char *pBuffer, int iResourceID)
  28. {
  29.     if (LoadStringA(g_hInst,iResourceID,pBuffer,STR_MAX_LENGTH) == 0) {
  30.         return "";
  31.     }
  32.     return pBuffer;
  33. }
  34. #endif
  35.  
  36.  
  37.  
  38. // Property pages typically are called through their OLE interfaces. These
  39. // use UNICODE strings regardless of how the binary is built. So when we
  40. // load strings from the resource file we sometimes want to convert them
  41. // to UNICODE. This method is passed the target UNICODE buffer and does a
  42. // convert after loading the string (if built UNICODE this is not needed)
  43. // On WinNT we can explicitly call LoadStringW which saves two conversions
  44.  
  45. #ifndef UNICODE
  46.  
  47. WCHAR * WINAPI WideStringFromResource(WCHAR *pBuffer, int iResourceID)
  48. {
  49.     *pBuffer = 0;
  50.  
  51.     if (g_amPlatform == VER_PLATFORM_WIN32_NT) {
  52.     LoadStringW(g_hInst,iResourceID,pBuffer,STR_MAX_LENGTH);
  53.     } else {
  54.  
  55.     CHAR szBuffer[STR_MAX_LENGTH];
  56.     DWORD dwStringLength = LoadString(g_hInst,iResourceID,szBuffer,STR_MAX_LENGTH);
  57.     // if we loaded a string convert it to wide characters, ensuring
  58.     // that we also null terminate the result.
  59.     if (dwStringLength++) {
  60.         MultiByteToWideChar(CP_ACP,0,szBuffer,dwStringLength,pBuffer,STR_MAX_LENGTH);
  61.     }
  62.     }
  63.     return pBuffer;
  64. }
  65.  
  66. #endif
  67.  
  68.  
  69. // Helper function to calculate the size of the dialog
  70.  
  71. BOOL WINAPI GetDialogSize(int iResourceID,
  72.                           DLGPROC pDlgProc,
  73.                           LPARAM lParam,
  74.                           SIZE *pResult)
  75. {
  76.     RECT rc;
  77.     HWND hwnd;
  78.  
  79.     // Create a temporary property page
  80.  
  81.     hwnd = CreateDialogParam(g_hInst,
  82.                              MAKEINTRESOURCE(iResourceID),
  83.                              GetDesktopWindow(),
  84.                              pDlgProc,
  85.                              lParam);
  86.     if (hwnd == NULL) {
  87.         return FALSE;
  88.     }
  89.  
  90.     GetWindowRect(hwnd, &rc);
  91.     pResult->cx = rc.right - rc.left;
  92.     pResult->cy = rc.bottom - rc.top;
  93.  
  94.     DestroyWindow(hwnd);
  95.     return TRUE;
  96. }
  97.  
  98.  
  99. // Class that aggregates on the IDirectDraw interface. Although DirectDraw
  100. // has the ability in its interfaces to be aggregated they're not currently
  101. // implemented. This makes it difficult for various parts of Quartz that want
  102. // to aggregate these interfaces. In particular the video renderer passes out
  103. // media samples that expose IDirectDraw and IDirectDrawSurface. The filter
  104. // graph manager also exposes IDirectDraw as a plug in distributor. For these
  105. // objects we provide these aggregation classes that republish the interfaces
  106.  
  107. STDMETHODIMP CAggDirectDraw::NonDelegatingQueryInterface(REFIID riid, void **ppv)
  108. {
  109.     ASSERT(m_pDirectDraw);
  110.  
  111.     // Do we have this interface
  112.  
  113.     if (riid == IID_IDirectDraw) {
  114.         return GetInterface((IDirectDraw *)this,ppv);
  115.     } else {
  116.         return CUnknown::NonDelegatingQueryInterface(riid,ppv);
  117.     }
  118. }
  119.  
  120.  
  121. STDMETHODIMP CAggDirectDraw::Compact()
  122. {
  123.     ASSERT(m_pDirectDraw);
  124.     return m_pDirectDraw->Compact();
  125. }
  126.  
  127.  
  128. STDMETHODIMP CAggDirectDraw::CreateClipper(DWORD dwFlags,LPDIRECTDRAWCLIPPER *lplpDDClipper,IUnknown *pUnkOuter)
  129. {
  130.     ASSERT(m_pDirectDraw);
  131.     return m_pDirectDraw->CreateClipper(dwFlags,lplpDDClipper,pUnkOuter);
  132. }
  133.  
  134.  
  135. STDMETHODIMP CAggDirectDraw::CreatePalette(DWORD dwFlags,LPPALETTEENTRY lpColorTable,LPDIRECTDRAWPALETTE *lplpDDPalette,IUnknown *pUnkOuter)
  136. {
  137.     ASSERT(m_pDirectDraw);
  138.     return m_pDirectDraw->CreatePalette(dwFlags,lpColorTable,lplpDDPalette,pUnkOuter);
  139. }
  140.  
  141.  
  142. STDMETHODIMP CAggDirectDraw::CreateSurface(LPDDSURFACEDESC lpDDSurfaceDesc,LPDIRECTDRAWSURFACE *lplpDDSurface,IUnknown *pUnkOuter)
  143. {
  144.     ASSERT(m_pDirectDraw);
  145.     return m_pDirectDraw->CreateSurface(lpDDSurfaceDesc,lplpDDSurface,pUnkOuter);
  146. }
  147.  
  148.  
  149. STDMETHODIMP CAggDirectDraw::DuplicateSurface(LPDIRECTDRAWSURFACE lpDDSurface,LPDIRECTDRAWSURFACE *lplpDupDDSurface)
  150. {
  151.     ASSERT(m_pDirectDraw);
  152.     return m_pDirectDraw->DuplicateSurface(lpDDSurface,lplpDupDDSurface);
  153. }
  154.  
  155.  
  156. STDMETHODIMP CAggDirectDraw::EnumDisplayModes(DWORD dwSurfaceDescCount,LPDDSURFACEDESC lplpDDSurfaceDescList,LPVOID lpContext,LPDDENUMMODESCALLBACK lpEnumCallback)
  157. {
  158.     ASSERT(m_pDirectDraw);
  159.     return m_pDirectDraw->EnumDisplayModes(dwSurfaceDescCount,lplpDDSurfaceDescList,lpContext,lpEnumCallback);
  160. }
  161.  
  162.  
  163. STDMETHODIMP CAggDirectDraw::EnumSurfaces(DWORD dwFlags,LPDDSURFACEDESC lpDDSD,LPVOID lpContext,LPDDENUMSURFACESCALLBACK lpEnumCallback)
  164. {
  165.     ASSERT(m_pDirectDraw);
  166.     return m_pDirectDraw->EnumSurfaces(dwFlags,lpDDSD,lpContext,lpEnumCallback);
  167. }
  168.  
  169.  
  170. STDMETHODIMP CAggDirectDraw::FlipToGDISurface()
  171. {
  172.     ASSERT(m_pDirectDraw);
  173.     return m_pDirectDraw->FlipToGDISurface();
  174. }
  175.  
  176.  
  177. STDMETHODIMP CAggDirectDraw::GetCaps(LPDDCAPS lpDDDriverCaps,LPDDCAPS lpDDHELCaps)
  178. {
  179.     ASSERT(m_pDirectDraw);
  180.     return m_pDirectDraw->GetCaps(lpDDDriverCaps,lpDDHELCaps);
  181. }
  182.  
  183.  
  184. STDMETHODIMP CAggDirectDraw::GetDisplayMode(LPDDSURFACEDESC lpDDSurfaceDesc)
  185. {
  186.     ASSERT(m_pDirectDraw);
  187.     return m_pDirectDraw->GetDisplayMode(lpDDSurfaceDesc);
  188. }
  189.  
  190.  
  191. STDMETHODIMP CAggDirectDraw::GetFourCCCodes(LPDWORD lpNumCodes,LPDWORD lpCodes)
  192. {
  193.     ASSERT(m_pDirectDraw);
  194.     return m_pDirectDraw->GetFourCCCodes(lpNumCodes,lpCodes);
  195. }
  196.  
  197.  
  198. STDMETHODIMP CAggDirectDraw::GetGDISurface(LPDIRECTDRAWSURFACE *lplpGDIDDSurface)
  199. {
  200.     ASSERT(m_pDirectDraw);
  201.     return m_pDirectDraw->GetGDISurface(lplpGDIDDSurface);
  202. }
  203.  
  204.  
  205. STDMETHODIMP CAggDirectDraw::GetMonitorFrequency(LPDWORD lpdwFrequency)
  206. {
  207.     ASSERT(m_pDirectDraw);
  208.     return m_pDirectDraw->GetMonitorFrequency(lpdwFrequency);
  209. }
  210.  
  211.  
  212. STDMETHODIMP CAggDirectDraw::GetScanLine(LPDWORD lpdwScanLine)
  213. {
  214.     ASSERT(m_pDirectDraw);
  215.     return m_pDirectDraw->GetScanLine(lpdwScanLine);
  216. }
  217.  
  218.  
  219. STDMETHODIMP CAggDirectDraw::GetVerticalBlankStatus(LPBOOL lpblsInVB)
  220. {
  221.     ASSERT(m_pDirectDraw);
  222.     return m_pDirectDraw->GetVerticalBlankStatus(lpblsInVB);
  223. }
  224.  
  225.  
  226. STDMETHODIMP CAggDirectDraw::Initialize(GUID *lpGUID)
  227. {
  228.     ASSERT(m_pDirectDraw);
  229.     return m_pDirectDraw->Initialize(lpGUID);
  230. }
  231.  
  232.  
  233. STDMETHODIMP CAggDirectDraw::RestoreDisplayMode()
  234. {
  235.     ASSERT(m_pDirectDraw);
  236.     return m_pDirectDraw->RestoreDisplayMode();
  237. }
  238.  
  239.  
  240. STDMETHODIMP CAggDirectDraw::SetCooperativeLevel(HWND hWnd,DWORD dwFlags)
  241. {
  242.     ASSERT(m_pDirectDraw);
  243.     return m_pDirectDraw->SetCooperativeLevel(hWnd,dwFlags);
  244. }
  245.  
  246.  
  247. STDMETHODIMP CAggDirectDraw::SetDisplayMode(DWORD dwWidth,DWORD dwHeight,DWORD dwBpp)
  248. {
  249.     ASSERT(m_pDirectDraw);
  250.     return m_pDirectDraw->SetDisplayMode(dwWidth,dwHeight,dwBpp);
  251. }
  252.  
  253.  
  254. STDMETHODIMP CAggDirectDraw::WaitForVerticalBlank(DWORD dwFlags,HANDLE hEvent)
  255. {
  256.     ASSERT(m_pDirectDraw);
  257.     return m_pDirectDraw->WaitForVerticalBlank(dwFlags,hEvent);
  258. }
  259.  
  260.  
  261. // Class that aggregates an IDirectDrawSurface interface. Although DirectDraw
  262. // has the ability in its interfaces to be aggregated they're not currently
  263. // implemented. This makes it difficult for various parts of Quartz that want
  264. // to aggregate these interfaces. In particular the video renderer passes out
  265. // media samples that expose IDirectDraw and IDirectDrawSurface. The filter
  266. // graph manager also exposes IDirectDraw as a plug in distributor. For these
  267. // objects we provide these aggregation classes that republish the interfaces
  268.  
  269. STDMETHODIMP CAggDrawSurface::NonDelegatingQueryInterface(REFIID riid, void **ppv)
  270. {
  271.     ASSERT(m_pDirectDrawSurface);
  272.  
  273.     // Do we have this interface
  274.  
  275.     if (riid == IID_IDirectDrawSurface) {
  276.         return GetInterface((IDirectDrawSurface *)this,ppv);
  277.     } else {
  278.         return CUnknown::NonDelegatingQueryInterface(riid,ppv);
  279.     }
  280. }
  281.  
  282.  
  283. STDMETHODIMP CAggDrawSurface::AddAttachedSurface(LPDIRECTDRAWSURFACE lpDDSAttachedSurface)
  284. {
  285.     ASSERT(m_pDirectDrawSurface);
  286.     return m_pDirectDrawSurface->AddAttachedSurface(lpDDSAttachedSurface);
  287. }
  288.  
  289.  
  290. STDMETHODIMP CAggDrawSurface::AddOverlayDirtyRect(LPRECT lpRect)
  291. {
  292.     ASSERT(m_pDirectDrawSurface);
  293.     return m_pDirectDrawSurface->AddOverlayDirtyRect(lpRect);
  294. }
  295.  
  296.  
  297. STDMETHODIMP CAggDrawSurface::Blt(LPRECT lpDestRect,LPDIRECTDRAWSURFACE lpDDSrcSurface,LPRECT lpSrcRect,DWORD dwFlags,LPDDBLTFX lpDDBltFx)
  298. {
  299.     ASSERT(m_pDirectDrawSurface);
  300.     return m_pDirectDrawSurface->Blt(lpDestRect,lpDDSrcSurface,lpSrcRect,dwFlags,lpDDBltFx);
  301. }
  302.  
  303.  
  304. STDMETHODIMP CAggDrawSurface::BltBatch(LPDDBLTBATCH lpDDBltBatch,DWORD dwCount,DWORD dwFlags)
  305. {
  306.     ASSERT(m_pDirectDrawSurface);
  307.     return m_pDirectDrawSurface->BltBatch(lpDDBltBatch,dwCount,dwFlags);
  308. }
  309.  
  310.  
  311. STDMETHODIMP CAggDrawSurface::BltFast(DWORD dwX,DWORD dwY,LPDIRECTDRAWSURFACE lpDDSrcSurface,LPRECT lpSrcRect,DWORD dwTrans)
  312. {
  313.     ASSERT(m_pDirectDrawSurface);
  314.     return m_pDirectDrawSurface->BltFast(dwX,dwY,lpDDSrcSurface,lpSrcRect,dwTrans);
  315. }
  316.  
  317.  
  318. STDMETHODIMP CAggDrawSurface::DeleteAttachedSurface(DWORD dwFlags,LPDIRECTDRAWSURFACE lpDDSAttachedSurface)
  319. {
  320.     ASSERT(m_pDirectDrawSurface);
  321.     return m_pDirectDrawSurface->DeleteAttachedSurface(dwFlags,lpDDSAttachedSurface);
  322. }
  323.  
  324.  
  325. STDMETHODIMP CAggDrawSurface::EnumAttachedSurfaces(LPVOID lpContext,LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback)
  326. {
  327.     ASSERT(m_pDirectDrawSurface);
  328.     return m_pDirectDrawSurface->EnumAttachedSurfaces(lpContext,lpEnumSurfacesCallback);
  329. }
  330.  
  331.  
  332. STDMETHODIMP CAggDrawSurface::EnumOverlayZOrders(DWORD dwFlags,LPVOID lpContext,LPDDENUMSURFACESCALLBACK lpfnCallback)
  333. {
  334.     ASSERT(m_pDirectDrawSurface);
  335.     return m_pDirectDrawSurface->EnumOverlayZOrders(dwFlags,lpContext,lpfnCallback);
  336. }
  337.  
  338.  
  339. STDMETHODIMP CAggDrawSurface::Flip(LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride,DWORD dwFlags)
  340. {
  341.     ASSERT(m_pDirectDrawSurface);
  342.     return m_pDirectDrawSurface->Flip(lpDDSurfaceTargetOverride,dwFlags);
  343. }
  344.  
  345.  
  346. STDMETHODIMP CAggDrawSurface::GetAttachedSurface(LPDDSCAPS lpDDSCaps,LPDIRECTDRAWSURFACE *lplpDDAttachedSurface)
  347. {
  348.     ASSERT(m_pDirectDrawSurface);
  349.     return m_pDirectDrawSurface->GetAttachedSurface(lpDDSCaps,lplpDDAttachedSurface);
  350. }
  351.  
  352.  
  353. STDMETHODIMP CAggDrawSurface::GetBltStatus(DWORD dwFlags)
  354. {
  355.     ASSERT(m_pDirectDrawSurface);
  356.     return m_pDirectDrawSurface->GetBltStatus(dwFlags);
  357. }
  358.  
  359.  
  360. STDMETHODIMP CAggDrawSurface::GetCaps(LPDDSCAPS lpDDSCaps)
  361. {
  362.     ASSERT(m_pDirectDrawSurface);
  363.     return m_pDirectDrawSurface->GetCaps(lpDDSCaps);
  364. }
  365.  
  366.  
  367. STDMETHODIMP CAggDrawSurface::GetClipper(LPDIRECTDRAWCLIPPER *lplpDDClipper)
  368. {
  369.     ASSERT(m_pDirectDrawSurface);
  370.     return m_pDirectDrawSurface->GetClipper(lplpDDClipper);
  371. }
  372.  
  373.  
  374. STDMETHODIMP CAggDrawSurface::GetColorKey(DWORD dwFlags,LPDDCOLORKEY lpDDColorKey)
  375. {
  376.     ASSERT(m_pDirectDrawSurface);
  377.     return m_pDirectDrawSurface->GetColorKey(dwFlags,lpDDColorKey);
  378. }
  379.  
  380.  
  381. STDMETHODIMP CAggDrawSurface::GetDC(HDC *lphDC)
  382. {
  383.     ASSERT(m_pDirectDrawSurface);
  384.     return m_pDirectDrawSurface->GetDC(lphDC);
  385. }
  386.  
  387.  
  388. STDMETHODIMP CAggDrawSurface::GetFlipStatus(DWORD dwFlags)
  389. {
  390.     ASSERT(m_pDirectDrawSurface);
  391.     return m_pDirectDrawSurface->GetFlipStatus(dwFlags);
  392. }
  393.  
  394.  
  395. STDMETHODIMP CAggDrawSurface::GetOverlayPosition(LPLONG lpdwX,LPLONG lpdwY)
  396. {
  397.     ASSERT(m_pDirectDrawSurface);
  398.     return m_pDirectDrawSurface->GetOverlayPosition(lpdwX,lpdwY);
  399. }
  400.  
  401.  
  402. STDMETHODIMP CAggDrawSurface::GetPalette(LPDIRECTDRAWPALETTE *lplpDDPalette)
  403. {
  404.     ASSERT(m_pDirectDrawSurface);
  405.     return m_pDirectDrawSurface->GetPalette(lplpDDPalette);
  406. }
  407.  
  408.  
  409. STDMETHODIMP CAggDrawSurface::GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat)
  410. {
  411.     ASSERT(m_pDirectDrawSurface);
  412.     return m_pDirectDrawSurface->GetPixelFormat(lpDDPixelFormat);
  413. }
  414.  
  415.  
  416. // A bit of a warning here: Our media samples in DirectShow aggregate on
  417. // IDirectDraw and IDirectDrawSurface (ie are available through IMediaSample
  418. // by QueryInterface). Unfortunately the underlying DirectDraw code cannot
  419. // be aggregated so we have to use these classes. The snag is that when we
  420. // call a different surface and pass in this interface as perhaps the source
  421. // surface the call will fail because DirectDraw dereferences the pointer to
  422. // get at its private data structures. Therefore we supply this workaround to give
  423. // access to the real IDirectDraw surface. A filter can call GetSurfaceDesc
  424. // and we will fill in the lpSurface pointer with the real underlying surface
  425.  
  426. STDMETHODIMP CAggDrawSurface::GetSurfaceDesc(LPDDSURFACEDESC lpDDSurfaceDesc)
  427. {
  428.     ASSERT(m_pDirectDrawSurface);
  429.  
  430.     // First call down to the underlying DirectDraw
  431.  
  432.     HRESULT hr = m_pDirectDrawSurface->GetSurfaceDesc(lpDDSurfaceDesc);
  433.     if (FAILED(hr)) {
  434.         return hr;
  435.     }
  436.  
  437.     // Store the real DirectDrawSurface interface
  438.     lpDDSurfaceDesc->lpSurface = m_pDirectDrawSurface;
  439.     return hr;
  440. }
  441.  
  442.  
  443. STDMETHODIMP CAggDrawSurface::Initialize(LPDIRECTDRAW lpDD,LPDDSURFACEDESC lpDDSurfaceDesc)
  444. {
  445.     ASSERT(m_pDirectDrawSurface);
  446.     return m_pDirectDrawSurface->Initialize(lpDD,lpDDSurfaceDesc);
  447. }
  448.  
  449.  
  450. STDMETHODIMP CAggDrawSurface::IsLost()
  451. {
  452.     ASSERT(m_pDirectDrawSurface);
  453.     return m_pDirectDrawSurface->IsLost();
  454. }
  455.  
  456.  
  457. STDMETHODIMP CAggDrawSurface::Lock(LPRECT lpDestRect,LPDDSURFACEDESC lpDDSurfaceDesc,DWORD dwFlags,HANDLE hEvent)
  458. {
  459.     ASSERT(m_pDirectDrawSurface);
  460.     return m_pDirectDrawSurface->Lock(lpDestRect,lpDDSurfaceDesc,dwFlags,hEvent);
  461. }
  462.  
  463.  
  464. STDMETHODIMP CAggDrawSurface::ReleaseDC(HDC hDC)
  465. {
  466.     ASSERT(m_pDirectDrawSurface);
  467.     return m_pDirectDrawSurface->ReleaseDC(hDC);
  468. }
  469.  
  470.  
  471. STDMETHODIMP CAggDrawSurface::Restore()
  472. {
  473.     ASSERT(m_pDirectDrawSurface);
  474.     return m_pDirectDrawSurface->Restore();
  475. }
  476.  
  477.  
  478. STDMETHODIMP CAggDrawSurface::SetClipper(LPDIRECTDRAWCLIPPER lpDDClipper)
  479. {
  480.     ASSERT(m_pDirectDrawSurface);
  481.     return m_pDirectDrawSurface->SetClipper(lpDDClipper);
  482. }
  483.  
  484.  
  485. STDMETHODIMP CAggDrawSurface::SetColorKey(DWORD dwFlags,LPDDCOLORKEY lpDDColorKey)
  486. {
  487.     ASSERT(m_pDirectDrawSurface);
  488.     return m_pDirectDrawSurface->SetColorKey(dwFlags,lpDDColorKey);
  489. }
  490.  
  491.  
  492. STDMETHODIMP CAggDrawSurface::SetOverlayPosition(LONG dwX,LONG dwY)
  493. {
  494.     ASSERT(m_pDirectDrawSurface);
  495.     return m_pDirectDrawSurface->SetOverlayPosition(dwX,dwY);
  496. }
  497.  
  498.  
  499. STDMETHODIMP CAggDrawSurface::SetPalette(LPDIRECTDRAWPALETTE lpDDPalette)
  500. {
  501.     ASSERT(m_pDirectDrawSurface);
  502.     return m_pDirectDrawSurface->SetPalette(lpDDPalette);
  503. }
  504.  
  505.  
  506. STDMETHODIMP CAggDrawSurface::Unlock(LPVOID lpSurfaceData)
  507. {
  508.     ASSERT(m_pDirectDrawSurface);
  509.     return m_pDirectDrawSurface->Unlock(lpSurfaceData);
  510. }
  511.  
  512.  
  513. STDMETHODIMP CAggDrawSurface::UpdateOverlay(LPRECT lpSrcRect,LPDIRECTDRAWSURFACE lpDDDestSurface,LPRECT lpDestRect,DWORD dwFlags,LPDDOVERLAYFX lpDDOverlayFX)
  514. {
  515.     ASSERT(m_pDirectDrawSurface);
  516.     return m_pDirectDrawSurface->UpdateOverlay(lpSrcRect,lpDDDestSurface,lpDestRect,dwFlags,lpDDOverlayFX);
  517. }
  518.  
  519.  
  520. STDMETHODIMP CAggDrawSurface::UpdateOverlayDisplay(DWORD dwFlags)
  521. {
  522.     ASSERT(m_pDirectDrawSurface);
  523.     return m_pDirectDrawSurface->UpdateOverlayDisplay(dwFlags);
  524. }
  525.  
  526.  
  527. STDMETHODIMP CAggDrawSurface::UpdateOverlayZOrder(DWORD dwFlags,LPDIRECTDRAWSURFACE lpDDSReference)
  528. {
  529.     ASSERT(m_pDirectDrawSurface);
  530.     return m_pDirectDrawSurface->UpdateOverlayZOrder(dwFlags,lpDDSReference);
  531. }
  532.  
  533.  
  534. // DirectShow must work on multiple platforms.  In particular, it also runs on
  535. // Windows NT 3.51 which does not have DirectDraw capabilities. The filters
  536. // cannot therefore link statically to the DirectDraw library. To make their
  537. // lives that little bit easier we provide this class that manages loading
  538. // and unloading the library and creating the initial IDirectDraw interface
  539.  
  540. CLoadDirectDraw::CLoadDirectDraw() :
  541.     m_pDirectDraw(NULL),
  542.     m_hDirectDraw(NULL)
  543. {
  544. }
  545.  
  546.  
  547. // Destructor forces unload
  548.  
  549. CLoadDirectDraw::~CLoadDirectDraw()
  550. {
  551.     ReleaseDirectDraw();
  552.  
  553.     if (m_hDirectDraw) {
  554.         NOTE("Unloading library");
  555.         FreeLibrary(m_hDirectDraw);
  556.     }
  557. }
  558.  
  559.  
  560. // We can't be sure that DirectDraw is always available so we can't statically
  561. // link to the library. Therefore we load the library, get the function entry
  562. // point addresses and call them to create the driver objects. We return S_OK
  563. // if we manage to load DirectDraw correctly otherwise we return E_NOINTERFACE
  564. // We initialise a DirectDraw instance by explicitely loading the library and
  565. // calling GetProcAddress on the DirectDrawCreate entry point that it exports
  566.  
  567. // On a multi monitor system, we can get the DirectDraw object for any
  568. // monitor (device) with the optional szDevice parameter
  569.  
  570. HRESULT CLoadDirectDraw::LoadDirectDraw(LPSTR szDevice)
  571. {
  572.     PDRAWCREATE pDrawCreate;
  573.     PDRAWENUM pDrawEnum;
  574.     LPDIRECTDRAWENUMERATEEXA pDrawEnumEx;
  575.     HRESULT hr = NOERROR;
  576.  
  577.     NOTE("Entering DoLoadDirectDraw");
  578.  
  579.     // Is DirectDraw already loaded
  580.  
  581.     if (m_pDirectDraw) {
  582.         NOTE("Already loaded");
  583.         ASSERT(m_hDirectDraw);
  584.         return NOERROR;
  585.     }
  586.  
  587.     // Make sure the library is available
  588.  
  589.     if(!m_hDirectDraw)
  590.     {
  591.         UINT ErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX);
  592.         m_hDirectDraw = LoadLibrary(TEXT("DDRAW.DLL"));
  593.         SetErrorMode(ErrorMode);
  594.  
  595.         if (m_hDirectDraw == NULL) {
  596.             DbgLog((LOG_ERROR,1,TEXT("Can't load DDRAW.DLL")));
  597.             NOTE("No library");
  598.             return E_NOINTERFACE;
  599.         }
  600.     }
  601.  
  602.     // Get the DLL address for the creator function
  603.  
  604.     pDrawCreate = (PDRAWCREATE)GetProcAddress(m_hDirectDraw,"DirectDrawCreate");
  605.     // force ANSI, we assume it
  606.     pDrawEnum = (PDRAWENUM)GetProcAddress(m_hDirectDraw,"DirectDrawEnumerateA");
  607.     pDrawEnumEx = (LPDIRECTDRAWENUMERATEEXA)GetProcAddress(m_hDirectDraw,
  608.                         "DirectDrawEnumerateExA");
  609.  
  610.     // We don't NEED DirectDrawEnumerateEx, that's just for multimon stuff
  611.     if (pDrawCreate == NULL || pDrawEnum == NULL) {
  612.         DbgLog((LOG_ERROR,1,TEXT("Can't get functions: Create=%x Enum=%x"),
  613.             pDrawCreate, pDrawEnum));
  614.         NOTE("No entry point");
  615.         ReleaseDirectDraw();
  616.         return E_NOINTERFACE;
  617.     }
  618.  
  619.     DbgLog((LOG_TRACE,3,TEXT("Creating DDraw for device %s"),
  620.                     szDevice ? szDevice : "<NULL>"));
  621.  
  622.     // Create a DirectDraw display provider for this device, using the fancy
  623.     // multimon-aware version, if it exists
  624.     if (pDrawEnumEx)
  625.         m_pDirectDraw = DirectDrawCreateFromDeviceEx(szDevice, pDrawCreate,
  626.                                 pDrawEnumEx);
  627.     else
  628.         m_pDirectDraw = DirectDrawCreateFromDevice(szDevice, pDrawCreate,
  629.                                 pDrawEnum);
  630.  
  631.     if (m_pDirectDraw == NULL) {
  632.             DbgLog((LOG_ERROR,1,TEXT("Can't create DDraw")));
  633.             NOTE("No instance");
  634.             ReleaseDirectDraw();
  635.             return E_NOINTERFACE;
  636.     }
  637.     return NOERROR;
  638. }
  639.  
  640.  
  641. // Called to release any DirectDraw provider we previously loaded. We may be
  642. // called at any time especially when something goes horribly wrong and when
  643. // we need to clean up before returning so we can't guarantee that all state
  644. // variables are consistent so free only those really allocated allocated
  645. // This should only be called once all reference counts have been released
  646.  
  647. void CLoadDirectDraw::ReleaseDirectDraw()
  648. {
  649.     NOTE("Releasing DirectDraw driver");
  650.  
  651.     // Release any DirectDraw provider interface
  652.  
  653.     if (m_pDirectDraw) {
  654.         NOTE("Releasing instance");
  655.         m_pDirectDraw->Release();
  656.         m_pDirectDraw = NULL;
  657.     }
  658.  
  659. }
  660.  
  661.  
  662. // Return NOERROR (S_OK) if DirectDraw has been loaded by this object
  663.  
  664. HRESULT CLoadDirectDraw::IsDirectDrawLoaded()
  665. {
  666.     NOTE("Entering IsDirectDrawLoaded");
  667.  
  668.     if (m_pDirectDraw == NULL) {
  669.         NOTE("DirectDraw not loaded");
  670.         return S_FALSE;
  671.     }
  672.     return NOERROR;
  673. }
  674.  
  675.  
  676. // Return the IDirectDraw interface we look after
  677.  
  678. LPDIRECTDRAW CLoadDirectDraw::GetDirectDraw()
  679. {
  680.     NOTE("Entering GetDirectDraw");
  681.  
  682.     if (m_pDirectDraw == NULL) {
  683.         NOTE("No DirectDraw");
  684.         return NULL;
  685.     }
  686.  
  687.     NOTE("Returning DirectDraw");
  688.     m_pDirectDraw->AddRef();
  689.     return m_pDirectDraw;
  690. }
  691.  
  692.  
  693. // Are we running on Direct Draw version 1?  We need to find out as
  694. // we rely on specific bug fixes in DirectDraw 2 for fullscreen playback. To
  695. // find out, we simply see if it supports IDirectDraw2.  Only version 2 and
  696. // higher support this.
  697.  
  698. BOOL CLoadDirectDraw::IsDirectDrawVersion1()
  699. {
  700.  
  701.     if (m_pDirectDraw == NULL)
  702.     return FALSE;
  703.  
  704.     IDirectDraw2 *p = NULL;
  705.     HRESULT hr = m_pDirectDraw->QueryInterface(IID_IDirectDraw2, (void **)&p);
  706.     if (p)
  707.     p->Release();
  708.     if (hr == NOERROR) {
  709.         DbgLog((LOG_TRACE,3,TEXT("Direct Draw Version 2 or greater")));
  710.     return FALSE;
  711.     } else {
  712.         DbgLog((LOG_TRACE,3,TEXT("Direct Draw Version 1")));
  713.     return TRUE;
  714.     }
  715. }
  716.