Annotation of ntddk/src/video/displays/s3/savescrn.c, revision 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.