--- Makefile.orig	2007-07-29 18:23:24.000000000 -0400
+++ Makefile	2007-07-29 17:57:30.000000000 -0400
@@ -17,6 +17,10 @@
 EXE  = nst
 LIBS = -lm -lz -lasound  `sdl-config --libs` `pkg-config --libs gtk+-2.0`
 
+# OpenGL Support
+CFLAGS += -DINCLUDE_OPENGL
+LIBS   += -lGL -lGLU
+
 # Linux objs
 OBJS = objs/linux/main.o objs/linux/oss.o objs/linux/interface.o objs/linux/support.o objs/linux/settings.o 
 OBJS += objs/linux/auxio.o objs/linux/input.o
--- source/linux/main.cpp.orig	2007-07-29 18:12:26.000000000 -0400
+++ source/linux/main.cpp	2007-07-29 18:20:03.000000000 -0400
@@ -29,6 +29,7 @@
 
 #define NST_VERSION "1.3.7"
 
+
 #define DRAG_TAR_NAME_0		"text/uri-list"
 #define DRAG_TAR_INFO_0		0
 
@@ -40,6 +41,11 @@
 #include "callbacks.h"
 }
 
+#ifdef INCLUDE_OPENGL
+	//#include "sdl-opengl.h"
+	#include "GL/glu.h"
+#endif
+
 // base class, all interfaces derives from this
 Nes::Api::Emulator emulator;
 
@@ -80,6 +86,142 @@
 
 static LinuxNstSettings *Settings;
 
+#ifdef INCLUDE_OPENGL
+static bool         using_opengl  = false;
+static bool         opengl_2xscale = false;
+static bool         linear_filter  = false;
+static GLuint       screenTexID  = 0;
+static SDL_Surface* openglBlit   = 0;
+static SDL_Surface* openglScreen = 0;
+static SDL_Rect     area;
+static int          gl_w;
+static int          gl_h;
+static int          gl_half_width;
+static int          gl_half_height;
+static int          draw_top;
+static int          draw_bottom;
+static int          draw_left;
+static int          draw_right;
+
+static int powerOfTwo( const int value )
+{
+	int result = 1;
+	while ( result < value )
+		result <<= 1;
+	return result;	
+}
+
+// surface is the screen
+static void opengl_init_structures()
+{
+	gl_half_width  = screen->w / 2;
+	gl_half_height = screen->h / 2;
+	openglScreen = screen;
+	screen = SDL_CreateRGBSurface( SDL_SWSURFACE, screen->w,
+ 										screen->h, 16 /* bits */,
+		   								0x001f, // little endian only
+			 							0x03e0, // little endian only
+		   								0x7c00, // little endian only
+			 							0 );
+
+	glEnable( GL_TEXTURE_2D );
+
+	gl_w = powerOfTwo( screen->w );
+	gl_h = powerOfTwo( screen->h );
+
+	draw_top    = -gl_half_height - (gl_h-screen->h); // 1.0 (inversion)
+	draw_bottom =  gl_half_height; // no adjustment here, causes scaling internally and hides the garbage
+    draw_left   = -gl_half_width  - (gl_w-screen->w); // 0.0
+    draw_right  =  gl_half_width  - (gl_w-screen->w); // 1.0
+
+	if ( opengl_2xscale )
+	{
+		// re-open the opengl screen
+		const int flags = openglScreen->flags;
+		const int bpp = openglScreen->format->BitsPerPixel;
+		
+		SDL_FreeSurface( openglScreen );
+		openglScreen = SDL_SetVideoMode(4*gl_half_width,
+										4*gl_half_height,
+										 bpp, flags);
+	}
+
+	openglBlit =  SDL_CreateRGBSurface( SDL_SWSURFACE, screen->w,
+ 										screen->h, 32 /* bits */,
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN // OpenGL RGBA masks 
+                               			0x000000ff,
+                               			0x0000ff00,
+                               			0x00ff0000,
+                               			0x00000000
+#else
+                               			0xFF000000,
+                               			0x00FF0000, 
+                               			0x0000FF00, 
+                               			0x00000000
+#endif
+							);
+
+	glGenTextures( 1, &screenTexID ) ;
+	glBindTexture( GL_TEXTURE_2D, screenTexID ) ;
+	// GL_LINEAR looks like ass
+
+	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (linear_filter?GL_LINEAR:GL_NEAREST) ) ;
+	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ) ;
+	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ) ;
+	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ) ;
+
+	area.x = area.y = 0;
+	area.w = screen->w;
+	area.h = screen->h;
+
+	glViewport( 0,0, openglScreen->w, openglScreen->h );
+	glDisable( GL_DEPTH_TEST );
+	glDisable( GL_ALPHA_TEST );
+	glDisable( GL_BLEND );
+	glDisable( GL_LIGHTING );
+	glDisable( GL_TEXTURE_3D_EXT );
+	glMatrixMode( GL_PROJECTION );
+	glLoadIdentity();
+
+	glOrtho(   /* left */ -gl_half_width, /* right */ gl_half_width,
+			 /* bottom */ -gl_half_height,   /* top */ gl_half_height,
+			/* near */ -1, /* far */ 1 ) ;
+	
+	//glMatrixMode(GL_MODELVIEW);
+}
+
+
+static void opengl_cleanup()
+{
+	SDL_FreeSurface( openglBlit );
+	SDL_FreeSurface( openglScreen );
+	glDeleteTextures( 1, &screenTexID );
+}
+
+static void opengl_blit()
+{
+	SDL_BlitSurface( screen, &area, openglBlit, &area ) ;
+
+	glTexImage2D( GL_TEXTURE_2D,
+    	          0,
+			      GL_RGBA,
+    	          gl_w, gl_h,
+    	          0,
+    	          GL_RGBA,
+    	          GL_UNSIGNED_BYTE,
+    	          openglBlit->pixels ) ;
+	//glLoadIdentity();
+	glBegin( GL_QUADS ) ;
+		glTexCoord2f( 1.0f, 0.0f ) ; glVertex2i(  draw_right,  draw_bottom ) ;
+		glTexCoord2f( 1.0f, 1.0f ) ; glVertex2i(  draw_right,  draw_top ) ;
+		glTexCoord2f( 0.0f, 1.0f ) ; glVertex2i(  draw_left,   draw_top ) ;
+		glTexCoord2f( 0.0f, 0.0f ) ; glVertex2i(  draw_left,   draw_bottom ) ;
+	glEnd();
+	//glFlush();
+	SDL_GL_SwapBuffers();	
+}
+#endif
+
 static void load_file_by_uri(char *filename)
 {
 	char *fsub;
@@ -192,7 +334,19 @@
 {
 	if(SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen);
 
-	SDL_Flip(screen);
+#ifdef INCLUDE_OPENGL
+	if ( using_opengl )
+	{
+		// TODO: add opengl calls to render screen to texture and flip
+		opengl_blit();
+		//SDL_Flip(screen);
+	}
+	else
+#endif
+	{
+		SDL_Flip(screen);
+	}
+
 }
 
 // called right before Nestopia is about to write pixels
@@ -294,6 +448,9 @@
 		if (!nsf_mode)
 		{
 			SDL_FreeSurface(screen);
+			#ifdef INCLUDE_OPENGL
+				opengl_cleanup();
+			#endif
 		}
 
 		// get machine interface...
@@ -1046,7 +1203,7 @@
 {
 	// renderstate structure
 	Nes::Api::Video::RenderState renderState;
-	Nes::Api::Video::RenderState::Filter filters[7] = 
+	Nes::Api::Video::RenderState::Filter filters[] = 
 	{ 
 		Nes::Api::Video::RenderState::FILTER_NONE, 
 		Nes::Api::Video::RenderState::FILTER_NTSC, 
@@ -1054,9 +1211,15 @@
 		Nes::Api::Video::RenderState::FILTER_SCALE3X, 
 		Nes::Api::Video::RenderState::FILTER_HQ2X, 
 		Nes::Api::Video::RenderState::FILTER_HQ3X, 
-		Nes::Api::Video::RenderState::FILTER_HQ4X 
+		Nes::Api::Video::RenderState::FILTER_HQ4X ,
+#ifdef INCLUDE_OPENGL
+		// no fltering
+		Nes::Api::Video::RenderState::FILTER_NONE, 
+		Nes::Api::Video::RenderState::FILTER_NONE, 		
+		Nes::Api::Video::RenderState::FILTER_NONE, 		
+#endif
 	};
-	int Widths[7] =
+	int Widths[] =
 	{
 		Nes::Api::Video::Output::WIDTH,
 		Nes::Api::Video::Output::NTSC_WIDTH,
@@ -1065,8 +1228,14 @@
 		Nes::Api::Video::Output::WIDTH*2,
 		Nes::Api::Video::Output::WIDTH*3,
 		Nes::Api::Video::Output::WIDTH*4,
+#ifdef INCLUDE_OPENGL
+		// STD width, OpenGL does the scaling
+		Nes::Api::Video::Output::WIDTH,
+		Nes::Api::Video::Output::WIDTH,
+		Nes::Api::Video::Output::WIDTH,
+#endif
 	};
-	int Heights[7] =
+	int Heights[] =
 	{
 		Nes::Api::Video::Output::HEIGHT,
 		Nes::Api::Video::Output::NTSC_HEIGHT,
@@ -1075,6 +1244,12 @@
 		Nes::Api::Video::Output::HEIGHT*2,
 		Nes::Api::Video::Output::HEIGHT*3,
 		Nes::Api::Video::Output::HEIGHT*4,
+#ifdef INCLUDE_OPENGL
+		// STD height, OpenGL does the scaling
+		Nes::Api::Video::Output::HEIGHT,
+		Nes::Api::Video::Output::HEIGHT,
+		Nes::Api::Video::Output::HEIGHT,
+#endif
 	};
 	Nes::Api::Machine machine( emulator );
 	Nes::Api::Cartridge::Database database( emulator );
@@ -1102,7 +1277,7 @@
 	{
 		if (database.IsLoaded())
 		{
-				if (database.GetRegion(dbentry) == Nes::Api::Cartridge::REGION_PAL)
+			if (database.GetRegion(dbentry) == Nes::Api::Cartridge::REGION_PAL)
 			{
 				machine.SetMode(Nes::Api::Machine::PAL);
 				framerate = 50;
@@ -1141,15 +1316,33 @@
 	cur_width = Widths[Settings->GetScale()];
 	cur_height = Heights[Settings->GetScale()];
 
+	int eFlags = SDL_HWSURFACE;
+	#ifdef INCLUDE_OPENGL
+        using_opengl = ( Settings->GetScale() >= 7);
+		opengl_2xscale = (Settings->GetScale() >= 8);
+		linear_filter = (Settings->GetScale() == 9);
+		if (using_opengl)
+		{
+			SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
+			eFlags = SDL_OPENGL;
+		}
+	#endif
+
 	if (Settings->GetFullscreen())
 	{
-		screen = SDL_SetVideoMode(cur_width, cur_height, 16, SDL_ANYFORMAT | SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_FULLSCREEN);
+		screen = SDL_SetVideoMode(cur_width, cur_height, 16, SDL_ANYFORMAT | SDL_DOUBLEBUF | SDL_FULLSCREEN | eFlags);
 	}
 	else
 	{
-		screen = SDL_SetVideoMode(cur_width, cur_height, 16, SDL_ANYFORMAT | SDL_DOUBLEBUF | SDL_HWSURFACE);
+		// took out SDL_DOUBLEBUF
+		screen = SDL_SetVideoMode(cur_width, cur_height, 16, SDL_ANYFORMAT | SDL_DOUBLEBUF | eFlags);
 	}
 
+	#ifdef INCLUDE_OPENGL
+		if (using_opengl)
+			opengl_init_structures();
+	#endif
+
 	if (!screen)
 	{
 		std::cout << "SDL couldn't set video mode\n";
@@ -1284,7 +1477,6 @@
 	strcat(savename, ".sav");
 }
 
-
 // load a game or NES music file
 void LoadGame(const char* filename)
 {
--- source/linux/interface.c.orig	2007-07-29 18:12:40.000000000 -0400
+++ source/linux/interface.c	2007-07-29 18:17:45.000000000 -0400
@@ -231,6 +231,11 @@
   gtk_combo_box_append_text (GTK_COMBO_BOX (scalecombo), _("Scale HQ2x"));
   gtk_combo_box_append_text (GTK_COMBO_BOX (scalecombo), _("Scale HQ3x"));
   gtk_combo_box_append_text (GTK_COMBO_BOX (scalecombo), _("Scale HQ4x"));
+#ifdef INCLUDE_OPENGL
+  gtk_combo_box_append_text (GTK_COMBO_BOX (scalecombo), _("OpenGL None"));
+  gtk_combo_box_append_text (GTK_COMBO_BOX (scalecombo), _("OpenGL 2X Nearest")); 
+  gtk_combo_box_append_text (GTK_COMBO_BOX (scalecombo), _("OpenGL 2X Linear")); 
+#endif
 
   videotab = gtk_label_new (_("Video"));
   gtk_widget_set_name (videotab, "videotab");

