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