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