Date: Sat, 9 Oct 1993 22:11:17 -0400 From: garym AT virtual DOT rose DOT utoronto DOT ca (Gary Lawrence Murphy) To: djgpp AT sun DOT soe DOT clarkson DOT edu, bernie AT ecr DOT mu DOT oz DOT au, thinman AT netcom DOT com Subject: UPDATE: GRX.C Driver for VOGL Stop the presses! Here's a corrected version of my GRX.C driver for the VOGL 3D graphics library. Having made the pointers 'volatile' and using GrClearContext in grx_vclear, I've got passable double buffering on a 486. I'm not happy with a polled mouse, some fonts won't load, and I still need to hack events for 3D and 6D pointers, but it's late and I'm out of Jack Daniel's. Just for fun (and for those who don't know VOGL or SGI's GL) I'll send my Red/Blue stereo 3D version of the tetra demo source and binary in a uuencoded zip file to follow this message (my apologies for the bandwidth ;-) [ cut here ] /* * GRX driver for VOGL c1993 by Gary Murphy (garym AT virtual DOT rose DOT utoronto DOT ca) * * To compile: * * 1) add GRX to device.c and mash-up your makefiles for MsDOS * 2) compile with DOBJ=-DPOSTSCRIPT -DHPGL -DGRX and MFLAGS=-O2 * * To run: * * set VDEVICE=grx * * grateful thanks to Lance Norskog (thinman AT netcom DOT com) and Birnie * Kirby (bernie AT ecr DOT mu DOT oz DOT au) --- should either of you be in my * neighbourhood, my offer of an Ice Beer is still open! */ #include #include #include #include #include #include #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 */ volatile unsigned long *sptr = (unsigned long *) grx.bbuf->gc_baseaddr; volatile unsigned long *tptr = (unsigned long *) grx.fbuf->gc_baseaddr; volatile 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" ); \ } 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)) { if (grx.fg == GrBlack()) { volatile unsigned long *zptr = (unsigned long *) grx.bbuf->gc_baseaddr; 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" ); \ } else GrClearContext(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 || 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