windows-nt/Source/XPSP1/NT/multimedia/directx/ddrawex/ddrawex.cpp
2020-09-26 16:20:57 +08:00

1019 lines
29 KiB
C++

/*==========================================================================
*
* Copyright (C) 1997 Microsoft Corporation. All Rights Reserved.
*
* File: ddrawex.cpp
* Content: new DirectDraw object support
* History:
* Date By Reason
* ==== == ======
* 24-feb-97 ralphl initial implementation
* 25-feb-97 craige minor tweaks for dx checkin; integrated IBitmapSurface
* stuff
* 03-mar-97 craige added palettes to CreateCompatibleBitmapSurface
* 06-mar-97 craige IDirectDrawSurface3 support
* 01-apr-97 jeffort Following changes checked in:
* Attachlist structure added (from ddrawi.h)
* Surface linked list handled
* D3D interfaces added to QueryInterface
* Complex surfaces are handled at CreateSurface calls
* CreatCompatibleBitmap changed to handle > 8bpp bitmaps
* Changed the call to GetPaletteEntries to use a handle to a palette
*
* 04-apr-97 jeffort Trident ifdef's removed
* IDirectDraw3 class implemntation
* paramter changed in recursive handling of attach lists
* 10-apr-97 jeffort Release of pSurface2 in creating a simple surface was incorrect
* this was already being done in surface.cpp
*
* 21-apr-97 jeffort Version Check for DX5 for QI of IDirectDrawSurface3
* 28-apr-97 jeffort Palette wrapping added/DX5 support
* 28-apr-97 jeffort Palette wrapping if CreatePalette fails in our internal
* function, cleanup code added
* 30-apr-97 jeffort No longer addref when querying for IDirect3D (done in ddraw QI)
* AddRef attached surfaces (release done in releasing the surface)
* 02-may-97 jeffort local variable changed from DWORD to WORD
*
* 08-may-97 jeffort Better parameter checking
* 09-may-97 jeffort If GetTransparentIndex has nothing set return OK/COLOR_NO_TRANSPARENT
* 16-may-97 jeffort A surface failing to be created is already released. The release here
* was removed.
* 20-may-97 jeffort GetFormatFromDC checks if this is a surface DC and gets the
* format from the surface instead of GetDeviceCaps
* 27-may-97 jeffort keep ref count on internal object eual to outer object
* 12-jun-97 jeffort reversed R and B fields in 32bpp PIXELFORMAT array
* 20-jun-97 jeffort added debug code to invaliudate objects when freed
* 27-jun-97 jeffort IDirectDrawSurface3 interface support for DX3 was not
* added. We now use an IDirectDrawSurface2 to spoof it
* so we can support SetSurfaceDesc
* 22-jul-97 jeffort Removed IBitmapSurface and associated interfaces
***************************************************************************/
#define INITGUID
#define CPP_FUNCTIONS
#include "ddfactry.h"
#define m_pDirectDraw (m_DDInt.m_pRealInterface)
#define m_pDirectDraw2 (m_DD2Int.m_pRealInterface)
#define m_pDirectDraw4 (m_DD4Int.m_pRealInterface)
typedef struct _ATTACHLIST
{
DWORD dwFlags;
struct _ATTACHLIST FAR *lpLink; // link to next attached surface
struct _DDRAWI_DDRAWSURFACE_LCL FAR *lpAttached; // attached surface local obj
struct _DDRAWI_DDRAWSURFACE_INT FAR *lpIAttached; // attached surface interface
} ATTACHLIST;
typedef ATTACHLIST FAR *LPATTACHLIST;
/*
* CDirectDrawEx::CDirectDrawEx
*
* Constructor for the new DirectDrawEx class
*/
CDirectDrawEx::CDirectDrawEx(IUnknown *pUnkOuter) :
m_cRef(1),
m_pUnkOuter(pUnkOuter != 0 ? pUnkOuter : CAST_TO_IUNKNOWN(this)),
m_pFirstSurface(NULL),
m_pFirstPalette(NULL),
m_pPrimaryPaletteList(NULL)
{
DllAddRef();
m_pDirectDraw = NULL;
m_pDirectDraw2 = NULL;
m_pDirectDraw4 = NULL;
m_DDInt.m_pDirectDrawEx = this;
m_DD2Int.m_pDirectDrawEx = this;
m_DD4Int.m_pDirectDrawEx = this;
} /* CDirectDrawEx::CDirectDrawEx */
/*
* CDirectDrawEx::Init
*/
HRESULT CDirectDrawEx::Init(
GUID * pGUID,
HWND hWnd,
DWORD dwCoopLevelFlags,
DWORD dwReserved,
LPDIRECTDRAWCREATE pDirectDrawCreate )
{
HRESULT hr;
if( dwReserved )
{
hr = DDERR_INVALIDPARAMS;
}
else
{
//DDraw will pop a dialog complaining about 4bpp modes, so we need to
//tell it not to. DDraw will sniff SEM and not pop the dialog if
//SEM_FAILCRITICALERRORS is set.
DWORD dw = SetErrorMode(SEM_FAILCRITICALERRORS);
SetErrorMode(dw | SEM_FAILCRITICALERRORS); // retain old flags too
hr = pDirectDrawCreate( pGUID, &m_pDirectDraw, NULL );
SetErrorMode(dw);
if( SUCCEEDED(hr) )
{
hr = m_pDirectDraw->SetCooperativeLevel(hWnd, dwCoopLevelFlags);
if( SUCCEEDED(hr) )
{
if (dwCoopLevelFlags & DDSCL_EXCLUSIVE)
m_bExclusive = TRUE;
else
m_bExclusive = FALSE;
hr = m_pDirectDraw->QueryInterface(IID_IDirectDraw2, (void **)&m_pDirectDraw2);
if( SUCCEEDED(hr) )
{
m_pDirectDraw->QueryInterface(IID_IDirectDraw4, (void **)&m_pDirectDraw4);
InitDirectDrawInterfaces(m_pDirectDraw, &m_DDInt, m_pDirectDraw2, &m_DD2Int, m_pDirectDraw4, &m_DD4Int);
}
}
}
}
return hr;
} /* CDirectDrawEx::Init */
/*
* CDirectDrawEx::~CDirectDrawEx
*
* destructor
*/
CDirectDrawEx::~CDirectDrawEx()
{
if( m_pDirectDraw )
{
m_pDirectDraw->Release();
}
if( m_pDirectDraw2 )
{
m_pDirectDraw2->Release();
}
if (m_pDirectDraw4)
{
m_pDirectDraw4->Release();
}
#ifdef DEBUG
DWORD * ptr;
ptr = (DWORD *)this;
for (int i = 0; i < sizeof(CDirectDrawEx) / sizeof(DWORD);i++)
*ptr++ = 0xDEADBEEF;
#endif
DllRelease();
} /* CDirectDrawEx::~CDirectDrawEx */
/*
* CDirectDrawEx::NonDelegatingQueryInterface
* NonDelegatingAddRef
* NonDelegatingRelease
*
* The base IUnknown interface (non-delegating)
*/
STDMETHODIMP CDirectDrawEx::NonDelegatingQueryInterface(REFIID riid, void ** ppv)
{
HRESULT hr;
*ppv=NULL;
if( IID_IUnknown == riid )
{
*ppv=(INonDelegatingUnknown *)this;
}
else if (IID_IDirectDraw3 == riid)
{
*ppv=(IDirectDraw3 *)this;
}
else if( IID_IDirectDraw==riid )
{
*ppv=&m_DDInt;
}
else if( IID_IDirectDraw2==riid )
{
*ppv=&m_DD2Int;
}
else if (IID_IDirectDraw4==riid && m_pDirectDraw4)
{
*ppv=&m_DD4Int;
}
else if (IID_IDirect3D == riid)
{
IUnknown* pUnk;
HRESULT (__stdcall *lpFunc)(IDirectDrawVtbl **,REFIID, void **);
*(DWORD *)(&lpFunc) = *(DWORD *)*(DWORD **)m_pDirectDraw;
hr = lpFunc(&(m_DDInt.lpVtbl), riid, (void **)&pUnk);
if( SUCCEEDED(hr) )
{
*ppv=pUnk;
}
else
{
*ppv = NULL;
}
return hr;
}
else if (IID_IDirect3D2 == riid)
{
IUnknown* pUnk;
HRESULT (__stdcall *lpFunc)(IDirectDrawVtbl **,REFIID, void **);
*(DWORD *)(&lpFunc) = *(DWORD *)*(DWORD **)m_pDirectDraw;
hr = lpFunc(&(m_DDInt.lpVtbl), riid, (void **)&pUnk);
if( SUCCEEDED(hr) )
{
*ppv=pUnk;
}
else
{
*ppv = NULL;
}
return hr;
}
else if (IID_IDirect3D3 == riid)
{
IUnknown* pUnk;
HRESULT (__stdcall *lpFunc)(IDirectDrawVtbl **,REFIID, void **);
*(DWORD *)(&lpFunc) = *(DWORD *)*(DWORD **)m_pDirectDraw;
hr = lpFunc(&(m_DDInt.lpVtbl), riid, (void **)&pUnk);
if( SUCCEEDED(hr) )
{
*ppv=pUnk;
}
else
{
*ppv = NULL;
}
return hr;
}
else
{
return E_NOINTERFACE;
}
((LPUNKNOWN)*ppv)->AddRef();
return NOERROR;
} /* CDirectDrawEx::NonDelegatingQueryInterface */
STDMETHODIMP_(ULONG) CDirectDrawEx::NonDelegatingAddRef()
{
m_pDirectDraw->AddRef();
return InterlockedIncrement(&m_cRef);
} /* CDirectDrawEx::NonDelegatingAddRef */
STDMETHODIMP_(ULONG) CDirectDrawEx::NonDelegatingRelease()
{
LONG lRefCount = InterlockedDecrement(&m_cRef);
if (lRefCount)
{
m_pDirectDraw->Release();
return lRefCount;
}
delete this;
return 0;
} /* CDirectDrawEx::NonDelegatingRelease */
/*
* CDirectDrawEx::QueryInterface
* AddRef
* Release
*
* The standard IUnknown that delegates...
*/
STDMETHODIMP CDirectDrawEx::QueryInterface(REFIID riid, void ** ppv)
{
return m_pUnkOuter->QueryInterface(riid, ppv);
} /* CDirectDrawEx::QueryInterface */
STDMETHODIMP_(ULONG) CDirectDrawEx::AddRef(void)
{
return m_pUnkOuter->AddRef();
} /* CDirectDrawEx::AddRef */
STDMETHODIMP_(ULONG) CDirectDrawEx::Release(void)
{
return m_pUnkOuter->Release();
} /* CDirectDrawEx::Release */
/*
* CDirectDrawEx::GetSurfaceFromDC
*
* Run the list of surfaces and find which one has this DC.
* Works with OWNDC surfaces only for now.
*/
STDMETHODIMP CDirectDrawEx::GetSurfaceFromDC(HDC hdc, IDirectDrawSurface **ppSurface)
{
HRESULT hr = DDERR_NOTFOUND;
if( !ppSurface )
{
hr = E_POINTER;
}
else
{
*ppSurface = NULL;
ENTER_DDEX();
CDDSurface *pSurface = m_pFirstSurface;
while( pSurface )
{
if( (pSurface->m_HDC == hdc) || (pSurface->m_hDCDib == hdc) )
{
hr = pSurface->m_pUnkOuter->QueryInterface(IID_IDirectDrawSurface, (void **)ppSurface);
break;
}
pSurface = pSurface->m_pNext;
}
LEAVE_DDEX();
}
return hr;
} /* CDirectDrawEx::GetSurfaceFromDC */
/*
* CDirectDrawEx::AddSurfaceToList
*
* Adds a surface to our doubly-linked surface list
*/
void CDirectDrawEx::AddSurfaceToList(CDDSurface *pSurface)
{
ENTER_DDEX();
if( m_pFirstSurface )
{
m_pFirstSurface->m_pPrev = pSurface;
}
pSurface->m_pPrev = NULL;
pSurface->m_pNext = m_pFirstSurface;
m_pFirstSurface = pSurface;
LEAVE_DDEX();
} /* CDirectDrawEx::AddSurfaceToList */
/*
* CDirectDrawEx::RemoveSurfaceToList
*
* Removes a surface to our doubly-linked surface list
*/
void CDirectDrawEx::RemoveSurfaceFromList(CDDSurface *pSurface)
{
ENTER_DDEX();
if( pSurface->m_pPrev )
{
pSurface->m_pPrev->m_pNext = pSurface->m_pNext;
}
else
{
m_pFirstSurface = pSurface->m_pNext;
}
if( pSurface->m_pNext )
{
pSurface->m_pNext->m_pPrev = pSurface->m_pPrev;
}
LEAVE_DDEX();
} /* CDirectDrawEx::RemoveSurfaceToList */
/*
* CDirectDrawEx::AddSurfaceToPrimarList
*
* Adds a surface to our doubly-linked surface list which use the primary palette
*/
void CDirectDrawEx::AddSurfaceToPrimaryList(CDDSurface *pSurface)
{
ENTER_DDEX();
if( m_pPrimaryPaletteList )
{
m_pPrimaryPaletteList->m_pPrevPalette = pSurface;
}
pSurface->m_pPrevPalette = NULL;
pSurface->m_pNextPalette = m_pPrimaryPaletteList;
m_pPrimaryPaletteList = pSurface;
pSurface->m_bPrimaryPalette = TRUE;
LEAVE_DDEX();
} /* CDirectDrawEx::AddSurfaceToList */
/*
* CDirectDrawEx::RemoveSurfaceFromPrimaryList
*
* Removes a surface to our doubly-linked surface list which use the primary palette
*/
void CDirectDrawEx::RemoveSurfaceFromPrimaryList(CDDSurface *pSurface)
{
ENTER_DDEX();
if( pSurface->m_pPrevPalette )
{
pSurface->m_pPrevPalette->m_pNextPalette = pSurface->m_pNextPalette;
}
else
{
m_pPrimaryPaletteList = pSurface->m_pNextPalette;
}
if( pSurface->m_pNextPalette )
{
pSurface->m_pNextPalette->m_pPrevPalette = pSurface->m_pPrevPalette;
}
pSurface->m_bPrimaryPalette = FALSE;
LEAVE_DDEX();
} /* CDirectDrawEx::RemoveSurfaceToList */
/*
* CDirectDrawEx::AddPaletteToList
*
* Adds a palette to our doubly-linked palette list
*/
void CDirectDrawEx::AddPaletteToList(CDDPalette *pPalette)
{
ENTER_DDEX();
if( m_pFirstPalette )
{
m_pFirstPalette->m_pPrev = pPalette;
}
pPalette->m_pPrev = NULL;
pPalette->m_pNext = m_pFirstPalette;
m_pFirstPalette = pPalette;
LEAVE_DDEX();
}
/*
* CDirectDrawEx::RemovePaletteToList
*
* Removes a palette to our doubly-linked palette list
*/
void CDirectDrawEx::RemovePaletteFromList(CDDPalette *pPalette)
{
ENTER_DDEX();
if( pPalette->m_pPrev )
{
pPalette->m_pPrev->m_pNext = pPalette->m_pNext;
}
else
{
m_pFirstPalette = pPalette->m_pNext;
}
if( pPalette->m_pNext )
{
pPalette->m_pNext->m_pPrev = pPalette->m_pPrev;
}
LEAVE_DDEX();
}
HRESULT CDirectDrawEx::CreateSimpleSurface(LPDDSURFACEDESC pSurfaceDesc, IUnknown *pUnkOuter, IDirectDrawSurface * pSurface, IDirectDrawSurface **ppNewSurface, DWORD dwFlags)
{
IDirectDrawSurface2 *pSurface2 = NULL;
IDirectDrawSurface3 *pSurface3 = NULL;
HRESULT hr;
hr = pSurface->QueryInterface(IID_IDirectDrawSurface2, (void **)&pSurface2);
if (FAILED(hr))
return hr;
//we only want to do this Query if we are on DX5 or above. On DX3, this is not supported,
//and this call will cause D3D to be loaded
pSurface3 = NULL;
if (m_dwDDVer == WIN95_DX5 || m_dwDDVer == WINNT_DX5)
{
hr = pSurface->QueryInterface(IID_IDirectDrawSurface3, (void **)&pSurface3);
if( FAILED( hr ) )
{
pSurface3 = NULL;
}
}
if (pSurface3 == NULL)
hr = pSurface->QueryInterface(IID_IDirectDrawSurface2, (void **)&pSurface3);
if (FAILED(hr))
return hr;
IDirectDrawSurface4 *pSurface4 = NULL;
//
// It's fine if this does not work... Just ignore return code.
//
pSurface->QueryInterface(IID_IDirectDrawSurface4, (void **)&pSurface4);
hr = CDDSurface::CreateSimpleSurface(
pSurfaceDesc,
pSurface,
pSurface2,
pSurface3,
pSurface4,
pUnkOuter,
this,
ppNewSurface,
dwFlags);
return hr;
}
HRESULT CDirectDrawEx::HandleAttachList(LPDDSURFACEDESC pSurfaceDesc, IUnknown *pUnkOuter,IDirectDrawSurface **ppNewSurface, IDirectDrawSurface * pOrigSurf, DWORD dwFlags)
{
IDirectDrawSurface *pSurface;
IDirectDrawSurface *pSurfaceReturn;
DDSURFACEDESC SurfaceDesc;
HRESULT hr;
//create the necessary SurfaceData here
pSurface = *ppNewSurface;
SurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
//add ref the attached surface here
pSurface->AddRef();
hr = pSurface->GetSurfaceDesc(&SurfaceDesc);
if (!SUCCEEDED(hr))
return hr;
hr = CreateSimpleSurface(&SurfaceDesc, pUnkOuter, pSurface, (IDirectDrawSurface **)&pSurfaceReturn, dwFlags);
if (!SUCCEEDED(hr))
return hr;
//we got here via an attachlist, so we need to recurse into the structure more
LPATTACHLIST lpAttach;
lpAttach = (LPATTACHLIST)(((LPDDRAWI_DDRAWSURFACE_INT)(pSurface))->lpLcl->lpAttachList);
while (lpAttach != NULL){
pSurface = (IDirectDrawSurface *)((LPATTACHLIST)(((LPDDRAWI_DDRAWSURFACE_INT)(pSurface))->lpLcl->lpAttachList))->lpIAttached;
lpAttach = lpAttach->lpLink;
if (pSurface != pOrigSurf){
hr = HandleAttachList(pSurfaceDesc, pUnkOuter, &pSurface, pOrigSurf, dwFlags);
if (!SUCCEEDED(hr))
return hr;
}
}
return hr;
}
/*
* CDirectDrawEx::CreateSurface
*
* Create a DirectDraw surface that supports OWNDC
*/
STDMETHODIMP CDirectDrawEx::CreateSurface(LPDDSURFACEDESC pSurfaceDesc, IDirectDrawSurface **ppNewSurface, IUnknown *pUnkOuter)
{
DWORD origcaps;
DWORD newcaps;
DWORD dwFlags;
IDirectDrawSurface *pSurface;
if (pSurfaceDesc == NULL)
return DDERR_INVALIDPARAMS;
if (ppNewSurface == NULL)
return DDERR_INVALIDPARAMS;
origcaps = pSurfaceDesc->ddsCaps.dwCaps;
newcaps = origcaps;
/*
* If OWNDC is specified, it must be a system memory surface
*/
if ((origcaps & (DDSCAPS_OWNDC | DDSCAPS_SYSTEMMEMORY)) == DDSCAPS_OWNDC)
{
return DDERR_INVALIDCAPS;
}
/*
* DATAEXCHANGE has some magic...
*/
if( (origcaps & DDSCAPS_DATAEXCHANGE) == DDSCAPS_DATAEXCHANGE )
{
dwFlags = SURFACE_DATAEXCHANGE;
//Do not allow the primary surface with these caps!!!!
if (origcaps & DDSCAPS_PRIMARYSURFACE)
return DDERR_INVALIDCAPS;
newcaps &= ~DDSCAPS_DATAEXCHANGE;
newcaps |= DDSCAPS_SYSTEMMEMORY | DDSCAPS_OWNDC | DDSCAPS_TEXTURE;
if (newcaps & DDSCAPS_OFFSCREENPLAIN)
newcaps &= ~DDSCAPS_OFFSCREENPLAIN;
}
else
dwFlags = 0;
/*
* turn off OWNDC when going to DirectDraw 3
*/
if (m_dwDDVer != WIN95_DX5 && m_dwDDVer != WINNT_DX5)
newcaps &= ~DDSCAPS_OWNDC;
/*
* go create the surface (without the OWNDC attribute)
*/
pSurfaceDesc->ddsCaps.dwCaps = newcaps;
HRESULT hr = m_pDirectDraw->CreateSurface(pSurfaceDesc, &pSurface, NULL);
pSurfaceDesc->ddsCaps.dwCaps = origcaps;
/*
* once we have the object, get any additional interfaces we need
* to support and then create our surface object
*/
if( SUCCEEDED(hr) )
{
hr = CreateSimpleSurface(pSurfaceDesc, pUnkOuter, pSurface, ppNewSurface, dwFlags);
if (!SUCCEEDED(hr))
{
return hr;
}
//we need to worry about attached surfaces, do so here
LPATTACHLIST lpAttach;
//add the current surface to our list of surfaces
IDirectDrawSurface * pOrigSurf = pSurface;
lpAttach = (LPATTACHLIST)(((LPDDRAWI_DDRAWSURFACE_INT)(pSurface))->lpLcl->lpAttachList);
while (lpAttach != NULL)
{
lpAttach = lpAttach->lpLink;
pSurface = (IDirectDrawSurface *)((LPATTACHLIST)(((LPDDRAWI_DDRAWSURFACE_INT)(pSurface))->lpLcl->lpAttachList))->lpIAttached;
hr = HandleAttachList(pSurfaceDesc, pUnkOuter, &pSurface, pOrigSurf, dwFlags);
if (!SUCCEEDED(hr))
{
//we need to drop out of the loop and clean up
lpAttach = NULL;
}
}
if (!SUCCEEDED(hr))
{
// pSurface = (IDirectDrawSurface *)((LPATTACHLIST)(((LPDDRAWI_DDRAWSURFACE_INT)(pOrigSurf))->lpLcl->lpAttachList))->lpIAttached;
// lpAttach = (LPATTACHLIST)(((LPDDRAWI_DDRAWSURFACE_INT)(pSurface))->lpLcl->lpAttachList);
while (lpAttach != NULL)
{
//clean up these surfaces
lpAttach = lpAttach->lpLink;
}
}
}
return hr;
} /* CDirectDrawEX::CreateSurface */
//
// This is a modified copy of the above except using surfacedesc2 and surface4
//
STDMETHODIMP CDirectDrawEx::CreateSurface(LPDDSURFACEDESC2 pSurfaceDesc2, IDirectDrawSurface4 **ppNewSurface4, IUnknown *pUnkOuter)
{
DWORD origcaps;
DWORD newcaps;
DWORD dwFlags;
IDirectDrawSurface4 *pSurface4;
if (pSurfaceDesc2 == NULL)
return DDERR_INVALIDPARAMS;
if (ppNewSurface4 == NULL)
return DDERR_INVALIDPARAMS;
origcaps = pSurfaceDesc2->ddsCaps.dwCaps;
newcaps = origcaps;
/*
* If OWNDC is specified, it must be a system memory surface
*/
if ((origcaps & (DDSCAPS_OWNDC | DDSCAPS_SYSTEMMEMORY)) == DDSCAPS_OWNDC)
{
return DDERR_INVALIDCAPS;
}
/*
* DATAEXCHANGE has some magic...
*/
if( (origcaps & DDSCAPS_DATAEXCHANGE) == DDSCAPS_DATAEXCHANGE )
{
dwFlags = SURFACE_DATAEXCHANGE;
//Do not allow the primary surface with these caps!!!!
if (origcaps & DDSCAPS_PRIMARYSURFACE)
return DDERR_INVALIDCAPS;
newcaps &= ~DDSCAPS_DATAEXCHANGE;
newcaps |= DDSCAPS_SYSTEMMEMORY | DDSCAPS_OWNDC | DDSCAPS_TEXTURE;
if (newcaps & DDSCAPS_OFFSCREENPLAIN)
newcaps &= ~DDSCAPS_OFFSCREENPLAIN;
}
else
dwFlags = 0;
/*
* turn off OWNDC when going to DirectDraw 3
*/
if (m_dwDDVer != WIN95_DX5 && m_dwDDVer != WINNT_DX5)
newcaps &= ~DDSCAPS_OWNDC;
/*
* go create the surface (without the OWNDC attribute)
*/
pSurfaceDesc2->ddsCaps.dwCaps = newcaps;
HRESULT hr = m_pDirectDraw4->CreateSurface(pSurfaceDesc2, &pSurface4, NULL);
pSurfaceDesc2->ddsCaps.dwCaps = origcaps;
/*
* once we have the object, get any additional interfaces we need
* to support and then create our surface object
*/
if( SUCCEEDED(hr) )
{
IDirectDrawSurface * pSurface;
pSurface4->QueryInterface(IID_IDirectDrawSurface, (void **)&pSurface);
pSurface4->Release();
DDSURFACEDESC ddsd;
ddsd.dwSize = sizeof(ddsd);
pSurface->GetSurfaceDesc(&ddsd);
ddsd.ddsCaps.dwCaps = origcaps;
IDirectDrawSurface *pNewSurf1;
hr = CreateSimpleSurface(&ddsd, pUnkOuter, pSurface, &pNewSurf1, dwFlags);
if (!SUCCEEDED(hr))
{
return hr;
}
pNewSurf1->QueryInterface(IID_IDirectDrawSurface4, (void **)ppNewSurface4);
pNewSurf1->Release();
//we need to worry about attached surfaces, do so here
LPATTACHLIST lpAttach;
//add the current surface to our list of surfaces
IDirectDrawSurface * pOrigSurf = pSurface;
lpAttach = (LPATTACHLIST)(((LPDDRAWI_DDRAWSURFACE_INT)(pSurface))->lpLcl->lpAttachList);
while (lpAttach != NULL)
{
lpAttach = lpAttach->lpLink;
pSurface = (IDirectDrawSurface *)((LPATTACHLIST)(((LPDDRAWI_DDRAWSURFACE_INT)(pSurface))->lpLcl->lpAttachList))->lpIAttached;
hr = HandleAttachList(&ddsd, pUnkOuter, &pSurface, pOrigSurf, dwFlags);
if (!SUCCEEDED(hr))
{
//we need to drop out of the loop and clean up
lpAttach = NULL;
}
}
if (!SUCCEEDED(hr))
{
// pSurface = (IDirectDrawSurface *)((LPATTACHLIST)(((LPDDRAWI_DDRAWSURFACE_INT)(pOrigSurf))->lpLcl->lpAttachList))->lpIAttached;
// lpAttach = (LPATTACHLIST)(((LPDDRAWI_DDRAWSURFACE_INT)(pSurface))->lpLcl->lpAttachList);
while (lpAttach != NULL)
{
//clean up these surfaces
lpAttach = lpAttach->lpLink;
}
}
}
return hr;
} /* CDirectDrawEX::CreateSurface */
STDMETHODIMP CDirectDrawEx::CreatePalette(DWORD dwFlags, LPPALETTEENTRY pEntries, LPDIRECTDRAWPALETTE FAR * ppPal, IUnknown FAR * pUnkOuter)
{
IDirectDrawPalette *pPalette;
HRESULT hr = m_pDirectDraw->CreatePalette(dwFlags, pEntries, &pPalette, NULL);
if (SUCCEEDED(hr))
{
hr = CDDPalette::CreateSimplePalette(pEntries, pPalette, ppPal, pUnkOuter, this);
if (FAILED(hr))
{
//we were unable to create our palette structure, so we must delete the palette
//we created here and fail
pPalette->Release();
*ppPal = NULL;
}
}
return hr;
}
STDMETHODIMP CDirectDrawEx::SetCooperativeLevel(HWND hwnd, DWORD dwFlags)
{
HRESULT hr = m_pDirectDraw->SetCooperativeLevel(hwnd, dwFlags);
//check for exclusive mode here
if (dwFlags & DDSCL_EXCLUSIVE)
m_bExclusive = TRUE;
else
m_bExclusive = FALSE;
return hr;
}
/*
* some quicky inline fns to get at our object data
*/
_inline CDirectDrawEx * PARENTOF(IDirectDraw * pDD)
{
return ((INTSTRUC_IDirectDraw *)pDD)->m_pDirectDrawEx;
}
_inline CDirectDrawEx * PARENTOF(IDirectDraw2 * pDD2)
{
return ((INTSTRUC_IDirectDraw2 *)pDD2)->m_pDirectDrawEx;
}
_inline CDirectDrawEx * PARENTOF(IDirectDraw4 * pDD4)
{
return ((INTSTRUC_IDirectDraw4 *)pDD4)->m_pDirectDrawEx;
}
/*
* the implementation of the functions in IDirectDraw that we are overriding
* (IUnknown and CreateSurface)
*/
STDMETHODIMP_(ULONG) IDirectDrawAggAddRef(IDirectDraw *pDD)
{
return PARENTOF(pDD)->m_pUnkOuter->AddRef();
}
STDMETHODIMP_(ULONG) IDirectDrawAggRelease(IDirectDraw *pDD)
{
return PARENTOF(pDD)->m_pUnkOuter->Release();
}
STDMETHODIMP IDirectDrawAggCreateSurface(IDirectDraw *pDD, LPDDSURFACEDESC pSurfaceDesc,
IDirectDrawSurface **ppNewSurface, IUnknown *pUnkOuter)
{
return PARENTOF(pDD)->CreateSurface(pSurfaceDesc, ppNewSurface, pUnkOuter);
}
STDMETHODIMP IDirectDrawAggCreatePalette(IDirectDraw *pDD,DWORD dwFlags, LPPALETTEENTRY pEntries, LPDIRECTDRAWPALETTE FAR * ppPal, IUnknown FAR * pUnkOuter)
{
return PARENTOF(pDD)->CreatePalette( dwFlags, pEntries, ppPal, pUnkOuter);
}
STDMETHODIMP IDirectDrawAggSetCooperativeLevel(IDirectDraw * pDD, HWND hwnd, DWORD dwFlags)
{
return PARENTOF(pDD)->SetCooperativeLevel(hwnd, dwFlags);
}
/*
* the implementation of the functions in IDirectDraw2 that we are overriding
* (IUnknown and CreateSurface)
*/
STDMETHODIMP_(ULONG) IDirectDraw2AggAddRef(IDirectDraw2 *pDD)
{
return PARENTOF(pDD)->m_pUnkOuter->AddRef();
}
STDMETHODIMP_(ULONG) IDirectDraw2AggRelease(IDirectDraw2 *pDD)
{
return PARENTOF(pDD)->m_pUnkOuter->Release();
}
STDMETHODIMP IDirectDraw2AggCreateSurface(IDirectDraw2 *pDD, LPDDSURFACEDESC pSurfaceDesc,
IDirectDrawSurface **ppNewSurface, IUnknown *pUnkOuter)
{
return PARENTOF(pDD)->CreateSurface(pSurfaceDesc, ppNewSurface, pUnkOuter);
}
STDMETHODIMP IDirectDraw2AggCreatePalette(IDirectDraw2 *pDD,DWORD dwFlags, LPPALETTEENTRY pEntries, LPDIRECTDRAWPALETTE FAR * ppPal, IUnknown FAR * pUnkOuter)
{
return PARENTOF(pDD)->CreatePalette( dwFlags, pEntries, ppPal, pUnkOuter);
}
STDMETHODIMP IDirectDraw2AggSetCooperativeLevel(IDirectDraw2 * pDD, HWND hwnd, DWORD dwFlags)
{
return PARENTOF(pDD)->SetCooperativeLevel(hwnd, dwFlags);
}
/***************************************************************************
*
*
* IDirectDraw3 stuff follows
*
*
***************************************************************************/
STDMETHODIMP CDirectDrawEx::Compact()
{
return m_pDirectDraw2->Compact();
}
STDMETHODIMP CDirectDrawEx::CreateClipper(DWORD dwParam, LPDIRECTDRAWCLIPPER FAR* pClip, IUnknown FAR * pIUnk )
{
return m_pDirectDraw2->CreateClipper(dwParam, pClip, pIUnk);
}
STDMETHODIMP CDirectDrawEx::DuplicateSurface(LPDIRECTDRAWSURFACE pSurf, LPDIRECTDRAWSURFACE FAR * ppSurf2)
{
return m_pDirectDraw2->DuplicateSurface(pSurf, ppSurf2);
}
STDMETHODIMP CDirectDrawEx::EnumDisplayModes(DWORD dwParam, LPDDSURFACEDESC pSurfDesc, LPVOID pPtr, LPDDENUMMODESCALLBACK pCallback )
{
return m_pDirectDraw2->EnumDisplayModes(dwParam, pSurfDesc, pPtr, pCallback);
}
STDMETHODIMP CDirectDrawEx::EnumSurfaces(DWORD dwParam, LPDDSURFACEDESC pSurfDesc, LPVOID pPtr,LPDDENUMSURFACESCALLBACK pCallback)
{
return m_pDirectDraw2->EnumSurfaces(dwParam, pSurfDesc, pPtr, pCallback);
}
STDMETHODIMP CDirectDrawEx::FlipToGDISurface()
{
return m_pDirectDraw2->FlipToGDISurface();
}
STDMETHODIMP CDirectDrawEx::GetCaps(LPDDCAPS pDDCaps1, LPDDCAPS pDDCaps2)
{
return m_pDirectDraw2->GetCaps(pDDCaps1, pDDCaps2);
}
STDMETHODIMP CDirectDrawEx::GetDisplayMode(LPDDSURFACEDESC pSurfDesc)
{
return m_pDirectDraw2->GetDisplayMode(pSurfDesc);
}
STDMETHODIMP CDirectDrawEx::GetFourCCCodes(LPDWORD pDW1, LPDWORD pDW2 )
{
return m_pDirectDraw2->GetFourCCCodes(pDW1, pDW2);
}
STDMETHODIMP CDirectDrawEx::GetGDISurface(LPDIRECTDRAWSURFACE FAR * ppSurf)
{
return m_pDirectDraw2->GetGDISurface(ppSurf);
}
STDMETHODIMP CDirectDrawEx::GetMonitorFrequency(LPDWORD pParam)
{
return m_pDirectDraw2->GetMonitorFrequency(pParam);
}
STDMETHODIMP CDirectDrawEx::GetScanLine(LPDWORD pParam)
{
return m_pDirectDraw2->GetScanLine(pParam);
}
STDMETHODIMP CDirectDrawEx::GetVerticalBlankStatus(LPBOOL lpParam )
{
return m_pDirectDraw2->GetVerticalBlankStatus(lpParam);
}
STDMETHODIMP CDirectDrawEx::Initialize(GUID FAR * pGUID)
{
return m_pDirectDraw2->Initialize(pGUID);
}
STDMETHODIMP CDirectDrawEx::RestoreDisplayMode()
{
return m_pDirectDraw2->RestoreDisplayMode();
}
STDMETHODIMP CDirectDrawEx::SetDisplayMode(DWORD dw1, DWORD dw2, DWORD dw3, DWORD dw4, DWORD dw5)
{
return m_pDirectDraw2->SetDisplayMode(dw1, dw2, dw3, dw4, dw5);
}
STDMETHODIMP CDirectDrawEx::WaitForVerticalBlank(DWORD dw1, HANDLE hdl)
{
return m_pDirectDraw2->WaitForVerticalBlank(dw1, hdl);
}
STDMETHODIMP CDirectDrawEx::GetAvailableVidMem(LPDDSCAPS pDDSCaps, LPDWORD pParam1, LPDWORD pParam2)
{
return m_pDirectDraw2->GetAvailableVidMem(pDDSCaps, pParam1, pParam2);
}
/*
* the implementation of the functions in IDirectDraw4 that we are overriding
* (IUnknown and CreateSurface)
*/
STDMETHODIMP_(ULONG) IDirectDraw4AggAddRef(IDirectDraw4 *pDD)
{
return PARENTOF(pDD)->m_pUnkOuter->AddRef();
}
STDMETHODIMP_(ULONG) IDirectDraw4AggRelease(IDirectDraw4 *pDD)
{
return PARENTOF(pDD)->m_pUnkOuter->Release();
}
STDMETHODIMP IDirectDraw4AggCreateSurface(IDirectDraw4 *pDD, LPDDSURFACEDESC2 pSurfaceDesc2,
IDirectDrawSurface4 **ppNewSurface4, IUnknown *pUnkOuter)
{
return PARENTOF(pDD)->CreateSurface(pSurfaceDesc2, ppNewSurface4, pUnkOuter);
}
STDMETHODIMP IDirectDraw4AggCreatePalette(IDirectDraw4 *pDD,DWORD dwFlags, LPPALETTEENTRY pEntries, LPDIRECTDRAWPALETTE FAR * ppPal, IUnknown FAR * pUnkOuter)
{
return PARENTOF(pDD)->CreatePalette( dwFlags, pEntries, ppPal, pUnkOuter);
}
STDMETHODIMP IDirectDraw4AggSetCooperativeLevel(IDirectDraw4 * pDD, HWND hwnd, DWORD dwFlags)
{
return PARENTOF(pDD)->SetCooperativeLevel(hwnd, dwFlags);
}