/*****************************************************************************\ * Smart 64k Color Bank Manager * * Copyright (c) 1992 Microsoft Corporation \*****************************************************************************/ #include "driver.h" /*****************************************************************************\ * pcoBankStart - Start the bank enumeration using the clip object. * * Used when the destination is the screen and we can't do the clipping * ourselves (as we can for blt's). \*****************************************************************************/ CLIPOBJ* pcoBankStart( PPDEV ppdev, RECTL* prclScans, SURFOBJ* pso, CLIPOBJ* pco) { LONG iTopScan; // Remember what the last scan is that we're going to, and // make sure we only try to go as far as we need to. It could // happen that when get a prclScans bigger than the screen: ppdev->iLastScan = min(prclScans->bottom, (LONG) ppdev->cyScreen); // Adjust for those weird cases where we're asked to start enumerating // above or below the bottom of the screen: iTopScan = max(0, prclScans->top); iTopScan = min(iTopScan, (LONG) ppdev->cyScreen - 1); if (pco->iDComplexity != DC_TRIVIAL) { iTopScan = max(pco->rclBounds.top, iTopScan); ppdev->iLastScan = min(pco->rclBounds.bottom, ppdev->iLastScan); } // Map in the top bank: if (iTopScan < ppdev->rcl1WindowClip.top || iTopScan >= ppdev->rcl1WindowClip.bottom) { ppdev->pfnBankControl(ppdev, iTopScan, JustifyTop); } pso->pvScan0 = ppdev->pvBitmapStart; if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL)) { // The call may have come down to us as having no clipping, but // we have to clip to the banks, so use our own clip object: pco = ppdev->pcoNull; pco->rclBounds = ppdev->rcl1WindowClip; ASSERTVGA(pco->fjOptions & OC_BANK_CLIP, "Default BANK_CLIP not set"); ASSERTVGA(pco->iDComplexity == DC_RECT, "Default clip not DC_RECT"); } else { // Save the engine's clip object data that we'll be tromping on: ppdev->rclSaveBounds = pco->rclBounds; ppdev->iSaveDComplexity = pco->iDComplexity; ppdev->fjSaveOptions = pco->fjOptions; // Let engine know it has to pay attention to the rclBounds of the // clip object: pco->fjOptions |= OC_BANK_CLIP; // Use the bank bounds if they are tighter than the existing // bounds. if (pco->rclBounds.top <= ppdev->rcl1WindowClip.top) pco->rclBounds.top = ppdev->rcl1WindowClip.top; if (pco->rclBounds.bottom >= ppdev->rcl1WindowClip.bottom) pco->rclBounds.bottom = ppdev->rcl1WindowClip.bottom; if ((pco->rclBounds.top >= pco->rclBounds.bottom) || (pco->rclBounds.left >= pco->rclBounds.right)) { // It's conceivable that we could get a situation where our // draw rectangle is completely disjoint from the specified // rectangle's rclBounds. Make sure we don't puke on our // shoes: pco->rclBounds.left = 0; pco->rclBounds.top = 0; pco->rclBounds.right = 0; pco->rclBounds.bottom = 0; ppdev->iLastScan = 0; } } return(pco); } /*****************************************************************************\ * bBankEnum - Continue the bank enumeration. \*****************************************************************************/ BOOL bBankEnum(PPDEV ppdev, SURFOBJ* pso, CLIPOBJ* pco) { LONG yNewTop = ppdev->rcl1WindowClip.bottom; if (yNewTop >= ppdev->iLastScan) { // Okay, that was the last bank, so restore our structures: if (pco != ppdev->pcoNull) { pco->rclBounds = ppdev->rclSaveBounds; pco->iDComplexity = ppdev->iSaveDComplexity; pco->fjOptions = ppdev->fjSaveOptions; } return(FALSE); } ppdev->pfnBankControl(ppdev, yNewTop, JustifyTop); ASSERTVGA(yNewTop >= ppdev->rcl1WindowClip.top && yNewTop < ppdev->rcl1WindowClip.bottom, "Out of bounds"); // Adjust the pvScan0 because we've moved the window to view // a different area: pso->pvScan0 = ppdev->pvBitmapStart; // Set the bounds to the new bank: pco->rclBounds.top = yNewTop; pco->rclBounds.left = ppdev->rcl1WindowClip.left; pco->rclBounds.bottom = ppdev->rcl1WindowClip.bottom; pco->rclBounds.right = ppdev->rcl1WindowClip.right; if (pco != ppdev->pcoNull) { // If we were originally given a non-trivial clip object, we have // to clip to the original bounds: if (pco->rclBounds.left <= ppdev->rclSaveBounds.left) pco->rclBounds.left = ppdev->rclSaveBounds.left; if (pco->rclBounds.right >= ppdev->rclSaveBounds.right) pco->rclBounds.right = ppdev->rclSaveBounds.right; if (pco->rclBounds.bottom >= ppdev->rclSaveBounds.bottom) pco->rclBounds.bottom = ppdev->rclSaveBounds.bottom; } return(TRUE); } /***************************************************************************\ * vBankStartBltSrc - Start the bank enumeration for when the screen is * the source. \***************************************************************************/ VOID vBankStartBltSrc( PPDEV ppdev, SURFOBJ* pso, POINTL* pptlSrc, RECTL* prclDest, POINTL* pptlNewSrc, RECTL* prclNewDest) { LONG xRightSrc; LONG yBottomSrc; LONG iTopScan = max(0, pptlSrc->y); if (iTopScan >= (LONG) ppdev->cyScreen) { // In some instances we may be asked to start on a scan below the screen. // Since we obviously won't be drawing anything, don't bother mapping in // a bank: return; } // Map in the bank: if (iTopScan < ppdev->rcl1WindowClip.top || iTopScan >= ppdev->rcl1WindowClip.bottom) { ppdev->pfnBankControl(ppdev, iTopScan, JustifyTop); } if (ppdev->rcl1WindowClip.right <= pptlSrc->x) { // We have to watch out for those rare cases where we're starting // on a broken raster and we won't be drawing on the first part: ASSERTVGA(ppdev->flBank & BANK_BROKEN_RASTER1, "Weird start bounds"); ppdev->pfnBankNext(ppdev); } pso->pvScan0 = ppdev->pvBitmapStart; // Adjust the source: pptlNewSrc->x = pptlSrc->x; pptlNewSrc->y = pptlSrc->y; // Adjust the destination: prclNewDest->left = prclDest->left; prclNewDest->top = prclDest->top; yBottomSrc = pptlSrc->y + prclDest->bottom - prclDest->top; prclNewDest->bottom = min(ppdev->rcl1WindowClip.bottom, yBottomSrc); prclNewDest->bottom += prclDest->top - pptlSrc->y; xRightSrc = pptlSrc->x + prclDest->right - prclDest->left; prclNewDest->right = min(ppdev->rcl1WindowClip.right, xRightSrc); prclNewDest->right += prclDest->left - pptlSrc->x; } /***************************************************************************\ * bBankEnumBltSrc - Continue the bank enumeration for when the screen is * the source. \***************************************************************************/ BOOL bBankEnumBltSrc( PPDEV ppdev, SURFOBJ* pso, POINTL* pptlSrc, RECTL* prclDest, POINTL* pptlNewSrc, RECTL* prclNewDest) { LONG xLeftSrc; LONG xRightSrc; LONG yBottomSrc; LONG cx = prclDest->right - prclDest->left; LONG cy = prclDest->bottom - prclDest->top; LONG dx; LONG dy; LONG yBottom = min(pptlSrc->y + cy, (LONG) ppdev->cyScreen); LONG yNewTop = ppdev->rcl1WindowClip.bottom; if (ppdev->flBank & BANK_BROKEN_RASTER1) { ppdev->pfnBankNext(ppdev); if (ppdev->rcl1WindowClip.left >= pptlSrc->x + cx) { if (ppdev->rcl1WindowClip.bottom < yBottom) ppdev->pfnBankNext(ppdev); else { // We're done: return(FALSE); } } } else if (yNewTop < yBottom) { ppdev->pfnBankControl(ppdev, yNewTop, JustifyTop); if (ppdev->rcl1WindowClip.right <= pptlSrc->x) { ASSERTVGA(ppdev->flBank & BANK_BROKEN_RASTER1, "Weird bounds"); ppdev->pfnBankNext(ppdev); } } else { // We're done: return(FALSE); } // Adjust the source: pso->pvScan0 = ppdev->pvBitmapStart; pptlNewSrc->x = max(ppdev->rcl1WindowClip.left, pptlSrc->x); pptlNewSrc->y = yNewTop; // Adjust the destination: dy = prclDest->top - pptlSrc->y; // y delta from source to dest prclNewDest->top = yNewTop + dy; yBottomSrc = pptlSrc->y + cy; prclNewDest->bottom = min(ppdev->rcl1WindowClip.bottom, yBottomSrc) + dy; dx = prclDest->left - pptlSrc->x; // x delta from source to dest xLeftSrc = pptlSrc->x; prclNewDest->left = pptlNewSrc->x + dx; xRightSrc = pptlSrc->x + cx; prclNewDest->right = min(ppdev->rcl1WindowClip.right, xRightSrc) + dx; return(TRUE); } /***************************************************************************\ * vBankStartBltDest - Start the bank enumeration for when the screen is * the destination. \***************************************************************************/ VOID vBankStartBltDest( PPDEV ppdev, SURFOBJ* pso, POINTL* pptlSrc, RECTL* prclDest, POINTL* pptlNewSrc, RECTL* prclNewDest) { LONG iTopScan = max(0, prclDest->top); if (iTopScan >= (LONG) ppdev->cyScreen) { // In some instances we may be asked to start on a scan below the screen. // Since we obviously won't be drawing anything, don't bother mapping in // a bank: return; } // Map in the bank: if (iTopScan < ppdev->rcl1WindowClip.top || iTopScan >= ppdev->rcl1WindowClip.bottom) { ppdev->pfnBankControl(ppdev, iTopScan, JustifyTop); } if (ppdev->rcl1WindowClip.right <= prclDest->left) { // We have to watch out for those rare cases where we're starting // on a broken raster and we won't be drawing on the first part: ASSERTVGA(ppdev->flBank & BANK_BROKEN_RASTER1, "Weird start bounds"); ppdev->pfnBankNext(ppdev); } pso->pvScan0 = ppdev->pvBitmapStart; // Adjust the destination: prclNewDest->left = prclDest->left; prclNewDest->top = prclDest->top; prclNewDest->bottom = min(ppdev->rcl1WindowClip.bottom, prclDest->bottom); prclNewDest->right = min(ppdev->rcl1WindowClip.right, prclDest->right); // Adjust the source if there is one: if (pptlSrc != NULL) *pptlNewSrc = *pptlSrc; } /***************************************************************************\ * bBankEnumBltDest - Continue the bank enumeration for when the screen is * the destination. \***************************************************************************/ BOOL bBankEnumBltDest( PPDEV ppdev, SURFOBJ* pso, POINTL* pptlSrc, RECTL* prclDest, POINTL* pptlNewSrc, RECTL* prclNewDest) { LONG yBottom = min(prclDest->bottom, (LONG) ppdev->cyScreen); LONG yNewTop = ppdev->rcl1WindowClip.bottom; if (ppdev->flBank & BANK_BROKEN_RASTER1) { ppdev->pfnBankNext(ppdev); if (ppdev->rcl1WindowClip.left >= prclDest->right) { if (ppdev->rcl1WindowClip.bottom < yBottom) ppdev->pfnBankNext(ppdev); else { // We're done: return(FALSE); } } } else if (yNewTop < yBottom) { ppdev->pfnBankControl(ppdev, yNewTop, JustifyTop); if (ppdev->rcl1WindowClip.right <= prclDest->left) { ASSERTVGA(ppdev->flBank & BANK_BROKEN_RASTER1, "Weird bounds"); ppdev->pfnBankNext(ppdev); } } else { // We're done: return(FALSE); } pso->pvScan0 = ppdev->pvBitmapStart; // Adjust the destination: prclNewDest->top = yNewTop; prclNewDest->left = max(ppdev->rcl1WindowClip.left, prclDest->left); prclNewDest->bottom = min(ppdev->rcl1WindowClip.bottom, prclDest->bottom); prclNewDest->right = min(ppdev->rcl1WindowClip.right, prclDest->right); // Adjust the source if there is one: if (pptlSrc != NULL) { pptlNewSrc->x = pptlSrc->x + (prclNewDest->left - prclDest->left); pptlNewSrc->y = pptlSrc->y + (prclNewDest->top - prclDest->top); } return(TRUE); }