You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
289 lines
8.0 KiB
289 lines
8.0 KiB
/******************************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);
|
|
}
|
|
|
|
// 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((2, "\n RBrush: "));
|
|
|
|
// If 8bpp or 4bpp, copy the bitmap to our local buffer:
|
|
|
|
if (psoPattern->iBitmapFormat == BMF_1BPP)
|
|
{
|
|
ULONG ulFlippedGlyph;
|
|
|
|
DISPDBG((2, "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((2, "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((2, "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((2, "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((2, "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);
|
|
}
|
|
|
|
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((2, "cy = 2 "));
|
|
|
|
prb->cy = 2;
|
|
prb->cyLog2 = 1;
|
|
}
|
|
else
|
|
{
|
|
DISPDBG((2, "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((2, "4pels wide"));
|
|
|
|
prb->fl |= RBRUSH_4PELS_WIDE;
|
|
|
|
done_this_realize_brush_stuff:
|
|
|
|
return(TRUE);
|
|
}
|