Annotation of ntddk/src/video/displays/s3/bitblt.c, revision 1.1

1.1     ! root        1: /******************************Module*Header*******************************\
        !             2: * Module Name: bitblt.c
        !             3: *
        !             4: * Banked Frame Buffer bitblit
        !             5: *
        !             6: * Copyright (c) 1992 Microsoft Corporation
        !             7: *
        !             8: \**************************************************************************/
        !             9: 
        !            10: #include "driver.h"
        !            11: 
        !            12: #define SRCBM_CACHE 1
        !            13: 
        !            14: BOOL    bTest = FALSE;
        !            15: 
        !            16: ULONG   nColorBrushes,
        !            17:         nColorBrushCacheHit,
        !            18:         nColorBrushExpansionCacheHit,
        !            19:         nColorBrushCacheInvalidations;
        !            20: 
        !            21: ULONG   nMonoBrushes,
        !            22:         nMonoBrushCacheHit,
        !            23:         nMonoBrushExpansionCacheHit,
        !            24:         nMonoBrushCacheInvalidations;
        !            25: 
        !            26: ULONG   n8BppBitmaps,
        !            27:         n8BppBmCacheHits;
        !            28: 
        !            29: ULONG   n1BppBitmaps,
        !            30:         n1BppBmCacheHits;
        !            31: 
        !            32: 
        !            33: extern  ULONG   nSsbMovedToHostFromSrcBmCache;
        !            34: 
        !            35: BYTE   ajMonoPatPlanes[] = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80};
        !            36: 
        !            37: 
        !            38: /// Define the A vector polynomial bits
        !            39: //
        !            40: // Each bit corresponds to one of the terms in the polynomial
        !            41: //
        !            42: // Rop(D,S,P) = a + a D + a S + a P + a  DS + a  DP + a  SP + a   DSP
        !            43: //               0   d     s     p     ds      dp      sp      dsp
        !            44: 
        !            45: #define AVEC_NOT    0x01
        !            46: #define AVEC_D      0x02
        !            47: #define AVEC_S      0x04
        !            48: #define AVEC_P      0x08
        !            49: #define AVEC_DS     0x10
        !            50: #define AVEC_DP     0x20
        !            51: #define AVEC_SP     0x40
        !            52: #define AVEC_DSP    0x80
        !            53: 
        !            54: #define AVEC_NEED_SOURCE  (AVEC_S | AVEC_DS | AVEC_SP | AVEC_DSP)
        !            55: #define AVEC_NEED_PATTERN (AVEC_P | AVEC_DP | AVEC_SP | AVEC_DSP)
        !            56: 
        !            57: #define BB_TARGET_SCREEN    0x0001
        !            58: #define BB_TARGET_ONLY      0x0002
        !            59: #define BB_SOURCE_COPY      0x0004
        !            60: #define BB_PATTERN_COPY     0x0008
        !            61: 
        !            62: 
        !            63: /******************************Public*Data*********************************\
        !            64: * ROP translation table
        !            65: *
        !            66: * Translates the usual ternary rop into A-vector notation.  Each bit in
        !            67: * this new notation corresponds to a term in a polynomial translation of
        !            68: * the rop.
        !            69: *
        !            70: * Rop(D,S,P) = a + a D + a S + a P + a  DS + a  DP + a  SP + a   DSP
        !            71: *               0   d     s     p     ds      dp      sp      dsp
        !            72: \**************************************************************************/
        !            73: 
        !            74: BYTE gajRop[] =
        !            75: {
        !            76:     0x00, 0xff, 0xb2, 0x4d, 0xd4, 0x2b, 0x66, 0x99,
        !            77:     0x90, 0x6f, 0x22, 0xdd, 0x44, 0xbb, 0xf6, 0x09,
        !            78:     0xe8, 0x17, 0x5a, 0xa5, 0x3c, 0xc3, 0x8e, 0x71,
        !            79:     0x78, 0x87, 0xca, 0x35, 0xac, 0x53, 0x1e, 0xe1,
        !            80:     0xa0, 0x5f, 0x12, 0xed, 0x74, 0x8b, 0xc6, 0x39,
        !            81:     0x30, 0xcf, 0x82, 0x7d, 0xe4, 0x1b, 0x56, 0xa9,
        !            82:     0x48, 0xb7, 0xfa, 0x05, 0x9c, 0x63, 0x2e, 0xd1,
        !            83:     0xd8, 0x27, 0x6a, 0x95, 0x0c, 0xf3, 0xbe, 0x41,
        !            84:     0xc0, 0x3f, 0x72, 0x8d, 0x14, 0xeb, 0xa6, 0x59,
        !            85:     0x50, 0xaf, 0xe2, 0x1d, 0x84, 0x7b, 0x36, 0xc9,
        !            86:     0x28, 0xd7, 0x9a, 0x65, 0xfc, 0x03, 0x4e, 0xb1,
        !            87:     0xb8, 0x47, 0x0a, 0xf5, 0x6c, 0x93, 0xde, 0x21,
        !            88:     0x60, 0x9f, 0xd2, 0x2d, 0xb4, 0x4b, 0x06, 0xf9,
        !            89:     0xf0, 0x0f, 0x42, 0xbd, 0x24, 0xdb, 0x96, 0x69,
        !            90:     0x88, 0x77, 0x3a, 0xc5, 0x5c, 0xa3, 0xee, 0x11,
        !            91:     0x18, 0xe7, 0xaa, 0x55, 0xcc, 0x33, 0x7e, 0x81,
        !            92:     0x80, 0x7f, 0x32, 0xcd, 0x54, 0xab, 0xe6, 0x19,
        !            93:     0x10, 0xef, 0xa2, 0x5d, 0xc4, 0x3b, 0x76, 0x89,
        !            94:     0x68, 0x97, 0xda, 0x25, 0xbc, 0x43, 0x0e, 0xf1,
        !            95:     0xf8, 0x07, 0x4a, 0xb5, 0x2c, 0xd3, 0x9e, 0x61,
        !            96:     0x20, 0xdf, 0x92, 0x6d, 0xf4, 0x0b, 0x46, 0xb9,
        !            97:     0xb0, 0x4f, 0x02, 0xfd, 0x64, 0x9b, 0xd6, 0x29,
        !            98:     0xc8, 0x37, 0x7a, 0x85, 0x1c, 0xe3, 0xae, 0x51,
        !            99:     0x58, 0xa7, 0xea, 0x15, 0x8c, 0x73, 0x3e, 0xc1,
        !           100:     0x40, 0xbf, 0xf2, 0x0d, 0x94, 0x6b, 0x26, 0xd9,
        !           101:     0xd0, 0x2f, 0x62, 0x9d, 0x04, 0xfb, 0xb6, 0x49,
        !           102:     0xa8, 0x57, 0x1a, 0xe5, 0x7c, 0x83, 0xce, 0x31,
        !           103:     0x38, 0xc7, 0x8a, 0x75, 0xec, 0x13, 0x5e, 0xa1,
        !           104:     0xe0, 0x1f, 0x52, 0xad, 0x34, 0xcb, 0x86, 0x79,
        !           105:     0x70, 0x8f, 0xc2, 0x3d, 0xa4, 0x5b, 0x16, 0xe9,
        !           106:     0x08, 0xf7, 0xba, 0x45, 0xdc, 0x23, 0x6e, 0x91,
        !           107:     0x98, 0x67, 0x2a, 0xd5, 0x4c, 0xb3, 0xfe, 0x01
        !           108: };
        !           109: 
        !           110: BOOL b8BppHostToScrnCachedWithRop(
        !           111:     SURFOBJ  *psoTrg,
        !           112:     SURFOBJ  *psoSrc,
        !           113:     CLIPOBJ  *pco,
        !           114:     XLATEOBJ *pxlo,
        !           115:     RECTL    *prclTrg,
        !           116:     POINTL   *pptlSrc,
        !           117:     WORD     s3Rop);
        !           118: 
        !           119: BOOL b1BppHostToScrnCachedWithRop(
        !           120:     SURFOBJ  *psoTrg,
        !           121:     SURFOBJ  *psoSrc,
        !           122:     CLIPOBJ  *pco,
        !           123:     XLATEOBJ *pxlo,
        !           124:     RECTL    *prclTrg,
        !           125:     POINTL   *pptlSrc,
        !           126:     WORD     s3Rop);
        !           127: 
        !           128: BOOL b8BppHostToScrnWithRop(
        !           129:     SURFOBJ  *psoTrg,
        !           130:     SURFOBJ  *psoSrc,
        !           131:     CLIPOBJ  *pco,
        !           132:     XLATEOBJ *pxlo,
        !           133:     RECTL    *prclTrg,
        !           134:     POINTL   *pptlSrc,
        !           135:     WORD     s3Rop);
        !           136: 
        !           137: VOID vLowLevel8BppHostToScrnWithRop(
        !           138:     PPDEV   ppdev,
        !           139:     PPOINT  pptTrg,
        !           140:     PSIZE   psizBlt,
        !           141:     PWORD   pwFirstWord,
        !           142:     INT     lSrcDelta,
        !           143:     XLATEOBJ *pxlo,
        !           144:     WORD    s3Rop);
        !           145: 
        !           146: BOOL b1BppHostToScrnWithRop(
        !           147:     SURFOBJ  *psoTrg,
        !           148:     SURFOBJ  *psoSrc,
        !           149:     CLIPOBJ  *pco,
        !           150:     XLATEOBJ *pxlo,
        !           151:     RECTL    *prclTrg,
        !           152:     POINTL   *pptlSrc,
        !           153:     WORD     s3Rop);
        !           154: 
        !           155: VOID vLowLevel1BppHostToScrnWithRop(
        !           156:     PPDEV   ppdev,
        !           157:     PPOINT  pptTrg,
        !           158:     PSIZE   psizBlt,
        !           159:     INT     xSrc,
        !           160:     PWORD   pwFirstWord,
        !           161:     INT     lSrcDelta,
        !           162:     XLATEOBJ *pxlo,
        !           163:     WORD    s3Rop);
        !           164: 
        !           165: BOOL b4BppHostToScrnWithRop(
        !           166:     SURFOBJ  *psoTrg,
        !           167:     SURFOBJ  *psoSrc,
        !           168:     CLIPOBJ  *pco,
        !           169:     XLATEOBJ *pxlo,
        !           170:     RECTL    *prclTrg,
        !           171:     POINTL   *pptlSrc,
        !           172:     WORD     s3Rop);
        !           173: 
        !           174: 
        !           175: VOID vLowLevel4BppHostToScrnWithRop(
        !           176:     PPDEV   ppdev,
        !           177:     PPOINT  pptTrg,
        !           178:     PSIZE   psizBlt,
        !           179:     INT     xSrc,
        !           180:     PWORD   pwFirstWord,
        !           181:     INT     lSrcDelta,
        !           182:     XLATEOBJ *pxlo,
        !           183:     WORD    s3Rop);
        !           184: 
        !           185: 
        !           186: WORD wXlateSrcRop3toS3Rop(PPDEV pdev, WORD rop3);
        !           187: 
        !           188: ROP4 bXlatePatRop4toS3Rop(
        !           189:     PPDEV pdev,
        !           190:     ROP4  rop4);
        !           191: 
        !           192: BOOL bDownLoadBrushIntoColorCache(
        !           193:     PPDEV      ppdev,
        !           194:     PS3BRUSH   ps3Brush,
        !           195:     PPOINT     ppt);
        !           196: 
        !           197: BOOL bDownLoadBrushIntoMonoCache(
        !           198:     PPDEV      ppdev,
        !           199:     PS3BRUSH   p3Brush,
        !           200:     PXYZPOINT  pxyzPt);
        !           201: 
        !           202: BOOL bExpandColorBrushIntoHorzCache(
        !           203:     PPDEV      ppdev,
        !           204:     PPOINT     ppt);
        !           205: 
        !           206: BOOL bExpandMonoBrushIntoHorzCache(
        !           207:     PPDEV      ppdev,
        !           208:     PXYZPOINT  pxyzPtl,
        !           209:     INT        zHorz);
        !           210: 
        !           211: BOOL bExpandColorBrushIntoVertCache(
        !           212:     PPDEV      ppdev,
        !           213:     PPOINT     ppt);
        !           214: 
        !           215: BOOL bExpandMonoBrushIntoVertCache(
        !           216:     PPDEV      ppdev,
        !           217:     PXYZPOINT  pxyzPt,
        !           218:     INT        zVert);
        !           219: 
        !           220: BOOL bColorHorzCacheToScreen(
        !           221:     PPDEV       ppdev,
        !           222:     PS3BRUSH    ps3Brush,
        !           223:     PPOINT      pptBrushOrg,
        !           224:     PPOINT      pptDest,
        !           225:     PSIZE       psizDest,
        !           226:     WORD        s3ForeRop,
        !           227:     WORD        s3BackRop);
        !           228: 
        !           229: BOOL bColorExpandHorzCacheToScreen(
        !           230:     PPDEV       ppdev,
        !           231:     PS3BRUSH    ps3Brush,
        !           232:     INT         zHorz,
        !           233:     PPOINT      pptBrushOrg,
        !           234:     PPOINT      pptDest,
        !           235:     PSIZE       psizDest,
        !           236:     WORD        s3ForeRop,
        !           237:     WORD        s3BackRop);
        !           238: 
        !           239: BOOL bCpyColorHorzCacheToScreen(
        !           240:     PPDEV       ppdev,
        !           241:     PS3BRUSH    ps3Brush,
        !           242:     PPOINT      pptBrushOrg,
        !           243:     PPOINT      pptDest,
        !           244:     PSIZE       psizDest);
        !           245: 
        !           246: BOOL bCpyColorExpandHorzCacheToScreen(
        !           247:     PPDEV       ppdev,
        !           248:     PS3BRUSH    ps3Brush,
        !           249:     INT         zHorz,
        !           250:     PPOINT      pptBrushOrg,
        !           251:     PPOINT      pptDest,
        !           252:     PSIZE       psizDest);
        !           253: 
        !           254: BOOL bColorVertCacheToScreen(
        !           255:     PPDEV       ppdev,
        !           256:     PS3BRUSH    ps3Brush,
        !           257:     PPOINT      pptBrushOrg,
        !           258:     PPOINT      pptDest,
        !           259:     PSIZE       psizDest,
        !           260:     WORD        s3ForeRop,
        !           261:     WORD        s3BackRop);
        !           262: 
        !           263: BOOL bColorExpandVertCacheToScreen(
        !           264:     PPDEV       ppdev,
        !           265:     PS3BRUSH    ps3Brush,
        !           266:     INT         zHorz,
        !           267:     PPOINT      pptBrushOrg,
        !           268:     PPOINT      pptDest,
        !           269:     PSIZE       psizDest,
        !           270:     WORD        s3ForeRop,
        !           271:     WORD        s3BackRop);
        !           272: 
        !           273: 
        !           274: BOOL bPuntBlit(
        !           275:     SURFOBJ  *psoTrg,
        !           276:     SURFOBJ  *psoSrc,
        !           277:     SURFOBJ  *psoMask,
        !           278:     CLIPOBJ  *pco,
        !           279:     XLATEOBJ *pxlo,
        !           280:     RECTL    *prclTrg,
        !           281:     POINTL   *pptlSrc,
        !           282:     POINTL   *pptlMask,
        !           283:     BRUSHOBJ *pbo,
        !           284:     POINTL   *pptlBrush,
        !           285:     ROP4     rop4);
        !           286: 
        !           287: BOOL bScrnToScrnPuntBlit(
        !           288:     SURFOBJ  *psoTrg,
        !           289:     SURFOBJ  *psoSrc,
        !           290:     SURFOBJ  *psoMask,
        !           291:     CLIPOBJ  *pco,
        !           292:     XLATEOBJ *pxlo,
        !           293:     RECTL    *prclTrg,
        !           294:     POINTL   *pptlSrc,
        !           295:     POINTL   *pptlMask,
        !           296:     BRUSHOBJ *pbo,
        !           297:     POINTL   *pptlBrush,
        !           298:     ROP4     rop4);
        !           299: 
        !           300: 
        !           301: BOOL bSpecialBlits(
        !           302:     SURFOBJ  *psoTrg,
        !           303:     SURFOBJ  *psoSrc,
        !           304:     SURFOBJ  *psoMask,
        !           305:     CLIPOBJ  *pco,
        !           306:     XLATEOBJ *pxlo,
        !           307:     RECTL    *prclTrg,
        !           308:     POINTL   *pptlSrc,
        !           309:     POINTL   *pptlMask,
        !           310:     BRUSHOBJ *pbo,
        !           311:     POINTL   *pptlBrush,
        !           312:     ROP4     rop4);
        !           313: 
        !           314: BOOL bScrnToScrnWithRop(
        !           315:     SURFOBJ  *psoTrg,
        !           316:     SURFOBJ  *psoSrc,
        !           317:     CLIPOBJ  *pco,
        !           318:     RECTL    *prclTrg,
        !           319:     POINTL   *pptlSrc,
        !           320:     WORD     s3Rop);
        !           321: 
        !           322: 
        !           323: VOID S3ScrnToScrnBlt(
        !           324:     PPDEV   ppdev,
        !           325:     INT     xSrc,
        !           326:     INT     ySrc,
        !           327:     INT     xTrg,
        !           328:     INT     yTrg,
        !           329:     INT     width,
        !           330:     INT     height,
        !           331:     WORD    s3Rop,
        !           332:     WORD    Cmd);
        !           333: 
        !           334: BOOL bPatternSolid(
        !           335:     SURFOBJ  *psoTrg,
        !           336:     SURFOBJ  *psoSrc,
        !           337:     SURFOBJ  *psoMask,
        !           338:     CLIPOBJ  *pco,
        !           339:     XLATEOBJ *pxlo,
        !           340:     RECTL    *prclTrg,
        !           341:     POINTL   *pptlSrc,
        !           342:     POINTL   *pptlMask,
        !           343:     BRUSHOBJ *pbo,
        !           344:     POINTL   *pptlBrush,
        !           345:     ROP4     rop4);
        !           346: 
        !           347: VOID vS3SolidPattern(
        !           348:     PPDEV   ppdev,
        !           349:     INT     left,
        !           350:     INT     top,
        !           351:     INT     width,
        !           352:     INT     height,
        !           353:     INT     color,
        !           354:     WORD    s3Mix);
        !           355: 
        !           356: 
        !           357: BOOL bPatternBrush(
        !           358:     SURFOBJ  *psoTrg,
        !           359:     CLIPOBJ  *pco,
        !           360:     RECTL    *prclTrg,
        !           361:     BRUSHOBJ *pbo,
        !           362:     POINTL   *pptlBrush,
        !           363:     ROP4     rop4);
        !           364: 
        !           365: 
        !           366: 
        !           367: /*****************************************************************************
        !           368:  * S3 (Banked Frame Buffer) DrvCopyBits
        !           369:  *
        !           370:  *  An I/O through the transfer register take 43 clocks.
        !           371:  *  A Memory access on the S3 takes 23 clocks, the memory window wins,
        !           372:  *  so this transfers bits through the memory window for some things.
        !           373:  ****************************************************************************/
        !           374: BOOL DrvCopyBits(
        !           375:     SURFOBJ  *psoDest,
        !           376:     SURFOBJ  *psoSrc,
        !           377:     CLIPOBJ  *pco,
        !           378:     XLATEOBJ *pxlo,
        !           379:     RECTL    *prclDest,
        !           380:     POINTL   *pptlSrc)
        !           381: {
        !           382: #if defined(_X86_) || defined(i386)
        !           383: 
        !           384:     INT     cy;
        !           385:     RECTL   rclScans;
        !           386:     RECTL   rclDest, rclTmp;
        !           387:     SURFOBJ *pso;
        !           388:     PPDEV   ppdev;
        !           389:     BOOL    bRet, bResetBounds;
        !           390: 
        !           391:     DISPDBG((3,"S3.DLL!DrvCopyBits - Entry\n"));
        !           392: 
        !           393:     bResetBounds = FALSE;
        !           394: 
        !           395:     rclDest = *prclDest;
        !           396: 
        !           397:     cy = prclDest->bottom - prclDest->top;
        !           398: 
        !           399:     if (psoDest->iType == STYPE_DEVICE)
        !           400:     {
        !           401:         ppdev = (PPDEV) psoDest->dhsurf;
        !           402: 
        !           403:         GPWAIT();
        !           404: 
        !           405:         if (pco == NULL)
        !           406:             pco = ppdev->pcoDefault;
        !           407: 
        !           408:         if (psoSrc->iType == STYPE_DEVICE)
        !           409:         {
        !           410:             // At this point we know it's a screen to screen copy.
        !           411:             // If a color translation needs to be applied then go through ScrnToScrnPuntBlit
        !           412: 
        !           413:             if ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL))
        !           414:             {
        !           415:                 bScrnToScrnWithRop(psoDest, psoSrc, pco, prclDest, pptlSrc, OVERPAINT);
        !           416:                 return (TRUE);
        !           417:             }
        !           418:             else
        !           419:             {
        !           420:                 bRet = bScrnToScrnPuntBlit(psoDest,
        !           421:                                            psoSrc,
        !           422:                                            NULL,
        !           423:                                            pco,
        !           424:                                            pxlo,
        !           425:                                            prclDest,
        !           426:                                            pptlSrc,
        !           427:                                            NULL,
        !           428:                                            NULL,
        !           429:                                            NULL,
        !           430:                                            0x0000CCCC);
        !           431: 
        !           432:                 return (bRet);
        !           433:             }
        !           434:         }
        !           435: 
        !           436:         else if (psoSrc->lDelta < 0)
        !           437:         {
        !           438:             rclScans.top    = prclDest->top;
        !           439:             rclScans.bottom = rclScans.top + cy;
        !           440: 
        !           441:             pso = ppdev->pSurfObj;
        !           442:             psoDest = pso;
        !           443:             bBankEnumStart(ppdev, &rclScans, pso, pco);
        !           444:         }
        !           445: 
        !           446:         else
        !           447:         {
        !           448:             switch (psoSrc->iBitmapFormat)
        !           449:             {
        !           450:                 case BMF_DEVICE:
        !           451:                 case BMF_8BPP:
        !           452:                     bRet = b8BppHostToScrnCachedWithRop(psoDest, psoSrc,
        !           453:                                                         pco, pxlo,
        !           454:                                                         prclDest, pptlSrc,
        !           455:                                                         OVERPAINT);
        !           456:                     break;
        !           457: 
        !           458:                 case BMF_1BPP:
        !           459:                     bRet = b1BppHostToScrnCachedWithRop(psoDest, psoSrc,
        !           460:                                                         pco, pxlo,
        !           461:                                                         prclDest, pptlSrc,
        !           462:                                                         OVERPAINT);
        !           463:                     break;
        !           464: 
        !           465:                 case BMF_4BPP:
        !           466:                     bRet = b4BppHostToScrnWithRop(psoDest, psoSrc, pco, pxlo,
        !           467:                                               prclDest, pptlSrc, OVERPAINT);
        !           468:                     break;
        !           469: 
        !           470:                 case BMF_16BPP:
        !           471:                 case BMF_24BPP:
        !           472:                 case BMF_32BPP:
        !           473:                 case BMF_4RLE:
        !           474:                 case BMF_8RLE:
        !           475:                 default:
        !           476:                     bRet = FALSE;
        !           477:             }
        !           478: 
        !           479:             if (bRet == TRUE)
        !           480:             {
        !           481:                 return (TRUE);
        !           482:             }
        !           483: 
        !           484:             rclScans.top    = prclDest->top;
        !           485:             rclScans.bottom = rclScans.top + cy;
        !           486: 
        !           487:             pso = ppdev->pSurfObj;
        !           488:             psoDest = pso;
        !           489:             bBankEnumStart(ppdev, &rclScans, pso, pco);
        !           490:         }
        !           491:     }
        !           492:     else
        !           493:     {
        !           494:         rclScans.top    = pptlSrc->y;
        !           495:         rclScans.bottom = pptlSrc->y + cy;
        !           496: 
        !           497:         ppdev = (PPDEV) psoSrc->dhsurf;
        !           498: 
        !           499:         GPWAIT();
        !           500: 
        !           501:         if (pco == NULL)
        !           502:         {
        !           503:             pco = ppdev->pcoDefault;
        !           504: 
        !           505:             // BUGBUG: This mucking around with pcoDefaults's rclBounds is
        !           506:             // no longer required by bSrcBankEnumStart:
        !           507: 
        !           508:             rclTmp = pco->rclBounds;
        !           509:             pco->rclBounds = *prclDest;
        !           510:             bResetBounds = TRUE;
        !           511:         }
        !           512: 
        !           513:         pso = ppdev->pSurfObj;
        !           514:         psoSrc = pso;
        !           515:         bSrcBankEnumStart(ppdev, &rclScans, pso, pco, prclDest);
        !           516:     }
        !           517: 
        !           518:     do
        !           519:     {
        !           520:         bRet = EngCopyBits(psoDest, psoSrc, pco, pxlo, &rclDest, pptlSrc);
        !           521: 
        !           522:     } while (bRet && (bBankEnum(ppdev, &rclScans, pso, pco)));
        !           523: 
        !           524:     bBankEnumEnd(ppdev, pso, pco);
        !           525: 
        !           526:     if (bResetBounds)
        !           527:     {
        !           528:         ppdev->pcoDefault->rclBounds = rclTmp;
        !           529:     }
        !           530: 
        !           531:     return(bRet);
        !           532: 
        !           533: #else
        !           534: 
        !           535:     // A DrvCopyBits is just a simplified DrvBitBlt:
        !           536: 
        !           537:     return(DrvBitBlt(psoDest,
        !           538:                      psoSrc,
        !           539:                      NULL,              // psoMask
        !           540:                      pco,
        !           541:                      pxlo,
        !           542:                      prclDest,
        !           543:                      pptlSrc,
        !           544:                      NULL,              // pptlMask
        !           545:                      NULL,              // pbo
        !           546:                      NULL,              // pptlBrush
        !           547:                      0x0000CCCC));      // mix = SRCCOPY
        !           548: 
        !           549: #endif
        !           550: }
        !           551: 
        !           552: 
        !           553: 
        !           554: 
        !           555: /*****************************************************************************
        !           556:  * S3 DrvBitBlt
        !           557:  ****************************************************************************/
        !           558: BOOL DrvBitBlt(
        !           559: SURFOBJ  *psoTrg,
        !           560: SURFOBJ  *psoSrc,
        !           561: SURFOBJ  *psoMask,
        !           562: CLIPOBJ  *pco,
        !           563: XLATEOBJ *pxlo,
        !           564: RECTL  *prclTrg,
        !           565: POINTL    *pptlSrc,
        !           566: POINTL    *pptlMask,
        !           567: BRUSHOBJ *pbo,
        !           568: POINTL    *pptlBrush,
        !           569: ROP4    rop4)
        !           570: 
        !           571: {
        !           572:     BOOL    b;
        !           573:     PPDEV   ppdev;
        !           574: 
        !           575:     DISPDBG((3,"S3.DLL!DrvBitBlt - Entry\n"));
        !           576: 
        !           577:     // Since we don't support Device-Format Bitmaps, either the source
        !           578:     // or the destination (or both) will be the device surface:
        !           579: 
        !           580:     if (psoTrg->iType == STYPE_DEVICE)
        !           581:         ppdev = (PPDEV) psoTrg->dhpdev;
        !           582:     else
        !           583:         ppdev = (PPDEV) psoSrc->dhpdev;
        !           584: 
        !           585:     // Protect the driver from a potentially NULL clip object.
        !           586: 
        !           587:     if (pco == NULL)
        !           588:     {
        !           589:         pco = ppdev->pcoDefault;
        !           590:     }
        !           591: 
        !           592:     if (bTest == FALSE)
        !           593:     {
        !           594:         b = bSpecialBlits(psoTrg, psoSrc, psoMask,
        !           595:                           pco, pxlo,
        !           596:                           prclTrg, pptlSrc, pptlMask,
        !           597:                           pbo, pptlBrush,
        !           598:                           rop4);
        !           599:     }
        !           600:     else
        !           601:     {
        !           602:         b = FALSE;
        !           603:     }
        !           604: 
        !           605:     if (b != TRUE)
        !           606:     {
        !           607:         bPuntBlit(psoTrg,
        !           608:                   psoSrc,
        !           609:                   psoMask,
        !           610:                   pco,
        !           611:                   pxlo,
        !           612:                   prclTrg,
        !           613:                   pptlSrc,
        !           614:                   pptlMask,
        !           615:                   pbo,
        !           616:                   pptlBrush,
        !           617:                   rop4);
        !           618:     }
        !           619: 
        !           620:     return (TRUE);
        !           621: }
        !           622: 
        !           623: /*****************************************************************************
        !           624:  * S3 General purpose blit handler.  This routine will handle any blit.
        !           625:  * Albeit slow, but it will be handled.
        !           626:  *
        !           627:  *  Returns TRUE if the blit was handled.
        !           628:  ****************************************************************************/
        !           629: BOOL bPuntBlit(
        !           630:     SURFOBJ  *psoTrg,
        !           631:     SURFOBJ  *psoSrc,
        !           632:     SURFOBJ  *psoMask,
        !           633:     CLIPOBJ  *pco,
        !           634:     XLATEOBJ *pxlo,
        !           635:     RECTL    *prclTrg,
        !           636:     POINTL   *pptlSrc,
        !           637:     POINTL   *pptlMask,
        !           638:     BRUSHOBJ *pbo,
        !           639:     POINTL   *pptlBrush,
        !           640:     ROP4     rop4)
        !           641: {
        !           642: 
        !           643: 
        !           644: #if defined(_X86_) || defined(i386)
        !           645: 
        !           646:     RECTL   rclScans;
        !           647:     RECTL   rclTrg;
        !           648:     PPDEV   ppdevTrg, ppdevSrc, ppdevBank;
        !           649:     SURFOBJ *psoBank;
        !           650:     BOOL    bRet;
        !           651:     PPDEV   ppdev;
        !           652: 
        !           653:     DISPDBG((2,"S3.DLL!bPuntBlit - Entry\n"));
        !           654: 
        !           655:     if (psoTrg->iType == STYPE_DEVICE)
        !           656:         ppdev = (PPDEV) psoTrg->dhsurf;
        !           657:     else
        !           658:         ppdev = (PPDEV) psoSrc->dhsurf;
        !           659: 
        !           660:     // Wait for the S3 coprocessor to finish with the VRAM before we touch it through
        !           661:     // the apperature.
        !           662: 
        !           663:     GPWAIT();
        !           664: 
        !           665:     rclTrg = *prclTrg;
        !           666: 
        !           667:     rclScans.top    = prclTrg->top;
        !           668:     rclScans.bottom = prclTrg->bottom;
        !           669: 
        !           670:     // Get the correct surface object for the target and the source
        !           671: 
        !           672:     if ((psoTrg->iType == STYPE_DEVICE) &&
        !           673:         ((psoSrc == NULL) || (psoSrc->iType != STYPE_DEVICE)))
        !           674:     {
        !           675:         ppdevTrg  = (PPDEV) psoTrg->dhsurf;
        !           676:         psoTrg    = ppdevTrg->pSurfObj;
        !           677: 
        !           678:         bBankEnumStart(ppdevTrg, &rclScans, psoTrg, pco);
        !           679:         ppdevBank = ppdevTrg;
        !           680:         psoBank = psoTrg;
        !           681: 
        !           682:     }
        !           683: 
        !           684:     else if ((psoTrg->iType != STYPE_DEVICE) &&
        !           685:              (psoSrc != NULL) && (psoSrc->iType == STYPE_DEVICE))
        !           686:     {
        !           687:         ppdevSrc  = (PPDEV) psoSrc->dhsurf;
        !           688:         psoSrc    = ppdevSrc->pSurfObj;
        !           689: 
        !           690:         rclScans.top    = pptlSrc->y;
        !           691:         rclScans.bottom = pptlSrc->y + (prclTrg->bottom - prclTrg->top);
        !           692: 
        !           693:         bSrcBankEnumStart(ppdevSrc, &rclScans, psoSrc, pco, prclTrg);
        !           694:         ppdevBank = ppdevSrc;
        !           695:         psoBank = psoSrc;
        !           696: 
        !           697:     }
        !           698:     else
        !           699:     {
        !           700:         bRet = bScrnToScrnPuntBlit(psoTrg,
        !           701:                                    psoSrc,
        !           702:                                    psoMask,
        !           703:                                    pco,
        !           704:                                    pxlo,
        !           705:                                    prclTrg,
        !           706:                                    pptlSrc,
        !           707:                                    pptlMask,
        !           708:                                    pbo,
        !           709:                                    pptlBrush,
        !           710:                                    rop4);
        !           711:         return (bRet);
        !           712:     }
        !           713: 
        !           714:     do
        !           715:     {
        !           716:         bRet = EngBitBlt(psoTrg,
        !           717:                   psoSrc,
        !           718:                   psoMask,
        !           719:                   pco,
        !           720:                   pxlo,
        !           721:                   &rclTrg,
        !           722:                   pptlSrc,
        !           723:                   pptlMask,
        !           724:                   pbo,
        !           725:                   pptlBrush,
        !           726:                   rop4);
        !           727: 
        !           728:     } while ((bBankEnum(ppdevBank, &rclScans, psoBank, pco)) && bRet);
        !           729: 
        !           730:     bBankEnumEnd(ppdevBank, psoBank, pco);
        !           731: 
        !           732:     return bRet;
        !           733: 
        !           734: #else
        !           735: 
        !           736:     BOOL    bRet;
        !           737:     PPDEV   ppdev;
        !           738:     RECTL   rclSrc;
        !           739: 
        !           740:     if (psoTrg->iType == STYPE_DEVICE)
        !           741:     {
        !           742:         ppdev = (PPDEV) psoTrg->dhsurf;
        !           743: 
        !           744:         if ((psoSrc != NULL) && (psoSrc->iType == STYPE_DEVICE))
        !           745:         {
        !           746:             // -------------------------------------------------------
        !           747:             // Handle screen-to-screen blit:
        !           748: 
        !           749:             // We have to copy both the source rectangle and the destination
        !           750:             // rectangle to the temporary bitmap (the destination rectangle
        !           751:             // is needed if there's complex clipping or if there's a ROP that
        !           752:             // affects need the destination).
        !           753:             //
        !           754:             // We simply copy the smallest entire rectangle containing both
        !           755:             // the source and the destination rectangles:
        !           756: 
        !           757:             rclSrc.left   = min(pptlSrc->x, prclTrg->left);
        !           758:             rclSrc.top    = min(pptlSrc->y, prclTrg->top);
        !           759:             rclSrc.right  = max(pptlSrc->x + prclTrg->right - prclTrg->left,
        !           760:                                 prclTrg->right);
        !           761:             rclSrc.bottom = max(pptlSrc->y + prclTrg->bottom - prclTrg->top,
        !           762:                                 prclTrg->bottom);
        !           763: 
        !           764:             vPuntGetBits(ppdev, psoSrc, &rclSrc);
        !           765: 
        !           766:             // Now do the copy entirely on the temporary bitmap surface:
        !           767: 
        !           768:             bRet = EngBitBlt(ppdev->psoTemp,
        !           769:                      ppdev->psoTemp,
        !           770:                      psoMask,
        !           771:                      pco,
        !           772:                      pxlo,
        !           773:                      prclTrg,
        !           774:                      pptlSrc,
        !           775:                      pptlMask,
        !           776:                      pbo,
        !           777:                      pptlBrush,
        !           778:                      rop4);
        !           779: 
        !           780:             // Just have to copy the destination back to the surface:
        !           781: 
        !           782:             if (bRet)
        !           783:             {
        !           784:                 vPuntPutBits(ppdev, psoTrg, prclTrg);
        !           785:             }
        !           786:         }
        !           787:         else
        !           788:         {
        !           789:             // -------------------------------------------------------
        !           790:             // Handle bitmap-to-screen blit:
        !           791: 
        !           792:             // Make a copy of the destination rectangle in case the ROP
        !           793:             // modifies the destination:
        !           794: 
        !           795:             vPuntGetBits(ppdev, psoTrg, prclTrg);
        !           796: 
        !           797:             // Do the blit operation on the temporary bitmap:
        !           798: 
        !           799:             bRet = EngBitBlt(ppdev->psoTemp,
        !           800:                      psoSrc,
        !           801:                      psoMask,
        !           802:                      pco,
        !           803:                      pxlo,
        !           804:                      prclTrg,
        !           805:                      pptlSrc,
        !           806:                      pptlMask,
        !           807:                      pbo,
        !           808:                      pptlBrush,
        !           809:                      rop4);
        !           810: 
        !           811:             // Copy everything back to the surface:
        !           812: 
        !           813:             if (bRet)
        !           814:             {
        !           815:                 vPuntPutBits(ppdev, psoTrg, prclTrg);
        !           816:             }
        !           817:         }
        !           818:     }
        !           819:     else
        !           820:     {
        !           821:         // -------------------------------------------------------
        !           822:         // Handle screen-to-bitmap blit:
        !           823: 
        !           824:         ppdev = (PPDEV) psoSrc->dhsurf;
        !           825: 
        !           826:         // Copy the source rectangle to the temporary bitmap, then get
        !           827:         // GDI to blit to the target surface:
        !           828: 
        !           829:         rclSrc.left   = pptlSrc->x;
        !           830:         rclSrc.top    = pptlSrc->y;
        !           831:         rclSrc.right  = pptlSrc->x + (prclTrg->right - prclTrg->left);
        !           832:         rclSrc.bottom = pptlSrc->y + (prclTrg->bottom - prclTrg->top);
        !           833: 
        !           834:         vPuntGetBits(ppdev, psoSrc, &rclSrc);
        !           835: 
        !           836:         bRet = EngBitBlt(psoTrg,
        !           837:                  ppdev->psoTemp,
        !           838:                  psoMask,
        !           839:                  pco,
        !           840:                  pxlo,
        !           841:                  prclTrg,
        !           842:                  pptlSrc,
        !           843:                  pptlMask,
        !           844:                  pbo,
        !           845:                  pptlBrush,
        !           846:                  rop4);
        !           847:     }
        !           848: 
        !           849:     vResetS3Clipping(ppdev);    // Always reset after using vPunt routines
        !           850: 
        !           851:     return(bRet);
        !           852: 
        !           853: #endif
        !           854: }
        !           855: 
        !           856: /******************************************************************************
        !           857:  * bScrnToScrnPuntBlit - Screen To Screen Punt Blit
        !           858:  *****************************************************************************/
        !           859: BOOL bScrnToScrnPuntBlit(
        !           860:     SURFOBJ  *psoTrg,
        !           861:     SURFOBJ  *psoSrc,
        !           862:     SURFOBJ  *psoMask,
        !           863:     CLIPOBJ  *pco,
        !           864:     XLATEOBJ *pxlo,
        !           865:     RECTL    *prclTrg,
        !           866:     POINTL   *pptlSrc,
        !           867:     POINTL   *pptlMask,
        !           868:     BRUSHOBJ *pbo,
        !           869:     POINTL   *pptlBrush,
        !           870:     ROP4     rop4)
        !           871: {
        !           872: 
        !           873:     SIZEL       sizl;
        !           874:     HSURF       hsurfBm;
        !           875:     SURFOBJ     *psoTempSrc;
        !           876:     WORD        cmd;
        !           877:     INT         i, cxInWords;
        !           878:     PBYTE       pb;
        !           879:     PWORD       pw;
        !           880:     PPDEV       ppdev;
        !           881:     RECTL       rclScans, rclTrg;
        !           882:     BOOL        bRet;
        !           883:     POINTL      ptlTempSrc;
        !           884: 
        !           885:     DISPDBG((2,"S3.DLL!bScrnToScrnPuntBlit - Entry\n"));
        !           886: 
        !           887:     // Pickup our pdev and a pointer to the surface object.
        !           888: 
        !           889:     ppdev  = (PPDEV) psoTrg->dhsurf;
        !           890:     psoTrg = ppdev->pSurfObj;
        !           891: 
        !           892:     // Set the default bounding rectangle for the bank manager.
        !           893: 
        !           894:     rclTrg = *prclTrg;
        !           895: 
        !           896:     // Create a temporary surface and bitmap.
        !           897: 
        !           898:     sizl.cx = prclTrg->right  - prclTrg->left;
        !           899:     sizl.cy = prclTrg->bottom - prclTrg->top;
        !           900: 
        !           901:     hsurfBm = (HSURF) EngCreateBitmap(sizl,
        !           902:                                       sizl.cx,
        !           903:                                       BMF_8BPP,
        !           904:                                       BMF_TOPDOWN,
        !           905:                                       NULL);
        !           906:     if (hsurfBm == NULL)
        !           907:     {
        !           908:         DISPDBG((0, "S3.DLL!bScrnToScrnPuntBlit - EngCreateBitmap failed\n"));
        !           909:         return(FALSE);
        !           910:     }
        !           911: 
        !           912:     // Get a pointer to the surface object.
        !           913: 
        !           914:     psoTempSrc = EngLockSurface(hsurfBm);
        !           915: 
        !           916:     // Copy the bits into it.
        !           917: 
        !           918:     if (!(sizl.cx & 0x01))
        !           919:     {
        !           920:         cmd =   RECTANGLE_FILL     | BYTE_SWAP      | BUS_SIZE_16 |
        !           921:                 DRAWING_DIR_TBLRXM | DIR_TYPE_XY    | WAIT |
        !           922:                 DRAW               | LAST_PIXEL_ON  | READ;
        !           923:     }
        !           924:     else
        !           925:     {
        !           926:         cmd =   RECTANGLE_FILL     | BUS_SIZE_8 |
        !           927:                 DRAWING_DIR_TBLRXM | DIR_TYPE_XY    | WAIT |
        !           928:                 DRAW               | LAST_PIXEL_ON  | READ;
        !           929:     }
        !           930: 
        !           931:     FIFOWAIT(FIFO_7_EMPTY);
        !           932: 
        !           933:     TEST_AND_SET_RD_MASK(0xff);
        !           934:     OUTPW (MULTIFUNC_CNTL, (DATA_EXTENSION | ALL_ONES));
        !           935: 
        !           936:     OUTPW (CUR_X, pptlSrc->x);
        !           937:     OUTPW (CUR_Y, pptlSrc->y);
        !           938:     OUTPW (RECT_WIDTH, (sizl.cx - 1));
        !           939:     OUTPW (MULTIFUNC_CNTL, (RECT_HEIGHT | (sizl.cy - 1)));
        !           940: 
        !           941:     GPWAIT();
        !           942: 
        !           943:     OUTPW (CMD, cmd);
        !           944: 
        !           945:     // Wait for the Data Available.
        !           946: 
        !           947:     while (!(inpw(GP_STAT) & READ_DATA_AVAILABLE));
        !           948: 
        !           949:     // Now transfer the data from the screen to the host memory bitmap.
        !           950: 
        !           951:     if (!(sizl.cx & 0x01))
        !           952:     {
        !           953:         cxInWords = (sizl.cx + 1) / 2;
        !           954:         pw = (PWORD) psoTempSrc->pvScan0;
        !           955:         for (i = 0; i < sizl.cy; i++)
        !           956:         {
        !           957:             vDataPortIn(ppdev, pw, cxInWords);
        !           958:             ((PBYTE) pw) += psoTempSrc->lDelta;
        !           959:         }
        !           960:     }
        !           961:     else
        !           962:     {
        !           963:         pb = psoTempSrc->pvScan0;
        !           964:         for (i = 0; i < sizl.cy; i++)
        !           965:         {
        !           966:             vDataPortInB(ppdev, pb, sizl.cx);
        !           967:             pb += psoTempSrc->lDelta;
        !           968:         }
        !           969:     }
        !           970: 
        !           971:     // Set the new source position
        !           972: 
        !           973:     ptlTempSrc.x = 0;
        !           974:     ptlTempSrc.y = 0;
        !           975: 
        !           976:     // Do the banked blit operation.
        !           977: 
        !           978:     rclScans.top    = prclTrg->top;
        !           979:     rclScans.bottom = prclTrg->bottom;
        !           980: 
        !           981:     bBankEnumStart(ppdev, &rclScans, psoTrg, pco);
        !           982: 
        !           983:     do
        !           984:     {
        !           985:         bRet = EngBitBlt(psoTrg,
        !           986:                   psoTempSrc,
        !           987:                   psoMask,
        !           988:                   pco,
        !           989:                   pxlo,
        !           990:                   &rclTrg,
        !           991:                   &ptlTempSrc,
        !           992:                   pptlMask,
        !           993:                   pbo,
        !           994:                   pptlBrush,
        !           995:                   rop4);
        !           996: 
        !           997:     } while ((bBankEnum(ppdev, &rclScans, psoTrg, pco)) && bRet);
        !           998: 
        !           999:     bBankEnumEnd(ppdev, psoTrg, pco);
        !          1000: 
        !          1001:     // free the temp bitmap.
        !          1002: 
        !          1003:     EngUnlockSurface(psoTempSrc);
        !          1004:     EngDeleteSurface(hsurfBm);
        !          1005: 
        !          1006:     return (bRet);
        !          1007: 
        !          1008: }
        !          1009: 
        !          1010: /*****************************************************************************
        !          1011:  * S3 Special case Blit handler
        !          1012:  *
        !          1013:  *  Returns TRUE if the blit was handled.
        !          1014:  ****************************************************************************/
        !          1015: BOOL bSpecialBlits(
        !          1016:     SURFOBJ     *psoTrg,
        !          1017:     SURFOBJ     *psoSrc,
        !          1018:     SURFOBJ     *psoMask,
        !          1019:     CLIPOBJ     *pco,
        !          1020:     XLATEOBJ    *pxlo,
        !          1021:     RECTL   *prclTrg,
        !          1022:     POINTL  *pptlSrc,
        !          1023:     POINTL  *pptlMask,
        !          1024:     BRUSHOBJ    *pbo,
        !          1025:     POINTL  *pptlBrush,
        !          1026:     ROP4  rop4)
        !          1027: {
        !          1028:     BOOL    bRet;
        !          1029:     PPDEV   ppdev;
        !          1030:     ROP4    s3Rop4;
        !          1031:     WORD    avecRop, s3Rop;
        !          1032:     BRUSHOBJ bo;
        !          1033: 
        !          1034:     bRet = FALSE;
        !          1035: 
        !          1036:     if (psoTrg->iType == STYPE_DEVICE)
        !          1037:         ppdev = (PPDEV) psoTrg->dhsurf;
        !          1038:     else
        !          1039:         ppdev = (PPDEV) psoSrc->dhsurf;
        !          1040: 
        !          1041:     // NOTE: If the ForeRop and BackRop are the same implicitly
        !          1042:     //       there is no mask.
        !          1043: 
        !          1044:     // First test for copy opperations.
        !          1045: 
        !          1046:     if (rop4 == 0x0000CCCC)
        !          1047:     {
        !          1048:         if ((psoTrg->iType == STYPE_DEVICE) && (psoSrc->iType == STYPE_DEVICE))
        !          1049:         {
        !          1050:             if ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL))
        !          1051:             {
        !          1052:                 bRet = bScrnToScrnWithRop(psoTrg, psoSrc, pco, prclTrg, pptlSrc, OVERPAINT);
        !          1053:                 return(bRet);
        !          1054:             }
        !          1055:             else
        !          1056:             {
        !          1057:                 return (FALSE);
        !          1058:             }
        !          1059:         }
        !          1060: 
        !          1061:     }
        !          1062: 
        !          1063:     // Check for a mask.  If there is one, at this time, reject the
        !          1064:     // acceleration.
        !          1065: 
        !          1066:     if (psoMask != NULL)
        !          1067:     {
        !          1068:         return (FALSE);
        !          1069:     }
        !          1070: 
        !          1071:     // If the background and foreground rops are not the same
        !          1072:     // reject the blit.
        !          1073: 
        !          1074:     if (((rop4 & 0xFF00) >> 8) != (rop4 & 0xff))
        !          1075:     {
        !          1076:         return (FALSE);
        !          1077:     }
        !          1078: 
        !          1079:     // Pickup the avec for some quick decision later.
        !          1080: 
        !          1081:     avecRop = gajRop[(rop4 & 0xff)];
        !          1082: 
        !          1083:     // Check for a DIB.  If this is a DIB reject the blit.
        !          1084:     // BUGBUG: At some future date (post BETA2) this should be optimized.
        !          1085: 
        !          1086:     if ((avecRop & AVEC_NEED_SOURCE) && (psoSrc->lDelta < 0))
        !          1087:     {
        !          1088:         return (FALSE);
        !          1089:     }
        !          1090: 
        !          1091:     // Check for whitness or blackness
        !          1092: 
        !          1093:     if (((rop4 & 0xff) == 0xff) ||
        !          1094:         ((rop4 & 0xff) == 0x00))
        !          1095:     {
        !          1096:         if ((rop4 & 0xff) == 0xff)
        !          1097:             s3Rop4 = LOGICAL_1;
        !          1098:         else
        !          1099:             s3Rop4 = LOGICAL_0;
        !          1100: 
        !          1101:         bRet = bPatternSolid(psoTrg, psoSrc, psoMask,
        !          1102:                           pco, pxlo,
        !          1103:                           prclTrg, pptlSrc, pptlMask,
        !          1104:                           pbo, pptlBrush,
        !          1105:                           s3Rop4);
        !          1106:         return (bRet);
        !          1107:     }
        !          1108: 
        !          1109:     // Check for Dest Invert
        !          1110: 
        !          1111:     if ((rop4 & 0xff) == 0x55)
        !          1112:     {
        !          1113:         s3Rop4 = SCREEN_XOR_NEW;
        !          1114:         bo.iSolidColor = 0xffff;
        !          1115: 
        !          1116:         bRet = bPatternSolid(psoTrg, psoSrc, psoMask,
        !          1117:                           pco, pxlo,
        !          1118:                           prclTrg, pptlSrc, pptlMask,
        !          1119:                           &bo, pptlBrush,
        !          1120:                           s3Rop4);
        !          1121:         return (bRet);
        !          1122: 
        !          1123:     }
        !          1124: 
        !          1125: 
        !          1126:     // Check for brushes.
        !          1127: 
        !          1128:     if ((avecRop & AVEC_NEED_PATTERN) && (!(avecRop & AVEC_NEED_SOURCE)))
        !          1129:     {
        !          1130:         // Translate the rop from GDI to S3.
        !          1131: 
        !          1132:         s3Rop4 = bXlatePatRop4toS3Rop(ppdev, rop4);
        !          1133: 
        !          1134:         // Check for a Solid Brush.
        !          1135: 
        !          1136:         if (pbo == NULL || pbo->iSolidColor != -1)
        !          1137:         {
        !          1138:             bRet = bPatternSolid(psoTrg, psoSrc, psoMask,
        !          1139:                               pco, pxlo,
        !          1140:                               prclTrg, pptlSrc, pptlMask,
        !          1141:                               pbo, pptlBrush,
        !          1142:                               s3Rop4);
        !          1143:         }
        !          1144: 
        !          1145:         // Handle this as a Pattern Brush.
        !          1146: 
        !          1147:         else
        !          1148:         {
        !          1149:             bRet = bPatternBrush(psoTrg, pco, prclTrg, pbo, pptlBrush, s3Rop4);
        !          1150:         }
        !          1151: 
        !          1152:     }
        !          1153: 
        !          1154:     // Check if we may be able to optimize for screen to screen or
        !          1155:     // host to screen blits.
        !          1156: 
        !          1157:     else if ((!(avecRop & AVEC_NEED_PATTERN)) &&
        !          1158:             (avecRop & AVEC_NEED_SOURCE))
        !          1159:     {
        !          1160:         s3Rop = wXlateSrcRop3toS3Rop(ppdev, LOWORD(rop4));
        !          1161:         if (s3Rop != 0)
        !          1162:         {
        !          1163:             if ((psoTrg->iType == STYPE_DEVICE) &&
        !          1164:                 (psoSrc->iType == STYPE_DEVICE) &&
        !          1165:                 ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)))
        !          1166:             {
        !          1167:                 bRet = bScrnToScrnWithRop(psoTrg, psoSrc, pco, prclTrg,
        !          1168:                                        pptlSrc, s3Rop);
        !          1169:             }
        !          1170:             else if (psoSrc->iType == STYPE_BITMAP)
        !          1171:             {
        !          1172:                 switch (psoSrc->iBitmapFormat)
        !          1173:                 {
        !          1174:                     case BMF_DEVICE:
        !          1175:                     case BMF_8BPP:
        !          1176:                         bRet = b8BppHostToScrnCachedWithRop(psoTrg,
        !          1177:                                                             psoSrc,
        !          1178:                                                             pco,
        !          1179:                                                             pxlo,
        !          1180:                                                             prclTrg,
        !          1181:                                                             pptlSrc,
        !          1182:                                                             s3Rop);
        !          1183:                         break;
        !          1184: 
        !          1185:                     case BMF_1BPP:
        !          1186:                         bRet = b1BppHostToScrnCachedWithRop(psoTrg,
        !          1187:                                                             psoSrc,
        !          1188:                                                             pco,
        !          1189:                                                             pxlo,
        !          1190:                                                             prclTrg,
        !          1191:                                                             pptlSrc,
        !          1192:                                                             s3Rop);
        !          1193:                         break;
        !          1194: 
        !          1195:                     case BMF_4BPP:
        !          1196:                         bRet = b4BppHostToScrnWithRop(psoTrg,
        !          1197:                                                       psoSrc,
        !          1198:                                                       pco,
        !          1199:                                                       pxlo,
        !          1200:                                                       prclTrg,
        !          1201:                                                       pptlSrc,
        !          1202:                                                       s3Rop);
        !          1203:                         break;
        !          1204: 
        !          1205:                     case BMF_16BPP:
        !          1206:                     case BMF_24BPP:
        !          1207:                     case BMF_32BPP:
        !          1208:                     case BMF_4RLE:
        !          1209:                     case BMF_8RLE:
        !          1210:                     default:
        !          1211:                         bRet = FALSE;
        !          1212:                         break;
        !          1213:                 }
        !          1214:             }
        !          1215:         }
        !          1216: 
        !          1217:         else
        !          1218:         {
        !          1219:             DISPDBG((0,"S3.DLL!bSpecialBlits - Missed SrcBlt opportunity - rop: 0x%x\n",
        !          1220:                         rop4));
        !          1221:         }
        !          1222:     }
        !          1223: 
        !          1224:     else if ((rop4 & 0xff) == 0xc0)     // Merge Copy
        !          1225:     {
        !          1226:         if ((psoTrg->iType == STYPE_DEVICE) &&
        !          1227:             (psoSrc->iType == STYPE_DEVICE) &&
        !          1228:             ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)))
        !          1229: 
        !          1230:         {
        !          1231:             bRet = bScrnToScrnWithRop(psoTrg, psoSrc,
        !          1232:                                       pco, prclTrg, pptlSrc,
        !          1233:                                       OVERPAINT);
        !          1234: 
        !          1235:             if (bRet)
        !          1236:             {
        !          1237:                 if (pbo == NULL || pbo->iSolidColor != -1)
        !          1238:                 {
        !          1239:                     bRet = bPatternSolid(psoTrg, psoSrc, psoMask,
        !          1240:                                       pco, pxlo,
        !          1241:                                       prclTrg, pptlSrc, pptlMask,
        !          1242:                                       pbo, pptlBrush,
        !          1243:                                       SCREEN_AND_NEW);
        !          1244:                 }
        !          1245:                 else
        !          1246:                 {
        !          1247:                     bRet = bPatternBrush(psoTrg, pco, prclTrg,
        !          1248:                                          pbo, pptlBrush,
        !          1249:                                          (SCREEN_AND_NEW << 8) | SCREEN_AND_NEW);
        !          1250:                 }
        !          1251:             }
        !          1252:         }
        !          1253:         else if (psoSrc->iType == STYPE_BITMAP)
        !          1254:         {
        !          1255:             switch (psoSrc->iBitmapFormat)
        !          1256:             {
        !          1257:                 case BMF_DEVICE:
        !          1258:                 case BMF_8BPP:
        !          1259:                     bRet = b8BppHostToScrnCachedWithRop(psoTrg,
        !          1260:                                                         psoSrc,
        !          1261:                                                         pco,
        !          1262:                                                         pxlo,
        !          1263:                                                         prclTrg,
        !          1264:                                                         pptlSrc,
        !          1265:                                                         OVERPAINT);
        !          1266:                     break;
        !          1267: 
        !          1268:                 case BMF_1BPP:
        !          1269:                     bRet = b1BppHostToScrnCachedWithRop(psoTrg,
        !          1270:                                                         psoSrc,
        !          1271:                                                         pco,
        !          1272:                                                         pxlo,
        !          1273:                                                         prclTrg,
        !          1274:                                                         pptlSrc,
        !          1275:                                                         OVERPAINT);
        !          1276:                     break;
        !          1277: 
        !          1278:                 case BMF_4BPP:
        !          1279:                     bRet = b4BppHostToScrnWithRop(psoTrg,
        !          1280:                                                   psoSrc,
        !          1281:                                                   pco,
        !          1282:                                                   pxlo,
        !          1283:                                                   prclTrg,
        !          1284:                                                   pptlSrc,
        !          1285:                                                   OVERPAINT);
        !          1286:                     break;
        !          1287: 
        !          1288:                 case BMF_16BPP:
        !          1289:                 case BMF_24BPP:
        !          1290:                 case BMF_32BPP:
        !          1291:                 case BMF_4RLE:
        !          1292:                 case BMF_8RLE:
        !          1293:                 default:
        !          1294:                     bRet = FALSE;
        !          1295:                     break;
        !          1296:             }
        !          1297: 
        !          1298:             if (bRet)
        !          1299:             {
        !          1300:                 if (pbo == NULL || pbo->iSolidColor != -1)
        !          1301:                 {
        !          1302:                     bRet = bPatternSolid(psoTrg, psoSrc, psoMask,
        !          1303:                                       pco, pxlo,
        !          1304:                                       prclTrg, pptlSrc, pptlMask,
        !          1305:                                       pbo, pptlBrush,
        !          1306:                                       SCREEN_AND_NEW);
        !          1307:                 }
        !          1308:                 else
        !          1309:                 {
        !          1310:                     bRet = bPatternBrush(psoTrg, pco, prclTrg,
        !          1311:                                          pbo, pptlBrush,
        !          1312:                                          (SCREEN_AND_NEW << 8) | SCREEN_AND_NEW);
        !          1313:                 }
        !          1314:             }
        !          1315:         }
        !          1316:     }
        !          1317: 
        !          1318: 
        !          1319: 
        !          1320:     return (bRet);
        !          1321: }
        !          1322: 
        !          1323: 
        !          1324: /*****************************************************************************
        !          1325:  * S3 Screen to Screen with a Rop
        !          1326:  *
        !          1327:  *  Returns TRUE if the blit was handled.
        !          1328:  ****************************************************************************/
        !          1329: BOOL bScrnToScrnWithRop(
        !          1330:     SURFOBJ  *psoTrg,
        !          1331:     SURFOBJ  *psoSrc,
        !          1332:     CLIPOBJ  *pco,
        !          1333:     RECTL    *prclTrg,
        !          1334:     POINTL   *pptlSrc,
        !          1335:     WORD     s3Rop)
        !          1336: {
        !          1337:     INT     width, height, xTrg, yTrg, xSrc, ySrc, cx, cy;
        !          1338:     WORD    cmd, wDirCode;
        !          1339:     RECTL   rclSrc, rclTrg;
        !          1340:     ULONG   DirClip;
        !          1341:     BOOL    bMore, bIntersect, bClipRequired;
        !          1342:     UINT    i;
        !          1343:     ENUMRECTS8   EnumRects8;
        !          1344:     PPDEV   ppdev;
        !          1345:     RECTL   rclBounds;
        !          1346:     BYTE    iDComplexity;
        !          1347: 
        !          1348:     // Get the pdev.
        !          1349: 
        !          1350:     ppdev = (PPDEV) psoTrg->dhpdev;
        !          1351: 
        !          1352:     // There are two completely different code paths.
        !          1353:     // for the complex and non-complex clip cases.
        !          1354:     // This is because most of the direction and intersection
        !          1355:     // calculations need to be done after the clipping.
        !          1356: 
        !          1357:     if ((iDComplexity = pco->iDComplexity) != DC_COMPLEX)
        !          1358:     {
        !          1359:         // Make a copy of the target, since we will have to change
        !          1360:         // it for clipping.
        !          1361: 
        !          1362:         rclTrg = *prclTrg;
        !          1363: 
        !          1364:         if (iDComplexity == DC_RECT)
        !          1365:         {
        !          1366:             rclBounds = pco->rclBounds;
        !          1367: 
        !          1368:             // First handle the trivial rejection.
        !          1369: 
        !          1370:             bClipRequired = bIntersectTest(&rclTrg, &rclBounds);
        !          1371: 
        !          1372:             // define the clipped target rectangle.
        !          1373: 
        !          1374:             if (bClipRequired)
        !          1375:             {
        !          1376:                 rclTrg.left   = max (rclTrg.left, rclBounds.left);
        !          1377:                 rclTrg.top    = max (rclTrg.top, rclBounds.top);
        !          1378:                 rclTrg.right  = min (rclTrg.right, rclBounds.right);
        !          1379:                 rclTrg.bottom = min (rclTrg.bottom, rclBounds.bottom);
        !          1380:             }
        !          1381:             else
        !          1382:             {
        !          1383:                 // The destination rectangle is completely clipped out,
        !          1384:                 // so just return.
        !          1385: 
        !          1386:                 return (TRUE);
        !          1387:             }
        !          1388:         }
        !          1389: 
        !          1390:         // define the cx & cy.
        !          1391: 
        !          1392:         width  = (rclTrg.right  - rclTrg.left) - 1;
        !          1393:         height = (rclTrg.bottom - rclTrg.top)  - 1;
        !          1394: 
        !          1395:         // calculate the cx & cy shift for the source.
        !          1396: 
        !          1397:         cx = rclTrg.left - prclTrg->left;
        !          1398:         cy = rclTrg.top  - prclTrg->top;
        !          1399: 
        !          1400:         // define the source rectangle.
        !          1401: 
        !          1402:         rclSrc.left   = pptlSrc->x + cx;
        !          1403:         rclSrc.top    = pptlSrc->y + cy;
        !          1404:         rclSrc.right  = pptlSrc->x + width + 1;
        !          1405:         rclSrc.bottom = pptlSrc->y + height + 1;
        !          1406: 
        !          1407:         // Determine the direction of the blit.
        !          1408:         // First, check for an intersection of the souce and dest rects.
        !          1409: 
        !          1410:         bIntersect = bIntersectTest(&rclTrg, &rclSrc);
        !          1411: 
        !          1412:         // Set defaults for the S3 blit direction and the
        !          1413:         // initial coordinates
        !          1414: 
        !          1415:         wDirCode = DRAWING_DIR_TBLRXM;
        !          1416: 
        !          1417:         xTrg = rclTrg.left;
        !          1418:         yTrg = rclTrg.top;
        !          1419:         xSrc = rclSrc.left;
        !          1420:         ySrc = rclSrc.top;
        !          1421: 
        !          1422:         // If the source & dest rects intersect adjust the
        !          1423:         // blit direction and initial coordinates.
        !          1424: 
        !          1425:         if (bIntersect)
        !          1426:         {
        !          1427:             // The horizontal copy direction.
        !          1428: 
        !          1429:             if (rclTrg.left > rclSrc.left)
        !          1430:             {
        !          1431:                 // R to L
        !          1432: 
        !          1433:                 xTrg = rclTrg.right - 1;
        !          1434:                 xSrc = rclSrc.left + width;
        !          1435:                 wDirCode &= ~PLUS_X;
        !          1436:             }
        !          1437: 
        !          1438:             // The vertical copy direction.
        !          1439: 
        !          1440:             if (rclTrg.top > rclSrc.top)
        !          1441:             {
        !          1442:                 // B to T
        !          1443: 
        !          1444:                 yTrg = rclTrg.bottom - 1;
        !          1445:                 ySrc = rclSrc.top + height;
        !          1446:                 wDirCode &= ~PLUS_Y;
        !          1447:             }
        !          1448:         }
        !          1449: 
        !          1450:         // Create the S3 Command.
        !          1451: 
        !          1452:         cmd  = BITBLT | DRAW | DIR_TYPE_XY | WRITE;
        !          1453:         cmd |= wDirCode;
        !          1454: 
        !          1455:         // Do the blit.
        !          1456: 
        !          1457:         S3ScrnToScrnBlt(ppdev, xSrc, ySrc, xTrg, yTrg, width, height, s3Rop, cmd);
        !          1458: 
        !          1459:     }
        !          1460:     else
        !          1461:     {
        !          1462:         // This a complex clip.
        !          1463: 
        !          1464:         DirClip  = CD_ANY;
        !          1465:         wDirCode = DRAWING_DIR_TBLRXM;
        !          1466: 
        !          1467:         if (prclTrg->left > pptlSrc->x)
        !          1468:             wDirCode &= ~PLUS_X;
        !          1469: 
        !          1470:         if (prclTrg->top > pptlSrc->y)
        !          1471:             wDirCode &= ~PLUS_Y;
        !          1472: 
        !          1473:         switch (wDirCode)
        !          1474:         {
        !          1475:             case DRAWING_DIR_TBLRXM:
        !          1476:                 DirClip = CD_RIGHTDOWN;
        !          1477:                 break;
        !          1478: 
        !          1479:             case DRAWING_DIR_TBRLXM:
        !          1480:                 DirClip = CD_LEFTDOWN;
        !          1481:                 break;
        !          1482: 
        !          1483:             case DRAWING_DIR_BTLRXM:
        !          1484:                 DirClip = CD_RIGHTUP;
        !          1485:                 break;
        !          1486: 
        !          1487:             case DRAWING_DIR_BTRLXM:
        !          1488:                 DirClip = CD_LEFTUP;
        !          1489:                 break;
        !          1490:         }
        !          1491: 
        !          1492:         CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, DirClip, 0);
        !          1493: 
        !          1494:         do
        !          1495:         {
        !          1496:             bMore = CLIPOBJ_bEnum(pco, sizeof (ENUMRECTS8),
        !          1497:                                   (PULONG) &EnumRects8);
        !          1498: 
        !          1499:             for (i = 0; i < EnumRects8.c; i++)
        !          1500:             {
        !          1501:                 rclTrg    = *prclTrg;
        !          1502:                 rclBounds = EnumRects8.arcl[i];
        !          1503: 
        !          1504:                 // handle the trivial rejection.
        !          1505: 
        !          1506:                 bClipRequired = bIntersectTest(&rclTrg, &rclBounds);
        !          1507: 
        !          1508:                 // define the clipped target rectangle.
        !          1509: 
        !          1510:                 if (bClipRequired)
        !          1511:                 {
        !          1512:                     rclTrg.left   = max (rclTrg.left, rclBounds.left);
        !          1513:                     rclTrg.top    = max (rclTrg.top, rclBounds.top);
        !          1514:                     rclTrg.right  = min (rclTrg.right, rclBounds.right);
        !          1515:                     rclTrg.bottom = min (rclTrg.bottom, rclBounds.bottom);
        !          1516:                 }
        !          1517:                 else
        !          1518:                 {
        !          1519:                     // The destination rectangle is completely clipped out,
        !          1520:                     // so use as an early out.
        !          1521: 
        !          1522:                     continue;
        !          1523:                 }
        !          1524: 
        !          1525:                 // define the cx & cy.
        !          1526: 
        !          1527:                 width  = (rclTrg.right  - rclTrg.left) - 1;
        !          1528:                 height = (rclTrg.bottom - rclTrg.top)  - 1;
        !          1529: 
        !          1530:                 // calculate the cx & cy shift for the source.
        !          1531: 
        !          1532:                 cx = rclTrg.left - prclTrg->left;
        !          1533:                 cy = rclTrg.top  - prclTrg->top;
        !          1534: 
        !          1535:                 // define the source rectangle.
        !          1536: 
        !          1537:                 rclSrc.left   = pptlSrc->x  + cx;
        !          1538:                 rclSrc.top    = pptlSrc->y  + cy;
        !          1539:                 rclSrc.right  = rclSrc.left + width + 1;
        !          1540:                 rclSrc.bottom = rclSrc.top  + height + 1;
        !          1541: 
        !          1542:                 // Determine the direction of the blit.
        !          1543:                 // First, check for an intersection of the souce and dest rects.
        !          1544: 
        !          1545:                 bIntersect = bIntersectTest(&rclTrg, &rclSrc);
        !          1546: 
        !          1547:                 // Set defaults for the S3 blit direction and the
        !          1548:                 // initial coordinates
        !          1549: 
        !          1550:                 wDirCode = DRAWING_DIR_TBLRXM;
        !          1551: 
        !          1552:                 xTrg = rclTrg.left;
        !          1553:                 yTrg = rclTrg.top;
        !          1554:                 xSrc = rclSrc.left;
        !          1555:                 ySrc = rclSrc.top;
        !          1556: 
        !          1557:                 // If the source & dest rects intersect adjust the
        !          1558:                 // blit direction and initial coordinates.
        !          1559: 
        !          1560:                 if (bIntersect)
        !          1561:                 {
        !          1562:                     // The horizontal copy direction.
        !          1563: 
        !          1564:                     if (rclTrg.left > rclSrc.left)
        !          1565:                     {
        !          1566:                         // R to L
        !          1567: 
        !          1568:                         xTrg = rclTrg.right - 1;
        !          1569:                         xSrc = rclSrc.left + width;
        !          1570:                         wDirCode &= ~PLUS_X;
        !          1571:                     }
        !          1572: 
        !          1573:                     // The vertical copy direction.
        !          1574: 
        !          1575:                     if (rclTrg.top > rclSrc.top)
        !          1576:                     {
        !          1577:                         // B to T
        !          1578: 
        !          1579:                         yTrg = rclTrg.bottom - 1;
        !          1580:                         ySrc = rclSrc.top + height;
        !          1581:                         wDirCode &= ~PLUS_Y;
        !          1582:                     }
        !          1583:                 }
        !          1584: 
        !          1585:                 // Create the S3 Command.
        !          1586: 
        !          1587:                 cmd  = BITBLT | DRAW | DIR_TYPE_XY | WRITE;
        !          1588:                 cmd |= wDirCode;
        !          1589: 
        !          1590:                 // Do the blit.
        !          1591: 
        !          1592:                 S3ScrnToScrnBlt(ppdev, xSrc, ySrc, xTrg, yTrg, width, height, s3Rop, cmd);
        !          1593: 
        !          1594:             }
        !          1595: 
        !          1596:         } while (bMore);
        !          1597:     }
        !          1598:     return(TRUE);
        !          1599: }
        !          1600: 
        !          1601: 
        !          1602: /*****************************************************************************
        !          1603:  * S3ScrnToScrnBlt
        !          1604:  ****************************************************************************/
        !          1605: VOID S3ScrnToScrnBlt(
        !          1606:     PPDEV   ppdev,
        !          1607:     INT     xSrc,
        !          1608:     INT     ySrc,
        !          1609:     INT     xTrg,
        !          1610:     INT     yTrg,
        !          1611:     INT     width,
        !          1612:     INT     height,
        !          1613:     WORD    s3Rop,
        !          1614:     WORD    cmd)
        !          1615: {
        !          1616: 
        !          1617: #if DBG
        !          1618: 
        !          1619:     if (cmd & 0x20)
        !          1620:     {
        !          1621:         ASSERTS3(((xTrg + width) < (INT) ppdev->cxScreen),
        !          1622:                  "S3.DLL!S3ScrnToScrnBlt - Blit Operation over right edge (1)\n");
        !          1623:     }
        !          1624: 
        !          1625: #endif
        !          1626:     // This is where the actual S3 registers are set.
        !          1627: 
        !          1628:     FIFOWAIT(FIFO_2_EMPTY);
        !          1629: 
        !          1630:     TEST_AND_SET_FRGD_MIX(SRC_DISPLAY_MEMORY | s3Rop);
        !          1631: 
        !          1632:     OUTPW(MULTIFUNC_CNTL, (DATA_EXTENSION | ALL_ONES));
        !          1633: 
        !          1634:     FIFOWAIT(FIFO_7_EMPTY);
        !          1635: 
        !          1636:     OUTPW(RECT_WIDTH, width);
        !          1637:     OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | height));
        !          1638:     OUTPW(CUR_X, xSrc);
        !          1639:     OUTPW(CUR_Y, ySrc);
        !          1640:     OUTPW(DEST_X, xTrg);
        !          1641:     OUTPW(DEST_Y, yTrg);
        !          1642: 
        !          1643:     OUTPW(CMD, cmd);
        !          1644: }
        !          1645: 
        !          1646: 
        !          1647: /*****************************************************************************
        !          1648:  * S3 Brush Pattern
        !          1649:  *
        !          1650:  *  Returns TRUE if the blit was handled.
        !          1651:  ****************************************************************************/
        !          1652: BOOL bPatternBrush(
        !          1653:     SURFOBJ  *psoTrg,
        !          1654:     CLIPOBJ  *pco,
        !          1655:     RECTL    *prclTrg,
        !          1656:     BRUSHOBJ *pbo,
        !          1657:     POINTL   *pptlBrush,
        !          1658:     ROP4      s3Rop4)           // Note that the least significant byte is
        !          1659:                                 // the S3 foreground ROP, and the next byte
        !          1660:                                 // is the S3 background ROP.  So you can't
        !          1661:                                 // just pass in a plain S3 ROP constant!
        !          1662: 
        !          1663: {
        !          1664:     PPDEV       ppdev;
        !          1665:     PS3BRUSH    ps3Brush;
        !          1666:     POINT       pt;
        !          1667:     XYZPOINT    xyzPt;
        !          1668:     INT         zHorz, zVert, i;
        !          1669:     POINT       ptDest;
        !          1670:     SIZE        sizDest;
        !          1671:     WORD        s3ForeRop, s3BackRop;
        !          1672:     BOOL        bClipRequired, bMore;
        !          1673:     RECTL       rclTrg, rclBounds;
        !          1674:     BYTE        iDComplexity;
        !          1675:     ENUMRECTS8  EnumRects8;
        !          1676: 
        !          1677:     DISPDBG((3, "S3.DLL!bPatternBrush - Entry\n"));
        !          1678: 
        !          1679:     // Get the pdev.
        !          1680: 
        !          1681:     ppdev = (PPDEV) psoTrg->dhpdev;
        !          1682: 
        !          1683:     // Get the pointer to our drivers realization of the brush.
        !          1684: 
        !          1685:     if (pbo->pvRbrush != NULL)
        !          1686:     {
        !          1687:         ps3Brush = pbo->pvRbrush;
        !          1688:     }
        !          1689:     else
        !          1690:     {
        !          1691:         ps3Brush = BRUSHOBJ_pvGetRbrush(pbo);
        !          1692: 
        !          1693:         // Fail if we do not handle the brush.
        !          1694: 
        !          1695:         if (ps3Brush == NULL)
        !          1696:             return (FALSE);
        !          1697:     }
        !          1698: 
        !          1699:     s3ForeRop = (WORD) (s3Rop4 & 0xFF);
        !          1700:     s3BackRop = (WORD) ((s3Rop4 >> 8) & 0xFF);
        !          1701: 
        !          1702:     if (ps3Brush->iBitmapFormat == BMF_1BPP)
        !          1703:     {
        !          1704:         DISPDBG((3, "S3.DLL!bPatternBrush - 1BPP brush\n"));
        !          1705: 
        !          1706:         // If we have never seen this brush before then allocate a slot
        !          1707:         // for it.
        !          1708: 
        !          1709:         // Keep a count of number of brushes we have seen.
        !          1710:         // This will be used to determine if the cache system is adaquate.
        !          1711: 
        !          1712:         nMonoBrushes++;
        !          1713: 
        !          1714:         // If we have never seen this brush before or if the cache has
        !          1715:         // changed since the last time
        !          1716:         // we have seen it then allocate a new cache entry for it.
        !          1717: 
        !          1718:         if ((ps3Brush->iBrushCacheID == -1) ||
        !          1719:             (ps3Brush->iPatternID != ppdev->pulMonoBrushCacheEntries[ps3Brush->iBrushCacheID]))
        !          1720:         {
        !          1721:             // If we have run out of cache entries invalidate the entire cache.
        !          1722: 
        !          1723:             if (ppdev->iNextMonoBrushCacheSlot >= ppdev->iMaxCachedMonoBrushes)
        !          1724:             {
        !          1725:                 nMonoBrushCacheInvalidations++;
        !          1726: 
        !          1727:                 memset(ppdev->pulMonoBrushCacheEntries, 0, ppdev->iMaxCachedMonoBrushes * sizeof(ULONG));
        !          1728:                 ppdev->iNextMonoBrushCacheSlot = 0;
        !          1729:             }
        !          1730: 
        !          1731:             // Get a slot in the cache for this brush.
        !          1732: 
        !          1733:             i = (ppdev->iNextMonoBrushCacheSlot)++;
        !          1734:             ps3Brush->iBrushCacheID = i;
        !          1735: 
        !          1736:             // Calculate the address of the brush in the cache.
        !          1737: 
        !          1738:             xyzPt.x = MONO_PATTERN_CACHE_X + ((i >>  3) * 16);
        !          1739:             xyzPt.y = MONO_PATTERN_CACHE_Y;
        !          1740:             xyzPt.z = ajMonoPatPlanes[i & 0x7];
        !          1741: 
        !          1742:             // Associate the brush with this cache entry.
        !          1743: 
        !          1744:             ppdev->pulMonoBrushCacheEntries[i] = ps3Brush->iPatternID;
        !          1745: 
        !          1746:             // Get an expansion cache slot for this brush.
        !          1747: 
        !          1748:             i = ppdev->iNextMonoBrushExpansionSlot;
        !          1749:             i = ++i % MAX_MONO_BRUSH_EXPANSION_SLOTS;
        !          1750:             ppdev->iNextMonoBrushExpansionSlot = i;
        !          1751:             ps3Brush->iExpansionCacheID = i;
        !          1752: 
        !          1753:             // Associate this brush with this expansion cache slot.
        !          1754: 
        !          1755:             ppdev->aulMonoExpansionCacheTag[i] = ps3Brush->iPatternID;
        !          1756: 
        !          1757:             // Set the expansion caches planes
        !          1758: 
        !          1759:             zHorz = zVert = ajMonoPatPlanes[i];
        !          1760: 
        !          1761:             // Down load the brush to the cache and expand it into
        !          1762:             // the horizontal and vertical caches.
        !          1763: 
        !          1764:             bDownLoadBrushIntoMonoCache(ppdev, ps3Brush, &xyzPt);
        !          1765:             bExpandMonoBrushIntoHorzCache(ppdev, &xyzPt, zHorz);
        !          1766:             bExpandMonoBrushIntoVertCache(ppdev, &xyzPt, zVert);
        !          1767: 
        !          1768:         }
        !          1769:         else
        !          1770:         {
        !          1771:             // We got a cache hit, so keep the statistic.
        !          1772: 
        !          1773:             nMonoBrushCacheHit++;
        !          1774: 
        !          1775:             // Calculate the address of the brush in the cache.
        !          1776: 
        !          1777:             i = ps3Brush->iBrushCacheID;
        !          1778:             xyzPt.x = MONO_PATTERN_CACHE_X + ((i >>  3) * 16);
        !          1779:             xyzPt.y = MONO_PATTERN_CACHE_Y;
        !          1780:             xyzPt.z = ajMonoPatPlanes[i & 0x7];
        !          1781: 
        !          1782:             // Check for an hit in the expansion cache.
        !          1783: 
        !          1784:             if (ps3Brush->iPatternID == ppdev->aulMonoExpansionCacheTag[(i = ps3Brush->iExpansionCacheID)])
        !          1785:             {
        !          1786:                 zHorz = zVert = ajMonoPatPlanes[i];
        !          1787:                 nMonoBrushExpansionCacheHit++;
        !          1788:             }
        !          1789:             else
        !          1790:             {
        !          1791:                 // Get an expansion cache slot for this brush.
        !          1792: 
        !          1793:                 i = ppdev->iNextMonoBrushExpansionSlot;
        !          1794:                 i = ++i % MAX_MONO_BRUSH_EXPANSION_SLOTS;
        !          1795:                 ppdev->iNextMonoBrushExpansionSlot = i;
        !          1796:                 ps3Brush->iExpansionCacheID = i;
        !          1797: 
        !          1798:                 // Associate this brush with this expansion cache slot.
        !          1799: 
        !          1800:                 ppdev->aulMonoExpansionCacheTag[i] = ps3Brush->iPatternID;
        !          1801: 
        !          1802:                 // Set the expansion caches planes
        !          1803: 
        !          1804:                 zHorz = zVert = ajMonoPatPlanes[i];
        !          1805: 
        !          1806:                 bExpandMonoBrushIntoHorzCache(ppdev, &xyzPt, zHorz);
        !          1807:                 bExpandMonoBrushIntoVertCache(ppdev, &xyzPt, zVert);
        !          1808:             }
        !          1809:         }
        !          1810:     }
        !          1811:     else
        !          1812:     {
        !          1813:         DISPDBG((3, "S3.DLL!bPatternBrush - 8BPP brush\n"));
        !          1814: 
        !          1815:         // If we have never seen this brush before then allocate a slot
        !          1816:         // for it.
        !          1817: 
        !          1818:         // Keep a count of number of brushes we have seen.
        !          1819:         // This will be used to determine if the cache system is adaquate.
        !          1820: 
        !          1821:         nColorBrushes++;
        !          1822: 
        !          1823:         // If we have never seen this brush before or if the cache
        !          1824:         // has changed since the last time
        !          1825:         // we have seen it then allocate a new cache entry for it.
        !          1826: 
        !          1827:         if ((ps3Brush->iBrushCacheID == -1) ||
        !          1828:             (ps3Brush->iPatternID != ppdev->pulColorBrushCacheEntries[ps3Brush->iBrushCacheID]))
        !          1829:         {
        !          1830:             // If we have run out of cache entries invalidate the entire cache.
        !          1831: 
        !          1832:             if (ppdev->iNextColorBrushCacheSlot >= ppdev->iMaxCachedColorBrushes)
        !          1833:             {
        !          1834:                 nColorBrushCacheInvalidations++;
        !          1835: 
        !          1836:                 memset(ppdev->pulColorBrushCacheEntries, 0, ppdev->iMaxCachedColorBrushes * sizeof(ULONG));
        !          1837:                 ppdev->iNextColorBrushCacheSlot = 0;
        !          1838:             }
        !          1839: 
        !          1840:             // Get a slot in the cache for this brush.
        !          1841: 
        !          1842:             i = (ppdev->iNextColorBrushCacheSlot)++;
        !          1843:             ps3Brush->iBrushCacheID = i;
        !          1844: 
        !          1845:             // Calculate the address of the brush in the cache.
        !          1846: 
        !          1847:             pt.x = COLOR_PATTERN_CACHE_X + ((i >>  2) * 16);
        !          1848:             pt.y = COLOR_PATTERN_CACHE_Y + ((i & 0x3) * 16);
        !          1849: 
        !          1850:             // Associate the brush with this cache entry.
        !          1851: 
        !          1852:             ppdev->pulColorBrushCacheEntries[i] = ps3Brush->iPatternID;
        !          1853:             ppdev->ulColorExpansionCacheTag     = ps3Brush->iPatternID;
        !          1854: 
        !          1855:             // Down load the brush to the cache and expand it into
        !          1856:             // the horizontal and vertical caches.
        !          1857: 
        !          1858:             bDownLoadBrushIntoColorCache(ppdev, ps3Brush, &pt);
        !          1859:             bExpandColorBrushIntoHorzCache(ppdev, &pt);
        !          1860:             bExpandColorBrushIntoVertCache(ppdev, &pt);
        !          1861:         }
        !          1862:         else
        !          1863:         {
        !          1864:             // We got a cache hit, so keep the statistic.
        !          1865: 
        !          1866:             nColorBrushCacheHit++;
        !          1867: 
        !          1868:             // Calculate the address of the brush in the cache.
        !          1869: 
        !          1870:             i = ps3Brush->iBrushCacheID;
        !          1871:             pt.x = COLOR_PATTERN_CACHE_X + ((i >>  2) * 16);
        !          1872:             pt.y = COLOR_PATTERN_CACHE_Y + ((i & 0x3) * 16);
        !          1873: 
        !          1874:             if (ps3Brush->iPatternID == ppdev->ulColorExpansionCacheTag)
        !          1875:             {
        !          1876:                 nColorBrushExpansionCacheHit++;
        !          1877:             }
        !          1878:             else
        !          1879:             {
        !          1880:                 ppdev->ulColorExpansionCacheTag = ps3Brush->iPatternID;
        !          1881: 
        !          1882:                 bExpandColorBrushIntoHorzCache(ppdev, &pt);
        !          1883:                 bExpandColorBrushIntoVertCache(ppdev, &pt);
        !          1884:             }
        !          1885:         }
        !          1886:     }
        !          1887: 
        !          1888:     // Handle the clipping.
        !          1889: 
        !          1890:     if ((iDComplexity = pco->iDComplexity) != DC_COMPLEX)
        !          1891:     {
        !          1892:         if (iDComplexity == DC_TRIVIAL)
        !          1893:         {
        !          1894:             rclTrg = *prclTrg;
        !          1895:         }
        !          1896:         else
        !          1897:         {
        !          1898:             rclTrg    = *prclTrg;
        !          1899:             rclBounds = pco->rclBounds;
        !          1900: 
        !          1901:             // First handle the trivial rejection.
        !          1902: 
        !          1903:             bClipRequired = bIntersectTest(&rclTrg, &rclBounds);
        !          1904: 
        !          1905:             if (bClipRequired)
        !          1906:             {
        !          1907:                 rclTrg.left   = max (rclTrg.left,  rclBounds.left);
        !          1908:                 rclTrg.top    = max (rclTrg.top,   rclBounds.top);
        !          1909:                 rclTrg.right  = min(rclTrg.right,  rclBounds.right);
        !          1910:                 rclTrg.bottom = min(rclTrg.bottom, rclBounds.bottom);
        !          1911:             }
        !          1912:             else
        !          1913:             {
        !          1914:                 // The brush is completely clipped out.
        !          1915:                 // so just return sucessfull.
        !          1916: 
        !          1917:                 return (TRUE);
        !          1918:             }
        !          1919:         }
        !          1920: 
        !          1921:         ptDest.x   = rclTrg.left;
        !          1922:         ptDest.y   = rclTrg.top;
        !          1923:         sizDest.cx = rclTrg.right  - rclTrg.left;
        !          1924:         sizDest.cy = rclTrg.bottom - rclTrg.top;
        !          1925: 
        !          1926:         // Color expand the monochrome brush in the Hoizontal Cache to the
        !          1927:         // screen.
        !          1928: 
        !          1929:         if (s3ForeRop == OVERPAINT && s3BackRop == OVERPAINT)
        !          1930:         {
        !          1931:             if (ps3Brush->iBitmapFormat == BMF_1BPP)
        !          1932:             {
        !          1933:                 bCpyColorExpandHorzCacheToScreen(ppdev, ps3Brush, zHorz,
        !          1934:                                                  (PPOINT) pptlBrush,
        !          1935:                                                  &ptDest, &sizDest);
        !          1936:             }
        !          1937:             else
        !          1938:             {
        !          1939:                 // NOTE: The S3-911/924 requries the cx of any "rolling blt"
        !          1940:                 //       to have a cx of >= 64 pels.  This is due to how the
        !          1941:                 //       chip's internal FIFO works.  This test will catch all
        !          1942:                 //       the souce copy operations that can be accelerated,
        !          1943:                 //       with the rolling blit.
        !          1944: 
        !          1945:                 if ((sizDest.cx >= 64) ||
        !          1946:                     (sizDest.cx > sizDest.cy))
        !          1947:                 {
        !          1948:                     bCpyColorHorzCacheToScreen(ppdev, ps3Brush,
        !          1949:                                                (PPOINT) pptlBrush,
        !          1950:                                                &ptDest, &sizDest);
        !          1951:                 }
        !          1952:                 else
        !          1953:                 {
        !          1954:                     bColorVertCacheToScreen(ppdev, ps3Brush,
        !          1955:                                             (PPOINT) pptlBrush,
        !          1956:                                             &ptDest, &sizDest,
        !          1957:                                             s3ForeRop, s3BackRop);
        !          1958:                 }
        !          1959:             }
        !          1960:         }
        !          1961:         else
        !          1962:         {
        !          1963:             if (sizDest.cy > sizDest.cx)
        !          1964:             {
        !          1965:                 if (ps3Brush->iBitmapFormat == BMF_1BPP)
        !          1966:                 {
        !          1967:                     bColorExpandVertCacheToScreen(ppdev, ps3Brush, zVert,
        !          1968:                                                   (PPOINT) pptlBrush,
        !          1969:                                                   &ptDest, &sizDest,
        !          1970:                                                   s3ForeRop, s3BackRop);
        !          1971:                 }
        !          1972:                 else
        !          1973:                 {
        !          1974:                     bColorVertCacheToScreen(ppdev, ps3Brush,
        !          1975:                                             (PPOINT) pptlBrush,
        !          1976:                                             &ptDest, &sizDest,
        !          1977:                                             s3ForeRop, s3BackRop);
        !          1978:                 }
        !          1979:             }
        !          1980:             else
        !          1981:             {
        !          1982:                 if (ps3Brush->iBitmapFormat == BMF_1BPP)
        !          1983:                 {
        !          1984:                     bColorExpandHorzCacheToScreen(ppdev, ps3Brush, zHorz,
        !          1985:                                                   (PPOINT) pptlBrush,
        !          1986:                                                   &ptDest, &sizDest,
        !          1987:                                                   s3ForeRop, s3BackRop);
        !          1988:                 }
        !          1989:                 else
        !          1990:                 {
        !          1991:                     bColorHorzCacheToScreen(ppdev, ps3Brush,
        !          1992:                                             (PPOINT) pptlBrush,
        !          1993:                                             &ptDest, &sizDest,
        !          1994:                                             s3ForeRop, s3BackRop);
        !          1995:                 }
        !          1996:             }
        !          1997:         }
        !          1998:     }
        !          1999:     else
        !          2000:     {
        !          2001:         CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
        !          2002: 
        !          2003:         do
        !          2004:         {
        !          2005:             bMore = CLIPOBJ_bEnum(pco, sizeof (ENUMRECTS8),
        !          2006:                                   (PULONG) &EnumRects8);
        !          2007: 
        !          2008:             for (i = 0; i < (INT) EnumRects8.c; i++)
        !          2009:             {
        !          2010:                 rclBounds = EnumRects8.arcl[i];
        !          2011: 
        !          2012:                 if (rclBounds.left < prclTrg->left)
        !          2013:                     rclBounds.left = prclTrg->left;
        !          2014: 
        !          2015:                 if (rclBounds.right > prclTrg->right)
        !          2016:                     rclBounds.right = prclTrg->right;
        !          2017: 
        !          2018:                 if (rclBounds.top < prclTrg->top)
        !          2019:                     rclBounds.top = prclTrg->top;
        !          2020: 
        !          2021:                 if (rclBounds.bottom > prclTrg->bottom)
        !          2022:                     rclBounds.bottom = prclTrg->bottom;
        !          2023: 
        !          2024:                 // Get the height and width for the blit.
        !          2025: 
        !          2026:                 ptDest.x   = rclBounds.left;
        !          2027:                 ptDest.y   = rclBounds.top;
        !          2028:                 sizDest.cx = rclBounds.right -  rclBounds.left;
        !          2029:                 sizDest.cy = rclBounds.bottom - rclBounds.top;
        !          2030: 
        !          2031:                 // Color expand the monochrome brush in the Hoizontal Cache
        !          2032:                 // to the screen.
        !          2033: 
        !          2034:                 if (s3ForeRop == OVERPAINT && s3BackRop == OVERPAINT)
        !          2035:                 {
        !          2036:                     if (ps3Brush->iBitmapFormat == BMF_1BPP)
        !          2037:                     {
        !          2038:                         bCpyColorExpandHorzCacheToScreen(ppdev, ps3Brush, zHorz,
        !          2039:                                                          (PPOINT) pptlBrush,
        !          2040:                                                          &ptDest, &sizDest);
        !          2041: 
        !          2042:                     }
        !          2043:                     else
        !          2044:                     {
        !          2045:                         if ((sizDest.cx >= 64) ||
        !          2046:                             (sizDest.cx > sizDest.cy))
        !          2047:                         {
        !          2048:                             bCpyColorHorzCacheToScreen(ppdev, ps3Brush,
        !          2049:                                                        (PPOINT) pptlBrush,
        !          2050:                                                        &ptDest, &sizDest);
        !          2051:                         }
        !          2052:                         else
        !          2053:                         {
        !          2054:                             bColorVertCacheToScreen(ppdev, ps3Brush,
        !          2055:                                                     (PPOINT) pptlBrush,
        !          2056:                                                     &ptDest, &sizDest,
        !          2057:                                                     s3ForeRop, s3BackRop);
        !          2058:                         }
        !          2059:                     }
        !          2060:                 }
        !          2061:                 else
        !          2062:                 {
        !          2063:                     if (sizDest.cy > sizDest.cx)
        !          2064:                     {
        !          2065:                         if (ps3Brush->iBitmapFormat == BMF_1BPP)
        !          2066:                         {
        !          2067:                             bColorExpandVertCacheToScreen(ppdev, ps3Brush, zVert,
        !          2068:                                                           (PPOINT) pptlBrush,
        !          2069:                                                           &ptDest, &sizDest,
        !          2070:                                                           s3ForeRop, s3BackRop);
        !          2071:                         }
        !          2072:                         else
        !          2073:                         {
        !          2074:                             bColorVertCacheToScreen(ppdev, ps3Brush,
        !          2075:                                                     (PPOINT) pptlBrush,
        !          2076:                                                     &ptDest, &sizDest,
        !          2077:                                                     s3ForeRop, s3BackRop);
        !          2078:                         }
        !          2079:                     }
        !          2080:                     else
        !          2081:                     {
        !          2082:                         if (ps3Brush->iBitmapFormat == BMF_1BPP)
        !          2083:                         {
        !          2084:                             bColorExpandHorzCacheToScreen(ppdev, ps3Brush, zHorz,
        !          2085:                                                           (PPOINT) pptlBrush,
        !          2086:                                                           &ptDest, &sizDest,
        !          2087:                                                           s3ForeRop, s3BackRop);
        !          2088:                         }
        !          2089:                         else
        !          2090:                         {
        !          2091:                             bColorHorzCacheToScreen(ppdev, ps3Brush,
        !          2092:                                                     (PPOINT) pptlBrush,
        !          2093:                                                     &ptDest, &sizDest,
        !          2094:                                                     s3ForeRop, s3BackRop);
        !          2095:                         }
        !          2096: 
        !          2097:                     }
        !          2098:                 }
        !          2099:             }
        !          2100:         } while (bMore);
        !          2101: 
        !          2102:     }
        !          2103: 
        !          2104:     return (TRUE);
        !          2105: 
        !          2106: }
        !          2107: 
        !          2108: /*****************************************************************************
        !          2109:  * wXlateSrcRop3toS3Rop - Translate the Source to Dest Rop 3 to an S3 rop
        !          2110:  ****************************************************************************/
        !          2111: WORD wXlateSrcRop3toS3Rop(PPDEV pdev, WORD rop3)
        !          2112: {
        !          2113: WORD    s3Rop;
        !          2114: 
        !          2115:     switch (LOBYTE(rop3))
        !          2116:     {
        !          2117:         case 0xBB:                      // DSno
        !          2118:             s3Rop = SCREEN_OR_NOT_NEW;
        !          2119:             break;
        !          2120: 
        !          2121:         case 0x33:                      // Sn
        !          2122:             s3Rop = NOT_NEW;
        !          2123:             break;
        !          2124: 
        !          2125:         case 0x44:                      // SDna
        !          2126:             s3Rop = NOT_SCREEN_AND_NEW;
        !          2127:             break;
        !          2128: 
        !          2129:         case 0x66:                      // DSx
        !          2130:             s3Rop = SCREEN_XOR_NEW;
        !          2131:             break;
        !          2132: 
        !          2133:         case 0x77:                      // DSan
        !          2134:             s3Rop = NOT_SCREEN_OR_NOT_NEW;
        !          2135:             break;
        !          2136: 
        !          2137:         case 0x88:                      // DSa
        !          2138:             s3Rop = SCREEN_AND_NEW;
        !          2139:             break;
        !          2140: 
        !          2141:         case 0x99:                      // DSxn
        !          2142:             s3Rop = NOT_SCREEN_XOR_NEW;
        !          2143:             break;
        !          2144: 
        !          2145:         case 0xDD:                      // SDno
        !          2146:             s3Rop = NOT_SCREEN_OR_NEW;
        !          2147:             break;
        !          2148: 
        !          2149:         case 0xCC:                      // S
        !          2150:             s3Rop = OVERPAINT;
        !          2151:             break;
        !          2152: 
        !          2153:         case 0x11:                      // DSon
        !          2154:             s3Rop = NOT_SCREEN_AND_NOT_NEW;
        !          2155:             break;
        !          2156: 
        !          2157:         case 0x22:                      // DSna
        !          2158:             s3Rop = SCREEN_AND_NOT_NEW;
        !          2159:             break;
        !          2160: 
        !          2161:         case 0xEE:                      // SDo
        !          2162:             s3Rop = SCREEN_OR_NEW;
        !          2163:             break;
        !          2164: 
        !          2165:         default:
        !          2166:             s3Rop = 0;
        !          2167:             break;
        !          2168:     }
        !          2169: 
        !          2170:     return (s3Rop);
        !          2171: 
        !          2172: }
        !          2173: 
        !          2174: 
        !          2175: /*****************************************************************************
        !          2176:  * Translate the ROP4 to S3 rops.
        !          2177:  ****************************************************************************/
        !          2178: 
        !          2179: ROP4 bXlatePatRop4toS3Rop(
        !          2180:     PPDEV pdev,
        !          2181:     ROP4  rop4)
        !          2182: {
        !          2183:     WORD    s3Rop;
        !          2184:     ROP4    s3Rop4;
        !          2185: 
        !          2186:     switch (rop4 & 0xff)
        !          2187:     {
        !          2188:         case 0x00:                      // 0
        !          2189:             s3Rop = LOGICAL_0;
        !          2190:             break;
        !          2191: 
        !          2192:         case 0x05:                      // ~(P | D)
        !          2193:             s3Rop = NOT_SCREEN_AND_NOT_NEW;
        !          2194:             break;
        !          2195: 
        !          2196:         case 0x0A:                      // ~P & D
        !          2197:             s3Rop = SCREEN_AND_NOT_NEW;
        !          2198:             break;
        !          2199: 
        !          2200:         case 0x0F:                      // ~P
        !          2201:             s3Rop = NOT_NEW;
        !          2202:             break;
        !          2203: 
        !          2204:         case 0x50:                      // P & ~D
        !          2205:             s3Rop = NOT_SCREEN_AND_NEW;
        !          2206:             break;
        !          2207: 
        !          2208:         case 0x55:                      // ~D
        !          2209:             s3Rop = NOT_SCREEN;
        !          2210:             break;
        !          2211: 
        !          2212:         case 0x5A:                      // P ^ D
        !          2213:             s3Rop = SCREEN_XOR_NEW;
        !          2214:             break;
        !          2215: 
        !          2216:         case 0x5F:                      // ~(P & D)
        !          2217:             s3Rop = NOT_SCREEN_OR_NOT_NEW;
        !          2218:             break;
        !          2219: 
        !          2220:         case 0xA0:                      // P & D
        !          2221:             s3Rop = SCREEN_AND_NEW;
        !          2222:             break;
        !          2223: 
        !          2224:         case 0xA5:                      // ~(P ^ D)
        !          2225:             s3Rop = NOT_SCREEN_XOR_NEW;
        !          2226:             break;
        !          2227: 
        !          2228:         case 0xAA:                      // D
        !          2229:             s3Rop = LEAVE_ALONE;
        !          2230:             break;
        !          2231: 
        !          2232:         case 0xAF:                      // ~P | D
        !          2233:             s3Rop = SCREEN_OR_NOT_NEW;
        !          2234:             break;
        !          2235: 
        !          2236:         case 0xF0:                      // P
        !          2237:             s3Rop = OVERPAINT;
        !          2238:             break;
        !          2239: 
        !          2240:         case 0xF5:                      // P | ~D
        !          2241:             s3Rop = NOT_SCREEN_OR_NEW;
        !          2242:             break;
        !          2243: 
        !          2244:         case 0xFA:                      // P | D
        !          2245:             s3Rop = SCREEN_OR_NEW;
        !          2246:             break;
        !          2247: 
        !          2248:         case 0xFF:                      // 1
        !          2249:             s3Rop = LOGICAL_1;
        !          2250:             break;
        !          2251:     }
        !          2252: 
        !          2253:     s3Rop4 = s3Rop | (s3Rop << 8);
        !          2254: 
        !          2255:     return(s3Rop4);
        !          2256: }
        !          2257: 
        !          2258: /*****************************************************************************
        !          2259:  * Download the Color Brush to the Color brush cache in
        !          2260:  * graphics memory.
        !          2261:  ****************************************************************************/
        !          2262: BOOL bDownLoadBrushIntoColorCache(
        !          2263:     PPDEV      ppdev,
        !          2264:     PS3BRUSH   ps3Brush,
        !          2265:     PPOINT     ppt)
        !          2266: {
        !          2267:     WORD    Cmd;
        !          2268: 
        !          2269:     DISPDBG((3, "S3.DLL!bDownLoadBrushIntoColorCache - Entry\n"));
        !          2270: 
        !          2271:     // Down load the initial pattern image, the upper left 8 X 8 cell.
        !          2272: 
        !          2273:     Cmd = RECTANGLE_FILL | BUS_SIZE_8         | WAIT |
        !          2274:           DRAW           | DRAWING_DIR_TBLRXM | DIR_TYPE_XY |
        !          2275:           LAST_PIXEL_ON  | WRITE;
        !          2276: 
        !          2277:     // Setup the S3 chip.
        !          2278: 
        !          2279:     FIFOWAIT(FIFO_6_EMPTY);
        !          2280: 
        !          2281:     TEST_AND_SET_FRGD_MIX(SRC_CPU_DATA | OVERPAINT);
        !          2282:     OUTPW(MULTIFUNC_CNTL, (DATA_EXTENSION | ALL_ONES));
        !          2283: 
        !          2284:     OUTPW(CUR_X, ppt->x);
        !          2285:     OUTPW(CUR_Y, ppt->y);
        !          2286: 
        !          2287:     OUTPW(RECT_WIDTH, 7);
        !          2288:     OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | 7));
        !          2289: 
        !          2290:     GPWAIT();
        !          2291:     OUTPW(CMD, Cmd);
        !          2292: 
        !          2293:     // Now transfer the data from host memory to graphics memory.
        !          2294: 
        !          2295:     CHECK_DATA_READY;
        !          2296: 
        !          2297:     vDataPortOutB(ppdev, ps3Brush->ajPattern, 64);
        !          2298: 
        !          2299:     CHECK_DATA_COMPLETE;
        !          2300: 
        !          2301:     // Make the pattern double wide. Make copy of the pattern to the right
        !          2302:     // of the original pattern.
        !          2303: 
        !          2304:     Cmd  = BITBLT          | DRAW | DIR_TYPE_XY | WRITE |
        !          2305:            MULTIPLE_PIXELS | DRAWING_DIR_TBLRXM;
        !          2306: 
        !          2307:     FIFOWAIT(FIFO_8_EMPTY);
        !          2308: 
        !          2309:     TEST_AND_SET_FRGD_MIX(SRC_DISPLAY_MEMORY | OVERPAINT);
        !          2310: 
        !          2311:     OUTPW(MULTIFUNC_CNTL, (DATA_EXTENSION | ALL_ONES));
        !          2312: 
        !          2313:     OUTPW(CUR_X,  ppt->x);
        !          2314:     OUTPW(CUR_Y,  ppt->y);
        !          2315:     OUTPW(DEST_X, ppt->x + 8);
        !          2316:     OUTPW(DEST_Y, ppt->y);
        !          2317: 
        !          2318:     OUTPW(CMD, Cmd);
        !          2319: 
        !          2320:     // Make the pattern double high. Make a copy of the double pattern
        !          2321:     // pattern below the original one.
        !          2322: 
        !          2323:     FIFOWAIT(FIFO_6_EMPTY);
        !          2324: 
        !          2325:     OUTPW(RECT_WIDTH, 15);
        !          2326: 
        !          2327:     OUTPW(CUR_X,  ppt->x);
        !          2328:     OUTPW(CUR_Y,  ppt->y);
        !          2329:     OUTPW(DEST_X, ppt->x);
        !          2330:     OUTPW(DEST_Y, ppt->y + 8);
        !          2331: 
        !          2332:     OUTPW(CMD, Cmd);
        !          2333: 
        !          2334:     return(TRUE);
        !          2335: }
        !          2336: 
        !          2337: 
        !          2338: 
        !          2339: /*****************************************************************************
        !          2340:  * Download the Monochrome Brush to the Monochrome brush cache in
        !          2341:  * graphics memory.
        !          2342:  ****************************************************************************/
        !          2343: BOOL bDownLoadBrushIntoMonoCache(
        !          2344:     PPDEV      ppdev,
        !          2345:     PS3BRUSH   p3Brush,
        !          2346:     PXYZPOINT  pxyzPt)
        !          2347: {
        !          2348:     WORD    Cmd;
        !          2349:     INT     i;
        !          2350:     BYTE    ajPattern[8];
        !          2351: 
        !          2352:     DISPDBG((3, "S3.DLL!bDownLoadBrushIntoMonoCache - Entry\n"));
        !          2353: 
        !          2354:     // Compress the dword aligned pattern to a byte aligned pattern.
        !          2355: 
        !          2356:     for (i = 0; i < 8; i++)
        !          2357:     {
        !          2358:         ajPattern[i] = p3Brush->ajPattern[i * p3Brush->lDeltaPattern];
        !          2359:     }
        !          2360: 
        !          2361:     // Down load the initial pattern image, the upper left 8 X 8 cell.
        !          2362: 
        !          2363:     Cmd = RECTANGLE_FILL | BUS_SIZE_8         | WAIT |
        !          2364:           DRAW           | DRAWING_DIR_TBLRXM | DIR_TYPE_XY |
        !          2365:           LAST_PIXEL_ON  | MULTIPLE_PIXELS    | WRITE;
        !          2366: 
        !          2367:     // Setup the S3 chip.
        !          2368: 
        !          2369:     FIFOWAIT(FIFO_8_EMPTY);
        !          2370: 
        !          2371:     TEST_AND_SET_FRGD_MIX(LOGICAL_1);
        !          2372:     TEST_AND_SET_BKGD_MIX(LOGICAL_0);
        !          2373: 
        !          2374:     TEST_AND_SET_WRT_MASK(LOWORD(pxyzPt->z));
        !          2375: 
        !          2376:     OUTPW(CUR_X, pxyzPt->x);
        !          2377:     OUTPW(CUR_Y, pxyzPt->y);
        !          2378: 
        !          2379:     OUTPW(MULTIFUNC_CNTL, (DATA_EXTENSION | CPU_DATA));
        !          2380:     OUTPW(RECT_WIDTH, 7);
        !          2381:     OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | 7));
        !          2382: 
        !          2383:     GPWAIT();
        !          2384:     OUTPW(CMD, Cmd);
        !          2385: 
        !          2386:     // Now transfer the data from host memory to graphics memory.
        !          2387: 
        !          2388:     CHECK_DATA_READY;
        !          2389: 
        !          2390:     vDataPortOutB(ppdev, ajPattern, 8);
        !          2391: 
        !          2392:     CHECK_DATA_COMPLETE;
        !          2393: 
        !          2394:     // Make the pattern double wide. Make copy of the pattern to the right
        !          2395:     // of the original pattern.
        !          2396: 
        !          2397:     Cmd  = BITBLT          | DRAW | DIR_TYPE_XY | WRITE |
        !          2398:            MULTIPLE_PIXELS | DRAWING_DIR_TBLRXM;
        !          2399: 
        !          2400:     FIFOWAIT(FIFO_8_EMPTY);
        !          2401: 
        !          2402:     TEST_AND_SET_RD_MASK (LOWORD(pxyzPt->z));
        !          2403:     TEST_AND_SET_FRGD_MIX(SRC_DISPLAY_MEMORY | OVERPAINT);
        !          2404: 
        !          2405:     OUTPW(MULTIFUNC_CNTL, (DATA_EXTENSION | ALL_ONES));
        !          2406: 
        !          2407:     OUTPW(CUR_X,  pxyzPt->x);
        !          2408:     OUTPW(CUR_Y,  pxyzPt->y);
        !          2409:     OUTPW(DEST_X, pxyzPt->x + 8);
        !          2410:     OUTPW(DEST_Y, pxyzPt->y);
        !          2411: 
        !          2412:     OUTPW(CMD, Cmd);
        !          2413: 
        !          2414:     // Make the pattern double high. Make a copy of the double pattern
        !          2415:     // pattern below the original one.
        !          2416: 
        !          2417:     FIFOWAIT(FIFO_6_EMPTY);
        !          2418: 
        !          2419:     OUTPW(RECT_WIDTH, 15);
        !          2420: 
        !          2421:     OUTPW(CUR_X,  pxyzPt->x);
        !          2422:     OUTPW(CUR_Y,  pxyzPt->y);
        !          2423:     OUTPW(DEST_X, pxyzPt->x);
        !          2424:     OUTPW(DEST_Y, pxyzPt->y + 8);
        !          2425: 
        !          2426:     OUTPW(CMD, Cmd);
        !          2427: 
        !          2428:     // Reset the read and write masks.
        !          2429: 
        !          2430:     FIFOWAIT(FIFO_2_EMPTY);
        !          2431: 
        !          2432:     TEST_AND_SET_WRT_MASK(0xff);
        !          2433:     TEST_AND_SET_RD_MASK(0xff);
        !          2434: 
        !          2435:     return(TRUE);
        !          2436: }
        !          2437: 
        !          2438: 
        !          2439: /*****************************************************************************
        !          2440:  * Expand the color brush in the vertical dimension.
        !          2441:  ****************************************************************************/
        !          2442: BOOL bExpandColorBrushIntoVertCache(
        !          2443:     PPDEV      ppdev,
        !          2444:     PPOINT     ppt)
        !          2445: {
        !          2446:     WORD    Cmd;
        !          2447: 
        !          2448:     DISPDBG((3, "S3.DLL!bExpandColorBrushIntoVertCache - Entry\n"));
        !          2449: 
        !          2450:     // Copy the cached double wide, double high pattern to the Horizontal
        !          2451:     // expansion cache area.
        !          2452: 
        !          2453:     Cmd  = BITBLT          | DRAW | DIR_TYPE_XY | WRITE |
        !          2454:            MULTIPLE_PIXELS | DRAWING_DIR_TBLRXM;
        !          2455: 
        !          2456:     FIFOWAIT(FIFO_1_EMPTY);
        !          2457: 
        !          2458:     TEST_AND_SET_FRGD_MIX(SRC_DISPLAY_MEMORY | OVERPAINT);
        !          2459: 
        !          2460:     FIFOWAIT(FIFO_8_EMPTY);
        !          2461: 
        !          2462:     OUTPW(MULTIFUNC_CNTL, (DATA_EXTENSION | ALL_ONES));
        !          2463:     OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | 15));
        !          2464:     OUTPW(RECT_WIDTH, 15);
        !          2465: 
        !          2466:     OUTPW(CUR_X,  ppt->x);
        !          2467:     OUTPW(CUR_Y,  ppt->y);
        !          2468:     OUTPW(DEST_X, COLOR_VERT_EXPANSION_CACHE_X);
        !          2469:     OUTPW(DEST_Y, COLOR_VERT_EXPANSION_CACHE_Y);
        !          2470: 
        !          2471:     OUTPW(CMD, Cmd);
        !          2472: 
        !          2473:     // Now the rolling blit to fill all the way.
        !          2474: 
        !          2475:     FIFOWAIT(FIFO_6_EMPTY);
        !          2476: 
        !          2477:     OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | COLOR_VERT_EXPANSION_CACHE_CY - 17));
        !          2478: 
        !          2479:     OUTPW(CUR_X,  COLOR_VERT_EXPANSION_CACHE_X);
        !          2480:     OUTPW(CUR_Y,  COLOR_VERT_EXPANSION_CACHE_Y);
        !          2481:     OUTPW(DEST_X, COLOR_VERT_EXPANSION_CACHE_X);
        !          2482:     OUTPW(DEST_Y, COLOR_VERT_EXPANSION_CACHE_Y + 16);
        !          2483: 
        !          2484:     OUTPW(CMD, Cmd);
        !          2485: 
        !          2486:     return(TRUE);
        !          2487: 
        !          2488: }
        !          2489: 
        !          2490: 
        !          2491: 
        !          2492: /*****************************************************************************
        !          2493:  * Expand the monochrome brush in the vertical dimension.
        !          2494:  ****************************************************************************/
        !          2495: BOOL bExpandMonoBrushIntoVertCache(
        !          2496:     PPDEV      ppdev,
        !          2497:     PXYZPOINT  pxyzPt,
        !          2498:     INT        zVert)
        !          2499: {
        !          2500:     WORD    Cmd;
        !          2501: 
        !          2502:     DISPDBG((3, "S3.DLL!bExpandMonoBrushIntoVertCache - Entry\n"));
        !          2503: 
        !          2504:     // Copy the cached double wide, double high pattern to the Horizontal
        !          2505:     // expansion cache area.
        !          2506: 
        !          2507:     Cmd  = BITBLT          | DRAW | DIR_TYPE_XY | WRITE |
        !          2508:            MULTIPLE_PIXELS | DRAWING_DIR_TBLRXM;
        !          2509: 
        !          2510:     FIFOWAIT(FIFO_7_EMPTY);
        !          2511: 
        !          2512:     OUTPW(MULTIFUNC_CNTL, (DATA_EXTENSION | DISPLAY_MEMORY));
        !          2513: 
        !          2514:     TEST_AND_SET_FRGD_MIX(FOREGROUND_COLOR | OVERPAINT);
        !          2515:     TEST_AND_SET_FRGD_COLOR(0xff);
        !          2516:     TEST_AND_SET_BKGD_MIX(BACKGROUND_COLOR | OVERPAINT);
        !          2517:     SET_BKGD_COLOR(0);
        !          2518: 
        !          2519:     TEST_AND_SET_RD_MASK(LOWORD(pxyzPt->z));
        !          2520:     TEST_AND_SET_WRT_MASK(LOWORD(zVert));
        !          2521: 
        !          2522:     FIFOWAIT(FIFO_7_EMPTY);
        !          2523: 
        !          2524:     OUTPW(RECT_WIDTH, 15);
        !          2525:     OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | 15));
        !          2526: 
        !          2527:     OUTPW(CUR_X,  pxyzPt->x);
        !          2528:     OUTPW(CUR_Y,  pxyzPt->y);
        !          2529:     OUTPW(DEST_X, MONO_VERT_EXPANSION_CACHE_X);
        !          2530:     OUTPW(DEST_Y, MONO_VERT_EXPANSION_CACHE_Y);
        !          2531: 
        !          2532:     OUTPW(CMD, Cmd);
        !          2533: 
        !          2534:     // Now the rolling blit to fill all the way.
        !          2535: 
        !          2536:     FIFOWAIT(FIFO_7_EMPTY);
        !          2537: 
        !          2538:     TEST_AND_SET_RD_MASK(zVert);
        !          2539: 
        !          2540:     OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | MONO_VERT_EXPANSION_CACHE_CY - 17));
        !          2541: 
        !          2542:     OUTPW(CUR_X,  MONO_VERT_EXPANSION_CACHE_X);
        !          2543:     OUTPW(CUR_Y,  MONO_VERT_EXPANSION_CACHE_Y);
        !          2544:     OUTPW(DEST_X, MONO_VERT_EXPANSION_CACHE_X);
        !          2545:     OUTPW(DEST_Y, MONO_VERT_EXPANSION_CACHE_Y + 16);
        !          2546: 
        !          2547:     OUTPW(CMD, Cmd);
        !          2548: 
        !          2549:     // Now reset the read and write plan masks.
        !          2550: 
        !          2551:     FIFOWAIT(FIFO_2_EMPTY);
        !          2552: 
        !          2553:     TEST_AND_SET_WRT_MASK(0xff);
        !          2554:     TEST_AND_SET_RD_MASK(0xff);
        !          2555: 
        !          2556:     return(TRUE);
        !          2557: 
        !          2558: }
        !          2559: 
        !          2560: /*****************************************************************************
        !          2561:  * Expand the color brush in the horizontal dimension.
        !          2562:  ****************************************************************************/
        !          2563: BOOL bExpandColorBrushIntoHorzCache(
        !          2564:     PPDEV      ppdev,
        !          2565:     PPOINT     ppt)
        !          2566: {
        !          2567:     WORD    Cmd;
        !          2568: 
        !          2569:     DISPDBG((3, "S3.DLL!bExpandColorBrushIntoHorzCache - Entry\n"));
        !          2570: 
        !          2571:     // Copy the cached double wide, double high pattern to the Horizontal
        !          2572:     // expansion cache area.
        !          2573: 
        !          2574:     Cmd  = BITBLT          | DRAW | DIR_TYPE_XY | WRITE |
        !          2575:            MULTIPLE_PIXELS | DRAWING_DIR_TBLRXM;
        !          2576: 
        !          2577:     FIFOWAIT(FIFO_1_EMPTY);
        !          2578: 
        !          2579:     TEST_AND_SET_FRGD_MIX(SRC_DISPLAY_MEMORY | OVERPAINT);
        !          2580: 
        !          2581:     FIFOWAIT(FIFO_8_EMPTY);
        !          2582: 
        !          2583:     OUTPW(MULTIFUNC_CNTL, (DATA_EXTENSION | ALL_ONES));
        !          2584:     OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | 15));
        !          2585:     OUTPW(RECT_WIDTH, 15);
        !          2586: 
        !          2587:     OUTPW(CUR_X,  ppt->x);
        !          2588:     OUTPW(CUR_Y,  ppt->y);
        !          2589:     OUTPW(DEST_X, COLOR_HORZ_EXPANSION_CACHE_X);
        !          2590:     OUTPW(DEST_Y, COLOR_HORZ_EXPANSION_CACHE_Y);
        !          2591: 
        !          2592:     OUTPW(CMD, Cmd);
        !          2593: 
        !          2594:     // Expand the 16 X 16 double wide, double high.
        !          2595:     // First to a 32 X 16
        !          2596: 
        !          2597:     FIFOWAIT(FIFO_5_EMPTY);
        !          2598: 
        !          2599:     OUTPW(CUR_X,  COLOR_HORZ_EXPANSION_CACHE_X);
        !          2600:     OUTPW(CUR_Y,  COLOR_HORZ_EXPANSION_CACHE_Y);
        !          2601:     OUTPW(DEST_X, COLOR_HORZ_EXPANSION_CACHE_X + 16);
        !          2602:     OUTPW(DEST_Y, COLOR_HORZ_EXPANSION_CACHE_Y);
        !          2603: 
        !          2604:     OUTPW(CMD, Cmd);
        !          2605: 
        !          2606:     // Now 64 X 16
        !          2607: 
        !          2608:     FIFOWAIT(FIFO_6_EMPTY);
        !          2609: 
        !          2610:     OUTPW(RECT_WIDTH, 31);
        !          2611: 
        !          2612:     OUTPW(CUR_X,  COLOR_HORZ_EXPANSION_CACHE_X);
        !          2613:     OUTPW(CUR_Y,  COLOR_HORZ_EXPANSION_CACHE_Y);
        !          2614:     OUTPW(DEST_X, COLOR_HORZ_EXPANSION_CACHE_X + 32);
        !          2615:     OUTPW(DEST_Y, COLOR_HORZ_EXPANSION_CACHE_Y);
        !          2616: 
        !          2617:     OUTPW(CMD, Cmd);
        !          2618: 
        !          2619:     // Now the rolling blit to fill all the way to 512 pels.
        !          2620: 
        !          2621:     FIFOWAIT(FIFO_7_EMPTY);
        !          2622: 
        !          2623:     OUTPW(RECT_WIDTH, COLOR_HORZ_EXPANSION_CACHE_CX - 65);
        !          2624: 
        !          2625:     OUTPW(CUR_X,  COLOR_HORZ_EXPANSION_CACHE_X);
        !          2626:     OUTPW(CUR_Y,  COLOR_HORZ_EXPANSION_CACHE_Y);
        !          2627:     OUTPW(DEST_X, COLOR_HORZ_EXPANSION_CACHE_X + 64);
        !          2628:     OUTPW(DEST_Y, COLOR_HORZ_EXPANSION_CACHE_Y);
        !          2629: 
        !          2630:     OUTPW(CMD, Cmd);
        !          2631: 
        !          2632:     return(TRUE);
        !          2633: }
        !          2634: 
        !          2635: 
        !          2636: 
        !          2637: 
        !          2638: /*****************************************************************************
        !          2639:  * Expand the monochrome brush in the horizontal dimension.
        !          2640:  ****************************************************************************/
        !          2641: BOOL bExpandMonoBrushIntoHorzCache(
        !          2642:     PPDEV      ppdev,
        !          2643:     PXYZPOINT  pxyzPt,
        !          2644:     INT        zHorz)
        !          2645: {
        !          2646:     WORD    Cmd;
        !          2647: 
        !          2648:     DISPDBG((3, "S3.DLL!bExpandMonoBrushIntoHorzCache - Entry\n"));
        !          2649: 
        !          2650:     // Copy the cached double wide, double high pattern to the Horizontal
        !          2651:     // expansion cache area.
        !          2652: 
        !          2653:     Cmd  = BITBLT          | DRAW | DIR_TYPE_XY | WRITE |
        !          2654:            MULTIPLE_PIXELS | DRAWING_DIR_TBLRXM;
        !          2655: 
        !          2656:     FIFOWAIT(FIFO_7_EMPTY);
        !          2657: 
        !          2658:     OUTPW(MULTIFUNC_CNTL, (DATA_EXTENSION | DISPLAY_MEMORY));
        !          2659: 
        !          2660:     TEST_AND_SET_FRGD_MIX(FOREGROUND_COLOR | OVERPAINT);
        !          2661:     TEST_AND_SET_FRGD_COLOR(0xff);
        !          2662:     TEST_AND_SET_BKGD_MIX(BACKGROUND_COLOR | OVERPAINT);
        !          2663:     SET_BKGD_COLOR(0);
        !          2664: 
        !          2665:     TEST_AND_SET_RD_MASK(LOWORD(pxyzPt->z));
        !          2666:     TEST_AND_SET_WRT_MASK(LOWORD(zHorz));
        !          2667: 
        !          2668:     FIFOWAIT(FIFO_7_EMPTY);
        !          2669: 
        !          2670:     OUTPW(RECT_WIDTH, 15);
        !          2671:     OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | 15));
        !          2672: 
        !          2673:     OUTPW(CUR_X,  pxyzPt->x);
        !          2674:     OUTPW(CUR_Y,  pxyzPt->y);
        !          2675:     OUTPW(DEST_X, MONO_HORZ_EXPANSION_CACHE_X);
        !          2676:     OUTPW(DEST_Y, MONO_HORZ_EXPANSION_CACHE_Y);
        !          2677: 
        !          2678:     OUTPW(CMD, Cmd);
        !          2679: 
        !          2680:     // Expand the 16 X 16 double wide, double high.
        !          2681:     // First to a 32 X 16
        !          2682: 
        !          2683:     FIFOWAIT(FIFO_7_EMPTY);
        !          2684: 
        !          2685:     TEST_AND_SET_RD_MASK(LOWORD(zHorz));
        !          2686: 
        !          2687:     OUTPW(RECT_WIDTH, 15);
        !          2688: 
        !          2689:     OUTPW(CUR_X,  MONO_HORZ_EXPANSION_CACHE_X);
        !          2690:     OUTPW(CUR_Y,  MONO_HORZ_EXPANSION_CACHE_Y);
        !          2691:     OUTPW(DEST_X, MONO_HORZ_EXPANSION_CACHE_X + 16);
        !          2692:     OUTPW(DEST_Y, MONO_HORZ_EXPANSION_CACHE_Y);
        !          2693: 
        !          2694:     OUTPW(CMD, Cmd);
        !          2695: 
        !          2696:     // Now 64 X 16
        !          2697: 
        !          2698:     FIFOWAIT(FIFO_6_EMPTY);
        !          2699: 
        !          2700:     OUTPW(RECT_WIDTH, 31);
        !          2701: 
        !          2702:     OUTPW(CUR_X,  MONO_HORZ_EXPANSION_CACHE_X);
        !          2703:     OUTPW(CUR_Y,  MONO_HORZ_EXPANSION_CACHE_Y);
        !          2704:     OUTPW(DEST_X, MONO_HORZ_EXPANSION_CACHE_X + 32);
        !          2705:     OUTPW(DEST_Y, MONO_HORZ_EXPANSION_CACHE_Y);
        !          2706: 
        !          2707:     OUTPW(CMD, Cmd);
        !          2708: 
        !          2709:     // Now the rolling blit to fill all the way to 512 pels.
        !          2710: 
        !          2711:     FIFOWAIT(FIFO_7_EMPTY);
        !          2712: 
        !          2713:     OUTPW(RECT_WIDTH, MONO_HORZ_EXPANSION_CACHE_CX - 65);
        !          2714: 
        !          2715:     OUTPW(CUR_X,  MONO_HORZ_EXPANSION_CACHE_X);
        !          2716:     OUTPW(CUR_Y,  MONO_HORZ_EXPANSION_CACHE_Y);
        !          2717:     OUTPW(DEST_X, MONO_HORZ_EXPANSION_CACHE_X + 64);
        !          2718:     OUTPW(DEST_Y, MONO_HORZ_EXPANSION_CACHE_Y);
        !          2719: 
        !          2720:     OUTPW(CMD, Cmd);
        !          2721: 
        !          2722:     // Now reset the read and write plan masks.
        !          2723: 
        !          2724:     FIFOWAIT(FIFO_2_EMPTY);
        !          2725: 
        !          2726:     TEST_AND_SET_WRT_MASK(0xff);
        !          2727:     TEST_AND_SET_RD_MASK(0xff);
        !          2728: 
        !          2729:     return(TRUE);
        !          2730: }
        !          2731: 
        !          2732: 
        !          2733: /*****************************************************************************
        !          2734:  * Color brush in the Vertical Cache to the screen.
        !          2735:  ****************************************************************************/
        !          2736: BOOL bColorVertCacheToScreen(
        !          2737:     PPDEV       ppdev,
        !          2738:     PS3BRUSH    ps3Brush,
        !          2739:     PPOINT      pptBrushOrg,
        !          2740:     PPOINT      pptDest,
        !          2741:     PSIZE       psizDest,
        !          2742:     WORD        s3ForeRop,
        !          2743:     WORD        s3BackRop)
        !          2744: {
        !          2745:     WORD    Cmd;
        !          2746:     INT     ixBlits, ixLast,
        !          2747:             iyFirst, iyBlits, iyLast,
        !          2748:             xOffset, yOffset,
        !          2749:             i, j;
        !          2750: 
        !          2751:     DISPDBG((3, "S3.DLL!bColorVertCacheToScreen - Entry\n"));
        !          2752: 
        !          2753:     // Take into account the pptBrushOrg.
        !          2754: 
        !          2755:     xOffset = pptDest->x - pptBrushOrg->x;
        !          2756:     yOffset = pptDest->y - pptBrushOrg->y;
        !          2757: 
        !          2758:     if (xOffset < 0)
        !          2759:         xOffset  = 8 - (-xOffset % 8);
        !          2760:     else
        !          2761:         xOffset %= 8;
        !          2762: 
        !          2763:     if (yOffset < 0)
        !          2764:         yOffset  = 8 - (-yOffset % 8);
        !          2765:     else
        !          2766:         yOffset %= 8;
        !          2767: 
        !          2768:     // Color Expand the monochrome vertical cache to the screen.
        !          2769:     // This is done in a loop to handle the general case ROPs.
        !          2770: 
        !          2771:     if (psizDest->cy < 8 - yOffset)
        !          2772:     {
        !          2773:         iyFirst = psizDest->cy;
        !          2774:         iyBlits = 0;
        !          2775:         iyLast  = 0;
        !          2776: 
        !          2777:     }
        !          2778:     else if (psizDest->cy - yOffset < COLOR_VERT_EXPANSION_CACHE_CY - 8)
        !          2779:     {
        !          2780:         iyFirst = 8 - yOffset;
        !          2781:         iyBlits = 0;
        !          2782:         iyLast  = psizDest->cy - iyFirst;
        !          2783:     }
        !          2784:     else
        !          2785:     {
        !          2786:         iyFirst = 8 - yOffset;
        !          2787:         iyBlits = (psizDest->cy - iyFirst) / (COLOR_VERT_EXPANSION_CACHE_CY - 8);
        !          2788:         iyLast  = (psizDest->cy - iyFirst) % (COLOR_VERT_EXPANSION_CACHE_CY - 8);
        !          2789:     }
        !          2790: 
        !          2791:     ixBlits = psizDest->cx / 8;
        !          2792:     ixLast  = psizDest->cx % 8;
        !          2793: 
        !          2794:     Cmd  = BITBLT         | DRAW | DIR_TYPE_XY | WRITE |
        !          2795:            MULTIPLE_PIXELS| DRAWING_DIR_TBLRXM;
        !          2796: 
        !          2797:     FIFOWAIT(FIFO_4_EMPTY);
        !          2798: 
        !          2799:     TEST_AND_SET_FRGD_MIX(SRC_DISPLAY_MEMORY | s3ForeRop);
        !          2800:     OUTPW(MULTIFUNC_CNTL, (DATA_EXTENSION | ALL_ONES));
        !          2801:     OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | 7));
        !          2802:     OUTPW(RECT_WIDTH, 7);
        !          2803: 
        !          2804:     for(i = 0; i < ixBlits; i++)
        !          2805:     {
        !          2806:         ASSERTS3(((pptDest->x + (i * 8) + 7) < (INT) ppdev->cxScreen),
        !          2807:                   "S3.DLL!bColorVertCacheToScreen - Blit Operation over right edge (1)\n");
        !          2808: 
        !          2809:         if (iyFirst != 0)
        !          2810:         {
        !          2811:             FIFOWAIT(FIFO_6_EMPTY);
        !          2812: 
        !          2813:             OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | iyFirst - 1));
        !          2814: 
        !          2815:             OUTPW(CUR_X,  COLOR_VERT_EXPANSION_CACHE_X + xOffset);
        !          2816:             OUTPW(CUR_Y,  COLOR_VERT_EXPANSION_CACHE_Y + yOffset);
        !          2817:             OUTPW(DEST_X, pptDest->x + (i * 8));
        !          2818:             OUTPW(DEST_Y, pptDest->y);
        !          2819: 
        !          2820:             OUTPW(CMD, Cmd);
        !          2821:         }
        !          2822: 
        !          2823:         if (iyBlits != 0)
        !          2824:         {
        !          2825:             FIFOWAIT(FIFO_1_EMPTY);
        !          2826:             OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | (COLOR_VERT_EXPANSION_CACHE_CY - 8) - 1));
        !          2827:         }
        !          2828: 
        !          2829:         for (j = 0; j <iyBlits; j++)
        !          2830:         {
        !          2831:             FIFOWAIT(FIFO_5_EMPTY);
        !          2832: 
        !          2833:             OUTPW(CUR_X,  COLOR_VERT_EXPANSION_CACHE_X + xOffset);
        !          2834:             OUTPW(CUR_Y,  COLOR_VERT_EXPANSION_CACHE_Y);
        !          2835:             OUTPW(DEST_X, pptDest->x + (i * 8));
        !          2836:             OUTPW(DEST_Y, pptDest->y + iyFirst +
        !          2837:                           (j * (COLOR_VERT_EXPANSION_CACHE_CY - 8)));
        !          2838: 
        !          2839:             OUTPW(CMD, Cmd);
        !          2840:         }
        !          2841: 
        !          2842:         if (iyLast != 0)
        !          2843:         {
        !          2844:             FIFOWAIT(FIFO_6_EMPTY);
        !          2845: 
        !          2846:             OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | iyLast - 1));
        !          2847: 
        !          2848:             OUTPW(CUR_X,  COLOR_VERT_EXPANSION_CACHE_X + xOffset);
        !          2849:             OUTPW(CUR_Y,  COLOR_VERT_EXPANSION_CACHE_Y);
        !          2850:             OUTPW(DEST_X, pptDest->x + (i * 8));
        !          2851:             OUTPW(DEST_Y, pptDest->y + iyFirst +
        !          2852:                           (iyBlits * (COLOR_VERT_EXPANSION_CACHE_CY - 8)));
        !          2853: 
        !          2854:             OUTPW(CMD, Cmd);
        !          2855:         }
        !          2856:     }
        !          2857: 
        !          2858:     if (ixLast != 0)
        !          2859:     {
        !          2860:         FIFOWAIT(FIFO_1_EMPTY);
        !          2861:         OUTPW(RECT_WIDTH, ixLast - 1);
        !          2862: 
        !          2863:         ASSERTS3(((pptDest->x + (ixBlits * 8) + (ixLast - 1)) < (INT) ppdev->cxScreen),
        !          2864:                   "S3.DLL!bColorVertCacheToScreen - Blit Operation over right edge (2)\n");
        !          2865: 
        !          2866:         if (iyFirst != 0)
        !          2867:         {
        !          2868:             FIFOWAIT(FIFO_6_EMPTY);
        !          2869: 
        !          2870:             OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | iyFirst - 1));
        !          2871: 
        !          2872:             OUTPW(CUR_X,  COLOR_VERT_EXPANSION_CACHE_X + xOffset);
        !          2873:             OUTPW(CUR_Y,  COLOR_VERT_EXPANSION_CACHE_Y + yOffset);
        !          2874:             OUTPW(DEST_X, pptDest->x + (ixBlits * 8));
        !          2875:             OUTPW(DEST_Y, pptDest->y);
        !          2876: 
        !          2877:             OUTPW(CMD, Cmd);
        !          2878:         }
        !          2879: 
        !          2880:         if (iyBlits != 0)
        !          2881:         {
        !          2882:             FIFOWAIT(FIFO_1_EMPTY);
        !          2883:             OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | (COLOR_VERT_EXPANSION_CACHE_CY - 8) - 1));
        !          2884:         }
        !          2885: 
        !          2886:         for (j = 0; j <iyBlits; j++)
        !          2887:         {
        !          2888:             FIFOWAIT(FIFO_5_EMPTY);
        !          2889: 
        !          2890:             OUTPW(CUR_X,  COLOR_VERT_EXPANSION_CACHE_X + xOffset);
        !          2891:             OUTPW(CUR_Y,  COLOR_VERT_EXPANSION_CACHE_Y);
        !          2892:             OUTPW(DEST_X, pptDest->x + (ixBlits * 8));
        !          2893:             OUTPW(DEST_Y, pptDest->y + iyFirst +
        !          2894:                           (j * (COLOR_VERT_EXPANSION_CACHE_CY - 8)));
        !          2895: 
        !          2896:             OUTPW(CMD, Cmd);
        !          2897:         }
        !          2898: 
        !          2899:         if (iyLast != 0)
        !          2900:         {
        !          2901:             FIFOWAIT(FIFO_6_EMPTY);
        !          2902: 
        !          2903:             OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | iyLast - 1));
        !          2904: 
        !          2905:             OUTPW(CUR_X,  COLOR_VERT_EXPANSION_CACHE_X + xOffset);
        !          2906:             OUTPW(CUR_Y,  COLOR_VERT_EXPANSION_CACHE_Y);
        !          2907:             OUTPW(DEST_X, pptDest->x + (ixBlits * 8));
        !          2908:             OUTPW(DEST_Y, pptDest->y + iyFirst +
        !          2909:                           (iyBlits * (COLOR_VERT_EXPANSION_CACHE_CY - 8)));
        !          2910: 
        !          2911:             OUTPW(CMD, Cmd);
        !          2912:         }
        !          2913:     }
        !          2914: 
        !          2915:     return(TRUE);
        !          2916: }
        !          2917: 
        !          2918: /*****************************************************************************
        !          2919:  * Color expand the monochrome brush in the Vertical Cache to the screen.
        !          2920:  ****************************************************************************/
        !          2921: BOOL bColorExpandVertCacheToScreen(
        !          2922:     PPDEV       ppdev,
        !          2923:     PS3BRUSH    ps3Brush,
        !          2924:     INT         zVert,
        !          2925:     PPOINT      pptBrushOrg,
        !          2926:     PPOINT      pptDest,
        !          2927:     PSIZE       psizDest,
        !          2928:     WORD        s3ForeRop,
        !          2929:     WORD        s3BackRop)
        !          2930: {
        !          2931:     WORD    Cmd;
        !          2932:     INT     ixBlits, ixLast,
        !          2933:             iyFirst, iyBlits, iyLast,
        !          2934:             xOffset, yOffset,
        !          2935:             i, j;
        !          2936: 
        !          2937:     DISPDBG((3, "S3.DLL!bColorExpandVertCacheToScreen - Entry\n"));
        !          2938: 
        !          2939:     // Take into account the pptBrushOrg.
        !          2940: 
        !          2941:     xOffset = pptDest->x - pptBrushOrg->x;
        !          2942:     yOffset = pptDest->y - pptBrushOrg->y;
        !          2943: 
        !          2944:     if (xOffset < 0)
        !          2945:         xOffset  = 8 - (-xOffset % 8);
        !          2946:     else
        !          2947:         xOffset %= 8;
        !          2948: 
        !          2949:     if (yOffset < 0)
        !          2950:         yOffset  = 8 - (-yOffset % 8);
        !          2951:     else
        !          2952:         yOffset %= 8;
        !          2953: 
        !          2954:     // Color Expand the monochrome vertical cache to the screen.
        !          2955:     // This is done in a loop to handle the general case ROPs.
        !          2956: 
        !          2957:     if (psizDest->cy < 8 - yOffset)
        !          2958:     {
        !          2959:         iyFirst = psizDest->cy;
        !          2960:         iyBlits = 0;
        !          2961:         iyLast  = 0;
        !          2962: 
        !          2963:     }
        !          2964:     else if (psizDest->cy - yOffset < MONO_VERT_EXPANSION_CACHE_CY - 8)
        !          2965:     {
        !          2966:         iyFirst = 8 - yOffset;
        !          2967:         iyBlits = 0;
        !          2968:         iyLast  = psizDest->cy - iyFirst;
        !          2969:     }
        !          2970:     else
        !          2971:     {
        !          2972:         iyFirst = 8 - yOffset;
        !          2973:         iyBlits = (psizDest->cy - iyFirst) / (MONO_VERT_EXPANSION_CACHE_CY - 8);
        !          2974:         iyLast  = (psizDest->cy - iyFirst) % (MONO_VERT_EXPANSION_CACHE_CY - 8);
        !          2975:     }
        !          2976: 
        !          2977:     ixBlits = psizDest->cx / 8;
        !          2978:     ixLast  = psizDest->cx % 8;
        !          2979: 
        !          2980:     Cmd  = BITBLT         | DRAW | DIR_TYPE_XY | WRITE |
        !          2981:            MULTIPLE_PIXELS| DRAWING_DIR_TBLRXM;
        !          2982: 
        !          2983:     FIFOWAIT(FIFO_7_EMPTY);
        !          2984: 
        !          2985:     TEST_AND_SET_RD_MASK(zVert);
        !          2986: 
        !          2987:     TEST_AND_SET_FRGD_MIX(FOREGROUND_COLOR | s3ForeRop);
        !          2988:     TEST_AND_SET_FRGD_COLOR(LOWORD(ps3Brush->ulForeColor));
        !          2989: 
        !          2990:     TEST_AND_SET_BKGD_MIX(BACKGROUND_COLOR | s3BackRop);
        !          2991:     SET_BKGD_COLOR(LOWORD(ps3Brush->ulBackColor));
        !          2992: 
        !          2993:     OUTPW(MULTIFUNC_CNTL, (DATA_EXTENSION | DISPLAY_MEMORY));
        !          2994: 
        !          2995:     OUTPW(RECT_WIDTH, 7);
        !          2996: 
        !          2997:     for(i = 0; i < ixBlits; i++)
        !          2998:     {
        !          2999:         ASSERTS3(((pptDest->x + (i * 8) + 7) < (INT) ppdev->cxScreen),
        !          3000:                   "S3.DLL!bColorExpandVertCacheToScreen - Blit Operation over right edge (1)\n");
        !          3001: 
        !          3002:         if (iyFirst != 0)
        !          3003:         {
        !          3004:             FIFOWAIT(FIFO_6_EMPTY);
        !          3005: 
        !          3006:             OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | iyFirst - 1));
        !          3007: 
        !          3008:             OUTPW(CUR_X,  MONO_VERT_EXPANSION_CACHE_X + xOffset);
        !          3009:             OUTPW(CUR_Y,  MONO_VERT_EXPANSION_CACHE_Y + yOffset);
        !          3010:             OUTPW(DEST_X, pptDest->x + (i * 8));
        !          3011:             OUTPW(DEST_Y, pptDest->y);
        !          3012: 
        !          3013:             OUTPW(CMD, Cmd);
        !          3014:         }
        !          3015: 
        !          3016:         if (iyBlits != 0)
        !          3017:         {
        !          3018:             FIFOWAIT(FIFO_1_EMPTY);
        !          3019:             OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | (MONO_VERT_EXPANSION_CACHE_CY - 8) - 1));
        !          3020:         }
        !          3021: 
        !          3022:         for (j = 0; j <iyBlits; j++)
        !          3023:         {
        !          3024:             FIFOWAIT(FIFO_5_EMPTY);
        !          3025: 
        !          3026:             OUTPW(CUR_X,  MONO_VERT_EXPANSION_CACHE_X + xOffset);
        !          3027:             OUTPW(CUR_Y,  MONO_VERT_EXPANSION_CACHE_Y);
        !          3028:             OUTPW(DEST_X, pptDest->x + (i * 8));
        !          3029:             OUTPW(DEST_Y, pptDest->y + iyFirst +
        !          3030:                           (j * (MONO_VERT_EXPANSION_CACHE_CY - 8)));
        !          3031: 
        !          3032:             OUTPW(CMD, Cmd);
        !          3033:         }
        !          3034: 
        !          3035:         if (iyLast != 0)
        !          3036:         {
        !          3037:             FIFOWAIT(FIFO_6_EMPTY);
        !          3038: 
        !          3039:             OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | iyLast - 1));
        !          3040: 
        !          3041:             OUTPW(CUR_X,  MONO_VERT_EXPANSION_CACHE_X + xOffset);
        !          3042:             OUTPW(CUR_Y,  MONO_VERT_EXPANSION_CACHE_Y);
        !          3043:             OUTPW(DEST_X, pptDest->x + (i * 8));
        !          3044:             OUTPW(DEST_Y, pptDest->y + iyFirst +
        !          3045:                           (iyBlits * (MONO_VERT_EXPANSION_CACHE_CY - 8)));
        !          3046: 
        !          3047:             OUTPW(CMD, Cmd);
        !          3048:         }
        !          3049:     }
        !          3050: 
        !          3051:     if (ixLast != 0)
        !          3052:     {
        !          3053:         FIFOWAIT(FIFO_1_EMPTY);
        !          3054:         OUTPW(RECT_WIDTH, ixLast - 1);
        !          3055: 
        !          3056:         ASSERTS3(((pptDest->x + (ixBlits * 8) + (ixLast - 1)) < (INT) ppdev->cxScreen),
        !          3057:                   "S3.DLL!bColorExpandVertCacheToScreen - Blit Operation over right edge (2)\n");
        !          3058: 
        !          3059:         if (iyFirst != 0)
        !          3060:         {
        !          3061:             FIFOWAIT(FIFO_6_EMPTY);
        !          3062: 
        !          3063:             OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | iyFirst - 1));
        !          3064: 
        !          3065:             OUTPW(CUR_X,  MONO_VERT_EXPANSION_CACHE_X + xOffset);
        !          3066:             OUTPW(CUR_Y,  MONO_VERT_EXPANSION_CACHE_Y + yOffset);
        !          3067:             OUTPW(DEST_X, pptDest->x + (ixBlits * 8));
        !          3068:             OUTPW(DEST_Y, pptDest->y);
        !          3069: 
        !          3070:             OUTPW(CMD, Cmd);
        !          3071:         }
        !          3072: 
        !          3073:         if (iyBlits != 0)
        !          3074:         {
        !          3075:             FIFOWAIT(FIFO_1_EMPTY);
        !          3076:             OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | (MONO_VERT_EXPANSION_CACHE_CY - 8) - 1));
        !          3077:         }
        !          3078: 
        !          3079:         for (j = 0; j <iyBlits; j++)
        !          3080:         {
        !          3081:             FIFOWAIT(FIFO_5_EMPTY);
        !          3082: 
        !          3083:             OUTPW(CUR_X,  MONO_VERT_EXPANSION_CACHE_X + xOffset);
        !          3084:             OUTPW(CUR_Y,  MONO_VERT_EXPANSION_CACHE_Y);
        !          3085:             OUTPW(DEST_X, pptDest->x + (ixBlits * 8));
        !          3086:             OUTPW(DEST_Y, pptDest->y + iyFirst +
        !          3087:                           (j * (MONO_VERT_EXPANSION_CACHE_CY - 8)));
        !          3088: 
        !          3089:             OUTPW(CMD, Cmd);
        !          3090:         }
        !          3091: 
        !          3092:         if (iyLast != 0)
        !          3093:         {
        !          3094:             FIFOWAIT(FIFO_6_EMPTY);
        !          3095: 
        !          3096:             OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | iyLast - 1));
        !          3097: 
        !          3098:             OUTPW(CUR_X,  MONO_VERT_EXPANSION_CACHE_X + xOffset);
        !          3099:             OUTPW(CUR_Y,  MONO_VERT_EXPANSION_CACHE_Y);
        !          3100:             OUTPW(DEST_X, pptDest->x + (ixBlits * 8));
        !          3101:             OUTPW(DEST_Y, pptDest->y + iyFirst +
        !          3102:                           (iyBlits * (MONO_VERT_EXPANSION_CACHE_CY - 8)));
        !          3103: 
        !          3104:             OUTPW(CMD, Cmd);
        !          3105:         }
        !          3106:     }
        !          3107: 
        !          3108:     // Reset the Read Mask
        !          3109: 
        !          3110:     FIFOWAIT(FIFO_2_EMPTY);
        !          3111: 
        !          3112:     TEST_AND_SET_WRT_MASK(0xff);
        !          3113:     TEST_AND_SET_RD_MASK(0xff);
        !          3114: 
        !          3115:     return(TRUE);
        !          3116: }
        !          3117: 
        !          3118: 
        !          3119: /*****************************************************************************
        !          3120:  * Color brush in the Hoizontal Cache to the screen.
        !          3121:  ****************************************************************************/
        !          3122: BOOL bColorHorzCacheToScreen(
        !          3123:     PPDEV       ppdev,
        !          3124:     PS3BRUSH    ps3Brush,
        !          3125:     PPOINT      pptBrushOrg,
        !          3126:     PPOINT      pptDest,
        !          3127:     PSIZE       psizDest,
        !          3128:     WORD        s3ForeRop,
        !          3129:     WORD        s3BackRop)
        !          3130: {
        !          3131:     WORD    Cmd;
        !          3132:     INT     xLeft, cxLeft, cxRight, ixBlits, i, j, x, cx,
        !          3133:             iyBlits, iyLast,
        !          3134:             xOffset, yOffset;
        !          3135: 
        !          3136:     DISPDBG((3, "S3.DLL!bColorHorzCacheToScreen - Entry\n"));
        !          3137: 
        !          3138:     // Take into account the pptBrushOrg.
        !          3139: 
        !          3140:     xOffset = pptDest->x - pptBrushOrg->x;
        !          3141:     yOffset = pptDest->y - pptBrushOrg->y;
        !          3142: 
        !          3143:     if (xOffset < 0)
        !          3144:         xOffset  = 8 - (-xOffset % 8);
        !          3145:     else
        !          3146:         xOffset %= 8;
        !          3147: 
        !          3148:     if (yOffset < 0)
        !          3149:         yOffset  = 8 - (-yOffset % 8);
        !          3150:     else
        !          3151:         yOffset %= 8;
        !          3152: 
        !          3153:     // Color Expand the monochrome horizontal cache to the screen.
        !          3154:     // This is done in a loop to handle the general case ROPs.
        !          3155: 
        !          3156:     xLeft  = pptDest->x;
        !          3157:     cxLeft = COLOR_HORZ_EXPANSION_CACHE_CX - xOffset;
        !          3158: 
        !          3159:     if ((cx = psizDest->cx - cxLeft) < 0)
        !          3160:     {
        !          3161:         cxLeft  = psizDest->cx;
        !          3162:         ixBlits = 0;
        !          3163:         cxRight = 0;
        !          3164:     }
        !          3165:     else
        !          3166:     {
        !          3167:         ixBlits = cx / COLOR_HORZ_EXPANSION_CACHE_CX;
        !          3168:         cxRight = cx % COLOR_HORZ_EXPANSION_CACHE_CX;
        !          3169:     }
        !          3170: 
        !          3171:     iyBlits = psizDest->cy / 8;
        !          3172:     iyLast  = psizDest->cy % 8;
        !          3173: 
        !          3174:     Cmd  = BITBLT         | DRAW | DIR_TYPE_XY | WRITE |
        !          3175:            MULTIPLE_PIXELS| DRAWING_DIR_TBLRXM;
        !          3176: 
        !          3177:     FIFOWAIT(FIFO_3_EMPTY);
        !          3178: 
        !          3179:     TEST_AND_SET_FRGD_MIX(SRC_DISPLAY_MEMORY | s3ForeRop);
        !          3180:     OUTPW(MULTIFUNC_CNTL, (DATA_EXTENSION | ALL_ONES));
        !          3181:     OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | 7));
        !          3182: 
        !          3183:     for (i = 0; i < iyBlits; i++)
        !          3184:     {
        !          3185:         ASSERTS3(((pptDest->x + (cxLeft - 1)) < (INT) ppdev->cxScreen),
        !          3186:                   "S3.DLL!bColorHorzCacheToScreen - Blit Operation over right edge (1)\n");
        !          3187: 
        !          3188:         FIFOWAIT(FIFO_6_EMPTY);
        !          3189: 
        !          3190:         OUTPW(RECT_WIDTH, cxLeft - 1);
        !          3191: 
        !          3192:         OUTPW(CUR_X,  COLOR_HORZ_EXPANSION_CACHE_X + xOffset);
        !          3193:         OUTPW(CUR_Y,  COLOR_HORZ_EXPANSION_CACHE_Y + yOffset);
        !          3194:         OUTPW(DEST_X, pptDest->x);
        !          3195:         OUTPW(DEST_Y, pptDest->y + (i * 8));
        !          3196: 
        !          3197:         OUTPW(CMD, Cmd);
        !          3198: 
        !          3199:         // If the the cxDest is wider than the cxHorzCache then fill in the
        !          3200:         // right side of the fill area.
        !          3201: 
        !          3202:         if (cx > 0)
        !          3203:         {
        !          3204:             FIFOWAIT(FIFO_1_EMPTY);
        !          3205:             OUTPW(RECT_WIDTH, COLOR_HORZ_EXPANSION_CACHE_CX - 1);
        !          3206: 
        !          3207:             for (j = 0; j < ixBlits; j++)
        !          3208:             {
        !          3209:                 x = pptDest->x + cxLeft + (j * COLOR_HORZ_EXPANSION_CACHE_CX);
        !          3210: 
        !          3211:                 ASSERTS3(((x + (COLOR_HORZ_EXPANSION_CACHE_CX - 1)) < (INT) ppdev->cxScreen),
        !          3212:                           "S3.DLL!bColorHorzCacheToScreen - Blit Operation over right edge (2)\n");
        !          3213: 
        !          3214:                 FIFOWAIT(FIFO_5_EMPTY);
        !          3215: 
        !          3216:                 OUTPW(CUR_X,  COLOR_HORZ_EXPANSION_CACHE_X);
        !          3217:                 OUTPW(CUR_Y,  COLOR_HORZ_EXPANSION_CACHE_Y + yOffset);
        !          3218:                 OUTPW(DEST_X, x);
        !          3219:                 OUTPW(DEST_Y, pptDest->y + (i * 8));
        !          3220: 
        !          3221:                 OUTPW(CMD, Cmd);
        !          3222:             }
        !          3223: 
        !          3224:             if (cxRight != 0)
        !          3225:             {
        !          3226:                 x = pptDest->x + cxLeft + (ixBlits * COLOR_HORZ_EXPANSION_CACHE_CX);
        !          3227: 
        !          3228:                 ASSERTS3(((x + (cxRight - 1)) < (INT) ppdev->cxScreen),
        !          3229:                           "S3.DLL!bColorHorzCacheToScreen - Blit Operation over right edge (3)\n");
        !          3230: 
        !          3231:                 FIFOWAIT(FIFO_6_EMPTY);
        !          3232: 
        !          3233:                 OUTPW(RECT_WIDTH, cxRight - 1);
        !          3234: 
        !          3235:                 OUTPW(CUR_X,  COLOR_HORZ_EXPANSION_CACHE_X);
        !          3236:                 OUTPW(CUR_Y,  COLOR_HORZ_EXPANSION_CACHE_Y + yOffset);
        !          3237:                 OUTPW(DEST_X, x);
        !          3238:                 OUTPW(DEST_Y, pptDest->y + (i * 8));
        !          3239: 
        !          3240:                 OUTPW(CMD, Cmd);
        !          3241:             }
        !          3242:         }
        !          3243:     }
        !          3244: 
        !          3245:     if (iyLast != 0)
        !          3246:     {
        !          3247:         ASSERTS3(((pptDest->x + (cxLeft - 1)) < (INT) ppdev->cxScreen),
        !          3248:                   "S3.DLL!bColorHorzCacheToScreen - Blit Operation over right edge (4)\n");
        !          3249: 
        !          3250:         FIFOWAIT(FIFO_7_EMPTY);
        !          3251: 
        !          3252:         OUTPW(RECT_WIDTH, cxLeft - 1);
        !          3253:         OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | iyLast - 1));
        !          3254: 
        !          3255:         OUTPW(CUR_X,  COLOR_HORZ_EXPANSION_CACHE_X + xOffset);
        !          3256:         OUTPW(CUR_Y,  COLOR_HORZ_EXPANSION_CACHE_Y + yOffset);
        !          3257:         OUTPW(DEST_X, pptDest->x);
        !          3258:         OUTPW(DEST_Y, pptDest->y + (iyBlits * 8));
        !          3259: 
        !          3260:         OUTPW(CMD, Cmd);
        !          3261: 
        !          3262:         // If the the cxDest is wider than the cxHorzCache then fill in the
        !          3263:         // right side of the fill area.
        !          3264: 
        !          3265:         if (cx > 0)
        !          3266:         {
        !          3267:             FIFOWAIT(FIFO_1_EMPTY);
        !          3268:             OUTPW(RECT_WIDTH, COLOR_HORZ_EXPANSION_CACHE_CX - 1);
        !          3269: 
        !          3270:             for (j = 0; j < ixBlits; j++)
        !          3271:             {
        !          3272:                 x = pptDest->x + cxLeft + (j * COLOR_HORZ_EXPANSION_CACHE_CX);
        !          3273: 
        !          3274:                 ASSERTS3(((x + (COLOR_HORZ_EXPANSION_CACHE_CX - 1)) < (INT) ppdev->cxScreen),
        !          3275:                           "S3.DLL!bColorHorzCacheToScreen - Blit Operation over right edge (5)\n");
        !          3276: 
        !          3277:                 FIFOWAIT(FIFO_5_EMPTY);
        !          3278: 
        !          3279:                 OUTPW(CUR_X,  COLOR_HORZ_EXPANSION_CACHE_X);
        !          3280:                 OUTPW(CUR_Y,  COLOR_HORZ_EXPANSION_CACHE_Y + yOffset);
        !          3281:                 OUTPW(DEST_X, x);
        !          3282:                 OUTPW(DEST_Y, pptDest->y + (iyBlits * 8));
        !          3283: 
        !          3284:                 OUTPW(CMD, Cmd);
        !          3285:             }
        !          3286: 
        !          3287:             if (cxRight != 0)
        !          3288:             {
        !          3289:                 x = pptDest->x + cxLeft + (ixBlits * COLOR_HORZ_EXPANSION_CACHE_CX);
        !          3290: 
        !          3291:                 ASSERTS3(((x + (cxRight - 1)) < (INT) ppdev->cxScreen),
        !          3292:                           "S3.DLL!bColorHorzCacheToScreen - Blit Operation over right edge (6)\n");
        !          3293: 
        !          3294:                 FIFOWAIT(FIFO_6_EMPTY);
        !          3295: 
        !          3296:                 OUTPW(RECT_WIDTH, cxRight - 1);
        !          3297: 
        !          3298:                 OUTPW(CUR_X,  COLOR_HORZ_EXPANSION_CACHE_X);
        !          3299:                 OUTPW(CUR_Y,  COLOR_HORZ_EXPANSION_CACHE_Y + yOffset);
        !          3300:                 OUTPW(DEST_X, x);
        !          3301:                 OUTPW(DEST_Y, pptDest->y + (iyBlits * 8));
        !          3302: 
        !          3303:                 OUTPW(CMD, Cmd);
        !          3304:             }
        !          3305:         }
        !          3306:     }
        !          3307: 
        !          3308:     return(TRUE);
        !          3309: }
        !          3310: 
        !          3311: /*****************************************************************************
        !          3312:  * Color expand the monochrome brush in the Hoizontal Cache to the screen.
        !          3313:  ****************************************************************************/
        !          3314: BOOL bColorExpandHorzCacheToScreen(
        !          3315:     PPDEV       ppdev,
        !          3316:     PS3BRUSH    ps3Brush,
        !          3317:     INT         zHorz,
        !          3318:     PPOINT      pptBrushOrg,
        !          3319:     PPOINT      pptDest,
        !          3320:     PSIZE       psizDest,
        !          3321:     WORD        s3ForeRop,
        !          3322:     WORD        s3BackRop)
        !          3323: {
        !          3324:     WORD    Cmd;
        !          3325:     INT     xLeft, cxLeft, xMiddle, cxMiddle, xRight, cxRight, i,
        !          3326:             iyBlits, iyLast,
        !          3327:             xOffset, yOffset;
        !          3328: 
        !          3329:     DISPDBG((3, "S3.DLL!bColorExpandHorzCacheToScreen - Entry\n"));
        !          3330: 
        !          3331:     // Take into account the pptBrushOrg.
        !          3332: 
        !          3333:     xOffset = pptDest->x - pptBrushOrg->x;
        !          3334:     yOffset = pptDest->y - pptBrushOrg->y;
        !          3335: 
        !          3336:     if (xOffset < 0)
        !          3337:         xOffset  = 8 - (-xOffset % 8);
        !          3338:     else
        !          3339:         xOffset %= 8;
        !          3340: 
        !          3341:     if (yOffset < 0)
        !          3342:         yOffset  = 8 - (-yOffset % 8);
        !          3343:     else
        !          3344:         yOffset %= 8;
        !          3345: 
        !          3346:     // Color Expand the monochrome horizontal cache to the screen.
        !          3347:     // This is done in a loop to handle the general case ROPs.
        !          3348: 
        !          3349:     xLeft  = pptDest->x;
        !          3350:     cxLeft = MONO_HORZ_EXPANSION_CACHE_CX - xOffset;
        !          3351: 
        !          3352:     if (psizDest->cx < cxLeft)
        !          3353:     {
        !          3354:         cxLeft  = psizDest->cx;
        !          3355:         xRight  = 0;
        !          3356:         cxRight = 0;
        !          3357:     }
        !          3358:     else
        !          3359:     {
        !          3360:         xRight  = pptDest->x + cxLeft;
        !          3361:         cxRight = psizDest->cx - cxLeft;
        !          3362:     }
        !          3363: 
        !          3364:     // This little hack is for 1280 mode.
        !          3365:     // Really the correct solution is to use the H/W support.
        !          3366: 
        !          3367:     if (cxRight > MONO_HORZ_EXPANSION_CACHE_CX)
        !          3368:     {
        !          3369:         xMiddle  = xRight;
        !          3370:         xRight  += MONO_HORZ_EXPANSION_CACHE_CX;
        !          3371:         cxMiddle = MONO_HORZ_EXPANSION_CACHE_CX;
        !          3372:         cxRight -= MONO_HORZ_EXPANSION_CACHE_CX;
        !          3373:     }
        !          3374:     else
        !          3375:     {
        !          3376:         xMiddle  = 0;
        !          3377:         cxMiddle = 0;
        !          3378:     }
        !          3379: 
        !          3380:     iyBlits = psizDest->cy / 8;
        !          3381:     iyLast  = psizDest->cy % 8;
        !          3382: 
        !          3383:     Cmd  = BITBLT         | DRAW | DIR_TYPE_XY | WRITE |
        !          3384:            MULTIPLE_PIXELS| DRAWING_DIR_TBLRXM;
        !          3385: 
        !          3386:     FIFOWAIT(FIFO_7_EMPTY);
        !          3387: 
        !          3388:     TEST_AND_SET_RD_MASK(zHorz);
        !          3389: 
        !          3390:     TEST_AND_SET_FRGD_MIX(FOREGROUND_COLOR | s3ForeRop);
        !          3391:     TEST_AND_SET_FRGD_COLOR(LOWORD(ps3Brush->ulForeColor));
        !          3392: 
        !          3393:     TEST_AND_SET_BKGD_MIX(BACKGROUND_COLOR | s3BackRop);
        !          3394:     SET_BKGD_COLOR(LOWORD(ps3Brush->ulBackColor));
        !          3395: 
        !          3396:     OUTPW(MULTIFUNC_CNTL, (DATA_EXTENSION | DISPLAY_MEMORY));
        !          3397: 
        !          3398:     OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | 7));
        !          3399: 
        !          3400:     for (i = 0; i < iyBlits; i++)
        !          3401:     {
        !          3402:         ASSERTS3(((pptDest->x + (cxLeft - 1)) < (INT) ppdev->cxScreen),
        !          3403:                   "S3.DLL!bColorExpandHorzCacheToScreen - Blit Operation over right edge (1)\n");
        !          3404: 
        !          3405:         FIFOWAIT(FIFO_6_EMPTY);
        !          3406: 
        !          3407:         OUTPW(RECT_WIDTH, cxLeft - 1);
        !          3408: 
        !          3409:         OUTPW(CUR_X,  MONO_HORZ_EXPANSION_CACHE_X + xOffset);
        !          3410:         OUTPW(CUR_Y,  MONO_HORZ_EXPANSION_CACHE_Y + yOffset);
        !          3411:         OUTPW(DEST_X, pptDest->x);
        !          3412:         OUTPW(DEST_Y, pptDest->y + (i * 8));
        !          3413: 
        !          3414:         OUTPW(CMD, Cmd);
        !          3415: 
        !          3416:         if (cxMiddle != 0)
        !          3417:         {
        !          3418:             ASSERTS3(((xMiddle + (cxMiddle - 1)) < (INT) ppdev->cxScreen),
        !          3419:                       "S3.DLL!bColorExpandHorzCacheToScreen - Blit Operation over right edge (2)\n");
        !          3420: 
        !          3421:             FIFOWAIT(FIFO_6_EMPTY);
        !          3422: 
        !          3423:             OUTPW(RECT_WIDTH, cxMiddle - 1);
        !          3424: 
        !          3425:             OUTPW(CUR_X,  MONO_HORZ_EXPANSION_CACHE_X);
        !          3426:             OUTPW(CUR_Y,  MONO_HORZ_EXPANSION_CACHE_Y + yOffset);
        !          3427:             OUTPW(DEST_X, xMiddle);
        !          3428:             OUTPW(DEST_Y, pptDest->y + (i * 8));
        !          3429: 
        !          3430:             OUTPW(CMD, Cmd);
        !          3431:         }
        !          3432: 
        !          3433:         // If the the cxDest is wider than the cxHorzCache then fill in the
        !          3434:         // right side of the fill area.
        !          3435: 
        !          3436:         if (cxRight != 0)
        !          3437:         {
        !          3438:             ASSERTS3(((xRight + (cxRight - 1)) < (INT) ppdev->cxScreen),
        !          3439:                       "S3.DLL!bColorExpandHorzCacheToScreen - Blit Operation over right edge (3)\n");
        !          3440: 
        !          3441:             FIFOWAIT(FIFO_6_EMPTY);
        !          3442: 
        !          3443:             OUTPW(RECT_WIDTH, cxRight - 1);
        !          3444: 
        !          3445:             OUTPW(CUR_X,  MONO_HORZ_EXPANSION_CACHE_X);
        !          3446:             OUTPW(CUR_Y,  MONO_HORZ_EXPANSION_CACHE_Y + yOffset);
        !          3447:             OUTPW(DEST_X, xRight);
        !          3448:             OUTPW(DEST_Y, pptDest->y + (i * 8));
        !          3449: 
        !          3450:             OUTPW(CMD, Cmd);
        !          3451:         }
        !          3452:     }
        !          3453: 
        !          3454:     if (iyLast != 0)
        !          3455:     {
        !          3456:         ASSERTS3(((pptDest->x + (cxLeft - 1)) < (INT) ppdev->cxScreen),
        !          3457:                   "S3.DLL!bColorExpandHorzCacheToScreen - Blit Operation over right edge (3)\n");
        !          3458: 
        !          3459:         FIFOWAIT(FIFO_7_EMPTY);
        !          3460: 
        !          3461:         OUTPW(RECT_WIDTH, cxLeft - 1);
        !          3462:         OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | iyLast - 1));
        !          3463: 
        !          3464:         OUTPW(CUR_X,  MONO_HORZ_EXPANSION_CACHE_X + xOffset);
        !          3465:         OUTPW(CUR_Y,  MONO_HORZ_EXPANSION_CACHE_Y + yOffset);
        !          3466:         OUTPW(DEST_X, pptDest->x);
        !          3467:         OUTPW(DEST_Y, pptDest->y + (iyBlits * 8));
        !          3468: 
        !          3469:         OUTPW(CMD, Cmd);
        !          3470: 
        !          3471:         if (cxMiddle != 0)
        !          3472:         {
        !          3473:             ASSERTS3(((xMiddle + (cxMiddle - 1)) < (INT) ppdev->cxScreen),
        !          3474:                       "S3.DLL!bColorExpandHorzCacheToScreen - Blit Operation over right edge (4)\n");
        !          3475: 
        !          3476:             FIFOWAIT(FIFO_6_EMPTY);
        !          3477: 
        !          3478:             OUTPW(RECT_WIDTH, cxMiddle - 1);
        !          3479: 
        !          3480:             OUTPW(CUR_X,  MONO_HORZ_EXPANSION_CACHE_X);
        !          3481:             OUTPW(CUR_Y,  MONO_HORZ_EXPANSION_CACHE_Y + yOffset);
        !          3482:             OUTPW(DEST_X, xMiddle);
        !          3483:             OUTPW(DEST_Y, pptDest->y + (iyBlits * 8));
        !          3484: 
        !          3485:             OUTPW(CMD, Cmd);
        !          3486:         }
        !          3487: 
        !          3488:         // If the the cxDest is wider than the cxHorzCache then fill in the
        !          3489:         // right side of the fill area.
        !          3490: 
        !          3491:         if (cxRight != 0)
        !          3492:         {
        !          3493:             ASSERTS3(((xRight + (cxRight - 1)) < (INT) ppdev->cxScreen),
        !          3494:                       "S3.DLL!bColorExpandHorzCacheToScreen - Blit Operation over right edge (4)\n");
        !          3495: 
        !          3496:             FIFOWAIT(FIFO_6_EMPTY);
        !          3497: 
        !          3498:             OUTPW(RECT_WIDTH, cxRight - 1);
        !          3499: 
        !          3500:             OUTPW(CUR_X,  MONO_HORZ_EXPANSION_CACHE_X);
        !          3501:             OUTPW(CUR_Y,  MONO_HORZ_EXPANSION_CACHE_Y + yOffset);
        !          3502:             OUTPW(DEST_X, xRight);
        !          3503:             OUTPW(DEST_Y, pptDest->y + (iyBlits * 8));
        !          3504: 
        !          3505:             OUTPW(CMD, Cmd);
        !          3506:         }
        !          3507:     }
        !          3508: 
        !          3509:     // Reset the Read Mask
        !          3510: 
        !          3511:     FIFOWAIT(FIFO_2_EMPTY);
        !          3512: 
        !          3513:     TEST_AND_SET_WRT_MASK(0xff);
        !          3514:     TEST_AND_SET_RD_MASK(0xff);
        !          3515: 
        !          3516:     return(TRUE);
        !          3517: }
        !          3518: 
        !          3519: 
        !          3520: /*****************************************************************************
        !          3521:  * Copy Optimized
        !          3522:  * Color brush in the Hoizontal Cache to the screen.
        !          3523:  ****************************************************************************/
        !          3524: BOOL bCpyColorHorzCacheToScreen(
        !          3525:     PPDEV       ppdev,
        !          3526:     PS3BRUSH    ps3Brush,
        !          3527:     PPOINT      pptBrushOrg,
        !          3528:     PPOINT      pptDest,
        !          3529:     PSIZE       psizDest)
        !          3530: {
        !          3531:     WORD    Cmd;
        !          3532:     INT     cx, cxLeft, ixBlits, ixLast, i,
        !          3533:             cy, x, xOffset, yOffset;
        !          3534: 
        !          3535:     DISPDBG((3, "S3.DLL!bCpyColorHorzCacheToScreen - Entry\n"));
        !          3536: 
        !          3537:     // Take into account the pptBrushOrg.
        !          3538: 
        !          3539:     xOffset = pptDest->x - pptBrushOrg->x;
        !          3540:     yOffset = pptDest->y - pptBrushOrg->y;
        !          3541: 
        !          3542:     if (xOffset < 0)
        !          3543:         xOffset  = 8 - (-xOffset % 8);
        !          3544:     else
        !          3545:         xOffset %= 8;
        !          3546: 
        !          3547:     if (yOffset < 0)
        !          3548:         yOffset  = 8 - (-yOffset % 8);
        !          3549:     else
        !          3550:         yOffset %= 8;
        !          3551: 
        !          3552:     // First Color Expand the monochrome horizontal cache to the screen.
        !          3553: 
        !          3554:     cxLeft = COLOR_HORZ_EXPANSION_CACHE_CX - xOffset;
        !          3555:     if (psizDest->cx < cxLeft)
        !          3556:         cxLeft = psizDest->cx;
        !          3557: 
        !          3558:     cy = 8;
        !          3559:     if (psizDest->cy < cy)
        !          3560:         cy = psizDest->cy;
        !          3561: 
        !          3562:     Cmd  = BITBLT         | DRAW | DIR_TYPE_XY | WRITE |
        !          3563:            MULTIPLE_PIXELS| DRAWING_DIR_TBLRXM;
        !          3564: 
        !          3565:     ASSERTS3(((pptDest->x + (cxLeft - 1)) < (INT) ppdev->cxScreen),
        !          3566:               "S3.DLL!bCpyColorHorzCacheToScreen - Blit Operation over right edge (1)\n");
        !          3567: 
        !          3568:     FIFOWAIT(FIFO_2_EMPTY);
        !          3569: 
        !          3570:     TEST_AND_SET_FRGD_MIX(SRC_DISPLAY_MEMORY | OVERPAINT);
        !          3571:     OUTPW(MULTIFUNC_CNTL, (DATA_EXTENSION | ALL_ONES));
        !          3572: 
        !          3573:     FIFOWAIT(FIFO_7_EMPTY);
        !          3574: 
        !          3575:     OUTPW(RECT_WIDTH, cxLeft - 1);
        !          3576:     OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | (cy - 1)));
        !          3577: 
        !          3578:     OUTPW(CUR_X,  COLOR_HORZ_EXPANSION_CACHE_X + xOffset);
        !          3579:     OUTPW(CUR_Y,  COLOR_HORZ_EXPANSION_CACHE_Y + yOffset);
        !          3580:     OUTPW(DEST_X, pptDest->x);
        !          3581:     OUTPW(DEST_Y, pptDest->y);
        !          3582: 
        !          3583:     OUTPW(CMD, Cmd);
        !          3584: 
        !          3585:     // If the the cxDest is wider than the cxHorzCache then fill in the
        !          3586:     // right side of the fill area.
        !          3587: 
        !          3588:     if ((cx = psizDest->cx - cxLeft) > 0)
        !          3589:     {
        !          3590:         ixBlits = cx / COLOR_HORZ_EXPANSION_CACHE_CX;
        !          3591:         ixLast  = cx % COLOR_HORZ_EXPANSION_CACHE_CX;
        !          3592: 
        !          3593:         FIFOWAIT(FIFO_1_EMPTY);
        !          3594:         OUTPW(RECT_WIDTH, COLOR_HORZ_EXPANSION_CACHE_CX - 1);
        !          3595: 
        !          3596:         for (i = 0; i < ixBlits; i++)
        !          3597:         {
        !          3598:             x = pptDest->x + cxLeft + (i * COLOR_HORZ_EXPANSION_CACHE_CX);
        !          3599: 
        !          3600:             ASSERTS3(((x + (COLOR_HORZ_EXPANSION_CACHE_CX - 1)) < (INT) ppdev->cxScreen),
        !          3601:                       "S3.DLL!bCpyColorHorzCacheToScreen - Blit Operation over right edge (2)\n");
        !          3602: 
        !          3603:             FIFOWAIT(FIFO_5_EMPTY);
        !          3604: 
        !          3605:             OUTPW(CUR_X,  COLOR_HORZ_EXPANSION_CACHE_X);
        !          3606:             OUTPW(CUR_Y,  COLOR_HORZ_EXPANSION_CACHE_Y + yOffset);
        !          3607:             OUTPW(DEST_X, x);
        !          3608:             OUTPW(DEST_Y, pptDest->y);
        !          3609: 
        !          3610:             OUTPW(CMD, Cmd);
        !          3611:         }
        !          3612: 
        !          3613:         if (ixLast != 0)
        !          3614:         {
        !          3615:             x = pptDest->x + cxLeft + (ixBlits * COLOR_HORZ_EXPANSION_CACHE_CX);
        !          3616: 
        !          3617:             ASSERTS3(((x + (ixLast - 1)) < (INT) ppdev->cxScreen),
        !          3618:                       "S3.DLL!bCpyColorHorzCacheToScreen - Blit Operation over right edge (3)\n");
        !          3619: 
        !          3620:             FIFOWAIT(FIFO_6_EMPTY);
        !          3621: 
        !          3622:             OUTPW(RECT_WIDTH, ixLast - 1);
        !          3623: 
        !          3624:             OUTPW(CUR_X,  COLOR_HORZ_EXPANSION_CACHE_X);
        !          3625:             OUTPW(CUR_Y,  COLOR_HORZ_EXPANSION_CACHE_Y + yOffset);
        !          3626:             OUTPW(DEST_X, x);
        !          3627:             OUTPW(DEST_Y, pptDest->y);
        !          3628: 
        !          3629:             OUTPW(CMD, Cmd);
        !          3630:         }
        !          3631:     }
        !          3632: 
        !          3633:     // If the cyDest is taller than 8 pels do a rolling blit to fill in
        !          3634:     // the bottom of the fill area.
        !          3635: 
        !          3636:     if (psizDest->cy > 8)
        !          3637:     {
        !          3638:         ASSERTS3(((pptDest->x + (psizDest->cx - 1)) < (INT) ppdev->cxScreen),
        !          3639:                   "S3.DLL!bCpyColorHorzCacheToScreen - Blit Operation over right edge (4)\n");
        !          3640: 
        !          3641:         FIFOWAIT(FIFO_7_EMPTY);
        !          3642: 
        !          3643:         OUTPW(RECT_WIDTH, psizDest->cx - 1);
        !          3644:         OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | psizDest->cy - (cy + 1)));
        !          3645: 
        !          3646:         OUTPW(CUR_X,  pptDest->x);
        !          3647:         OUTPW(CUR_Y,  pptDest->y);
        !          3648:         OUTPW(DEST_X, pptDest->x);
        !          3649:         OUTPW(DEST_Y, pptDest->y + 8);
        !          3650: 
        !          3651:         OUTPW(CMD, Cmd);
        !          3652:     }
        !          3653: 
        !          3654:     return(TRUE);
        !          3655: }
        !          3656: 
        !          3657: /*****************************************************************************
        !          3658:  * Copy Optimized
        !          3659:  * Color expand the monochrome brush in the Hoizontal Cache to the screen.
        !          3660:  ****************************************************************************/
        !          3661: BOOL bCpyColorExpandHorzCacheToScreen(
        !          3662:     PPDEV       ppdev,
        !          3663:     PS3BRUSH    ps3Brush,
        !          3664:     INT         zHorz,
        !          3665:     PPOINT      pptBrushOrg,
        !          3666:     PPOINT      pptDest,
        !          3667:     PSIZE       psizDest)
        !          3668: {
        !          3669:     WORD    Cmd;
        !          3670:     INT     cx, cxLeft, ixBlits, ixLast, i,
        !          3671:             cy, x, xOffset, yOffset;
        !          3672: 
        !          3673:     DISPDBG((3, "S3.DLL!bCpyColorExpandHorzCacheToScreen - Entry\n"));
        !          3674: 
        !          3675:     // Take into account the pptBrushOrg.
        !          3676: 
        !          3677:     xOffset = pptDest->x - pptBrushOrg->x;
        !          3678:     yOffset = pptDest->y - pptBrushOrg->y;
        !          3679: 
        !          3680:     if (xOffset < 0)
        !          3681:         xOffset  = 8 - (-xOffset % 8);
        !          3682:     else
        !          3683:         xOffset %= 8;
        !          3684: 
        !          3685:     if (yOffset < 0)
        !          3686:         yOffset  = 8 - (-yOffset % 8);
        !          3687:     else
        !          3688:         yOffset %= 8;
        !          3689: 
        !          3690:     // First Color Expand the monochrome horizontal cache to the screen.
        !          3691: 
        !          3692:     cxLeft = MONO_HORZ_EXPANSION_CACHE_CX - xOffset;
        !          3693:     if (psizDest->cx < cxLeft)
        !          3694:         cxLeft = psizDest->cx;
        !          3695: 
        !          3696:     cy = 8;
        !          3697:     if (psizDest->cy < cy)
        !          3698:         cy = psizDest->cy;
        !          3699: 
        !          3700:     Cmd  = BITBLT         | DRAW | DIR_TYPE_XY | WRITE |
        !          3701:            MULTIPLE_PIXELS| DRAWING_DIR_TBLRXM;
        !          3702: 
        !          3703:     ASSERTS3(((pptDest->x + (cxLeft - 1)) < (INT) ppdev->cxScreen),
        !          3704:               "S3.DLL!bCpyColorExpandHorzCacheToScreen - Blit Operation over right edge (1)\n");
        !          3705: 
        !          3706:     FIFOWAIT(FIFO_6_EMPTY);
        !          3707: 
        !          3708:     TEST_AND_SET_RD_MASK(zHorz);
        !          3709: 
        !          3710:     TEST_AND_SET_FRGD_MIX(FOREGROUND_COLOR | OVERPAINT);
        !          3711:     TEST_AND_SET_FRGD_COLOR(LOWORD(ps3Brush->ulForeColor));
        !          3712: 
        !          3713:     TEST_AND_SET_BKGD_MIX(BACKGROUND_COLOR | OVERPAINT);
        !          3714:     SET_BKGD_COLOR(LOWORD(ps3Brush->ulBackColor));
        !          3715: 
        !          3716:     OUTPW(MULTIFUNC_CNTL, (DATA_EXTENSION | DISPLAY_MEMORY));
        !          3717: 
        !          3718:     FIFOWAIT(FIFO_7_EMPTY);
        !          3719: 
        !          3720:     OUTPW(RECT_WIDTH, cxLeft - 1);
        !          3721:     OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | (cy - 1)));
        !          3722: 
        !          3723:     OUTPW(CUR_X,  MONO_HORZ_EXPANSION_CACHE_X + xOffset);
        !          3724:     OUTPW(CUR_Y,  MONO_HORZ_EXPANSION_CACHE_Y + yOffset);
        !          3725:     OUTPW(DEST_X, pptDest->x);
        !          3726:     OUTPW(DEST_Y, pptDest->y);
        !          3727: 
        !          3728:     OUTPW(CMD, Cmd);
        !          3729: 
        !          3730:     // If the the cxDest is wider than the cxHorzCache then fill in the
        !          3731:     // right side of the fill area.
        !          3732: 
        !          3733:     if ((cx = psizDest->cx - cxLeft) > 0)
        !          3734:     {
        !          3735:         ixBlits = cx / MONO_HORZ_EXPANSION_CACHE_CX;
        !          3736:         ixLast  = cx % MONO_HORZ_EXPANSION_CACHE_CX;
        !          3737: 
        !          3738:         FIFOWAIT(FIFO_1_EMPTY);
        !          3739:         OUTPW(RECT_WIDTH, MONO_HORZ_EXPANSION_CACHE_CX - 1);
        !          3740: 
        !          3741:         for (i = 0; i < ixBlits; i++)
        !          3742:         {
        !          3743:             x = pptDest->x + cxLeft + (i * MONO_HORZ_EXPANSION_CACHE_CX);
        !          3744: 
        !          3745:             ASSERTS3(((x + (COLOR_HORZ_EXPANSION_CACHE_CX - 1)) < (INT) ppdev->cxScreen),
        !          3746:                       "S3.DLL!bCpyColorExpandHorzCacheToScreen - Blit Operation over right edge (2)\n");
        !          3747: 
        !          3748:             FIFOWAIT(FIFO_5_EMPTY);
        !          3749: 
        !          3750:             OUTPW(CUR_X,  MONO_HORZ_EXPANSION_CACHE_X);
        !          3751:             OUTPW(CUR_Y,  MONO_HORZ_EXPANSION_CACHE_Y + yOffset);
        !          3752:             OUTPW(DEST_X, x);
        !          3753:             OUTPW(DEST_Y, pptDest->y);
        !          3754: 
        !          3755:             OUTPW(CMD, Cmd);
        !          3756:         }
        !          3757: 
        !          3758:         if (ixLast != 0)
        !          3759:         {
        !          3760:             x = pptDest->x + cxLeft + (ixBlits * MONO_HORZ_EXPANSION_CACHE_CX);
        !          3761: 
        !          3762:             ASSERTS3(((x + (ixLast - 1)) < (INT) ppdev->cxScreen),
        !          3763:                       "S3.DLL!bCpyColorExpandHorzCacheToScreen - Blit Operation over right edge (3)\n");
        !          3764: 
        !          3765:             FIFOWAIT(FIFO_6_EMPTY);
        !          3766: 
        !          3767:             OUTPW(RECT_WIDTH, ixLast - 1);
        !          3768: 
        !          3769:             OUTPW(CUR_X,  MONO_HORZ_EXPANSION_CACHE_X);
        !          3770:             OUTPW(CUR_Y,  MONO_HORZ_EXPANSION_CACHE_Y + yOffset);
        !          3771:             OUTPW(DEST_X, x);
        !          3772:             OUTPW(DEST_Y, pptDest->y);
        !          3773: 
        !          3774:             OUTPW(CMD, Cmd);
        !          3775:         }
        !          3776:     }
        !          3777: 
        !          3778:     // If the cyDest is taller than 8 pels do a rolling blit to fill in
        !          3779:     // the bottom of the fill area.
        !          3780: 
        !          3781:     if (psizDest->cy > 8)
        !          3782:     {
        !          3783:         ASSERTS3(((pptDest->x + (psizDest->cx - 1)) < (INT) ppdev->cxScreen),
        !          3784:                   "S3.DLL!bCpyColorExpandHorzCacheToScreen - Blit Operation over right edge (4)\n");
        !          3785: 
        !          3786:         FIFOWAIT(FIFO_2_EMPTY);
        !          3787: 
        !          3788:         TEST_AND_SET_RD_MASK(0xff);
        !          3789:         TEST_AND_SET_FRGD_MIX(SRC_DISPLAY_MEMORY | OVERPAINT);
        !          3790: 
        !          3791:         FIFOWAIT(FIFO_8_EMPTY);
        !          3792: 
        !          3793:         OUTPW(MULTIFUNC_CNTL, (DATA_EXTENSION | ALL_ONES));
        !          3794: 
        !          3795:         OUTPW(RECT_WIDTH, psizDest->cx - 1);
        !          3796:         OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | psizDest->cy - (cy + 1)));
        !          3797: 
        !          3798:         OUTPW(CUR_X,  pptDest->x);
        !          3799:         OUTPW(CUR_Y,  pptDest->y);
        !          3800:         OUTPW(DEST_X, pptDest->x);
        !          3801:         OUTPW(DEST_Y, pptDest->y + 8);
        !          3802: 
        !          3803:         OUTPW(CMD, Cmd);
        !          3804:     }
        !          3805: 
        !          3806:     // Reset the Read Mask
        !          3807: 
        !          3808:     FIFOWAIT(FIFO_2_EMPTY);
        !          3809: 
        !          3810:     TEST_AND_SET_WRT_MASK(0xff);
        !          3811:     TEST_AND_SET_RD_MASK(0xff);
        !          3812: 
        !          3813:     return(TRUE);
        !          3814: }
        !          3815: 
        !          3816: 
        !          3817: /*****************************************************************************
        !          3818:  * S3 Solid Pattern
        !          3819:  *
        !          3820:  *  Returns TRUE if the blit was handled.
        !          3821:  ****************************************************************************/
        !          3822: BOOL bPatternSolid(
        !          3823:     SURFOBJ  *psoTrg,
        !          3824:     SURFOBJ  *psoSrc,
        !          3825:     SURFOBJ  *psoMask,
        !          3826:     CLIPOBJ  *pco,
        !          3827:     XLATEOBJ *pxlo,
        !          3828:     RECTL    *prclTrg,
        !          3829:     POINTL   *pptlSrc,
        !          3830:     POINTL   *pptlMask,
        !          3831:     BRUSHOBJ *pbo,
        !          3832:     POINTL   *pptlBrush,
        !          3833:     ROP4     s3Rop4)
        !          3834: {
        !          3835:     INT     width,height;
        !          3836:     WORD    s3Mix;
        !          3837:     BOOL    bMore;
        !          3838:     UINT        i;
        !          3839:     ENUMRECTS8  EnumRects8;
        !          3840: 
        !          3841:     LONG    rleft;                          // render coordinates
        !          3842:     LONG    rtop;
        !          3843:     LONG    rright;
        !          3844:     LONG    rbottom;
        !          3845:     LONG    cleft;                          // clip coorindates
        !          3846:     LONG    ctop;
        !          3847:     LONG    cright;
        !          3848:     LONG    cbottom;
        !          3849:     LONG    left;
        !          3850:     LONG    top;
        !          3851:     RECTL   rclBounds;
        !          3852:     BOOL    bClipRequired, bDrawRequired;
        !          3853:     PPDEV   ppdev;
        !          3854: 
        !          3855:     DISPDBG((3,"S3.DLL!bPatternSolid - Entry\n"));
        !          3856: 
        !          3857:     // Get the pdev.
        !          3858: 
        !          3859:     ppdev = (PPDEV) psoTrg->dhpdev;
        !          3860: 
        !          3861:     // Just use the for ground mix.
        !          3862: 
        !          3863:     s3Mix = (WORD) (s3Rop4 & 0xFF);
        !          3864: 
        !          3865:     // Dereference the target rectangle.
        !          3866: 
        !          3867:     rleft   = prclTrg->left;
        !          3868:     rtop    = prclTrg->top;
        !          3869:     rright  = prclTrg->right;
        !          3870:     rbottom = prclTrg->bottom;
        !          3871: 
        !          3872:     // Use software clipping. It's faster than H/W clipping.
        !          3873: 
        !          3874:     if (pco->iDComplexity != DC_COMPLEX)
        !          3875:     {
        !          3876:         if (pco->iDComplexity == DC_TRIVIAL)
        !          3877:         {
        !          3878:             width  = (rright - rleft) - 1;
        !          3879:             height = (rbottom - rtop) - 1;
        !          3880: 
        !          3881:             bDrawRequired = TRUE;
        !          3882:         }
        !          3883:         else
        !          3884:         {
        !          3885:             bDrawRequired = FALSE;
        !          3886: 
        !          3887:             rclBounds = pco->rclBounds;
        !          3888: 
        !          3889:             // First handle the trivial rejection.
        !          3890: 
        !          3891:             bClipRequired = bIntersectTest(prclTrg, &rclBounds);
        !          3892: 
        !          3893:             if (bClipRequired)
        !          3894:             {
        !          3895:                 rleft   = max (rleft, rclBounds.left);
        !          3896:                 rtop    = max (rtop, rclBounds.top);
        !          3897:                 width  = (min(rright, rclBounds.right) - rleft) - 1;
        !          3898:                 height = (min(rbottom, rclBounds.bottom) - rtop) - 1;
        !          3899: 
        !          3900:                 bDrawRequired = TRUE;
        !          3901:             }
        !          3902:         }
        !          3903: 
        !          3904:         if (bDrawRequired && width >= 0 && height >= 0)
        !          3905:         {
        !          3906:             vS3SolidPattern(ppdev,
        !          3907:                             rleft, rtop, width, height,
        !          3908:                             (pbo != NULL)? pbo->iSolidColor: 0, s3Mix);
        !          3909:         }
        !          3910:     }
        !          3911:     else
        !          3912:     {
        !          3913:         CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
        !          3914: 
        !          3915:         do
        !          3916:         {
        !          3917:             bMore = CLIPOBJ_bEnum(pco, sizeof (ENUMRECTS8),
        !          3918:                                   (PULONG) &EnumRects8);
        !          3919:             for (i = 0; i < EnumRects8.c; i++)
        !          3920:             {
        !          3921:                 // Do a trivial reject on Y.
        !          3922: 
        !          3923:                 if (rtop > (cbottom = EnumRects8.arcl[i].bottom))
        !          3924:                     continue;
        !          3925:                 if (rbottom < (ctop = EnumRects8.arcl[i].top))
        !          3926:                     continue;
        !          3927: 
        !          3928:                 // Do a trivial reject on X.
        !          3929: 
        !          3930:                 if (rleft > (cright = EnumRects8.arcl[i].right))
        !          3931:                     continue;
        !          3932:                 if (rright < (cleft = EnumRects8.arcl[i].left))
        !          3933:                     continue;
        !          3934: 
        !          3935:                 // It's not a trivial reject, so calculate the
        !          3936:                 // minimal clip area.
        !          3937: 
        !          3938:                 left   = max (rleft, cleft);
        !          3939:                 top    = max (rtop, ctop);
        !          3940:                 width  = (min(rright, cright) - left) - 1;
        !          3941:                 height = (min(rbottom, cbottom) - top) - 1;
        !          3942: 
        !          3943:                 if (width < 0 || height < 0)
        !          3944:                     continue;
        !          3945: 
        !          3946:                 vS3SolidPattern(ppdev,
        !          3947:                                 left, top,
        !          3948:                                 width, height,
        !          3949:                                 (pbo != NULL)? pbo->iSolidColor: 0, s3Mix);
        !          3950:             }
        !          3951:         } while (bMore);
        !          3952:     }
        !          3953: 
        !          3954:     return (TRUE);
        !          3955: }
        !          3956: 
        !          3957: /*****************************************************************************
        !          3958:  * vS3SolidPattern
        !          3959:  ****************************************************************************/
        !          3960: VOID vS3SolidPattern(
        !          3961:     PPDEV   ppdev,
        !          3962:     INT     left,
        !          3963:     INT     top,
        !          3964:     INT     width,
        !          3965:     INT     height,
        !          3966:     INT     color,
        !          3967:     WORD    s3Mix)
        !          3968: {
        !          3969:     FIFOWAIT(FIFO_8_EMPTY);
        !          3970: 
        !          3971:     ASSERTS3 (((left + width) < (INT) ppdev->cxScreen),
        !          3972:               "S3.DLL!vS3SolidPattern - (left + width) > (ppdev->cxScreen - 1)\n");
        !          3973: 
        !          3974:     TEST_AND_SET_FRGD_MIX(FOREGROUND_COLOR | s3Mix);
        !          3975:     TEST_AND_SET_FRGD_COLOR(color);
        !          3976: 
        !          3977:     OUTPW (MULTIFUNC_CNTL, (DATA_EXTENSION | ALL_ONES));
        !          3978: 
        !          3979:     OUTPW (CUR_X, left);
        !          3980:     OUTPW (CUR_Y, top);
        !          3981:     OUTPW (RECT_WIDTH, width);
        !          3982:     OUTPW (MULTIFUNC_CNTL, (RECT_HEIGHT | height));
        !          3983: 
        !          3984:     OUTPW (CMD, RECTANGLE_FILL | DRAWING_DIR_TBLRXM |
        !          3985:                 DRAW           | DIR_TYPE_XY        |
        !          3986:                 LAST_PIXEL_ON  | MULTIPLE_PIXELS    |
        !          3987:                 WRITE);
        !          3988: }
        !          3989: 
        !          3990: /*****************************************************************************
        !          3991:  * S3 8bpp Cached Managed Host to Screen Copy
        !          3992:  *
        !          3993:  *  Returns TRUE if the blit was handled.
        !          3994:  ****************************************************************************/
        !          3995: BOOL b8BppHostToScrnCachedWithRop(
        !          3996:     SURFOBJ  *psoTrg,
        !          3997:     SURFOBJ  *psoSrc,
        !          3998:     CLIPOBJ  *pco,
        !          3999:     XLATEOBJ *pxlo,
        !          4000:     RECTL    *prclTrg,
        !          4001:     POINTL   *pptlSrc,
        !          4002:     WORD     s3Rop)
        !          4003: {
        !          4004:     BOOL    bRet;
        !          4005:     HSURF   hsurf;
        !          4006:     PPDEV   ppdev;
        !          4007:     POINTL  ptlSrc;
        !          4008:     RECTL   rclTrg;
        !          4009:     SIZEL   sizlBitmap;
        !          4010: 
        !          4011:     PSAVEDSCRNBITSHDR   pssbhInPdev;
        !          4012:     PSAVEDSCRNBITS      pssbNewNode, pssbTemp;
        !          4013: 
        !          4014:     DISPDBG((3, "S3.DLL!b8BppHostToScrnCachedWithRop - entry\n"));
        !          4015: 
        !          4016:     n8BppBitmaps++;
        !          4017: 
        !          4018:     ppdev = (PPDEV) psoTrg->dhpdev;
        !          4019:     hsurf = psoSrc->hsurf;
        !          4020: 
        !          4021: #if 0
        !          4022:     DISPDBG((2, "\thsurf                : %x\n", hsurf));
        !          4023:     DISPDBG((2, "\tpsoSrc->iUniq        : %x\n", psoSrc->iUniq));
        !          4024:     DISPDBG((2, "\tpsoSrc->sizlBitmap.cx: %d\n", psoSrc->sizlBitmap.cx));
        !          4025:     DISPDBG((2, "\tpsoSrc->sizlBitmap.cy: %d\n", psoSrc->sizlBitmap.cy));
        !          4026: #endif
        !          4027: 
        !          4028: #if SRCBM_CACHE
        !          4029: 
        !          4030:     // Is this bitmap in the cache?
        !          4031: 
        !          4032:     if ((hsurf == ppdev->hsurfCachedBitmap) &&
        !          4033:         (psoSrc->iUniq == ppdev->iUniqCachedBitmap))
        !          4034:     {
        !          4035:         if ((((pxlo == NULL) ||
        !          4036:               (pxlo->flXlate & XO_TRIVIAL)) && (ppdev->iUniqXlate == 1)) ||
        !          4037:             (pxlo->iUniq == ppdev->iUniqXlate))
        !          4038:         {
        !          4039:             // The bitmap is in the cache
        !          4040:             // Keep a cache hit count.
        !          4041: 
        !          4042:             n8BppBmCacheHits++;
        !          4043: 
        !          4044:             // Blt from the cache.
        !          4045: 
        !          4046:             ptlSrc.x = pptlSrc->x + OFF_SCREEN_BITMAP_X;
        !          4047:             ptlSrc.y = pptlSrc->y + OFF_SCREEN_BITMAP_Y;
        !          4048: 
        !          4049:             return(bScrnToScrnWithRop(psoTrg, psoTrg, pco, prclTrg,
        !          4050:                                       &ptlSrc, s3Rop));
        !          4051:         }
        !          4052:     }
        !          4053: 
        !          4054:     // The bitmap is not in the cache.
        !          4055:     // Is it small enough to fit into the cache?
        !          4056: 
        !          4057:     sizlBitmap = psoSrc->sizlBitmap;
        !          4058: 
        !          4059:     if ((sizlBitmap.cx <= OFF_SCREEN_BITMAP_CX) &&
        !          4060:         (sizlBitmap.cy <= OFF_SCREEN_BITMAP_CY))
        !          4061:     {
        !          4062:         // It will fit in the cache.
        !          4063:         // If the cache is being used for some saved screen bits
        !          4064:         // move them to host memory.
        !          4065: 
        !          4066:         if (ppdev->SavedScreenBitsHeader.iUniq != -1)
        !          4067:         {
        !          4068:             nSsbMovedToHostFromSrcBmCache++;
        !          4069: 
        !          4070:             DISPDBG((1, "S3.DLL - Saved Screen Bits Moved to Host Memory from Source Bitmap Cache Manager \n"));
        !          4071: 
        !          4072:             // Move the actual bits to host memory.
        !          4073: 
        !          4074:             bRet = bMoveSaveScreenBitsToHost(ppdev, &pssbNewNode);
        !          4075: 
        !          4076:             if (bRet == FALSE)
        !          4077:                 return(FALSE);
        !          4078: 
        !          4079:             // Connect this newNode to the beginning of the list of
        !          4080:             // save screen bits nodes.
        !          4081: 
        !          4082:             pssbhInPdev = &(ppdev->SavedScreenBitsHeader);
        !          4083: 
        !          4084:             pssbTemp                   = pssbhInPdev->pssbLink;
        !          4085:             pssbhInPdev->pssbLink      = pssbNewNode;
        !          4086:             pssbNewNode->ssbh.pssbLink = pssbTemp;
        !          4087: 
        !          4088:             // Invalidate the Save Screen bits in off screen memory
        !          4089: 
        !          4090:             ppdev->SavedScreenBitsHeader.iUniq = (ULONG) -1;
        !          4091:         }
        !          4092: 
        !          4093: 
        !          4094:         // Set the cache tags.
        !          4095: 
        !          4096:         ppdev->hsurfCachedBitmap = hsurf;
        !          4097:         ppdev->iUniqCachedBitmap = psoSrc->iUniq;
        !          4098: 
        !          4099:         if ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL))
        !          4100:         {
        !          4101:             ppdev->iUniqXlate = 1;
        !          4102:         }
        !          4103:         else
        !          4104:         {
        !          4105:             ppdev->iUniqXlate = pxlo->iUniq;
        !          4106:         }
        !          4107: 
        !          4108:         // Put the entire bitmap into the cache.
        !          4109: 
        !          4110:         rclTrg.left   = OFF_SCREEN_BITMAP_X;
        !          4111:         rclTrg.top    = OFF_SCREEN_BITMAP_Y;
        !          4112:         rclTrg.right  = OFF_SCREEN_BITMAP_X + sizlBitmap.cx;
        !          4113:         rclTrg.bottom = OFF_SCREEN_BITMAP_Y + sizlBitmap.cy;
        !          4114: 
        !          4115:         ptlSrc.x = 0;
        !          4116:         ptlSrc.y = 0;
        !          4117: 
        !          4118:         bRet = b8BppHostToScrnWithRop(psoTrg, psoSrc, ppdev->pcoFullRam,
        !          4119:                                       pxlo, &rclTrg, &ptlSrc, OVERPAINT);
        !          4120: 
        !          4121:         if (bRet == TRUE)
        !          4122:         {
        !          4123:             // Blt from the cache.
        !          4124: 
        !          4125:             ptlSrc.x = pptlSrc->x + OFF_SCREEN_BITMAP_X;
        !          4126:             ptlSrc.y = pptlSrc->y + OFF_SCREEN_BITMAP_Y;
        !          4127: 
        !          4128:             bRet = bScrnToScrnWithRop(psoTrg, psoTrg, pco, prclTrg,
        !          4129:                                       &ptlSrc, s3Rop);
        !          4130: 
        !          4131:         }
        !          4132:     }
        !          4133:     else
        !          4134:     {
        !          4135:         // The bitmap was too large to cache.
        !          4136:         // So, just blt it directly to the screen.
        !          4137: 
        !          4138:         bRet = b8BppHostToScrnWithRop(psoTrg, psoSrc, pco, pxlo,
        !          4139:                                       prclTrg, pptlSrc, s3Rop);
        !          4140:     }
        !          4141: #else
        !          4142: 
        !          4143:     bRet = b8BppHostToScrnWithRop(psoTrg, psoSrc, pco, pxlo,
        !          4144:                                   prclTrg, pptlSrc, s3Rop);
        !          4145: 
        !          4146: #endif
        !          4147: 
        !          4148:     return (bRet);
        !          4149: }
        !          4150: 
        !          4151: /*****************************************************************************
        !          4152:  * S3 8bpp Host to Screen Copy
        !          4153:  *
        !          4154:  *  Returns TRUE if the blit was handled.
        !          4155:  ****************************************************************************/
        !          4156: BOOL b8BppHostToScrnWithRop(
        !          4157:     SURFOBJ  *psoTrg,
        !          4158:     SURFOBJ  *psoSrc,
        !          4159:     CLIPOBJ  *pco,
        !          4160:     XLATEOBJ *pxlo,
        !          4161:     RECTL    *prclTrg,
        !          4162:     POINTL   *pptlSrc,
        !          4163:     WORD     s3Rop)
        !          4164: {
        !          4165:     LONG    lSrcDelta;
        !          4166:     PWORD   pwFirstWord;
        !          4167:     BOOL    bMore;
        !          4168:     PPDEV   ppdev;
        !          4169:     BYTE    iDComplexity;
        !          4170:     RECTL   rclTrg, rclBounds;
        !          4171:     POINT   ptSrc;
        !          4172:     INT     i;
        !          4173:     SIZE    sizBlt;
        !          4174: 
        !          4175:     ENUMRECTS8  EnumRects8;
        !          4176: 
        !          4177:     DISPDBG((3, "S3.DLL!b8BppHostToScrnWithRop - entry\n"));
        !          4178: 
        !          4179:     ppdev = (PPDEV) psoTrg->dhpdev;
        !          4180: 
        !          4181:     // Pickup some convienent locals.
        !          4182: 
        !          4183:     lSrcDelta = psoSrc->lDelta;
        !          4184: 
        !          4185:     if ((iDComplexity = pco->iDComplexity) != DC_COMPLEX)
        !          4186:     {
        !          4187:         // Make a copy of the target, since we will have to change
        !          4188:         // it for clipping.
        !          4189: 
        !          4190:         rclTrg = *prclTrg;
        !          4191: 
        !          4192:         if (iDComplexity == DC_RECT)
        !          4193:         {
        !          4194:             rclBounds = pco->rclBounds;
        !          4195: 
        !          4196:             // Handle the trivial rejection and
        !          4197:             // define the clipped target rectangle.
        !          4198: 
        !          4199:             if (bIntersectTest(&rclTrg, &rclBounds))
        !          4200:             {
        !          4201:                 rclTrg.left   = max (rclTrg.left, rclBounds.left);
        !          4202:                 rclTrg.top    = max (rclTrg.top, rclBounds.top);
        !          4203:                 rclTrg.right  = min (rclTrg.right, rclBounds.right);
        !          4204:                 rclTrg.bottom = min (rclTrg.bottom, rclBounds.bottom);
        !          4205:             }
        !          4206:             else
        !          4207:             {
        !          4208:                 // The destination rectangle is completely clipped out,
        !          4209:                 // so just return.
        !          4210: 
        !          4211:                 return (TRUE);
        !          4212:             }
        !          4213:         }
        !          4214: 
        !          4215:         // define the cx & cy for the blit.
        !          4216: 
        !          4217:         sizBlt.cx = rclTrg.right  - rclTrg.left;
        !          4218:         sizBlt.cy = rclTrg.bottom - rclTrg.top;
        !          4219: 
        !          4220:         // calculate the cx & cy shift (due to clipping) for the source.
        !          4221:         // and define the upper left corner of the source.
        !          4222: 
        !          4223:         ptSrc.x = pptlSrc->x + (rclTrg.left - prclTrg->left);
        !          4224:         ptSrc.y = pptlSrc->y + (rclTrg.top  - prclTrg->top);
        !          4225: 
        !          4226:         // Calculate the first word to blit
        !          4227: 
        !          4228:         pwFirstWord = (PWORD) (((PBYTE) psoSrc->pvScan0)
        !          4229:                      + (ptSrc.y * lSrcDelta) + ptSrc.x);
        !          4230: 
        !          4231:         vLowLevel8BppHostToScrnWithRop(ppdev, (PPOINT) &rclTrg, &sizBlt,
        !          4232:                                        pwFirstWord, lSrcDelta, pxlo, s3Rop);
        !          4233: 
        !          4234:     }
        !          4235:     else
        !          4236:     {
        !          4237:         CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
        !          4238: 
        !          4239:         do
        !          4240:         {
        !          4241:             bMore = CLIPOBJ_bEnum(pco, sizeof (ENUMRECTS8), (PULONG) &EnumRects8);
        !          4242: 
        !          4243:             for (i = 0; i < (INT) EnumRects8.c; i++)
        !          4244:             {
        !          4245:                 rclTrg = *prclTrg;
        !          4246:                 rclBounds = EnumRects8.arcl[i];
        !          4247: 
        !          4248:                 // Handle the trivial rejection and
        !          4249:                 // define the clipped target rectangle.
        !          4250: 
        !          4251:                 if (bIntersectTest(&rclTrg, &rclBounds))
        !          4252:                 {
        !          4253:                     rclTrg.left   = max (rclTrg.left, rclBounds.left);
        !          4254:                     rclTrg.top    = max (rclTrg.top, rclBounds.top);
        !          4255:                     rclTrg.right  = min (rclTrg.right, rclBounds.right);
        !          4256:                     rclTrg.bottom = min (rclTrg.bottom, rclBounds.bottom);
        !          4257: 
        !          4258:                     // define the cx & cy for the blit.
        !          4259: 
        !          4260:                     sizBlt.cx = rclTrg.right  - rclTrg.left;
        !          4261:                     sizBlt.cy = rclTrg.bottom - rclTrg.top;
        !          4262: 
        !          4263:                     // calculate the cx & cy shift (due to clipping) for the source.
        !          4264:                     // and define the upper left corner of the source.
        !          4265: 
        !          4266:                     ptSrc.x = pptlSrc->x + (rclTrg.left - prclTrg->left);
        !          4267:                     ptSrc.y = pptlSrc->y + (rclTrg.top  - prclTrg->top);
        !          4268: 
        !          4269:                     // Calculate the first word to blit
        !          4270: 
        !          4271:                     pwFirstWord = (PWORD) (((PBYTE) psoSrc->pvScan0)
        !          4272:                                  + (ptSrc.y * lSrcDelta) + ptSrc.x);
        !          4273: 
        !          4274:                     vLowLevel8BppHostToScrnWithRop(ppdev,
        !          4275:                                                    (PPOINT) &rclTrg,
        !          4276:                                                    &sizBlt,
        !          4277:                                                    pwFirstWord,
        !          4278:                                                    lSrcDelta,
        !          4279:                                                    pxlo,
        !          4280:                                                    s3Rop);
        !          4281:                 }
        !          4282:             }
        !          4283:         } while (bMore);
        !          4284:     }
        !          4285: 
        !          4286:     return (TRUE);
        !          4287: }
        !          4288: 
        !          4289: 
        !          4290: 
        !          4291: /*****************************************************************************
        !          4292:  * Low Level 8bpp host to screen copy.
        !          4293:  ****************************************************************************/
        !          4294: VOID vLowLevel8BppHostToScrnWithRop(
        !          4295:     PPDEV   ppdev,
        !          4296:     PPOINT  pptTrg,
        !          4297:     PSIZE   psizBlt,
        !          4298:     PWORD   pwFirstWord,
        !          4299:     INT     lSrcDelta,
        !          4300:     XLATEOBJ *pxlo,
        !          4301:     WORD    s3Rop)
        !          4302: {
        !          4303:     PWORD   pw;
        !          4304:     INT     i, j;
        !          4305:     WORD    Cmd;
        !          4306:     PBYTE   pbSrc;
        !          4307:     INT     nSrc;
        !          4308:     PULONG  pulXlate;
        !          4309:     INT     cy, wpl;
        !          4310:     BYTE    LineBuff[DRIVERS_MAX_CX];
        !          4311: 
        !          4312:     // Setup the S3 chip.
        !          4313: 
        !          4314:     cy = psizBlt->cy;
        !          4315: 
        !          4316:     Cmd = RECTANGLE_FILL | BYTE_SWAP          | BUS_SIZE_16 | WAIT |
        !          4317:           DRAW           | DRAWING_DIR_TBLRXM | DIR_TYPE_XY |
        !          4318:           LAST_PIXEL_ON  | SINGLE_PIXEL       | WRITE;
        !          4319: 
        !          4320:     FIFOWAIT(FIFO_7_EMPTY);
        !          4321: 
        !          4322:     TEST_AND_SET_FRGD_MIX(SRC_CPU_DATA | s3Rop);
        !          4323:     OUTPW(MULTIFUNC_CNTL, (DATA_EXTENSION | ALL_ONES));
        !          4324: 
        !          4325:     OUTPW(CUR_X, pptTrg->x);
        !          4326:     OUTPW(CUR_Y, pptTrg->y);
        !          4327:     OUTPW(RECT_WIDTH, psizBlt->cx - 1);
        !          4328:     OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | cy - 1));
        !          4329: 
        !          4330:     GPWAIT();
        !          4331: 
        !          4332:     OUTPW(CMD, Cmd);
        !          4333: 
        !          4334:     CHECK_DATA_READY;
        !          4335: 
        !          4336:     wpl = (psizBlt->cx + 1) >> 1;
        !          4337: 
        !          4338:     // We may have to do some color translation.
        !          4339: 
        !          4340:     if ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL))
        !          4341:     {
        !          4342:         // Now transfer the data.
        !          4343: 
        !          4344:         // Note: It would nice to do the entire bitmap in one
        !          4345:         //       fell swoop, but there is no gaurantee source will
        !          4346:         //       wrap on a bitmap boundary.
        !          4347: 
        !          4348:         pw = pwFirstWord;
        !          4349:         for (i = 0; i < cy; i++)
        !          4350:         {
        !          4351:             vDataPortOut(ppdev, (PWORD) pw, wpl);
        !          4352:             ((PBYTE) pw) += lSrcDelta;
        !          4353:         }
        !          4354:     }
        !          4355:     else
        !          4356:     {
        !          4357:         if (pxlo->flXlate & XO_TABLE)
        !          4358:         {
        !          4359:             pulXlate = pxlo->pulXlate;
        !          4360:         }
        !          4361:         else
        !          4362:         {
        !          4363:             pulXlate = XLATEOBJ_piVector(pxlo);
        !          4364:         }
        !          4365: 
        !          4366:         pbSrc = (PBYTE) pwFirstWord;
        !          4367:         nSrc  = wpl * 2;
        !          4368: 
        !          4369:         for (i = 0; i < cy; i++)
        !          4370:         {
        !          4371:             for (j = 0; j < nSrc; j++)
        !          4372:             {
        !          4373:                 LineBuff[j] = LOBYTE(pulXlate[pbSrc[j]]);
        !          4374:             }
        !          4375: 
        !          4376:             vDataPortOut(ppdev, (PWORD) LineBuff, wpl);
        !          4377:             pbSrc += lSrcDelta;
        !          4378:         }
        !          4379:     }
        !          4380: 
        !          4381:     CHECK_DATA_COMPLETE;
        !          4382: 
        !          4383:     return;
        !          4384: 
        !          4385: }
        !          4386: 
        !          4387: 
        !          4388: /*****************************************************************************
        !          4389:  * S3 1bpp Cached Managed Host to Screen With Rop
        !          4390:  *
        !          4391:  *  Returns TRUE if the blit was handled.
        !          4392:  ****************************************************************************/
        !          4393: BOOL b1BppHostToScrnCachedWithRop(
        !          4394:     SURFOBJ  *psoTrg,
        !          4395:     SURFOBJ  *psoSrc,
        !          4396:     CLIPOBJ  *pco,
        !          4397:     XLATEOBJ *pxlo,
        !          4398:     RECTL    *prclTrg,
        !          4399:     POINTL   *pptlSrc,
        !          4400:     WORD     s3Rop)
        !          4401: {
        !          4402:     BOOL    bRet;
        !          4403:     HSURF   hsurf;
        !          4404:     PPDEV   ppdev;
        !          4405:     POINTL  ptlSrc;
        !          4406:     RECTL   rclTrg;
        !          4407:     SIZEL   sizlBitmap;
        !          4408: 
        !          4409:     PSAVEDSCRNBITSHDR   pssbhInPdev;
        !          4410:     PSAVEDSCRNBITS      pssbNewNode, pssbTemp;
        !          4411: 
        !          4412:     DISPDBG((3, "S3.DLL!b1BppHostToScrnCachedWithRop - entry\n"));
        !          4413: 
        !          4414:     n1BppBitmaps++;
        !          4415: 
        !          4416:     ppdev = (PPDEV) psoTrg->dhpdev;
        !          4417:     hsurf = psoSrc->hsurf;
        !          4418: 
        !          4419: #if 1
        !          4420:     DISPDBG((2, "\thsurf                : %x\n", hsurf));
        !          4421:     DISPDBG((2, "\tpsoSrc->iUniq        : %x\n", psoSrc->iUniq));
        !          4422:     DISPDBG((2, "\tpsoSrc->sizlBitmap.cx: %d\n", psoSrc->sizlBitmap.cx));
        !          4423:     DISPDBG((2, "\tpsoSrc->sizlBitmap.cy: %d\n", psoSrc->sizlBitmap.cy));
        !          4424: #endif
        !          4425: 
        !          4426: #if SRCBM_CACHE
        !          4427: 
        !          4428:     // Is this bitmap in the cache?
        !          4429: 
        !          4430:     if ((hsurf == ppdev->hsurfCachedBitmap) &&
        !          4431:         (psoSrc->iUniq == ppdev->iUniqCachedBitmap))
        !          4432:     {
        !          4433:         if ((((pxlo == NULL) ||
        !          4434:               (pxlo->flXlate & XO_TRIVIAL)) && (ppdev->iUniqXlate == 1)) ||
        !          4435:             (pxlo->iUniq == ppdev->iUniqXlate))
        !          4436:         {
        !          4437:             // The bitmap is in the cache
        !          4438:             // Keep a cache hit count.
        !          4439: 
        !          4440:             n1BppBmCacheHits++;
        !          4441: 
        !          4442:             // Blt from the cache.
        !          4443: 
        !          4444:             ptlSrc.x = pptlSrc->x + OFF_SCREEN_BITMAP_X;
        !          4445:             ptlSrc.y = pptlSrc->y + OFF_SCREEN_BITMAP_Y;
        !          4446: 
        !          4447:             return(bScrnToScrnWithRop(psoTrg, psoTrg, pco, prclTrg,
        !          4448:                                       &ptlSrc, s3Rop));
        !          4449:         }
        !          4450:     }
        !          4451: 
        !          4452:     // The bitmap is not in the cache.
        !          4453:     // Is it small enough to fit into the cache?
        !          4454: 
        !          4455:     sizlBitmap = psoSrc->sizlBitmap;
        !          4456: 
        !          4457:     if ((sizlBitmap.cx <= OFF_SCREEN_BITMAP_CX) &&
        !          4458:         (sizlBitmap.cy <= OFF_SCREEN_BITMAP_CY))
        !          4459:     {
        !          4460:         // It will fit in the cache.
        !          4461:         // If the cache is being used for some saved screen bits
        !          4462:         // move them to host memory.
        !          4463: 
        !          4464:         if (ppdev->SavedScreenBitsHeader.iUniq != -1)
        !          4465:         {
        !          4466:             nSsbMovedToHostFromSrcBmCache++;
        !          4467: 
        !          4468:             DISPDBG((1, "S3.DLL - Saved Screen Bits Moved to Host Memory from Source Bitmap Cache Manager \n"));
        !          4469: 
        !          4470:             // Move the actual bits to host memory.
        !          4471: 
        !          4472:             bRet = bMoveSaveScreenBitsToHost(ppdev, &pssbNewNode);
        !          4473: 
        !          4474:             if (bRet == FALSE)
        !          4475:                 return(FALSE);
        !          4476: 
        !          4477:             // Connect this newNode to the beginning of the list of
        !          4478:             // save screen bits nodes.
        !          4479: 
        !          4480:             pssbhInPdev = &(ppdev->SavedScreenBitsHeader);
        !          4481: 
        !          4482:             pssbTemp                   = pssbhInPdev->pssbLink;
        !          4483:             pssbhInPdev->pssbLink      = pssbNewNode;
        !          4484:             pssbNewNode->ssbh.pssbLink = pssbTemp;
        !          4485: 
        !          4486:             // Invalidate the Save Screen bits in off screen memory
        !          4487: 
        !          4488:             ppdev->SavedScreenBitsHeader.iUniq = (ULONG) -1;
        !          4489:         }
        !          4490: 
        !          4491: 
        !          4492:         // Set the cache tags.
        !          4493: 
        !          4494:         ppdev->hsurfCachedBitmap = hsurf;
        !          4495:         ppdev->iUniqCachedBitmap = psoSrc->iUniq;
        !          4496: 
        !          4497:         if ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL))
        !          4498:         {
        !          4499:             ppdev->iUniqXlate = 1;
        !          4500:         }
        !          4501:         else
        !          4502:         {
        !          4503:             ppdev->iUniqXlate = pxlo->iUniq;
        !          4504:         }
        !          4505: 
        !          4506:         // Put the entire bitmap into the cache.
        !          4507: 
        !          4508:         rclTrg.left   = OFF_SCREEN_BITMAP_X;
        !          4509:         rclTrg.top    = OFF_SCREEN_BITMAP_Y;
        !          4510:         rclTrg.right  = OFF_SCREEN_BITMAP_X + sizlBitmap.cx;
        !          4511:         rclTrg.bottom = OFF_SCREEN_BITMAP_Y + sizlBitmap.cy;
        !          4512: 
        !          4513:         ptlSrc.x = 0;
        !          4514:         ptlSrc.y = 0;
        !          4515: 
        !          4516:         bRet = b1BppHostToScrnWithRop(psoTrg, psoSrc, ppdev->pcoFullRam,
        !          4517:                                       pxlo, &rclTrg, &ptlSrc, OVERPAINT);
        !          4518: 
        !          4519:         if (bRet == TRUE)
        !          4520:         {
        !          4521:             // Blt from the cache.
        !          4522: 
        !          4523:             ptlSrc.x = pptlSrc->x + OFF_SCREEN_BITMAP_X;
        !          4524:             ptlSrc.y = pptlSrc->y + OFF_SCREEN_BITMAP_Y;
        !          4525: 
        !          4526:             bRet = bScrnToScrnWithRop(psoTrg, psoTrg, pco, prclTrg,
        !          4527:                                       &ptlSrc, s3Rop);
        !          4528: 
        !          4529:         }
        !          4530:     }
        !          4531:     else
        !          4532:     {
        !          4533:         // The bitmap was too large to cache.
        !          4534:         // So, just blt it directly to the screen.
        !          4535: 
        !          4536:         bRet = b1BppHostToScrnWithRop(psoTrg, psoSrc, pco, pxlo,
        !          4537:                                       prclTrg, pptlSrc, s3Rop);
        !          4538:     }
        !          4539: #else
        !          4540: 
        !          4541:     bRet = b1BppHostToScrnWithRop(psoTrg, psoSrc, pco, pxlo,
        !          4542:                                   prclTrg, pptlSrc, s3Rop);
        !          4543: 
        !          4544: #endif
        !          4545: 
        !          4546:     return (bRet);
        !          4547: }
        !          4548: 
        !          4549: 
        !          4550: 
        !          4551: 
        !          4552: 
        !          4553: /*****************************************************************************
        !          4554:  * S3 1bpp Host to Screen With ROP
        !          4555:  *
        !          4556:  *  Returns TRUE if the blit was handled.
        !          4557:  ****************************************************************************/
        !          4558: BOOL b1BppHostToScrnWithRop(
        !          4559:     SURFOBJ  *psoTrg,
        !          4560:     SURFOBJ  *psoSrc,
        !          4561:     CLIPOBJ  *pco,
        !          4562:     XLATEOBJ *pxlo,
        !          4563:     RECTL    *prclTrg,
        !          4564:     POINTL   *pptlSrc,
        !          4565:     WORD     s3Rop)
        !          4566: {
        !          4567:     LONG    lSrcDelta;
        !          4568:     PWORD   pwFirstWord;
        !          4569:     BOOL    bMore;
        !          4570:     PPDEV   ppdev;
        !          4571:     BYTE    iDComplexity;
        !          4572:     RECTL   rclTrg, rclBounds;
        !          4573:     POINT   ptSrc;
        !          4574:     INT     i;
        !          4575:     SIZE    sizBlt;
        !          4576: 
        !          4577:     ENUMRECTS8  EnumRects8;
        !          4578: 
        !          4579:     DISPDBG((3, "S3.DLL!b1BppHostToScrnWithRop - entry\n"));
        !          4580: 
        !          4581:     ppdev = (PPDEV) psoTrg->dhpdev;
        !          4582: 
        !          4583:     // Pickup some convienent locals.
        !          4584: 
        !          4585:     lSrcDelta = psoSrc->lDelta;
        !          4586: 
        !          4587:     if ((iDComplexity = pco->iDComplexity) != DC_COMPLEX)
        !          4588:     {
        !          4589:         // Make a copy of the target, since we will have to change
        !          4590:         // it for clipping.
        !          4591: 
        !          4592:         rclTrg = *prclTrg;
        !          4593: 
        !          4594:         if (iDComplexity == DC_RECT)
        !          4595:         {
        !          4596:             rclBounds = pco->rclBounds;
        !          4597: 
        !          4598:             // Handle the trivial rejection and
        !          4599:             // define the clipped target rectangle.
        !          4600: 
        !          4601:             if (bIntersectTest(&rclTrg, &rclBounds))
        !          4602:             {
        !          4603:                 rclTrg.left   = max (rclTrg.left, rclBounds.left);
        !          4604:                 rclTrg.top    = max (rclTrg.top, rclBounds.top);
        !          4605:                 rclTrg.right  = min (rclTrg.right, rclBounds.right);
        !          4606:                 rclTrg.bottom = min (rclTrg.bottom, rclBounds.bottom);
        !          4607:             }
        !          4608:             else
        !          4609:             {
        !          4610:                 // The destination rectangle is completely clipped out,
        !          4611:                 // so just return.
        !          4612: 
        !          4613:                 return (TRUE);
        !          4614:             }
        !          4615:         }
        !          4616: 
        !          4617:         // define the cx & cy for the blit.
        !          4618: 
        !          4619:         sizBlt.cx = rclTrg.right  - rclTrg.left;
        !          4620:         sizBlt.cy = rclTrg.bottom - rclTrg.top;
        !          4621: 
        !          4622:         // calculate the cx & cy shift (due to clipping) for the source.
        !          4623:         // and define the upper left corner of the source.
        !          4624: 
        !          4625:         ptSrc.x = pptlSrc->x + (rclTrg.left - prclTrg->left);
        !          4626:         ptSrc.y = pptlSrc->y + (rclTrg.top  - prclTrg->top);
        !          4627: 
        !          4628:         // Calculate the first word to blit
        !          4629: 
        !          4630:         pwFirstWord = (PWORD) (((PBYTE) psoSrc->pvScan0)
        !          4631:                      + (ptSrc.y * lSrcDelta) + (ptSrc.x / 8));
        !          4632: 
        !          4633:         vSetS3ClipRect(ppdev, &rclTrg);
        !          4634:         vLowLevel1BppHostToScrnWithRop(ppdev,
        !          4635:                                        (PPOINT) &rclTrg,
        !          4636:                                        &sizBlt,
        !          4637:                                        ptSrc.x,
        !          4638:                                        pwFirstWord,
        !          4639:                                        lSrcDelta,
        !          4640:                                        pxlo,
        !          4641:                                        s3Rop);
        !          4642: 
        !          4643:     }
        !          4644:     else
        !          4645:     {
        !          4646:         CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
        !          4647: 
        !          4648:         do
        !          4649:         {
        !          4650:             bMore = CLIPOBJ_bEnum(pco, sizeof (ENUMRECTS8), (PULONG) &EnumRects8);
        !          4651: 
        !          4652:             for (i = 0; i < (INT) EnumRects8.c; i++)
        !          4653:             {
        !          4654:                 rclTrg = *prclTrg;
        !          4655:                 rclBounds = EnumRects8.arcl[i];
        !          4656: 
        !          4657:                 // Handle the trivial rejection and
        !          4658:                 // define the clipped target rectangle.
        !          4659: 
        !          4660:                 if (bIntersectTest(&rclTrg, &rclBounds))
        !          4661:                 {
        !          4662:                     rclTrg.left   = max (rclTrg.left, rclBounds.left);
        !          4663:                     rclTrg.top    = max (rclTrg.top, rclBounds.top);
        !          4664:                     rclTrg.right  = min (rclTrg.right, rclBounds.right);
        !          4665:                     rclTrg.bottom = min (rclTrg.bottom, rclBounds.bottom);
        !          4666: 
        !          4667:                     // define the cx & cy for the blit.
        !          4668: 
        !          4669:                     sizBlt.cx = rclTrg.right  - rclTrg.left;
        !          4670:                     sizBlt.cy = rclTrg.bottom - rclTrg.top;
        !          4671: 
        !          4672:                     // calculate the cx & cy shift (due to clipping) for the source.
        !          4673:                     // and define the upper left corner of the source.
        !          4674: 
        !          4675:                     ptSrc.x = pptlSrc->x + (rclTrg.left - prclTrg->left);
        !          4676:                     ptSrc.y = pptlSrc->y + (rclTrg.top  - prclTrg->top);
        !          4677: 
        !          4678:                     // Calculate the first word to blit
        !          4679: 
        !          4680:                     pwFirstWord = (PWORD) (((PBYTE) psoSrc->pvScan0)
        !          4681:                                  + (ptSrc.y * lSrcDelta) + (ptSrc.x / 8));
        !          4682: 
        !          4683:                     vSetS3ClipRect(ppdev, &rclTrg);
        !          4684:                     vLowLevel1BppHostToScrnWithRop(ppdev,
        !          4685:                                                    (PPOINT) &rclTrg,
        !          4686:                                                    &sizBlt,
        !          4687:                                                    ptSrc.x,
        !          4688:                                                    pwFirstWord,
        !          4689:                                                    lSrcDelta,
        !          4690:                                                    pxlo,
        !          4691:                                                    s3Rop);
        !          4692:                 }
        !          4693:             }
        !          4694:         } while (bMore);
        !          4695:     }
        !          4696: 
        !          4697:     vResetS3Clipping(ppdev);
        !          4698: 
        !          4699:     return (TRUE);
        !          4700: }
        !          4701: 
        !          4702: 
        !          4703: /*****************************************************************************
        !          4704:  * Low Level 1bpp host to screen copy.
        !          4705:  *
        !          4706:  * Note: This routine should be modified to handle separate foreground
        !          4707:  *       and background mix modes.
        !          4708:  ****************************************************************************/
        !          4709: VOID vLowLevel1BppHostToScrnWithRop(
        !          4710:     PPDEV   ppdev,
        !          4711:     PPOINT  pptTrg,
        !          4712:     PSIZE   psizBlt,
        !          4713:     INT     xSrc,
        !          4714:     PWORD   pwFirstWord,
        !          4715:     INT     lSrcDelta,
        !          4716:     XLATEOBJ *pxlo,
        !          4717:     WORD    s3Rop)
        !          4718: {
        !          4719: PBYTE   pb1bpp;
        !          4720: INT     i, x, cx, cy, nSrcBytes, xClip;
        !          4721: WORD    Cmd;
        !          4722: PULONG  pulXlate;
        !          4723: 
        !          4724:         if (pxlo->flXlate & XO_TABLE)
        !          4725:         {
        !          4726:             pulXlate = pxlo->pulXlate;
        !          4727:         }
        !          4728:         else
        !          4729:         {
        !          4730:             pulXlate = XLATEOBJ_piVector(pxlo);
        !          4731:         }
        !          4732: 
        !          4733: 
        !          4734:         x = pptTrg->x;
        !          4735:         cx = psizBlt->cx;
        !          4736: 
        !          4737:         // Take care of the non-byte aligned source case.
        !          4738: 
        !          4739:         if (xSrc & 0x7)
        !          4740:         {
        !          4741:             xClip = x;
        !          4742:             x  -= (xSrc & 0x7);
        !          4743:             cx += (xSrc & 0x7);
        !          4744: 
        !          4745:             FIFOWAIT(FIFO_1_EMPTY);
        !          4746:           outpw (MULTIFUNC_CNTL, (CLIP_LEFT   | xClip));
        !          4747:         }
        !          4748: 
        !          4749:         Cmd = RECTANGLE_FILL | BUS_SIZE_8         | WAIT |
        !          4750:               DRAW           | DRAWING_DIR_TBLRXM | DIR_TYPE_XY |
        !          4751:               LAST_PIXEL_ON  | MULTIPLE_PIXELS    | WRITE;
        !          4752: 
        !          4753:         // Setup the S3 chip.
        !          4754: 
        !          4755:         cy = psizBlt->cy;
        !          4756: 
        !          4757:         FIFOWAIT(FIFO_4_EMPTY);
        !          4758: 
        !          4759:         TEST_AND_SET_FRGD_MIX(FOREGROUND_COLOR | s3Rop);
        !          4760:         TEST_AND_SET_FRGD_COLOR(LOWORD(pulXlate[1]));
        !          4761:         TEST_AND_SET_BKGD_MIX(BACKGROUND_COLOR | s3Rop);
        !          4762:         SET_BKGD_COLOR(LOWORD(pulXlate[0]));
        !          4763: 
        !          4764:         FIFOWAIT(FIFO_5_EMPTY);
        !          4765: 
        !          4766:         OUTPW(MULTIFUNC_CNTL, (DATA_EXTENSION | CPU_DATA));
        !          4767: 
        !          4768:         OUTPW(CUR_X, x);
        !          4769:         OUTPW(CUR_Y, pptTrg->y);
        !          4770:         OUTPW(RECT_WIDTH, cx - 1);
        !          4771:         OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | cy - 1));
        !          4772: 
        !          4773:         GPWAIT();
        !          4774: 
        !          4775:         OUTPW(CMD, Cmd);
        !          4776: 
        !          4777:         CHECK_DATA_READY;
        !          4778: 
        !          4779:         pb1bpp = (PBYTE) pwFirstWord;
        !          4780:         nSrcBytes = (cx + 7) / 8;
        !          4781: 
        !          4782:         for (i = 0; i < cy; i++)
        !          4783:         {
        !          4784:             vDataPortOutB(ppdev, pb1bpp, nSrcBytes);
        !          4785:             pb1bpp += lSrcDelta;
        !          4786:         }
        !          4787: 
        !          4788:         CHECK_DATA_COMPLETE;
        !          4789: 
        !          4790:         return;
        !          4791: 
        !          4792: }
        !          4793: 
        !          4794: 
        !          4795: /*****************************************************************************
        !          4796:  * S3 4bpp Host to Screen Copy
        !          4797:  *
        !          4798:  *  Returns TRUE if the blit was handled.
        !          4799:  ****************************************************************************/
        !          4800: BOOL b4BppHostToScrnWithRop(
        !          4801:     SURFOBJ  *psoTrg,
        !          4802:     SURFOBJ  *psoSrc,
        !          4803:     CLIPOBJ  *pco,
        !          4804:     XLATEOBJ *pxlo,
        !          4805:     RECTL    *prclTrg,
        !          4806:     POINTL   *pptlSrc,
        !          4807:     WORD     s3Rop)
        !          4808: {
        !          4809:     LONG    lSrcDelta;
        !          4810:     PWORD   pwFirstWord;
        !          4811:     BOOL    bMore;
        !          4812:     PPDEV   ppdev;
        !          4813:     BYTE    iDComplexity;
        !          4814:     RECTL   rclTrg, rclBounds;
        !          4815:     POINT   ptSrc;
        !          4816:     INT     i;
        !          4817:     SIZE    sizBlt;
        !          4818: 
        !          4819:     ENUMRECTS8  EnumRects8;
        !          4820: 
        !          4821:     DISPDBG((2, "S3.DLL!b4BppHostToScrnWithRop - entry\n"));
        !          4822: 
        !          4823:     ppdev = (PPDEV) psoTrg->dhpdev;
        !          4824: 
        !          4825:     // Pickup some convienent locals.
        !          4826: 
        !          4827:     lSrcDelta = psoSrc->lDelta;
        !          4828: 
        !          4829:     if ((iDComplexity = pco->iDComplexity) != DC_COMPLEX)
        !          4830:     {
        !          4831:         // Make a copy of the target, since we will have to change
        !          4832:         // it for clipping.
        !          4833: 
        !          4834:         rclTrg = *prclTrg;
        !          4835: 
        !          4836:         if (iDComplexity == DC_RECT)
        !          4837:         {
        !          4838:             rclBounds = pco->rclBounds;
        !          4839: 
        !          4840:             // Handle the trivial rejection and
        !          4841:             // define the clipped target rectangle.
        !          4842: 
        !          4843:             if (bIntersectTest(&rclTrg, &rclBounds))
        !          4844:             {
        !          4845:                 rclTrg.left   = max (rclTrg.left, rclBounds.left);
        !          4846:                 rclTrg.top    = max (rclTrg.top, rclBounds.top);
        !          4847:                 rclTrg.right  = min (rclTrg.right, rclBounds.right);
        !          4848:                 rclTrg.bottom = min (rclTrg.bottom, rclBounds.bottom);
        !          4849:             }
        !          4850:             else
        !          4851:             {
        !          4852:                 // The destination rectangle is completely clipped out,
        !          4853:                 // so just return.
        !          4854: 
        !          4855:                 return (TRUE);
        !          4856:             }
        !          4857:         }
        !          4858: 
        !          4859:         // define the cx & cy for the blit.
        !          4860: 
        !          4861:         sizBlt.cx = rclTrg.right  - rclTrg.left;
        !          4862:         sizBlt.cy = rclTrg.bottom - rclTrg.top;
        !          4863: 
        !          4864:         // calculate the cx & cy shift (due to clipping) for the source.
        !          4865:         // and define the upper left corner of the source.
        !          4866: 
        !          4867:         ptSrc.x = pptlSrc->x + (rclTrg.left - prclTrg->left);
        !          4868:         ptSrc.y = pptlSrc->y + (rclTrg.top  - prclTrg->top);
        !          4869: 
        !          4870:         // Calculate the first word to blit
        !          4871: 
        !          4872:         pwFirstWord = (PWORD) (((PBYTE) psoSrc->pvScan0)
        !          4873:                      + (ptSrc.y * lSrcDelta) + (ptSrc.x / 2));
        !          4874: 
        !          4875:         vSetS3ClipRect(ppdev, &rclTrg);
        !          4876:         vLowLevel4BppHostToScrnWithRop(ppdev, (PPOINT) &rclTrg, &sizBlt,
        !          4877:                                    ptSrc.x,
        !          4878:                                    pwFirstWord, lSrcDelta, pxlo, s3Rop);
        !          4879: 
        !          4880:     }
        !          4881:     else
        !          4882:     {
        !          4883:         CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
        !          4884: 
        !          4885:         do
        !          4886:         {
        !          4887:             bMore = CLIPOBJ_bEnum(pco, sizeof (ENUMRECTS8), (PULONG) &EnumRects8);
        !          4888: 
        !          4889:             for (i = 0; i < (INT) EnumRects8.c; i++)
        !          4890:             {
        !          4891:                 rclTrg = *prclTrg;
        !          4892:                 rclBounds = EnumRects8.arcl[i];
        !          4893: 
        !          4894:                 // Handle the trivial rejection and
        !          4895:                 // define the clipped target rectangle.
        !          4896: 
        !          4897:                 if (bIntersectTest(&rclTrg, &rclBounds))
        !          4898:                 {
        !          4899:                     rclTrg.left   = max (rclTrg.left, rclBounds.left);
        !          4900:                     rclTrg.top    = max (rclTrg.top, rclBounds.top);
        !          4901:                     rclTrg.right  = min (rclTrg.right, rclBounds.right);
        !          4902:                     rclTrg.bottom = min (rclTrg.bottom, rclBounds.bottom);
        !          4903: 
        !          4904:                     // define the cx & cy for the blit.
        !          4905: 
        !          4906:                     sizBlt.cx = rclTrg.right  - rclTrg.left;
        !          4907:                     sizBlt.cy = rclTrg.bottom - rclTrg.top;
        !          4908: 
        !          4909:                     // calculate the cx & cy shift (due to clipping) for the source.
        !          4910:                     // and define the upper left corner of the source.
        !          4911: 
        !          4912:                     ptSrc.x = pptlSrc->x + (rclTrg.left - prclTrg->left);
        !          4913:                     ptSrc.y = pptlSrc->y + (rclTrg.top  - prclTrg->top);
        !          4914: 
        !          4915:                     // Calculate the first word to blit
        !          4916: 
        !          4917:                     pwFirstWord = (PWORD) (((PBYTE) psoSrc->pvScan0)
        !          4918:                                  + (ptSrc.y * lSrcDelta) + (ptSrc.x / 2));
        !          4919: 
        !          4920:                     vSetS3ClipRect(ppdev, &rclTrg);
        !          4921:                     vLowLevel4BppHostToScrnWithRop(ppdev, (PPOINT) &rclTrg, &sizBlt,
        !          4922:                                                ptSrc.x,
        !          4923:                                                pwFirstWord, lSrcDelta, pxlo, s3Rop);
        !          4924:                 }
        !          4925:             }
        !          4926:         } while (bMore);
        !          4927:     }
        !          4928: 
        !          4929:     vResetS3Clipping(ppdev);
        !          4930: 
        !          4931:     return (TRUE);
        !          4932: 
        !          4933: }
        !          4934: 
        !          4935: 
        !          4936: 
        !          4937: 
        !          4938: /*****************************************************************************
        !          4939:  * Low Level 4bpp host to screen copy.
        !          4940:  ****************************************************************************/
        !          4941: VOID vLowLevel4BppHostToScrnWithRop(
        !          4942:     PPDEV   ppdev,
        !          4943:     PPOINT  pptTrg,
        !          4944:     PSIZE   psizBlt,
        !          4945:     INT     xSrc,
        !          4946:     PWORD   pwFirstWord,
        !          4947:     INT     lSrcDelta,
        !          4948:     XLATEOBJ *pxlo,
        !          4949:     WORD    s3Rop)
        !          4950: {
        !          4951: PBYTE   pb4Bpp;
        !          4952: INT     i, j, k, x, cx, cy, nSrcBytes, xClip;
        !          4953: WORD    Cmd;
        !          4954: PULONG  pulXlate;
        !          4955: 
        !          4956: BYTE    LineBuff8Bpp[DRIVERS_MAX_CX];
        !          4957: 
        !          4958:         if (pxlo->flXlate & XO_TABLE)
        !          4959:         {
        !          4960:             pulXlate = pxlo->pulXlate;
        !          4961:         }
        !          4962:         else
        !          4963:         {
        !          4964:             pulXlate = XLATEOBJ_piVector(pxlo);
        !          4965:         }
        !          4966: 
        !          4967:         pb4Bpp = (PBYTE) pwFirstWord;
        !          4968: 
        !          4969:         x = pptTrg->x;
        !          4970:         cx = psizBlt->cx;
        !          4971:         cy = psizBlt->cy;
        !          4972: 
        !          4973:         // Take care of the non-byte aligned source case.
        !          4974: 
        !          4975:         if (xSrc & 0x1)
        !          4976:         {
        !          4977:             xClip = x;
        !          4978:             x--;
        !          4979:             cx++;
        !          4980: 
        !          4981:             FIFOWAIT(FIFO_1_EMPTY);
        !          4982:             outpw (MULTIFUNC_CNTL, (CLIP_LEFT   | xClip));
        !          4983:         }
        !          4984: 
        !          4985:         nSrcBytes = (cx + 1) / 2;
        !          4986: 
        !          4987:         // Setup the S3 chip.
        !          4988: 
        !          4989:         Cmd = RECTANGLE_FILL | BYTE_SWAP          | BUS_SIZE_16 | WAIT |
        !          4990:               DRAW           | DRAWING_DIR_TBLRXM | DIR_TYPE_XY |
        !          4991:               LAST_PIXEL_ON  | SINGLE_PIXEL       | WRITE;
        !          4992: 
        !          4993:         FIFOWAIT(FIFO_7_EMPTY);
        !          4994: 
        !          4995:         TEST_AND_SET_FRGD_MIX(SRC_CPU_DATA | s3Rop);
        !          4996:         outpw(MULTIFUNC_CNTL, (DATA_EXTENSION | ALL_ONES));
        !          4997: 
        !          4998:         outpw(CUR_X, x);
        !          4999:         outpw(CUR_Y, pptTrg->y);
        !          5000:         outpw(RECT_WIDTH, cx - 1);
        !          5001:         outpw(MULTIFUNC_CNTL, (RECT_HEIGHT | cy - 1));
        !          5002: 
        !          5003:         GPWAIT();
        !          5004: 
        !          5005:         outpw(CMD, Cmd);
        !          5006: 
        !          5007:         CHECK_DATA_READY;
        !          5008: 
        !          5009:         // Now transfer the data.
        !          5010: 
        !          5011:         for (i = 0; i < cy; i++)
        !          5012:         {
        !          5013:             for (k = 0, j = 0; j < nSrcBytes; j++)
        !          5014:             {
        !          5015:                 LineBuff8Bpp[k++] = (BYTE) pulXlate[(pb4Bpp[j] & 0xF0) >> 4];
        !          5016:                 LineBuff8Bpp[k++] = (BYTE) pulXlate[pb4Bpp[j] & 0x0F];
        !          5017:             }
        !          5018: 
        !          5019:             vDataPortOut(ppdev, (PWORD) LineBuff8Bpp, nSrcBytes);
        !          5020:             pb4Bpp += lSrcDelta;
        !          5021:         }
        !          5022: 
        !          5023:         CHECK_DATA_COMPLETE;
        !          5024: 
        !          5025:         return;
        !          5026: 
        !          5027: }

unix.superglobalmegacorp.com

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