SvgaLib/doc/man3/vga_accel.3

602 lines
20 KiB
Groff

.TH vga_accel 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual"
.SH NAME
vga_accel \- calls the graphics accelerator
.SH SYNOPSIS
.B "#include <vga.h>"
.BI "int vga_accel(unsigned " operation ", " ... );
.SH DESCRIPTION
This is the major function of the new accelerator interface which was sketched in
version 1.2.3 (Michael: Hmm, it must have been later) but was implemented much later.
The main goal is to define functions that can be used as part of
certain kinds of interesting graphical operations (not necessarily
interesting primitives on their own). Obvious useful primitives
in their own are FillBox, ScreenCopy, DrawHLineList (solid polygon),
DrawLine.
An interesting purpose is the fast drawing of color bitmaps, both
straight and transparent (masked, certain color not written). For
masked bitmaps ("sprites"), there is a number of possible methods,
the availability of which depends on the chips. Caching in
non-visible video memory is often useful. One way is to use a
transparency color compare feature of a BITBLT chip, either
transferring the image from system memory or cached in video memory.
If transparency compare is not available, it may be possible to first
clear (zeroe) the mask in the destination area, and then use BITBLT
raster-operation to OR the image into the destination (this requires
the mask color to be 0). A higher level (library) interface should
control this kind of operation.
.I vga.h
contains several macros which may be used for
.IR operation .
Most of them accept
several optional arguments which you may specify after them. The
.BR accel (6)
svgalib demo shows basic usage of this function. The function returns -1 if the
operation is
not available and 0 if it is (or better: wasi and could be performed).
Currently the following parameters for
.B vga_accel()
are defined:
.TP
.BI "vga_accel(ACCEL_FILLBOX, int " x ", int " y ", int " w ", int " h )
Simple solid fill of a box at pixels
.IR x ", " y " with width " w " and height " h
in the current foreground color
.TP
.BI "vga_accel(ACCEL_SCREENCOPY, int " x1 ", int " y1 ", int " x2 ", int " y2 ", int " w ", int " h )
Simple screen-to-screen blit. It copies a box of width
.IR w " and height " h
pixels from position
.IR x1 ", " y1
to position
.IR x2 ", " y2 .
You may assume that the copy is non corrupting in case of overlapping source and destination
areas.
.TP
.BI "vga_accel(ACCEL_SCREENCOPYMONO, int " x1 ", int " y1 ", int " x2 ", int " y2 ", int " w ", int " h )
Monochrome screen-to-screen blit. It copies a box of width
.IR w " and height " h
pixels from position
.IR x1 ", " y1
to position
.IR x2 ", " y2 .
However, each pixel will all bits set to 0 is drawn in the background color, each pixel with all
bits set to 1 is drawn in the foreground color. To allow many different architectures supporting
this routine, behaviour is undefined for other values. Bitmap transparency might be supported
as well.
You should not expect
.B ACCEL_SCREENCOPYBITMAP
handling overlapping screen areas gracefully.
.TP
.BI "vga_accel(ACCEL_PUTIMAGE, int " x ", int " y ", int " w ", int " h ", void *" p )
Straight image transfer. It fills the given box with the data in memory area
.IR p .
The memory buffer must contain the pixels in the same representation as used in the vga memory,
starting at the top left corner, from left to right, and then, line by line, from up to down,
without any gaps and interline spaces.
.TP
.BI "vga_accel(ACCEL_DRAWLINE, int " x1 ", int " y1 ", int " x2 ", int " y2 ))
General line draw. Draws a line from
.IR x1 ", " y1
to position
.IR x2 ", " y2 " in the foreground color."
You should not expect the reverse line from
.IR x2 ", " y2
to position
.IR x1 ", " y1 " to use the exact same pixels on the screen."
Several, esp. hardware, algorithms tend to yield to surprising results.
.TP
.BI "vga_accel(ACCEL_SETFGCOLOR, int " color )
Sets foreground color. It is used by most other draw commands.
.TP
.BI "vga_accel(ACCEL_SETBGCOLOR, int " color )
Set background color. It is used by draw commands which might also
.TP
.BI "vga_accel(ACCEL_SETTRANSPARENCY, int " mode ", " ... )
Set transparency mode, see the table below for an explanation parameters.
.TP
.BI "vga_accel(ACCEL_SETRASTEROP, int " mode )
Set raster-operation, see the table below for an explanation of parameters.
.TP
.BI "vga_accel(ACCEL_PUTBITMAP, int " x ", int " y ", int " w ", int " h ", void *" p )
Color-expand bitmap. This works similar to
.B ACCEL_PUTIMAGE
but the bitmap
.I *p
is a one bit bitmap.
Each pixel related to a set bit in
.I *p
is drawn in the foreground color, the other pixels are drawn in the background color.
Each byte at
.I *p
contains 8 pixels.
The lowest order bit of each byte is leftmost on the screen
(contrary to the VGA tradition), irrespective of the bitmap
bit order flag. Each scanline is aligned to a multiple of
32-bits.
If the transparency mode is enabled (irrespective of the
transparency color), then bits that are zero in the bitmap
are not written (the background color is not used).
.TP
.BI "vga_accel(ACCEL_SCREENCOPYBITMAP, int " x1 ", int " y1 ", int " x2 ", int " y2 ", int " w ", int " h )
Color-expand from screen. This works similar to
.B ACCEL_PUTBITMAP
but the bitmap
lies at position
.IR x1 ", " y1
and the destination box at
.IR x2 ", " y2.
Alas, the sizes of the pixels in both bitmap are different. The bitmap
.I *p
must have the format corresponding to
.B ACCEL_PUTBITMAP
but will start at the screen memory location where
the pixel
.RI ( x1 ", " y1 )
would be (probably in off screen memory).
In modes where pixel will not start at byte boundaries (typically those with less then
256 colors), the pixel
.RI ( x1 ", " y1 )
must start at a byte boundary (for example in a 16 color mode (4bpp rather than 8bpp for
256 colors) this means that
.I x1
should be an even number).
The easiest way to achieve this is probably to choose
.IB x1 " == 0"
in these situations.
You should not expect
.B ACCEL_SCREENCOPYBITMAP
handling overlapping screen areas gracefully.
.TP
.BI "vga_accel(ACCEL_DRAWHLINELIST, int " y ", int " n ", int *" x1 ", int *" x2 )
Draw horizontal spans. Each of the
.IR *x1 " and " *x2
arrays contains
.I n
x-coordinate pairs. Starting with a horizontal line from
.IR *x1 , y " to " *x2 , y
consecutive horizontal lines (with increasing
.I y
values) are drawn using the start and end points in
.IR *x1 " and " *x2 .
This is usually a very quick operation and useful to draw arbitrary polygons (when the
accelerator cannot do an arbitrary polygon fill itself).
.TP
.BI "vga_accel(ACCEL_POLYLINE, int " flag ", int " n ", unsigned short *" coords )
draws a contiguous line through the
.I n
points listed in
.IR *coords .
.I *coords
contains
.I n
pairs of shorts, the first is the x coordinate, the second is the y coordinate.
Normally
.I
flag
should have the value
.BR "ACCEL_START | ACCEL_END" .
However, if the evaluation of the points is costly, you can mix calculations and drawings.
Your first call to
.BI "vga_accel(ACCEL_POLYLINE, " ... )
must have
.B ACCEL_START
set. This will initialize the accelerator. If you do not specify
.BR ACCEL_END ,
you can (actually you have to) follow your call with another
.BI "vga_accel(ACCEL_POLYLINE, " ... )
call which will give additional points to connect.
It is important that no other operations (even no color settings) take place
between a call with
.BR ACCEL_START " and the one with the corresponding " ACCEL_END .
Because of this, it is also important that you lock the console with
.BR vga_lockvc (3)
and
.BR vga_unlockvc (3),
s.t. you cannot be interrupted by a console switch.
It is allowed not to set
.B ACCEL_END
for your last call to
.BI "vga_accel(ACCEL_POLYLINE, " ... ). This will not draw the last pixel of the last
line which is important for some raster operations when drawing closed polygons.
The accelerator will automatically deinitialize when called with another operation in
this situation.
It is undefined what happens when you specify other values for
.I flag
and when your polyline contains only a single point. The line segments must also not
be of length zero.
For implementors: In conjunction with raster operations
.RB ( ROP_XOR ", " ROP_INV )
it is important that endpoints of inner line section are only drawn once. If you cannot achieve
that, you must signal that this function cannot be used in conjunction with raster operations.
In this case it is valid to always draw all points of the line segments including the endpoints
regardless of the existence of a
.B ACCEL_END
parameter.
.TP
.BI "vga_accel(ACCEL_POLYHLINE, int " flag ", int " y ", int " n ", unsigned short *" xcoords )
This function combines the features of
.B ACCEL_POLYLINE
and
.BR ACCEL_DRAWHLINELIST .
Starting in row
.I y
horizontal lines are drawn from top to bottom. For each horizontal scanline the
.I *coords
array will contain a number
.I m
followed by
.I m
x coordinates in left to right order. Horizontal lines are drawn between the first and the
second, the third and the fourth x coordinates, and so on. If the
.I m
coordinates are exhausted,
.I y
is increased, a new number
.I m
is read from the
.I *coords
array and operation continues.
This procedure is done for
.I n
scan lines.
In addition there is a
.I flag parameter which works similar to
.BR ACCEL_POLYLINE .
Your first call to
.B ACCEL_DRAWHLINELIST
must have the
.B ACCEL_START
bit set for proper initialization. The
.I y
parameter is ignored when
.B ACCEL_START
is not given.
On contrary to
.B ACCEL_POLYLINE
it is required that the last call has the
.B ACCEL_END
bit set.
The function is intended for drawing complex filled polygons using horizontal scanlines.
By issuing small and fast calls for few scanlines only it is possible to intermix drawing and
calculations.
The operation of
.B ACCEL_POLYHLINE
is undefined if the x coordinates are not sorted from left to right or there are zero length
segments in any scan line or if
.IR n " or one of the " m
counters are zero, or one of the
.IR m 's
is not even.
.TP
.BI "vga_accel(ACCEL_POLYFILLMODE, " onoff )
Switches polygon fill mode on
.RI ( onoff " non-zero)
or off.
When in polygon fill mode,
.BR ACCEL_DRAWLINE " and " ACCEL_POLYLINE
will only draw a single point on each scanline of each line segment.
.B ACCEL_SCREENCOPYMONO
will horizontally scan it's source area and start drawing in the foreground color when it
encounters a set pixel. When the next pixel is encountered, it will start using the background
color and so on.
This can be used for hardware filled polygons:
.RS
.IP 1.
Enable polygon fill mode.
.IP 2.
Fill an offscreen rectangular area with a the color with all bits zero (usually black).
.IP 3.
Draw a (usually closed) polygon outline in this offscreen area in the color with all bits set
(usually white). To get the proper bits set for the polygon outline, it is recommended
to use
.B ROP_XOR
s.t. outlines intersecting in a single point are handled correctly. To ensure that polygon
corners are handled right, both start and end points must be drawn (in
.B ROP_XOR
mode). Thus it is best to use
.B ACCEL_DRAWLINE
instead of
.BR ACCEL_POLYLINE .
Finally, skip drawing all horizontal lines (which would confuse
.BR ACCEL_SCREENCOPYMONO ).
.IP 4.
Set fore- and background colors, raster operation, bitmap transparency to those you want for
your polygon.
.IP 5.
Use
.B ACCEL_SCREENCOPYMONO
to copy the offscreen pattern to the screen.
.RE
.IP
The rasteroperations and transparency which are signalled to be supported for
.B ACCEL_POLYFILLMODE
by
.BR vga_ext_set (3)
are actually meant to apply to the last
.B ACCEL_SCREENCOPYMONO
call.
Because this polygon drawing uses more screen read/write operations it is probably slower
than using
.B ACCEL_DRAWHLINELIST
or
.BR ACCEL_POLYHLINE
for drawing a polygon scanline by scanline. However, it is easier to use and it will work
mostly without intervention of the CPU which can do other calculations then. See
.B BUGS
below.
It is unspecified if the left or right end points of the scanlines are drawn, and most
probably some cards (like Mach32) will omit them on one end, at least. Because of that you
should always draw the boundary line in the fill color (or another color) after filling the
polygon.
.TP
.BI "vga_accel(ACCEL_SETMODE, " mode )
Set blit strategy. There are two choices for
.IR mode ,
namely
.BR BLITS_SYNC " and " BLITS_IN_BACKGROUND .
The first ensures that a
.B vga_accel()
call only returns when the accelerator has finished its operation. The second
allows for an immediate return and thus allows parallel operation of the CPU and the
accelerator. Consecutive accelerator operations will wait for
each other to complete (and block if necessary). However, direct screen memory
access (also when done implicitly by some call to an svgalib function) may find any intermediate
state in vga memory or even corrupt the running accelerator operation.
.TP
.BI vga_accel(ACCEL_SYNC)
Wait for accelerator to finish when in
.B vga_accel(BLITS_IN_BACKGROUND)
mode.
.TP
.BI "vga_accel(ACCEL_SETOFFSET, int " address )
set a screen offset as
.BI vga_setdisplaystart (3)
does. The same restrictions for this function as reported by
.BI vga_getmodeinfo (3)
apply to
.RI address.
Whenever the video screen offset is modified, the accelerator's offset will follow. However
you can modify it later with this function.
.PP
The following
.I mode
values are defined for
.BI "vga_accel(ACCEL_SETTRANSPARENCY, int " mode ", " ... )
.TP
.BI "vga_accel(ACCEL_SETTRANSPARENCY, ENABLE_TRANSPARENCY_COLOR, int " color )
Whenever one of the
.B vga_accel()
operations would draw a pixel in color
.IR color ,
no operation is performed and the destination pixel is left unchanged. In fact
that color is defined to be transparent.
.TP
.BI "vga_accel(ACCEL_SETTRANSPARENCY, DISABLE_TRANSPARENCY_COLOR)"
disables the previous functionality.
.TP
.BI "vga_accel(ACCEL_SETTRANSPARENCY, ENABLE_BITMAP_TRANSPARENCY)"
in the bitmap expanding operations
.BR ACCEL_PUTBITMAP " and " ACCEL_SCREENCOPYBITMAP
whenever a non set bit is encountered, to not perform any draw operation. The 0 bits
do not draw in the background color. Instead they are defined to be transparent.
.TP
.BI "vga_accel(ACCEL_SETTRANSPARENCY, DISABLE_BITMAP_TRANSPARENCY)"
disables the previous functionality.
.PP
The following
.I mode
values are defined for
.BI "vga_accel(ACCEL_SETRASTEROP, int " mode )
.TP
.BI "vga_accel(ACCEL_SETRASTEROP, ROP_COPY)
Straight copy. Pixels drawn by
.B vga_accel()
replace the destination.
.TP
.BI "vga_accel(ACCEL_SETRASTEROP, ROP_OR)
Logical or. Pixels drawn by
.B vga_accel()
are logical (bitwise) ored to the destination.
.TP
.BI "vga_accel(ACCEL_SETRASTEROP, ROP_AND)
Logical and. Pixels drawn by
.B vga_accel()
are logical (bitwise) anded to the destination.
.TP
.BI "vga_accel(ACCEL_SETRASTEROP, ROP_XOR)
Logical exclusive or. Pixels drawn by
.B vga_accel()
are logical (bitwise) exclusive ored to the destination (bits set in the drawn pixels
flip those pits in the destination).
.TP
.BI "vga_accel(ACCEL_SETRASTEROP, ROP_INV)
Inversion. Pixels drawn by
.B vga_accel()
are inverted. Which color is drawn is actually ignored. Any pixel which would be
overwritten is simply inverted (bitwise) instead.
.PP
.B IMPORTANT!
Please note that a 0 returned by
.BI "vga_accel(ACCEL_SETTRANSPARENCY, int " mode ", " ... )
and
.BI "vga_accel(ACCEL_SETRASTEROP, int " mode )
simply means that the set function is available (and thus probably
.I some
of above features) but only partial functionality may be available.
The
.BR VGA_AVAIL_ROPMODES " and " VGA_AVAIL_TRANSMODES
subfunctions of
.BR vga_ext_set (3)
allow you to check for valid parameters. The
.BR VGA_AVAIL_ROP " and " VGA_AVAIL_TRANSPARENCY
subfunctions return which of the
.B vga_accel
operations are actually affected by these set functions.
.PP
Instead of calling
.B vga_accel()
for each operation to find out if it is supported, you can call:
.B "#include <vga.h>"
.BI "int vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_ACCEL)"
When the logical bitwise and of the return value with one of the following predefined
(one bit set only) integer constants is non zero, the corresponding operation is available:
.BR ACCELFLAG_FILLBOX ,
.BR ACCELFLAG_SCREENCOPY ,
.BR ACCELFLAG_PUTIMAGE ,
.BR ACCELFLAG_DRAWLINE ,
.BR ACCELFLAG_SETFGCOLOR ,
.BR ACCELFLAG_SETBGCOLOR ,
.BR ACCELFLAG_SETTRANSPARENCY ,
.BR ACCELFLAG_SETRASTEROP ,
.BR ACCELFLAG_PUTBITMAP ,
.BR ACCELFLAG_SCREENCOPYBITMAP ,
.BR ACCELFLAG_DRAWHLINELIST ,
.BR ACCELFLAG_SETMODE " and "
.BR ACCELFLAG_SYNC .
In addition, calling
.B "#include <vga.h>"
.BI "int vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_TRANSPARENCY)"
or
.BI "int vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_ROP)"
does
.B not
list the supported values for raster operations and transparency but instead
returns the
.BR ACCELFLAG_
values for the accelerator operations which respond the raster operation resp. transparency
settings.
.PP
The availability of the operations will usually depend on the current video mode selected.
You should not try to use them or check for availability prior to selecting the mode you
want to use with
.BR set_mode (3).
.SH BUGS
I found the Mach32 buggy in that it occasionally omits drawing last pixels of lines when
in polygon fill modes (that means, a single point for the last scanline touched by a line).
Obviously this confuses the polygon fill hardware. However, screen corruption will always be
restricted to a small area as
.B ACCEL_SCREENCOPYMONO
will work only on a limited area. It is not clear if this is a driver error, but it seems
to be a hardware bug, and I don't know a clutch to avoid it yet. In case you experience problems
with certain applications, try
.B blit nopolyfillmode
in the configuration file or the SVGALIB_CONFIG
environment variable.
You must ensure that the given screen coordinates lie in screen memory. Actually you may
not really be sure how offscreen areas are handled, you can only really trust that coordinates
which are visible are supported. For example, the Mach32 restricts the allowable x and
y coordinates to the range -512 .. 1535. However, even on a 1MB VGA memory card, the offscreen
point (0, 1599) would identify a valid screen memory location (if you could use it).
Where supported, the
.BI "vga_accel(ACCEL_SETOFFSET, " ... )
directive might help to ease things a bit in such situations.
Svgalib's accelerator support is a mess. Right now, only the Ark, the Cirrus, the
Chips&Technologies, and the Mach32 svga drivers
really support this function. The Mach32 still also supports the
old style accelerator functions
.BR vga_bitblt (3),
.BR vga_blitwait (3),
.BR vga_fillblt (3),
.BR vga_hlinelistblt "(3) and "
.BR vga_imageblt (3)
which were first designed for the Cirrus cards and thus the Mach32 has its problems
emulating them. The
.B gl_
functions use the accelerator to some extend. Currently the use both
the new and the old style accelerator. You should avoid mixing calls of the new and the old
style kinds.
These functions are not well tested. You should expect weird bugs. In any case, the
accelerator is of not much use in many typical svgalib applications. Best if you are
not using them.
.B BEWARE!
You should not use the graphics accelerator together with the background feature of
.BR vga_runinbackground (3).
However, you can try using
.BR vga_lockvc (3)
to lock the vc prior to using the accelerator.
The Mach32 driver does this on it's own, and even keeps the console locked while background
accelerator functions are in progress. Other drivers might not be as graceful.
.SH SEE ALSO
.BR svgalib (7),
.BR vgagl (7),
.BR libvga.config (5),
.BR accel (6),
.BR vga_bitblt (3),
.BR vga_blitwait (3),
.BR vga_ext_set (3),
.BR vga_fillblt (3),
.BR vga_getmodeinfo (3),
.BR vga_hlinelistblt (3),
.BR vga_imageblt (3),
.BR vga_runinbackground (3),
.BR vga_runinbackground_version (3)
.SH AUTHOR
This manual page was edited by Michael Weller <eowmob@exp-math.uni-essen.de>. The
exact source of the referenced function as well as of the original documentation is
unknown.
It is very likely that both are at least to some extent are due to
Harm Hanemaayer <H.Hanemaayer@inter.nl.net>.
Occasionally this might be wrong. I hereby
asked to be excused by the original author and will happily accept any additions or corrections
to this first version of the svgalib manual.