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