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