/*
**  wt -- a 3d game engine
**
**  Copyright (C) 1994 by Chris Laurel
**  email:  claurel@mr.net
**  snail mail:  Chris Laurel, 5700 W Lake St #208,  St. Louis Park, MN  55416
**
**  This program is free software; you can redistribute it and/or modify
**  it under the terms of the GNU General Public License as published by
**  the Free Software Foundation; either version 2 of the License, or
**  (at your option) any later version.
**
**  This program 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 General Public License for more details.
**
**  You should have received a copy of the GNU General Public License
**  along with this program; if not, write to the Free Software
**  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/*
 * Modified:
 * Handle virtual screen graphics with vgagl. This allows for
 * transparent page flipping in 256 color modes, including SVGA resolutions.
 * Also supports planar (mode X-like) 256 color modes, and even 16-color
 * modes.
 *
 * Triple-buffering is automatically used by vgagl if enough video memory
 * is available.
 */


#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <vga.h>
#include <vgagl.h>
#include <vgakeyboard.h>
#include "wt.h"
#include "error.h"
#include "wtmem.h"
#include "framebuf.h"
#include "graphics.h"
#include "dither.h"


static Palette_info load_palette(void);

static int graphics_initialized = 0;
static DevicePixel *display_fb;
static Pixel *render_fb;
static Boolean dither_mode, direct_mode;


GraphicsContext physicalscreen;


Graphics_info *init_graphics(int width, int height, Boolean blocky)
{
     static Graphics_info ginfo;
     int width, height;
     int vgamode;


     width = 320;
     height = 200;

     if (graphics_initialized == 1)
	  return &ginfo;

     ginfo.width = width;
     ginfo.height = height;

     vga_init();              /* This gives up root privileges. */
     vgamode = G320x200x256;
     vga_setmode(vgamode);
     gl_setcontextvga(vgamode);
     gl_getcontext(&physicalscreen);
     ginfo.palette = load_palette();
     /* Create the virtual screen framebuffer. */
     gl_setcontextvgavirtual(vgamode);

     if (sizeof(Pixel) != sizeof(DevicePixel))
	  dither_mode = True;
     if (dither_mode)
	  direct_mode = False;
     else
	  direct_mode = True;

     /* VBUF points to the virtual screen framebuffer. */
     display_fb = (DevicePixel *) VBUF;

     if (direct_mode)
	  render_fb = (Pixel *) display_fb;
     else
	  render_fb = wtmalloc(sizeof(Pixel) * height * width);

     if (dither_mode)
	  calc_dither(&ginfo);

     /* The following function returns 3 if triple-buffering is used,
     ** 2 for double-buffering, 0 otherwise.
     */
     gl_enablepageflipping(&physicalscreen);

     graphics_initialized = 1;

     return &ginfo;
}


static Palette_info load_palette(void)
{
     int color_levels = 6;
     int r, g, b;
     int index = 0;
     Palette_info pinfo;


     pinfo.rgb_cube_size = color_levels;
     pinfo.color_lookup = wtmalloc(sizeof(int) * color_levels *
				   color_levels * color_levels);

     for (r = 0; r < color_levels; r++)
     for (g = 0; g < color_levels; g++)
     for (b = 0; b < color_levels; b++) {
	  int red, green, blue;

	  red =   (short) (r * 63 / (color_levels - 1));
	  green = (short) (g * 63 / (color_levels - 1));
	  blue =  (short) (b * 63 / (color_levels - 1));

	  vga_setpalette(index, red, green, blue);

	  pinfo.color_lookup[index] = index;
	  index++;
     }
     
     return pinfo;
}


void end_graphics(void)
{
     if (graphics_initialized) {
	  keyboard_close();	/* This is required! */
	  vga_setmode(TEXT);
	  graphics_initialized = 0;
     }
}


void update_screen(Framebuffer *fb)
{
     /* Page flipping is done transparently. */
     if (dither_mode)
	  dither(render_fb, display_fb, fb->fb_width, fb->fb_height);
     gl_copyscreen(&physicalscreen);
}


Pixel *get_framebuffer_memory(int width, int height)
{
     return render_fb;
}
