mirror of https://github.com/lianthony/NT4.0
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
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++;
|
|
}
|
|
}
|
|
|