Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2145 lines
59 KiB

/*==========================================================================
*
* Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
*
* File: ddpal.c
* Content: DirectDraw palette functions
* History:
* Date By Reason
* ==== == ======
* 27-jan-95 craige initial implementation
* 11-mar-95 craige more HAL fns, filled out CreatePalette
* 19-mar-95 craige use HRESULTs, process termination cleanup fixes
* 26-mar-95 craige filled out remaining fns
* 28-mar-95 craige switched to PALETTEENTRY from RGBQUAD
* 31-mar-95 craige use critical sections with palettes
* 01-apr-95 craige happy fun joy updated header file
* 04-apr-95 craige use driver directly in exclusive mode
* 07-apr-95 craige bug 14 - check GUID ptr in QI
* 10-apr-95 craige mods to process list stuff
* bug 3,16 - palette issues: use driver in excl. mode
* 12-apr-95 craige don't use GETCURRPID all the time; proper csect ordering
* 06-may-95 craige use driver-level csects only
* 12-may-95 craige check for real guids in QI
* 02-jun-95 craige extra parm in AddToActiveProcessList
* 12-jun-95 craige new process list stuff
* 20-jun-95 kylej moved palette emulation code into ddhel
* 21-jun-95 craige couple of internal inteface cleanup issues
* 25-jun-95 craige one ddraw mutex
* 26-jun-95 craige reorganized surface structure
* 28-jun-95 craige ENTER_DDRAW at very start of fns
* 02-jul-95 craige implemented GetCaps; added SEH for parm. validation
* 04-jul-95 craige YEEHAW: new driver struct
* 05-jul-95 craige added Initialize
* 08-jul-95 kylej Surface and DirectDraw Palette calls require
* exclusive mode. Removed ResetSysPalette. Make a
* SetPalette call to the HAL/HEL to detach a palette.
* 11-jul-95 craige fail aggregation calls
* 13-jul-95 craige bug 94 - flag validation fixes
* 20-jul-95 craige stop palette code from running non-palettized
* 31-jul-95 toddla unselect palette in InternalPaletteRelease
* 31-jul-95 craige validate flags
* 21-aug-95 craige mode X support
* 27-aug-95 craige bug 735: added SetPaletteAlways
* bug 742: use ALLOW256
* 14-oct-95 colinmc add support for attaching palettes to offscreen and
* texture map surfaces
* 07-nov-95 colinmc support for 1, 2 and 4-bit palettes and palette
* sharing added
* 09-dec-95 colinmc added execute buffer support
* 02-jan-96 kylej handle new interface structs
* 09-feb-96 colinmc surface lost flag moved from global to local object
* 03-mar-96 colinmc fixed problem with QueryInterface returning local
* object rather than interface.
* 13-mar-96 colinmc added IID validation to QueryInterface
* 16-mar-96 colinmc fixed problem with palettes being released too many
* times
* 19-mar-96 colinmc Bug 12129: Bogus lpColorTable causes CreatePalette
* to bomb
* 19-apr-96 colinmc Bug 17473: CreatePalette faults on bogus palette
* pointer
* 02-may-96 kylej Bug 20066: GetPalette doesn't NULL pointer on failure
* 23-sep-96 ketand Added TIMING routines
* 24-mar-97 jeffno Optimized Surfaces
* 26-nov-97 t-craigs Added IDirectDrawPalette2 stuff
*
***************************************************************************/
#include "ddrawpr.h"
#define SIZE_DDPCAPS (DDPCAPS_1BIT | DDPCAPS_2BIT | DDPCAPS_4BIT | DDPCAPS_8BIT)
#define PE_FLAGS (PC_NOCOLLAPSE |PC_RESERVED)
#define BITS_PER_BITFIELD_ENTRY (sizeof(DWORD)*8)
/*
* Generate a palette handle. We keep a bitfiled in the ddraw local that
* tells us if we can recycle a handle. Note that handles are 1-based,
* and these routines deal with that
*/
DWORD GeneratePaletteHandle(LPDDRAWI_DIRECTDRAW_LCL lpDD_lcl)
{
DWORD cbits,*pdw;
/*
* Check for an unused entry in the palette-handle-used bitfield. We check
*/
for (cbits=0; cbits< lpDD_lcl->cbitsPaletteBitfieldBitCount; cbits++ )
{
if ( 0 == (lpDD_lcl->pPaletteHandleUsedBitfield[cbits/BITS_PER_BITFIELD_ENTRY]
& (1<<(cbits % BITS_PER_BITFIELD_ENTRY))) )
{
/*
* Found a recycled handle
*/
lpDD_lcl->pPaletteHandleUsedBitfield[cbits/BITS_PER_BITFIELD_ENTRY] |=
(1<<(cbits % BITS_PER_BITFIELD_ENTRY));
return cbits+1; //plus one since 0 is error return
}
}
/*
* Didn't find a recycled entry. Get a new handle
*/
DDASSERT( cbits == lpDD_lcl->cbitsPaletteBitfieldBitCount );
if ( (cbits% BITS_PER_BITFIELD_ENTRY) == 0)
{
/*
* Have to grow the table since the current table fits exactly in a number of DWORDs
*/
pdw = MemAlloc( ((cbits / BITS_PER_BITFIELD_ENTRY) +1)*sizeof(DWORD) );
if (pdw)
{
/*
* Couldn't convince myself the MemRealloc both worked and would zero remaining space.
*/
memcpy(pdw, lpDD_lcl->pPaletteHandleUsedBitfield,
(cbits / BITS_PER_BITFIELD_ENTRY) * sizeof(DWORD) );
MemFree(lpDD_lcl->pPaletteHandleUsedBitfield);
lpDD_lcl->pPaletteHandleUsedBitfield = pdw;
}
else
{
return 0;
}
}
/*
* Table is big enough. Grab the entry and mark it.
*/
cbits = lpDD_lcl->cbitsPaletteBitfieldBitCount++;
lpDD_lcl->pPaletteHandleUsedBitfield[cbits/BITS_PER_BITFIELD_ENTRY] |=
(1<<(cbits % BITS_PER_BITFIELD_ENTRY));
return cbits+1; //+1 since zero is an error return, and it helps out drivers to know 0 is invalid
}
void FreePaletteHandle(LPDDRAWI_DIRECTDRAW_LCL lpDD_lcl, DWORD dwHandle)
{
DDASSERT( dwHandle <= lpDD_lcl->cbitsPaletteBitfieldBitCount );
if (dwHandle == 0)
return;
dwHandle -=1; //since handles are 1-based
lpDD_lcl->pPaletteHandleUsedBitfield[dwHandle/BITS_PER_BITFIELD_ENTRY] &=
~(1<<(dwHandle % BITS_PER_BITFIELD_ENTRY));
}
/*
* newPaletteInterface
*
* Construct a new palette interface which points to an existing local object.
*/
static LPVOID newPaletteInterface( LPDDRAWI_DDRAWPALETTE_LCL this_lcl, LPVOID lpvtbl )
{
LPDDRAWI_DDRAWPALETTE_INT pnew_int;
LPDDRAWI_DIRECTDRAW_GBL pdrv;
pnew_int = MemAlloc( sizeof( DDRAWI_DDRAWPALETTE_INT ));
if( NULL == pnew_int )
{
return NULL;
}
/*
* set up data
*/
pnew_int->lpVtbl = lpvtbl;
pnew_int->lpLcl = this_lcl;
pnew_int->dwIntRefCnt = 0;
/*
* link this into the global list of palettes
*/
pdrv = this_lcl->lpDD_lcl->lpGbl;
pnew_int->lpLink = pdrv->palList;
pdrv->palList = pnew_int;
return pnew_int;
} /* newPaletteInterface */
#undef DPF_MODNAME
#define DPF_MODNAME "Palette::QueryInterface"
/*
* DD_Palette_QueryInterface
*/
HRESULT DDAPI DD_Palette_QueryInterface(
LPDIRECTDRAWPALETTE lpDDPalette,
REFIID riid,
LPVOID FAR * ppvObj )
{
LPDDRAWI_DDRAWPALETTE_GBL this;
LPDDRAWI_DDRAWPALETTE_LCL this_lcl;
LPDDRAWI_DDRAWPALETTE_INT this_int;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_Palette_QueryInterface");
TRY
{
this_int = (LPDDRAWI_DDRAWPALETTE_INT) lpDDPalette;
if( !VALID_DIRECTDRAWPALETTE_PTR( this_int ) )
{
DPF_ERR( "Invalid palette pointer" );
LEAVE_DDRAW();
return (DWORD) DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
if( !VALID_PTR_PTR( ppvObj ) )
{
DPF( 1, "Invalid palette pointer" );
LEAVE_DDRAW();
return (DWORD) DDERR_INVALIDPARAMS;
}
if( !VALIDEX_IID_PTR( riid ) )
{
DPF_ERR( "Invalid IID pointer" );
LEAVE_DDRAW();
return (DWORD) DDERR_INVALIDPARAMS;
}
this = this_lcl->lpGbl;
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return (DWORD) DDERR_INVALIDPARAMS;
}
if( IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid, &IID_IDirectDrawPalette) )
{
if( this_int->lpVtbl == (LPVOID) &ddPaletteCallbacks )
*ppvObj = (LPVOID) this_int;
else
*ppvObj = (LPVOID) newPaletteInterface( this_lcl, (LPVOID)&ddPaletteCallbacks );
if( NULL == *ppvObj )
{
LEAVE_DDRAW();
return E_NOINTERFACE;
}
else
{
DD_Palette_AddRef( *ppvObj );
LEAVE_DDRAW();
return DD_OK;
}
}
#ifdef POSTPONED
if (IsEqualIID(riid, &IID_IPersist))
{
/*
* if this is already an IID_IPersist interface, just
* addref and return
*/
if( this_int->lpVtbl == (LPVOID) &ddPalettePersistCallbacks )
*ppvObj = (LPVOID) this_int;
else
*ppvObj = (LPVOID) newPaletteInterface( this_lcl, (LPVOID)&ddPalettePersistCallbacks );
if( NULL == *ppvObj )
{
LEAVE_DDRAW();
return E_NOINTERFACE;
}
else
{
DD_Palette_AddRef( *ppvObj );
LEAVE_DDRAW();
return DD_OK;
}
}
if (IsEqualIID(riid, &IID_IPersistStream))
{
/*
* if this is already an IID_IPersistStream interface, just
* addref and return
*/
if( this_int->lpVtbl == (LPVOID) &ddPalettePersistStreamCallbacks )
*ppvObj = (LPVOID) this_int;
else
*ppvObj = (LPVOID) newPaletteInterface( this_lcl, (LPVOID)&ddPalettePersistStreamCallbacks );
if( NULL == *ppvObj )
{
LEAVE_DDRAW();
return E_NOINTERFACE;
}
else
{
DD_Palette_AddRef( *ppvObj );
LEAVE_DDRAW();
return DD_OK;
}
}
if (IsEqualIID(riid, &IID_IDirectDrawPalette2))
{
/*
* if this is already an IID_IDirectDrawPalette2 interface, just
* addref and return
*/
if( this_int->lpVtbl == (LPVOID) &ddPalette2Callbacks )
*ppvObj = (LPVOID) this_int;
else
*ppvObj = (LPVOID) newPaletteInterface( this_lcl, (LPVOID)&ddPalette2Callbacks );
if( NULL == *ppvObj )
{
LEAVE_DDRAW();
return E_NOINTERFACE;
}
else
{
DD_Palette_AddRef( *ppvObj );
LEAVE_DDRAW();
return DD_OK;
}
}
#endif //POSTPONED
LEAVE_DDRAW();
return (DWORD) DDERR_GENERIC;
} /* DD_Palette_QueryInterface */
#undef DPF_MODNAME
#define DPF_MODNAME "Palette::AddRef"
/*
* DD_Palette_AddRef
*/
DWORD DDAPI DD_Palette_AddRef( LPDIRECTDRAWPALETTE lpDDPalette )
{
LPDDRAWI_DDRAWPALETTE_GBL this;
LPDDRAWI_DDRAWPALETTE_LCL this_lcl;
LPDDRAWI_DDRAWPALETTE_INT this_int;
DWORD rcnt;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_Palette_AddRef");
TRY
{
this_int = (LPDDRAWI_DDRAWPALETTE_INT) lpDDPalette;
if( !VALID_DIRECTDRAWPALETTE_PTR( this_int ) )
{
LEAVE_DDRAW();
return 0;
}
this_lcl = this_int->lpLcl;
this = this_lcl->lpGbl;
/*
* update palette reference count
*/
this->dwRefCnt++;
this_lcl->dwLocalRefCnt++;
this_int->dwIntRefCnt++;
rcnt = this_lcl->dwLocalRefCnt & ~OBJECT_ISROOT;
DPF( 5, "Palette %08lx addrefed, refcnt = %ld,%ld,%ld",
this_lcl, this->dwRefCnt, rcnt,
this_int->dwIntRefCnt );
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return 0;
}
LEAVE_DDRAW();
return this_int->dwIntRefCnt;
} /* DD_Palette_AddRef */
#undef DPF_MODNAME
#define DPF_MODNAME "Palette::Release"
/*
* InternalPaletteRelease
*
* Done with a palette. if no one else is using it, then we can free it.
* Also called by ProcessPaletteCleanup
*/
ULONG DDAPI InternalPaletteRelease( LPDDRAWI_DDRAWPALETTE_INT this_int )
{
DWORD intrefcnt;
DWORD lclrefcnt;
DWORD gblrefcnt;
BOOL root_object_deleted;
BOOL do_free;
ULONG rc;
DDHAL_DESTROYPALETTEDATA dpd;
LPDDRAWI_DDRAWPALETTE_GBL this;
LPDDRAWI_DDRAWPALETTE_INT curr_int;
LPDDRAWI_DDRAWPALETTE_LCL this_lcl;
LPDDRAWI_DDRAWPALETTE_INT last_int;
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
LPDDRAWI_DIRECTDRAW_GBL pdrv;
IUnknown * pOwner = NULL;
this_lcl = this_int->lpLcl;
this = this_lcl->lpGbl;
pdrv_lcl = this->lpDD_lcl;
pdrv = pdrv_lcl->lpGbl;
/*
* decrement reference count to this palette. If it hits zero,
* cleanup
*/
this->dwRefCnt--;
this_lcl->dwLocalRefCnt--;
this_int->dwIntRefCnt--;
intrefcnt = this_int->dwIntRefCnt;
lclrefcnt = this_lcl->dwLocalRefCnt & ~OBJECT_ISROOT;
gblrefcnt = this->dwRefCnt;
DPF( 5, "Palette %08lx released, refcnt = %ld,%ld,%ld", this_int, gblrefcnt, lclrefcnt, intrefcnt );
/*
* local object gone?
*/
root_object_deleted = FALSE;
if( lclrefcnt == 0 )
{
/*
* Remove private data
*/
FreeAllPrivateData( &this_lcl->pPrivateDataHead );
/*
* If the ddraw interface which created this palette caused the surface to addref the ddraw
* object, then we need to release that addref now.
*/
pOwner = this_lcl->pAddrefedThisOwner;
/*
* see if we are deleting the root object
*/
if( this_lcl->dwLocalRefCnt & OBJECT_ISROOT )
{
root_object_deleted = TRUE;
}
}
/*
* did the object get globally deleted?
*/
do_free = FALSE;
if( gblrefcnt == 0 )
{
LPDDHALPALCB_DESTROYPALETTE dphalfn;
LPDDHALPALCB_DESTROYPALETTE dpfn;
BOOL emulation;
do_free = TRUE;
/*
* if this palette is selected into the primary, unselect it!
*/
if (pdrv_lcl && pdrv_lcl->lpPrimary &&
pdrv_lcl->lpPrimary->lpLcl->lpDDPalette == this_int)
{
SetPaletteAlways(pdrv_lcl->lpPrimary, NULL);
}
FreePaletteHandle( pdrv_lcl, this->dwHandle );
/*
* destroy the hardware
*/
if( ( pdrv_lcl->lpDDCB->HALDDPalette.DestroyPalette == NULL ) ||
( this->dwFlags & DDRAWIPAL_INHEL ) )
{
// use HEL
dpfn = pdrv_lcl->lpDDCB->HELDDPalette.DestroyPalette;
dphalfn = dpfn;
emulation = TRUE;
}
else
{
// use HAL
dpfn = pdrv_lcl->lpDDCB->HALDDPalette.DestroyPalette;
dphalfn = pdrv_lcl->lpDDCB->cbDDPaletteCallbacks.DestroyPalette;
emulation = FALSE;
}
if( dphalfn != NULL )
{
dpd.DestroyPalette = dphalfn;
dpd.lpDD = pdrv_lcl->lpGbl;
dpd.lpDDPalette = this;
DOHALCALL( DestroyPalette, dpfn, dpd, rc, emulation );
if( rc == DDHAL_DRIVER_HANDLED )
{
if( dpd.ddRVal != DD_OK )
{
DPF_ERR( "HAL call failed" );
/*
* If the palette took a ref count on the ddraw object that created it,
* release that ref now as the very last thing
* We don't want to do this on ddhelp's thread cuz it really mucks up the
* process cleanup stuff.
*/
if (pOwner && (dwHelperPid != GetCurrentProcessId()) )
{
pOwner->lpVtbl->Release(pOwner);
}
/* GEE: What do we do here since we no longer return
* error codes from Release.
*/
return (DWORD) dpd.ddRVal;
}
}
/*
* Moved here from ddhel.c. Non-display drivers mean that the hel isn't called for palette
* destroy, so we were leaking palette tables. It's called exactly here to most closely
* duplicate the old behaviour, but reduce any risk of drivers using the color table or whatever.
*/
if (this->lpColorTable)
{
MemFree(this->lpColorTable);
this->lpColorTable = NULL;
}
}
else
{
/*
* We can't do this; we've already committed to releasing at
* this point!
*/
// couldn't handle it
// return (ULONG)DDERR_UNSUPPORTED;
}
/*
* if this was the final delete, but this wasn't the root object,
* then we need to delete the dangling root object
*/
if( !root_object_deleted )
{
LPVOID root_lcl;
root_lcl = (LPVOID) (((LPBYTE) this) - sizeof( DDRAWI_DDRAWPALETTE_LCL ) );
MemFree( root_lcl );
}
}
else if( lclrefcnt == 0 )
{
/*
* only remove the object if it wasn't the root. if it
* was the root, we must leave it dangling until the last
* object referencing it goes away.
*/
if( !root_object_deleted )
{
do_free = TRUE;
}
}
/*
* free the object if needed
*/
if( do_free )
{
/*
* just in case someone comes back in with this pointer, set
* an invalid vtbl & data ptr.
*/
this_lcl->lpGbl = NULL;
MemFree( this_lcl );
}
/*
* need to delete the interface?
*/
if( intrefcnt == 0 )
{
/*
* remove palette from list of all palettes
*/
curr_int = pdrv->palList;
last_int = NULL;
while( curr_int != this_int )
{
last_int = curr_int;
curr_int = curr_int->lpLink;
if( curr_int == NULL )
{
return 0;
}
}
if( last_int == NULL )
{
pdrv->palList = pdrv->palList->lpLink;
}
else
{
last_int->lpLink = curr_int->lpLink;
}
/*
* Invalidate the interface
*/
this_int->lpVtbl = NULL;
this_int->lpLcl = NULL;
MemFree( this_int );
}
/*
* If the palette took a ref count on the ddraw object that created it,
* release that ref now as the very last thing
* We don't want to do this on ddhelp's thread cuz it really mucks up the
* process cleanup stuff.
*/
if (pOwner && (dwHelperPid != GetCurrentProcessId()) )
{
pOwner->lpVtbl->Release(pOwner);
}
return intrefcnt;
} /* InternalPaletteRelease */
/*
* DD_Palette_Release
*
* Done with a palette. if no one else is using it, then we can free it.
*/
ULONG DDAPI DD_Palette_Release( LPDIRECTDRAWPALETTE lpDDPalette )
{
LPDDRAWI_DDRAWPALETTE_GBL this;
LPDDRAWI_DDRAWPALETTE_LCL this_lcl;
LPDDRAWI_DDRAWPALETTE_INT this_int;
ULONG rc;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_Palette_Release");
TRY
{
this_int = (LPDDRAWI_DDRAWPALETTE_INT) lpDDPalette;
if( !VALIDEX_DIRECTDRAWPALETTE_PTR( this_int ) )
{
LEAVE_DDRAW();
return 0;
}
this_lcl = this_int->lpLcl;
this = this_lcl->lpGbl;
rc = InternalPaletteRelease( this_int );
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return 0;
}
LEAVE_DDRAW();
return rc;
} /* DD_Palette_Release */
#undef DPF_MODNAME
#define DPF_MODNAME "GetCaps"
/*
* DD_Palette_GetCaps
*/
HRESULT DDAPI DD_Palette_GetCaps(
LPDIRECTDRAWPALETTE lpDDPalette,
LPDWORD lpdwCaps )
{
LPDDRAWI_DDRAWPALETTE_GBL this;
LPDDRAWI_DDRAWPALETTE_LCL this_lcl;
LPDDRAWI_DDRAWPALETTE_INT this_int;
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
DWORD caps;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_Palette_GetCaps");
TRY
{
this_int = (LPDDRAWI_DDRAWPALETTE_INT) lpDDPalette;
if( !VALID_DIRECTDRAWPALETTE_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
if( !VALID_DWORD_PTR( lpdwCaps ) )
{
DPF_ERR( "invalid caps pointer" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
*lpdwCaps = 0;
this = this_lcl->lpGbl;
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* basic palette size caps.
*/
caps = SIZE_FLAGS_TO_PCAPS( this->dwFlags );
/*
* is this palette attached to the primary?
*/
pdrv_lcl = this->lpDD_lcl;
if (pdrv_lcl && pdrv_lcl->lpPrimary && pdrv_lcl->lpPrimary->lpLcl->lpDDPalette &&
(pdrv_lcl->lpPrimary->lpLcl->lpDDPalette == this_int))
caps |= DDPCAPS_PRIMARYSURFACE;
/*
* an allow256 palette?
*/
if( this->dwFlags & DDRAWIPAL_ALLOW256 )
{
caps |= DDPCAPS_ALLOW256;
}
/*
* does this palette store indices into an 8-bit destination
* palette.
*/
if( this->dwFlags & DDRAWIPAL_STORED_8INDEX )
{
caps |= DDPCAPS_8BITENTRIES;
}
*lpdwCaps = caps;
LEAVE_DDRAW();
return DD_OK;
} /* DD_Palette_GetCaps */
#undef DPF_MODNAME
#define DPF_MODNAME "Initialize"
/*
* DD_Palette_Initialize
*/
HRESULT DDAPI DD_Palette_Initialize(
LPDIRECTDRAWPALETTE lpDDPalette,
LPDIRECTDRAW lpDD,
DWORD dwFlags,
LPPALETTEENTRY lpDDColorTable )
{
DPF_ERR( "DirectDrawPalette: DD_Palette_Initialize");
DPF(2,A,"ENTERAPI: ");
return DDERR_ALREADYINITIALIZED;
} /* DD_Palette_Initialize */
#undef DPF_MODNAME
#define DPF_MODNAME "SetEntries"
/*
* DD_Palette_SetEntries
*/
HRESULT DDAPI DD_Palette_SetEntries(
LPDIRECTDRAWPALETTE lpDDPalette,
DWORD dwFlags,
DWORD dwBase,
DWORD dwNumEntries,
LPPALETTEENTRY lpEntries )
{
LPDDRAWI_DDRAWPALETTE_INT this_int;
LPDDRAWI_DDRAWPALETTE_LCL this_lcl;
LPDDRAWI_DDRAWPALETTE_GBL this;
DWORD rc;
DDHAL_SETENTRIESDATA sed;
LPDDRAWI_DIRECTDRAW_GBL pdrv;
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
LPDDHALPALCB_SETENTRIES sehalfn;
LPDDHALPALCB_SETENTRIES sefn;
DWORD size;
BOOL emulation;
DWORD entry_size;
ENTER_BOTH();
DPF(2,A,"ENTERAPI: DD_Palette_SetEntries");
TRY
{
this_int = (LPDDRAWI_DDRAWPALETTE_INT) lpDDPalette;
if( !VALID_DIRECTDRAWPALETTE_PTR( this_int ) )
{
LEAVE_BOTH();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
if( dwFlags )
{
DPF_ERR( "Invalid flags" );
LEAVE_BOTH();
return DDERR_INVALIDPARAMS;
}
this = this_lcl->lpGbl;
/*
* check number of entries
*/
size = FLAGS_TO_SIZE( this->dwFlags );
if( dwNumEntries < 1 || dwNumEntries > size )
{
DPF_ERR( "Invalid number of entries" );
LEAVE_BOTH();
return DDERR_INVALIDPARAMS;
}
if( dwBase >= size )
{
DPF_ERR( "Invalid base palette index" );
LEAVE_BOTH();
return DDERR_INVALIDPARAMS;
}
if( dwNumEntries+dwBase > size )
{
DPF_ERR( "palette indices requested would go past the end of the palette" );
LEAVE_BOTH();
return DDERR_INVALIDPARAMS;
}
if( this->dwFlags & DDRAWIPAL_STORED_8INDEX )
{
entry_size = sizeof( BYTE );
if( !VALID_BYTE_ARRAY( lpEntries, dwNumEntries ) )
{
DPF_ERR( "Invalid 8-bit palette index array" );
LEAVE_BOTH();
return DDERR_INVALIDPARAMS;
}
}
else
{
entry_size = sizeof( PALETTEENTRY );
if( !VALID_PALETTEENTRY_ARRAY( lpEntries, dwNumEntries ) )
{
DPF_ERR( "Invalid PALETTEENTRY array" );
LEAVE_BOTH();
return DDERR_INVALIDPARAMS;
}
}
pdrv_lcl = this->lpDD_lcl;
pdrv = pdrv_lcl->lpGbl;
/*
* copy the entries
*/
memcpy( ((LPBYTE)this->lpColorTable) + (entry_size * dwBase),
lpEntries, dwNumEntries * entry_size );
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_BOTH();
return DDERR_INVALIDPARAMS;
}
if( ( pdrv_lcl->lpDDCB->HALDDPalette.SetEntries == NULL ) ||
( this->dwFlags & DDRAWIPAL_INHEL ) )
{
// use HEL
sefn = pdrv_lcl->lpDDCB->HELDDPalette.SetEntries;
sehalfn = sefn;
emulation = TRUE;
}
else
{
// use HAL
sefn = pdrv_lcl->lpDDCB->HALDDPalette.SetEntries;
sehalfn = pdrv_lcl->lpDDCB->cbDDPaletteCallbacks.SetEntries;
emulation = FALSE;
}
if( sehalfn != NULL )
{
sed.SetEntries = sehalfn;
sed.lpDD = pdrv;
sed.lpDDPalette = this;
sed.dwBase = dwBase;
sed.dwNumEntries = dwNumEntries;
sed.lpEntries = lpEntries;
DOHALCALL_NOWIN16( SetEntries, sefn, sed, rc, emulation );
if( rc == DDHAL_DRIVER_HANDLED )
{
if( sed.ddRVal != DD_OK )
{
DPF( 5, "DDHAL_SetEntries: ddrval = %ld", sed.ddRVal );
LEAVE_BOTH();
return (DWORD) sed.ddRVal;
}
// We have now set the palette as we have been asked; so
// we may need to update some outstanding DCs.
UpdateDCOnPaletteChanges( this );
}
}
else
{
LEAVE_BOTH();
return DDERR_UNSUPPORTED;
}
BUMP_PALETTE_STAMP(this);
/*
* If the palette's handle is non-zero, that means the palette has already been exposed to the
* driver by a palette associate notify call. If the handle is zero, then the driver has never
* seen the palette before and doesn't care about setentries for it. The driver will get its
* first setentries immediately after the setpalette call (See DD_Surface_SetPalette)
* Mustn't do this on ddhelp's context, since the DLL will be long gone. (Note this should never
* happen anyway).
*/
if( dwHelperPid != GetCurrentProcessId() )
{
if (this->dwHandle)
{
if ( pdrv_lcl->pPaletteUpdateNotify && pdrv_lcl->pD3DIUnknown)
{
pdrv_lcl->pPaletteUpdateNotify( pdrv_lcl->pD3DIUnknown, this->dwHandle , dwBase, dwNumEntries, lpEntries );
}
}
}
LEAVE_BOTH();
return DD_OK;
} /* DD_Palette_SetEntries */
#undef DPF_MODNAME
#define DPF_MODNAME "GetEntries"
/*
* DD_Palette_GetEntries
*/
HRESULT DDAPI DD_Palette_GetEntries(
LPDIRECTDRAWPALETTE lpDDPalette,
DWORD dwFlags,
DWORD dwBase,
DWORD dwNumEntries,
LPPALETTEENTRY lpEntries )
{
LPDDRAWI_DDRAWPALETTE_INT this_int;
LPDDRAWI_DDRAWPALETTE_LCL this_lcl;
LPDDRAWI_DDRAWPALETTE_GBL this;
DWORD size;
DWORD entry_size;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_Palette_GetEntries");
TRY
{
this_int = (LPDDRAWI_DDRAWPALETTE_INT) lpDDPalette;
if( !VALID_DIRECTDRAWPALETTE_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
if( dwFlags )
{
DPF_ERR( "Invalid flags" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
this = this_lcl->lpGbl;
/*
* check number of entries
*/
size = FLAGS_TO_SIZE( this->dwFlags );
if( dwNumEntries < 1 || dwNumEntries > size )
{
DPF_ERR( "Invalid number of entries" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( dwBase >= size )
{
DPF_ERR( "Invalid base palette index" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( dwNumEntries+dwBase > size )
{
DPF_ERR( "palette indices requested would go past the end of the palette" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( this->dwFlags & DDRAWIPAL_STORED_8INDEX )
{
entry_size = sizeof( BYTE );
if( !VALID_BYTE_ARRAY( lpEntries, dwNumEntries ) )
{
DPF_ERR( "Invalid 8-bit palette index array" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
else
{
entry_size = sizeof( PALETTEENTRY );
if( !VALID_PALETTEENTRY_ARRAY( lpEntries, dwNumEntries ) )
{
DPF_ERR( "Invalid PALETTEENTRY array" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
/* GetEntries function body */
memcpy( lpEntries, ((LPBYTE)this->lpColorTable) + (dwBase * entry_size),
dwNumEntries * entry_size );
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
LEAVE_DDRAW();
return DD_OK;
} /* DD_Palette_GetEntries */
#undef DPF_MODNAME
#define DPF_MODNAME "GetPalette"
/*
* DD_Surface_GetPalette
*
* Surface function: get the palette associated with surface
*/
HRESULT DDAPI DD_Surface_GetPalette(
LPDIRECTDRAWSURFACE lpDDSurface,
LPDIRECTDRAWPALETTE FAR * lplpDDPalette)
{
LPDDRAWI_DDRAWSURFACE_INT this_int;
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
LPDDRAWI_DDRAWSURFACE_GBL this;
HRESULT hr;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_Surface_GetPalette");
TRY
{
if( !VALID_PTR_PTR( lplpDDPalette ) )
{
DPF_ERR( "Invalid palette pointer" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
*lplpDDPalette = NULL; // in case we fail
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
this = this_lcl->lpGbl;
if( SURFACE_LOST( this_lcl ) )
{
LEAVE_DDRAW();
return DDERR_SURFACELOST;
}
//
// For now, if the current surface is optimized, quit
//
if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
{
DPF_ERR( "It is an optimized surface" );
LEAVE_DDRAW();
return DDERR_ISOPTIMIZEDSURFACE;
}
if( this_lcl->lpDDPalette == NULL )
{
DPF( 1, "No palette associated with surface" );
LEAVE_DDRAW();
return DDERR_NOPALETTEATTACHED;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
#ifdef POSTPONED
if (LOWERTHANSURFACE4(this_int))
{
hr = DD_Palette_QueryInterface(
(LPDIRECTDRAWPALETTE) this_lcl->lpDDPalette,
&IID_IDirectDrawPalette,
(void**)lplpDDPalette );
}
else
{
hr = DD_Palette_QueryInterface(
(LPDIRECTDRAWPALETTE) this_lcl->lpDDPalette,
&IID_IDirectDrawPalette2,
(void**)lplpDDPalette );
}
#else
hr = DD_Palette_QueryInterface(
(LPDIRECTDRAWPALETTE) this_lcl->lpDDPalette,
&IID_IDirectDrawPalette,
(void**)lplpDDPalette );
#endif
LEAVE_DDRAW();
return hr;
} /* DD_Surface_GetPalette */
#undef DPF_MODNAME
#define DPF_MODNAME "SetPalette"
/*
* DD_Surface_SetPalette
*
* Surface function: set the palette associated with surface
*
* NOTE: Currently the only way a windowed app. has of
* realizing its palette on the primary is to call SetPalette
* (full screen app. palette's are realized for them by the
* WM_ACTIVATEAPP hook). Hence, the logic is to AddRef the
* palette only if it is not already set as the surface's
* palette).
* Perhaps we need a RealizePalette() call?
*/
HRESULT DDAPI DD_Surface_SetPalette(
LPDIRECTDRAWSURFACE lpDDSurface,
LPDIRECTDRAWPALETTE lpDDPalette )
{
LPDDRAWI_DDRAWSURFACE_INT this_int;
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
LPDDRAWI_DDRAWSURFACE_GBL this;
LPDDRAWI_DDRAWPALETTE_INT this_pal_int;
LPDDRAWI_DDRAWPALETTE_LCL this_pal_lcl;
LPDDRAWI_DDRAWPALETTE_GBL this_pal;
LPDDRAWI_DDRAWPALETTE_INT prev_pal_int;
LPDDPIXELFORMAT pddpf;
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
LPDDRAWI_DIRECTDRAW_GBL pdrv;
BOOL attach;
DWORD rc;
DDHAL_SETPALETTEDATA spd;
LPDDHALSURFCB_SETPALETTE sphalfn;
LPDDHALSURFCB_SETPALETTE spfn;
BOOL emulation;
BOOL isprimary;
BOOL excl_exists;
BOOL has_excl;
ENTER_BOTH();
DPF(2,A,"ENTERAPI: DD_Surface_SetPalette");
TRY
{
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
{
LEAVE_BOTH();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
this = this_lcl->lpGbl;
//
// For now, if the current surface is optimized, quit
//
if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
{
DPF_ERR( "It is an optimized surface" );
LEAVE_DDRAW();
return DDERR_ISOPTIMIZEDSURFACE;
}
/*
* Palettes don't make any sense on z-buffers or execute
* buffers.
*/
if( this_lcl->ddsCaps.dwCaps & ( DDSCAPS_ZBUFFER | DDSCAPS_EXECUTEBUFFER ) )
{
DPF_ERR( "Invalid surface type: cannot attach palette" );
LEAVE_BOTH();
return DDERR_INVALIDSURFACETYPE;
}
//
// New interfaces don't let mipmap sublevels have palettes
//
if ((!LOWERTHANSURFACE7(this_int)) &&
(this_lcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL))
{
DPF_ERR( "Cannot attach palette to mipmap sublevels" );
LEAVE_BOTH();
return DDERR_NOTONMIPMAPSUBLEVEL;
}
if( SURFACE_LOST( this_lcl ) )
{
LEAVE_BOTH();
return DDERR_SURFACELOST;
}
this_pal_int = (LPDDRAWI_DDRAWPALETTE_INT) lpDDPalette;
if( this_pal_int != NULL )
{
if( !VALID_DIRECTDRAWPALETTE_PTR( this_pal_int ) )
{
LEAVE_BOTH();
return DDERR_INVALIDOBJECT;
}
this_pal_lcl = this_pal_int->lpLcl;
this_pal = this_pal_lcl->lpGbl;
}
else
{
this_pal_lcl = NULL;
this_pal = NULL;
}
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
pdrv = pdrv_lcl->lpGbl;
if ( this_pal_int &&
(this_pal->dwFlags & DDRAWIPAL_ALPHA) &&
(! (this_lcl->ddsCaps.dwCaps & DDSCAPS_TEXTURE)) )
{
DPF_ERR( "Attaching palette w/alpha to non-texture surface" );
LEAVE_BOTH();
return DDERR_INVALIDSURFACETYPE;
}
/*
* don't allow a palette from one global to be
* used with a different one (because it doesn't work)
*/
if( this_pal_int && pdrv != this_pal_lcl->lpDD_lcl->lpGbl )
{
/*
* Don't check if either device isn't a display driver (i.e. 3dfx)
* since that's a back-compat hole.
*/
if ( (this->lpDD->dwFlags & DDRAWI_DISPLAYDRV) &&
(this_pal_lcl->lpDD_lcl->lpGbl->dwFlags & DDRAWI_DISPLAYDRV) )
{
DPF_ERR( "Can't set a palette created from one DDraw onto a surface created by another DDraw" );
LEAVE_BOTH();
return DDERR_INVALIDPARAMS;
}
}
CheckExclusiveMode(pdrv_lcl, &excl_exists, &has_excl, FALSE, NULL, FALSE);
/*
* don't allow primary palette set if not exclusive mode owner
*/
isprimary = FALSE;
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE )
{
isprimary = TRUE;
if( excl_exists )
{
if( !has_excl )
{
DPF_ERR( "Cannot set palette on primary when other process owns exclusive mode" );
LEAVE_BOTH();
return DDERR_NOEXCLUSIVEMODE;
}
}
}
/*
* Was a palette previously attached to this surface?
* If so, we will need to release if all goes well so
* remember it.
*/
prev_pal_int = this_lcl->lpDDPalette;
/*
* NULL palette, remove palette from this surface
*/
attach = TRUE;
if( this_pal == NULL )
{
attach = FALSE;
this_pal_int = prev_pal_int;
if( this_pal_int == NULL )
{
DPF_ERR( "No attached palette" );
LEAVE_BOTH();
return DDERR_NOPALETTEATTACHED;
}
this_pal_lcl = this_pal_int->lpLcl;
this_pal = this_pal_lcl->lpGbl;
}
if( attach )
{
/*
* NOTE: We used to do a lot of HEL specific checking. With the
* addition of support for palettes on non-primary surfaces and
* non-256 entry palettes this became redundant. We also used
* to explicitly check that, if attaching to the primary, the
* current mode was palettized and 8-bit. Doesn't look to me like
* any of that was necessary as DDPF_PALETTEINDEXED8 should be
* set if the primary is 8-bit palettized.
*/
GET_PIXEL_FORMAT( this_lcl, this, pddpf );
if( ( ( this_pal->dwFlags & DDRAWIPAL_2 ) && !( pddpf->dwFlags & DDPF_PALETTEINDEXED1 ) ) ||
( ( this_pal->dwFlags & DDRAWIPAL_4 ) && !( pddpf->dwFlags & DDPF_PALETTEINDEXED2 ) ) ||
( ( this_pal->dwFlags & DDRAWIPAL_16 ) && !( pddpf->dwFlags & DDPF_PALETTEINDEXED4 ) ) ||
( ( this_pal->dwFlags & DDRAWIPAL_256 ) && !( pddpf->dwFlags & DDPF_PALETTEINDEXED8 ) ) )
{
DPF_ERR( "Palette size does not match surface format - cannot set palette" );
LEAVE_BOTH();
return DDERR_INVALIDPIXELFORMAT;
}
/*
* Ensure that both the palette and surface agree on whether they are using
* indices into the destination surface's palette.
*/
if( this_pal->dwFlags & DDRAWIPAL_STORED_8INDEX )
{
if( !(pddpf->dwFlags & DDPF_PALETTEINDEXEDTO8) )
{
DPF_ERR( "Surface is not PALETTEINDEXEDTO8 - cannot set palette" );
LEAVE_BOTH();
return DDERR_INVALIDPIXELFORMAT;
}
}
else
{
if( pddpf->dwFlags & DDPF_PALETTEINDEXEDTO8 )
{
DPF_ERR( "Surface is PALETTEINDEXEDTO8 - cannot set palette" );
LEAVE_BOTH();
return DDERR_INVALIDPIXELFORMAT;
}
}
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_BOTH();
return DDERR_INVALIDPARAMS;
}
/*
* ATTENTION!!!
* We shouldn't pass optimized surfaces to an unsuspecting HAL, but if we don't then we could
* break drivers that hook SetPalette... Since the HAL is probably only going to be watching
* for a primary, and also is unlikely to go looking at the surface's contents,
* I'm going to let this one slide.
*/
if( ( this_pal->dwFlags & DDRAWIPAL_INHEL) ||
( pdrv_lcl->lpDDCB->HALDDSurface.SetPalette == NULL ) )
{
// use HEL
spfn = pdrv_lcl->lpDDCB->HELDDSurface.SetPalette;
sphalfn = spfn;
emulation = TRUE;
}
else
{
// use HAL
spfn = pdrv_lcl->lpDDCB->HALDDSurface.SetPalette;
sphalfn = pdrv_lcl->lpDDCB->cbDDSurfaceCallbacks.SetPalette;
emulation = FALSE;
}
if( sphalfn != NULL )
{
spd.SetPalette = sphalfn;
spd.lpDD = pdrv;
spd.lpDDPalette = this_pal;
spd.lpDDSurface = this_lcl;
spd.Attach = attach;
DOHALCALL_NOWIN16( SetPalette, spfn, spd, rc, emulation );
if( rc == DDHAL_DRIVER_HANDLED )
{
if( spd.ddRVal == DD_OK )
{
if( attach )
{
/*
* Only AddRef the palette if its being attached to
* a new surface.
*/
if( this_lcl->lpDDPalette != this_pal_int )
{
this_lcl->lpDDPalette = this_pal_int;
DD_Palette_AddRef( lpDDPalette );
}
}
else
{
this_lcl->lpDDPalette = NULL;
}
/*
* If we had a previous palette and it was different
* from the new palette then we must release it.
* NOTE: We compare against the incoming parameter
* rather than this_pal_lcl as this_pal_lcl is set to the
* previous palette if we are removing a palette.
* NOTE: It is important that we update the surface's
* palette pointer before calling Release() as, otherwise,
* release can end up calling SetPalette() and so on.
*/
if( ( prev_pal_int != NULL ) &&
( prev_pal_int != (LPDDRAWI_DDRAWPALETTE_INT )lpDDPalette ) )
{
// This palette may no longer the exclusive one
if( isprimary )
{
if( has_excl )
{
prev_pal_int->lpLcl->lpGbl->dwFlags &= ~DDRAWIPAL_EXCLUSIVE;
}
}
// Release it
DD_Palette_Release( (LPDIRECTDRAWPALETTE)prev_pal_int );
}
if( attach )
{
// Ok, we have set the palette onto the surface
// Check if there are any outstanding DCs that need updating
UpdateOutstandingDC( this_lcl, this_pal );
}
else
{
// Ok, we have removed a palette onto the surface
// Check if there are any outstanding DCs that need updating
UpdateOutstandingDC( this_lcl, NULL );
}
BUMP_SURFACE_STAMP(this);
/*
* Update the driver's associations and palette entries
*/
if( dwHelperPid != GetCurrentProcessId() )
{
BOOL bUpdateEntries = FALSE;
if (attach)
{
if (this_pal->dwHandle == 0)
{
/*
* The driver has never seen this palette before. We must send an associate notify first, and
* then an update entries
*/
bUpdateEntries = TRUE;
this_pal->dwHandle = GeneratePaletteHandle(pdrv_lcl);
}
if (this_pal->dwHandle && pdrv_lcl->pD3DIUnknown )
//could be zero in low memory conditions
{
if ( pdrv_lcl->pPaletteAssociateNotify )
{
// NOTE: we send the handle for DX6 and down
// for DX7 we pass the the local itself.
// DX7 needs the whole local to get the
// batching correct; MB41840
if( DDRAWILCL_DIRECTDRAW7 & pdrv_lcl->dwLocalFlags )
{
LPPALETTEASSOCIATENOTIFY7 pPaletteAssociateNotify =
(LPPALETTEASSOCIATENOTIFY7)pdrv_lcl->pPaletteAssociateNotify;
pPaletteAssociateNotify(
pdrv_lcl->pD3DIUnknown,
this_pal->dwHandle,
this_pal->dwFlags,
this_lcl );
}
else
{
// When a DX6 app is talking to a DX7 driver,
// we need to force a flush of the token
// stream as part of this SetPalette.
//
// This automatically happens if the number
// of devices is > 1. So if necessary
// we temporarily increment the device
// count. We don't do this for IA64.
// MB41840 for more details.
#ifndef _WIN64
DWORD *pIUnknown = (DWORD *)(pdrv_lcl->pD3DIUnknown);
DWORD *pD3D = (DWORD *)(*(pIUnknown + 2));
DWORD *pnumDevs = (DWORD *)(pD3D + 3);
BOOL bFixDeviceCount = FALSE;
DDASSERT(pD3D != NULL);
if (*pnumDevs == 1)
{
*pnumDevs = 2;
bFixDeviceCount = TRUE;
}
#endif // _WIN64
pdrv_lcl->pPaletteAssociateNotify(
pdrv_lcl->pD3DIUnknown,
this_pal->dwHandle,
this_pal->dwFlags,
this_lcl->lpSurfMore->dwSurfaceHandle );
#ifndef _WIN64
// Restore the device count
if (bFixDeviceCount)
{
DDASSERT(*pnumDevs == 2);
*pnumDevs = 1;
}
#endif // _WIN64
}
}
if ( pdrv_lcl->pPaletteUpdateNotify )
{
pdrv_lcl->pPaletteUpdateNotify(
pdrv_lcl->pD3DIUnknown,
this_pal->dwHandle ,
0,
FLAGS_TO_SIZE(this_pal->dwFlags),
this_pal->lpColorTable );
}
}
}
}
}
LEAVE_BOTH();
return spd.ddRVal;
}
LEAVE_BOTH();
return DDERR_UNSUPPORTED;
}
/*
* !!! NOTE: Currently if the driver does not care about
* SetPalette we do nothing but return OK. Should we
* not, however, still point the surface at the palette
* and point the palette at the surface at the very
* least?
*/
LEAVE_BOTH();
return DD_OK;
} /* DD_Surface_SetPalette */
/*
* SetPaletteAlways
*/
HRESULT SetPaletteAlways(
LPDDRAWI_DDRAWSURFACE_INT psurf_int,
LPDIRECTDRAWPALETTE lpDDPalette )
{
LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
DWORD oldflag;
HRESULT ddrval;
psurf_lcl = psurf_int->lpLcl;
oldflag = psurf_lcl->dwFlags & DDRAWISURF_INVALID;
psurf_lcl->dwFlags &= ~DDRAWISURF_INVALID;
ddrval = DD_Surface_SetPalette( (LPDIRECTDRAWSURFACE) psurf_int, lpDDPalette );
psurf_lcl->dwFlags |= oldflag;
return ddrval;
} /* SetPaletteAlways */
#undef DPF_MODNAME
#define DPF_MODNAME "CreatePalette"
/*
* DD_CreatePalette
*
* Driver function: create a palette
*/
HRESULT DDAPI DD_CreatePalette(
LPDIRECTDRAW lpDD,
DWORD dwFlags,
LPPALETTEENTRY lpColorTable,
LPDIRECTDRAWPALETTE FAR *lplpDDPalette,
IUnknown FAR *pUnkOuter )
{
LPDDRAWI_DIRECTDRAW_INT this_int;
LPDDRAWI_DIRECTDRAW_LCL this_lcl;
LPDDRAWI_DIRECTDRAW_GBL this;
LPDDRAWI_DDRAWPALETTE_INT ppal_int;
LPDDRAWI_DDRAWPALETTE_LCL ppal_lcl;
LPDDRAWI_DDRAWPALETTE_GBL ppal;
DWORD pal_size;
DDHAL_CREATEPALETTEDATA cpd;
DWORD rc;
DWORD pflags;
BOOL is_excl;
LPDDHAL_CREATEPALETTE cpfn;
LPDDHAL_CREATEPALETTE cphalfn;
BOOL emulation;
BYTE indexedpe;
BYTE hackindexedpe;
PALETTEENTRY pe;
PALETTEENTRY hackpe;
DWORD num_entries;
DWORD entry_size;
int num_size_flags;
if( pUnkOuter != NULL )
{
return CLASS_E_NOAGGREGATION;
}
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_CreatePalette");
TRY
{
this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
if( !VALID_DIRECTDRAW_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
this = this_lcl->lpGbl;
if( !VALID_PTR_PTR( lplpDDPalette ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
*lplpDDPalette = NULL;
if( dwFlags & ~DDPCAPS_VALID )
{
DPF_ERR( "Invalid caps" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* verify that cooperative level is set
*/
if( !(this_lcl->dwLocalFlags & DDRAWILCL_SETCOOPCALLED) )
{
DPF_ERR( "Must call SetCooperativeLevel before calling Create functions" );
LEAVE_DDRAW();
return DDERR_NOCOOPERATIVELEVELSET;
}
/*
* verify flags
*/
if( dwFlags & (DDPCAPS_VSYNC|
DDPCAPS_PRIMARYSURFACE|
DDPCAPS_PRIMARYSURFACELEFT) )
{
DPF_ERR( "Read only flags specified" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
num_size_flags = 0;
if( dwFlags & DDPCAPS_1BIT )
num_size_flags++;
if( dwFlags & DDPCAPS_2BIT )
num_size_flags++;
if( dwFlags & DDPCAPS_4BIT )
num_size_flags++;
if( dwFlags & DDPCAPS_8BIT )
num_size_flags++;
if( num_size_flags != 1 )
{
DPF_ERR( "Must specify one and one only of 2, 4, 16 or 256 color palette" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( dwFlags & DDPCAPS_ALPHA )
{
if( dwFlags & DDPCAPS_8BITENTRIES )
{
DPF_ERR( "8BITENTRIES not valid with ALPHA" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
if( dwFlags & DDPCAPS_8BIT )
{
if( dwFlags & DDPCAPS_8BITENTRIES )
{
DPF_ERR( "8BITENTRIES only valid with 1BIT, 2BIT or 4BIT palette" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
else
{
if( dwFlags & DDPCAPS_ALLOW256 )
{
DPF_ERR( "ALLOW256 only valid with 8BIT palette" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
pflags = SIZE_PCAPS_TO_FLAGS( dwFlags );
num_entries = FLAGS_TO_SIZE( pflags );
/*
* Can't just assume the lpColorTable is an array of PALETTENTRYs.
* If DDPCAPS_8BITENTRIES is set then this is in fact an array of
* bytes in disguise. Validate appropriately.
*/
if( dwFlags & DDPCAPS_8BITENTRIES )
{
entry_size = sizeof(BYTE);
indexedpe = ((LPBYTE)lpColorTable)[num_entries-1]; // validate
if( !VALID_BYTE_ARRAY( lpColorTable, num_entries ) )
{
DPF_ERR( "Invalid lpColorTable array" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* NOTE: You may well be wondering what this "hackindexedpe" bit is all about.
* Well - indexedpe is not actually used for anything. It's only a probe to
* test to see if the color table array is valid. We do this all over the place
* but unfortunately we don't actually need the result here so our friend
* Mr. Optimizing Compiler decides to discard the assignment and so nullify
* the test. In order to ensure the array access stays in we declare dummy
* variable and assign to them. This is enough to keep the code in (the
* compiler is not smart enough to see that the variable assigned to is
* not used). Same goes for hackpe below.
*/
hackindexedpe = indexedpe;
}
else
{
entry_size = sizeof(PALETTEENTRY);
pe = lpColorTable[num_entries-1]; // validate
if( !VALID_PALETTEENTRY_ARRAY( lpColorTable, num_entries ) )
{
DPF_ERR( "Invalid lpColorTable array" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
hackpe = pe;
}
CheckExclusiveMode(this_lcl, NULL, &is_excl, FALSE, NULL, FALSE);
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* allocate the palette object
*/
pal_size = sizeof( DDRAWI_DDRAWPALETTE_GBL ) +
sizeof( DDRAWI_DDRAWPALETTE_LCL );
ppal_lcl = (LPDDRAWI_DDRAWPALETTE_LCL) MemAlloc( pal_size );
if( ppal_lcl == NULL )
{
LEAVE_DDRAW();
return DDERR_OUTOFMEMORY;
}
ppal_lcl->lpGbl = (LPDDRAWI_DDRAWPALETTE_GBL) (((LPBYTE)ppal_lcl) +
sizeof( DDRAWI_DDRAWPALETTE_LCL ) );
ppal = ppal_lcl->lpGbl;
ppal_lcl->lpDD_lcl = this_lcl;
ppal_lcl->lpDD_Int = this_int;
/*
* Initialize some palette global state
*/
ppal->dwContentsStamp = 1;
if( dwFlags & DDPCAPS_ALLOW256 )
{
pflags |= DDRAWIPAL_ALLOW256;
}
if( dwFlags & DDPCAPS_8BITENTRIES )
{
pflags |= DDRAWIPAL_STORED_8INDEX;
}
if (dwFlags & DDPCAPS_ALPHA )
{
pflags |= DDRAWIPAL_ALPHA;
}
ppal_lcl->pPrivateDataHead = NULL;
/*
* allocate palette
*/
ppal->lpColorTable = MemAlloc( entry_size * num_entries );
if( ppal->lpColorTable == NULL )
{
MemFree( ppal_lcl );
LEAVE_DDRAW();
return DDERR_OUTOFMEMORY;
}
/*
* Create an interface for this palette
*/
#ifdef POSTPONED
if (LOWERTHANDDRAW4(this_int))
{
#endif
ppal_int = newPaletteInterface( ppal_lcl, (LPVOID)&ddPaletteCallbacks );
#ifdef POSTPONED
}
else
{
ppal_int = newPaletteInterface( ppal_lcl, (LPVOID)&ddPalette2Callbacks );
}
#endif
if( NULL == ppal_int )
{
MemFree( ppal->lpColorTable );
MemFree( ppal_lcl );
LEAVE_DDRAW();
return DDERR_OUTOFMEMORY;
}
/*
* copy the color table
* we now copy the color table BEFORE we call the device's CreatePalette()
* this is done as the device may want to overwrite certain of the palette
* entries (e.g. if you don't specify DDPCAPS_ALLOW256 then the driver may
* well choose to overwrite the 0 and 255 with black and white).
*/
memcpy( ppal->lpColorTable, lpColorTable, entry_size * num_entries );
/*
* fill in misc stuff
*/
ppal->lpDD_lcl = this_lcl;
ppal->dwFlags = pflags;
/*
* are palettes even supported by the driver?
*/
if( ( this->ddCaps.ddsCaps.dwCaps & DDSCAPS_PALETTE ) ||
( this->ddHELCaps.ddsCaps.dwCaps & DDSCAPS_PALETTE ) )
{
/* GEE: where do we allow the caller to require the palette
* be provided in hardware?
*/
if( (this->dwFlags & DDRAWI_DISPLAYDRV) ||
this_lcl->lpDDCB->cbDDCallbacks.CreatePalette == NULL )
{
// use HEL
cpfn = this_lcl->lpDDCB->HELDD.CreatePalette;
cphalfn = cpfn;
emulation = TRUE;
}
else
{
// use HAL
cpfn = this_lcl->lpDDCB->HALDD.CreatePalette;
cphalfn = this_lcl->lpDDCB->cbDDCallbacks.CreatePalette;
emulation = FALSE;
}
cpd.CreatePalette = this_lcl->lpDDCB->cbDDCallbacks.CreatePalette;
cpd.lpDD = this;
cpd.lpDDPalette=ppal;
cpd.lpColorTable=lpColorTable;
cpd.is_excl = is_excl;
DOHALCALL( CreatePalette, cpfn, cpd, rc, emulation );
if( rc == DDHAL_DRIVER_HANDLED )
{
if( cpd.ddRVal != DD_OK )
{
DPF( 5, "DDHAL_CreatePalette: ddrval = %ld", cpd.ddRVal );
LEAVE_DDRAW();
return cpd.ddRVal;
}
}
else
{
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
}
else
{
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
/*
* bump reference count, return object
*/
ppal->dwProcessId = GetCurrentProcessId();
ppal_lcl->dwLocalRefCnt = OBJECT_ISROOT;
ppal_int->dwIntRefCnt++;
ppal_lcl->dwLocalRefCnt++;
ppal->dwRefCnt++;
*lplpDDPalette = (LPDIRECTDRAWPALETTE) ppal_int;
/*
* If this ddraw object generates independent child objects, then this palette takes
* a ref count on that ddraw object.
*/
if (CHILD_SHOULD_TAKE_REFCNT(this_int))
{
/*
* We need to remember which interface created this palette, in case we need to take a ref count
* and then release it when the palette dies
*/
lpDD->lpVtbl->AddRef(lpDD);
ppal_lcl->pAddrefedThisOwner = (IUnknown *) lpDD;
}
LEAVE_DDRAW();
return DD_OK;
} /* DD_CreatePalette */
/*
* ProcessPaletteCleanup
*
* A process is done, clean up any surfaces that it may have locked.
*
* NOTE: we enter with a lock taken on the DIRECTDRAW object.
*/
void ProcessPaletteCleanup( LPDDRAWI_DIRECTDRAW_GBL pdrv, DWORD pid, LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl )
{
LPDDRAWI_DDRAWPALETTE_INT ppal_int;
LPDDRAWI_DDRAWPALETTE_INT ppnext_int;
LPDDRAWI_DDRAWPALETTE_GBL ppal;
DWORD rcnt;
/*
* run through all palettes owned by the driver object, and find ones
* that have been accessed by this process
*/
ppal_int = pdrv->palList;
DPF( 4, "ProcessPaletteCleanup, ppal=%08lx", ppal_int );
while( ppal_int != NULL )
{
ULONG rc;
ppal = ppal_int->lpLcl->lpGbl;
ppnext_int = ppal_int->lpLink;
rc = 1;
if( ( ppal->dwProcessId == pid ) &&
( ( NULL == pdrv_lcl ) || ( pdrv_lcl == ppal_int->lpLcl->lpDD_lcl ) ) )
{
/*
* release the references by this process
*/
rcnt = ppal_int->dwIntRefCnt;
DPF( 5, "Process %08lx had %ld accesses to palette %08lx", pid, rcnt, ppal_int );
while( rcnt > 0 )
{
rc = InternalPaletteRelease( ppal_int );
if( rc == 0 )
{
break;
}
rcnt--;
}
}
else
{
DPF( 5, "Process %08lx does not have access to palette" );
}
ppal_int = ppnext_int;
}
} /* ProcessPaletteCleanup */
/*
* DD_Palette_IsEqual
*/
HRESULT EXTERN_DDAPI DD_Palette_IsEqual(
LPDIRECTDRAWPALETTE lpDDPThis,
LPDIRECTDRAWPALETTE lpDDPalette )
{
LPDDRAWI_DDRAWPALETTE_INT this_int;
LPDDRAWI_DDRAWPALETTE_LCL this_lcl;
LPDDRAWI_DDRAWPALETTE_GBL this;
LPDDRAWI_DDRAWPALETTE_INT pal_int;
LPDDRAWI_DDRAWPALETTE_LCL pal_lcl;
LPDDRAWI_DDRAWPALETTE_GBL pal;
DWORD size;
DWORD entry_size;
UINT i,j;
DWORD entry;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_Palette_IsEqual");
TRY
{
this_int = (LPDDRAWI_DDRAWPALETTE_INT) lpDDPThis;
if( !VALID_DIRECTDRAWPALETTE_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
this = this_lcl->lpGbl;
pal_int = (LPDDRAWI_DDRAWPALETTE_INT) lpDDPalette;
if( !VALID_DIRECTDRAWPALETTE_PTR( pal_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
pal_lcl = pal_int->lpLcl;
pal = pal_lcl->lpGbl;
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* First check the flags
*/
if (this->dwFlags != pal->dwFlags)
{
DPF(2,"Different palette structures");
LEAVE_DDRAW();
return DD_FALSE;
}
size = FLAGS_TO_SIZE(this->dwFlags);
if( this->dwFlags & DDRAWIPAL_STORED_8INDEX )
{
entry_size = sizeof( BYTE );
}
else
{
entry_size = sizeof( PALETTEENTRY );
}
switch (size)
{
case 2: // fall-thru
case 4: // fall-thru
case 16:
if (memcmp(this->lpColorTable, pal->lpColorTable, size*entry_size) != 0)
{
DPF(2, "Color tables are not the same" );
LEAVE_DDRAW();
return DD_FALSE;
}
break;
case 256:
for (i = 0; i < 16; ++i)
{
entry = i;
for (j = 0; j < 16; j++)
{
if ((*(LPDWORD)&(this->lpColorTable[entry]) != (*(LPDWORD)&pal->lpColorTable[entry])))
{
DPF(5,"Color table entry mismatch: 0x%08x, 0x%08x",
*(LPDWORD)&this->lpColorTable[entry],
*(LPDWORD)&pal->lpColorTable[entry] );
LEAVE_DDRAW();
return DD_FALSE;
}
entry += 16;
}
}
}
/*
* The palettes are the same!
*/
LEAVE_DDRAW();
return DD_OK;
} /* DD_Palette_SetEntries */