executor/docs/vdriver-specs

282 lines
14 KiB
Plaintext

Each host is required to provide a "vdriver" package that presents a
consistent video interface to the rest of Executor.
The vdriver provides an idealized rectangular frame buffer to
Executor. Pixels occupy either 1, 2, 4, or 8 bits and are stored in
in "packed" format in big endian bit order (MSB on the left). The
frame buffer bytes per row may exceed the bytes occupied by the pixels
on that row, but both sizes will always be multiples of four bytes.
The actual video hardware on the host machine will constrain the
maximum pixel depths and screen sizes available to Executor, but the
hardware modes used need not map directly to the format of the
vdriver's frame buffer. The vdriver is responsible for selecting
efficient hardware graphics modes and translating the information in
the internal frame buffer into bits that appear on the real screen
when `vdriver_update_screen' is called. The "internal" frame buffer
may optionally be one and the same as the actual hardware frame
buffer, in which case `vdriver_update_screen' does nothing.
For example, consider the case where Executor requests a 4 bpp (bits
per pixel) frame buffer on a SuperVGA system. On most SuperVGA
boards, 4 bpp requires using a complicated and slow "planar mode".
Therefore, the vdriver might choose to use an available SuperVGA 8 bpp
mode and use lookup tables to convert from 4 bpp to 8 bpp whenever the
hardware screen is updated, since this is faster than converting from
4 bpp "packed" pixels to 4 bpp "planar" pixels. Executor will still
only "see" a 4 bpp frame buffer, and the user won't be able to tell
the difference.
Each vdriver maintains a maximum bits per pixel and a list of
acceptable screen sizes. The vdriver must be able to accept any
power-of-two bits per pixel (up to the maximum) at any allowed screen
size. This allows users to always change the pixel depth without
altering the screen size, and to alter the screen size without
changing the pixel depth.
Some systems, like X windows, don't have a fixed list of screen sizes
from which Executor can select. In those cases, the list of canonical
sizes will contain two elements, the minimum and the maximum, and
continuous_range_p will be TRUE. `vdriver_acceptable_mode' will
return TRUE for acceptable sizes in between the minimum and the
maximum. This is useful when the user wants to resize Executor's
screen to some arbitrary size by using facilities in the host's window
system.
The functions in this file are prototyped in "vdriver.h". vdriver.h
#include's "host_vdriver.h" before prototyping any of these functions,
so that host_vdriver.h may replace some of them with macros on systems
where that is appropriate. vdriver.h will not prototype any function
that is defined as a macro by host_vdriver.h.
-- Function: boolean_t vdriver_init (int MAX_WIDTH, int MAX_HEIGHT,
int MAX_BPP, boolean_t FIXED_P,
int *argc, char *argv[])
`vdriver_init' must be called exactly once, before any other
vdriver routines. It is responsible for allocating memory to
hold the frame buffer (if necessary) and performing any other
host-specific initialization.
The frame buffer's base address can never change, so the
parameters to this function are hints that specify the biggest
mode that might ever be requested so that sufficient memory can
be allocated initially. The allocated frame buffer should
usually be big enough to support either that mode or the biggest
mode the hardware can physically support, but it need not be.
Each row of the frame buffer must start on a 32-bit boundary
(i.e. the starting addresses must be divisible by four).
If MAX_WIDTH is zero, this function should choose a largest size
and bpp in a host-defined way and allocate frame buffer memory
appropriately. For example, if MAX_WIDTH == 0 and the graphics
hardware can only support a window at most 800x600 with at most 4
bits per pixel, 800x600x4 should be used. If the hardware can
support 3000x3000x8, this function may decide to choose a smaller
maximum size and stick with it.
If FIXED_P is TRUE, then the graphics mode will never be set to
any size other than MAX_WIDTHxMAX_HEIGHTxMAX_BPP. Fixing these
parameters can sometimes enable speedups not otherwise available,
but at the cost of losing the ability to do dynamic mode sets.
It is of course safe to assume this flag is FALSE. It is an
error for MAX_WIDTH to be zero and for FIXED_P to be true.
ARGC and ARGV specify command line options given to the program.
The vdriver can ignore these parameters, but if it wants to process
any of these arguments, it should remove them from argv and adjust
argc appropriately.
Frame buffer memory need not be initialized here. In general,
you should avoid touching frame buffer memory that might not end
up getting used, since this will be more efficient on systems
that lazily allocate memory pages.
`vdriver_init' should not set up any default graphics mode.
`vdriver_set_mode' will take care of that.
`vdriver_init' should return TRUE if successful, FALSE if
it failed to open the display (which will be a fatal error
for Executor).
-- Function: void vdriver_shutdown (void)
`vdriver_shutdown' is responsible for cleaning up after the
vdriver routines and returning the display back to a state
appropriate for Executor to exit. For convenience, this function
can be called more than once; however, once it is called, no
vdriver routine other than this one should be called. This
routine must be called once before Executor exits.
-- Function: boolean_t vdriver_acceptable_mode_p (int WIDTH, int HEIGHT,
int BPP,
boolean_t EXACT_MATCH_P)
Returns TRUE if the given mode will work if passed to
`vdriver_set_mode', else FALSE. If EXACT_MATCH_P is true, this
function will only return TRUE if `vdriver_set_mode' will
accept the mode without adjusting the screen size at all.
If WIDTH, HEIGHT, or BPP are zero, they are replaced with default
values as described in `vdriver_set_mode'.
-- Function: boolean_t vdriver_set_mode (int WIDTH, int HEIGHT, int BPP)
`vdriver_set_mode' does the dirty work of actually setting up a
particular graphics mode. BPP must be a power of two between 1
and the maximum bpp returned by vdriver_mode_info, and must be
honored. If WIDTHxHEIGHT is a mode listed as canonical by
`vdriver_mode_info', it must be honored exactly. Otherwise, this
function should try to choose the smallest mode which is at least
as large as that specified by the caller. If even that is not
large enough, this function should choose the largest available
mode. The actual screen size chosen by this function can and
should be determined by calling `vdriver_frame_buffer', since it
may not be exactly what was passed in.
If WIDTH, HEIGHT, or BPP is zero, it is replaced with the current
value for that parameter (if a mode has been set) or, if no mode
has yet been set, it is replaced with an host-defined default value.
This function need not redraw the screen, and is entitled to
leave the screen in a "garbage" state. The caller is responsible
for properly redrawing the frame buffer after a mode set.
This function returns TRUE if a mode set was achieved, FALSE
otherwise (in which case the mode should remain unchanged).
-- Function: void vdriver_set_colors (int FIRST_COLOR, int NUM_COLORS,
const ColorSpec *COLOR_ARRAY)
`vdriver_set_colors' is called when the color table of the display
has changed. The colors for pixel values:
FIRST_COLOR ... FIRST_COLOR + NUM_COLORS - 1
are set to the values specified by:
COLOR_ARRAY[0] ... COLOR_ARRAY[NUM_COLORS - 1], respectively.
NOTE: For convenience, each ColorSpec is assumed to store its values
in big endian byte order. That way you can just pass a real
color table to this function.
Of course, the graphics hardware may not actually have a color
table, but the vdriver must at least provide the illusion of one.
All changed color values must be visible to the user before this
function returns or after `vdriver_flush_display' is next called.
-- Function: int vdriver_update_screen (int top, int left, int bottom,
int right, boolean_t cursor_p)
`vdriver_update_screen' transfers the specified rectangle from the
internal frame buffer to the actual graphics hardware. If the
rectangle exceeds the bounds of the frame buffer, it will be
pinned to fit within it. CURSOR_P should only be TRUE when it
is the cursor being drawn to the screen. Most implementations
can ignore this flag, but DOS uses it to tell whether or not the
cursor got overwritten by an update and needs to be redisplayed.
You almost always want to pass FALSE for this flag when calling
this routine.
The return value is implementation-dependent and should be ignored.
The transferred information need not be visible to the user by
the time this function exits. `vdriver_update_screen' may only
queue up the display with the host's windowing system. To
guarantee that the information is visible to the user, call
`vdriver_flush_display'
-- Function: int vdriver_update_screen_rects (int NUM_RECTS,
const vdriver_rect_t *R,
boolean_t CURSOR_P)
Like vdriver_update_screen, but can update many rectangles at
once. Calling this may be more efficient than making separate
calls to `vdriver_update_screen'.
-- Function: void vdriver_flush_display (void)
This function guarantees that any updates from
`vdriver_update_screen' will be made visible to the user "soon",
even if no further vdriver calls are made. The intent of this
function is that calling it frequently will make graphics animate
smoothly, instead of queueing up with the window server and
getting blasted out in chunks. This is only relevant for hosts
that talk to a window server, but it's always safe to call it.
-- Function: void vdriver_system_busy (int BUSY_P)
This function is sometimes called when Executor is busy and wants
to inform the user that it is actually doing something and not
just hung. During such times, it may be called extremely frequently,
so this function should be very fast. If BUSY_P is true,
the system is still busy. If it's FALSE, the system is no longer
busy. This function is optional and calls to it may be ignored on
any system; if you want calls to be ignored, don't write this
function and instead put this line in host_vdriver.h:
#define vdriver_system_busy 0
-- Function: vdriver_accel_result_t
vdriver_accel_rect_fill (int TOP, int LEFT, int BOTTOM,
int RIGHT, uint32 COLOR)
This function optionally fills in the specified screen rectangle
with the given solid COLOR. COLOR is a pixel for the internal
frame buffer (if any), and may not correspond to the host
screen's color space. The vdriver is responsible for making that
translation.
The vdriver is not allowed to update the screen "out of order".
All dirty rects must be flushed to the screen before any
accelerated drawing can take place.
This function returns a value indicating what effect it had:
typedef enum
{
VDRIVER_ACCEL_NO_UPDATE,
VDRIVER_ACCEL_FULL_UPDATE,
VDRIVER_ACCEL_HOST_SCREEN_UPDATE_ONLY
} vdriver_accel_result_t;
VDRIVER_ACCEL_NO_UPDATE means no action was performed, and
the usual blitting and dirty rect mechanisms should be
employed.
VDRIVER_ACCEL_FULL_UPDATE means that both the host screen
and internal frame buffer have been fully updated, and no
more work needs to be done.
VDRIVER_ACCEL_HOST_SCREEN_UPDATE_ONLY means that the host screen
now has the correct data, but the internal frame buffer still
needs to be updated. The internal frame buffer will be updated
by the usual mechanisms, but no dirty rect will be accrued for
that update because the screen already has the correct
information.
If the vdriver doesn't support this function, the easiest way
to note that is to add this line to host_vdriver.h:
#define vdriver_accel_rect_fill(t, l, b, r, c) VDRIVER_ACCEL_NO_UPDATE
It may be advantageous for the vdriver to decide that using an
accelerated mechanism is a lose and return
VDRIVER_ACCEL_NO_UPDATE. For example, this might make sense if
the rectangle is very small or if it overlaps an existing dirty
rectangle.
-- Function: vdriver_accel_result_t
vdriver_accel_rect_scroll (int TOP, int LEFT, int BOTTOM,
int RIGHT, int DX, int DY)
The specified rectangle is copied on the screen DX pixels to the
right and DY pixels down from its current location. DX and DY may
each be negative, 0, or positive. Overlapping data must be
handled correctly. The return value and semantics are otherwise
analagous to those of `vdriver_accel_rect_fill'.
-- Function: void vdriver_accel_wait (void)
This function waits until it is safe to access the frame buffer's
pixels directly and then returns. For example, an accelerated
SVGA vdriver might have the SVGA board fill in a rectangle in
VRAM. You are not guaranteed to get the correct pixel values from
the frame buffer until this rect fill has completed, so you must
wait until the rect fill is done.
This call is only useful on systems where the bitmap being
modified by the accelerator is the same as the bitmap that
Executor references directly. This is not the case under X
windows, for example. Most vdrivers will just want to put:
#define vdriver_accel_wait()
in host_vdriver.h.