Hi,

A few months back I mentioned that a good way to handle the current
graphics subsystem inefficencies and its lack of scalability would be
to design and re-implement a more modular system. Here's a preliminary
proposal for the driver part of the system; I'd like to hear your opinions
about it (if you have any ;-)

----
FreeSCI graphics subsystem redesign: Proposal
04/12/2000, Christoph Reichenbach <[EMAIL PROTECTED]>


        The FreeSCI graphics subsystem


-- First draft --

Preamble
--------
At the time of this writing, the FreeSCI graphics subsystem consists
mostly
of a bunch of random functions writing to a virtual display. This virtual
display is then copied to the real display as neccessary.
While this method allows for an easy implementation of graphics drivers,
its performance is less than optimal. It does not allow for any hardware
acceleration to have effect, uses huge amounts of bandwidth when displayed
remotely, and does not scale very well.
In order to take care of those problems (and to clean up the graphics
API),
a new API for the graphics subsystem is proposed in this document.


1 Basic ideas
-------------
The new graphics subsystem was designed to fullfill the following critera:

- Portability: The subsystem should be portable to any platform with
  support for 32 bit integers or better.
- State-dependancy: The subsystem should be able to keep a list of the
  location of and all information related to pixmaps and other widgets.
- Persistancy: The subsystem should be able to store and retreive the
state
  and content of all of its widgets
- Scalability: The subsystem should be able to work on any resolution that
  is a multiple of 320x200 (the original resolution used by Sierra SCI),
  and any color depths, 8 bit color index mode, and monochrome displays.
  (see below for a discussion of the restriction to screen resolutions)
- Performance: The subsystem should perform well on both local (direct
  rendering) and remote displays

Restricting the screen resolutions to multiples of 320x200 may seem to
be a bit cowardly, but this is only an internal restriction (Internally,
the SCI graphics coordinate system (SGCS) assumes a resolution of 320x200
pixels). Display targets may choose to be arbitrarily scaleable (e.g. by
displaying to scaleable targets such as glx windows or the GNOME canvas),
but they will have to operate on data generated for a resultion of
320x200,
or any multiple of that.

Since some of the ideas described herein are relevant for SCI1 only, some
of
the functions described below will have sections marked with [SCI0: x].
These
sections describe relaxations that apply as long as SCI1 is not supported
by
the interpreter.


2 Dividing the subsystem
------------------------
As hinted above, the subsystem needs to be divided into several separate
parts.
These parts are listed below:

+- - - - - - -+
| Interpreter | (not really a part of the graphics subsystem :)
+- - - - - - -+
        |
        |
        |
        v
+----------------------+     +-----------------------------+
| Widget state manager |---->| Widget state storage system |
+----------------------+     +-----------------------------+
        |          |
        |          |
        |          v
        |       +-------------------------+   +--------------------------+
        |       | Graphics support library|-->| Graphics resource loader |
        |       +-------------------------+   +--------------------------+
        |        ^ |
        |        | |
        v        | v
+---------------------+
|   Display target    |
+---------------------+

...where a -> b means "a calls functions from b".

Everything here must be generic, scaleable, portable etc., except for the
display target (which could also be referred to as a 'graphics driver').
Display targets will have to be implemented individually for each intended
target platform. They will be able to make ample use of the functions
provided by the graphics support library, so that they can 'fake'
functionality
they don't really support; this should be especially helpful in the
transitional phase.

The individual subsystems will now be described in bottom-up order.


3 Display target API
--------------------

The display target will have to handle all actual drawing commands. Many
of
these can be emulated easily by calling appropriate functions from the
grahics support library, but this will not always result in optimal
performance.

Display targets (struct display_target_t) must provide the following:

char *name; /* Unique name of this display target */
int xfact, yfact, color_mode; /* x and y scale factors, color mode */
/* Initialization/deinitialization */
void parse_init_parameter(display_target_t *, char *, char *);
int init_specific(display_target_t *, int, int, int);
int init(display_target_t *);
int exit(display_target_t *);
int get_hint(display_target_t *, int hint_id);
/* Drawing */
int draw_line(display_target_t *, rect_t, color_t);
int draw_rectangle(display_target_t *, rect_t, color_t);
int draw_box(display_target_t *, rect_t, color_t);
int register_font(display_target_t *, resource_t);
int dispose_font(display_target_t *, int);
int draw_text(display_target_t *, int, rect_t, char *, int, short,
color_t,
         color_t);
int register_pixmap(display_target_t *, resource_t *, int, int);
int dispose_pixmap(display_target_t *, int);
int draw_pixmap(display_target_t *, int, rect_t, rect_t, byte, byte);
int grab_screen(display_target_t *, int);
int register_pixmap_pointer(display_target_t *, resource_t *);
/* graphical meta-operations */
int update(display_target_t *, rect_t);
int set_palette(display_target_t *, color_t *);
uint16 get_control(display_target_t *, rect_t);
/* Event management */
sci_event_t get_event(display_target_t *);
int usleep(display_target_t *, int);

Return values (unless specified otherwise) should be one of
GFX_OK (equals 0) whenever no error occured
GFX_FATAL (non-zero) whener a fatal error occured. Fatal errors imply that
        the display system is no longer useable; they should be returned
only
        after freeing all resources allocated by it.
GFX_ERROR (non-zero) whenever an operation failed in a non-fatal way.

Mask values are
GFX_MASK_VISUAL (equals 1) The visible display
GFX_MASK_PRIORITY (equals 2) The priority display
GFX_MASK_CONTROL (equals 4) The control display

The data type 'color' is defined as
typedef struct {
        uint8 red, green, blue, alpha; /* see description of 'hint()' for
a 
                                        ** discussion of the alpha value
                                        */
        byte priority, control;
        byte mask; /* see mask values above */
} color_t;

typedef struct {
        short x, y;
        short xl, yl; /* width */
        /* Coordinate system ALWAYS uses a 320x200 matrix
        ** and scales automatically
        */
} rect_t;

Alignment values:
TEXT_ALIGN_LEFT
TEXT_ALIGN_CENTER
TEXT_ALIGN_RIGHT


3.1 Startup and shutdown operations
-----------------------------------

3.1.1 parse_init_parameter(display_target_t *drv, char *parameter,
------------------------------------------------------------------
        char *value)
--------------------
This function is called prior to init() to specify setup information
specifically directed to the graphics target. This information is
typically
set in in the ~/.freesci/config file or passed to the program during
startup.
This information can be highly target dependant, so no restrictions
concerning
it are specified in this document.
Options set in this function may override parameters of init_specific().

This function must return non-zero on fatal errors only.


3.1.2 init_specific(display_target_t *drv, int xfact, int yfact,
----------------------------------------------------------------
        int color_mode)
-----------------------
This function initializes a specific graphics mode. The specified
resolution
is determined by xfact and yfact as follows:
resolution = (320*xfact, 200*yfact)
((xfact <= 0) || (yfact <=0)) should be treated as a normal error.

color_mode may be any of the following:
GFX_TRUE_COLOR (24 bits color depth or better)
GFX_HI_COLOR (15 or 16 bits color depth)
GFX_COLOR_INDEX (8 bit color index mode)

In 8 bit color index mode, a palette is set by calling set_palette()
afterwards.
xfact, yfact and color_mode (the display target variables) are set by this
function.

This function must only return SCI_FATAL if the display target is not
useable
in _any_ way, as other init_specific() or init() calls might follow this
one.


3.1.3 init(display_target_t *drv)
---------------------------------
Initializes the display target. This function leaves the mode selection
heuristics up to the target implementation. This function must fail only
if no useful display mode could be found.


3.1.4 exit(display_target_t *drv)
---------------------------------
Uninitializes the specified display target. This function frees all memory
associated to the target, unallocates any allocated color maps, and closes
any
opened windows, visuals, or graphics contexts.


3.1.5 get_hint(display_target_t *drv, int hint_nr)
--------------------------------------------------
Retreives a value from the display target. Possible values for hint_nr
are:

GFX_HINT_GET_FAST_FREE_MEM
GFX_HINT_FAST_PALETTE


3.1.5.1 get_hint(display_target_t *drv, GFX_HINT_GET_FAST_FREE_MEM)
-------------------------------------------------------------------
Calculates the amount of free fast pixel space, in pixels. It is used by
the
widget set pixmap/font LRU management as a rule of thumb for optimization.
Implementations must not rely on this value being used as a hard limit.
The return value should be calculated using the memory usage of a single
pixel in the original data, i.e. a target on a 32 bit display, scaling 2x2
and
caching scaled images (as opposed to scaling them while drawing) would
have
to assume a cost of 2x2 * 32bit = 16 bytes per original pixel.


3.1.5.3 get_hint(display_target_t *drv, GFX_HINT_PALETTE)
---------------------------------------------------------
Returns whether palette operations are available. If they aren't, SCI1
palette
effects will have to be emulated.


3.2 Drawing operations
----------------------
All drawing operations should be considered performance critical (to a
reasonable extent). Also, it is imperative that all directives implied by
color_t parameters are handled correctly. The following rules apply
always,
except when stated otherwise in function descriptions:

- All maps (visual, priority, control) indicated by the 'mask' byte must
be
  operated on. No other planes must be touched.
- Alpha values may be treated in one of the following ways (in respect to
the
  visual map):
        * Full alpha support: The alpha value is used for transparency
        * Alpha dithering: Pixels with alpha=0xff are never drawn, pixels
                with alpha=0x00 are always drawn. Pixels with other values
                may or may not be drawn.
        * No alpha support: Pixels with alpha=0xff are never drawn. All
                other pixels are drawn at all times.
- Clipping must always be performed by the display target (graphics
support
  functions for this will be provided for targets that don't support this
  automatically)
- All coordinate parameters apply to the 320x200 grid used internally by
SCI.
  Display targets must scale these coordinates automatically.
- Line thicknesses used by draw_line() and draw_rectangle() are dictated
by
  the scale factor.


3.2.1 draw_line(display_target_t *drv, rect_t line, color_t color)
------------------------------------------------------------------
Draws a line from the coordinates specified in 'line' to the relative
coordinates specified by the xl, yl parameters. xl and yl may be negative
in this case.
Note that the line thickness is dictated by the scale factors.
Implementations may choose to interpolate the total line thickness for
performance reasons. (This function isn't called too often, though).


3.2.2 draw_rectangle(display_tartet_t *drv, rect_t rect, color_t color)
-----------------------------------------------------------------------
Draws the rectangle specified by the 'rect' parameter. Behaviour for
negative xl, yl values is explicitly unspecified.


3.2.3 draw_box(display_target_t *drv, rect_t rect, color_t color)
-----------------------------------------------------------------
Draws a solid box, as specified by the parameters. Behaviour for negative
xl, yl values is unspecified.


3.2.3 register_font(display_target_t *drv, resource_t *font)
------------------------------------------------------------
Registers the specified font resource as a bitmap font. Returns a handle
for
that font to be used later on.
Display target implementations may want to convert the font resource to a
native format for performance reasons.

Returns 0 on error.


3.2.4 dispose_font(display_target_t *drv, int font_id)
------------------------------------------------------
Frees all ressources associated to the font registered with the specified
font
ID.


3.2.5 draw_text(display_target_t *drv, int font_id, rect_t bounds,
------------------------------------------------------------------
        char *text, int maxchars, short align, color_t color, color_t
bgcolor);
-------------------------------------------------------------------------------
Draws 'text' to the display, using the font with the specified 'font_id'
inside the rectangle set by 'bounds'. The yl element of 'bounds' is
ignored
here.
If 'maxchars' is non-negative, it sets the maximum amount of characters
that
will be written. 'align' sets the text alignment, and 'color' and
'bgcolor'
specify the foreground and background color, respectively.


3.2.6 register_pixmap(display_target_t *drv, resource_t *resource, int
loop,
----------------------------------------------------------------------------
        int cel)
----------------
Registers a graphical resource as a pixmap. 'resource' may be any of the
following:
- pic resource
- view resource
- cursor resource

'loop' and 'cel' specify loop and cel for view resources; they are ignored
for other resources.

(SCI1 defines more resources that will need to be covered by this
function)

The pixmap structure is not specified in any way; it should be something
the display target can operate on easily.
Note that pic resources consist of three layers (visual, priority, and
control); all of these must be handled here.


3.2.7 dispose_pixmap(display_taret_t *drv, int pxm_id)
------------------------------------------------------
Frees all ressources associated to the pixmap specified by 'pxm_id'.


3.2.8 draw_pixmap(display_target_t *drv, int pxm_id, rect_t source,
-------------------------------------------------------------------
        rect_t dest, byte priority, byte mask)
----------------------------------------------
Draws the region 'source' from the pixmap 'pxm_id' (source may be assumed
to be clipped) to the region 'dest' on the screen, using the specified
'priority' (if enforced by 'mask'). Resouces with built-in priority (like
pics) are not affected by 'mask'. GFX_MASK_CONTROL implies that the
pixmap's
control mask should now be set to be the active control mask.
This function should check for differences in the source and dest sizes,
and scale the pixmap, if neccessary.
[SCI0: Scaling is optional]


3.2.9 grab_screen(display_target_t *drv, int map)
-------------------------------------------------
Grabs one of the three display maps. 'map' must be one of GFX_MASK_VISUAL,
GFX_MASK_PRIORITY and GFX_MASK_CONTROL; the resulting pixmap should
therefore
consist only of a single layer.
The pixmap will be treated like a registered pixmap, i.e. it will be freed
when it is no longer needed.
Performance considerations: This function should be as fast as possible
for
GFX_MASK_VISUAL. GFX_MASK_PRIORITY and GFX_MASK_CONTROL are only used for
debugging purposes, so a (possibly costly) translation may occur for them.

Returns 0 on error.


3.2.10 register_pixmap_pointer(display_target_t *drv, resource_t
*resource)
---------------------------------------------------------------------------
Sets the indicated resource as the new mouse pointer. 'resource' may be of
any
resource type supported by register_pixmap().
[SCI0: Only cursor resources need to be supported]


3.3 Graphical meta-operations
-----------------------------

3.3.1 update(display_target_t *, rect_t)
----------------------------------------
Updates the visible display in the indicated region. Also updates the
mouse
pointer, if emulated in software.


3.3.2 set_palette(display_target_t *drv, color_t *palette)
----------------------------------------------------------
Sets the palette registers. 'palette' points to 256 color_t entries, which
should be used to set the palette. This function is a no-op for non-color
index modes.


3.3.3 get_control(display_target_t *drv, rect_t area)
-----------------------------------------------------
Returns the control mask of the specified area (usually an alias for a
standard utility function).


3.4 Event management
--------------------
This is basically the same as the original FreeSCI system.


3.4.1 get_event(display_target_t *drv)
--------------------------------------
Retreives the next event from the display target's event queue, without
blocking. May return the null event.


3.4.2 usleep(display_target_t *drv, int usecs)
----------------------------------------------
Waits 'usecs' microseconds. During this time, neccessary updates (pointer
updates, expose events etc.) may be handled by the graphics target.


4 Graphics support library and the resource loader
--------------------------------------------------
[TODO]

5 The widget state manager
--------------------------
[TODO]


Appendix A
----------
Revision history:
04/14/00: first draft of the driver infrastructure


---
llap,
 Christoph


Reply via email to