|
|
/******************************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); }
|