|
|
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.