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