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