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.

4874 lines
145 KiB

  1. /**************************************************************************
  2. DRAWDIB.C - routines for drawing DIBs to the screen.
  3. Copyright (c) Microsoft Corporation 1992 - 1995. All rights reserved.
  4. this code handles stretching and dithering with custom code, none
  5. of this slow GDI code.
  6. the following DIB formats are supported:
  7. 4bpp (will just draw it with GDI...)
  8. 8bpp
  9. 16bpp
  10. 24bpp
  11. compressed DIBs
  12. drawing to:
  13. 16 color DC (will dither 8bpp down)
  14. 256 (paletized) DC (will dither 16 and 24bpp down)
  15. Full-color DC (will just draw it!)
  16. **************************************************************************/
  17. #include <windows.h>
  18. #include <windowsx.h>
  19. #include <profile.h>
  20. #include "drawdibi.h"
  21. #include "profdisp.h"
  22. #define USE_DCI
  23. #ifdef DAYTONA
  24. // Daytona dynamically links to DCI - see dcilink.h for details
  25. #include "dcilink.h"
  26. #endif
  27. #ifndef abs
  28. #define abs(x) ((x) < 0 ? -(x) : (x))
  29. #endif
  30. #ifndef ICMODE_FASTDECOMPRESS
  31. #define ICMODE_FASTDECOMPRESS 3
  32. #endif
  33. #define USE_SETDI 1
  34. #define DIB_PAL_INDICES 2
  35. #ifndef BI_BITMAP
  36. #define BI_BITMAP 0x4D544942 // 'BITM'
  37. #endif
  38. #ifdef _WIN32
  39. #define FlatToHuge(a, b, c)
  40. #define HugeToFlat(a, b, c)
  41. #ifdef DEBUG
  42. #define FlushBuffer() GdiFlush()
  43. #else
  44. #define FlushBuffer()
  45. #endif
  46. #else //Win16
  47. extern FAR PASCAL FlatToHuge(LPVOID,DWORD,DWORD);
  48. extern FAR PASCAL HugeToFlat(LPVOID,DWORD,DWORD);
  49. #define FlushBuffer()
  50. #endif
  51. #define IsScreenDC(hdc) (WindowFromDC(hdc) != NULL)
  52. STATICFN BOOL DrawDibCheckPalette(PDD pdd);
  53. BOOL VFWAPI DrawDibTerm(void);
  54. BOOL VFWAPI DrawDibInit(void);
  55. //
  56. // Local variables
  57. //
  58. #ifdef DEBUG_RETAIL
  59. static int fDebug = -1;
  60. #endif
  61. /**************************************************************************
  62. **************************************************************************/
  63. WORD gwScreenBitDepth = (WORD)-1;
  64. UINT gwScreenWidth = 0;
  65. UINT gwScreenHeight = 0;
  66. UINT gwRasterCaps = 0;
  67. #ifndef _WIN32
  68. BOOL gf286= FALSE;
  69. #else
  70. #define gf286 FALSE
  71. #endif
  72. static UINT gUsage = 0;
  73. static BOOL gfInit = FALSE;
  74. static BOOL gfHalftone = FALSE;
  75. static BOOL gfBitmap = FALSE;
  76. static BOOL gfBitmapX = FALSE;
  77. #ifdef USE_DCI
  78. #ifdef UNICODE
  79. // we expose the DCI variables on NT to aid with stress debugging
  80. #define STATIC
  81. #else // for Win95
  82. #define STATIC static
  83. #endif
  84. STATIC BOOL gfScreenX = FALSE;
  85. #ifdef WANT_DRAW_DIRECT_TO_SCREEN
  86. STATIC BOOL gfDrawX = FALSE;
  87. #endif
  88. #endif // USE_DCI
  89. static HBITMAP hbmStockMono; // the stock mono bitmap.
  90. #ifdef USE_DCI
  91. STATIC BOOL gfDisplayHasBrokenRasters;
  92. STATIC HDC hdcDCI;
  93. STATIC DCISURFACEINFO FAR *pdci;
  94. STATIC struct {
  95. BITMAPINFOHEADER bi;
  96. DWORD dwMask[4];
  97. } biScreen;
  98. STATIC LPVOID lpScreen;
  99. #ifndef _WIN32
  100. static UINT ScreenSel;
  101. static DCISURFACEINFO dci;
  102. #endif
  103. SZCODEA szDVA[] = "dva";
  104. #define DCAlignment 3
  105. __inline int DCNotAligned(HDC hdc, int xDst) {
  106. POINT pt;
  107. pt.x = xDst; pt.y = 0;
  108. LPtoDP(hdc, &pt, 1);
  109. xDst = pt.x;
  110. #ifdef _WIN32
  111. GetDCOrgEx(hdc, &pt);
  112. #else
  113. pt.x = LOWORD(GetDCOrg(hdc));
  114. #endif
  115. return (pt.x + xDst) & DCAlignment;
  116. }
  117. #endif // USE_DCI
  118. /**************************************************************************
  119. **************************************************************************/
  120. SZCODEA szDrawDib[] = "DrawDib";
  121. SZCODEA szHalftone[] = "Halftone";
  122. SZCODEA szDrawToBitmap[] = "DrawToBitmap";
  123. SZCODEA szDecompressToBitmap[] = "DecompressToBitmap";
  124. #ifdef USE_DCI
  125. SZCODEA szDecompressToScreen[] = "DecompressToScreen";
  126. SZCODEA szDrawToScreen[] = "DrawToScreen";
  127. #endif
  128. /**************************************************************************
  129. **************************************************************************/
  130. #if 0
  131. /**************************************************************************
  132. **************************************************************************/
  133. typedef struct {
  134. UINT Usage;
  135. HBITMAP hbm;
  136. int dx,dy;
  137. } BITBUF, *PBITBUF;
  138. static BITBUF bb;
  139. static HBITMAP AllocBitmap(int dx, int dy)
  140. {
  141. return NULL;
  142. }
  143. #endif
  144. /**************************************************************************
  145. **************************************************************************/
  146. STATICFN BOOL NEAR PASCAL DrawDibFree(PDD pdd, BOOL fSameDib, BOOL fSameSize);
  147. STATICFN HPALETTE CreateBIPalette(HPALETTE hpal, LPBITMAPINFOHEADER lpbi);
  148. STATICFN BOOL NEAR IsIdentityPalette(HPALETTE hpal);
  149. STATICFN BOOL NEAR AreColorsAllGDIColors(LPBITMAPINFOHEADER lpbi);
  150. STATICFN BOOL SetPalFlags(HPALETTE hpal, int iIndex, int cntEntries, UINT wFlags);
  151. static void DrawDibPalChange(PDD pdd, HDC hdc, HPALETTE hpal);
  152. static void DrawDibClipChange(PDD pdd, UINT wFlags);
  153. static BOOL FixUpCodecPalette(HIC hic, LPBITMAPINFOHEADER lpbi);
  154. static BOOL SendSetPalette(PDD pdd);
  155. #ifdef USE_DCI
  156. #ifndef _WIN32
  157. #define GetDS() SELECTOROF((LPVOID)&ScreenSel)
  158. /****************************************************************************
  159. ***************************************************************************/
  160. #pragma optimize("", off)
  161. static void SetSelLimit(UINT sel, DWORD limit)
  162. {
  163. if (limit >= 1024*1024l)
  164. limit = ((limit+4096) & ~4095) - 1;
  165. _asm
  166. {
  167. mov ax,0008h ; DPMI set limit
  168. mov bx,sel
  169. mov dx,word ptr limit[0]
  170. mov cx,word ptr limit[2]
  171. int 31h
  172. }
  173. }
  174. #pragma optimize("", on)
  175. #endif // _WIN32
  176. /**************************************************************************
  177. **************************************************************************/
  178. static void InitDCI()
  179. {
  180. UINT WidthBytes;
  181. //
  182. // initialize DCI and open a surface handle to it.
  183. //
  184. // if DVA = 0 in WIN.INI, don't use DCI or DVA.
  185. // PSS tells people to use this if they have video problems,
  186. // so we shouldn't change the string.
  187. // On NT the value is in the REGISTRY,
  188. // HKEY_CURRENT_USER\SOFTWARE\Microsoft\Multimedia\Drawdib
  189. // REG_DWORD dva 1 dci enabled
  190. // REG_DWORD dva 0 dci disabled
  191. // This value can also be set through the Video For Windows configuration
  192. // dialog (control panel, drivers, or via Mplay32 on an open avi file).
  193. if (!mmGetProfileIntA(szDrawDib, szDVA, TRUE))
  194. return;
  195. #ifdef DAYTONA
  196. if (!InitialiseDCI()) return;
  197. #endif
  198. hdcDCI = DCIOpenProvider();
  199. if (hdcDCI == NULL) {
  200. DPF(("Failed to open DCI provider"));
  201. return;
  202. }
  203. #ifndef _WIN32
  204. SetObjectOwner(hdcDCI, NULL); // on Win16, this is shared between
  205. // processes, so tell GDI not to clean it up or whine about it not
  206. // being freed.
  207. #endif
  208. #ifdef _WIN32
  209. DCICreatePrimary(hdcDCI, &pdci);
  210. #else
  211. //
  212. // because we call 32-bit codecs we want a 32-bit DCI surface
  213. // (with a linear pointer, etc...)
  214. //
  215. dci.dwSize = sizeof(dci);
  216. if (DCICreatePrimary32(hdcDCI, &dci) == 0)
  217. pdci = &dci;
  218. else
  219. pdci = NULL;
  220. #endif
  221. if (pdci == NULL) {
  222. DCICloseProvider(hdcDCI);
  223. hdcDCI = NULL;
  224. return;
  225. }
  226. WidthBytes = (UINT) abs(pdci->lStride);
  227. //
  228. // convert DCISURFACEINFO into a BITMAPINFOHEADER...
  229. //
  230. biScreen.bi.biSize = sizeof(BITMAPINFOHEADER);
  231. biScreen.bi.biCompression = pdci->dwCompression;
  232. biScreen.bi.biWidth = WidthBytes*8/(UINT)pdci->dwBitCount;
  233. biScreen.bi.biHeight = pdci->dwHeight;
  234. biScreen.bi.biPlanes = 1;
  235. biScreen.bi.biBitCount = (UINT)pdci->dwBitCount;
  236. biScreen.bi.biSizeImage = pdci->dwHeight * WidthBytes;
  237. biScreen.bi.biXPelsPerMeter = WidthBytes;
  238. biScreen.bi.biYPelsPerMeter = 0;
  239. biScreen.bi.biClrUsed = 0;
  240. biScreen.bi.biClrImportant = 0;
  241. biScreen.dwMask[0] = pdci->dwMask[0];
  242. biScreen.dwMask[1] = pdci->dwMask[1];
  243. biScreen.dwMask[2] = pdci->dwMask[2];
  244. if (pdci->dwCompression == 0) {
  245. if ((UINT)pdci->dwBitCount == 16)
  246. {
  247. biScreen.dwMask[0] = 0x007C00;
  248. biScreen.dwMask[1] = 0x0003E0;
  249. biScreen.dwMask[2] = 0x00001F;
  250. }
  251. else if ((UINT)pdci->dwBitCount >= 24)
  252. {
  253. biScreen.dwMask[0] = 0xFF0000;
  254. biScreen.dwMask[1] = 0x00FF00;
  255. biScreen.dwMask[2] = 0x0000FF;
  256. }
  257. }
  258. if (pdci->lStride > 0)
  259. biScreen.bi.biHeight = -(int)pdci->dwHeight;
  260. #if 0 // BOGUS
  261. else
  262. pdci->dwOffSurface -= biScreen.bi.biSizeImage;
  263. #endif
  264. if (pdci->dwDCICaps & DCI_1632_ACCESS)
  265. {
  266. biScreen.bi.biCompression = BI_1632;
  267. //
  268. // make sure the pointer is valid.
  269. //
  270. if (pdci->dwOffSurface >= 0x10000)
  271. {
  272. DPF(("DCI Surface can't be supported: offset >64K"));
  273. lpScreen = NULL;
  274. biScreen.bi.biBitCount = 0;
  275. }
  276. else
  277. {
  278. #ifdef _WIN32
  279. lpScreen = (LPVOID)MAKELONG((WORD)pdci->dwOffSurface, pdci->wSelSurface);
  280. #else
  281. lpScreen = (LPVOID)MAKELP(pdci->wSelSurface,pdci->dwOffSurface);
  282. #endif
  283. }
  284. }
  285. else
  286. {
  287. #ifdef _WIN32
  288. lpScreen = (LPVOID) pdci->dwOffSurface;
  289. #else
  290. //
  291. // If we weren't given a selector, or the offset is >64K, we should
  292. // handle this case and reset the base of the selector.
  293. //
  294. // Also must do this for GDT selectors, or the Kernel thunking
  295. // code will kill us.
  296. //
  297. if (pdci->wSelSurface == 0 || pdci->dwOffSurface >= 0x10000)
  298. {
  299. ScreenSel = AllocSelector(GetDS());
  300. if (pdci->wSelSurface)
  301. SetSelectorBase(ScreenSel,
  302. GetSelectorBase(pdci->wSelSurface) + pdci->dwOffSurface);
  303. else
  304. SetSelectorBase(ScreenSel, pdci->dwOffSurface);
  305. SetSelLimit(ScreenSel, biScreen.bi.biSizeImage - 1);
  306. lpScreen = (LPVOID)MAKELP(ScreenSel,0);
  307. }
  308. else
  309. {
  310. lpScreen = (LPVOID)MAKELP(pdci->wSelSurface,pdci->dwOffSurface);
  311. }
  312. #endif
  313. }
  314. DPF(("DCI Surface: %ldx%ldx%ld, lpScreen = %08I", pdci->dwWidth, pdci->dwHeight, pdci->dwBitCount, (DWORD_PTR) lpScreen));
  315. DPF(("DCI Surface: biCompression= %ld '%4.4hs' Masks: %04lX %04lX %04lX",biScreen.bi.biCompression, (LPSTR) &biScreen.bi.biCompression,biScreen.dwMask[0],biScreen.dwMask[1],biScreen.dwMask[2]));
  316. //
  317. // check if the display has broken rasters.
  318. //
  319. #if defined(DAYTONA) && !defined(_X86_)
  320. // On MIPS and other machines that have problems with
  321. // unaligned code we always set gfDisplayHasBrokenRasters to TRUE!
  322. gfDisplayHasBrokenRasters = TRUE;
  323. #else
  324. gfDisplayHasBrokenRasters = (0x10000l % WidthBytes) != 0;
  325. #endif
  326. if (gfDisplayHasBrokenRasters)
  327. {
  328. DPF(("*** Display has broken rasters"));
  329. }
  330. }
  331. void TermDCI()
  332. {
  333. if (pdci)
  334. {
  335. DCIDestroy(pdci);
  336. pdci = NULL;
  337. }
  338. if (hdcDCI)
  339. {
  340. DCICloseProvider(hdcDCI);
  341. hdcDCI = NULL;
  342. }
  343. #ifndef _WIN32
  344. if (ScreenSel)
  345. {
  346. SetSelLimit(ScreenSel, 0);
  347. FreeSelector(ScreenSel);
  348. ScreenSel = 0;
  349. }
  350. #endif
  351. #ifdef DAYTONA
  352. TerminateDCI();
  353. #endif
  354. }
  355. #else
  356. #define InitDCI()
  357. #define TermDCI()
  358. #endif
  359. /**************************************************************************
  360. * @doc INTERNAL DrawDib
  361. *
  362. * @api BOOL | DrawDibInit | This function initalizes the DrawDib library.
  363. *
  364. * @rdesc Returns TRUE if the library is initialized properly, otherwise
  365. * it returns FALSE.
  366. *
  367. * @comm Users don't need to call this, because <f DrawDibOpen> does it for them.
  368. *
  369. * @xref DrawDibTerm
  370. *
  371. **************************************************************************/
  372. BOOL VFWAPI DrawDibInit()
  373. {
  374. HDC hdc;
  375. WORD wScreenBitDepth;
  376. UINT wScreenWidth;
  377. UINT wScreenHeight;
  378. UINT wRasterCaps;
  379. hdc = GetDC(NULL);
  380. wScreenBitDepth = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
  381. wScreenWidth = GetSystemMetrics(SM_CXSCREEN);
  382. wScreenHeight = GetSystemMetrics(SM_CYSCREEN);
  383. wRasterCaps = GetDeviceCaps(hdc, RASTERCAPS);
  384. ReleaseDC(NULL, hdc);
  385. if (gfInit)
  386. {
  387. //
  388. // handle a screen res change.
  389. //
  390. if (gwScreenWidth == wScreenWidth &&
  391. gwScreenHeight == wScreenHeight &&
  392. gwScreenBitDepth == wScreenBitDepth)
  393. {
  394. return TRUE;
  395. }
  396. DPF(("Screen has changed from %dx%dx%d to %dx%dx%d", gwScreenWidth, gwScreenHeight, gwScreenBitDepth, wScreenWidth, wScreenHeight, wScreenBitDepth));
  397. DrawDibTerm();
  398. }
  399. #ifndef _WIN32
  400. gf286 = (BOOL)(GetWinFlags() & WF_CPU286);
  401. #endif
  402. gwScreenBitDepth = wScreenBitDepth;
  403. gwScreenWidth = wScreenWidth;
  404. gwScreenHeight = wScreenHeight;
  405. gwRasterCaps = wRasterCaps;
  406. gfHalftone = mmGetProfileIntA(szDrawDib, szHalftone, FALSE);
  407. gfBitmap = mmGetProfileIntA(szDrawDib, szDrawToBitmap, -1);
  408. gfBitmapX = mmGetProfileIntA(szDrawDib, szDecompressToBitmap, TRUE);
  409. #ifdef USE_DCI
  410. gfScreenX = mmGetProfileIntA(szDrawDib, szDecompressToScreen, TRUE);
  411. #ifdef WANT_DRAW_DIRECT_TO_SCREEN
  412. gfDrawX = mmGetProfileIntA(szDrawDib, szDrawToScreen, TRUE);
  413. #endif
  414. #endif
  415. #ifdef DEBUG
  416. gwRasterCaps = mmGetProfileIntA(szDrawDib, "RasterCaps", gwRasterCaps);
  417. gwScreenBitDepth = (WORD) mmGetProfileIntA(szDrawDib, "ScreenBitDepth", gwScreenBitDepth);
  418. #ifndef _WIN32
  419. gf286 = GetProfileIntA(szDrawDib, "cpu", gf286 ? 286 : 386) == 286;
  420. #endif
  421. #endif
  422. InitDCI();
  423. #ifdef DEBUG
  424. {
  425. UINT wType = GetBitmapType();
  426. switch(wType & BM_TYPE)
  427. {
  428. case BM_VGA:
  429. DPF(("display format: VGA mode"));
  430. break;
  431. case BM_1BIT:
  432. DPF(("display format: 1 bpp"));
  433. break;
  434. case BM_4BIT:
  435. DPF(("display format: 4 bpp"));
  436. break;
  437. case BM_8BIT:
  438. DPF(("display format: 8 bpp"));
  439. break;
  440. case BM_16555:
  441. DPF(("display format: 16-bits, 555"));
  442. break;
  443. case BM_24BGR:
  444. DPF(("display format: 24-bits BGR"));
  445. break;
  446. case BM_32BGR:
  447. DPF(("display format: 32-bits BGR"));
  448. break;
  449. case BM_16565:
  450. DPF(("display format: 16-bits, 565"));
  451. break;
  452. case BM_24RGB:
  453. case BM_32RGB:
  454. DPF(("display format: %d-bits RGB",
  455. ((wType == BM_24RGB) ? 24 : 32)));
  456. break;
  457. default:
  458. DPF(("display format: unknown (type %d)", wType));
  459. break;
  460. }
  461. }
  462. #endif
  463. //
  464. // fix up the bit-depth of the display.
  465. //
  466. if (gwScreenBitDepth > 32)
  467. gwScreenBitDepth = 32;
  468. if (gwScreenBitDepth == 16 || gwScreenBitDepth == 32)
  469. {
  470. BITMAPINFOHEADER bi;
  471. UINT u;
  472. bi.biSize = sizeof(bi);
  473. bi.biWidth = 1;
  474. bi.biHeight = 1;
  475. bi.biPlanes = 1;
  476. bi.biBitCount = gwScreenBitDepth;
  477. bi.biCompression = 0;
  478. bi.biSizeImage = 0;
  479. bi.biXPelsPerMeter = 0;
  480. bi.biYPelsPerMeter = 0;
  481. bi.biClrUsed = 0;
  482. bi.biClrImportant = 0;
  483. u = (UINT)DrawDibProfileDisplay(&bi);
  484. if (u == 0)
  485. {
  486. DPF(("Pretending display is 24 bit (not %d)", gwScreenBitDepth));
  487. gwScreenBitDepth = 24;
  488. }
  489. }
  490. gfInit = TRUE;
  491. return TRUE;
  492. }
  493. /**************************************************************************
  494. * @doc INTERNAL DrawTerm
  495. *
  496. * @api BOOL | DrawDibTerm | This function teminates the DrawDib library.
  497. *
  498. * @rdesc Returns TRUE.
  499. *
  500. * @comm Users don't need to call this, because <f DrawDibClose> does it for them.
  501. *
  502. * @xref DrawDibInit
  503. *
  504. **************************************************************************/
  505. BOOL VFWAPI DrawDibTerm()
  506. {
  507. //
  508. // free global stuff.
  509. //
  510. TermDCI();
  511. gfInit = FALSE;
  512. return TRUE;
  513. }
  514. /**************************************************************************
  515. * @doc INTERNAL DrawDib
  516. *
  517. * @api void | DrawDibCleanup | clean up drawdib stuff
  518. * called in MSVIDEOs WEP()
  519. *
  520. **************************************************************************/
  521. void FAR PASCAL DrawDibCleanup(HTASK hTask)
  522. {
  523. if (gUsage > 0)
  524. RPF(("%d DrawDib handles left open", gUsage));
  525. DrawDibTerm();
  526. }
  527. /**************************************************************************
  528. * @doc INTERNAL
  529. *
  530. * @api BOOL | DibEq | This function compares two dibs.
  531. *
  532. * @parm LPBITMAPINFOHEADER | lpbi1 | Pointer to one bitmap.
  533. * this DIB is assumed to have the colors after biSize bytes.
  534. *
  535. * @parm LPBITMAPINFOHEADER | lpbi2 | Pointer to second bitmap.
  536. * this DIB is assumed to have the colors after biSize bytes.
  537. *
  538. * @rdesc Returns TRUE if bitmaps are identical, FALSE otherwise.
  539. *
  540. **************************************************************************/
  541. INLINE BOOL NEAR PASCAL DibEq(LPBITMAPINFOHEADER lpbi1,LPBITMAPINFOHEADER lpbi2)
  542. {
  543. if (lpbi1 == NULL || lpbi2 == NULL)
  544. return FALSE;
  545. return
  546. lpbi1->biCompression == lpbi2->biCompression &&
  547. (int)lpbi1->biSize == (int)lpbi2->biSize &&
  548. (int)lpbi1->biWidth == (int)lpbi2->biWidth &&
  549. (int)lpbi1->biHeight == (int)lpbi2->biHeight &&
  550. (int)lpbi1->biBitCount == (int)lpbi2->biBitCount &&
  551. ((int)lpbi1->biBitCount > 8 ||
  552. (int)lpbi1->biClrUsed == (int)lpbi2->biClrUsed &&
  553. _fmemcmp((LPBYTE)lpbi1 + lpbi1->biSize,
  554. (LPBYTE)lpbi2 + lpbi2->biSize,
  555. (int)lpbi1->biClrUsed*sizeof(RGBQUAD)) == 0);
  556. }
  557. /**************************************************************************
  558. * @doc INTERNAL
  559. *
  560. * @api PDD NEAR | DrawDibLockNoTaskCheck | Lock the DrawDib handle.
  561. *
  562. * @comm No check is made on the validity of the calling task
  563. *
  564. * @parm HDRAWDIB | hdd | DrawDib handle.
  565. *
  566. * @rdesc Returns a pointer to a <t DRAWDIB_STRUCT> if successful, NULL otherwise.
  567. *
  568. **************************************************************************/
  569. #define OffsetOf(s,m) (DWORD_PTR)&(((s *)0)->m)
  570. INLINE PDD NEAR PASCAL DrawDibLockNoTaskCheck(HDRAWDIB hdd)
  571. {
  572. #ifdef DEBUG
  573. if (OffsetOf(DRAWDIB_STRUCT, wSize) != 0) {
  574. DPF0(("INTERNAL FAILURE"));
  575. DebugBreak();
  576. }
  577. #endif
  578. if (hdd == NULL ||
  579. IsBadWritePtr((LPVOID) (PDD) hdd, sizeof(DRAWDIB_STRUCT)) ||
  580. #if defined(DAYTONA) && !defined(_X86_)
  581. (*(DWORD UNALIGNED *)hdd) != sizeof(DRAWDIB_STRUCT))
  582. #else
  583. ((PDD)hdd)->wSize != sizeof(DRAWDIB_STRUCT))
  584. #endif
  585. {
  586. #ifndef _WIN32
  587. #ifdef DEBUG_RETAIL
  588. LogParamError(ERR_BAD_HANDLE, DrawDibDraw, (LPVOID) (DWORD) (UINT) hdd);
  589. #endif
  590. #endif
  591. return NULL;
  592. }
  593. return (PDD) hdd;
  594. }
  595. /**************************************************************************
  596. * @doc INTERNAL
  597. *
  598. * @api PDD NEAR | DrawDibLock | Lock the DrawDib handle.
  599. *
  600. * @parm HDRAWDIB | hdd | DrawDib handle.
  601. *
  602. * @rdesc Returns a pointer to a <t DRAWDIB_STRUCT> if successful, NULL otherwise.
  603. *
  604. **************************************************************************/
  605. INLINE PDD NEAR PASCAL DrawDibLock(HDRAWDIB hdd)
  606. {
  607. PDD pdd = DrawDibLockNoTaskCheck(hdd);
  608. #ifndef _WIN32
  609. if (pdd && (pdd->htask != GetCurrentTask())) {
  610. DPF(("DrawDib handle used from wrong task!"));
  611. #ifdef DEBUG_RETAIL
  612. LogParamError(ERR_BAD_HANDLE, DrawDibDraw, (LPVOID) (DWORD) (UINT) hdd);
  613. #endif
  614. return NULL;
  615. }
  616. #endif
  617. return pdd;
  618. }
  619. /**************************************************************************
  620. * @doc EXTERNAL DrawDib
  621. *
  622. * @api HDRAWDIB | DrawDibOpen | This function opens a DrawDib context for drawing.
  623. *
  624. * @rdesc Returns a handle to a DrawDib context if successful,
  625. * otherwise it returns NULL.
  626. *
  627. * @comm Use this function to obtain a handle to a DrawDib context
  628. * before drawing device independent bitmaps.
  629. *
  630. * If drawing multiple device independent bitmaps simultaneously,
  631. * obtain a handle to a DrawDib context for each bitmap.
  632. *
  633. * @xref <f DrawDibClose>
  634. *
  635. **************************************************************************/
  636. HDRAWDIB VFWAPI DrawDibOpen(void)
  637. {
  638. HDRAWDIB hdd;
  639. PDD pdd;
  640. hdd = LocalAlloc(LPTR, sizeof(DRAWDIB_STRUCT)); /* zero init */
  641. if (hdd == NULL)
  642. return NULL;
  643. pdd = (PDD)hdd;
  644. pdd->wSize = sizeof(DRAWDIB_STRUCT);
  645. #ifndef _WIN32
  646. pdd->htask = GetCurrentTask();
  647. #endif
  648. if (gUsage++ == 0)
  649. DrawDibInit();
  650. return hdd;
  651. }
  652. /**************************************************************************
  653. * @doc EXTERNAL DrawDib
  654. *
  655. * @api BOOL | DrawDibClose | This function closes a DrawDib context
  656. * and frees the resources DrawDib allocated for it.
  657. *
  658. * @parm HDRAWDIB | hdd | Specifies a handle to a DrawDib context.
  659. *
  660. * @rdesc Returns TRUE if the context closed successfully.
  661. *
  662. * @comm Use this function to free the <p hdd> handle
  663. * after the application has finished drawing.
  664. *
  665. * @xref <f DrawDibOpen>
  666. **************************************************************************/
  667. BOOL VFWAPI DrawDibClose(HDRAWDIB hdd)
  668. {
  669. PDD pdd;
  670. if ((pdd = DrawDibLock(hdd)) == NULL)
  671. return FALSE;
  672. DrawDibFree(pdd, FALSE, FALSE);
  673. pdd->wSize = 0;
  674. LocalFree(hdd);
  675. if (--gUsage == 0)
  676. DrawDibTerm();
  677. return TRUE;
  678. }
  679. /**************************************************************************
  680. * @doc INTERNAL
  681. *
  682. * @api BOOL | DrawDibFree | Free up everything in a <t DRAWDIB_STRUCT>.
  683. *
  684. * @parm PDD | pdd | Pointer to a <t DRAWDIB_STRUCT>.
  685. *
  686. * @rdesc Returns TRUE if successful, FALSE otherwise.
  687. *
  688. **************************************************************************/
  689. STATICFN BOOL NEAR PASCAL DrawDibFree(PDD pdd, BOOL fSameDib, BOOL fSameSize)
  690. {
  691. if (pdd == NULL)
  692. return FALSE;
  693. //
  694. // If the draw palette has changed, the compressor may now be giving us DIBs
  695. // mapped to a different palette, so we need to clean up so we'll produce
  696. // a new mapping table so we'll actually draw with the new palette.
  697. // (see SendSetPalette)
  698. //
  699. if (!fSameDib) {
  700. //
  701. // if this palette is selected as the foreground palette
  702. // and we delete it we are going to hose GDI!
  703. //
  704. if (pdd->hpal)
  705. DeleteObject(pdd->hpal);
  706. if (pdd->hpalCopy)
  707. DeleteObject(pdd->hpalCopy);
  708. pdd->hpal = NULL;
  709. pdd->hpalCopy = NULL;
  710. }
  711. if (!fSameDib) {
  712. if (pdd->lpbi) {
  713. GlobalFreePtr(pdd->lpbi);
  714. pdd->lpbi = NULL;
  715. pdd->lpargbqIn = NULL;
  716. }
  717. if (pdd->lpDitherTable)
  718. {
  719. DitherTerm(pdd->lpDitherTable);
  720. pdd->lpDitherTable = NULL;
  721. }
  722. if (pdd->hic && pdd->hic != (HIC)-1)
  723. {
  724. ICDecompressEnd(pdd->hic);
  725. ICDecompressExEnd(pdd->hic);
  726. ICClose(pdd->hic);
  727. }
  728. pdd->ulFlags &= ~(DDF_IDENTITYPAL);
  729. pdd->hic = NULL;
  730. pdd->iAnimateStart = 0;
  731. pdd->iAnimateLen = 0;
  732. pdd->iAnimateEnd = 0;
  733. }
  734. if (!fSameSize || !fSameDib)
  735. {
  736. if (pdd->hdcDraw) {
  737. if (hbmStockMono)
  738. SelectObject(pdd->hdcDraw, hbmStockMono);
  739. DeleteDC(pdd->hdcDraw);
  740. }
  741. if (pdd->hbmDraw) {
  742. DeleteObject(pdd->hbmDraw);
  743. //
  744. // if we have a bitmap pointer lose it
  745. //
  746. if (pdd->ulFlags & (DDF_CANBITMAPX))
  747. pdd->pbBitmap = NULL;
  748. }
  749. if ((pdd->pbStretch) && (pdd->pbStretch != pdd->lpDIBSection))
  750. GlobalFreePtr(pdd->pbStretch);
  751. if ((pdd->pbDither) && (pdd->pbDither != pdd->lpDIBSection))
  752. GlobalFreePtr(pdd->pbDither);
  753. if ((pdd->pbBuffer) && (pdd->pbBuffer != pdd->lpDIBSection))
  754. GlobalFreePtr(pdd->pbBuffer);
  755. #if USE_SETDI
  756. if (pdd->hbmDraw)
  757. SetBitmapEnd(&pdd->sd);
  758. #endif
  759. pdd->hdcDraw = NULL;
  760. pdd->hbmDraw = NULL;
  761. pdd->lpDIBSection = NULL;
  762. pdd->pbStretch = NULL;
  763. pdd->pbDither = NULL;
  764. pdd->pbBuffer = NULL;
  765. pdd->biDraw.biBitCount = 0;
  766. pdd->biDraw.biWidth = 0;
  767. pdd->biDraw.biHeight = 0;
  768. pdd->biBuffer.biBitCount = 0;
  769. pdd->biBuffer.biWidth = 0;
  770. pdd->biBuffer.biHeight = 0;
  771. // clear all the internal flags (except palette stuff)
  772. pdd->ulFlags &= ~(DDF_OURFLAGS ^ DDF_IDENTITYPAL);
  773. pdd->ulFlags |= DDF_DIRTY;
  774. pdd->iDecompress = 0;
  775. }
  776. return TRUE;
  777. }
  778. /**************************************************************************
  779. * @doc INTERNAL
  780. *
  781. * @api UINT | QueryDraw | see if the current display device
  782. * (DISPDIB or GDI) can draw the given dib
  783. *
  784. * @parm PDD | pdd | pointer to a <t DRAWDIB_STRUCT>.
  785. *
  786. * @parm LPBITMAPINFOHEADER | lpbi | pointer to a bitmap.
  787. *
  788. * @rdesc Returns display flags, see profdisp.h
  789. *
  790. **************************************************************************/
  791. #ifndef DEBUG
  792. #define QueryDraw(pdd, lpbi) (UINT)DrawDibProfileDisplay((lpbi))
  793. #endif
  794. #ifndef QueryDraw
  795. STATICFN UINT NEAR QueryDraw(PDD pdd, LPBITMAPINFOHEADER lpbi)
  796. {
  797. UINT u;
  798. u = (UINT)DrawDibProfileDisplay(lpbi);
  799. DPF(("QueryDraw (%dx%dx%d): %d", PUSHBI(*lpbi), u));
  800. return u;
  801. }
  802. #endif
  803. /**************************************************************************
  804. * @doc INTERNAL DrawDib
  805. *
  806. * @comm Called from DrawDibBegin to try decompression to a bitmap.
  807. *
  808. **************************************************************************/
  809. BOOL DrawDibQueryBitmapX(
  810. PDD pdd
  811. )
  812. {
  813. BITMAPINFOHEADER *pbi;
  814. #ifndef _WIN32
  815. if (!CanLockBitmaps()) {
  816. return FALSE;
  817. }
  818. #endif
  819. if (gwScreenBitDepth == 8 && !(gwRasterCaps & RC_PALETTE))
  820. return FALSE;
  821. if ((gwRasterCaps & RC_PALETTE) && !(pdd->ulFlags & DDF_IDENTITYPAL))
  822. return FALSE;
  823. pbi = &pdd->biStretch;
  824. if (!GetDIBBitmap(pdd->hbmDraw, pbi))
  825. return FALSE;
  826. #ifdef XDEBUG
  827. if (ICDecompressQuery(pdd->hic, pdd->lpbi, pbi) != ICERR_OK)
  828. {
  829. if (mmGetProfileIntA(szDrawDib, "ForceDecompressToBitmap", FALSE))
  830. {
  831. pbi->biHeight = -pbi->biHeight;
  832. pbi->biCompression = 0;
  833. }
  834. }
  835. #endif
  836. if (ICDecompressQuery(pdd->hic, pdd->lpbi, pbi) != ICERR_OK)
  837. {
  838. if (pbi->biCompression == BI_BITMAP &&
  839. pbi->biSizeImage <= 128*1024l &&
  840. (pbi->biXPelsPerMeter & 0x03) == 0 &&
  841. pbi->biSizeImage > 64*1024l)
  842. {
  843. pdd->ulFlags |= DDF_HUGEBITMAP;
  844. pbi->biCompression = 0;
  845. pbi->biSizeImage -= pbi->biYPelsPerMeter; //FillBytes
  846. if (ICDecompressQuery(pdd->hic, pdd->lpbi, pbi) != ICERR_OK)
  847. return FALSE;
  848. }
  849. else
  850. return FALSE;
  851. }
  852. pdd->ulFlags |= DDF_NEWPALETTE; // force check in DrawDibRealize
  853. pdd->ulFlags |= DDF_CANBITMAPX; // can decompress to bitmaps
  854. if (pdd->ulFlags & DDF_HUGEBITMAP)
  855. RPF((" Can decompress '%4.4hs' to a HUGE BITMAP (%dx%dx%d)",(LPSTR)&pdd->lpbi->biCompression, PUSHBI(*pbi)));
  856. else
  857. RPF((" Can decompress '%4.4hs' to a BITMAP (%dx%dx%d)",(LPSTR)&pdd->lpbi->biCompression, PUSHBI(*pbi)));
  858. //
  859. // reuse the stretch buffer for the bitmap.
  860. //
  861. pdd->biStretch = *pbi;
  862. #ifndef _WIN32
  863. pdd->pbStretch = LockBitmap(pdd->hbmDraw);
  864. if (pdd->pbStretch == NULL)
  865. {
  866. DPF((" Unable to lock bitmap!"));
  867. pdd->ulFlags &= ~DDF_CANBITMAPX; // can't decompress to bitmaps
  868. return FALSE;
  869. }
  870. #endif
  871. return TRUE;
  872. }
  873. #define Is565(bi) (((bi)->biCompression == BI_BITFIELDS) && \
  874. ((bi)->biBitCount == 16) && \
  875. (((LPDWORD)((bi)+1))[0] == 0x00F800) && \
  876. (((LPDWORD)((bi)+1))[1] == 0x0007E0) && \
  877. (((LPDWORD)((bi)+1))[2] == 0x00001F) )
  878. /**************************************************************************
  879. * @doc EXTERNAL DrawDib
  880. *
  881. * @api BOOL | DrawDibBegin | This function changes parameters
  882. * of a DrawDib context or it initializes a new DrawDib context.
  883. *
  884. * @parm HDRAWDIB | hdd | Specifies a handle to a DrawDib context.
  885. *
  886. * @parm HDC | hdc | Specifies a handle to a display context for drawing (optional).
  887. *
  888. * @parm int | dxDest | Specifies the width of the destination rectangle.
  889. * Width is specified in MM_TEXT client units.
  890. *
  891. * @parm int | dyDest | Specifies the height of the destination rectangle.
  892. * Height is specified in MM_TEXT client units.
  893. *
  894. * @parm LPBITMAPINFOHEADER | lpbi | Specifies a pointer to a
  895. * <t BITMAPINFOHEADER> structure containing the
  896. * image format. The color table for the DIB follows the
  897. * image format.
  898. *
  899. * @parm int | dxSrc | Specifies the width of the source rectangle.
  900. * Width is specified in pixels.
  901. *
  902. * @parm int | dySrc | Specifies the height of the source rectangle.
  903. * Height is specified in pixels.
  904. *
  905. * @parm UNIT | wFlags | Specifies the applicable flags for
  906. * the function. The following flags are defined:
  907. *
  908. * @flag DDF_UPDATE | Indicates the last buffered bitmap is to be redrawn.
  909. * If drawing fails with this flag, a buffered image is not available
  910. * and a new image needs to be specified before the display is updated.
  911. *
  912. * @flag DDF_SAME_HDC | Assumes the handle to the display context
  913. * is already specified. When this flag is used,
  914. * DrawDib also assumes the correct palette has already been
  915. * realized into the device context (possibly by
  916. * <f DrawDibRealize>).
  917. *
  918. * @flag DDF_SAME_DRAW | Uses the drawing parameters previously
  919. * specified for this function. Use this flag only
  920. * if <p lpbi>, <p dxDst>, <p dyDst>, <p dxSrc>, and <p dySrc>
  921. * have not changed since using <f DrawDibDraw> or <f DrawDibBegin>.
  922. *
  923. * @flag DDF_DONTDRAW | Indicates the frame is to be decompressed
  924. * and not drawn. The DDF_UPDATE flag can be used later
  925. * to actually draw the image.
  926. *
  927. * @flag DDF_ANIMATE | Allows palette animation. If this flag is present,
  928. * the palette <f DrawDib> creates will have the PC_RESERVED flag set for
  929. * as many entries as possible, and the palette can be animated by
  930. * <f DrawDibChangePalette>. If using <f DrawDibBegin> with
  931. * <f DrawDibDraw>, set this flag with <f DrawDibBegin>
  932. * rather than <f DrawDibDraw>.
  933. *
  934. * @flag DDF_JUSTDRAWIT | Uses GDI to draw the image. This prevents
  935. * the DrawDib functions from calling ICM to decompress
  936. * the image or prevents them from
  937. * using their own routines to stretch or dither the image.
  938. * This essentially reduces <f DrawDibDraw> to <f StretchDIBits>.
  939. *
  940. * @flag DDF_BACKGROUNDPAL | Realizes the palette used for drawing
  941. * in the background leaving the actual palette used for display
  942. * unchanged. (This flag is valid only if DDF_SAME_HDC is not set.)
  943. *
  944. * @flag DDF_HALFTONE | Always dithers the DIB to a standard palette
  945. * regardless of the palette of the DIB. If using <f DrawDibBegin> with
  946. * <f DrawDibDraw>, set this flag with <f DrawDibBegin>
  947. * rather than <f DrawDibDraw>.
  948. *
  949. * @flag DDF_BUFFER | Indicates DrawDib should try to use a
  950. * offscreen buffer so DDF_UPDATE can be used. This
  951. * disables decompression and drawing directly to the screen.
  952. * If DrawDib is unable to create an offscreen buffer,
  953. * it will decompress or draw directly to the screen.
  954. *
  955. * For more information, see the DDF_UPDATE and DDF_DONTDRAW
  956. * flags described for <f DrawDibDraw>.
  957. *
  958. *
  959. * @rdesc Returns TRUE if successful.
  960. *
  961. * @comm This function prepares to draw a bitmap specified by <p lpbi>
  962. * to the display context <p hdc>. The image is stretched to
  963. * the size specified by <p dxDest> and <p dyDest>. If <p dxDest> and
  964. * <p dyDest> are (-1, -1), the bitmap is drawn to a
  965. * 1:1 scale without stretching.
  966. *
  967. * Use this function only if you want to prepare DrawDib
  968. * before using <f DrawDibDraw> to draw the image.
  969. * If you do not use this function, <f DrawDibDraw> implicitly
  970. * uses it when it draws the image.
  971. *
  972. * To update the flags set with <f DrawDibBegin>, use
  973. * <f DrawDibEnd> to free the DrawDib context and reset
  974. * the flags with <f DrawDibBegin>, or specify the new flags
  975. * with changed values for <p dxDest>, <p dyDest>, <p lpbi>, <p dxSrc>,
  976. * or <p dySrc>.
  977. *
  978. * When <f DrawDibBegin> is used, the <f DDF_SAME_DRAW>
  979. * flag is normally set for <f DrawDibDraw>.
  980. *
  981. * If the parameters of <f DrawDibBegin> have not changed, subsequent
  982. * uses of it have not effect.
  983. *
  984. * Use <f DrawDibEnd> to free memory used by the DrawDib context.
  985. *
  986. * @xref <f DrawDibEnd> <f DrawDibDraw>
  987. **************************************************************************/
  988. #ifndef _WIN32
  989. #pragma message("Make DrawDibBegin faster for changing the size only!")
  990. #endif
  991. BOOL VFWAPI DrawDibBegin(HDRAWDIB hdd,
  992. HDC hdc,
  993. int dxDst,
  994. int dyDst,
  995. LPBITMAPINFOHEADER lpbi,
  996. int dxSrc,
  997. int dySrc,
  998. UINT wFlags)
  999. {
  1000. PDD pdd;
  1001. WORD ScreenBitDepth;
  1002. int dxSave,dySave;
  1003. BOOL fNewPal;
  1004. BOOL fSameDib;
  1005. BOOL fSameSize;
  1006. BOOL fSameFlags;
  1007. BOOL fSameHdc;
  1008. UINT wFlagsChanged;
  1009. DWORD ulFlagsSave;
  1010. LRESULT dw;
  1011. UINT w;
  1012. HPALETTE hPal;
  1013. LONG lSize;
  1014. //
  1015. // Quick sanity checks....
  1016. //
  1017. if (lpbi == NULL)
  1018. return FALSE;
  1019. if ((pdd = DrawDibLock(hdd)) == NULL)
  1020. return FALSE;
  1021. DrawDibInit();
  1022. //
  1023. // fill in defaults.
  1024. //
  1025. if (dxSrc < 0)
  1026. dxSrc = (int)lpbi->biWidth;
  1027. if (dySrc < 0)
  1028. dySrc = (int)lpbi->biHeight;
  1029. if (dxDst < 0)
  1030. dxDst = dxSrc;
  1031. if (dyDst < 0)
  1032. dyDst = dySrc;
  1033. if (dxSrc == 0 || dySrc == 0) // !!! || dxDst == 0 || dyDst == 0)
  1034. return FALSE;
  1035. ulFlagsSave = pdd->ulFlags;
  1036. wFlagsChanged = ((UINT)pdd->ulFlags ^ wFlags);
  1037. fSameHdc = hdc == pdd->hdcLast;
  1038. fSameDib = DibEq(pdd->lpbi, lpbi) && !(wFlagsChanged & DDF_HALFTONE) &&
  1039. (pdd->hpalDraw == pdd->hpalDrawLast);
  1040. fSameFlags = (pdd->ulFlags & DDF_BEGINFLAGS) == (wFlags & DDF_BEGINFLAGS);
  1041. fSameSize = pdd->dxDst == dxDst && pdd->dyDst == dyDst &&
  1042. pdd->dxSrc == dxSrc && pdd->dySrc == dySrc;
  1043. pdd->hdcLast = hdc;
  1044. // When the hpalDraw field changes, we need to tell the compressor about it
  1045. // by calling SendSetPalette.
  1046. // !!! NO we don't
  1047. //
  1048. // Do a quick check to see if the params have changed.
  1049. // If the DIB, and size of the DIB, and flags used are the same as the last
  1050. // time we called DrawDibBegin, then there's nothing to do and we'll only
  1051. // waste time plodding through this code.
  1052. // There is one case when all these could be the same, but the situation
  1053. // has still changed enough so that we need to recompute things... if the
  1054. // hdc is different than last time, and we're dealing with RLE. You see,
  1055. // we make some decisions about RLE (like we can go direct to a screen DC
  1056. // but not a memory DC) that are affected by what hdc we're using. So
  1057. // we will not bail out early if we are using RLE and the hdc's are
  1058. // different.
  1059. //
  1060. if (fSameDib && fSameSize && fSameFlags)
  1061. {
  1062. if ((lpbi->biCompression != BI_RLE8 && lpbi->biCompression != BI_RLE4)
  1063. || fSameHdc)
  1064. return TRUE;
  1065. }
  1066. pdd->hpalDrawLast = pdd->hpalDraw;
  1067. RPF(("DrawDibBegin %dx%dx%d '%4.4hs' [%d %d] [%d %d]",
  1068. (int)lpbi->biWidth,
  1069. (int)lpbi->biHeight,
  1070. (int)lpbi->biBitCount,
  1071. (lpbi->biCompression == BI_RGB ? (LPSTR)"None" :
  1072. lpbi->biCompression == BI_RLE8 ? (LPSTR)"Rle8" :
  1073. lpbi->biCompression == BI_RLE4 ? (LPSTR)"Rle4" :
  1074. (LPSTR)&lpbi->biCompression),
  1075. dxSrc, dySrc, dxDst, dyDst));
  1076. fNewPal = pdd->hpal == NULL || !fSameDib;
  1077. //
  1078. // make sure this palette is not the in the DC, because we
  1079. // are going to delete it, and GDI get real upset if we do this.
  1080. //
  1081. if (fNewPal && pdd->hpal && hdc)
  1082. {
  1083. hPal = SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), TRUE);
  1084. if (hPal == pdd->hpal)
  1085. RPF((" Warning unselecting palette..."));
  1086. }
  1087. DrawDibFree(pdd, fSameDib, fSameSize);
  1088. pdd->dxSrc = dxSrc;
  1089. pdd->dySrc = dySrc;
  1090. pdd->dxDst = dxDst;
  1091. pdd->dyDst = dyDst;
  1092. //
  1093. // copy the source DIB header and the colors.
  1094. //
  1095. if (lpbi->biClrUsed == 0 && lpbi->biBitCount <= 8)
  1096. lpbi->biClrUsed = (1 << (int)lpbi->biBitCount);
  1097. ////if (lpbi->biClrUsed != 0 && lpbi->biBitCount > 8)
  1098. //// lpbi->biClrUsed = 0;
  1099. // Make a copy of the source format. Remember, some codec could have
  1100. // defined a custom format larger than a BITMAPINFOHEADER so make a copy
  1101. // of EVERYTHING.
  1102. if (!fSameDib) {
  1103. lSize = lpbi->biSize + lpbi->biClrUsed * sizeof(RGBQUAD);
  1104. pdd->lpbi = (LPBITMAPINFOHEADER)GlobalAllocPtr(GPTR, lSize);
  1105. if (pdd->lpbi == NULL)
  1106. return FALSE;
  1107. _fmemcpy(pdd->lpbi, lpbi, (int)lSize);
  1108. // This is where the colour info is
  1109. pdd->lpargbqIn = (LPVOID)((LPBYTE)lpbi + lpbi->biSize);
  1110. }
  1111. pdd->biBuffer = *lpbi;
  1112. pdd->lpbi->biSizeImage = 0;
  1113. pdd->biBuffer.biSizeImage = 0;
  1114. //
  1115. // init all other color tables to be the initial colors
  1116. //
  1117. if (lpbi->biBitCount <= 8)
  1118. {
  1119. _fmemcpy(pdd->argbq, (LPBYTE)lpbi+(int)lpbi->biSize,
  1120. (int)lpbi->biClrUsed * sizeof(RGBQUAD));
  1121. _fmemcpy(pdd->aw, (LPBYTE)lpbi+(int)lpbi->biSize,
  1122. (int)lpbi->biClrUsed * sizeof(RGBQUAD));
  1123. }
  1124. // set PalUse to default: DIB_PAL_COLORS. This will be set
  1125. // to DIB_PAL_INDICES if DrawdibCheckPalette is called and detects
  1126. // that it is safe to use indices. DIB_PAL_COLORS is a safe
  1127. // default.
  1128. pdd->uiPalUse = DIB_RGB_COLORS; // assume RGB colors for now.
  1129. //
  1130. // make sure the device is a palette device before dinking with
  1131. // palette animation.
  1132. //
  1133. if (wFlags & DDF_ANIMATE)
  1134. {
  1135. if (!(gwRasterCaps & RC_PALETTE) ||
  1136. (int)lpbi->biBitCount > 8 || pdd->hpalDraw)
  1137. wFlags &= ~DDF_ANIMATE;
  1138. }
  1139. //
  1140. // copy the flags
  1141. //
  1142. try_again:
  1143. pdd->ulFlags &= ~DDF_USERFLAGS;
  1144. pdd->ulFlags |= (wFlags & DDF_USERFLAGS);
  1145. pdd->ulFlags &= ~DDF_UPDATE;
  1146. //
  1147. // deal with a decompressor if needed.
  1148. //
  1149. switch (lpbi->biCompression)
  1150. {
  1151. case BI_RGB:
  1152. break;
  1153. default:
  1154. //
  1155. // see if the DISPLAY/DISPDIB can draw the format directly!
  1156. //
  1157. // if the buffer flag is set we MUST use a decompress buffer.
  1158. // regardless of what the display can do
  1159. //
  1160. if (wFlags & DDF_BUFFER)
  1161. w = 0;
  1162. else
  1163. w = QueryDraw(pdd, lpbi);
  1164. if (w & PD_CAN_DRAW_DIB)
  1165. {
  1166. if (((dxSrc == dxDst && dySrc == dyDst) && (w & PD_STRETCHDIB_1_1_OK)) ||
  1167. ((dxSrc != dxDst || dySrc != dyDst) && (w & PD_STRETCHDIB_1_N_OK)) ||
  1168. ((dxDst % dxSrc) == 0 && (dyDst % dySrc) == 0 && (w & PD_STRETCHDIB_1_2_OK)))
  1169. {
  1170. // GDI can't handle drawing RLEs to a memory DC so we will
  1171. // have to pretend that RLE can't be drawn to the screen
  1172. // and decompress it first.
  1173. // We also can't DITHER RLE, so if we're running on a
  1174. // 16 colour display, make sure we're using a decompressor.
  1175. if (((lpbi->biCompression != BI_RLE8) &&
  1176. (lpbi->biCompression != BI_RLE4)) ||
  1177. (hdc && IsScreenDC(hdc) && gwScreenBitDepth >=8))
  1178. {
  1179. wFlags |= DDF_JUSTDRAWIT;
  1180. if (pdd->hic)
  1181. ICClose(pdd->hic);
  1182. pdd->hic = NULL;
  1183. goto no_decomp;
  1184. }
  1185. }
  1186. }
  1187. if (pdd->hic == NULL)
  1188. {
  1189. DWORD fccHandler;
  1190. fccHandler = 0;
  1191. if (lpbi->biCompression == BI_RLE8)
  1192. fccHandler = mmioFOURCC('R','L','E',' ');
  1193. pdd->hic = ICLocate(ICTYPE_VIDEO,
  1194. fccHandler,
  1195. lpbi, NULL,
  1196. ICMODE_FASTDECOMPRESS);
  1197. if (pdd->hic == NULL)
  1198. pdd->hic = ICDecompressOpen(ICTYPE_VIDEO,
  1199. fccHandler,lpbi,NULL);
  1200. if (pdd->hic)
  1201. {
  1202. //
  1203. // make sure the codec uses its default palette out of the gate
  1204. //
  1205. if (ICDecompressSetPalette(pdd->hic, NULL) == ICERR_OK)
  1206. {
  1207. pdd->ulFlags |= DDF_CANSETPAL;
  1208. RPF((" codec supports ICM_SET_PALETTE"));
  1209. }
  1210. else
  1211. {
  1212. pdd->ulFlags &= ~DDF_CANSETPAL;
  1213. }
  1214. }
  1215. }
  1216. if (pdd->hic == NULL || pdd->hic == (HIC)-1)
  1217. {
  1218. RPF((" Unable to open compressor '%4.4ls'",(LPSTR)&lpbi->biCompression));
  1219. pdd->hic = (HIC)-1;
  1220. if (wFlags & DDF_BUFFER)
  1221. {
  1222. RPF((" Turning DDF_BUFFER off"));
  1223. wFlags &= ~DDF_BUFFER;
  1224. goto try_again;
  1225. }
  1226. return FALSE;
  1227. }
  1228. //
  1229. // now find the best DIB format to decompress to.
  1230. //
  1231. if (!ICGetDisplayFormat(pdd->hic, lpbi, &pdd->biBuffer,
  1232. (gfHalftone || (wFlags & DDF_HALFTONE)) ? 16 : 0,
  1233. MulDiv(dxDst,abs((int)lpbi->biWidth),dxSrc),
  1234. MulDiv(dyDst,abs((int)lpbi->biHeight),dySrc)))
  1235. {
  1236. RPF((" Compressor error!"));
  1237. codec_error:
  1238. // ICClose(pdd->hic);
  1239. // pdd->hic = (HIC)-1;
  1240. return FALSE;
  1241. }
  1242. // Indeo5 codec has a bug where asking it to stretch by 2 and
  1243. // produce 32 bit RGB will only produce black frames, so ask it to
  1244. // do 24 bit instead. (bug 402298)
  1245. if ( pdd->biBuffer.biBitCount == 32 &&
  1246. pdd->biBuffer.biCompression == 0 &&
  1247. lpbi->biCompression == mmioFOURCC('I','V','5','0') &&
  1248. pdd->biBuffer.biWidth == 2 * lpbi->biWidth &&
  1249. pdd->biBuffer.biHeight == 2 * lpbi->biHeight) {
  1250. pdd->biBuffer.biBitCount = 24;
  1251. // biSizeImage will get fixed up below
  1252. }
  1253. //
  1254. // we have new source params
  1255. //
  1256. dxSrc = MulDiv(dxSrc, abs((int)pdd->biBuffer.biWidth), (int)pdd->lpbi->biWidth);
  1257. dySrc = MulDiv(dySrc, abs((int)pdd->biBuffer.biHeight), (int)pdd->lpbi->biHeight);
  1258. // xSrc = MulDiv(xSrc, abs((int)pdd->biBuffer.biWidth), (int)pdd->lpbi->biWidth);
  1259. // ySrc = MulDiv(ySrc, abs((int)pdd->biBuffer.biHeight), (int)pdd->lpbi->biHeight);
  1260. //
  1261. // now allocate the decompress buffer!
  1262. //
  1263. pdd->biBuffer.biSizeImage = DIBSIZEIMAGE(pdd->biBuffer);
  1264. //Question: do we need to zeroinit the allocated buffer??
  1265. //SD
  1266. pdd->pbBuffer = GlobalAllocPtr(GMEM_MOVEABLE,pdd->biBuffer.biSizeImage);
  1267. // pdd->pbBuffer = GlobalAllocPtr(GHND,pdd->biBuffer.biSizeImage);
  1268. if (pdd->pbBuffer == NULL)
  1269. {
  1270. RPF((" No Memory for decompress buffer"));
  1271. ICClose(pdd->hic);
  1272. pdd->hic = (HIC)-1;
  1273. return FALSE;
  1274. }
  1275. pdd->ulFlags |= DDF_DIRTY;
  1276. dw = ICDecompressBegin(pdd->hic, lpbi, &pdd->biBuffer);
  1277. if (dw != ICERR_OK)
  1278. {
  1279. RPF((" Compressor failed ICM_DECOMPRESS_BEGIN"));
  1280. goto codec_error;
  1281. }
  1282. RPF((" Decompressing '%4.4hs' to %dx%dx%d%s",(LPSTR)&lpbi->biCompression, PUSHBI(pdd->biBuffer),
  1283. Is565(&pdd->biBuffer) ? (LPSTR) "(565)" : (LPSTR) ""
  1284. ));
  1285. pdd->iDecompress = DECOMPRESS_BUFFER;
  1286. _fmemcpy(pdd->aw,pdd->argbq, 256*sizeof(RGBQUAD));
  1287. lpbi = &pdd->biBuffer;
  1288. break;
  1289. }
  1290. no_decomp:
  1291. pdd->biDraw = pdd->biBuffer;
  1292. pdd->biDraw.biSizeImage = 0;
  1293. pdd->biDraw.biHeight = abs((int)pdd->biDraw.biHeight);
  1294. if ((!(wFlags & DDF_JUSTDRAWIT)) && (lpbi->biCompression == BI_RGB))
  1295. {
  1296. //
  1297. // test the display device for this DIB format
  1298. //
  1299. w = QueryDraw(pdd, lpbi);
  1300. //
  1301. // get the bit depth of the screen device.
  1302. //
  1303. ScreenBitDepth = gwScreenBitDepth;
  1304. if (ScreenBitDepth > 24)
  1305. ScreenBitDepth = 32; //???!!!
  1306. // does the display support drawing 16bpp DIBs?
  1307. // if it does not, treat it like a 24bpp device.
  1308. if (ScreenBitDepth >= 24 && lpbi->biBitCount == 32 && !(w & PD_CAN_DRAW_DIB))
  1309. ScreenBitDepth = 24;
  1310. if (ScreenBitDepth >= 16 && lpbi->biBitCount == 16 && !(w & PD_CAN_DRAW_DIB))
  1311. ScreenBitDepth = 24;
  1312. //
  1313. // check if the display driver isn't very good for this format
  1314. //
  1315. if (!(w & PD_STRETCHDIB_1_1_OK))
  1316. {
  1317. pdd->ulFlags |= DDF_BITMAP;
  1318. }
  1319. //
  1320. // if the display driver isn't very good make a bitmap to copy into
  1321. // to draw.
  1322. //
  1323. switch (gfBitmap)
  1324. {
  1325. case 0:
  1326. pdd->ulFlags &= ~DDF_BITMAP;
  1327. break;
  1328. case 1:
  1329. pdd->ulFlags |= DDF_BITMAP;
  1330. break;
  1331. }
  1332. #ifndef _WIN32 // !!! why only !WIN32?
  1333. //
  1334. // for 16/32 bit DIBs, the display may not support DIBS at all and
  1335. // we should use bitmaps anyway just in case, even if the user
  1336. // tried to override
  1337. //
  1338. if ((pdd->biDraw.biBitCount == 16 || pdd->biDraw.biBitCount == 32) &&
  1339. w == PD_CAN_DRAW_DIB)
  1340. {
  1341. pdd->ulFlags |= DDF_BITMAP;
  1342. }
  1343. #endif
  1344. if ((dxSrc != dxDst || dySrc != dyDst) && !(w & PD_STRETCHDIB_1_N_OK))
  1345. pdd->ulFlags |= DDF_STRETCH;
  1346. if (dxSrc*2 == dxDst && dySrc*2 == dyDst && (w & PD_STRETCHDIB_1_2_OK))
  1347. pdd->ulFlags &= ~DDF_STRETCH;
  1348. if ((dxDst % dxSrc) == 0 && (dyDst % dySrc) == 0 && (w & PD_STRETCHDIB_1_2_OK))
  1349. pdd->ulFlags &= ~DDF_STRETCH;
  1350. if ((int)lpbi->biBitCount > ScreenBitDepth) {
  1351. DPF(("Turning on DITHER as bitcount is greater than screen bit depth"));
  1352. pdd->ulFlags |= DDF_DITHER;
  1353. }
  1354. //
  1355. // force halftone palette
  1356. //
  1357. if ((gfHalftone || (wFlags & DDF_HALFTONE)) && ScreenBitDepth <= 8) {
  1358. DPF(("Turning on DITHER because of halftoning\n"));
  1359. pdd->ulFlags |= DDF_DITHER;
  1360. }
  1361. // NOTE we treat a convert up (ie 16->24) as a dither too.
  1362. if ((int)lpbi->biBitCount > 8 && (int)lpbi->biBitCount < ScreenBitDepth) {
  1363. DPF(("Turning on DITHER as bitcount does not match screen bit depth"));
  1364. pdd->ulFlags |= DDF_DITHER;
  1365. }
  1366. if (pdd->ulFlags & DDF_DITHER) {
  1367. if (lpbi->biBitCount == 16 && (w & PD_CAN_DRAW_DIB)) {
  1368. pdd->ulFlags &= ~DDF_DITHER;
  1369. DPF(("Turning off DITHER for 16-bit DIBs, since we can draw them"));
  1370. }
  1371. if (lpbi->biBitCount == 32 && (w & PD_CAN_DRAW_DIB)) {
  1372. pdd->ulFlags &= ~DDF_DITHER;
  1373. DPF(("Turning off DITHER for 32-bit DIBs, since we can draw them"));
  1374. }
  1375. if (lpbi->biBitCount == 8 &&
  1376. lpbi->biClrUsed <= 16 &&
  1377. AreColorsAllGDIColors(lpbi)) {
  1378. pdd->ulFlags &= ~DDF_DITHER;
  1379. DPF(("Turning off DITHER for 8-bit DIBs already using the VGA colors"));
  1380. }
  1381. }
  1382. // force stretching in drawdib if we are dithering
  1383. if ((pdd->ulFlags & DDF_DITHER) &&
  1384. ((dxSrc != dxDst) || (dySrc != dyDst))) {
  1385. pdd->ulFlags |= DDF_STRETCH;
  1386. }
  1387. //
  1388. // Force a buffer if we dont have one. We only buffer if we're
  1389. // decompressing or dithering or stretching or using bitmaps, so our
  1390. // hacky way of forcing a buffer is to pretend we're stretching 1:1.
  1391. //
  1392. if ((pdd->ulFlags & DDF_BUFFER) &&
  1393. pdd->hic == NULL &&
  1394. !(pdd->ulFlags & DDF_DITHER) &&
  1395. !(pdd->ulFlags & DDF_STRETCH) &&
  1396. !(pdd->ulFlags & DDF_BITMAP))
  1397. {
  1398. RPF((" Using a buffer because DDF_BUFFER is set."));
  1399. pdd->ulFlags |= DDF_STRETCH; // force a 1:1 stretch
  1400. }
  1401. if (lpbi->biBitCount != 8
  1402. && lpbi->biBitCount != 16
  1403. && lpbi->biBitCount != 24
  1404. #ifndef _WIN32
  1405. && lpbi->biBitCount != 32
  1406. #endif
  1407. ) {
  1408. DPF(("Turning off stretch for an unsupported format...."));
  1409. pdd->ulFlags &= ~(DDF_STRETCH);
  1410. }
  1411. }
  1412. //
  1413. // delete the palette if we are changing who dithers.
  1414. //
  1415. if (pdd->hpal &&
  1416. pdd->lpbi->biBitCount > 8 &&
  1417. ((pdd->ulFlags ^ ulFlagsSave) & (DDF_DITHER)))
  1418. {
  1419. DPF((" Dither person has changed..."));
  1420. if (pdd->lpDitherTable)
  1421. {
  1422. DitherTerm(pdd->lpDitherTable);
  1423. pdd->lpDitherTable = NULL;
  1424. }
  1425. if (hdc) {
  1426. hPal = SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), TRUE);
  1427. if (hPal == pdd->hpal)
  1428. RPF((" Warning unselecting palette..."));
  1429. }
  1430. DeleteObject(pdd->hpal);
  1431. if (pdd->hpalCopy)
  1432. DeleteObject(pdd->hpalCopy);
  1433. pdd->hpal = NULL;
  1434. pdd->hpalCopy = NULL;
  1435. }
  1436. if (pdd->ulFlags & DDF_STRETCH)
  1437. {
  1438. /* the code for stretching *only* works on a 386+ */
  1439. if (gf286 || pdd->biBuffer.biBitCount < 8)
  1440. {
  1441. RPF((" Using GDI to stretch"));
  1442. pdd->ulFlags &= ~DDF_STRETCH;
  1443. }
  1444. else
  1445. {
  1446. //
  1447. // we have stretching to do, this requires extra
  1448. // headers and buffers.
  1449. //
  1450. pdd->biStretch = pdd->biBuffer;
  1451. pdd->biStretch.biWidth = dxDst;
  1452. pdd->biStretch.biHeight = dyDst;
  1453. pdd->biStretch.biSizeImage = DIBSIZEIMAGE(pdd->biStretch);
  1454. pdd->pbStretch = GlobalAllocPtr(GHND,pdd->biStretch.biSizeImage);
  1455. if (pdd->pbStretch == NULL)
  1456. {
  1457. RPF((" No memory for stretch buffer, using GDI"));
  1458. pdd->ulFlags &= ~DDF_STRETCH;
  1459. }
  1460. else
  1461. {
  1462. RPF((" Stretching %dx%dx%d%s --> %dx%dx%d",
  1463. dxSrc, dySrc, (int)lpbi->biBitCount,
  1464. (LPSTR) (Is565(lpbi) ? "(565)":""),
  1465. dxDst, dyDst, (int)pdd->biStretch.biBitCount,
  1466. (LPSTR) (Is565(&pdd->biStretch) ? "(565)":"")
  1467. ));
  1468. pdd->biDraw.biWidth = dxDst;
  1469. pdd->biDraw.biHeight = dyDst;
  1470. dxSrc = dxDst;
  1471. dySrc = dyDst;
  1472. lpbi = &pdd->biStretch;
  1473. }
  1474. }
  1475. }
  1476. if (pdd->ulFlags & DDF_DITHER)
  1477. {
  1478. pdd->ulFlags &= ~DDF_ANIMATE; // cant animate and dither!
  1479. if (ScreenBitDepth <= 8)
  1480. pdd->biDraw.biBitCount = 8;
  1481. else if (lpbi->biBitCount <= 8)
  1482. pdd->biDraw.biBitCount = lpbi->biBitCount;
  1483. else
  1484. ////////////pdd->biDraw.biBitCount = 24; //!!! what about 16bit DIB support
  1485. pdd->biDraw.biBitCount = ScreenBitDepth;
  1486. w = QueryDraw(pdd, &pdd->biDraw);
  1487. if (w & PD_STRETCHDIB_1_1_OK)
  1488. pdd->ulFlags &= ~DDF_BITMAP;
  1489. else
  1490. pdd->ulFlags |= DDF_BITMAP;
  1491. // this is wrong isn't it ? biDraw will be set to
  1492. // dxDst if we are stretching, or dxSrc if not. If we are asked to
  1493. // dither and stretch together, and we choose to leave the stretching
  1494. // to GDI, we will here set biDraw so that we ask the dither code
  1495. // to dither from dx/dySrc to dx/dyDst - ie stretch and dither in
  1496. // one go. Our current dither code will crash if you ask it to do this.
  1497. dxSave = (int)pdd->biDraw.biWidth;
  1498. dySave = (int)pdd->biDraw.biHeight;
  1499. #if 0
  1500. pdd->biDraw.biWidth = lpbi->biWidth;
  1501. pdd->biDraw.biHeight = lpbi->biHeight;
  1502. #endif
  1503. // !!! So DrawDibDraw will not DebugBreak
  1504. pdd->biDraw.biWidth = dxSrc;
  1505. pdd->biDraw.biHeight = dySrc;
  1506. pdd->biDraw.biSizeImage = DIBSIZEIMAGE(pdd->biDraw);
  1507. RPF((" Dithering %dx%dx%d --> %dx%dx%d", PUSHBI(*lpbi), PUSHBI(pdd->biDraw)));
  1508. //
  1509. // NOTE we need to use &pdd->biBuffer *not* lpbi because in the
  1510. // stretched case lpbi will point to pdd->biStretch and biStretch
  1511. // has NO COLOR TABLE
  1512. //
  1513. pdd->lpDitherTable = DitherInit(&pdd->biBuffer, &pdd->biDraw,
  1514. &pdd->DitherProc, pdd->lpDitherTable);
  1515. if (pdd->lpDitherTable == (LPVOID)-1 ||
  1516. pdd->DitherProc == NULL ||
  1517. !(pdd->pbDither = GlobalAllocPtr(GHND,pdd->biDraw.biSizeImage)))
  1518. {
  1519. if (pdd->lpDitherTable == (LPVOID)-1)
  1520. pdd->lpDitherTable = NULL;
  1521. if (pdd->lpDitherTable)
  1522. DitherTerm(pdd->lpDitherTable);
  1523. if ((pdd->pbDither) && (pdd->pbDither != pdd->lpDIBSection))
  1524. GlobalFreePtr(pdd->pbDither);
  1525. pdd->lpDitherTable = NULL;
  1526. pdd->pbDither = NULL;
  1527. pdd->biDraw.biBitCount = pdd->biBuffer.biBitCount;
  1528. pdd->biDraw.biWidth = dxSave;
  1529. pdd->biDraw.biHeight = dySave;
  1530. pdd->biDraw.biSizeImage = 0;
  1531. pdd->ulFlags &= ~DDF_DITHER;
  1532. #ifdef DEBUG_RETAIL
  1533. if (pdd->DitherProc)
  1534. RPF((" No Memory for dither tables!"));
  1535. else
  1536. RPF((" No DitherProc!"));
  1537. #endif
  1538. }
  1539. }
  1540. //
  1541. // create a palette (if needed)
  1542. //
  1543. if ((gwRasterCaps & RC_PALETTE) &&
  1544. pdd->biDraw.biBitCount <= 8 &&
  1545. pdd->hpal == NULL)
  1546. {
  1547. pdd->hpal = CreateBIPalette(pdd->hpal, &pdd->biDraw);
  1548. pdd->ulFlags |= DDF_NEWPALETTE;
  1549. }
  1550. //
  1551. // make sure we treat the palette as new when starting/stopping animate
  1552. //
  1553. if (wFlagsChanged & DDF_ANIMATE)
  1554. {
  1555. pdd->ulFlags |= DDF_NEWPALETTE;
  1556. }
  1557. //
  1558. // check for a identity palette
  1559. //
  1560. if (pdd->hpal == NULL)
  1561. {
  1562. pdd->ClrUsed = 0;
  1563. }
  1564. else if (pdd->ulFlags & DDF_NEWPALETTE)
  1565. {
  1566. #ifdef _WIN32
  1567. if (HIWORD(pdd->ClrUsed!=0)) {
  1568. DPF(("Hiword of variable non zero before calling GetObject\n"));
  1569. }
  1570. #endif
  1571. GetObject(pdd->hpal,sizeof(int),(LPVOID)&pdd->ClrUsed);
  1572. if (wFlagsChanged & DDF_ANIMATE)
  1573. SetPalFlags(pdd->hpal,0,pdd->ClrUsed,0);
  1574. if (IsIdentityPalette(pdd->hpal))
  1575. {
  1576. pdd->ulFlags |= DDF_IDENTITYPAL;
  1577. pdd->iAnimateStart = 10;
  1578. }
  1579. else
  1580. {
  1581. pdd->ulFlags &= ~DDF_IDENTITYPAL;
  1582. pdd->iAnimateStart = 0;
  1583. }
  1584. pdd->iAnimateLen = min(236,pdd->ClrUsed);
  1585. pdd->iAnimateEnd = pdd->iAnimateStart + pdd->iAnimateLen;
  1586. if (pdd->ulFlags & DDF_ANIMATE)
  1587. {
  1588. RPF((" Palette animation"));
  1589. SetPalFlags(pdd->hpal,pdd->iAnimateStart,pdd->iAnimateLen,PC_RESERVED);
  1590. }
  1591. }
  1592. //
  1593. // because of bugs in GDIs StretchDIBits (doing a stretch) we
  1594. // always set the number of colors to be the maximum.
  1595. //
  1596. // this is not a big deal because we are mostly drawing full-color-table
  1597. // DIBs any way.
  1598. //
  1599. if (pdd->biDraw.biBitCount <= 8)
  1600. pdd->biDraw.biClrUsed = (1 << (int)pdd->biDraw.biBitCount);
  1601. else
  1602. pdd->biDraw.biClrUsed = 0;
  1603. DrawDibSetPalette(hdd, pdd->hpalDraw);
  1604. if (pdd->hpal)
  1605. {
  1606. if (pdd->ulFlags & DDF_IDENTITYPAL)
  1607. RPF((" Drawing with an identity palette"));
  1608. else
  1609. RPF((" Drawing with a non-identity palette"));
  1610. }
  1611. if (pdd->uiPalUse == DIB_RGB_COLORS)
  1612. RPF((" Using DIB_RGB_COLORS"));
  1613. else
  1614. RPF((" Using DIB_PAL_COLORS"));
  1615. if (pdd->hpalDraw)
  1616. RPF((" Mapping to another palette"));
  1617. if (pdd->ulFlags & DDF_BITMAP)
  1618. {
  1619. BOOL fGetDC;
  1620. BOOL f;
  1621. HWND hwndActive;
  1622. RPF((" Display driver slow for DIBs, using bitmaps"));
  1623. if (fGetDC = (hdc == NULL))
  1624. {
  1625. hwndActive = GetActiveWindow();
  1626. hdc = GetDC(hwndActive);
  1627. }
  1628. if (pdd->hdcDraw) {
  1629. if (hbmStockMono) {
  1630. SelectObject(pdd->hdcDraw, hbmStockMono);
  1631. }
  1632. } else /* if (!pdd->hdcDraw) */ {
  1633. pdd->hdcDraw = CreateCompatibleDC(hdc);
  1634. }
  1635. if (pdd->hbmDraw) {
  1636. // This fixes a memory leak. Perhaps we can just use the old one?
  1637. DPF(("Freeing hbmDraw!\n"));
  1638. DeleteObject(pdd->hbmDraw);
  1639. }
  1640. //
  1641. // NOTE the bitmap must be as wide as the source DIB when we are
  1642. // using SetDIBits() because SetDIBits() only takes a start scan not a (x,y)
  1643. //
  1644. // pdd->hbmDraw = CreateCompatibleBitmap(hdc, (int)pdd->biDraw.biWidth, (int)pdd->biDraw.biHeight);
  1645. pdd->hbmDraw = CreateCompatibleBitmap(hdc, (int)pdd->biDraw.biWidth, dySrc);
  1646. if (pdd->hbmDraw == NULL || pdd->hdcDraw == NULL)
  1647. goto bitmap_fail;
  1648. hbmStockMono = SelectObject(pdd->hdcDraw,pdd->hbmDraw);
  1649. pdd->ulFlags |= DDF_NEWPALETTE;
  1650. #if USE_SETDI
  1651. f = SetBitmapBegin(
  1652. &pdd->sd, // structure
  1653. hdc, // device
  1654. pdd->hbmDraw, // bitmap to set into
  1655. &pdd->biDraw, // --> BITMAPINFO of source
  1656. pdd->uiPalUse);
  1657. #else
  1658. f = TRUE;
  1659. #endif
  1660. if (!f)
  1661. {
  1662. bitmap_fail:
  1663. if (pdd->hdcDraw) {
  1664. DeleteDC(pdd->hdcDraw);
  1665. pdd->hdcDraw = NULL;
  1666. }
  1667. if (pdd->hbmDraw) {
  1668. DeleteObject(pdd->hbmDraw);
  1669. pdd->hbmDraw = NULL;
  1670. }
  1671. pdd->ulFlags &= ~DDF_BITMAP;
  1672. }
  1673. if (fGetDC)
  1674. {
  1675. ReleaseDC(hwndActive, hdc);
  1676. hdc = NULL;
  1677. }
  1678. }
  1679. //
  1680. // Use CreateDibSection unless we're in VGA mode, or we're not
  1681. // decompressing, stretching, or dithering.
  1682. //
  1683. if (ScreenBitDepth > 4 &&
  1684. (pdd->hic || (pdd->ulFlags & (DDF_STRETCH|DDF_DITHER)))) {
  1685. BOOL fGetDC;
  1686. HWND hwndActive;
  1687. HPALETTE hpalOld = NULL;
  1688. if (pdd->hbmDraw) {
  1689. // !!! Shouldn't we really not delete these until after we know
  1690. // we can use CreateDIBSection?
  1691. SelectObject(pdd->hdcDraw, hbmStockMono);
  1692. DeleteObject(pdd->hbmDraw);
  1693. DeleteDC(pdd->hdcDraw);
  1694. pdd->hdcDraw = NULL;
  1695. pdd->hbmDraw = NULL;
  1696. }
  1697. if (fGetDC = (hdc == NULL))
  1698. {
  1699. hwndActive = GetActiveWindow();
  1700. hdc = GetDC(hwndActive);
  1701. }
  1702. if (pdd->hpalDraw || pdd->hpal) {
  1703. hpalOld = SelectPalette(hdc,
  1704. pdd->hpalDraw ? pdd->hpalDraw :
  1705. pdd->hpal,
  1706. TRUE);
  1707. }
  1708. pdd->hbmDraw = CreateDIBSection(
  1709. hdc,
  1710. (LPBITMAPINFO)&pdd->biDraw,
  1711. // we don't want to use DIB_PAL_INDICES for create dib section
  1712. (pdd->uiPalUse == DIB_RGB_COLORS) ? DIB_RGB_COLORS : DIB_PAL_COLORS,
  1713. &pdd->lpDIBSection,
  1714. 0, // handle to section
  1715. 0); // offset within section
  1716. pdd->hdcDraw = CreateCompatibleDC(hdc);
  1717. if ((pdd->hdcDraw == NULL) ||
  1718. (pdd->hbmDraw == NULL) ||
  1719. (pdd->lpDIBSection == NULL)) {
  1720. if (pdd->hdcDraw)
  1721. DeleteDC(pdd->hdcDraw);
  1722. if (pdd->hbmDraw)
  1723. DeleteObject(pdd->hbmDraw);
  1724. pdd->lpDIBSection = NULL;
  1725. pdd->hdcDraw = NULL;
  1726. pdd->hbmDraw = NULL;
  1727. RPF(("CreateDIBSection FAILED"));
  1728. } else {
  1729. hbmStockMono = SelectObject(pdd->hdcDraw,pdd->hbmDraw);
  1730. // make sure we decomp, stretch or dither into the right place
  1731. if (pdd->pbDither) {
  1732. GlobalFreePtr(pdd->pbDither);
  1733. pdd->pbDither = pdd->lpDIBSection;
  1734. } else if (pdd->pbStretch) {
  1735. GlobalFreePtr(pdd->pbStretch);
  1736. pdd->pbStretch = pdd->lpDIBSection;
  1737. } else if (pdd->pbBuffer) {
  1738. GlobalFreePtr(pdd->pbBuffer);
  1739. pdd->pbBuffer = pdd->lpDIBSection;
  1740. }
  1741. }
  1742. if (fGetDC)
  1743. {
  1744. if (hpalOld)
  1745. SelectPalette(hdc, hpalOld, FALSE);
  1746. ReleaseDC(hwndActive, hdc);
  1747. hdc = NULL;
  1748. }
  1749. } else {
  1750. // We are NOT using DIBSection. We might have an old one sitting around,
  1751. // so clear it out. The reason we might have an old one sitting around is
  1752. // that deciding whether or not to try to draw RLE directly or to decompress
  1753. // it first to RGB (based on if our DC is a screen DC or not - because of a
  1754. // GDI bug that can't draw RLE deltas to memory DCs) can affect whether or
  1755. // not we use DIBSections, and our code at the beginning of DrawDibBegin is
  1756. // not smart enough to call DrawDibFree in this case to clear this stuff
  1757. // out. I hate this code. - DannyMi
  1758. // NOTE: This code appears at least 3 times in this file.
  1759. if (pdd->hdcDraw) {
  1760. if (hbmStockMono)
  1761. SelectObject(pdd->hdcDraw, hbmStockMono);
  1762. DeleteDC(pdd->hdcDraw);
  1763. pdd->hdcDraw = NULL;
  1764. }
  1765. if (pdd->hbmDraw) {
  1766. DeleteObject(pdd->hbmDraw);
  1767. pdd->hbmDraw = NULL;
  1768. }
  1769. // I have to throw away these if I'm throwing away the DIB section, so
  1770. // we don't end up trying to free it twice.
  1771. if (pdd->pbDither == pdd->lpDIBSection)
  1772. pdd->pbDither = NULL;
  1773. if (pdd->pbStretch == pdd->lpDIBSection)
  1774. pdd->pbStretch = NULL;
  1775. if (pdd->pbBuffer == pdd->lpDIBSection)
  1776. pdd->pbBuffer = NULL;
  1777. pdd->lpDIBSection = NULL;
  1778. }
  1779. //
  1780. // now try to decompress to a bitmap, we only decompress to
  1781. // bitmaps if the following is true.
  1782. //
  1783. // the decompressor must decompress direct, we will not
  1784. // stretch/dither afterward
  1785. //
  1786. // if on a palette device, the color table must be 1:1
  1787. //
  1788. // we should check a decompressor flag
  1789. //
  1790. if (pdd->hic &&
  1791. !(pdd->ulFlags & (DDF_STRETCH|DDF_DITHER)) &&
  1792. gfBitmapX &&
  1793. (pdd->lpDIBSection == NULL) &&
  1794. (dxDst == pdd->lpbi->biWidth) &&
  1795. (dyDst == pdd->lpbi->biHeight)
  1796. )
  1797. {
  1798. if (pdd->ulFlags & DDF_BITMAP) {
  1799. if (pdd->hbmDraw) {
  1800. DrawDibQueryBitmapX(pdd);
  1801. }
  1802. } else {
  1803. //even though we decided not to use bitmaps, it might still
  1804. //be worth trying decompression to bitmaps. the DDF_BITMAP
  1805. //flag is based on a comparison of StretchDIBits vs
  1806. //SetDIBits+BitBlt. Decompressing to a bitmap could be
  1807. //faster even when SetDIBits+Bitblt is slower
  1808. // but in this case, if we fail, we have to make sure we don't
  1809. // end up doing DDF_BITMAP as we know that's slower.
  1810. if (QueryDraw(pdd, &pdd->biBuffer) & PD_BITBLT_FAST) {
  1811. BOOL fGetDC;
  1812. HWND hwndActive;
  1813. RPF((" Not using BITMAPS, but trying Decomp to Bitmap"));
  1814. if (fGetDC = (hdc == NULL))
  1815. {
  1816. hwndActive = GetActiveWindow();
  1817. hdc = GetDC(hwndActive);
  1818. }
  1819. pdd->hdcDraw = CreateCompatibleDC(hdc);
  1820. pdd->hbmDraw = CreateCompatibleBitmap(hdc, (int)pdd->biDraw.biWidth, (int)pdd->biDraw.biHeight);
  1821. if ((pdd->hbmDraw != NULL) && (pdd->hdcDraw != NULL)) {
  1822. hbmStockMono = SelectObject(pdd->hdcDraw,pdd->hbmDraw);
  1823. if (fGetDC)
  1824. {
  1825. ReleaseDC(hwndActive, hdc);
  1826. hdc = NULL;
  1827. }
  1828. DrawDibQueryBitmapX(pdd);
  1829. }
  1830. if (!(pdd->ulFlags & DDF_CANBITMAPX)) {
  1831. if (pdd->hdcDraw) {
  1832. DeleteDC(pdd->hdcDraw);
  1833. pdd->hdcDraw = NULL;
  1834. }
  1835. if (pdd->hbmDraw) {
  1836. DeleteObject(pdd->hbmDraw);
  1837. pdd->hbmDraw = NULL;
  1838. }
  1839. }
  1840. }
  1841. }
  1842. }
  1843. #ifdef USE_DCI
  1844. //
  1845. // see if the decompressor can decompress directly to the screen
  1846. // doing everything, stretching and all.
  1847. //
  1848. if (pdd->hic && pdci && gfScreenX)
  1849. {
  1850. if (wFlags & DDF_BUFFER)
  1851. {
  1852. DPF((" DDF_BUFFER specified, unable to decompres to screen"));
  1853. goto cant_do_screen;
  1854. }
  1855. // Indeo5 codec has a bug where asking it to stretch by 2 and
  1856. // produce 32 bit RGB will only produce black frames, so disable DCI
  1857. // if it would do this
  1858. if ( biScreen.bi.biBitCount == 32 &&
  1859. pdd->lpbi->biCompression == mmioFOURCC('I','V','5','0') &&
  1860. pdd->dxDst == 2 * pdd->lpbi->biWidth &&
  1861. pdd->dyDst == 2 * pdd->lpbi->biHeight) {
  1862. DPF((" Indeo 5 bug - unable to decompres to screen"));
  1863. goto cant_do_screen;
  1864. }
  1865. //
  1866. // try to decompress to screen.
  1867. //
  1868. if (((gwRasterCaps & RC_PALETTE) && !(pdd->ulFlags & DDF_IDENTITYPAL)) ||
  1869. (gwScreenBitDepth == 8 && !(gwRasterCaps & RC_PALETTE)) ||
  1870. (pdd->ulFlags & (DDF_STRETCH|DDF_DITHER)) ||
  1871. (ICDecompressExQuery(pdd->hic, 0,
  1872. pdd->lpbi, NULL, 0, 0, pdd->dxSrc, pdd->dySrc,
  1873. (LPBITMAPINFOHEADER) &biScreen, lpScreen,
  1874. 0, 0, pdd->dxDst, pdd->dyDst) != ICERR_OK))
  1875. {
  1876. cant_do_screen:
  1877. ; // we can't decompress to the screen
  1878. }
  1879. else
  1880. { // we can decompress to the screen
  1881. pdd->ulFlags |= DDF_CLIPCHECK; // we need clipping checking
  1882. pdd->ulFlags |= DDF_NEWPALETTE; // force check in DrawDibRealize
  1883. pdd->ulFlags |= DDF_CANSCREENX; // we can decompress to screen
  1884. pdd->ulFlags |= DDF_CLIPPED; // we are initialized for clipped now
  1885. RPF((" Can decompress '%4.4hs' to the SCREEN",(LPSTR)&pdd->lpbi->biCompression));
  1886. }
  1887. }
  1888. #ifdef WANT_DRAW_DIRECT_TO_SCREEN
  1889. //
  1890. // see if we can draw direct to the screen
  1891. //
  1892. if (pdd->hic && pdci && gfDrawX)
  1893. {
  1894. if (TRUE)
  1895. goto cant_draw_screen;
  1896. pdd->ulFlags |= DDF_CLIPCHECK; // we need clipping checking
  1897. pdd->ulFlags |= DDF_NEWPALETTE; // force check in DrawDibRealize
  1898. pdd->ulFlags |= DDF_CANDRAWX; // we can decompress to screen
  1899. pdd->ulFlags |= DDF_CLIPPED; // we are initialized for clipped now
  1900. RPF((" Can draw to the SCREEN"));
  1901. cant_draw_screen:
  1902. ;
  1903. }
  1904. #endif
  1905. #endif
  1906. //
  1907. // see if the source cordinates need translated
  1908. //
  1909. if (abs((int)pdd->biBuffer.biWidth) != (int)pdd->lpbi->biWidth ||
  1910. abs((int)pdd->biBuffer.biHeight) != (int)pdd->lpbi->biHeight)
  1911. {
  1912. pdd->ulFlags |= DDF_XLATSOURCE;
  1913. }
  1914. return TRUE;
  1915. }
  1916. /**************************************************************************
  1917. * @doc EXTERNAL DrawDib
  1918. *
  1919. * @api BOOL | DrawDibEnd | This function frees a DrawDib context.
  1920. *
  1921. * @parm HDRAWDIB | hdd | Specifies the handle to the DrawDib context to free.
  1922. *
  1923. * @rdesc Returns TRUE if successful.
  1924. *
  1925. * @comm Any flags set or palette changes made by <f DrawDibBegin> or
  1926. * <f DrawDibDraw> is discarded by <f DrawDibEnd>.
  1927. *
  1928. **************************************************************************/
  1929. BOOL VFWAPI DrawDibEnd(HDRAWDIB hdd)
  1930. {
  1931. PDD pdd;
  1932. if ((pdd = DrawDibLock(hdd)) == NULL)
  1933. return FALSE;
  1934. DrawDibFree(pdd, FALSE, FALSE);
  1935. return TRUE;
  1936. }
  1937. /**************************************************************************
  1938. * @doc EXTERNAL DrawDib
  1939. *
  1940. * @api BOOL | DrawDibTime | Returns timing information about
  1941. * the drawing during debug operation.
  1942. *
  1943. * @parm HDRAWDIB | hdd | Specifies a handle to a DrawDib context.
  1944. *
  1945. * @parm LPDRAWDIBTIME | lpddtime | Specifies a pointer to
  1946. * a <t DRAWDIBTIME> structure.
  1947. *
  1948. * @rdesc Returns TRUE if successful.
  1949. *
  1950. **************************************************************************/
  1951. BOOL VFWAPI DrawDibTime(HDRAWDIB hdd, LPDRAWDIBTIME lpddtime)
  1952. {
  1953. #ifdef DEBUG_RETAIL
  1954. PDD pdd;
  1955. if ((pdd = DrawDibLockNoTaskCheck(hdd)) == NULL)
  1956. return FALSE;
  1957. if (lpddtime)
  1958. *lpddtime = pdd->ddtime;
  1959. if (pdd->ddtime.timeCount > 0)
  1960. {
  1961. RPF(("timeCount: %u", (UINT)pdd->ddtime.timeCount));
  1962. RPF(("timeDraw: %ums (%u)", (UINT)pdd->ddtime.timeDraw, (UINT)pdd->ddtime.timeDraw/(UINT)pdd->ddtime.timeCount));
  1963. RPF(("timeDecompress: %ums (%u)", (UINT)pdd->ddtime.timeDecompress, (UINT)pdd->ddtime.timeDecompress/(UINT)pdd->ddtime.timeCount));
  1964. RPF(("timeDither: %ums (%u)", (UINT)pdd->ddtime.timeDither, (UINT)pdd->ddtime.timeDither/(UINT)pdd->ddtime.timeCount));
  1965. RPF(("timeStretch: %ums (%u)", (UINT)pdd->ddtime.timeStretch, (UINT)pdd->ddtime.timeStretch/(UINT)pdd->ddtime.timeCount));
  1966. RPF(("timeSetDIBits: %ums (%u)", (UINT)pdd->ddtime.timeSetDIBits, (UINT)pdd->ddtime.timeSetDIBits/(UINT)pdd->ddtime.timeCount));
  1967. RPF(("timeBlt: %ums (%u)", (UINT)pdd->ddtime.timeBlt, (UINT)pdd->ddtime.timeBlt/(UINT)pdd->ddtime.timeCount));
  1968. }
  1969. pdd->ddtime.timeCount = 0;
  1970. pdd->ddtime.timeDraw = 0;
  1971. pdd->ddtime.timeDecompress = 0;
  1972. pdd->ddtime.timeDither = 0;
  1973. pdd->ddtime.timeStretch = 0;
  1974. pdd->ddtime.timeSetDIBits = 0;
  1975. pdd->ddtime.timeBlt = 0;
  1976. return TRUE;
  1977. #else
  1978. return FALSE;
  1979. #endif
  1980. }
  1981. /*
  1982. * CopyPal -- copy a palette
  1983. */
  1984. HPALETTE CopyPal(HPALETTE hpal)
  1985. {
  1986. NPLOGPALETTE pLogPal = NULL;
  1987. HPALETTE hpalNew = NULL;
  1988. int iSizePalette = 0; // size of entire palette
  1989. if (hpal == NULL)
  1990. return NULL;
  1991. DPF(("CopyPal routine\n"));
  1992. GetObject(hpal,sizeof(iSizePalette),(LPSTR)&iSizePalette);
  1993. pLogPal = (NPLOGPALETTE)LocalAlloc(LPTR, sizeof(LOGPALETTE)
  1994. + iSizePalette * sizeof(PALETTEENTRY));
  1995. if (!pLogPal)
  1996. return NULL;
  1997. pLogPal->palVersion = 0x300;
  1998. pLogPal->palNumEntries = (WORD) iSizePalette;
  1999. GetPaletteEntries(hpal, 0, iSizePalette, pLogPal->palPalEntry);
  2000. hpal = CreatePalette(pLogPal);
  2001. LocalFree((HLOCAL) pLogPal);
  2002. return hpal;
  2003. }
  2004. /**************************************************************************
  2005. * @doc EXTERNAL DrawDib
  2006. *
  2007. * @api HPALETTE | DrawDibGetPalette | This function obtains the palette
  2008. * used by a DrawDib context.
  2009. *
  2010. * @parm HDRAWDIB | hdd | Specifies a handle to a DrawDib context.
  2011. *
  2012. * @rdesc Returns a handle for the palette if successful, otherwise
  2013. * it returns NULL.
  2014. *
  2015. * @comm Use <f DrawDibRealize> instead of this function
  2016. * to realize the correct palette in response to a window
  2017. * message. You should rarely need to call this function.
  2018. *
  2019. * Applications do not have exclusive use of the palette
  2020. * obtained with this function. Applications should not
  2021. * free the palette or assign it to a display context
  2022. * with functions such as <f SelectPalette>. Applications
  2023. * should also anticipate that some other
  2024. * application can invalidate the handle. The palette
  2025. * handle might also become invalid after the next use of a DrawDib function.
  2026. *
  2027. * This function returns a valid handle only after
  2028. * <f DrawDibBegin> has been used without pairing it with
  2029. * <f DrawDibEnd>, or if <f DrawDibDraw> has been used.
  2030. *
  2031. * @xref <f DrawDibSetPalette> <f DrawDibRealize>
  2032. *
  2033. **************************************************************************/
  2034. HPALETTE VFWAPI DrawDibGetPalette(HDRAWDIB hdd)
  2035. {
  2036. PDD pdd;
  2037. if ((pdd = DrawDibLockNoTaskCheck(hdd)) == NULL)
  2038. return NULL;
  2039. if (pdd->hpalDraw)
  2040. return pdd->hpalDraw;
  2041. else {
  2042. // For palette animation we can't return a different palette than the
  2043. // real palette, so return hpal, not hpalCopy.
  2044. // Just trust me. - Toddla
  2045. if (pdd->ulFlags & DDF_ANIMATE)
  2046. return pdd->hpal;
  2047. // In order for us to play direct to screen, etc, all palette
  2048. // realization has to come through DrawDibRealize. But that won't
  2049. // always happen. Some apps will always ask us for our palette and
  2050. // realize it themselves. So if we give them a copy of our palette,
  2051. // and never our true palette, when our play code realizes the true
  2052. // palette it's guarenteed to cause an actual palette change and we'll
  2053. // correctly detect playing to screen. (BUG 1761)
  2054. if (pdd->hpalCopy == NULL)
  2055. pdd->hpalCopy = CopyPal(pdd->hpal);
  2056. return pdd->hpalCopy;
  2057. }
  2058. }
  2059. /**************************************************************************
  2060. * @doc EXTERNAL DrawDib
  2061. *
  2062. * @api BOOL | DrawDibSetPalette | This function sets the palette
  2063. * used for drawing device independent bitmaps.
  2064. *
  2065. * @parm HDRAWDIB | hdd | Specifies a handle to a DrawDib context.
  2066. *
  2067. * @parm HPALETTE | hpal | Specifies a handle to the palette.
  2068. * Specify NULL to use the default palette.
  2069. *
  2070. * @rdesc Returns TRUE if successful.
  2071. *
  2072. * @comm Use this function when the application needs to realize an
  2073. * alternate palette. The function forces the DrawDib context to use the
  2074. * specified palette, possibly at the expense of image quality.
  2075. *
  2076. * Do not free a palette assigned to a DrawDib context until
  2077. * either a new palette replaces it (for example, if hpal1 is the
  2078. * current palette, replacing it with DrawDibSetPalette(hdd, hpal2)),
  2079. * or until the palette handle for the DrawDib context is set to
  2080. * to the default palette (for example, DrawDibSetPalette(hdd, NULL)).
  2081. *
  2082. * @xref <f DrawDibGetPalette>
  2083. *
  2084. **************************************************************************/
  2085. BOOL VFWAPI DrawDibSetPalette(HDRAWDIB hdd, HPALETTE hpal)
  2086. {
  2087. PDD pdd;
  2088. int i;
  2089. if ((pdd = DrawDibLock(hdd)) == NULL)
  2090. return FALSE;
  2091. if (hpal == pdd->hpalCopy)
  2092. hpal = NULL;
  2093. if (pdd->hpalDraw != hpal)
  2094. pdd->ulFlags |= DDF_NEWPALETTE;
  2095. pdd->hpalDraw = hpal; // always set this variable
  2096. if (pdd->hpal == NULL) // no palette to dink with
  2097. return TRUE;
  2098. if (pdd->biDraw.biBitCount > 8) // make sure we are drawing palettized
  2099. return TRUE;
  2100. if (pdd->ulFlags & DDF_ANIMATE)
  2101. {
  2102. DPF(("DrawDibSetPalette called while in DDF_ANIMATE mode!"));
  2103. }
  2104. //
  2105. // we are now using PAL colors...
  2106. //
  2107. pdd->uiPalUse = DIB_PAL_COLORS;
  2108. if (pdd->hpalDraw != NULL)
  2109. {
  2110. /* Set up table for BI_PAL_COLORS non 1:1 drawing */
  2111. //
  2112. // map all of our colors onto the given palette
  2113. // NOTE we can't use the select background trick
  2114. // because the given palette <hpalDraw> may have
  2115. // PC_RESERVED entries in it.
  2116. //
  2117. // SendSetPalette(pdd);
  2118. for (i=0; i < 256; i++)
  2119. {
  2120. if (pdd->biBuffer.biBitCount == 8)
  2121. {
  2122. pdd->aw[i] = (WORD) GetNearestPaletteIndex(pdd->hpalDraw,
  2123. RGB(pdd->argbq[i].rgbRed,
  2124. pdd->argbq[i].rgbGreen,
  2125. pdd->argbq[i].rgbBlue));
  2126. }
  2127. else
  2128. {
  2129. PALETTEENTRY pe;
  2130. GetPaletteEntries(pdd->hpal, i, 1, &pe);
  2131. pdd->aw[i] = (WORD) GetNearestPaletteIndex(pdd->hpalDraw,
  2132. RGB(pe.peRed,
  2133. pe.peGreen,
  2134. pe.peBlue));
  2135. }
  2136. }
  2137. for (; i<256; i++)
  2138. pdd->aw[i] = 0;
  2139. }
  2140. else
  2141. {
  2142. /* Set up table for BI_PAL_COLORS 1:1 drawing */
  2143. // SendSetPalette(pdd);
  2144. for (i=0; i<(int)pdd->ClrUsed; i++)
  2145. pdd->aw[i] = (WORD) i;
  2146. for (; i<256; i++)
  2147. pdd->aw[i] = 0;
  2148. }
  2149. return TRUE;
  2150. }
  2151. /**************************************************************************
  2152. * @doc EXTERNAL DrawDib
  2153. *
  2154. * @api BOOL | DrawDibChangePalette | This function sets the palette entries
  2155. * used for drawing device independent bitmaps.
  2156. *
  2157. * @parm HDRAWDIB | hdd | Specifies a handle to a DrawDib context.
  2158. *
  2159. * @parm int | iStart | Specifies the starting palette entry number.
  2160. *
  2161. * @parm int | iLen | Specifies the number of palette entries.
  2162. *
  2163. * @parm LPPALETTEENTRY | lppe | Specifies a pointer to an
  2164. * array of palette entries.
  2165. *
  2166. * @rdesc Returns TRUE if successful.
  2167. *
  2168. * @comm
  2169. * Use this function when the DIB color table changes and
  2170. * other parameters stay constant. This function changes
  2171. * the physical palette only if the current
  2172. * DrawDib palette is curently realized by calling <f DrawDibRealize>.
  2173. *
  2174. * The DIB color table must be changed by the user or
  2175. * the next use of <f DrawDibDraw> without the DDF_SAME_DRAW flag
  2176. * implicity calls <f DrawDibBegin>.
  2177. *
  2178. * If the DDF_ANIMATE flag is not set in the previous call to
  2179. * <f DrawDibBegin> or <f DrawDibDraw>, this function will
  2180. * animate the palette. In this case, update the DIB color
  2181. * table from the palette specified by <p lppe> and use
  2182. * <f DrawDibRealize> to realize the updated palette. Redraw
  2183. * the image to see the updated colors.
  2184. *
  2185. * @xref <f DrawDibSetPalette> <f DrawDibRealize>
  2186. *
  2187. **************************************************************************/
  2188. BOOL VFWAPI DrawDibChangePalette(HDRAWDIB hdd, int iStart, int iLen, LPPALETTEENTRY lppe)
  2189. {
  2190. PDD pdd;
  2191. int i;
  2192. int iStartSave;
  2193. int iLenSave;
  2194. LPPALETTEENTRY lppeSave;
  2195. if ((pdd = DrawDibLock(hdd)) == NULL)
  2196. return FALSE;
  2197. if (pdd->biBuffer.biBitCount != 8)
  2198. return FALSE;
  2199. if (lppe == NULL || iStart < 0 || iLen + iStart > 256)
  2200. return FALSE;
  2201. for (i=0; i<iLen; i++)
  2202. {
  2203. (*(pdd->lpargbqIn))[iStart+i].rgbRed = lppe[i].peRed;
  2204. (*(pdd->lpargbqIn))[iStart+i].rgbGreen = lppe[i].peGreen;
  2205. (*(pdd->lpargbqIn))[iStart+i].rgbBlue = lppe[i].peBlue;
  2206. }
  2207. //
  2208. // handle a palette change for 8bit dither
  2209. //
  2210. if (pdd->lpDitherTable)
  2211. {
  2212. for (i=0; i<iLen; i++)
  2213. {
  2214. pdd->argbq[iStart+i].rgbRed = lppe[i].peRed;
  2215. pdd->argbq[iStart+i].rgbGreen = lppe[i].peGreen;
  2216. pdd->argbq[iStart+i].rgbBlue = lppe[i].peBlue;
  2217. }
  2218. pdd->lpDitherTable = DitherInit(pdd->lpbi, &pdd->biDraw, &pdd->DitherProc, pdd->lpDitherTable);
  2219. }
  2220. else if (pdd->hpalDraw)
  2221. {
  2222. SetPaletteEntries(pdd->hpal, iStart, iLen, lppe);
  2223. pdd->ulFlags |= DDF_NEWPALETTE;
  2224. for (i=iStart; i<iLen; i++)
  2225. {
  2226. pdd->aw[i] = (WORD) GetNearestPaletteIndex(pdd->hpalDraw,
  2227. RGB(lppe[i].peRed,lppe[i].peGreen,lppe[i].peBlue));
  2228. }
  2229. }
  2230. else if (pdd->ulFlags & DDF_ANIMATE)
  2231. {
  2232. for (i=iStart; i<iStart+iLen; i++)
  2233. {
  2234. if (i >= pdd->iAnimateStart && i < pdd->iAnimateEnd)
  2235. lppe[i-iStart].peFlags = PC_RESERVED;
  2236. else
  2237. lppe[i-iStart].peFlags = 0;
  2238. }
  2239. /* Change iLen, iStart so that they only include the colors
  2240. ** we can actually animate. If we don't do this, the
  2241. ** AnimatePalette() call just returns without doing anything.
  2242. */
  2243. iStartSave = iStart;
  2244. iLenSave = iLen;
  2245. lppeSave = lppe;
  2246. if (iStart < pdd->iAnimateStart)
  2247. {
  2248. iLen -= (pdd->iAnimateStart - iStart);
  2249. lppe += (pdd->iAnimateStart - iStart);
  2250. iStart = pdd->iAnimateStart;
  2251. }
  2252. if (iStart + iLen > pdd->iAnimateEnd)
  2253. iLen = pdd->iAnimateEnd - iStart;
  2254. AnimatePalette(pdd->hpal, iStart, iLen, lppe);
  2255. //
  2256. // any colors we could not animate, map to nearest
  2257. //
  2258. for (i=iStartSave; i<iStartSave+iLenSave; i++)
  2259. {
  2260. if (i >= pdd->iAnimateStart && i < pdd->iAnimateEnd)
  2261. pdd->aw[i] = (WORD) i;
  2262. else
  2263. pdd->aw[i] = (WORD) GetNearestPaletteIndex(pdd->hpal,
  2264. RGB(lppeSave[i-iStartSave].peRed,
  2265. lppeSave[i-iStartSave].peGreen,
  2266. lppeSave[i-iStartSave].peBlue));
  2267. }
  2268. }
  2269. else if (pdd->hpal)
  2270. {
  2271. SetPaletteEntries(pdd->hpal, iStart, iLen, lppe);
  2272. pdd->ulFlags |= DDF_NEWPALETTE;
  2273. }
  2274. else
  2275. {
  2276. DPF(("Copying palette entries \n"));
  2277. for (i=0; i<iLen; i++)
  2278. {
  2279. ((RGBQUAD *)pdd->aw)[iStart+i].rgbRed = lppe[i].peRed;
  2280. ((RGBQUAD *)pdd->aw)[iStart+i].rgbGreen = lppe[i].peGreen;
  2281. ((RGBQUAD *)pdd->aw)[iStart+i].rgbBlue = lppe[i].peBlue;
  2282. }
  2283. if (pdd->hbmDraw)
  2284. pdd->ulFlags |= DDF_NEWPALETTE;
  2285. }
  2286. if (pdd->lpDIBSection) {
  2287. // the colour table of a DIB Section is not changed when the palette
  2288. // used to create it changes. We need to explicitly change it.
  2289. SetDIBColorTable(pdd->hdcDraw, iStart, iLen,
  2290. &(*(pdd->lpargbqIn))[iStart]);
  2291. }
  2292. // We'll break buggy apps if we delete a palette we've given them
  2293. // even though we told them not to use it.
  2294. //
  2295. // if (pdd->hpalCopy)
  2296. // DeleteObject(pdd->hpalCopy);
  2297. // pdd->hpalCopy = NULL;
  2298. return TRUE;
  2299. }
  2300. /**************************************************************************
  2301. *
  2302. * @doc EXTERNAL DrawDib
  2303. *
  2304. * @api UINT | DrawDibRealize | This function realizes palette
  2305. * of the display context specified into the DrawDib context.
  2306. *
  2307. * @parm HDRAWDIB | hdd | Specifies a handle to a DrawDib context.
  2308. *
  2309. * @parm HDC | hdc | Specifies a handle to the display context containing
  2310. * the palette.
  2311. *
  2312. * @parm BOOL | fBackground | If set to a nonzero value,
  2313. * the selected palette is selected as a background palette.
  2314. * If this is set to zero and the device context is attached
  2315. * to a window, the logical palette is a foreground palette when
  2316. * the window has the input focus. (The device context is attached
  2317. * to a window if it was obtained by using the <f GetDC> function
  2318. * or if the window-class style is CS_OWNDC.)
  2319. *
  2320. * @rdesc Returns number of entries in the logical palette
  2321. * mapped to different values in the system palette. If
  2322. * an error occurs or no colors were updated, it returns zero.
  2323. *
  2324. * @comm This function should only be used to
  2325. * handle a <m WM_PALETTECHANGE> or <m WM_QUERYNEWPALETTE>
  2326. * message, or used in conjunction with the DDF_SAME_HDC flag
  2327. * to prepare a display context prior to calling <f DrawDibDraw>
  2328. * multiple times.
  2329. *
  2330. * @ex The following example shows how the function is used to
  2331. * handle a <m WM_PALETTECHANGE> or <m WM_QUERYNEWPALETTE>
  2332. * message: |
  2333. *
  2334. * case WM_PALETTECHANGE:
  2335. * if ((HWND)wParam == hwnd)
  2336. * break;
  2337. *
  2338. * case WM_QUERYNEWPALETTE:
  2339. * hdc = GetDC(hwnd);
  2340. *
  2341. * f = DrawDibRealize(hdd, hdc, FALSE) > 0;
  2342. *
  2343. * ReleaseDC(hwnd, hdc);
  2344. *
  2345. * if (f)
  2346. * InvalidateRect(hwnd, NULL, TRUE);
  2347. * break;
  2348. *
  2349. * @ex The following example shows using <f DrawDibRealize> use prior to
  2350. * calling <f DrawDibDraw> multiple times: |
  2351. *
  2352. * hdc = GetDC(hwnd);
  2353. * DrawDibRealize(hdd, hdc, fBackground);
  2354. * DrawDibDraw(hdd, hdc, ..........., DDF_SAME_DRAW|DDF_SAME_HDC);
  2355. * DrawDibDraw(hdd, hdc, ..........., DDF_SAME_DRAW|DDF_SAME_HDC);
  2356. * DrawDibDraw(hdd, hdc, ..........., DDF_SAME_DRAW|DDF_SAME_HDC);
  2357. * ReleaseDC(hwnd, hdc);
  2358. *
  2359. * @ex The following example shows using <f DrawDibRealize> with <f DDF_ANIMATE>
  2360. * and (f DrawDibChangePalette> to do palette animation |
  2361. *
  2362. * hdc = GetDC(hwnd);
  2363. * DrawDibBegin(hdd, ....., DDF_ANIMATE);
  2364. * DrawDibRealize(hdd, hdc, fBackground);
  2365. * DrawDibDraw(hdd, hdc, ...., DDF_SAME_DRAW|DDF_SAME_HDC);
  2366. * DrawDibChangePalette(hdd, ....);
  2367. * ReleaseDC(hwnd, hdc);
  2368. *
  2369. * @comm To draw an image mapped to another palette use <f DrawDibSetPalette>.
  2370. *
  2371. * To make <f DrawDibDraw> select its palette as a background palette
  2372. * use the DDF_BACKGROUNDPAL flag and not this function.
  2373. *
  2374. * While the DrawDib palette is selected into the display context,
  2375. * do not call <f DrawDibEnd>, <f DrawDibClose>, <f DrawDibBegin>, or
  2376. * <f DrawDibDraw> (with a different draw/format) on the same DrawDib
  2377. * context <p hdd>. These can free the selected palette
  2378. * while it is being used by your display context and cause
  2379. * a GDI error.
  2380. *
  2381. * @xref <f SelectPalette>
  2382. *
  2383. **************************************************************************/
  2384. UINT VFWAPI DrawDibRealize(HDRAWDIB hdd, HDC hdc, BOOL fBackground)
  2385. {
  2386. PDD pdd;
  2387. HPALETTE hpal;
  2388. UINT u;
  2389. if (hdc == NULL)
  2390. return 0;
  2391. if ((pdd = DrawDibLock(hdd)) == NULL)
  2392. return 0;
  2393. if (IsScreenDC(hdc))
  2394. pdd->ulFlags &= ~DDF_MEMORYDC;
  2395. else {
  2396. pdd->ulFlags |= DDF_MEMORYDC;
  2397. DPF(("Drawing to a memory DC"));
  2398. }
  2399. SetStretchBltMode(hdc, COLORONCOLOR);
  2400. //
  2401. // what palette should we realize
  2402. //
  2403. hpal = pdd->hpalDraw ? pdd->hpalDraw : pdd->hpal;
  2404. //
  2405. // if we dont have a palette, we have nothing to realize
  2406. // still call DrawDibPalChange though
  2407. //
  2408. if (hpal == NULL)
  2409. {
  2410. if (pdd->ulFlags & DDF_NEWPALETTE)
  2411. {
  2412. DrawDibPalChange(pdd, hdc, hpal);
  2413. pdd->ulFlags &= ~DDF_NEWPALETTE;
  2414. }
  2415. return 0;
  2416. }
  2417. // !!! There is a bug in GDI that will not map an identity palette 1-1 into
  2418. // !!! the system palette every time, which hoses us and makes it look like
  2419. // !!! dog spew. This ICKITY-ACKITY-OOP code will flush the palette and
  2420. // !!! prevent the bug... BUT it introduces another bug where if we are a
  2421. // !!! background app, we hose everybody else's palette but ours. So let's
  2422. // !!! live with the GDI bug. One other thing... attempting this fix will
  2423. // !!! cause the bug to repro more often than it would have if you had left
  2424. // !!! it alone, unless you do the fix JUST RIGHT! I don't trust myself
  2425. // !!! that much.
  2426. #if 0
  2427. if ((pdd->ulFlags & DDF_NEWPALETTE) && (pdd->ulFlags & DDF_IDENTITYPAL) &&
  2428. !fBackground)
  2429. {
  2430. //
  2431. // this will flush the palette clean to avoid a GDI BUG!!!
  2432. //
  2433. SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC);
  2434. SetSystemPaletteUse(hdc, SYSPAL_STATIC);
  2435. }
  2436. #endif
  2437. //
  2438. // select and realize it
  2439. //
  2440. SelectPalette(hdc, hpal, fBackground);
  2441. u = RealizePalette(hdc);
  2442. // !!! If two DrawDib instances share the same palette handle, the second
  2443. // one will not change any colours and u will be 0, and it will not stop
  2444. // decompressing to screen or recompute stuff for bitmaps when it goes
  2445. // into the background and it will get a messed up palette.
  2446. // !!! This is a known bug we don't care about
  2447. //
  2448. // this should be fixed by the hpalCopy stuff.
  2449. if (u > 0 || (pdd->ulFlags & DDF_NEWPALETTE))
  2450. {
  2451. pdd->ulFlags |= DDF_NEWPALETTE;
  2452. DrawDibPalChange(pdd, hdc, hpal);
  2453. pdd->ulFlags &= ~DDF_NEWPALETTE;
  2454. }
  2455. return u;
  2456. }
  2457. /**************************************************************************
  2458. * @doc EXTERNAL DrawDib VFW11
  2459. *
  2460. * @api LPVOID | DrawDibGetBuffer | This function returns the pointer
  2461. * to the DrawDib decompress buffer.
  2462. *
  2463. * @parm HDRAWDIB | hdd | Specifies a handle to a DrawDib context.
  2464. *
  2465. * @parm LPBITMAPINFOHEADER | lpbi | Specifies a pointer to a
  2466. * <t BITMAPINFOHEADER> structure.
  2467. *
  2468. * @parm DWORD | dwSize | Specifies the size of the buffer pointed to by <p lpbi>
  2469. *
  2470. * @parm DWORD | dwFlags | Set to zero.
  2471. *
  2472. * @rdesc Returns a pointer to the buffer used by DrawDib for decompression,
  2473. * or NULL if no buffer is used. If <p lpbi> is not NULL,
  2474. * it is filled in with a copy of the <t BITMAPINFOHEADER>
  2475. * describing the buffer.
  2476. *
  2477. * The structure for <p lpbi> must have room for a
  2478. * <t BITMAPINFOHEADER> and 256 colors.
  2479. *
  2480. **************************************************************************/
  2481. LPVOID VFWAPI DrawDibGetBuffer(HDRAWDIB hdd, LPBITMAPINFOHEADER lpbi, DWORD dwSize, DWORD dwFlags)
  2482. {
  2483. PDD pdd;
  2484. if ((pdd = DrawDibLock(hdd)) == NULL)
  2485. return NULL;
  2486. if (lpbi)
  2487. {
  2488. hmemcpy(lpbi, &pdd->biBuffer,
  2489. min(dwSize, pdd->biBuffer.biSize + 256*sizeof(RGBQUAD)));
  2490. }
  2491. return pdd->pbBuffer;
  2492. }
  2493. LPVOID VFWAPI DrawDibGetBufferOld(HDRAWDIB hdd, LPBITMAPINFOHEADER lpbi)
  2494. {
  2495. return DrawDibGetBuffer(hdd, lpbi, sizeof(BITMAPINFOHEADER), 0);
  2496. }
  2497. /**************************************************************************
  2498. * @doc EXTERNAL DrawDibStart
  2499. *
  2500. * @api BOOL | DrawDibStart | This function prepares a DrawDib
  2501. * context for streaming playback.
  2502. *
  2503. * @parm HDRAWDIB | hdd | Specifies a handle to a DrawDib context.
  2504. *
  2505. * @parm LONG | rate | Specifies the playback rate (in microseconds per frame).
  2506. *
  2507. * @rdesc Returns TRUE if successful.
  2508. *
  2509. * @xref <f DrawDibStop>
  2510. *
  2511. **************************************************************************/
  2512. BOOL VFWAPI DrawDibStart(HDRAWDIB hdd, DWORD rate)
  2513. {
  2514. PDD pdd;
  2515. if ((pdd = DrawDibLock(hdd)) == NULL)
  2516. return FALSE;
  2517. if (pdd->hic == (HIC)-1)
  2518. return FALSE;
  2519. // if the codec does not care about this message dont fail.
  2520. if (pdd->hic != NULL)
  2521. ICSendMessage(pdd->hic, ICM_DRAW_START, rate, 0);
  2522. return TRUE;
  2523. }
  2524. /**************************************************************************
  2525. * @doc EXTERNAL DrawDibStop
  2526. *
  2527. * @api BOOL | DrawDibStop | This function frees the resources
  2528. * used by a DrawDib context for streaming playback.
  2529. *
  2530. * @parm HDRAWDIB | hdd | Specifies a handle to a DrawDib context.
  2531. *
  2532. * @rdesc Returns TRUE if successful.
  2533. *
  2534. * @xref <f DrawDibStart>
  2535. *
  2536. **************************************************************************/
  2537. BOOL VFWAPI DrawDibStop(HDRAWDIB hdd)
  2538. {
  2539. PDD pdd;
  2540. if ((pdd = DrawDibLock(hdd)) == NULL)
  2541. return FALSE;
  2542. if (pdd->hic == (HIC)-1)
  2543. return FALSE;
  2544. if (pdd->hic != NULL)
  2545. ICSendMessage(pdd->hic, ICM_DRAW_STOP, 0, 0);
  2546. return TRUE;
  2547. }
  2548. /**************************************************************************
  2549. * @doc EXTERNAL DrawDib
  2550. *
  2551. * @api BOOL | DrawDibUpdate | This macro updates the last
  2552. * buffered frame drawn.
  2553. *
  2554. * @parm HDRAWDIB | hdd | Specifies a handle to a DrawDib context.
  2555. *
  2556. * @parm HDC | hdc | Specifies a handle to the display context.
  2557. *
  2558. * @parm int | xDst | Specifies the x-coordinate of the upper left-corner
  2559. * of the destination rectangle. Coordinates are specified
  2560. * in MM_TEXT client coordinates.
  2561. *
  2562. * @parm int | yDst | Specifies the y-coordinate of the upper-left corner
  2563. * of the destination rectangle. Coordinates are specified
  2564. * in MM_TEXT client coordinates.
  2565. *
  2566. * @rdesc Returns TRUE if successful.
  2567. *
  2568. * @comm This macro uses <f DrawDibDraw> to send the DDF_UPDATE flag
  2569. * to the DrawDib context.
  2570. *
  2571. **************************************************************************/
  2572. /**************************************************************************
  2573. * @doc EXTERNAL DrawDib
  2574. *
  2575. * @api BOOL | DrawDibDraw | This function draws a device independent
  2576. * bitmap to the screen.
  2577. *
  2578. * @parm HDRAWDIB | hdd | Specifies a handle to a DrawDib context.
  2579. *
  2580. * @parm HDC | hdc | Specifies a handle to the display context.
  2581. *
  2582. * @parm int | xDst | Specifies the x-coordinate of the upper left-corner
  2583. * of the destination rectangle. Coordinates are specified
  2584. * in MM_TEXT client coordinates.
  2585. *
  2586. * @parm int | yDst | Specifies the y-coordinate of the upper-left corner
  2587. * of the destination rectangle. Coordinates are specified
  2588. * in MM_TEXT client coordinates.
  2589. *
  2590. * @parm int | dxDst | Specifies the width of the destination rectangle.
  2591. * The width is specified in MM_TEXT client coordinates. If
  2592. * <p dxDst> is -1, the width of the bitmap is used.
  2593. *
  2594. * @parm int | dyDst | Specifies the height of the destination rectangle.
  2595. * The height is specified in MM_TEXT client coordinates. If
  2596. * <p dyDst> is -1, the height of the bitmap is used.
  2597. *
  2598. * @parm LPBITMAPINFOHEADER | lpbi | Specifies a pointer to the
  2599. * <t BITMAPINFOHEADER> structure for the bitmap. The color
  2600. * table for the DIB follows the format information. The
  2601. * height specified for the DIB in the structure must be
  2602. * positive (that is, this function will not draw inverted DIBs).
  2603. *
  2604. * @parm LPVOID | lpBits | Specifies a pointer to the buffer
  2605. * containing the bitmap bits.
  2606. *
  2607. * @parm int | xSrc | Specifies the x-coordinate of the upper-left corner
  2608. * source rectangle. Coordinates are specified in pixels.
  2609. * The coordinates (0,0) represent the upper left corner
  2610. * of the bitmap.
  2611. *
  2612. * @parm int | ySrc | Specifies the y-coordinate of the upper left corner
  2613. * source rectangle. Coordinates are specified in pixels.
  2614. * The coordinates (0,0) represent the upper left corner
  2615. * of the bitmap.
  2616. *
  2617. * @parm int | dxSrc | Specifies the width of the source rectangle.
  2618. * The width is specified in pixels.
  2619. *
  2620. * @parm int | dySrc | Specifies the height of the source rectangle.
  2621. * The height is specified in pixels.
  2622. *
  2623. * @parm UINT | wFlags | Specifies any applicable flags for drawing.
  2624. * The following flags are defined:
  2625. *
  2626. * @flag DDF_UPDATE | Indicates the last buffered bitmap is to be redrawn.
  2627. * If drawing fails with this flag, a buffered image is not available
  2628. * and a new image needs to be specified before the display is updated.
  2629. *
  2630. * @flag DDF_SAME_HDC | Assumes the handle to the display context
  2631. * is already specified. When this flag is used,
  2632. * DrawDib also assumes the correct palette has already been
  2633. * realized into the device context (possibly by
  2634. * <f DrawDibRealize>).
  2635. *
  2636. * @flag DDF_SAME_DRAW | Uses the drawing parameters previously
  2637. * specified for this function. Use this flag only
  2638. * if <p lpbi>, <p dxDst>, <p dyDst>, <p dxSrc>, and <p dySrc>
  2639. * have not changed since using <f DrawDibDraw> or <f DrawDibBegin>.
  2640. * Normally <f DrawDibDraw> checks the parameters, and if they
  2641. * have changed, <f DrawDibBegin> prepares the DrawDib context
  2642. * for drawing.
  2643. *
  2644. * @flag DDF_DONTDRAW | Indicates the frame is not to be drawn and will
  2645. * later be recalled with the <f DDF_UPDATE> flag. DrawDib does
  2646. * not buffer an image if an offscreen buffer does not exist.
  2647. * In this case, DDF_DONTDRAW draws the frame to the screen and
  2648. * the subsequent use of DDF_UPDATE fails. DrawDib does
  2649. * guarantee that the following will
  2650. * always draw "image" B to the screen.
  2651. *
  2652. * DrawDibDraw(hdd, ..., lpbiA, ..., DDF_DONTDRAW);
  2653. * DrawDibDraw(hdd, ..., lpbiB, ..., DDF_DONTDRAW);
  2654. * DrawDibDraw(hdd, ..., NULL, ..., DDF_UPDATE);
  2655. *
  2656. * The DDF_UPDATE and DDF_DONTDRAW flags are used
  2657. * together to create composite images
  2658. * offscreen, and then do a final update when finished.
  2659. *
  2660. * @flag DDF_HURRYUP | Indicates the data does not have to
  2661. * drawn (that is, it can be dropped) and the DDF_UPDATE flags will
  2662. * not be used to recall this information. DrawDib looks at
  2663. * this data only if it is required to build the next frame, otherwise
  2664. * the data is ignored.
  2665. *
  2666. * This flag is usually used to resynchronize video and audio. When
  2667. * resynchronizing data, applications should send the image
  2668. * with this flag in case the driver needs to
  2669. * to buffer the frame to decompress subsequent frames.
  2670. *
  2671. * @flag DDF_UPDATE | Indicates the last buffered bitmap is to be redrawn.
  2672. * If drawing fails with this flag, a buffered image is not available
  2673. * and a new image needs to be specified before the display is updated.
  2674. * For more information, see the <f DDF_DONTDRAW> flag.
  2675. *
  2676. * @flag DDF_BACKGROUNDPAL | Realizes the palette used for drawing
  2677. * in the background leaving the actual palette used for display
  2678. * unchanged. (This flag is valid only if DDF_SAME_HDC is not set.)
  2679. *
  2680. * @flag DDF_HALFTONE | Always dithers the DIB to a standard palette
  2681. * regardless of the palette of the DIB. If using <f DrawDibBegin>,
  2682. * set this flag for it rather than <f DrawDibDraw>.
  2683. *
  2684. * @flag DDF_NOTKEYFRAME | Indicates the DIB data is not a key frame.
  2685. *
  2686. * @flag DDF_HURRYUP | Indicates the DIB data does not have to
  2687. * drawn (that is, it can be dropped). This flag is usually
  2688. * used to resynchronize the video to the audio. When
  2689. * resynchronizing data, applications should send the image
  2690. * with this flag in case the driver needs to
  2691. * to buffer the frame to decompress subsequent frames.
  2692. *
  2693. * @rdesc Returns TRUE if successful.
  2694. *
  2695. * @comm This function replaces <f StretchDIBits> and supports
  2696. * decompression of bitmaps by installable compressors.
  2697. * This function dithers true color bitmaps properly on
  2698. * 8-bit display devices.
  2699. *
  2700. **************************************************************************/
  2701. BOOL VFWAPI DrawDibDraw(HDRAWDIB hdd,
  2702. HDC hdc,
  2703. int xDst,
  2704. int yDst,
  2705. int dxDst,
  2706. int dyDst,
  2707. LPBITMAPINFOHEADER lpbi,
  2708. LPVOID lpBits,
  2709. int xSrc,
  2710. int ySrc,
  2711. int dxSrc,
  2712. int dySrc,
  2713. UINT wFlags)
  2714. {
  2715. PDD pdd;
  2716. BOOL f;
  2717. RECT rc;
  2718. DWORD icFlags;
  2719. LRESULT dw;
  2720. if ((pdd = DrawDibLock(hdd)) == NULL)
  2721. return FALSE;
  2722. if (hdc == NULL)
  2723. return FALSE;
  2724. if (wFlags & DDF_UPDATE)
  2725. {
  2726. lpbi = pdd->lpbi;
  2727. dxDst = pdd->dxDst;
  2728. dyDst = pdd->dyDst;
  2729. dxSrc = pdd->dxSrc;
  2730. dySrc = pdd->dySrc;
  2731. }
  2732. else
  2733. {
  2734. if (lpbi == NULL)
  2735. return FALSE;
  2736. //
  2737. // fill in defaults.
  2738. //
  2739. if (dxSrc < 0)
  2740. dxSrc = (int)lpbi->biWidth - xSrc;
  2741. if (dySrc < 0)
  2742. dySrc = (int)lpbi->biHeight - ySrc;
  2743. if (dxDst < 0)
  2744. dxDst = dxSrc;
  2745. if (dyDst < 0)
  2746. dyDst = dySrc;
  2747. }
  2748. #ifdef DEBUG_RETAIL
  2749. if (xSrc < 0 ||
  2750. ySrc < 0 ||
  2751. dxSrc <= 0 ||
  2752. dySrc <= 0 ||
  2753. xSrc + dxSrc > (int)lpbi->biWidth ||
  2754. ySrc + dySrc > (int)lpbi->biHeight)
  2755. {
  2756. RPF(("DrawDibBegin(): bad source parameters [%d %d %d %d]", xSrc, ySrc, dxSrc, dySrc));
  2757. // return 0; // see what happens.
  2758. }
  2759. #endif
  2760. if (dxSrc == 0 || dySrc == 0) // !!! || dxDst == 0 || dyDst == 0)
  2761. return FALSE;
  2762. //
  2763. // check and make sure the params of the draw has not changed
  2764. //
  2765. if (!(wFlags & (DDF_SAME_DRAW|DDF_UPDATE)) &&
  2766. !(DibEq(pdd->lpbi, lpbi) &&
  2767. !(((UINT)pdd->ulFlags ^ wFlags) & DDF_HALFTONE) &&
  2768. pdd->dxDst == dxDst &&
  2769. pdd->dyDst == dyDst &&
  2770. pdd->dxSrc == dxSrc &&
  2771. pdd->dySrc == dySrc))
  2772. {
  2773. wFlags &= ~(DDF_UPDATE | DDF_FULLSCREEN);
  2774. if (!DrawDibBegin(hdd, hdc, dxDst, dyDst, lpbi, dxSrc, dySrc, wFlags))
  2775. return FALSE;
  2776. }
  2777. TIMEINC(); // should we include DibEq?
  2778. TIMESTART(timeDraw);
  2779. // convert to DIB cordinates
  2780. ySrc = (int)pdd->lpbi->biHeight - (ySrc + dySrc);
  2781. //
  2782. // Initialize the DC: We need to realize the palette if we are not
  2783. // guarenteed to be using the same DC as before, if we've been told we
  2784. // have a new palette, or if we are mapping to somebody else's palette.
  2785. // The owner of the palette could be changing it on us all the time or
  2786. // doing who knows what, so to be safe we will realize it every frame.
  2787. // If nothing's changed, this should be a really cheap operation, and
  2788. // it doesn't appear to be causing any palette fights that end in somebody
  2789. // getting hurt. This is required for Magic School Bus, and PageMaster,
  2790. // at the very least. (WIN95B 12204 and 9637)
  2791. //
  2792. if (!(wFlags & DDF_SAME_HDC) || (pdd->ulFlags & DDF_NEWPALETTE) ||
  2793. pdd->hpalDraw)
  2794. {
  2795. //
  2796. // image will be totally clipped anyway
  2797. //
  2798. if (GetClipBox(hdc, &rc) == NULLREGION)
  2799. {
  2800. wFlags |= DDF_DONTDRAW;
  2801. }
  2802. //
  2803. // select and realize the palette.
  2804. //
  2805. // NOTE you must unselect this thing, dont return early
  2806. //
  2807. DrawDibRealize(hdd, hdc, (wFlags & DDF_BACKGROUNDPAL) != 0);
  2808. }
  2809. #ifdef USE_DCI
  2810. //
  2811. // do a clipping check
  2812. //
  2813. if (pdd->ulFlags & DDF_CLIPCHECK)
  2814. {
  2815. RECT rc;
  2816. if (!(pdd->ulFlags & DDF_CLIPPED) &&
  2817. (pdd->iDecompress == DECOMPRESS_SCREEN) && // (pdd->ulFlags & DDF_SCREENX) &&
  2818. (wFlags & (DDF_PREROLL|DDF_DONTDRAW)))
  2819. {
  2820. DPF(("DDF_DONTDRAW while decompressing to screen, staying clipped"));
  2821. }
  2822. if ((pdd->ulFlags & DDF_MEMORYDC) ||
  2823. GetClipBox(hdc, &rc) != SIMPLEREGION ||
  2824. xDst < rc.left ||
  2825. yDst < rc.top ||
  2826. xDst + dxDst > rc.right ||
  2827. yDst + dyDst > rc.bottom ||
  2828. (wFlags & (DDF_PREROLL|DDF_DONTDRAW)) ||
  2829. (gfDisplayHasBrokenRasters &&
  2830. (DCNotAligned(hdc, xDst) || gwScreenBitDepth == 24)))
  2831. // Note: if we're on a 24-bit display with broken rasters, we don't
  2832. // decompress to the screen even if the rectangle is aligned,
  2833. // because it's just too easy for somebody to try to write out
  2834. // a whole pixel in one gulp and hit the 64K boundary.
  2835. {
  2836. //
  2837. // we are clipped, check for a change.
  2838. //
  2839. if (!(pdd->ulFlags & DDF_CLIPPED))
  2840. {
  2841. pdd->ulFlags |= DDF_CLIPPED;
  2842. DrawDibClipChange(pdd, wFlags);
  2843. }
  2844. }
  2845. else
  2846. {
  2847. // !!!
  2848. // check for the screen width changing, Chicago
  2849. // currently can't change the bitdepth so don't
  2850. // worry about that right now.
  2851. //
  2852. if (GetSystemMetrics(SM_CXSCREEN) != (int)gwScreenWidth)
  2853. {
  2854. pdd->ulFlags |= DDF_CLIPPED;
  2855. DrawDibClipChange(pdd, wFlags);
  2856. DrawDibInit();
  2857. }
  2858. //
  2859. // we are now unclipped, check for a change
  2860. //
  2861. if ((pdd->ulFlags & DDF_CLIPPED) && !(pdd->ulFlags & DDF_UPDATE))
  2862. {
  2863. #ifdef DEBUG
  2864. if (DCNotAligned(hdc, xDst))
  2865. DPF(("Warning draw is not aligned on 4 pixel boundary"));
  2866. #endif
  2867. pdd->ulFlags &= ~DDF_CLIPPED;
  2868. DrawDibClipChange(pdd, wFlags);
  2869. }
  2870. }
  2871. DPF(("Clip Box: %d %d %d %d Dest: %d %d %d %d", rc.left, rc.top, rc.right, rc.bottom, xDst, yDst, xDst + dxDst, yDst + dyDst));
  2872. }
  2873. #endif //_WIN32
  2874. if (pdd->ulFlags & DDF_WANTKEY)
  2875. {
  2876. //
  2877. // Adobe hack: If the DDF_UPDATE flag is on in our internal
  2878. // flags, that means we've just been getting a bunch of frames
  2879. // with the DONTDRAW flag set. In that case, if this frame
  2880. // immediately after those frames is marked as a key frame
  2881. // we assume that it might not be a key frame and refrain from
  2882. // switching immediately to decompressing to screen.
  2883. //
  2884. if (!(wFlags & DDF_NOTKEYFRAME) && !(pdd->ulFlags & DDF_UPDATE))
  2885. {
  2886. pdd->ulFlags &= ~DDF_WANTKEY;
  2887. DrawDibClipChange(pdd, wFlags);
  2888. }
  2889. }
  2890. //
  2891. // if update is set re-draw what ever we drew last time
  2892. //
  2893. if (wFlags & DDF_UPDATE)
  2894. {
  2895. if (pdd->hic == (HIC)-1 || (pdd->ulFlags & DDF_DIRTY))
  2896. {
  2897. f = FALSE;
  2898. DPF(("Can't update: no decompress buffer!"));
  2899. goto exit;
  2900. }
  2901. if (pdd->hic)
  2902. {
  2903. if (pdd->ulFlags & DDF_UPDATE)
  2904. {
  2905. goto redraw;
  2906. }
  2907. lpbi = &pdd->biBuffer;
  2908. lpBits = pdd->pbBuffer;
  2909. //!!! set the source right.
  2910. if ((pdd->ulFlags & DDF_XLATSOURCE))
  2911. {
  2912. dxSrc = MulDiv(dxSrc, abs((int)pdd->biBuffer.biWidth), (int)pdd->lpbi->biWidth);
  2913. dySrc = MulDiv(dySrc, abs((int)pdd->biBuffer.biHeight), (int)pdd->lpbi->biHeight);
  2914. xSrc = MulDiv(xSrc, abs((int)pdd->biBuffer.biWidth), (int)pdd->lpbi->biWidth);
  2915. ySrc = MulDiv(ySrc, abs((int)pdd->biBuffer.biHeight), (int)pdd->lpbi->biHeight);
  2916. }
  2917. }
  2918. if (pdd->ulFlags & DDF_STRETCH)
  2919. {
  2920. lpbi = &pdd->biStretch;
  2921. lpBits = pdd->pbStretch;
  2922. dxSrc = dxDst;
  2923. dySrc = dyDst;
  2924. xSrc = 0;
  2925. ySrc = 0;
  2926. }
  2927. if (pdd->ulFlags & DDF_DITHER)
  2928. {
  2929. lpBits = pdd->pbDither;
  2930. xSrc = 0;
  2931. ySrc = 0;
  2932. }
  2933. if (pdd->lpDIBSection != NULL)
  2934. goto bltDIB;
  2935. if (pdd->hbmDraw && (pdd->ulFlags & DDF_BITMAP))
  2936. goto bltit;
  2937. if (lpBits == NULL)
  2938. {
  2939. f = FALSE; // no buffer, can't update....
  2940. goto exit;
  2941. }
  2942. goto drawit;
  2943. }
  2944. //
  2945. // default for bits pointerdefault
  2946. //
  2947. if (lpBits == NULL)
  2948. lpBits = (LPBYTE)lpbi+(int)lpbi->biSize + (int)lpbi->biClrUsed * sizeof(RGBQUAD);
  2949. //
  2950. // call any decompressor if needed
  2951. //
  2952. if (pdd->hic)
  2953. {
  2954. if (pdd->hic == (HIC)-1)
  2955. {
  2956. f = FALSE;
  2957. goto exit;
  2958. }
  2959. #ifdef USE_DCI // exclude all code that references biscreen
  2960. if (pdd->iDecompress == DECOMPRESS_SCREEN) // pdd->ulFlags & DDF_SCREENX
  2961. {
  2962. DCIRVAL DCIResult;
  2963. int xDstC = xDst, yDstC = yDst;
  2964. POINT pt;
  2965. pt.x = xDst; pt.y = yDst;
  2966. LPtoDP(hdc, &pt, 1);
  2967. xDst = pt.x;
  2968. yDst = pt.y;
  2969. #ifdef _WIN32
  2970. GetDCOrgEx(hdc, &pt);
  2971. xDst += pt.x;
  2972. yDst += pt.y;
  2973. #else
  2974. DWORD dwOrg;
  2975. dwOrg = GetDCOrg(hdc);
  2976. xDst += LOWORD(dwOrg);
  2977. yDst += HIWORD(dwOrg);
  2978. #endif
  2979. //
  2980. // we are decompressing to the screen not the buffer, so
  2981. // the buffer is dirty now
  2982. //
  2983. pdd->ulFlags |= DDF_DIRTY;
  2984. #define USEGETCLIPBOXEARLY
  2985. // IF we call GetClipBox AFTER doing DCIBeginAccess we end up with
  2986. // EXTREMELY slow drawing.
  2987. #ifdef USEGETCLIPBOXEARLY
  2988. // To see whether or not decompressing to the screen was OK, we
  2989. // called GetClipBox. But that was a long time ago, and as of
  2990. // Chicago, things could have changed since then. We call 32 bit
  2991. // code in the meantime, which lets other 16 bit code run, like USER
  2992. // which might clip the window with another window or worse yet,
  2993. // move this window off the screen so decompressing to the screen
  2994. // will crash! Calling GetClipBox way back then was just not valid.
  2995. // We have to call it again now. I'm not removing the call way back
  2996. // then because touching this code is known to ruin the stability
  2997. // of the universe. (WIN95 BUG#20754 and WIN95B BUG#8374)
  2998. // WARNING: xDst, yDst are in SCREEN co-ords now. Use the client
  2999. // ones.
  3000. if (GetClipBox(hdc, &rc) != SIMPLEREGION ||
  3001. xDstC < rc.left ||
  3002. yDstC < rc.top ||
  3003. xDstC + dxDst > rc.right ||
  3004. yDstC + dyDst > rc.bottom) {
  3005. dw = ICERR_OK;
  3006. f = TRUE;
  3007. goto exit;
  3008. }
  3009. #endif
  3010. DCIResult = DCIBeginAccess(pdci, xDst, yDst, dxDst, dyDst);
  3011. //
  3012. // if DCIBeginAccess fails we are in the background, and should
  3013. // not draw.
  3014. //
  3015. if (DCIResult < 0)
  3016. {
  3017. DPF(("DCIBeginAccess returns %d\n", DCIResult));
  3018. f = TRUE; //!!! handle more error values!
  3019. goto exit;
  3020. }
  3021. else if (DCIResult > 0)
  3022. {
  3023. if (DCIResult & DCI_STATUS_POINTERCHANGED)
  3024. {
  3025. #ifdef _WIN32
  3026. if (pdci->dwDCICaps & DCI_1632_ACCESS)
  3027. {
  3028. //
  3029. // make sure the pointer is valid.
  3030. //
  3031. if (pdci->dwOffSurface >= 0x10000)
  3032. {
  3033. DPF(("DCI Surface can't be supported: offset >64K"));
  3034. lpScreen = NULL;
  3035. }
  3036. else
  3037. lpScreen = (LPVOID)MAKELONG((WORD)pdci->dwOffSurface, pdci->wSelSurface);
  3038. }
  3039. else
  3040. {
  3041. lpScreen = (LPVOID) pdci->dwOffSurface;
  3042. }
  3043. #else
  3044. //
  3045. // make sure the pointer is valid.
  3046. //
  3047. if (pdci->dwOffSurface >= 0x10000)
  3048. {
  3049. DPF(("DCI Surface can't be supported: offset >64K"));
  3050. lpScreen = NULL;
  3051. }
  3052. else
  3053. lpScreen = (LPVOID)MAKELP(pdci->wSelSurface,pdci->dwOffSurface);
  3054. #endif
  3055. }
  3056. if (DCIResult & (DCI_STATUS_STRIDECHANGED |
  3057. DCI_STATUS_FORMATCHANGED |
  3058. DCI_STATUS_SURFACEINFOCHANGED |
  3059. DCI_STATUS_CHROMAKEYCHANGED))
  3060. {
  3061. DPF(("Unhandled DCI Flags! (%04X)", DCIResult));
  3062. }
  3063. if (DCIResult & DCI_STATUS_WASSTILLDRAWING)
  3064. {
  3065. DPF(("DCI still drawing!?!", DCIResult));
  3066. f = TRUE; //!!!
  3067. goto EndAccess;
  3068. }
  3069. }
  3070. if (lpScreen == NULL)
  3071. {
  3072. DPF(("DCI pointer is NULL when about to draw!"));
  3073. f = FALSE;
  3074. goto EndAccess;
  3075. }
  3076. //convert to DIB corrds.
  3077. yDst = (int)pdci->dwHeight - (yDst + dyDst);
  3078. TIMESTART(timeDecompress);
  3079. icFlags = 0;
  3080. if (wFlags & DDF_HURRYUP)
  3081. icFlags |= ICDECOMPRESS_HURRYUP;
  3082. if (wFlags & DDF_NOTKEYFRAME)
  3083. icFlags |= ICDECOMPRESS_NOTKEYFRAME;
  3084. DPF2(("Drawing To Screen: %d %d %d %d", xDst, yDst, xDst + dxDst, yDst + dyDst));
  3085. #ifdef USEGETCLIPBOXLATE
  3086. // To see whether or not decompressing to the screen was OK, we
  3087. // called GetClipBox. But that was a long time ago, and as of
  3088. // Chicago, things could have changed since then. We call 32 bit
  3089. // code in the meantime, which lets other 16 bit code run, like USER
  3090. // which might clip the window with another window or worse yet,
  3091. // move this window off the screen so decompressing to the screen
  3092. // will crash! Calling GetClipBox way back then was just not valid.
  3093. // We have to call it again now. I'm not removing the call way back
  3094. // then because touching this code is known to ruin the stability
  3095. // of the universe. (WIN95 BUG#20754 and WIN95B BUG#8374)
  3096. // WARNING: xDst, yDst are in SCREEN co-ords now. Use the client
  3097. // ones.
  3098. if (GetClipBox(hdc, &rc) != SIMPLEREGION ||
  3099. xDstC < rc.left ||
  3100. yDstC < rc.top ||
  3101. xDstC + dxDst > rc.right ||
  3102. yDstC + dyDst > rc.bottom) {
  3103. dw = ICERR_OK;
  3104. }
  3105. else
  3106. #endif
  3107. {
  3108. dw = ICDecompressEx(pdd->hic, icFlags,
  3109. lpbi, lpBits, xSrc, ySrc, dxSrc, dySrc,
  3110. (LPBITMAPINFOHEADER) &biScreen, lpScreen,
  3111. xDst, yDst, dxDst, dyDst);
  3112. }
  3113. if (dw == ICERR_DONTDRAW)
  3114. dw = ICERR_OK;
  3115. f = (dw == ICERR_OK);
  3116. TIMEEND(timeDecompress);
  3117. EndAccess:
  3118. DCIEndAccess(pdci);
  3119. goto exit;
  3120. }
  3121. else
  3122. #endif // biscreen references
  3123. {
  3124. //
  3125. // if the offscreen buffer is dirty, only a key frame will
  3126. // clean our soul.
  3127. //
  3128. if (pdd->ulFlags & DDF_DIRTY)
  3129. {
  3130. if (wFlags & DDF_NOTKEYFRAME)
  3131. {
  3132. //!!! playing files with no key frames we will get into
  3133. //a state where we will never draw a frame ever again.
  3134. //we need a punt count?
  3135. DPF(("punt frame"));
  3136. f = TRUE;
  3137. goto exit;
  3138. }
  3139. else // if (!(wFlags & DDF_HURRYUP))
  3140. {
  3141. pdd->ulFlags &= ~DDF_DIRTY;
  3142. }
  3143. }
  3144. TIMESTART(timeDecompress);
  3145. icFlags = 0;
  3146. if (wFlags & DDF_HURRYUP)
  3147. icFlags |= ICDECOMPRESS_HURRYUP;
  3148. if (wFlags & DDF_NOTKEYFRAME)
  3149. icFlags |= ICDECOMPRESS_NOTKEYFRAME;
  3150. if (pdd->lpDIBSection != 0)
  3151. {
  3152. dw = ICDecompress(pdd->hic, icFlags, lpbi, lpBits, &pdd->biBuffer, pdd->pbBuffer);
  3153. }
  3154. else if (pdd->iDecompress == DECOMPRESS_BITMAP) //pdd->ulFlags & DDF_BITMAPX
  3155. {
  3156. //!!! should we check FASTTEMPORALD?
  3157. if (pdd->ulFlags & DDF_HUGEBITMAP)
  3158. HugeToFlat(pdd->pbBitmap,pdd->biBitmap.biSizeImage,pdd->biBitmap.biYPelsPerMeter);
  3159. #ifdef _WIN32
  3160. // Win32: still use the decomp buffer, then SetBitmapBits
  3161. dw = ICDecompress(pdd->hic, icFlags, lpbi, lpBits, &pdd->biBitmap, pdd->pbBuffer);
  3162. SetBitmapBits(pdd->hbmDraw, pdd->biBitmap.biSizeImage, pdd->pbBuffer);
  3163. #else
  3164. dw = ICDecompress(pdd->hic, icFlags, lpbi, lpBits, &pdd->biBitmap, pdd->pbBitmap);
  3165. #endif
  3166. if (pdd->ulFlags & DDF_HUGEBITMAP)
  3167. FlatToHuge(pdd->pbBitmap,pdd->biBitmap.biSizeImage,pdd->biBitmap.biYPelsPerMeter);
  3168. }
  3169. else
  3170. {
  3171. dw = ICDecompress(pdd->hic, icFlags, lpbi, lpBits, &pdd->biBuffer, pdd->pbBuffer);
  3172. }
  3173. TIMEEND(timeDecompress);
  3174. FlushBuffer();
  3175. if (dw == ICERR_DONTDRAW) {
  3176. // Decompressor doesn't want us to draw, for some reason....
  3177. wFlags |= DDF_DONTDRAW;
  3178. } else if (dw != 0) {
  3179. f = FALSE;
  3180. DPF(("Error %ld from decompressor!\n", dw));
  3181. goto exit;
  3182. }
  3183. }
  3184. //
  3185. // if don't draw is set we just need to decompress
  3186. //
  3187. if (wFlags & (DDF_DONTDRAW|DDF_HURRYUP))
  3188. {
  3189. f = TRUE;
  3190. pdd->ulFlags |= DDF_UPDATE|DDF_DONTDRAW; // make sure update knows what to do
  3191. goto exit;
  3192. }
  3193. #ifndef DAYTONA
  3194. // this does not work on Daytona (because the biSizeImage is confused?)
  3195. // but in any case it's not clear that a delta draw from client side is a
  3196. // win over a DIBSection blt from server side.
  3197. //
  3198. // draw RLE delta's to the screen even when we are buffering,
  3199. // as long as we're not stretching, dithering or using a memory DC.
  3200. // Drawing RLE's to a memory DC won't work in GDI.
  3201. // I will also refuse to draw RLE directly if we are using a
  3202. // decompressor (pdd->hic). I do this for no good reason other than
  3203. // it fixes Win95 bug 24412
  3204. //
  3205. if (!(pdd->ulFlags & (DDF_MEMORYDC|DDF_DONTDRAW|DDF_STRETCH|DDF_DITHER))
  3206. && lpbi->biCompression == BI_RLE8 &&
  3207. (dxDst == dxSrc) && (dyDst == dySrc) &&
  3208. lpbi->biSizeImage != pdd->biBuffer.biSizeImage &&
  3209. !(pdd->hic))
  3210. {
  3211. pdd->ulFlags |= DDF_UPDATE; // make sure update knows what to do
  3212. pdd->biDraw.biCompression = BI_RLE8;
  3213. goto drawit;
  3214. }
  3215. #endif
  3216. redraw:
  3217. pdd->ulFlags &= ~(DDF_UPDATE|DDF_DONTDRAW);
  3218. if ((pdd->ulFlags & DDF_XLATSOURCE))
  3219. {
  3220. dxSrc = MulDiv(dxSrc, abs((int)pdd->biBuffer.biWidth), (int)pdd->lpbi->biWidth);
  3221. dySrc = MulDiv(dySrc, abs((int)pdd->biBuffer.biHeight), (int)pdd->lpbi->biHeight);
  3222. xSrc = MulDiv(xSrc, abs((int)pdd->biBuffer.biWidth), (int)pdd->lpbi->biWidth);
  3223. ySrc = MulDiv(ySrc, abs((int)pdd->biBuffer.biHeight), (int)pdd->lpbi->biHeight);
  3224. }
  3225. lpbi = &pdd->biBuffer;
  3226. lpBits = pdd->pbBuffer;
  3227. pdd->biDraw.biCompression = pdd->biBuffer.biCompression;
  3228. }
  3229. else
  3230. {
  3231. // if we are using DIB Sections, and there is no decompression,
  3232. // dither or stretch step, then we need to explicitly copy the data
  3233. // into the dib section.
  3234. // maybe with the revised CreateDIBSection we could map the existing
  3235. // read buffer and avoid this step
  3236. if (pdd->lpDIBSection && ((pdd->ulFlags & (DDF_STRETCH|DDF_DITHER)) == 0)) {
  3237. // Include time taken here as 'stretching'.
  3238. // Really, though, we shouldn't be using DIB Sections in this case.
  3239. TIMESTART(timeStretch);
  3240. if (lpbi->biCompression == BI_RGB) {
  3241. lpbi->biSizeImage = DIBSIZEIMAGE(*lpbi);
  3242. }
  3243. hmemcpy(pdd->lpDIBSection, lpBits, lpbi->biSizeImage);
  3244. TIMEEND(timeStretch);
  3245. }
  3246. //
  3247. // when directly drawing RLE data we cant hurry
  3248. //
  3249. if (pdd->lpbi->biCompression == BI_RLE8)
  3250. wFlags &= ~DDF_HURRYUP;
  3251. //
  3252. // if don't draw is set we just need to stretch/dither
  3253. //
  3254. if (wFlags & DDF_HURRYUP)
  3255. {
  3256. f = TRUE;
  3257. pdd->ulFlags |= DDF_DIRTY;
  3258. goto exit;
  3259. }
  3260. pdd->ulFlags &= ~DDF_DIRTY;
  3261. pdd->biDraw.biCompression = lpbi->biCompression;
  3262. }
  3263. if (pdd->biDraw.biCompression == BI_RGB &&
  3264. (pdd->ulFlags & (DDF_DITHER|DDF_STRETCH)))
  3265. {
  3266. if (pdd->ulFlags & DDF_STRETCH)
  3267. {
  3268. TIMESTART(timeStretch);
  3269. StretchDIB(&pdd->biStretch, pdd->pbStretch,
  3270. 0, 0, dxDst, dyDst,
  3271. lpbi,lpBits,
  3272. xSrc,ySrc,dxSrc,dySrc);
  3273. TIMEEND(timeStretch);
  3274. lpbi = &pdd->biStretch;
  3275. lpBits = pdd->pbStretch;
  3276. dxSrc = dxDst;
  3277. dySrc = dyDst;
  3278. xSrc = 0;
  3279. ySrc = 0;
  3280. }
  3281. if (pdd->ulFlags & DDF_DITHER)
  3282. {
  3283. TIMESTART(timeDither);
  3284. #if 0 // this check isn't right.
  3285. // current dither code can only handle 1:1 sizing
  3286. if ((pdd->biDraw.biWidth != dxSrc) ||
  3287. (pdd->biDraw.biHeight != dySrc)) {
  3288. #ifdef DEBUG
  3289. DPF(("dither expected to stretch?"));
  3290. DebugBreak();
  3291. #endif
  3292. // fix it up somehow to avoid crash
  3293. dxSrc = (int) pdd->biDraw.biWidth;
  3294. dySrc = (int) pdd->biDraw.biHeight;
  3295. }
  3296. #endif
  3297. pdd->DitherProc(&pdd->biDraw, pdd->pbDither,0,0,dxSrc,dySrc,
  3298. lpbi,lpBits,xSrc, ySrc, pdd->lpDitherTable);
  3299. TIMEEND(timeDither);
  3300. lpBits = pdd->pbDither;
  3301. xSrc = 0;
  3302. ySrc = 0;
  3303. }
  3304. if ((wFlags & DDF_DONTDRAW) && !pdd->hbmDraw)
  3305. {
  3306. f = TRUE;
  3307. goto exit;
  3308. }
  3309. }
  3310. #ifdef _WIN32
  3311. else if (pdd->biDraw.biCompression == BI_RLE8)
  3312. {
  3313. /*
  3314. * if drawing RLE deltas on NT, the biSizeImage field needs to
  3315. * accurately reflect the amount of RLE data present in lpBits.
  3316. */
  3317. pdd->biDraw.biSizeImage = lpbi->biSizeImage;
  3318. }
  3319. #endif
  3320. if (pdd->lpDIBSection != NULL) {
  3321. //ASSERT(pdd->hbmDraw != NULL);
  3322. if (wFlags & DDF_DONTDRAW)
  3323. {
  3324. f = TRUE;
  3325. goto exit;
  3326. }
  3327. bltDIB:
  3328. TIMESTART(timeBlt);
  3329. // Put things back in right-side-up coordinates
  3330. ySrc = (int)pdd->biDraw.biHeight - (ySrc + dySrc);
  3331. // ySrc = 0; // Was like this for Chicago M6!
  3332. f = StretchBlt(hdc,xDst,yDst,dxDst,dyDst,pdd->hdcDraw,
  3333. xSrc,ySrc,dxSrc,dySrc,SRCCOPY) != 0;
  3334. #ifdef DEBUG
  3335. // Whistler: failure expected when desktops change
  3336. if(!f && GetLastError() != ERROR_ACCESS_DENIED) {
  3337. DPF(("StretchBlt failed %d", GetLastError()));
  3338. }
  3339. #endif
  3340. f = TRUE;
  3341. FlushBuffer();
  3342. TIMEEND(timeBlt);
  3343. } else if (pdd->hbmDraw)
  3344. {
  3345. #ifndef _WIN32
  3346. //
  3347. // when MCIAVI is playing we need realize our palette for each
  3348. // draw operation because another app may have drawn a translated
  3349. // bitmap thus screwing up the GDI *global* device translate table.
  3350. // RonG I hate you some times
  3351. //
  3352. if (pdd->hpal && (wFlags & DDF_SAME_HDC))
  3353. RealizePalette(hdc);
  3354. #endif
  3355. if (pdd->iDecompress != DECOMPRESS_BITMAP) // !(pdd->ulFlags & DDF_BITMAPX)
  3356. {
  3357. TIMESTART(timeSetDIBits);
  3358. #if USE_SETDI
  3359. pdd->sd.hdc = hdc; //!!!ack!
  3360. SetBitmap(&pdd->sd,xSrc,0,dxSrc,dySrc,lpBits,xSrc,ySrc,dxSrc,dySrc);
  3361. pdd->sd.hdc = NULL; //!!!ack!
  3362. ySrc = 0;
  3363. #else
  3364. SetDIBits(hdc, pdd->hbmDraw, 0, dySrc,
  3365. lpBits, (LPBITMAPINFO)&pdd->biDraw, pdd->uiPalUse);
  3366. #endif
  3367. FlushBuffer();
  3368. TIMEEND(timeSetDIBits);
  3369. }
  3370. if (wFlags & DDF_DONTDRAW)
  3371. {
  3372. f = TRUE;
  3373. goto exit;
  3374. }
  3375. bltit:
  3376. TIMESTART(timeBlt);
  3377. // Put things back in right-side-up coordinates
  3378. ySrc = (int)pdd->biDraw.biHeight - (ySrc + dySrc);
  3379. // ySrc = 0; // Was like this for Chicago M6!
  3380. f = StretchBlt(hdc,xDst,yDst,dxDst,dyDst,pdd->hdcDraw,
  3381. xSrc,ySrc,dxSrc,dySrc,SRCCOPY) != 0;
  3382. #ifdef DEBUG
  3383. // Whistler: failure expected when desktops change
  3384. if(!f && GetLastError() != ERROR_ACCESS_DENIED) {
  3385. DPF(("StretchBlt failed %d", GetLastError()));
  3386. }
  3387. #endif
  3388. f = TRUE;
  3389. FlushBuffer();
  3390. TIMEEND(timeBlt);
  3391. }
  3392. else
  3393. drawit:
  3394. {
  3395. // Sometimes when you read an RLE file, you get RGB data back (ie. the
  3396. // first frame). Passing RGB data to a display driver who thinks it
  3397. // is getting RLE data will blow it up. If the RLE data is the exact
  3398. // size of RGB data, we decide that's just too much of a coincidence.
  3399. BOOL fNotReallyRLE = (pdd->biDraw.biCompression == BI_RLE8 &&
  3400. lpbi->biSizeImage == DIBWIDTHBYTES(*lpbi) * (DWORD)lpbi->biHeight);
  3401. if (wFlags & DDF_DONTDRAW)
  3402. {
  3403. f = TRUE;
  3404. goto exit;
  3405. }
  3406. if (fNotReallyRLE)
  3407. pdd->biDraw.biCompression = BI_RGB;
  3408. TIMESTART(timeBlt);
  3409. // NT StretchDIBits does not work with RLE deltas, even 1:1
  3410. #ifndef CHICAGO
  3411. /*
  3412. * also note use of pdd->uiPalUse: this is DIB_PAL_COLORS by
  3413. * default, but may be set to DIB_PAL_INDICES if we detect that
  3414. * the system palette is identical to ours, and thus
  3415. * we can safely take this huge performance benefit (on NT,
  3416. * DIB_PAL_INDICES nearly halves the cost of this call)
  3417. */
  3418. if ((dxDst == dxSrc) && (dyDst == dySrc))
  3419. {
  3420. f = SetDIBitsToDevice(hdc, xDst, yDst, dxDst, dyDst,
  3421. xSrc, ySrc, 0, (UINT)pdd->biDraw.biHeight, lpBits,
  3422. (LPBITMAPINFO)&pdd->biDraw, pdd->uiPalUse) != 0;
  3423. }
  3424. else
  3425. #endif
  3426. {
  3427. f = StretchDIBits(hdc,xDst,yDst,dxDst,dyDst,
  3428. xSrc,ySrc,dxSrc,dySrc,
  3429. lpBits, (LPBITMAPINFO)&pdd->biDraw,
  3430. pdd->uiPalUse, SRCCOPY) != 0;
  3431. }
  3432. FlushBuffer();
  3433. TIMEEND(timeBlt);
  3434. if (fNotReallyRLE)
  3435. pdd->biDraw.biCompression = BI_RLE8;
  3436. }
  3437. exit:
  3438. #ifdef _WIN32
  3439. // from build 549 (or thereabouts) we need at least one of these per
  3440. // frame!
  3441. // But not if we are using DCI?? Although the cost is small so leave it in
  3442. GdiFlush();
  3443. #endif
  3444. if (!(wFlags & DDF_SAME_HDC) && pdd->hpal)
  3445. SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), TRUE);
  3446. TIMEEND(timeDraw);
  3447. return f;
  3448. }
  3449. #if 0
  3450. /**************************************************************************
  3451. * @doc INTERNAL
  3452. *
  3453. * @api BOOL| InitDrawToScreen | init drawing to the screen via DCI
  3454. *
  3455. **************************************************************************/
  3456. static BOOL InitDrawToScreen(PDD pdd)
  3457. {
  3458. BOOL f;
  3459. if (!(pdd->ulFlags & DDF_CANDRAWX))
  3460. return FALSE;
  3461. f = !(pdd->ulFlags & DDF_CLIPPED);
  3462. if (f && !(pdd->ulFlags & DDF_DRAWX))
  3463. {
  3464. DPF(("drawing to SCREEN now"));
  3465. pdd->ulFlags |= DDF_DRAWX;
  3466. }
  3467. else if (!f && (pdd->ulFlags & DDF_DRAWX))
  3468. {
  3469. DPF(("not drawing to SCREEN anymore"));
  3470. pdd->ulFlags &= ~DDF_DRAWX;
  3471. }
  3472. }
  3473. #endif
  3474. /**************************************************************************
  3475. * @doc INTERNAL
  3476. *
  3477. * @api BOOL| InitDecompress | init every thing for decompressing
  3478. * to the screen or a bitmap or a memory buffer.
  3479. *
  3480. * we can decompress to the screen if the following is true:
  3481. *
  3482. * palette must be 1:1
  3483. * must be unclipped
  3484. *
  3485. **************************************************************************/
  3486. static BOOL InitDecompress(PDD pdd)
  3487. {
  3488. BOOL f;
  3489. BOOL fBitmap;
  3490. BOOL fScreen;
  3491. //
  3492. // nothing to init
  3493. //
  3494. if (!(pdd->ulFlags & (DDF_CANSCREENX|DDF_CANBITMAPX)))
  3495. return TRUE;
  3496. //
  3497. // make sure we rebegin when the palette changes
  3498. //
  3499. if (pdd->ulFlags & (DDF_NEWPALETTE|DDF_WANTKEY))
  3500. pdd->iDecompress = 0;
  3501. //
  3502. // we need to decompress to either a memory bitmap or buffer.
  3503. //
  3504. fBitmap = (pdd->ulFlags & DDF_CANBITMAPX) &&
  3505. (pdd->ulFlags & DDF_IDENTITYPAL|DDF_CANSETPAL);
  3506. fScreen = (pdd->ulFlags & DDF_CANSCREENX) &&
  3507. !(pdd->ulFlags & DDF_CLIPPED) &&
  3508. (pdd->ulFlags & DDF_IDENTITYPAL|DDF_CANSETPAL);
  3509. //
  3510. // should we be decompressing to the screen?
  3511. //
  3512. #ifdef USE_DCI
  3513. if (fScreen && pdd->iDecompress != DECOMPRESS_SCREEN)
  3514. {
  3515. if (pdd->ulFlags & DDF_IDENTITYPAL)
  3516. {
  3517. if (pdd->hpalDraw)
  3518. ICDecompressSetPalette(pdd->hic, &pdd->biBuffer);
  3519. else
  3520. ICDecompressSetPalette(pdd->hic, NULL);
  3521. }
  3522. else
  3523. {
  3524. if (FixUpCodecPalette(pdd->hic, pdd->lpbi))
  3525. {
  3526. DPF(("Codec notified of palette change...."));
  3527. }
  3528. else
  3529. {
  3530. DPF(("Codec failed palette change...."));
  3531. pdd->iDecompress = 0;
  3532. goto ack;
  3533. }
  3534. }
  3535. //
  3536. // now init the compressor for screen decompress.
  3537. //
  3538. f = ICDecompressExBegin(pdd->hic, 0,
  3539. pdd->lpbi, NULL, 0, 0, pdd->dxSrc, pdd->dySrc,
  3540. (LPBITMAPINFOHEADER) &biScreen, lpScreen,
  3541. 0, 0, pdd->dxDst, pdd->dyDst) == ICERR_OK;
  3542. if (f)
  3543. {
  3544. pdd->ulFlags |= DDF_DIRTY; // buffer is dirty now?
  3545. RPF(("Decompressing to screen now"));
  3546. pdd->iDecompress = DECOMPRESS_SCREEN;
  3547. return TRUE;
  3548. }
  3549. else
  3550. {
  3551. ack: DPF(("Compressor failed decompress to SCREEN, so not decompressing to screen!!!!"));
  3552. pdd->iDecompress = 0;
  3553. pdd->ulFlags &= ~DDF_CANSCREENX;
  3554. }
  3555. }
  3556. else if (fScreen)
  3557. {
  3558. //
  3559. // already decompressing to screen.
  3560. //
  3561. return TRUE;
  3562. }
  3563. #endif
  3564. if (fBitmap && pdd->iDecompress != DECOMPRESS_BITMAP)
  3565. {
  3566. if (pdd->ulFlags & DDF_IDENTITYPAL)
  3567. {
  3568. if (pdd->hpalDraw)
  3569. ICDecompressSetPalette(pdd->hic, &pdd->biBuffer);
  3570. else
  3571. ICDecompressSetPalette(pdd->hic, NULL);
  3572. }
  3573. else
  3574. {
  3575. if (FixUpCodecPalette(pdd->hic, pdd->lpbi))
  3576. {
  3577. DPF(("Codec notified of palette change...."));
  3578. }
  3579. else
  3580. {
  3581. DPF(("Codec failed palette change...."));
  3582. pdd->iDecompress = 0;
  3583. goto ackack;
  3584. }
  3585. }
  3586. f = ICDecompressBegin(pdd->hic, pdd->lpbi, &pdd->biBitmap) == ICERR_OK;
  3587. if (f)
  3588. {
  3589. DPF(("decompressing to BITMAP now"));
  3590. pdd->ulFlags |= DDF_DIRTY; // buffer is dirty now?
  3591. pdd->iDecompress = DECOMPRESS_BITMAP;
  3592. // naked bitmap translate stuff?
  3593. return TRUE;
  3594. }
  3595. else
  3596. {
  3597. ackack: DPF(("Unable to init decompress to bitmap"));
  3598. pdd->iDecompress = 0;
  3599. }
  3600. }
  3601. else if (fBitmap)
  3602. {
  3603. //
  3604. // already decompressing to bitmap.
  3605. //
  3606. return TRUE;
  3607. }
  3608. //
  3609. // should we decompress to a buffer?
  3610. //
  3611. if (pdd->iDecompress != DECOMPRESS_BUFFER)
  3612. {
  3613. DPF(("decompressing to DIB now"));
  3614. pdd->ulFlags |= DDF_DIRTY; // buffer is dirty now?
  3615. pdd->iDecompress = DECOMPRESS_BUFFER;
  3616. if (pdd->hpalDraw)
  3617. ICDecompressSetPalette(pdd->hic, &pdd->biBuffer);
  3618. else
  3619. ICDecompressSetPalette(pdd->hic, NULL);
  3620. f = ICDecompressBegin(pdd->hic, pdd->lpbi, &pdd->biBuffer) == ICERR_OK;
  3621. if (!f)
  3622. {
  3623. DPF(("Unable to re-begin compressor"));
  3624. }
  3625. }
  3626. return TRUE; // nothing to change
  3627. }
  3628. /**************************************************************************
  3629. * @doc INTERNAL
  3630. *
  3631. * @api void | DrawDibClipChange | called when the clipping has changed
  3632. * from clipped to totaly un-clipped or whatever.
  3633. *
  3634. **************************************************************************/
  3635. static void DrawDibClipChange(PDD pdd, UINT wFlags)
  3636. {
  3637. if (!(pdd->ulFlags & DDF_NEWPALETTE))
  3638. {
  3639. if (pdd->ulFlags & DDF_CLIPPED)
  3640. DPF(("now clipped"));
  3641. else
  3642. DPF(("now un-clipped"));
  3643. }
  3644. ////InitDrawToScreen(pdd);
  3645. //
  3646. // dont change Decompressors on a non key frame, unless we have
  3647. // to (ie getting clipped while decompressing to screen)
  3648. //
  3649. if (pdd->ulFlags & DDF_NEWPALETTE)
  3650. {
  3651. if (wFlags & DDF_NOTKEYFRAME)
  3652. {
  3653. if (pdd->iDecompress == DECOMPRESS_BUFFER)
  3654. {
  3655. DPF(("waiting for a key frame to change decompressor (palette change)"));
  3656. pdd->ulFlags |= DDF_WANTKEY;
  3657. return;
  3658. }
  3659. }
  3660. }
  3661. else
  3662. {
  3663. if (wFlags & DDF_NOTKEYFRAME)
  3664. {
  3665. if (pdd->iDecompress != DECOMPRESS_SCREEN) // !(pdd->ulFlags & DDF_SCREENX))
  3666. {
  3667. DPF(("waiting for a key frame to change (clipped) decompressor"));
  3668. pdd->ulFlags |= DDF_WANTKEY;
  3669. return;
  3670. }
  3671. }
  3672. }
  3673. InitDecompress(pdd);
  3674. pdd->ulFlags &= ~DDF_WANTKEY;
  3675. }
  3676. /**************************************************************************
  3677. * @doc INTERNAL
  3678. *
  3679. * @api void | DrawDibPalChange | called when the physical palette mapping
  3680. * has changed.
  3681. *
  3682. **************************************************************************/
  3683. static void DrawDibPalChange(PDD pdd, HDC hdc, HPALETTE hpal)
  3684. {
  3685. #ifndef _WIN32
  3686. #ifdef DEBUG
  3687. extern BOOL FAR PASCAL IsDCCurrentPalette(HDC hdc);
  3688. BOOL fForeground = IsDCCurrentPalette(hdc);
  3689. if (fForeground)
  3690. DPF(("Palette mapping has changed (foreground)..."));
  3691. else
  3692. DPF(("Palette mapping has changed (background)..."));
  3693. #endif
  3694. #endif
  3695. //
  3696. // if we are on a palette device we need to do some special stuff.
  3697. //
  3698. if (gwScreenBitDepth == 8 && (gwRasterCaps & RC_PALETTE))
  3699. {
  3700. //
  3701. // get the logical->physical mapping
  3702. //
  3703. if (GetPhysDibPaletteMap(hdc, &pdd->biDraw, pdd->uiPalUse, pdd->ab))
  3704. pdd->ulFlags |= DDF_IDENTITYPAL;
  3705. else
  3706. pdd->ulFlags &= ~DDF_IDENTITYPAL;
  3707. if (pdd->ulFlags & DDF_IDENTITYPAL)
  3708. DPF(("Palette mapping is 1:1"));
  3709. else
  3710. DPF(("Palette mapping is not 1:1"));
  3711. #ifdef DAYTONA // !!! Not on Chicago!
  3712. if (pdd->ulFlags & DDF_IDENTITYPAL) {
  3713. DPF(("using DIB_PAL_INDICES"));
  3714. pdd->uiPalUse = DIB_PAL_INDICES;
  3715. } else {
  3716. pdd->uiPalUse = DIB_PAL_COLORS;
  3717. }
  3718. #endif
  3719. }
  3720. else
  3721. {
  3722. //
  3723. // we are not on a palette device, some code checks DDF_IDENTITYPAL
  3724. // anyway so set it.
  3725. //
  3726. pdd->ulFlags |= DDF_IDENTITYPAL;
  3727. }
  3728. if (pdd->hbmDraw && (pdd->ulFlags & DDF_BITMAP))
  3729. {
  3730. //!!! we should pass pdd->ab to this function!
  3731. //!!! and use a naked translate.
  3732. SetBitmapColorChange(&pdd->sd, hdc, hpal);
  3733. }
  3734. DrawDibClipChange(pdd, DDF_NOTKEYFRAME);
  3735. }
  3736. /**************************************************************************
  3737. * @doc INTERNAL
  3738. *
  3739. * @api HPALETTE | CreateBIPalette | Create palette from bitmap.
  3740. *
  3741. * @parm LPBITMAPINFOHEADER | lpbi | Pointer to bitmap.
  3742. *
  3743. * @rdesc Returns handle to the palette, NULL if error.
  3744. *
  3745. **************************************************************************/
  3746. STATICFN HPALETTE CreateBIPalette(HPALETTE hpal, LPBITMAPINFOHEADER lpbi)
  3747. {
  3748. LPRGBQUAD prgb;
  3749. int i;
  3750. // This structure is the same as LOGPALETTE EXCEPT for the array of
  3751. // palette entries which here is 256 long. The "template" in the
  3752. // SDK header files only has an array of size one, hence the "duplication".
  3753. struct {
  3754. WORD palVersion; /* tomor - don't mess with word */
  3755. WORD palNumEntries;
  3756. PALETTEENTRY palPalEntry[256];
  3757. } pal;
  3758. pal.palVersion = 0x300;
  3759. pal.palNumEntries = (int)lpbi->biClrUsed;
  3760. if (pal.palNumEntries == 0 && lpbi->biBitCount <= 8)
  3761. pal.palNumEntries = (1 << (int)lpbi->biBitCount);
  3762. if (pal.palNumEntries == 0)
  3763. return NULL;
  3764. prgb = (LPRGBQUAD)(lpbi+1);
  3765. for (i=0; i<(int)pal.palNumEntries; i++)
  3766. {
  3767. pal.palPalEntry[i].peRed = prgb[i].rgbRed;
  3768. pal.palPalEntry[i].peGreen = prgb[i].rgbGreen;
  3769. pal.palPalEntry[i].peBlue = prgb[i].rgbBlue;
  3770. pal.palPalEntry[i].peFlags = 0;
  3771. }
  3772. if (hpal)
  3773. {
  3774. ResizePalette(hpal, pal.palNumEntries);
  3775. SetPaletteEntries(hpal, 0, pal.palNumEntries, pal.palPalEntry);
  3776. }
  3777. else
  3778. {
  3779. hpal = CreatePalette((LPLOGPALETTE)&pal);
  3780. }
  3781. return hpal;
  3782. }
  3783. /**************************************************************************
  3784. * @doc INTERNAL
  3785. *
  3786. * @api BOOL | SetPalFlags | Modifies the palette flags.
  3787. *
  3788. * @parm HPALETTE | hpal | Handle to the palette.
  3789. *
  3790. * @parm int | iIndex | Starting palette index.
  3791. *
  3792. * @parm int | cntEntries | Number of entries to set flags on.
  3793. *
  3794. * @parm UINT | wFlags | Palette flags.
  3795. *
  3796. * @rdesc Returns TRUE if successful, FALSE otherwise.
  3797. *
  3798. **************************************************************************/
  3799. STATICFN BOOL SetPalFlags(HPALETTE hpal, int iIndex, int cntEntries, UINT wFlags)
  3800. {
  3801. int i;
  3802. PALETTEENTRY ape[256];
  3803. if (hpal == NULL)
  3804. return FALSE;
  3805. if (cntEntries < 0) {
  3806. cntEntries = 0; // GetObject returns 2 bytes
  3807. GetObject(hpal,sizeof(int),(LPSTR)&cntEntries);
  3808. }
  3809. GetPaletteEntries(hpal, iIndex, cntEntries, ape);
  3810. for (i=0; i<cntEntries; i++)
  3811. ape[i].peFlags = (BYTE)wFlags;
  3812. return SetPaletteEntries(hpal, iIndex, cntEntries, ape);
  3813. }
  3814. /**************************************************************************
  3815. * @doc INTERNAL
  3816. *
  3817. * @api BOOL | IsIdentityPalette | Check if palette is an identity palette.
  3818. *
  3819. * @parm HPALETTE | hpal | Handle to the palette.
  3820. *
  3821. * @rdesc Returns TRUE if the palette is an identity palette, FALSE otherwise.
  3822. *
  3823. **************************************************************************/
  3824. #define CODE _based(_segname("_CODE"))
  3825. //
  3826. // These are the standard VGA colors, we will be stuck with until the
  3827. // end of time!
  3828. //
  3829. static PALETTEENTRY CODE apeCosmic[16] = {
  3830. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3831. 0x80, 0x00, 0x00, 0x00, // 0001 dark red
  3832. 0x00, 0x80, 0x00, 0x00, // 0010 dark green
  3833. 0x80, 0x80, 0x00, 0x00, // 0011 mustard
  3834. 0x00, 0x00, 0x80, 0x00, // 0100 dark blue
  3835. 0x80, 0x00, 0x80, 0x00, // 0101 purple
  3836. 0x00, 0x80, 0x80, 0x00, // 0110 dark turquoise
  3837. 0xC0, 0xC0, 0xC0, 0x00, // 1000 gray
  3838. 0x80, 0x80, 0x80, 0x00, // 0111 dark gray
  3839. 0xFF, 0x00, 0x00, 0x00, // 1001 red
  3840. 0x00, 0xFF, 0x00, 0x00, // 1010 green
  3841. 0xFF, 0xFF, 0x00, 0x00, // 1011 yellow
  3842. 0x00, 0x00, 0xFF, 0x00, // 1100 blue
  3843. 0xFF, 0x00, 0xFF, 0x00, // 1101 pink (magenta)
  3844. 0x00, 0xFF, 0xFF, 0x00, // 1110 cyan
  3845. 0xFF, 0xFF, 0xFF, 0x00 // 1111 white
  3846. };
  3847. static PALETTEENTRY CODE apeFake[16] = {
  3848. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3849. 0xBF, 0x00, 0x00, 0x00, // 0001 dark red
  3850. 0x00, 0xBF, 0x00, 0x00, // 0010 dark green
  3851. 0xBF, 0xBF, 0x00, 0x00, // 0011 mustard
  3852. 0x00, 0x00, 0xBF, 0x00, // 0100 dark blue
  3853. 0xBF, 0x00, 0xBF, 0x00, // 0101 purple
  3854. 0x00, 0xBF, 0xBF, 0x00, // 0110 dark turquoise
  3855. 0xC0, 0xC0, 0xC0, 0x00, // 1000 gray
  3856. 0x80, 0x80, 0x80, 0x00, // 0111 dark gray
  3857. 0xFF, 0x00, 0x00, 0x00, // 1001 red
  3858. 0x00, 0xFF, 0x00, 0x00, // 1010 green
  3859. 0xFF, 0xFF, 0x00, 0x00, // 1011 yellow
  3860. 0x00, 0x00, 0xFF, 0x00, // 1100 blue
  3861. 0xFF, 0x00, 0xFF, 0x00, // 1101 pink (magenta)
  3862. 0x00, 0xFF, 0xFF, 0x00, // 1110 cyan
  3863. 0xFF, 0xFF, 0xFF, 0x00, // 1111 white
  3864. };
  3865. static PALETTEENTRY CODE apeBlackWhite[16] = {
  3866. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3867. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3868. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3869. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3870. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3871. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3872. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3873. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3874. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3875. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3876. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3877. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3878. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3879. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3880. 0xFF, 0xFF, 0xFF, 0x00 // 1111 white
  3881. };
  3882. STATICFN BOOL NEAR IsIdentityPalette(HPALETTE hpal)
  3883. {
  3884. int i,n=0; // n is initialised as GetObject returns a 2 byte value
  3885. HDC hdc;
  3886. PALETTEENTRY ape[256];
  3887. PALETTEENTRY apeSystem[16];
  3888. if (hpal == NULL || !(gwRasterCaps & RC_PALETTE) || gwScreenBitDepth != 8)
  3889. return FALSE;
  3890. ZeroMemory(ape, sizeof(ape));
  3891. // Some wierd display cards actually have different numbers of system
  3892. // colours! We definitely don't want to think we can do identity palettes.
  3893. hdc = GetDC(NULL);
  3894. if (NULL == hdc) {
  3895. return FALSE;
  3896. }
  3897. n = GetDeviceCaps(hdc, NUMRESERVED);
  3898. ReleaseDC(NULL, hdc);
  3899. if (n != 20)
  3900. return FALSE;
  3901. GetObject(hpal, sizeof(n), (LPVOID)&n);
  3902. if (n != 256)
  3903. return FALSE;
  3904. GetPaletteEntries(hpal, 0, 8, &ape[0]);
  3905. GetPaletteEntries(hpal, 248, 8, &ape[8]);
  3906. for (i=0; i<16; i++)
  3907. ape[i].peFlags = 0;
  3908. if (!_fmemcmp(ape, apeCosmic, sizeof(apeCosmic)))
  3909. goto DoneChecking;
  3910. if (!_fmemcmp(ape, apeFake, sizeof(apeFake)))
  3911. goto DoneChecking;
  3912. if (!_fmemcmp(ape, apeBlackWhite, sizeof(apeBlackWhite)))
  3913. goto DoneChecking;
  3914. hdc = GetDC(NULL);
  3915. if (NULL == hdc) {
  3916. return FALSE;
  3917. }
  3918. GetSystemPaletteEntries(hdc, 0, 8, &apeSystem[0]);
  3919. GetSystemPaletteEntries(hdc, 248, 8, &apeSystem[8]);
  3920. ReleaseDC(NULL, hdc);
  3921. for (i=0; i<16; i++)
  3922. apeSystem[i].peFlags = 0;
  3923. if (!_fmemcmp(ape, apeSystem, sizeof(apeSystem)))
  3924. goto DoneChecking;
  3925. return FALSE;
  3926. DoneChecking:
  3927. //
  3928. // if we have an identity palette then, patch the colors to match
  3929. // the driver ones exactly.
  3930. //
  3931. GetPaletteEntries(hpal, 0, 256, ape);
  3932. hdc = GetDC(NULL);
  3933. GetSystemPaletteEntries(hdc, 0, 10, &ape[0]);
  3934. GetSystemPaletteEntries(hdc, 246, 10, &ape[246]);
  3935. ReleaseDC(NULL, hdc);
  3936. for (i=0; i<10; i++)
  3937. ape[i].peFlags = 0;
  3938. for (i=10; i<246; i++)
  3939. ape[i].peFlags = PC_NOCOLLAPSE;
  3940. for (i=246; i<256; i++)
  3941. ape[i].peFlags = 0;
  3942. SetPaletteEntries(hpal, 0, 256, ape);
  3943. DPF(("Calling UnrealizeObject on hpal==%8x\n", hpal));
  3944. UnrealizeObject(hpal); //??? needed
  3945. return TRUE;
  3946. }
  3947. #define COLORMASK 0xF8
  3948. STATICFN BOOL NEAR AreColorsAllGDIColors(LPBITMAPINFOHEADER lpbi)
  3949. {
  3950. int cColors;
  3951. LPRGBQUAD lprgb = (LPRGBQUAD) ((LPBYTE) lpbi + lpbi->biSize);
  3952. int i;
  3953. for (cColors = (int) lpbi->biClrUsed; cColors > 0; cColors--, lprgb++) {
  3954. for (i = 0; i < 16; i++) {
  3955. if (((lprgb->rgbRed & COLORMASK) == (apeCosmic[i].peRed & COLORMASK)) &&
  3956. ((lprgb->rgbGreen & COLORMASK) == (apeCosmic[i].peGreen & COLORMASK)) &&
  3957. ((lprgb->rgbBlue & COLORMASK) == (apeCosmic[i].peBlue & COLORMASK)))
  3958. goto Onward;
  3959. if (((lprgb->rgbRed & COLORMASK) == (apeFake[i].peRed & COLORMASK)) &&
  3960. ((lprgb->rgbGreen & COLORMASK) == (apeFake[i].peGreen & COLORMASK)) &&
  3961. ((lprgb->rgbBlue & COLORMASK) == (apeFake[i].peBlue & COLORMASK)))
  3962. goto Onward;
  3963. }
  3964. return FALSE;
  3965. Onward:
  3966. ; // There's got to be a nicer way to arrange this code!
  3967. }
  3968. return TRUE; // !!!!!
  3969. }
  3970. #if 0
  3971. #ifdef _WIN32
  3972. /*
  3973. * check if the system palette is identical to the palette we want
  3974. * to draw with. This should be the same as checking both IsIdentityPalette
  3975. * and also that we have the foreground window. If the palettes are the same,
  3976. * then set a flag showing that we can safely use DIB_PAL_INDICES instead of
  3977. * DIB_PAL_COLORS.
  3978. *
  3979. * On NT at least, DIB_PAL_INDICES saves a large amount of time from the
  3980. * critical GDI drawing call (SetDIBitsToDevice). But we can only use it
  3981. * if our palette is really the same as the system palette. This function
  3982. * should be called from the WM_NEWPALETTE message so that every time
  3983. * a new palette is realised (by us or anyone else) we will accurately set
  3984. * this flag.
  3985. */
  3986. static void DrawDibCheckPalette(PDD pdd)
  3987. {
  3988. PALETTEENTRY apeSystem[256];
  3989. PALETTEENTRY apeLocal[256];
  3990. UINT palcount = 0; // GetObject stores two bytes. Rest of code prefers 32 bits
  3991. HDC hdc;
  3992. HPALETTE hpal;
  3993. hpal = (pdd->hpalDraw ? pdd->hpalDraw : pdd->hpal);
  3994. if (hpal == NULL)
  3995. return;
  3996. /*
  3997. * check that it is 8-bit colour in use
  3998. */
  3999. if (gwScreenBitDepth != 8 || !(gwRasterCaps & RC_PALETTE))
  4000. return ;
  4001. GetObject(hpal, sizeof(palcount), (LPVOID)&palcount);
  4002. if (palcount != 256)
  4003. return ;
  4004. /*
  4005. * read all the system palette
  4006. */
  4007. hdc = GetDC(NULL);
  4008. GetSystemPaletteEntries(hdc, 0, 256, apeSystem);
  4009. ReleaseDC(NULL, hdc);
  4010. /* read local palette entries */
  4011. GetPaletteEntries(hpal, 0, 256, apeLocal);
  4012. /* compare colours */
  4013. #define BETTER_PAL_INDICES // Faster when the result is DIB_PAL_INDICES
  4014. #ifdef BETTER_PAL_INDICES // but slower when DIB_PAL_COLORS is the outcome
  4015. // unless the quick check is OK
  4016. StartCounting();
  4017. if (apeLocal[17].peRed == apeSystem[17].peRed) { // Quick check
  4018. for (palcount=256; palcount--; ) {
  4019. apeLocal[palcount].peFlags = apeSystem[palcount].peFlags = 0;
  4020. } // its a shame we have to clear the flags out
  4021. if (!memcmp(apeLocal, apeSystem, sizeof(apeSystem))) {
  4022. /* all ok - we can use INDICES */
  4023. RPF(("\tUsing PAL_INDICES"));
  4024. pdd->uiPalUse = DIB_PAL_INDICES;
  4025. EndCounting("(memcmp) DIB_PAL_INDICES");
  4026. return;
  4027. }
  4028. }
  4029. /* comparison failed - forget it */
  4030. RPF(("\tUsing DIB_PAL_COLORS"));
  4031. pdd->uiPalUse = DIB_PAL_COLORS;
  4032. EndCounting("(memcmp) DIB_PAL_COLORS");
  4033. #else
  4034. StartCounting();
  4035. for (palcount = 0; palcount < 256; palcount++) {
  4036. if ((apeLocal[palcount].peRed != apeSystem[palcount].peRed) ||
  4037. (apeLocal[palcount].peGreen != apeSystem[palcount].peGreen) ||
  4038. (apeLocal[palcount].peBlue != apeSystem[palcount].peBlue)) {
  4039. /* comparison failed - forget it */
  4040. DPF(("\tUsing DIB_PAL_COLORS Failed with palcount=%d",palcount));
  4041. pdd->uiPalUse = DIB_PAL_COLORS;
  4042. EndCounting(" DIB_PAL_COLORS");
  4043. return;
  4044. }
  4045. }
  4046. /* all ok - we can use INDICES */
  4047. RPF(("\tUsing PAL_INDICES"));
  4048. pdd->uiPalUse = DIB_PAL_INDICES;
  4049. EndCounting(" DIB_PAL_INDICES");
  4050. #endif
  4051. }
  4052. #endif
  4053. #endif
  4054. /**************************************************************************
  4055. let codec adapt to the system palette.
  4056. **************************************************************************/
  4057. static BOOL FixUpCodecPalette(HIC hic, LPBITMAPINFOHEADER lpbi)
  4058. {
  4059. struct {
  4060. BITMAPINFOHEADER bi;
  4061. RGBQUAD argbq[256];
  4062. } s;
  4063. int i;
  4064. HDC hdc;
  4065. s.bi.biSize = sizeof(s.bi);
  4066. s.bi.biWidth = lpbi->biWidth;
  4067. s.bi.biHeight = lpbi->biHeight;
  4068. s.bi.biPlanes = 1;
  4069. s.bi.biBitCount = 8;
  4070. s.bi.biCompression = 0;
  4071. s.bi.biSizeImage = 0;
  4072. s.bi.biXPelsPerMeter = 0;
  4073. s.bi.biYPelsPerMeter = 0;
  4074. s.bi.biClrUsed = 256;
  4075. s.bi.biClrImportant = 0;
  4076. hdc = GetDC(NULL);
  4077. GetSystemPaletteEntries(hdc, 0, 256, (LPPALETTEENTRY) &s.argbq);
  4078. ReleaseDC(NULL, hdc);
  4079. for (i = 0; i < 256; i++)
  4080. ((DWORD FAR*)s.argbq)[i] = i < 8 || i >= 248 ? 0 :
  4081. RGB(s.argbq[i].rgbRed,s.argbq[i].rgbGreen,s.argbq[i].rgbBlue);
  4082. return ICDecompressSetPalette(hic, &s.bi) == ICERR_OK;
  4083. }
  4084. /**************************************************************************
  4085. let codec adapt to a palette passed by the app.
  4086. **************************************************************************/
  4087. static BOOL NEAR SendSetPalette(PDD pdd)
  4088. {
  4089. int i;
  4090. int iPalColors = 0;
  4091. BOOL f;
  4092. if (pdd->hic == NULL) // nobody to send too
  4093. return FALSE;
  4094. if (pdd->biBuffer.biBitCount != 8) // not decompressing to 8bit
  4095. return FALSE;
  4096. if (!(gwRasterCaps & RC_PALETTE)) // not a palette device who cares.
  4097. return FALSE;
  4098. if (pdd->hpalDraw)
  4099. {
  4100. GetObject(pdd->hpalDraw, sizeof(iPalColors), (void FAR *)&iPalColors);
  4101. if (iPalColors == 0)
  4102. return FALSE;
  4103. if (iPalColors > 256)
  4104. iPalColors = 256;
  4105. pdd->biBuffer.biClrUsed = iPalColors;
  4106. GetPaletteEntries(pdd->hpalDraw, 0, iPalColors, (PALETTEENTRY FAR *)pdd->argbq);
  4107. for (i = 0; i < iPalColors; i++)
  4108. ((DWORD*)pdd->argbq)[i] = RGB(pdd->argbq[i].rgbRed,pdd->argbq[i].rgbGreen,pdd->argbq[i].rgbBlue);
  4109. f = ICDecompressSetPalette(pdd->hic, &pdd->biBuffer) == ICERR_OK;
  4110. ICDecompressGetPalette(pdd->hic, pdd->lpbi, &pdd->biBuffer);
  4111. }
  4112. else
  4113. {
  4114. pdd->biBuffer.biClrUsed = pdd->ClrUsed;
  4115. f = ICDecompressSetPalette(pdd->hic, NULL) == ICERR_OK;
  4116. ICDecompressGetPalette(pdd->hic, pdd->lpbi, &pdd->biBuffer);
  4117. }
  4118. return f;
  4119. }
  4120. #ifdef DEBUG_RETAIL
  4121. #define _WINDLL
  4122. #include <stdarg.h>
  4123. #include <stdio.h>
  4124. void FAR CDECL ddprintf(LPSTR szFormat, ...)
  4125. {
  4126. char ach[128];
  4127. va_list va;
  4128. UINT n;
  4129. if (fDebug == -1)
  4130. fDebug = mmGetProfileIntA("Debug", MODNAME, FALSE);
  4131. if (!fDebug)
  4132. return;
  4133. va_start(va, szFormat);
  4134. #ifdef _WIN32
  4135. if ('+' == *szFormat) {
  4136. n = 0;
  4137. ++szFormat;
  4138. } else {
  4139. n = sprintf(ach, MODNAME ": (tid %x) ", GetCurrentThreadId());
  4140. }
  4141. n += vsprintf(ach+n, szFormat, va);
  4142. #else
  4143. lstrcpy(ach, MODNAME ": ");
  4144. n = lstrlen(ach);
  4145. n += wvsprintf(ach+n, szFormat, va);
  4146. #endif
  4147. va_end(va);
  4148. if ('+' == ach[n-1]) {
  4149. --n;
  4150. } else {
  4151. ach[n++] = '\r';
  4152. ach[n++] = '\n';
  4153. }
  4154. ach[n] = 0;
  4155. OutputDebugStringA(ach);
  4156. }
  4157. #endif