1019 lines
29 KiB
C++
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);
|
|
}
|