Hi.
I'm working in put up to date the GRX user's manual, attached to this mail is the first part, about video modes and context. Any comment will be apreciated.
Greetings, M.Alvarez
GRX 2.3 A graphics library for DOS, Linux and X11 User's Manual August 17, 2000 Based on the original doc written by: Csaba Biegl August 10, 1992 ---- Abstract
LIBGRX is a graphics library for DOS (DJGPP v2 and Turbo C/Borland C++ versions), Linux and X11. On DOS it supports VGA (32768, 256 or 16 colors), EGA (16 colors), and VESA compliant cards (up to 16M colors). On Linux console it uses svgalib. On X11 it must work on any X11R5 (or later).
Data types, function declarations
All public data structures and graphics primitives meant for usage by the application program are declared/prototyped in the header files (in the 'include' sub-directory):
grdriver.h graphics driver format specifications grfontdv.h format of a font when loaded into memory grx20.h drawing-related structures and functions grxkeys.h platform independent key definitions
User programs normally only include grx20.h and grxkeys.h
Setting the graphics driver
The graphics driver is normally set by the final user by the environment variable GRX20DRV, but a program can set it using:
int GrSetDriver(char *drvspec);
The drvspec string has the same format as the environment variable:
"<driver> gw <width> gh <height> nc <colors>"
Available drivers are for DOS : stdvga, stdega, et4000, cl5426, mach64, ati28800, VESA, memory Linux: svgalib, memory X11 : xwin, memory
The optionals gw, gh and nc parameters set the desired default graphics mode. Normal values for 'nc' are 2, 16, 256, 64K and 16M.
The current driver name can be obtained from:
GrCurrentVideoDriver()->name
Setting video modes
Before a program can do any graphics drawing it has to configure the graphics driver for the desired graphics mode. It is done with the 'GrSetMode' function as follows:
void GrSetMode(int which,...);
The 'which' parameter can be one of the following constants, declared in "grx20.h":
typedef enum _GR_graphicsModes { GR_80_25_text, GR_default_text, GR_width_height_text, GR_biggest_text, GR_320_200_graphics, GR_default_graphics, GR_width_height_graphics, GR_biggest_noninterlaced_graphics, GR_biggest_graphics, GR_width_height_color_graphics, GR_width_height_color_text, GR_custom_graphics, GR_width_height_bpp_graphics, GR_width_height_bpp_text, GR_custom_bpp_graphics, GR_NC_80_25_text, GR_NC_default_text, GR_NC_width_height_text, GR_NC_biggest_text, GR_NC_320_200_graphics, GR_NC_default_graphics, GR_NC_width_height_graphics, GR_NC_biggest_noninterlaced_graphics, GR_NC_biggest_graphics, GR_NC_width_height_color_graphics, GR_NC_width_height_color_text, GR_NC_custom_graphics, GR_NC_width_height_bpp_graphics, GR_NC_width_height_bpp_text, GR_NC_custom_bpp_graphics, } GrGraphicsMode;
The 'GR_width_height_text' and 'GR_width_height_graphics' modes require the two size arguments: int width and int height.
The 'GR_width_height_color_graphics' and 'GR_width_height_color_text' modes require three arguments: int width, int height and GrColor colors.
The 'GR_width_height_bpp_graphics' and 'GR_width_height_bpp_text' modes require three arguments: int width, int height and int bpp (bits per plane instead number of colors).
The 'GR_custom_graphics' and 'GR_custom_bpp_graphics' modes require five arguments: int width, int height, GrColor colors or int bpp, int vx and int vy. Using this modes you can set a virtual screen of 'vx' by 'vy' size.
A call with any other mode does not require any arguments.
The 'GR_NC_...' modes are equivalent to the 'GR_..' ones, but they don't clear the video memory.
Graphics drivers can provide info of the supported graphics modes, use the next code skeleton to colect the data:
{ GrFrameMode fm; const GrVideoMode *mp; for(fm =GR_firstGraphicsFrameMode; fm <= GR_lastGraphicsFrameMode; fm++) { mp = GrFirstVideoMode(fm); while( mp != NULL ){ .. .. use the mp info .. mp = GrNextVideoMode(mp)) } } }
Don't worry if you don't understand it, normal user programs don't need to know about FrameModes. The GrVideoMode structure has the following fields:
typedef struct _GR_videoMode GrVideoMode; struct _GR_videoMode { char present; /* is it really available? */ char bpp; /* log2 of # of colors */ short width,height; /* video mode geometry */ short mode; /* BIOS mode number (if any) */ int lineoffset; /* scan line length */ int privdata; /* driver can use it for anything */ struct _GR_videoModeExt *extinfo; /* extra info (maybe shared) */ };
The width, height and bpp members are the useful information if you are interested in set modes other than the 'GR_default_graphics'.
A user-defined function can be invoked every time the video mode is changed (i.e. 'GrSetMode' is called). This function should not take any parameters and don't return any value. It can be installed (for all subsequent 'GrSetMode' calls) with the:
void GrSetModeHook(void (*hookfunc)(void));
function. The current graphics mode (one of the valid 'mode' argument values for 'GrSetMode') can be obtained with the:
GrGraphicsMode GrCurrentMode(void);
function, while the type of the installed graphics adapter can be determined with the
GrVideoAdapter GrAdapterType(void);
function. 'GrAdapterType' returns the type of the adapter as one of the following symbolic constants (defined in "grx20.h"):
typedef enum _GR_videoAdapters { GR_UNKNOWN = (-1), /* not known (before driver set) */ GR_VGA, /* VGA adapter */ GR_EGA, /* EGA adapter */ GR_HERC, /* Hercules mono adapter */ GR_8514A, /* 8514A or compatible */ GR_S3, /* S3 graphics accelerator */ GR_XWIN, /* X11 driver */ GR_MEM /* memory only driver */ } GrVideoAdapter;
Note that the 'VESA' driver return 'GR_VGA' here.
Graphics contexts
The library supports a set of drawing regions called 'contexts' (the 'GrContext' structure). These can be in video memory or in system memory. Contexts in system memory always have the same memory organization as the video memory. When 'GrSetMode' is called, a default context is created which maps to the whole graphics screen. Contexts are described by the 'GrContext' data structure:
typedef struct _GR_context GrContext; struct _GR_context { struct _GR_frame gc_frame; /* frame buffer info */ struct _GR_context *gc_root; /* context which owns frame */ int gc_xmax; /* max X coord (width - 1) */ int gc_ymax; /* max Y coord (height - 1) */ int gc_xoffset; /* X offset from root's base */ int gc_yoffset; /* Y offset from root's base */ int gc_xcliplo; /* low X clipping limit */ int gc_ycliplo; /* low Y clipping limit */ int gc_xcliphi; /* high X clipping limit */ int gc_ycliphi; /* high Y clipping limit */ int gc_usrxbase; /* user window min X coordinate */ int gc_usrybase; /* user window min Y coordinate */ int gc_usrwidth; /* user window width */ int gc_usrheight; /* user window height */ # define gc_baseaddr gc_frame.gf_baseaddr # define gc_selector gc_frame.gf_selector # define gc_onscreen gc_frame.gf_onscreen # define gc_memflags gc_frame.gf_memflags # define gc_lineoffset gc_frame.gf_lineoffset # define gc_driver gc_frame.gf_driver };
The following four functions return information about the layout of and memory occupied by a graphics context of size 'width' by 'height' in the current graphics mode (as set up by 'GrSetMode'):
int GrLineOffset(int width); int GrNumPlanes(void); long GrPlaneSize(int w,int h); long GrContextSize(int w,int h);
'GrLineOffset' always returns the offset between successive pixel rows of the context in bytes. 'GrNumPlanes' returns the number of bitmap planes in the current graphics mode. 'GrContextSize' calculates the total amount of memory needed by a context, while 'GrPlaneSize' calculates the size of a bitplane in the context. The function:
GrContext *GrCreateContext(int w,int h,char far *memory[4],GrContext *where);
can be used to create a new context in system memory. The NULL pointer is also accepted as the value of the 'memory' and 'where' arguments, in this case the library allocates the necessary amount of memory internally. It is a general convention in the library that functions returning pointers to any LIBGRX specific data structure have a last argument (most of the time named 'where' in the prototypes) which can be used to pass the address of the data structure which should be filled with the result. If this 'where' pointer has the value of NULL, then the library allocates space for the data structure internally.
The 'memory' argument is really a 4 pointer array, each pointer must point to space to handle 'GrPlaneSize(w,h)' bytes, really only 'GrNumPlanes()' pointers must be malloced, the rest can be NULL. Nevertheless the normal use (see below) is 'gc = GrCreateContext(w,h,NULL,NULL)', so yo don't need to care about.
The function:
GrContext *GrCreateSubContext(int x1,int y1,int x2,int y2, const GrContext *parent,GrContext *where);
creates a new sub-context which maps to a part of an existing context. The coordinate arguments ('x1' through 'y2') are interpreted relative to the parent context's limits. Pixel addressing is zero-based even in sub-contexts, i.e. the address of the top left pixel is (0,0) even in a sub-context which has been mapped onto the interior of its parent context.
Sub-contexts can be resized, but not their parents (i.e. anything returned by 'GrCreateContext' or set up by 'GrSetMode' cannot be resized -- because this could lead to irrecoverable "loss" of drawing memory. The following function can be used for this purpose:
void GrResizeSubContext(GrContext *context,int x1,int y1,int x2,int y2);
The current context structure is stored in a static location in the library. (For efficiency reasons -- it is used quite frequently, and this way no pointer dereferencing is necessary.) The context stores all relevant information about the video organization, coordinate limits, etc... The current context can be set with the:
void GrSetContext(const GrContext *context);
function. This function will reset the current context to the full graphics screen if it is passed the NULL pointer as argument. The value of the current context can be saved into a 'GrContext' structure pointed to by 'where' using:
GrContext *GrSaveContext(GrContext *where);
(Again, if 'where' is NULL, the library allocates the space.) The next two functions:
const GrContext *GrCurrentContext(void); const GrContext *GrScreenContext(void);
return the current context and the screen context respectively. Contexts can be destroyed with:
void GrDestroyContext(GrContext *context);
This function will free the memory occupied by the context only if it was allocated originally by the library. The next three functions set up and query the clipping limits associated with the current context:
void GrSetClipBox(int x1,int y1,int x2,int y2); void GrGetClipBox(int *x1p,int *y1p,int *x2p,int *y2p); void GrResetClipBox(void);
'GrResetClipBox' sets the clipping limits to the limits of context. These are the limits set up initially when a context is created. There are three similar functions to sets/gets the clipping limits of any context:
void GrSetClipBoxC(GrContext *c,int x1,int y1,int x2,int y2); void GrGetClipBoxC(const GrContext *c,int *x1p,int *y1p,int *x2p,int *y2p); void GrResetClipBoxC(GrContext *c);
The limits of the current context can be obtained using the following functions:
int GrMaxX(void); int GrMaxY(void); int GrSizeX(void); int GrSizeY(void);
The 'Max' functions return the biggest valid coordinate, while the 'Size' functions return a value one higher. The limits of the graphics screen (regardless of the current context) can be obtained with:
int GrScreenX(void); int GrScreenY(void);
If you had set a virtual screen (using a custom graphics mode), the limits of the virtual screen can be fetched with:
int GrVirtualX(void); int GrVirtualY(void);
The routine:
int GrScreenIsVirtual(void);
returns non zero if a virtual screen is set. The rectangle showed in the real screen can be set with:
int GrSetViewport(int xpos,int ypos);
and the current viewport position can be obtained by:
int GrViewportX(void); int GrViewportY(void);
Context use
Here is a example of normal context use:
GrContext *grc;
if( (grc = GrCreateContext( w,h,NULL,NULL )) == NULL ){ ...process the error } else{ GrSetContext( grc ); ...do some drawing ...and probably bitblt to the screen context GrSetContext( NULL ); /* the screen context! */ GrDestroyContext( grc ); }
But if you have a GrContext variable (not a pointer) you want to use (probably because is static to some routines) you can do:
static GrContext grc; /* not a pointer!! */
if( GrCreateContext( w,h,NULL,&grc )) == NULL ){ ...process the error } else{ GrSetContext( &grc ); ...do some drawing ...and probably bitblt to the screen context GrSetContext( NULL ); /* the screen context! */ GrDestroyContext( &grc ); }
Note that GrDestoryContext know if grc was automatically malloced or no!!
Only if you don't want GrCreateContext use malloc at all, you must allocate the memory buffers and pass it to GrCreateContext.
Using GrCreateSubContext is the same, except it didn't need the buffer, because it uses the parent buffer.
Mariano Alvarez Fernandez wrote:
I'm working in put up to date the GRX user's manual, attached to
this mail is the first part, about video modes and context. Any comment will be apreciated.
Just one comment: Whow! (-8
This is what was missing all the time from GRX.
To make maximum use of it, someone should collect this manual (and other things) and bundle the next GRX release. Any takers?
Peter
Peter Gerwinski escribió:
Mariano Alvarez Fernandez wrote:
I'm working in put up to date the GRX user's manual, attached to
this mail is the first part, about video modes and context. Any comment will be apreciated.
Just one comment: Whow! (-8
Thanks
This is what was missing all the time from GRX.
To make maximum use of it, someone should collect this manual (and other things) and bundle the next GRX release. Any takers?
I had two reasons to mail it by parts: first to encourage myself to write; second I expect somebody check my english and any wrong technical assumption I can do.
If nobody have the time, I will try to package next release. I think the most urgent thing to do it's adapt the bgi copyright to the GRX one, if Hartmut agree.
Greetings, M.Alvarez