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.

1032 lines
34 KiB

  1. /*========================================================================== *
  2. *
  3. * Copyright (C) 1999-2000 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: ddcursor.c
  6. * Content: DirectDraw cursor support
  7. * History:
  8. * Date By Reason
  9. * ==== == ======
  10. * 17-Jan-00 kanqiu initial implementation(Kan Qiu)
  11. *
  12. ***************************************************************************/
  13. #include "ddrawpr.h"
  14. #include "dxcursor.hpp"
  15. #include "swapchan.hpp"
  16. #define FORMAT_8888_1555(val) \
  17. ( ((val & 0x80000000) >> 16) | ((val & 0xF80000) >> 9) | ((val & 0xF800) >> 6) | ((val & 0xF8) >> 3))
  18. #define FORMAT_8888_555(val) \
  19. ( ((val & 0xF80000) >> 9) | ((val & 0xF800) >> 6) | ((val & 0xF8) >> 3))
  20. #define FORMAT_8888_565(val) \
  21. ( ((val & 0xF80000) >> 8) | ((val & 0xFC00) >> 5) | ((val & 0xF8) >> 3))
  22. #define ISOPAQUE(val) \
  23. ( 0xFF000000 == (val & 0xFF000000))
  24. #undef DPF_MODNAME
  25. #define DPF_MODNAME "CCursor::CCursor"
  26. //=============================================================================
  27. // CCursor::CCursor
  28. //
  29. //=============================================================================
  30. CCursor::CCursor(CBaseDevice *pDevice)
  31. {
  32. m_pDevice = pDevice;
  33. m_dwCursorFlags = 0;
  34. m_hCursorDdb = NULL;
  35. m_hFrontSave = NULL;
  36. m_hBackSave = NULL;
  37. m_Width = m_Height = 0;
  38. m_hOsCursor = NULL;
  39. m_hHWCursor = NULL;
  40. m_SavedMouseTrails = 0;
  41. m_xCursor = pDevice->SwapChain()->Width()/2;
  42. m_yCursor = pDevice->SwapChain()->Height()/2;
  43. m_MonitorOrigin.x = m_MonitorOrigin.y = 0;
  44. if ( (!pDevice->SwapChain()->Windowed())
  45. && (1 < pDevice->Enum()->GetAdapterCount()))
  46. {
  47. HMONITOR hMonitor = pDevice->Enum()->
  48. GetAdapterMonitor(pDevice->AdapterIndex());
  49. if (hMonitor)
  50. {
  51. MONITORINFO MonInfo;
  52. MonInfo.rcMonitor.top = MonInfo.rcMonitor.left = 0;
  53. MonInfo.cbSize = sizeof(MONITORINFO);
  54. InternalGetMonitorInfo(hMonitor, &MonInfo);
  55. m_MonitorOrigin.x = MonInfo.rcMonitor.left;
  56. m_MonitorOrigin.y = MonInfo.rcMonitor.top;
  57. }
  58. }
  59. } // CCursor::CCursor
  60. #undef DPF_MODNAME
  61. #define DPF_MODNAME "CCursor::~CCursor"
  62. //=============================================================================
  63. // CCursor::~CCursor
  64. //
  65. //=============================================================================
  66. CCursor::~CCursor()
  67. {
  68. Destroy();
  69. if (m_hOsCursor)
  70. {
  71. SetCursor(m_hOsCursor);
  72. m_hOsCursor = NULL;
  73. }
  74. }
  75. void
  76. CCursor::Destroy()
  77. {
  78. D3D8_DESTROYSURFACEDATA DestroySurfData;
  79. DestroySurfData.hDD = m_pDevice->GetHandle();
  80. if (m_hCursorDdb)
  81. {
  82. DestroySurfData.hSurface = m_hCursorDdb;
  83. m_pDevice->GetHalCallbacks()->DestroySurface(&DestroySurfData);
  84. m_hCursorDdb = NULL;
  85. }
  86. if (m_hFrontSave)
  87. {
  88. DestroySurfData.hSurface = m_hFrontSave;
  89. m_pDevice->GetHalCallbacks()->DestroySurface(&DestroySurfData);
  90. m_hFrontSave = NULL;
  91. }
  92. if (m_hBackSave)
  93. {
  94. DestroySurfData.hSurface = m_hBackSave;
  95. m_pDevice->GetHalCallbacks()->DestroySurface(&DestroySurfData);
  96. m_hBackSave = NULL;
  97. }
  98. if ( NULL != m_hHWCursor )
  99. {
  100. if ( GetCursor() == m_hHWCursor )
  101. SetCursor(NULL); // turn it off before destroy
  102. if (!DestroyIcon((HICON)m_hHWCursor))
  103. {
  104. DPF_ERR("Destroy Failed to Destroy Old hwcursor Icon");
  105. }
  106. m_hHWCursor = NULL;
  107. if (m_SavedMouseTrails > 1)
  108. {
  109. SystemParametersInfo(SPI_SETMOUSETRAILS,m_SavedMouseTrails,0,0);
  110. m_SavedMouseTrails = 0;
  111. }
  112. }
  113. }
  114. void
  115. CCursor::UpdateRects()
  116. {
  117. if (DDRAWI_CURSORISON & m_dwCursorFlags)
  118. {
  119. if (DDRAWI_CURSORSAVERECT & m_dwCursorFlags)
  120. {
  121. // SetPosition didn't update RECTs, but next Flip will
  122. m_dwCursorFlags &= ~DDRAWI_CURSORSAVERECT;
  123. m_dwCursorFlags |= DDRAWI_CURSORRECTSAVED;
  124. m_CursorRectSave = m_CursorRect;
  125. m_BufferRectSave = m_BufferRect;
  126. }
  127. if (m_xCursor < m_xCursorHotSpot)
  128. {
  129. m_CursorRect.left = m_xCursorHotSpot - m_xCursor;
  130. m_CursorRect.right = m_Width;
  131. m_BufferRect.left = 0;
  132. }
  133. else
  134. {
  135. m_CursorRect.left = 0;
  136. m_BufferRect.left = m_xCursor - m_xCursorHotSpot;
  137. if (m_xCursor + m_Width >
  138. m_pDevice->DisplayWidth() + m_xCursorHotSpot )
  139. {
  140. m_CursorRect.right = m_pDevice->DisplayWidth() + m_xCursorHotSpot
  141. - m_xCursor;
  142. }
  143. else
  144. {
  145. m_CursorRect.right = m_Width;
  146. }
  147. }
  148. m_BufferRect.right = m_BufferRect.left + m_CursorRect.right - m_CursorRect.left;
  149. if (m_yCursor < m_yCursorHotSpot)
  150. {
  151. m_CursorRect.top = m_yCursorHotSpot - m_yCursor;
  152. m_CursorRect.bottom = m_Height;
  153. m_BufferRect.top = 0;
  154. }
  155. else
  156. {
  157. m_CursorRect.top = 0;
  158. m_BufferRect.top = m_yCursor - m_yCursorHotSpot;
  159. if (m_yCursor + m_Height >
  160. m_pDevice->DisplayHeight() + m_yCursorHotSpot )
  161. {
  162. m_CursorRect.bottom = m_pDevice->DisplayHeight() + m_yCursorHotSpot
  163. - m_yCursor;
  164. }
  165. else
  166. {
  167. m_CursorRect.bottom = m_Height;
  168. }
  169. }
  170. m_BufferRect.bottom = m_BufferRect.top + m_CursorRect.bottom - m_CursorRect.top;
  171. }
  172. }
  173. /*
  174. * Hide
  175. *
  176. * Hide the cursor. Restore buffer with saved area
  177. */
  178. #undef DPF_MODNAME
  179. #define DPF_MODNAME "CCursor::Hide"
  180. HRESULT
  181. CCursor::Hide(HANDLE hSurf)
  182. {
  183. if (!(DDRAWI_CURSORISON & m_dwCursorFlags))
  184. {
  185. return S_OK;
  186. }
  187. D3D8_BLTDATA BltData;
  188. ZeroMemory(&BltData, sizeof BltData);
  189. if (DDRAWI_CURSORRECTSAVED & m_dwCursorFlags)
  190. {
  191. // this Hide Must have been caused by flip
  192. m_dwCursorFlags &= ~DDRAWI_CURSORRECTSAVED;
  193. BltData.rSrc.left = m_CursorRectSave.left;
  194. BltData.rSrc.right = m_CursorRectSave.right;
  195. BltData.rSrc.top = m_CursorRectSave.top;
  196. BltData.rSrc.bottom = m_CursorRectSave.bottom;
  197. BltData.rDest.left = m_BufferRectSave.left;
  198. BltData.rDest.top = m_BufferRectSave.top;
  199. BltData.rDest.right = m_BufferRectSave.right;
  200. BltData.rDest.bottom = m_BufferRectSave.bottom;
  201. }
  202. else
  203. {
  204. BltData.rSrc.left = m_CursorRect.left;
  205. BltData.rSrc.right = m_CursorRect.right;
  206. BltData.rSrc.top = m_CursorRect.top;
  207. BltData.rSrc.bottom = m_CursorRect.bottom;
  208. BltData.rDest.left = m_BufferRect.left;
  209. BltData.rDest.top = m_BufferRect.top;
  210. BltData.rDest.right = m_BufferRect.right;
  211. BltData.rDest.bottom = m_BufferRect.bottom;
  212. }
  213. BltData.hSrcSurface = m_hFrontSave;
  214. BltData.hDestSurface = hSurf;
  215. BltData.hDD = m_pDevice->GetHandle();
  216. BltData.dwFlags = DDBLT_ROP | DDBLT_WAIT;
  217. BltData.bltFX.dwROP = SRCCOPY;
  218. BltData.ddRVal = E_FAIL;
  219. m_pDevice->GetHalCallbacks()->Blt(&BltData);
  220. return BltData.ddRVal;
  221. }
  222. /*
  223. * ShowCursor
  224. *
  225. * Show the cursor. save exclusion area and blt cursor to it
  226. */
  227. #undef DPF_MODNAME
  228. #define DPF_MODNAME "CCursor::Show"
  229. HRESULT
  230. CCursor::Show(HANDLE hSurf)
  231. {
  232. if (!(DDRAWI_CURSORISON & m_dwCursorFlags))
  233. {
  234. return S_OK;
  235. }
  236. D3D8_BLTDATA BltData;
  237. ZeroMemory(&BltData, sizeof BltData);
  238. UpdateRects();
  239. BltData.rSrc.left = m_BufferRect.left;
  240. BltData.rSrc.right = m_BufferRect.right;
  241. BltData.rSrc.top = m_BufferRect.top;
  242. BltData.rSrc.bottom = m_BufferRect.bottom;
  243. BltData.hSrcSurface = hSurf;
  244. BltData.rDest.left = m_CursorRect.left;
  245. BltData.rDest.top = m_CursorRect.top;
  246. BltData.rDest.right = m_CursorRect.right;
  247. BltData.rDest.bottom = m_CursorRect.bottom;
  248. BltData.hDestSurface = m_hFrontSave;
  249. BltData.hDD = m_pDevice->GetHandle();
  250. BltData.dwFlags = DDBLT_ROP | DDBLT_WAIT;
  251. BltData.bltFX.dwROP = SRCCOPY;
  252. BltData.ddRVal = E_FAIL;
  253. m_pDevice->GetHalCallbacks()->Blt(&BltData);
  254. if (SUCCEEDED(BltData.ddRVal))
  255. {
  256. BltData.rSrc.left = m_CursorRect.left;
  257. BltData.rSrc.right = m_CursorRect.right;
  258. BltData.rSrc.top = m_CursorRect.top;
  259. BltData.rSrc.bottom = m_CursorRect.bottom;
  260. BltData.hSrcSurface = m_hCursorDdb;
  261. BltData.rDest.left = m_BufferRect.left;
  262. BltData.rDest.top = m_BufferRect.top;
  263. BltData.rDest.right = m_BufferRect.right;
  264. BltData.rDest.bottom = m_BufferRect.bottom;
  265. BltData.hDestSurface = hSurf;
  266. BltData.hDD = m_pDevice->GetHandle();
  267. BltData.dwFlags = DDBLT_ROP | DDBLT_WAIT | DDBLT_KEYSRCOVERRIDE;
  268. //always use black as key
  269. BltData.bltFX.ddckSrcColorkey.dwColorSpaceLowValue =
  270. BltData.bltFX.ddckSrcColorkey.dwColorSpaceHighValue = 0;
  271. BltData.bltFX.dwROP = SRCCOPY;
  272. BltData.ddRVal = E_FAIL;
  273. m_pDevice->GetHalCallbacks()->Blt(&BltData);
  274. }
  275. return BltData.ddRVal;
  276. }
  277. void
  278. CCursor::Flip()
  279. {
  280. if (DDRAWI_CURSORISON & m_dwCursorFlags)
  281. {
  282. HANDLE htemp = m_hFrontSave;
  283. m_hFrontSave = m_hBackSave;
  284. m_hBackSave = htemp;
  285. }
  286. }
  287. HCURSOR CreateColorCursor(
  288. UINT xHotSpot,
  289. UINT yHotSpot,
  290. UINT BitmapWidth,
  291. UINT BitmapHeight,
  292. CBaseSurface *pCursorBitmap)
  293. {
  294. UINT Width = (UINT)GetSystemMetrics(SM_CXCURSOR);
  295. UINT Height = (UINT)GetSystemMetrics(SM_CYCURSOR);
  296. ICONINFO iconinfo;
  297. D3DLOCKED_RECT lock;
  298. DWORD *pSourceBitmap;
  299. DWORD *pColorMask;
  300. BYTE *pMonoMask;
  301. HCURSOR hCursor = NULL;
  302. HDC hdcMem = NULL;
  303. HBITMAP hbmANDMask = NULL;
  304. HWND hwndDesktop = NULL;
  305. HBITMAP hbmXORBitmap;
  306. HDC hdcScreen;
  307. static char bmi[sizeof(BITMAPINFO) + (sizeof(RGBQUAD) * 255)];
  308. LPBITMAPINFO pbmi = (LPBITMAPINFO)bmi;
  309. iconinfo.fIcon = FALSE;
  310. iconinfo.xHotspot = xHotSpot*Width/BitmapWidth;
  311. iconinfo.yHotspot = yHotSpot*Height/BitmapHeight;
  312. pMonoMask = new BYTE [Width * Height / 8];
  313. if ( NULL == pMonoMask )
  314. {
  315. DPF_ERR("Out of Memory. Unable to create Cursor");
  316. return NULL;
  317. }
  318. ZeroMemory(pMonoMask, (Width * Height / 8));
  319. pColorMask = new DWORD [Width * Height];
  320. if ( NULL == pColorMask )
  321. {
  322. DPF_ERR("Out of Memory. Unable to CreateCursor");
  323. delete[] pMonoMask;
  324. return NULL;
  325. }
  326. if (FAILED(pCursorBitmap->LockRect(&lock, NULL, 0)))
  327. {
  328. DPF_ERR("Failed to lock pCursorBitmap, it must be lockable. CreateCursor failed");
  329. delete[] pMonoMask;
  330. delete[] pColorMask;
  331. return NULL;
  332. }
  333. pSourceBitmap = (DWORD*)lock.pBits;
  334. for (int j = (int)(Height - 1); j >= 0 ; j--)
  335. {
  336. for (UINT i = 0; i < Width; ++i)
  337. {
  338. DWORD pixel= pSourceBitmap[i*BitmapWidth/Width];
  339. if (ISOPAQUE(pixel))
  340. {
  341. pColorMask[j*Width+i] = pixel;
  342. }
  343. else
  344. {
  345. pMonoMask[(j*Width+i)/8]
  346. |= 1 << (7-((j*Width+i) % 8));
  347. pColorMask[j*Width+i] = 0;
  348. }
  349. }
  350. pSourceBitmap += lock.Pitch* BitmapHeight/4/Height;
  351. }
  352. if (FAILED(pCursorBitmap->UnlockRect()))
  353. {
  354. DPF_ERR("Driver surface failed to unlock pCursorBitmap");
  355. }
  356. /************************************************************************/
  357. /* Initialize the bitmap header for the XOR data. */
  358. /************************************************************************/
  359. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  360. pbmi->bmiHeader.biWidth = Width;
  361. pbmi->bmiHeader.biHeight = Height;
  362. pbmi->bmiHeader.biPlanes = 1;
  363. pbmi->bmiHeader.biBitCount = 32;
  364. pbmi->bmiHeader.biCompression = BI_RGB;
  365. pbmi->bmiHeader.biSizeImage = Width*Height*sizeof(DWORD);
  366. pbmi->bmiHeader.biXPelsPerMeter = 0;
  367. pbmi->bmiHeader.biYPelsPerMeter = 0;
  368. pbmi->bmiHeader.biClrUsed = 0;
  369. pbmi->bmiHeader.biClrImportant = 0;
  370. hwndDesktop = GetDesktopWindow();
  371. hdcScreen = GetWindowDC(hwndDesktop);
  372. if (0 == hdcScreen)
  373. {
  374. // Error getting the screen DC.
  375. DPF_ERR("Failed to create screen DC");
  376. delete[] pMonoMask;
  377. delete[] pColorMask;
  378. return NULL;
  379. }
  380. /********************************************************************/
  381. /* Create XOR Bitmap */
  382. /********************************************************************/
  383. iconinfo.hbmColor = CreateDIBitmap(hdcScreen,
  384. (LPBITMAPINFOHEADER)pbmi,
  385. CBM_INIT,
  386. pColorMask,
  387. pbmi,
  388. DIB_RGB_COLORS);
  389. delete[] pColorMask;
  390. /********************************************************************/
  391. /* Release the DC. */
  392. /********************************************************************/
  393. ReleaseDC(hwndDesktop, hdcScreen);
  394. if ( NULL == iconinfo.hbmColor)
  395. {
  396. delete[] pMonoMask;
  397. return NULL;
  398. }
  399. /************************************************************************/
  400. /* For the mono bitmap, use CreateCompatibleDC - this makes no */
  401. /* difference on NT, but allows this code to work on Windows 95. */
  402. /************************************************************************/
  403. hdcMem = CreateCompatibleDC(NULL);
  404. if ( NULL == hdcMem)
  405. {
  406. DPF_ERR("Failed to create DC");
  407. delete[] pMonoMask;
  408. DeleteObject( iconinfo.hbmColor );
  409. return NULL;
  410. }
  411. /************************************************************************/
  412. /* Create AND Mask (1bpp) - set the RGB colors to black and white. */
  413. /************************************************************************/
  414. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  415. pbmi->bmiHeader.biWidth = Width;
  416. pbmi->bmiHeader.biHeight = Height;
  417. pbmi->bmiHeader.biPlanes = 1;
  418. pbmi->bmiHeader.biBitCount = 1;
  419. pbmi->bmiHeader.biCompression = BI_RGB;
  420. pbmi->bmiHeader.biSizeImage = Width*Height/8;
  421. pbmi->bmiHeader.biXPelsPerMeter = 0;
  422. pbmi->bmiHeader.biYPelsPerMeter = 0;
  423. pbmi->bmiHeader.biClrUsed = 2;
  424. pbmi->bmiHeader.biClrImportant = 0;
  425. pbmi->bmiColors[0].rgbRed = 0x00;
  426. pbmi->bmiColors[0].rgbGreen = 0x00;
  427. pbmi->bmiColors[0].rgbBlue = 0x00;
  428. pbmi->bmiColors[0].rgbReserved = 0x00;
  429. pbmi->bmiColors[1].rgbRed = 0xFF;
  430. pbmi->bmiColors[1].rgbGreen = 0xFF;
  431. pbmi->bmiColors[1].rgbBlue = 0xFF;
  432. pbmi->bmiColors[1].rgbReserved = 0x00;
  433. iconinfo.hbmMask = CreateDIBitmap(hdcMem,
  434. (LPBITMAPINFOHEADER)pbmi,
  435. CBM_INIT,
  436. pMonoMask,
  437. pbmi,
  438. DIB_RGB_COLORS);
  439. /************************************************************************/
  440. /* Free the DC. */
  441. /************************************************************************/
  442. DeleteDC(hdcMem);
  443. delete[] pMonoMask;
  444. if ( NULL == iconinfo.hbmMask)
  445. {
  446. DPF_ERR("Failed to create AND mask");
  447. DeleteObject( iconinfo.hbmColor );
  448. return NULL;
  449. }
  450. hCursor = (HCURSOR) CreateIconIndirect(&iconinfo);
  451. DeleteObject( iconinfo.hbmMask );
  452. DeleteObject( iconinfo.hbmColor );
  453. return hCursor;
  454. }
  455. HRESULT
  456. CCursor::CursorInit(
  457. UINT xHotSpot,
  458. UINT yHotSpot,
  459. CBaseSurface *pCursorBitmap)
  460. {
  461. HRESULT hr=S_OK;
  462. D3DSURFACE_DESC desc;
  463. HCURSOR oscursor;
  464. ICONINFO cursorinfo;
  465. BITMAP bmColor;
  466. BITMAP bmMask;
  467. HDC hdcBitmap;
  468. HDC hdcCursorDdb;
  469. ZeroMemory(&cursorinfo, sizeof cursorinfo);
  470. m_dwCursorFlags &= ~DDRAWI_CURSORINIT;
  471. if (NULL != pCursorBitmap)
  472. {
  473. hr = pCursorBitmap->GetDesc(&desc);
  474. DXGASSERT(SUCCEEDED(hr));
  475. if (desc.Format != D3DFMT_A8R8G8B8)
  476. {
  477. DPF_ERR("Invalid Format for pCursorBitmap. Must be D3DFMT_A8R8G8B8");
  478. return D3DERR_INVALIDCALL;
  479. }
  480. if ((desc.Width -1) & desc.Width)
  481. {
  482. DPF_ERR("Failed to Initialize Cursor: Width must be a 2^n");
  483. return D3DERR_INVALIDCALL;
  484. }
  485. if ((desc.Height -1) & desc.Height)
  486. {
  487. DPF_ERR("Failed to Initialize Cursor: Height must be a 2^n");
  488. return D3DERR_INVALIDCALL;
  489. }
  490. if (desc.Width > m_pDevice->DisplayWidth())
  491. {
  492. DPF_ERR("Cursor Width must be smaller than DisplayWidth");
  493. return D3DERR_INVALIDCALL;
  494. }
  495. if (desc.Height > m_pDevice->DisplayHeight())
  496. {
  497. DPF_ERR("Cursor Height must be smaller than DisplayHeight");
  498. return D3DERR_INVALIDCALL;
  499. }
  500. if (desc.Width <= xHotSpot)
  501. {
  502. DPF_ERR("Cursor xHotSpot must be smaller than its Width");
  503. return D3DERR_INVALIDCALL;
  504. }
  505. if (desc.Height <= yHotSpot)
  506. {
  507. DPF_ERR("Cursor yHotSpot must be smaller than its Height");
  508. return D3DERR_INVALIDCALL;
  509. }
  510. }
  511. else if ( NULL == m_hCursorDdb)
  512. {
  513. oscursor = SetCursor(NULL);
  514. if (oscursor)
  515. m_hOsCursor = oscursor;
  516. else if (m_hOsCursor)
  517. oscursor = m_hOsCursor;
  518. desc.Width = GetSystemMetrics(SM_CXCURSOR);
  519. desc.Height = GetSystemMetrics(SM_CYCURSOR); //default
  520. if (oscursor && GetIconInfo(oscursor,&cursorinfo))
  521. {
  522. GetObject( cursorinfo.hbmMask, sizeof(BITMAP), &bmMask );
  523. desc.Width = bmMask.bmWidth;
  524. if (cursorinfo.hbmColor)
  525. {
  526. GetObject( cursorinfo.hbmColor, sizeof(BITMAP), &bmColor );
  527. desc.Height = bmColor.bmHeight; //color cursor has only AND mask
  528. }
  529. else
  530. {
  531. desc.Height = bmMask.bmHeight/2;
  532. }
  533. }
  534. }
  535. else
  536. return S_OK;
  537. const D3D8_DRIVERCAPS* pDriverCaps=m_pDevice->GetCoreCaps();
  538. if ((NULL != pCursorBitmap)
  539. && (
  540. (
  541. // either driver says it can support
  542. (
  543. (D3DCURSORCAPS_COLOR & pDriverCaps->D3DCaps.CursorCaps)
  544. &&
  545. (
  546. (400 <= pDriverCaps->DisplayHeight)
  547. ||
  548. (D3DCURSORCAPS_LOWRES & pDriverCaps->D3DCaps.CursorCaps)
  549. )
  550. )
  551. && ((UINT)GetSystemMetrics(SM_CXCURSOR) == desc.Width)
  552. && ((UINT)GetSystemMetrics(SM_CYCURSOR) == desc.Height)
  553. )
  554. // or windowed case where we have to use OS cursor
  555. ||
  556. m_pDevice->SwapChain()->m_PresentationData.Windowed
  557. // or there is no ddraw support
  558. ||
  559. m_pDevice->Enum()->NoDDrawSupport(m_pDevice->AdapterIndex())
  560. )
  561. )
  562. {
  563. HCURSOR hCursor;
  564. if (!m_pDevice->SwapChain()->m_PresentationData.Windowed
  565. && (NULL == m_hHWCursor))
  566. {
  567. SystemParametersInfo(SPI_GETMOUSETRAILS,0,&m_SavedMouseTrails,0);
  568. if (m_SavedMouseTrails > 1)
  569. {
  570. // always make sure it's disabled
  571. SystemParametersInfo(SPI_SETMOUSETRAILS,0,0,0);
  572. }
  573. }
  574. hCursor = CreateColorCursor(xHotSpot,yHotSpot,
  575. desc.Width, desc.Height, pCursorBitmap);
  576. if ( NULL != hCursor)
  577. {
  578. if ( NULL != m_hHWCursor)
  579. {
  580. if ( GetCursor() == m_hHWCursor )
  581. SetCursor(hCursor); // turn it on if it was on
  582. if (!DestroyIcon((HICON)m_hHWCursor))
  583. {
  584. DPF_ERR("Failed to Destroy Old hwcursor Icon");
  585. }
  586. }
  587. else
  588. if ( DDRAWI_CURSORISON & m_dwCursorFlags)
  589. {
  590. SetCursor(hCursor); // turn it on if it was on
  591. // make sure software cursor is off
  592. m_dwCursorFlags &= ~DDRAWI_CURSORISON;
  593. }
  594. m_hHWCursor = hCursor;
  595. m_dwCursorFlags |= DDRAWI_CURSORINIT;
  596. return S_OK;
  597. }
  598. }
  599. if (m_SavedMouseTrails > 1)
  600. {
  601. SystemParametersInfo(SPI_SETMOUSETRAILS,m_SavedMouseTrails,0,0);
  602. m_SavedMouseTrails = 0;
  603. }
  604. SetCursor(NULL);
  605. if ( NULL != m_hHWCursor )
  606. {
  607. if (!DestroyIcon((HICON)m_hHWCursor))
  608. {
  609. DPF_ERR("Failed to Destroy Old hwcursor Icon");
  610. }
  611. m_hHWCursor = NULL;
  612. }
  613. if (desc.Width != m_Width || desc.Height != m_Height)
  614. {
  615. DDSURFACEINFO SurfInfoArray[3];
  616. D3D8_CREATESURFACEDATA CreateSurfaceData;
  617. ZeroMemory(&CreateSurfaceData, sizeof(CreateSurfaceData));
  618. Destroy();
  619. ZeroMemory(SurfInfoArray, sizeof(SurfInfoArray));
  620. for (int i = 0; i < 3; i++)
  621. {
  622. SurfInfoArray[i].cpWidth = desc.Width;
  623. SurfInfoArray[i].cpHeight = desc.Height;
  624. ZeroMemory(&CreateSurfaceData, sizeof(CreateSurfaceData));
  625. CreateSurfaceData.hDD = m_pDevice->GetHandle();
  626. CreateSurfaceData.pSList = &SurfInfoArray[i];
  627. CreateSurfaceData.dwSCnt = 1;
  628. CreateSurfaceData.Type = D3DRTYPE_SURFACE;
  629. CreateSurfaceData.Pool = D3DPOOL_LOCALVIDMEM;
  630. CreateSurfaceData.dwUsage = D3DUSAGE_OFFSCREENPLAIN;
  631. CreateSurfaceData.Format = m_pDevice->DisplayFormat();
  632. CreateSurfaceData.MultiSampleType = D3DMULTISAMPLE_NONE;
  633. hr = m_pDevice->GetHalCallbacks()->CreateSurface(&CreateSurfaceData);
  634. if (NULL == SurfInfoArray[i].hKernelHandle)
  635. {
  636. CreateSurfaceData.Pool = D3DPOOL_SYSTEMMEM;
  637. hr = m_pDevice->GetHalCallbacks()->CreateSurface(&CreateSurfaceData);
  638. }
  639. DPF(10,"CursorInit CreateSurface returns hr=%08lx handle=%08lx",
  640. hr, SurfInfoArray[i].hKernelHandle);
  641. }
  642. m_hCursorDdb = SurfInfoArray[0].hKernelHandle;
  643. m_hFrontSave = SurfInfoArray[1].hKernelHandle;
  644. m_hBackSave = SurfInfoArray[2].hKernelHandle;
  645. if (m_hCursorDdb && m_hFrontSave && m_hBackSave)
  646. {
  647. m_Width = desc.Width;
  648. m_Height = desc.Height;
  649. }
  650. else
  651. {
  652. DPF_ERR("Cursor not available for this device");
  653. return D3DERR_NOTAVAILABLE;
  654. }
  655. }
  656. if (NULL != pCursorBitmap)
  657. {
  658. D3D8_LOCKDATA lockData;
  659. D3DLOCKED_RECT lock;
  660. DWORD *pSourceBitmap;
  661. INT SourcePitch;
  662. ZeroMemory(&lockData, sizeof lockData);
  663. hr = pCursorBitmap->LockRect(&lock, NULL, 0);
  664. if (FAILED(hr))
  665. {
  666. DPF_ERR("Failed to lock pCursorBitmap surface; Surface must be lockable.");
  667. return D3DERR_INVALIDCALL;
  668. }
  669. lockData.hDD = m_pDevice->GetHandle();
  670. lockData.hSurface = m_hCursorDdb;
  671. hr = m_pDevice->GetHalCallbacks()->Lock(&lockData);
  672. if (FAILED(hr))
  673. {
  674. DPF_ERR("Failed to lock driver cursor surface.");
  675. pCursorBitmap->UnlockRect();
  676. return hr;
  677. }
  678. SourcePitch = lock.Pitch;
  679. pSourceBitmap = (DWORD*)lock.pBits;
  680. switch (m_pDevice->DisplayFormat())
  681. {
  682. case D3DFMT_A1R5G5B5:
  683. {
  684. BYTE *pScan = (BYTE *) lockData.lpSurfData;
  685. for (UINT j = 0; j < m_Height; ++j)
  686. {
  687. WORD *pPixel = (WORD *) pScan;
  688. for (UINT i = 0; i < m_Width; ++i)
  689. {
  690. if (ISOPAQUE(pSourceBitmap[i]))
  691. {
  692. *pPixel =
  693. (WORD)FORMAT_8888_1555(pSourceBitmap[i]);
  694. if (0 == (0x7FFF & *pPixel))
  695. *pPixel |= 0x0421; //off black color
  696. }
  697. else
  698. *pPixel = 0;
  699. pPixel ++;
  700. }
  701. pScan += lockData.lPitch;
  702. pSourceBitmap += SourcePitch/4;
  703. }
  704. }
  705. break;
  706. case D3DFMT_X1R5G5B5:
  707. {
  708. BYTE *pScan = (BYTE *) lockData.lpSurfData;
  709. for (UINT j = 0; j < m_Height; ++j)
  710. {
  711. WORD *pPixel = (WORD *) pScan;
  712. for (UINT i = 0; i < m_Width; ++i)
  713. {
  714. if (ISOPAQUE(pSourceBitmap[i]))
  715. {
  716. *pPixel =
  717. (WORD)FORMAT_8888_555(pSourceBitmap[i]);
  718. if (0 == *pPixel)
  719. *pPixel |= 0x0421; //off black color
  720. }
  721. else
  722. *pPixel = 0;
  723. pPixel ++;
  724. }
  725. pScan += lockData.lPitch;
  726. pSourceBitmap += SourcePitch/4;
  727. }
  728. }
  729. break;
  730. case D3DFMT_R5G6B5:
  731. {
  732. BYTE *pScan = (BYTE *) lockData.lpSurfData;
  733. for (UINT j = 0; j < m_Height; ++j)
  734. {
  735. WORD *pPixel = (WORD *) pScan;
  736. for (UINT i = 0; i < m_Width; ++i)
  737. {
  738. if (ISOPAQUE(pSourceBitmap[i]))
  739. {
  740. *pPixel =
  741. (WORD)FORMAT_8888_565(pSourceBitmap[i]);
  742. if (0 == *pPixel)
  743. *pPixel |= 0x0821; //off black color
  744. }
  745. else
  746. *pPixel = 0;
  747. pPixel ++;
  748. }
  749. pScan += lockData.lPitch;
  750. pSourceBitmap += SourcePitch/4;
  751. }
  752. }
  753. break;
  754. case D3DFMT_X8R8G8B8:
  755. {
  756. BYTE *pScan = (BYTE *) lockData.lpSurfData;
  757. for (UINT j = 0; j < m_Height; ++j)
  758. {
  759. DWORD *pPixel = (DWORD *) pScan;
  760. for (UINT i = 0; i < m_Width; ++i)
  761. {
  762. if (ISOPAQUE(pSourceBitmap[i]))
  763. {
  764. *pPixel = pSourceBitmap[i] & 0x00FFFFFF;
  765. if (0 == *pPixel)
  766. *pPixel |= 0x010101; //off black color
  767. }
  768. else
  769. *pPixel = 0;
  770. pPixel ++;
  771. }
  772. pScan += lockData.lPitch;
  773. pSourceBitmap += SourcePitch/4;
  774. }
  775. }
  776. break;
  777. case D3DFMT_A8R8G8B8:
  778. {
  779. BYTE *pScan = (BYTE *) lockData.lpSurfData;
  780. for (UINT j = 0; j < m_Height; ++j)
  781. {
  782. DWORD *pPixel = (DWORD *) pScan;
  783. for (UINT i = 0; i < m_Width; ++i)
  784. {
  785. if (ISOPAQUE(pSourceBitmap[i]))
  786. {
  787. *pPixel = pSourceBitmap[i];
  788. if (0 == (0x00FFFFFF & *pPixel))
  789. *pPixel |= 0x010101; //off black color
  790. }
  791. else
  792. *pPixel = 0;
  793. pPixel ++;
  794. }
  795. pScan += lockData.lPitch;
  796. pSourceBitmap += SourcePitch/4;
  797. }
  798. }
  799. break;
  800. default:
  801. // this should never happen
  802. DDASSERT(FALSE);
  803. }
  804. D3D8_UNLOCKDATA unlockData;
  805. ZeroMemory(&unlockData, sizeof unlockData);
  806. unlockData.hDD = m_pDevice->GetHandle();
  807. unlockData.hSurface = m_hCursorDdb;
  808. hr = m_pDevice->GetHalCallbacks()->Unlock(&unlockData);
  809. if (FAILED(hr))
  810. {
  811. DPF_ERR("Driver surface failed to unlock driver cursor surface");
  812. }
  813. hr = pCursorBitmap->UnlockRect();
  814. if (FAILED(hr))
  815. {
  816. DPF_ERR("Driver surface failed to unlock pCursorBitmap");
  817. }
  818. m_xCursorHotSpot = xHotSpot;
  819. m_yCursorHotSpot = yHotSpot;
  820. }
  821. if (SUCCEEDED(hr))
  822. m_dwCursorFlags |= DDRAWI_CURSORINIT;
  823. return hr;
  824. }
  825. #undef DPF_MODNAME
  826. #define DPF_MODNAME "SetVisibility"
  827. BOOL
  828. CCursor::SetVisibility(BOOL bVisible)
  829. {
  830. BOOL retval = FALSE;
  831. if (DDRAWI_CURSORINIT & m_dwCursorFlags)
  832. {
  833. if (NULL == m_hHWCursor)
  834. {
  835. retval = (BOOL) (DDRAWI_CURSORISON & m_dwCursorFlags);
  836. SetCursor(NULL);
  837. if (bVisible)
  838. {
  839. if (!retval)
  840. {
  841. m_dwCursorFlags |= DDRAWI_CURSORISON;
  842. Show(m_pDevice->SwapChain()->
  843. PrimarySurface()->KernelHandle());
  844. m_dwCursorFlags &= ~(DDRAWI_CURSORSAVERECT | DDRAWI_CURSORRECTSAVED);
  845. }
  846. }
  847. else
  848. {
  849. Hide(m_pDevice->SwapChain()->
  850. PrimarySurface()->KernelHandle());
  851. m_dwCursorFlags &= ~(DDRAWI_CURSORISON |
  852. DDRAWI_CURSORSAVERECT | DDRAWI_CURSORRECTSAVED);
  853. }
  854. }
  855. else
  856. {
  857. if (m_hHWCursor == GetCursor())
  858. {
  859. if (!bVisible)
  860. SetCursor(NULL);
  861. retval = TRUE;
  862. }
  863. else
  864. {
  865. if (bVisible)
  866. SetCursor(m_hHWCursor);
  867. else
  868. SetCursor(NULL);
  869. }
  870. }
  871. }
  872. return retval;
  873. }
  874. /*
  875. * SetCursorProperties
  876. *
  877. * Setup a cursor
  878. * This is the method visible to the outside world.
  879. */
  880. #undef DPF_MODNAME
  881. #define DPF_MODNAME "SetProperties"
  882. HRESULT
  883. CCursor::SetProperties(
  884. UINT xHotSpot,
  885. UINT yHotSpot,
  886. CBaseSurface *pCursorBitmap)
  887. {
  888. HRESULT hr;
  889. DPF(10,"ENTERAPI: SetCursorProperties "
  890. "xh=%d yh=%d pCursorBitmap=%08lx",
  891. xHotSpot,yHotSpot,pCursorBitmap);
  892. m_dwCursorFlags &= ~(DDRAWI_CURSORSAVERECT | DDRAWI_CURSORRECTSAVED);
  893. hr = Hide(m_pDevice->SwapChain()
  894. ->PrimarySurface()->KernelHandle());
  895. if (FAILED(hr))
  896. {
  897. DPF_ERR("Failed to Hide Cursor.");
  898. return hr;
  899. }
  900. hr = CursorInit(xHotSpot, yHotSpot, pCursorBitmap);
  901. if (FAILED(hr))
  902. {
  903. DPF_ERR("Failed to CursorInit.");
  904. return hr;
  905. }
  906. hr = Show(m_pDevice->SwapChain()->PrimarySurface()->KernelHandle());
  907. return hr;
  908. }
  909. /*
  910. * Cursor::SetPosition
  911. *
  912. * Setup a cursor
  913. * This is the method visible to the outside world.
  914. */
  915. #undef DPF_MODNAME
  916. #define DPF_MODNAME "Cursor::SetPosition"
  917. void
  918. CCursor::SetPosition(
  919. UINT xScreenSpace,
  920. UINT yScreenSpace,
  921. DWORD Flags)
  922. {
  923. HRESULT hr = S_OK;
  924. if (DDRAWI_CURSORINIT & m_dwCursorFlags)
  925. {
  926. if ( m_hHWCursor)
  927. {
  928. if (xScreenSpace == m_xCursor && yScreenSpace == m_yCursor)
  929. {
  930. POINT current;
  931. if (GetCursorPos(&current))
  932. {
  933. if ((current.x == (INT)xScreenSpace + m_MonitorOrigin.x) &&
  934. (current.y == (INT)yScreenSpace + m_MonitorOrigin.y)
  935. )
  936. return;
  937. }
  938. }
  939. else
  940. {
  941. m_xCursor = xScreenSpace;
  942. m_yCursor = yScreenSpace;
  943. }
  944. SetCursorPos(xScreenSpace+m_MonitorOrigin.x,
  945. yScreenSpace+m_MonitorOrigin.y);
  946. return;
  947. }
  948. if (xScreenSpace == m_xCursor && yScreenSpace == m_yCursor)
  949. return;
  950. // only emulated fullscreen cursor ever gets down here
  951. if (D3DCURSOR_IMMEDIATE_UPDATE & Flags)
  952. hr = Hide(m_pDevice->SwapChain()->PrimarySurface()->KernelHandle());
  953. else if (DDRAWI_CURSORISON & m_dwCursorFlags)
  954. m_dwCursorFlags |= DDRAWI_CURSORSAVERECT;
  955. m_xCursor = xScreenSpace;
  956. m_yCursor = yScreenSpace;
  957. if (m_xCursor >= m_pDevice->DisplayWidth())
  958. {
  959. m_xCursor = m_pDevice->DisplayWidth()-1;
  960. }
  961. if (m_yCursor >= m_pDevice->DisplayHeight())
  962. {
  963. m_yCursor = m_pDevice->DisplayHeight()-1;
  964. }
  965. if (D3DCURSOR_IMMEDIATE_UPDATE & Flags)
  966. {
  967. hr = Show(m_pDevice->SwapChain()->PrimarySurface()->KernelHandle());
  968. }
  969. }
  970. else
  971. {
  972. m_xCursor = xScreenSpace;
  973. m_yCursor = yScreenSpace;
  974. }
  975. return;
  976. }