|
|
1.1 ! root 1: /***************************************************************************** ! 2: * 12/9/92 ! 3: * ! 4: * Save Screen Bits ! 5: * ! 6: * Copyright (c) Microsoft Corp. 1992 ! 7: *****************************************************************************/ ! 8: ! 9: #include "driver.h" ! 10: ! 11: BOOL bMoveSaveScreenBitsToHost(PPDEV ppdev, PSAVEDSCRNBITS *ppssbNewNode); ! 12: ! 13: ULONG nSaveScreenBitsCalls, ! 14: nSaveScreenBits, ! 15: nRestoreScreenBits, ! 16: nFreeScreenBits, ! 17: nRestoreScreenBitsHit, ! 18: nRestoreScreenBitsMiss, ! 19: nSsbMovedToHostFromSS_SAVE, ! 20: nSsbMovedToHostFromSrcBmCache; ! 21: ! 22: ! 23: ! 24: /***************************************************************************** ! 25: * DrvSaveScreenBits - Save and Restore the screen bits. ! 26: * ! 27: * Notes: ! 28: * ! 29: * The same storage in off screen video memory is used ! 30: * for the saved screen bits and source bitmap caching. ! 31: * ! 32: * The off screen memory is treated as a one level deep ! 33: * cache. So, if a source bitmap is used while there are ! 34: * saved screen bits in the offscreen area then the saved ! 35: * screen bits are moved to host memory. ! 36: * ! 37: * typedef struct _savedscrnbitshdr { ! 38: * struct __savedscrnbitshdr * pssbhLink; ! 39: * ULONG iUniq; ! 40: * INT x, ! 41: * y, ! 42: * cx, ! 43: * cy; ! 44: * } SAVEDSCRNBITSHDR; ! 45: * ! 46: * The Saved Screen Bits Header has two functions, closely ! 47: * related but different. When the SavedScreenBitsHeader is ! 48: * used in the pdev the fields have the following meaning: ! 49: * ! 50: * pssbhLink: This is the link to a list of saved areas in ! 51: * host memory. If this link is NULL there is no ! 52: * list of saved areas. ! 53: * ! 54: * iUniq: This is the unique ID for the screen bits in ! 55: * off screen video memory. If this is -1 then ! 56: * there are no valid bits in off screen memory. ! 57: * ! 58: * This field may be -1 and pssbhLink may be non-null. ! 59: * This case would indicate that the off screen memory ! 60: * does not contain valid bits, but there are ! 61: * valid bits stored in host memory. ! 62: * ! 63: * When used as a header for saved bits in host memory: ! 64: * ! 65: * pssbhLink: This is the link to the next set of saved ! 66: * bits. If this is NULL then this is the last ! 67: * set of bits in the chain. ! 68: * ! 69: * iUniq: This is the uinque ID for bits associated with ! 70: * this header. ! 71: * ! 72: ****************************************************************************/ ! 73: ! 74: ULONG DrvSaveScreenBits( ! 75: SURFOBJ *pso, ! 76: ULONG iMode, ! 77: ULONG ident, ! 78: RECTL *prcl) ! 79: { ! 80: PPDEV ppdev; ! 81: PSAVEDSCRNBITSHDR pssbhInPdev; ! 82: PSAVEDSCRNBITS pssb, pssbLast, pssbTemp; ! 83: PSAVEDSCRNBITS pssbNewNode; ! 84: WORD cmd; ! 85: BOOL bRet; ! 86: INT cx, cy, cxInWords, x; ! 87: ! 88: ppdev = (PPDEV) pso->dhpdev; ! 89: ! 90: #if 1 ! 91: DISPDBG((1, "S3.DLL!DrvSaveScreenBits - Entry\n")); ! 92: DISPDBG((1, "\tiMode: %d\n", iMode)); ! 93: DISPDBG((1, "\tident: %x\n", ident)); ! 94: #endif ! 95: ! 96: nSaveScreenBitsCalls++; ! 97: ! 98: switch (iMode) ! 99: { ! 100: case SS_SAVE: ! 101: ! 102: // First test if this rectangle is small enough for us to ! 103: // handle in the off screen memory. ! 104: ! 105: cx = prcl->right - prcl->left; ! 106: cy = prcl->bottom - prcl->top; ! 107: ! 108: if ((cx > OFF_SCREEN_BITMAP_CX) || ! 109: (cy > OFF_SCREEN_BITMAP_CY)) ! 110: { ! 111: return(0); ! 112: } ! 113: ! 114: nSaveScreenBits++; ! 115: ! 116: // Invalidate any cached source bitmap. ! 117: ! 118: ppdev->hsurfCachedBitmap = (HSURF) -1; ! 119: ! 120: // if valid bits are already in the cache ! 121: // move them to host memory. ! 122: ! 123: pssbhInPdev = &(ppdev->SavedScreenBitsHeader); ! 124: ! 125: if (pssbhInPdev->iUniq != -1) ! 126: { ! 127: // We're treating the saved bits as a stack, since this ! 128: // makes the most sense from how User uses it. ! 129: ! 130: nSsbMovedToHostFromSS_SAVE++; ! 131: ! 132: DISPDBG((1, "S3.DLL - Saved Screen Bits Moved to Host Memory from SS_SAVE\n")); ! 133: ! 134: bRet = bMoveSaveScreenBitsToHost(ppdev, &pssbNewNode); ! 135: if (bRet == FALSE) ! 136: return(0); ! 137: ! 138: // Connect this newNode to the beginning of the list of ! 139: // save screen bits nodes. ! 140: ! 141: pssbTemp = pssbhInPdev->pssbLink; ! 142: pssbhInPdev->pssbLink = pssbNewNode; ! 143: pssbNewNode->ssbh.pssbLink = pssbTemp; ! 144: ! 145: } ! 146: ! 147: // Tag the off screen cache with the save bits information. ! 148: ! 149: pssbhInPdev->iUniq = ++(ppdev->iUniqeSaveScreenBits); ! 150: pssbhInPdev->x = prcl->left; ! 151: pssbhInPdev->y = prcl->top; ! 152: pssbhInPdev->cx = cx; ! 153: pssbhInPdev->cy = cy; ! 154: ! 155: // Copy the screen bits to the off screen cache. ! 156: ! 157: cmd = BITBLT | DRAW | DIR_TYPE_XY | WRITE | DRAWING_DIR_TBLRXM; ! 158: ! 159: FIFOWAIT(FIFO_2_EMPTY); ! 160: ! 161: TEST_AND_SET_FRGD_MIX(SRC_DISPLAY_MEMORY | OVERPAINT); ! 162: ! 163: OUTPW(MULTIFUNC_CNTL, (DATA_EXTENSION | ALL_ONES)); ! 164: ! 165: FIFOWAIT(FIFO_7_EMPTY); ! 166: ! 167: OUTPW(CUR_X, pssbhInPdev->x); ! 168: OUTPW(CUR_Y, pssbhInPdev->y); ! 169: OUTPW(DEST_X, OFF_SCREEN_BITMAP_X); ! 170: OUTPW(DEST_Y, OFF_SCREEN_BITMAP_Y); ! 171: ! 172: OUTPW(RECT_WIDTH, pssbhInPdev->cx - 1); ! 173: OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | pssbhInPdev->cy - 1)); ! 174: ! 175: OUTPW(CMD, cmd); ! 176: ! 177: // Return the ID of this set of screen bits. ! 178: ! 179: return(pssbhInPdev->iUniq); ! 180: ! 181: case SS_RESTORE: ! 182: ! 183: nRestoreScreenBits++; ! 184: ! 185: // If the bits to restore are in the off screen cache ! 186: // copy them to the screen. Invalidate the cache. ! 187: ! 188: pssbhInPdev = &(ppdev->SavedScreenBitsHeader); ! 189: ! 190: if (ident == pssbhInPdev->iUniq) ! 191: { ! 192: nRestoreScreenBitsHit++; ! 193: ! 194: // Copy the cached off screen bits to the screen. ! 195: ! 196: cmd = BITBLT | DRAW | DIR_TYPE_XY | WRITE | DRAWING_DIR_TBLRXM; ! 197: ! 198: FIFOWAIT(FIFO_2_EMPTY); ! 199: ! 200: TEST_AND_SET_FRGD_MIX(SRC_DISPLAY_MEMORY | OVERPAINT); ! 201: ! 202: OUTPW(MULTIFUNC_CNTL, (DATA_EXTENSION | ALL_ONES)); ! 203: ! 204: FIFOWAIT(FIFO_7_EMPTY); ! 205: ! 206: OUTPW(CUR_X, OFF_SCREEN_BITMAP_X); ! 207: OUTPW(CUR_Y, OFF_SCREEN_BITMAP_Y); ! 208: OUTPW(DEST_X, pssbhInPdev->x); ! 209: OUTPW(DEST_Y, pssbhInPdev->y); ! 210: ! 211: OUTPW(RECT_WIDTH, pssbhInPdev->cx - 1); ! 212: OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | pssbhInPdev->cy - 1)); ! 213: ! 214: OUTPW(CMD, cmd); ! 215: ! 216: // Invalidate the cache. ! 217: ! 218: pssbhInPdev->iUniq = (ULONG) -1; ! 219: ! 220: return (TRUE); ! 221: ! 222: } ! 223: else ! 224: { ! 225: // First find the SavedBits Node. ! 226: ! 227: nRestoreScreenBitsMiss++; ! 228: ! 229: pssbLast = (PSAVEDSCRNBITS) pssbhInPdev; ! 230: for (pssb = pssbhInPdev->pssbLink; ! 231: pssb != NULL; ! 232: pssb = pssb->ssbh.pssbLink) ! 233: { ! 234: // If this is the node we're looking for then ! 235: // restore the bits and free the node. ! 236: ! 237: if (pssb->ssbh.iUniq == ident) ! 238: { ! 239: x = pssb->ssbh.x; ! 240: cx = pssb->ssbh.cx; ! 241: cy = pssb->ssbh.cy; ! 242: ! 243: // Restore the bits to the screen. ! 244: ! 245: if (!(x & 0x1) && !(cx & 0x01)) ! 246: { ! 247: cmd = RECTANGLE_FILL | BYTE_SWAP | BUS_SIZE_16 | ! 248: DRAWING_DIR_TBLRXM | DIR_TYPE_XY | WAIT | ! 249: DRAW | LAST_PIXEL_ON | WRITE; ! 250: } ! 251: else ! 252: { ! 253: cmd = RECTANGLE_FILL | BUS_SIZE_8 | ! 254: DRAWING_DIR_TBLRXM | DIR_TYPE_XY | WAIT | ! 255: DRAW | LAST_PIXEL_ON | WRITE; ! 256: } ! 257: ! 258: FIFOWAIT(FIFO_8_EMPTY); ! 259: ! 260: TEST_AND_SET_WRT_MASK(0xff); ! 261: OUTPW (MULTIFUNC_CNTL, (DATA_EXTENSION | ALL_ONES)); ! 262: TEST_AND_SET_FRGD_MIX(SRC_CPU_DATA | OVERPAINT); ! 263: ! 264: OUTPW (CUR_X, x); ! 265: OUTPW (CUR_Y, pssb->ssbh.y); ! 266: OUTPW (RECT_WIDTH, (cx - 1)); ! 267: OUTPW (MULTIFUNC_CNTL, (RECT_HEIGHT | (cy - 1))); ! 268: ! 269: GPWAIT(); ! 270: ! 271: OUTPW (CMD, cmd); ! 272: ! 273: // Now transfer the data from the screen to the host memory bitmap. ! 274: ! 275: CHECK_DATA_READY; ! 276: ! 277: if (!(x & 0x1) && !(cx & 0x01)) ! 278: { ! 279: cxInWords = (cx + 1) / 2; ! 280: vDataPortOut(ppdev, (PWORD) pssb->aBits, (cxInWords * cy)); ! 281: } ! 282: else ! 283: { ! 284: vDataPortOutB(ppdev, (PBYTE) pssb->aBits, (cx * cy)); ! 285: } ! 286: ! 287: CHECK_DATA_COMPLETE; ! 288: ! 289: // Snip this node out of the list. ! 290: ! 291: pssbLast->ssbh.pssbLink = pssb->ssbh.pssbLink; ! 292: ! 293: // free the memory used to hold the bits. ! 294: ! 295: LocalFree(pssb); ! 296: ! 297: return (TRUE); ! 298: } ! 299: ! 300: pssbLast = pssb; ! 301: } ! 302: ! 303: DISPDBG((0, "S3.DLL!DrvSaveScreenBits (restore) - Could not find iUniq in the Saved Bits list\n")); ! 304: return (0); ! 305: } ! 306: ! 307: break; ! 308: ! 309: case SS_FREE: ! 310: ! 311: nFreeScreenBits++; ! 312: ! 313: pssbhInPdev = &(ppdev->SavedScreenBitsHeader); ! 314: ! 315: // If the bits to free are in the offscreen cache ! 316: // Just invalidate the cache. ! 317: ! 318: if (ident == pssbhInPdev->iUniq) ! 319: { ! 320: pssbhInPdev->iUniq = (ULONG) -1; ! 321: } ! 322: else ! 323: { ! 324: pssbLast = (PSAVEDSCRNBITS) pssbhInPdev; ! 325: for (pssb = pssbhInPdev->pssbLink; ! 326: pssb != NULL; ! 327: pssb = pssb->ssbh.pssbLink) ! 328: { ! 329: if (pssb->ssbh.iUniq == ident) ! 330: { ! 331: // Snip this node out of the list. ! 332: ! 333: pssbLast->ssbh.pssbLink = pssb->ssbh.pssbLink; ! 334: ! 335: // free the memory used to hold the bits. ! 336: ! 337: LocalFree(pssb); ! 338: ! 339: return (TRUE); ! 340: } ! 341: ! 342: pssbLast = pssb; ! 343: } ! 344: ! 345: DISPDBG((0, "S3.DLL!DrvSaveScreenBits (free) - Could not find iUniq in the Saved Bits list\n")); ! 346: } ! 347: ! 348: break; ! 349: ! 350: default: ! 351: break; ! 352: ! 353: } ! 354: ! 355: return (0); ! 356: ! 357: ! 358: } ! 359: ! 360: /***************************************************************************** ! 361: * bMoveSaveScreenBitsToHost ! 362: ****************************************************************************/ ! 363: BOOL bMoveSaveScreenBitsToHost(PPDEV ppdev, PSAVEDSCRNBITS *ppssbNewNode) ! 364: { ! 365: PSAVEDSCRNBITSHDR pssbhInPdev; ! 366: PSAVEDSCRNBITS pssbNewNode; ! 367: INT nSize, cx, cy, cxInWords, x; ! 368: WORD cmd; ! 369: WORD* pwBuffer; ! 370: BYTE* pjBuffer; ! 371: ULONG i; ! 372: ! 373: pssbhInPdev = &(ppdev->SavedScreenBitsHeader); ! 374: ! 375: // Allocate a new node for the bit in the cache. ! 376: // Note: this calculation assumes an 8bpp display. ! 377: ! 378: x = pssbhInPdev->x; ! 379: cx = pssbhInPdev->cx; ! 380: cy = pssbhInPdev->cy; ! 381: ! 382: ! 383: nSize = sizeof (SAVEDSCRNBITSHDR) + ((cx + 4) & ~0x3) * cy; ! 384: ! 385: pssbNewNode = (PSAVEDSCRNBITS) LocalAlloc(LMEM_FIXED, nSize); ! 386: ! 387: if (pssbNewNode == NULL) ! 388: { ! 389: DISPDBG((0, "S3.DLL!bMoveSaveScreenBitsToHost - LocalAlloc for pssbNewNode failed\n")); ! 390: EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); ! 391: return (FALSE); ! 392: } ! 393: ! 394: // Pass back the address of the node we allocated here. ! 395: ! 396: *ppssbNewNode = pssbNewNode; ! 397: ! 398: // Assign all the save screen bits header information ! 399: // about the bits in the cache to the newly allocated ! 400: // node. ! 401: ! 402: pssbNewNode->ssbh = *pssbhInPdev; ! 403: ! 404: // Copy the bits into the new node. ! 405: ! 406: if (!(x & 0x1) && !(cx & 0x01)) ! 407: { ! 408: cmd = RECTANGLE_FILL | BYTE_SWAP | BUS_SIZE_16 | ! 409: DRAWING_DIR_TBLRXM | DIR_TYPE_XY | WAIT | ! 410: DRAW | LAST_PIXEL_ON | READ; ! 411: } ! 412: else ! 413: { ! 414: cmd = RECTANGLE_FILL | BUS_SIZE_8 | ! 415: DRAWING_DIR_TBLRXM | DIR_TYPE_XY | WAIT | ! 416: DRAW | LAST_PIXEL_ON | READ; ! 417: } ! 418: ! 419: ! 420: FIFOWAIT(FIFO_7_EMPTY); ! 421: ! 422: TEST_AND_SET_RD_MASK(0xff); ! 423: OUTPW (MULTIFUNC_CNTL, (DATA_EXTENSION | ALL_ONES)); ! 424: ! 425: OUTPW (CUR_X, OFF_SCREEN_BITMAP_X); ! 426: OUTPW (CUR_Y, OFF_SCREEN_BITMAP_Y); ! 427: OUTPW (RECT_WIDTH, (cx - 1)); ! 428: OUTPW (MULTIFUNC_CNTL, (RECT_HEIGHT | (cy - 1))); ! 429: ! 430: OUTPW (CMD, cmd); ! 431: ! 432: // Wait for the Data Available. ! 433: ! 434: while (!(inpw(GP_STAT) & READ_DATA_AVAILABLE)); ! 435: ! 436: // Now transfer the data from the screen to the host memory bitmap. ! 437: ! 438: // NOTE: We call vDataPortIn once for each scan instead of doing just ! 439: // one large call to vDataPortIn because for some reason some machines ! 440: // choke on a REP INSW of such a large size -- the S3 gets into a mode ! 441: // such that even when the transfer is completely done, it still ! 442: // claims there's more data to be sent. This happens on the machine ! 443: // regardless of S3 chip type, but this seems to be an effective work- ! 444: // around for all cases: ! 445: ! 446: if (!(x & 0x1) && !(cx & 0x01)) ! 447: { ! 448: pwBuffer = (WORD*) pssbNewNode->aBits; ! 449: cxInWords = (cx + 1) / 2; ! 450: for (i = cy; i > 0; i--) ! 451: { ! 452: vDataPortIn(ppdev, pwBuffer, cxInWords); ! 453: pwBuffer += cxInWords; ! 454: } ! 455: } ! 456: else ! 457: { ! 458: pjBuffer = (BYTE*) pssbNewNode->aBits; ! 459: for (i = cy; i > 0; i--) ! 460: { ! 461: vDataPortInB(ppdev, pjBuffer, cx); ! 462: pjBuffer += cx; ! 463: } ! 464: } ! 465: ! 466: return(TRUE); ! 467: } ! 468: ! 469: ! 470: ! 471:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.