Annotation of ntddk/src/video/displays/s3/savescrn.c, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.