/****************************************************************************
*                linux.c
*
*  This module implements LINUX/SVGALIB specific routines.
*
*  from Persistence of Vision Raytracer
*  Copyright 1993 Persistence of Vision Team
*---------------------------------------------------------------------------
*  NOTICE: This source code file is provided so that users may experiment
*  with enhancements to POV-Ray and to port the software to platforms other 
*  than those supported by the POV-Ray Team.  There are strict rules under
*  which you are permitted to use this file.  The rules are in the file
*  named POVLEGAL.DOC which should be distributed with this file. If 
*  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
*  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
*  Forum.  The latest version of POV-Ray may be found there as well.
*
* This program is based on the popular DKB raytracer version 2.12.
* DKBTrace was originally written by David K. Buck.
* DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
*
* This source code was modified by Jeff Epler to display on Linux using
* the 'svgalib' package by Harm Hannemayer.  Full details on svgalib
* can be found in the package: sunsite.unc.edu:/pub/Linux/lib/svgalib098.tgz
* or a newer version.
*
*****************************************************************************/


#include <math.h>
#include <vga.h>
#include <vgagl.h>

#include "config.h"
#include "frame.h"

extern FRAME Frame;
extern char DisplayFormat,PaletteOption;

GraphicsContext physicalScreen, internalScreen;
vga_modeinfo *minfo;

void unix_init_POVRAY PARAMS ((void))
   {
   }

#ifdef UNDERFLOW
int matherr (x)
   struct exception *x;
   {
   switch(x->type) 
     {
     case DOMAIN:
     case OVERFLOW:
        x->retval = 1.0e17;
        break;

     case SING:
     case UNDERFLOW:
        x->retval = 0.0;
        break;

     default:
        break;
     }
   return(1);
   }
#endif

void display_finished ()
   {
   vga_setmode(TEXT);
   }

void display_init ()
   {
   int displaymode=vga_getdefaultmode();
   vga_runinbackground(1);
   if (displaymode==-1) displaymode=G320x200x256;
   if (DisplayFormat!='0') 
	if (DisplayFormat<'A') displaymode=DisplayFormat-'0';
	else displaymode=DisplayFormat-'A'+10;
   vga_setmode(displaymode);
   minfo=vga_getmodeinfo(displaymode);
   gl_setrgbpalette();

   gl_setcontextvga(displaymode);
   gl_getcontext(&physicalScreen);

   gl_setcontextvgavirtual(displaymode);
   gl_getcontext(&internalScreen);
  
   gl_clearscreen(0);
   }

void display_close ()
   {
   vga_setmode(TEXT);
   }

void display_plot (x, y, Red, Green, Blue)
   int x, y;
   unsigned char Red, Green, Blue;
   {
   static unsigned dm[] = {
	0, 192, 48, 240, 12, 204, 60, 252,
	128, 64, 176, 112, 140, 76, 188, 124,
	32, 224, 16, 208, 44, 236, 28, 220,
	160, 96, 144, 80, 172, 108, 156, 92,
	8, 200, 56, 248, 4, 196, 52, 244,
	136, 72, 184, 120, 132, 68, 180, 116,
	40, 232, 24, 216, 36, 228, 20, 212,
	168, 104, 152, 88, 164, 100, 148, 84
    };
   int temp,r,g,b;
   static int couldwrite;

   if(PaletteOption!='U') 
        {
	int i=(x&7)+8*(y&7);
	switch (minfo->colors) 
	     {
	     case 256:
		r=Red+(dm[i]>>3);
		g=Green+(dm[i]>>3);
		b=Blue+(dm[i]>>2);
		break;
	    case 2<<15:
	    case 2<<16: /* Should use that one extra bit of resolution, but I don't know which one it is */
		r=Red+(dm[i]>>5);
		g=Green+(dm[i]>>5);
		b=Blue+(dm[i]>>5);
		break;
	    default:
		r=Red;
		g=Green;
		b=Blue;
		break;
	    }
	if (r>255) r=255;
	if (g>255) g=255;
	if (b>255) b=255;
        } else { 
	    r=Red;
	    g=Green;
	    b=Blue;
	}
   gl_setpixelrgb(x,y,r,g,b);
   if(temp=vga_oktowrite())
        {
	if (!couldwrite) gl_copyscreen(&physicalScreen);
	gl_setcontext(&physicalScreen);
	gl_setpixelrgb(x,y,r,g,b);
	gl_setcontext(&internalScreen);
        }
   couldwrite=temp;
   }
