File:  [WindowsNT SDKs] / ntddk / src / video / displays / vga256 / brush.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 18:31:12 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: ntddk-nov-1993, HEAD
Microsoft Windows NT Build 511 (DDK SDK) 11-01-1993

/******************************Module*Header*******************************\
* Module Name: Brush.c
*
* Brush support.
*
* Copyright (c) 1992-1993 Microsoft Corporation
*
\**************************************************************************/

#include "driver.h"

/****************************************************************************
 * DrvRealizeBrush
 ***************************************************************************/

BOOL DrvRealizeBrush(
BRUSHOBJ* pbo,
SURFOBJ*  psoTarget,
SURFOBJ*  psoPattern,
SURFOBJ*  psoMask,
XLATEOBJ* pxlo,
ULONG     iHatch)
{
    RBRUSH* prb;        // Pointer to where realization goes
    ULONG*  pulSrc;     // Temporary pointer
    ULONG*  pulDst;     // Temporary pointer
    BYTE*   pjSrc;
    BYTE*   pjDst;
    ULONG*  pulRBits;   // Points to RBRUSH pattern bits
    BYTE    jBkColor;
    BYTE    jFgColor;
    LONG    i;
    LONG    j;

    PPDEV   ppdev = (PPDEV) psoTarget->dhsurf;

    // For now, we only accelerate patterns using the latches, and we
    // sometimes need offscreen memory as a temporary work space to
    // initialize the latches for 2-color patterns:

    if ((ppdev->fl & (DRIVER_PLANAR_CAPABLE | DRIVER_HAS_OFFSCREEN)) !=
        (DRIVER_PLANAR_CAPABLE | DRIVER_HAS_OFFSCREEN) )
    {
        return(FALSE);
    }

    // See if it's a default hatch brush:

    if (iHatch < HS_DDI_MAX)
    {
        DISPDBG((1, "\n  RBrush: Default"));

        prb = BRUSHOBJ_pvAllocRbrush(pbo, sizeof(RBRUSH));
        if (prb == NULL)
            return(FALSE);

        prb->xBrush    = 0;
        prb->ulBkColor = (pxlo->pulXlate[0] & 0xff);
        prb->ulFgColor = (pxlo->pulXlate[1] & 0xff);

        if (prb->ulFgColor == 0xff && prb->ulBkColor == 0x00)
        {
            prb->fl = RBRUSH_BLACKWHITE;
            memcpy(&prb->aulPattern[0],
                   &gaaulPlanarPat[iHatch][0],
                   8 * sizeof(DWORD));
        }
        else if (prb->ulFgColor == 0x00 && prb->ulBkColor == 0xff)
        {
            // We have to invert the brush:

            prb->fl = RBRUSH_BLACKWHITE;
            for (i = 0; i < 8; i++)
            {
                prb->aulPattern[i] = ~gaaulPlanarPat[iHatch][i];
            }
        }
        else
        {
            prb->fl = RBRUSH_2COLOR;
            memmove(&prb->aulPattern[0], &gaaulPlanarPat[iHatch][0], 32);
        }

        return(TRUE);
    }

    // We only accelerate 8x8 patterns:

    if (psoPattern->sizlBitmap.cx != 8 || psoPattern->sizlBitmap.cy != 8)
        return(FALSE);

    // We only implement n-color patterns on devices that have multiple
    // or separate read/write banks:

    if (ppdev->vbtPlanarType == VideoBanked1RW)
        return(FALSE);

    // We also only handle 1bpp, 4bpp and 8bpp patterns:

    if (psoPattern->iBitmapFormat > BMF_8BPP)
        return(FALSE);

    // At this point, we're definitely going to realize the brush:

    prb = BRUSHOBJ_pvAllocRbrush(pbo, sizeof(RBRUSH));
    if (prb == NULL)
        return(FALSE);

    pulRBits = &prb->aulPattern[0];

    DISPDBG((1, "\n  RBrush: "));

    // If 8bpp or 4bpp, copy the bitmap to our local buffer:

    if (psoPattern->iBitmapFormat == BMF_1BPP)
    {
        ULONG ulFlippedGlyph;

        DISPDBG((1, "1bpp "));

        // First, convert the bits to our desired format:

        pjSrc  = psoPattern->pvScan0;
        pulDst = pulRBits;
        for (i = 8; i > 0; i--)
        {
            // We want to take the byte with bits 76543210 and convert it
            // to the word 4567012301234567.  The pjGlyphFlipTable gives
            // us 45670123 from 76543210.

            ulFlippedGlyph = (ULONG) ppdev->pjGlyphFlipTable[*pjSrc];
            *pulDst = (ulFlippedGlyph << 8) | ((ulFlippedGlyph & 15) << 4) |
                      (ulFlippedGlyph >> 4);

            pulDst++;
            pjSrc += psoPattern->lDelta;
        }

        // Now initialize the rest of the RBrush fields:

        prb->xBrush    = 0;
        prb->ulBkColor = (pxlo->pulXlate[0] & 0xff);
        prb->ulFgColor = (pxlo->pulXlate[1] & 0xff);

        if (prb->ulFgColor == 0xff && prb->ulBkColor == 0x00)
        {
            prb->fl = RBRUSH_BLACKWHITE;
        }
        else if (prb->ulFgColor == 0x00 && prb->ulBkColor == 0xff)
        {
            // We have to invert the brush:

            prb->fl = RBRUSH_BLACKWHITE;
            for (i = 0; i < 8; i++)
            {
                prb->aulPattern[i] = ~prb->aulPattern[i];
            }
        }
        else
        {
            prb->fl = RBRUSH_2COLOR;
        }

        return(TRUE);
    }
    else if (psoPattern->iBitmapFormat == BMF_8BPP)
    {

        if (pxlo == NULL || pxlo->flXlate & XO_TRIVIAL)
        {
            pulSrc = psoPattern->pvScan0;
            pulDst = pulRBits;

            DISPDBG((1, "8bpp noxlate "));

            // 8bpp no translate case:

            for (i = 4; i > 0; i--)
            {
                *(pulDst)     = *(pulSrc);
                *(pulDst + 1) = *(pulSrc + 1);
                pulSrc = (ULONG*) ((BYTE*) pulSrc + psoPattern->lDelta);

                *(pulDst + 2) = *(pulSrc);
                *(pulDst + 3) = *(pulSrc + 1);

                pulSrc = (ULONG*) ((BYTE*) pulSrc + psoPattern->lDelta);
                pulDst += 4;
            }
        }
        else
        {
            pjSrc = (BYTE*) psoPattern->pvScan0;
            pjDst = (BYTE*) pulRBits;

            DISPDBG((1, "8bpp xlate "));

            // 8bpp translate case:

            for (i = 8; i > 0; i--)
            {
                for (j = 8; j > 0; j--)
                {
                    *pjDst++ = (BYTE) pxlo->pulXlate[*pjSrc++];
                }

                pjSrc += psoPattern->lDelta - 8;
            }
        }
    }
    else
    {
        DISPDBG((1, "4bpp xlate "));

        ASSERTVGA(psoPattern->iBitmapFormat == BMF_4BPP, "Extra case added?");

        // 4bpp case:

        pjSrc = (BYTE*) psoPattern->pvScan0;
        pjDst = (BYTE*) pulRBits;

        for (i = 8; i > 0; i--)
        {
            // Inner loop is repeated only 4 times because each loop handles
            // 2 pixels:

            for (j = 4; j > 0; j--)
            {
                *pjDst++ = (BYTE) pxlo->pulXlate[*pjSrc >> 4];
                *pjDst++ = (BYTE) pxlo->pulXlate[*pjSrc & 15];
                pjSrc++;
            }

            pjSrc += psoPattern->lDelta - 4;
        }
    }

    // We want to check if the 4bpp or 8bpp patterns are actually
    // only two colors:

    if (b2ColorBrush(pulRBits, &jFgColor, &jBkColor))
    {
        DISPDBG((1, "2 color "));

        // ??? We could actually also handle this case even if we have only
        // 1 r/w window in planar format:

        prb->xBrush    = 0;
        prb->ulBkColor = (ULONG) jBkColor;
        prb->ulFgColor = (ULONG) jFgColor;
        prb->fl        = RBRUSH_2COLOR;

        if (jFgColor == 0x00 && jBkColor == 0xff)
        {
            // Monochrome brushes always have to have the '0' bits
            // as black and the '1' bits as white, so we'll have to
            // invert the 1bpp pattern:

            prb->fl = RBRUSH_BLACKWHITE;
            for (i = 0; i < 8; i++)
            {
                prb->aulPattern[i] = ~prb->aulPattern[i];
            }
        }

        return(TRUE);
    }

    // For n-color brushes, we maintain a brush cache in offscreen memory.
    // If the DRIVER_USE_OFFSCREEN flag isn't set (i.e., the offscreen
    // memory isn't being refreshed), the cache is pretty useless.  In that
    // case, we simply disable n-color patterns:

    if ((ppdev->fl & DRIVER_USE_OFFSCREEN) == 0)
    {
        return(FALSE);
    }

    prb->fl     = RBRUSH_NCOLOR;
    prb->cy     = 8;
    prb->cyLog2 = 3;

    // xBrush is the brush alignment for the cached brush, and this value
    // will get compared to (pptlBrush->x & 7) to see if the cache brush
    // is correctly aligned with the brush requested.  Since it will never
    // match with -1, the brush will be correctly aligned and placed in
    // the cache (which, of course, is what we want to finish our
    // initialization):

    prb->xBrush = -1;

    // Copy those bitmap bits:

    // See if pattern is really only 4 scans long:

    if (pulRBits[0] == pulRBits[8]  && pulRBits[1] == pulRBits[9]  &&
        pulRBits[2] == pulRBits[10] && pulRBits[3] == pulRBits[11] &&
        pulRBits[4] == pulRBits[12] && pulRBits[5] == pulRBits[13] &&
        pulRBits[6] == pulRBits[14] && pulRBits[7] == pulRBits[15])
    {
        prb->cy     = 4;
        prb->cyLog2 = 2;

        // See if pattern is really only 2 scans long:

        if (pulRBits[0] == pulRBits[4] && pulRBits[1] == pulRBits[5] &&
            pulRBits[2] == pulRBits[6] && pulRBits[3] == pulRBits[7])
        {
            DISPDBG((1, "cy = 2 "));

            prb->cy     = 2;
            prb->cyLog2 = 1;
        }
        else
        {
            DISPDBG((1, "cy = 4 "));
        }
    }

    // See if pattern is really only 4 pels wide:

    pulDst = pulRBits;
    for (i = prb->cy / 2; i > 0; i--)
    {
        if (*(pulDst    ) != *(pulDst + 1) ||
            *(pulDst + 2) != *(pulDst + 3))
            goto done_this_realize_brush_stuff;

        pulDst += 4;
    }

    DISPDBG((1, "4pels wide"));

    prb->fl |= RBRUSH_4PELS_WIDE;

done_this_realize_brush_stuff:

    return(TRUE);
}

unix.superglobalmegacorp.com

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