blob: 1c380d5276d58ce7d9367bbd6ea46f43bc6bcd9d [file] [log] [blame]
/* $Id: dosmesa.c,v 1.1.1.1 1999/08/19 00:55:41 jtg Exp $ */
/*
* Mesa 3-D graphics library
* Version: 2.3
* Copyright (C) 1995-1997 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* $Log: dosmesa.c,v $
* Revision 1.1.1.1 1999/08/19 00:55:41 jtg
* Imported sources
*
* Revision 1.2 1999/03/28 21:11:57 brianp
* updated SetBuffer driver function
*
* Revision 1.1 1999/02/24 03:56:31 brianp
* initial check-in
*
*
* Revision 1.5 1997/06/19 22:00:00 Brian Paul
* Removed all ColorShift stuff
*
* Revision 1.4 1997/06/03 19:00:00 Brian Paul
* Replaced VB->Unclipped[] with VB->ClipMask[]
*
* Revision 1.3 1997/05/28 07:00:00 Phil Frisbie, Jr.
* Now pass red/green/blue/alpha bits to gl_create_visual()
* Fixed DJGPP mode 13 support.
*
* Revision 1.2 1996/12/08 16:13:45 Charlie
* Added VESA support via Scitechs SVGA kit.
*
* Revision 1.1 1996/12/08 16:09:52 Charlie
* Initial revision
*
*/
/*
* DOS VGA/VESA/MGL/Mesa interface.
*
*/
/*
*
* TODO: (cw)
* Improve the colour matcher for rgb non vesa modes, its pretty bad and incorrect
* Keyboard interrupt.
* Comments and tidy up.
* Add support for VESA without SVGAKIT.
* DirectX Support.
* Better GLIDE Support.
* Clear up the #ifdef madness.
*/
#ifdef DOSVGA
#if defined(DOSVGA) && !defined(GLIDE) && defined(DJGPP) && !defined(UNIVBE) && !defined(MGL)
/* Should help cut down on the crazy #if`s */
#define MODE13 1
#else
#undef MODE13
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <dos.h>
#ifdef DJGPP
#include <go32.h>
#endif
#ifdef MGL
#include <mgraph.h>
#endif
#include "GL/DOSmesa.h"
#include "context.h"
#include "matrix.h"
#include "types.h"
#ifdef GLIDE
static void glideshutdown( void );
#include "vb.h"
#include "glide.h"
/* the glide modes available, set one */
//#define GLIDE_MODE GR_RESOLUTION_
#define GLIDE_MODE GR_RESOLUTION_800x600
//#define GLIDE_MODE GR_RESOLUTION_640x480
static GrVertex gr_vtx,gr_vtx1,gr_vtx2;
#endif
#ifdef UNIVBE
/* You get this file from Scitechs VESA development kit */
#include "svga.h"
/*
Set these to the VESA mode you require, the first is for 256 colour modes,
the other is High colour modes, they must both be the same XRes and YRes.
*/
#define VESA_256COLOUR_MODE 0x11c
#define VESA_HICOLOUR_MODE 0x11f
#endif
struct DOSmesa_context {
GLcontext *gl_ctx; /* the core Mesa context */
GLvisual *gl_vis; /* describes the color buffer */
GLframebuffer *gl_buffer; /* the ancillary buffers */
GLuint index; /* current color index */
GLint red, green, blue; /* current rgb color */
GLint width, height; /* size of color buffer */
GLint depth; /* bits per pixel (8,16,24 or 32) */
};
static DOSMesaContext DOSMesa = NULL; /* the current context */
#ifdef UNIVBE
SV_devCtx *DC=NULL;
int useLinear = TRUE;
SV_modeInfo *mi=NULL;
unsigned long modeNumber = 0;
int activePage = 0;
int visualPage = 1;
#endif
#if defined(MODE13)
/* DOSVGA With no UniVBE support */
unsigned char *video_buffer;
#define VID_BUF(x,y) *(video_buffer+x+(y*320))
#if defined(__WATCOMC__) && defined(__386__) && defined(__DOS__)
void setupcopy(void);
void copyscr(void);
/* Watcom C specfic, screen copy and clear */
#pragma aux setupcopy = \
".386P"\
"push ebp" \
"mov esi,video_buffer" \
"mov edi,0xa0000" \
"mov ecx,2000" \
"xor ebp,ebp";
#pragma aux copyscr = \
".386P" \
"lop1: mov eax,[esi]"\
"mov ebx,[esi+4]"\
"mov edx,[esi+8]"\
"mov [edi],eax"\
"mov eax,[esi+12]"\
"mov dword ptr [esi],ebp"\
"mov dword ptr [esi+4],ebp"\
"mov dword ptr [esi+8],ebp"\
"mov dword ptr [esi+12],ebp"\
"mov [edi+4],ebx"\
"mov [edi+8],edx"\
"mov [edi+12],eax"\
"mov eax,[esi+16]"\
"mov ebx,[esi+4+16]"\
"mov edx,[esi+8+16]"\
"mov [edi+16],eax"\
"mov eax,[esi+12+16]"\
"mov dword ptr [esi+16],ebp"\
"mov dword ptr [esi+4+16],ebp"\
"mov dword ptr [esi+8+16],ebp"\
"mov dword ptr [esi+12+16],ebp"\
"mov [edi+4+16],ebx"\
"mov [edi+8+16],edx"\
"mov [edi+12+16],eax"\
"add esi,32"\
"add edi,32"\
"dec ecx"\
"jnz lop1"\
"pop ebp"\
modify exact [edi esi eax ebx ecx] ;
#endif // WATCOM
#endif // MODE13
/*
* Convert Mesa window Y coordinate to VGA screen Y coordinate:
*/
#define FLIP(Y) (DOSMesa->height-(Y)-1)
unsigned short vga_cindex = 32768 ;
static points_func choose_points_function( void );
static line_func choose_line_function( void );
static triangle_func choose_polygon_function( void );
static void fast_tri(GLcontext *ctx,GLuint v0, GLuint v1, GLuint v2, GLuint pv );
static points_func choose_points_function( void )
{
return NULL;
}
static line_func choose_line_function( void )
{
return NULL;
}
static triangle_func choose_triangle_function( void )
{
#if defined(MODE13)
return NULL;
#endif
#if defined(GLIDE)
return fast_tri;
#endif
return NULL;
}
#if defined(MODE13)
void setgfxmode(void);
void settextmode(void);
#ifndef DJGPP
#pragma aux setgfxmode = \
"mov ax,13h" \
"int 10h" \
modify [eax];
#pragma aux settextmode = \
"mov ax,3h" \
"int 10h" \
modify [eax];
#else
void setgfxmode(void)
{
union REGS in_regs,out_regs;
in_regs.x.ax = 0x13;
int386(0x10,&in_regs,&out_regs);
}
void settextmode(void)
{
union REGS in_regs,out_regs;
in_regs.x.ax = 0x3;
int386(0x10,&in_regs,&out_regs);
}
#endif
int set_video_mode(unsigned short x,unsigned short y,char mode)
{
setgfxmode();
return 1; /* likelyhood of this failing is very small */
}
void restore_video_mode(void)
{
settextmode();
}
int vga_getcolors(void)
{
return vga_cindex;
}
int vga_getxdim(void)
{
return 320;
}
int vga_getydim(void)
{
return 200;
}
static unsigned short num_rgb_alloc = 1; /* start from 1, zero is black */
/* an unlikely colour */
static unsigned char last_r=1,last_g=255,last_b=99;
extern void set_onecolor(int index,int R,int G,int B);
static unsigned char rgbtable[64][64][64];
void vga_setrgbcolor(int r,int g,int b)
{
/*
* make this into a translation table
*/
DOSMesa->red = r;
DOSMesa->green = g ;
DOSMesa->blue = b ;
r/=4; g/=4; b/=4;
if( (r == last_r) && (g == last_g) && (b == last_b) ) return;
last_r = r ;
last_g = g ;
last_b = b ;
if(r+g+b == 0 ) {
DOSMesa->index = 0 ;
return ;
}
if( rgbtable[r][g][b] == 0 ) {
/* not allocated yet */
if(num_rgb_alloc<256) {
DOSMesa->index = num_rgb_alloc;
set_onecolor(num_rgb_alloc,r,g,b);
rgbtable[r][g][b] = num_rgb_alloc;
num_rgb_alloc++;
return;
} else {
/* need to search for a close colour */
{
unsigned short pass ;
for(pass=0;pass<64;pass++) {
if(r-pass>0) {
if( rgbtable[r-pass][g][b] !=0 ) {
rgbtable[r][g][b] = rgbtable[r-pass][g][b];
DOSMesa->index = rgbtable[r-pass][g][b];
return;
}
}
if(r+pass<64) {
if( rgbtable[r+pass][g][b] !=0 ) {
rgbtable[r][g][b] = rgbtable[r+pass][g][b];
DOSMesa->index = rgbtable[r+pass][g][b];
return;
}
}
}
}
rgbtable[r][g][b] = rand()%255;
}
}
DOSMesa->index = rgbtable[r][g][b];
}
#if defined(DJGPP)
static int dos_seg;
#endif
void vga_clear(void)
{
/* Check if we`re using watcom and DOS */
#if defined(__WATCOMC__) && defined(__386__) && defined(__DOS__)
setupcopy();
copyscr();
#else
#if defined (DJGPP)
asm ("
pusha
pushw %es
movw _dos_seg, %es
movl _video_buffer, %esi
movl $0xa0000, %edi
movl $64000, %ecx
rep ; movsb
popw %es
popa
");
#else
/* copy the RAM buffer to the Video memory */
memcpy((unsigned char *)0xa0000,video_buffer, vga_getxdim()*vga_getydim() );
#endif //DJGPP
/* clear the RAM buffer */
memset(video_buffer,0, vga_getxdim()*vga_getydim() );
#endif //WATCOMC
}
#ifndef DEBUG
#define vga_drawpixel(x,y) { VID_BUF(x,y) = DOSMesa->index; }
#else
void vga_drawpixel(x,y)
{
VID_BUF(x,y) = DOSMesa->index;
}
#endif
int vga_getpixel(int x,int y)
{
return 1;
}
void vga_flip(void)
{
}
void vga_setcolor(int index)
{
/* does something, what i`ve no idea */
DOSMesa->index = index;
}
#endif
#if defined(UNIVBE)
/* UniVBE VESA support */
void set_video_mode(unsigned short x,unsigned short y,char mode)
{
if( setup_vesa_mode(x,y,mode) == FALSE ) {
fprintf(stderr,"VESA: Set mode failed\n");
exit(1);
}
}
/*
This is problematic as we don`t know what resolution the user program
wants when we reach here. This is why the 256 colour and HiColour modes
should be the same resolution, perhaps i`ll make this an environment
variable
*/
void check_mi(void)
{
if(mi!=0) return;
if(DC==NULL) {
DC = SV_init( TRUE );
}
if(modeNumber == 0 ) {
modeNumber = VESA_HICOLOUR_MODE;
}
SV_getModeInfo(modeNumber,mi);
return;
}
int setup_vesa_mode(short height,short width,short depth)
{
if(DC==NULL) {
DC = SV_init( TRUE );
/* how many bits per pixel */
if( depth == 0)
modeNumber = VESA_256COLOUR_MODE;
else
modeNumber = VESA_HICOLOUR_MODE;
}
/* Check if correct VESA Version is available */
if( !DC || DC->VBEVersion < 0x0102) {
fprintf(stderr,"Require a VESA VBE version 1.2 or higher\n");
return FALSE;
}
/* Check for LFB Supprt */
if(DC->VBEVersion < 0x0200 ) {
useLinear = FALSE;
} else {
useLinear = TRUE ;
}
/* Get desired mode info */
if(!SV_getModeInfo( modeNumber, mi))
return FALSE;
/* Set VESA mode */
if(!SV_setMode(modeNumber | svMultiBuffer, FALSE, TRUE, mi->NumberOfPages) )
return FALSE;
return TRUE;
}
void restore_video_mode(void)
{
SV_restoreMode();
}
void vga_clear(void)
{
SV_clear(0);
}
void vga_flip(void)
{
activePage = 1-activePage;
visualPage = 1-activePage;
SV_setActivePage(activePage);
/*
Change false to true if you`re getting flickering
even in double buffer mode, ( sets wait for Vertical retrace )
*/
SV_setVisualPage(visualPage,false);
}
int vga_getcolors(void)
{
check_mi();
switch ( mi->BitsPerPixel ) {
case 8:
return 256;
case 15:
case 16:
return 32768;
default:
return 64000;
}
}
int vga_getxdim(void)
{
check_mi();
return mi->XResolution;
}
int vga_getydim(void)
{
check_mi();
return mi->YResolution;
}
unsigned long current_color = 255;
void vga_setrgbcolor(int r,int g,int b)
{
DOSMesa->red = r;
DOSMesa->green = g ;
DOSMesa->blue = b ;
current_color = SV_rgbColor(r,g,b);
}
void vga_setcolor(int index)
{
DOSMesa->index = index;
current_color = index;
}
void vga_drawpixel(x,y)
{
SV_putPixel(x,y,current_color);
}
/* TODO: */
int vga_getpixel(x,y)
{
/* return (int)SV_getPixel(x,y); */
fprintf(stderr,"vga_getpixel: Not implemented yet\n");
return 1;
}
/* End of UNIVBE section */
#endif
/* Scitechs MegaGraphicsLibrary http://www.scitechsoft.com/ */
#if defined(MGL)
/* MGL support */
struct MI {
unsigned short BitsPerPixel;
unsigned long XResolution;
unsigned long YResolution;
};
struct MI*mi;
static MGLDC*DC;
static int activePage = 0;
static int visualPage = 1;
static int modeNumber = 0;
void set_video_mode(unsigned short xres,unsigned short yres,char mode)
{
int i,driver = grDETECT,dmode = grDETECT;
event_t evt;
/* Start the MGL with only the SVGA 16m driver active */
MGL_registerDriver(MGL_SVGA16NAME,SVGA16_driver);
if (!MGL_init(&driver,&dmode,"..\\..\\"))
MGL_fatalError(MGL_errorMsg(MGL_result()));
if ((DC = MGL_createDisplayDC(false)) == NULL)
MGL_fatalError(MGL_errorMsg(MGL_result()));
MGL_makeCurrentDC(DC);
}
/*
This is problematic as we don`t know what resolution the user program
wants when we reach here. This is why the 256 colour and HiColour modes
should be the same resolution, perhaps i`ll make this an environment
variable
*/
#define MGL_HICOLOUR_MODE 0
void check_mi(void)
{
if(mi!=0) return;
if(DC==NULL) {
// DC = SV_init( TRUE );
}
if(modeNumber == 0 ) {
modeNumber = MGL_HICOLOUR_MODE;
}
// SV_getModeInfo(modeNumber,mi);
return;
}
void restore_video_mode(void)
{
MGL_exit();
}
void vga_clear(void)
{
MGL_clearDevice();
}
void vga_flip(void)
{
activePage = 1-activePage;
visualPage = 1-activePage;
// SV_setActivePage(activePage);
/*
Change false to true if you`re getting flickering
even in double buffer mode, ( sets wait for Vertical retrace )
*/
// SV_setVisualPage(visualPage,false);
}
int vga_getcolors(void)
{
check_mi();
switch ( mi->BitsPerPixel ) {
case 8:
return 256;
case 15:
case 16:
return 32768;
default:
return 64000;
}
}
int vga_getxdim(void)
{
check_mi();
return mi->XResolution;
}
int vga_getydim(void)
{
check_mi();
return mi->YResolution;
}
unsigned long current_color = 255;
void vga_setrgbcolor(int r,int g,int b)
{
DOSMesa->red = r;
DOSMesa->green = g ;
DOSMesa->blue = b ;
current_color = MGL_rgbColor(DC,r,g,b);
}
void vga_setcolor(int index)
{
DOSMesa->index = index;
current_color = index;
}
void vga_drawpixel(x,y)
{
MGL_pixelCoord(x,y);
}
/* TODO: */
int vga_getpixel(x,y)
{
/* return (int)SV_getPixel(x,y); */
fprintf(stderr,"vga_getpixel: Not implemented yet\n");
return 1;
}
/* End of UNIVBE section */
#endif
#ifdef GLIDE
/* GLIDE support */
static GrHwConfiguration hwconfig;
void set_video_mode(unsigned short x,unsigned short y,char mode)
{
grGlideInit();
if( grSstQueryHardware( &hwconfig ) ) {
grSstSelect( 0 ) ;
if( !grSstOpen( GLIDE_MODE,
GR_REFRESH_60Hz,
GR_COLORFORMAT_ABGR,
GR_ORIGIN_UPPER_LEFT,
GR_SMOOTHING_ENABLE,
2 ) ) {
fprintf(stderr,"Detected 3DFX board, but couldn`t initialize!");
exit(1);
}
grBufferClear( 0, 0, GR_WDEPTHVALUE_FARTHEST);
grDisableAllEffects();
atexit( glideshutdown );
// guColorCombineFunction( GR_COLORCOMBINE_ITRGB );
// grTexCombineFunction( GR_TMU0, GR_TEXTURECOMBINE_ZERO);
}
}
void restore_video_mode(void)
{
}
static void glideshutdown( void )
{
grGlideShutdown() ;
}
void vga_clear(void)
{
grBufferSwap(0);
grBufferClear( 0, 0, GR_WDEPTHVALUE_FARTHEST);
}
void vga_flip(void)
{
}
int vga_getcolors(void)
{
return 32768;
}
int vga_getxdim(void)
{
#if GLIDE_MODE == GR_RESOLUTION_800x600
return 800;
#else
return 640;
#endif
}
int vga_getydim(void)
{
#if GLIDE_MODE == GR_RESOLUTION_800x600
return 600;
#else
return 480;
#endif
}
unsigned long current_color = 255;
void vga_setrgbcolor(int r,int g,int b)
{
DOSMesa->red = r;
DOSMesa->green = g ;
DOSMesa->blue = b ;
}
void vga_setcolor(int index)
{
DOSMesa->index = index;
}
void vga_drawpixel(x,y)
{
gr_vtx.x = x;
gr_vtx.y = y;
gr_vtx.z = 0;
gr_vtx.r = DOSMesa->red;
gr_vtx.g = DOSMesa->green;
gr_vtx.b = DOSMesa->blue;
grDrawPoint( &gr_vtx );
}
static void fast_tri(GLcontext *ctx,GLuint v0, GLuint v1, GLuint v2, GLuint pv )
{
struct vertex_buffer *VB = ctx->VB;
gr_vtx.z = 0;
gr_vtx1.z = 0;
gr_vtx2.z = 0;
if (VB->MonoColor) {
gr_vtx.r = DOSMesa->red;
gr_vtx.g = DOSMesa->green;
gr_vtx.b = DOSMesa->blue;
gr_vtx1.r = DOSMesa->red;
gr_vtx1.g = DOSMesa->green;
gr_vtx1.b = DOSMesa->blue;
gr_vtx2.r = DOSMesa->red;
gr_vtx2.g = DOSMesa->green;
gr_vtx2.b = DOSMesa->blue;
} else {
if(ctx->Light.ShadeModel == GL_SMOOTH ) {
gr_vtx.r = FixedToInt( VB->Color[v0][0] );
gr_vtx.g = FixedToInt( VB->Color[v0][1] );
gr_vtx.b = FixedToInt( VB->Color[v0][2] );
gr_vtx1.r = FixedToInt( VB->Color[v1][0] );
gr_vtx1.g = FixedToInt( VB->Color[v1][1] );
gr_vtx1.b = FixedToInt( VB->Color[v1][2] );
gr_vtx2.r = FixedToInt( VB->Color[v2][0] );
gr_vtx2.g = FixedToInt( VB->Color[v2][1] );
gr_vtx2.b = FixedToInt( VB->Color[v2][2] );
} else {
gr_vtx.r = VB->Color[pv][0];
gr_vtx.g = VB->Color[pv][1];
gr_vtx.b = VB->Color[pv][2];
gr_vtx1.r = VB->Color[pv][0];
gr_vtx1.g = VB->Color[pv][1];
gr_vtx1.b = VB->Color[pv][2];
gr_vtx2.r = VB->Color[pv][0];
gr_vtx2.g = VB->Color[pv][1];
gr_vtx2.b = VB->Color[pv][2];
}
}
gr_vtx.x = (VB->Win[v0][0] );
gr_vtx.y = FLIP( (VB->Win[v0][1] ) );
gr_vtx1.x = (VB->Win[v1][0] );
gr_vtx1.y = FLIP( (VB->Win[v1][1] ) );
gr_vtx2.x = (VB->Win[v2][0] );
gr_vtx2.y = FLIP( (VB->Win[v2][1] ) );
if(gr_vtx.x <0 || gr_vtx.x > 639 )
return;
if(gr_vtx1.x <0 || gr_vtx1.x > 639 )
return;
if(gr_vtx2.x <0 || gr_vtx2.x > 639 )
return;
if(gr_vtx.y <0 || gr_vtx.y > 479 )
return;
if(gr_vtx1.y <0 || gr_vtx1.y > 479 )
return;
if(gr_vtx2.y <0 || gr_vtx2.y > 479 )
return;
grDrawTriangle( &gr_vtx,&gr_vtx1,&gr_vtx2);
}
void fast_plot(GLcontext *ctx,GLuint first,GLuint last )
{
struct vertex_buffer *VB = ctx->VB;
register GLuint i;
if(VB->MonoColor) {
/* all same color */
gr_vtx.r = DOSMesa->red;
gr_vtx.g = DOSMesa->green;
gr_vtx.b = DOSMesa->blue;
for(i=first;i<last;i++) {
if(VB->ClipMask[i]==0) {
gr_vtx.x = VB->Win[i][0];
gr_vtx.y = FLIP(VB->Win[i][1]);
}
}
}
}
/* TODO: */
int vga_getpixel(x,y)
{
/* return (int)SV_getPixel(x,y); */
fprintf(stderr,"vga_getpixel: Not implemented yet\n");
return 1;
}
/* End of GLIDE section */
#endif // GLIDE
/**********************************************************************/
/***** Miscellaneous functions *****/
/**********************************************************************/
static void get_buffer_size( GLcontext *ctx, GLuint *width, GLuint *height )
{
*width = DOSMesa->width = vga_getxdim();
*height = DOSMesa->height = vga_getydim();
}
/* Set current color index */
static void set_index( GLcontext *ctx, GLuint index )
{
DOSMesa->index = index;
/*vga_setcolor( index );*/
}
/* Set current drawing color */
static void set_color( GLcontext *ctx,
GLubyte red, GLubyte green,
GLubyte blue, GLubyte alpha )
{
DOSMesa->red = red;
DOSMesa->green = green;
DOSMesa->blue = blue;
vga_setrgbcolor( red, green, blue );
}
static void clear_index( GLcontext *ctx, GLuint index )
{
/* TODO: Implements glClearIndex() */
}
static void clear_color( GLcontext *ctx,
GLubyte red, GLubyte green,
GLubyte blue, GLubyte alpha )
{
/* TODO: Implements glClearColor() */
}
static void clear( GLcontext *ctx,
GLboolean all,
GLint x, GLint y, GLint width, GLint height )
{
vga_clear();
}
static GLboolean set_buffer( GLcontext *ctx,
GLenum mode )
{
/* TODO: implement double buffering and use this function to select */
/* between front and back buffers. */
if (buffer == GL_FRONT_LEFT)
return GL_TRUE;
else if (buffer == GL_BACK_LEFT)
return GL_TRUE;
else
return GL_FALSE;
}
/**********************************************************************/
/***** Write spans of pixels *****/
/**********************************************************************/
static void write_index_span( GLcontext *ctx,
GLuint n, GLint x, GLint y,
const GLuint index[],
const GLubyte mask[] )
{
int i;
y = FLIP(y);
#ifdef UNIVBE
SV_beginPixel();
#endif
for (i=0;i<n;i++,x++) {
if (mask[i]) {
#ifdef UNIVBE
SV_putPixelFast(x,y,current_color);
#else
vga_setcolor( index[i] );
vga_drawpixel( x, y );
#endif
}
}
#ifdef UNIVBE
SV_endPixel();
#endif
}
static void write_monoindex_span( GLcontext *ctx,
GLuint n, GLint x, GLint y,
const GLubyte mask[] )
{
int i;
y = FLIP(y);
/* use current color index */
vga_setcolor( DOSMesa->index );
#ifdef UNIVBE
SV_beginPixel();
#endif
for (i=0;i<n;i++,x++) {
if (mask[i]) {
#ifdef UNIVBE
SV_putPixelFast(x,y,current_color);
#else
vga_drawpixel( x, y );
#endif
}
}
#ifdef UNIVBE
SV_endPixel();
#endif
}
static void write_color_span( GLcontext *ctx,
GLuint n, GLint x, GLint y,
const GLubyte red[], const GLubyte green[],
const GLubyte blue[], const GLubyte alpha[],
const GLubyte mask[] )
{
int i;
y=FLIP(y);
#ifdef UNIVBE
SV_beginPixel();
#endif
if (mask) {
/* draw some pixels */
for (i=0; i<n; i++, x++) {
if (mask[i]) {
#ifdef UNIVBE
SV_putPixelFast(x,y,SV_rgbColor(red[i], green[i], blue[i]) );
#else
vga_setrgbcolor( red[i], green[i], blue[i] );
vga_drawpixel( x, y );
#endif
}
}
}
else {
/* draw all pixels */
for (i=0; i<n; i++, x++) {
#ifdef UNIVBE
SV_putPixelFast(x,y,SV_rgbColor(red[i], green[i], blue[i]) );
#else
vga_setrgbcolor( red[i], green[i], blue[i] );
vga_drawpixel( x, y );
#endif
}
}
#ifdef UNIVBE
SV_endPixel();
#endif
}
static void write_monocolor_span( GLcontext *ctx,
GLuint n, GLint x, GLint y,
const GLubyte mask[])
{
int i;
y=FLIP(y);
#ifdef UNIVBE
SV_beginPixel();
#endif
/* use current rgb color */
vga_setrgbcolor( DOSMesa->red, DOSMesa->green, DOSMesa->blue );
for (i=0; i<n; i++, x++) {
if (mask[i]) {
#ifdef UNIVBE
SV_putPixelFast(x,y,current_color);
#else
vga_drawpixel( x, y );
#endif
}
}
#ifdef UNIVBE
SV_endPixel();
#endif
}
/**********************************************************************/
/***** Read spans of pixels *****/
/**********************************************************************/
static void read_index_span( GLcontext *ctx,
GLuint n, GLint x, GLint y, GLuint index[])
{
int i;
y = FLIP(y);
for (i=0; i<n; i++,x++) {
index[i] = vga_getpixel( x, y );
}
}
static void read_color_span( GLcontext *ctx,
GLuint n, GLint x, GLint y,
GLubyte red[], GLubyte green[],
GLubyte blue[], GLubyte alpha[] )
{
int i;
for (i=0; i<n; i++, x++) {
/* TODO */
}
}
/**********************************************************************/
/***** Write arrays of pixels *****/
/**********************************************************************/
static void write_index_pixels( GLcontext *ctx,
GLuint n, const GLint x[], const GLint y[],
const GLuint index[], const GLubyte mask[] )
{
int i;
#ifdef UNIVBE
SV_beginPixel();
#endif
for (i=0; i<n; i++) {
if (mask[i]) {
#ifdef UNIVBE
SV_putPixelFast(x[i], FLIP(y[i]), index[i] );
#else
vga_setcolor( index[i] );
vga_drawpixel( x[i], FLIP(y[i]) );
#endif
}
}
#ifdef UNIVBE
SV_endPixel();
#endif
}
static void write_monoindex_pixels( GLcontext *ctx,
GLuint n,
const GLint x[], const GLint y[],
const GLubyte mask[] )
{
int i;
/* use current color index */
vga_setcolor( DOSMesa->index );
#ifdef UNIVBE
SV_beginPixel();
#endif
for (i=0; i<n; i++) {
if (mask[i]) {
#ifdef UNIVBE
SV_putPixelFast(x[i], FLIP(y[i]), DOSMesa->index);
#else
vga_drawpixel( x[i], FLIP(y[i]) );
#endif
}
}
#ifdef UNIVBE
SV_endPixel();
#endif
}
static void write_color_pixels( GLcontext *ctx,
GLuint n, const GLint x[], const GLint y[],
const GLubyte r[], const GLubyte g[],
const GLubyte b[], const GLubyte a[],
const GLubyte mask[] )
{
int i;
#ifdef UNIVBE
SV_beginPixel();
#endif
for (i=0; i<n; i++) {
if (mask[i]) {
#ifdef UNIVBE
SV_putPixelFast(x[i], FLIP(y[i]), SV_rgbColor(r[i], g[i], b[i]) );
#else
vga_setrgbcolor( r[i], g[i], b[i] );
vga_drawpixel( x[i], FLIP(y[i]) );
#endif
}
}
#ifdef UNIVBE
SV_endPixel();
#endif
}
static void write_monocolor_pixels( GLcontext *ctx,
GLuint n,
const GLint x[], const GLint y[],
const GLubyte mask[] )
{
int i;
/* use current rgb color */
vga_setrgbcolor( DOSMesa->red, DOSMesa->green, DOSMesa->blue );
#ifdef UNIVBE
SV_beginPixel();
#endif
for (i=0; i<n; i++) {
if (mask[i]) {
#ifdef UNIVBE
SV_putPixelFast(x[i], FLIP(y[i]), current_color );
#else
vga_drawpixel( x[i], FLIP(y[i]) );
#endif
}
}
#ifdef UNIVBE
SV_endPixel();
#endif
}
/**********************************************************************/
/***** Read arrays of pixels *****/
/**********************************************************************/
/* Read an array of color index pixels. */
static void read_index_pixels( GLcontext *ctx,
GLuint n, const GLint x[], const GLint y[],
GLuint index[], const GLubyte mask[] )
{
int i;
for (i=0; i<n; i++) {
index[i] = vga_getpixel( x[i], FLIP(y[i]) );
}
}
static void read_color_pixels( GLcontext *ctx,
GLuint n, const GLint x[], const GLint y[],
GLubyte red[], GLubyte green[],
GLubyte blue[], GLubyte alpha[],
const GLubyte mask[] )
{
/* TODO */
}
static void DOSmesa_setup_DD_pointers( GLcontext *ctx )
{
/* Initialize all the pointers in the DD struct. Do this whenever */
/* a new context is made current or we change buffers via set_buffer! */
ctx->Driver.UpdateState = DOSmesa_setup_DD_pointers;
ctx->Driver.ClearIndex = clear_index;
ctx->Driver.ClearColor = clear_color;
ctx->Driver.Clear = clear;
ctx->Driver.Index = set_index;
ctx->Driver.Color = set_color;
ctx->Driver.SetBuffer = set_buffer;
ctx->Driver.GetBufferSize = get_buffer_size;
ctx->Driver.PointsFunc = choose_points_function();
ctx->Driver.LineFunc = choose_line_function();
ctx->Driver.TriangleFunc = choose_triangle_function();
/* Pixel/span writing functions: */
/* TODO: use different funcs for 8, 16, 32-bit depths */
ctx->Driver.WriteColorSpan = write_color_span;
ctx->Driver.WriteMonocolorSpan = write_monocolor_span;
ctx->Driver.WriteColorPixels = write_color_pixels;
ctx->Driver.WriteMonocolorPixels = write_monocolor_pixels;
ctx->Driver.WriteIndexSpan = write_index_span;
ctx->Driver.WriteMonoindexSpan = write_monoindex_span;
ctx->Driver.WriteIndexPixels = write_index_pixels;
ctx->Driver.WriteMonoindexPixels = write_monoindex_pixels;
/* Pixel/span reading functions: */
/* TODO: use different funcs for 8, 16, 32-bit depths */
ctx->Driver.ReadIndexSpan = read_index_span;
ctx->Driver.ReadColorSpan = read_color_span;
ctx->Driver.ReadIndexPixels = read_index_pixels;
ctx->Driver.ReadColorPixels = read_color_pixels;
}
/*
* Create a new VGA/Mesa context and return a handle to it.
*/
DOSMesaContext DOSMesaCreateContext( void )
{
DOSMesaContext ctx;
GLboolean rgb_flag;
GLfloat redscale, greenscale, bluescale, alphascale;
GLboolean db_flag = GL_FALSE;
GLboolean alpha_flag = GL_FALSE;
int colors;
GLint index_bits;
GLint redbits, greenbits, bluebits, alphabits;
#if !defined(UNIVBE) && !defined(GLIDE) && !defined(MGL)
video_buffer = (unsigned char *) malloc( vga_getxdim() * vga_getydim() );
memset(video_buffer,0, vga_getxdim() * vga_getydim() );
memset(rgbtable,0,sizeof( rgbtable ) );
#endif
#if defined( DJGPP ) && !defined(UNIVBE) && !defined(GLIDE)
dos_seg = _go32_conventional_mem_selector();
#endif
/* determine if we're in RGB or color index mode */
colors = vga_getcolors();
if (colors==32768) {
rgb_flag = GL_TRUE;
redscale = greenscale = bluescale = alphascale = 255.0;
redbits = greenbits = bluebits = 8;
alphabits = 0;
index_bits = 0;
}
else if (colors==256) {
rgb_flag = GL_FALSE;
redscale = greenscale = bluescale = alphascale = 0.0;
redbits = greenbits = bluebits = alphabits = 0;
index_bits = 8;
}
else {
restore_video_mode();
fprintf(stderr,"[%d] >16 bit color not implemented yet!\n",colors);
return NULL;
}
ctx = (DOSMesaContext) calloc( 1, sizeof(struct DOSmesa_context) );
if (!ctx) {
return NULL;
}
ctx->gl_vis = gl_create_visual( rgb_flag,
alpha_flag,
db_flag,
16, /* depth_size */
8, /* stencil_size */
16, /* accum_size */
index_bits,
redscale,
greenscale,
bluescale,
alphascale,
redbits, greenbits,
bluebits, alphabits);
ctx->gl_ctx = gl_create_context( ctx->gl_vis,
NULL, /* share list context */
(void *) ctx
);
ctx->gl_buffer = gl_create_framebuffer( ctx->gl_vis );
ctx->index = 1;
ctx->red = ctx->green = ctx->blue = 255;
ctx->width = ctx->height = 0; /* temporary until first "make-current" */
return ctx;
}
/*
* Destroy the given VGA/Mesa context.
*/
void DOSMesaDestroyContext( DOSMesaContext ctx )
{
if (ctx) {
gl_destroy_visual( ctx->gl_vis );
gl_destroy_context( ctx->gl_ctx );
gl_destroy_framebuffer( ctx->gl_buffer );
free( ctx );
if (ctx==DOSMesa) {
DOSMesa = NULL;
}
}
}
/*
* Make the specified VGA/Mesa context the current one.
*/
void DOSMesaMakeCurrent( DOSMesaContext ctx )
{
DOSMesa = ctx;
gl_make_current( ctx->gl_ctx, ctx->gl_buffer );
DOSmesa_setup_DD_pointers( ctx->gl_ctx );
if (ctx->width==0 || ctx->height==0) {
/* setup initial viewport */
ctx->width = vga_getxdim();
ctx->height = vga_getydim();
gl_Viewport( ctx->gl_ctx, 0, 0, ctx->width, ctx->height );
}
}
/*
* Return a handle to the current VGA/Mesa context.
*/
DOSMesaContext DOSMesaGetCurrentContext( void )
{
return DOSMesa;
}
/*
* Swap front/back buffers for current context if double buffered.
*/
void DOSMesaSwapBuffers( void )
{
#if !defined(UNIVBE)
/* Assume double buffering is available if in UNIVBE,
if it isn`t its taken care of anyway */
// if (DOSMesa->gl_vis->DBflag)
#endif
{
vga_flip();
}
}
#else
/*
* Need this to provide at least one external definition when DOS is
* not defined on the compiler command line.
*/
int gl_DOS_dummy_function(void)
{
return 0;
}
#endif /*DOS*/