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