|
|
1.1 ! root 1: /******************************Module*Header*******************************\ ! 2: * Module Name: savescr.c * ! 3: * * ! 4: * DrvSaveScreenBits * ! 5: * * ! 6: * Copyright (c) 1992 Microsoft Corporation * ! 7: \**************************************************************************/ ! 8: ! 9: ! 10: #include <driver.h> ! 11: ! 12: ! 13: //**************************************************************************// ! 14: // Note: if this is turned on, you *MUST* make sure to invalidate and reset // ! 15: // this when going to/returning from fullscreen mode (in DrvAssertMode). // ! 16: //**************************************************************************// ! 17: #define OFFSCREEN_SUPPORTED 0 // 1 to support saves to offscreen memory ! 18: // (code currently not written) ! 19: ! 20: VOID ! 21: vRestoreScreenBitsFromOffscreen( ! 22: PDEVSURF pdsurf, ! 23: PRECTL prcl, ! 24: PBYTE pjSrcBuffer ! 25: ); ! 26: ! 27: VOID ! 28: vRestoreScreenBitsFromMemory( ! 29: PDEVSURF pdsurf, ! 30: PRECTL prcl, ! 31: PBYTE pjSrcBuffer, ! 32: ULONG ulRestoreWidthInBytes, ! 33: ULONG ulSrcDelta ! 34: ); ! 35: ! 36: VOID ! 37: vSaveScreenBitsToMemory( ! 38: PDEVSURF pdsurf, ! 39: PRECTL prcl, ! 40: PVOID pjDestBuffer, ! 41: ULONG ulSaveWidthInBytes, ! 42: ULONG ulSaveHeight, ! 43: ULONG ulDestScanWidth ! 44: ); ! 45: ! 46: /******************************Public*Routine******************************\ ! 47: * DrvSaveScreenBits(pso,iMode,iIdent,prcl) * ! 48: * * ! 49: * Saves and restores the specified area of the screen * ! 50: * * ! 51: \**************************************************************************/ ! 52: ! 53: ULONG DrvSaveScreenBits(SURFOBJ *pso, ULONG iMode, ULONG iIdent, RECTL *prcl) ! 54: { ! 55: PDEVSURF pdsurf; ! 56: PPDEV ppdev; ! 57: PSAVED_SCREEN_BITS pSSB, *pLastSSBPtr, pSSBTemp; ! 58: BOOL bIdentFound; ! 59: ULONG ulSaveSize, ulSaveHeight; ! 60: ULONG ulSaveWidthInBytes, ulSaveWidthInAlignedBytes; ! 61: ! 62: // ASSERT(pso != (SURFOBJ *) NULL,"DrvSaveScreenBits invalid pso"); ! 63: ! 64: pdsurf = (PDEVSURF) pso->dhsurf; ! 65: ! 66: // ASSERT(pdsurf != (PDEVSURF) NULL,"DrvSaveScreenBits invalid dhsurf"); ! 67: // ASSERT(pdsurf->iFormat == BMF_PHYSDEVICE, ! 68: // "DrvSaveScreenBits DFBs not supported"); ! 69: ! 70: ppdev = pdsurf->ppdev; // find the PDEV that goes with this surface ! 71: ! 72: // ! 73: // Save, restore, or free a block of screen bits. ! 74: // ! 75: ! 76: switch(iMode) ! 77: { ! 78: // ! 79: // Save a block of screen bits. ! 80: // ! 81: ! 82: case SS_SAVE: ! 83: ! 84: // ASSERT(prcl != (RECTL *) NULL,"DrvSaveScreenBits invalid prcl"); ! 85: // Figure out how big the save area will be ! 86: ulSaveHeight = prcl->bottom - prcl->top; ! 87: ulSaveWidthInBytes = ! 88: ((ULONG)((prcl->right + 7) - (prcl->left & ~0x07))) >> 3; ! 89: ! 90: #if OFFSCREEN_SUPPORTED ! 91: // This is the size of the the save area for one plane, or the ! 92: // number of addresses required to save this in offscreen memory. ! 93: // A system memory save area would require four times as many bytes ! 94: ulSaveSize = ulSaveHeight * pSSB->ulSaveWidthInBytes; ! 95: ! 96: // See if there's enough memory left in the display memory heap to ! 97: // save this rectangle ! 98: if (ulSaveSize > ! 99: (pdsurf->pjAdapterHeapTop - pdsurf->pjAdapterHeapStart)) ! 100: { ! 101: #endif ! 102: // Not enough offscreen memory; store in system memory. ! 103: // Calculate new buffer width, allowing for padding so we can ! 104: // dword align ! 105: ulSaveWidthInAlignedBytes = ! 106: (((ULONG)((prcl->right + 31) - (prcl->left & ~0x1F))) ! 107: >> 5) << 2; ! 108: ! 109: // # of bytes to hold all 4 planes of save rect in memory ! 110: ulSaveSize = ((ulSaveHeight * ulSaveWidthInAlignedBytes) << 2) ! 111: + sizeof(SAVED_SCREEN_BITS); ! 112: ! 113: // If the preallocated saved screen bits buffer is free and big ! 114: // enough to handle this save, we'll use that ! 115: if ((ppdev->flPreallocSSBBufferInUse == FALSE) && ! 116: (ulSaveSize <= ppdev->ulPreallocSSBSize)) ! 117: { ! 118: // Save in preallocated buffer ! 119: ! 120: pSSB = (PSAVED_SCREEN_BITS) ppdev->pjPreallocSSBBuffer; ! 121: ! 122: // Mark that we're saving in the preallocated buffer ! 123: pSSB->bFlags = SSB_IN_PREALLOC_BUFFER; ! 124: ! 125: // Make sure no other screen bits save tries to use the ! 126: // buffer ! 127: ppdev->flPreallocSSBBufferInUse = TRUE; ! 128: } ! 129: else ! 130: { ! 131: // Save in system memory buffer ! 132: ! 133: // Allocate a structure to contain the save info and the ! 134: // save buffer (four planes' worth) ! 135: pSSB = (PSAVED_SCREEN_BITS) ! 136: (LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, ! 137: ulSaveSize)); ! 138: if (pSSB == NULL) ! 139: { ! 140: // Couldn't get memory, so fail this call ! 141: return((ULONG)0); ! 142: } ! 143: ! 144: // Mark that we're not saving in display memory ! 145: pSSB->bFlags = 0; ! 146: } ! 147: ! 148: // Start address at which to save, accounting for ! 149: // the number of bytes by which to pad on the left to dword ! 150: // align (assumes each scan line starts dword aligned, which is ! 151: // true in 640, 800, and 1024 wide cases) ! 152: pSSB->pjBuffer = ((PBYTE) pSSB) + sizeof(SAVED_SCREEN_BITS) + ! 153: ((prcl->left >> 3) & 0x03); ! 154: ! 155: pSSB->ulSaveWidthInBytes = ulSaveWidthInBytes; ! 156: ! 157: // Distance from end of one scan to start of next (number of ! 158: // padding bytes for dword alignment purposes) ! 159: pSSB->ulDelta = ! 160: ulSaveWidthInAlignedBytes - pSSB->ulSaveWidthInBytes; ! 161: ! 162: // Save the rectangle to system memory ! 163: vSaveScreenBitsToMemory(pdsurf, ! 164: prcl, ! 165: pSSB->pjBuffer, ! 166: pSSB->ulSaveWidthInBytes, ! 167: ulSaveHeight, ! 168: ulSaveWidthInAlignedBytes); ! 169: #if OFFSCREEN_SUPPORTED ! 170: } ! 171: else ! 172: { ! 173: // Store in offscreen memory ! 174: // Allocate a structure to contain the save info ! 175: pSSB = (PSAVED_SCREEN_BITS) ! 176: (LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, ! 177: sizeof(SAVED_SCREEN_BITS)); ! 178: if (pSSB == NULL) ! 179: { ! 180: // Couldn't get memory, so fail this call ! 181: return(0); ! 182: } ! 183: pSSB->bFlags = SSB_IN_ADAPTER_MEMORY; ! 184: ! 185: pSSB->ulSaveWidthInBytes = ulSaveWidthInBytes; ! 186: ! 187: /***/ ! 188: ! 189: } ! 190: #endif ! 191: ! 192: // Link the new saved screen bits block into the list ! 193: pSSB->pvNextSSB = pdsurf->ssbList; ! 194: pdsurf->ssbList = pSSB; ! 195: ! 196: return((ULONG) pSSB); ! 197: ! 198: // ! 199: // Restore a saved screen bits block to the screen, then free it. ! 200: // ! 201: ! 202: case SS_RESTORE: ! 203: // ASSERT(prcl != (RECTL *) NULL,"DrvSaveScreenBits invalid prcl"); ! 204: ! 205: // Point to the first block in the saved screen bits list ! 206: pSSB = pdsurf->ssbList; ! 207: ! 208: // Try to find the specified saved screen bits block ! 209: bIdentFound = FALSE; ! 210: while ((pSSB != (PSAVED_SCREEN_BITS) NULL) && !bIdentFound) ! 211: { ! 212: if (pSSB == (PSAVED_SCREEN_BITS) iIdent) ! 213: { ! 214: // It's a match; restore this block ! 215: ! 216: // Handle copies from offscreen memory and system memory ! 217: // separately ! 218: #if OFFSCREEN_SUPPORTED ! 219: if (pSSB->bFlags & SSB_IN_ADAPTER_MEMORY) ! 220: { ! 221: vRestoreScreenBitsFromOffscreen(pdsurf, ! 222: prcl, ! 223: pSSB->pjBuffer); ! 224: } ! 225: else ! 226: { ! 227: #endif ! 228: vRestoreScreenBitsFromMemory(pdsurf, ! 229: prcl, ! 230: pSSB->pjBuffer, ! 231: pSSB->ulSaveWidthInBytes, ! 232: pSSB->ulDelta); ! 233: #if OFFSCREEN_SUPPORTED ! 234: } ! 235: #endif ! 236: ! 237: bIdentFound = TRUE; ! 238: } ! 239: else ! 240: { ! 241: // Not a match, so check another block, if there is one. ! 242: // Point to the next saved screen bits block ! 243: pSSB = (PSAVED_SCREEN_BITS) pSSB->pvNextSSB; ! 244: } ! 245: } ! 246: ! 247: // See if we succeeded in finding a block to restore ! 248: if (!bIdentFound) ! 249: { ! 250: // It was a bad identifier, so we'll return failure ! 251: ! 252: DISPDBG((0, "DrvSaveScreenBits SS_RESTORE invalid iIdent")); ! 253: return(FALSE); ! 254: } ! 255: ! 256: // Always free the saved screen bits block after restoring it ! 257: ! 258: // ! 259: // Free up the saved screen bits block. ! 260: // ! 261: ! 262: case SS_FREE: ! 263: ! 264: // Point to the first block in the saved screen bits list ! 265: pSSB = pdsurf->ssbList; ! 266: ! 267: // Point to the pointer to the first block, so we can unlink the ! 268: // first block if it's the one we're freeing ! 269: pLastSSBPtr = &pdsurf->ssbList; ! 270: ! 271: // Try to find the specified saved screen bits block ! 272: while (pSSB != (PSAVED_SCREEN_BITS) NULL) ! 273: { ! 274: if (pSSB == (PSAVED_SCREEN_BITS) iIdent) ! 275: { ! 276: // It's a match; free up this block ! 277: ! 278: // Unlink the block from the list ! 279: *pLastSSBPtr = (PSAVED_SCREEN_BITS) pSSB->pvNextSSB; ! 280: ! 281: // If the block is in offscreen memory, adjust the display ! 282: // memory heap to free up the offscreen memory allocated to ! 283: // the block ! 284: if (pSSB->bFlags & SSB_IN_ADAPTER_MEMORY) ! 285: { ! 286: if (pSSB->pjBuffer != pdsurf->pjAdapterHeapTop) ! 287: { ! 288: // The block is not on top of the heap, so compact ! 289: // the heap to move the newly freed space to the ! 290: // top of the display memory heap ! 291: ! 292: // First, adjust the pointers to all the blocks ! 293: // that are above the freed one in the display ! 294: // memory heap ! 295: pSSBTemp = pdsurf->ssbList; ! 296: while (pSSBTemp != NULL) ! 297: { ! 298: if (pSSBTemp->pjBuffer < pSSB->pjBuffer) ! 299: { ! 300: // This block is above the one we're ! 301: // freeing in the display memory heap, so ! 302: // shift its pointer down (the actual ! 303: // movement of the bytes happens below) ! 304: pSSBTemp->pjBuffer += pSSB->ulSize; ! 305: } ! 306: pSSBTemp = (PSAVED_SCREEN_BITS) ! 307: pSSBTemp->pvNextSSB; ! 308: } ! 309: // Now actually shift all the higher blocks to ! 310: // squeeze out the block we just freed ! 311: ! 312: memcpy(pdsurf->pjAdapterHeapTop + pSSB->ulSize, ! 313: pdsurf->pjAdapterHeapTop, ! 314: pSSB->pjBuffer - pdsurf->pjAdapterHeapTop); ! 315: } ! 316: ! 317: // Adjust the top of the used display memory heap to ! 318: // account for the block we just freed ! 319: pdsurf->pjAdapterHeapTop += pSSB->ulSize; ! 320: } ! 321: else if (pSSB->bFlags & SSB_IN_PREALLOC_BUFFER) ! 322: { ! 323: // If the block's save area is in the preallocated ! 324: // buffer, mark that the buffer is no longer in use ! 325: // and is free for reuse ! 326: ppdev->flPreallocSSBBufferInUse = FALSE; ! 327: ! 328: // We're done; there's nothing to free up ! 329: return(TRUE); ! 330: } ! 331: ! 332: // Deallocate the block's memory ! 333: LocalFree(pSSB); ! 334: ! 335: // We've successfully freed the block ! 336: return(TRUE); ! 337: } ! 338: ! 339: // Not a match, so check another block, if there is one ! 340: // Remember the block that points to the block we're advancing ! 341: // to, for unlinking later ! 342: pLastSSBPtr = (PSAVED_SCREEN_BITS *) &pSSB->pvNextSSB; ! 343: ! 344: // Point to the next saved screen bits block ! 345: pSSB = (PSAVED_SCREEN_BITS) pSSB->pvNextSSB; ! 346: } ! 347: ! 348: // It was a bad identifier, so we'll do nothing. We won't return ! 349: // FALSE because SS_FREE always returns TRUE ! 350: ! 351: DISPDBG((0, "DrvSaveScreenBits SS_FREE invalid iIdent")); ! 352: ! 353: return(TRUE); ! 354: ! 355: // ! 356: // An unknown mode was passed in. ! 357: // ! 358: ! 359: default: ! 360: ! 361: DISPDBG((0, "DrvSaveScreenBits invalid iMode")); ! 362: ! 363: return(FALSE); ! 364: break; ! 365: } ! 366: } ! 367:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.