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.

942 lines
36 KiB

  1. /****************************************************************************/
  2. // nssidisp.c
  3. //
  4. // SaveScreenBits Interceptor API functions.
  5. //
  6. // Copyright (C) 1997-2000 Microsoft Corporation
  7. /****************************************************************************/
  8. #include <precmpdd.h>
  9. #define TRC_FILE "nssidisp"
  10. #include <winddi.h>
  11. #include <adcg.h>
  12. #include <adcs.h>
  13. #include <aprot.h>
  14. #include <aordprot.h>
  15. #include <nddapi.h>
  16. #include <aoaapi.h>
  17. #include <noadisp.h>
  18. #include <noedisp.h>
  19. #include <acpcapi.h>
  20. #include <ausrapi.h>
  21. #include <nschdisp.h>
  22. #include <nprcount.h>
  23. #include <oe2.h>
  24. #define DC_INCLUDE_DATA
  25. #include <ndddata.c>
  26. #include <oe2data.c>
  27. #undef DC_INCLUDE_DATA
  28. #include <assiapi.h>
  29. #include <nssidisp.h>
  30. #include <nssidata.c>
  31. #include <noeinl.h>
  32. /****************************************************************************/
  33. // SSI_DDInit
  34. /****************************************************************************/
  35. void SSI_DDInit()
  36. {
  37. DC_BEGIN_FN("SSI_DDInit");
  38. memset(&ssiLocalSSBState, 0, sizeof(LOCAL_SSB_STATE));
  39. SSIResetSaveScreenBitmap();
  40. DC_END_FN();
  41. }
  42. /****************************************************************************/
  43. // SSI_InitShm
  44. //
  45. // Alloc-time SHM init.
  46. /****************************************************************************/
  47. void SSI_InitShm()
  48. {
  49. DC_BEGIN_FN("SSI_InitShm");
  50. pddShm->ssi.resetInterceptor = FALSE;
  51. pddShm->ssi.newSaveBitmapSize = FALSE;
  52. pddShm->ssi.sendSaveBitmapSize = 0;
  53. pddShm->ssi.newSaveBitmapSize = 0;
  54. DC_END_FN();
  55. }
  56. /****************************************************************************/
  57. // SSI_Update
  58. //
  59. // Called when there is an SSI update from the WD. bForce forces a reset;
  60. // it's used by shadowing.
  61. /****************************************************************************/
  62. void SSI_Update(BOOL bForce)
  63. {
  64. DC_BEGIN_FN("SSI_Update");
  65. if (pddShm->ssi.resetInterceptor || bForce)
  66. SSIResetSaveScreenBitmap();
  67. if (pddShm->ssi.saveBitmapSizeChanged || bForce) {
  68. pddShm->ssi.sendSaveBitmapSize = pddShm->ssi.newSaveBitmapSize;
  69. pddShm->ssi.saveBitmapSizeChanged = FALSE;
  70. TRC_NRM((TB, "SSI caps: Size %ld", pddShm->ssi.sendSaveBitmapSize));
  71. }
  72. DC_END_FN();
  73. }
  74. /****************************************************************************/
  75. // SSI_ClearOrderEncoding
  76. //
  77. // Called on share state change to reset the order state info for
  78. // orders stored in the DD data segment.
  79. /****************************************************************************/
  80. void SSI_ClearOrderEncoding()
  81. {
  82. DC_BEGIN_FN("SSI_ClearOrderEncoding");
  83. memset(&PrevSaveBitmap, 0, sizeof(PrevSaveBitmap));
  84. DC_END_FN();
  85. }
  86. /****************************************************************************/
  87. // SSIResetSaveScreenBitmap
  88. //
  89. // Resets the SaveScreenBitmap state.
  90. /****************************************************************************/
  91. void SSIResetSaveScreenBitmap()
  92. {
  93. int i;
  94. DC_BEGIN_FN("SSIResetSaveScreenBitmap");
  95. TRC_DBG((TB, "Reset (%d)", ssiLocalSSBState.saveLevel));
  96. // Discard all currently saved bits.
  97. ssiLocalSSBState.saveLevel = 0;
  98. // Reset the number of remote pels saved.
  99. ssiRemoteSSBState.pelsSaved = 0;
  100. // Note that we've seen the update.
  101. pddShm->ssi.resetInterceptor = FALSE;
  102. // Free off any memory we may have allocated.
  103. for (i = 0; i < SSB_MAX_SAVE_LEVEL; i++) {
  104. if (ssiLocalSSBState.saveState[i].pSaveData != NULL) {
  105. EngFreeMem(ssiLocalSSBState.saveState[i].pSaveData);
  106. ssiLocalSSBState.saveState[i].pSaveData = NULL;
  107. }
  108. }
  109. DC_END_FN();
  110. }
  111. /****************************************************************************/
  112. // DrvSaveScreenBits - see NT DDK documentation.
  113. /****************************************************************************/
  114. ULONG_PTR DrvSaveScreenBits(
  115. SURFOBJ *pso,
  116. ULONG iMode,
  117. ULONG_PTR ident,
  118. RECTL *prcl)
  119. {
  120. ULONG_PTR rc;
  121. unsigned ourMode;
  122. RECTL rectTrg;
  123. PDD_PDEV ppdev = (PDD_PDEV)pso->dhpdev;
  124. PDD_DSURF pdsurf;
  125. DC_BEGIN_FN("DrvSaveScreenBits");
  126. // Default is FALSE: let GRE handle SaveBits if we are not in a
  127. // position to do it ourselves - no reason for us to get in the
  128. // business of saving off memory etc.
  129. rc = FALSE;
  130. // Sometimes we're called after being disconnected.
  131. if (ddConnected && pddShm != NULL) {
  132. // Surface is non-NULL.
  133. pso = OEGetSurfObjBitmap(pso, &pdsurf);
  134. INC_OUTCOUNTER(OUT_SAVESCREEN_ALL);
  135. // Get the exclusive bounding rectangle for the operation.
  136. RECT_FROM_RECTL(rectTrg, (*prcl));
  137. TRC_ASSERT((pso->hsurf == ppdev->hsurfFrameBuf),
  138. (TB, "DrvSaveScreenBits should be called for screen surface only"));
  139. if (pso->hsurf == ppdev->hsurfFrameBuf) {
  140. // Send a switch surface PDU if the destination surface is different
  141. // from last drawing order. If we failed to send the PDU, we will
  142. // just have to bail on this drawing order.
  143. if (!OESendSwitchSurfacePDU(ppdev, pdsurf)) {
  144. TRC_ERR((TB, "failed to send the switch surface PDU"));
  145. // We always return TRUE on SS_SAVE operations, as we
  146. // don't want the engine saving away the bits in a bitmap
  147. // and doing a MemBlt to restore the data (not very
  148. // efficient). Instead we return FALSE (failure) on the
  149. // SS_RESTORE to force User to repaint the affected area,
  150. // which we then accumulate in the normal way.
  151. //
  152. // Return TRUE for SS_DISCARD too (although it shouldn't
  153. // matter what we return).
  154. rc = (iMode == SS_RESTORE) ? FALSE : TRUE;
  155. DC_QUIT;
  156. }
  157. } else {
  158. // We don't support DrvSaveScreenBits for offscreen
  159. // rendering.
  160. TRC_ERR((TB, "Offscreen blt bail"));
  161. // We always return TRUE on SS_SAVE operations, as we
  162. // don't want the engine saving away the bits in a bitmap
  163. // and doing a MemBlt to restore the data (not very
  164. // efficient). Instead we return FALSE (failure) on the
  165. // SS_RESTORE to force User to repaint the affected area,
  166. // which we then accumulate in the normal way.
  167. //
  168. // Return TRUE for SS_DISCARD too (although it shouldn't
  169. // matter what we return).
  170. rc = (iMode == SS_RESTORE) ? FALSE : TRUE;
  171. DC_QUIT;
  172. }
  173. // Make sure we can send the order.
  174. if (OE_SendAsOrder(TS_ENC_SAVEBITMAP_ORDER)) {
  175. switch (iMode) {
  176. case SS_SAVE:
  177. TRC_DBG((TB, "SaveBits=%u", ssiLocalSSBState.saveLevel));
  178. // Save the bits.
  179. // Update the save level if the save was successful.
  180. // If it was not successful then RestoreBits will not
  181. // be called so we do not want to increment the save
  182. // level.
  183. rc = SSISaveBits(pso, &rectTrg);
  184. if (rc) {
  185. ssiLocalSSBState.saveLevel++;
  186. // Set the returned ident value to the index of
  187. // the save. Do this after the increment in
  188. // order to avoid returning index 0 (0=FAIL).
  189. rc = ssiLocalSSBState.saveLevel;
  190. }
  191. break;
  192. case SS_RESTORE:
  193. // Update the save level first.
  194. ssiLocalSSBState.saveLevel--;
  195. ident--;
  196. TRC_DBG((TB, "RestoreBits (%d), ident (%u)",
  197. ssiLocalSSBState.saveLevel, ident));
  198. // Restore the bits.
  199. rc = SSIRestoreBits(pso, &rectTrg, ident);
  200. // Check for a negative save level. This will happen
  201. // if there are outstanding saves when the share is
  202. // started or when we get out-of-order restores/
  203. // discards.
  204. if (ssiLocalSSBState.saveLevel < 0) {
  205. TRC_NRM((TB, "RestoreBits caused neg save level"));
  206. ssiLocalSSBState.saveLevel = 0;
  207. }
  208. break;
  209. case SS_FREE:
  210. // Update the save level first.
  211. ssiLocalSSBState.saveLevel--;
  212. ident--;
  213. TRC_DBG((TB, "Discard Bits (%d) ident(%d)",
  214. ssiLocalSSBState.saveLevel, ident));
  215. // Discard the saved bits.
  216. rc = SSIDiscardSave(&rectTrg, ident);
  217. // Check for a negative save level. This will happen
  218. // if there are outstanding saves when the share is
  219. // started or when we get out-of-order restores/
  220. // discards.
  221. if (ssiLocalSSBState.saveLevel < 0) {
  222. TRC_NRM((TB, "DiscardSave caused neg save level"));
  223. ssiLocalSSBState.saveLevel = 0;
  224. }
  225. break;
  226. }
  227. // Make an "insurance" check: If the local save level is zero
  228. // then there should be no pels saved remotely.
  229. if ((ssiLocalSSBState.saveLevel == 0) &&
  230. (ssiRemoteSSBState.pelsSaved != 0)) {
  231. TRC_ALT((TB, "Outstanding remote pels %ld",
  232. ssiRemoteSSBState.pelsSaved ));
  233. ssiRemoteSSBState.pelsSaved = 0;
  234. }
  235. TRC_DBG((TB, "RemotePelsSaved (%ld) rc %u",
  236. ssiRemoteSSBState.pelsSaved, rc));
  237. }
  238. else {
  239. // If the SaveBitmap order is not supported then return
  240. // 0 immediately. 0 is failure for SAVE (the return value
  241. // is a non-0 identifier for success) and FALSE is failure
  242. // for RESTORE. If we've failed SAVEs, we can never get a
  243. // FREE.
  244. TRC_DBG((TB, "SaveBmp not supported"));
  245. INC_OUTCOUNTER(OUT_SAVESCREEN_UNSUPP);
  246. // We always return TRUE on SS_SAVE operations, as we
  247. // don't want the engine saving away the bits in a bitmap
  248. // and doing a MemBlt to restore the data (not very
  249. // efficient). Instead we return FALSE (failure) on the
  250. // SS_RESTORE to force User to repaint the affected area,
  251. // which we then accumulate in the normal way.
  252. //
  253. // Return TRUE for SS_DISCARD too (although it shouldn't
  254. // matter what we return).
  255. rc = (iMode == SS_RESTORE) ? FALSE : TRUE;
  256. }
  257. }
  258. else {
  259. TRC_ERR((TB, "Called when disconnected"));
  260. rc = (iMode == SS_RESTORE) ? FALSE : TRUE;
  261. }
  262. DC_EXIT_POINT:
  263. DC_END_FN();
  264. return rc;
  265. }
  266. /****************************************************************************/
  267. // SSIRemotePelsRequired
  268. //
  269. // Returns the number of remote pels required to store the supplied
  270. // rectangle, taking account of the Save Bitmap granularity.
  271. /****************************************************************************/
  272. __inline UINT32 SSIRemotePelsRequired(PRECTL pRect)
  273. {
  274. UINT32 rectWidth, rectHeight;
  275. UINT32 rc;
  276. DC_BEGIN_FN("SSIRemotePelsRequired");
  277. // Calculate the supplied rectangle size (it is in EXCLUSIVE coords).
  278. rectWidth = pRect->right - pRect->left;
  279. rectHeight = pRect->bottom - pRect->top;
  280. // Required width and height are rounded up to next granularity level for
  281. // that dimension.
  282. rc = (UINT32)(((rectWidth + SAVE_BITMAP_X_GRANULARITY - 1) /
  283. SAVE_BITMAP_X_GRANULARITY * SAVE_BITMAP_X_GRANULARITY) *
  284. ((rectHeight + SAVE_BITMAP_Y_GRANULARITY - 1) /
  285. SAVE_BITMAP_Y_GRANULARITY * SAVE_BITMAP_Y_GRANULARITY));
  286. DC_END_FN();
  287. return rc;
  288. }
  289. /****************************************************************************/
  290. // SSISendSaveBitmapOrder
  291. //
  292. // Sends a SaveBitmap order. Returns FALSE on failure.
  293. /****************************************************************************/
  294. BOOL SSISendSaveBitmapOrder(
  295. PDD_PDEV ppdev,
  296. PRECTL pRect,
  297. unsigned SavePosition,
  298. unsigned Operation)
  299. {
  300. SAVEBITMAP_ORDER *pSaveBitmapOrder;
  301. PINT_ORDER pOrder;
  302. BOOL rc;
  303. DC_BEGIN_FN("SSISendSaveBitmapOrder");
  304. TRC_NRM((TB, "Rect before conversion (%d,%d)(%d,%d)", pRect->left,
  305. pRect->bottom, pRect->right, pRect->top));
  306. // 1 field flag byte. Note that SaveBitmap orders are not clipped,
  307. // so set zero for the number of clip rects.
  308. pOrder = OA_AllocOrderMem(ppdev, MAX_ORDER_SIZE(0, 1,
  309. MAX_SAVEBITMAP_FIELD_SIZE));
  310. if (pOrder != NULL) {
  311. // Target rect is in exclusive coords, convert to inclusive
  312. // for the wire format.
  313. pSaveBitmapOrder = (SAVEBITMAP_ORDER *)oeTempOrderBuffer;
  314. pSaveBitmapOrder->SavedBitmapPosition = SavePosition;
  315. pSaveBitmapOrder->nLeftRect = pRect->left;
  316. pSaveBitmapOrder->nTopRect = pRect->top;
  317. pSaveBitmapOrder->nRightRect = pRect->right - 1;
  318. pSaveBitmapOrder->nBottomRect = pRect->bottom - 1;
  319. pSaveBitmapOrder->Operation = Operation;
  320. // Slow-field-encode the order. NULL for clip rect since we don't clip
  321. // SaveBitmaps.
  322. pOrder->OrderLength = OE2_EncodeOrder(pOrder->OrderData,
  323. TS_ENC_SAVEBITMAP_ORDER, NUM_SAVEBITMAP_FIELDS,
  324. (BYTE *)pSaveBitmapOrder, (BYTE *)&PrevSaveBitmap, etable_SV,
  325. NULL);
  326. INC_OUTCOUNTER(OUT_SAVEBITMAP_ORDERS);
  327. ADD_INCOUNTER(IN_SAVEBITMAP_BYTES, pOrder->OrderLength);
  328. OA_AppendToOrderList(pOrder);
  329. // All done: consider sending the output.
  330. SCH_DDOutputAvailable(ppdev, FALSE);
  331. rc = TRUE;
  332. TRC_NRM((TB, "SaveBitmap op %d pos %ld rect %d %d %d %d",
  333. Operation, SavePosition, pRect->left, pRect->top,
  334. pRect->right - 1, pRect->bottom - 1));
  335. }
  336. else {
  337. TRC_ERR((TB, "Failed to alloc order mem"));
  338. rc= FALSE;
  339. }
  340. DC_END_FN();
  341. return rc;
  342. }
  343. /****************************************************************************/
  344. // SSISaveBits
  345. //
  346. // Saves the specified screen rectangle bits and sends a SaveBitmap order.
  347. // pRect is in exclusive coords. We return FALSE only on low-bounds errors;
  348. // this indicates to GDI that it must simulate the SaveBits using a
  349. // BitBlt without corresponding RestoreBits calls, which is not desirable.
  350. // Instead, if we cannot send a SaveBitmap order or other problems, we return
  351. // TRUE and note that we need to return FALSE on the Restore call, which
  352. // causes a less expensive repaint of the target area.
  353. /****************************************************************************/
  354. BOOL SSISaveBits(SURFOBJ *pso, PRECTL pRect)
  355. {
  356. BOOL rc = TRUE;
  357. DC_BEGIN_FN("SSISaveBits");
  358. TRC_DBG((TB, "SaveScreenBits (%d, %d, %d, %d) level %d",
  359. pRect->left, pRect->bottom, pRect->right, pRect->top,
  360. ssiLocalSSBState.saveLevel));
  361. // The saveLevel should never be negative.
  362. if (ssiLocalSSBState.saveLevel >= 0) {
  363. // If the save level is greater than the number of levels that we
  364. // support we just return TRUE. The corresponding RestoreBits call
  365. // will return FALSE, causing Windows to repaint the area.
  366. // Our maximum save level is such that we should very rarely (if ever)
  367. // go through this path.
  368. if (ssiLocalSSBState.saveLevel < SSB_MAX_SAVE_LEVEL) {
  369. CURRENT_LOCAL_SSB_STATE.pSaveData = NULL;
  370. CURRENT_LOCAL_SSB_STATE.rect = *pRect;
  371. CURRENT_LOCAL_SSB_STATE.fSavedRemotely = FALSE;
  372. // If the rectangle to be saved intersects the current SDA then
  373. // we will have to force a repaint on the restore. This is
  374. // because orders are always sent before Screen Data, so if we
  375. // sent a SAVEBITS order at this point, we would not save the
  376. // intersecting Screen Data.
  377. if (!OE_RectIntersectsSDA(pRect)) {
  378. UINT32 cRemotePelsRequired;
  379. // Calculate the number of pels required in the remote Save
  380. // Bitmap to handle this rectangle.
  381. cRemotePelsRequired = SSIRemotePelsRequired(pRect);
  382. // If there aren't enough pels in the remote Save Bitmap to
  383. // handle this rectangle then return immediately.
  384. if ((ssiRemoteSSBState.pelsSaved + cRemotePelsRequired) <=
  385. pddShm->ssi.sendSaveBitmapSize) {
  386. // Try to send the SaveBits as an order.
  387. CURRENT_LOCAL_SSB_STATE.fSavedRemotely =
  388. SSISendSaveBitmapOrder((PDD_PDEV)(pso->dhpdev),
  389. pRect, ssiRemoteSSBState.pelsSaved, SV_SAVEBITS);
  390. if (CURRENT_LOCAL_SSB_STATE.fSavedRemotely) {
  391. // Store the relevant details in the current entry of
  392. // the local SSB structure.
  393. CURRENT_LOCAL_SSB_STATE.remoteSavedPosition =
  394. ssiRemoteSSBState.pelsSaved;
  395. CURRENT_LOCAL_SSB_STATE.remotePelsRequired =
  396. cRemotePelsRequired;
  397. // Update the count of remote pels saved.
  398. ssiRemoteSSBState.pelsSaved += cRemotePelsRequired;
  399. // Store the rectangle saved. Note that we still claim
  400. // success, even if the copy fails. The result of this
  401. // is that
  402. // - we send save and restore orders to the client
  403. // (gives bandwidth saving and client
  404. // responsiveness)
  405. // - we fail the restore, causing a less efficient
  406. // repaint at the server.
  407. // Other compromise options also available if this
  408. // proves inappropriate.
  409. SSICopyRect(pso, TRUE);
  410. }
  411. }
  412. else {
  413. TRC_NRM((TB, "no space for %lu pels", cRemotePelsRequired));
  414. }
  415. }
  416. else {
  417. // Note we do not save the rect via SSICopyRect -- we only
  418. // restore when fSavedRemotely is TRUE.
  419. TRC_DBG((TB, "SSI intersects SDA, storing failed save"));
  420. CURRENT_LOCAL_SSB_STATE.fSavedRemotely = FALSE;
  421. }
  422. }
  423. else {
  424. // We return TRUE. On Restore, we'll get the same out-of-bounds
  425. // value and return FALSE to repaint.
  426. TRC_ALT((TB, "saveLevel(%d) exceeds maximum",
  427. ssiLocalSSBState.saveLevel));
  428. }
  429. }
  430. else {
  431. // This is a real problem, so we tell GDI to to what it needs to.
  432. TRC_ERR((TB, "SSISaveBits called with negative saveLevel"));
  433. rc = FALSE;
  434. }
  435. DC_END_FN();
  436. return rc;
  437. }
  438. /****************************************************************************/
  439. /* FUNCTION: SSIFindSlotAndDiscardAbove */
  440. /* */
  441. /* Finds the top slot in the SSB stack which matches pRect and updates */
  442. /* ssiLocalSSBState.saveLevel to index it. */
  443. /* RETURNS: TRUE if a match was found, FALSE otherwise */
  444. /****************************************************************************/
  445. BOOL SSIFindSlotAndDiscardAbove(PRECTL pRect, ULONG_PTR ident)
  446. {
  447. int i;
  448. BOOL rc = FALSE;
  449. DC_BEGIN_FN("SSIFindSlotAndDiscardAbove");
  450. // Find the bits we are trying to restore.
  451. for (i = ssiLocalSSBState.saveLevel; i >= 0; i--) {
  452. if (i == (int)ident) {
  453. // We're at the right level in the saveState.
  454. TRC_NRM((TB, "found match at level %d", i));
  455. TRC_DBG((TB, "Rect matched (%d, %d, %d, %d)",
  456. ssiLocalSSBState.saveState[i].rect.left,
  457. ssiLocalSSBState.saveState[i].rect.bottom,
  458. ssiLocalSSBState.saveState[i].rect.right,
  459. ssiLocalSSBState.saveState[i].rect.top));
  460. ssiLocalSSBState.saveLevel = i;
  461. rc = TRUE;
  462. DC_QUIT;
  463. }
  464. else {
  465. // Discard this entry on the stack.
  466. ssiRemoteSSBState.pelsSaved -=
  467. ssiLocalSSBState.saveState[i].remotePelsRequired;
  468. if (ssiLocalSSBState.saveState[i].pSaveData != NULL) {
  469. TRC_DBG((TB, "Freeing memory at %p",
  470. ssiLocalSSBState.saveState[i].pSaveData));
  471. EngFreeMem(ssiLocalSSBState.saveState[i].pSaveData);
  472. ssiLocalSSBState.saveState[i].pSaveData = NULL;
  473. }
  474. }
  475. }
  476. // If we get here we failed to match on any of the entries.
  477. TRC_NRM((TB, "no match on stack"));
  478. ssiLocalSSBState.saveLevel = 0;
  479. DC_EXIT_POINT:
  480. DC_END_FN();
  481. return rc;
  482. }
  483. /****************************************************************************/
  484. // SSIRestoreBits
  485. //
  486. // Restores the specified screen rectangle. If the bits were saved remotely
  487. // we make sure to send a SaveBitmap order. We return TRUE if we restored
  488. // the bits at the client, else we return FALSE to have GDI repaint the
  489. // target rect.
  490. /****************************************************************************/
  491. BOOL SSIRestoreBits(SURFOBJ *pso, PRECTL pRect, ULONG_PTR ident)
  492. {
  493. BOOL rc = FALSE;
  494. DC_BEGIN_FN("SSIRestoreBits");
  495. TRC_DBG((TB, "RestoreScreenBits (%d, %d, %d, %d) level %d",
  496. pRect->left, pRect->bottom, pRect->right, pRect->top,
  497. ssiLocalSSBState.saveLevel));
  498. pddCacheStats[SSI].CacheReads++;
  499. // If the save level is negative then either there was a save
  500. // outstanding when we hooked the SSB or we have received out of order
  501. // restores/discards so we discarded stuff from the SSB stack
  502. // ourselves. We can't distinguish between these two cases at this
  503. // point so we will always pass this on to the display driver and hope
  504. // that it is robust enough to cope with a discard which didn't have a
  505. // corresponding save.
  506. if (ssiLocalSSBState.saveLevel >= 0) {
  507. // If we don't have enough levels (rare problem), we return FALSE
  508. // which causes a repaint.
  509. if (ssiLocalSSBState.saveLevel < SSB_MAX_SAVE_LEVEL) {
  510. // Search for the corresponding save order on our stack.
  511. if (SSIFindSlotAndDiscardAbove(pRect, ident)) {
  512. if (CURRENT_LOCAL_SSB_STATE.fSavedRemotely) {
  513. // Make sure GDI is giving us back the same sized
  514. // block, otherwise the client can get messed up.
  515. //TRC_ASSERT((CURRENT_LOCAL_SSB_STATE.remotePelsRequired ==
  516. // SSIRemotePelsRequired(pRect)),
  517. // (TB,"Rect (%d,%d,%d,%d) for restore level %u "
  518. // "size %u is too large (stored size=%u)",
  519. // pRect->left, pRect->top, pRect->right,
  520. // pRect->bottom, ssiLocalSSBState.saveLevel,
  521. // SSIRemotePelsRequired(pRect),
  522. // CURRENT_LOCAL_SSB_STATE.remotePelsRequired));
  523. // Update the remote pel count first. Even if we fail
  524. // to send the order we want to free up the remote pels.
  525. ssiRemoteSSBState.pelsSaved -=
  526. CURRENT_LOCAL_SSB_STATE.remotePelsRequired;
  527. // The bits were saved remotely, send the restore order.
  528. TRC_DBG((TB, "Try sending the order"));
  529. rc = SSISendSaveBitmapOrder((PDD_PDEV)(pso->dhpdev),
  530. pRect, CURRENT_LOCAL_SSB_STATE.remoteSavedPosition,
  531. SV_RESTOREBITS);
  532. // Now restore the bits to the screen, so long as we sent
  533. // the order. No point repainting the screen if we could
  534. // not send the order as we'll want GRE+USER to redraw it
  535. // so that we can accumulate the output.
  536. if (rc) {
  537. pddCacheStats[SSI].CacheHits++;
  538. if (CURRENT_LOCAL_SSB_STATE.pSaveData != NULL) {
  539. TRC_DBG((TB, "Restore bits to local screen"));
  540. SSICopyRect(pso, FALSE);
  541. }
  542. else {
  543. TRC_DBG((TB, "No data to restore, repaint"));
  544. rc = FALSE;
  545. }
  546. }
  547. else {
  548. // We failed the send, but still need to discard any
  549. // locally saved data.
  550. if (CURRENT_LOCAL_SSB_STATE.pSaveData != NULL) {
  551. EngFreeMem(CURRENT_LOCAL_SSB_STATE.pSaveData);
  552. CURRENT_LOCAL_SSB_STATE.pSaveData = NULL;
  553. }
  554. }
  555. }
  556. else {
  557. // We failed to save the bitmap remotely originally so now
  558. // we need to return FALSE to force a repaint.
  559. // We should never have allocated any local memory.
  560. TRC_ASSERT((CURRENT_LOCAL_SSB_STATE.pSaveData == NULL),
  561. (TB,"We allocated memory without remote save!"));
  562. TRC_NRM((TB, "No remote save, force repaint"));
  563. }
  564. }
  565. else {
  566. // We failed to find a match. This is not an error -
  567. // it will happen when saves are not restored in LIFO fashion
  568. // and it will also happen when SSI gets a sync now whilst
  569. // something is saved.
  570. TRC_DBG((TB, "Cannot find save request"));
  571. }
  572. }
  573. else {
  574. TRC_ALT((TB, "saveLevel(%d) exceeds maximum",
  575. ssiLocalSSBState.saveLevel));
  576. }
  577. }
  578. else {
  579. TRC_ALT((TB, "Restore without save"));
  580. }
  581. DC_END_FN();
  582. return rc;
  583. }
  584. /****************************************************************************/
  585. // SSIDiscardSave
  586. //
  587. // Discards the specified screen rectangle bits. Always returns TRUE
  588. // saying that the discard succeeded.
  589. /****************************************************************************/
  590. BOOL SSIDiscardSave(PRECTL pRect, ULONG_PTR ident)
  591. {
  592. BOOL rc;
  593. DC_BEGIN_FN("SSIDiscardSave");
  594. TRC_DBG((TB, "Discard for rect L%u R%u T%u B%u", pRect->left,
  595. pRect->right, pRect->top, pRect->bottom));
  596. // If the save level is negative then either there was a save
  597. // outstanding when we hooked the SSB or we have received out of order
  598. // restores/discards so we discarded stuff from the SSB stack ourselves.
  599. if (ssiLocalSSBState.saveLevel >= 0) {
  600. // If the save level is greater than the number of levels that we
  601. // support we just return TRUE. We will have ignored the SaveBits
  602. // call - so we have effectively discarded the bits already.
  603. // Our maximum save level is such that we should very rarely (if ever)
  604. // go through this path.
  605. if (ssiLocalSSBState.saveLevel < SSB_MAX_SAVE_LEVEL) {
  606. pddCacheStats[SSI].CacheReads++;
  607. // Search for the corresponding save order on our stack.
  608. // Not finding a slot match is not unusual, it can happen
  609. // when saves are not restored in LIFO fashion or when SSI
  610. // gets a sync while something is saved.
  611. if (SSIFindSlotAndDiscardAbove(pRect, ident)) {
  612. // If the bits were saved remotely then update local counter
  613. // for removed bits.
  614. if (CURRENT_LOCAL_SSB_STATE.fSavedRemotely) {
  615. // We don't transmit FREE/DISCARDSAVE orders - there is
  616. // no need because each Save/Restore order contains all
  617. // the necessary information (e.g. position of the bits
  618. // in the Save Bitmap). Just update our counter to take
  619. // account of the remote freed bits.
  620. ssiRemoteSSBState.pelsSaved -=
  621. CURRENT_LOCAL_SSB_STATE.remotePelsRequired;
  622. }
  623. // If we actually copied the bits, then free the memory.
  624. if (CURRENT_LOCAL_SSB_STATE.pSaveData != NULL) {
  625. TRC_DBG((TB, "Free off stored memory at %p",
  626. CURRENT_LOCAL_SSB_STATE.pSaveData));
  627. EngFreeMem(CURRENT_LOCAL_SSB_STATE.pSaveData);
  628. CURRENT_LOCAL_SSB_STATE.pSaveData = NULL;
  629. }
  630. }
  631. }
  632. else {
  633. TRC_ALT((TB, "saveLevel(%d) exceeds maximum",
  634. ssiLocalSSBState.saveLevel));
  635. }
  636. }
  637. else {
  638. TRC_ALT((TB, "Restore without save"));
  639. }
  640. DC_END_FN();
  641. return TRUE;
  642. }
  643. /****************************************************************************/
  644. // SSICopyRect
  645. //
  646. // Copy a screen rectangle.
  647. /****************************************************************************/
  648. void SSICopyRect(SURFOBJ *pso, BOOL save)
  649. {
  650. UINT32 size;
  651. PBYTE pSrc;
  652. PBYTE pDest;
  653. PBYTE pScreenLocation;
  654. unsigned rectWidth;
  655. unsigned rectHeight;
  656. unsigned paddedRectWidth;
  657. unsigned row;
  658. unsigned srcDelta;
  659. unsigned destDelta;
  660. PDD_PDEV pPDev;
  661. #ifdef DC_HICOLOR
  662. #ifdef DC_DEBUG
  663. unsigned bpp;
  664. #endif
  665. #endif
  666. DC_BEGIN_FN("SSICopyRect");
  667. // Set up some key params which are independent of the direction of
  668. // copy.
  669. rectHeight = CURRENT_LOCAL_SSB_STATE.rect.bottom -
  670. CURRENT_LOCAL_SSB_STATE.rect.top;
  671. pPDev = (PDD_PDEV)pso->dhpdev;
  672. #ifdef DC_HICOLOR
  673. if (pso->iBitmapFormat == BMF_24BPP) {
  674. pScreenLocation = pPDev->pFrameBuf +
  675. (CURRENT_LOCAL_SSB_STATE.rect.top * pso->lDelta) +
  676. (CURRENT_LOCAL_SSB_STATE.rect.left * 3);
  677. // rectWidth is in bytes. At 24bpp, this is 3 * number of pels.
  678. rectWidth = (CURRENT_LOCAL_SSB_STATE.rect.right -
  679. CURRENT_LOCAL_SSB_STATE.rect.left) * 3;
  680. #ifdef DC_DEBUG
  681. bpp = 24;
  682. #endif
  683. }
  684. else if (pso->iBitmapFormat == BMF_16BPP) {
  685. pScreenLocation = pPDev->pFrameBuf +
  686. (CURRENT_LOCAL_SSB_STATE.rect.top * pso->lDelta) +
  687. (CURRENT_LOCAL_SSB_STATE.rect.left * 2);
  688. // rectWidth is in bytes. At 16bpp, this is 2 * number of pels.
  689. rectWidth = (CURRENT_LOCAL_SSB_STATE.rect.right -
  690. CURRENT_LOCAL_SSB_STATE.rect.left) * 2;
  691. #ifdef DC_DEBUG
  692. bpp = 16;
  693. #endif
  694. }
  695. else
  696. #endif
  697. if (pso->iBitmapFormat == BMF_8BPP) {
  698. pScreenLocation = pPDev->pFrameBuf +
  699. (CURRENT_LOCAL_SSB_STATE.rect.top * pso->lDelta) +
  700. CURRENT_LOCAL_SSB_STATE.rect.left;
  701. // rectWidth is in bytes. At 8bpp, this is the number of pels.
  702. rectWidth = CURRENT_LOCAL_SSB_STATE.rect.right -
  703. CURRENT_LOCAL_SSB_STATE.rect.left;
  704. #ifdef DC_HICOLOR
  705. #ifdef DC_DEBUG
  706. bpp = 8;
  707. #endif
  708. #endif
  709. }
  710. else {
  711. pScreenLocation = pPDev->pFrameBuf +
  712. (CURRENT_LOCAL_SSB_STATE.rect.top * pso->lDelta) +
  713. (CURRENT_LOCAL_SSB_STATE.rect.left / 2);
  714. // rectWidth is in bytes. At 4bpp, this is (number of pels)/2.
  715. // However, since we copy whole bytes, we need to round 'right' up
  716. // and 'left' down to the nearest multiple of 2.
  717. rectWidth = ((CURRENT_LOCAL_SSB_STATE.rect.right + 1) -
  718. (CURRENT_LOCAL_SSB_STATE.rect.left & ~1)) / 2;
  719. #ifdef DC_HICOLOR
  720. #ifdef DC_DEBUG
  721. bpp = 4;
  722. #endif
  723. #endif
  724. }
  725. paddedRectWidth = (unsigned)DC_ROUND_UP_4(rectWidth);
  726. TRC_DBG((TB, "CopyRect: L%u R%u B%u T%u H%u W%u, PW%u sc%p index %d",
  727. CURRENT_LOCAL_SSB_STATE.rect.left,
  728. CURRENT_LOCAL_SSB_STATE.rect.right,
  729. CURRENT_LOCAL_SSB_STATE.rect.bottom,
  730. CURRENT_LOCAL_SSB_STATE.rect.top,
  731. rectHeight,
  732. rectWidth,
  733. paddedRectWidth,
  734. pScreenLocation,
  735. ssiLocalSSBState.saveLevel));
  736. #ifdef DC_HICOLOR
  737. TRC_ASSERT(((pso->iBitmapFormat == BMF_4BPP) ||
  738. (pso->iBitmapFormat == BMF_8BPP) ||
  739. (pso->iBitmapFormat == BMF_16BPP) ||
  740. (pso->iBitmapFormat == BMF_24BPP)),
  741. (TB, "Bitmap format %d unsupported", pso->iBitmapFormat));
  742. #else
  743. // Only coded for 4bpp and 8bpp thus far.
  744. TRC_ASSERT(((pso->iBitmapFormat == BMF_8BPP) ||
  745. (pso->iBitmapFormat == BMF_4BPP)),
  746. (TB, "Bitmap format %d unsupported", pso->iBitmapFormat));
  747. #endif
  748. // Allocate memory if required. The size can be calculated from the
  749. // rectl field: NB This is in exclusive coords.
  750. if (save) {
  751. size = rectHeight * paddedRectWidth;
  752. CURRENT_LOCAL_SSB_STATE.pSaveData = EngAllocMem(FL_ZERO_MEMORY,
  753. size, DD_ALLOC_TAG);
  754. #ifdef DC_HICOLOR
  755. TRC_DBG((TB, "Save: alloc %u bytes for %dBPP at %p",
  756. size, bpp,
  757. CURRENT_LOCAL_SSB_STATE.pSaveData));
  758. #else
  759. TRC_DBG((TB, "Save: alloc %u bytes for %dBPP at %p",
  760. size,
  761. pso->iBitmapFormat == BMF_8BPP ? 8 : 4,
  762. CURRENT_LOCAL_SSB_STATE.pSaveData));
  763. #endif
  764. if (CURRENT_LOCAL_SSB_STATE.pSaveData != NULL) {
  765. // Now copy the bits. No need to explicitly zero the pad bytes as
  766. // we've nulled the memory on allocation.
  767. pSrc = pScreenLocation;
  768. pDest = CURRENT_LOCAL_SSB_STATE.pSaveData;
  769. srcDelta = pso->lDelta;
  770. destDelta = paddedRectWidth;
  771. TRC_DBG((TB, "Save: Copying from %p to %p", pSrc, pDest));
  772. for (row = 0; row < rectHeight; row++) {
  773. memcpy(pDest, pSrc, rectWidth);
  774. pDest += destDelta;
  775. pSrc += srcDelta;
  776. }
  777. }
  778. else {
  779. TRC_ALT((TB, "Failed alloc %ul bytes, SSI save aborted", size));
  780. }
  781. }
  782. else {
  783. // Copy the bits to the screen bitmap.
  784. pSrc = CURRENT_LOCAL_SSB_STATE.pSaveData;
  785. pDest = pScreenLocation;
  786. srcDelta = paddedRectWidth;
  787. destDelta = pso->lDelta;
  788. TRC_DBG((TB, "Restore: Copying from %p to %p", pSrc, pDest));
  789. TRC_ASSERT((pSrc != NULL), (TB,"Source for SSI restore is NULL!"));
  790. for (row = 0; row < rectHeight; row++) {
  791. memcpy(pDest, pSrc, rectWidth);
  792. pDest += destDelta;
  793. pSrc += srcDelta;
  794. }
  795. TRC_DBG((TB, "Freeing memory at %p"));
  796. EngFreeMem(CURRENT_LOCAL_SSB_STATE.pSaveData);
  797. CURRENT_LOCAL_SSB_STATE.pSaveData = NULL;
  798. }
  799. DC_END_FN();
  800. } /* SSICopyRect */