diff -u ./ddraw_main.c ../ddraw/ddraw_main.c
--- ./ddraw_main.c	2005-12-04 20:13:14.000000000 -0500
+++ ../ddraw/ddraw_main.c	2005-11-21 17:00:45.000000000 -0500
@@ -689,7 +689,7 @@
 	/* create primary surface & backbuffers */
 	hr = create_primary(This, pDDSD, ppSurf, pUnkOuter);
 	
-	if(opengl_initialized && use_ddraw_over_d3d) {
+	if(use_ddraw_over_d3d) {
 	    IDirect3DDeviceImpl *dummy;
 	    d3ddevice_create(&dummy, This, *ppSurf, 1, D3D_BLIT);
 	}
diff -u ./gl_api.h ../ddraw/gl_api.h
--- ./gl_api.h	2005-12-04 19:57:54.000000000 -0500
+++ ../ddraw/gl_api.h	2005-12-04 20:43:44.000000000 -0500
@@ -107,6 +107,7 @@
 GL_API_FUNCTION(glTexEnvf)
 GL_API_FUNCTION(glTexEnvfv)
 GL_API_FUNCTION(glTexEnvi)
+GL_API_FUNCTION(glTexImage1D)
 GL_API_FUNCTION(glTexImage2D)
 GL_API_FUNCTION(glTexParameteri)
 GL_API_FUNCTION(glTexParameterfv)
diff -u ./gl_private.h ../ddraw/gl_private.h
--- ./gl_private.h	2005-12-04 19:56:27.000000000 -0500
+++ ../ddraw/gl_private.h	2005-11-22 12:47:25.000000000 -0500
@@ -67,6 +67,9 @@
 #define GL_TEXTURE7_WINE                        0x84C7
 #define GL_MAX_TEXTURE_UNITS_WINE               0x84E2
 
+#define GL_FRAGMENT_PROGRAM_ARB_WINE            0x8804
+#define GL_PROGRAM_FORMAT_ASCII_ARB_WINE        0x8875
+
 #ifndef GLPRIVATE_NO_REDEFINE
 
 #define glAlphaFunc pglAlphaFunc
@@ -150,6 +153,7 @@
 #define glTexEnvf pglTexEnvf
 #define glTexEnvfv pglTexEnvfv
 #define glTexEnvi pglTexEnvi
+#define glTexImage1D pglTexImage1D
 #define glTexImage2D pglTexImage2D
 #define glTexParameteri pglTexParameteri
 #define glTexParameterfv pglTexParameterfv
diff -u ./opengl_private.h ../ddraw/opengl_private.h
--- ./opengl_private.h	2005-12-04 19:57:26.000000000 -0500
+++ ../ddraw/opengl_private.h	2005-11-20 10:28:31.000000000 -0500
@@ -180,6 +180,14 @@
                                  GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
     void (*glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset,
                                     GLsizei width, GLsizei height, GLsizei imageSize, const GLvoid *data);
+    /* Paletted texture support */
+    BOOLEAN paletted_texture;
+    void (*glColorTable)(GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *);
+    /* Fragment program support */ 
+    BOOLEAN fragment_program;
+    void (*glBindProgramARB)(GLenum, GLuint);
+    void (*glGenProgramsARB)(GLsizei, GLuint *);
+    void (*glProgramStringARB)(GLenum, GLenum, GLsizei, const GLvoid *);
 } GL_EXTENSIONS_LIST; 
 extern GL_EXTENSIONS_LIST GL_extensions;
 
diff -u ./opengl_utils.c ../ddraw/opengl_utils.c
--- ./opengl_utils.c	2005-12-04 19:57:09.000000000 -0500
+++ ../ddraw/opengl_utils.c	2005-12-04 19:46:54.000000000 -0500
@@ -640,6 +640,15 @@
 static DWORD current_tex_height;
 static GLuint current_alignement_constraints;
 static int current_storage_width;
+static int use_fragment_program;
+
+static unsigned int shader_id;
+const char *fragment_palette_conversion =
+    "!!ARBfp1.0\n"
+    "TEMP index;\n"
+    "TEX index.x, fragment.texcoord[0], texture[0], 2D;\n" /* store the red-component of the current pixel */
+    "TEX result.color, index, texture[1], 1D;\n" /* use the red-component as a index in the palette to get the final color */
+    "END";
 
 HRESULT upload_surface_to_tex_memory_init(IDirectDrawSurfaceImpl *surf_ptr, GLuint level, GLenum *current_internal_format,
 					  BOOLEAN need_to_alloc, BOOLEAN need_alpha_ck, DWORD tex_width, DWORD tex_height, 
@@ -705,10 +714,117 @@
 	/* ****************
 	   Paletted Texture
 	   **************** */
-	current_format = GL_RGBA;
-	internal_format = GL_RGBA;
-	current_pixel_format = GL_UNSIGNED_BYTE;
-	convert_type = CONVERT_PALETTED;
+
+	/* First check if the hardware can do the conversion for us using the paletted texture extension.
+	In case we are in D3D_BLIT mode we can also use a fragment program. If neither of both is supported
+	we should do the conversion in software but that is SLOW. */
+	if(GL_extensions.paletted_texture)
+	{	   
+	    IDirectDrawPaletteImpl* pal = current_surface->palette;
+	    int i;
+	    BYTE table[256][4];
+
+	    if (pal == NULL) {
+		/* Upload a black texture. The real one will be uploaded on palette change */
+		WARN("Palettized texture Loading with a NULL palette !\n");
+		memset(table, 0, 256 * 4);
+	    } else {
+		for (i = 0; i < 256; i++) {
+		    table[i][0] = pal->palents[i].peRed;
+		    table[i][1] = pal->palents[i].peGreen;
+		    table[i][2] = pal->palents[i].peBlue;
+		    if ((surf_ptr->surface_desc.dwFlags & DDSD_CKSRCBLT) && 
+			(i >= surf_ptr->surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue) &&
+			(i <= surf_ptr->surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue))
+			/* We should maybe here put a more 'neutral' color than the standard bright purple
+			   one often used by application to prevent the nice purple borders when bi-linear
+			   filtering is on */
+			table[i][3] = 0x00;
+		    else
+			table[i][3] = 0xFF;
+		}
+	    }
+
+	    current_format = GL_COLOR_INDEX;
+	    internal_format = GL_COLOR_INDEX8_EXT;
+	    current_pixel_format = GL_UNSIGNED_BYTE;
+	    convert_type = NO_CONVERSION;
+
+	    GL_extensions.glColorTable(GL_TEXTURE_2D,GL_RGBA,256,GL_RGBA,GL_UNSIGNED_BYTE, table);
+	}  else if(GL_extensions.fragment_program && (d3d_mode == D3D_BLIT)) {	   
+	    IDirectDrawPaletteImpl* pal = current_surface->palette;
+	    int i;
+	    BYTE table[512][4];
+	    static unsigned int have_fragment_program = 0;
+
+	    if (pal == NULL) {
+		/* Upload a black texture. The real one will be uploaded on palette change */
+		WARN("Palettized texture Loading with a NULL palette !\n");
+		memset(table, 0, 512 * 4);
+	    } else {
+		for (i = 0; i < 512; i+=2) {
+		    table[i][0] = pal->palents[i/2].peRed;
+		    table[i][1] = pal->palents[i/2].peGreen;
+		    table[i][2] = pal->palents[i/2].peBlue;
+		    table[i][3] = 0xFF;
+
+		    table[i+1][0] = table[i][0];
+		    table[i+1][1] = table[i][1];
+		    table[i+1][2] = table[i][2];
+		    table[i+1][3] = table[i][3];
+		}
+	    }
+		
+	    /* Create the fragment program if we don't have it */
+	    if(!have_fragment_program)
+	    {
+	        glEnable(GL_FRAGMENT_PROGRAM_ARB_WINE);
+	        GL_extensions.glGenProgramsARB(1, &shader_id);
+	        GL_extensions.glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB_WINE, shader_id);
+	        GL_extensions.glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB_WINE, GL_PROGRAM_FORMAT_ASCII_ARB_WINE, strlen(fragment_palette_conversion), (const GLbyte *)fragment_palette_conversion);
+	        glDisable(GL_FRAGMENT_PROGRAM_ARB_WINE);
+	        have_fragment_program=1;
+	    }
+		
+	    /* We emulate paletted texture support using a simple fragment program.
+	    The palette consisting of 256 colors itself is uploaded using a 512x1 texture with two
+	    entries for each color. The reason for this is that in the shader texture coordinates
+	    and indexing in textures works using floats [0.0, 1.0]. Further the texture magnification/minifying
+	    function is set to GL_NEAREST so that we get discrete color levels. The entry closest to
+	    a specific index is chosen. Due to precision problems in some cases the wrong color is sampled.
+	    Uploading each color twice fixed this problem for both Mesa 6.4 and a Nvidia Geforce6 card. Note that
+	    this precision problem didn't appear on a GeforceFX card using the same drivers.
+	    
+	    Further the (8-bit) 2D texture is uploaded with current_format set to GL_RED, so that all
+	    pixel data is stored in the red channel. For the color conversion the red part of the pixel
+	    is then used as an index in the palette to find the 'real' color. */
+
+	    glEnable(GL_FRAGMENT_PROGRAM_ARB_WINE);
+	    GL_extensions.glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB_WINE, shader_id);
+	    use_fragment_program = 1;
+		
+	    /* The palette will be stored in texture unit 1. We know for
+	    sure that there are atleast two units as this is required for
+	    cards in order to support the fragment program extension. */		
+	    GL_extensions.glActiveTexture(GL_TEXTURE1_WINE);
+    	    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    	    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); /* Make sure we have discrete color levels. */
+    	    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    	    glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, 512, 1, GL_RGBA, GL_UNSIGNED_BYTE, table);
+
+	    /* Switch back to unit 0 in which the 2D texture will be stored. */
+	    GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
+
+	    current_format = GL_RED; /* Put all the color information in the red channel. */
+	    internal_format = GL_RGBA;
+	    current_pixel_format = GL_UNSIGNED_BYTE;
+	    convert_type = NO_CONVERSION;
+	} else {
+	    current_format = GL_RGBA;
+	    internal_format = GL_RGBA;
+	    current_pixel_format = GL_UNSIGNED_BYTE;
+	    convert_type = CONVERT_PALETTED;
+	}
     } else if (src_pf->dwFlags & DDPF_RGB) {
 	/* ************
 	   RGB Textures
@@ -1323,5 +1439,12 @@
 {
     current_surface = NULL;
 
+    /* Disable the fragment program after the 8-bit texture is uploaded. */
+    if(use_fragment_program)
+    {
+	glDisable(GL_FRAGMENT_PROGRAM_ARB_WINE);
+	use_fragment_program = 0;
+    }
+
     return DD_OK;
 }
