/*========================================================================== * * 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); }