Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

498 lines
14 KiB

/*
* Copyright (c) 1994-1995 Digital Equipment Corporation
*
* Module Name: fillutil.c
*
* This module contains routines to fill a list of rectangles. The routines
* are called from DrvFillPath
*
* History:
*
* 30-May-1994 Barry Tannenbaum
* Initial version.
*
* 21-Jul-1994 Bob Seitsinger
* Write the Plane mask register when using block fill mode.
*
* 9-Aug-1994 Barry Tannenbaum
* Setup for 24 plane support:
* - TGAMODE and TGAROP now take simple ULONGs instead of structures
* - Use default values from ppdev->ulModeTemplate & ppdev->ulRopTemplate
*
* 22-Sep-1994 Bob Seitsinger
* Make use of ppdev->ulPlanemaskTemplate. Also, alignment is 1-pixel for
* all 'Fill' modes, so no need to 'if' on bmf, just align to 4 bytes.
*
* 25-Oct-1994 Bob Seitsinger
* Write plane mask with ppdev->ulPlanemaskTemplate all the
* time.
*
* For 24 plane boards we don't want to blow away the
* windows ids for 3d windows. The GL driver removes the
* window ids when it relinquishes a rectangular area.
*
* 2-Mar-1995 Barry Tannenbaum
* EV5 changes
*/
#include "driver.h"
#include "fill.h"
/*
* do_opaque_8
*
* This routine actually fills the target rectangle. It assumes that
* it's been given clipped rectangles.
*/
static __inline
VOID do_solid_pattern (PPDEV ppdev, // Device context
RECTL *rect, // Rectangle to be filled
fill_data_t *fill_data) // Pattern data
{
PBYTE left_edge; // Framebuffer address of left edge of rectangle
PBYTE base_address;
int y; // Counts number of scanlines written
int width; // Width of the rectangle
int height;
ULONG stride, stride8; // Width of surface being filled
int align_bytes; // Pixels shifted to align
int i, j, max_j; // Index for pattern
// Calculate the PixelCount and check for a valid number. Remember that
// the PixelCount is one minus the width
width = (rect->right - rect->left) - 1;
if (width < 0)
return;
// Fill each line of the rectangle. In block mode we can fill up to 2048
// pixels each write. Since none of the displays we're considering are
// wider than 1280 pixels/scanline, it should be safe to ignore considering
// whether we need more than 1 write/scanline
CYCLE_FB (ppdev);
stride = ppdev->lScreenStride;
stride8 = stride * 8;
base_address = ppdev->pjFrameBuffer +
(rect->top * stride) +
rect->left;
// Calculate the alignment bytes and subtract them from the left edge to
// align to a 1-pixel boundary.
align_bytes = (unsigned int)base_address & 0x03;
base_address = base_address - align_bytes;
// OR in the low bits of the address (the alignment pixels) into the upper
// word, since that's where BLOCK FILL mode looks for them
width |= (align_bytes << 16);
// Calculate the initial pattern index
i = (rect->top - fill_data->yOffset) % 8;
if (i < 0)
i += 8;
i *= 2;
// Fill each scanline
// For each of the sets of data registers that we use
height = rect->bottom - rect->top;
if (8 < height)
max_j = 8;
else
max_j = height;
for (j = 0; j < max_j; j++)
{
// Load the pattern into the color registers taking the brush origin
// into account. Note that we don't have to worry about where we're
// starting to paint since the color registers always start at an
// octa-pixel boundry
CYCLE_REGS (ppdev);
if (TGA_ROP_COPY == fill_data->tga_rop)
{
TGACOLOR0 (ppdev, fill_data->pattern[i]);
TGACOLOR1 (ppdev, fill_data->pattern[i+1]);
}
else
{
TGAFOREGROUND (ppdev, fill_data->pattern[i]);
TGABACKGROUND (ppdev, fill_data->pattern[i+1]);
}
i += 2;
if (i >= 8*2)
i = 0;
// Set the base address for this set of writes
left_edge = base_address;
base_address += stride;
// Fill each scanline which uses this set of colors
for (y = rect->top + j; y < rect->bottom; y += 8)
{
TGAWRITE (ppdev, left_edge, width);
left_edge += stride8;
}
}
}
VOID fill_solid_pattern_rects (PPDEV ppdev, //
LONG count,
RECTL *prcl,
fill_data_t *fill_data)
{
ULONG mask;
LONG i;
ULONG mode; // TGA mode register
ULONG rop; // Assembles TGA raster op register
// Note that the chip is no long in simple mode
ppdev->bSimpleMode = FALSE;
WBFLUSH (ppdev);
// Set the mode and raster op registers
if (TGA_ROP_COPY == fill_data->tga_rop)
{
mode = TGA_MODE_BLOCK_FILL;
mask = 0xffffffff;
}
else
{
mode = TGA_MODE_OPAQUE_FILL;
mask = 0xf0f0f0f0;
}
TGAPLANEMASK (ppdev, ppdev->ulPlanemaskTemplate);
mode |= ppdev->ulModeTemplate;
TGAMODE (ppdev, mode);
rop = fill_data->tga_rop |= ppdev->ulRopTemplate;
TGAROP (ppdev, rop);
// For BLOCK_FILL mode, the data register specifies which pixel to set.
// For OPAQUE_FILL mode, the data register specifies whether a pixel is
// set to the foreground or background color
TGADATA (ppdev, mask); // Write to all 32 pixels
// Fill the rectangles
for (i = 0; i < count; i++)
{
do_solid_pattern (ppdev, prcl, fill_data);
prcl++;
}
}
/*
* do_trans_pattern
*
* This routine actually fills the target rectangle. It assumes that
* it's been given clipped rectangles.
*/
static __inline
VOID do_trans_pattern (PPDEV ppdev, // Device context
RECTL *rect, // Rectangle to be filled
fill_data_t *fill_data) // Data for fill
{
PBYTE left_edge; // Framebuffer address of left edge of rectangle
PBYTE base_address;
int y; // Counts number of scanlines written
int width; // Width of the rectangle
ULONG stride; // Width of surface being filled
ULONG stride8; // Width of surface being filled
int align_bytes; // Pixels shifted to align
int i; // Index for pattern
ULONG *mask_ptr;
int j, max_j; // Index for pattern
int height;
// Calculate the PixelCount and check for a valid number. Remember that
// the PixelCount is one minus the width
width = (rect->right - rect->left) - 1;
if (width < 0)
return;
// Fill each line of the rectangle. In block mode we can fill up to 2048
// pixels each write. Since none of the displays we're considering are
// wider than 1280 pixels/scanline, it should be safe to ignore considering
// whether we need more than 1 write/scanline
CYCLE_FB (ppdev);
stride = ppdev->lScreenStride;
stride8 = 8 * stride;
base_address = ppdev->pjFrameBuffer +
(rect->top * stride) + rect->left;
// Calculate the alignment bytes and subtract them from the left edge to
// align to a 1-pixel boundary.
align_bytes = (unsigned int)base_address & 0x03;
base_address = base_address - align_bytes;
// OR in the low bits of the address (the alignment pixels) into the upper
// word, since that's where BLOCK FILL mode looks for them
width |= (align_bytes << 16);
// Calculate the initial pattern index
i = (rect->top - fill_data->yOffset) % 8;
if (i < 0)
i += 8;
// For each of the masks that we use
if ((ULONG)base_address & 0x04)
mask_ptr = fill_data->mask + 8;
else
mask_ptr = fill_data->mask;
height = rect->bottom - rect->top;
if (8 < height)
max_j = 8;
else
max_j = height;
for (j = 0; j < max_j; j++)
{
// Load the mask and pattern into the color registers taking the brush
// origin into account. Note that we don't have to worry about where
// we're starting to paint since the color registers always start at an
// octa-pixel boundry
CYCLE_REGS (ppdev);
TGADATA (ppdev, mask_ptr[i]);
if (++i >= 8)
i = 0;
// Set the base address for this set of writes
left_edge = base_address;
base_address += stride;
// Fill each scanline
for (y = rect->top + j; y < rect->bottom; y += 8)
{
TGAWRITE (ppdev, left_edge, width);
left_edge += stride8;
}
}
}
VOID fill_trans_pattern_rects (PPDEV ppdev, //
LONG count,
RECTL *prcl,
fill_data_t *fill_data)
{
ULONG mode;
LONG i;
ppdev->bSimpleMode = FALSE;
WBFLUSH (ppdev);
// Set the mode and raster op registers
if (TGA_ROP_COPY == fill_data->tga_rop)
{
mode = TGA_MODE_BLOCK_FILL;
}
else
{
mode = TGA_MODE_TRANSPARENT_FILL;
TGAFOREGROUND (ppdev, fill_data->iSolidColor);
}
TGAPLANEMASK (ppdev, ppdev->ulPlanemaskTemplate);
mode |= ppdev->ulModeTemplate;
TGAMODE (ppdev, mode);
TGAROP (ppdev, ppdev->ulRopTemplate | fill_data->tga_rop);
// Set the block fill registers to the foregound color. The mask
// will determine which pixels are set
if (TGA_ROP_COPY == fill_data->tga_rop)
{
TGACOLOR0 (ppdev, fill_data->iSolidColor);
TGACOLOR1 (ppdev, fill_data->iSolidColor);
}
// Fill the rectangles
for (i = 0; i < count; i++)
{
do_trans_pattern (ppdev, prcl, fill_data);
prcl++;
}
}
/*
* do_solid
*
* This routine actually fills the opaque rectangle. It assumes that
* it's been given clipped rectangles.
*/
static __inline
VOID do_solid (PPDEV ppdev, // Surface to fill
RECTL *rect) // Rectangle to be filled
{
PBYTE left_edge; // Framebuffer address of left edge of rectangle
int y; // Counts number of scanlines written
int width; // Width of the opaque rectangle
int align_bytes; // Pixels shifted to align
ULONG stride; // Width of destination
// Remember that the width does *not* include the right edge, so subtract
// one
width = (rect->right - rect->left) - 1;
if (width < 0)
return;
// Fill each line of the rectangle. In block mode we can fill up to 2048
// pixels each write. Since none of the displays we're considering are
// wider than 1280 pixels/scanline, it should be safe to ignore considering
// whether we need more than 1 write/scanline
CYCLE_FB (ppdev);
stride = ppdev->lScreenStride;
left_edge = ppdev->pjFrameBuffer +
(rect->top * stride) +
rect->left;
// Calculate the alignment pixels and subtract them from the left edge to
// align to a 1-pixel boundary.
align_bytes = (unsigned int)left_edge & 0x03;
left_edge = left_edge - align_bytes;
// OR in the low bits of the address (the alignment pixels) into the upper
// word, since that's where BLOCK FILL mode looks for them
width |= (align_bytes << 16);
// Fill each scanline
for (y = 0; y < rect->bottom - rect->top; y++)
{
TGAWRITE (ppdev, left_edge, width);
left_edge += stride;
}
}
VOID fill_solid_rects (PPDEV ppdev, //
LONG count,
RECTL *prcl,
fill_data_t *fill_data)
{
ULONG mode; // TGA mode to use
ULONG color;
LONG i;
BOOL block_fill;
// Note that the chip is no long in simple mode
ppdev->bSimpleMode = FALSE;
WBFLUSH (ppdev);
// If the ROP is COPY (simply set the pixmap to the solid color) we can
// use BLOCK_FILL mode. Unfortunately, BLOCK_FILL mode doesn't pay any
// attention to the ROP, so if we want to do anything fancy (say, XOR the
// the data onto the screen) we have to use TRANSPARENT_FILL. BLOCK_FILL
// is faster (about 4x, but TRANSPARENT_FILL is more flexible)
switch (fill_data->tga_rop)
{
case TGA_ROP_COPY:
mode = TGA_MODE_BLOCK_FILL;
if (BMF_8BPP == ppdev->iFormat)
{
color = fill_data->iSolidColor |
(fill_data->iSolidColor << 8);
color |= color << 16;
}
else
color = fill_data->iSolidColor;
break;
case TGA_ROP_SET:
fill_data->tga_rop = TGA_ROP_COPY;
color = 0xffffffff;
mode = TGA_MODE_BLOCK_FILL;
break;
case TGA_ROP_CLEAR:
fill_data->tga_rop = TGA_ROP_COPY;
color = 0x00000000;
mode = TGA_MODE_BLOCK_FILL;
break;
case TGA_ROP_INVERT:
mode = TGA_MODE_TRANSPARENT_FILL;
break;
default:
mode = TGA_MODE_TRANSPARENT_FILL;
if (BMF_8BPP == ppdev->iFormat)
{
color = fill_data->iSolidColor |
(fill_data->iSolidColor << 8);
color |= color << 16;
}
else
color = fill_data->iSolidColor;
TGAFOREGROUND (ppdev, color);
break;
}
TGAPLANEMASK (ppdev, ppdev->ulPlanemaskTemplate);
// Set the mode and raster op registers
block_fill = (TGA_MODE_BLOCK_FILL == mode);
mode |= ppdev->ulModeTemplate;
TGAMODE (ppdev, mode);
TGAROP (ppdev, fill_data->tga_rop | ppdev->ulRopTemplate);
TGADATA (ppdev, 0xffffffff); // Write to all 32 pixels
// If we're using BLOCK_FILL mode, load the BLK_COLOR registers
if (block_fill)
TGALOADCOLORREGS (ppdev, color, ppdev->ulBitCount);
CYCLE_REGS (ppdev);
// Fill the rectangles
for (i = 0; i < count; i++)
{
do_solid (ppdev, prcl);
prcl++;
}
}