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.

1431 lines
39 KiB

  1. #include <windows.h>
  2. #include <windowsx.h>
  3. #include <mmsystem.h> // for timeGetTime()
  4. #include <profile.h>
  5. #include "drawdibi.h"
  6. #include "profdisp.h"
  7. #ifdef UNICODE
  8. #include <wchar.h>
  9. #endif
  10. #include <vfw.h>
  11. //#include "lockbm.h"
  12. //#include "setdi.h"
  13. // daytona will check the device capabilities but will do no timing.
  14. // we are hardwired to use CreateDIBSection on Daytona, and to use GDI for
  15. // all stretching
  16. // Remove inline assembly warning
  17. #pragma warning(disable:4704)
  18. //
  19. // Set+Blt must be N% faster in order to say a driver isn't good
  20. //
  21. #define PROFDISP_FUDGE 110
  22. #ifndef _WIN32
  23. #define GdiFlush()
  24. #endif
  25. LRESULT VFWAPI DrawDibProfileDisplay(LPBITMAPINFOHEADER lpbi);
  26. STATICFN UINT NEAR PASCAL ProfDispCanDrawDib(LPBITMAPINFOHEADER lpbi);
  27. STATICFN HPALETTE CreateTestPalette(BOOL);
  28. #ifndef _WIN32
  29. //C6 will die if we dont redefine this.
  30. #undef GlobalFreePtr
  31. #define GlobalFreePtr(p) GlobalFree(GlobalPtrHandle(p))
  32. #pragma alloc_text(DRAWDIB, DrawDibProfileDisplay)
  33. #pragma alloc_text(DRAWDIB, ProfDispCanDrawDib)
  34. #endif
  35. #ifndef QUERYDIBSUPPORT
  36. #define QUERYDIBSUPPORT 3073
  37. #endif
  38. #ifndef QDI_SETDIBITS
  39. #define QDI_SETDIBITS 0x0001
  40. #define QDI_GETDIBITS 0x0002
  41. #define QDI_DIBTOSCREEN 0x0004
  42. #define QDI_STRETCHDIB 0x0008
  43. #endif
  44. /*
  45. ** ProfDisp - profile the display driver
  46. */
  47. #define BITMAP_X 320
  48. #define BITMAP_Y 240
  49. #define N_FRAMES 10
  50. #define STRETCH_N 125
  51. #ifdef DEBUG
  52. #define FIRST_N 0 // do four bit
  53. #else
  54. #define FIRST_N 1
  55. #endif
  56. #define BITBLTINDEX 5
  57. #define BACKINDEX 6
  58. // Internal return codes from DrawDibTest
  59. #define CANT_DO_THESE_BITS 1
  60. #define CANT_DO_STRETCHDIBITS 2
  61. #define STRETCHDI_FASTER 3
  62. #define OTHER_FASTER 4
  63. #define STRETCHDI_BUT_TRY_BLT 5
  64. static HWND ghwnd ;
  65. extern BOOL gfIsRTL; // in MSVIDEO\init.c
  66. #ifndef _WIN32
  67. #define CODE _based(_segname("_CODE"))
  68. #define STACK _based(_segname("_STACK"))
  69. #else
  70. #define CODE
  71. #define STACK
  72. #endif
  73. STATICFN UINT ProfileDisplay(HDC hdc, UINT wBitsToTest, int dx, int dy) ;
  74. STATICFN BOOL IsDisplay16Bit(HDC hdc ) ;
  75. STATICFN BOOL IsDisplay32Bit(HDC hdc ) ;
  76. STATICFN UINT DrawDibTest(HDC hdc, UINT wBits, LPBITMAPINFOHEADER FAR *alpbi, UINT wFrames,UINT wStretch ) ;
  77. #ifndef DAYTONA
  78. STATICFN void FreeFrames( LPBITMAPINFOHEADER FAR *alpbi) ;
  79. STATICFN void MakeFrames(LPBITMAPINFOHEADER FAR *alpbi, UINT bits, UINT wXSize,UINT wYSize ) ;
  80. #endif
  81. STATICFN HANDLE MakeDib( HBITMAP hbitmap, UINT bits ) ;
  82. static TCHAR CODE szBoot[] = TEXT("boot" );
  83. static TCHAR CODE szDisplay[] = TEXT("display.drv" );
  84. static TCHAR CODE szNull[] = TEXT("") ;
  85. static TCHAR CODE szDrawdib[] = TEXT("DrawDib");
  86. static TCHAR CODE szSystemIni[] = TEXT("system.ini") ;
  87. static TCHAR CODE szNxNxNxType[] = TEXT(" %dx%dx%d(%s%u)");
  88. static TCHAR CODE szEntryFormat[] = TEXT("%d,%d,%d,%d");
  89. static TCHAR CODE szU[] = TEXT("%u");
  90. static TCHAR CODE sz02U[] = TEXT("%02u");
  91. static TCHAR CODE sz565[] = TEXT("565 ");
  92. static TCHAR CODE sz555[] = TEXT("555 ");
  93. static TCHAR CODE szRGB[] = TEXT("RGB ");
  94. static TCHAR CODE szBGR[] = TEXT("BGR ");
  95. // The following two strings are loaded from MSVIDEO.DLL - defined in
  96. // video\video.rc. If they cannot be found there, use these definitions
  97. static TCHAR CODE szProfilingDefault[] = TEXT("Profiling Display");
  98. static TCHAR CODE szListbox[] = TEXT("ListBox");
  99. #if 0 // dont warn any-more
  100. #ifndef _WIN32
  101. static TCHAR CODE szWarning[] = TEXT("Warning!");
  102. static TCHAR CODE szDisplaySucks[]=
  103. TEXT("You may encounter display performance problems; ")
  104. TEXT("please contact the manufacturer of your video ")
  105. TEXT("board to see if an updated driver is available.");
  106. #endif
  107. #endif
  108. #define ARRAYLEN(array) (sizeof(array)/sizeof(array[0]))
  109. static int result[5] = {
  110. -1,
  111. -1,
  112. -1,
  113. -1,
  114. -1};
  115. //
  116. // UINT displayFPS[7][3][2] [test dib][stretch][method]
  117. //
  118. // this array contains fps numbers times 10, ie 10 == 1fps
  119. // zero means the test was not run.
  120. //
  121. // testdib:
  122. // 0 = 4bpp DIB (debug only)
  123. // 1 = 8bpp DIB
  124. // 2 = 16bpp DIB
  125. // 3 = 24bpp DIB
  126. // 4 = 32bpp DIB
  127. // 5 = BitBlt
  128. // 6 = 8bpp DIB (with non identity palette)
  129. //
  130. // stretch:
  131. // 0 = 1:1
  132. // 1 = 1:2
  133. // 2 = 1:N (realy 2:3)
  134. //
  135. // method (for stretch == 1:1)
  136. // 0 = StretchDIBits()
  137. // 1 = SetDIBits() + BitBlt *
  138. //
  139. // method (for stretch != 1:1)
  140. // 0 = StretchDIBits()
  141. // 1 = StretchDIB() + StretchDIBits() **
  142. //
  143. // method (for testdib == 5, bitblt)
  144. // 0 = BitBlt foreground palette
  145. // 1 = BitBlt background palette
  146. //
  147. // NOTE high color dibs (> 8) are not tested on devices with bitdepths <= 8
  148. //
  149. // NOTE stretching tests are not run unless the device does stretching.
  150. // (RasterCaps has RC_STRETCHBLT or RC_STRETCHDIBITS set)
  151. //
  152. // * NOTE if we can access bitmaps, we dont use SetDIBits() we use direct
  153. // code.
  154. //
  155. // ** NOTE (StretchDIB is not a GDI api...)
  156. //
  157. // EXAMPLE:
  158. // displayFPS[1][0][0] is the FPS of 1:1 StretchDIBits() on a 8bpp DIB
  159. // displayFPS[1][0][1] is the FPS of Set+BitBlt() on a 8bpp DIB
  160. // displayFPS[1][1][0] is the FPS of 1:2 StretchDIBits() on a 8bpp DIB
  161. //
  162. // how the ResultN flags get set:
  163. //
  164. // PD_CAN_DRAW_DIB (can draw this dib 1:1 using some method...)
  165. // displayFPS[N][0][0] != 0 or displayFPS[N][0][1] != 0
  166. //
  167. // PD_CAN_STRETCHDIB (can stretch this dib using StretchDIBits)
  168. // displayFPS[N][1][0] > displayFPS[N][1][1] or
  169. // displayFPS[N][2][0] > displayFPS[N][2][1]
  170. //
  171. // PD_STRETCHDIB_1_1_OK (StretchDIBits faster than Set+BitBlt)
  172. // displayFPS[N][0][0] > displayFPS[N][0][1]
  173. //
  174. // PD_STRETCHDIB_1_2_OK (StretchDIBits 1:2 is faster the doing it our self)
  175. // displayFPS[N][1][0] > displayFPS[N][1][1]
  176. //
  177. // PD_STRETCHDIB_1_N_OK (StretchDIBits 1:N is faster the doing it our self)
  178. // displayFPS[N][2][0] > displayFPS[N][2][1]
  179. //
  180. static UINT displayFPS[7] // 0=4bbp, 1=8bpp, 2=16bpp, 3=24bpp, 4=32bit, 5=BitBlt, 6=Dib ~1:1
  181. [3] // 0=1:1, 1=1:2, 2=1:N
  182. [2]; // 0=DrawDib, 1=Set+Blt (or ~1:1 for BitBlt)
  183. #ifndef _WIN32
  184. /***************************************************************************
  185. *
  186. * @doc INTERNAL
  187. *
  188. * @api LONG | atoi | local version of atoi
  189. *
  190. ***************************************************************************/
  191. INLINE STATICFN int NEAR PASCAL atoi(TCHAR FAR *sz)
  192. {
  193. int i = 0;
  194. while (*sz && *sz >= TEXT('0') && *sz <= TEXT('9'))
  195. i = i*10 + *sz++ - TEXT('0');
  196. return i;
  197. }
  198. #endif
  199. STATICFN void FAR InitProfDisp(BOOL fForceMe)
  200. {
  201. TCHAR ach[80];
  202. TCHAR achDisplay[80];
  203. HDC hdc;
  204. int i;
  205. int n;
  206. int BitDepth;
  207. GetPrivateProfileString(szBoot, szDisplay, szNull,
  208. achDisplay, ARRAYLEN(achDisplay), szSystemIni);
  209. hdc = GetDC(NULL);
  210. BitDepth = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL);
  211. n = GetBitmapType();
  212. switch(n & BM_TYPE)
  213. {
  214. default:
  215. case BM_8BIT: ach[0] = 0; break;
  216. case BM_16555: lstrcpy(ach, sz555); break;
  217. case BM_16565: lstrcpy(ach, sz565); break;
  218. case BM_24BGR:
  219. case BM_32BGR: lstrcpy(ach, szBGR); break;
  220. case BM_24RGB:
  221. case BM_32RGB: lstrcpy(ach, szRGB); break;
  222. }
  223. wsprintf(achDisplay + lstrlen(achDisplay), szNxNxNxType,
  224. GetSystemMetrics(SM_CXSCREEN),
  225. GetSystemMetrics(SM_CYSCREEN),
  226. BitDepth,(LPTSTR)ach, n >> 4);
  227. ReleaseDC(NULL, hdc);
  228. mmGetProfileString(szDrawdib, achDisplay, szNull, ach, ARRAYLEN(ach));
  229. for (i=0,n=1; n<5; n++)
  230. {
  231. if (ach[i] == TEXT('\0'))
  232. {
  233. result[n] = -1;
  234. }
  235. else
  236. {
  237. #ifdef UNICODE
  238. result[n] = wcstol(ach+i, NULL, 10);
  239. #else
  240. result[n] = atoi(ach+i);
  241. #endif
  242. while (ach[i] != 0 && ach[i] != TEXT(','))
  243. i++;
  244. if (ach[i] != 0)
  245. i++;
  246. }
  247. }
  248. if (fForceMe ||
  249. result[1] == -1 ||
  250. result[2] == -1 ||
  251. result[3] == -1 ||
  252. result[4] == -1)
  253. {
  254. TestDibFormats(BITMAP_X,BITMAP_Y,fForceMe);
  255. wsprintf(ach, szEntryFormat,
  256. result[1], result[2], result[3], result[4]);
  257. mmWriteProfileString(szDrawdib, achDisplay, ach);
  258. #if 0
  259. //
  260. // if the DISPLAY driver isn't very good drawing DIBs then warn the user.
  261. //
  262. // we will only warn if the device is at least 8bpp
  263. //
  264. if (BitDepth >= 8 && !(result[1] & PD_STRETCHDIB_1_1_OK))
  265. {
  266. #ifndef _WIN32
  267. MessageBox(NULL, szDisplaySucks, szWarning, MB_OK | MB_SYSTEMMODAL | MB_ICONEXCLAMATION);
  268. #else
  269. RPF(("Display driver probably too slow for AVI"));
  270. #endif
  271. }
  272. #endif
  273. }
  274. }
  275. /****************************************************************
  276. *
  277. *****************************************************************/
  278. STATICFN UINT NEAR PASCAL ProfDispCanDrawDib(LPBITMAPINFOHEADER lpbi)
  279. {
  280. int n;
  281. LONG l;
  282. HDC hdc;
  283. UINT w;
  284. if (result[1] == -1 || lpbi==NULL)
  285. InitProfDisp(FALSE);
  286. if (lpbi == NULL)
  287. return 0;
  288. switch (lpbi->biCompression)
  289. {
  290. //
  291. // standard format use our pre-computed performance numbers.
  292. //
  293. case BI_RGB:
  294. n = (int)lpbi->biBitCount / 8;
  295. return result[n];
  296. case BI_RLE4:
  297. case BI_RLE8:
  298. //
  299. // return the un-rle results *but* RLE can't stretch
  300. //
  301. return result[1] & PD_CAN_DRAW_DIB|PD_STRETCHDIB_1_1_OK;
  302. //
  303. // custom format, ask the DISPLAY driver
  304. //
  305. default:
  306. l = 0;
  307. w = 0;
  308. hdc = GetDC(NULL);
  309. if (Escape(hdc, QUERYDIBSUPPORT, (int)lpbi->biSize, (LPVOID)lpbi, (LPVOID)&l) > 0)
  310. {
  311. // make sure the driver realy realy gave us back flags.
  312. if (l & ~(0x00FF))
  313. l = 0;
  314. if (l & QDI_DIBTOSCREEN)
  315. w |= PD_STRETCHDIB_1_1_OK | PD_CAN_DRAW_DIB;
  316. if (l & QDI_STRETCHDIB)
  317. w |= PD_CAN_STRETCHDIB;
  318. /* what about stretching? fast? */
  319. }
  320. ReleaseDC(NULL, hdc);
  321. return w;
  322. }
  323. }
  324. /****************************************************************
  325. * @doc EXTERNAL DrawDib
  326. *
  327. * @api void | DrawDibProfileDisplay | Profiles the display for DrawDib.
  328. *
  329. * @parm LPBITMAPINFOHEADER | parms | Specifies bitmap information.
  330. * Set to null if no information is available.
  331. *
  332. *****************************************************************/
  333. LRESULT VFWAPI DrawDibProfileDisplay(LPBITMAPINFOHEADER lpbi)
  334. {
  335. if (lpbi == NULL)
  336. {
  337. InitProfDisp(TRUE) ;
  338. return (DWORD_PTR)(LPVOID)displayFPS;
  339. }
  340. else
  341. return ProfDispCanDrawDib(lpbi);
  342. }
  343. LPVOID FAR TestDibFormats(int dx, int dy, BOOL fForceMe)
  344. {
  345. int dxScreen,dyScreen;
  346. HDC hdc;
  347. int n;
  348. int i;
  349. #ifndef DAYTONA
  350. HCURSOR hcur;
  351. HPALETTE hpal;
  352. RECT rc;
  353. HWND hwnd;
  354. HWND hwndActive;
  355. DWORD fdwExStyle;
  356. #endif
  357. BOOL fMiniDriver = FALSE;
  358. TCHAR szProfiling[80];
  359. // dont change this without changing MSVIDEO.RC
  360. #define IDS_PROFILING 4000
  361. extern HMODULE ghInst; // in MSVIDEO\init.c
  362. // fill in displayFPS[7][3][2];
  363. for (n=0; n<7; n++)
  364. for (i=0; i<3; i++)
  365. displayFPS[n][i][0] =
  366. displayFPS[n][i][1] = 0;
  367. #ifndef CAPS1
  368. #define CAPS1 94
  369. #endif
  370. #ifndef C1_DIBENGINE
  371. #define C1_DIBENGINE 0x0010
  372. #endif
  373. hdc = GetDC(NULL);
  374. i = GetDeviceCaps(hdc, CAPS1);
  375. n = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
  376. ReleaseDC(NULL, hdc);
  377. if (i & C1_DIBENGINE) {
  378. DPF(("Display is DIB Engine-based; not profiling...."));
  379. fMiniDriver = TRUE;
  380. result[0] = 1;
  381. if (n < 8) {
  382. result[1] = 33; // 8bpp
  383. result[2] = 0; // 16bpp
  384. result[3] = 0; // 24bpp
  385. result[4] = 0; // 32bpp
  386. } else if (n == 8) {
  387. result[1] = 55; // 8bpp
  388. result[2] = 0; // 16bpp
  389. result[3] = 0; // 24bpp
  390. result[4] = 0; // 32bpp
  391. } else {
  392. result[1] = 37; // 8bpp
  393. result[2] = 5; // 16bpp
  394. result[3] = 5; // 24bpp
  395. result[4] = 5; // 32bpp
  396. }
  397. // Normally, if we are a mini-driver, we don't need to profile the
  398. // display. But because of a Kings Quest VII bug, we have to at least
  399. // create a window, or they'll hang. They call us with the fForceMe
  400. // flag on, so we can't return now, we have to go ahead and pretend
  401. // we're profiling. But we don't want to actually profile the display,
  402. // so we'll just do everything BUT the calls to ProfileDisplay() if
  403. // we're a mini driver.
  404. if (!fForceMe)
  405. return (LPVOID) displayFPS;
  406. }
  407. if (!LoadString(ghInst, IDS_PROFILING, szProfiling, sizeof(szProfiling)/sizeof(TCHAR)))
  408. lstrcpy(szProfiling, szProfilingDefault);
  409. #ifdef _WIN32
  410. #define GetCurrentInstance() GetModuleHandle(NULL)
  411. #else
  412. #define GetCurrentInstance() GetWindowWord(IsWindow(GetActiveWindow()) ? GetActiveWindow() : GetDesktopWindow(), GWW_HINSTANCE)
  413. #endif
  414. dxScreen = GetSystemMetrics(SM_CXSCREEN);
  415. dyScreen = GetSystemMetrics(SM_CYSCREEN);
  416. #ifdef DAYTONA
  417. // we don't do any drawing - just get caps
  418. hdc = GetDC(NULL);
  419. #else
  420. SetRect(&rc, 0, 0, dx, dy);
  421. AdjustWindowRect(&rc, (WS_OVERLAPPED | WS_CAPTION | WS_BORDER), FALSE);
  422. OffsetRect(&rc, -rc.left, -rc.top);
  423. fdwExStyle = gfIsRTL ? WS_EX_LEFTSCROLLBAR | WS_EX_RIGHT | WS_EX_RTLREADING : 0;
  424. hwnd = CreateWindowEx(fdwExStyle,
  425. szListbox, // Class name
  426. szProfiling, // Caption
  427. LBS_NOINTEGRALHEIGHT|
  428. (WS_OVERLAPPED | WS_CAPTION | WS_BORDER),
  429. (dxScreen - rc.right) / 2,
  430. (dyScreen - rc.bottom) / 2,
  431. rc.right,
  432. rc.bottom,
  433. (HWND)NULL, // Parent window (no parent)
  434. (HMENU)NULL, // use class menu
  435. GetCurrentInstance(), // handle to window instance
  436. (LPTSTR)NULL // no params to pass on
  437. );
  438. // make the window top most
  439. SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0,
  440. SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
  441. // and show it.
  442. SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
  443. SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_SHOWWINDOW);
  444. // and activate it.
  445. hwndActive = GetActiveWindow();
  446. SetActiveWindow(hwnd);
  447. hdc = GetDC(hwnd);
  448. hcur = SetCursor(NULL);
  449. if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
  450. {
  451. hpal = CreateTestPalette(TRUE);
  452. SelectPalette(hdc, hpal, FALSE);
  453. RealizePalette(hdc);
  454. }
  455. Yield();
  456. Yield();
  457. Yield();
  458. #endif
  459. #ifndef _WIN32
  460. //
  461. // make sure no junk is around in the SmartDrv cache, this will
  462. // mess with the timings
  463. //
  464. _asm {
  465. mov ax,4A10h ; tell Bambi to flush the cache
  466. mov bx,0001h
  467. int 2fh
  468. mov ah,0Dh ; tell other people to commit...
  469. int 21h
  470. }
  471. #else
  472. GdiFlush();
  473. #endif
  474. // King's Quest bug - don't actually profile
  475. if (!fMiniDriver)
  476. {
  477. for (n=FIRST_N; n<5; n++)
  478. result[n] = ProfileDisplay(hdc, n==0 ? 4 : n*8, dx, dy);
  479. }
  480. #ifndef DAYTONA
  481. #ifdef DEBUG
  482. if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
  483. {
  484. HPALETTE hpalT;
  485. //
  486. // re-run the 8bit tests with a background palette
  487. //
  488. SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), FALSE);
  489. RealizePalette(hdc);
  490. hpalT = CreateTestPalette(FALSE);
  491. SelectPalette(hdc, hpalT, TRUE);
  492. RealizePalette(hdc);
  493. Yield();
  494. Yield();
  495. Yield();
  496. if (!fMiniDriver)
  497. ProfileDisplay(hdc, 8, dx, dy);
  498. SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), FALSE);
  499. RealizePalette(hdc);
  500. DeleteObject(hpalT);
  501. DeleteObject(hpal);
  502. }
  503. #endif
  504. SetCursor(hcur);
  505. ReleaseDC(hwnd, hdc);
  506. if (hwndActive)
  507. SetActiveWindow(hwndActive);
  508. DestroyWindow(hwnd) ;
  509. #else
  510. ReleaseDC(NULL, hdc);
  511. #endif
  512. return (LPVOID)displayFPS;
  513. }
  514. STATICFN UINT ProfileDisplay(HDC hdc, UINT wBitsToTest, int dx, int dy)
  515. {
  516. LPBITMAPINFOHEADER alpbi[N_FRAMES];
  517. UINT wRetval;
  518. if (GetDeviceCaps(hdc, BITSPIXEL) *
  519. GetDeviceCaps(hdc, PLANES) <= 8 && wBitsToTest > 8)
  520. return 0;
  521. alpbi[0] = NULL;
  522. #ifndef DAYTONA
  523. MakeFrames(alpbi,wBitsToTest,dx,dy);
  524. if (!alpbi[0])
  525. return (UINT)-1 ;
  526. #endif
  527. wRetval = 0 ;
  528. switch(DrawDibTest(hdc, wBitsToTest, alpbi,N_FRAMES,100))
  529. {
  530. case CANT_DO_THESE_BITS:
  531. goto done ;
  532. case CANT_DO_STRETCHDIBITS:
  533. wRetval = PD_CAN_DRAW_DIB ;
  534. goto done ;
  535. case STRETCHDI_BUT_TRY_BLT:
  536. // stretchdi_faster, but bitblt is >20% faster than
  537. // StretchDIBits, so worth trying decomp to bitmap.
  538. wRetval = PD_BITBLT_FAST;
  539. /* falling through .... */
  540. case STRETCHDI_FASTER:
  541. wRetval |= PD_STRETCHDIB_1_1_OK ;
  542. /* Falling through */
  543. case OTHER_FASTER:
  544. wRetval |= PD_CAN_DRAW_DIB;
  545. }
  546. if (DrawDibTest(hdc, wBitsToTest, alpbi,N_FRAMES,STRETCH_N) == STRETCHDI_FASTER)
  547. wRetval |= PD_STRETCHDIB_1_N_OK|PD_CAN_STRETCHDIB;
  548. if (DrawDibTest(hdc, wBitsToTest, alpbi,N_FRAMES,200) == STRETCHDI_FASTER)
  549. wRetval |= PD_STRETCHDIB_1_2_OK|PD_CAN_STRETCHDIB;
  550. done:
  551. #ifndef DAYTONA
  552. FreeFrames(alpbi);
  553. #endif
  554. return wRetval;
  555. }
  556. STATICFN UINT DrawDibTest(HDC hdc, UINT wBits, LPBITMAPINFOHEADER FAR *alpbi,UINT wFrames,UINT wStretch)
  557. {
  558. int n ;
  559. BOOL fBack;
  560. #ifndef DAYTONA
  561. HDC hdcMem ;
  562. HBITMAP hbitmap ;
  563. HBITMAP hbitmapOld ;
  564. DWORD wSizeColors ;
  565. volatile LPBITMAPINFOHEADER lpbi ;
  566. LPBYTE bits ;
  567. LPBITMAPINFOHEADER lpbiStretch ;
  568. LPBYTE bitsStretch ;
  569. DWORD time0 = 0;
  570. DWORD time1 = 0;
  571. DWORD time2 = 0;
  572. RECT rc ;
  573. int XDest,YDest,cXDest,cYDest ;
  574. int cXSrc,cYSrc ;
  575. int i ;
  576. UINT DibUsage;
  577. BOOL f;
  578. DWORD dwSize;
  579. DWORD dwSizeImage;
  580. HPALETTE hpal;
  581. int q ;
  582. lpbi = alpbi[0];
  583. /*
  584. ** Get stuff common to all frames
  585. */
  586. //cXSrc = (int)lpbi->biWidth ;
  587. //cYSrc = (int)lpbi->biHeight ;
  588. //cXDest = wStretch*(int)lpbi->biWidth/100 ;
  589. //cYDest = wStretch*(int)lpbi->biHeight/100 ;
  590. cXSrc = 100*(int)lpbi->biWidth/wStretch ;
  591. cYSrc = 100*(int)lpbi->biHeight/wStretch ;
  592. cXDest = (int)lpbi->biWidth ;
  593. cYDest = (int)lpbi->biHeight ;
  594. #endif
  595. // are we background'ed
  596. n = wStretch == 100 ? 0 : wStretch == 200 ? 1 : 2;
  597. fBack = wBits==8 && displayFPS[1][n][0] != 0;
  598. #ifndef DAYTONA
  599. if (lpbi->biBitCount <= 8)
  600. wSizeColors = sizeof(RGBQUAD) * (int)(lpbi->biClrUsed ? lpbi->biClrUsed : (1 << (int)lpbi->biBitCount));
  601. else
  602. wSizeColors = 0 ;
  603. bits = (LPBYTE)lpbi + (int)lpbi->biSize + wSizeColors ;
  604. #endif
  605. if (GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES) <= 8 && wBits > 8)
  606. return CANT_DO_STRETCHDIBITS;
  607. ////if (wStretch != 100 && !(GetDeviceCaps(hdc,RASTERCAPS)&(RC_STRETCHDIB|RC_STRETCHBLT)))
  608. if (wStretch != 100 && !(GetDeviceCaps(hdc,RASTERCAPS)&(RC_STRETCHDIB)))
  609. return CANT_DO_STRETCHDIBITS ;
  610. if (wStretch != 100 && wBits == 4)
  611. return CANT_DO_STRETCHDIBITS ;
  612. #ifndef _WIN32
  613. if (wStretch != 100 && (GetWinFlags() & WF_CPU286))
  614. return STRETCHDI_FASTER;
  615. #endif
  616. // if (wStretch != 100 && wBits > 8) //!!!
  617. // wFrames = 4;
  618. #ifdef DAYTONA
  619. return STRETCHDI_FASTER;
  620. #else
  621. lpbi->biWidth = cXSrc;
  622. lpbi->biHeight = cYSrc;
  623. // get current palette
  624. hpal = SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), FALSE);
  625. SelectPalette(hdc, hpal, fBack);
  626. RealizePalette(hdc);
  627. if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
  628. {
  629. DibUsage = DIB_PAL_COLORS;
  630. }
  631. else
  632. {
  633. DibUsage = DIB_RGB_COLORS;
  634. }
  635. ////GetClientRect(hwnd,&rc) ;
  636. GetClipBox(hdc,&rc) ;
  637. XDest = (rc.right - cXDest)/2 ;
  638. YDest = (rc.bottom - cYDest)/2 ;
  639. time0 = 0;
  640. if (wBits == 16 && !IsDisplay16Bit(hdc))
  641. goto test_bitmap;
  642. if (wBits == 32 && !IsDisplay32Bit(hdc))
  643. goto test_bitmap;
  644. time0 = timeGetTime() ;
  645. for (i=0; i<(int)wFrames; i++)
  646. {
  647. lpbi = alpbi[i%N_FRAMES];
  648. bits = ((LPBYTE)lpbi) + (int)lpbi->biSize + wSizeColors ;
  649. #ifdef _WIN32
  650. /*
  651. * to correctly model the behaviour of DrawDibDraw, we
  652. * use SetDIBitsToDevice if 1:1 (source rect == dest rect).
  653. */
  654. if ( (cXSrc == cXDest) && (cYSrc == cYDest)) {
  655. f = SetDIBitsToDevice(hdc, XDest, YDest, cXDest, cYDest,
  656. 0, 0, 0, cYSrc,
  657. bits, (LPBITMAPINFO)lpbi, DibUsage);
  658. } else
  659. #endif
  660. {
  661. f = StretchDIBits(
  662. hdc,
  663. XDest,YDest,cXDest,cYDest,
  664. 0,0,cXSrc, cYSrc,
  665. bits,(LPBITMAPINFO)lpbi,DibUsage,SRCCOPY) ;
  666. }
  667. }
  668. GdiFlush();
  669. time0 = timeGetTime() - time0 ;
  670. if (f == 0)
  671. time0 = 0;
  672. test_bitmap:
  673. time1 = 0;
  674. if (wStretch == 100)
  675. {
  676. PSETDI psd;
  677. psd = (PSETDI)LocalAlloc(LPTR, sizeof(SETDI));
  678. if (psd == NULL)
  679. goto done;
  680. hbitmap = CreateCompatibleBitmap(hdc,cXDest,cYDest) ;
  681. hdcMem = CreateCompatibleDC(NULL) ;
  682. hbitmapOld = SelectObject(hdcMem,hbitmap) ;
  683. f = SetBitmapBegin(
  684. psd, // structure
  685. hdc, // device
  686. hbitmap, // bitmap to set into
  687. lpbi, // --> BITMAPINFO of source
  688. DibUsage);
  689. psd->hdc = hdc;
  690. if (f)
  691. f = SetBitmap(psd, 0, 0, cXDest, cYDest, bits, 0, 0, cXDest, cYDest);
  692. if (f)
  693. {
  694. // SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), FALSE);
  695. // RealizePalette(hdc);
  696. time1 = timeGetTime();
  697. for (i=0; i<(int)wFrames; i++)
  698. {
  699. SetBitmap(psd, 0, 0, cXDest, cYDest, bits, 0, 0, cXDest, cYDest);
  700. BitBlt(hdc,XDest,YDest,cXDest,cYDest,hdcMem,0,0,SRCCOPY);
  701. }
  702. GdiFlush();
  703. time1 = timeGetTime() - time1 ;
  704. SetBitmapEnd(psd);
  705. // SelectPalette(hdc, hpal, fBack);
  706. // RealizePalette(hdc);
  707. }
  708. #ifdef DEBUG
  709. if ((int)lpbi->biBitCount == GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES))
  710. {
  711. time2 = timeGetTime() ;
  712. for (i=0; i<(int)wFrames; i++)
  713. BitBlt(hdc,XDest,YDest,cXDest,cYDest,hdcMem,0,0,SRCCOPY) ;
  714. GdiFlush();
  715. time2 = timeGetTime() - time2 ;
  716. }
  717. #endif
  718. LocalFree((HLOCAL)psd);
  719. SelectObject(hdcMem,hbitmapOld) ;
  720. DeleteObject(hbitmap) ;
  721. DeleteDC(hdcMem) ;
  722. } else {
  723. if (wBits == 16 && !IsDisplay16Bit(hdc))
  724. goto done;
  725. if (wBits == 32 && !IsDisplay32Bit(hdc))
  726. goto done;
  727. // Calc size we need to allocate for stretched bits
  728. dwSizeImage = (DWORD)(UINT)cYDest*(DWORD)(((UINT)cXDest*(UINT)lpbi->biBitCount+31)/32*4);
  729. dwSize = (int)lpbi->biSize + (int)lpbi->biClrUsed*sizeof(RGBQUAD);
  730. if ((lpbiStretch = (LPVOID)GlobalAllocPtr(GHND,dwSize + dwSizeImage)) != NULL)
  731. {
  732. hmemcpy(lpbiStretch, lpbi, dwSize);
  733. lpbiStretch->biWidth = cXDest;
  734. lpbiStretch->biHeight = cYDest;
  735. lpbiStretch->biSizeImage = dwSizeImage;
  736. bitsStretch = (LPBYTE)lpbiStretch + (UINT)dwSize;
  737. time1 = timeGetTime() ;
  738. for (i=0; i<(int)wFrames; i++)
  739. {
  740. lpbi = alpbi[i%N_FRAMES];
  741. bits = ((LPBYTE)lpbi) + (int)lpbi->biSize + wSizeColors;
  742. StretchDIB(
  743. lpbiStretch,bitsStretch,
  744. 0,0,cXDest,cYDest,
  745. lpbi,bits,
  746. 0,0,cXSrc,cYSrc);
  747. #ifdef _WIN32
  748. /*
  749. * to correctly model the behaviour of DrawDibDraw, we
  750. * use SetDIBitsToDevice if 1:1 (source rect == dest rect).
  751. */
  752. f = SetDIBitsToDevice(hdc, XDest, YDest, cXDest, cYDest,
  753. 0, 0, 0, cYSrc,
  754. bits, (LPBITMAPINFO)lpbi, DibUsage);
  755. #else
  756. f = StretchDIBits(
  757. hdc,
  758. XDest,YDest,cXDest,cYDest,
  759. 0,0,cXDest,cYDest,
  760. bitsStretch,(LPBITMAPINFO)lpbiStretch,DibUsage,SRCCOPY);
  761. #endif
  762. }
  763. GdiFlush();
  764. time1 = timeGetTime() - time1 ;
  765. GlobalFreePtr(lpbiStretch);
  766. if (f == 0)
  767. time1 = 0;
  768. }
  769. #ifdef DEBUG
  770. if ((int)lpbi->biBitCount == GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES))
  771. {
  772. hbitmap = CreateCompatibleBitmap(hdc,cXSrc,cYSrc) ;
  773. hdcMem = CreateCompatibleDC(NULL) ;
  774. hbitmapOld = SelectObject(hdcMem,hbitmap) ;
  775. lpbi = alpbi[0];
  776. bits = ((LPBYTE)lpbi) + (int)lpbi->biSize + wSizeColors;
  777. SetDIBits(hdc,hbitmap,0,cYSrc,bits,(LPBITMAPINFO)lpbi,DibUsage);
  778. SelectPalette(hdcMem, hpal, FALSE);
  779. // RealizePalette(hdcMem);
  780. time2 = timeGetTime() ;
  781. for (i=0; i<(int)wFrames; i++)
  782. StretchBlt(hdc,XDest,YDest,cXDest,cYDest,hdcMem,0,0,cXSrc,cYSrc,SRCCOPY) ;
  783. GdiFlush();
  784. time2 = timeGetTime() - time2 ;
  785. SelectObject(hdcMem,hbitmapOld) ;
  786. DeleteObject(hbitmap) ;
  787. DeleteDC(hdcMem) ;
  788. }
  789. #endif
  790. }
  791. done:
  792. /* time0 is the time required to do StretchDIBits */
  793. /* time1 is the time required to do Set + BitBlt */
  794. /* time2 is the time required to do a BitBlt */
  795. //
  796. // compute the FPS * 10 and store for later use.
  797. //
  798. n = wStretch == 100 ? 0 : wStretch == 200 ? 1 : 2;
  799. q = fBack ? BACKINDEX : wBits/8;
  800. time1 = (DWORD)MulDiv((int)time1,PROFDISP_FUDGE,100);
  801. displayFPS[q][n][0] = time0 ? (UINT)MulDiv(wFrames,10000,(int)time0) : 0;
  802. displayFPS[q][n][1] = time1 ? (UINT)MulDiv(wFrames,10000,(int)time1) : 0;
  803. if (time2)
  804. displayFPS[BITBLTINDEX][n][fBack] = (UINT)MulDiv(wFrames,10000,(int)time2);
  805. RPF(("DrawDibTest %dx%dx%d %d StretchDIBits=%04lu SetDI+BitBlt=%04lu BitBlt=%04lu %ls",cXDest,cYDest,wBits,wStretch,time0,time1,time2,(LPSTR)(time0 < time1 ? TEXT("") : TEXT("SLOW"))));
  806. lpbi->biWidth = cXDest;
  807. lpbi->biHeight = cYDest;
  808. if (time0 == 0)
  809. {
  810. return time1 ? OTHER_FASTER : CANT_DO_THESE_BITS;
  811. }
  812. else
  813. {
  814. if (time1) {
  815. if (time0 < time1) {
  816. // in the 1:1 case, see if it's worth trying decomp to bitmap
  817. // - this maybe worthwhile even if StretchDIBits is faster
  818. // than SetDIBits+BitBlt, so long as BitBlt is > 20% or so
  819. // faster than StretchDIBits.
  820. if ((wStretch == 100) && (time2) &&
  821. ( (time0 * 80 / 100) > time2)) {
  822. return STRETCHDI_BUT_TRY_BLT;
  823. } else {
  824. return STRETCHDI_FASTER;
  825. }
  826. } else {
  827. return OTHER_FASTER;
  828. }
  829. } else {
  830. return STRETCHDI_FASTER;
  831. }
  832. }
  833. #endif
  834. }
  835. #ifndef DAYTONA
  836. STATICFN void MakeFrames(LPBITMAPINFOHEADER FAR *alpbi, UINT bits, UINT wXSize,UINT wYSize )
  837. {
  838. int i ;
  839. int x ;
  840. int y ;
  841. LPBITMAPINFOHEADER lpbi ;
  842. DWORD dwSizeImage;
  843. BYTE _huge *pb;
  844. WORD FAR *pw;
  845. DWORD FAR *pdw;
  846. UINT rc;
  847. HDC hdc;
  848. hdc = GetDC(NULL);
  849. rc = GetDeviceCaps(hdc, RASTERCAPS);
  850. ReleaseDC(NULL,hdc);
  851. FreeFrames(alpbi);
  852. dwSizeImage = wYSize*(DWORD)((wXSize*bits/8+3)&~3);
  853. lpbi = (LPVOID)GlobalAllocPtr(GHND,sizeof(BITMAPINFOHEADER)+dwSizeImage + 1024);
  854. lpbi->biSize = sizeof(BITMAPINFOHEADER) ;
  855. lpbi->biWidth = wXSize ;
  856. lpbi->biHeight = wYSize ;
  857. lpbi->biPlanes = 1 ;
  858. lpbi->biBitCount = bits ;
  859. lpbi->biCompression = BI_RGB ;
  860. lpbi->biSizeImage = dwSizeImage;
  861. lpbi->biXPelsPerMeter = 0 ;
  862. lpbi->biYPelsPerMeter = 0 ;
  863. lpbi->biClrUsed = 0 ;
  864. lpbi->biClrImportant = 0 ;
  865. // !!! These should be RGB DIBs if the device isn't a palette device!
  866. if (bits == 4)
  867. {
  868. lpbi->biClrUsed = 16;
  869. }
  870. else if (bits == 8)
  871. {
  872. lpbi->biClrUsed = 256;
  873. }
  874. pb = (BYTE _huge *)lpbi+lpbi->biSize+lpbi->biClrUsed * sizeof(RGBQUAD);
  875. if (bits == 4)
  876. {
  877. for (y=0; y<(int)wYSize; y++)
  878. for (x=0; x<(int)wXSize; x += 2)
  879. {
  880. i = ((x / (wXSize / 4)) + 4 * (y / (wYSize / 4)));
  881. i += i * 16;
  882. *pb++ = i;
  883. }
  884. if (rc & RC_PALETTE)
  885. {
  886. pw = (LPVOID)((LPBYTE)lpbi+(int)lpbi->biSize);
  887. for (i=0; i<8; i++)
  888. *pw++ = i;
  889. for (i=0; i<8; i++)
  890. *pw++ = 248+i;
  891. }
  892. else
  893. {
  894. pdw = (LPVOID)((LPBYTE)lpbi+(int)lpbi->biSize);
  895. *pdw++ = 0x00000000; // 0000 black
  896. *pdw++ = 0x00800000; // 0001 dark red
  897. *pdw++ = 0x00008000; // 0010 dark green
  898. *pdw++ = 0x00808000; // 0011 mustard
  899. *pdw++ = 0x00000080; // 0100 dark blue
  900. *pdw++ = 0x00800080; // 0101 purple
  901. *pdw++ = 0x00008080; // 0110 dark turquoise
  902. *pdw++ = 0x00C0C0C0; // 1000 gray
  903. *pdw++ = 0x00808080; // 0111 dark gray
  904. *pdw++ = 0x00FF0000; // 1001 red
  905. *pdw++ = 0x0000FF00; // 1010 green
  906. *pdw++ = 0x00FFFF00; // 1011 yellow
  907. *pdw++ = 0x000000FF; // 1100 blue
  908. *pdw++ = 0x00FF00FF; // 1101 pink (magenta)
  909. *pdw++ = 0x0000FFFF; // 1110 cyan
  910. *pdw++ = 0x00FFFFFF; // 1111 white
  911. }
  912. }
  913. else if (bits == 8)
  914. {
  915. for (y=0; y<(int)wYSize; y++)
  916. for (x=0; x<(int)wXSize; x++)
  917. {
  918. *pb++ = 10 + y * 236 / (int)wYSize;
  919. }
  920. if (rc & RC_PALETTE)
  921. {
  922. pw = (LPVOID)((LPBYTE)lpbi+(int)lpbi->biSize);
  923. for (i=0; i<256; i++)
  924. *pw++ = i;
  925. }
  926. else
  927. {
  928. pdw = (LPVOID)((LPBYTE)lpbi+(int)lpbi->biSize);
  929. for (i=0; i<256; i++)
  930. *pdw++ = RGB(i,0,0);
  931. }
  932. }
  933. else if (bits == 16)
  934. {
  935. for (y=0; y<(int)wYSize; y++)
  936. for (x=0; x<(int)wXSize; x++)
  937. {
  938. *pb++ = (BYTE) ((UINT)y * 32u / wYSize);
  939. *pb++ = (BYTE)(((UINT)x * 32u / wXSize) << 2);
  940. }
  941. }
  942. else if (bits == 24)
  943. {
  944. for (y=0; y<(int)wYSize; y++)
  945. for (x=0; x<(int)wXSize; x++)
  946. {
  947. *pb++ = (BYTE) (y * 256l / wYSize);
  948. *pb++ = (BYTE)~(x * 256l / wXSize);
  949. *pb++ = (BYTE) (x * 256l / wXSize);
  950. }
  951. }
  952. else if (bits == 32)
  953. {
  954. for (y=0; y<(int)wYSize; y++)
  955. for (x=0; x<(int)wXSize; x++)
  956. {
  957. *pb++ = (BYTE)~(x * 256l / wXSize);
  958. *pb++ = (BYTE) (y * 256l / wYSize);
  959. *pb++ = (BYTE) (x * 256l / wXSize);
  960. *pb++ = 0;
  961. }
  962. }
  963. for ( i=0; i<N_FRAMES; i++ )
  964. alpbi[i] = lpbi;
  965. }
  966. STATICFN void FreeFrames(LPBITMAPINFOHEADER FAR *alpbi)
  967. {
  968. UINT w ;
  969. if (!alpbi[0])
  970. return ;
  971. for (w=0; w<N_FRAMES; w++)
  972. if (alpbi[w] && (w == 0 || alpbi[w] != alpbi[w-1]))
  973. GlobalFreePtr(alpbi[w]);
  974. for (w=0; w<N_FRAMES; w++)
  975. alpbi[w] = NULL;
  976. }
  977. #endif
  978. #if 0
  979. /*
  980. * CreateTestPalette()
  981. *
  982. */
  983. STATICFN HPALETTE CreateTestPalette(BOOL f)
  984. {
  985. HDC hdc;
  986. int i;
  987. struct {
  988. WORD palVersion;
  989. WORD palNumEntries;
  990. PALETTEENTRY palPalEntry[256];
  991. } pal;
  992. pal.palNumEntries = 256;
  993. pal.palVersion = 0x0300;
  994. hdc = GetDC(NULL);
  995. GetSystemPaletteEntries(hdc, 0, 256, &pal.palPalEntry[0]);
  996. ReleaseDC(NULL,hdc);
  997. for (i = 10; i < 246; i++)
  998. pal.palPalEntry[i].peFlags = PC_NOCOLLAPSE;
  999. if (!f)
  1000. pal.palPalEntry[0].peRed = 255;
  1001. return CreatePalette((LPLOGPALETTE)&pal);
  1002. }
  1003. #else
  1004. /*
  1005. * CreateTestPalette()
  1006. *
  1007. */
  1008. STATICFN HPALETTE CreateTestPalette(BOOL fUp)
  1009. {
  1010. int i;
  1011. HDC hdc;
  1012. struct {
  1013. WORD palVersion;
  1014. WORD palNumEntries;
  1015. PALETTEENTRY palPalEntry[256];
  1016. } pal;
  1017. pal.palNumEntries = 256;
  1018. pal.palVersion = 0x0300;
  1019. for (i = 0; i < 256; i++)
  1020. {
  1021. pal.palPalEntry[i].peRed = 0;
  1022. pal.palPalEntry[i].peGreen = 0;
  1023. pal.palPalEntry[i].peBlue = (BYTE)(fUp ? i : 255 - i);
  1024. pal.palPalEntry[i].peFlags = PC_NOCOLLAPSE;
  1025. }
  1026. hdc = GetDC(NULL);
  1027. GetSystemPaletteEntries(hdc, 0, 10, &pal.palPalEntry[0]);
  1028. GetSystemPaletteEntries(hdc, 246, 10, &pal.palPalEntry[246]);
  1029. ReleaseDC(NULL,hdc);
  1030. return CreatePalette((LPLOGPALETTE)&pal);
  1031. }
  1032. #endif
  1033. #define RGB555_RED 0x7C00
  1034. #define RGB555_GREEN 0x03E0
  1035. #define RGB555_BLUE 0x001F
  1036. STATICFN BOOL IsDisplay16Bit( HDC hdc )
  1037. {
  1038. struct {
  1039. BITMAPINFOHEADER bi;
  1040. RGBQUAD rgbq[256];
  1041. } dib;
  1042. int w ;
  1043. LONG l=0;
  1044. WORD bits[2];
  1045. COLORREF cref ;
  1046. w = GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES) ;
  1047. if ( w < 15 )
  1048. return FALSE;
  1049. /*
  1050. ** OK, the hardware is at least 16 bits - now test to see
  1051. ** if they impelement 5-5-5 RGB
  1052. */
  1053. dib.bi.biSize = sizeof(BITMAPINFOHEADER);
  1054. dib.bi.biWidth = 1;
  1055. dib.bi.biHeight = 1;
  1056. dib.bi.biPlanes = 1;
  1057. dib.bi.biBitCount = 16;
  1058. dib.bi.biCompression = BI_RGB;
  1059. dib.bi.biSizeImage = 4;
  1060. dib.bi.biXPelsPerMeter = 0;
  1061. dib.bi.biYPelsPerMeter = 0;
  1062. dib.bi.biClrUsed = 1;
  1063. dib.bi.biClrImportant = 0;
  1064. //
  1065. // just in case they try to decode it as rle
  1066. //
  1067. bits[0] = 0x0000; // this is RLE EOL
  1068. bits[1] = 0x0100; // this is RLE EOF
  1069. //
  1070. // send the Escape to see if they support 16bpp DIBs
  1071. //
  1072. if (Escape(hdc, QUERYDIBSUPPORT, (int)dib.bi.biSize, (LPVOID)&dib, (LPVOID)&l) > 0)
  1073. {
  1074. // make sure the driver realy realy gave us back flags.
  1075. if (l & ~(0x00FF))
  1076. l = 0;
  1077. if (l & (QDI_DIBTOSCREEN|QDI_STRETCHDIB))
  1078. return TRUE;
  1079. }
  1080. //
  1081. // they dont support the QUERYDIBSUPPORT Escape, try to draw DIBs and see
  1082. // what they do!
  1083. //
  1084. if ( !StretchDIBits(hdc,0,0,1,1,0,0,1,1,bits,(LPBITMAPINFO)&dib,DIB_RGB_COLORS,SRCCOPY))
  1085. return FALSE;
  1086. cref = GetPixel(hdc,0,0) ;
  1087. if (cref != RGB(0,0,0))
  1088. return FALSE;
  1089. /*
  1090. ** Display a red pixel of the max value and get it back with
  1091. ** GetPixel(). Verify that red has the max value in the RGB
  1092. ** triplet and green and blue are nothing.
  1093. */
  1094. bits[0] = RGB555_RED ;
  1095. if ( !StretchDIBits(hdc,0,0,1,1,0,0,1,1,bits,(LPBITMAPINFO)&dib,DIB_RGB_COLORS,SRCCOPY))
  1096. return FALSE;
  1097. cref = GetPixel(hdc,0,0) & 0x00F8F8F8;
  1098. if (cref != RGB(0xF8,0,0))
  1099. return FALSE;
  1100. /*
  1101. ** Ditto green. Note that if the driver is implementing 5-6-5, then
  1102. ** green will read back as less than full scale and we will catch
  1103. ** it here.
  1104. */
  1105. bits[0] = RGB555_GREEN ;
  1106. if ( !StretchDIBits(hdc,0,0,1,1,0,0,1,1,bits,(LPBITMAPINFO)&dib,DIB_RGB_COLORS,SRCCOPY))
  1107. return FALSE;
  1108. cref = GetPixel(hdc,0,0) & 0x00F8F8F8;
  1109. if (cref != RGB(0,0xF8,0))
  1110. return FALSE;
  1111. /*
  1112. ** Ditto blue.
  1113. */
  1114. bits[0] = RGB555_BLUE ;
  1115. if ( !StretchDIBits(hdc,0,0,1,1,0,0,1,1,bits,(LPBITMAPINFO)&dib,DIB_RGB_COLORS,SRCCOPY))
  1116. return FALSE;
  1117. cref = GetPixel(hdc,0,0) & 0x00F8F8F8;
  1118. if (cref != RGB(0,0,0xF8))
  1119. return FALSE;
  1120. return TRUE;
  1121. }
  1122. STATICFN BOOL IsDisplay32Bit( HDC hdc )
  1123. {
  1124. struct {
  1125. BITMAPINFOHEADER bi;
  1126. RGBQUAD rgbq[256];
  1127. } dib;
  1128. int w ;
  1129. LONG l=0;
  1130. DWORD bits[2];
  1131. w = GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES) ;
  1132. if ( w < 15 )
  1133. return FALSE;
  1134. /*
  1135. ** OK, the hardware is at least 16 bits - now test to see
  1136. ** if they impelement a 32 bit DIB
  1137. */
  1138. dib.bi.biSize = sizeof(BITMAPINFOHEADER);
  1139. dib.bi.biWidth = 2;
  1140. dib.bi.biHeight = 1;
  1141. dib.bi.biPlanes = 1;
  1142. dib.bi.biBitCount = 32;
  1143. dib.bi.biCompression = BI_RGB;
  1144. dib.bi.biSizeImage = 4;
  1145. dib.bi.biXPelsPerMeter = 0;
  1146. dib.bi.biYPelsPerMeter = 0;
  1147. dib.bi.biClrUsed = 1;
  1148. dib.bi.biClrImportant = 0;
  1149. //
  1150. // send the Escape to see if they support 32bpp DIBs
  1151. //
  1152. if (Escape(hdc, QUERYDIBSUPPORT, (int)dib.bi.biSize, (LPVOID)&dib, (LPVOID)&l) > 0)
  1153. {
  1154. // make sure the driver realy realy gave us back flags.
  1155. if (l & ~(0x00FF))
  1156. l = 0;
  1157. if (l & (QDI_DIBTOSCREEN|QDI_STRETCHDIB))
  1158. return TRUE;
  1159. }
  1160. bits[0] = 0x00000000;
  1161. bits[1] = 0x00FFFFFF;
  1162. //
  1163. // they dont support the QUERYDIBSUPPORT Escape, try to draw DIBs and see
  1164. // what they do!
  1165. //
  1166. if (!StretchDIBits(hdc,0,0,2,1,0,0,2,1,bits,(LPBITMAPINFO)&dib,DIB_RGB_COLORS,SRCCOPY))
  1167. return FALSE;
  1168. if (GetPixel(hdc,0,0) != 0)
  1169. return FALSE;
  1170. if ((GetPixel(hdc,1,0) & 0x00F8F8F8) != 0x00F8F8F8)
  1171. return FALSE;
  1172. return TRUE;
  1173. }