Mail Archives: djgpp/1993/10/09/18:31:53
Well, here's the first provisional copy of my LIBGRX driver for the
VOGL 'GL' emulation.
Fool that I am, I started in on implementing a back-buffer for VGA
(other recommendations welcome), and then, double-a-fool, I sought to
optimize it a little by putting the asm code in-line (adapted from
XFER.S). The linked version worked, and a first inline version that
called a C function also worked, but inline I get the errors:
cd c:/vogl/drivers/
make -k
gcc -I../src -O2 -M > depend
Incorrect DOS version
gcc -c -I../src -O2 grx.c
grx.c:256:operands given don't match any known 386 instruction
grx.c:270:operands given don't match any known 386 instruction
make.exe: *** [grx.o] Error 1
make.exe: Target `all' not remade because of errors.
These errors vanish if I comment out the first "asm volatile" section
in the grx_swapbuffers function! What did I do wrong? Any and all
suggestions, recommendations and obtuse musing are most welcome ;-)
The good news is, it works. I can compile all of the VOGL examples
and while slow, I get what I should get. I'm also open to caveats
about implementing Events and any other speed-ups.
Here's the code: If you want to hook this into a VOGL port, you will
also need to update DRIVERS.C to include a GRX driver, then hack up the
makefiles to avoid spilling over the max-line-length of MsDOS :-(
--------------------------------cut here--------------------------------
/*
* GRX driver for VOGL c1993 by Gary Murphy garym AT virtual DOT rose DOT utoronto DOT c
*
*/
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <memory.h>
#include <grx.h>
#include <mousex.h>
#define MSG( m ) fprintf(stderr, "\n%s: %d: %s", __FILE__, __LINE__, (m))
#define ERROR1( m, p ) fprintf(stderr, "\n%s: %d: " m, __FILE__, __LINE__, (p))
#include "vogl.h"
#define MAXCOLOR 256
static struct {
GR_graphics_modes old_mode;
int width, height, planes;
unsigned scrsize; /* size of buffer in long words */
GrContext *cbuf; /* current context */
GrContext *fbuf;
GrContext *bbuf;
int palette[8];
GrLineOption lopt; /* pen drawing options */
int fg; /* foreground/background colours */
int bg;
int has_mouse;
GrFont *font;
GrFont *lfont;
GrFont *sfont;
/* GrTextOption *lfont;
* GrTextOption *sfont;
*/
int cx;
int cy;
} grx;
/* access functions: *
/* I'm going to need this to fudge in stereo graphics ... */
GrContext *setBackBuffer( GrContext *newBB )
{
GrContext *oldBB = grx.bbuf;
assert( newBB != NULL);
grx.bbuf = newBB;
return oldBB;
}
static int
grx_init()
{
grx.old_mode = GrCurrentMode();
GrSetMode(GR_default_graphics);
#ifndef VOGLE
vdevice.devname = "Grx";
#endif
/* set the VOGL device */
vdevice.sizeX = GrSizeY(); /* square max, was GrScreenX(); */
vdevice.sizeY = GrSizeY();
grx.width = vdevice.sizeSx = GrScreenX();
grx.height = vdevice.sizeSy = GrScreenY();
grx.planes = vdevice.depth = GrNumPlanes();
grx.scrsize=( GrPlaneSize(grx.width, grx.height)* grx.planes)/sizeof(long);
/* setup default palette */
GrSetRGBcolorMode();
grx.lopt.lno_color = grx.fg = GrWhite();
grx.bg = GrBlack();
grx.palette[BLACK] = GrAllocColor( 0, 0, 0 );
grx.palette[RED] = GrAllocColor( 255, 0, 0 );
grx.palette[GREEN] = GrAllocColor( 0, 255, 0 );
grx.palette[YELLOW] = GrAllocColor( 255, 255, 0 );
grx.palette[BLUE] = GrAllocColor( 0, 0, 255 );
grx.palette[MAGENTA] = GrAllocColor( 255, 0, 255 );
grx.palette[CYAN] = GrAllocColor( 0, 255, 255 );
grx.palette[WHITE] = GrAllocColor( 255, 255, 255 );
/* setup back/front buffers:
* frontbuffer is the current screen, back is a ram context
*/
grx.cbuf = grx.fbuf = GrSaveContext( NULL );
grx.bbuf = NULL;
/* initialize mouse */
if ((grx.has_mouse = MouseDetect())==TRUE)
{
/* can I do interrupts? stay polled for now ... */
MouseEventMode(0);
MouseInit();
/* no keyboard (use getch) */
MouseEventEnable(0, 1);
/* cheezy mouse speed algorithm */
if (grx.width * grx.height < 100000)
MouseSetSpeed(6);
else if (grx.width * grx.height < 200000)
MouseSetSpeed(4);
else if (grx.width * grx.height < 500000)
MouseSetSpeed(3);
else
MouseSetSpeed(2);
MouseWarp(1,1);
MouseDisplayCursor();
};
/* initial drawing style to thin solid lines */
grx.lopt.lno_width = 1;
grx.lopt.lno_pattlen = 0;
grx.lopt.lno_dashpat = NULL;
/* load initial fonts */
if(getenv("GRXFONT") == NULL) GrSetFontPath("fonts");
grx.font = grx.sfont = grx.lfont = NULL;
vdevice.hwidth = 8.0;
vdevice.hheight = 8.0;
return (1);
}
/*
* grx_frontbuffer, grx_backbuffer, grx_swapbuffers
*
*/
static
int grx_frontbuffer()
{ grx.cbuf = grx.fbuf; GrSetContext( grx.fbuf ); return (0); }
static
int grx_backbuffer()
{
/* if they want a backbuffer, we'd better make one ... */
if (grx.bbuf == NULL)
grx.bbuf = GrCreateContext( GrSizeX(), GrSizeY(), NULL, NULL );
assert( grx.bbuf != NULL);
grx.cbuf = grx.bbuf;
GrSetContext( grx.bbuf );
return (0);
}
static
int grx_swapbuffers()
{
if (grx.cbuf == grx.fbuf )
grx_backbuffer();
else
{
unsigned long *zptr = (unsigned long *) grx.bbuf->gc_baseaddr;
/* there is no inherently portable VGA backbuffer.
* the following copies by long words from back to front buffer
* modify this for regions by triming the first x-limit and y-limit
* and upping the pointers to the start of your subcontext
*/
unsigned long *sptr = (unsigned long *) grx.bbuf->gc_baseaddr;
unsigned long *tptr = (unsigned long *) grx.fbuf->gc_baseaddr;
unsigned lc = 0;
asm volatile(" \n\
yloop: \n\
movl %1,%%ecx \n\
cmpl %%ecx,%6 \n\
jae alldone \n\
cld \n\
xloop: \n\
movl %4,%%esi \n\
movl %5,%%edi \n\
movl %0,%%ecx \n\
rep \n\
movsl \n\
xdone: \n\
movl %2,%%ecx \n\
addl %%ecx,%4 \n\
movl %3,%%ecx \n\
addl %%ecx,%5 \n\
incl %6 \n\
jmp yloop \n\
alldone: " \
: /*no output*/ \
: "g" (grx.width), "g" (grx.height), \
"g" (grx.bbuf->gc_lineoffset), \
"g" (grx.fbuf->gc_lineoffset), \
"g" (sptr), "g" (tptr), "g" (lc) \
: "si", "di", "cx" ); \
asm volatile(" \n\
movl %0,%%edi \n\
movl %1,%%ecx \n\
xorl %%eax,%%eax \n\
cld \n\
rep \n\
stosl "\
: /*no output*/ \
: "g" (zptr), "g" (grx.scrsize) \
: "di", "cx" ); \
}
return (0);
}
#ifdef VOGLE
/*
* grx_vclear
*
* Clear the screen to current colour
*/
grx_vclear()
{
GrClearScreen(grx.fg);
}
#else
/*
* grx_vclear
*
* Clear the viewport to current colour
*/
static int
grx_vclear()
{
unsigned int vw = vdevice.maxVx - vdevice.minVx;
unsigned int vh = vdevice.maxVy - vdevice.minVy;
if ((vdevice.sizeSx == vw) && (vdevice.sizeSy == vh))
GrClearScreen(grx.fg); /* full screen */
else
GrFilledBox(
vdevice.minVx,
vdevice.sizeSy - vdevice.maxVy,
grx.width,
grx.height,
grx.fg);
return (1);
}
#endif
/*
* grx_exit
*
* Sets the display back to text mode.
*/
static
grx_exit()
{
MouseUnInit(); /* disable mouse/keyboard interrupts */
GrSetMode( grx.old_mode );
GrDestroyContext( grx.bbuf );
return (1);
}
static int grx_sync () {};
static int
noop()
{
return (-1);
}
/*
* grx_font : load either of the fonts
*/
static int
grx_font(char *name)
{
GrUnloadFont( grx.font );
grx.font = GrLoadFont( name );
vdevice.hheight = 16;
vdevice.hwidth = 8;
return (1);
}
static
int grx_char( int c )
{
static char s[2] = "\0\0";
s[0] = c;
GrTextXY(vdevice.cpVx, vdevice.sizeSy - vdevice.cpVy + 16, s, grx.fg, 0);
return (1);
};
static int
grx_string(char *s)
{
GrTextXY(vdevice.cpVx, vdevice.sizeSy - vdevice.cpVy + 16, s, grx.fg, 0);
return (1);
}
static int
grx_draw( int x, int y )
{
GrCustomLine(vdevice.cpVx,
vdevice.sizeSy - vdevice.cpVy,
x, vdevice.sizeSy - y,
&grx.lopt );
vdevice.cpVx = x;
vdevice.cpVy = y;
return(0);
};
static int
grx_colour(int i)
{
if (i<MAXCOLOR) grx.fg = grx.palette[i]; /* for now */
else grx.fg = GrBlack();
grx.lopt.lno_color = grx.fg;
return (0);
};
/*
* grx_mapcolor
*
* change index i in the color map to the appropriate r, g, b, value.
*/
static int
grx_mapcolor(int c, int r, int g, int b)
{
int j;
if (c >= MAXCOLOR || vdevice.depth == 1)
return(-1);
grx.palette[c] = GrAllocColor(r, g, b);
}
static int
grx_fill( int sides, int *x, int *y )
{
int i,j;
int points[sides][2];
for (i=0; i<sides; i++)
{
points[i][0] = x[i];
points[i][1] = grx.height - y[i];
}
GrFilledPolygon( sides, points, grx.fg );
return (0);
};
static int
grx_checkkey()
{
char c;
if (kbhit()) {
if ((c = getkey()) == 3) { /* control-c */
grx_exit();
/* don't call vexit(), avoid back-refs */
exit(0);
} else
return c;
} else return 0;
}
static int
grx_locator(int *x, int *y)
{
MouseEvent mEv;
static ox = 0, oy = 0, obuttons = 0;
if (!grx.has_mouse)
{
*x = *y = 0;
return (-1);
}
MouseGetEvent( M_MOTION | M_BUTTON_CHANGE | M_POLL, &mEv );
if (mEv.flags & M_MOTION) {
ox = mEv.x;
oy = vdevice.sizeSy - mEv.y;
}
if (mEv.flags & M_BUTTON_CHANGE) {
obuttons = ((mEv.buttons & M_LEFT) ? 1 : 0) |
((mEv.buttons & M_MIDDLE) ? 2 : 0) |
((mEv.buttons & M_RIGHT) ? 4 : 0);
}
*x = ox;
*y = oy;
return (obuttons);
}
static
int grx_lwidth( int w )
{
grx.lopt.lno_width = w;
}
static DevEntry grxdev = {
"grx",
"@:pc8x8.fnt",
"@:pc8x16.fnt",
grx_backbuffer, /* backbuffer */
grx_char, /* hardware char */
grx_checkkey, /* keyhit */
grx_vclear, /* clear viewport to current colour */
grx_colour, /* set current colour */
grx_draw, /* draw line */
grx_exit, /* close graphics & exit */
grx_fill, /* fill polygon */
grx_font, /* set hardware font */
grx_frontbuffer, /* front buffer */
getkey, /* wait for and get key */
grx_init, /* begin graphics */
grx_locator, /* get mouse position */
grx_mapcolor, /* map colour (set indices) */
noop, /* set linestyle */
grx_lwidth, /* set line width */
grx_string, /* draw string of chars */
grx_swapbuffers, /* swap buffers */
grx_sync /* sync display */
};
/*
* _grx_devcpy
*
* copy the pc device into vdevice.dev. (as listed in drivers.c)
*/
_grx_devcpy()
{
vdevice.dev = grxdev;
return(0);
}
/*
* Gary Lawrence Murphy ----------------- garym AT virtual DOT rose DOT utoronto DOT ca
* University of Toronto ---------- 4 Taddle Creek, Toronto, Ont M5S 1A4
* Human Factors, Ind Engineering ------------ fax/voice: (416) 978-3776
* ----------------------- The true destination is always just here, now
*/
- Raw text -