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