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