306 lines
7.6 KiB
C++
306 lines
7.6 KiB
C++
/*==========================================================================
|
|
*
|
|
* Copyright (C) 1997 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: palette.cpp
|
|
* Content: new DirectDraw object support
|
|
* History:
|
|
* Date By Reason
|
|
* ==== == ======
|
|
* 22-apr-97 jeffort initial implementation
|
|
* 30-apr-97 jeffort critical section shared from ddrawex object
|
|
* 27-may-97 jeffort keep ref count on internal object eual to outer object
|
|
* 18-jun-97 jeffort linked list fix, we were using m_pNext instead of m_pNextPalette
|
|
* 20-jun-97 jeffort added debug code to invaliudate objects when freed
|
|
* 08-jul-97 jeffort switched order of releasing real palette interface BEFORE ddrawex release
|
|
* due to the fact if ddraw is released before hand we will GP fault
|
|
***************************************************************************/
|
|
#include "ddfactry.h"
|
|
|
|
#define m_pDDPalette (m_DDPInt.m_pRealInterface)
|
|
|
|
|
|
|
|
CDDPalette::CDDPalette( IDirectDrawPalette * pDDPalette,
|
|
IUnknown *pUnkOuter,
|
|
CDirectDrawEx *pDirectDrawEx) :
|
|
m_cRef(1),
|
|
m_pUnkOuter(pUnkOuter != 0 ? pUnkOuter : CAST_TO_IUNKNOWN(this)),
|
|
m_pDirectDrawEx(pDirectDrawEx)
|
|
{
|
|
|
|
m_DDPInt.m_pSimplePalette = this;
|
|
m_pDDPalette = pDDPalette;
|
|
m_pFirstSurface = NULL;
|
|
InitDirectDrawPaletteInterfaces( pDDPalette, &m_DDPInt);
|
|
pDirectDrawEx->AddRef();
|
|
pDirectDrawEx->AddPaletteToList(this);
|
|
DllAddRef();
|
|
|
|
}
|
|
|
|
|
|
|
|
CDDPalette::~CDDPalette()
|
|
{
|
|
/*
|
|
* clean up...
|
|
*/
|
|
//we must mark any surfaces in our list as having no palette
|
|
//we are running this list, must bracket by critical section
|
|
|
|
CDDSurface *pSurface = m_pFirstSurface;
|
|
|
|
ENTER_DDEX();
|
|
while (pSurface != NULL)
|
|
{
|
|
pSurface->m_pCurrentPalette = NULL;
|
|
pSurface = pSurface->m_pNextPalette;
|
|
}
|
|
//if this is the primary surface, go down the primary list and mark the current palette as null
|
|
if (m_bIsPrimary)
|
|
{
|
|
CDDSurface *pSurface = m_pDirectDrawEx->m_pPrimaryPaletteList;
|
|
while (pSurface != NULL)
|
|
{
|
|
pSurface->m_pCurrentPalette = NULL;
|
|
pSurface = pSurface->m_pNextPalette;
|
|
}
|
|
}
|
|
LEAVE_DDEX();
|
|
m_pDirectDrawEx->RemovePaletteFromList(this);
|
|
m_pDDPalette->Release();
|
|
m_pDirectDrawEx->Release();
|
|
DllRelease();
|
|
#ifdef DEBUG
|
|
DWORD * ptr;
|
|
ptr = (DWORD *)this;
|
|
for (int i = 0; i < sizeof(CDDPalette) / sizeof(DWORD);i++)
|
|
*ptr++ = 0xDEADBEEF;
|
|
#endif
|
|
} /* CDDSurface::~CDDSurface */
|
|
|
|
|
|
|
|
|
|
/*
|
|
* CDirectDrawEx::AddSurfaceToList
|
|
*
|
|
* Adds a surface to our doubly-linked list of surfaces conatining this palette
|
|
*/
|
|
void CDDPalette::AddSurfaceToList(CDDSurface *pSurface)
|
|
{
|
|
ENTER_DDEX();
|
|
if( m_pFirstSurface )
|
|
{
|
|
m_pFirstSurface->m_pPrevPalette = pSurface;
|
|
}
|
|
pSurface->m_pPrevPalette = NULL;
|
|
pSurface->m_pNextPalette = m_pFirstSurface;
|
|
m_pFirstSurface = pSurface;
|
|
LEAVE_DDEX();
|
|
|
|
}
|
|
|
|
/*
|
|
* CDirectDrawEx::RemoveSurfaceFromList
|
|
*
|
|
* Removes a surface from our doubly-linked surface list
|
|
*/
|
|
void CDDPalette::RemoveSurfaceFromList(CDDSurface *pSurface)
|
|
{
|
|
ENTER_DDEX();
|
|
if( pSurface->m_pPrevPalette )
|
|
{
|
|
pSurface->m_pPrevPalette->m_pNextPalette = pSurface->m_pNextPalette;
|
|
}
|
|
else
|
|
{
|
|
m_pFirstSurface = pSurface->m_pNextPalette;
|
|
}
|
|
if( pSurface->m_pNextPalette )
|
|
{
|
|
pSurface->m_pNextPalette->m_pPrevPalette = pSurface->m_pPrevPalette;
|
|
}
|
|
LEAVE_DDEX();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HRESULT CDDPalette::CreateSimplePalette(LPPALETTEENTRY pEntries,
|
|
IDirectDrawPalette *pDDPalette,
|
|
LPDIRECTDRAWPALETTE FAR * ppPal,
|
|
IUnknown FAR * pUnkOuter,
|
|
CDirectDrawEx *pDirectDrawEx)
|
|
{
|
|
HRESULT hr = DD_OK;
|
|
CDDPalette *pPalette = new CDDPalette(pDDPalette,
|
|
pUnkOuter,
|
|
pDirectDrawEx);
|
|
if( !pPalette)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
pPalette->NonDelegatingQueryInterface(pUnkOuter ? IID_IUnknown : IID_IDirectDrawPalette, (void **)ppPal);
|
|
pPalette->NonDelegatingRelease();
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
HRESULT CDDPalette::SetColorTable (CDDSurface * pSurface, LPPALETTEENTRY pEntries, DWORD dwNumEntries, DWORD dwBase)
|
|
{
|
|
//cal SetDIBColorTable here
|
|
RGBQUAD rgbq[256];
|
|
HDC hdc;
|
|
HRESULT hr;
|
|
|
|
hr = DD_OK;
|
|
if (pSurface->m_bOwnDC)
|
|
{
|
|
if( pSurface->m_hDCDib )
|
|
{
|
|
hdc = pSurface->m_hDCDib;
|
|
}
|
|
else if( pSurface->m_bOwnDC )
|
|
{
|
|
hdc = pSurface->m_HDC;
|
|
}
|
|
else
|
|
{
|
|
return DD_OK;
|
|
}
|
|
// we need to copy the entries here for
|
|
// a logical palette
|
|
// we need to ues the struct as a LogPal struct
|
|
for( int i=0;i<(int) dwNumEntries;i++ )
|
|
{
|
|
rgbq[i].rgbBlue = pEntries[i].peBlue;
|
|
rgbq[i].rgbGreen = pEntries[i].peGreen;
|
|
rgbq[i].rgbRed = pEntries[i].peRed;
|
|
rgbq[i].rgbReserved = 0;
|
|
}
|
|
SetDIBColorTable(hdc, dwBase, dwNumEntries, rgbq);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CDDPalette::InternalSetEntries(DWORD dwFlags, DWORD dwBase, DWORD dwNumEntries, LPPALETTEENTRY lpe)
|
|
{
|
|
HRESULT hr;
|
|
CDDSurface *pSurfaceList;
|
|
|
|
hr = m_pDDPalette->SetEntries(dwFlags, dwBase, dwNumEntries, lpe);
|
|
//now we need to traverse the list of Surfaces and if OWNDC is set, set the DibSection ColorTable
|
|
if (m_bIsPrimary)
|
|
pSurfaceList = m_pDirectDrawEx->m_pPrimaryPaletteList;
|
|
else
|
|
pSurfaceList = m_pFirstSurface;
|
|
|
|
while (pSurfaceList != NULL)
|
|
{
|
|
SetColorTable(pSurfaceList, lpe, dwNumEntries, dwBase);
|
|
pSurfaceList = pSurfaceList->m_pNextPalette;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CDDPalette::QueryInterface(REFIID riid, void ** ppv)
|
|
{
|
|
return m_pUnkOuter->QueryInterface(riid, ppv);
|
|
|
|
} /* CDirectDrawEx::QueryInterface */
|
|
|
|
STDMETHODIMP_(ULONG) CDDPalette::AddRef(void)
|
|
{
|
|
return m_pUnkOuter->AddRef();
|
|
|
|
} /* CDirectDrawEx::AddRef */
|
|
|
|
STDMETHODIMP_(ULONG) CDDPalette::Release(void)
|
|
{
|
|
return m_pUnkOuter->Release();
|
|
|
|
} /* CDirectDrawEx::Release */
|
|
|
|
/*
|
|
* NonDelegating IUnknown for simple surface follows...
|
|
*/
|
|
|
|
STDMETHODIMP CDDPalette::NonDelegatingQueryInterface(REFIID riid, void ** ppv)
|
|
{
|
|
// HRESULT hr;
|
|
|
|
*ppv=NULL;
|
|
|
|
if( IID_IUnknown==riid )
|
|
{
|
|
*ppv=(INonDelegatingUnknown *)this;
|
|
}
|
|
else if( IID_IDirectDrawPalette==riid )
|
|
{
|
|
*ppv=&m_DDPInt;
|
|
}
|
|
|
|
else
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
((LPUNKNOWN)*ppv)->AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CDDPalette::NonDelegatingAddRef()
|
|
{
|
|
//addref the internal palette interface
|
|
m_pDDPalette->AddRef();
|
|
return InterlockedIncrement(&m_cRef);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CDDPalette::NonDelegatingRelease()
|
|
{
|
|
LONG lRefCount = InterlockedDecrement(&m_cRef);
|
|
if (lRefCount) {
|
|
//we need to release the internal interface as well
|
|
m_pDDPalette->Release();
|
|
return lRefCount;
|
|
}
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Quick inline fns to get at our internal data...
|
|
*/
|
|
_inline CDDPalette * PALETTEOF(IDirectDrawPalette * pDDP)
|
|
{
|
|
return ((INTSTRUC_IDirectDrawPalette *)pDDP)->m_pSimplePalette;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP_(ULONG) IDirectDrawPaletteAggAddRef(IDirectDrawPalette *pDDP)
|
|
{
|
|
return PALETTEOF(pDDP)->m_pUnkOuter->AddRef();
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) IDirectDrawPaletteAggRelease(IDirectDrawPalette *pDDP)
|
|
{
|
|
return PALETTEOF(pDDP)->m_pUnkOuter->Release();
|
|
}
|
|
|
|
|
|
STDMETHODIMP IDirectDrawPaletteAggSetEntries(IDirectDrawPalette *pDDP, DWORD dw1, DWORD dw2, DWORD dw3, LPPALETTEENTRY lpe)
|
|
{
|
|
return PALETTEOF(pDDP)->InternalSetEntries(dw1, dw2, dw3, lpe);
|
|
}
|