/******************************Module*Header*******************************\ * Module Name: bltmil24.c * * Contains the low-level blt functions for the Millenium at 24bpp. * * Hopefully, if you're basing your display driver on this code, to * support all of DrvBitBlt and DrvCopyBits, you'll only have to implement * the following routines. You shouldn't have to modify much in * 'bitblt.c'. I've tried to make these routines as few, modular, simple, * and efficient as I could, while still accelerating as many calls as * possible that would be cost-effective in terms of performance wins * versus size and effort. * * Note: In the following, 'relative' coordinates refers to coordinates * that haven't yet had the offscreen bitmap (DFB) offset applied. * 'Absolute' coordinates have had the offset applied. For example, * we may be told to blt to (1, 1) of the bitmap, but the bitmap may * be sitting in offscreen memory starting at coordinate (0, 768) -- * (1, 1) would be the 'relative' start coordinate, and (1, 769) * would be the 'absolute' start coordinate'. * * Copyright (c) 1992-1996 Microsoft Corporation * Copyright (c) 1993-1996 Matrox Electronic Systems, Ltd. \**************************************************************************/ #include "precomp.h" /******************************Public*Routine******************************\ * VOID vMilPatRealize24bpp * * Download the Color Brush to the Color brush cache in the Storm offscreen * memory. We download a 16x8 brush. We'll use direct frame buffer access. * * There are some hardware restrictions concerning the way that a pattern * must be stored in memory: * - the first pixel of the pattern must be stored so that the first pixel * address mod 256 is 0 or 16; * - each line of 16 pixels is stored continuously, but there must be a * difference of 32 in the pixel addresses of successive pattern lines. * This means that we will store patterns in the following way: * * +----+---------------+---------------+---------------+---------------+ * | | Pattern 0 | Pattern 1 | * |Line| | |1 1 1 1 1 1 1 1|1 1 1 1 1 1 1 1| * | |0 1 2 3 4 5 6 7|8 9 a b c d e f|0 1 2 3 4 5 6 7|8 9 a b c d e f| * +----+---------------+---------------+---------------+---------------+ * | 0 |* * * * * * * * | o o o o| * | 1 | * * * * * * * *| o o o o | * | 2 |* * * * * * * * | o o o o | * | 3 | * * * * * * * *|o o o o | * | 4 |* * * * * * * * | o o o o| * | 5 | * * * * * * * *| o o o o | * | 6 |* * * * * * * * | o o o o | * | 7 | * * * * * * * *|o o o o | * +----+---------------+---------------+---------------+---------------+ * * where a given pixel address is * FirstPixelAddress + Line*0x20 + Pattern*0x10 + xPat. * \**************************************************************************/ VOID vMilPatRealize24bpp( PDEV* ppdev, RBRUSH* prb) { BYTE* pjBase; BRUSHENTRY* pbe; LONG iBrushCache; ULONG i; ULONG j; ULONG* pulBrush; ULONG* pulDst; ULONG lDeltaPat; pjBase = ppdev->pjBase; // Allocate a new off-screen cache brush entry for the brush. iBrushCache = ppdev->iBrushCache; pbe = &ppdev->pbe[iBrushCache]; iBrushCache++; if (iBrushCache >= ppdev->cBrushCache) iBrushCache = 0; ppdev->iBrushCache = iBrushCache; // Update our links. pbe->prbVerify = prb; prb->apbe[IBOARD(ppdev)] = pbe; // Point to the pattern bits. pulBrush = prb->aulPattern; pulDst = (ULONG*) (pbe->pvScan0); pulDst = (ULONG*) (ppdev->pjScreen + (pbe->ulLinear * 3)); DISPDBG((1,"pulBrush = %x", pulBrush)); DISPDBG((1,"pulDst = %x", pulDst)); { ULONG y; for (y = 0; y < 8; y++) { DISPDBG((2, "%02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x", ((BYTE*)pulBrush)[y*48 + 0], ((BYTE*)pulBrush)[y*48 + 1], ((BYTE*)pulBrush)[y*48 + 2], ((BYTE*)pulBrush)[y*48 + 3], ((BYTE*)pulBrush)[y*48 + 4], ((BYTE*)pulBrush)[y*48 + 5], ((BYTE*)pulBrush)[y*48 + 6], ((BYTE*)pulBrush)[y*48 + 7], ((BYTE*)pulBrush)[y*48 + 8], ((BYTE*)pulBrush)[y*48 + 9], ((BYTE*)pulBrush)[y*48 + 10], ((BYTE*)pulBrush)[y*48 + 11], ((BYTE*)pulBrush)[y*48 + 12], ((BYTE*)pulBrush)[y*48 + 13], ((BYTE*)pulBrush)[y*48 + 14], ((BYTE*)pulBrush)[y*48 + 15], ((BYTE*)pulBrush)[y*48 + 16], ((BYTE*)pulBrush)[y*48 + 17], ((BYTE*)pulBrush)[y*48 + 18], ((BYTE*)pulBrush)[y*48 + 19], ((BYTE*)pulBrush)[y*48 + 20], ((BYTE*)pulBrush)[y*48 + 21], ((BYTE*)pulBrush)[y*48 + 22], ((BYTE*)pulBrush)[y*48 + 23], ((BYTE*)pulBrush)[y*48 + 24], ((BYTE*)pulBrush)[y*48 + 25], ((BYTE*)pulBrush)[y*48 + 26], ((BYTE*)pulBrush)[y*48 + 27], ((BYTE*)pulBrush)[y*48 + 28], ((BYTE*)pulBrush)[y*48 + 29], ((BYTE*)pulBrush)[y*48 + 30], ((BYTE*)pulBrush)[y*48 + 31], ((BYTE*)pulBrush)[y*48 + 32], ((BYTE*)pulBrush)[y*48 + 33], ((BYTE*)pulBrush)[y*48 + 34], ((BYTE*)pulBrush)[y*48 + 35], ((BYTE*)pulBrush)[y*48 + 36], ((BYTE*)pulBrush)[y*48 + 37], ((BYTE*)pulBrush)[y*48 + 38], ((BYTE*)pulBrush)[y*48 + 39], ((BYTE*)pulBrush)[y*48 + 40], ((BYTE*)pulBrush)[y*48 + 41], ((BYTE*)pulBrush)[y*48 + 42], ((BYTE*)pulBrush)[y*48 + 43], ((BYTE*)pulBrush)[y*48 + 44], ((BYTE*)pulBrush)[y*48 + 45], ((BYTE*)pulBrush)[y*48 + 46], ((BYTE*)pulBrush)[y*48 + 47] )); } } START_DIRECT_ACCESS_STORM(ppdev, pjBase); for (i = 8; i != 0 ; i--) { for (j = 0; j < 12; j++) { pulDst[j] = *pulBrush++; } pulDst += (8 * 3); // dwords! } END_DIRECT_ACCESS_STORM(ppdev, pjBase); } /***************************************************************************** * VOID vMilFillPat24bpp * * 24bpp patterned color fills for Storm. ****************************************************************************/ VOID vMilFillPat24bpp( PDEV* ppdev, LONG c, // Can't be zero RECTL* prcl, // List of rectangles to be filled, in relative // coordinates ULONG rop4, // Rop4 RBRUSH_COLOR rbc, // rbc.prb points to brush realization structure POINTL* pptlBrush) // Pattern alignment { BRUSHENTRY* pbe; LONG xOffset; LONG yOffset; LONG xLeft; LONG yTop; LONG xBrush; LONG yBrush; LONG lSrcAdd; ULONG ulLinear; BYTE* pjBase; ULONG ulHwMix; ASSERTDD(!(rbc.prb->fl & RBRUSH_2COLOR), "Can't do 2 colour brushes here"); // We have to ensure that no other brush took our spot in off-screen // memory, or we might have to realize the brush for the first time. pbe = rbc.prb->apbe[IBOARD(ppdev)]; if (pbe->prbVerify != rbc.prb) { vMilPatRealize24bpp(ppdev, rbc.prb); pbe = rbc.prb->apbe[IBOARD(ppdev)]; } pjBase = ppdev->pjBase; xOffset = ppdev->xOffset; yOffset = ppdev->yOffset; lSrcAdd = ppdev->lPatSrcAdd; CHECK_FIFO_SPACE(pjBase, 6); CP_WRITE(pjBase, DWG_AR5, 32); // Source (pattern) pitch. ppdev->HopeFlags = SIGN_CACHE; if ((rop4 & 0x000000FF) == 0x000000F0) { // The rop is PATCOPY. CP_WRITE(pjBase, DWG_DWGCTL, (opcode_BITBLT + atype_RPL + sgnzero_ZERO + shftzero_ZERO + bop_SRCCOPY + bltmod_BFCOL + pattern_ON + transc_BG_OPAQUE)); } else { ulHwMix = (rop4 & 0x03) + ((rop4 & 0x30) >> 2); CP_WRITE(pjBase, DWG_DWGCTL, (opcode_BITBLT + atype_RSTR + sgnzero_ZERO + shftzero_ZERO + bltmod_BFCOL + pattern_ON + transc_BG_OPAQUE + (ulHwMix << 16))); } // The pattern setup is complete. while(TRUE) { // Take into account the brush origin. The upper left pel of the // brush should be aligned here in the destination surface. yTop = prcl->top; xLeft = prcl->left; xBrush = (xLeft - pptlBrush->x) & 7; yBrush = (yTop - pptlBrush->y) & 7; ulLinear = pbe->ulLinear + (yBrush << 5) + xBrush; CP_WRITE(pjBase, DWG_AR3, ulLinear); CP_WRITE(pjBase, DWG_AR0, (ulLinear +7)); CP_WRITE(pjBase, DWG_FXBNDRY, (((prcl->right + xOffset - 1) << bfxright_SHIFT) | ((xLeft + xOffset) & bfxleft_MASK))); // ylength_MASK not is needed since coordinates are within range CP_START(pjBase, DWG_YDSTLEN, (((yTop + yOffset ) << yval_SHIFT) | ((prcl->bottom - yTop)))); if (--c == 0) return; CHECK_FIFO_SPACE(pjBase, 4); prcl++; } }