]> icculus.org git repositories - taylor/freespace2.git/blob - src/graphics/gropengl.cpp
use d3d rect_internal
[taylor/freespace2.git] / src / graphics / gropengl.cpp
1 /*
2  * $Logfile: /Freespace2/code/Graphics/GrOpenGL.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * Code that uses the OpenGL graphics library
8  *
9  * $Log$
10  * Revision 1.33  2002/05/31 22:04:55  relnev
11  * use d3d rect_internal
12  *
13  * Revision 1.32  2002/05/31 06:28:23  relnev
14  * more stuff
15  *
16  * Revision 1.31  2002/05/31 06:04:39  relnev
17  * fog
18  *
19  * Revision 1.30  2002/05/31 03:56:11  theoddone33
20  * Change tmapper polygon winding and enable culling
21  *
22  * Revision 1.29  2002/05/31 03:34:02  theoddone33
23  * Fix Keyboard
24  * Add titlebar
25  *
26  * Revision 1.28  2002/05/31 00:06:59  relnev
27  * minor change
28  *
29  * Revision 1.27  2002/05/30 23:46:29  theoddone33
30  * some minor key changes (not necessarily fixes)
31  *
32  * Revision 1.26  2002/05/30 23:33:12  relnev
33  * implemented a few more functions.
34  *
35  * Revision 1.25  2002/05/30 23:01:16  relnev
36  * implement gr_opengl_set_state.
37  *
38  * Revision 1.24  2002/05/30 22:12:57  relnev
39  * finish default texture case
40  *
41  * Revision 1.23  2002/05/30 22:02:30  theoddone33
42  * More gl changes
43  *
44  * Revision 1.22  2002/05/30 21:44:48  relnev
45  * implemented some missing texture stuff.
46  *
47  * enable bitmap polys for opengl.
48  *
49  * work around greenness in bitmaps.
50  *
51  * Revision 1.21  2002/05/30 17:29:30  theoddone33
52  * Fix some more stubs, change at least one polygon winding since culling is now
53  * enabled.
54  *
55  * Revision 1.20  2002/05/30 16:50:24  theoddone33
56  * Keyboard partially fixed
57  *
58  * Revision 1.19  2002/05/30 08:13:14  relnev
59  * fonts are fixed
60  *
61  * Revision 1.18  2002/05/29 23:37:36  relnev
62  * fix bitmap bug
63  *
64  * Revision 1.17  2002/05/29 23:17:49  theoddone33
65  * Non working text code and fixed keys
66  *
67  * Revision 1.16  2002/05/29 19:45:13  theoddone33
68  * More changes on texture loading
69  *
70  * Revision 1.15  2002/05/29 19:06:48  theoddone33
71  * Enable string printing.  Enable texture mapping
72  *
73  * Revision 1.14  2002/05/29 08:54:40  relnev
74  * "fixed" bitmap drawing.
75  *
76  * copied more d3d code over.
77  *
78  * Revision 1.13  2002/05/29 06:25:13  theoddone33
79  * Keyboard input, mouse tracking now work
80  *
81  * Revision 1.12  2002/05/29 04:52:45  relnev
82  * bitmap
83  *
84  * Revision 1.11  2002/05/29 04:29:56  relnev
85  * removed some unncessary stubbing, implemented opengl rect
86  *
87  * Revision 1.10  2002/05/29 04:13:27  theoddone33
88  * enable opengl_line
89  *
90  * Revision 1.9  2002/05/29 03:35:51  relnev
91  * added rest of init
92  *
93  * Revision 1.8  2002/05/29 03:30:05  relnev
94  * update opengl stubs
95  *
96  * Revision 1.7  2002/05/29 02:52:32  theoddone33
97  * Enable OpenGL renderer
98  *
99  * Revision 1.6  2002/05/28 04:56:51  theoddone33
100  * runs a little bit now
101  *
102  * Revision 1.5  2002/05/28 04:07:28  theoddone33
103  * New graphics stubbing arrangement
104  *
105  * Revision 1.4  2002/05/27 23:39:34  relnev
106  * 0
107  *
108  * Revision 1.3  2002/05/27 22:35:01  theoddone33
109  * more symbols
110  *
111  * Revision 1.2  2002/05/27 22:32:02  theoddone33
112  * throw all d3d stuff at opengl
113  *
114  * Revision 1.1.1.1  2002/05/03 03:28:09  root
115  * Initial import.
116  *
117  * 
118  * 10    7/14/99 9:42a Dave
119  * Put in clear_color debug function. Put in base for 3dnow stuff / P3
120  * stuff
121  * 
122  * 9     7/09/99 9:51a Dave
123  * Added thick polyline code.
124  * 
125  * 8     6/29/99 10:35a Dave
126  * Interface polygon bitmaps! Whee!
127  * 
128  * 7     2/03/99 11:44a Dave
129  * Fixed d3d transparent textures.
130  * 
131  * 6     1/24/99 11:37p Dave
132  * First full rev of beam weapons. Very customizable. Removed some bogus
133  * Int3()'s in low level net code.
134  * 
135  * 5     12/18/98 1:13a Dave
136  * Rough 1024x768 support for Direct3D. Proper detection and usage through
137  * the launcher.
138  * 
139  * 4     12/06/98 2:36p Dave
140  * Drastically improved nebula fogging.
141  * 
142  * 3     11/11/98 5:37p Dave
143  * Checkin for multiplayer testing.
144  * 
145  * 2     10/07/98 10:53a Dave
146  * Initial checkin.
147  * 
148  * 1     10/07/98 10:49a Dave
149  * 
150  * 14    5/20/98 9:46p John
151  * added code so the places in code that change half the palette don't
152  * have to clear the screen.
153  * 
154  * 13    5/06/98 5:30p John
155  * Removed unused cfilearchiver.  Removed/replaced some unused/little used
156  * graphics functions, namely gradient_h and _v and pixel_sp.   Put in new
157  * DirectX header files and libs that fixed the Direct3D alpha blending
158  * problems.
159  * 
160  * 12    4/14/98 12:15p John
161  * Made 16-bpp movies work.
162  * 
163  * 11    3/12/98 5:36p John
164  * Took out any unused shaders.  Made shader code take rgbc instead of
165  * matrix and vector since noone used it like a matrix and it would have
166  * been impossible to do in hardware.   Made Glide implement a basic
167  * shader for online help.  
168  * 
169  * 10    3/10/98 4:18p John
170  * Cleaned up graphics lib.  Took out most unused gr functions.   Made D3D
171  * & Glide have popups and print screen.  Took out all >8bpp software
172  * support.  Made Fred zbuffer.  Made zbuffer allocate dynamically to
173  * support Fred.  Made zbuffering key off of functions rather than one
174  * global variable.
175  * 
176  * 9     12/02/97 4:00p John
177  * Added first rev of thruster glow, along with variable levels of
178  * translucency, which retquired some restructing of palman.
179  * 
180  * 8     10/03/97 9:10a John
181  * added better antialiased line drawer
182  * 
183  * 7     9/23/97 10:45a John
184  * made so you can tell bitblt code to rle a bitmap by passing flag to
185  * gr_set_bitmap
186  * 
187  * 6     9/09/97 11:01a Sandeep
188  * fixed warning level 4 bugs
189  * 
190  * 5     7/10/97 2:06p John
191  * added code to specify alphablending type for bitmaps.
192  * 
193  * 4     6/17/97 7:04p John
194  * added d3d support for gradients.
195  * fixed some color bugs by adding screen signatures instead of watching
196  * flags and palette changes.
197  * 
198  * 3     6/12/97 2:50a Lawrance
199  * bm_unlock() now passed bitmap number, not pointer
200  * 
201  * 2     6/11/97 1:12p John
202  * Started fixing all the text colors in the game.
203  * 
204  * 1     5/12/97 12:14p John
205  *
206  * $NoKeywords: $
207  */
208
209 #ifndef PLAT_UNIX
210 #include <windows.h>
211 #include <windowsx.h>
212 #endif
213 #include <GL/gl.h>
214
215 #include "pstypes.h"
216 #include "osapi.h"
217 #include "2d.h"
218 #include "3d.h"
219 #include "bmpman.h"
220 #include "floating.h"
221 #include "palman.h"
222 #include "grinternal.h"
223 #include "gropengl.h"
224 #include "line.h"
225 #include "neb.h"
226
227 static int Inited = 0;
228
229 //static GLuint bitmapTex;
230 //static GLubyte *bitmapMem;
231
232 typedef enum gr_texture_source {
233         TEXTURE_SOURCE_NONE,
234         TEXTURE_SOURCE_DECAL,
235         TEXTURE_SOURCE_NO_FILTERING,
236 } gr_texture_source;
237
238 typedef enum gr_alpha_blend {
239         ALPHA_BLEND_NONE,                       // 1*SrcPixel + 0*DestPixel
240         ALPHA_BLEND_ALPHA_ADDITIVE,             // Alpha*SrcPixel + 1*DestPixel
241         ALPHA_BLEND_ALPHA_BLEND_ALPHA,          // Alpha*SrcPixel + (1-Alpha)*DestPixel
242         ALPHA_BLEND_ALPHA_BLEND_SRC_COLOR,      // Alpha*SrcPixel + (1-SrcPixel)*DestPixel
243 } gr_alpha_blend;
244
245 typedef enum gr_zbuffer_type {
246         ZBUFFER_TYPE_NONE,
247         ZBUFFER_TYPE_READ,
248         ZBUFFER_TYPE_WRITE,
249         ZBUFFER_TYPE_FULL,
250 } gr_zbuffer_type;
251                         
252 float z_mult = 30000.0f;
253 #define NEBULA_COLORS 20
254
255 static char *Gr_saved_screen = NULL;
256
257 #ifdef PLAT_UNIX
258 // Throw in some dummy functions - DDOI
259
260 int D3D_32bit = 0;              // grd3d.cpp
261 int D3D_fog_mode = -1;          // grd3d.cpp
262 int D3D_inited = 0;             // grd3d.cpp
263 int D3D_zbias = 1;              // grd3d.cpp
264 int D3d_rendition_uvs = 0;      // grd3d.cpp
265
266 void gr_dd_activate(int active)         // grdirectdraw.cpp
267 {
268         STUB_FUNCTION;
269 }
270
271 void gr_directdraw_cleanup()            // grdirectdraw.cpp
272 {
273         STUB_FUNCTION;
274 }
275
276 void gr_directdraw_force_windowed()     // grdirectdraw.cpp
277 {
278         STUB_FUNCTION;
279 }
280
281 void gr_directdraw_init()
282 {
283         STUB_FUNCTION;
284 }
285
286 extern int gr_opengl_preload (int x, int y);
287 int gr_d3d_preload (int x, int y)
288 {
289         return gr_opengl_preload(x, y);
290 }
291
292 void d3d_start_frame()
293 {
294         STUB_FUNCTION;
295 }
296
297 void d3d_stop_frame()
298 {
299         STUB_FUNCTION;
300 }
301
302 void d3d_flush ()
303 {
304         STUB_FUNCTION;
305 }
306
307 void d3d_zbias (int a)
308 {
309         STUB_FUNCTION;
310 }
311 #endif
312
313 void gr_opengl_set_state(gr_texture_source ts, gr_alpha_blend ab, gr_zbuffer_type zt)
314 {
315         switch (ts) {
316                 case TEXTURE_SOURCE_NONE:
317                         glBindTexture(GL_TEXTURE_2D, 0);
318                         gr_tcache_set(-1, -1, NULL, NULL );
319                         break;
320                 case TEXTURE_SOURCE_DECAL:
321                         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
322                         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
323                         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
324                         break;
325                 case TEXTURE_SOURCE_NO_FILTERING:
326                         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
327                         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
328                         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
329                         break;
330                 default:
331                         break;
332         }
333         
334         switch (ab) {
335                 case ALPHA_BLEND_NONE:
336                         glBlendFunc(GL_ONE, GL_ZERO);
337                         break;
338                 case ALPHA_BLEND_ALPHA_ADDITIVE:
339                         glBlendFunc(GL_ONE, GL_ONE);
340                         break;
341                 case ALPHA_BLEND_ALPHA_BLEND_ALPHA:
342                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
343                         break;
344                 case ALPHA_BLEND_ALPHA_BLEND_SRC_COLOR:
345                         glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR);
346                         break;
347                 default:
348                         break;
349         }
350         
351         switch (zt) {
352                 case ZBUFFER_TYPE_NONE:
353                         glDepthFunc(GL_ALWAYS);
354                         glDepthMask(GL_FALSE);
355                         break;
356                 case ZBUFFER_TYPE_READ:
357                         glDepthFunc(GL_LESS);
358                         glDepthMask(GL_FALSE);  
359                         break;
360                 case ZBUFFER_TYPE_WRITE:
361                         glDepthFunc(GL_ALWAYS);
362                         glDepthMask(GL_TRUE);
363                         break;
364                 case ZBUFFER_TYPE_FULL:
365                         glDepthFunc(GL_LESS);
366                         glDepthMask(GL_TRUE);
367                         break;
368                 default:
369                         break;
370         }               
371 }
372
373 void gr_opengl_activate(int b)
374 {
375         STUB_FUNCTION;
376 }
377
378
379 void opengl_tcache_flush ();
380
381 void gr_opengl_preload_init()
382 {
383         if (gr_screen.mode != GR_OPENGL) {
384                 return;
385         }
386
387         opengl_tcache_flush ();
388 }
389
390 int GL_should_preload = 0;
391 int gr_opengl_preload(int bitmap_num, int is_aabitmap)
392 {
393         if ( gr_screen.mode != GR_OPENGL) {
394                 return 0;
395         }
396
397         if ( !GL_should_preload )      {
398                 return 0;
399         }
400
401         float u_scale, v_scale;
402
403         int retval;
404         if ( is_aabitmap )      {
405                 retval = gr_tcache_set(bitmap_num, TCACHE_TYPE_AABITMAP, &u_scale, &v_scale, 1 );
406         } else {
407                 retval = gr_tcache_set(bitmap_num, TCACHE_TYPE_NORMAL, &u_scale, &v_scale, 1 );
408         }
409
410         if ( !retval )  {
411                 mprintf(("Texture upload failed!\n" ));
412         }
413
414         return retval;
415 }
416
417 void gr_opengl_pixel(int x, int y)
418 {
419         gr_line(x,y,x,y);
420 }
421
422 void gr_opengl_clear()
423 {
424         glClearColor(gr_screen.current_clear_color.red / 255.0, 
425                 gr_screen.current_clear_color.red / 255.0, 
426                 gr_screen.current_clear_color.red / 255.0, 1.0);
427
428         glClear ( GL_COLOR_BUFFER_BIT );
429 }
430
431 void opengl_tcache_frame ();
432 void gr_opengl_flip()
433 {
434         if (!Inited) return;
435
436         SDL_GL_SwapBuffers ();
437
438         opengl_tcache_frame ();
439 }
440
441 void gr_opengl_flip_window(uint _hdc, int x, int y, int w, int h )
442 {
443         STUB_FUNCTION;
444 }
445
446 void gr_opengl_set_clip(int x,int y,int w,int h)
447 {
448         // check for sanity of parameters
449         if (x < 0)
450                 x = 0;
451         if (y < 0)
452                 y = 0;
453
454         if (x >= gr_screen.max_w)
455                 x = gr_screen.max_w - 1;
456         if (y >= gr_screen.max_h)
457                 y = gr_screen.max_h - 1;
458
459         if (x + w > gr_screen.max_w)
460                 w = gr_screen.max_w - x;
461         if (y + h > gr_screen.max_h)
462                 h = gr_screen.max_h - y;
463         
464         if (w > gr_screen.max_w)
465                 w = gr_screen.max_w;
466         if (h > gr_screen.max_h)
467                 h = gr_screen.max_h;
468         
469         gr_screen.offset_x = x;
470         gr_screen.offset_y = y;
471         gr_screen.clip_left = 0;
472         gr_screen.clip_right = w-1;
473         gr_screen.clip_top = 0;
474         gr_screen.clip_bottom = h-1;
475         gr_screen.clip_width = w;
476         gr_screen.clip_height = h;
477         
478 //      glViewport(x, y, w, h);
479 }
480
481 void gr_opengl_reset_clip()
482 {
483         gr_screen.offset_x = 0;
484         gr_screen.offset_y = 0;
485         gr_screen.clip_left = 0;
486         gr_screen.clip_top = 0;
487         gr_screen.clip_right = gr_screen.max_w - 1;
488         gr_screen.clip_bottom = gr_screen.max_h - 1;
489         gr_screen.clip_width = gr_screen.max_w;
490         gr_screen.clip_height = gr_screen.max_h;
491         
492 //      glViewport(0, 0, gr_screen.max_w, gr_screen.max_h);
493 }
494
495 void gr_opengl_set_bitmap( int bitmap_num, int alphablend_mode, int bitblt_mode, float alpha, int sx, int sy )
496 {
497         gr_screen.current_alpha = alpha;
498         gr_screen.current_alphablend_mode = alphablend_mode;
499         gr_screen.current_bitblt_mode = bitblt_mode;
500         gr_screen.current_bitmap = bitmap_num;
501
502         gr_screen.current_bitmap_sx = sx;
503         gr_screen.current_bitmap_sy = sy;
504 }
505
506 void gr_opengl_create_shader(shader * shade, float r, float g, float b, float c )
507 {
508         shade->screen_sig = gr_screen.signature;
509         shade->r = r;
510         shade->g = g;
511         shade->b = b;
512         shade->c = c;   
513 }
514
515 void gr_opengl_set_shader( shader * shade )
516 {       
517         if ( shade )    {
518                 if (shade->screen_sig != gr_screen.signature)   {
519                         gr_create_shader( shade, shade->r, shade->g, shade->b, shade->c );
520                 }
521                 gr_screen.current_shader = *shade;
522         } else {
523                 gr_create_shader( &gr_screen.current_shader, 0.0f, 0.0f, 0.0f, 0.0f );
524         }
525 }
526
527
528 void gr_opengl_bitmap_ex_internal(int x,int y,int w,int h,int sx,int sy)
529 {
530         STUB_FUNCTION; /* who called me? */
531 #if 0
532         bitmap * bmp;
533         extern int GL_last_bitmap_id;   
534         bmp = bm_lock( gr_screen.current_bitmap, 16, 0 );
535         
536         int ix, iy, iw, ih;
537         int px, py, qx, qy;
538         GLubyte *sptr, *dptr;
539         
540         float s, t;
541         
542         int cw = min(bmp->w, w);
543         int ch = min(bmp->h, h);
544
545         GL_last_bitmap_id = -1; /* HACK! */
546         
547         glColor4f(1.0, 1.0, 1.0, 1.0);  
548         glBindTexture(GL_TEXTURE_2D, bitmapTex);
549                 
550         py = y;
551         for (iy = sy; iy < ch; iy += 256) {
552                 px = x;
553                 ih = min(256, (ch-iy));
554                 qy = py+ih;
555                 for (ix = sx; ix < cw; ix += 256) {
556                         dptr = bitmapMem;
557                         sptr = ((unsigned char *)bmp->data) + 2*(iy*bmp->w + ix);
558                         
559                         iw = min(256, (cw-ix));
560                                 
561                         qx = px+iw;
562                         
563                         int ihx = ih;
564                         while (ihx > 0) {
565                                 memcpy(dptr, sptr, iw*2);
566                                 
567                                 sptr += 2*bmp->w;
568                                 dptr += 2*iw;
569                                 
570                                 ihx--;
571                         }                       
572                         
573                         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, iw, ih, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, bitmapMem);
574                         glBegin(GL_QUADS);
575                                 /* upper left */
576                                 s = 0.0;
577                                 t = 0.0;
578                                 glTexCoord2f(s, t);
579                                 glVertex2i(px, py);
580                                 
581                                 /* lower left */
582                                 s = 0.0;
583                                 t = (float)ih / 256.0;
584                                 glTexCoord2f(s, t);
585                                 glVertex2i(px, qy);
586                                 
587                                 /* lower right */
588                                 s = (float)iw / 256.0;
589                                 t = (float)ih / 256.0;
590                                 glTexCoord2f(s, t);
591                                 glVertex2i(qx, qy);
592                                 
593                                 /* upper left */
594                                 s = (float)iw / 256.0;
595                                 t = 0.0;
596                                 glTexCoord2f(s, t);
597                                 glVertex2i(qx, py);
598                         glEnd();
599                         
600                         px = qx;
601                 }
602                 
603                 py = qy;
604         }
605         
606         bm_unlock(gr_screen.current_bitmap);
607 #endif  
608 }
609
610
611 void gr_opengl_bitmap_ex(int x,int y,int w,int h,int sx,int sy)
612 {
613         int reclip;
614         #ifndef NDEBUG
615         int count = 0;
616         #endif
617
618         int dx1=x, dx2=x+w-1;
619         int dy1=y, dy2=y+h-1;
620
621         int bw, bh;
622         bm_get_info( gr_screen.current_bitmap, &bw, &bh, NULL );
623
624         do {
625                 reclip = 0;
626                 #ifndef NDEBUG
627                         if ( count > 1 ) Int3();
628                         count++;
629                 #endif
630         
631                 if ((dx1 > gr_screen.clip_right ) || (dx2 < gr_screen.clip_left)) return;
632                 if ((dy1 > gr_screen.clip_bottom ) || (dy2 < gr_screen.clip_top)) return;
633                 if ( dx1 < gr_screen.clip_left ) { sx += gr_screen.clip_left-dx1; dx1 = gr_screen.clip_left; }
634                 if ( dy1 < gr_screen.clip_top ) { sy += gr_screen.clip_top-dy1; dy1 = gr_screen.clip_top; }
635                 if ( dx2 > gr_screen.clip_right )       { dx2 = gr_screen.clip_right; }
636                 if ( dy2 > gr_screen.clip_bottom )      { dy2 = gr_screen.clip_bottom; }
637
638                 if ( sx < 0 ) {
639                         dx1 -= sx;
640                         sx = 0;
641                         reclip = 1;
642                 }
643
644                 if ( sy < 0 ) {
645                         dy1 -= sy;
646                         sy = 0;
647                         reclip = 1;
648                 }
649
650                 w = dx2-dx1+1;
651                 h = dy2-dy1+1;
652
653                 if ( sx + w > bw ) {
654                         w = bw - sx;
655                         dx2 = dx1 + w - 1;
656                 }
657
658                 if ( sy + h > bh ) {
659                         h = bh - sy;
660                         dy2 = dy1 + h - 1;
661                 }
662
663                 if ( w < 1 ) return;            // clipped away!
664                 if ( h < 1 ) return;            // clipped away!
665
666         } while (reclip);
667
668         // Make sure clipping algorithm works
669         #ifndef NDEBUG
670                 Assert( w > 0 );
671                 Assert( h > 0 );
672                 Assert( w == (dx2-dx1+1) );
673                 Assert( h == (dy2-dy1+1) );
674                 Assert( sx >= 0 );
675                 Assert( sy >= 0 );
676                 Assert( sx+w <= bw );
677                 Assert( sy+h <= bh );
678                 Assert( dx2 >= dx1 );
679                 Assert( dy2 >= dy1 );
680                 Assert( (dx1 >= gr_screen.clip_left ) && (dx1 <= gr_screen.clip_right) );
681                 Assert( (dx2 >= gr_screen.clip_left ) && (dx2 <= gr_screen.clip_right) );
682                 Assert( (dy1 >= gr_screen.clip_top ) && (dy1 <= gr_screen.clip_bottom) );
683                 Assert( (dy2 >= gr_screen.clip_top ) && (dy2 <= gr_screen.clip_bottom) );
684         #endif
685
686         // We now have dx1,dy1 and dx2,dy2 and sx, sy all set validly within clip regions.
687         // Draw bitmap bm[sx,sy] into (dx1,dy1)-(dx2,dy2)
688
689         gr_opengl_bitmap_ex_internal(dx1,dy1,dx2-dx1+1,dy2-dy1+1,sx,sy);
690 }
691
692 void gr_opengl_bitmap(int x, int y)
693 {
694         int w, h;
695
696         bm_get_info( gr_screen.current_bitmap, &w, &h, NULL );
697         int dx1=x, dx2=x+w-1;
698         int dy1=y, dy2=y+h-1;
699         int sx=0, sy=0;
700
701         if ((dx1 > gr_screen.clip_right ) || (dx2 < gr_screen.clip_left)) return;
702         if ((dy1 > gr_screen.clip_bottom ) || (dy2 < gr_screen.clip_top)) return;
703         if ( dx1 < gr_screen.clip_left ) { sx = gr_screen.clip_left-dx1; dx1 = gr_screen.clip_left; }
704         if ( dy1 < gr_screen.clip_top ) { sy = gr_screen.clip_top-dy1; dy1 = gr_screen.clip_top; }
705         if ( dx2 > gr_screen.clip_right )       { dx2 = gr_screen.clip_right; }
706         if ( dy2 > gr_screen.clip_bottom )      { dy2 = gr_screen.clip_bottom; }
707
708         if ( sx < 0 ) return;
709         if ( sy < 0 ) return;
710         if ( sx >= w ) return;
711         if ( sy >= h ) return;
712
713         // Draw bitmap bm[sx,sy] into (dx1,dy1)-(dx2,dy2)
714
715         gr_opengl_bitmap_ex_internal(dx1,dy1,dx2-dx1+1,dy2-dy1+1,sx,sy);        
716 }
717
718 void gr_opengl_rect_internal(int x, int y, int w, int h, int r, int g, int b, int a)
719 {
720         int saved_zbuf;
721         vertex v[4];
722         vertex *verts[4] = {&v[0], &v[1], &v[2], &v[3]};
723
724         saved_zbuf = gr_zbuffer_get();
725         
726         // start the frame, no zbuffering, no culling
727         g3_start_frame(1);      
728         gr_zbuffer_set(GR_ZBUFF_NONE);          
729         gr_set_cull(0);         
730
731         // stuff coords         
732         v[0].sx = i2fl(x);
733         v[0].sy = i2fl(y);
734         v[0].sw = 0.0f;
735         v[0].u = 0.0f;
736         v[0].v = 0.0f;
737         v[0].flags = PF_PROJECTED;
738         v[0].codes = 0;
739         v[0].r = (ubyte)r;
740         v[0].g = (ubyte)g;
741         v[0].b = (ubyte)b;
742         v[0].a = (ubyte)a;
743
744         v[1].sx = i2fl(x + w);
745         v[1].sy = i2fl(y);      
746         v[1].sw = 0.0f;
747         v[1].u = 0.0f;
748         v[1].v = 0.0f;
749         v[1].flags = PF_PROJECTED;
750         v[1].codes = 0;
751         v[1].r = (ubyte)r;
752         v[1].g = (ubyte)g;
753         v[1].b = (ubyte)b;
754         v[1].a = (ubyte)a;
755
756         v[2].sx = i2fl(x + w);
757         v[2].sy = i2fl(y + h);
758         v[2].sw = 0.0f;
759         v[2].u = 0.0f;
760         v[2].v = 0.0f;
761         v[2].flags = PF_PROJECTED;
762         v[2].codes = 0;
763         v[2].r = (ubyte)r;
764         v[2].g = (ubyte)g;
765         v[2].b = (ubyte)b;
766         v[2].a = (ubyte)a;
767
768         v[3].sx = i2fl(x);
769         v[3].sy = i2fl(y + h);
770         v[3].sw = 0.0f;
771         v[3].u = 0.0f;
772         v[3].v = 0.0f;
773         v[3].flags = PF_PROJECTED;
774         v[3].codes = 0;                         
775         v[3].r = (ubyte)r;
776         v[3].g = (ubyte)g;
777         v[3].b = (ubyte)b;
778         v[3].a = (ubyte)a;
779
780         // draw the polys
781         g3_draw_poly_constant_sw(4, verts, TMAP_FLAG_GOURAUD | TMAP_FLAG_RGB | TMAP_FLAG_ALPHA, 0.1f);          
782
783         g3_end_frame();
784
785         // restore zbuffer and culling
786         gr_zbuffer_set(saved_zbuf);
787         gr_set_cull(1); 
788 }
789
790 void gr_opengl_rect(int x,int y,int w,int h)
791 {
792         gr_opengl_rect_internal(x, y, w, h, gr_screen.current_color.red, gr_screen.current_color.green, gr_screen.current_color.blue, gr_screen.current_color.alpha);
793 }
794
795 void gr_opengl_shade(int x,int y,int w,int h)
796 {
797         int r,g,b,a;
798         
799         float shade1 = 1.0f;
800         float shade2 = 6.0f;
801
802         r = fl2i(gr_screen.current_shader.r*255.0f*shade1);
803         if ( r < 0 ) r = 0; else if ( r > 255 ) r = 255;
804         g = fl2i(gr_screen.current_shader.g*255.0f*shade1);
805         if ( g < 0 ) g = 0; else if ( g > 255 ) g = 255;
806         b = fl2i(gr_screen.current_shader.b*255.0f*shade1);
807         if ( b < 0 ) b = 0; else if ( b > 255 ) b = 255;
808         a = fl2i(gr_screen.current_shader.c*255.0f*shade2);
809         if ( a < 0 ) a = 0; else if ( a > 255 ) a = 255;
810
811         gr_opengl_rect_internal(x, y, w, h, r, g, b, a);        
812 }
813
814 void gr_opengl_aabitmap_ex_internal(int x,int y,int w,int h,int sx,int sy)
815 {
816         if ( w < 1 ) return;
817         if ( h < 1 ) return;
818
819         if ( !gr_screen.current_color.is_alphacolor )   return;
820
821         float u_scale, v_scale;
822
823         gr_opengl_set_state( TEXTURE_SOURCE_NO_FILTERING, ALPHA_BLEND_ALPHA_BLEND_ALPHA, ZBUFFER_TYPE_NONE );
824
825         if ( !gr_tcache_set( gr_screen.current_bitmap, TCACHE_TYPE_AABITMAP, &u_scale, &v_scale ) )     {
826                 // Couldn't set texture
827                 mprintf(( "WARNING: Error setting aabitmap texture!\n" ));
828                 return;
829         }
830
831         float u0, u1, v0, v1;
832         float x1, x2, y1, y2;
833         int bw, bh;
834
835         bm_get_info( gr_screen.current_bitmap, &bw, &bh );
836
837         u0 = u_scale*i2fl(sx)/i2fl(bw);
838         v0 = v_scale*i2fl(sy)/i2fl(bh);
839
840         u1 = u_scale*i2fl(sx+w)/i2fl(bw);
841         v1 = v_scale*i2fl(sy+h)/i2fl(bh);
842
843         x1 = i2fl(x+gr_screen.offset_x);
844         y1 = i2fl(y+gr_screen.offset_y);
845         x2 = i2fl(x+w+gr_screen.offset_x);
846         y2 = i2fl(y+h+gr_screen.offset_y);
847
848         if ( gr_screen.current_color.is_alphacolor )    {
849                 glColor4ub(gr_screen.current_color.red, gr_screen.current_color.green, gr_screen.current_color.blue,gr_screen.current_color.alpha);
850         } else {
851                 glColor3ub(gr_screen.current_color.red, gr_screen.current_color.green, gr_screen.current_color.blue);
852         }
853
854         glBegin (GL_QUADS);
855           glTexCoord2f (u0, v1);
856           glVertex3f (x1, y2, -0.99);
857
858           glTexCoord2f (u1, v1);
859           glVertex3f (x2, y2, -0.99);
860
861           glTexCoord2f (u1, v0);
862           glVertex3f (x2, y1, -0.99);
863
864           glTexCoord2f (u0, v0);
865           glVertex3f (x1, y1, -0.99);
866         glEnd ();
867 }
868
869 void gr_opengl_aabitmap_ex(int x,int y,int w,int h,int sx,int sy)
870 {
871         int reclip;
872         #ifndef NDEBUG
873         int count = 0;
874         #endif
875
876         int dx1=x, dx2=x+w-1;
877         int dy1=y, dy2=y+h-1;
878
879         int bw, bh;
880         bm_get_info( gr_screen.current_bitmap, &bw, &bh, NULL );
881
882         do {
883                 reclip = 0;
884                 #ifndef NDEBUG
885                         if ( count > 1 ) Int3();
886                         count++;
887                 #endif
888         
889                 if ((dx1 > gr_screen.clip_right ) || (dx2 < gr_screen.clip_left)) return;
890                 if ((dy1 > gr_screen.clip_bottom ) || (dy2 < gr_screen.clip_top)) return;
891                 if ( dx1 < gr_screen.clip_left ) { sx += gr_screen.clip_left-dx1; dx1 = gr_screen.clip_left; }
892                 if ( dy1 < gr_screen.clip_top ) { sy += gr_screen.clip_top-dy1; dy1 = gr_screen.clip_top; }
893                 if ( dx2 > gr_screen.clip_right )       { dx2 = gr_screen.clip_right; }
894                 if ( dy2 > gr_screen.clip_bottom )      { dy2 = gr_screen.clip_bottom; }
895
896                 if ( sx < 0 ) {
897                         dx1 -= sx;
898                         sx = 0;
899                         reclip = 1;
900                 }
901
902                 if ( sy < 0 ) {
903                         dy1 -= sy;
904                         sy = 0;
905                         reclip = 1;
906                 }
907
908                 w = dx2-dx1+1;
909                 h = dy2-dy1+1;
910
911                 if ( sx + w > bw ) {
912                         w = bw - sx;
913                         dx2 = dx1 + w - 1;
914                 }
915
916                 if ( sy + h > bh ) {
917                         h = bh - sy;
918                         dy2 = dy1 + h - 1;
919                 }
920
921                 if ( w < 1 ) return;            // clipped away!
922                 if ( h < 1 ) return;            // clipped away!
923
924         } while (reclip);
925
926         // Make sure clipping algorithm works
927         #ifndef NDEBUG
928                 Assert( w > 0 );
929                 Assert( h > 0 );
930                 Assert( w == (dx2-dx1+1) );
931                 Assert( h == (dy2-dy1+1) );
932                 Assert( sx >= 0 );
933                 Assert( sy >= 0 );
934                 Assert( sx+w <= bw );
935                 Assert( sy+h <= bh );
936                 Assert( dx2 >= dx1 );
937                 Assert( dy2 >= dy1 );
938                 Assert( (dx1 >= gr_screen.clip_left ) && (dx1 <= gr_screen.clip_right) );
939                 Assert( (dx2 >= gr_screen.clip_left ) && (dx2 <= gr_screen.clip_right) );
940                 Assert( (dy1 >= gr_screen.clip_top ) && (dy1 <= gr_screen.clip_bottom) );
941                 Assert( (dy2 >= gr_screen.clip_top ) && (dy2 <= gr_screen.clip_bottom) );
942         #endif
943
944         // We now have dx1,dy1 and dx2,dy2 and sx, sy all set validly within clip regions.
945         gr_opengl_aabitmap_ex_internal(dx1,dy1,dx2-dx1+1,dy2-dy1+1,sx,sy);
946 }
947
948 void gr_opengl_aabitmap(int x, int y)
949 {
950         int w, h;
951
952         bm_get_info( gr_screen.current_bitmap, &w, &h, NULL );
953         int dx1=x, dx2=x+w-1;
954         int dy1=y, dy2=y+h-1;
955         int sx=0, sy=0;
956
957         if ((dx1 > gr_screen.clip_right ) || (dx2 < gr_screen.clip_left)) return;
958         if ((dy1 > gr_screen.clip_bottom ) || (dy2 < gr_screen.clip_top)) return;
959         if ( dx1 < gr_screen.clip_left ) { sx = gr_screen.clip_left-dx1; dx1 = gr_screen.clip_left; }
960         if ( dy1 < gr_screen.clip_top ) { sy = gr_screen.clip_top-dy1; dy1 = gr_screen.clip_top; }
961         if ( dx2 > gr_screen.clip_right )       { dx2 = gr_screen.clip_right; }
962         if ( dy2 > gr_screen.clip_bottom )      { dy2 = gr_screen.clip_bottom; }
963
964         if ( sx < 0 ) return;
965         if ( sy < 0 ) return;
966         if ( sx >= w ) return;
967         if ( sy >= h ) return;
968
969         // Draw bitmap bm[sx,sy] into (dx1,dy1)-(dx2,dy2)
970         gr_aabitmap_ex(dx1,dy1,dx2-dx1+1,dy2-dy1+1,sx,sy);
971 }
972
973
974 void gr_opengl_string( int sx, int sy, char *s )
975 {
976         int width, spacing, letter;
977         int x, y;
978
979         if ( !Current_font )    {
980                 return;
981         }
982
983         gr_set_bitmap(Current_font->bitmap_id);
984
985         x = sx;
986         y = sy;
987
988         if (sx==0x8000) {                       //centered
989                 x = get_centered_x(s);
990         } else {
991                 x = sx;
992         }
993         
994         spacing = 0;
995
996         while (*s)      {
997                 x += spacing;
998
999                 while (*s== '\n' )      {
1000                         s++;
1001                         y += Current_font->h;
1002                         if (sx==0x8000) {                       //centered
1003                                 x = get_centered_x(s);
1004                         } else {
1005                                 x = sx;
1006                         }
1007                 }
1008                 if (*s == 0 ) break;
1009
1010                 letter = get_char_width(s[0],s[1],&width,&spacing);
1011                 s++;
1012
1013                 //not in font, draw as space
1014                 if (letter<0)   {
1015                         continue;
1016                 }
1017
1018                 int xd, yd, xc, yc;
1019                 int wc, hc;
1020
1021                 // Check if this character is totally clipped
1022                 if ( x + width < gr_screen.clip_left ) continue;
1023                 if ( y + Current_font->h < gr_screen.clip_top ) continue;
1024                 if ( x > gr_screen.clip_right ) continue;
1025                 if ( y > gr_screen.clip_bottom ) continue;
1026
1027                 xd = yd = 0;
1028                 if ( x < gr_screen.clip_left ) xd = gr_screen.clip_left - x;
1029                 if ( y < gr_screen.clip_top ) yd = gr_screen.clip_top - y;
1030                 xc = x+xd;
1031                 yc = y+yd;
1032
1033                 wc = width - xd; hc = Current_font->h - yd;
1034                 if ( xc + wc > gr_screen.clip_right ) wc = gr_screen.clip_right - xc;
1035                 if ( yc + hc > gr_screen.clip_bottom ) hc = gr_screen.clip_bottom - yc;
1036
1037                 if ( wc < 1 ) continue;
1038                 if ( hc < 1 ) continue;
1039
1040                 int u = Current_font->bm_u[letter];
1041                 int v = Current_font->bm_v[letter];
1042
1043                 gr_opengl_aabitmap_ex_internal( xc, yc, wc, hc, u+xd, v+yd );
1044         }
1045 }
1046
1047 void gr_opengl_line(int x1,int y1,int x2,int y2)
1048 {
1049         int clipped = 0, swapped=0;
1050
1051         gr_opengl_set_state( TEXTURE_SOURCE_NONE, ALPHA_BLEND_ALPHA_BLEND_ALPHA, ZBUFFER_TYPE_NONE );
1052         
1053         INT_CLIPLINE(x1,y1,x2,y2,gr_screen.clip_left,gr_screen.clip_top,gr_screen.clip_right,gr_screen.clip_bottom,return,clipped=1,swapped=1);
1054                 
1055         glBegin (GL_LINE);
1056           glColor4ub (gr_screen.current_color.red, gr_screen.current_color.green, gr_screen.current_color.blue, gr_screen.current_color.alpha);
1057           glVertex3f (i2fl (x2+gr_screen.offset_x),i2fl (y2+gr_screen.offset_y), -0.99f);
1058           glVertex3f (i2fl (x1+gr_screen.offset_x),i2fl (y1+gr_screen.offset_y), -0.99f);
1059         glEnd ();
1060 }
1061
1062 void gr_opengl_gradient(int x1,int y1,int x2,int y2)
1063 {
1064         int clipped = 0, swapped=0;
1065
1066         if ( !gr_screen.current_color.is_alphacolor )   {
1067                 gr_line( x1, y1, x2, y2 );
1068                 return;
1069         }
1070
1071         INT_CLIPLINE(x1,y1,x2,y2,gr_screen.clip_left,gr_screen.clip_top,gr_screen.clip_right,gr_screen.clip_bottom,return,clipped=1,swapped=1);
1072
1073         gr_opengl_set_state( TEXTURE_SOURCE_NONE, ALPHA_BLEND_ALPHA_BLEND_ALPHA, ZBUFFER_TYPE_NONE );
1074
1075         glBegin (GL_LINE);
1076           glColor4ub (gr_screen.current_color.red, gr_screen.current_color.green, gr_screen.current_color.blue, gr_screen.current_color.alpha);
1077           glVertex3f (i2fl (x2+gr_screen.offset_x),i2fl (y2+gr_screen.offset_y), -0.99f);
1078           glColor4ub (gr_screen.current_color.red, gr_screen.current_color.green, gr_screen.current_color.blue, 0);
1079           glVertex3f (i2fl (x1+gr_screen.offset_x),i2fl (y1+gr_screen.offset_y), -0.99f);
1080         glEnd ();       
1081 }
1082
1083 void gr_opengl_circle( int xc, int yc, int d )
1084 {
1085         int p,x, y, r;
1086
1087         r = d/2;
1088         p=3-d;
1089         x=0;
1090         y=r;
1091
1092         // Big clip
1093         if ( (xc+r) < gr_screen.clip_left ) return;
1094         if ( (xc-r) > gr_screen.clip_right ) return;
1095         if ( (yc+r) < gr_screen.clip_top ) return;
1096         if ( (yc-r) > gr_screen.clip_bottom ) return;
1097
1098         while(x<y)      {
1099                 // Draw the first octant
1100                 gr_opengl_line( xc-y, yc-x, xc+y, yc-x );
1101                 gr_opengl_line( xc-y, yc+x, xc+y, yc+x );
1102                                 
1103                 if (p<0) 
1104                         p=p+(x<<2)+6;
1105                 else    {
1106                         // Draw the second octant
1107                         gr_opengl_line( xc-x, yc-y, xc+x, yc-y );
1108                         gr_opengl_line( xc-x, yc+y, xc+x, yc+y );
1109                                                 
1110                         p=p+((x-y)<<2)+10;
1111                         y--;
1112                 }
1113                 x++;
1114         }
1115         if(x==y) {
1116                 gr_opengl_line( xc-x, yc-y, xc+x, yc-y );
1117                 gr_opengl_line( xc-x, yc+y, xc+x, yc+y );
1118         }
1119         return;
1120 }
1121
1122 void gr_opengl_stuff_fog_value(float z, int *r, int *g, int *b, int *a)
1123 {
1124         float f_float;
1125         
1126         f_float = (gr_screen.fog_far - z) / (gr_screen.fog_far - gr_screen.fog_near);
1127         if (f_float < 0.0f) {
1128                 f_float = 0.0f;
1129         } else {
1130                 f_float = 1.0f;
1131         }
1132         *r = 0;
1133         *g = 0;
1134         *b = 0;
1135         *a = (int)(f_float * 255.0);
1136 }
1137
1138 void gr_opengl_tmapper_internal( int nv, vertex ** verts, uint flags, int is_scaler )
1139 {
1140         int i;
1141         float u_scale = 1.0f, v_scale = 1.0f;
1142
1143         // Make nebula use the texture mapper... this blends the colors better.
1144         if ( flags & TMAP_FLAG_NEBULA ){
1145                 Int3 ();
1146         }
1147
1148         gr_texture_source texture_source = (gr_texture_source)-1;
1149         gr_alpha_blend alpha_blend = (gr_alpha_blend)-1;
1150         gr_zbuffer_type zbuffer_type = (gr_zbuffer_type)-1;
1151         
1152         if ( gr_zbuffering )    {
1153                 if ( is_scaler || (gr_screen.current_alphablend_mode == GR_ALPHABLEND_FILTER)   )       {
1154                         zbuffer_type = ZBUFFER_TYPE_READ;
1155                 } else {
1156                         zbuffer_type = ZBUFFER_TYPE_FULL;
1157                 }
1158         } else {
1159                 zbuffer_type = ZBUFFER_TYPE_NONE;
1160         }
1161         
1162         int alpha;
1163
1164         int tmap_type = TCACHE_TYPE_NORMAL;
1165
1166         int r, g, b;
1167
1168         if ( flags & TMAP_FLAG_TEXTURED )       {
1169                 r = g = b = 255;
1170         } else {
1171                 r = gr_screen.current_color.red;
1172                 g = gr_screen.current_color.green;
1173                 b = gr_screen.current_color.blue;
1174         }
1175
1176         if ( gr_screen.current_alphablend_mode == GR_ALPHABLEND_FILTER )        
1177         {
1178                 if (1) {
1179                         tmap_type = TCACHE_TYPE_NORMAL;
1180                         alpha_blend = ALPHA_BLEND_ALPHA_ADDITIVE;
1181                         
1182                         // Blend with screen pixel using src*alpha+dst
1183                         float factor = gr_screen.current_alpha;
1184                         
1185                         alpha = 255;
1186                         
1187                         if ( factor <= 1.0f )   {
1188                                 int tmp_alpha = fl2i(gr_screen.current_alpha*255.0f);
1189                                 r = (r*tmp_alpha)/255;
1190                                 g = (g*tmp_alpha)/255;
1191                                 b = (b*tmp_alpha)/255;
1192                         }
1193                 } else {
1194                         tmap_type = TCACHE_TYPE_XPARENT;
1195                         
1196                         alpha_blend = ALPHA_BLEND_ALPHA_BLEND_ALPHA;
1197                         
1198                         // Blend with screen pixel using src*alpha+dst
1199                         float factor = gr_screen.current_alpha;
1200                                 
1201                         if ( factor > 1.0f )    {
1202                                 alpha = 255;
1203                         } else {
1204                                 alpha = fl2i(gr_screen.current_alpha*255.0f);
1205                         }
1206                 }
1207         } else {
1208                 if(Bm_pixel_format == BM_PIXEL_FORMAT_ARGB) {
1209                         alpha_blend = ALPHA_BLEND_ALPHA_BLEND_ALPHA;
1210                 } else {
1211                         alpha_blend = ALPHA_BLEND_NONE;
1212                 }
1213                 alpha = 255;
1214         }
1215
1216         if(flags & TMAP_FLAG_BITMAP_SECTION){
1217                 tmap_type = TCACHE_TYPE_BITMAP_SECTION;
1218         }
1219         
1220         texture_source = TEXTURE_SOURCE_NONE;
1221         
1222         if ( flags & TMAP_FLAG_TEXTURED )       {
1223                 if ( !gr_tcache_set(gr_screen.current_bitmap, tmap_type, &u_scale, &v_scale, 0, gr_screen.current_bitmap_sx, gr_screen.current_bitmap_sy ))
1224                 {
1225                         mprintf(( "Not rendering a texture because it didn't fit in VRAM!\n" ));
1226                         return;
1227                 }
1228
1229                 // use nonfiltered textures for bitmap sections
1230                 if(flags & TMAP_FLAG_BITMAP_SECTION){
1231                         texture_source = TEXTURE_SOURCE_NO_FILTERING;
1232                 } else {
1233                         texture_source = TEXTURE_SOURCE_DECAL;
1234                 }
1235         }
1236
1237
1238         gr_opengl_set_state( texture_source, alpha_blend, zbuffer_type );
1239         
1240         if ( flags & TMAP_FLAG_TEXTURED )
1241         {
1242                 // rendition junk
1243                 // STUB_FUNCTION;
1244         }
1245
1246         if (flags & TMAP_FLAG_PIXEL_FOG) {
1247                 int r, g, b;
1248                 int ra, ga, ba;
1249                 ra = ga = ba = 0;
1250         
1251                 /* argh */
1252                 for (i=nv-1;i>=0;i--)   // DDOI - change polygon winding
1253                 {
1254                         vertex * va = verts[i];
1255                         float sx, sy;
1256                 
1257                         int x, y;
1258                         x = fl2i(va->sx*16.0f);
1259                         y = fl2i(va->sy*16.0f);
1260                 
1261                         x += gr_screen.offset_x*16;
1262                         y += gr_screen.offset_y*16;
1263                 
1264                         sx = i2fl(x) / 16.0f;
1265                         sy = i2fl(y) / 16.0f;
1266                 
1267                         neb2_get_pixel((int)sx, (int)sy, &r, &g, &b);
1268                         
1269                         ra += r;
1270                         ga += g;
1271                         ba += b;
1272                 }
1273                 
1274                 ra /= nv;
1275                 ga /= nv;
1276                 ba /= nv;
1277                 
1278                 gr_fog_set(GR_FOGMODE_FOG, ra, ga, ba);
1279         }
1280         
1281         glBegin(GL_TRIANGLE_FAN);
1282         for (i = nv-1; i >= 0; i--) {           
1283                 vertex * va = verts[i];
1284                 float sx, sy, sz, sw;
1285                 float tu, tv;
1286                 float rhw;
1287                 int a;
1288                 
1289                 if ( gr_zbuffering || (flags & TMAP_FLAG_NEBULA) )      {
1290                         sz = va->z / z_mult;
1291                         if ( sz > 0.98f ) {
1292                                 sz = 0.98f;
1293                         }
1294                 } else {
1295                         sz = 0.99f;
1296                 }
1297                                 
1298                 if ( flags & TMAP_FLAG_CORRECT )        {
1299                         rhw = va->sw;
1300                 } else {
1301                         rhw = 1.0f;
1302                 }
1303                 
1304                 if (flags & TMAP_FLAG_ALPHA) {
1305                         a = verts[i]->a;
1306                 } else {
1307                         a = alpha;
1308                 }
1309
1310                 if (flags & TMAP_FLAG_NEBULA ) {
1311                         int pal = (verts[i]->b*(NEBULA_COLORS-1))/255;
1312                         r = gr_palette[pal*3+0];
1313                         g = gr_palette[pal*3+1];
1314                         b = gr_palette[pal*3+2];
1315                 } else if ( (flags & TMAP_FLAG_RAMP) && (flags & TMAP_FLAG_GOURAUD) )   {
1316                         r = Gr_gamma_lookup[verts[i]->b];
1317                         g = Gr_gamma_lookup[verts[i]->b];
1318                         b = Gr_gamma_lookup[verts[i]->b];
1319                 } else if ( (flags & TMAP_FLAG_RGB)  && (flags & TMAP_FLAG_GOURAUD) )   {
1320                         // Make 0.75 be 256.0f
1321                         r = Gr_gamma_lookup[verts[i]->r];
1322                         g = Gr_gamma_lookup[verts[i]->g];
1323                         b = Gr_gamma_lookup[verts[i]->b];
1324                 } else {
1325                         // use constant RGB values...
1326                 }
1327                 glColor4ub (r,g,b,a);
1328
1329                 if((gr_screen.current_fog_mode != GR_FOGMODE_NONE) && (D3D_fog_mode == 1)){
1330                         int sr, sg, sb, sa;
1331                         
1332                         /* this is for GL_EXT_SECONDARY_COLOR */
1333                         gr_opengl_stuff_fog_value(va->z, &sr, &sg, &sb, &sa);
1334                         /* do separate color call here */
1335                         
1336                         STUB_FUNCTION;
1337                 }
1338                 
1339                 int x, y;
1340                 x = fl2i(va->sx*16.0f);
1341                 y = fl2i(va->sy*16.0f);
1342                 
1343                 x += gr_screen.offset_x*16;
1344                 y += gr_screen.offset_y*16;
1345                 
1346                 sx = i2fl(x) / 16.0f;
1347                 sy = i2fl(y) / 16.0f;
1348                 
1349                 if ( flags & TMAP_FLAG_TEXTURED )       {
1350                         tu = va->u*u_scale;
1351                         tv = va->v*v_scale;
1352                         glTexCoord2d(tu, tv);
1353                 }
1354                 
1355                 sw = 1.0;
1356                 
1357                 glVertex4d(sx/rhw, sy/rhw, -sz/rhw, sw/rhw);
1358         }
1359         glEnd();
1360 }
1361
1362 void gr_opengl_tmapper( int nverts, vertex **verts, uint flags )
1363 {
1364         gr_opengl_tmapper_internal( nverts, verts, flags, 0 );
1365 }
1366
1367 #define FIND_SCALED_NUM(x,x0,x1,y0,y1) (((((x)-(x0))*((y1)-(y0)))/((x1)-(x0)))+(y0))
1368
1369 void gr_opengl_scaler(vertex *va, vertex *vb )
1370 {
1371         float x0, y0, x1, y1;
1372         float u0, v0, u1, v1;
1373         float clipped_x0, clipped_y0, clipped_x1, clipped_y1;
1374         float clipped_u0, clipped_v0, clipped_u1, clipped_v1;
1375         float xmin, xmax, ymin, ymax;
1376         int dx0, dy0, dx1, dy1;
1377
1378         //============= CLIP IT =====================
1379
1380         x0 = va->sx; y0 = va->sy;
1381         x1 = vb->sx; y1 = vb->sy;
1382
1383         xmin = i2fl(gr_screen.clip_left); ymin = i2fl(gr_screen.clip_top);
1384         xmax = i2fl(gr_screen.clip_right); ymax = i2fl(gr_screen.clip_bottom);
1385
1386         u0 = va->u; v0 = va->v;
1387         u1 = vb->u; v1 = vb->v;
1388
1389         // Check for obviously offscreen bitmaps...
1390         if ( (y1<=y0) || (x1<=x0) ) return;
1391         if ( (x1<xmin ) || (x0>xmax) ) return;
1392         if ( (y1<ymin ) || (y0>ymax) ) return;
1393
1394         clipped_u0 = u0; clipped_v0 = v0;
1395         clipped_u1 = u1; clipped_v1 = v1;
1396
1397         clipped_x0 = x0; clipped_y0 = y0;
1398         clipped_x1 = x1; clipped_y1 = y1;
1399
1400         // Clip the left, moving u0 right as necessary
1401         if ( x0 < xmin )        {
1402                 clipped_u0 = FIND_SCALED_NUM(xmin,x0,x1,u0,u1);
1403                 clipped_x0 = xmin;
1404         }
1405
1406         // Clip the right, moving u1 left as necessary
1407         if ( x1 > xmax )        {
1408                 clipped_u1 = FIND_SCALED_NUM(xmax,x0,x1,u0,u1);
1409                 clipped_x1 = xmax;
1410         }
1411
1412         // Clip the top, moving v0 down as necessary
1413         if ( y0 < ymin )        {
1414                 clipped_v0 = FIND_SCALED_NUM(ymin,y0,y1,v0,v1);
1415                 clipped_y0 = ymin;
1416         }
1417
1418         // Clip the bottom, moving v1 up as necessary
1419         if ( y1 > ymax )        {
1420                 clipped_v1 = FIND_SCALED_NUM(ymax,y0,y1,v0,v1);
1421                 clipped_y1 = ymax;
1422         }
1423         
1424         dx0 = fl2i(clipped_x0); dx1 = fl2i(clipped_x1);
1425         dy0 = fl2i(clipped_y0); dy1 = fl2i(clipped_y1);
1426
1427         if (dx1<=dx0) return;
1428         if (dy1<=dy0) return;
1429
1430         //============= DRAW IT =====================
1431
1432         vertex v[4];
1433         vertex *vl[4];
1434
1435         vl[0] = &v[0];  
1436         v->sx = clipped_x0;
1437         v->sy = clipped_y0;
1438         v->sw = va->sw;
1439         v->z = va->z;
1440         v->u = clipped_u0;
1441         v->v = clipped_v0;
1442
1443         vl[1] = &v[1];  
1444         v[1].sx = clipped_x1;
1445         v[1].sy = clipped_y0;
1446         v[1].sw = va->sw;
1447         v[1].z = va->z;
1448         v[1].u = clipped_u1;
1449         v[1].v = clipped_v0;
1450
1451         vl[2] = &v[2];  
1452         v[2].sx = clipped_x1;
1453         v[2].sy = clipped_y1;
1454         v[2].sw = va->sw;
1455         v[2].z = va->z;
1456         v[2].u = clipped_u1;
1457         v[2].v = clipped_v1;
1458
1459         vl[3] = &v[3];  
1460         v[3].sx = clipped_x0;
1461         v[3].sy = clipped_y1;
1462         v[3].sw = va->sw;
1463         v[3].z = va->z;
1464         v[3].u = clipped_u0;
1465         v[3].v = clipped_v1;
1466
1467         gr_opengl_tmapper_internal( 4, vl, TMAP_FLAG_TEXTURED, 1 );
1468 }
1469
1470 void gr_opengl_set_palette(ubyte *new_palette, int is_alphacolor)
1471 {
1472 }
1473
1474 void gr_opengl_get_color( int * r, int * g, int * b )
1475 {
1476         if (r) *r = gr_screen.current_color.red;
1477         if (g) *g = gr_screen.current_color.green;
1478         if (b) *b = gr_screen.current_color.blue;
1479 }
1480
1481 void gr_opengl_init_color(color *c, int r, int g, int b)
1482 {
1483         c->screen_sig = gr_screen.signature;
1484         c->red = (unsigned char)r;
1485         c->green = (unsigned char)g;
1486         c->blue = (unsigned char)b;
1487         c->alpha = 255;
1488         c->ac_type = AC_TYPE_NONE;
1489         c->alphacolor = -1;
1490         c->is_alphacolor = 0;
1491         c->magic = 0xAC01;
1492 }
1493
1494 void gr_opengl_init_alphacolor( color *clr, int r, int g, int b, int alpha, int type )
1495 {
1496         if ( r < 0 ) r = 0; else if ( r > 255 ) r = 255;
1497         if ( g < 0 ) g = 0; else if ( g > 255 ) g = 255;
1498         if ( b < 0 ) b = 0; else if ( b > 255 ) b = 255;
1499         if ( alpha < 0 ) alpha = 0; else if ( alpha > 255 ) alpha = 255;
1500
1501         gr_opengl_init_color( clr, r, g, b );
1502
1503         clr->alpha = (unsigned char)alpha;
1504         clr->ac_type = (ubyte)type;
1505         clr->alphacolor = -1;
1506         clr->is_alphacolor = 1;
1507 }
1508
1509 void gr_opengl_set_color( int r, int g, int b )
1510 {
1511         Assert((r >= 0) && (r < 256));
1512         Assert((g >= 0) && (g < 256));
1513         Assert((b >= 0) && (b < 256));
1514
1515         gr_opengl_init_color( &gr_screen.current_color, r, g, b );      
1516 }
1517
1518 void gr_opengl_set_color_fast(color *dst)
1519 {
1520         if ( dst->screen_sig != gr_screen.signature )   {
1521                 if ( dst->is_alphacolor )       {
1522                         gr_opengl_init_alphacolor( dst, dst->red, dst->green, dst->blue, dst->alpha, dst->ac_type );
1523                 } else {
1524                         gr_opengl_init_color( dst, dst->red, dst->green, dst->blue );
1525                 }
1526         }
1527         gr_screen.current_color = *dst;
1528 }
1529
1530 void gr_opengl_print_screen(char *filename)
1531 {
1532         STUB_FUNCTION;
1533 }
1534
1535 int gr_opengl_supports_res_ingame(int res)
1536 {
1537         STUB_FUNCTION;
1538         
1539         return 1;
1540 }
1541
1542 int gr_opengl_supports_res_interface(int res)
1543 {
1544         STUB_FUNCTION;
1545         
1546         return 1;
1547 }
1548
1549 void opengl_tcache_cleanup ();
1550 void gr_opengl_cleanup()
1551 {
1552         if ( !Inited )  return;
1553
1554
1555         gr_reset_clip();
1556         gr_clear();
1557         gr_flip();
1558
1559         opengl_tcache_cleanup ();
1560
1561         Inited = 0;
1562 }
1563
1564 void gr_opengl_fog_set(int fog_mode, int r, int g, int b, float fog_near, float fog_far)
1565 {
1566         Assert((r >= 0) && (r < 256));
1567         Assert((g >= 0) && (g < 256));
1568         Assert((b >= 0) && (b < 256));
1569         
1570         if (fog_mode == GR_FOGMODE_NONE) {
1571                 if (gr_screen.current_fog_mode != fog_mode) {
1572                         glDisable(GL_FOG);
1573                 }
1574                 gr_screen.current_fog_mode = fog_mode;
1575                 
1576                 return;
1577         }
1578         
1579         if (gr_screen.current_fog_mode != fog_mode) {
1580                 glEnable(GL_FOG);
1581                 
1582                 if (D3D_fog_mode == 2) {
1583                         glFogi(GL_FOG_MODE, GL_LINEAR);
1584                 }
1585                 
1586                 gr_screen.current_fog_mode = fog_mode;
1587         }
1588         
1589         if ( (gr_screen.current_fog_color.red != r) ||
1590                         (gr_screen.current_fog_color.green != g) ||
1591                         (gr_screen.current_fog_color.blue != b) ) {
1592                 GLfloat fc[4];
1593                 
1594                 gr_opengl_init_color( &gr_screen.current_fog_color, r, g, b );
1595         
1596                 fc[0] = (float)r/255.0;
1597                 fc[1] = (float)g/255.0;
1598                 fc[2] = (float)b/255.0;
1599                 fc[3] = 1.0;
1600                 
1601                 glFogfv(GL_FOG_COLOR, fc);
1602         }
1603         
1604         if( (fog_near >= 0.0f) && (fog_far >= 0.0f) && 
1605                         ((fog_near != gr_screen.fog_near) || 
1606                         (fog_far != gr_screen.fog_far)) ) {
1607                 gr_screen.fog_near = fog_near;
1608                 gr_screen.fog_far = fog_far;
1609                 
1610                 if (D3D_fog_mode == 2) {
1611                         glFogf(GL_FOG_START, fog_near);
1612                         glFogf(GL_FOG_END, fog_far);
1613                 }
1614         }
1615 }
1616
1617 void gr_opengl_get_pixel(int x, int y, int *r, int *g, int *b)
1618 {
1619         STUB_FUNCTION;
1620 }
1621
1622 void gr_opengl_set_cull(int cull)
1623 {
1624         if (cull) {
1625                 // DDOI - disabled for debugging purposes
1626                 glEnable (GL_CULL_FACE);
1627                 glFrontFace (GL_CCW);
1628         } else {
1629                 glDisable (GL_CULL_FACE);
1630         }
1631 }
1632
1633 void gr_opengl_filter_set(int filter)
1634 {
1635 }
1636
1637 // cross fade
1638 void gr_opengl_cross_fade(int bmap1, int bmap2, int x1, int y1, int x2, int y2, float pct)
1639 {
1640         STUB_FUNCTION;
1641 }
1642
1643
1644 typedef struct tcache_slot_opengl {
1645         GLuint  texture_handle;
1646         float   u_scale, v_scale;
1647         int     bitmap_id;
1648         int     size;
1649         char    used_this_frame;
1650         int     time_created;
1651         ushort  w,h;
1652
1653         // sections
1654         tcache_slot_opengl      *data_sections[MAX_BMAP_SECTIONS_X][MAX_BMAP_SECTIONS_Y];
1655         tcache_slot_opengl      *parent;
1656 } tcache_slot_opengl;
1657
1658 static void *Texture_sections = NULL;
1659 tcache_slot_opengl *Textures = NULL;
1660
1661 int GL_texture_sections = 0;
1662 int GL_texture_ram = 0;
1663 int GL_frame_count = 0;
1664 int GL_min_texture_width = 0;
1665 int GL_max_texture_width = 0;
1666 int GL_min_texture_height = 0;
1667 int GL_max_texture_height = 0;
1668 int GL_square_textures = 0;
1669 int GL_textures_in = 0;
1670 int GL_textures_in_frame = 0;
1671 int GL_last_bitmap_id = -1;
1672 int GL_last_detail = -1;
1673 int GL_last_bitmap_type = -1;
1674 int GL_last_section_x = -1;
1675 int GL_last_section_y = -1;
1676
1677 int vram_full = 0;
1678
1679 void opengl_tcache_init (int use_sections)
1680 {
1681         int i, idx, s_idx;
1682
1683         // DDOI - FIXME skipped a lot of stuff here
1684         GL_should_preload = 0;
1685
1686         //uint tmp_pl = os_config_read_uint( NULL, NOX("D3DPreloadTextures"), 255 );
1687         uint tmp_pl = 1;
1688
1689         if ( tmp_pl == 0 )      {
1690                 GL_should_preload = 0;
1691         } else if ( tmp_pl == 1 )       {
1692                 GL_should_preload = 1;
1693         } else {
1694                 GL_should_preload = 1;
1695         }
1696
1697         STUB_FUNCTION;
1698
1699         GL_min_texture_width = 16;
1700         GL_min_texture_height = 16;
1701         GL_max_texture_width = 256;
1702         GL_max_texture_height = 256;
1703
1704         GL_square_textures = 1;
1705
1706         Textures = (tcache_slot_opengl *)malloc(MAX_BITMAPS*sizeof(tcache_slot_opengl));
1707         if ( !Textures )        {
1708                 exit(1);
1709         }
1710
1711         if(use_sections){
1712                 Texture_sections = (tcache_slot_opengl*)malloc(MAX_BITMAPS * MAX_BMAP_SECTIONS_X * MAX_BMAP_SECTIONS_Y * sizeof(tcache_slot_opengl));
1713                 if(!Texture_sections){
1714                         exit(1);
1715                 }
1716                 memset(Texture_sections, 0, MAX_BITMAPS * MAX_BMAP_SECTIONS_X * MAX_BMAP_SECTIONS_Y * sizeof(tcache_slot_opengl));
1717         }
1718
1719         // Init the texture structures
1720         int section_count = 0;
1721         for( i=0; i<MAX_BITMAPS; i++ )  {
1722                 /*
1723                 Textures[i].vram_texture = NULL;
1724                 Textures[i].vram_texture_surface = NULL;
1725                 */
1726                 Textures[i].texture_handle = 0;
1727
1728                 Textures[i].bitmap_id = -1;
1729                 Textures[i].size = 0;
1730                 Textures[i].used_this_frame = 0;
1731
1732                 Textures[i].parent = NULL;
1733
1734                 // allocate sections
1735                 if(use_sections){
1736                         for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
1737                                 for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
1738                                         Textures[i].data_sections[idx][s_idx] = &((tcache_slot_opengl*)Texture_sections)[section_count++];
1739                                         Textures[i].data_sections[idx][s_idx]->parent = &Textures[i];
1740                                         /*
1741                                         Textures[i].data_sections[idx][s_idx]->vram_texture = NULL;
1742                                         Textures[i].data_sections[idx][s_idx]->vram_texture_surface = NULL;
1743                                         */
1744                                         Textures[i].data_sections[idx][s_idx]->texture_handle = 0;
1745                                         Textures[i].data_sections[idx][s_idx]->bitmap_id = -1;
1746                                         Textures[i].data_sections[idx][s_idx]->size = 0;
1747                                         Textures[i].data_sections[idx][s_idx]->used_this_frame = 0;
1748                                 }
1749                         }
1750                 } else {
1751                         for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
1752                                 for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
1753                                         Textures[i].data_sections[idx][s_idx] = NULL;
1754                                 }
1755                         }
1756                 }
1757         }
1758
1759         GL_texture_sections = use_sections;
1760
1761         //GL_last_detail = Detail.hardware_textures;
1762         GL_last_bitmap_id = -1;
1763         GL_last_bitmap_type = -1;
1764
1765         GL_last_section_x = -1;
1766         GL_last_section_y = -1;
1767
1768         GL_textures_in = 0;
1769         GL_textures_in_frame = 0;
1770 }
1771
1772 int opengl_free_texture (tcache_slot_opengl *t);
1773
1774 void opengl_tcache_flush ()
1775 {
1776         int i;
1777
1778         for( i=0; i<MAX_BITMAPS; i++ )  {
1779                 opengl_free_texture ( &Textures[i] );
1780         }
1781         if (GL_textures_in != 0) {
1782                 mprintf(( "WARNING: VRAM is at %d instead of zero after flushing!\n", GL_textures_in ));
1783                 GL_textures_in = 0;
1784         }
1785
1786         GL_last_bitmap_id = -1;
1787         GL_last_section_x = -1;
1788         GL_last_section_y = -1;
1789 }
1790
1791 void opengl_tcache_cleanup ()
1792 {
1793         opengl_tcache_flush ();
1794
1795         GL_textures_in = 0;
1796         GL_textures_in_frame = 0;
1797
1798         if ( Textures ) {
1799                 free(Textures);
1800                 Textures = NULL;
1801         }
1802
1803         if( Texture_sections != NULL ){
1804                 free(Texture_sections);
1805                 Texture_sections = NULL;
1806         }
1807 }
1808
1809 void opengl_tcache_frame ()
1810 {
1811         int idx, s_idx;
1812
1813         GL_last_bitmap_id = -1;
1814         GL_textures_in_frame = 0;
1815
1816         GL_frame_count++;
1817
1818         int i;
1819         for( i=0; i<MAX_BITMAPS; i++ )  {
1820                 Textures[i].used_this_frame = 0;
1821
1822                 // data sections
1823                 if(Textures[i].data_sections[0][0] != NULL){
1824                         Assert(GL_texture_sections);
1825                         if(GL_texture_sections){
1826                                 for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
1827                                         for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
1828                                                 if(Textures[i].data_sections[idx][s_idx] != NULL){
1829                                                         Textures[i].data_sections[idx][s_idx]->used_this_frame = 0;
1830                                                 }
1831                                         }
1832                                 }
1833                         }
1834                 }
1835         }
1836
1837         if ( vram_full )        {
1838                 opengl_tcache_flush();
1839                 vram_full = 0;
1840         }
1841 }
1842
1843 int opengl_free_texture ( tcache_slot_opengl *t )
1844 {
1845         int idx, s_idx;
1846         
1847
1848         // Bitmap changed!!     
1849         if ( t->bitmap_id > -1 )        {
1850                 // if I, or any of my children have been used this frame, bail  
1851                 if(t->used_this_frame){
1852                         return 0;
1853                 }
1854                 for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
1855                         for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
1856                                 if((t->data_sections[idx][s_idx] != NULL) && (t->data_sections[idx][s_idx]->used_this_frame)){
1857                                         return 0;
1858                                 }
1859                         }
1860                 }
1861
1862                 // ok, now we know its legal to free everything safely
1863                 glDeleteTextures (1, &t->texture_handle);
1864                 t->texture_handle = 0;
1865
1866                 if ( GL_last_bitmap_id == t->bitmap_id )       {
1867                         GL_last_bitmap_id = -1;
1868                 }
1869
1870                 // if this guy has children, free them too, since the children
1871                 // actually make up his size
1872                 for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
1873                         for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
1874                                 if(t->data_sections[idx][s_idx] != NULL){
1875                                         opengl_free_texture(t->data_sections[idx][s_idx]);
1876                                 }
1877                         }
1878                 }
1879
1880                 t->bitmap_id = -1;
1881                 t->used_this_frame = 0;
1882                 GL_textures_in -= t->size;
1883         }
1884
1885         return 1;
1886 }
1887
1888 void opengl_tcache_get_adjusted_texture_size(int w_in, int h_in, int *w_out, int *h_out)
1889 {
1890         int tex_w, tex_h;
1891
1892         // bogus
1893         if((w_out == NULL) ||  (h_out == NULL)){
1894                 return;
1895         }
1896
1897         // starting size
1898         tex_w = w_in;
1899         tex_h = h_in;
1900
1901         if (1)        {
1902                 int i;
1903                 for (i=0; i<16; i++ )   {
1904                         if ( (tex_w > (1<<i)) && (tex_w <= (1<<(i+1))) )        {
1905                                 tex_w = 1 << (i+1);
1906                                 break;
1907                         }
1908                 }
1909
1910                 for (i=0; i<16; i++ )   {
1911                         if ( (tex_h > (1<<i)) && (tex_h <= (1<<(i+1))) )        {
1912                                 tex_h = 1 << (i+1);
1913                                 break;
1914                         }
1915                 }
1916         }
1917
1918         if ( tex_w < GL_min_texture_width ) {
1919                 tex_w = GL_min_texture_width;
1920         } else if ( tex_w > GL_max_texture_width )     {
1921                 tex_w = GL_max_texture_width;
1922         }
1923
1924         if ( tex_h < GL_min_texture_height ) {
1925                 tex_h = GL_min_texture_height;
1926         } else if ( tex_h > GL_max_texture_height )    {
1927                 tex_h = GL_max_texture_height;
1928         }
1929
1930         if ( GL_square_textures )      {
1931                 int new_size;
1932                 // Make the both be equal to larger of the two
1933                 new_size = max(tex_w, tex_h);
1934                 tex_w = new_size;
1935                 tex_h = new_size;
1936         }
1937
1938         // store the outgoing size
1939         *w_out = tex_w;
1940         *h_out = tex_h;
1941 }
1942
1943 // data == start of bitmap data
1944 // sx == x offset into bitmap
1945 // sy == y offset into bitmap
1946 // src_w == absolute width of section on source bitmap
1947 // src_h == absolute height of section on source bitmap
1948 // bmap_w == width of source bitmap
1949 // bmap_h == height of source bitmap
1950 // tex_w == width of final texture
1951 // tex_h == height of final texture
1952 int opengl_create_texture_sub(int bitmap_type, int texture_handle, ushort *data, int sx, int sy, int src_w, int src_h, int bmap_w, int bmap_h, int tex_w, int tex_h, tcache_slot_opengl *t, int reload, int fail_on_full)
1953 {
1954         int ret_val = 1;
1955
1956         // bogus
1957         if(t == NULL){
1958                 return 0;
1959         }
1960
1961         if ( t->used_this_frame )       {
1962                 mprintf(( "ARGHH!!! Texture already used this frame!  Cannot free it!\n" ));
1963                 return 0;
1964         }
1965         if ( !reload )  {
1966                 // gah
1967                 if(!opengl_free_texture(t)){
1968                         return 0;
1969                 }
1970         }
1971
1972         // get final texture size
1973         opengl_tcache_get_adjusted_texture_size(tex_w, tex_h, &tex_w, &tex_h);
1974
1975         if ( (tex_w < 1) || (tex_h < 1) )       {
1976                 mprintf(("Bitmap is to small at %dx%d.\n", tex_w, tex_h ));
1977                 return 0;
1978         }
1979
1980         if ( bitmap_type == TCACHE_TYPE_AABITMAP )      {
1981                 t->u_scale = (float)bmap_w / (float)tex_w;
1982                 t->v_scale = (float)bmap_h / (float)tex_h;
1983         } else if(bitmap_type == TCACHE_TYPE_BITMAP_SECTION){
1984                 t->u_scale = (float)src_w / (float)tex_w;
1985                 t->v_scale = (float)src_h / (float)tex_h;
1986         } else {
1987                 t->u_scale = 1.0f;
1988                 t->v_scale = 1.0f;
1989         }
1990
1991         glGenTextures (1, &t->texture_handle);
1992         glBindTexture (GL_TEXTURE_2D, t->texture_handle);
1993
1994         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1995         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1996         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1997         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1998
1999         switch (bitmap_type) {
2000
2001                 case TCACHE_TYPE_AABITMAP:
2002                         {
2003                         int i,j;
2004                         ubyte *bmp_data = ((ubyte*)data);
2005                         ubyte *texmem = (ubyte *) malloc (tex_w*tex_h*2);
2006                         ubyte *texmemp = texmem;
2007                         ubyte xlat[256];
2008                         
2009                         for (i=0; i<16; i++) {
2010                                 xlat[i] = Gr_gamma_lookup[(i*255)/15];
2011                         }
2012                         xlat[15] = xlat[1];
2013                         for ( ; i<256; i++ )    {
2014                                 xlat[i] = xlat[0];
2015                         }
2016                         
2017                         for (i=0;i<tex_h;i++)
2018                         {
2019                                 for (j=0;j<tex_w;j++)
2020                                 {
2021                                         if (i < bmap_h && j < bmap_w) {
2022                                                 *texmemp++ = 0xff;
2023                                                 *texmemp++ = xlat[bmp_data[i*bmap_w+j]];
2024                                         } else {
2025                                                 *texmemp++ = 0;
2026                                                 *texmemp++ = 0;
2027                                         }
2028                                 }
2029                         }
2030
2031                         glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, tex_w, tex_h, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, texmem);
2032
2033                         free (texmem);
2034                         }
2035                         break;
2036                 case TCACHE_TYPE_BITMAP_SECTION:
2037                         {
2038                                 int i,j;
2039                                 ubyte *bmp_data = ((ubyte*)data);
2040                                 ubyte *texmem = (ubyte *) malloc (tex_w*tex_h*2);
2041                                 ubyte *texmemp = texmem;
2042                                 
2043                                 for (i=0;i<tex_h;i++)
2044                                 {
2045                                         for (j=0;j<tex_w;j++)
2046                                         {
2047                                                 if (i < src_h && j < src_w) {
2048                                                         *texmemp++ = bmp_data[((i+sy)*bmap_w+(j+sx))*2+0];
2049                                                         *texmemp++ = bmp_data[((i+sy)*bmap_w+(j+sx))*2+1];
2050                                                 } else {
2051                                                         *texmemp++ = 0;
2052                                                         *texmemp++ = 0;
2053                                                 }
2054                                         }
2055                                 }
2056                                 glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, tex_w, tex_h, 0, GL_RGBA,
2057                                         GL_UNSIGNED_SHORT_1_5_5_5_REV, texmem);
2058                                         
2059                                 free(texmem);
2060                                 break;
2061                         }
2062                 default:
2063                         {
2064                                 int i,j;
2065                                 ubyte *bmp_data = ((ubyte*)data);
2066                                 ubyte *texmem = (ubyte *) malloc (tex_w*tex_h*2);
2067                                 ubyte *texmemp = texmem;
2068                                 
2069                                 fix u, utmp, v, du, dv;
2070                                 
2071                                 u = v = 0;
2072                                 
2073                                 du = ( (bmap_w-1)*F1_0 ) / tex_w;
2074                                 dv = ( (bmap_h-1)*F1_0 ) / tex_h;
2075                                 
2076                                 for (j=0;j<tex_h;j++)
2077                                 {
2078                                         utmp = u;
2079                                         for (i=0;i<tex_w;i++)
2080                                         {
2081                                                 *texmemp++ = bmp_data[(f2i(v)*bmap_w+f2i(utmp))*2+0];
2082                                                 *texmemp++ = bmp_data[(f2i(v)*bmap_w+f2i(utmp))*2+1];
2083                                         }
2084                                         v += dv;
2085                                 }
2086
2087                                 glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, tex_w, tex_h, 0, GL_RGBA,
2088                                         GL_UNSIGNED_SHORT_1_5_5_5_REV, texmem);
2089                                         
2090                                 free(texmem);
2091                                 break;
2092                         }
2093                         break;
2094         }
2095         
2096         t->bitmap_id = texture_handle;
2097         t->time_created = GL_frame_count;
2098         t->used_this_frame = 0;
2099         t->size = tex_w * tex_h * 2;
2100         t->w = (ushort)tex_w;
2101         t->h = (ushort)tex_h;
2102         GL_textures_in_frame += t->size;
2103         if (!reload) {
2104                 GL_textures_in += t->size;
2105         }
2106
2107         return ret_val;
2108 }
2109
2110 int opengl_create_texture (int bitmap_handle, int bitmap_type, tcache_slot_opengl *tslot, int fail_on_full)
2111 {
2112         ubyte flags;
2113         bitmap *bmp;
2114         int final_w, final_h;
2115         ubyte bpp = 16;
2116         int reload = 0;
2117
2118         // setup texture/bitmap flags
2119         flags = 0;
2120         switch(bitmap_type){
2121                 case TCACHE_TYPE_AABITMAP:
2122                         flags |= BMP_AABITMAP;
2123                         bpp = 8;
2124                         break;
2125                 case TCACHE_TYPE_NORMAL:
2126                         flags |= BMP_TEX_OTHER;
2127                 case TCACHE_TYPE_XPARENT:
2128                         flags |= BMP_TEX_XPARENT;
2129                         break;
2130                 case TCACHE_TYPE_NONDARKENING:
2131                         Int3();
2132                         flags |= BMP_TEX_NONDARK;
2133                         break;
2134         }
2135
2136         // lock the bitmap into the proper format
2137         bmp = bm_lock(bitmap_handle, bpp, flags);
2138         if ( bmp == NULL ) {
2139                 mprintf(("Couldn't lock bitmap %d.\n", bitmap_handle ));
2140                 return 0;
2141         }
2142
2143         int max_w = bmp->w;
2144         int max_h = bmp->h;
2145
2146         /*
2147            // DDOI - TODO
2148         if ( bitmap_type != TCACHE_TYPE_AABITMAP )      {
2149                 max_w /= D3D_texture_divider;
2150                 max_h /= D3D_texture_divider;
2151
2152                 // Detail.debris_culling goes from 0 to 4.
2153                 max_w /= 16 >> Detail.hardware_textures;
2154                 max_h /= 16 >> Detail.hardware_textures;
2155         }
2156         */
2157
2158         // get final texture size as it will be allocated as a DD surface
2159         opengl_tcache_get_adjusted_texture_size(max_w, max_h, &final_w, &final_h); 
2160
2161         // if this tcache slot has no bitmap
2162         if ( tslot->bitmap_id < 0) {
2163                 reload = 0;
2164         }
2165         // different bitmap altogether - determine if the new one can use the old one's slot
2166         else if (tslot->bitmap_id != bitmap_handle)     {
2167                 if((final_w == tslot->w) && (final_h == tslot->h)){
2168                         reload = 1;
2169                         //ml_printf("Reloading texture %d\n", bitmap_handle);
2170                 } else {
2171                         reload = 0;
2172                 }
2173         }
2174
2175         // call the helper
2176         int ret_val = opengl_create_texture_sub(bitmap_type, bitmap_handle, (ushort*)bmp->data, 0, 0, bmp->w, bmp->h, bmp->w, bmp->h, max_w, max_h, tslot, reload, fail_on_full);
2177
2178         // unlock the bitmap
2179         bm_unlock(bitmap_handle);
2180
2181         return ret_val;
2182 }
2183
2184 int opengl_create_texture_sectioned(int bitmap_handle, int bitmap_type, tcache_slot_opengl *tslot, int sx, int sy, int fail_on_full)
2185 {
2186         ubyte flags;
2187         bitmap *bmp;
2188         int final_w, final_h;
2189         int section_x, section_y;
2190         int reload = 0;
2191
2192         // setup texture/bitmap flags
2193         Assert(bitmap_type == TCACHE_TYPE_BITMAP_SECTION);
2194         if(bitmap_type != TCACHE_TYPE_BITMAP_SECTION){
2195                 bitmap_type = TCACHE_TYPE_BITMAP_SECTION;
2196         }
2197         flags = BMP_TEX_XPARENT;
2198
2199         // lock the bitmap in the proper format
2200         bmp = bm_lock(bitmap_handle, 16, flags);
2201         if ( bmp == NULL ) {
2202                 mprintf(("Couldn't lock bitmap %d.\n", bitmap_handle ));
2203                 return 0;
2204         }
2205         // determine the width and height of this section
2206         bm_get_section_size(bitmap_handle, sx, sy, &section_x, &section_y);
2207
2208         // get final texture size as it will be allocated as an opengl texture
2209         opengl_tcache_get_adjusted_texture_size(section_x, section_y, &final_w, &final_h);
2210
2211         // if this tcache slot has no bitmap
2212         if ( tslot->bitmap_id < 0) {
2213                 reload = 0;
2214         }
2215         // different bitmap altogether - determine if the new one can use the old one's slot
2216         else if (tslot->bitmap_id != bitmap_handle)     {
2217                 if((final_w == tslot->w) && (final_h == tslot->h)){
2218                         reload = 1;
2219                 } else {
2220                         reload = 0;
2221                 }
2222         }
2223
2224         // call the helper
2225         int ret_val = opengl_create_texture_sub(bitmap_type, bitmap_handle, (ushort*)bmp->data, bmp->sections.sx[sx], bmp->sections.sy[sy], section_x, section_y, bmp->w, bmp->h, section_x, section_y, tslot, reload, fail_on_full);
2226
2227         // unlock the bitmap
2228         bm_unlock(bitmap_handle);
2229
2230         return ret_val;
2231 }
2232
2233                 
2234 extern int bm_get_cache_slot( int bitmap_id, int separate_ani_frames );
2235 int gr_opengl_tcache_set(int bitmap_id, int bitmap_type, float *u_scale, float *v_scale, int fail_on_full = 0, int sx = -1, int sy = -1, int force = 0)
2236 {
2237         bitmap *bmp = NULL;
2238
2239         int idx, s_idx;
2240         int ret_val = 1;
2241
2242         if (bitmap_id < 0)
2243         {
2244                 GL_last_bitmap_id = -1;
2245                 return 0;
2246         }
2247
2248         /*
2249         if ( GL_last_detail != Detail.hardware_textures )      {
2250                 GL_last_detail = Detail.hardware_textures;
2251                 opengl_tcache_flush();
2252         }
2253         */
2254
2255         if (vram_full) {
2256                 return 0;
2257         }
2258
2259         int n = bm_get_cache_slot (bitmap_id, 1);
2260         tcache_slot_opengl *t = &Textures[n];
2261
2262         if ( (GL_last_bitmap_id == bitmap_id) && (GL_last_bitmap_type==bitmap_type) && (t->bitmap_id == bitmap_id) && (GL_last_section_x == sx) && (GL_last_section_y == sy))       {
2263                 t->used_this_frame++;
2264
2265                 // mark all children as used
2266                 if(GL_texture_sections){
2267                         for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
2268                                 for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
2269                                         if(t->data_sections[idx][s_idx] != NULL){
2270                                                 t->data_sections[idx][s_idx]->used_this_frame++;
2271                                         }
2272                                 }
2273                         }
2274                 }
2275
2276                 *u_scale = t->u_scale;
2277                 *v_scale = t->v_scale;
2278                 return 1;
2279         }
2280
2281         if (bitmap_type == TCACHE_TYPE_BITMAP_SECTION){
2282                 Assert((sx >= 0) && (sy >= 0) && (sx < MAX_BMAP_SECTIONS_X) && (sy < MAX_BMAP_SECTIONS_Y));
2283                 if(!((sx >= 0) && (sy >= 0) && (sx < MAX_BMAP_SECTIONS_X) && (sy < MAX_BMAP_SECTIONS_Y))){
2284                         return 0;
2285                 }
2286
2287                 ret_val = 1;
2288
2289                 // if the texture sections haven't been created yet
2290                 if((t->bitmap_id < 0) || (t->bitmap_id != bitmap_id)){
2291
2292                         // lock the bitmap in the proper format
2293                         bmp = bm_lock(bitmap_id, 16, BMP_TEX_XPARENT);
2294                         bm_unlock(bitmap_id);
2295
2296                         // now lets do something for each texture
2297
2298                         for(idx=0; idx<bmp->sections.num_x; idx++){
2299                                 for(s_idx=0; s_idx<bmp->sections.num_y; s_idx++){
2300                                         // hmm. i'd rather we didn't have to do it this way...
2301                                         if(!opengl_create_texture_sectioned(bitmap_id, bitmap_type, t->data_sections[idx][s_idx], idx, s_idx, fail_on_full)){
2302                                                 ret_val = 0;
2303                                         }
2304
2305                                         // not used this frame
2306                                         t->data_sections[idx][s_idx]->used_this_frame = 0;
2307                                 }
2308                         }
2309
2310                         // zero out pretty much everything in the parent struct since he's just the root
2311                         t->bitmap_id = bitmap_id;
2312                         t->texture_handle = 0;
2313                         t->time_created = t->data_sections[sx][sy]->time_created;
2314                         t->used_this_frame = 0;
2315                         /*
2316                         t->vram_texture = NULL;
2317                         t->vram_texture_surface = NULL
2318                         */
2319                 }
2320
2321                 // argh. we failed to upload. free anything we can
2322                 if(!ret_val){
2323                         opengl_free_texture(t);
2324                 }
2325                 // swap in the texture we want
2326                 else {
2327                         t = t->data_sections[sx][sy];
2328                 }
2329         }
2330         // all other "normal" textures
2331         else if((bitmap_id < 0) || (bitmap_id != t->bitmap_id)){
2332                 ret_val = opengl_create_texture( bitmap_id, bitmap_type, t, fail_on_full );
2333         }
2334
2335         // everything went ok
2336         if(ret_val && (t->texture_handle) && !vram_full){
2337                 *u_scale = t->u_scale;
2338                 *v_scale = t->v_scale;
2339
2340                 glBindTexture (GL_TEXTURE_2D, t->texture_handle );
2341
2342                 GL_last_bitmap_id = t->bitmap_id;
2343                 GL_last_bitmap_type = bitmap_type;
2344                 GL_last_section_x = sx;
2345                 GL_last_section_y = sy;
2346
2347                 t->used_this_frame++;
2348         }
2349         // gah
2350         else {
2351                 glBindTexture (GL_TEXTURE_2D, 0);       // test - DDOI
2352                 return 0;
2353         }
2354
2355         return 1;
2356 }
2357
2358 void gr_opengl_set_clear_color(int r, int g, int b)
2359 {
2360         gr_init_color (&gr_screen.current_clear_color, r, g, b);
2361 }
2362
2363 void gr_opengl_aaline(vertex *v1, vertex *v2)
2364 {
2365         gr_opengl_line( fl2i(v1->sx), fl2i(v1->sy), fl2i(v2->sx), fl2i(v2->sy) );
2366 }
2367
2368 void gr_opengl_flash(int r, int g, int b)
2369 {
2370         CAP(r,0,255);
2371         CAP(g,0,255);
2372         CAP(b,0,255);
2373         
2374         if ( r || g || b ) {
2375                 gr_opengl_set_state( TEXTURE_SOURCE_NONE, ALPHA_BLEND_ALPHA_ADDITIVE, ZBUFFER_TYPE_NONE );
2376                 
2377                 float x1, x2, y1, y2;
2378                 x1 = i2fl(gr_screen.clip_left+gr_screen.offset_x);
2379                 y1 = i2fl(gr_screen.clip_top+gr_screen.offset_y);
2380                 x2 = i2fl(gr_screen.clip_right+gr_screen.offset_x);
2381                 y2 = i2fl(gr_screen.clip_bottom+gr_screen.offset_y);
2382                 
2383                 glColor4ub(r, g, b, 255);
2384                 glBegin (GL_QUADS);
2385                   glVertex3f (x1, y2, -0.99);
2386
2387                   glVertex3f (x2, y2, -0.99);
2388
2389                   glVertex3f (x2, y1, -0.99);
2390
2391                   glVertex3f (x1, y1, -0.99);
2392                 glEnd ();         
2393         }
2394 }
2395
2396 int gr_opengl_zbuffer_get()
2397 {
2398         if ( !gr_global_zbuffering )    {
2399                 return GR_ZBUFF_NONE;
2400         }
2401         return gr_zbuffering_mode;
2402 }
2403
2404 int gr_opengl_zbuffer_set(int mode)
2405 {
2406         int tmp = gr_zbuffering_mode;
2407
2408         gr_zbuffering_mode = mode;
2409
2410         if (gr_zbuffering_mode == GR_ZBUFF_NONE )      {
2411                 gr_zbuffering = 0;
2412         } else {
2413                 gr_zbuffering = 1;
2414         }
2415         return tmp;
2416 }
2417
2418 void gr_opengl_zbuffer_clear(int mode)
2419 {
2420         if (mode) {
2421                 gr_zbuffering = 1;
2422                 gr_zbuffering_mode = GR_ZBUFF_FULL;
2423                 gr_global_zbuffering = 1;
2424                 
2425                 gr_opengl_set_state( TEXTURE_SOURCE_NONE, ALPHA_BLEND_NONE, ZBUFFER_TYPE_FULL );
2426                 glClear(GL_DEPTH_BUFFER_BIT);
2427         } else {
2428                 gr_zbuffering = 0;
2429                 gr_zbuffering_mode = GR_ZBUFF_NONE;
2430                 gr_global_zbuffering = 0;
2431         }
2432 }
2433
2434 void gr_opengl_set_gamma(float gamma)
2435 {
2436         Gr_gamma = gamma;
2437         Gr_gamma_int = int (Gr_gamma*10);
2438
2439         // Create the Gamma lookup table
2440         int i;
2441         for (i=0;i<256; i++) {
2442                 int v = fl2i(pow(i2fl(i)/255.0f, 1.0f/Gr_gamma)*255.0f);
2443                 if ( v > 255 ) {
2444                         v = 255;
2445                 } else if ( v < 0 )     {
2446                         v = 0;
2447                 }
2448                 Gr_gamma_lookup[i] = v;
2449         }
2450
2451         // Flush any existing textures
2452         opengl_tcache_flush();
2453 }
2454
2455 void gr_opengl_fade_in(int instantaneous)
2456 {
2457         // Empty - DDOI
2458 }
2459
2460 void gr_opengl_fade_out(int instantaneous)
2461 {
2462         // Empty - DDOI
2463 }
2464
2465 void gr_opengl_get_region(int front, int w, int h, ubyte *data)
2466 {
2467         if (front) {
2468                 glReadBuffer(GL_FRONT);
2469         } else {
2470                 glReadBuffer(GL_BACK);
2471         }
2472 // TODO
2473 //      glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, data);
2474 }
2475
2476 int gr_opengl_save_screen()
2477 {
2478         gr_reset_clip();
2479
2480         if ( Gr_saved_screen )  {
2481                 mprintf(( "Screen alread saved!\n" ));
2482                 return -1;
2483         }
2484
2485         Gr_saved_screen = (char*)malloc( gr_screen.max_w * gr_screen.max_h * gr_screen.bytes_per_pixel );
2486         if (!Gr_saved_screen) {
2487                 mprintf(( "Couldn't get memory for saved screen!\n" ));
2488                 return -1;
2489         }
2490
2491         gr_opengl_get_region(1, gr_screen.max_w, gr_screen.max_h, (ubyte *)Gr_saved_screen);
2492         
2493         return 0;
2494 }
2495
2496 void gr_opengl_restore_screen(int id)
2497 {
2498         gr_reset_clip();
2499         
2500         if ( !Gr_saved_screen ) {
2501                 gr_clear();
2502                 return;
2503         }
2504
2505 // TODO 
2506 //      glDrawPixels(gr_screen.max_w, gr_screen.max_h, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, Gr_saved_screen);
2507 }
2508
2509 void gr_opengl_free_screen(int id)
2510 {
2511         if ( Gr_saved_screen )  {
2512                 free( Gr_saved_screen );
2513                 Gr_saved_screen = NULL;
2514         }
2515 }
2516
2517 void gr_opengl_dump_frame_start(int first_frame, int frames_between_dumps)
2518 {
2519         STUB_FUNCTION;
2520 }
2521
2522 void gr_opengl_dump_frame_stop()
2523 {
2524         STUB_FUNCTION;
2525 }
2526
2527 void gr_opengl_dump_frame()
2528 {
2529         STUB_FUNCTION;
2530 }
2531
2532 uint gr_opengl_lock()
2533 {
2534         STUB_FUNCTION;
2535         
2536         return 1;
2537 }
2538         
2539 void gr_opengl_unlock()
2540 {
2541 }
2542         
2543 extern char *Osreg_title;
2544 void gr_opengl_init()
2545 {
2546         if ( Inited )   {
2547                 gr_opengl_cleanup();
2548                 Inited = 0;
2549         }
2550
2551         mprintf(( "Initializing opengl graphics device...\n" ));
2552         Inited = 1;
2553
2554 #ifdef PLAT_UNIX
2555         if (SDL_InitSubSystem (SDL_INIT_VIDEO) < 0)
2556         {
2557                 fprintf (stderr, "Couldn't init SDL: %s", SDL_GetError());
2558                 exit (1);
2559         }
2560
2561         atexit (SDL_Quit);
2562
2563         SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
2564         SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
2565         SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
2566         SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
2567         SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
2568                                                 
2569         if (SDL_SetVideoMode (gr_screen.max_w, gr_screen.max_h,0,SDL_OPENGL) == NULL)
2570         {
2571                 fprintf (stderr, "Couldn't set video mode: %s", SDL_GetError ());
2572                 exit (1);
2573         }               
2574
2575         SDL_WM_SetCaption (Osreg_title, "FS2");
2576 #endif
2577         glViewport(0, 0, gr_screen.max_w, gr_screen.max_h);
2578
2579         glMatrixMode(GL_PROJECTION);
2580         glLoadIdentity();
2581         glMatrixMode(GL_MODELVIEW);
2582         glLoadIdentity();
2583         
2584         glShadeModel(GL_SMOOTH);
2585         glEnable(GL_DITHER);
2586         glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
2587         glHint(GL_FOG_HINT, GL_NICEST);
2588                 
2589         glEnable(GL_DEPTH_TEST);
2590         glEnable(GL_BLEND);
2591         
2592         glEnable(GL_TEXTURE_2D);
2593
2594         glMatrixMode(GL_PROJECTION);
2595         glPushMatrix();
2596         glLoadIdentity();
2597         
2598         glOrtho(0, gr_screen.max_w, gr_screen.max_h, 0, 0.0, 1.0);
2599         glDepthRange(0.0, 1.0);
2600         
2601         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2602         
2603         //glGenTextures(1, &bitmapTex);
2604         //glBindTexture(GL_TEXTURE_2D, bitmapTex);
2605         //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2606         //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2607         //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
2608         //bitmapMem = (GLubyte *)malloc(256*256*4);
2609         //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV, bitmapMem);
2610         
2611         D3D_32bit = 1;              // grd3d.cpp
2612         
2613         /* 
2614           TODO: set fog_mode to 1 if EXT_secondary_color found and wanted 
2615           1 = use secondary color ext
2616           2 = use opengl linear fog
2617          */
2618         D3D_fog_mode = 2;          // grd3d.cpp
2619
2620         glFlush();
2621         
2622         Bm_pixel_format = BM_PIXEL_FORMAT_ARGB;
2623         Gr_bitmap_poly = 1;
2624         
2625         int bpp = 15;
2626         
2627         switch( bpp )   {
2628         case 8:
2629                 Gr_red.bits = 8;
2630                 Gr_red.shift = 16;
2631                 Gr_red.scale = 1;
2632                 Gr_red.mask = 0xff0000;
2633
2634                 Gr_green.bits = 8;
2635                 Gr_green.shift = 8;
2636                 Gr_green.scale = 1;
2637                 Gr_green.mask = 0xff00;
2638
2639                 Gr_blue.bits = 8;
2640                 Gr_blue.shift = 0;
2641                 Gr_blue.scale = 1;
2642                 Gr_blue.mask = 0xff;
2643                 
2644                 break;
2645                 
2646         case 15:
2647                 Gr_red.bits = 5;
2648                 Gr_red.shift = 10;
2649                 Gr_red.scale = 8;
2650                 Gr_red.mask = 0x7C00;
2651
2652                 Gr_green.bits = 5;
2653                 Gr_green.shift = 5;
2654                 Gr_green.scale = 8;
2655                 Gr_green.mask = 0x3E0;
2656
2657                 Gr_blue.bits = 5;
2658                 Gr_blue.shift = 0;
2659                 Gr_blue.scale = 8;
2660                 Gr_blue.mask = 0x1F;
2661
2662                 break;
2663
2664         case 16:
2665                 Gr_red.bits = 5;
2666                 Gr_red.shift = 11;
2667                 Gr_red.scale = 8;
2668                 Gr_red.mask = 0xF800;
2669
2670                 Gr_green.bits = 6;
2671                 Gr_green.shift = 5;
2672                 Gr_green.scale = 4;
2673                 Gr_green.mask = 0x7E0;
2674
2675                 Gr_blue.bits = 5;
2676                 Gr_blue.shift = 0;
2677                 Gr_blue.scale = 8;
2678                 Gr_blue.mask = 0x1F;
2679
2680                 break;
2681
2682         case 24:
2683         case 32:
2684                 Gr_red.bits = 8;
2685                 Gr_red.shift = 16;
2686                 Gr_red.scale = 1;
2687                 Gr_red.mask = 0xff0000;
2688
2689                 Gr_green.bits = 8;
2690                 Gr_green.shift = 8;
2691                 Gr_green.scale = 1;
2692                 Gr_green.mask = 0xff00;
2693
2694                 Gr_blue.bits = 8;
2695                 Gr_blue.shift = 0;
2696                 Gr_blue.scale = 1;
2697                 Gr_blue.mask = 0xff;
2698
2699                 break;
2700
2701         default:
2702                 Int3(); // Illegal bpp
2703         }
2704
2705         // DDOI - set these so no one else does!
2706         Gr_ta_red.mask = 0x0f00;
2707         Gr_ta_red.shift = 8;
2708         Gr_ta_red.scale = 16;
2709
2710         Gr_ta_green.mask = 0x00f0;
2711         Gr_ta_green.shift = 4;
2712         Gr_ta_green.scale = 16;
2713         
2714         Gr_ta_blue.mask = 0x000f;
2715         Gr_ta_blue.shift = 0;
2716         Gr_ta_blue.scale = 16;
2717
2718         Gr_ta_alpha.mask = 0xf000;
2719         Gr_ta_alpha.shift = 12;
2720         Gr_ta_alpha.scale = 16;
2721
2722
2723         opengl_tcache_init (1);
2724         gr_opengl_clear();
2725
2726         Gr_current_red = &Gr_red;
2727         Gr_current_blue = &Gr_blue;
2728         Gr_current_green = &Gr_green;
2729         Gr_current_alpha = &Gr_alpha;
2730                                 
2731         gr_screen.gf_flip = gr_opengl_flip;
2732         gr_screen.gf_flip_window = gr_opengl_flip_window;
2733         gr_screen.gf_set_clip = gr_opengl_set_clip;
2734         gr_screen.gf_reset_clip = gr_opengl_reset_clip;
2735         gr_screen.gf_set_font = grx_set_font;
2736         
2737         gr_screen.gf_set_color = gr_opengl_set_color;
2738         gr_screen.gf_set_bitmap = gr_opengl_set_bitmap;
2739         gr_screen.gf_create_shader = gr_opengl_create_shader;
2740         gr_screen.gf_set_shader = gr_opengl_set_shader;
2741         gr_screen.gf_clear = gr_opengl_clear;
2742         // gr_screen.gf_bitmap = gr_opengl_bitmap;
2743         // gr_screen.gf_bitmap_ex = gr_opengl_bitmap_ex;
2744         gr_screen.gf_aabitmap = gr_opengl_aabitmap;
2745         gr_screen.gf_aabitmap_ex = gr_opengl_aabitmap_ex;
2746         
2747         gr_screen.gf_rect = gr_opengl_rect;
2748         gr_screen.gf_shade = gr_opengl_shade;
2749         gr_screen.gf_string = gr_opengl_string;
2750         gr_screen.gf_circle = gr_opengl_circle;
2751
2752         gr_screen.gf_line = gr_opengl_line;
2753         gr_screen.gf_aaline = gr_opengl_aaline;
2754         gr_screen.gf_pixel = gr_opengl_pixel;
2755         gr_screen.gf_scaler = gr_opengl_scaler;
2756         gr_screen.gf_tmapper = gr_opengl_tmapper;
2757
2758         gr_screen.gf_gradient = gr_opengl_gradient;
2759
2760         gr_screen.gf_set_palette = gr_opengl_set_palette;
2761         gr_screen.gf_get_color = gr_opengl_get_color;
2762         gr_screen.gf_init_color = gr_opengl_init_color;
2763         gr_screen.gf_init_alphacolor = gr_opengl_init_alphacolor;
2764         gr_screen.gf_set_color_fast = gr_opengl_set_color_fast;
2765         gr_screen.gf_print_screen = gr_opengl_print_screen;
2766
2767         gr_screen.gf_fade_in = gr_opengl_fade_in;
2768         gr_screen.gf_fade_out = gr_opengl_fade_out;
2769         gr_screen.gf_flash = gr_opengl_flash;
2770         
2771         gr_screen.gf_zbuffer_get = gr_opengl_zbuffer_get;
2772         gr_screen.gf_zbuffer_set = gr_opengl_zbuffer_set;
2773         gr_screen.gf_zbuffer_clear = gr_opengl_zbuffer_clear;
2774         
2775         gr_screen.gf_save_screen = gr_opengl_save_screen;
2776         gr_screen.gf_restore_screen = gr_opengl_restore_screen;
2777         gr_screen.gf_free_screen = gr_opengl_free_screen;
2778         
2779         gr_screen.gf_dump_frame_start = gr_opengl_dump_frame_start;
2780         gr_screen.gf_dump_frame_stop = gr_opengl_dump_frame_stop;
2781         gr_screen.gf_dump_frame = gr_opengl_dump_frame;
2782         
2783         gr_screen.gf_set_gamma = gr_opengl_set_gamma;
2784         
2785         gr_screen.gf_lock = gr_opengl_lock;
2786         gr_screen.gf_unlock = gr_opengl_unlock;
2787         
2788         gr_screen.gf_fog_set = gr_opengl_fog_set;       
2789
2790         gr_screen.gf_get_region = gr_opengl_get_region;
2791
2792         gr_screen.gf_get_pixel = gr_opengl_get_pixel;
2793
2794         gr_screen.gf_set_cull = gr_opengl_set_cull;
2795
2796         gr_screen.gf_cross_fade = gr_opengl_cross_fade;
2797
2798         gr_screen.gf_filter_set = gr_opengl_filter_set;
2799
2800         gr_screen.gf_tcache_set = gr_opengl_tcache_set;
2801
2802         gr_screen.gf_set_clear_color = gr_opengl_set_clear_color;
2803 }
2804