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

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: ddpal.c
  6. * Content: DirectDraw palette functions
  7. * History:
  8. * Date By Reason
  9. * ==== == ======
  10. * 27-jan-95 craige initial implementation
  11. * 11-mar-95 craige more HAL fns, filled out CreatePalette
  12. * 19-mar-95 craige use HRESULTs, process termination cleanup fixes
  13. * 26-mar-95 craige filled out remaining fns
  14. * 28-mar-95 craige switched to PALETTEENTRY from RGBQUAD
  15. * 31-mar-95 craige use critical sections with palettes
  16. * 01-apr-95 craige happy fun joy updated header file
  17. * 04-apr-95 craige use driver directly in exclusive mode
  18. * 07-apr-95 craige bug 14 - check GUID ptr in QI
  19. * 10-apr-95 craige mods to process list stuff
  20. * bug 3,16 - palette issues: use driver in excl. mode
  21. * 12-apr-95 craige don't use GETCURRPID all the time; proper csect ordering
  22. * 06-may-95 craige use driver-level csects only
  23. * 12-may-95 craige check for real guids in QI
  24. * 02-jun-95 craige extra parm in AddToActiveProcessList
  25. * 12-jun-95 craige new process list stuff
  26. * 20-jun-95 kylej moved palette emulation code into ddhel
  27. * 21-jun-95 craige couple of internal inteface cleanup issues
  28. * 25-jun-95 craige one ddraw mutex
  29. * 26-jun-95 craige reorganized surface structure
  30. * 28-jun-95 craige ENTER_DDRAW at very start of fns
  31. * 02-jul-95 craige implemented GetCaps; added SEH for parm. validation
  32. * 04-jul-95 craige YEEHAW: new driver struct
  33. * 05-jul-95 craige added Initialize
  34. * 08-jul-95 kylej Surface and DirectDraw Palette calls require
  35. * exclusive mode. Removed ResetSysPalette. Make a
  36. * SetPalette call to the HAL/HEL to detach a palette.
  37. * 11-jul-95 craige fail aggregation calls
  38. * 13-jul-95 craige bug 94 - flag validation fixes
  39. * 20-jul-95 craige stop palette code from running non-palettized
  40. * 31-jul-95 toddla unselect palette in InternalPaletteRelease
  41. * 31-jul-95 craige validate flags
  42. * 21-aug-95 craige mode X support
  43. * 27-aug-95 craige bug 735: added SetPaletteAlways
  44. * bug 742: use ALLOW256
  45. * 14-oct-95 colinmc add support for attaching palettes to offscreen and
  46. * texture map surfaces
  47. * 07-nov-95 colinmc support for 1, 2 and 4-bit palettes and palette
  48. * sharing added
  49. * 09-dec-95 colinmc added execute buffer support
  50. * 02-jan-96 kylej handle new interface structs
  51. * 09-feb-96 colinmc surface lost flag moved from global to local object
  52. * 03-mar-96 colinmc fixed problem with QueryInterface returning local
  53. * object rather than interface.
  54. * 13-mar-96 colinmc added IID validation to QueryInterface
  55. * 16-mar-96 colinmc fixed problem with palettes being released too many
  56. * times
  57. * 19-mar-96 colinmc Bug 12129: Bogus lpColorTable causes CreatePalette
  58. * to bomb
  59. * 19-apr-96 colinmc Bug 17473: CreatePalette faults on bogus palette
  60. * pointer
  61. * 02-may-96 kylej Bug 20066: GetPalette doesn't NULL pointer on failure
  62. * 23-sep-96 ketand Added TIMING routines
  63. * 24-mar-97 jeffno Optimized Surfaces
  64. * 26-nov-97 t-craigs Added IDirectDrawPalette2 stuff
  65. *
  66. ***************************************************************************/
  67. #include "ddrawpr.h"
  68. #define SIZE_DDPCAPS (DDPCAPS_1BIT | DDPCAPS_2BIT | DDPCAPS_4BIT | DDPCAPS_8BIT)
  69. #define PE_FLAGS (PC_NOCOLLAPSE |PC_RESERVED)
  70. #define BITS_PER_BITFIELD_ENTRY (sizeof(DWORD)*8)
  71. /*
  72. * Generate a palette handle. We keep a bitfiled in the ddraw local that
  73. * tells us if we can recycle a handle. Note that handles are 1-based,
  74. * and these routines deal with that
  75. */
  76. DWORD GeneratePaletteHandle(LPDDRAWI_DIRECTDRAW_LCL lpDD_lcl)
  77. {
  78. DWORD cbits,*pdw;
  79. /*
  80. * Check for an unused entry in the palette-handle-used bitfield. We check
  81. */
  82. for (cbits=0; cbits< lpDD_lcl->cbitsPaletteBitfieldBitCount; cbits++ )
  83. {
  84. if ( 0 == (lpDD_lcl->pPaletteHandleUsedBitfield[cbits/BITS_PER_BITFIELD_ENTRY]
  85. & (1<<(cbits % BITS_PER_BITFIELD_ENTRY))) )
  86. {
  87. /*
  88. * Found a recycled handle
  89. */
  90. lpDD_lcl->pPaletteHandleUsedBitfield[cbits/BITS_PER_BITFIELD_ENTRY] |=
  91. (1<<(cbits % BITS_PER_BITFIELD_ENTRY));
  92. return cbits+1; //plus one since 0 is error return
  93. }
  94. }
  95. /*
  96. * Didn't find a recycled entry. Get a new handle
  97. */
  98. DDASSERT( cbits == lpDD_lcl->cbitsPaletteBitfieldBitCount );
  99. if ( (cbits% BITS_PER_BITFIELD_ENTRY) == 0)
  100. {
  101. /*
  102. * Have to grow the table since the current table fits exactly in a number of DWORDs
  103. */
  104. pdw = MemAlloc( ((cbits / BITS_PER_BITFIELD_ENTRY) +1)*sizeof(DWORD) );
  105. if (pdw)
  106. {
  107. /*
  108. * Couldn't convince myself the MemRealloc both worked and would zero remaining space.
  109. */
  110. memcpy(pdw, lpDD_lcl->pPaletteHandleUsedBitfield,
  111. (cbits / BITS_PER_BITFIELD_ENTRY) * sizeof(DWORD) );
  112. MemFree(lpDD_lcl->pPaletteHandleUsedBitfield);
  113. lpDD_lcl->pPaletteHandleUsedBitfield = pdw;
  114. }
  115. else
  116. {
  117. return 0;
  118. }
  119. }
  120. /*
  121. * Table is big enough. Grab the entry and mark it.
  122. */
  123. cbits = lpDD_lcl->cbitsPaletteBitfieldBitCount++;
  124. lpDD_lcl->pPaletteHandleUsedBitfield[cbits/BITS_PER_BITFIELD_ENTRY] |=
  125. (1<<(cbits % BITS_PER_BITFIELD_ENTRY));
  126. return cbits+1; //+1 since zero is an error return, and it helps out drivers to know 0 is invalid
  127. }
  128. void FreePaletteHandle(LPDDRAWI_DIRECTDRAW_LCL lpDD_lcl, DWORD dwHandle)
  129. {
  130. DDASSERT( dwHandle <= lpDD_lcl->cbitsPaletteBitfieldBitCount );
  131. if (dwHandle == 0)
  132. return;
  133. dwHandle -=1; //since handles are 1-based
  134. lpDD_lcl->pPaletteHandleUsedBitfield[dwHandle/BITS_PER_BITFIELD_ENTRY] &=
  135. ~(1<<(dwHandle % BITS_PER_BITFIELD_ENTRY));
  136. }
  137. /*
  138. * newPaletteInterface
  139. *
  140. * Construct a new palette interface which points to an existing local object.
  141. */
  142. static LPVOID newPaletteInterface( LPDDRAWI_DDRAWPALETTE_LCL this_lcl, LPVOID lpvtbl )
  143. {
  144. LPDDRAWI_DDRAWPALETTE_INT pnew_int;
  145. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  146. pnew_int = MemAlloc( sizeof( DDRAWI_DDRAWPALETTE_INT ));
  147. if( NULL == pnew_int )
  148. {
  149. return NULL;
  150. }
  151. /*
  152. * set up data
  153. */
  154. pnew_int->lpVtbl = lpvtbl;
  155. pnew_int->lpLcl = this_lcl;
  156. pnew_int->dwIntRefCnt = 0;
  157. /*
  158. * link this into the global list of palettes
  159. */
  160. pdrv = this_lcl->lpDD_lcl->lpGbl;
  161. pnew_int->lpLink = pdrv->palList;
  162. pdrv->palList = pnew_int;
  163. return pnew_int;
  164. } /* newPaletteInterface */
  165. #undef DPF_MODNAME
  166. #define DPF_MODNAME "Palette::QueryInterface"
  167. /*
  168. * DD_Palette_QueryInterface
  169. */
  170. HRESULT DDAPI DD_Palette_QueryInterface(
  171. LPDIRECTDRAWPALETTE lpDDPalette,
  172. REFIID riid,
  173. LPVOID FAR * ppvObj )
  174. {
  175. LPDDRAWI_DDRAWPALETTE_GBL this;
  176. LPDDRAWI_DDRAWPALETTE_LCL this_lcl;
  177. LPDDRAWI_DDRAWPALETTE_INT this_int;
  178. ENTER_DDRAW();
  179. DPF(2,A,"ENTERAPI: DD_Palette_QueryInterface");
  180. TRY
  181. {
  182. this_int = (LPDDRAWI_DDRAWPALETTE_INT) lpDDPalette;
  183. if( !VALID_DIRECTDRAWPALETTE_PTR( this_int ) )
  184. {
  185. DPF_ERR( "Invalid palette pointer" );
  186. LEAVE_DDRAW();
  187. return (DWORD) DDERR_INVALIDOBJECT;
  188. }
  189. this_lcl = this_int->lpLcl;
  190. if( !VALID_PTR_PTR( ppvObj ) )
  191. {
  192. DPF( 1, "Invalid palette pointer" );
  193. LEAVE_DDRAW();
  194. return (DWORD) DDERR_INVALIDPARAMS;
  195. }
  196. if( !VALIDEX_IID_PTR( riid ) )
  197. {
  198. DPF_ERR( "Invalid IID pointer" );
  199. LEAVE_DDRAW();
  200. return (DWORD) DDERR_INVALIDPARAMS;
  201. }
  202. this = this_lcl->lpGbl;
  203. }
  204. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  205. {
  206. DPF_ERR( "Exception encountered validating parameters" );
  207. LEAVE_DDRAW();
  208. return (DWORD) DDERR_INVALIDPARAMS;
  209. }
  210. if( IsEqualIID(riid, &IID_IUnknown) ||
  211. IsEqualIID(riid, &IID_IDirectDrawPalette) )
  212. {
  213. if( this_int->lpVtbl == (LPVOID) &ddPaletteCallbacks )
  214. *ppvObj = (LPVOID) this_int;
  215. else
  216. *ppvObj = (LPVOID) newPaletteInterface( this_lcl, (LPVOID)&ddPaletteCallbacks );
  217. if( NULL == *ppvObj )
  218. {
  219. LEAVE_DDRAW();
  220. return E_NOINTERFACE;
  221. }
  222. else
  223. {
  224. DD_Palette_AddRef( *ppvObj );
  225. LEAVE_DDRAW();
  226. return DD_OK;
  227. }
  228. }
  229. #ifdef POSTPONED
  230. if (IsEqualIID(riid, &IID_IPersist))
  231. {
  232. /*
  233. * if this is already an IID_IPersist interface, just
  234. * addref and return
  235. */
  236. if( this_int->lpVtbl == (LPVOID) &ddPalettePersistCallbacks )
  237. *ppvObj = (LPVOID) this_int;
  238. else
  239. *ppvObj = (LPVOID) newPaletteInterface( this_lcl, (LPVOID)&ddPalettePersistCallbacks );
  240. if( NULL == *ppvObj )
  241. {
  242. LEAVE_DDRAW();
  243. return E_NOINTERFACE;
  244. }
  245. else
  246. {
  247. DD_Palette_AddRef( *ppvObj );
  248. LEAVE_DDRAW();
  249. return DD_OK;
  250. }
  251. }
  252. if (IsEqualIID(riid, &IID_IPersistStream))
  253. {
  254. /*
  255. * if this is already an IID_IPersistStream interface, just
  256. * addref and return
  257. */
  258. if( this_int->lpVtbl == (LPVOID) &ddPalettePersistStreamCallbacks )
  259. *ppvObj = (LPVOID) this_int;
  260. else
  261. *ppvObj = (LPVOID) newPaletteInterface( this_lcl, (LPVOID)&ddPalettePersistStreamCallbacks );
  262. if( NULL == *ppvObj )
  263. {
  264. LEAVE_DDRAW();
  265. return E_NOINTERFACE;
  266. }
  267. else
  268. {
  269. DD_Palette_AddRef( *ppvObj );
  270. LEAVE_DDRAW();
  271. return DD_OK;
  272. }
  273. }
  274. if (IsEqualIID(riid, &IID_IDirectDrawPalette2))
  275. {
  276. /*
  277. * if this is already an IID_IDirectDrawPalette2 interface, just
  278. * addref and return
  279. */
  280. if( this_int->lpVtbl == (LPVOID) &ddPalette2Callbacks )
  281. *ppvObj = (LPVOID) this_int;
  282. else
  283. *ppvObj = (LPVOID) newPaletteInterface( this_lcl, (LPVOID)&ddPalette2Callbacks );
  284. if( NULL == *ppvObj )
  285. {
  286. LEAVE_DDRAW();
  287. return E_NOINTERFACE;
  288. }
  289. else
  290. {
  291. DD_Palette_AddRef( *ppvObj );
  292. LEAVE_DDRAW();
  293. return DD_OK;
  294. }
  295. }
  296. #endif //POSTPONED
  297. LEAVE_DDRAW();
  298. return (DWORD) DDERR_GENERIC;
  299. } /* DD_Palette_QueryInterface */
  300. #undef DPF_MODNAME
  301. #define DPF_MODNAME "Palette::AddRef"
  302. /*
  303. * DD_Palette_AddRef
  304. */
  305. DWORD DDAPI DD_Palette_AddRef( LPDIRECTDRAWPALETTE lpDDPalette )
  306. {
  307. LPDDRAWI_DDRAWPALETTE_GBL this;
  308. LPDDRAWI_DDRAWPALETTE_LCL this_lcl;
  309. LPDDRAWI_DDRAWPALETTE_INT this_int;
  310. DWORD rcnt;
  311. ENTER_DDRAW();
  312. DPF(2,A,"ENTERAPI: DD_Palette_AddRef");
  313. TRY
  314. {
  315. this_int = (LPDDRAWI_DDRAWPALETTE_INT) lpDDPalette;
  316. if( !VALID_DIRECTDRAWPALETTE_PTR( this_int ) )
  317. {
  318. LEAVE_DDRAW();
  319. return 0;
  320. }
  321. this_lcl = this_int->lpLcl;
  322. this = this_lcl->lpGbl;
  323. /*
  324. * update palette reference count
  325. */
  326. this->dwRefCnt++;
  327. this_lcl->dwLocalRefCnt++;
  328. this_int->dwIntRefCnt++;
  329. rcnt = this_lcl->dwLocalRefCnt & ~OBJECT_ISROOT;
  330. DPF( 5, "Palette %08lx addrefed, refcnt = %ld,%ld,%ld",
  331. this_lcl, this->dwRefCnt, rcnt,
  332. this_int->dwIntRefCnt );
  333. }
  334. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  335. {
  336. DPF_ERR( "Exception encountered validating parameters" );
  337. LEAVE_DDRAW();
  338. return 0;
  339. }
  340. LEAVE_DDRAW();
  341. return this_int->dwIntRefCnt;
  342. } /* DD_Palette_AddRef */
  343. #undef DPF_MODNAME
  344. #define DPF_MODNAME "Palette::Release"
  345. /*
  346. * InternalPaletteRelease
  347. *
  348. * Done with a palette. if no one else is using it, then we can free it.
  349. * Also called by ProcessPaletteCleanup
  350. */
  351. ULONG DDAPI InternalPaletteRelease( LPDDRAWI_DDRAWPALETTE_INT this_int )
  352. {
  353. DWORD intrefcnt;
  354. DWORD lclrefcnt;
  355. DWORD gblrefcnt;
  356. BOOL root_object_deleted;
  357. BOOL do_free;
  358. ULONG rc;
  359. DDHAL_DESTROYPALETTEDATA dpd;
  360. LPDDRAWI_DDRAWPALETTE_GBL this;
  361. LPDDRAWI_DDRAWPALETTE_INT curr_int;
  362. LPDDRAWI_DDRAWPALETTE_LCL this_lcl;
  363. LPDDRAWI_DDRAWPALETTE_INT last_int;
  364. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  365. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  366. IUnknown * pOwner = NULL;
  367. this_lcl = this_int->lpLcl;
  368. this = this_lcl->lpGbl;
  369. pdrv_lcl = this->lpDD_lcl;
  370. pdrv = pdrv_lcl->lpGbl;
  371. /*
  372. * decrement reference count to this palette. If it hits zero,
  373. * cleanup
  374. */
  375. this->dwRefCnt--;
  376. this_lcl->dwLocalRefCnt--;
  377. this_int->dwIntRefCnt--;
  378. intrefcnt = this_int->dwIntRefCnt;
  379. lclrefcnt = this_lcl->dwLocalRefCnt & ~OBJECT_ISROOT;
  380. gblrefcnt = this->dwRefCnt;
  381. DPF( 5, "Palette %08lx released, refcnt = %ld,%ld,%ld", this_int, gblrefcnt, lclrefcnt, intrefcnt );
  382. /*
  383. * local object gone?
  384. */
  385. root_object_deleted = FALSE;
  386. if( lclrefcnt == 0 )
  387. {
  388. /*
  389. * Remove private data
  390. */
  391. FreeAllPrivateData( &this_lcl->pPrivateDataHead );
  392. /*
  393. * If the ddraw interface which created this palette caused the surface to addref the ddraw
  394. * object, then we need to release that addref now.
  395. */
  396. pOwner = this_lcl->pAddrefedThisOwner;
  397. /*
  398. * see if we are deleting the root object
  399. */
  400. if( this_lcl->dwLocalRefCnt & OBJECT_ISROOT )
  401. {
  402. root_object_deleted = TRUE;
  403. }
  404. }
  405. /*
  406. * did the object get globally deleted?
  407. */
  408. do_free = FALSE;
  409. if( gblrefcnt == 0 )
  410. {
  411. LPDDHALPALCB_DESTROYPALETTE dphalfn;
  412. LPDDHALPALCB_DESTROYPALETTE dpfn;
  413. BOOL emulation;
  414. do_free = TRUE;
  415. /*
  416. * if this palette is selected into the primary, unselect it!
  417. */
  418. if (pdrv_lcl && pdrv_lcl->lpPrimary &&
  419. pdrv_lcl->lpPrimary->lpLcl->lpDDPalette == this_int)
  420. {
  421. SetPaletteAlways(pdrv_lcl->lpPrimary, NULL);
  422. }
  423. FreePaletteHandle( pdrv_lcl, this->dwHandle );
  424. /*
  425. * destroy the hardware
  426. */
  427. if( ( pdrv_lcl->lpDDCB->HALDDPalette.DestroyPalette == NULL ) ||
  428. ( this->dwFlags & DDRAWIPAL_INHEL ) )
  429. {
  430. // use HEL
  431. dpfn = pdrv_lcl->lpDDCB->HELDDPalette.DestroyPalette;
  432. dphalfn = dpfn;
  433. emulation = TRUE;
  434. }
  435. else
  436. {
  437. // use HAL
  438. dpfn = pdrv_lcl->lpDDCB->HALDDPalette.DestroyPalette;
  439. dphalfn = pdrv_lcl->lpDDCB->cbDDPaletteCallbacks.DestroyPalette;
  440. emulation = FALSE;
  441. }
  442. if( dphalfn != NULL )
  443. {
  444. dpd.DestroyPalette = dphalfn;
  445. dpd.lpDD = pdrv_lcl->lpGbl;
  446. dpd.lpDDPalette = this;
  447. DOHALCALL( DestroyPalette, dpfn, dpd, rc, emulation );
  448. if( rc == DDHAL_DRIVER_HANDLED )
  449. {
  450. if( dpd.ddRVal != DD_OK )
  451. {
  452. DPF_ERR( "HAL call failed" );
  453. /*
  454. * If the palette took a ref count on the ddraw object that created it,
  455. * release that ref now as the very last thing
  456. * We don't want to do this on ddhelp's thread cuz it really mucks up the
  457. * process cleanup stuff.
  458. */
  459. if (pOwner && (dwHelperPid != GetCurrentProcessId()) )
  460. {
  461. pOwner->lpVtbl->Release(pOwner);
  462. }
  463. /* GEE: What do we do here since we no longer return
  464. * error codes from Release.
  465. */
  466. return (DWORD) dpd.ddRVal;
  467. }
  468. }
  469. /*
  470. * Moved here from ddhel.c. Non-display drivers mean that the hel isn't called for palette
  471. * destroy, so we were leaking palette tables. It's called exactly here to most closely
  472. * duplicate the old behaviour, but reduce any risk of drivers using the color table or whatever.
  473. */
  474. if (this->lpColorTable)
  475. {
  476. MemFree(this->lpColorTable);
  477. this->lpColorTable = NULL;
  478. }
  479. }
  480. else
  481. {
  482. /*
  483. * We can't do this; we've already committed to releasing at
  484. * this point!
  485. */
  486. // couldn't handle it
  487. // return (ULONG)DDERR_UNSUPPORTED;
  488. }
  489. /*
  490. * if this was the final delete, but this wasn't the root object,
  491. * then we need to delete the dangling root object
  492. */
  493. if( !root_object_deleted )
  494. {
  495. LPVOID root_lcl;
  496. root_lcl = (LPVOID) (((LPBYTE) this) - sizeof( DDRAWI_DDRAWPALETTE_LCL ) );
  497. MemFree( root_lcl );
  498. }
  499. }
  500. else if( lclrefcnt == 0 )
  501. {
  502. /*
  503. * only remove the object if it wasn't the root. if it
  504. * was the root, we must leave it dangling until the last
  505. * object referencing it goes away.
  506. */
  507. if( !root_object_deleted )
  508. {
  509. do_free = TRUE;
  510. }
  511. }
  512. /*
  513. * free the object if needed
  514. */
  515. if( do_free )
  516. {
  517. /*
  518. * just in case someone comes back in with this pointer, set
  519. * an invalid vtbl & data ptr.
  520. */
  521. this_lcl->lpGbl = NULL;
  522. MemFree( this_lcl );
  523. }
  524. /*
  525. * need to delete the interface?
  526. */
  527. if( intrefcnt == 0 )
  528. {
  529. /*
  530. * remove palette from list of all palettes
  531. */
  532. curr_int = pdrv->palList;
  533. last_int = NULL;
  534. while( curr_int != this_int )
  535. {
  536. last_int = curr_int;
  537. curr_int = curr_int->lpLink;
  538. if( curr_int == NULL )
  539. {
  540. return 0;
  541. }
  542. }
  543. if( last_int == NULL )
  544. {
  545. pdrv->palList = pdrv->palList->lpLink;
  546. }
  547. else
  548. {
  549. last_int->lpLink = curr_int->lpLink;
  550. }
  551. /*
  552. * Invalidate the interface
  553. */
  554. this_int->lpVtbl = NULL;
  555. this_int->lpLcl = NULL;
  556. MemFree( this_int );
  557. }
  558. /*
  559. * If the palette took a ref count on the ddraw object that created it,
  560. * release that ref now as the very last thing
  561. * We don't want to do this on ddhelp's thread cuz it really mucks up the
  562. * process cleanup stuff.
  563. */
  564. if (pOwner && (dwHelperPid != GetCurrentProcessId()) )
  565. {
  566. pOwner->lpVtbl->Release(pOwner);
  567. }
  568. return intrefcnt;
  569. } /* InternalPaletteRelease */
  570. /*
  571. * DD_Palette_Release
  572. *
  573. * Done with a palette. if no one else is using it, then we can free it.
  574. */
  575. ULONG DDAPI DD_Palette_Release( LPDIRECTDRAWPALETTE lpDDPalette )
  576. {
  577. LPDDRAWI_DDRAWPALETTE_GBL this;
  578. LPDDRAWI_DDRAWPALETTE_LCL this_lcl;
  579. LPDDRAWI_DDRAWPALETTE_INT this_int;
  580. ULONG rc;
  581. ENTER_DDRAW();
  582. DPF(2,A,"ENTERAPI: DD_Palette_Release");
  583. TRY
  584. {
  585. this_int = (LPDDRAWI_DDRAWPALETTE_INT) lpDDPalette;
  586. if( !VALIDEX_DIRECTDRAWPALETTE_PTR( this_int ) )
  587. {
  588. LEAVE_DDRAW();
  589. return 0;
  590. }
  591. this_lcl = this_int->lpLcl;
  592. this = this_lcl->lpGbl;
  593. rc = InternalPaletteRelease( this_int );
  594. }
  595. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  596. {
  597. DPF_ERR( "Exception encountered validating parameters" );
  598. LEAVE_DDRAW();
  599. return 0;
  600. }
  601. LEAVE_DDRAW();
  602. return rc;
  603. } /* DD_Palette_Release */
  604. #undef DPF_MODNAME
  605. #define DPF_MODNAME "GetCaps"
  606. /*
  607. * DD_Palette_GetCaps
  608. */
  609. HRESULT DDAPI DD_Palette_GetCaps(
  610. LPDIRECTDRAWPALETTE lpDDPalette,
  611. LPDWORD lpdwCaps )
  612. {
  613. LPDDRAWI_DDRAWPALETTE_GBL this;
  614. LPDDRAWI_DDRAWPALETTE_LCL this_lcl;
  615. LPDDRAWI_DDRAWPALETTE_INT this_int;
  616. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  617. DWORD caps;
  618. ENTER_DDRAW();
  619. DPF(2,A,"ENTERAPI: DD_Palette_GetCaps");
  620. TRY
  621. {
  622. this_int = (LPDDRAWI_DDRAWPALETTE_INT) lpDDPalette;
  623. if( !VALID_DIRECTDRAWPALETTE_PTR( this_int ) )
  624. {
  625. LEAVE_DDRAW();
  626. return DDERR_INVALIDOBJECT;
  627. }
  628. this_lcl = this_int->lpLcl;
  629. if( !VALID_DWORD_PTR( lpdwCaps ) )
  630. {
  631. DPF_ERR( "invalid caps pointer" );
  632. LEAVE_DDRAW();
  633. return DDERR_INVALIDPARAMS;
  634. }
  635. *lpdwCaps = 0;
  636. this = this_lcl->lpGbl;
  637. }
  638. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  639. {
  640. DPF_ERR( "Exception encountered validating parameters" );
  641. LEAVE_DDRAW();
  642. return DDERR_INVALIDPARAMS;
  643. }
  644. /*
  645. * basic palette size caps.
  646. */
  647. caps = SIZE_FLAGS_TO_PCAPS( this->dwFlags );
  648. /*
  649. * is this palette attached to the primary?
  650. */
  651. pdrv_lcl = this->lpDD_lcl;
  652. if (pdrv_lcl && pdrv_lcl->lpPrimary && pdrv_lcl->lpPrimary->lpLcl->lpDDPalette &&
  653. (pdrv_lcl->lpPrimary->lpLcl->lpDDPalette == this_int))
  654. caps |= DDPCAPS_PRIMARYSURFACE;
  655. /*
  656. * an allow256 palette?
  657. */
  658. if( this->dwFlags & DDRAWIPAL_ALLOW256 )
  659. {
  660. caps |= DDPCAPS_ALLOW256;
  661. }
  662. /*
  663. * does this palette store indices into an 8-bit destination
  664. * palette.
  665. */
  666. if( this->dwFlags & DDRAWIPAL_STORED_8INDEX )
  667. {
  668. caps |= DDPCAPS_8BITENTRIES;
  669. }
  670. *lpdwCaps = caps;
  671. LEAVE_DDRAW();
  672. return DD_OK;
  673. } /* DD_Palette_GetCaps */
  674. #undef DPF_MODNAME
  675. #define DPF_MODNAME "Initialize"
  676. /*
  677. * DD_Palette_Initialize
  678. */
  679. HRESULT DDAPI DD_Palette_Initialize(
  680. LPDIRECTDRAWPALETTE lpDDPalette,
  681. LPDIRECTDRAW lpDD,
  682. DWORD dwFlags,
  683. LPPALETTEENTRY lpDDColorTable )
  684. {
  685. DPF_ERR( "DirectDrawPalette: DD_Palette_Initialize");
  686. DPF(2,A,"ENTERAPI: ");
  687. return DDERR_ALREADYINITIALIZED;
  688. } /* DD_Palette_Initialize */
  689. #undef DPF_MODNAME
  690. #define DPF_MODNAME "SetEntries"
  691. /*
  692. * DD_Palette_SetEntries
  693. */
  694. HRESULT DDAPI DD_Palette_SetEntries(
  695. LPDIRECTDRAWPALETTE lpDDPalette,
  696. DWORD dwFlags,
  697. DWORD dwBase,
  698. DWORD dwNumEntries,
  699. LPPALETTEENTRY lpEntries )
  700. {
  701. LPDDRAWI_DDRAWPALETTE_INT this_int;
  702. LPDDRAWI_DDRAWPALETTE_LCL this_lcl;
  703. LPDDRAWI_DDRAWPALETTE_GBL this;
  704. DWORD rc;
  705. DDHAL_SETENTRIESDATA sed;
  706. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  707. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  708. LPDDHALPALCB_SETENTRIES sehalfn;
  709. LPDDHALPALCB_SETENTRIES sefn;
  710. DWORD size;
  711. BOOL emulation;
  712. DWORD entry_size;
  713. ENTER_BOTH();
  714. DPF(2,A,"ENTERAPI: DD_Palette_SetEntries");
  715. TRY
  716. {
  717. this_int = (LPDDRAWI_DDRAWPALETTE_INT) lpDDPalette;
  718. if( !VALID_DIRECTDRAWPALETTE_PTR( this_int ) )
  719. {
  720. LEAVE_BOTH();
  721. return DDERR_INVALIDOBJECT;
  722. }
  723. this_lcl = this_int->lpLcl;
  724. if( dwFlags )
  725. {
  726. DPF_ERR( "Invalid flags" );
  727. LEAVE_BOTH();
  728. return DDERR_INVALIDPARAMS;
  729. }
  730. this = this_lcl->lpGbl;
  731. /*
  732. * check number of entries
  733. */
  734. size = FLAGS_TO_SIZE( this->dwFlags );
  735. if( dwNumEntries < 1 || dwNumEntries > size )
  736. {
  737. DPF_ERR( "Invalid number of entries" );
  738. LEAVE_BOTH();
  739. return DDERR_INVALIDPARAMS;
  740. }
  741. if( dwBase >= size )
  742. {
  743. DPF_ERR( "Invalid base palette index" );
  744. LEAVE_BOTH();
  745. return DDERR_INVALIDPARAMS;
  746. }
  747. if( dwNumEntries+dwBase > size )
  748. {
  749. DPF_ERR( "palette indices requested would go past the end of the palette" );
  750. LEAVE_BOTH();
  751. return DDERR_INVALIDPARAMS;
  752. }
  753. if( this->dwFlags & DDRAWIPAL_STORED_8INDEX )
  754. {
  755. entry_size = sizeof( BYTE );
  756. if( !VALID_BYTE_ARRAY( lpEntries, dwNumEntries ) )
  757. {
  758. DPF_ERR( "Invalid 8-bit palette index array" );
  759. LEAVE_BOTH();
  760. return DDERR_INVALIDPARAMS;
  761. }
  762. }
  763. else
  764. {
  765. entry_size = sizeof( PALETTEENTRY );
  766. if( !VALID_PALETTEENTRY_ARRAY( lpEntries, dwNumEntries ) )
  767. {
  768. DPF_ERR( "Invalid PALETTEENTRY array" );
  769. LEAVE_BOTH();
  770. return DDERR_INVALIDPARAMS;
  771. }
  772. }
  773. pdrv_lcl = this->lpDD_lcl;
  774. pdrv = pdrv_lcl->lpGbl;
  775. /*
  776. * copy the entries
  777. */
  778. memcpy( ((LPBYTE)this->lpColorTable) + (entry_size * dwBase),
  779. lpEntries, dwNumEntries * entry_size );
  780. }
  781. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  782. {
  783. DPF_ERR( "Exception encountered validating parameters" );
  784. LEAVE_BOTH();
  785. return DDERR_INVALIDPARAMS;
  786. }
  787. if( ( pdrv_lcl->lpDDCB->HALDDPalette.SetEntries == NULL ) ||
  788. ( this->dwFlags & DDRAWIPAL_INHEL ) )
  789. {
  790. // use HEL
  791. sefn = pdrv_lcl->lpDDCB->HELDDPalette.SetEntries;
  792. sehalfn = sefn;
  793. emulation = TRUE;
  794. }
  795. else
  796. {
  797. // use HAL
  798. sefn = pdrv_lcl->lpDDCB->HALDDPalette.SetEntries;
  799. sehalfn = pdrv_lcl->lpDDCB->cbDDPaletteCallbacks.SetEntries;
  800. emulation = FALSE;
  801. }
  802. if( sehalfn != NULL )
  803. {
  804. sed.SetEntries = sehalfn;
  805. sed.lpDD = pdrv;
  806. sed.lpDDPalette = this;
  807. sed.dwBase = dwBase;
  808. sed.dwNumEntries = dwNumEntries;
  809. sed.lpEntries = lpEntries;
  810. DOHALCALL_NOWIN16( SetEntries, sefn, sed, rc, emulation );
  811. if( rc == DDHAL_DRIVER_HANDLED )
  812. {
  813. if( sed.ddRVal != DD_OK )
  814. {
  815. DPF( 5, "DDHAL_SetEntries: ddrval = %ld", sed.ddRVal );
  816. LEAVE_BOTH();
  817. return (DWORD) sed.ddRVal;
  818. }
  819. // We have now set the palette as we have been asked; so
  820. // we may need to update some outstanding DCs.
  821. UpdateDCOnPaletteChanges( this );
  822. }
  823. }
  824. else
  825. {
  826. LEAVE_BOTH();
  827. return DDERR_UNSUPPORTED;
  828. }
  829. BUMP_PALETTE_STAMP(this);
  830. /*
  831. * If the palette's handle is non-zero, that means the palette has already been exposed to the
  832. * driver by a palette associate notify call. If the handle is zero, then the driver has never
  833. * seen the palette before and doesn't care about setentries for it. The driver will get its
  834. * first setentries immediately after the setpalette call (See DD_Surface_SetPalette)
  835. * Mustn't do this on ddhelp's context, since the DLL will be long gone. (Note this should never
  836. * happen anyway).
  837. */
  838. if( dwHelperPid != GetCurrentProcessId() )
  839. {
  840. if (this->dwHandle)
  841. {
  842. if ( pdrv_lcl->pPaletteUpdateNotify && pdrv_lcl->pD3DIUnknown)
  843. {
  844. pdrv_lcl->pPaletteUpdateNotify( pdrv_lcl->pD3DIUnknown, this->dwHandle , dwBase, dwNumEntries, lpEntries );
  845. }
  846. }
  847. }
  848. LEAVE_BOTH();
  849. return DD_OK;
  850. } /* DD_Palette_SetEntries */
  851. #undef DPF_MODNAME
  852. #define DPF_MODNAME "GetEntries"
  853. /*
  854. * DD_Palette_GetEntries
  855. */
  856. HRESULT DDAPI DD_Palette_GetEntries(
  857. LPDIRECTDRAWPALETTE lpDDPalette,
  858. DWORD dwFlags,
  859. DWORD dwBase,
  860. DWORD dwNumEntries,
  861. LPPALETTEENTRY lpEntries )
  862. {
  863. LPDDRAWI_DDRAWPALETTE_INT this_int;
  864. LPDDRAWI_DDRAWPALETTE_LCL this_lcl;
  865. LPDDRAWI_DDRAWPALETTE_GBL this;
  866. DWORD size;
  867. DWORD entry_size;
  868. ENTER_DDRAW();
  869. DPF(2,A,"ENTERAPI: DD_Palette_GetEntries");
  870. TRY
  871. {
  872. this_int = (LPDDRAWI_DDRAWPALETTE_INT) lpDDPalette;
  873. if( !VALID_DIRECTDRAWPALETTE_PTR( this_int ) )
  874. {
  875. LEAVE_DDRAW();
  876. return DDERR_INVALIDOBJECT;
  877. }
  878. this_lcl = this_int->lpLcl;
  879. if( dwFlags )
  880. {
  881. DPF_ERR( "Invalid flags" );
  882. LEAVE_DDRAW();
  883. return DDERR_INVALIDPARAMS;
  884. }
  885. this = this_lcl->lpGbl;
  886. /*
  887. * check number of entries
  888. */
  889. size = FLAGS_TO_SIZE( this->dwFlags );
  890. if( dwNumEntries < 1 || dwNumEntries > size )
  891. {
  892. DPF_ERR( "Invalid number of entries" );
  893. LEAVE_DDRAW();
  894. return DDERR_INVALIDPARAMS;
  895. }
  896. if( dwBase >= size )
  897. {
  898. DPF_ERR( "Invalid base palette index" );
  899. LEAVE_DDRAW();
  900. return DDERR_INVALIDPARAMS;
  901. }
  902. if( dwNumEntries+dwBase > size )
  903. {
  904. DPF_ERR( "palette indices requested would go past the end of the palette" );
  905. LEAVE_DDRAW();
  906. return DDERR_INVALIDPARAMS;
  907. }
  908. if( this->dwFlags & DDRAWIPAL_STORED_8INDEX )
  909. {
  910. entry_size = sizeof( BYTE );
  911. if( !VALID_BYTE_ARRAY( lpEntries, dwNumEntries ) )
  912. {
  913. DPF_ERR( "Invalid 8-bit palette index array" );
  914. LEAVE_DDRAW();
  915. return DDERR_INVALIDPARAMS;
  916. }
  917. }
  918. else
  919. {
  920. entry_size = sizeof( PALETTEENTRY );
  921. if( !VALID_PALETTEENTRY_ARRAY( lpEntries, dwNumEntries ) )
  922. {
  923. DPF_ERR( "Invalid PALETTEENTRY array" );
  924. LEAVE_DDRAW();
  925. return DDERR_INVALIDPARAMS;
  926. }
  927. }
  928. /* GetEntries function body */
  929. memcpy( lpEntries, ((LPBYTE)this->lpColorTable) + (dwBase * entry_size),
  930. dwNumEntries * entry_size );
  931. }
  932. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  933. {
  934. DPF_ERR( "Exception encountered validating parameters" );
  935. LEAVE_DDRAW();
  936. return DDERR_INVALIDPARAMS;
  937. }
  938. LEAVE_DDRAW();
  939. return DD_OK;
  940. } /* DD_Palette_GetEntries */
  941. #undef DPF_MODNAME
  942. #define DPF_MODNAME "GetPalette"
  943. /*
  944. * DD_Surface_GetPalette
  945. *
  946. * Surface function: get the palette associated with surface
  947. */
  948. HRESULT DDAPI DD_Surface_GetPalette(
  949. LPDIRECTDRAWSURFACE lpDDSurface,
  950. LPDIRECTDRAWPALETTE FAR * lplpDDPalette)
  951. {
  952. LPDDRAWI_DDRAWSURFACE_INT this_int;
  953. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  954. LPDDRAWI_DDRAWSURFACE_GBL this;
  955. HRESULT hr;
  956. ENTER_DDRAW();
  957. DPF(2,A,"ENTERAPI: DD_Surface_GetPalette");
  958. TRY
  959. {
  960. if( !VALID_PTR_PTR( lplpDDPalette ) )
  961. {
  962. DPF_ERR( "Invalid palette pointer" );
  963. LEAVE_DDRAW();
  964. return DDERR_INVALIDPARAMS;
  965. }
  966. *lplpDDPalette = NULL; // in case we fail
  967. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  968. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  969. {
  970. LEAVE_DDRAW();
  971. return DDERR_INVALIDOBJECT;
  972. }
  973. this_lcl = this_int->lpLcl;
  974. this = this_lcl->lpGbl;
  975. if( SURFACE_LOST( this_lcl ) )
  976. {
  977. LEAVE_DDRAW();
  978. return DDERR_SURFACELOST;
  979. }
  980. //
  981. // For now, if the current surface is optimized, quit
  982. //
  983. if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
  984. {
  985. DPF_ERR( "It is an optimized surface" );
  986. LEAVE_DDRAW();
  987. return DDERR_ISOPTIMIZEDSURFACE;
  988. }
  989. if( this_lcl->lpDDPalette == NULL )
  990. {
  991. DPF( 1, "No palette associated with surface" );
  992. LEAVE_DDRAW();
  993. return DDERR_NOPALETTEATTACHED;
  994. }
  995. }
  996. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  997. {
  998. DPF_ERR( "Exception encountered validating parameters" );
  999. LEAVE_DDRAW();
  1000. return DDERR_INVALIDPARAMS;
  1001. }
  1002. #ifdef POSTPONED
  1003. if (LOWERTHANSURFACE4(this_int))
  1004. {
  1005. hr = DD_Palette_QueryInterface(
  1006. (LPDIRECTDRAWPALETTE) this_lcl->lpDDPalette,
  1007. &IID_IDirectDrawPalette,
  1008. (void**)lplpDDPalette );
  1009. }
  1010. else
  1011. {
  1012. hr = DD_Palette_QueryInterface(
  1013. (LPDIRECTDRAWPALETTE) this_lcl->lpDDPalette,
  1014. &IID_IDirectDrawPalette2,
  1015. (void**)lplpDDPalette );
  1016. }
  1017. #else
  1018. hr = DD_Palette_QueryInterface(
  1019. (LPDIRECTDRAWPALETTE) this_lcl->lpDDPalette,
  1020. &IID_IDirectDrawPalette,
  1021. (void**)lplpDDPalette );
  1022. #endif
  1023. LEAVE_DDRAW();
  1024. return hr;
  1025. } /* DD_Surface_GetPalette */
  1026. #undef DPF_MODNAME
  1027. #define DPF_MODNAME "SetPalette"
  1028. /*
  1029. * DD_Surface_SetPalette
  1030. *
  1031. * Surface function: set the palette associated with surface
  1032. *
  1033. * NOTE: Currently the only way a windowed app. has of
  1034. * realizing its palette on the primary is to call SetPalette
  1035. * (full screen app. palette's are realized for them by the
  1036. * WM_ACTIVATEAPP hook). Hence, the logic is to AddRef the
  1037. * palette only if it is not already set as the surface's
  1038. * palette).
  1039. * Perhaps we need a RealizePalette() call?
  1040. */
  1041. HRESULT DDAPI DD_Surface_SetPalette(
  1042. LPDIRECTDRAWSURFACE lpDDSurface,
  1043. LPDIRECTDRAWPALETTE lpDDPalette )
  1044. {
  1045. LPDDRAWI_DDRAWSURFACE_INT this_int;
  1046. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  1047. LPDDRAWI_DDRAWSURFACE_GBL this;
  1048. LPDDRAWI_DDRAWPALETTE_INT this_pal_int;
  1049. LPDDRAWI_DDRAWPALETTE_LCL this_pal_lcl;
  1050. LPDDRAWI_DDRAWPALETTE_GBL this_pal;
  1051. LPDDRAWI_DDRAWPALETTE_INT prev_pal_int;
  1052. LPDDPIXELFORMAT pddpf;
  1053. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  1054. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  1055. BOOL attach;
  1056. DWORD rc;
  1057. DDHAL_SETPALETTEDATA spd;
  1058. LPDDHALSURFCB_SETPALETTE sphalfn;
  1059. LPDDHALSURFCB_SETPALETTE spfn;
  1060. BOOL emulation;
  1061. BOOL isprimary;
  1062. BOOL excl_exists;
  1063. BOOL has_excl;
  1064. ENTER_BOTH();
  1065. DPF(2,A,"ENTERAPI: DD_Surface_SetPalette");
  1066. TRY
  1067. {
  1068. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  1069. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  1070. {
  1071. LEAVE_BOTH();
  1072. return DDERR_INVALIDOBJECT;
  1073. }
  1074. this_lcl = this_int->lpLcl;
  1075. this = this_lcl->lpGbl;
  1076. //
  1077. // For now, if the current surface is optimized, quit
  1078. //
  1079. if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
  1080. {
  1081. DPF_ERR( "It is an optimized surface" );
  1082. LEAVE_DDRAW();
  1083. return DDERR_ISOPTIMIZEDSURFACE;
  1084. }
  1085. /*
  1086. * Palettes don't make any sense on z-buffers or execute
  1087. * buffers.
  1088. */
  1089. if( this_lcl->ddsCaps.dwCaps & ( DDSCAPS_ZBUFFER | DDSCAPS_EXECUTEBUFFER ) )
  1090. {
  1091. DPF_ERR( "Invalid surface type: cannot attach palette" );
  1092. LEAVE_BOTH();
  1093. return DDERR_INVALIDSURFACETYPE;
  1094. }
  1095. //
  1096. // New interfaces don't let mipmap sublevels have palettes
  1097. //
  1098. if ((!LOWERTHANSURFACE7(this_int)) &&
  1099. (this_lcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL))
  1100. {
  1101. DPF_ERR( "Cannot attach palette to mipmap sublevels" );
  1102. LEAVE_BOTH();
  1103. return DDERR_NOTONMIPMAPSUBLEVEL;
  1104. }
  1105. if( SURFACE_LOST( this_lcl ) )
  1106. {
  1107. LEAVE_BOTH();
  1108. return DDERR_SURFACELOST;
  1109. }
  1110. this_pal_int = (LPDDRAWI_DDRAWPALETTE_INT) lpDDPalette;
  1111. if( this_pal_int != NULL )
  1112. {
  1113. if( !VALID_DIRECTDRAWPALETTE_PTR( this_pal_int ) )
  1114. {
  1115. LEAVE_BOTH();
  1116. return DDERR_INVALIDOBJECT;
  1117. }
  1118. this_pal_lcl = this_pal_int->lpLcl;
  1119. this_pal = this_pal_lcl->lpGbl;
  1120. }
  1121. else
  1122. {
  1123. this_pal_lcl = NULL;
  1124. this_pal = NULL;
  1125. }
  1126. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  1127. pdrv = pdrv_lcl->lpGbl;
  1128. if ( this_pal_int &&
  1129. (this_pal->dwFlags & DDRAWIPAL_ALPHA) &&
  1130. (! (this_lcl->ddsCaps.dwCaps & DDSCAPS_TEXTURE)) )
  1131. {
  1132. DPF_ERR( "Attaching palette w/alpha to non-texture surface" );
  1133. LEAVE_BOTH();
  1134. return DDERR_INVALIDSURFACETYPE;
  1135. }
  1136. /*
  1137. * don't allow a palette from one global to be
  1138. * used with a different one (because it doesn't work)
  1139. */
  1140. if( this_pal_int && pdrv != this_pal_lcl->lpDD_lcl->lpGbl )
  1141. {
  1142. /*
  1143. * Don't check if either device isn't a display driver (i.e. 3dfx)
  1144. * since that's a back-compat hole.
  1145. */
  1146. if ( (this->lpDD->dwFlags & DDRAWI_DISPLAYDRV) &&
  1147. (this_pal_lcl->lpDD_lcl->lpGbl->dwFlags & DDRAWI_DISPLAYDRV) )
  1148. {
  1149. DPF_ERR( "Can't set a palette created from one DDraw onto a surface created by another DDraw" );
  1150. LEAVE_BOTH();
  1151. return DDERR_INVALIDPARAMS;
  1152. }
  1153. }
  1154. CheckExclusiveMode(pdrv_lcl, &excl_exists, &has_excl, FALSE, NULL, FALSE);
  1155. /*
  1156. * don't allow primary palette set if not exclusive mode owner
  1157. */
  1158. isprimary = FALSE;
  1159. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE )
  1160. {
  1161. isprimary = TRUE;
  1162. if( excl_exists )
  1163. {
  1164. if( !has_excl )
  1165. {
  1166. DPF_ERR( "Cannot set palette on primary when other process owns exclusive mode" );
  1167. LEAVE_BOTH();
  1168. return DDERR_NOEXCLUSIVEMODE;
  1169. }
  1170. }
  1171. }
  1172. /*
  1173. * Was a palette previously attached to this surface?
  1174. * If so, we will need to release if all goes well so
  1175. * remember it.
  1176. */
  1177. prev_pal_int = this_lcl->lpDDPalette;
  1178. /*
  1179. * NULL palette, remove palette from this surface
  1180. */
  1181. attach = TRUE;
  1182. if( this_pal == NULL )
  1183. {
  1184. attach = FALSE;
  1185. this_pal_int = prev_pal_int;
  1186. if( this_pal_int == NULL )
  1187. {
  1188. DPF_ERR( "No attached palette" );
  1189. LEAVE_BOTH();
  1190. return DDERR_NOPALETTEATTACHED;
  1191. }
  1192. this_pal_lcl = this_pal_int->lpLcl;
  1193. this_pal = this_pal_lcl->lpGbl;
  1194. }
  1195. if( attach )
  1196. {
  1197. /*
  1198. * NOTE: We used to do a lot of HEL specific checking. With the
  1199. * addition of support for palettes on non-primary surfaces and
  1200. * non-256 entry palettes this became redundant. We also used
  1201. * to explicitly check that, if attaching to the primary, the
  1202. * current mode was palettized and 8-bit. Doesn't look to me like
  1203. * any of that was necessary as DDPF_PALETTEINDEXED8 should be
  1204. * set if the primary is 8-bit palettized.
  1205. */
  1206. GET_PIXEL_FORMAT( this_lcl, this, pddpf );
  1207. if( ( ( this_pal->dwFlags & DDRAWIPAL_2 ) && !( pddpf->dwFlags & DDPF_PALETTEINDEXED1 ) ) ||
  1208. ( ( this_pal->dwFlags & DDRAWIPAL_4 ) && !( pddpf->dwFlags & DDPF_PALETTEINDEXED2 ) ) ||
  1209. ( ( this_pal->dwFlags & DDRAWIPAL_16 ) && !( pddpf->dwFlags & DDPF_PALETTEINDEXED4 ) ) ||
  1210. ( ( this_pal->dwFlags & DDRAWIPAL_256 ) && !( pddpf->dwFlags & DDPF_PALETTEINDEXED8 ) ) )
  1211. {
  1212. DPF_ERR( "Palette size does not match surface format - cannot set palette" );
  1213. LEAVE_BOTH();
  1214. return DDERR_INVALIDPIXELFORMAT;
  1215. }
  1216. /*
  1217. * Ensure that both the palette and surface agree on whether they are using
  1218. * indices into the destination surface's palette.
  1219. */
  1220. if( this_pal->dwFlags & DDRAWIPAL_STORED_8INDEX )
  1221. {
  1222. if( !(pddpf->dwFlags & DDPF_PALETTEINDEXEDTO8) )
  1223. {
  1224. DPF_ERR( "Surface is not PALETTEINDEXEDTO8 - cannot set palette" );
  1225. LEAVE_BOTH();
  1226. return DDERR_INVALIDPIXELFORMAT;
  1227. }
  1228. }
  1229. else
  1230. {
  1231. if( pddpf->dwFlags & DDPF_PALETTEINDEXEDTO8 )
  1232. {
  1233. DPF_ERR( "Surface is PALETTEINDEXEDTO8 - cannot set palette" );
  1234. LEAVE_BOTH();
  1235. return DDERR_INVALIDPIXELFORMAT;
  1236. }
  1237. }
  1238. }
  1239. }
  1240. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1241. {
  1242. DPF_ERR( "Exception encountered validating parameters" );
  1243. LEAVE_BOTH();
  1244. return DDERR_INVALIDPARAMS;
  1245. }
  1246. /*
  1247. * ATTENTION!!!
  1248. * We shouldn't pass optimized surfaces to an unsuspecting HAL, but if we don't then we could
  1249. * break drivers that hook SetPalette... Since the HAL is probably only going to be watching
  1250. * for a primary, and also is unlikely to go looking at the surface's contents,
  1251. * I'm going to let this one slide.
  1252. */
  1253. if( ( this_pal->dwFlags & DDRAWIPAL_INHEL) ||
  1254. ( pdrv_lcl->lpDDCB->HALDDSurface.SetPalette == NULL ) )
  1255. {
  1256. // use HEL
  1257. spfn = pdrv_lcl->lpDDCB->HELDDSurface.SetPalette;
  1258. sphalfn = spfn;
  1259. emulation = TRUE;
  1260. }
  1261. else
  1262. {
  1263. // use HAL
  1264. spfn = pdrv_lcl->lpDDCB->HALDDSurface.SetPalette;
  1265. sphalfn = pdrv_lcl->lpDDCB->cbDDSurfaceCallbacks.SetPalette;
  1266. emulation = FALSE;
  1267. }
  1268. if( sphalfn != NULL )
  1269. {
  1270. spd.SetPalette = sphalfn;
  1271. spd.lpDD = pdrv;
  1272. spd.lpDDPalette = this_pal;
  1273. spd.lpDDSurface = this_lcl;
  1274. spd.Attach = attach;
  1275. DOHALCALL_NOWIN16( SetPalette, spfn, spd, rc, emulation );
  1276. if( rc == DDHAL_DRIVER_HANDLED )
  1277. {
  1278. if( spd.ddRVal == DD_OK )
  1279. {
  1280. if( attach )
  1281. {
  1282. /*
  1283. * Only AddRef the palette if its being attached to
  1284. * a new surface.
  1285. */
  1286. if( this_lcl->lpDDPalette != this_pal_int )
  1287. {
  1288. this_lcl->lpDDPalette = this_pal_int;
  1289. DD_Palette_AddRef( lpDDPalette );
  1290. }
  1291. }
  1292. else
  1293. {
  1294. this_lcl->lpDDPalette = NULL;
  1295. }
  1296. /*
  1297. * If we had a previous palette and it was different
  1298. * from the new palette then we must release it.
  1299. * NOTE: We compare against the incoming parameter
  1300. * rather than this_pal_lcl as this_pal_lcl is set to the
  1301. * previous palette if we are removing a palette.
  1302. * NOTE: It is important that we update the surface's
  1303. * palette pointer before calling Release() as, otherwise,
  1304. * release can end up calling SetPalette() and so on.
  1305. */
  1306. if( ( prev_pal_int != NULL ) &&
  1307. ( prev_pal_int != (LPDDRAWI_DDRAWPALETTE_INT )lpDDPalette ) )
  1308. {
  1309. // This palette may no longer the exclusive one
  1310. if( isprimary )
  1311. {
  1312. if( has_excl )
  1313. {
  1314. prev_pal_int->lpLcl->lpGbl->dwFlags &= ~DDRAWIPAL_EXCLUSIVE;
  1315. }
  1316. }
  1317. // Release it
  1318. DD_Palette_Release( (LPDIRECTDRAWPALETTE)prev_pal_int );
  1319. }
  1320. if( attach )
  1321. {
  1322. // Ok, we have set the palette onto the surface
  1323. // Check if there are any outstanding DCs that need updating
  1324. UpdateOutstandingDC( this_lcl, this_pal );
  1325. }
  1326. else
  1327. {
  1328. // Ok, we have removed a palette onto the surface
  1329. // Check if there are any outstanding DCs that need updating
  1330. UpdateOutstandingDC( this_lcl, NULL );
  1331. }
  1332. BUMP_SURFACE_STAMP(this);
  1333. /*
  1334. * Update the driver's associations and palette entries
  1335. */
  1336. if( dwHelperPid != GetCurrentProcessId() )
  1337. {
  1338. BOOL bUpdateEntries = FALSE;
  1339. if (attach)
  1340. {
  1341. if (this_pal->dwHandle == 0)
  1342. {
  1343. /*
  1344. * The driver has never seen this palette before. We must send an associate notify first, and
  1345. * then an update entries
  1346. */
  1347. bUpdateEntries = TRUE;
  1348. this_pal->dwHandle = GeneratePaletteHandle(pdrv_lcl);
  1349. }
  1350. if (this_pal->dwHandle && pdrv_lcl->pD3DIUnknown )
  1351. //could be zero in low memory conditions
  1352. {
  1353. if ( pdrv_lcl->pPaletteAssociateNotify )
  1354. {
  1355. // NOTE: we send the handle for DX6 and down
  1356. // for DX7 we pass the the local itself.
  1357. // DX7 needs the whole local to get the
  1358. // batching correct; MB41840
  1359. if( DDRAWILCL_DIRECTDRAW7 & pdrv_lcl->dwLocalFlags )
  1360. {
  1361. LPPALETTEASSOCIATENOTIFY7 pPaletteAssociateNotify =
  1362. (LPPALETTEASSOCIATENOTIFY7)pdrv_lcl->pPaletteAssociateNotify;
  1363. pPaletteAssociateNotify(
  1364. pdrv_lcl->pD3DIUnknown,
  1365. this_pal->dwHandle,
  1366. this_pal->dwFlags,
  1367. this_lcl );
  1368. }
  1369. else
  1370. {
  1371. // When a DX6 app is talking to a DX7 driver,
  1372. // we need to force a flush of the token
  1373. // stream as part of this SetPalette.
  1374. //
  1375. // This automatically happens if the number
  1376. // of devices is > 1. So if necessary
  1377. // we temporarily increment the device
  1378. // count. We don't do this for IA64.
  1379. // MB41840 for more details.
  1380. #ifndef _WIN64
  1381. DWORD *pIUnknown = (DWORD *)(pdrv_lcl->pD3DIUnknown);
  1382. DWORD *pD3D = (DWORD *)(*(pIUnknown + 2));
  1383. DWORD *pnumDevs = (DWORD *)(pD3D + 3);
  1384. BOOL bFixDeviceCount = FALSE;
  1385. DDASSERT(pD3D != NULL);
  1386. if (*pnumDevs == 1)
  1387. {
  1388. *pnumDevs = 2;
  1389. bFixDeviceCount = TRUE;
  1390. }
  1391. #endif // _WIN64
  1392. pdrv_lcl->pPaletteAssociateNotify(
  1393. pdrv_lcl->pD3DIUnknown,
  1394. this_pal->dwHandle,
  1395. this_pal->dwFlags,
  1396. this_lcl->lpSurfMore->dwSurfaceHandle );
  1397. #ifndef _WIN64
  1398. // Restore the device count
  1399. if (bFixDeviceCount)
  1400. {
  1401. DDASSERT(*pnumDevs == 2);
  1402. *pnumDevs = 1;
  1403. }
  1404. #endif // _WIN64
  1405. }
  1406. }
  1407. if ( pdrv_lcl->pPaletteUpdateNotify )
  1408. {
  1409. pdrv_lcl->pPaletteUpdateNotify(
  1410. pdrv_lcl->pD3DIUnknown,
  1411. this_pal->dwHandle ,
  1412. 0,
  1413. FLAGS_TO_SIZE(this_pal->dwFlags),
  1414. this_pal->lpColorTable );
  1415. }
  1416. }
  1417. }
  1418. }
  1419. }
  1420. LEAVE_BOTH();
  1421. return spd.ddRVal;
  1422. }
  1423. LEAVE_BOTH();
  1424. return DDERR_UNSUPPORTED;
  1425. }
  1426. /*
  1427. * !!! NOTE: Currently if the driver does not care about
  1428. * SetPalette we do nothing but return OK. Should we
  1429. * not, however, still point the surface at the palette
  1430. * and point the palette at the surface at the very
  1431. * least?
  1432. */
  1433. LEAVE_BOTH();
  1434. return DD_OK;
  1435. } /* DD_Surface_SetPalette */
  1436. /*
  1437. * SetPaletteAlways
  1438. */
  1439. HRESULT SetPaletteAlways(
  1440. LPDDRAWI_DDRAWSURFACE_INT psurf_int,
  1441. LPDIRECTDRAWPALETTE lpDDPalette )
  1442. {
  1443. LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
  1444. DWORD oldflag;
  1445. HRESULT ddrval;
  1446. psurf_lcl = psurf_int->lpLcl;
  1447. oldflag = psurf_lcl->dwFlags & DDRAWISURF_INVALID;
  1448. psurf_lcl->dwFlags &= ~DDRAWISURF_INVALID;
  1449. ddrval = DD_Surface_SetPalette( (LPDIRECTDRAWSURFACE) psurf_int, lpDDPalette );
  1450. psurf_lcl->dwFlags |= oldflag;
  1451. return ddrval;
  1452. } /* SetPaletteAlways */
  1453. #undef DPF_MODNAME
  1454. #define DPF_MODNAME "CreatePalette"
  1455. /*
  1456. * DD_CreatePalette
  1457. *
  1458. * Driver function: create a palette
  1459. */
  1460. HRESULT DDAPI DD_CreatePalette(
  1461. LPDIRECTDRAW lpDD,
  1462. DWORD dwFlags,
  1463. LPPALETTEENTRY lpColorTable,
  1464. LPDIRECTDRAWPALETTE FAR *lplpDDPalette,
  1465. IUnknown FAR *pUnkOuter )
  1466. {
  1467. LPDDRAWI_DIRECTDRAW_INT this_int;
  1468. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  1469. LPDDRAWI_DIRECTDRAW_GBL this;
  1470. LPDDRAWI_DDRAWPALETTE_INT ppal_int;
  1471. LPDDRAWI_DDRAWPALETTE_LCL ppal_lcl;
  1472. LPDDRAWI_DDRAWPALETTE_GBL ppal;
  1473. DWORD pal_size;
  1474. DDHAL_CREATEPALETTEDATA cpd;
  1475. DWORD rc;
  1476. DWORD pflags;
  1477. BOOL is_excl;
  1478. LPDDHAL_CREATEPALETTE cpfn;
  1479. LPDDHAL_CREATEPALETTE cphalfn;
  1480. BOOL emulation;
  1481. BYTE indexedpe;
  1482. BYTE hackindexedpe;
  1483. PALETTEENTRY pe;
  1484. PALETTEENTRY hackpe;
  1485. DWORD num_entries;
  1486. DWORD entry_size;
  1487. int num_size_flags;
  1488. if( pUnkOuter != NULL )
  1489. {
  1490. return CLASS_E_NOAGGREGATION;
  1491. }
  1492. ENTER_DDRAW();
  1493. DPF(2,A,"ENTERAPI: DD_CreatePalette");
  1494. TRY
  1495. {
  1496. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  1497. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  1498. {
  1499. LEAVE_DDRAW();
  1500. return DDERR_INVALIDOBJECT;
  1501. }
  1502. this_lcl = this_int->lpLcl;
  1503. this = this_lcl->lpGbl;
  1504. if( !VALID_PTR_PTR( lplpDDPalette ) )
  1505. {
  1506. LEAVE_DDRAW();
  1507. return DDERR_INVALIDPARAMS;
  1508. }
  1509. *lplpDDPalette = NULL;
  1510. if( dwFlags & ~DDPCAPS_VALID )
  1511. {
  1512. DPF_ERR( "Invalid caps" );
  1513. LEAVE_DDRAW();
  1514. return DDERR_INVALIDPARAMS;
  1515. }
  1516. /*
  1517. * verify that cooperative level is set
  1518. */
  1519. if( !(this_lcl->dwLocalFlags & DDRAWILCL_SETCOOPCALLED) )
  1520. {
  1521. DPF_ERR( "Must call SetCooperativeLevel before calling Create functions" );
  1522. LEAVE_DDRAW();
  1523. return DDERR_NOCOOPERATIVELEVELSET;
  1524. }
  1525. /*
  1526. * verify flags
  1527. */
  1528. if( dwFlags & (DDPCAPS_VSYNC|
  1529. DDPCAPS_PRIMARYSURFACE|
  1530. DDPCAPS_PRIMARYSURFACELEFT) )
  1531. {
  1532. DPF_ERR( "Read only flags specified" );
  1533. LEAVE_DDRAW();
  1534. return DDERR_INVALIDPARAMS;
  1535. }
  1536. num_size_flags = 0;
  1537. if( dwFlags & DDPCAPS_1BIT )
  1538. num_size_flags++;
  1539. if( dwFlags & DDPCAPS_2BIT )
  1540. num_size_flags++;
  1541. if( dwFlags & DDPCAPS_4BIT )
  1542. num_size_flags++;
  1543. if( dwFlags & DDPCAPS_8BIT )
  1544. num_size_flags++;
  1545. if( num_size_flags != 1 )
  1546. {
  1547. DPF_ERR( "Must specify one and one only of 2, 4, 16 or 256 color palette" );
  1548. LEAVE_DDRAW();
  1549. return DDERR_INVALIDPARAMS;
  1550. }
  1551. if( dwFlags & DDPCAPS_ALPHA )
  1552. {
  1553. if( dwFlags & DDPCAPS_8BITENTRIES )
  1554. {
  1555. DPF_ERR( "8BITENTRIES not valid with ALPHA" );
  1556. LEAVE_DDRAW();
  1557. return DDERR_INVALIDPARAMS;
  1558. }
  1559. }
  1560. if( dwFlags & DDPCAPS_8BIT )
  1561. {
  1562. if( dwFlags & DDPCAPS_8BITENTRIES )
  1563. {
  1564. DPF_ERR( "8BITENTRIES only valid with 1BIT, 2BIT or 4BIT palette" );
  1565. LEAVE_DDRAW();
  1566. return DDERR_INVALIDPARAMS;
  1567. }
  1568. }
  1569. else
  1570. {
  1571. if( dwFlags & DDPCAPS_ALLOW256 )
  1572. {
  1573. DPF_ERR( "ALLOW256 only valid with 8BIT palette" );
  1574. LEAVE_DDRAW();
  1575. return DDERR_INVALIDPARAMS;
  1576. }
  1577. }
  1578. pflags = SIZE_PCAPS_TO_FLAGS( dwFlags );
  1579. num_entries = FLAGS_TO_SIZE( pflags );
  1580. /*
  1581. * Can't just assume the lpColorTable is an array of PALETTENTRYs.
  1582. * If DDPCAPS_8BITENTRIES is set then this is in fact an array of
  1583. * bytes in disguise. Validate appropriately.
  1584. */
  1585. if( dwFlags & DDPCAPS_8BITENTRIES )
  1586. {
  1587. entry_size = sizeof(BYTE);
  1588. indexedpe = ((LPBYTE)lpColorTable)[num_entries-1]; // validate
  1589. if( !VALID_BYTE_ARRAY( lpColorTable, num_entries ) )
  1590. {
  1591. DPF_ERR( "Invalid lpColorTable array" );
  1592. LEAVE_DDRAW();
  1593. return DDERR_INVALIDPARAMS;
  1594. }
  1595. /*
  1596. * NOTE: You may well be wondering what this "hackindexedpe" bit is all about.
  1597. * Well - indexedpe is not actually used for anything. It's only a probe to
  1598. * test to see if the color table array is valid. We do this all over the place
  1599. * but unfortunately we don't actually need the result here so our friend
  1600. * Mr. Optimizing Compiler decides to discard the assignment and so nullify
  1601. * the test. In order to ensure the array access stays in we declare dummy
  1602. * variable and assign to them. This is enough to keep the code in (the
  1603. * compiler is not smart enough to see that the variable assigned to is
  1604. * not used). Same goes for hackpe below.
  1605. */
  1606. hackindexedpe = indexedpe;
  1607. }
  1608. else
  1609. {
  1610. entry_size = sizeof(PALETTEENTRY);
  1611. pe = lpColorTable[num_entries-1]; // validate
  1612. if( !VALID_PALETTEENTRY_ARRAY( lpColorTable, num_entries ) )
  1613. {
  1614. DPF_ERR( "Invalid lpColorTable array" );
  1615. LEAVE_DDRAW();
  1616. return DDERR_INVALIDPARAMS;
  1617. }
  1618. hackpe = pe;
  1619. }
  1620. CheckExclusiveMode(this_lcl, NULL, &is_excl, FALSE, NULL, FALSE);
  1621. }
  1622. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1623. {
  1624. DPF_ERR( "Exception encountered validating parameters" );
  1625. LEAVE_DDRAW();
  1626. return DDERR_INVALIDPARAMS;
  1627. }
  1628. /*
  1629. * allocate the palette object
  1630. */
  1631. pal_size = sizeof( DDRAWI_DDRAWPALETTE_GBL ) +
  1632. sizeof( DDRAWI_DDRAWPALETTE_LCL );
  1633. ppal_lcl = (LPDDRAWI_DDRAWPALETTE_LCL) MemAlloc( pal_size );
  1634. if( ppal_lcl == NULL )
  1635. {
  1636. LEAVE_DDRAW();
  1637. return DDERR_OUTOFMEMORY;
  1638. }
  1639. ppal_lcl->lpGbl = (LPDDRAWI_DDRAWPALETTE_GBL) (((LPBYTE)ppal_lcl) +
  1640. sizeof( DDRAWI_DDRAWPALETTE_LCL ) );
  1641. ppal = ppal_lcl->lpGbl;
  1642. ppal_lcl->lpDD_lcl = this_lcl;
  1643. ppal_lcl->lpDD_Int = this_int;
  1644. /*
  1645. * Initialize some palette global state
  1646. */
  1647. ppal->dwContentsStamp = 1;
  1648. if( dwFlags & DDPCAPS_ALLOW256 )
  1649. {
  1650. pflags |= DDRAWIPAL_ALLOW256;
  1651. }
  1652. if( dwFlags & DDPCAPS_8BITENTRIES )
  1653. {
  1654. pflags |= DDRAWIPAL_STORED_8INDEX;
  1655. }
  1656. if (dwFlags & DDPCAPS_ALPHA )
  1657. {
  1658. pflags |= DDRAWIPAL_ALPHA;
  1659. }
  1660. ppal_lcl->pPrivateDataHead = NULL;
  1661. /*
  1662. * allocate palette
  1663. */
  1664. ppal->lpColorTable = MemAlloc( entry_size * num_entries );
  1665. if( ppal->lpColorTable == NULL )
  1666. {
  1667. MemFree( ppal_lcl );
  1668. LEAVE_DDRAW();
  1669. return DDERR_OUTOFMEMORY;
  1670. }
  1671. /*
  1672. * Create an interface for this palette
  1673. */
  1674. #ifdef POSTPONED
  1675. if (LOWERTHANDDRAW4(this_int))
  1676. {
  1677. #endif
  1678. ppal_int = newPaletteInterface( ppal_lcl, (LPVOID)&ddPaletteCallbacks );
  1679. #ifdef POSTPONED
  1680. }
  1681. else
  1682. {
  1683. ppal_int = newPaletteInterface( ppal_lcl, (LPVOID)&ddPalette2Callbacks );
  1684. }
  1685. #endif
  1686. if( NULL == ppal_int )
  1687. {
  1688. MemFree( ppal->lpColorTable );
  1689. MemFree( ppal_lcl );
  1690. LEAVE_DDRAW();
  1691. return DDERR_OUTOFMEMORY;
  1692. }
  1693. /*
  1694. * copy the color table
  1695. * we now copy the color table BEFORE we call the device's CreatePalette()
  1696. * this is done as the device may want to overwrite certain of the palette
  1697. * entries (e.g. if you don't specify DDPCAPS_ALLOW256 then the driver may
  1698. * well choose to overwrite the 0 and 255 with black and white).
  1699. */
  1700. memcpy( ppal->lpColorTable, lpColorTable, entry_size * num_entries );
  1701. /*
  1702. * fill in misc stuff
  1703. */
  1704. ppal->lpDD_lcl = this_lcl;
  1705. ppal->dwFlags = pflags;
  1706. /*
  1707. * are palettes even supported by the driver?
  1708. */
  1709. if( ( this->ddCaps.ddsCaps.dwCaps & DDSCAPS_PALETTE ) ||
  1710. ( this->ddHELCaps.ddsCaps.dwCaps & DDSCAPS_PALETTE ) )
  1711. {
  1712. /* GEE: where do we allow the caller to require the palette
  1713. * be provided in hardware?
  1714. */
  1715. if( (this->dwFlags & DDRAWI_DISPLAYDRV) ||
  1716. this_lcl->lpDDCB->cbDDCallbacks.CreatePalette == NULL )
  1717. {
  1718. // use HEL
  1719. cpfn = this_lcl->lpDDCB->HELDD.CreatePalette;
  1720. cphalfn = cpfn;
  1721. emulation = TRUE;
  1722. }
  1723. else
  1724. {
  1725. // use HAL
  1726. cpfn = this_lcl->lpDDCB->HALDD.CreatePalette;
  1727. cphalfn = this_lcl->lpDDCB->cbDDCallbacks.CreatePalette;
  1728. emulation = FALSE;
  1729. }
  1730. cpd.CreatePalette = this_lcl->lpDDCB->cbDDCallbacks.CreatePalette;
  1731. cpd.lpDD = this;
  1732. cpd.lpDDPalette=ppal;
  1733. cpd.lpColorTable=lpColorTable;
  1734. cpd.is_excl = is_excl;
  1735. DOHALCALL( CreatePalette, cpfn, cpd, rc, emulation );
  1736. if( rc == DDHAL_DRIVER_HANDLED )
  1737. {
  1738. if( cpd.ddRVal != DD_OK )
  1739. {
  1740. DPF( 5, "DDHAL_CreatePalette: ddrval = %ld", cpd.ddRVal );
  1741. LEAVE_DDRAW();
  1742. return cpd.ddRVal;
  1743. }
  1744. }
  1745. else
  1746. {
  1747. LEAVE_DDRAW();
  1748. return DDERR_UNSUPPORTED;
  1749. }
  1750. }
  1751. else
  1752. {
  1753. LEAVE_DDRAW();
  1754. return DDERR_UNSUPPORTED;
  1755. }
  1756. /*
  1757. * bump reference count, return object
  1758. */
  1759. ppal->dwProcessId = GetCurrentProcessId();
  1760. ppal_lcl->dwLocalRefCnt = OBJECT_ISROOT;
  1761. ppal_int->dwIntRefCnt++;
  1762. ppal_lcl->dwLocalRefCnt++;
  1763. ppal->dwRefCnt++;
  1764. *lplpDDPalette = (LPDIRECTDRAWPALETTE) ppal_int;
  1765. /*
  1766. * If this ddraw object generates independent child objects, then this palette takes
  1767. * a ref count on that ddraw object.
  1768. */
  1769. if (CHILD_SHOULD_TAKE_REFCNT(this_int))
  1770. {
  1771. /*
  1772. * We need to remember which interface created this palette, in case we need to take a ref count
  1773. * and then release it when the palette dies
  1774. */
  1775. lpDD->lpVtbl->AddRef(lpDD);
  1776. ppal_lcl->pAddrefedThisOwner = (IUnknown *) lpDD;
  1777. }
  1778. LEAVE_DDRAW();
  1779. return DD_OK;
  1780. } /* DD_CreatePalette */
  1781. /*
  1782. * ProcessPaletteCleanup
  1783. *
  1784. * A process is done, clean up any surfaces that it may have locked.
  1785. *
  1786. * NOTE: we enter with a lock taken on the DIRECTDRAW object.
  1787. */
  1788. void ProcessPaletteCleanup( LPDDRAWI_DIRECTDRAW_GBL pdrv, DWORD pid, LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl )
  1789. {
  1790. LPDDRAWI_DDRAWPALETTE_INT ppal_int;
  1791. LPDDRAWI_DDRAWPALETTE_INT ppnext_int;
  1792. LPDDRAWI_DDRAWPALETTE_GBL ppal;
  1793. DWORD rcnt;
  1794. /*
  1795. * run through all palettes owned by the driver object, and find ones
  1796. * that have been accessed by this process
  1797. */
  1798. ppal_int = pdrv->palList;
  1799. DPF( 4, "ProcessPaletteCleanup, ppal=%08lx", ppal_int );
  1800. while( ppal_int != NULL )
  1801. {
  1802. ULONG rc;
  1803. ppal = ppal_int->lpLcl->lpGbl;
  1804. ppnext_int = ppal_int->lpLink;
  1805. rc = 1;
  1806. if( ( ppal->dwProcessId == pid ) &&
  1807. ( ( NULL == pdrv_lcl ) || ( pdrv_lcl == ppal_int->lpLcl->lpDD_lcl ) ) )
  1808. {
  1809. /*
  1810. * release the references by this process
  1811. */
  1812. rcnt = ppal_int->dwIntRefCnt;
  1813. DPF( 5, "Process %08lx had %ld accesses to palette %08lx", pid, rcnt, ppal_int );
  1814. while( rcnt > 0 )
  1815. {
  1816. rc = InternalPaletteRelease( ppal_int );
  1817. if( rc == 0 )
  1818. {
  1819. break;
  1820. }
  1821. rcnt--;
  1822. }
  1823. }
  1824. else
  1825. {
  1826. DPF( 5, "Process %08lx does not have access to palette" );
  1827. }
  1828. ppal_int = ppnext_int;
  1829. }
  1830. } /* ProcessPaletteCleanup */
  1831. /*
  1832. * DD_Palette_IsEqual
  1833. */
  1834. HRESULT EXTERN_DDAPI DD_Palette_IsEqual(
  1835. LPDIRECTDRAWPALETTE lpDDPThis,
  1836. LPDIRECTDRAWPALETTE lpDDPalette )
  1837. {
  1838. LPDDRAWI_DDRAWPALETTE_INT this_int;
  1839. LPDDRAWI_DDRAWPALETTE_LCL this_lcl;
  1840. LPDDRAWI_DDRAWPALETTE_GBL this;
  1841. LPDDRAWI_DDRAWPALETTE_INT pal_int;
  1842. LPDDRAWI_DDRAWPALETTE_LCL pal_lcl;
  1843. LPDDRAWI_DDRAWPALETTE_GBL pal;
  1844. DWORD size;
  1845. DWORD entry_size;
  1846. UINT i,j;
  1847. DWORD entry;
  1848. ENTER_DDRAW();
  1849. DPF(2,A,"ENTERAPI: DD_Palette_IsEqual");
  1850. TRY
  1851. {
  1852. this_int = (LPDDRAWI_DDRAWPALETTE_INT) lpDDPThis;
  1853. if( !VALID_DIRECTDRAWPALETTE_PTR( this_int ) )
  1854. {
  1855. LEAVE_DDRAW();
  1856. return DDERR_INVALIDOBJECT;
  1857. }
  1858. this_lcl = this_int->lpLcl;
  1859. this = this_lcl->lpGbl;
  1860. pal_int = (LPDDRAWI_DDRAWPALETTE_INT) lpDDPalette;
  1861. if( !VALID_DIRECTDRAWPALETTE_PTR( pal_int ) )
  1862. {
  1863. LEAVE_DDRAW();
  1864. return DDERR_INVALIDPARAMS;
  1865. }
  1866. pal_lcl = pal_int->lpLcl;
  1867. pal = pal_lcl->lpGbl;
  1868. }
  1869. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1870. {
  1871. DPF_ERR( "Exception encountered validating parameters" );
  1872. LEAVE_DDRAW();
  1873. return DDERR_INVALIDPARAMS;
  1874. }
  1875. /*
  1876. * First check the flags
  1877. */
  1878. if (this->dwFlags != pal->dwFlags)
  1879. {
  1880. DPF(2,"Different palette structures");
  1881. LEAVE_DDRAW();
  1882. return DD_FALSE;
  1883. }
  1884. size = FLAGS_TO_SIZE(this->dwFlags);
  1885. if( this->dwFlags & DDRAWIPAL_STORED_8INDEX )
  1886. {
  1887. entry_size = sizeof( BYTE );
  1888. }
  1889. else
  1890. {
  1891. entry_size = sizeof( PALETTEENTRY );
  1892. }
  1893. switch (size)
  1894. {
  1895. case 2: // fall-thru
  1896. case 4: // fall-thru
  1897. case 16:
  1898. if (memcmp(this->lpColorTable, pal->lpColorTable, size*entry_size) != 0)
  1899. {
  1900. DPF(2, "Color tables are not the same" );
  1901. LEAVE_DDRAW();
  1902. return DD_FALSE;
  1903. }
  1904. break;
  1905. case 256:
  1906. for (i = 0; i < 16; ++i)
  1907. {
  1908. entry = i;
  1909. for (j = 0; j < 16; j++)
  1910. {
  1911. if ((*(LPDWORD)&(this->lpColorTable[entry]) != (*(LPDWORD)&pal->lpColorTable[entry])))
  1912. {
  1913. DPF(5,"Color table entry mismatch: 0x%08x, 0x%08x",
  1914. *(LPDWORD)&this->lpColorTable[entry],
  1915. *(LPDWORD)&pal->lpColorTable[entry] );
  1916. LEAVE_DDRAW();
  1917. return DD_FALSE;
  1918. }
  1919. entry += 16;
  1920. }
  1921. }
  1922. }
  1923. /*
  1924. * The palettes are the same!
  1925. */
  1926. LEAVE_DDRAW();
  1927. return DD_OK;
  1928. } /* DD_Palette_SetEntries */