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.

563 lines
17 KiB

  1. //=============================================================================
  2. //
  3. // Copyright (C) 1997 Microsoft Corporation. All rights reserved.
  4. //
  5. // File: ddrestor.c
  6. // Content: DirectDraw persistent-content surfaces for Windows 9x
  7. //
  8. // Date By Reason
  9. // ---------- -------- -----------------------------------------------------
  10. // 09/30/1997 jeffno Created
  11. // 10/02/1997 johnstep Initial implementation
  12. //
  13. //=============================================================================
  14. #include "ddrawpr.h"
  15. #include "dx8priv.h"
  16. //
  17. // MEM_SHARED is an undocumented flag for VirtualAlloc, taken from the Windows
  18. // 9x source code.
  19. //
  20. #define MEM_SHARED 0x08000000 // make memory globally visible
  21. //
  22. // QWORD_MULTIPLE is used to compute the pitch of a dummy surface,
  23. // based on its width, given that the pitch must be a QWORD multiple.
  24. //
  25. #define QWORD_MULTIPLE(x) (((x) + 7) & 0xFFFFFFF8)
  26. //=============================================================================
  27. //
  28. // Function: allocSurfaceContentsMemory
  29. //
  30. //=============================================================================
  31. static HRESULT allocSurfaceContentsMemory(LPDDRAWI_DDRAWSURFACE_LCL this_lcl)
  32. {
  33. LPDDRAWI_DDRAWSURFACE_GBL this_gbl;
  34. LPDDRAWI_DDRAWSURFACE_GBL_MORE this_gbl_more;
  35. DWORD size;
  36. LPVOID pvContents;
  37. LPDDPIXELFORMAT lpddpf;
  38. this_gbl = this_lcl->lpGbl;
  39. this_gbl_more = GET_LPDDRAWSURFACE_GBL_MORE(this_gbl);
  40. this_gbl_more->pvContents = NULL;
  41. this_gbl_more->dwBackupStamp = 0;
  42. if (this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  43. {
  44. return DD_OK;
  45. }
  46. if (this_gbl->wHeight)
  47. {
  48. GET_PIXEL_FORMAT(this_lcl, this_gbl, lpddpf);
  49. size = QWORD_MULTIPLE((this_gbl->wWidth * lpddpf->dwRGBBitCount) >> 3) * this_gbl->wHeight;
  50. }
  51. else
  52. {
  53. size = this_gbl->dwLinearSize;
  54. }
  55. //
  56. // Use VirtualAlloc with the undocumented MEM_SHARED flag so the memory
  57. // is allcocated from the Windows 9x shared arena. We could change this to
  58. // use MemAlloc() and instead of VirtualFree, MemFree().
  59. //
  60. pvContents = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_SHARED, PAGE_READWRITE);
  61. if (!pvContents)
  62. {
  63. return DDERR_GENERIC;
  64. }
  65. this_gbl_more->pvContents = pvContents;
  66. return DD_OK;
  67. }
  68. //=============================================================================
  69. //
  70. // Function: allocSurfaceAttachContents
  71. //
  72. //=============================================================================
  73. static HRESULT allocSurfaceAttachContents(LPDDRAWI_DDRAWSURFACE_LCL this_lcl)
  74. {
  75. LPATTACHLIST pattachList;
  76. LPDDRAWI_DDRAWSURFACE_INT curr_int;
  77. LPDDRAWI_DDRAWSURFACE_LCL curr_lcl;
  78. HRESULT ddrval;
  79. for (pattachList = this_lcl->lpAttachList; pattachList; pattachList = pattachList->lpLink)
  80. {
  81. curr_int = pattachList->lpIAttached;
  82. curr_lcl = curr_int->lpLcl;
  83. if (curr_lcl->dwFlags & DDRAWISURF_IMPLICITCREATE)
  84. {
  85. ddrval = AllocSurfaceContents(curr_lcl);
  86. if (FAILED(ddrval))
  87. {
  88. return ddrval;
  89. }
  90. }
  91. }
  92. return DD_OK;
  93. }
  94. //=============================================================================
  95. //
  96. // Function: AllocSurfaceContents
  97. //
  98. //=============================================================================
  99. HRESULT AllocSurfaceContents(LPDDRAWI_DDRAWSURFACE_LCL this_lcl)
  100. {
  101. HRESULT ddrval;
  102. ddrval = allocSurfaceContentsMemory(this_lcl);
  103. if (FAILED(ddrval))
  104. {
  105. return ddrval;
  106. }
  107. ddrval = allocSurfaceAttachContents(this_lcl);
  108. if (FAILED(ddrval))
  109. {
  110. return ddrval;
  111. }
  112. return DD_OK;
  113. }
  114. //=============================================================================
  115. //
  116. // Function: FreeSurfaceContents
  117. //
  118. //=============================================================================
  119. void FreeSurfaceContents(LPDDRAWI_DDRAWSURFACE_LCL this_lcl)
  120. {
  121. LPDDRAWI_DDRAWSURFACE_GBL_MORE this_gbl_more;
  122. this_gbl_more = GET_LPDDRAWSURFACE_GBL_MORE(this_lcl->lpGbl);
  123. VirtualFree(this_gbl_more->pvContents, 0, MEM_RELEASE);
  124. this_gbl_more->pvContents = NULL;
  125. }
  126. //=============================================================================
  127. //
  128. // Function: createDummySurface
  129. //
  130. //=============================================================================
  131. static LPDDRAWI_DDRAWSURFACE_INT createDummySurface(LPDDRAWI_DDRAWSURFACE_LCL this_lcl)
  132. {
  133. LPDDRAWI_DIRECTDRAW_INT pdrv_int;
  134. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  135. DDSURFACEDESC2 ddsd;
  136. LPDIRECTDRAWSURFACE lpdds;
  137. HRESULT ddrval;
  138. pdrv_int = this_lcl->lpSurfMore->lpDD_int;
  139. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  140. ZeroMemory(&ddsd, sizeof ddsd);
  141. ddsd.dwSize = sizeof ddsd;
  142. ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
  143. ddsd.dwWidth = 1;
  144. ddsd.dwHeight = 1;
  145. ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY;
  146. ddrval = InternalCreateSurface(pdrv_lcl, &ddsd, &lpdds, pdrv_int, NULL, 0);
  147. if (FAILED(ddrval))
  148. {
  149. return NULL;
  150. }
  151. return (LPDDRAWI_DDRAWSURFACE_INT) lpdds;
  152. }
  153. //=============================================================================
  154. //
  155. // Function: BackupSurfaceContents
  156. //
  157. // This function assumes that the surface passed in is a video memory
  158. // surface.
  159. //
  160. //=============================================================================
  161. HRESULT BackupSurfaceContents(LPDDRAWI_DDRAWSURFACE_LCL this_lcl)
  162. {
  163. LPDDRAWI_DDRAWSURFACE_GBL this_gbl;
  164. LPDDRAWI_DDRAWSURFACE_GBL_MORE this_gbl_more;
  165. HRESULT ddrval;
  166. LPVOID pbits;
  167. LPDDRAWI_DDRAWSURFACE_INT psurf_int;
  168. LPDDRAWI_DDRAWSURFACE_INT pnew_int;
  169. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  170. DDSURFACEDESC2 ddsd;
  171. DWORD bytes;
  172. LPBYTE psrc;
  173. LPBYTE pdst;
  174. DWORD y;
  175. LONG pitch;
  176. LPDDPIXELFORMAT lpddpf;
  177. this_gbl = this_lcl->lpGbl;
  178. this_gbl_more = GET_LPDDRAWSURFACE_GBL_MORE(this_gbl);
  179. if (!this_gbl_more->dwBackupStamp &&
  180. (this_gbl_more->dwBackupStamp == this_gbl_more->dwContentsStamp))
  181. {
  182. DPF(3, "Contents unchanged, so not backing up again");
  183. return DD_OK;
  184. }
  185. if (!this_gbl_more->pvContents)
  186. {
  187. return DDERR_GENERIC;
  188. }
  189. pdrv = this_gbl->lpDD;
  190. GET_PIXEL_FORMAT(this_lcl, this_gbl, lpddpf);
  191. pitch = QWORD_MULTIPLE((this_gbl->wWidth * lpddpf->dwRGBBitCount) >> 3);
  192. psurf_int = createDummySurface(this_lcl);
  193. //
  194. // First try to blt, if that fails, we'll lock and copy memory
  195. //
  196. if (psurf_int)
  197. {
  198. ZeroMemory(&ddsd, sizeof ddsd);
  199. ddsd.dwSize = sizeof ddsd;
  200. ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE | DDSD_PIXELFORMAT;
  201. ddsd.ddpfPixelFormat.dwSize = sizeof ddsd.ddpfPixelFormat;
  202. DD_Surface_GetPixelFormat((LPDIRECTDRAWSURFACE) psurf_int, &ddsd.ddpfPixelFormat);
  203. ddsd.dwWidth = this_gbl->wWidth;
  204. ddsd.dwHeight = this_gbl->wHeight;
  205. ddsd.lPitch = pitch;
  206. ddsd.lpSurface = this_gbl_more->pvContents;
  207. ddrval = DD_Surface_SetSurfaceDesc4((LPDIRECTDRAWSURFACE3) psurf_int, &ddsd, 0);
  208. if (SUCCEEDED(ddrval))
  209. {
  210. pnew_int = MemAlloc(sizeof (DDRAWI_DDRAWSURFACE_INT));
  211. if (pnew_int)
  212. {
  213. pnew_int->lpVtbl = &ddSurface4Callbacks;
  214. pnew_int->lpLcl = this_lcl;
  215. pnew_int->lpLink = pdrv->dsList;
  216. pdrv->dsList = pnew_int;
  217. pnew_int->dwIntRefCnt = 0;
  218. ddrval = ((LPDIRECTDRAWSURFACE) psurf_int)->lpVtbl->Blt(
  219. (LPDIRECTDRAWSURFACE) psurf_int,
  220. NULL,
  221. (LPDIRECTDRAWSURFACE) pnew_int,
  222. NULL,
  223. DDBLT_WAIT,
  224. NULL);
  225. pdrv->dsList = pnew_int->lpLink;
  226. MemFree(pnew_int);
  227. if (SUCCEEDED(ddrval))
  228. {
  229. InternalSurfaceRelease(psurf_int, FALSE, FALSE);
  230. this_gbl_more->dwBackupStamp = this_gbl_more->dwContentsStamp;
  231. DPF(4, "BackupSurfaceContents Blt succeeded");
  232. return DD_OK;
  233. }
  234. }
  235. }
  236. InternalSurfaceRelease(psurf_int, FALSE, FALSE);
  237. }
  238. //
  239. // Blt failed, so now we'll just lock and copy memory
  240. //
  241. ddrval = InternalLock(this_lcl, &pbits, NULL , DDLOCK_WAIT | DDLOCK_TAKE_WIN16);
  242. if (SUCCEEDED(ddrval))
  243. {
  244. psrc = pbits;
  245. pdst = this_gbl_more->pvContents;
  246. bytes = this_gbl->wWidth;
  247. bytes *= lpddpf->dwRGBBitCount;
  248. bytes >>= 3;
  249. for (y = 0; y < this_gbl->wHeight; ++y)
  250. {
  251. CopyMemory(pdst, psrc, bytes);
  252. psrc += this_gbl->lPitch;
  253. pdst += pitch;
  254. }
  255. InternalUnlock(this_lcl, NULL, NULL, DDLOCK_TAKE_WIN16);
  256. DPF(5, "BackupSurfaceContents CopyMemory succeeded");
  257. }
  258. else
  259. {
  260. FreeSurfaceContents(this_lcl);
  261. return ddrval;
  262. }
  263. return DD_OK;
  264. }
  265. //=============================================================================
  266. //
  267. // Function: RestoreSurfaceContents
  268. //
  269. //=============================================================================
  270. HRESULT RestoreSurfaceContents(LPDDRAWI_DDRAWSURFACE_LCL this_lcl)
  271. {
  272. LPDDRAWI_DDRAWSURFACE_GBL this_gbl;
  273. LPDDRAWI_DDRAWSURFACE_GBL_MORE this_gbl_more;
  274. HRESULT ddrval;
  275. LPVOID pbits;
  276. LPDDRAWI_DDRAWSURFACE_INT psurf_int;
  277. LPDDRAWI_DDRAWSURFACE_INT pnew_int;
  278. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  279. DDSURFACEDESC2 ddsd;
  280. DWORD bytes;
  281. LPBYTE psrc;
  282. LPBYTE pdst;
  283. DWORD y;
  284. LONG pitch;
  285. LPDDPIXELFORMAT lpddpf;
  286. this_gbl = this_lcl->lpGbl;
  287. this_gbl_more = GET_LPDDRAWSURFACE_GBL_MORE(this_gbl);
  288. if (!this_gbl_more->pvContents)
  289. {
  290. return DDERR_GENERIC; // backup probably failed
  291. }
  292. pdrv = this_gbl->lpDD;
  293. GET_PIXEL_FORMAT(this_lcl, this_gbl, lpddpf);
  294. pitch = QWORD_MULTIPLE((this_gbl->wWidth * lpddpf->dwRGBBitCount) >> 3);
  295. psurf_int = createDummySurface(this_lcl);
  296. //
  297. // First try to blt, if that fails, we'll lock and copy memory
  298. //
  299. if (psurf_int)
  300. {
  301. ZeroMemory(&ddsd, sizeof ddsd);
  302. ddsd.dwSize = sizeof ddsd;
  303. ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE | DDSD_PIXELFORMAT;
  304. ddsd.ddpfPixelFormat.dwSize = sizeof ddsd.ddpfPixelFormat;
  305. DD_Surface_GetPixelFormat((LPDIRECTDRAWSURFACE) psurf_int, &ddsd.ddpfPixelFormat);
  306. ddsd.dwWidth = this_gbl->wWidth;
  307. ddsd.dwHeight = this_gbl->wHeight;
  308. ddsd.lPitch = pitch;
  309. ddsd.lpSurface = this_gbl_more->pvContents;
  310. ddrval = DD_Surface_SetSurfaceDesc4((LPDIRECTDRAWSURFACE3) psurf_int, &ddsd, 0);
  311. if (SUCCEEDED(ddrval))
  312. {
  313. pnew_int = MemAlloc(sizeof (DDRAWI_DDRAWSURFACE_INT));
  314. if (pnew_int)
  315. {
  316. pnew_int->lpVtbl = &ddSurface4Callbacks;
  317. pnew_int->lpLcl = this_lcl;
  318. pnew_int->lpLink = pdrv->dsList;
  319. pdrv->dsList = pnew_int;
  320. pnew_int->dwIntRefCnt = 0;
  321. ddrval = ((LPDIRECTDRAWSURFACE) psurf_int)->lpVtbl->Blt(
  322. (LPDIRECTDRAWSURFACE) pnew_int,
  323. NULL,
  324. (LPDIRECTDRAWSURFACE) psurf_int,
  325. NULL,
  326. DDBLT_WAIT,
  327. NULL);
  328. this_gbl_more->dwBackupStamp = this_gbl_more->dwContentsStamp;
  329. pdrv->dsList = pnew_int->lpLink;
  330. MemFree(pnew_int);
  331. if (SUCCEEDED(ddrval))
  332. {
  333. InternalSurfaceRelease(psurf_int, FALSE, FALSE);
  334. DPF(5, "RestoreSurfaceContents Blt succeeded");
  335. return DD_OK;
  336. }
  337. }
  338. }
  339. InternalSurfaceRelease(psurf_int, FALSE, FALSE);
  340. }
  341. //
  342. // Blt failed, so now we'll just lock and copy memory
  343. //
  344. ddrval = InternalLock(this_lcl, &pbits, NULL , DDLOCK_WAIT | DDLOCK_TAKE_WIN16);
  345. if (SUCCEEDED(ddrval))
  346. {
  347. psrc = this_gbl_more->pvContents;
  348. pdst = pbits;
  349. bytes = this_gbl->wWidth;
  350. bytes *= lpddpf->dwRGBBitCount;
  351. bytes >>= 3;
  352. for (y = 0; y < this_gbl->wHeight; ++y)
  353. {
  354. CopyMemory(pdst, psrc, bytes);
  355. psrc += pitch;
  356. pdst += this_gbl->lPitch;
  357. }
  358. InternalUnlock(this_lcl, NULL, NULL, DDLOCK_TAKE_WIN16);
  359. DPF(5, "RestoreSurfaceContents CopyMemory succeeded");
  360. this_gbl_more->dwBackupStamp = this_gbl_more->dwContentsStamp;
  361. }
  362. else
  363. {
  364. return ddrval;
  365. }
  366. return DD_OK;
  367. }
  368. //=============================================================================
  369. //
  370. // Function: restoreSurfaces
  371. //
  372. //=============================================================================
  373. static HRESULT restoreSurfaces(LPDDRAWI_DDRAWSURFACE_INT this_int, LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl)
  374. {
  375. HRESULT ddrval;
  376. if (this_int)
  377. {
  378. while (this_int &&
  379. ((this_int->lpLcl->lpSurfMore->lpDD_lcl != pdrv_lcl) ||
  380. (this_int->lpLcl->dwFlags & DDRAWISURF_IMPLICITCREATE)))
  381. {
  382. this_int = this_int->lpLink;
  383. }
  384. if (this_int)
  385. {
  386. ddrval = restoreSurfaces(this_int->lpLink, pdrv_lcl);
  387. if (SUCCEEDED(ddrval))
  388. {
  389. ddrval = DD_Surface_Restore((LPDIRECTDRAWSURFACE) this_int);
  390. if (FAILED(ddrval))
  391. {
  392. return ddrval;
  393. }
  394. }
  395. else
  396. {
  397. return ddrval;
  398. }
  399. }
  400. }
  401. return DD_OK;
  402. }
  403. //=============================================================================
  404. //
  405. // Function: DD_RestoreAllSurfaces
  406. //
  407. // Restore all surfaces owned by the DirectDraw object.
  408. //
  409. //=============================================================================
  410. HRESULT EXTERN_DDAPI DD_RestoreAllSurfaces(LPDIRECTDRAW lpDD)
  411. {
  412. LPDDRAWI_DIRECTDRAW_INT this_int;
  413. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  414. HRESULT ddrval;
  415. ENTER_DDRAW()
  416. DPF(2,A,"ENTERAPI: DD_RestoreALlSurfaces");
  417. /*DPF(2, "RestoreAllSurfaces");*/
  418. TRY
  419. {
  420. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  421. if (!VALID_DIRECTDRAW_PTR(this_int))
  422. {
  423. LEAVE_DDRAW()
  424. return DDERR_INVALIDOBJECT;
  425. }
  426. this_lcl = this_int->lpLcl;
  427. }
  428. EXCEPT(EXCEPTION_EXECUTE_HANDLER)
  429. {
  430. DPF_ERR("Exception encountered validating parameters");
  431. LEAVE_DDRAW()
  432. return DDERR_INVALIDPARAMS;
  433. }
  434. ddrval = restoreSurfaces(this_lcl->lpGbl->dsList, this_lcl);
  435. DPF(5, "RestoreAllSurfaces returns: %08x (%u)", ddrval, HRESULT_CODE(ddrval));
  436. LEAVE_DDRAW()
  437. return ddrval;
  438. }
  439. //=============================================================================
  440. //
  441. // Function: BackupAllSurfaces
  442. //
  443. // Backup all surfaces owned by the DirectDraw object.
  444. //
  445. //=============================================================================
  446. void BackupAllSurfaces(LPDDRAWI_DIRECTDRAW_GBL this_gbl)
  447. {
  448. LPDDRAWI_DDRAWSURFACE_INT psurf_int;
  449. DPF(5, "BackupAllSurfaces: %08x", this_gbl);
  450. psurf_int = this_gbl->dsList;
  451. while (psurf_int)
  452. {
  453. if (!SURFACE_LOST(psurf_int->lpLcl) &&
  454. (psurf_int->lpLcl->lpSurfMore->lpDD_lcl->lpGbl == this_gbl) &&
  455. (psurf_int->lpLcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) &&
  456. (psurf_int->lpLcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_PERSISTENTCONTENTS))
  457. {
  458. DPF(5, "BackupSurfaceContents: %08x", psurf_int->lpLcl);
  459. BackupSurfaceContents(psurf_int->lpLcl);
  460. }
  461. psurf_int = psurf_int->lpLink;
  462. }
  463. }