|
|
/*==========================================================================
* * 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 */
|