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