mirror of https://github.com/lianthony/NT4.0
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.
1530 lines
38 KiB
1530 lines
38 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
|
|
*
|
|
***************************************************************************/
|
|
#include "ddrawpr.h"
|
|
|
|
/*
|
|
* All these flags are really iritating to handle but but changing
|
|
* to use a numeric palette size would require an API change and
|
|
* internal structure mods (visible to the driver) so I am sticking
|
|
* with flags.
|
|
*/
|
|
#define SIZE_PCAPS_TO_FLAGS( pcaps ) \
|
|
(((pcaps) & DDPCAPS_1BIT) ? DDRAWIPAL_2 : \
|
|
(((pcaps) & DDPCAPS_2BIT) ? DDRAWIPAL_4 : \
|
|
(((pcaps) & DDPCAPS_4BIT) ? DDRAWIPAL_16 : DDRAWIPAL_256)))
|
|
|
|
#define SIZE_FLAGS_TO_PCAPS( flags ) \
|
|
(((flags) & DDRAWIPAL_2) ? DDPCAPS_1BIT : \
|
|
(((flags) & DDRAWIPAL_4) ? DDPCAPS_2BIT : \
|
|
(((flags) & DDRAWIPAL_16) ? DDPCAPS_4BIT : DDPCAPS_8BIT)))
|
|
|
|
#define FLAGS_TO_SIZE( flags ) \
|
|
(((flags) & DDRAWIPAL_2) ? 2 : \
|
|
(((flags) & DDRAWIPAL_4) ? 4 : \
|
|
(((flags) & DDRAWIPAL_16) ? 16 : 256)))
|
|
|
|
#define SIZE_DDPCAPS (DDPCAPS_1BIT | DDPCAPS_2BIT | DDPCAPS_4BIT | DDPCAPS_8BIT)
|
|
|
|
#define PE_FLAGS (PC_NOCOLLAPSE |PC_RESERVED)
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "Palette::QueryInterface"
|
|
|
|
/*
|
|
* DD_Palette_QueryInterface
|
|
*/
|
|
DWORD 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();
|
|
|
|
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) )
|
|
{
|
|
DD_Palette_AddRef( lpDDPalette );
|
|
*ppvObj = (LPVOID) this_int;
|
|
LEAVE_DDRAW();
|
|
return DD_OK;
|
|
}
|
|
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();
|
|
|
|
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( 2, "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;
|
|
|
|
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( 2, "Palette %08lx released, refcnt = %ld,%ld,%ld", this_int, gblrefcnt, lclrefcnt, intrefcnt );
|
|
|
|
/*
|
|
* local object gone?
|
|
*/
|
|
root_object_deleted = FALSE;
|
|
if( lclrefcnt == 0 )
|
|
{
|
|
/*
|
|
* 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);
|
|
}
|
|
|
|
/*
|
|
* 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" );
|
|
/* GEE: What do we do here since we no longer return
|
|
* error codes from Release.
|
|
*/
|
|
return (DWORD) dpd.ddRVal;
|
|
}
|
|
}
|
|
}
|
|
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 );
|
|
}
|
|
|
|
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();
|
|
|
|
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;
|
|
|
|
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();
|
|
|
|
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: already initialized" );
|
|
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_DDRAW();
|
|
|
|
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;
|
|
}
|
|
}
|
|
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_DDRAW();
|
|
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( SetEntries, sefn, sed, rc, emulation );
|
|
if( rc == DDHAL_DRIVER_HANDLED )
|
|
{
|
|
if( sed.ddRVal != DD_OK )
|
|
{
|
|
DPF( 2, "DDHAL_SetEntries: ddrval = %ld", sed.ddRVal );
|
|
LEAVE_DDRAW();
|
|
return (DWORD) sed.ddRVal;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
|
|
LEAVE_DDRAW();
|
|
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();
|
|
|
|
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;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
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;
|
|
}
|
|
|
|
if( this_lcl->lpDDPalette == NULL )
|
|
{
|
|
DPF_ERR( "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;
|
|
}
|
|
|
|
DD_Palette_AddRef( (LPDIRECTDRAWPALETTE) this_lcl->lpDDPalette );
|
|
*lplpDDPalette = (LPDIRECTDRAWPALETTE) this_lcl->lpDDPalette;
|
|
|
|
LEAVE_DDRAW();
|
|
return DD_OK;
|
|
|
|
} /* 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;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
|
|
TRY
|
|
{
|
|
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;
|
|
|
|
/*
|
|
* 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_DDRAW();
|
|
return DDERR_INVALIDSURFACETYPE;
|
|
}
|
|
|
|
if( SURFACE_LOST( this_lcl ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
|
|
this_pal_int = (LPDDRAWI_DDRAWPALETTE_INT) lpDDPalette;
|
|
if( this_pal_int != NULL )
|
|
{
|
|
if( !VALID_DIRECTDRAWPALETTE_PTR( this_pal_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
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;
|
|
|
|
/*
|
|
* don't allow primary palette set if not exclusive mode owner
|
|
*/
|
|
isprimary = FALSE;
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE )
|
|
{
|
|
isprimary = TRUE;
|
|
if( pdrv->lpExclusiveOwner != NULL )
|
|
{
|
|
if( pdrv->lpExclusiveOwner != pdrv_lcl )
|
|
{
|
|
DPF_ERR( "Cannot set palette on primary when other process owns exclusive mode" );
|
|
LEAVE_DDRAW();
|
|
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_DDRAW();
|
|
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_DDRAW();
|
|
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_DDRAW();
|
|
return DDERR_INVALIDPIXELFORMAT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( pddpf->dwFlags & DDPF_PALETTEINDEXEDTO8 )
|
|
{
|
|
DPF_ERR( "Surface is PALETTEINDEXEDTO8 - cannot set palette" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPIXELFORMAT;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
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( 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 ) )
|
|
DD_Palette_Release( (LPDIRECTDRAWPALETTE)prev_pal_int );
|
|
}
|
|
LEAVE_DDRAW();
|
|
return spd.ddRVal;
|
|
}
|
|
LEAVE_DDRAW();
|
|
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_DDRAW();
|
|
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"
|
|
|
|
/*
|
|
* 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;
|
|
|
|
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;
|
|
|
|
return pnew_int;
|
|
|
|
} /* newPaletteInterface */
|
|
|
|
|
|
/*
|
|
* 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();
|
|
|
|
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_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;
|
|
}
|
|
is_excl = (this->lpExclusiveOwner == this_lcl);
|
|
}
|
|
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;
|
|
|
|
if( dwFlags & DDPCAPS_ALLOW256 )
|
|
{
|
|
pflags |= DDRAWIPAL_ALLOW256;
|
|
}
|
|
|
|
if( dwFlags & DDPCAPS_8BITENTRIES )
|
|
{
|
|
pflags |= DDRAWIPAL_STORED_8INDEX;
|
|
}
|
|
|
|
/*
|
|
* 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
|
|
*/
|
|
ppal_int = newPaletteInterface( ppal_lcl, (LPVOID)&ddPaletteCallbacks );
|
|
if( NULL == ppal_int )
|
|
{
|
|
MemFree( ppal->lpColorTable );
|
|
MemFree( ppal_lcl );
|
|
LEAVE_DDRAW();
|
|
return DDERR_OUTOFMEMORY;
|
|
}
|
|
|
|
/*
|
|
* link this into the global list of palettes
|
|
*/
|
|
ppal_int->lpLink = this->palList;
|
|
this->palList = ppal_int;
|
|
/*
|
|
* 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( 2, "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;
|
|
|
|
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( 2, "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( 4, "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( 4, "Process %08lx does not have access to palette" );
|
|
}
|
|
ppal_int = ppnext_int;
|
|
}
|
|
|
|
} /* ProcessPaletteCleanup */
|